Writing archive

Operating model

Inside the Dark Factory: What Autonomous Software Delivery Actually Looks Like After 124 Iterations

My autonomous delivery loop ran for 49 hours, completed 124 iterations, filed 313 findings, shipped 40 fixes with regression specs, and then scored itself 78.85 against a ship bar of 80. It refused to call itself done. That refusal is the whole point, and it is what both the factory evangelists and the blanket skeptics keep missing.

June 29, 202612 min
dark factoryautonomous deliveryverificationagent harnessgovernance
A gated software-delivery pipeline running autonomously through planning, harness design, building, and verification phases, with a single human review boundary at the merge gate

49 hours, 124 iterations, no ship

At 7:05 p.m. UTC on April 20 I pointed my autonomous improvement loop at one of my own products and walked away. Just over 49 hours later it had completed 124 iterations, filed 313 findings, fixed 40 of them with regression specs attached, and classified 224 as noise it should not chase. Its last scored pass came in at a composite of 78.85. My ship bar is 80, plus zero task-level failures. The factory looked at two days of its own work and declined to call it done.

That run is the most honest summary of autonomous software delivery I can offer. There are two loud camps right now. One says three engineers can run a software factory and the rest of the org chart is legacy. The other says agents cannot be trusted near production code and the whole exercise is expensive theater. Both camps are arguing about the model. Almost everything that decides whether a dark factory works lives in the harness around the model: the gates, the evidence, the scoring, and one carefully placed human.

I run one of these factories daily. This piece is what I would want someone to tell me before building one: what the thing actually is, where the human boundary survives contact with production, where autonomy gets earned instead of granted, and the specific ways mine has broken.

What a dark factory actually is

The name comes from lights-out manufacturing: a plant that runs with nobody on the floor. Mine is a daemon that runs coding agents through a gated lifecycle. Work enters as a feature or a bug, and moves through phases. No agent can advance past a gate it has not satisfied, and the gates are checked by the orchestrator, never by the agent that did the work.

PLANNING -> HARNESS_DESIGN -> BUILDING -> SPEC_DRIFT_CHECK -> REGRESSION_GATE -> TRIAGING
                                                          |
     ESCALATED (human off-ramp) <---            FIX_LOOP <-+
                                                          |
                                  REVIEW_READY -> PENDING_AUDIT -> COMPLETED
PhaseExit gatesWhat it prevents
PLANNINGcodex_plan_reviewBuilding the wrong thing confidently
HARNESS_DESIGNharness_baseline_recorded, codex_harness_review, tier_distribution_checkA definition of done written after the work
SPEC_DRIFT_CHECKspec_drift_check, stub_detectionScope creep and TODO-stubs shipped as features
REGRESSION_GATEharness_verificationMerging on the worker agent word alone
REVIEW_READYmode-dependent: human, or auto-approve at quality 80+ with zero P0/P1Unearned autonomy
Exit gates per phase, from the lifecycle state machine. A phase without its gates satisfied cannot advance; it can only escalate.

Two of those rows do most of the governance work. The harness, meaning the programmatic checks that define done, is designed and baselined before implementation starts, then adversarially reviewed by a second model. And the regression gate runs those same checks under orchestrator control, so the agent that wrote the code never adjudicates its own success. That is the no-unverified-merge invariant I published as Verification-Gated Orchestration; I wrote about VGO in a research-style piece on this blog. In its substrate simulation, at 200,000 tasks per condition, a claim-trusting baseline produced false accepts among merges at rates up to 0.70, while the gated substrate produced zero unsafe merges. The factory is that paper running as a daemon. VGO is the governance spine; everything else here is muscle attached to it.

The QA department is a roster of simulated people

Gates catch code that fails its spec. They do not catch a product that passes every spec and still cannot be used. For that, the factory runs a persona harness: an improvement loop where LLM pilots impersonate specific users and try to get real jobs done through the actual UI and CLI, while the harness scores every attempt.

The personas are not scripts. Each one is a Pydantic trait sheet, and the pilot drifts inside those traits. It mistypes at the persona typo rate. It gives up when patience runs out. It clicks the wrong thing the way a distracted human clicks the wrong thing. The drift is the point: it surfaces friction no hand-written happy-path spec would ever encode, because I did not know to look for it.

PersonaTyping speed (cpm)Typo ratePatienceAbandonment risk
Parent, 38 (careful reader)1804%20s0.15
Parent, 41 (skims, wants speed)1606%15s0.25
Teen, 15 (fast, privacy-skeptical)2403%8s0.35
Child, 11 (rambling, error-prone)9512%10s0.40
The persona roster from the 124-iteration run, with real trait values. The developer-persona variant (JUNIOR_DEV through STAFF_DEV and ONCALL_SRE) uses the same trait system extended with flaky_test_patience (1 to 50 retries) and unknown_error_patience (1 to 30 minutes before escalating).

Every act gets scored on five dimensions: effectiveness at 35 percent of the composite, accuracy 25, quality 15, edge-case handling 15, reliability 10. Effectiveness is checked against a completion signal that exists outside the transcript, a database row or a visible UI state, never against whether the pilot said it succeeded. Ship-ready means a composite of 80 or better with zero task-level failures.

What did the loop actually find? Of 313 findings: 89 reliability, 70 quality, 44 feature gaps, 44 accuracy, 36 bugs, 30 edge cases. The fixed list is unglamorous and real. There was no UI to invite a second family member at all. A sidebar link went to a 404. The signup form failed silently if a session already existed. The chat placeholder still read like the B2B product this platform was converted from. A fast persona harness finds the things your own familiarity has made invisible.

