`sed 's/--*>/-->/g; s/-->/ /g'` rewrote `->` (ONE dash) into `-->` and then blanked it, so a reason written the way this repo writes prose - "premise -> dead" - silently lost its arrow. The intent was only to stop a literal `-->` from closing the trailer's HTML comment early. Replaced with a single expression matching two-or-more dashes, `s/---*>/ /g`. Same over-broad-escaping class as the `$`-pattern bug in pre-state-line-guard.mjs, and invisible for the same reason: the fixture reason had no arrow. Two checks added - a plain arrow must survive, a literal `-->` must still be neutralised - so the escape now has both a known-positive and a known-negative. orders 97 -> 99. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0134iB7ipXGgEpv9imYoVmr2
370 lines
22 KiB
Bash
Executable file
370 lines
22 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" $?
|
|
printf '%s' "$r2" | grep -q "coord-order-claim $oid1"; check "read gives a per-order claim hint" $?
|
|
# 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" $?
|
|
[ ! -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 -q "coord-order-done $oid1 --return"; check "read gives the return hint for a claimed order" $?
|
|
|
|
# --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
|