Repository navigation
chore(agents): cut token use and gate /implement on an approved plan - #318
Conversation
…ion cap and a flat pipeline Last week 1.8B tokens of context went through gmt sessions. Most of it was long sessions resending 300K+ of history every turn, nine personas inheriting Opus, and nested spawns. - Models: architect, dox-architect, researcher and gmt-reviewer run on Opus at high effort; tdd-dev, tester, finalizer, dox-builder, dox-tester and a project Explore agent run on Sonnet. No persona inherits. kilo.jsonc carries the same models. - Context: project settings auto-compact at 200K, default subagents to Sonnet and cap spawn depth at 1. Every persona lists Agent in disallowedTools. - Pipeline: the master and driver personas become the /pipeline skill, run by the main session. A new /plan-story skill resolves the story from the branch name, has architect write a spec folder, grills the owner with the vendored grilling skill, then has dox-architect shortlist Dox tools for the owner to choose before it writes their spec. - Specs: architect writes an index of 150 lines or fewer plus one slice per function; workers read the index and their slice only. tdd-dev and tester keep test output short. - agent-optimizer: scans all of context/, follows links to find orphans, adds line budgets, audits persona models and the no-spawn rule, checks .claude symlinks and kilo.jsonc, and adds usage.py, a 7-day token tally by agent and model. - skill-optimizer: runs without PyYAML, adds line budgets and the .claude symlink check, resolves file references from the repo root, and reports vendored skills as notes. - Skills: grilling and grill-me vendored from mattpocock/skills; agent-optimizer, skill-optimizer, caveman, astro, pipeline and plan-story linked into .claude/skills.
…he spec - plan_gate.py checks the story's spec index exists, is marked status: approved, stays within 150 lines, links slices that exist and stay within 200 lines, and records the Dox decision (dox: none or an approved Dox spec). The story comes from the branch name or an argument. - /implement is now a repo skill (unpinned from skills-lock.json, so skills update no longer overwrites it). It runs the gate first and stops on FAIL, then builds through /pipeline. - /pipeline runs the gate for stories too, so saying implement in prose cannot skip it. - /plan-story sets status: approved only after grilling ends and the owner approves, then runs the gate. architect and dox-architect write their indexes as status: draft.
- run.py runs agent-optimizer and skill-optimizer and prints at most 30 lines: findings in files the branch changed plus repo-wide symlink, kilo.jsonc and skill-name problems. The rest is counted as backlog; --all lists it, --usage appends the 7-day token report. - /implement ends with /optimize: fix what the story caused, list what was already there. - The CLAUDE.md skills table moves to context/skills.md with the story flow, and the Python setup note moves there from AGENTS.md. CLAUDE.md is back within budget and AGENTS.md is slightly smaller than on main.
baldurpan
left a comment
There was a problem hiding this comment.
Not approving yet. Three small bugs in the new flow each need a one- or two-line fix, and I'll approve once they're in. The direction is right, and the numbers back it up.
What works well
- The cuts come from measured transcripts, not guesses.
usage.pygives a baseline to check them against next week. - There is one orchestrator, and the no-spawn rule is enforced twice:
disallowedTools: Agenton every persona, plusCLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH=1. I checked all three env vars against the Claude Code docs. They exist and do what the PR says. The projectExploreon Sonnet is a real saving too, because the built-in Explore runs on the main session's model, which is Opus here. - Spec folders, workers that get only their own slice, short worker reports and
--reporter=dot | tailall cut context where it starts. That's the right lever. - Capping auto-compact at 200K is most of the win. Bigger isn't always better. (That's what she said.)
Must fix before merge
The inline comments have the detail and a suggested fix for each.
/optimizecrashes on macOS'spython3(3.9.6).skill-optimizer/scripts/optimize.pyusesstr | Nonewithoutfrom __future__ import annotations.run.pyswallows the error, so the owner sees onlyJSONDecodeError: Expecting value./implementends with this step, so every story hits it on a machine like mine.plan_gate.pyrejects the frontmatter template fromplan-story§6. The template has inline# …comments, and the gate reads them as part of the value.plan-storystep 5b can't ask about 5 candidates. It wants oneAskUserQuestionoption per candidate, anddox-architectmay return 5, but the tool takes at most 4.
Should fix
- Every library story will end
/optimizewithFAIL.finalizereditscontext/domination/tracker.md, which is already over both budgets, sorun.pylists it as a finding to fix. A check that fails on every run teaches the agent to skim pastFAIL.
Smaller things
These are inline, and none of them blocks the PR:
- A
kilo.jsoncthat doesn't parse passes silently. - The plan gate contradicts three rules in
pipeline. settings.jsonneeds a Claude Code version note.- The usage window counts whole files, not the last 7 days.
- Two passages are out of date.
One question
The plan gate is a convention, not a lock. Any agent that can edit the index can write status: approved itself. Is that enough, or do you want a hook to make it hard? (That's what she said.) I'd ship it as a convention. A hook would also block the main session's legitimate edit, so it needs more design than it's worth right now.
What I ran
I ran these in a detached worktree at 9a70bd71:
uv run --extra dev pytest -q .agents/skills: 126 passed.uv run python .agents/skills/optimize/scripts/run.py: only the 2 pre-existing findings your description names.python3 .agents/skills/optimize/scripts/run.pyon Python 3.9.6: crash (item 1).agent-optimizer/scripts/optimize.py .: 0 broken links, 0 symlink or Kilo problems, and every persona on its intended model.- I reproduced items 2 and 4 and the
kilo.jsonccomment by running the scripts against edited copies.
Review fixes from baldurpan: - Python 3.9: every skill script runs on macOS's python3 (3.9.6). The suite passes on 3.9 and 3.14. context/skills.md says scripts run with python3 and tests with uv. - run.py stops with the failing script's name, exit code and stderr instead of a JSONDecodeError. - plan_gate.py strips inline comments and quotes from frontmatter values, and prints FAIL for an absolute dox path or one outside the repo instead of raising. - plan-story and dox-architect cap the Dox shortlist at 4, the most AskUserQuestion takes. - /optimize lists a size finding only when the file is new or was within budget at the base; files already over budget, like the tracker finalizer edits, count as backlog. - usage.py filters each transcript line by its timestamp, not just the file's mtime. - pipeline: the plan gate runs for tracker stories only, and every story is planned however small. G is an owner's spec with no story; H is a Dox fix with no story. architect no longer says it can be skipped. - AGENTS.md notes the Claude Code 2.1.251 minimum, and stays smaller than on main. - dox-builder, dox-tester and dox-architect no longer say dox-architect orchestrates. Kilo is removed: kilo.jsonc, the .kilo/ ignore line, the Kilo checks in agent-optimizer and run.py with their tests, and every Kilo mention in docs and comments.
|
@baldurpan Thanks for the thorough review. Everything is in On your question about the gate: we're shipping it as a convention, as you suggested. A hook strong enough to stop an agent from writing Also in this push: Kilo is gone from the project. Neither of us uses it, so Re-checked after the fixes:
|
baldurpan
left a comment
There was a problem hiding this comment.
Approving. All three must-fix items are fixed. I checked each one on bf1c07f6 by rerunning the case that failed before:
- On macOS's Python 3.9.6,
run.pyprintsPASS: 0 finding(s) to fix; 154 backlog. When a child crashes,run.pynow prints the child's real error. plan_gate.pypasses the §6 template exactly as written, comments included.- The Dox shortlist is capped at 4 in both places.
The should-fix is done too: a story that edits the tracker now ends /optimize with PASS. The smaller comments are all addressed, and Kilo is removed cleanly.
Tests: 141 pass on 3.14. On 3.9.6, 138 pass and 3 skip; the skips are the PyYAML tests, because that Python has no PyYAML. All 39 CI checks pass.
There's one optional follow-up in the size-finding thread, about files that are already over budget getting bigger. It doesn't need to be in this PR. Nice work.
Why
Last week our gmt agent sessions sent about 1.8 billion tokens of context and used 92% of the weekly limit in three days. I measured every request in the transcripts. Three things drove it:
model: inherit, so workers such as tdd-dev ran on Opus.Re-pricing last week's requests with this PR's settings gives an estimated 35–50% cut. The 200K compaction cap is most of that.
The flow
What changes
Models and limits
architect,dox-architect,researcher,gmt-reviewer. Sonnet 5.5:tdd-dev,tester,finalizer,dox-builder,dox-tester, plus a projectExploreagent that replaces the built-in one..claude/settings.json: auto-compact at 200K, subagents default to Sonnet, spawn depth 1. Every persona also listsAgentindisallowedTools. Needs Claude Code 2.1.251 or later; older versions run every agent on Sonnet.kilo.jsonc, the.kilo/ignore line, the Kilo checks and every Kilo mention are gone.One way to plan, one way to build
masteranddriverare gone. The main session orchestrates with the new/pipelineskill./plan-story: in a story worktree, say "plan" and it reads the story from the branch name (feature/197-mar-16-…→ MAR-16). It checksBlocked by, hasarchitectwrite a spec folder, then grills the owner on open decisions using the vendoredgrillingskill. Next,dox-architectshortlists Dox tools for the owner to pick before it specs them.index.mdof 150 lines or fewer plus one slice per function, at most 200 lines each. Each worker reads the index plus its own slice.plan-story/scripts/plan_gate.py)./implementand/pipelineboth refuse to build a tracker story until its spec is markedstatus: approvedand every slice exists. Only the owner's approval at the end of/plan-storysets that marker. Every story is planned, however small; bug fixes, Dox fixes and other work with no story id skip the gate./implementis now a repo skill, unpinned fromskills-lock.json, sonpx skills updateno longer overwrites it./optimizeruns both optimizers and prints at most 30 lines. It lists findings only in files the branch changed, plus repo-wide symlink problems. A size finding is listed only when the branch caused it (the file is new, or was within budget at the base); the rest is counted as backlog./implementruns it last: fix what the story caused, and log what was already there.context/skills.md, so CLAUDE.md is now within its budget.AGENTS.mdends up slightly smaller than onmain.Optimizer skills
agent-optimizernow:context/and follows links to find orphans;.claudesymlinks;usage.py, a token report by agent and model that filters each request by its timestamp.skill-optimizernow:.claudesymlinks;Not in this PR
Phase B is a follow-up PR: splitting the 39 existing files over budget (
gmt-reviewer.mdat 398 lines, the 1,000–2,000-line specs,coding-standards.mdand others) and archiving the specs of finished stories. The optimizer reports also flag 81 orphaned context files, mostly specs and research for stories that are already done.How to review
uv run --extra dev pytest -q .agents/skillsruns 141 tests. They also pass on macOS's/usr/bin/python3(3.9.6), which is what the skills call./optimize:python3 .agents/skills/optimize/scripts/run.pyon this branch printsPASS: 0 finding(s) to fix; 154 backlog.python3 .agents/skills/agent-optimizer/scripts/optimize.py .reports 0 broken links, 0 symlink problems, and every persona on its intended model.python3 .agents/skills/agent-optimizer/scripts/usage.py --days 7 --project-glob '*northguild-gmt*'gives the baseline to compare against after a week on this setup./agentsin a new session to confirm the models..agents/,.claude/,AGENTS.md,CLAUDE.md,context/skills.md,skills-lock.json,.gitignore, the deletedkilo.jsonc, and one stale comment inapps/dox/scripts/build-utils/build-utils.ts.packages/is untouched, so there is no changeset.