fix(board): a missing coord-count.sh sibling warns instead of lying

Review finding 1 (docs/2026-08-14-confident-zero-review.md), tier 1 #2,
prioritized by .claude 2026-08-14T21:24:16Z coord message.

board.sh:381,395,409,516-517 gated four coord-count.sh invocations on
`[ -f "$SELFDIR/coord-count.sh" ]` and silently continued with empty
lookups when it failed - the 0.12.1 deployed-copy incident shape, a real
deployment state, not hypothetical. Reproduced exactly as the review
measured it (copy board.sh + route.sh to a scratch dir without
coord-count.sh, fixture mailbox with one reply-owing message): --brief
claimed "Ingen repo skylder noen et svar i dag." and then actively
mislabeled the reply-owing repo as "bare FYI-post" - a false statement,
not merely an absent one, since inbox>0/owed==0 looks identical whether
owed is genuinely 0 or simply uncomputed. --inbox-plan silently rendered
0 blocks instead of 1.

Fixed by computing HAVE_COUNT once and checking it everywhere a missing
sibling would otherwise read as "checked, found nothing": brief() no
longer enters the zero-debt/FYI-mislabel branch when the sibling is
missing, printing a warning instead; brief_orphans() and
brief_deadletters() warn instead of silently returning nothing (the
review's "dead-letter and orphan cross-checks vanish silently too");
plan() and inbox_plan() emit a key=value `advarsel=` line (not a '#'
comment - the driver consumer drops comment lines by rule, same
reasoning as the existing fokus= disclosure). plan()'s `keep` membership
logic is deliberately untouched: changing which repos appear in --plan
under this condition is a policy change to a format with a second
consumer in another repo that no test here can hold stable, and is a
proposal for the operator, not this fix.

Verified red before fixing: the reviewer's exact reproduction against
`git show HEAD:scripts/board.sh` (pre-fix) confirmed the mislabel and
the silent 0-block --inbox-plan, so the new board-selftest.sh section 17
fixture is red for the right reason, not by accident. Smoke-tested
against the real ~/repos tree (coord-count.sh present, HAVE_COUNT=1):
unchanged output, no warning.

All four selftest suites green: coord 200/200, board 183/183 (5 new
checks in section 17), route 69/69, guard 21/21.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F1mzsaUmjqFHArbArG7EpF
This commit is contained in:
Kjell Tore Guttormsen 2026-08-14 23:53:31 +02:00
commit 87194fe574
2 changed files with 104 additions and 6 deletions

View file

@ -1532,6 +1532,61 @@ check "a mailbox WITH .origin is never flagged, regardless of message age" $?
/bin/rm -rf "$DL_ROOT" "$DL_COORD" 2>/dev/null
# --- 17. Missing coord-count.sh sibling never reads as "checked, zero debt" -
# Review finding 1 (2026-08-14), reproduced exactly as measured: copy board.sh
# + route.sh to a scratch dir WITHOUT coord-count.sh (the 0.12.1 deployed-copy
# incident shape), point it at a fixture mailbox where one repo holds a
# reply-owing message. Before the fix, the copy's --brief claimed "Ingen repo
# skylder noen et svar i dag." and then actively mislabeled the reply-owing
# repo as "bare FYI-post" - a false statement, not merely an absent one - and
# --inbox-plan silently rendered 0 blocks instead of 1. This section pins the
# fix's actual claim: a warning, never a confident zero or a mislabel.
SIB_ROOT="$(mktemp -d)"
SIB_COORD="$(mktemp -d)"
SIB_SCRATCH="$(mktemp -d)"
cp "$DIR/board.sh" "$SIB_SCRATCH/board.sh"
cp "$DIR/route.sh" "$SIB_SCRATCH/route.sh"
chmod +x "$SIB_SCRATCH/board.sh" "$SIB_SCRATCH/route.sh"
# coord-count.sh deliberately not copied here.
mkrepo "$SIB_ROOT/repo-a"
{
echo "# STATE - repo-a"
echo ""
printf '## %s NESTE %s START HER\n' "$HAND" "$EMDASH"
echo "<!-- board: status=in-progress; blocked-on=-; next-cost=sonnet/high -->"
echo "Noe a gjore."
} > "$SIB_ROOT/repo-a/STATE.md"
mkdir -p "$SIB_COORD/repo-a/inbox"
cat > "$SIB_COORD/repo-a/inbox/20260101T000000Z-1-from-somebody.md" <<'EOF'
---
from: somebody
to: repo-a
subject: needs an answer
date: 2026-01-01T00:00:00Z
reply-expected: yes
---
Please respond.
EOF
SIBBRIEF="$(CLAUDE_COORD_DIR="$SIB_COORD" "$SIB_SCRATCH/board.sh" --roots "$SIB_ROOT" --brief 2>/dev/null)"
printf '%s' "$SIBBRIEF" | grep -qi 'bare FYI-post'; [ $? -ne 0 ]
check "missing sibling: --brief never mislabels a reply-owing repo as FYI-only" $?
printf '%s' "$SIBBRIEF" | grep -qi 'coord-count.sh mangler'
check "missing sibling: --brief surfaces a warning instead of a confident zero" $?
printf '%s' "$SIBBRIEF" | grep -qi '^Ingen repo skylder noen et svar i dag\.$'; [ $? -ne 0 ]
check "missing sibling: --brief does not print the debt-free claim it could not verify" $?
SIBPLAN="$(CLAUDE_COORD_DIR="$SIB_COORD" "$SIB_SCRATCH/board.sh" --roots "$SIB_ROOT" --plan 2>/dev/null)"
printf '%s' "$SIBPLAN" | grep -q '^advarsel=coord-count.sh mangler'
check "missing sibling: --plan carries a machine-readable warning key" $?
SIBIP="$(CLAUDE_COORD_DIR="$SIB_COORD" "$SIB_SCRATCH/board.sh" --roots "$SIB_ROOT" --inbox-plan 2>/dev/null)"
printf '%s' "$SIBIP" | grep -q '^advarsel=coord-count.sh mangler'
check "missing sibling: --inbox-plan carries a machine-readable warning key, not a silent 0 blocks" $?
/bin/rm -rf "$SIB_ROOT" "$SIB_COORD" "$SIB_SCRATCH" 2>/dev/null
echo ""
echo "board-selftest: $PASS passed, $FAIL failed"
[ "$FAIL" -eq 0 ] || exit 1

View file

@ -377,8 +377,16 @@ trap '/bin/rm -f "$RECORDS" "$UNBLOCKS" "$OWED" "$ALLMAIL" "$DEADLETTERS" 2>/dev
# mailbox beyond what RECORDS already read, and paying an extra coord-count.sh
# subprocess on every invocation would tax that path for a lookup it never
# uses.
# HAVE_COUNT, computed once: a missing sibling (the 0.12.1 deployed-copy
# incident shape - review finding 1, 2026-08-14) must never read as "coord-
# count.sh ran and found nothing". Every site below that would otherwise
# treat an empty $OWED/$DEADLETTERS/$ALLMAIL as a confident zero checks this
# flag first and warns instead - see brief(), plan(), inbox_plan().
HAVE_COUNT=1
[ -f "$SELFDIR/coord-count.sh" ] || HAVE_COUNT=0
: > "$OWED"
if { [ "$BRIEF" -eq 1 ] || [ "$PLAN" -eq 1 ]; } && [ -f "$SELFDIR/coord-count.sh" ]; then
if { [ "$BRIEF" -eq 1 ] || [ "$PLAN" -eq 1 ]; } && [ "$HAVE_COUNT" -eq 1 ]; then
ow_tab="$(printf '\t')"
bash "$SELFDIR/coord-count.sh" 2>/dev/null \
| awk -F"$ow_tab" -v OFS='|' '{print $1, $3}' > "$OWED"
@ -392,7 +400,7 @@ fi
# 3-day threshold reach $DEADLETTERS, so brief_deadletters() below never has to
# re-parse the raw column or re-apply the threshold itself.
: > "$DEADLETTERS"
if [ "$BRIEF" -eq 1 ] && [ -f "$SELFDIR/coord-count.sh" ]; then
if [ "$BRIEF" -eq 1 ] && [ "$HAVE_COUNT" -eq 1 ]; then
dl_tab="$(printf '\t')"
bash "$SELFDIR/coord-count.sh" 2>/dev/null \
| awk -F"$dl_tab" -v OFS='|' '$4 != "-" && $4+0 >= 3 {print $1, $4}' > "$DEADLETTERS"
@ -406,7 +414,7 @@ fi
# gated: an extra coord-count.sh subprocess on every table/plain invocation
# would tax a path that never reads it.
: > "$ALLMAIL"
if [ "$INBOX_PLAN" -eq 1 ] && [ -f "$SELFDIR/coord-count.sh" ]; then
if [ "$INBOX_PLAN" -eq 1 ] && [ "$HAVE_COUNT" -eq 1 ]; then
am_tab="$(printf '\t')"
bash "$SELFDIR/coord-count.sh" 2>/dev/null \
| awk -F"$am_tab" -v OFS='|' '{print $1, $2, $3}' > "$ALLMAIL"
@ -513,10 +521,13 @@ brief_cmd() {
# coord-count.sh is the right source and the only safe one: it counts without
# delivering, where coord-inbox.sh would mark broadcasts seen just by looking.
brief_orphans() {
bo_count="$SELFDIR/coord-count.sh"
[ -f "$bo_count" ] || return 0
if [ "$HAVE_COUNT" -ne 1 ]; then
echo ""
echo "UTENFOR REPO-SKANNEN: kan ikke sjekke - coord-count.sh mangler."
return 0
fi
bo_tab="$(printf '\t')"
bo_out="$(bash "$bo_count" 2>/dev/null \
bo_out="$(bash "$SELFDIR/coord-count.sh" 2>/dev/null \
| awk -F"$bo_tab" '$2+0>0 {print $1"'"$bo_tab"'"$2}' \
| while IFS="$bo_tab" read -r bo_name bo_n; do
[ -n "$bo_name" ] || continue
@ -539,6 +550,11 @@ brief_orphans() {
# claimed-repo in board-selftest.sh section 16 both do). The action half
# (report to sender / retract) is unapproved design and is not built here.
brief_deadletters() {
if [ "$HAVE_COUNT" -ne 1 ]; then
echo ""
echo "ALDRI LEST: kan ikke sjekke - coord-count.sh mangler."
return 0
fi
[ -s "$DEADLETTERS" ] || return 0
echo ""
echo "ALDRI LEST - postkasser uten .origin med post eldre enn 3 dogn:"
@ -568,6 +584,19 @@ brief() {
echo "Kilder: STATE.md (NESTE + route-linje), git, coord-innboks. 0 modellkall."
echo ""
# A missing coord-count.sh sibling (review finding 1, 2026-08-14 - the
# 0.12.1 deployed-copy incident shape) must never be read as "checked, zero
# debt": $OWED is empty for the same reason it would be on a genuinely
# debt-free day, and continuing into the branch below actively mislabeled a
# reply-owing repo as FYI-only (inbox>0, owed==0 looks identical either way).
if [ "$HAVE_COUNT" -ne 1 ]; then
echo "ADVARSEL: coord-count.sh mangler - kan ikke avgjore hvem som skylder svar."
echo "Gjeldstall er IKKE null, bare ikke beregnet. Se ${SELFDIR}/coord-count.sh."
brief_orphans
brief_deadletters
return 0
fi
if [ "${n_owe:-0}" -eq 0 ]; then
# Only the debt claim, never "no repo has unhandled inbox": n_owe counts
# OWED repos since 0.22.0, so this branch can fire while a repo still
@ -909,6 +938,13 @@ plan() {
# consumer drops every comment line by rule - a disclosure written as a
# comment would reach the operator on the terminal path and vanish on the
# driver path, which is the one case where the cutoff is applied unseen.
# Same rule applies to the coord-count.sh warning below (review finding 1,
# 2026-08-14): a missing sibling makes `owed` 0 for every repo above, which
# can silently drop a done/deferred debtor from group 2 - `keep` itself is
# intentionally left unchanged (a policy change to a format the operator
# decided has a second consumer elsewhere), but the driver must be able to
# see that the omission happened rather than read a shorter list as complete.
[ "$HAVE_COUNT" -eq 1 ] || printf 'advarsel=coord-count.sh mangler - gjeldsvekting (gruppe 2, inbox:N) er ikke beregnet\n'
if [ -n "$FOCUS" ]; then
fp_state="$(awk -F'|' '{print $10}' "$RECORDS" | while read -r fp_sd; do
[ -n "$fp_sd" ] && [ -f "$fp_sd/STATE.md" ] && echo x
@ -1023,6 +1059,13 @@ inbox_plan() {
echo "# pending=meldinger totalt, owed=derav skylder svar (resten er FYI)."
echo ""
# Review finding 1 (2026-08-14): a missing coord-count.sh sibling leaves
# $ALLMAIL empty, and the population below is entirely $ALLMAIL rows - the
# measured effect was 1 block silently becoming 0, not an empty population
# rendered as such. key=value, not '#', for the same reason as plan()'s
# advarsel= line: the driver consumer drops comment lines by rule.
[ "$HAVE_COUNT" -eq 1 ] || printf 'advarsel=coord-count.sh mangler - populasjonen er ikke beregnet, ikke tom\n'
ipn=0
while IFS='|' read -r owed pend name cls dir status cost neste; do
[ -n "$name" ] || continue