feat(board): --voyage reports the Voyage briefs in flight
board read STATE lines and knew nothing about a brief, so a programme running Voyage across several repos had no shared surface: nobody could answer which briefs were in flight, in what phase, and who was waiting on whom. Order 20260831T135934Z-696228720 fired the programme-level B1 row once /trekplan had been delivered in llm-ingestion-okf, so the fields were chosen against a run that had gone the whole way rather than guessed. Adds board.sh --voyage (a sixth rendering of the same scan, read-only) and a VOY column beside ORDRE and FLY, never summed with them and never in the sort. Detection is by PROPERTY, never by directory name: a directory holding brief.md or brief.md.draft under any of the three planning locations the convention recognises. It walks the FILESYSTEM, never the git index - llm-ingestion-okf gitignores .claude/projects/ (087be0b), so an index-based detector would report ZERO briefs in the one repo actually running one. The phase ladder measures ARTIFACTS, not sessions, and the legend says so: /trekexecute leaves a file behind only in its multi-session form, so a plan executed in one session leaves nothing and `plan` is the last thing the filesystem can prove. Nothing here claims a session is alive - the same refusal FLY carries. Three absences that must not borrow the shape of a measurement: brief_quality is read from the frontmatter block only and an absent field reads `-`, never `complete` (only 8 of ~40 briefs on the real tree carry it); research=- (never started) is distinct from research=0 (a directory holding nothing); and --voyage always prints its own denominator rather than rendering as an empty page. Blocking decisions are counted at DECLARATION SITES, not mentions: the pattern occurs on four lines of the real brief, of which one declares it, so a bare grep -c answers 4 where the honest answer is 1. The age is the NEWEST artifact, inverting the oldest-wins rule ORDRE and FLY carry - an order queue's problem is the oldest item still waiting, a project's problem is that its most recent activity is old. Mutation-verified three ways: newest->oldest turns exactly one check red, anchored pattern->bare string turns three red (the known-negative control among them), filesystem->git ls-files turns 23 red. Live-verified against the completed run: fase=plan, kvalitet=complete, blokkerende=1, gate=S4, research=5 - the only project of 51 across 14 repos with an open blocking decision. Cost measured rather than assumed: 0.31.0 takes 6.3s over the real 52-repo tree, with VOY 7.7-9.2s. The first cut called stat once per artifact and took 13.4s; the batched form is what makes the column affordable. CLAUDE.md's old "~3s" claim did not survive the measurement and is corrected. Bounded gap, stated rather than closed: whether a detected project is still "in flight" is not decided here. That needs a threshold, and a threshold would make the board decide that work is abandoned - the identical thing the order queue is already forbidden from doing. board-selftest.sh: 325 -> 360 checks. Co-Authored-By: Claude <claude-opus-5>
This commit is contained in:
parent
0711b4209c
commit
85cd628c3e
5 changed files with 701 additions and 21 deletions
|
|
@ -114,6 +114,7 @@ Ownership is explicit rather than implied. An order is pending until a session *
|
|||
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 --voyage # Voyage briefs in flight (read-only)
|
||||
board.sh --dispatch --repo <name> --order-id <id> \
|
||||
--target-pane <yes|no> --path <v> ... --rationale "<why>" # startup command for a session in <name>
|
||||
coord-order-send.sh --to <repo> --subject "<s>" --prompt-file <abs path> # deliver a work order into <repo>'s queue
|
||||
|
|
@ -133,6 +134,8 @@ 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 --voyage` reports the Voyage briefs in flight**, a sixth rendering of the same scan. `board` reads STATE lines, which say nothing about a brief, so a programme running Voyage across several repos had no shared surface: nobody could answer which briefs were running, in what phase, and who was waiting on whom. Detection is by **property, never by directory name** — a directory holding `brief.md` or `brief.md.draft` under any of the three planning locations the convention recognises (`.claude/projects/`, `docs/`, `features/<n>-<name>/`) — and it walks the **filesystem, never the git index**: a repo that gitignores `.claude/projects/` would otherwise report zero briefs while actually running one. The phase ladder measures *artifacts*, not sessions: a plan executed in a single session leaves no file behind, so `plan` is the last thing the filesystem can prove, and nothing here claims a session is alive. `brief_quality` is read out of the brief's frontmatter and an absent field reads `-`, never `complete`; a research directory that exists and holds nothing reads `0`, distinct from the `-` that means no research step was ever started. The table carries a matching `VOY` column beside `ORDRE` and `FLY` — the same class of durable filesystem fact, and never summed with them.
|
||||
|
||||
**`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 one deterministic score decides it: `40 ×` repos released transitively, `15 ×` unhandled inbox messages, plus small bonuses for live work and for a cheap `next-cost` row. Four hard buckets preceded it and could not express "this repo owes one message and releases two others" — which is how a blocked chain's root ended up ranked *below* the repos waiting on it. **Chain-root credit** follows `blocked-on` transitively to the first repo that is not itself blocked and credits only that root: opening a blocked repo releases nobody, since its own next step is by definition waiting. A cycle, or a `blocked-on` naming a repo the scan never produced, credits nobody rather than inventing a root — a plan that looks correct while sending you to the wrong repo is worse than one that says nothing. Repos owing mail still rank high *whatever their status*, and debt is deliberately **uncapped**: excluding `blocked` or `done` is a statement about a repo's own next step, which cannot be moved, while owing an answer is a different axis and answering is often what unblocks it. Repos with no board line come last and labelled — the table already prints a note about those, so a plan that dropped them silently would repeat exactly that defect. `why=` names the dominant term, so a block reads `unblocks:2` rather than the `inbox:N` every block used to repeat. Still zero model calls, still read-only, and still cross-checked against `coord-count.sh`.
|
||||
|
||||
**`--focus "<prose>"` narrows that plan to one subject, and reports what it held back.** It is the only cutoff this format has, which is why the report is a condition of the feature rather than a refinement of it: `--plan` documents that it hides nothing and labels what it cannot rank, so a silent filter would break a property already written down. The same run prints the subjects the prose resolved to, how many blocks were removed, how many `STATE.md` were searched, and — named, not counted — the repos that *mention* a resolved subject without declaring a marker line. That last class is enumerated because it is where the misses live: a repo can be a heavy participant and never have written a marker, and no string measurement finds it until the held-back population is listed. Each surviving block carries the declaration it survived on. Prose matching nothing prints the *full* plan and says so, since the phrase arrives verbatim from a person and a typo must not empty the day. The subject vocabulary is read from the scanned `STATE.md` themselves, so the "reads `STATE.md` and no other file" invariant is untouched.
|
||||
|
|
@ -180,7 +183,7 @@ Note that raising the inbox's priority (Rule 7) deliberately does **not** widen
|
|||
## Development
|
||||
|
||||
bash scripts/coord-selftest.sh # 220 checks against a throwaway mailbox
|
||||
bash scripts/board-selftest.sh # 237 checks against a throwaway repo tree
|
||||
bash scripts/board-selftest.sh # 360 checks against a throwaway repo tree
|
||||
bash scripts/route-selftest.sh # 69 checks, incl. the route->board round trip
|
||||
bash scripts/orders-selftest.sh # 99 checks, incl. the 20-way barriered claim race
|
||||
bash scripts/state-line-guard-selftest.sh # 40 checks, incl. the Edit replace_all projection and the ratchet
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue