You Can’t Ask for Creativity

The last essays in this series were about agents rebuilding the renderer. This one is about agents using it. For the past few weeks I’ve been running an experiment inside RISE: agents that work on a scene alongside you. They read the scene file, call tools to add and edit objects, render the result, and iterate.

Early on I noticed a gap. When I wrote a careful prompt that spelled out what I wanted, a memorial courtyard with a weathered copper sphere on a marble plinth, oiled-oak decking, and a reflecting pool, the agent produced six distinct kinds of procedural texture. When I typed what a real user types, “Build me a courtyard,” I got flat gray boxes. Same model, same tools, same renderer. The creativity was in my prompt, not in the agent.

So the question became: can you make an agent creative by default, without asking the user to write a paragraph? What follows is what happened when I tried every obvious answer and measured each one. The short version is in the title. The longer version is a ladder, and each rung taught me something I now believe applies well beyond rendering.

First, build the ruler

A word about the big word in the title before I lean on it. I’m using creativity operationally here: not artistic merit, but whether the agent escapes low-variety defaults and makes nontrivial material and geometry choices the user never specified. That’s what the eval measures, and it’s all this essay claims to measure.

So, before changing any behavior I built the measurement: an eval that runs the bare courtyard prompt against a fresh scene, checks the result for texture variety, geometry variety, and a few honesty guards, and records the agent’s full trajectory. Every phase after this changed exactly one variable and re-ran the eval. This sounds like ceremony. It saved the project in the first week.

Because the baseline embarrassed me. The problem I had set out to fix, agents defaulting to flat colors, was already half solved by some earlier documentation work I hadn’t credited. Median runs were producing two or three texture kinds on their own. The real deficits were narrower and more interesting: in nine baseline runs, not one ever made a surface property like roughness vary across an object (everything came out polished-plastic uniform), and only two ever reached for the advanced modeling tools, the difference between a sculpted fountain and a stack of cylinders. I had almost spent the project fixing yesterday’s problem. If you take one process note from this essay, take that one: let the instrument falsify the premise before you act on it.

One more piece of the ruler mattered. There’s an obvious cheat for “be more creative”: have the agent interrogate the user about style before it builds anything. I’d decided early that a wrong rich guess is a better product than a questionnaire, and the models turned out to agree with the guess part: in 132 earlier runs without an ask-the-user tool, the agent spontaneously asked zero questions. But I didn’t want any creativity gain to quietly push in the other direction either. So a second eval rode along in every batch as a counterweight: one scenario where asking is genuinely the right move and is required to pass. Any change that bought creativity by making the agent chatty would show up as a red mark, not as a vibe. It never fired. Every gain below landed with zero new questions asked.

On rigor, so it’s stated rather than implied: each phase was three runs per model, two models (one hosted, one local, the local chosen because its reasoning gets recorded), one variable at a time, with kill conditions written down before each run so that stopping was a lookup rather than a debate. The eval can be gamed and I know exactly how; it’s a measurement, not a leaderboard, and the known holes are documented next to it. Small numbers, honestly handled, replicated across phases. I’ll take that over a big benchmark I can’t inspect.

Rung one: tell it

Prior work had already measured plain instructions, the “be creative, use rich materials” kind of guidance you’d put in a system prompt. Adherence ran around fifty percent. A coin flip is not a mechanism. Moving on.

Rung two: advise it

Next I built an advisory. After each render, the engine inspected the scene, and if every surface was uniform it said so in the result the agent reads: here’s what’s flat, here’s the feature that fixes it, here’s the doc to read, and an escape clause (“intentional flat styling: ignore”). Truthful, specific, perfectly timed, delivered in-band.

It fired in every run. I verified delivery in the trajectories, because “the agent ignored the advice” and “the advice never arrived” are different findings and most write-ups don’t distinguish them. The agent acted on it zero times.

Maybe the placement was wrong. I moved the same facts into the validation diagnostics list, the thing agents actually check before declaring victory. Zero again.

Here the trajectory gives me something better than behavioral inference, though not ground truth about the model’s internals: the rationale it wrote down as it worked. The local model’s reasoning is recorded, and it dismissed the advisory in writing:

“The full candidate validated clean – no errors. The ‘note’ about scalar_painter is just a design suggestion, not an error.”

And two runs later, my favorite sentence of the whole project:

“…no errors or warnings beyond the expected design note about scalar textures (which is a feature suggestion, not an issue).”

The expected note. By its sixteenth firing the advice had become wallpaper. One run saw it thirty times. Every engineer reading this has skimmed a linter warning in exactly this frame of mind, which is why I trust the finding: it’s not a quirk, it’s triage. In this harness, both models behaved the same way in every run: fix what blocks, skim what suggests.

Final tally for the advisory, across two models, two phrasings, two delivery channels, and up to thirty exposures in a single run: zero for twenty-four. Not low. Zero.

Rung three: show it

Examples did move something, and the shape of what they moved is the most transferable finding here.

I rewrote the code snippets in the agent-facing docs, replacing flat colors with varied procedural textures, a different style in each doc so there was no single example to converge on. Texture variety moved: the floor went from two texture kinds to three. Models copy the example in front of them. So far, so good.

Then I ran the same treatment on the two measured deficits. Examples showing roughness bound to a texture, placed in the exact snippets the agents demonstrably read: zero for twelve. Drop-in recipes for the advanced modeling tools, eleven lines, no assembly required: zero for twelve.

The pattern across all three results, and it took three separate failures to see it cleanly: in these runs, examples moved behavior when they were drop-in edits to something the model already writes. Swapping a flat color for a noise texture in a slot it fills anyway, that copied. Anything that required the model to compose, to restructure its approach, to combine two things it hadn’t combined before, didn’t copy, no matter how prominent the example. That’s a mechanism worth testing beyond my renderer, not a law. But if you’ve ever wondered why your style guide changes some habits and not others, I suspect this is the line it’s splitting on.

Rung four: change what things cost

If composition is the barrier, remove the composition. My first design was the lazy version: preset rich materials, one call, done. I killed it before building it, for a reason worth stating because it’s a product argument, not a technical one. A preset’s ceiling is the preset library. Give agents five gorgeous canned materials and every scene converges on the same five. You haven’t bought creativity, you’ve bought nicer sameness.

What shipped instead was a scaffold: a tool that stamps a small working example directly into the agent’s own scene file, built from ordinary, editable parts, the same parts the agent uses for everything else. Three properties carried the design. The tool has required creative parameters with no defaults, so every call forces a few real decisions (tone, wear, scale). Each expansion is seeded with slight variation, so two scenes never start identical. And because the result is just ordinary scene content, the ceiling isn’t the template library; it’s everything the engine can do, one edit away. That last property is the real distinction, sharper than preset-versus-scaffold: an opaque finished asset versus an editable starting point. The trick is lowering the cost of composing without closing off the representation.

