fix(coord-send): reply mode claimed "marked handled" without checking
coord-send.sh ran coord-done under `>/dev/null 2>&1` and then printed the handled claim unconditionally. Measured with a stub coord-done exiting 1: the original stayed in the inbox, no archive/ was created, and coord-send still exited 0 saying "marked handled" - a false success in the message transport itself, which is why every reply had to be verified by hand. The predicate is deliberately wider than the exit code: coord-done exits 0 when it archives nothing (an unknown name is idempotently fine by its own contract), so an exit-code-only fix still certifies a message that never moved. The check is exit 0 AND the original no longer being at $COORD/$FROM/inbox/$REPLYTO - recomputed rather than reusing $REPLY_ORIG, which resolves to the inbox OR the archive, so replying to an already archived original moves nothing and must not warn. Failure is exit 1, a new status: the reply WAS delivered and re-sending it would duplicate it, so 2 stays the nothing-was-written status. Selftest section 34 (14 checks, red first) pins all four cases: coord-done fails outright, coord-done exits 0 without moving, the real happy path, and an archive-path reply. coord-selftest 206 -> 220. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ett8uHMDLir6trFaMzrYRu
This commit is contained in:
parent
b5c860eb03
commit
21e2873e21
3 changed files with 130 additions and 4 deletions
23
CLAUDE.md
23
CLAUDE.md
|
|
@ -16,7 +16,7 @@ marketplace plugin. Three components, one boundary:
|
|||
`coord-done.sh` archives, `coord-count.sh` counts without delivering,
|
||||
`coord-sweep.sh` closes the aged FYI backlog machine-wide.
|
||||
Everything is pinned by `coord-selftest.sh`
|
||||
(206 checks, throwaway mailbox via `CLAUDE_COORD_DIR`).
|
||||
(220 checks, throwaway mailbox via `CLAUDE_COORD_DIR`).
|
||||
|
||||
**`ktg-plugin-marketplace` is a RETIRED `--to` address (operator decision
|
||||
2026-08-15), rejected rather than redirected.** It is a polyrepo directory,
|
||||
|
|
@ -30,6 +30,25 @@ marketplace plugin. Three components, one boundary:
|
|||
mistake is made. Only `--to` is retired, not `--from` - the defect was mail
|
||||
*arriving* there, never mail claiming to *originate* there.
|
||||
|
||||
**`coord-send --reply-to` asserts "marked handled" against GROUND TRUTH, and
|
||||
the exit code alone is NOT that ground truth.** The line used to print
|
||||
unconditionally with `coord-done`'s output discarded (`>/dev/null 2>&1`),
|
||||
so the one line a session relies on to close a reply debt was false at the
|
||||
moment it was printed — measured with a stub `coord-done` exiting 1: original
|
||||
still in the inbox, no `archive/`, exit 0, "marked handled". Every reply this
|
||||
repo sent had to be verified by hand afterwards, which is what a false
|
||||
success in the TRANSPORT costs. The check is `exit 0` **and** the original no
|
||||
longer being at `$COORD/$FROM/inbox/$REPLYTO`, because `coord-done` exits 0
|
||||
when it archives nothing (an unknown name is idempotently fine by its own
|
||||
contract), so a nonzero-exit test still certifies a message that never moved.
|
||||
The path is recomputed rather than reusing `$REPLY_ORIG`, which resolves to
|
||||
the inbox OR the archive — replying to an already-archived original moves
|
||||
nothing and must not warn. Failure is exit **1**, a new status: the reply WAS
|
||||
delivered and re-sending would duplicate it, so 2 stays the
|
||||
nothing-was-written status it has always been. Selftest section 34 pins all
|
||||
four cases (fails outright / exits 0 without moving / real happy path /
|
||||
archive-path reply).
|
||||
|
||||
**`coord-sweep.sh` is the only path that closes a message with no human in
|
||||
the loop, and every constraint on it follows from that.** It may close exactly
|
||||
one mechanically decidable class - `reply-expected: no`, older than the grace
|
||||
|
|
@ -460,7 +479,7 @@ obligations in another repo.
|
|||
- Zero dependencies everywhere: bash + coreutils in the engine, `node:`
|
||||
builtins only in hook and tests.
|
||||
- TDD: no behavior change without a failing selftest check first.
|
||||
`bash scripts/coord-selftest.sh` must exit 0 (206/206),
|
||||
`bash scripts/coord-selftest.sh` must exit 0 (220/220),
|
||||
`bash scripts/board-selftest.sh` must exit 0 (183/183),
|
||||
`bash scripts/route-selftest.sh` must exit 0 (69/69) and
|
||||
`bash scripts/state-line-guard-selftest.sh` must exit 0 (23/23).
|
||||
|
|
|
|||
|
|
@ -1014,6 +1014,81 @@ rre="$("$SEND" --from somerepo --reply-to "$rfn" --message "reply" 2>&1)"; rc=$?
|
|||
[ "$rc" -eq 2 ]; check "retired: replying to a message FROM the retired address also refuses" $?
|
||||
printf '%s' "$rre" | grep -q "catalog"; check "retired: the reply-path refusal also points at catalog" $?
|
||||
|
||||
# 34. Reply mode claims the original was handled - and the claim is asserted
|
||||
# against GROUND TRUTH, not against the call having been made. coord-send
|
||||
# invoked coord-done under `>/dev/null 2>&1` and then printed "marked handled"
|
||||
# unconditionally: the review's stub-coord-done repro (docs/2026-08-14-
|
||||
# confident-zero-review.md, finding 9) showed exit 0 plus a false success line
|
||||
# while the original sat untouched in the inbox and no archive/ existed. That
|
||||
# is a false success in the message TRANSPORT itself, which is why every reply
|
||||
# this repo sent had to be verified by hand afterwards.
|
||||
#
|
||||
# THE PREDICATE IS DELIBERATELY WIDER THAN "CHECK THE EXIT CODE", and a later
|
||||
# session must not narrow it back. coord-done exits 0 when it archives NOTHING
|
||||
# (a name that is not in the inbox is idempotently fine, :54 and :70), so an
|
||||
# exit-code-only check still certifies a message that never moved - case (b)
|
||||
# below fails against that narrower fix and passes only against this one. The
|
||||
# ground truth is the inbox path itself.
|
||||
#
|
||||
# The path recomputed here is `$COORD/$FROM/inbox/$REPLYTO`, NOT `$REPLY_ORIG`:
|
||||
# that variable resolves to the inbox OR the archive (coord-send.sh:129-130),
|
||||
# so replying to an already-archived original leaves the file exactly where
|
||||
# `$REPLY_ORIG` points and a `[ ! -e "$REPLY_ORIG" ]` test would warn on every
|
||||
# legitimate archive-path reply - case (d) pins that it does not.
|
||||
#
|
||||
# The stubbing works because coord-send resolves its sibling by `dirname $0`:
|
||||
# a copy of the script in a scratch directory picks up whatever coord-done.sh
|
||||
# sits next to it.
|
||||
F9DIR="$(mktemp -d)"
|
||||
SBOX="$(mktemp -d)"
|
||||
cp "$SEND" "$SBOX/coord-send.sh" && chmod +x "$SBOX/coord-send.sh"
|
||||
F9SEND="$SBOX/coord-send.sh"
|
||||
|
||||
CLAUDE_COORD_DIR="$F9DIR" "$F9SEND" --to f9repo --from f9sender --subject "orig" --message "F9-BODY" >/dev/null
|
||||
f9base="$(basename "$(ls "$F9DIR"/f9repo/inbox/*.md 2>/dev/null | head -1)")"
|
||||
[ -n "$f9base" ]; check "F9 setup: original delivered to f9repo" $?
|
||||
|
||||
# (a) coord-done FAILS outright. The reply is still delivered - that half was
|
||||
# never in doubt - but the handled claim must not be printed, the failure must
|
||||
# reach stderr, and the exit status must stop a caller from recording the debt
|
||||
# as closed.
|
||||
printf '#!/bin/bash\nexit 1\n' > "$SBOX/coord-done.sh"; chmod +x "$SBOX/coord-done.sh"
|
||||
f9a="$(CLAUDE_COORD_DIR="$F9DIR" "$F9SEND" --from f9repo --reply-to "$f9base" --message "reply-a" 2>&1)"; f9a_rc=$?
|
||||
printf '%s' "$f9a" | grep -q "delivered to f9sender"; check "F9(a): the reply itself is still delivered when coord-done fails" $?
|
||||
printf '%s' "$f9a" | grep -q "marked handled"; [ $? -ne 0 ]; check "F9(a): no false 'marked handled' claim when coord-done exits nonzero" $?
|
||||
printf '%s' "$f9a" | grep -qi "still pending"; check "F9(a): the failure is reported, naming the original as still pending" $?
|
||||
[ "$f9a_rc" -ne 0 ]; check "F9(a): exit status is nonzero so a caller cannot record the debt as closed" $?
|
||||
[ -e "$F9DIR/f9repo/inbox/$f9base" ]; check "F9(a): ground truth - the original really is still in the inbox" $?
|
||||
|
||||
# (b) coord-done exits 0 and moves NOTHING. This is the case an exit-code-only
|
||||
# fix passes and this one must fail: coord-done's own contract exits 0 for a
|
||||
# name it did not find, so the exit code alone cannot distinguish "closed" from
|
||||
# "never touched".
|
||||
printf '#!/bin/bash\nexit 0\n' > "$SBOX/coord-done.sh"; chmod +x "$SBOX/coord-done.sh"
|
||||
f9b="$(CLAUDE_COORD_DIR="$F9DIR" "$F9SEND" --from f9repo --reply-to "$f9base" --message "reply-b" 2>&1)"; f9b_rc=$?
|
||||
printf '%s' "$f9b" | grep -q "marked handled"; [ $? -ne 0 ]; check "F9(b): coord-done exiting 0 without moving the file is NOT accepted as handled" $?
|
||||
[ "$f9b_rc" -ne 0 ]; check "F9(b): exit status is nonzero for the silent no-op too" $?
|
||||
[ -e "$F9DIR/f9repo/inbox/$f9base" ]; check "F9(b): ground truth - the original is still in the inbox" $?
|
||||
|
||||
# (c) The real coord-done. The happy path is unchanged: the claim is printed,
|
||||
# exit stays 0, and the file is where the claim says it is.
|
||||
cp "$DONE" "$SBOX/coord-done.sh" && chmod +x "$SBOX/coord-done.sh"
|
||||
f9c="$(CLAUDE_COORD_DIR="$F9DIR" "$F9SEND" --from f9repo --reply-to "$f9base" --message "reply-c" 2>&1)"; f9c_rc=$?
|
||||
printf '%s' "$f9c" | grep -q "marked handled"; check "F9(c): the real coord-done still gets the handled claim" $?
|
||||
[ "$f9c_rc" -eq 0 ]; check "F9(c): happy path still exits 0" $?
|
||||
[ ! -e "$F9DIR/f9repo/inbox/$f9base" ] && [ -e "$F9DIR/f9repo/archive/$f9base" ]
|
||||
check "F9(c): ground truth - the original moved from inbox to archive" $?
|
||||
|
||||
# (d) Reply to an ALREADY-archived original (coord-send.sh:130 resolves it
|
||||
# there). coord-done archives nothing and exits 0, and that is correct: the
|
||||
# message is handled. A predicate written against `$REPLY_ORIG` instead of the
|
||||
# inbox path would warn here, on a reply that is entirely legitimate.
|
||||
f9d="$(CLAUDE_COORD_DIR="$F9DIR" "$F9SEND" --from f9repo --reply-to "$f9base" --message "reply-d" 2>&1)"; f9d_rc=$?
|
||||
[ "$f9d_rc" -eq 0 ]; check "F9(d): replying to an already-archived original still exits 0" $?
|
||||
printf '%s' "$f9d" | grep -qi "still pending"; [ $? -ne 0 ]; check "F9(d): and does not warn - nothing is pending" $?
|
||||
|
||||
/bin/rm -rf "$F9DIR" "$SBOX" 2>/dev/null
|
||||
|
||||
echo "----"
|
||||
echo "PASS=$PASS FAIL=$FAIL"
|
||||
[ "$FAIL" -eq 0 ]
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@
|
|||
# recall - repos that already received it are unaffected.
|
||||
# --from overrides the sender/self identity (default: basename of git toplevel/cwd).
|
||||
#
|
||||
# Exit: 0 delivered, 2 usage/IO error. ASCII only, bash 3.2 safe.
|
||||
# Exit: 0 delivered, 1 delivered but --reply-to's original could NOT be closed
|
||||
# (the reply is sent; do not re-send it, close the original by hand),
|
||||
# 2 usage/IO error, nothing written. ASCII only, bash 3.2 safe.
|
||||
set -u
|
||||
export LC_ALL=C
|
||||
|
||||
|
|
@ -246,8 +248,38 @@ if [ "$BROADCAST" -eq 1 ]; then
|
|||
fi
|
||||
|
||||
# --- Reply mode: mark the original handled ---
|
||||
# The handled claim is asserted against GROUND TRUTH - is the original still
|
||||
# pending in the inbox - and not against the call having been made. It used to
|
||||
# print unconditionally with coord-done's output discarded, which made the one
|
||||
# line a session relies on to close a reply debt false at the moment it was
|
||||
# printed (review finding 9, 2026-08-14: stub coord-done exiting 1, original
|
||||
# untouched, no archive/, and coord-send still exited 0 saying "marked
|
||||
# handled"). A false success in the transport is worse than a loud failure:
|
||||
# every reply had to be verified by hand afterwards, so the exit code carried
|
||||
# no information at all.
|
||||
#
|
||||
# CHECKING THE EXIT CODE ALONE IS NOT ENOUGH, and this is the half a later
|
||||
# session is most likely to simplify away. coord-done exits 0 when it archives
|
||||
# NOTHING - an unknown name is idempotently fine by its own contract
|
||||
# (coord-done.sh:54, :70) - so a nonzero-exit test still certifies a message
|
||||
# that never moved. Selftest section 34(b) is that exact case.
|
||||
#
|
||||
# The path is recomputed rather than reusing $REPLY_ORIG, which resolves to the
|
||||
# inbox OR the archive (:129-130). Replying to an already-archived original is
|
||||
# legitimate and moves nothing; testing $REPLY_ORIG would warn on every one of
|
||||
# those (section 34(d)).
|
||||
#
|
||||
# Exit 1, not 2: the reply WAS delivered and re-sending it would duplicate it.
|
||||
# The distinct status says "delivered, original not closed" - 2 stays the
|
||||
# nothing-was-written status it has always been.
|
||||
if [ -n "$REPLY_ORIG" ]; then
|
||||
"$(dirname "$0")/coord-done.sh" --repo "$FROM" "$REPLYTO" >/dev/null 2>&1
|
||||
echo "coord-send: original ($REPLYTO) marked handled"
|
||||
DONE_RC=$?
|
||||
if [ "$DONE_RC" -eq 0 ] && [ ! -e "$COORD/$FROM/inbox/$REPLYTO" ]; then
|
||||
echo "coord-send: original ($REPLYTO) marked handled"
|
||||
else
|
||||
echo "coord-send: the reply was delivered, but the original ($REPLYTO) is STILL PENDING in $FROM's inbox (coord-done exit $DONE_RC) - it is NOT handled; close it by hand: coord-done $REPLYTO" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
exit 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue