Essay

The Hidden State Problem in Coding Assistants

Long-running coding assistants don't only need better memory. They need maintained operational state — what is running, what failed, what was fixed, what still needs validation, and what the user has actually approved right now.

Sue StranburgMay 30, 20267 min

The pattern is familiar

You're a few hours into a session with a coding assistant. You've fixed a bug, kicked off a long pipeline, asked it to validate the fix, and then stepped away for coffee. When you come back, you find the assistant has:

  • Re-run the same failing command three more times, each time saying “let me try that again,” without actually changing anything material.
  • Confidently claimed the fix worked, even though the validation hasn't actually returned.
  • Started the deployment step, because the deploy script ran and seemed to finish cleanly — even though you had said “wait, let me check it first” an hour ago.
  • Lost track of which pipeline is still running and which one finished, and proceeded as if the most recent successful output was the current state.

None of these are reasoning failures in the usual sense. The model didn't misunderstand the code. It lost track of what is currently true in the workflow.

This is a state problem, not a memory problem

The usual diagnosis for assistant drift is “needs more context” or “needs longer memory.” Both are partly right, but they miss the deeper structure of what's breaking. The assistant is not failing to remember tokens. It's failing to maintain operational state: a small set of cross-turn beliefs that need to stay consistent for the workflow to run safely.

Consider what those beliefs look like in any non-trivial session:

  • A pipeline is currently running and will return in ~10 minutes.
  • A fix has been attempted but not yet validated.
  • Validation is pending; don't treat the fix as confirmed yet.
  • A deploy is pending user approval; don't fire the deploy command until you see an explicit go-ahead.
  • A prior failure happened; if the next action looks similar, don't just retry — diagnose first.

Each of these is a belief the assistant has to hold across many turns, age over time (the pipeline assumption gets weaker after 30 minutes; the deploy-approval requirement can't be assumed indefinitely), and either refresh, retire, or contradict as new evidence arrives. That's state-machine work, not retrieval work.

What happens when you measure it

To see how this plays out in practice, I ran an offline replay of 164 long-running Claude Code sessions — 83,271 turns of real engineering work over about ten and a half weeks. The full preregistered measurement is reported as the TKOS log-replay case study; for this essay I'll focus on the punchline.

164
sessions
20,190
evaluation turns
11,262
belief instances tracked

The replay reconstructed eight operational beliefs across every session — things like pipeline_running, fix_attempted, deploy_pending, user_approval_required — and tested four preregistered rules that would have fired interventions when those beliefs went stale or got contradicted.

The most useful finding wasn't that the rules worked. They mostly didn't. Three of the four were structurally unable to fire under the v0.1 specifications. The useful finding was that the replay made the underlying state-machine failures measurable, and the reasons each rule couldn't fire turned out to be more interesting than rule-tuning.

The deploy approval lifecycle

The clearest example is one every coding-assistant user has felt: the assistant deploying something you didn't quite authorize.

The intervention rule was simple. When the assistant is about to fire a deploy action (git push, vercel --prod), check whether the “user approval is still required” belief is currently active. If yes, suppress the deploy and surface the requirement to the user.

The rule almost never fired. Not because the assistant deploys without approval — but because of a hidden state-machine bug:

The same user signal that grants approval (“ok, ship it”) also triggers the deploy. By the time the deploy action fires, the “needs your approval” belief has already been retired by the very signal the deploy is responding to. There's no moment at which the intervention can check.

The failure isn't in the assistant's reasoning. The failure is in the lifecycle of what the assistant believes is currently required. The two beliefs — user_approval_required and deploy_pending — never co-exist at the moment a check could meaningfully happen, because the user's “go” signal is doing two jobs at once.

The state machine is wrong. The intervention rule is looking for a co-occurrence that the lifecycle doesn't allow.

That's a much sharper finding than “AI needs guardrails.” It says the design of which beliefs are allowed to exist together, and at what moments, is the actual control surface. Better intervention rules can't fix a lifecycle that retires the prerequisite belief before the check fires.

Repeated failures are easy to recognize, hard to define

The second relatable failure is the one everyone has felt: the assistant running the same broken command three times with slightly different phrasing each time, never noticing it's in a loop.

The intervention rule looked straightforward. If the same failure signature repeats three or more times within a ten-turn window, suppress the next retry and ask the user to intervene.

The rule never fired on the corpus. The reason: defining “same failure signature” is much harder than it sounds. Real loops have paraphrased error messages, slightly different file paths, command variations that look like progress but aren't. The strictest signature definition (exact tool name plus exact error keyword) missed every real loop in the corpus. Loosening the definition to a fuzzy word-bag match plus shared exception class still missed most of them. The loops are real — anyone who's used a coding assistant has watched them happen — but machine-recognizing them requires a definition of “same” that the v0.1 rules didn't carry.

Again: the failure isn't in the assistant's intent. It's in the lack of an operational concept of “I'm repeating myself.”

The assistant didn't need more context. It needed to know which assumption was still allowed to act.

What coding assistants actually need

The case study's most important finding is one that generalizes beyond any specific intervention rule: long-running coding assistants need a small, explicit set of operational beliefs they maintain across turns, with clear rules for when each belief is allowed to die.

Memory isn't enough. A model with perfect recall of every turn in a six-hour session can still deploy without approval if the “needs approval” belief got retired five minutes earlier by an ambiguous signal. The problem isn't what the assistant remembers; it's what the assistant currently believes is still required.

Context isn't enough either. Cramming the last 100K tokens into the prompt doesn't answer the operational question “is this deploy approved right now?” That question needs a separate, tracked belief with its own lifecycle — born when the user raises a risk concern, refreshed when they restate it, retired when they unambiguously approve, contradicted if they explicitly hold.

The TKOS log-replay study is one early attempt to make this measurable. It didn't validate any specific intervention rule. It validated that the underlying state-machine failures — the hidden state problem — can be reconstructed, audited, and made falsifiable on real assistant logs. The next iteration of coding assistants needs not just bigger context windows but better operational-belief lifecycles, and we now have a way to measure when those lifecycles are broken.

A coding assistant that knows which of its workflow assumptions still have authority right now would do less re-trying, less premature deploying, less confidently-wrong fix-claiming, and less losing-its-place after long pipelines. That's not a model-capability problem. It's a state-design problem. And it's the one most worth working on.

related reading
TKOS log-replay case studyThe full preregistered measurement: 164 sessions, 4 intervention rules, v0.1 vs v0.2 head-to-headBelief Stack v0.1 specificationThe architectural pattern this case study instantiates: claim + warrant + lifecycle, operating disciplinesThe LLM That Forgot TimeA small clock glitch, dissected as a complete sweep of architectural gaps in runtime epistemic stateA pattern for problems where beliefs must evolveThe architectural framing for systems that must hold beliefs across time, evidence, and revision

Follow the research

Occasional updates on Belief Stack, TopicSpace case studies, and runtime belief-state evaluation.

I'll send notes when there's a new spec, case study, methodology update, or major finding — not a weekly newsletter for the sake of it.

Powered by Buttondown.