feat(brief): render the nightly cross-repo briefing without a model
The operator has more repos than they can hold in their head, and the question that actually costs them is "who is waiting on me, and what does answering cost". board.sh already scans for it; nothing rendered it in a form an unattended job could leave behind. --brief is a second RENDERING of that scan, never a second scan. It prints NESTE uncut, because the 38-character cut is the table column's property and not the record's - the value used to be truncated at record-build time, which left the cut string as the only copy. Each startup command is derived by CALLING route.sh with that repo's own four traits; next-cost alone cannot produce it, since the advisor flag is a property of the ROW and two rows can share a model/effort pair while differing on it. A repo with no route line is told so rather than handed a guess. It cross-checks itself against coord-count.sh, and that is the substance of the change rather than a nicety. The repo scan and the mailbox are two different populations: a mailbox can carry a name no scan will ever produce - a declared non-git surface (CLAUDE_COORD_REPO, e.g. ~/repos) or a checkout outside the roots. Measured on the real mailbox: 11 repos / 21 messages in the briefing against coord-count's 12 / 22, the missing one being the declared surface `repos`. A briefing that only walked the scan would answer "who is waiting on you" with a number it quietly knew was short. Zero model calls, which was the deciding property. Measured against 2.1.220 under subscription auth: --max-budget-usd DOES bite (terminal_reason budget_exhausted, exit 1), but it aborts AFTER turn one - floor ~0.25 USD-equivalent per turn on claude-opus-5[1m]. It is a runaway brake, not a pre-flight gate, so a nightly claude -p job would draw on the same quota pool as interactive work every night. Determinism removes the question. board.sh stays read-only: the file write lives in brief-nightly.sh, which renders to a temp file and renames it into place, and treats an EMPTY render as a FAILED one - board prints nothing when its scan roots do not exist, which is what a mistyped path or a moved home looks like, and a plain `> file` redirect would destroy yesterday's briefing on a bad launchd environment. The launchd template carries placeholders, not absolute paths: this repo is mirrored publicly and a plist is the one file here that would need a home directory in it. It points at a checkout rather than the plugin cache, which is version-pinned and would break silently on the next bump. board-selftest 36 -> 49. One check pins a defect caught only by eye against the real tree: fold copies its input's missing trailing newline, which ran the command onto the tail of the NESTE prose and produced a briefing whose commands could not be copied. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017orCFDkmp88fLnqDR3chdJ
This commit is contained in:
parent
459c9feec0
commit
9dd24c3446
11 changed files with 435 additions and 18 deletions
49
CLAUDE.md
49
CLAUDE.md
|
|
@ -54,7 +54,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` (36 checks).
|
||||
STATE.md and no mailbox. Pinned by `board-selftest.sh` (49 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
|
||||
|
|
@ -69,6 +69,46 @@ marketplace plugin. Three components, one boundary:
|
|||
one measured effect was an accidental fallback target for Claude sessions'
|
||||
own Bash tool calls (the bug 0.12.1 fixed) — once that fallback was gone they
|
||||
had no remaining function and were deleted.
|
||||
**`board.sh --brief` is a second RENDERING of that scan, never a second
|
||||
scan, and `brief-nightly.sh` is the only writer in that path.** The briefing
|
||||
answers the narrower question an unattended job can answer without judgement:
|
||||
which repos have an unhandled inbox, what their next step says in full, and
|
||||
the exact command to start a session in each. It prints NESTE uncut because
|
||||
the 38-character cut is the table column's property, not the record's — the
|
||||
value used to be truncated at record-build time, which left the cut string as
|
||||
the only copy. Each command is derived by CALLING `route.sh` with that repo's
|
||||
own four traits; `next-cost` alone cannot yield it, since the advisor flag is
|
||||
a property of the ROW and two rows can share a model/effort pair while
|
||||
differing on it. A repo with no route line is told so rather than handed a
|
||||
guess, because a guessed command reads as authoritative.
|
||||
|
||||
It also cross-checks itself against `coord-count.sh`, and that is not
|
||||
belt-and-braces. The repo scan and the mailbox are two different populations:
|
||||
a mailbox can carry a name no scan will ever produce — a declared non-git
|
||||
surface (`CLAUDE_COORD_REPO`, e.g. `~/repos` itself) or a checkout outside the
|
||||
roots. Measured on the real mailbox at 0.15.0: the briefing found 11 repos /
|
||||
21 messages where `coord-count` saw 12 mailboxes / 22 pending, the missing one
|
||||
being the declared surface `repos`. A briefing that only walks the scan
|
||||
answers "who is waiting on you" with a number it quietly knows is short.
|
||||
|
||||
**Zero model calls, and that is the load-bearing property, not an
|
||||
implementation detail.** The operator authenticates by subscription, so a
|
||||
headless `claude -p` job draws from the same quota pool as interactive work.
|
||||
Measured against 2.1.220: `--max-budget-usd` DOES bite under subscription auth
|
||||
(`terminal_reason: budget_exhausted`, exit 1), but it aborts AFTER turn one,
|
||||
never before it — floor ~0.25 USD-equivalent per turn on `claude-opus-5[1m]`.
|
||||
It is a runaway brake, not a pre-flight gate. Making the briefing deterministic
|
||||
removes the question entirely.
|
||||
|
||||
`board.sh` stays read-only, which is why the file write lives in the wrapper
|
||||
instead of behind a `--brief --out FILE` flag. The wrapper renders to a temp
|
||||
file in the target directory and renames it into place, and treats an EMPTY
|
||||
render as a FAILED one: board prints nothing at all when its scan roots do not
|
||||
exist, which is what a mistyped path or a moved home directory looks like, and
|
||||
a plain `> file` redirect would destroy yesterday's briefing on a bad launchd
|
||||
environment. A tree where nobody owes anything is a different case — that is a
|
||||
valid, non-empty briefing saying so, and is written normally.
|
||||
|
||||
- **Route (`scripts/route.sh`):** pure calculator for the next session's model
|
||||
and effort. Takes four scored traits of the next task plus a required
|
||||
rationale, and prints one block of `key=value` lines: the rubric row, the rule
|
||||
|
|
@ -169,7 +209,7 @@ 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 (182/182),
|
||||
`bash scripts/board-selftest.sh` must exit 0 (36/36) and
|
||||
`bash scripts/board-selftest.sh` must exit 0 (49/49) and
|
||||
`bash scripts/route-selftest.sh` must exit 0 (73/73).
|
||||
- English for all code, docs, and commit messages (public repo). Norwegian
|
||||
trigger aliases in the skill description are deliberate.
|
||||
|
|
@ -181,6 +221,11 @@ obligations in another repo.
|
|||
`bash scripts/route-selftest.sh` (or `npm test`, the Node wrapper around all three)
|
||||
- Hook smoke test: `node hooks/scripts/session-start.mjs` (expects JSON on stdout)
|
||||
- Board smoke test: `bash scripts/board.sh` (read-only, ~3s over the real tree)
|
||||
- Briefing smoke test: `bash scripts/board.sh --brief` (read-only, writes
|
||||
nothing). `brief-nightly.sh` DOES write — it overwrites `$CLAUDE_BRIEF_FILE`
|
||||
(default `~/.claude/briefing.md`), so point that at a scratch path when
|
||||
testing. Installed as a launchd agent from `launchd/`, which points at the
|
||||
SOURCE repo, never the version-pinned plugin cache.
|
||||
- Route smoke test: `bash scripts/route.sh --path known --verification strong
|
||||
--reversibility cheap --scope local --rationale x` (writes nothing, instant)
|
||||
- Sweep smoke test: `bash scripts/coord-sweep.sh` (dry-run is the default, so
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue