feat(board): render the day plan as a third rendering of the same scan
The table says what the state of every repo is; the briefing says who is waiting. Neither says which repos to open a tab for today, in what order, and with which command - so a day plan was assembled by hand every morning from a table that deliberately takes no position. --plan is built on exactly the argument --brief was: a lookup over data the scan already holds, zero model calls, and route.sh already derives the per-repo command. The order IS the position it takes, and the only one - there is no cutoff, so nothing is hidden. The rule most likely to be "fixed" into a defect: repos owing mail rank first regardless of status. Excluding blocked or done is a claim about a repo's OWN next step, which by definition cannot be moved, while owing an answer is the other axis entirely - and answering is often what unblocks it. Measured on the real tree, two of 26 planned repos were done with an unhandled inbox, so the fixture tree pins done-with-debt and blocked-with-debt rather than the general rule alone. Repos with no board line rank last and are LABELLED, because the table already prints a note about them and dropping them silently would repeat that defect. key=value rather than prose, because the plan has two consumers: the operator, and a separate repo driving a terminal from it. Prose would make the rendered format an API no test here could hold stable for a consumer living in another repo. dir= is absolute because a new pane inherits its anchor's directory; command_missing= carries both no-command causes, because a driver reading ^command= would type a blank line into a live pane. route_cmd_for() becomes the single reader of the route-line grammar, shared with --brief, distinguishing the two failure causes by exit code rather than by an empty string. --brief output is unchanged. Driving a terminal from the plan stays OUT of this repo, on the measurement in docs/ghostty-orchestration-measurement.md rather than on taste. board-selftest: 51 -> 86 checks. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011eKRzhD1RqY2MxvDEkrJAM
This commit is contained in:
parent
5d9c76763d
commit
6d0fe14d0f
10 changed files with 485 additions and 31 deletions
12
README.md
12
README.md
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
*AI-generated: all code produced by Claude Code through dialog-driven development.*
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
|
@ -94,7 +94,7 @@ Scoring is judgement and belongs to the skill; turning scores into a row is a lo
|
|||
coord-done.sh <filename>... | --all # archive without replying
|
||||
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] # cross-repo attention board (read-only)
|
||||
board.sh [--roots <dir>[,<dir>...]] [--brief|--plan] # cross-repo attention board (read-only)
|
||||
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
|
||||
|
|
@ -107,6 +107,12 @@ The reply/resolve hints the hook injects (`-> reply: coord-send --reply-to …
|
|||
|
||||
It makes **zero model calls**, which is the point rather than a detail. Under subscription auth a headless session draws from the same quota pool as interactive work, and `--max-budget-usd` is a runaway brake rather than a pre-flight gate — measured against 2.1.220, it aborts *after* the first turn, never before it. `board.sh --brief` writes nothing; the file write lives in `brief-nightly.sh`, which renders to a temp file and renames it into place, and refuses to replace a good briefing with an empty render. `launchd/` holds a sample agent that runs it nightly; it points at a checkout, never at the version-pinned plugin cache.
|
||||
|
||||
**`board.sh --plan` renders the day plan**, a *third* rendering of that same scan and the only one that takes a position: which repos to open a tab for today, in what order, and the command to start each. The order is the position, and there is no cutoff — nothing is hidden, and four deterministic rules decide it. Repos owing mail come first, most-owed first, *whatever their status*: excluding `blocked` or `done` is a statement about a repo's own next step, which by definition cannot be moved, while owing an answer is a different axis and answering is often what unblocks it. Then live work (`in-progress`), then `planned`, then last and labelled, the repos with no board line at all — the table already prints a note about those, so a plan that dropped them silently would repeat exactly that defect. Still zero model calls, still read-only, and still cross-checked against `coord-count.sh`.
|
||||
|
||||
It prints `key=value` blocks rather than prose because it has **two consumers**: the operator pasting a command, and a separate repo driving a terminal from it. Prose would make the rendered format an API that no test here could hold stable for a consumer living in another repo. Each block carries `dir=` as an absolute path — a new terminal pane inherits its anchor's working directory, so a plan that omitted it would look right and point at the wrong repo. A repo whose route line is missing or unparseable gets `command_missing=` with the reason, never an empty `command=`: a driver reading `^command=` would type a blank line into a live pane.
|
||||
|
||||
Driving a terminal from this plan deliberately lives **outside this repo**. That work is a version-pinned, undocumented composition on top of a preview API whose documented path is already broken upstream, and its blast radius reaches into other repos' running sessions. The dependency runs one way — the driver consumes the plan, the plan never knows a terminal exists — so if the terminal API breaks, the plan still prints and the operator still pastes.
|
||||
|
||||
## Security Model
|
||||
|
||||
Cross-repo message content is untrusted input by design:
|
||||
|
|
@ -141,7 +147,7 @@ Note that raising the inbox's priority (Rule 7) deliberately does **not** widen
|
|||
## Development
|
||||
|
||||
bash scripts/coord-selftest.sh # 183 checks against a throwaway mailbox
|
||||
bash scripts/board-selftest.sh # 36 checks against a throwaway repo tree
|
||||
bash scripts/board-selftest.sh # 86 checks against a throwaway repo tree
|
||||
bash scripts/route-selftest.sh # 73 checks, incl. the route->board round trip
|
||||
npm test # all three selftests via node --test
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue