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?