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:
parent
3e4a3bc62a
commit
4369499e4b
3 changed files with 236 additions and 22 deletions
53
CLAUDE.md
53
CLAUDE.md
|
|
@ -411,7 +411,7 @@ marketplace plugin. Three components, one boundary:
|
|||
- **Board (`scripts/board.sh`):** cross-repo attention board. Reads STATE.md
|
||||
next-step blocks + board lines, `git status`, and mailbox pending counts, and
|
||||
prints one line per repo. Read-only by construction: it writes to no repo, no
|
||||
STATE.md and no mailbox. Pinned by `board-selftest.sh` (300 checks).
|
||||
STATE.md and no mailbox. Pinned by `board-selftest.sh` (314 checks).
|
||||
|
||||
**It lives here because the mailbox is one of its three inputs, and it carries
|
||||
the same axis distinction the mailbox does.** A pending count means *others
|
||||
|
|
@ -631,6 +631,55 @@ marketplace plugin. Three components, one boundary:
|
|||
`coord-inbox` or `board`. The dependency runs one way: the driver consumes the
|
||||
plan, the plan never knows a terminal exists.
|
||||
|
||||
**Order 20260826T115026Z-9982513971 (2026-08-26): board consumed
|
||||
`coord-count.sh`'s STDOUT and threw away its EXIT STATUS, so the whole
|
||||
three-status contract F5 had just built stopped at the producer.** Every call
|
||||
site piped it (`bash coord-count.sh 2>/dev/null | awk ...`), and a pipeline
|
||||
reports the LAST stage's status, so `exit 3` - "the mailbox root you named is
|
||||
not there, not counted, not zero" - was discarded at each one. `HAVE_COUNT`
|
||||
only ever tested that the SIBLING FILE exists, which is a strictly weaker
|
||||
question. Measured on the shipped 0.30.0 script against a mailbox root that
|
||||
does not exist: `coord-count.sh` 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. It was carved out of F5 deliberately
|
||||
rather than swept in - that session scoped itself to `coord-count.sh` and said
|
||||
widening in silence was not its call, and the operator agreed - which is why
|
||||
this is its own order and its own commit.
|
||||
|
||||
**`COUNT_OK` is the measurement's verdict; `HAVE_COUNT` stays, and the two
|
||||
messages stay DISTINCT.** "The sibling is missing" is repaired by restoring a
|
||||
file, "the world you named is not there" by fixing `CLAUDE_COORD_DIR` - the
|
||||
same reason `coord-count.sh`'s own 2 and 3 are different statuses, and a
|
||||
reader handed one "unavailable" for both cannot tell which repair to make.
|
||||
`$COUNT_WHY` carries the exact reason, including the status number, into all
|
||||
five reporting sites, and any nonzero is caught - the rule is "the measurement
|
||||
failed", not "3 specifically". A partial stdout captured before a failure is
|
||||
DISCARDED: a half-count is the same defect one layer down, since it also looks
|
||||
measured. Selftest section 27 pins the failure cases behind SIX known-positive
|
||||
controls (an existing root still names its debtor; a successful measurement
|
||||
warns about nothing; an existing but EMPTY root still claims zero debt) plus a
|
||||
ground-truth assertion that `coord-count.sh` really does exit 3 on that input,
|
||||
so a future coord-count that stops doing so fails the section rather than
|
||||
silently disarming it. Mutation-verified: restoring `if true` in place of the
|
||||
status test turns exactly those seven checks red and leaves all six controls
|
||||
green.
|
||||
|
||||
**The three separate `coord-count.sh` invocations `--brief` used to make are
|
||||
now one.** With a status to honour, three runs would mean three statuses to
|
||||
reconcile; `coord-count.sh` writes nothing, so one reading is the same reading.
|
||||
The table and `--plain` views still never invoke it at all - they read the
|
||||
mailbox only through what `RECORDS` already counted, and `$COUNT_WHY` says so
|
||||
in those words rather than claiming a measurement nobody attempted.
|
||||
|
||||
**Bounded gap, stated rather than closed:** the TABLE's own `INN`/`ORDRE`/`FLY`
|
||||
columns count with `ls "$COORD/$name/..."`, which yields 0 for every repo when
|
||||
the mailbox root is absent - the same "failed measurement renders as a
|
||||
reassuring value" shape, one source over. It is NOT a `coord-count.sh`
|
||||
consumer, so consuming exit 3 cannot reach it, and the order scoped itself to
|
||||
exit 3 and warned by name against silent widening. Naming it here is the
|
||||
point: the next session finds a decision, not an oversight.
|
||||
|
||||
It also cross-checks itself against `coord-count.sh`, and that is not
|
||||
belt-and-braces. The repo scan and the mailbox are two different populations:
|
||||
a mailbox can carry a name no scan will ever produce — a declared non-git
|
||||
|
|
@ -1030,7 +1079,7 @@ obligations in another repo.
|
|||
builtins only in hook and tests.
|
||||
- TDD: no behavior change without a failing selftest check first.
|
||||
`bash scripts/coord-selftest.sh` must exit 0 (242/242),
|
||||
`bash scripts/board-selftest.sh` must exit 0 (300/300),
|
||||
`bash scripts/board-selftest.sh` must exit 0 (314/314),
|
||||
`bash scripts/route-selftest.sh` must exit 0 (69/69),
|
||||
`bash scripts/orders-selftest.sh` must exit 0 (110/110) and
|
||||
`bash scripts/state-line-guard-selftest.sh` must exit 0 (54/54).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue