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
61
launchd/com.ktg.repo-mailbox-brief.plist
Normal file
61
launchd/com.ktg.repo-mailbox-brief.plist
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<!--
|
||||
Nightly cross-repo briefing. Renders ~/.claude/briefing.md from the same scan
|
||||
board.sh already does: which repos have an unhandled inbox, their next step
|
||||
in full, and the exact command to start a session in each.
|
||||
|
||||
ZERO MODEL CALLS. It runs two shell scripts and nothing else. This was the
|
||||
deciding property, not an implementation detail: the operator authenticates
|
||||
by subscription, so a headless `claude -p` job would draw from the same quota
|
||||
pool as interactive work - measured floor ~0.25 USD-equivalent per turn on
|
||||
claude-opus-5[1m], which --max-budget-usd cannot prevent because it aborts
|
||||
AFTER turn one, never before it.
|
||||
|
||||
PATH: every binary this touches (bash, git, awk, sed, fold, stat, find, date)
|
||||
lives in /usr/bin or /bin, so launchd's minimal default PATH is sufficient
|
||||
and no EnvironmentVariables block is needed.
|
||||
|
||||
The program path points at the SOURCE REPO, deliberately, not at the plugin
|
||||
cache. The cache path is version-pinned
|
||||
(~/.claude/plugins/cache/ktg-plugin-marketplace/repo-mailbox/0.13.0/...), so
|
||||
a plist pointing there would break silently on the next version bump - and a
|
||||
second copy of these scripts on disk is the exact defect class that produced
|
||||
the 0.12.1 stale-fallback bug.
|
||||
|
||||
This file is a TEMPLATE. It carries no absolute home path on purpose: the
|
||||
repo is mirrored publicly, and a plist is the one file here that would need
|
||||
one. Substitute both placeholders at install time.
|
||||
|
||||
Install: sed -e "s|__CHECKOUT__|$PWD|g" -e "s|__HOME__|$HOME|g" \
|
||||
launchd/com.ktg.repo-mailbox-brief.plist \
|
||||
> ~/Library/LaunchAgents/com.ktg.repo-mailbox-brief.plist
|
||||
launchctl load ~/Library/LaunchAgents/com.ktg.repo-mailbox-brief.plist
|
||||
Run now: launchctl start com.ktg.repo-mailbox-brief
|
||||
Remove: launchctl unload ~/Library/LaunchAgents/com.ktg.repo-mailbox-brief.plist
|
||||
-->
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.ktg.repo-mailbox-brief</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>__CHECKOUT__/scripts/brief-nightly.sh</string>
|
||||
</array>
|
||||
|
||||
<key>StandardErrorPath</key>
|
||||
<string>__HOME__/Library/Logs/repo-mailbox-brief.log</string>
|
||||
<key>StandardOutPath</key>
|
||||
<string>__HOME__/Library/Logs/repo-mailbox-brief.log</string>
|
||||
|
||||
<key>StartCalendarInterval</key>
|
||||
<dict>
|
||||
<key>Hour</key>
|
||||
<integer>6</integer>
|
||||
<key>Minute</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
Loading…
Add table
Add a link
Reference in a new issue