Skip to content

Don't fold it in: when an agent notices a second problem, file a ticket

You ask a coding agent to fix one thing. While it is in there, it notices a second thing -- a function next door that is clearly wrong, a test that was already failing before you showed up, an import that should be reorganized. And it helpfully fixes that too, because it is right there and the agent is already loaded with the context to do it. That feels like initiative. A good engineer fixes what they trip over.

For autonomous work, it is exactly backwards, and this project encodes the opposite as hard rules. When an agent notices a second problem mid-task, the right move is not to fold it into the current run. It is to write it down as durable deferred work -- a ticket -- and leave the current change as small as it was scoped to be. "Don't fix it, file it" sounds like bureaucracy until you understand the one constraint that makes it the correct call: the agent is working inside a context window, and that window is the most expensive thing in the room.

The instinct is borrowed from a world the agent does not live in

The "fix what you noticed while you were in there" instinct is a good one for a human who carries the whole codebase in their head, will remember the detour tomorrow, and pays almost nothing to glance two files over. None of those things are true for an agent.

An agent starts every task with an empty mental index. It does not carry yesterday's detour into today's task, and it cannot cheaply hold "the bug I came to fix" and "the unrelated thing I noticed" in view at the same time without each one crowding the other. The companion mindset post, Read before you write, names the underlying limit in a section heading: the blind spot is the context window, not the model. The agent does not fail because it is unintelligent; it fails because the relevant fact was not in front of it. Folding in a second fix makes the problem worse from both ends -- it spends scarce context on a problem the current run was never scoped to solve, and it blurs the blast radius of the change you actually asked for. A one-line fix and an opportunistic refactor in the same diff are no longer a one-line fix. They are a thing you cannot bisect, cannot review cleanly, and cannot revert without losing the part that was correct.

So the bet this project makes is simple: the second problem is real, and it deserves to be fixed -- later, in its own run, in a fresh context that is loaded for exactly that problem and nothing else. The way you make "later" trustworthy is that you write the problem down somewhere the next run will actually find it.

The rules that make "file it" the default

Two hard rules in this repo's CLAUDE.md turn that habit from good advice into something the agent is not allowed to skip.

The first is minimum-diff UI bug fixes. When fixing a bug that shows up in the browser, the rule says to change only the lines required to fix the reported symptom -- no refactoring surrounding code "while you're in there," no renaming variables, no fixing related issues that were not part of the report. And it names the escape hatch explicitly: "If you notice a separate problem while fixing the reported bug: stop, note it in ## Surprises / judgment calls in the run record, and file a follow-up ticket. Do not fix it inline." The newer companion rule closes the loophole in that sentence: "file a follow-up ticket" means author the ticket file in the same turn, not merely mention that one would be useful. The noticing is welcome. The inline fix is not.

The second is the protocol for pre-existing test failures during implementation -- the case where the agent runs the suite and finds something already red on the branch it cloned from, through no fault of its own. The rule gives exactly two acceptable responses: fix it in your current branch only when the fix is small and clearly in scope, or "Open a P0 backlog ticket for it... Write a minimal confirmed ticket in the backlog with state: confirmed and priority: P0." Then it names the thing you must not do, and the reason is the whole argument of this post in one line: do not "Note the failure in ## Dead ends and move on without fixing it or filing a ticket. That exports the problem to every subsequent ticket that touches the same test file."

That phrase -- exports the problem -- is the point. A second problem you neither fix nor record does not disappear. It becomes a tax on every future run that wanders into the same code, each one rediscovering it, each one deciding from scratch whether to fold it in or look away. Filing it once converts that recurring tax into a single line item the system can schedule and a human can prioritize. The rules are not there to slow the agent down. They are there to stop one run from quietly making every later run worse.

The backlog is the working memory the context window is not

A habit of deferral only works if "deferred" means something concrete. In this project it does: a problem you choose not to fold in becomes a markdown ticket under the backlog, and that ticket is a first-class, durable object the rest of the machine knows how to handle. The orchestrator under the orchestration control plane schedules from the backlog; the ## Depends on graph in each ticket says what has to land first; verbs like /dev-backlog-list and the /dev-status family let a human see what is queued. The deferred problem is not lost in a chat transcript or a ## Dead ends note nobody reads. It is in the tree, in git diff, queryable.

That last word matters more than it looks. Every run in this project leaves a sibling run record next to its ticket -- a *.run.md file that captures what the code cannot: the surprises, the judgment calls, the dead ends, and exactly the kind of "I noticed X but it was out of scope" observation this post is about. And because tickets and run records are plain files committed with the code, the whole trail is searchable. the orchestrator dispatcher runs SQL over an index built from those tickets, run records, and git history, so the next agent wondering "have we seen this before?" runs a query instead of guessing. The companion post The project that remembers itself is the full field report on that index; the short version is that the backlog plus the run records plus the history index are the orchestrator's working memory across time. They are the durable substrate the per-run context window is not.

Once you see it that way, the reason deferral compounds instead of just delaying becomes obvious. The flywheel post, The cross-game compounding flywheel, argues that quality in this catalog accrues because lessons learned in one place get folded back into everything else through a governed loop -- not because anything gets crammed into an already-loaded window. Deferred work is the same shape. The second problem gets fixed later, in a run that opens with a fresh context loaded for that problem and a run record that already explains what was seen and why it was left alone. That is strictly more information than the original run had while it was busy doing something else. Folding the fix in would have spent context to do the work worse, right now; filing it spends almost no context to do the work better, soon.

The honest edge: deferral is governance, not a magic inbox

I would be selling you something if I stopped at "just file everything and the system takes care of it." It does not, and the costs are real enough to name.

Deferral buys latency. The second problem is not fixed when it is noticed; it is fixed whenever its ticket is scheduled, which is a later run at the earliest. A P0 ticket filed mid-batch does not even join the batch that is already running -- by this project's own rules it sorts to the front of the next backlog-batch invocation, not the current one. For a genuinely urgent, genuinely small fix, that delay can be worse than the blast-radius cost of just doing it inline, which is exactly why the minimum-diff rule keeps a narrow "fix it now if it is small and in scope" door open. Deferral is the default, not a law of physics.

Deferral also grows the backlog, and a backlog is only working memory if someone tends it. Every "don't fold it in" decision adds a row. Tickets land as state: draft or state: confirmed, and a human still has to read them, decide which ones are worth a run, and let the rest age out -- the backlog selection rules in the workflow docs and the authoring contract in the ticket-authoring contract exist precisely so that filing is cheap and triage is deliberate. The flywheel post is blunt about the failure mode this shares: the loop "stalls the instant the retro discipline lapses." An untended backlog is not a memory; it is a landfill that hides the three tickets that mattered under three hundred that did not. The discipline is not "file it and forget it." It is "file it so a human can decide, on purpose, and on their own schedule."

That is the honest shape of "don't fold it in." It is a strong default for autonomous work, because it protects the one resource an agent cannot buy more of -- the context window of the run it is in -- and because it turns a problem one agent happened to notice into a durable artifact the whole system can reason about. It is not free, because latency is real and a backlog needs a gardener. The habit keeps each run small, honest, and reviewable. Keeping the backlog worth reading is still a person's job.

So when the agent says "while I was in there, I also noticed..." -- the right ending to that sentence is not "...so I fixed it." It is "...so I wrote it down where the next run can find it."


Or: subscribe to the newsletter for more posts on building this stuff.