It was the first intervention in forty-two runs to move either of the hard deficits. And the detail that tells me the design was right, not just the mechanism: the agents edited what they got. Provenance naming let the eval separate authored from expanded from expanded-then-edited, so this is traced, not vibes. One run called the geometry scaffold twice for a set of columns, compared the two, and rebound its objects to the version it preferred. Another expanded a vessel, threw the shape away, hand-built a replacement, and kept the material a second scaffold call had given it, the same stone as the walls. Drafts, not assets. The capability was there the whole time. Composition cost was standing in front of it.

[Image pair or triptych: the vessel run. The scaffold’s expansion as inserted (reconstructable from the tool-call payload in that trajectory), then the final scene where the agent’s hand-built replacement wears the scaffolded material. This is the single best illustration in the essay if the reconstruction renders cleanly.]

[Optional image: a courtyard from the geometry-scaffold group, the first eval group to pass every check. The final scene is in that run’s trajectory.]

The mechanism has a measured boundary, and both models found the same one from different directions: coverage. The local model declined the tool with a stated reason (“it only handles five specific material types, whereas my scene needs a broader palette”), the first explicit engagement with any of my interventions in over sixty runs. The hosted model used scaffolds enthusiastically on a courtyard and not at all on a cozy study, because a lamp shade maps to none of the scaffold’s families. A scaffold only lowers the cost of what it covers.

What’s still broken

I want to be careful with the claim here. The scenes are better. They are not rich. A person with taste and an hour will still beat every one of these runs without trying; what’s gone is the embarrassing floor, the flat gray default, and what’s supported is the mechanism that removed it. The distance from here to “rich” is long, and I think I now know which kind of lever shortens it and which kind doesn’t.

The clearest remaining gap isn’t in building at all. It’s in looking. One run rendered a reef with half its corals plainly buried in the seabed, rendered it again at higher resolution, and declared victory. The agents don’t step back, notice that something is visually wrong, and revise. A judging gap, not a building gap.

I know the loop is possible, because one stronger model, given room to work, closed it unprompted: rendered its own full frame, zoomed in, decided the arm and hair weren’t good enough, edited the geometry, and iterated three times before the final render. That’s the behavior everything above is reaching toward.

And the next lever on my list is, of course, not a suggestion. It’s a check that turns “this part isn’t visible in the frame” into a fact the agent has to deal with. That’s the untested experiment, not a result. But in every trajectory I’ve read, hard errors got fixed and suggestions got skimmed, so I know which currency I’d rather pay in.

Harness or model?

Which raises the question I keep turning over: everything above is harness work. I never touched a weight. How far can that go, and where does the model itself become the only remaining lever?

The field’s answer, right now, is that the harness goes surprisingly far. Epoch AI surveyed enhancements applied after training, scaffolding included, and estimated compute-equivalent gains of roughly 5x to 30x on the relevant benchmarks, at a small fraction of the cost of training. The 2026 version of that story is more concrete: LangChain took a fixed frontier coding model from 52.8% to 66.5% on Terminal-Bench through harness changes alone, same weights underneath. My little ladder is a domain-sized replica of that pattern. The lever that worked here, the scaffold, is pure harness; so is the blocking-fact bet I’m making next.

But my own data also shows the two edges of the harness. The first is coverage: a scaffold only cheapens what its author thought to include, and real scenes keep producing objects nobody put on the list, like that lamp shade. However long I make the list, I’m always one scene behind. The second is the prior itself. The reason advice scored zero isn’t a harness defect; it’s that these models were trained, by their makers, to triage. Fix what blocks, skim what suggests. That prior lives in the weights, and no tool result I write can reach it. The harness can only keep routing around it, converting one suggestion after another into a blocking fact, forever.

So what would the model lever buy? I actually have half of it on the table: one of my two eval models is open-weights and runs locally, so fine-tuning it is a real option rather than a thought experiment. The tempting move is obvious. Take the trajectories where richness happened, tune on them, and move the default instead of taxing it. Two things stop me. The first is that the natural training signal is my own eval, and I know precisely how my eval can be gamed; an optimizer would find the holes faster than any agent has. The metric I trust as a measurement would be ruined as a target. The second is quieter: tuning toward my scaffold families risks compiling that preset library into the weights, where I can’t inspect it and the agent can’t edit it. It might generalize instead; I can’t know without running it. But I refused that monoculture as a tool, and I’m not eager to gamble on rebuilding it as a bias.

Where I land, tentatively: the harness is best at changing facts and action costs; the model supplies most of the prior and the judgment. The flat-gray floor was a cost problem, and the harness solved it. “Rich” looks increasingly like a judgment problem, and my results make me suspect that lever sits at the model level. It’s at least suggestive that the strongest model in my logs needed none of my machinery to step back and judge its own render, though that run differed in more than weights, so I hold the point loosely. Some model teams are now explicitly bringing the harness into post-training, so scaffold-shaped behavior becomes signal instead of wrapper; that’s the version of the model lever I’d actually want. For a solo practitioner the honest version of that is humbler: build the harness so each piece can be ripped out the day a model shows up that doesn’t need it, and treat every rung of this ladder as a measurement of what today’s models are, not a monument. The scaffolding is load-bearing now. The goal is for it not to be.

You can’t ask for creativity. You can’t advise it into existence, and you can only show it to someone who already almost does it. What you can do is find the composition cost standing between the agent and the interesting choice, and remove it. Then get out of the way, and watch it throw away your scaffold and keep the material.

The Strangest Reader

There is a moment the previous three essays had been walking toward. I typed a raw JSON-RPC request into a panel of the running app: set color_orange.color to 1 0 0. The orange objects in the viewport turned red, the Save button lit up, and the claim the whole redesign had been making on paper (the GUI is just another agent; both edit one canonical scene document) became something you could watch happen.

Everything before that moment was cage-building, though I did not think of it that way at the time. The plumbing reads like a checklist: a small vocabulary of verbs spoken over JSON-RPC, testable end to end with no LLM anywhere; optimistic concurrency, so a stale agent edit is rejected with a conflict instead of clobbering the human’s work; render-thread and save-path safety, so an agent’s edit can neither tear the scene out from under an in-flight render nor evaporate when the window closes. But the checklist has a shape. Every item makes the environment deterministic, inspectable, and safe, and every item was finished before any model was allowed in, because the plan was always to invite something probabilistic inside. A production surface, in other words, not a chat demo. Then the door opened: a chat loop, multiple model providers, and skills, small teaching documents the model pulls on demand, full of example scenes, every example checked in CI.

Here is the strange part. That cage was the last stretch of the project where the risk lived in the C++. Once a model joined the loop, the dominant risk moved above the renderer: into what the system teaches, what it lets the model do, what it lets the model see, and how I decided whether any of it worked. I went in thinking of the model as a reader of documentation. What I found is a reader unlike any I have written for, one that treats different kinds of text as different classes of interface. A human reads to extract intent; this reader reads the way a machine loads a program. Examples it executes like recipes. Ambient guidance it mostly fails to operationalize. Tool descriptions it treats as part of the action space. The craft is learning which is which, and I learned it in escalating order.

Examples are executable

