fix(board): consume coord-count's exit status, not just its stdout

F5 gave coord-count.sh a three-status contract (0 counted, 2 usage error,
3 mailbox root absent) so it could SAY the measurement failed instead of
rendering a reassuring value. board.sh threw that signal away: every call
site piped it into awk, and a pipeline reports the LAST stage's status,
so the producer's exit code was discarded at each one. HAVE_COUNT only
ever tested that the sibling FILE exists - a strictly weaker question.

Measured on 0.30.0 with a mailbox root that does not exist: coord-count
printed "not counted, not zero" and exited 3, while --brief answered
"Ingen repo skylder noen et svar i dag." and --plan emitted no advarsel=
key at all. A gate that can fail whose consumer does not listen is a gate
that does not fall.

COUNT_OK is now the measurement's verdict, and COUNT_WHY carries the exact
reason - including the status number - into all five reporting sites. The
two causes stay distinguishable: "the sibling is missing" and "the world
you named is not there" are different repairs. Any nonzero is caught, not
3 specifically, and a partial stdout captured before a failure is
discarded because a half-count also looks measured. --brief's three
separate coord-count invocations collapse to one: with a status to honour,
three runs would mean three statuses to reconcile.

board.sh stays read-only. The table and --plain views still never invoke
coord-count at all, and COUNT_WHY says so rather than claiming a
measurement nobody attempted.

Bounded gap, stated rather than closed: the table's own INN/ORDRE/FLY
columns count with ls and read 0 for every repo when the mailbox root is
absent. Same defect shape, different source - not a coord-count consumer,
so exit 3 cannot reach it, and the order warned by name against silent
widening.

TDD: board-selftest.sh section 27 written first and RED (7 failures)
before board.sh was touched, behind six known-positive controls and a
ground-truth assertion that coord-count really does exit 3 on that input.
Mutation-verified: restoring `if true` in place of the status test turns
exactly those seven red and leaves all six controls green.

Suites under real /bin/bash 3.2: board 314/314 (was 300), coord 242/242,
route 69/69, orders 110/110, guard 54/54.

No version bump: 0.30.0 shipped two days ago, and this adds no flag, no
exit code and no env var - it repairs an existing consumer. Recommend it
rides the next collection rather than minting a release of its own; the
operator decides, and the catalog owns the tag.

Order: 20260826T115026Z-9982513971-from-.claude

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-08-29 07:10:21 +02:00
commit 4369499e4b
3 changed files with 236 additions and 22 deletions

View file

