feat(board): --dispatch, the startup command a dispatched session can act on
"Start a session in repo X, on order Y, at cost Z" was produced by hand, and it misfired four times on 2026-08-16 across two repos. Three distinct holes, all measured, all closed here: 1. A bare `claude --model X --effort Y` forces the operator to type Go, and the session then guesses its task out of STATE.md. The emitted command carries the prompt in argv: `... "$(cat <file>)"`. Verified directly that this passes the file's bytes as ONE argv element with no re-evaluation, so $(...), backticks, quotes and UTF-8 in the prompt BODY are inert - only the PATH is expanded, so it must be absolute and shell-clean. 2. --no-go stops only the follow-up Go message, never the work (morning:806). The plan-file form says so in its own output, not just in a comment. 3. A session dispatching its own next session gets an empty plan: morning's plan_drop_open (morning:1788) drops a block whose repo already has a pane, and --dry-run says "0 of 1", which reads as a broken plan file. --dispatch therefore emits two forms, chosen by --target-pane: a plan block, or a bare paste line for the tab that already exists (and no tab= key at all, so it can never be fed to morning as a plan). Generator ownership, the question left open for two sessions: it goes in board.sh, which already owns the block format including paste=. A second emitter of tab=/repo=/dir=/command=/paste= would be two copies of one file format. Read-only survives - the prompt file and the plan file are written by the caller, the brief-nightly.sh split unchanged. --target-pane yes|no is REQUIRED with no default, the same rule --last-effort carries: it is a measurement (morning --probe-panes, which works without a tty), and the dry-run cannot substitute for it - run from a Claude session morning reports "window: unknown ... assuming an empty window" and plan_drop_open never fires, so a dry-run gate would pass the self-dispatch case every time. Cost comes from route.sh's row table; --dispatch deliberately takes no --model/--effort, because --advisor opus is a property of the ROW and a dispatch taking the model directly has no honest source for that flag. New skills/dispatch/SKILL.md is the front door. board-selftest 183 -> 217. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ett8uHMDLir6trFaMzrYRu
This commit is contained in:
parent
21e2873e21
commit
1ee003328c
5 changed files with 580 additions and 10 deletions
12
README.md
12
README.md
|
|
@ -12,7 +12,7 @@ Session A in repo X leaves a message for repo Y; the next session in repo Y gets
|
|||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
|
|
@ -94,6 +94,8 @@ It lives here because it is the **writer** for the cost field the board already
|
|||
|
||||
Scoring is judgement and belongs to the skill; turning scores into a row is a lookup and costs no model calls. One deliberate side effect is worth more than the tokens saved: a next step that cannot be scored `known` or `partial`, with no design phase planned, is an **underspecified task description** — the answer is to rewrite the step, not to upgrade the model.
|
||||
|
||||
**Handing a task to another session (the `dispatch` skill).** "Start a session in repo X on this order." `board.sh --dispatch` turns that into one line the operator can paste: the order written to a prompt file, the model and effort looked up from the same row table `route.sh` uses, and the prompt passed **in argv** — `claude --model … --effort … "$(cat <file>)"` — so the session is handed its task instead of having to guess it out of STATE.md. It emits one of two forms, and which one is a measurement rather than a preference: a repo with no terminal pane gets a plan block (`morning --plan-file <f> --no-go`), while a repo that already has one gets a bare paste line for that tab, because a plan block for an already-open repo is silently dropped by the driver and reads as a broken plan file. `--target-pane yes|no` is therefore required with no default, exactly as `route.sh` refuses to default `--last-effort`: it is a fact about the world, and this plugin never looks for a terminal itself. Read-only holds — the prompt file and the plan file are written by the caller, never by `board.sh`.
|
||||
|
||||
**CLI.** The engine is eight user-facing bash scripts in the plugin's `scripts/` directory (plus four selftests); resolve them as `"${CLAUDE_PLUGIN_ROOT:-$HOME/.claude}/scripts/coord-<name>.sh"` (from a terminal, use the plugin's install path):
|
||||
|
||||
coord-send.sh --to <repo> --subject "<subject>" [--message "<text>"] # or body on stdin
|
||||
|
|
@ -106,6 +108,8 @@ Scoring is judgement and belongs to the skill; turning scores into a row is a lo
|
|||
coord-count.sh [--exclude <mailbox>] # per mailbox: pending + replies owed, delivering nothing
|
||||
coord-sweep.sh [--write] [--days <n>] [--log <path>] # close aged notices machine-wide (dry-run by default)
|
||||
board.sh [--roots <dir>[,<dir>...]] [--brief|--plan] [--focus "<prose>"] # cross-repo attention board (read-only)
|
||||
board.sh --dispatch --repo <name> --prompt-file <abs path> \
|
||||
--target-pane <yes|no> --path <v> ... --rationale "<why>" # startup command for a session in <name>
|
||||
brief-nightly.sh # render the briefing to a file, atomically
|
||||
route.sh --path <v> --verification <v> --reversibility <v> \
|
||||
--scope <v> --rationale "<why>" # model + effort for the next session
|
||||
|
|
@ -163,10 +167,10 @@ Note that raising the inbox's priority (Rule 7) deliberately does **not** widen
|
|||
|
||||
## Development
|
||||
|
||||
bash scripts/coord-selftest.sh # 197 checks against a throwaway mailbox
|
||||
bash scripts/board-selftest.sh # 178 checks against a throwaway repo tree
|
||||
bash scripts/coord-selftest.sh # 220 checks against a throwaway mailbox
|
||||
bash scripts/board-selftest.sh # 217 checks against a throwaway repo tree
|
||||
bash scripts/route-selftest.sh # 69 checks, incl. the route->board round trip
|
||||
bash scripts/state-line-guard-selftest.sh # 21 checks, incl. the Edit replace_all projection and the ratchet
|
||||
bash scripts/state-line-guard-selftest.sh # 23 checks, incl. the Edit replace_all projection and the ratchet
|
||||
npm test # all four selftests via node --test
|
||||
|
||||
TDD is the house rule: every behavior change lands with a failing selftest check first.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue