repo-mailbox/scripts/orders-selftest.sh
Kjell Tore Guttormsen 393499c3ee fix(orders): call the order-verbs by absolute path, not bare PATH names
board.sh's --dispatch --order-id thin starter told a dispatched session
to run `coord-order-claim <id>` / `coord-order-done <id> ...` literally.
Neither is on PATH, so step one was command-not-found - easy to misread
as "the order does not exist" (Verifiseringsloven ansikt 4).

Measuring the denominator beyond the one line the order named found the
same defect in two more emitters that hand a session its own next-step
text: coord-order-inbox.sh's SessionStart injection (every pending/claimed
order, not only dispatched ones) and coord-order-claim.sh's own WHEN DONE
/ IF YOU CANNOT lines. All three now call the verb via $SELFDIR (derived
from $0's directory, correct at emission time), and board.sh's interpolation
of it is shell-clean-guarded like the other two values sharing its
double-quoted position - reachability proven with a copy of board.sh run
from a space-containing path, not asserted.

board-selftest 239->246, orders-selftest 99->104. CLAUDE.md counts and a
new F-paragraph updated to match.

ORDRE 20260817T213139Z-643032142-from-.claude

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019syEQHvw2jf1dTR4bUPKRG
2026-08-18 09:16:59 +02:00

383 lines
24 KiB
Bash
Executable file

#!/bin/bash
# orders-selftest.sh - prove the ORDER QUEUE end-to-end against a throwaway
# mailbox (never touches ~/.claude/coord). Re-run after any edit to
# coord-order-send.sh / coord-order-inbox.sh / coord-order-claim.sh /
# coord-order-done.sh. ASCII only, bash 3.2 safe.
#
# The order queue is a SECOND channel beside inbox/, with the opposite
# authorization class: mail is untrusted cross-repo data that may never
# instruct a session, an order is operator-authorized work delivered by
# dispatch. The two must never be able to become each other, so section 4
# pins the separation STRUCTURALLY (no write path exists) and not only
# behaviourally (this one send did not cross over).
set -u
export LC_ALL=C
DIR="$(cd "$(dirname "$0")" && pwd)"
SEND="$DIR/coord-order-send.sh"
READ="$DIR/coord-order-inbox.sh"
CLAIM="$DIR/coord-order-claim.sh"
ODONE="$DIR/coord-order-done.sh"
MSEND="$DIR/coord-send.sh"
MDONE="$DIR/coord-done.sh"
BOARD="$DIR/board.sh"
CLAUDE_COORD_DIR="$(mktemp -d)"
export CLAUDE_COORD_DIR
WORK="$(mktemp -d)"
cleanup() { /bin/rm -rf "$CLAUDE_COORD_DIR" "$WORK" 2>/dev/null; }
trap cleanup EXIT
PASS=0; FAIL=0; SKIP=0
check() { if [ "$2" -eq 0 ]; then PASS=$((PASS+1)); echo " ok - $1"; else FAIL=$((FAIL+1)); echo " FAIL - $1"; fi; }
# A skip is NOT a pass and is never silent: it prints, it is counted, and the
# denominator at the bottom names it. Verifiseringsloven face 4 - an absent
# measurement must not read as a positive one.
skip() { SKIP=$((SKIP+1)); echo " SKIP - $1"; }
echo "orders-selftest (mailbox: $CLAUDE_COORD_DIR)"
# --- 1. Delivery -----------------------------------------------------------
out1="$("$SEND" --to fake-repo --from dispatcher --subject "order one" --message "do the thing" 2>&1)"; rc=$?
[ "$rc" -eq 0 ]; check "order send exits 0" $?
oid1="$(printf '%s\n' "$out1" | sed -n 's/^order-id=//p')"
[ -n "$oid1" ]; check "order send prints order-id=" $?
of1="$CLAUDE_COORD_DIR/fake-repo/orders/$oid1.md"
[ -f "$of1" ]; check "order file lands in the recipient's orders/" $?
grep -q "^from: dispatcher$" "$of1" 2>/dev/null; check "frontmatter carries from" $?
grep -q "^to: fake-repo$" "$of1" 2>/dev/null; check "frontmatter carries to" $?
grep -q "^order-id: $oid1$" "$of1" 2>/dev/null; check "frontmatter carries order-id" $?
grep -q "^subject: order one$" "$of1" 2>/dev/null; check "frontmatter carries subject" $?
grep -q "^date: " "$of1" 2>/dev/null; check "frontmatter carries date" $?
grep -q "^do the thing$" "$of1" 2>/dev/null; check "body is the whole prompt" $?
# The prompt normally arrives as a FILE (that is what dispatch writes), so the
# file path must be a first-class input and not something the caller has to
# shell out to cat.
printf 'line A\nline B\n' > "$WORK/p.prompt"
out1b="$("$SEND" --to fake-repo --from dispatcher --subject "from file" --prompt-file "$WORK/p.prompt" 2>&1)"
oid1b="$(printf '%s\n' "$out1b" | sed -n 's/^order-id=//p')"
grep -q "^line B$" "$CLAUDE_COORD_DIR/fake-repo/orders/$oid1b.md" 2>/dev/null
check "--prompt-file carries the whole file as the body" $?
# --- 2. Read side: injection -----------------------------------------------
r2="$("$READ" --repo fake-repo)"; rc=$?
[ "$rc" -eq 0 ]; check "order read exits 0" $?
printf '%s' "$r2" | grep -q "2 pending"; check "read reports the pending count" $?
printf '%s' "$r2" | grep -q "order one"; check "read shows the subject" $?
printf '%s' "$r2" | grep -q "dispatcher"; check "read shows the sender" $?
# ORDRE 65 follow-on (2026-08-17): this is the SessionStart injection - the
# same bare-name defect the order named in board.sh's dispatch starter also
# lived here, and arguably worse: it fires on every session with a pending
# order, not only a dispatched one (this is the literal text this session saw
# at its own start). Pinned by absolute path, exactly like board.sh's fix.
printf '%s' "$r2" | grep -qF "bash $DIR/coord-order-claim.sh $oid1"; check "read gives a per-order claim hint by an ABSOLUTE script path, not a bare PATH name" $?
printf '%s' "$r2" | grep -Eq "(^|[^./])coord-order-claim $oid1"; [ $? -ne 0 ]; check "read: no bare, un-pathed coord-order-claim invocation survives the injection" $?
# The order body is deliberately NOT injected: an order can be a full session
# prompt, and the queue view has to stay readable at session start. The text
# arrives at claim time, from the one place it lives.
[ "$(printf '%s' "$r2" | grep -c 'do the thing')" -eq 0 ]
check "read does NOT inject the order body (that arrives at claim)" $?
# The authorization class is the whole point of the second channel, and it has
# to be stated where a session reads it, not only in a doc.
printf '%s' "$r2" | grep -q "OPERATOR-AUTHORIZED"; check "read states the order authorization class" $?
printf '%s' "$r2" | grep -q "CONVENTION"; check "read states that the writer rule is convention, not enforcement" $?
printf '%s' "$r2" | grep -q "NESTE"; check "read carries the D-check against STATE's NESTE" $?
# Rule 7's shape, transposed: a pending order may be left, but never silently.
printf '%s' "$r2" | grep -q "leaving it pending"; check "read states the procedural duty" $?
r2b="$("$READ" --repo fake-repo)"
printf '%s' "$r2b" | grep -q "order one"
check "pending order re-injected on the next read (survives /clear)" $?
[ -f "$of1" ]; check "reading an order does not move it" $?
# Silence is reserved for a genuinely empty queue.
r2c="$("$READ" --repo nobody)"; rc=$?
[ -z "$r2c" ] && [ "$rc" -eq 0 ]; check "empty order queue is a silent no-op" $?
# --- 3. Claim --------------------------------------------------------------
c3="$("$CLAIM" --repo fake-repo "$oid1" 2>&1)"; rc=$?
[ "$rc" -eq 0 ]; check "claim exits 0" $?
printf '%s' "$c3" | grep -q "do the thing"; check "claim prints the full order body" $?
printf '%s' "$c3" | grep -q "NESTE"; check "claim instructs the D-check against STATE's NESTE" $?
# ORDRE 65 follow-on: the claim's own "WHEN DONE"/"IF YOU CANNOT" lines are the
# THIRD live emitter of the same bare-name defect - the text handed directly
# to the claiming session as its own next-step instruction.
printf '%s' "$c3" | grep -qF "WHEN DONE: bash $DIR/coord-order-done.sh $oid1 --commit"; check "claim's WHEN DONE line calls coord-order-done.sh by an ABSOLUTE script path" $?
printf '%s' "$c3" | grep -qF "IF YOU CANNOT: bash $DIR/coord-order-done.sh $oid1 --return"; check "claim's IF YOU CANNOT line calls coord-order-done.sh by an ABSOLUTE script path" $?
printf '%s' "$c3" | grep -Eq "(^|[^./])coord-order-done $oid1"; [ $? -ne 0 ]; check "claim output: no bare, un-pathed coord-order-done invocation" $?
[ ! -e "$of1" ]; check "claimed order leaves the pending queue" $?
[ -f "$CLAUDE_COORD_DIR/fake-repo/orders/claimed/$oid1.md" ]; check "claimed order lands in orders/claimed" $?
# A second claim of the same order must lose, and must not be mistaken for a
# usage error: exit 1 is "you did not get it", exit 2 stays "nothing was even
# attempted".
"$CLAIM" --repo fake-repo "$oid1" >/dev/null 2>&1; [ $? -eq 1 ]
check "re-claiming an already claimed order exits 1" $?
# Claimed but abandoned is the one way an order could still evaporate, so the
# read side has to keep showing it - with its age - rather than let the queue
# read as empty.
r3="$("$READ" --repo fake-repo)"
printf '%s' "$r3" | grep -q "1 claimed"; check "read reports the claimed count" $?
printf '%s' "$r3" | grep -q "CLAIMED"; check "read shows a claimed order as in flight" $?
printf '%s' "$r3" | grep -qF "bash $DIR/coord-order-done.sh $oid1 --return"; check "read gives the return hint for a claimed order by an ABSOLUTE script path" $?
printf '%s' "$r3" | grep -Eq "(^|[^./])coord-order-done $oid1 --return"; [ $? -ne 0 ]; check "read: no bare, un-pathed coord-order-done invocation survives the in-flight hint" $?
# --next takes the oldest pending order, so a session never has to parse the
# queue to obey it.
c3b="$("$CLAIM" --repo fake-repo --next 2>&1)"; rc=$?
[ "$rc" -eq 0 ]; check "claim --next takes the oldest pending order" $?
printf '%s' "$c3b" | grep -q "line B"; check "claim --next printed that order's body" $?
"$CLAIM" --repo fake-repo --next >/dev/null 2>&1; [ $? -eq 1 ]
check "claim --next on an empty queue exits 1" $?
# --- 4. Channel separation -------------------------------------------------
# STRUCTURAL first: the claim is "no write path from mail to orders exists",
# and a behavioural test only samples one case.
sep_hits="$(grep -l 'orders' "$MSEND" "$MDONE" "$DIR/coord-inbox.sh" "$DIR/coord-sweep.sh" "$DIR/coord-count.sh" 2>/dev/null | wc -l | tr -d ' ')"
[ "$sep_hits" -eq 0 ]; check "no mail script mentions orders at all (no write path)" $?
# Known-positive control for that grep: it must be able to find the string.
grep -q 'orders' "$SEND" 2>/dev/null; check "control: the grep CAN find 'orders' (in the order engine)" $?
# BEHAVIOURAL, both directions.
"$MSEND" --to sep-repo --from someone --subject "just mail" --message "not an order" >/dev/null 2>&1
[ ! -d "$CLAUDE_COORD_DIR/sep-repo/orders" ]; check "a coord message never creates an orders queue" $?
"$SEND" --to sep2-repo --from dispatcher --subject "just an order" --message "an order" >/dev/null 2>&1
[ ! -d "$CLAUDE_COORD_DIR/sep2-repo/inbox" ]; check "an order never creates an inbox" $?
r4="$("$READ" --repo sep-repo)"
[ -z "$r4" ]; check "the order read path shows nothing for a mail-only mailbox" $?
# The two done-verbs must not reach across either.
mb="$(basename "$(ls "$CLAUDE_COORD_DIR"/sep-repo/inbox/*.md 2>/dev/null | head -1)")"
oid4="$(printf '%s\n' "$("$SEND" --to sep-repo --from dispatcher --subject "x" --message "y" 2>&1)" | sed -n 's/^order-id=//p')"
"$MDONE" --repo sep-repo "$oid4.md" >/dev/null 2>&1
[ -f "$CLAUDE_COORD_DIR/sep-repo/orders/$oid4.md" ]; check "coord-done cannot archive an order" $?
"$CLAIM" --repo sep-repo "$mb" >/dev/null 2>&1; [ $? -ne 0 ]
check "coord-order-claim cannot claim a coord message" $?
[ -f "$CLAUDE_COORD_DIR/sep-repo/inbox/$mb" ]; check "the coord message is untouched by the order engine" $?
# --- 5. Atomic claim (antakelse 4 - the design marks this RISIKO) ----------
# A naive "two claimers, one winner" test does not race at all: the first
# finishes before the second starts and the test goes green having proven
# nothing. Every claimer is therefore barriered on a start flag, and the whole
# harness is validated against a deliberately RACY claim that must produce
# more than one winner. Without that control, "exactly one winner" is
# indistinguishable from "the race never happened".
race_one() {
# $1 = label, $2 = claim command as a shell snippet operating on $SRC/$DST
rc_dir="$WORK/race-$1"
mkdir -p "$rc_dir/ready" "$rc_dir/won"
rc_start="$rc_dir/start"
rc_n=20
rc_i=1
while [ "$rc_i" -le "$rc_n" ]; do
(
: > "$rc_dir/ready/$rc_i"
while [ ! -e "$rc_start" ]; do :; done
if eval "$2" >/dev/null 2>&1; then : > "$rc_dir/won/$rc_i"; fi
) &
rc_i=$((rc_i + 1))
done
rc_w=0
while [ "$(ls "$rc_dir/ready" 2>/dev/null | wc -l | tr -d ' ')" -lt "$rc_n" ] && [ "$rc_w" -lt 100 ]; do
sleep 0.1; rc_w=$((rc_w + 1))
done
: > "$rc_start"
wait
ls "$rc_dir/won" 2>/dev/null | wc -l | tr -d ' '
}
oid5="$(printf '%s\n' "$("$SEND" --to race-repo --from dispatcher --subject "contended" --message "one winner only" 2>&1)" | sed -n 's/^order-id=//p')"
[ -n "$oid5" ]; check "race fixture: order delivered" $?
winners="$(race_one real "\"$CLAIM\" --repo race-repo $oid5")"
[ "$winners" -eq 1 ]; check "20 concurrent claims produce EXACTLY ONE winner (got $winners)" $?
[ -f "$CLAUDE_COORD_DIR/race-repo/orders/claimed/$oid5.md" ]; check "the contended order exists in exactly one place after the race" $?
[ ! -e "$CLAUDE_COORD_DIR/race-repo/orders/$oid5.md" ]; check "the contended order is gone from pending after the race" $?
# Known-negative control: the same harness against a check-then-act claim.
# The sleep makes it deterministic rather than merely likely - every child
# passes the existence test before any of them acts.
SRC="$WORK/racy-src"; DST="$WORK/racy-dst"
mkdir -p "$DST"; : > "$SRC"
racy_winners="$(race_one control "[ -e \"$SRC\" ] && { sleep 0.3; cp \"$SRC\" \"$DST/\$\$\"; /bin/rm -f \"$SRC\"; }")"
[ "$racy_winners" -gt 1 ]; check "control: a check-then-act claim DOES produce multiple winners (got $racy_winners)" $?
# --- 6. Terminal states ----------------------------------------------------
# Executed: archived with a result pointer. The commit hash is the pointer, and
# it is required - an order that finished with nothing to show for it is either
# a --no-commit with a stated why, or a return.
"$ODONE" --repo fake-repo "$oid1" --commit deadbee >/dev/null 2>&1; rc=$?
[ "$rc" -eq 0 ]; check "order-done --commit exits 0" $?
[ -f "$CLAUDE_COORD_DIR/fake-repo/orders/archive/$oid1.md" ]; check "executed order lands in orders/archive" $?
[ ! -e "$CLAUDE_COORD_DIR/fake-repo/orders/claimed/$oid1.md" ]; check "executed order leaves orders/claimed" $?
grep -q 'order-result: executed' "$CLAUDE_COORD_DIR/fake-repo/orders/archive/$oid1.md" 2>/dev/null
check "archived order records the result" $?
grep -q 'commit=deadbee' "$CLAUDE_COORD_DIR/fake-repo/orders/archive/$oid1.md" 2>/dev/null
check "archived order records the commit pointer" $?
[ ! -e "$CLAUDE_COORD_DIR/fake-repo/orders/claimed/$oid1.claim" ]; check "the claim marker is cleared on a terminal state" $?
"$ODONE" --repo fake-repo "$oid1" --commit deadbee >/dev/null 2>&1; [ $? -eq 1 ]
check "closing an order twice exits 1 (nothing left to close)" $?
"$ODONE" --repo fake-repo "$oid1b" --commit x >/dev/null 2>&1
[ -f "$CLAUDE_COORD_DIR/fake-repo/orders/archive/$oid1b.md" ]; check "the --next-claimed order closes too" $?
# --no-commit is the honest form of "executed, nothing to commit"; it costs a
# stated reason so it cannot become the silent default.
oid6="$(printf '%s\n' "$("$SEND" --to nc-repo --from dispatcher --subject "measure" --message "just measure" 2>&1)" | sed -n 's/^order-id=//p')"
"$CLAIM" --repo nc-repo "$oid6" >/dev/null 2>&1
"$ODONE" --repo nc-repo "$oid6" --no-commit >/dev/null 2>&1; [ $? -eq 2 ]
check "--no-commit without --reason is refused" $?
"$ODONE" --repo nc-repo "$oid6" --no-commit --reason "measurement only" >/dev/null 2>&1; [ $? -eq 0 ]
check "--no-commit with a reason closes the order" $?
grep -q 'commit=none' "$CLAUDE_COORD_DIR/nc-repo/orders/archive/$oid6.md" 2>/dev/null
check "a --no-commit close records commit=none" $?
# Returned: back to pending, with the reason visible to whoever picks it up.
oid7="$(printf '%s\n' "$("$SEND" --to ret-repo --from dispatcher --subject "stale" --message "premise is dead" 2>&1)" | sed -n 's/^order-id=//p')"
"$CLAIM" --repo ret-repo "$oid7" >/dev/null 2>&1
"$ODONE" --repo ret-repo "$oid7" --return >/dev/null 2>&1; [ $? -eq 2 ]
check "--return without --reason is refused" $?
# The reason carries a plain arrow on purpose: this repo writes prose that way
# ("premise -> dead"), and an escape aimed at '-->' that also eats '->' would
# silently mangle the one field whose whole value is being readable.
"$ODONE" --repo ret-repo "$oid7" --return --reason "forutsetningen er dod -> ikke kjorbar" >/dev/null 2>&1; [ $? -eq 0 ]
check "--return with a reason exits 0" $?
[ -f "$CLAUDE_COORD_DIR/ret-repo/orders/$oid7.md" ]; check "returned order is pending again" $?
[ ! -e "$CLAUDE_COORD_DIR/ret-repo/orders/claimed/$oid7.md" ]; check "returned order left orders/claimed" $?
grep -q 'order-returned' "$CLAUDE_COORD_DIR/ret-repo/orders/$oid7.md" 2>/dev/null
check "returned order records the return" $?
r7="$("$READ" --repo ret-repo)"
printf '%s' "$r7" | grep -q "forutsetningen er dod"
check "the return reason reaches the next session's injection" $?
printf '%s' "$r7" | grep -q "dod -> ikke kjorbar"
check "a plain arrow in the reason survives the comment escaping" $?
# The escaping still has to do its actual job.
oid7b="$(printf '%s\n' "$("$SEND" --to ret2-repo --from dispatcher --subject "s" --message "m" 2>&1)" | sed -n 's/^order-id=//p')"
"$CLAIM" --repo ret2-repo "$oid7b" >/dev/null 2>&1
"$ODONE" --repo ret2-repo "$oid7b" --return --reason "closes here --> and then prose" >/dev/null 2>&1
[ "$(grep -c '^<!-- order-returned:' "$CLAUDE_COORD_DIR/ret2-repo/orders/$oid7b.md" 2>/dev/null)" -eq 1 ] &&
[ "$(tail -1 "$CLAUDE_COORD_DIR/ret2-repo/orders/$oid7b.md" | grep -c 'and then prose -->')" -eq 1 ]
check "a literal --> in the reason cannot close the trailer early" $?
"$CLAIM" --repo ret-repo "$oid7" >/dev/null 2>&1; [ $? -eq 0 ]
check "a returned order can be claimed again" $?
# --- 7. Usage guards -------------------------------------------------------
"$SEND" --from x --subject s --message m >/dev/null 2>&1; [ $? -eq 2 ]; check "order send without --to is refused" $?
"$SEND" --to x --from y --message m >/dev/null 2>&1; [ $? -eq 2 ]; check "order send without --subject is refused" $?
"$SEND" --to x --from y --subject s --message "" >/dev/null 2>&1; [ $? -eq 2 ]; check "empty order body is refused" $?
: > "$WORK/empty.prompt"
"$SEND" --to x --from y --subject s --prompt-file "$WORK/empty.prompt" >/dev/null 2>&1; [ $? -eq 2 ]
check "an empty --prompt-file is refused (a session told nothing)" $?
"$SEND" --to x --from y --subject s --prompt-file "$WORK/missing.prompt" >/dev/null 2>&1; [ $? -eq 2 ]
check "a missing --prompt-file is refused" $?
"$SEND" --to "../evil" --from y --subject s --message m >/dev/null 2>&1; [ $? -eq 2 ]
check "path-traversal --to is refused" $?
"$SEND" --to _broadcast --from y --subject s --message m >/dev/null 2>&1; [ $? -eq 2 ]
check "the reserved _ namespace is refused as an order target" $?
"$SEND" --to ktg-plugin-marketplace --from y --subject s --message m >/dev/null 2>&1; [ $? -eq 2 ]
check "the retired ktg-plugin-marketplace address is refused" $?
"$SEND" --to x --from _engine --subject s --message m >/dev/null 2>&1; [ $? -eq 2 ]
check "a reserved sender identity is refused" $?
"$CLAIM" --repo x "../evil" >/dev/null 2>&1; [ $? -eq 2 ]; check "path-traversal order id is refused at claim" $?
"$CLAIM" --repo _broadcast anything >/dev/null 2>&1; [ $? -eq 2 ]; check "the reserved namespace is refused at claim" $?
"$ODONE" --repo x someid >/dev/null 2>&1; [ $? -eq 2 ]; check "order-done without a mode is refused" $?
"$ODONE" --repo x someid --commit a --return --reason r >/dev/null 2>&1; [ $? -eq 2 ]
check "order-done with two modes is refused" $?
# A trailing value-flag with no value must exit, never hang (bash 3.2 shift 2).
fast_exit() {
"$@" >/dev/null 2>&1 &
fe_pid=$!
fe_i=0
while [ "$fe_i" -lt 30 ]; do
if ! kill -0 "$fe_pid" 2>/dev/null; then wait "$fe_pid" 2>/dev/null; echo "rc=$?"; return 0; fi
sleep 0.1; fe_i=$((fe_i + 1))
done
kill -9 "$fe_pid" 2>/dev/null; echo "HUNG"; return 0
}
[ "$(fast_exit "$SEND" --to)" = "rc=2" ]; check "order send --to with no value exits 2, never hangs" $?
[ "$(fast_exit "$CLAIM" --repo)" = "rc=2" ]; check "claim --repo with no value exits 2, never hangs" $?
[ "$(fast_exit "$ODONE" --repo)" = "rc=2" ]; check "order-done --repo with no value exits 2, never hangs" $?
[ "$(fast_exit "$READ" --repo)" = "rc=2" ]; check "order read --repo with no value exits 2, never hangs" $?
# The order id round-trips through argv and into shell-quoted hints, so it must
# be shell-clean by construction even when the sender's name is not.
oid8="$(printf '%s\n' "$("$SEND" --to odd-repo --from 'we ird/name' --subject s --message m 2>&1)" | sed -n 's/^order-id=//p')"
case "$oid8" in *[!A-Za-z0-9._-]*) false ;; *) true ;; esac
check "order id is shell-clean even for an odd sender name" $?
# A newline in the subject would forge extra frontmatter lines.
"$SEND" --to nl-repo --from y --subject "$(printf 'a\nsubject: b')" --message m >/dev/null 2>&1
nlf="$(ls "$CLAUDE_COORD_DIR"/nl-repo/orders/*.md 2>/dev/null | head -1)"
[ "$(grep -c '^subject:' "$nlf" 2>/dev/null)" -eq 1 ]
check "a newline in the subject cannot inject a second frontmatter line" $?
# --- 8. Board integration --------------------------------------------------
# The ORDRE column is a repo-scan property like INN, counted the same way, and
# the two are never summed: INN is "others are waiting on you", ORDRE is
# "work is waiting on this repo".
bt="$WORK/boardroot"
mkdir -p "$bt/ordrepo/.git"
cat > "$bt/ordrepo/STATE.md" <<'EOF'
# STATE
## NESTE
<!-- board: status=planned; blocked-on=-; next-cost=Sonnet 5/high -->
<!-- route: path=known; verification=strong; reversibility=cheap; scope=local; rationale=x -->
Do the planned thing.
EOF
boid="$("$SEND" --to ordrepo --from dispatcher --subject "board order" --message "b" 2>&1 | sed -n 's/^order-id=//p')"
"$SEND" --to ordrepo --from dispatcher --subject "board order 2" --message "b" >/dev/null 2>&1
"$MSEND" --to ordrepo --from someone --subject "board mail" --message "m" >/dev/null 2>&1
bout="$(BOARD_ROOTS="$bt" bash "$BOARD" 2>/dev/null)"
printf '%s' "$bout" | grep -q 'ORDRE'; check "board table has an ORDRE column" $?
printf '%s' "$bout" | grep -q 'ordrepo'; check "board table lists the fixture repo" $?
# One mail, two orders, and neither number absorbed the other.
# Matched on the rendered row rather than by awk field number: KOST is
# "Sonnet 5/high", which contains a space, so a field index would be counting
# the wrong columns and would keep "passing" if the layout shifted.
printf '%s' "$bout" | grep -qE '^ordrepo[[:space:]]+planned[[:space:]]+Sonnet 5/high[[:space:]]+1[[:space:]]+2[[:space:]]'
check "board prints INN 1 and ORDRE 2 side by side, never summed" $?
# --dispatch --order-id: the thin starter form. The order text lives in the
# queue; the pasted line only points at it.
dout="$(BOARD_ROOTS="$bt" bash "$BOARD" --dispatch --repo ordrepo --order-id "$boid" \
--target-pane yes --path known --verification strong --reversibility cheap --scope local --rationale "smoke" 2>&1)"; rc=$?
[ "$rc" -eq 0 ]; check "--dispatch --order-id exits 0" $?
printf '%s' "$dout" | grep -q '^paste='; check "--dispatch --order-id emits a paste line" $?
printf '%s' "$dout" | grep -q 'coord-order-claim'; check "the starter tells the session to claim the order" $?
printf '%s' "$dout" | grep -q 'NESTE'; check "the starter carries the D-check" $?
BOARD_ROOTS="$bt" bash "$BOARD" --dispatch --repo ordrepo --order-id 'evil;id' \
--target-pane yes --path known --verification strong --reversibility cheap --scope local --rationale x >/dev/null 2>&1
[ $? -eq 2 ]; check "a non-shell-clean --order-id is refused" $?
BOARD_ROOTS="$bt" bash "$BOARD" --dispatch --repo ordrepo --order-id 20990101T000000Z-0-from-nobody \
--target-pane yes --path known --verification strong --reversibility cheap --scope local --rationale x >/dev/null 2>&1
[ $? -eq 2 ]; check "an --order-id with no order in the queue is refused" $?
BOARD_ROOTS="$bt" bash "$BOARD" --dispatch --repo ordrepo --order-id someid --prompt-file /etc/hosts \
--target-pane yes --path known --verification strong --reversibility cheap --scope local --rationale x >/dev/null 2>&1
[ $? -eq 2 ]; check "--order-id and --prompt-file together are refused" $?
# --- 9. Plan-file starter through the real morning (antakelse 6) -----------
# The design leaves this UNMEASURED and calls it an acceptance test for this
# order. It runs against the installed morning; if morning is absent it SKIPS
# loudly rather than passing, because an unmeasured assumption that reads as
# green is the failure this test exists to prevent.
if command -v morning >/dev/null 2>&1; then
poid="$("$SEND" --to ordrepo --from dispatcher --subject "plan starter" --message "p" 2>&1 | sed -n 's/^order-id=//p')"
planf="$WORK/starter.plan"
BOARD_ROOTS="$bt" bash "$BOARD" --dispatch --repo ordrepo --order-id "$poid" \
--target-pane no --path known --verification strong --reversibility cheap \
--scope local --rationale "antakelse 6" > "$planf" 2>/dev/null
[ -s "$planf" ]; check "plan-file starter renders" $?
mout="$(morning --plan-file "$planf" --dry-run 2>&1)"
printf '%s' "$mout" | grep -q '1 of 1'
check "morning --plan-file --dry-run reports 1 of 1 for the thin starter" $?
else
skip "morning not installed - antakelse 6 (plan-file starter) NOT measured"
skip "morning not installed - plan-file starter render NOT measured"
fi
echo
echo "orders-selftest: $PASS passed, $FAIL failed, $SKIP skipped (of $((PASS+FAIL+SKIP)) checks)"
[ "$FAIL" -eq 0 ] || exit 1
exit 0