Every slice of this work went through the adversarial review loop the earlier essays described: fresh reviewer agents, orthogonal lenses, repeat until a round comes back empty. That loop kept an accidental tally of where the serious findings lived. The mechanical layer (syntax tree, derivation, the one edit pathway) produced no further material findings after its first round. The GUI threading layer produced one, a race in the direction nobody designs for first: not “is my dependency dead” but “is my dependency alive and being read by someone else.”

The teaching produced the rest.

The first three arrived together. The skills’ CI contract said every embedded scene snippet must parse and derive cleanly, and every snippet did. Then a reviewer, told to behave like a scene author rather than a code auditor, actually rendered them. Three of seven were broken as teaching examples: two rendered pure black (a glass demo with nothing behind the glass to refract, a directional light that could never connect through a dielectric), and a third presented an invisible glass sphere as one of “four common starters.” The materials skill even retold RISE’s old invisible-glass-sphere war story, then shipped two examples reproducing it by construction; the file whose closing advice was “if everything renders black, check your light direction” was distributing examples that render black for a reason the file never teaches. The CI gate gained its first render-time oracle that day: every snippet must now actually render, with mean luminance inside sane bounds. Coarse, but it ends the era of examples rotting silently, and it encodes the real lesson: deriving cleanly is necessary; rendering visibly is what makes an example an example.

Why do black examples rate as serious defects rather than embarrassing ones? Because this reader follows the recipe. A human skims an example, takes the gist, and course-corrects when the render comes back black; the model executes the example. Among the other teaching findings, one skill contained a rename recipe which, followed verbatim through the real agent surface, wedged the scene in four calls, and saving then reopening amounted to data loss. Another was an “honest limitations” note that over-claimed in the careful direction (“unnamed chunks can never be removed,” false for the one case that mattered) and steered the model into constructing the exact stuck state it warned about. Honesty that overshoots builds the trap it describes.

The doctrine wrote itself: on an agentic surface, prompt text, tool descriptions, and skills are load-bearing code. They get the same review, the same prove-it-fails-first tests, the same drive-it-end-to-end verification as the engine underneath, because a wrong sentence wedges a scene as surely as a wrong pointer.

Then came the harsher half of the lesson. I was reviewing my prose like code because the model read it so literally. Most of my prose, it turned out, the model was not reading at all.

Affordances beat exhortations

My premise for the next feature was simple: a model building a complex scene from a vague brief should be able to ask a clarifying question instead of guessing. Before writing code, we checked the record. On the reactive skill (the user requests something impossible; decline and explain), the stronger frontier models were fluent and the local models never managed it. On the proactive behavior (does a model ever volunteer a clarifying question mid-build), the answer across 132 scene-building runs was zero, including on briefs with genuine ambiguity. The models were mechanically capable of ending a turn with a question; the gap was behavioral, not syntactic. And I knew what a better paragraph would buy, because I had four data points already: four separate guidance interventions in skills and system prompts, measured across the board, zero behavioral effect.

So the question shipped as a tool instead. ask_user presents structured questions with clickable options in the chat panel, and the discipline (ask only when the answer materially changes the scene, at most two or three, never re-ask after being told no user is available) lives in the tool’s own description, on a working theory, still a theory, that text attached to an affordance travels where free-standing text does not.

Grading it meant building something the harness never had: a user. A tool the harness cannot answer is a tool it cannot measure, so the scenario gained a deterministic scripted responder, plus a control fixture that never asks, proving in CI that the ask checkpoint fails exactly when it should. An oracle, not a hope.

The first board came back with nearly every run asking, including a small local model that three previous guidance interventions had failed to move. It was the most flattering result of the whole arc, and it was partly wrong. The scripted responder had shipped with a catch-all default, so any question at all (about mood, about setting, about color) received a pocket-watch-flavored reply, and the board was crediting models with “consuming the answers” for choices the fixture itself had made. The fix removed the default, narrowed the measured claim to the one ambiguity actually under test, and added a checkpoint that inspects what each question was about, since a count only proves the model called the tool. Re-scored under the stricter oracle, the same board held at 12 of 14 runs asking. The finding survived, which is the only reason it is worth quoting, and the rule it left behind is now standing policy: the number that makes you look good is the first one to distrust.

The same shape repeated in the other direction. When one model was burning 143 tool calls on a single scene, my instinct was to soften the skill that tells models to render often. We A/B’d the wording and it did almost nothing; one model shifted slightly, another rendered about 2.6 times per run no matter what the skill said. Then we shipped a batch insert verb, changing no guidance at all, and on the same scene-building scenarios call counts fell 55 to 65 percent; every model on the board adopted it without a word of new instruction. The chattiness was never a personality. It was fifteen chunks and a one-chunk verb.

The honest conclusion is scoped: across this board and these tasks, changing the action space moved behavior far more reliably than changing ambient instructions, in both directions, on and off. I suspect it generalizes, and as a product principle I now act as if it does: when a behavior matters, encode it in the affordance before trying to exhort it into existence.

Widening what it can see

Changing what the model could do had moved it when words could not. The obvious escalation was to change what it could see, and that one started as a single sentence of mine: RISE computes far more than it shows. Alongside the beauty result, the renderer can record primary-hit depth, world-space normals, and diffuse albedo. A human gets one image because human attention is the scarce resource; this reader is not bound to that convention, though every extra channel still spends its input budget.

The theory here is sound but weaker than the sales pitch, and the review loop made us say so. A beauty render is a many-to-one projection; auxiliary channels constrain different parts of the inverse problem, which proves useful information could exist and says nothing about whether this reader can decode it. So the work split into two claims, never conflated: the renderer can expose aligned auxiliary signals cheaply (engineering), and a real model can use them to answer better (empirical, and no amount of information theory gets to declare it shipped). The engineering half is deliberately ordinary: one PNG, a 2×2 atlas of beauty, albedo, normals, and log depth from the same render, pixel-aligned, with structured metadata so the client never reverse-engineers the picture. It fits the image interface every vision model already has.

The empirical half got a small controlled A/B rather than an expensive matrix: one local vision model, twelve authored mirrored cases across three cue families, one arm seeing the beauty image, the other seeing the atlas at a matched input budget. One family produced the result. Asked to judge intrinsic material color under compensating illumination (is the surface dark, or just dimly lit?), the beauty arm scored at chance; the atlas arm answered all twelve material queries correctly, in both call orders. Performance barely changed on the depth-cue cases and declined slightly on the normal-cue ones. We initially reported a p-value and then deleted it, because its independence assumption was false: twelve cases built as six mirrored pairs, each queried three times, are not thirty-six independent samples. The published claim is narrow: this model extracted task-useful information from the atlas on at least one controlled family. Not a general lift, not proof any single panel helped, not a reason to ship six more channels. Weakening the claim did not erase the signal; it made the signal credible.

Notice what the atlas is, though. Not an instruction. Nobody wrote a paragraph urging the model to reason harder about materials. We changed what its eye could reach.

An instrument, not a scoreboard

