feat(orders): order queue channel with atomic claim, board ORDRE column

ORDRE 59. A dispatched order used to live only in a scratch prompt file
passed through argv, so it died with the pane it was typed into. Measured
2026-08-17: one order was dispatched three times over 90 minutes before it
was worked, because the first two tabs ran something else and the order
left no trace in the receiving repo at all.

New channel `~/.claude/coord/<repo>/orders/`, beside `inbox/` and never
merged with it. The axis is authorization: inbox content is untrusted
cross-repo data that may never instruct a session (Rule 6), a dispatch
order is operator-authorized work by construction. One channel carrying
both classes would mean either mail that can instruct or orders that
cannot, so the infrastructure is reused and the channel is not.

Four one-verb engines: coord-order-send.sh (write), coord-order-inbox.sh
(read, writes nothing at all), coord-order-claim.sh (atomic claim),
coord-order-done.sh (executed with a commit pointer / --no-commit with a
reason / --return with a reason).

The claim is a rename with no check-then-act step, so of N racing sessions
exactly one finds the source and the rest get ENOENT. The test that proves
it spawns 20 claimers BARRIERED on a start flag - unbarriered children do
not race at all - and runs the identical harness against a deliberately
racy `[ -e src ] && cp && rm` as a known-negative control, which must
produce many winners. Without that control, "exactly one winner" is
indistinguishable from "the race never happened".

Channel separation is pinned structurally, not only behaviourally: no mail
script may contain the string `orders`, with a known-positive control
proving the grep can find. coord-done cannot archive an order and
coord-order-claim cannot claim a message.

board gains an ORDRE column beside INN, counted with the identical idiom
and never summed with it: INN is "others are waiting on YOU", ORDRE is
"work is waiting on this REPO". Claimed orders are excluded - the column
answers what a session can pick up. board.sh --dispatch --order-id emits a
thin starter carrying only the id and the four steps, so the order text has
exactly one home; the id is validated shell-clean and must be pending in
the target's queue.

SessionStart injects the queue as its own block below the mailbox block.
Two channels, two blocks, mail first: it carries Rule 7, and the queue
order is mail -> orders -> STATE's NESTE.

Also folds in dde392d (board prefix-match fix), which landed after the
0.26.0 bump and before any tag. v0.26.0 was never tagged, so 0.27.0 is the
release that carries all of it.

Suites: coord 220, board 237, route 69, orders 97, guard 40; npm test 11/11.
Antakelse 4 (atomic claim) and antakelse 6 (morning --plan-file --dry-run
reports 1 of 1 for the thin starter) both measured, not assumed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0134iB7ipXGgEpv9imYoVmr2
This commit is contained in:
Kjell Tore Guttormsen 2026-08-17 21:17:17 +02:00
commit c519ab4994
18 changed files with 1410 additions and 80 deletions

View file

@ -1838,6 +1838,72 @@ check "dispatch SKILL.md's BOARD assignment carries no fallback" "$rc"
# session (no tty -> morning assumes an empty window).
grep -q 'probe-panes' "$DSKILL"
check "dispatch SKILL.md names --probe-panes as the pane measurement" $?
# The order engine is the second engine line in the same skill, and it carries
# the identical fallback hazard for the identical reason.
grep -q 'ORDER="\${CLAUDE_PLUGIN_ROOT}/scripts/coord-order-send.sh"' "$DSKILL"
check "dispatch SKILL.md's order engine line has no fallback path" $?
if grep -q 'ORDER=.*CLAUDE_PLUGIN_ROOT:-' "$DSKILL"; then rc=1; else rc=0; fi
check "dispatch SKILL.md's ORDER assignment carries no fallback" "$rc"
# The queue is the canonical home of the order text; a skill that still told
# the caller to inline the prompt would reopen the scratch-only defect.
grep -q -- '--order-id' "$DSKILL"
check "dispatch SKILL.md dispatches on --order-id" $?
# --- 20. The ORDRE column ---------------------------------------------------
# Two mailbox-derived columns, never summed and never merged: INN is "others
# are waiting on YOU", ORDRE is "authorized work is waiting on this REPO".
# Own root, so the two counts can be set independently of the shared fixture
# tree and read off one rendered row.
ORD_ROOT="$(mktemp -d)"
mkrepo "$ORD_ROOT/ord-both"
{
echo "# STATE - ord-both"
echo ""
printf '## %s NESTE\n' "$HAND"
echo "<!-- board: status=planned; blocked-on=-; next-cost=Sonnet 5/high -->"
echo "Do the planned thing."
} > "$ORD_ROOT/ord-both/STATE.md"
mkrepo "$ORD_ROOT/ord-none"
{
echo "# STATE - ord-none"
echo ""
printf '## %s NESTE\n' "$HAND"
echo "<!-- board: status=planned; blocked-on=-; next-cost=Sonnet 5/high -->"
echo "Nothing waiting here."
} > "$ORD_ROOT/ord-none/STATE.md"
mkdir -p "$CLAUDE_COORD_DIR/ord-both/inbox" "$CLAUDE_COORD_DIR/ord-both/orders" \
"$CLAUDE_COORD_DIR/ord-both/orders/claimed"
for i in 1 2 3; do
printf -- '---\nfrom: x\nto: ord-both\nsubject: m%s\n---\nbody\n' "$i" \
> "$CLAUDE_COORD_DIR/ord-both/inbox/2026010${i}T000000Z-${i}-from-x.md"
done
for i in 1 2; do
printf -- '---\nfrom: d\nto: ord-both\norder-id: o%s\nsubject: order %s\n---\nbody\n' "$i" "$i" \
> "$CLAUDE_COORD_DIR/ord-both/orders/2026010${i}T000000Z-${i}-from-d.md"
done
# A CLAIMED order is deliberately NOT counted: the column answers "what can a
# session pick up here", and one already in flight cannot be. Counting it would
# open a tab for work someone else holds.
printf -- '---\nfrom: d\nto: ord-both\norder-id: o9\nsubject: in flight\n---\nbody\n' \
> "$CLAUDE_COORD_DIR/ord-both/orders/claimed/20260109T000000Z-9-from-d.md"
ORD_OUT="$("$BOARD" --roots "$ORD_ROOT" 2>/dev/null)"
printf '%s' "$ORD_OUT" | grep -q 'ORDRE'; check "table header carries an ORDRE column" $?
# Matched on the rendered row, not by awk field index: KOST is "Sonnet 5/high"
# and contains a space, so a field number would be counting other columns and
# would keep passing if the layout shifted.
printf '%s' "$ORD_OUT" | grep -qE '^ord-both[[:space:]]+planned[[:space:]]+Sonnet 5/high[[:space:]]+3[[:space:]]+2[[:space:]]'
check "INN 3 and ORDRE 2 are printed side by side, never summed" $?
printf '%s' "$ORD_OUT" | grep -qE '^ord-none[[:space:]]+planned[[:space:]]+Sonnet 5/high[[:space:]]+0[[:space:]]+0[[:space:]]'
check "a repo with no mail and no orders reads 0 in both columns" $?
# neste is the LAST field of the record and may contain a literal '|' from a
# markdown table, which is why orders was inserted before it and not after.
printf '%s' "$ORD_OUT" | grep -q 'Do the planned thing'
check "NESTE still renders after the field insertion" $?
printf '%s' "$ORD_OUT" | grep -q 'summeres ALDRI'
check "the legend states that INN and ORDRE are never summed" $?
/bin/rm -rf "$ORD_ROOT" 2>/dev/null
echo ""
echo "board-selftest: $PASS passed, $FAIL failed"