The discipline that makes the numbers trustworthy is the unfashionable one: 224 of 313 findings, 71.6 percent, were closed as WONT_FIX because they were harness noise, turn-budget artifacts, or pilot mistakes a human would not make. An autonomous loop that fixes everything it finds is mostly fixing its own reflection. The triage seat is where the judgment lives, and in my factory that seat is human.

The failure modes I actually hit

The best argument against factory evangelism is my own incident log, so here it is.

In iteration 4, the fix phase scaffolded a new accept-invite page without checking whether the route already existed. It did, under a different route group. Next.js refused to build, the primary chat surface returned 500s, and the next piloting pass dutifully registered 7 downstream findings against a regression the factory itself had caused. The loop spent a chunk of an iteration investigating its own vandalism. The fix was procedural, not clever: before any new page or route, glob for the path first. Cheap rule, real scar.

Same iteration, different lesson: the harness persists state after every act, and a manual WONT_FIX I entered mid-run was silently clobbered by the next per-act save. Two writers, one JSON file, no lock. State now goes through file locks and atomic renames, and the longer-term answer is an append-only event log. If your factory has a state file, it has a race; you just have not run it long enough yet.

Then there is the class of failure that looks like a product bug and is actually a harness budget. The default turn cap was 15 turns per job; wizard-style flows need 25 or more. Early runs kept producing max-turns failures that read as user abandonment. Almost all were the cap. Likewise, pilots kept landing at the signup page and giving up on jobs that required an existing invite, because the harness never created one. The fix was a bootstrap phase that mints real invites through the backend API before piloting starts. Rule of thumb from both: when the factory reports a failure, suspect the factory first. I made that mistake in the other direction once with a broken eval harness and nearly discarded a perfectly good model over a 0.0 score my own plumbing caused.

And the composite trend is not the smooth upward curve the demo videos promise. Sampled passes in this run scored 77.77, then 68.8, then 66.75, then 78.85. Fixes land, new findings land harder, and adding personas or acts resets the denominator. Anyone who shows you a monotonic score curve from an autonomous loop is showing you a loop that stopped looking.

Why the human review boundary survives

Here is the experiment that settled where the boundary belongs, run on another agent platform I operate. I generated the same client-loss post-mortem, an investigation across an 87-location hospitality enterprise, through four frontier models. Same data, same tools, same task.

The count of stalled equipment orders came back as 37, 38, 40 of 69, and 48. Total equipment units came back as 662, 694, and 900-plus across reports. Expected monthly volume was 16.1 million dollars in one report and 20-million-plus in another. Every one of the four reports was fluent, internally coherent, and confident. All four told the same true story in the large, and no two agreed on the numbers a board member would quote.

If four independent frontier models cannot agree on a numerator, then no single agent claim can be a merge authority, in analytics or in code. So the factory treats worker claims as triage input, never as acceptance. When an agent self-reports a gate as PASSED with no supporting harness evidence, a resolver pattern catches it and independently re-runs the harness rather than advancing. When a session hits its resume limit, the resolver refuses to pattern-match at all and passes through to a human, because a terminal that keeps dying is a signal, not a nuisance. And even a fully green feature does not go from REVIEW_READY to done in one hop; it lands in PENDING_AUDIT, which exists so that completed work stays inspectable after the fact.

The human boundary that survives production is narrow and specific: triage judgment on findings, review at the merge gate for anything that has not earned its lane, and every escalation the resolver refuses to eat. Everything else is compute.

Where autonomy is earned, not granted

The factory does have an autonomous mode, and its terms are written in code, not vibes. The resolver auto-approves a REVIEW_READY feature only when the latest quality score is 80 or above and the P0 and P1 finding counts are both zero. Miss any condition and a human reviews it. That is the entire policy, and its precision is the feature: autonomy is a lane, earned per gate with evidence, and revoked by a single P1.

The economics justify the strictness. In the VGO ablation, verification cost nothing in capability: true resolution was identical with and without the anti-false-acceptance machinery. But at equal repair budget, the claim-trusting condition resolved 52.3 percent of tasks while the gated condition resolved 78.6 percent, because accepting a false done terminates the repair loop early and burns the remaining attempts on nothing. That is a 50 percent improvement in genuinely resolved tasks for the same repair spend. Verification reads as overhead on an org chart and as margin in a ledger. For a board: the expensive line item was never the gate. It was every unverified claim the gate would have caught.

Notice what the model never appears in. Nothing in the gate table or the auto-approve rule names a vendor or a parameter count. I have swapped frontier models mid-session in this factory and written up the differences; the error profiles changed, the token economics changed, and the gates did not move. That is the property that makes a factory operable: models are staff, gates are law.

The claim I will defend

The evangelists are wrong about the direction of the headcount story. A working dark factory does not delete the engineers; it concentrates them at the boundary, in triage and at the gates, where one person's judgment now multiplies across 124 iterations instead of one pull request. The skeptics are wrong about the ceiling. My loop found and fixed 40 real product defects in two days, with regression specs, under an invariant that provably prevents the failure mode skeptics fear most, the confident false done.

So here is the position, and it cuts against both camps. Autonomy percentage is a property of your verification substrate, not your model subscription, and you can audit it: if your agent system cannot produce per-gate evidence for its last hundred accepted changes, your autonomy number is a guess dressed as a metric. And no factory should merge unattended before its own composite clears the bar it enforces on the product. Mine has not cleared 80 yet, so mine does not. If that bar feels like it is slowing you down, that feeling is the product working.