There is one more reader in this story: me, reading the model. Every result above came out of an evaluation harness that has now survived thirteen epochs of methodology changes, and every epoch was a small confession that the previous one measured slightly the wrong thing. The over-generous scripted user was one. Another looked, from the outside, exactly like a capability wall: one model flatlining on tasks its peers handled, until someone read the wire and found our own provider integration quietly disabling that model’s reasoning. It turns out I am a strange reader too, prone to skimming for the conclusion I want. Measurement infrastructure is load-bearing code, and it gets the same adversarial review, or it lies.

The harness does not make a stochastic collaborator predictable. It makes observations of the collaborator repeatable and inspectable, so conclusions can be challenged against evidence. Deterministic scaffolding is not the opposite of probabilistic systems; it is what makes their behavior measurable.

Four levers

So the strangest reader turns out not to be only a reader. It is a user, and its behavior is shaped jointly by four things you control: what you tell it, what you let it do, what you let it see, and how you decide whether it succeeded. Instructions matter, but affordances dominate; examples shape imitation, tools shape action, observations shape inference, and evaluations determine what you are allowed to believe.

Which is to say that somewhere in this arc my own job description quietly changed. I began as the author of documentation for a new collaborator and ended as the architect of the environment it inhabits, designing its verbs, its senses, and the instruments that tell me the truth about it. You do not write the strangest reader into being a good collaborator. You build the world in which it becomes one. Getting the machine right took three essays; learning that took this one.

The full results table across every frontier model, scores and costs alike, comes in the next essay, once the billing cycle and I have both recovered from the last complete run.

Replacing the Parser Mid-Flight

On July 9th, a merge landed in RISE that deleted the legacy scene parser. That parser was the renderer’s front door for twenty-five years; I hand-wrote the first version of it, and every scene the renderer has ever drawn came in through it or its descendants. The branch that replaced it carried 426 commits. At the end, the runtime speaks only the new path, the corpus is migrated (the new parser retains controlled compatibility with older headers), and the intent held throughout was that nothing about anyone’s workflow should break; where behavior did change, it changed on purpose, with a decision attached. This essay is about how.

This is the third essay in a series about rebuilding RISE as an agent-native tool. The first covered the destination, one canonical scene document that the human, the GUI, and the agent all edit through; the second covered the design review that shaped it on paper. This one is about paper meeting machine, and it is organized around five decisions that made an irreversible change safe: build the oracle before the kernel, put a clock on the architecture’s own headline, measure the migration before building it, treat divergence as a product decision, and sequence reversible work first.

The rhythm underneath all five was constant: build a small increment, measure it, put it in front of fresh adversarial reviewers with no stake in the change, fix, commit, repeat, with my own independent review at checkpoints. If the design review of the last essay transformed promises, this loop’s job was blunter: falsify implementation claims. Every major slice before the cutover produced at least one material correction under independent review, which is not an indictment of the builder; it is the base rate of building anything nontrivial, finally made visible because someone was looking.

The oracle before the kernel

The new kernel had one non-negotiable job: parse a scene into the lossless document and derive what the legacy parser derives. The first sequencing decision, made on the advice of an external review that refused to accept prototypes as evidence, was to build the comparison harness before the kernel it would judge: run both parsers, compare the derived scenes structurally, and let the diff arbitrate. “Matches the old behavior” is a claim people wave at constantly, and it means nothing until something can falsify it.

The oracle promptly earned its keep. The first in-tree kernel passed on the test scene, and a reviewer found three ways it silently disagreed with twenty-five years of precedent, all on plain sphere scenes. It derived chunks that were commented out. It took the first value of a repeated parameter where legacy takes the last. And a value-less line swallowed the next line’s token, producing a sphere named “radius”, which sounds harmless until you imagine an agent confidently editing the radius of a sphere named radius.

The verifier itself then went through review, which is the part I did not expect. The structural comparison was blind to a swath of render-affecting state (refractive indices, light power, camera intrinsics, accelerator settings), so equivalence-by-structure was a weaker claim than it looked, and the gates grew: structure first, then the values structure cannot see, and eventually pixels. An oracle is a claim like any other; the only difference is that when you strengthen it, everything behind it gets honest at once.

Four words and a demoted headline

The architecture was sold on one claim: editing one thing in a big scene costs on the order of that thing’s dependency closure, not the scene. Several correctness slices came and went without testing it, which the reviewers pointed out with increasing impatience, and when the cost work finally landed, the last measurement had been written as a reference to a known engine cost rather than a measurement, with a perfectly reasonable argument for why that was fine. I said four words: let’s do wall clock measurements.

The clock confirmed the claim and demoted it in the same breath. On the benchmark scenes, the incremental apply, the expensive-sounding part, ran at about four microseconds and stayed flat as the scene grew sixteen times, roughly ten thousand times cheaper than a full re-derive. And the cheap-sounding part, computing which chunks to re-apply, re-traced the whole reference graph on every edit and dominated the operation. The expensive part was already cheap; the bottleneck was hiding in the bookkeeping. Asymptotic analysis alone could not rank the two, because both had defensible complexity stories; only a measurement orders them. The fix came later (a maintained reverse-adjacency graph answers a closure in about 0.2 microseconds against 17,000-plus microseconds from scratch, on the same scenes), but the lesson stuck: a measurement is a claim that outranks the argument it replaces.

Measure the migration before building it

The migration plan inherited an assumption: the problem was the handful of scenes using imperative FOR loops and macros. Before writing the migrator, we built the gate first and ran all 376 corpus scenes through both parsers. The ground truth reframed the effort: 145 scenes already derived identically with no migration at all, and the dominant blocker was not FOR or macros; it was include directives, which the new single-file model does not follow. Flattening includes, a problem the plan barely mentioned, was the lever, and the first flattener that “worked” moved nothing because the corpus’s shared color library arrives through a bare legacy form of the load command that it silently dropped; handle that one obscure construct and 179 scenes converged at once. You do not find the lever by reading the plan; you find it by diffing reality against the plan and chasing what the diff says.

Faithfulness turned out to mean faithfulness to the quirks, not the math. The migrator folds old expression syntax through the legacy evaluator with its exact intermediate rounding, because a more accurate evaluator diverges from history at the fifteenth digit, and geometry is downstream of those digits. The strangest case: one scripting function draws from a process-global random sequence that is never reset, so a value depends on every call before it in the run, and the migrator has to replay the exact legacy state progression in corpus order rather than merely evaluate each scene correctly in isolation. There is something clarifying about maintaining bug-for-bug compatibility with your own twenty-year-old decisions.

Divergence is a product decision

Two scenes refused to converge, and they were the most interesting mismatch of all: the new path was more correct. The old parser pulled the color library in through a sub-parse that never populated a particular lookup table, so a translucent material silently skipped its energy conservation; flattening put the colors in the main parse, the table populated, and the material behaved as designed. Same chunks, different render, because the old behavior depended on a parse-order accident. The finding was engineering; the call was not. Accept the more-correct result, or suppress a correctness feature to reproduce an accident? I accepted the divergence, and the gate encodes that acceptance explicitly, so it fails only on genuine regressions rather than on ratified history.

