Move the local-environment section out of CLAUDE.md, which every bot stage loads on every turn - #651
Conversation
Every bot stage loads CLAUDE.md before it does anything, on the main agent and again on its sub-agent, and re-sends it on every turn. It was 45,488 B, of which 33,743 B (74%) was one section describing this machine: the macOS sandbox knobs, podman, the permission deny/ask/allow rules, worktree layout, the Playwright install hang. None of it can apply in CI. All five stages run on a fresh ubuntu-latest checkout under `--permission-mode bypassPermissions`, so there is no prompt to avoid, no sandbox, no podman VM, no worktrees and no .venv symlinks. The `git stash` prohibition's own reasoning is "~20 worktrees share one refs/stash"; a runner has one checkout and no other agents. No workflow references the section. Measured on Stage 2, whose floor before it reads the issue, the bundle or any source was 92,438 B: CLAUDE.md 45,488 + bess-analyst.md 25,681 + rules.md 10,548 + the inline prompt 7,098 + architecture.md 3,623. The relocated section alone was 36% of that, twice over, on every turn. So it moves to docs/agents/local-agent-environment.md and is reached through the Agent Documentation Index, which is the mechanism CLAUDE.md already uses for rules.md, architecture.md, patterns.md and the rest. Nothing is deleted or condensed -- the content is hard-won, much of it marked (measured), and it is still required reading for autonomous local work. CLAUDE.md goes 45,488 B -> 11,926 B. One wording change was forced by the move: the text said "CLAUDE.md itself teaches `git -C .claude/worktrees/<name>`", which stops being true once the text is the teacher. It now says "this document itself". quality-check.sh gains a byte-budget gate so the section cannot creep back inline, written RED first (45,488 B against a 16,000 B cap) and green after at 11,926 B. Its failure message points at the relocate-and-link mechanism rather than at raising the cap, because raising the cap is how this grew. Five inbound references repointed, two of which only surface on a failure path and would have sent the reader to a file that no longer had the answer: worktree-setup.sh's blocked-cache diagnostic and verify-sandbox.sh's two assertion messages, plus sweep-prs/SKILL.md and skill-architecture.md. No CHANGELOG entry: zero user-visible effect, agent-facing documentation only, matching #649 which changed the same pipeline and added none. Closes #650
|
@claude-bot review |
There was a problem hiding this comment.
Summary
Root cause match: Yes. This closes #650 exactly — #650 measured CLAUDE.md at 45,488 B with ## Worktree Conventions (incl. Permissions/sandbox/podman/Playwright) accounting for 33,743 B (74%), loaded on every bot-stage turn on both the main and sub-agent. The PR relocates that section verbatim to docs/agents/local-agent-environment.md, reached through the existing Agent Documentation Index. Verified independently against the PR branch:
git show origin/worktree-issue-650-trim-ci-preamble:CLAUDE.md | wc -c→ 11,926 B, matching the PR description exactly.- Diffed the removed
CLAUDE.mdsection against the new file's content — byte-identical except the one deliberate rewrite ("CLAUDE.md itself teaches" → "this document itself teaches"), which is correctly forced by the relocation. bash -non all three touched scripts (quality-check.sh,verify-sandbox.sh,worktree-setup.sh) — no syntax errors.
Would the added test catch a regression? Yes. scripts/quality-check.sh's new CLAUDE_MD_MAX_BYTES=16000 gate (lines ~538–548 of the PR version) fails the build if the moved content creeps back inline, and the PR's RED→GREEN evidence (45,488 B failing against the cap, 11,926 B passing after the move) is a legitimate regression test for the stated problem — bot-stage context bloat.
Minimal / no scope creep? Yes. Every touched file is either the relocated content itself, the gate that pins it, or a reference that pointed at the moved section. No unrelated cleanup, no parameter/flag/fallback added — matches the PR's own scope-assessment statement (rules.md Debugging Protocol step 9 satisfied).
Architecture/style checklist: N/A for this diff — no Python/TS code, no sensor access, no new classes, no exception handling touched.
Finding (nit, not a blocker)
gh api is unavailable to me in this run, so posting this as a summary note per the review instructions rather than an inline comment.
-
.claude/skills/release/SKILL.md:29— still reads:"e.g. it was cut fresh via
git worktree add ... origin/main, per the Worktree Conventions inCLAUDE.md"This is a fifth dangling reference to "Worktree Conventions in
CLAUDE.md" that the PR's cleanup sweep missed.CLAUDE.mdno longer has aWorktree Conventionssection at all after this PR (confirmed:grep -n "Worktree Conventions" CLAUDE.mdon the PR branch returns nothing) — it moved entirely intodocs/agents/local-agent-environment.md. The PR description says "/code-reviewfound four dangling pointers, all fixed in this branch," and listsworktree-setup.sh,verify-sandbox.sh(×3),sweep-prs/SKILL.md(×2), andskill-architecture.md—release/SKILL.mdisn't in that list and wasn't updated. Not a functional break (the release skill still works; the pointer is just stale), but worth a one-line follow-up fix:`CLAUDE.md`→`docs/agents/local-agent-environment.md`(or drop theCLAUDE.mdcitation entirely per the Agent Documentation Index pattern).
Everything else — the doc move, the byte-budget gate, the four other repointed references, the test plan evidence — checks out. Approving; the one stale reference above is small enough to fix in a follow-up rather than block this PR.
The Stage 4 review found one more dangling pointer the sweep missed:
release/SKILL.md:29 still cited "the Worktree Conventions in CLAUDE.md",
a section that no longer exists there.
The sweep missed it because the exclusion pattern was wrong, not because
the search was too narrow. It filtered `\.venv` to skip the vendored tree,
but grep -v applies to the whole line, and this line's TEXT contains
`.venv` ("If this branch/worktree has no `.venv` yet"), so a real hit was
dropped silently. Same shape as the earlier `head -20` truncation: a filter
that reads as coverage while removing results.
Re-swept with path exclusions anchored to path separators. Four references
to "Worktree Conventions" remain and all four resolve; every other file
citing CLAUDE.md points at a section still in it (Verification Before
Action, Cost Discipline, Release Workflow, General bot rules, the index).
main moved the local-environment section out of CLAUDE.md (#651), so the gh scopeless-token note lands in docs/agents/local-agent-environment.md instead. The backlog/board half of this branch is removed here, not lost: it is preserved at eb4d00e and moves to its own PR, per the review's primary blocker (undescribed, orthogonal changes making up over half the diff). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vHvj9qtD1jDYVnm3LjTnt
…655) Stage 2's main agent listed `.claude/agents/bess-analyst.md` (25,681 B) as REQUIRED READING item 3. That file IS the bess-analyst sub-agent's system prompt -- frontmatter `name: bess-analyst`, `tools: Read, Grep, Glob, Bash, WebFetch` -- so the main agent was loading a second copy of another agent's instructions into its own context, on every turn. Nothing consumed it. The six PROCESS steps are: get issue context, identify the current problem, delegate, verify the cited file:line, publish, label. No step applies a "domain expertise checklist". The one distinctive task, step 4, needs the cited code -- not a triage procedure the main agent never runs. The content was in fact loaded three times. The section that could plausibly serve as a judging standard, "Separate Evidence from Claims", is already restated almost verbatim in the sub-agent task the same prompt passes: hypothesis-not-diagnosis, triage-the-bundle-first, verify-the-code-path- matches-this-user's-setup, intentional-design-is-not-a-bug. Sub-agent system prompt, main-agent file read, and inline paraphrase. All four landed Stage 2 analyses (#118, #252, #624, #627) use the workflow's four headings, never bess-analyst.md's seven-item Output Format or its six-item type-B shape -- the main agent follows the prompt, not the file. So item 3 is removed, with an explicit note saying why, and step 4 gains the check that was missing: a report fails verification if it claims a CODE bug with no file:line, if a cited location does not say what is claimed, or if it blends P-optimality / forecast error / control noise into one verdict when actual behavior diverged from plan. Dead weight becomes an instruction that fires. Three things the first draft got wrong, found in review: - "cites no file:line" alone would have rejected CORRECT diagnoses. The same prompt tells the analyst that unavailable sensors, wrong inverter type or an HA integration mismatch are likely the real cause, and those cite no code. Now qualified to code-bug claims only. - The inconclusive path never removed `ready-for-analysis`, and backlog-digest.sh checks that label BEFORE `needs-human-review`, so the backlog pass reports the issue as un-analysed and re-dispatches analyze -- re-billing the stage. Widening that path without fixing it would have made a cost bug worse. It now clears the label. - The new criterion used vocabulary defined only in the file this diff stops the agent reading. P-optimality had a gloss; P≠R never expanded P or R and control noise had no definition. All three are now glossed inline. quality-check.sh gains a context contract gate, written RED first: no workflow may list a `.claude/agents/*.md` file as a numbered required read, and Stage 2 must still delegate. Both assertions were mutation-tested -- removing the delegation reddens it, and reformatting `subagent_type` with backticks or quotes does not, which the first bare-substring version got wrong in both directions. Saving is up to 25,681 B off the main agent per turn; the prompt itself grew 7,098 -> 7,821 B, so net is roughly -24.9 KB. "Up to", because whether a run obeyed the read instruction is not observable -- #646 showed it need not. No CHANGELOG entry: agent-facing, zero user-visible effect, as #649 and #651. Closes #654
Summary
CLAUDE.md45,488 B → 11,926 B (−74%), by relocating one section todocs/agents/local-agent-environment.mdquality-check.shgains a byte-budget gate so it cannot creep back inlineRoot cause
Every bot stage loads
CLAUDE.mdbefore it does anything, on the main agent and again on its sub-agent, and re-sends it on every turn. 74% of it was one section describing this machine — the macOS sandbox knobs, podman, the permissiondeny/ask/allowrules, worktree layout, the Playwright install hang.None of it can apply in CI. All five stages run on a fresh
ubuntu-latestcheckout under--permission-mode bypassPermissions: no prompt to avoid, no sandbox, no podman VM, no worktrees, no.venvsymlinks. Thegit stashprohibition's own reasoning is "~20 worktrees share onerefs/stash" — a runner has one checkout and no other agents. Grep confirms no workflow references it.Stage 2's fixed floor, before it reads the issue, the bundle, or any source:
CLAUDE.md.claude/agents/bess-analyst.mddocs/agents/rules.mdprompt:docs/agents/architecture.mdThe relocated section was 36% of that, twice over (main agent + sub-agent), on every turn.
Fix
Move
## Worktree Conventionstodocs/agents/local-agent-environment.md, linked from the Agent Documentation Index — the mechanismCLAUDE.mdalready uses forrules.md,architecture.md,patterns.md. The new file opens with a header saying what it covers and that it does not apply to the CI stages.One wording change was forced by the move: the text said "CLAUDE.md itself teaches
git -C .claude/worktrees/<name>", which stops being true once the text is the teacher. Now "this document itself". That is the only altered word; everything else is byte-identical.Test plan
./scripts/quality-check.sh— Errors: 0, Warnings: 0.venv/bin/pytest -m slow— 554 passed, 8 skippedworktree-setup.shnames ("Why each non-default knob is there") exists in the new docworktree-setup.sh's blocked-cache message and confirmed it now names the right filebash -non both edited scriptsStep 8's mock-HA E2E has no surface here — this change has no runtime behaviour. What was observed instead is the gate's RED→GREEN transition and the rendered script guidance.
Evidence the test discriminates
The gate was written before the move and watched fail:
CLAUDE_MD_MAX_BYTES=16000toquality-check.shwhileCLAUDE.mdwas still 45,488 B✅ CLAUDE.md within context budget (11926 B / 16000 B)Its failure message points at the relocate-and-link mechanism rather than at raising the cap — raising the cap is how this grew in the first place.
Outcome-level coverage
quality-check.sh's context-budget gate pins the byte size, which is the outcome this issue is about. No optimizer fixture or golden is involved — the diff touches no runtime code./code-reviewindependently extracted the 574 removed lines and diffed them against the new doc: identical except the header and the one deliberate rewrite. It also confirmed the load-bearing prohibitions (nevergit stash, worktree-before-edit, the cross-checkout patch recipe) are independently stated indocs/agents/rules.md, the always-read file — so no safety content moved further from an agent that needs it.Review findings fixed
/code-reviewfound four dangling pointers, all fixed in this branch. Two only surface on a failure path, which is the worst place to send someone to a file that no longer has the answer:worktree-setup.sh:261exit 1when a blocked cache stops setupverify-sandbox.sh:111,:139,:141sweep-prs/SKILL.md×2,skill-architecture.mdgit add -ADocumentation check
Neither
docs/agents/bess-knowledge.mdnordocs/SOFTWARE_DESIGN.mdmentions anything this diff touches — no mechanism, formula, threshold or code path changed.No CHANGELOG entry
Deliberate: zero user-visible effect, agent-facing documentation only. #649 changed the same pipeline and added none.
Scope assessment
Adds no parameter, flag, default-fallback, second construction site or extra trigger. Scope is local — the destination is the doc structure
CLAUDE.mdalready establishes. Explicitly out of scope: deleting or condensing any relocated content, and droppingprojectfrom--setting-sources(it would cut more, but.claude/agents/bess-analyst.mdis discovered through project settings, so it would break Stage 2's delegation).Closes #650