feat(cli): the turn-start brief names the docs the code outran (BEA-202) - #208
Open
ssowonny wants to merge 2 commits into
Open
feat(cli): the turn-start brief names the docs the code outran (BEA-202)#208ssowonny wants to merge 2 commits into
ssowonny wants to merge 2 commits into
Conversation
Three of the brief's four pieces already shipped from emitHookContext every turn: the gated-link formula, what teammates changed, credential-shaped files. The fourth — which synced docs their own code has moved past — was computed by `bdrive stale` and seen only by a human who typed the command. Agents do not type commands. stale.go and hooksync.go are the same package, so this is one shared helper and two appended sentences, not an extraction: - staleDocs lifts runStale's doc loop out unchanged, plus a deadline. The command passes the zero time (no budget); the hook passes one shared across every mount, because staleRefs opens every synced markdown file and a hook that blocks the turn must drop the sentence, never the turn. - The hook takes its inputs from the session it already holds — AllOps to date the paths (mtime is wrong on a freshly synced machine) and the cycle's own materialization cache as the synced set, which is fresher than a second walk and free. Nothing here touches the network. - A second sentence names the mount's AGENTS.md when it syncs. Codex never discovers one off the root->cwd path and the others find it only lazily, so this is where every platform with hooks at all gets told. It is the one place hookAgentPath is deliberately skipped: rules above the session are still the agent's to open, so the path climbs with ../ instead of being dropped. Every failure — a journal read error, an expired budget, a missing cache — is a missing sentence and an exit 0. Measured: a 500-file / 200-doc project runs the whole hook in ~24ms against a 250ms budget. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
runHookSync returns false for a non-hub remote, so everything computed before that check is discarded. Move the scan after it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TL;DR
bdrive stalealready computed it — only nobody who wasn't typing the command ever saw it.AGENTS.mdwhen it syncs. Codex never finds one off the root→cwd path, so this is the one place every platform with hooks gets told the rules exist.The shape of the change
Three of four pieces already shipped from
emitHookContextevery turn. This fills the hole.flowchart TB B["the agent's turn-start brief"] B --> L["link formula<br/><b>shipped</b><br/>hooksync.go"] B --> C["changed-since<br/><b>shipped</b><br/>hookChanged"] B --> R["team rules<br/><b>this PR</b><br/>hookRules"] B --> S["hot / stale<br/><b>this PR, stale half</b><br/>hookStale"] style R fill:#dcfce7,stroke:#16a34a style S fill:#dcfce7,stroke:#16a34aWhat an agent actually receives now, appended to the same single JSON object:
What can't break
bdrive staleitself. Step 1 is a pure refactor:runStale's doc loop moves intostaleDocs, which the command calls with a zero deadline (no budget). Every line of its printing, its-l/-nflags and its exit status are untouched, and every existingTestStale*passes unchanged — that is the proof.The turn. Every failure path — a journal read error, a missing materialization cache, an expired budget — is a missing sentence and an exit 0. Same silent-degrade posture
hookChangedandhookSecretsalready have.TestSyncHookModeStaleDegradessetshookStaleBudget = -time.Secondand asserts the sentence is gone, the links survive, and the JSON is still one valid object.Sync invariants. Nothing here writes a journal, takes the volume flock, or touches the network.
AllOpsandLoadCacheare reads on a store the session already holds.What you're accepting
syncer.SyncedFiles(a second walk)bdrive stale's by a turn+N morehookChangedMax's 20../-climbing path for the rules pointerhookAgentPathhookAgentPathdrops anything outside the session's subpath — right for a sibling folder's doc, wrong for rules the agent should still openThree small deviations from the reviewed plan, all cheap to reverse. The gap format is normalized to
(N files newer, oldest gap Xd)for every doc (the spec's example rendered the second one differently). The rules sentence has a second phrasing for the multi-mount case, since "this project's team rules" reads wrong with two paths in it. AndhookStaleDocssorts the cache keys before scanning, so the tie-break between equal gaps doesn't ride on Go's map order.What was run
go test ./...— green, every package, at HEAD (cmd/bdrive40s,internal/webapp380s).go vet ./...— clean.gofmton the four touched files only; a blanket run drags six unrelated files in.emitHookContextappends removed, six of the seven new cases fail. They bite.--hookinvocation in ~24 ms against the 250 ms budget.web/docsbuilds (Astro + Pagefind, 20 pages).No frontend change, so no
npm run e2eand no UI screenshots — the diff iscmd/bdriveand four doc surfaces.Tests, one per acceptance criterion
TestSyncHookModeReportsStaleDocsTestSyncHookModeNoStaleSaysNothingTestSyncHookModeStaleNoJournal+N moreTestSyncHookModeStaleCapTestSyncHookModeStaleMultipleMountsTestSyncHookModeStaleInsideMountTestSyncHookModeStaleDegradesAGENTS.mdsynced → named once; absent → nothingTestSyncHookModeRulesPointerTestSyncHookModeRulesAboveSessionDocs
Four surfaces, all of which describe the hook's output and all of which went stale together:
README.md'sbdrive syncrow,reference/cli.md's,manual/hooks.md's "Three hooks, three jobs", andguides/shared-agent-memory.md's "Your agent is told what moved" — which is also where theAGENTS.mdpointer belongs, right under the platform-discovery table that motivates it.Architecture changes
None.
staleDocsis a new function, andhookLink/hookSyncgained two fields each — none of them are types thearchitecture/diagrams draw, and no seam between drawn packages changed. Hence# skip-diagram-check.Open question
Is the multi-mount rules sentence worth the second phrasing at all, or should a run covering several projects just name the nearest
AGENTS.mdand stay silent about the others? One project per session is the overwhelmingly common case, and I built for the rare one.Build session
(only works on this machine)