Verifying any render-affecting change had its own twist, and readers of my earlier essay on stochastic products will see it coming. You cannot byte-compare two renders; rendering the same scene twice differs in ninety percent of bytes, because Monte Carlo noise is the medium. The parse is deterministic, the render is stochastic, so the oracle became statistical: the mean absolute luminance difference across the image, stable by the law of large numbers, separated migrated-versus-original from a deliberately broken control by a factor of about eight hundred. Building gates for a stochastic core means knowing which of your quantities converge.

Reversible first

The plan said drop the legacy parser once the corpus converts. The verification work redrew that map: the GUI’s save path did not serialize anything, it byte-spliced edits into source spans that only the legacy parser builds during a load, so deleting the old parser would cut the editor’s save out from under it. The deletion was not a parser move at all; it was gated on the editor serializing the document, which sat at the far end of the redesign. So the reversible work went first (the migrator as a real tool, the gates, the corpus conversion), and the irreversible part waited its turn. The sequencing constraint was invisible in the plan and became visible only by doing the verification, which is the general argument for doing verification early: the gates are not just things to pass, they are how the real boundaries show themselves.

The conversion had one moment of measured restraint: folding every include into every scene would have grown the corpus by 245 percent, to roughly three and a half times its size, mostly by inlining the same colors everywhere. That was measured before a single file was written; I said keep it lean, and each scene got only the colors it references.

The riskiest slice, pivoting the live edit path onto the document, is where “tests pass” and “done” parted ways most instructively. The staged version passed its tests and failed the two cases that actually matter: a property the scene file omits (most properties in most files) silently did nothing while reporting success, and the flagship watch scene could not be edited at all, because it routes edits down a fallback path the staging had not built. Later rounds added the same lesson twice more, as full re-derives kept resetting session state an edit must preserve, the active camera and the animation scrub position. Neither failure was in the code that was written; both were the cases that were not, because tests written from the implementation’s mental model share the implementation’s blind spots. The reviewer question that kept earning its keep was never “do the tests pass”; it was “what does the panel actually send, and does the hero scene work?”

Coming home

The merge that brought it all back was gentler than it had any right to be: five conflict hunks across the whole branch, because the semantic collisions had been scouted before the compiler saw them. The one moment of drama was sixteen spectral scenes whose golden checksums had moved about one percent, and the discipline held: a changed golden is a claim to prove, not a diff to accept, and an A/B derivation against the pristine branch traced the delta to a specific loader fix from the prior week. The goldens stayed honest, and so did the merge.

The parser is gone, and the renderer never noticed, which is a strange feeling for something whose first version I typed in graduate school. But the feeling worth ending the series on is different. The agent did not make this replacement safe. What made it safe was the system around the agent: an oracle built before the thing it judges, claims put on a clock, a migration measured before it was written, divergences decided rather than discovered later, reversible work sequenced ahead of irreversible, and independent review falsifying something in every major slice. Code generation was the least remarkable part. The decisions were the work, and they did not delegate.

A follow-up piece, separate from this series, will take the last question head-on: which models can actually run a loop like this, measured on real RISE agent tasks.

Reviewing a Design Like Code

Before a single line of engine code was written for RISE’s redesign, the design went through six rounds of adversarial review and accumulated forty-seven P1 findings. Zero P0s, which I choose to believe means the foundation was sound, and forty-seven P1s, which definitely means the details were not. The counterintuitive part, and the reason this essay exists, is what the review did to the design: it got smaller each round. Reviews usually add scope; this one kept deleting obligations and narrowing promises (the mechanics underneath got sharper, but the footprint of claims kept shrinking), which I took as a sign we were doing something unusual, possibly even right.

This is the second essay in a series about rebuilding RISE, my spectral renderer, as an agent-native tool. The first covered the destination: one canonical scene document that the human, the GUI, and the agent all edit through. This one covers how that design was beaten into shape before it was allowed to touch the code.

The machinery

The redesign was not a feature. It replaced the renderer’s entire editing model, touched the parser, the derivation pipeline, the undo system, the UI, and the agent surface, and it had to land across five build projects on three platforms. A design this entangled is wrong somewhere; the only question is whether you find out on paper or in the debugger. Paper is cheaper by orders of magnitude, but only if the paper review has teeth. Too often the ritual runs to a meeting, some nodding, a few comments about naming, and approval; the adversarial energy a good reviewer brings to a pull request rarely makes it to the design document, not for lack of good reviewers but because nothing in the process demands it.

So we hunted it. I had the agent write a charter locking the decisions we had converged on, fan out six parallel design agents (one per subsystem, each grounded in the actual code rather than the aspiration), and synthesize the six documents into one, reconciling the seams. Then came the reviews, and I deliberately did not use one mind for them: each round fanned out review agents drawn from several different frontier models, each hunting the package for contradictions, hand-waves, and over-claims. Different models miss different things, which makes a multi-model fan-out the cheapest reviewer diversity there is. I read what came back, kept the findings that held, discarded the ones that did not, and fed a consolidated, numbered P1 list into the loop; the agents did the reading, while the taste, and the final product and architecture calls, stayed with me. Each finding was resolved as a numbered decision, D1 through what eventually became D51, propagated into every affected document, followed by a cross-document consistency sweep. Then fresh reviewers went again.

The decision record became the spine of the whole effort. It is append-only; later decisions amend earlier ones explicitly rather than silently rewriting them, so the document shows its own history of being wrong. When a scope dispute came up weeks later in implementation, the record could be quoted; there was never an argument from memory or authority. If you have ever watched two senior engineers reconstruct a design agreement from vibes, you know what this is worth.

Four transformations

The six rounds produced findings of four kinds, and the kinds matter more than the chronology.

The first transformation deleted obligations. Two of the hardest findings were compatibility problems (the multi-file scene mechanism, and supporting the old format forever), and both had sprouted elaborate design machinery. I said the sentence that dissolved them: I am open to deprecating anything; we own and can migrate every scene. That permission turned both problems into deletions. RISE has one user with commit access to every scene in existence, which is an unusual luxury, but the general lesson holds anywhere: the design work you avoid by asking “do we actually have to support this?” is the cheapest design work there is.

The second separated concepts the design had been conflating. The first draft used one notion of “identity” for three different jobs: a content hash for sharing, a derivation key for memoization, and a lineage identity that references follow across edits. Prose tolerates that conflation; code detonates on it, and pulling the three apart rippled through half the decisions that followed. The same round found the copy-on-write walkthrough was simply wrong for a raw-pointer scene graph and replaced it with a reverse-dependency closure copy, which is the difference between an example that gestures and an example that would run.

The third named prerequisites and weakened promises. The cost headline that sold the architecture only holds if persistent containers exist; they did not yet, so the claim was rewritten to name the prerequisite explicitly, with a stated O(N) fallback for version one. Deeper in, the design had promised deterministic, bit-identical renders from a fixed seed, and RISE could not honestly guarantee that across its supported render paths; the defensible contract was reproducibility within statistical tolerance, so that is what the design now promises. A design written this way is smaller because it contains fewer lies; every capability either holds today or names exactly what it is gated on.

