fix(coord-count): distinguish claimed from unmeasured, fix Linux date parse
Review finding 11 (docs/2026-08-14-confident-zero-review.md), tier 1,
prioritized by .claude 2026-08-14T21:24:16Z coord message.
Two bugs collapsed into one token. Column 4 of coord-count.sh (the WP1d
origin-age column) printed "-" for both "has .origin" (claimed, not a
dead-letter candidate) and "age could not be measured" - a consumer could
not tell "not a dead letter" from "not measured". Fixed by reserving "-"
for claimed only and introducing "?" for could-not-measure; board.sh's
sole column-4 consumer (awk '$4 != "-" && $4+0 >= 3') needed no change,
since awk's numeric coercion already treats "?" as 0 and filters it out
the same way "-" always was.
Second, the age computation itself used `date -u -j -f ...`, a BSD-only
invocation. Measured directly (Ubuntu 24.04, GNU coreutils 9.4, real
coord-count.sh, unmodified) rather than reasoned about: GNU date rejects
-j outright ("invalid option -- 'j'", exit 1), so every mailbox printed
"-" on Linux regardless of actual dead-letter status - WP1d detection was
silently inert on the one platform this public plugin cannot assume away.
Fixed with a one-time `date --version` flavor check (measured: exits 0
with a GNU banner on GNU date, exits nonzero with "illegal option" on BSD
date) branching to `date -u -d <RFC-3339-string>` on GNU, unchanged
`-j -f` on BSD. The RFC 3339 acceptance is documented (GNU Coreutils
manual, "Options for date"), not live-measured, since Colima was removed
from this machine mid-session before that specific sub-claim could be
re-verified live.
coord-selftest.sh section 31 (e) previously pinned the bug (asserted "-"
for an ungrammatical filename); updated to assert "?", plus a new
contrast check that claimed and could-not-measure are always different
tokens. Section 32 pins the GNU branch with a PATH shim for `date` that
replays only measured facts (the --version and -j behaviors above) rather
than a speculative mock.
All four selftest suites green: coord 200/200, board 178/178 (regression,
unaffected as predicted), route 69/69, guard 21/21.
Out of scope, reported not fixed: coord-sweep.sh:77 and both selftests'
fixture generators use `date -v-Nd` (BSD-only, same class) - the suite
itself cannot run on Linux yet. No CI exists in this repo to catch that
drift automatically.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F1mzsaUmjqFHArbArG7EpF
This commit is contained in:
parent
108a73a497
commit
db57b43f50
2 changed files with 112 additions and 15 deletions
|
|
@ -58,6 +58,19 @@ done
|
|||
|
||||
[ -d "$COORD" ] || exit 0
|
||||
|
||||
# GNU/BSD date flavor, detected once per run (not per mailbox): BSD date
|
||||
# rejects --version outright (exit nonzero, "illegal option" - measured on
|
||||
# this machine); GNU date supports it and prints a version banner (exit 0 -
|
||||
# measured directly against Ubuntu 24.04 / GNU coreutils 9.4). The origin_age
|
||||
# column below needs this because BSD's `date -j -f` and GNU's `date -d`
|
||||
# share no common invocation - GNU date has no -j at all (measured: "date:
|
||||
# invalid option -- 'j'", exit 1), which is why every mailbox printed "-"
|
||||
# (now "?", see the F11a comment below) on Linux before this branch existed.
|
||||
# coord-selftest.sh section 32 pins the GNU branch via a PATH shim that
|
||||
# replays these measured facts.
|
||||
DATE_IS_GNU=0
|
||||
date --version >/dev/null 2>&1 && DATE_IS_GNU=1
|
||||
|
||||
# Does this message owe a reply? Absent field means YES: every message written
|
||||
# before 0.11.0 lacks it, so absence has to keep meaning what it always meant.
|
||||
# The read is bounded to the frontmatter block - a body line is untrusted
|
||||
|
|
@ -108,20 +121,35 @@ for d in "$COORD"/* "$COORD"/.[!.]*; do
|
|||
fi
|
||||
done
|
||||
[ "$n" -gt 0 ] || continue
|
||||
# "-" means either .origin exists (claimed, never a dead-letter candidate
|
||||
# regardless of age) or the age could not be read (fail-safe, not
|
||||
# fail-open - an unreadable age must never be treated as old, matching
|
||||
# coord-sweep.sh's identical rule for the same filename grammar).
|
||||
# "-" means .origin exists (claimed, never a dead-letter candidate
|
||||
# regardless of age). "?" means unclaimed but the age could not be read -
|
||||
# fail-safe, not fail-open, an unreadable age must never be treated as old,
|
||||
# matching coord-sweep.sh's identical rule for the same filename grammar -
|
||||
# and, critically, must never be reported as the SAME token as claimed
|
||||
# (review finding 11, 2026-08-14: both used to print "-", collapsing "not a
|
||||
# dead-letter candidate" and "not measured" into one token a consumer could
|
||||
# not tell apart). Only a real computed age is neither.
|
||||
origin_age="-"
|
||||
if [ ! -f "$d/.origin" ] && [ -n "$oldest_ts" ]; then
|
||||
oldest_epoch="$(date -u -j -f '%Y%m%dT%H%M%SZ' "$oldest_ts" '+%s' 2>/dev/null)"
|
||||
case "$oldest_epoch" in
|
||||
[0-9]*)
|
||||
now_epoch="$(date -u +%s)"
|
||||
age_days=$(( (now_epoch - oldest_epoch) / 86400 ))
|
||||
[ "$age_days" -ge 0 ] && origin_age="$age_days"
|
||||
;;
|
||||
esac
|
||||
if [ ! -f "$d/.origin" ]; then
|
||||
origin_age="?"
|
||||
if [ -n "$oldest_ts" ]; then
|
||||
if [ "$DATE_IS_GNU" -eq 1 ]; then
|
||||
# Compact grammar (YYYYMMDDTHHMMSSZ) expanded to the RFC 3339 form
|
||||
# GNU date documents as always parseable by -d regardless of locale.
|
||||
# Bash 3.2 substring expansion, no external command needed.
|
||||
oldest_iso="${oldest_ts:0:4}-${oldest_ts:4:2}-${oldest_ts:6:2}T${oldest_ts:9:2}:${oldest_ts:11:2}:${oldest_ts:13:2}Z"
|
||||
oldest_epoch="$(date -u -d "$oldest_iso" '+%s' 2>/dev/null)"
|
||||
else
|
||||
oldest_epoch="$(date -u -j -f '%Y%m%dT%H%M%SZ' "$oldest_ts" '+%s' 2>/dev/null)"
|
||||
fi
|
||||
case "$oldest_epoch" in
|
||||
[0-9]*)
|
||||
now_epoch="$(date -u +%s)"
|
||||
age_days=$(( (now_epoch - oldest_epoch) / 86400 ))
|
||||
[ "$age_days" -ge 0 ] && origin_age="$age_days"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
# Absent, not zero: the question is "who has unhandled mail", and a list of
|
||||
# zeroes answers a different one at every reader's expense. A mailbox holding
|
||||
|
|
|
|||
|
|
@ -905,15 +905,84 @@ check "origin-age: reports the OLDEST pending message's age, not the newest" $?
|
|||
# (e) A message whose filename does not match the timestamp grammar (pre-0.x
|
||||
# or hand-crafted) must never crash the count and must never be misread as
|
||||
# ancient - fail-safe, not fail-open, matching coord-sweep.sh's identical rule.
|
||||
# It must also never be misread as CLAIMED: review finding 11 (2026-08-14)
|
||||
# measured that "-" collapsed two different states - has .origin, and
|
||||
# could-not-measure - into one token a consumer cannot tell apart. "?" is
|
||||
# reserved for could-not-measure from here on; "-" means only "has .origin".
|
||||
mkdir -p "$OADIR/oa-garbage/inbox"
|
||||
echo "not from the grammar" > "$OADIR/oa-garbage/inbox/not-a-timestamp-from-x.md"
|
||||
oa_g_out="$(CLAUDE_COORD_DIR="$OADIR" "$COUNT" 2>/dev/null)"; oa_g_rc=$?
|
||||
[ "$oa_g_rc" -eq 0 ]; check "origin-age: a filename outside the timestamp grammar never crashes the count" $?
|
||||
printf '%s\n' "$oa_g_out" | grep -q "^oa-garbage${TAB}1${TAB}1${TAB}-$"
|
||||
check "origin-age: an unreadable timestamp reports '-', never a fabricated age" $?
|
||||
printf '%s\n' "$oa_g_out" | grep -q "^oa-garbage${TAB}1${TAB}1${TAB}?$"
|
||||
check "origin-age: an unreadable timestamp reports '?', never '-' and never a fabricated age" $?
|
||||
|
||||
# Finding 11's actual complaint, pinned directly: claimed and could-not-measure
|
||||
# must be DIFFERENT tokens, so a consumer can tell them apart without
|
||||
# inferring it from two separate checks above.
|
||||
oa_claimed_tok="$(CLAUDE_COORD_DIR="$OADIR" "$COUNT" 2>/dev/null | awk -F"$TAB" '$1=="oa-claimed"{print $4}')"
|
||||
oa_garbage_tok="$(printf '%s\n' "$oa_g_out" | awk -F"$TAB" '$1=="oa-garbage"{print $4}')"
|
||||
[ "$oa_claimed_tok" = "-" ] && [ "$oa_garbage_tok" = "?" ]
|
||||
check "origin-age: claimed ('-') and could-not-measure ('?') are distinct tokens" $?
|
||||
|
||||
/bin/rm -rf "$OADIR" 2>/dev/null
|
||||
|
||||
# 32. origin-age portability (F11b, review 2026-08-14): the date parse above
|
||||
# used a single BSD-only invocation (`date -u -j -f ...`). GNU date rejects
|
||||
# it outright - measured directly against Ubuntu 24.04 / GNU coreutils 9.4:
|
||||
# `date: invalid option -- 'j'`, exit 1 - so on Linux every mailbox's
|
||||
# origin_age fell into the F11a could-not-measure bucket, machine-wide,
|
||||
# forever; WP1d detection was silently inert on the one platform this public
|
||||
# plugin cannot assume away. The fix branches on `date --version`, which
|
||||
# empirically exits 0 with a GNU banner on GNU date and exits nonzero with
|
||||
# "illegal option" on BSD date (both measured on this machine and on real
|
||||
# GNU date in the same session). This section pins the GNU branch with a
|
||||
# PATH shim that REPLAYS those measured facts rather than inventing new
|
||||
# ones: --version succeeds like real GNU date, a bare -j invocation is
|
||||
# rejected like real GNU date, and -d receives the expanded ISO 8601 string
|
||||
# GNU's documented RFC 3339 support accepts (GNU Coreutils manual, "Options
|
||||
# for date": "RFC 3339 format is always suitable as input for the --date
|
||||
# (-d) ... option, regardless of the current locale" - verified 2026-08-14,
|
||||
# not just reasoned, since no live GNU date remained available this session
|
||||
# to re-measure -d directly).
|
||||
PADIR="$(mktemp -d)"
|
||||
SHIMDIR="$(mktemp -d)"
|
||||
KNOWN_TS="20260101T000000Z"
|
||||
KNOWN_ISO="2026-01-01T00:00:00Z"
|
||||
# Ground truth computed on THIS machine's real (BSD) date, independent of
|
||||
# the code under test - the shim only needs to echo it back correctly.
|
||||
KNOWN_EPOCH="$(date -u -j -f '%Y%m%dT%H%M%SZ' "$KNOWN_TS" '+%s')"
|
||||
|
||||
cat > "$SHIMDIR/date" <<SHIMEOF
|
||||
#!/bin/bash
|
||||
# Replays measured GNU-date behavior (see section 32 comment above) rather
|
||||
# than a speculative mock. Falls through to the real system date for the
|
||||
# flavor-independent "current epoch" call so age math stays correct.
|
||||
if [ "\$1" = "--version" ]; then
|
||||
echo "date (GNU coreutils) 9.4-shim"
|
||||
exit 0
|
||||
fi
|
||||
if [ "\$1" = "-u" ] && [ "\$2" = "-d" ] && [ "\$3" = "$KNOWN_ISO" ] && [ "\$4" = "+%s" ]; then
|
||||
echo "$KNOWN_EPOCH"
|
||||
exit 0
|
||||
fi
|
||||
if [ "\$1" = "-u" ] && [ "\$2" = "+%s" ]; then
|
||||
exec /bin/date -u +%s
|
||||
fi
|
||||
echo "date: invalid option -- 'j'" >&2
|
||||
exit 1
|
||||
SHIMEOF
|
||||
chmod +x "$SHIMDIR/date"
|
||||
|
||||
CLAUDE_COORD_DIR="$PADIR" "$SEND" --to pa-linux --from pas --subject "p1" --message "PORTABLE" >/dev/null
|
||||
age_it "$PADIR" pa-linux PORTABLE "$KNOWN_TS"
|
||||
pa_out="$(PATH="$SHIMDIR:$PATH" CLAUDE_COORD_DIR="$PADIR" "$COUNT" 2>/dev/null)"; pa_rc=$?
|
||||
[ "$pa_rc" -eq 0 ]; check "origin-age portability: a GNU-flavored PATH never crashes the count" $?
|
||||
pa_tok="$(printf '%s\n' "$pa_out" | awk -F"$TAB" '$1=="pa-linux"{print $4}')"
|
||||
[ -n "$pa_tok" ] && [ "$pa_tok" != "-" ] && [ "$pa_tok" != "?" ] && [ "$pa_tok" -ge 1 ] 2>/dev/null
|
||||
check "origin-age portability: under a GNU-date PATH (shimmed from measured behavior), the age is computed, not collapsed to '?'" $?
|
||||
|
||||
/bin/rm -rf "$PADIR" "$SHIMDIR" 2>/dev/null
|
||||
|
||||
echo "----"
|
||||
echo "PASS=$PASS FAIL=$FAIL"
|
||||
[ "$FAIL" -eq 0 ]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue