Continuous Dissociation: Ralph Wiggum, Generative UI, and A Scanner Darkly
Coding agents can run all night with a pattern called the Ralph Wiggum loop, named for the Simpsons kid who announces “I’m helping!” while making things worse. In its barest form it’s one line of Bash:
while :; do cat PROMPT.md | claude-code; doneThe agent gets the same prompt, works until it exits, and starts again, forever. It’s crude and works better than it should. It also resembles Philip K. Dick’s A Scanner Darkly closely enough to be unsettling. In the novel, an undercover narc named Fred is assigned to surveil a dealer named Bob Arctor, who is Fred himself. The drug he takes on the job splits his brain until neither half knows what the other is doing.
Generative interfaces, screens an LLM assembles on the fly for each user and task, borrow the novel’s other great invention, the scramble suit. Both show what happens when a system loses a stable identity, and both point toward what we need to build to keep shared understanding intact.
Forgetting on a schedule
Every agent has a context window, a hard limit on how much it can hold in mind. Push past it and you get context rot: drift, hallucination, a model that has lost track of its own session.
Ralph handles this with deliberate amnesia. When an iteration ends, its context is discarded and a fresh instance starts with nothing. The context limit works like a dose of Substance D. Past it, memory stops and the split begins. Iteration N+1 can’t recall iteration N, the way Arctor’s left hemisphere loses track of what his right one just did.
(Some packaged versions, like Claude Code’s plugin, re-feed the prompt within a single session instead of spawning a new process. The clean amnesia belongs to the original Bash loop.)
The amnesia is cleaner in theory than on disk. Each iteration
forgets, and the environment remembers everything: half-finished diffs,
stray scratch files, a package cache from three runs ago, a
progress.txt that gets less accurate as it gets longer.
Every fresh mind wakes up in a house its earlier selves have been slowly
wrecking. Arctor lives the same way in the novel, in a run-down house
wired with scanners and full of burnt-out roommates, which ends up as
the main record of who he has been.
Reviewing the tapes
An agent with no memory learns about the world only from what earlier
runs left behind: git history, uncommitted changes, a
progress.txt file. Fred reviews his holo-scanner footage
the same way.
A new Ralph opens the log and reads it like a detective at a crime scene. Someone left an exception unhandled. Someone wrote this tangled function. The agent sets out to clean up after a stranger, and the stranger is itself from twenty minutes earlier.
The suit
Narcs in the novel wear scramble suits, membranes that cycle through
fragments of about a million and a half people so nobody can identify
the wearer. The while loop gives the agent the same
disguise. Every pass is a new probabilistic variation on the same
intent, and no single pass counts as the real agent.
You might expect the prompt to be what’s hidden underneath, but
PROMPT.md is the most visible thing in the setup. The
person who stays hidden is the operator, asleep at 3 AM, who handed out
the assignment and never appears.
Faces that won’t hold still
Generative UI puts the suit on software. A conventional application has a canonical face. Photoshop’s layers panel sits where it sat yesterday, and the export button does what it did last week. A generated interface reassembles itself around each request. The same data might appear to one user as an interactive chart, to another as a table or a conversational summary, and to the first user differently on Tuesday.
That flexibility has real benefits, since the interface fits the task in front of you. The cost shows up in a scene from the novel. Fred meets with his boss, Hank, and both wear scramble suits. Neither can see the other’s face, and Fred has no idea how much Hank knows, including that the man Fred is watching is Fred. One side of the conversation sees everything and the other sees blur.
Every user of a generative interface sits in that meeting. The system has a detailed model of you, and you have a shimmering surface that won’t stay the same long enough to learn.
A scramble suit at least has a body inside it. Generated interfaces sometimes skip that part. A model can render a button labeled “Merge duplicates” or a filter for a field the schema never had, because those controls look plausible for the task. Click one and nothing happens, or something unexpected does. The interface has grown a phantom limb, a lever the user can see and reach for that connects to nothing underneath.
Grammar and common ground
Language works because its grammar holds still while sentences vary. The psycholinguist Herbert Clark calls the process of building mutual understanding “grounding.” People in conversation accumulate a store of shared reference, their common ground, and lean on it to say more with less. “Click the blue button in the top right” depends entirely on common ground. It assumes both people see the same button in the same place.
Linguists call words like “this,” “here,” and “the third column” deictic, meaning they only work inside a shared scene. Pull the scene apart and the pointing stops landing. Clark and Deanna Wilkes-Gibbs also found that partners in conversation try to minimize the effort they spend together, instead of each minimizing their own share. A stable interface charges a large grounding cost once, while you learn it, and every later session rides on that investment. A generated interface charges a smaller fee every time. The machine does the layout work, and the person re-reads, re-orients, and double-checks before each click. For a one-off task, a perfectly fitted screen may be worth the fee. For a tool someone opens every day, the fees add up to far more than the original lesson would have cost.
Software interfaces have long served as a large body of shared reference. Documentation, tutorials, screenshots in bug reports, and a coworker leaning over to point at your screen all assume your screen and theirs show the same thing. Once each person’s interface is generated, that assumption fails. Support staff can’t reproduce what a customer saw. Docs describe a layout nobody has. Two collaborators discussing “the chart” may be looking at different charts built from different readings of their intent, and neither knows it. Muscle memory and spatial memory fade too, because there is nothing stable to remember.
Ralph has the same problem across time instead of across people. Each iteration forms its own reading of the codebase, and the only common ground it shares with its predecessors is whatever got written down.
Witnesses outside the loop
For Ralph, the standard defense is backpressure: tests, type checkers, and builds, verdicts no iteration can talk its way around. Fred never had anything like that. He had only the tapes, and he misread them because he was watching himself.
When the map is wrong
Tests help only if they come from somewhere other than the agent’s
own assumptions. Usually they don’t. They were written from the same
understanding as the spec, often by the same author and sometimes inside
the same loop. If PROMPT.md misunderstands what the
software should do, the tests misunderstand it identically.
Then the loop converges. Each amnesiac iteration enforces a map that never matched the ground, and the suite turns green. A formalism can confirm that code agrees with the formalism, and it has no way to report that the formalism was a mistake.
Dick saw this coming. The holo-scanners in the novel record flawlessly. The errors come earlier, from whoever chose where to point them and what they were supposed to find.
Generative UI inherits the same weakness. The model renders whatever it inferred you meant. If the inference was off, you get a polished, coherent interface for the wrong task, and nothing on screen tells you so.
New-Path
At the end of the novel we learn Arctor’s collapse was planned. The agency burned him down deliberately, because only a genuine husk could get inside New-Path, the rehab network, and find where the drug is grown. The institution built to cure addiction turns out to be cultivating the flowers.
Ralph runs on a similar bet. An agent with no memory of its own assumptions sometimes notices a bug that a coherent one kept explaining away. The ending carries a warning too. The structures meant to keep the agent honest (the spec, the tests, the loop) can also steer it wrong, and the operator wrote all of them.
A song for the mayflies
Some agent harnesses now treat these failures as design problems. dirge, an open-source coding agent written in Rust, makes a useful case study. Its README names it after a funeral song, “a song to keep the dead from losing their way,” and compares agents to mayflies that wake briefly to work and then forget, each new session erasing the last. The project carries memory and past mistakes across that gap, so that “no grave need be dug twice.”
Memory outside the window. dirge accepts that older history will fold and works to keep what mattered. It caps the live context at 250k tokens by default. When history folds, it writes a resumable checkpoint and stores facts and pitfalls in a session database instead of the transcript. Less salient entries shrink to a one-line index the agent can search on demand, and a post-session process extracts learnings into memory and skills. Each new Fred gets a case file kept by someone who was paying attention, in place of raw tapes.
The operator’s words, verbatim. Its sharpest design choice targets the drift this essay worries about. The docs point out that summarizers paraphrase, and that paraphrase is where stated constraints go soft. Their example is “use ESM not CJS” decaying into a note that module format was discussed. So the user’s own messages ride along with every summary unedited, carried across successive folds. dirge also keeps exactly one compaction block, so the model never accumulates competing summaries that each claim a different active task, and a summary that fails validation is thrown out instead of silently replacing real history. In Scanner Darkly terms, Fred always has one set of orders, in Hank’s own words.
Witnesses from other minds. Roles can run on
different models, so the main loop, the reviewer, the escalation path,
and the summarizer can each use a separate provider. In its phased
/plan workflow, a reviewer with no ability to write files
runs the code and returns a verdict, and anything other than a clean
“done” counts as not done, on the reasoning that a false pass ships
broken work while a false fail costs only a retry. An optional approval
gate shows the plan to a human before any code is touched. That puts a
person at the exact spot where the map gets drawn.
Breaking the hall of mirrors. A repeat-loop guard
catches an agent issuing the same call over and over. Instead of a bare
“try again,” which tends to reinforce the failing line of reasoning, it
makes the agent state what it was attempting, name the assumption that
might be wrong, and propose two or three fundamentally different
approaches. That middle step asks the agent to doubt its own map. One
documented failure belongs in this essay. An agent had decided it needed
a particular tool, couldn’t bring itself to call it, and instead ran a
string of harmless echo and true commands
while narrating its intent between each one. dirge now treats all such
no-op commands as one repeated behavior and trips the guard on the
third. Ralph announcing “I’m helping!” to an empty terminal now sets off
an alarm.
Protecting the house. dirge validates every write
through tree-sitter before it touches disk, supports git worktrees, and
offers an optional sandbox that runs each shell command in isolation,
which limits how much each pass can wreck for the next one. Malformed
tool calls are checked against their schemas and repaired before
dispatch, so the agent pulls levers that exist. All authorization flows
through a single policy engine, and a /why command traces
which policy made a decision and why, which drags part of the operator
layer into view.
What it can’t fix. Every one of these witnesses still reads the same map. A critic on a different model brings different priors to the same spec, which helps, but nothing in a harness can tell you the spec described the wrong territory. dirge’s gates also fail open, so an errored judge never blocks a run, and its code review runs in advisory mode by default. Those are reasonable engineering tradeoffs, and they leave the last check where this essay keeps putting it, with a human standing outside the loop. dirge narrows the gap Fred fell into. Someone still has to stand on the other side of it.
Keeping vigil
Ralph never sleeps. while : relaunches the agent the
moment it exits, whether or not anything has changed. Arctor’s trouble
was partly that he was never off duty, and dirge’s vigil mode starts
from the same observation. A vigil wakes the agent only when something
happens: a timer fires (a “toll”), a file changes (a “watcher”), or a
message arrives on a socket (a “harbinger”). The agent runs one turn and
goes back to sleep.
Before the agent runs, an optional check called a rite, either a shell command or a git dirty check, decides whether this wake-up deserves a turn, and its output goes into the prompt along with the list of changed files. The agent stops rereading the same instructions for the hundredth time and starts from evidence: a failing test, a set of edits, a broken build reported by CI. The territory gets to write part of the prompt.
Events that arrive close together are merged into one batch, so fifteen file saves become a single turn with the full set of changes. The agent reasons over one account of what happened, which is grounding at the scale of a single mind. When a vigil’s queue fills up, the oldest events are dropped with a logged warning. Vigil still forgets, but it says so.
One mode skips the model entirely. A socket caller in commands mode sends a command name and a few arguments, chosen from a menu the project owner declared in advance. The caller never names a tool or writes raw arguments, the socket only listens on the local machine, nothing that needs elevated permission is auto-confirmed, and every dispatch is logged. The design proposal also admits that templated argument values can still inject into a shell command, and recommends fully static commands for untrusted callers. A design doc that names its own holes is doing the grounding work this essay keeps asking for.
When the work is done, the vigil is laid to rest, and the record of when and by which session stays in the database. Chaining stays deliberately flat: one vigil can hand off to at most one next vigil, a “procession.” Arctor ends the novel without a record of who he was.
Vigil doesn’t escape Dick’s point. Its watchers are holo-scanners aimed at directories and ports, and its rites are checks the operator wrote. Point them at the wrong thing and the vigil keeps a faithful watch over the wrong thing. The difference is that the orders sit in config files and a database table anyone on the project can read, with a history of state changes. Hank still writes them, but he has to sign them.
Building shared reality on purpose
Agent harnesses are learning these lessons faster than interfaces are. dirge’s own interface is conservative, a terminal UI with fixed slash commands and panels in set places, and generative UI could borrow the rest of its ideas too. Interfaces could keep vigil instead of looping: hold still until something changes in the world, collect changes into one update on a fixed cadence, gate regeneration on a check, and show the reason next to the change.
Keep the nouns stable. Objects, records, and files should have permanent names and addresses even when the views around them change. A user can lose the layout and still say “open invoice 4471” and mean what everyone else means.
Offer a canonical view. Generated layouts can act as lenses over a default face that always exists, one click away, and that documentation and support can describe. Personal views then work like dialects of a shared language.
Carry the user’s words verbatim. Next to any generated view, keep the literal request that produced it, the same way dirge preserves user turns through compaction. When the interface drifts from what was asked, the original ask is right there to check against.
Bind every control to something real. Let the model compose only from a registry of actions tied to actual endpoints and schema fields, the way vigil’s commands mode offers a fixed menu. It can rearrange the levers as much as it likes, and it can never invent one.
Make views shareable and reproducible. If a generated screen can be captured as a spec, link, or seed, “send me what you’re seeing” works again, and a bug report can include the exact interface that failed.
Show the inferred intent and the reasoning. Before
or alongside rendering, the system can state what it thinks you’re
trying to do, with something like dirge’s /why for layout
decisions. That gives you a chance to correct the map before the
territory gets built.
Lock to a shared view for collaboration. When two people work together, render once for both of them, so joint attention has a real object to land on.
Change the grammar slowly, and say so. Navigation, primary actions, and undo should stay put. When a generated layout does shift, a short note on what changed and why helps people keep their bearings.
Wake on evidence. Run the agent, or regenerate the interface, when something in the world changes, and feed that change into the prompt. A schedule alone just re-reads the map.
Batch before you reason. Collect related changes into one update so the agent, or the person looking at the screen, gets one coherent account instead of a stream of fragments.
Forget out loud. Bounded memory is fine. Log what was dropped.
Close work on the record. When a task ends, record that it ended, when, and who decided.
Get a second map for agent loops. Acceptance criteria written by someone other than the spec’s author, examples from real users, production telemetry, and property-based tests all come from outside the operator’s head. A human reading diffs on a schedule is a witness the loop can’t produce for itself.
Review the spec hardest. In a Ralph loop, the prompt survives every act of forgetting. In a generative interface, the inferred intent shapes every render. In a vigil, the rite decides what counts as worth waking for. Errors live longest in those places, so they deserve the most scrutiny.
Matins
“Dirge” comes from Dirige, “direct my way,” the opening of a chant sung in the hours before sunrise in the old Office for the Dead. The monks who sang it kept that watch on purpose, on a schedule, with every word written down.
Skip the vigil and you’ll come down at dawn to a green test suite, a hundred commits, a dashboard that looks different for every person on your team, and a cheerful voice from the terminal: I’m helping.
Sources on dirge: the project README, the agent loop docs, the vigil proposal, and the vigil docs.