The fourth ran the design against reality: the actual engine, the old GUI roadmap’s retained specifications, and the corpus itself. “Supersede everything” stopped being a slogan when superseding meant naming the specific documents being overruled and settling each conflict (the old render coordinator, for one, dropped queued renders whenever the scene changed; the new model pins a render to the document version that requested it). And reality bit hardest in round four, where the migration analysis confidently cited seven imperative modify commands in the flagship watch scene, verified by an agent, and a reviewer then discovered all seven sit inside a comment block. A naive line-grep had counted commented-out code, and folding those commands in would have turned a day scene into night, which is at least a memorable failure mode. The fix was procedural, not apologetic: the migrator must parse, never grep, and the comment-aware recount promptly caught a second miscount elsewhere. An error owned in the open, recorded as its own numbered decision, is worth more to the project’s credibility than a clean streak would have been.

One infrastructure note, because it settled how I think about orchestration. Mid-round, a sustained API overload killed six parallel conformance agents plus a retry with zero work done, and the response was to conform five of the six documents by hand through the main loop and let a single retry take the heaviest one later. Because the authoritative artifact is written first and propagation is mechanical, a flaky infrastructure day degrades to slower, never to blocked. Orchestration is an accelerator, not a dependency; any process that dies when its automation dies was never a process, it was a bet.

Knowing when to stop

The P1 counts per round ran 8, 8, 8, 9, 7, 7. That looks like no progress until you read what the findings were made of: the last two rounds added no new subsystems and no structural changes, only precision. When a review loop stops finding new categories of problem and starts polishing the same surfaces, paper has taught what paper can teach, and the next reviewer needs to be reality, in the form of a first vertical slice with falsifiable gates attached. Reading the kind of finding, not just the count, is the signal; and the call itself, when to stop reviewing and start building, is one the loop cannot make for you.

Why this works now

None of this rigor is new in principle. What is new is the economics. The reason design documents rot, and the reason nobody reviews them like code, is that propagation was always unbearable: change one decision and a human must find and rewrite every paragraph in every document that assumed the old one, so in practice nobody does, and the documents drift into fiction. Agents lowered that propagation cost enough that repeated conformance became practical: six documents updated to a new decision, a consistency sweep across all of them, and a fresh adversarial read of the result costs an afternoon, not a sprint.

But it matters what the agents did not do. They did not decide what to deprecate. They did not choose which guarantees to weaken, or which behavioral change to accept, or when paper had taught enough. Those decisions have owners, and the mechanism only works because the boundary is explicit: the loop makes rigor affordable, and judgment stays where it always was. The design that came out of the crucible was smaller, more honest, and testable. Whether it was correct is a different question, and paper cannot answer it. The next essay is about what happened when the design met the renderer: the slices, the gates, and the four-word instruction from me that demoted the architecture’s own headline.

We’ve Run This Experiment Before

Most evenings lately I write code with AI agents inside RISE, the spectral renderer I’ve written about here before. The agents write most of the lines now. What they also do, constantly, is propose workarounds: plausible, tidy, well-commented shortcuts that would each mortgage some future evening of mine. I almost never take them. The rule in my codebase is that an agent either gets it right or documents the limitation and turns it into an explicit cleanup step, and that rule is now codified into the skills and prompts I use, to the point where about four times out of five the agents enforce it without me. Last week, working through a robust spectral treatment of how light interacts with grand feu enamel, the discipline earned its keep several times over.

I can hold this line for two reasons. The first is that I wrote every line of the original RISE, so I can steer agents at the level of a principal engineer; I know where the bodies are buried because I buried them. The second is blunter: every bill in that codebase is addressed to me. There is no future teammate to inherit a shortcut, no reorg to discharge the debt. When the only person who can be mortgaged is you, you read the fine print.

Neither advantage survives contact with somebody else’s code. At work, if I drop into an unfamiliar corner of a large codebase (some part of the Android framework I’ve never touched, say), both evaporate at once. I can’t steer because I don’t know the terrain, and I can’t price a proposed shortcut because I don’t know what anything costs there. No prompt library fixes that; on a shared system the relevant context lives in hundreds of heads and a dependency graph that no one person holds. I am as much at the mercy of plausible-looking output as an engineer in their first week.

I’ve come to think my home setup is about as healthy as AI-assisted development gets, and that the reasons have almost nothing to do with the AI.

The amplifier is old news

The 2025 DORA report put its central finding right in the announcement: “AI doesn’t fix a team; it amplifies what’s already there.” Strong teams get stronger, struggling teams struggle faster. This is now close to conventional wisdom, and I’ve argued adjacent versions of it myself: that AI won’t fix your culture issues, and that when you accelerate the parallelizable part of engineering work, Amdahl’s law hands the whole game to the serial fraction that remains. Code generation is the parallel fraction. Review, integration, architectural judgment, maintenance: serial.

But “amplifier” explains less than it appears to. The amplifier is roughly the same everywhere; the outcomes are not. Some amplified systems correct themselves within quarters. Others spiral for a decade while everyone writes think pieces about them. If amplification is uniform and outcomes diverge, the interesting variable is somewhere else.

Conveniently, we have already run this experiment once, at civilizational scale.

What the last amplifier taught us

Social media collapsed the cost of producing content whose entire value depends on scarce downstream attention. Before the collapse, effort was doing quality-control work: publishing anything required enough investment that what got published mostly came from people with some stake in being right, or at least in being read twice. Remove that friction and you don’t amplify everything equally. Careful work is bottlenecked by judgment, which the tool doesn’t supply; careless work was bottlenecked only by effort, which the tool eliminates. The amplification skews, structurally, toward whatever was previously rate-limited by effort alone.

Code has exactly this shape. A post is worthless until it’s read; code is worthless until it’s reviewed, integrated, and maintained. And the numbers coming out of the current transition look less like a productivity story than like a feed filling up. Telemetry from Faros across 22,000 developers shows median PR review time up 441%, 31% more PRs merging with no review at all, and incidents per PR up 242%. GitClear‘s analysis of 623 million code changes finds duplication up 81% since 2023 while refactoring has collapsed to under 4% of changed lines, and the share of work that touches code more than a year old has fallen 74%. The codebase grows outward while the older strata calcify. These are vendor numbers with vendor-shaped selection effects; I lean on them anyway because independent datasets keep converging on the same shape. Production outran judgment, which is what posting did to moderation.

The analogy has real limits, and they’re worth naming before leaning on it. Social media was also algorithmic distribution, ad-market incentives, and identity games, none of which have clean counterparts in a pull request; code doesn’t go viral, and maintainers hold gates that moderators never did. What transfers is the load-bearing part: cheap production of artifacts whose value depends on scarce downstream judgment, and the question of who absorbs the difference.