@ -2446,6 +2446,122 @@ check "F10: the bad root is still named on stderr in the mixed case" $?
/bin/rm -rf "$F10ROOT" "$F10COORD" "$F10EMPTY" "$f10a_err" "$f10b_err" \
"$f10c_err" "$f10d_err" 2>/dev/null
# --- 27. board must CONSUME coord-count.sh's exit 3, not just its stdout ----
# Order 20260826T115026Z-9982513971 (.claude, operator decision 2026-08-26).
# F5 gave coord-count.sh a three-status contract - 0 counted, 2 usage error,
# 3 mailbox root absent - so it can now SAY that the measurement failed instead
# of rendering a reassuring value. board.sh threw that signal away: every call
# site piped it into awk (`bash coord-count.sh 2>/dev/null | awk ...`), which
# discards the producer's status, and HAVE_COUNT only ever tested that the
# SIBLING FILE exists. A gate that can fail whose consumer does not listen is a
# gate that does not fall.
#
# Measured on the shipped 0.30.0 script before this section was written, with a
# mailbox root that does not exist: coord-count.sh printed "mailbox root does
# not exist ... (not counted, not zero)" and exited 3, while board.sh --brief
# answered "Ingen repo skylder noen et svar i dag." and --plan emitted no
# advarsel= key at all. A failed measurement rendered as a confident zero.
#
# The two causes must stay DISTINGUISHABLE, for the same reason coord-count's
# own 2 and 3 do: "the sibling is missing" and "the world you named is not
# there" are different repairs, and section 17 pins the first one.
F3ROOT="$(mktemp -d)"
mkrepo "$F3ROOT/f3-debtor"
{
echo "# STATE - f3-debtor"
echo ""
printf '## %s NESTE %s START HER\n' "$HAND" "$EMDASH"
echo "<!-- board: status=in-progress; blocked-on=-; next-cost=Sonnet 5/high -->"
echo "Noe a gjore."
} > "$F3ROOT/f3-debtor/STATE.md"
# --- Known-positive control 1: a mailbox root that EXISTS and holds a debt.
# Without this, a guard that warned on every invocation would pass the defect
# checks below while proving nothing.
F3GOOD="$(mktemp -d)"
mkdir -p "$F3GOOD/f3-debtor/inbox"
cat > "$F3GOOD/f3-debtor/inbox/20260101T000000Z-1-from-somebody.md" <<'EOF'
---
from: somebody
to: f3-debtor
subject: needs an answer
date: 2026-01-01T00:00:00Z
reply-expected: yes
---
Please respond.
EOF
F3GB="$(CLAUDE_COORD_DIR="$F3GOOD" "$BOARD" --roots "$F3ROOT" --brief 2>/dev/null)"
printf '%s' "$F3GB" | grep -q 'f3-debtor'
check "exit3: control - an existing mailbox root still names the debtor in --brief" $?
printf '%s' "$F3GB" | grep -qi 'coord-count'; [ $? -ne 0 ]
check "exit3: control - a successful measurement warns about nothing" $?
F3GP="$(CLAUDE_COORD_DIR="$F3GOOD" "$BOARD" --roots "$F3ROOT" --plan 2>/dev/null)"
printf '%s' "$F3GP" | grep -q '^advarsel='; [ $? -ne 0 ]
check "exit3: control - a successful measurement emits no advarsel= key" $?
# --- Known-positive control 2: an EXISTING but empty mailbox root. A genuine
# zero must stay a zero - this is the reading the defect case is meant to stop
# being indistinguishable from, so it has to keep working.
F3EMPTY="$(mktemp -d)"
F3EB="$(CLAUDE_COORD_DIR="$F3EMPTY" "$BOARD" --roots "$F3ROOT" --brief 2>/dev/null)"
printf '%s' "$F3EB" | grep -q '^Ingen repo skylder noen et svar i dag\.$'
check "exit3: control - an existing but EMPTY mailbox root still claims zero debt" $?
printf '%s' "$F3EB" | grep -qi 'coord-count'; [ $? -ne 0 ]
check "exit3: control - an empty mailbox root is not reported as a failure" $?
# --- Ground truth for the defect case, asserted before anything depends on it:
# coord-count.sh really does exit 3 on this input. If a future coord-count
# stops doing that, this section must go red rather than silently disarm.
F3MISS="$F3ROOT/no-such-mailbox-root"
CLAUDE_COORD_DIR="$F3MISS" /bin/bash "$DIR/coord-count.sh" >/dev/null 2>&1
[ "$?" -eq 3 ]
check "exit3: ground truth - coord-count.sh exits 3 for an absent mailbox root" $?
# --- The defect.
F3B="$(CLAUDE_COORD_DIR="$F3MISS" "$BOARD" --roots "$F3ROOT" --brief 2>/dev/null)"
printf '%s' "$F3B" | grep -q '^Ingen repo skylder noen et svar i dag\.$'; [ $? -ne 0 ]
check "exit3: --brief does not claim zero debt from a measurement that failed" $?
printf '%s' "$F3B" | grep -qi 'coord-count.sh avsluttet 3'
check "exit3: --brief names the failed measurement and its status" $?
printf '%s' "$F3B" | grep -qi 'coord-count.sh mangler'; [ $? -ne 0 ]
check "exit3: a failed measurement is NOT reported as a missing sibling" $?
F3P="$(CLAUDE_COORD_DIR="$F3MISS" "$BOARD" --roots "$F3ROOT" --plan 2>/dev/null)"
printf '%s' "$F3P" | grep -q '^advarsel=coord-count.sh avsluttet 3'
check "exit3: --plan carries a machine-readable advarsel= key, not a silent omission" $?
F3IP="$(CLAUDE_COORD_DIR="$F3MISS" "$BOARD" --roots "$F3ROOT" --inbox-plan 2>/dev/null)"
printf '%s' "$F3IP" | grep -q '^advarsel=coord-count.sh avsluttet 3'
check "exit3: --inbox-plan carries a machine-readable advarsel= key" $?
# The two --brief subsections that ALSO rest on coord-count.sh must not render
# their absence as an answer either: "no orphan mailboxes" and "no dead letters"
# are claims, and neither was measured here.
printf '%s' "$F3B" | grep -qi 'UTENFOR REPO-SKANNEN'
check "exit3: --brief's orphan-mailbox section says it could not check" $?
printf '%s' "$F3B" | grep -qi 'ALDRI LEST'
check "exit3: --brief's dead-letter section says it could not check" $?
# A nonzero that is NOT 3 must still be caught: the rule is "the measurement
# failed", not "3 specifically". Simulated with a stub sibling in a scratch
# copy, the same technique section 17 uses for the missing-sibling case.
F3SCRATCH="$(mktemp -d)"
cp "$DIR/board.sh" "$F3SCRATCH/board.sh"
cp "$DIR/route.sh" "$F3SCRATCH/route.sh"
cat > "$F3SCRATCH/coord-count.sh" <<'EOF'
#!/bin/bash
echo "stub: something went wrong" >&2
exit 2
EOF
chmod +x "$F3SCRATCH/board.sh" "$F3SCRATCH/route.sh" "$F3SCRATCH/coord-count.sh"
F3SP="$(CLAUDE_COORD_DIR="$F3GOOD" "$F3SCRATCH/board.sh" --roots "$F3ROOT" --plan 2>/dev/null)"
printf '%s' "$F3SP" | grep -q '^advarsel=coord-count.sh avsluttet 2'
check "exit3: a nonzero that is not 3 is caught too, and names its own status" $?
/bin/rm -rf "$F3ROOT" "$F3GOOD" "$F3EMPTY" "$F3SCRATCH" 2>/dev/null
echo ""
echo "board-selftest: $PASS passed, $FAIL failed"
[ "$FAIL" -eq 0 ] || exit 1