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
This commit is contained in:
Kjell Tore Guttormsen 2026-08-18 09:16:59 +02:00
commit 393499c3ee
6 changed files with 130 additions and 11 deletions

View file

@ -82,7 +82,7 @@ marketplace plugin. Three components, one boundary:
mailbox, `~/.claude/coord/<repo>/orders/`, with four one-verb scripts —
`coord-order-send.sh` (write), `coord-order-inbox.sh` (read for injection),
`coord-order-claim.sh` (claim), `coord-order-done.sh` (terminal state).
Pinned by `orders-selftest.sh` (99 checks).
Pinned by `orders-selftest.sh` (104 checks).
**It is a separate CHANNEL, not more mail, and the axis is authorization.**
Inbox content is untrusted cross-repo data that may never instruct a session
@ -128,6 +128,33 @@ marketplace plugin. Three components, one boundary:
reason is "trust me" and would quietly become the cheapest way to close any
order. The reason is written INTO the order, so the next session that picks
it up sees why the last one put it down.
**ORDRE 65 (.claude, 2026-08-17): the verbs told a session to run themselves
by a BARE name, and neither is on PATH.** `board.sh`'s dispatch starter
(`--dispatch --order-id`) told a dispatched session to run `coord-order-claim
<id>` and `coord-order-done <id> ...` literally — command-not-found on step
one, misreadable as "the order does not exist" (Verifiseringsloven ansikt 4).
Measuring the denominator (the order asked only about `board.sh`, but the
defect is a class, not one line) found the SAME bare name in two more places
that print text a session is meant to execute next: `coord-order-inbox.sh`'s
SessionStart injection (the `-> claim:` / `-> in flight` hints shown for
EVERY pending/claimed order, not only a dispatched one) and
`coord-order-claim.sh`'s own `WHEN DONE` / `IF YOU CANNOT` lines, printed
directly to the session that just claimed. All three now call the verb by
the absolute path SIBLING TO THE PRINTING SCRIPT ITSELF (`$SELFDIR`, derived
from `$0`'s directory — the same technique `route.sh`'s own path already
uses in `board.sh`), not a literal version string: correct at the moment the
text is generated, for whichever install location is live then. It does not
survive a version bump landing between generation and paste — a plan-file
form held across a release can still go stale, the same way any other path
baked into a plan file would. `board.sh`'s `$SELFDIR` interpolation sits in
the exact double-quoted position `--prompt-file`/`--order-id` are already
shell-clean-checked in, so it got the identical guard — proven reachable
(not speculative) by invoking a COPY of `board.sh` from a directory whose
path contains a space, mirroring the fixture the `--prompt-file` tests
already use for the same reason. `coord-inbox.sh`/`coord-send.sh`/
`coord-done.sh` remain undisturbed: they have only ever been documented as
bare names in prose a human reads, never in text a session is handed to run.
- **Hook (`hooks/scripts/session-start.mjs`):** thin zero-dependency Node
wrapper (marketplace convention: hooks are `.mjs`) that calls
`coord-inbox.sh` AND `coord-order-inbox.sh` and emits the
@ -289,7 +316,7 @@ marketplace plugin. Three components, one boundary:
- **Board (`scripts/board.sh`):** cross-repo attention board. Reads STATE.md
next-step blocks + board lines, `git status`, and mailbox pending counts, and
prints one line per repo. Read-only by construction: it writes to no repo, no
STATE.md and no mailbox. Pinned by `board-selftest.sh` (217 checks).
STATE.md and no mailbox. Pinned by `board-selftest.sh` (246 checks).
**It lives here because the mailbox is one of its three inputs, and it carries
the same axis distinction the mailbox does.** A pending count means *others
@ -715,9 +742,9 @@ obligations in another repo.
builtins only in hook and tests.
- TDD: no behavior change without a failing selftest check first.
`bash scripts/coord-selftest.sh` must exit 0 (220/220),
`bash scripts/board-selftest.sh` must exit 0 (239/239),
`bash scripts/board-selftest.sh` must exit 0 (246/246),
`bash scripts/route-selftest.sh` must exit 0 (69/69),
`bash scripts/orders-selftest.sh` must exit 0 (99/99) and
`bash scripts/orders-selftest.sh` must exit 0 (104/104) and
`bash scripts/state-line-guard-selftest.sh` must exit 0 (40/40).
- English for all code, docs, and commit messages (public repo). Norwegian
trigger aliases in the skill description are deliberate.