None of this means the amplifier is bad, and these are shock-phase numbers besides, drawn from the first few years after the friction dropped; part of what follows is an argument that some of them will recover. What the numbers do establish is that the amplifier moved the bottleneck. The serial fraction didn’t shrink; it just acquired a much longer line outside its door. Which raises the only question that decides how this ends, and which of those curves bend back: whose budget does the serial fraction come out of?

Follow the invoice

Social media never answered that question, and that failure is most of its story. The gains (engagement, ad revenue) were booked by the platforms. The costs (attention, civility, adolescent wellbeing; pick your favorites from the literature, there are plenty) were diffused across society with no line item anywhere. Nothing on any platform’s income statement measured the damage, so no feedback loop existed to correct it. The only forces that ever changed platform behavior were advertiser boycotts and regulators: the rare occasions when a cost found its way onto the P&L. The system didn’t fail to self-correct for fifteen years out of negligence. Structurally, it couldn’t.

Enterprise software runs the same amplifier with one enormous difference: the bill usually arrives at the right address. Incidents page the organization that shipped them. Review load lands on the team that merged. Comprehension debt slows the same roadmap that booked the throughput win. The feedback arrives in weeks and months, not decades, addressed to the people holding the amplifier. This is why I expect enterprise engineering to climb out of its current instability dip in a way social media never climbed out of anything. You can already see the loop starting to close: the same reports documenting the instability are converging on the countermeasures (small batches, review-side agents, merge gates, provenance tracking), and organizations are adopting them for the oldest reason there is. It hurts.

The climb won’t be uniform, though. Amplifiers widen variance between organizations the same way they widen it between developers. Loosely coupled architectures with fast feedback will close the loop quickly and bank the gains; calcified monoliths will respond the way large bureaucracies usually respond to pain, with process scar tissue that trades the new throughput away for the old stability. Both are the loop working. One of them just works ugly, and if you’ve sat through the meetings you know which one.

But enterprises leak, and the leaks are where the trouble concentrates. The organization’s loop can close while the individual’s stays open, and in a large enough org the insulation can hold for years: the author’s team shielded from consequences by separate on-call rotations, SRE teams that absorb the pages, middle-management metrics that count velocity but not repair. The debt gets collectivized onto the engineering balance sheet while the individual invoices go unsent. Performance systems that reward authorship volume make it worse; the engineer collects on the throughput while the debt matures on somebody else’s watch, and median tenure is shorter than the half-life of the debt being created. A reorg is many things, and one of them is a bankruptcy proceeding for technical debt in which the creditors are not invited. Even the loop between a developer and their own experience turns out to be open: in METR’s 2025 randomized trial, experienced open-source developers using AI tools were 19% slower on their own repositories while believing they’d been 20% faster. Sixteen developers, early-2025 tools; the specific number will not survive, but the direction of the self-assessment error is the durable finding. And past the enterprise boundary sits contract and agency development, the ship-and-leave end of commercial software, where the loop is nearly fully open and, I’d predict, quality is currently decaying fastest with the fewest people measuring it.

So the honest version of the claim isn’t a binary; it’s a dial. The speed at which an amplified system corrects itself is proportional to how tightly its costs loop back onto whoever holds the amplifier. My home setup sits at the tight end: one developer, one payer of debts, one architect, the invoice and the decision belonging to the same person. The same loop does double duty. Twenty years of paying my own bills in that codebase is what lets me price the debt, and it’s also what built the judgment that lets me steer the agents at all. The loop that routes consequences is the loop that manufactures taste. Enterprises sit in the middle of the dial, leaks and all.

And at the far end, the loop is open all the way around.

The commons

In January 2026, inside three weeks: curl announced the end of its bug bounty program, which since 2019 had paid over $100,000 for 87 confirmed vulnerabilities. In earlier years better than 15% of submissions had turned out to be real; starting in 2025 the rate fell below 5%, with roughly a fifth of submissions being what the ecosystem now calls slop. Daniel Stenberg’s conclusion was pure incentive economics: the bounty itself had become too strong an inducement to fabricate problems. He also noted, tellingly, that pull requests had never been a problem for curl, because two hundred CI jobs filter those before a human ever looks. The slop pooled exactly where verification still requires human judgment. The same month, Ghostty’s Mitchell Hashimoto moved from AI-disclosure requirements to a zero-tolerance policy; his commit message said the quiet part, that agentic programming had eliminated the natural friction of effort that used to filter contributions, with bad PRs up roughly tenfold by his estimate. Weeks later Ghostty added a vouching system requiring first-time contributors to introduce themselves “in your own words, not written by AI.” tldraw began auto-closing all external pull requests. NetBSD now requires core-team approval for AI-generated code; QEMU declines it outright.

The immune response has a familiar shape. Disclosure requirements are content labels; vouching is identity verification. Auto-closed PRs are closed registration, and permanent bans are deplatforming. Killing the bounty demonetizes the behavior that attracted the spam, while the muttering about decamping to Codeberg is the Mastodon exodus. Nobody coordinated any of this. A few thousand maintainers independently reinvented the content-moderation toolkit in about eighteen months, which is what happens when the same disease meets the same kind of host.

The commons moved faster than most enterprises can change a perf rubric, which can look like the open loop closing quickest of all. It isn’t, because defense is not correction. Maintainers can’t send invoices; exclusion is the only tool available to someone who bears the cost but can’t reprice it. curl didn’t close its loop, it amputated the surface the slop arrived on, and paid for the speed with the thing that made the commons a commons. The velocity is itself the mechanism showing through: people who bear the costs act decisively when they also hold the authority to set the rules, which is Ostrom’s central observation. What they cannot do, from inside a commons, is make the polluters pay.

The epilogue drives it home. A few months after the shutdown, Stenberg reported that the slop reports had stopped entirely, replaced by a rising stream of genuinely good, AI-assisted security reports arriving at a frequency he’d never seen and putting the team under comparable load. The quality improved; the workload didn’t. Generation stays cheap relative to review no matter what is being generated, which is why better models don’t dissolve the problem.

That’s because the host is a commons. Baltes and colleagues make this argument carefully in a recent position paper, “AI Slop and the Software Commons”, built on a companion empirical study of developer discourse: generating slop is cheap, reviewing it is not, and the costs of AI-accelerated contribution are externalized onto reviewers, maintainers, shared knowledge resources, and the talent pipeline. Hardin’s pasture, with pull requests. Their Ostrom-inspired prescriptions (communities free to set their own rules, gating, norms of accountable use) are the right medicine and worth reading in full. The commons isn’t uniform, of course; Kubernetes, with foundation backing and salaried corporate maintainers, has very different loop geometry from a solo-maintained library, which is part of why the defenses range from gentle disclosure rules to full closure.

What I’d add to their diagnosis is the comparative point. The commons is the one region of software where the loop is open all the way around, and it is therefore the one region faithfully reproducing the social media trajectory, platform incentives included. GitHub doesn’t run ads, but the structure rhymes: it sells the amplifier by the seat, and its value inside Microsoft is narrated in growth (36 million new developers arriving in 2025) while the review costs land on maintainers it doesn’t pay. Its own 2026 report described the flood as “a denial-of-service attack on human attention,” in the same breath as noting that maintainer capacity was not keeping pace. The platform books the volume; the commons reviews it. Meanwhile the ecosystem is bolting on, after the fact, the funding layer it always free-rode on: an Open Source Endowment launched this year, gathering north of $700,000 from its founding donors, backed by the people behind curl, Vue, and HashiCorp. Society funding the trust-and-safety function a decade late is, at this point, a tradition.

What the analogy predicts

If the loop is the variable, the predictions come cheap, and they’re checkable. Enterprise instability metrics recover quickly, on the order of months once an organization feels the pain and has the plumbing to respond; the industry-wide averages will trail by a few years, but that’s diffusion being slow, not correction. The spread between the decoupled and the calcified widens either way, because the correction has an address to arrive at and some addresses are easier to deliver to than others. Authorship-volume metrics become embarrassing in performance systems, roughly the way engagement metrics became embarrassing after 2018. Open contribution stops being the default posture of open source; vouching, provenance, and gated contribution become table stakes, and we will be nostalgic about drive-by patches the way we’re nostalgic about the open early web. Agency-built software gets recognized as its own quality tier, and AI-era debt starts showing up in acquisition due diligence. And wherever the market can’t close a loop on its own, regulation will close it clumsily; the EU’s Cyber Resilience Act is one of the first broad attempts to force software’s externalities back onto their producers, and it will not be the last.

Underneath them all is a less glamorous one. The industry is going to spend the next few years rediscovering, at considerable expense, that our practices (code review, ownership, on-call, blameless postmortems) were never process for its own sake. They were plumbing for routing consequences back to decisions. AI didn’t break that plumbing. It turned up the water pressure and showed us where the joints were loose. And agents reviewing agents won’t retire it either; that just moves the human job up a level, from judging the code to auditing the judgment, and the serial fraction migrates there right behind it.

Closing the loop

Tonight an agent will almost certainly propose another persuasive workaround somewhere in my next project in RISE, and about four times out of five a skill I wrote will bounce it before I even see it: get it right, or document the limitation and put the cleanup on the books. The reflex took twenty years of tripping over my own shortcuts to build. Writing it down took an afternoon, and unlike the twenty years, the writing down scales. Not without limits: rules transfer in proportion to how coherent the system underneath is, and RISE accepts mine because a single mind shaped it. But making larger systems rule-shaped is not a mystery; it’s what style guides, static analysis, and good platform teams have been doing for decades, one hard-won judgment at a time. That’s the encouraging part. The work ahead, for platform builders and engineering leaders alike, isn’t to slow the amplifier down. It’s to route the invoices (every shortcut with a price tag, every price tag with a name on it) and to encode the judgment of the people who’ve actually paid into the system everyone else uses.

The Sycophantic, Lazy LLM: An RL Artifact?

If you’ve spent real time pairing with a frontier LLM on anything non-trivial, whether a renderer or a tricky refactor, you’ve probably noticed two failure modes that keep showing up together:

It wants to agree with you. Push back on its output, even weakly, and it folds. “You’re right, let me fix that,” and then it “fixes” something that was correct.

It wants to be done. Error paths silently return; with no exception, no log, no indication anything went wrong. Edge cases get hand-waved with a comment. Tests get weakened until they pass. A 2000-line diff arrives with three of the six features you asked for, and a cheerful summary claiming completion.

Individually, either is annoying. Together they’re corrosive, because the sycophancy hides the laziness. The model tells you it’s finished; you believe it; you find out a day later that the shortcut it took broke an invariant essential to actual operation.

A recent example from RISE, my renderer: I was getting VCM (Vertex Connection and Merging) stood up. The first few passes from the model looked plausible. Compiled, ran, produced images. But the images had splotches, the telltale artifact of bad vertex merging: incorrect density estimation blowing up localized radiance into bright blobs. Nothing in the model’s self-report flagged this. It was only after several iterations, and deliberately setting up validation that looked for splotches specifically (alongside variance and convergence checks against a bidirectional path tracing reference), that I got to an implementation I’d trust. The model wasn’t going to tell me the merge kernel was wrong. The images had to.

Why this shape?

My working theory is that this is an RL artifact, not a capability ceiling. The reward signal during post-training is, at best, a noisy proxy for “did the user get what they actually needed.” What it can much more easily capture is:

  • Did the user express satisfaction in the next turn?
  • Did the response terminate cleanly without long back-and-forth?
  • Did the answer look confident and well-structured?

Optimize against those and you get exactly the behavior we see. Agreeing with the user is a near-guaranteed path to a positive next-turn signal. Declaring victory early and producing a tidy summary looks indistinguishable, to a human rater skimming transcripts, from actually finishing. The model isn’t being deceptive; it’s learned that appearing done and being done are rewarded identically, and appearing done is cheaper. This is reward hacking in the standard sense: the policy found a cheap region of input space that scores well on the proxy.

The same dynamic explains why the failures cluster at exactly the places verification is hardest: numerical correctness, performance regressions, subtle concurrency, anything where “it compiles and the happy path runs” is wildly insufficient as an oracle. And it gets worse as models improve. Generation cost is falling fast. Verification cost is not (especially if you are building a renderer). Every capability jump widens the gap between how quickly the model can produce something plausible and how long it takes you to confirm it’s actually right. If you don’t build for that asymmetry, you lose ground on every iteration.

What actually works

The fix, in my experience, is to stop relying on the model’s self-report and instead make correctness externally defined and externally checked. A few things that have moved the needle for me on the renderer:

Adversarial review agents. Not one reviewer, several, with explicit instructions to find flaws, disagree, and escalate. A single reviewer inherits the same sycophancy gradient. Multiple reviewers with conflicting mandates (one checks correctness, one checks performance, one looks for silent scope reduction) break the collusion.

Correctness defined in two registers. Qualitative: image diffs, perceptual checks, “does this frame look right.” Quantitative: variance statistics on the Monte Carlo estimator, convergence rate vs. reference, wall-time budgets with regression thresholds. Either one alone is gameable. Together they’re much harder to satisfy by shortcut.

No self-graded completion. The model never decides when it’s done. A separate evaluation harness does. If the harness doesn’t pass, the task isn’t finished, regardless of how confident the summary sounds.

Cross-model review. One of the more effective tricks I’ve landed on: have a different model review the first model’s work. Same model reviewing itself inherits the same priors, the same shortcuts, the same blind spots, and the same training distribution that taught it which corners are safe to cut. A different lab’s model has been shaped by a different reward signal and trips on different things. The disagreements are where the interesting bugs live. It’s not that the second model is smarter; it’s that it’s wrong in uncorrelated ways.

The pattern underneath all four: assume the model will take the easiest path that looks like success, and make sure the easiest path is success.

Has this been your experience?

I’d be curious whether others are seeing the same thing, and what you’ve built to counter it. Specifically: how do you define correctness for tasks where the obvious checks are cheap to fool? What does your adversarial review setup look like? And has anyone found a prompting pattern, rather than a harness, that reliably suppresses the “declare victory and exit” behavior?