You state the requirements; QA to fix to re-QA runs on a loop up to a stop condition
  • Human input was 4 requirements only. The remaining 22 actions (13 QA audits and 9 auto-fixes) ran on the loop.
  • All 4 phases reached the stop condition (blocking bugs high/mid = 0). A no-loop control built the same way left 5 blocking bugs under the same QA.
  • Cost rose from ~73 minutes of build alone to ~3 hours with QA and fixes.

The experiment

The question after “make an AI write code” is how far the human can step back. Once the requirements are in, can the build, review, and fix cycle be run by a loop instead of a person? I ran it to find out.

The subject is a 20-feature browser paint app, followed by three complex modifications applied in sequence:

  • Mod A: multiple layers (add/delete/reorder/visibility/opacity/merge)
  • Mod B: free transform of a selection (move/scale/rotate, preview commit/cancel, Undo)
  • Mod C: animation (frames / onion skin / playback / numbered PNG export)

All the human submits is the base spec plus the three requirement texts.

The rest is the loop’s job. In each phase an independent QA agent reads the source and emits bugs.json. If blocking bugs (high/mid) remain, the full list is auto-formatted and dispatched to the fix builder, then re-QA’d. This repeats mechanically until high/mid = 0 (cap: 4 fixes per phase).

Builder and QA are separate agents with separate labs and memory. The builder does not know it is in an experiment.

Prompts used (base + mods A/B/C + QA/fix templates):
▶ Download all prompts (.txt)

Human: submit goaldefine the goalBuildbuildIndependent QAemit bugs.jsonblocking bugshigh/mid = 0 ?Next req / donestop condition metYesAuto-fixsend full bug listNore-QA (max 4 fixes per phase)

The human only states the goal. Build → independent QA → decision → auto-fix → re-QA loops automatically until blocking bugs reach 0.

Repeated QA and design generalization

The most interesting result: a repeated QA lifted local fixes into a codebase-wide invariant.

In Mod B (free transform), the independent QA caught the same class of defect over and over: if a destructive operation from outside the transform session (save, clear, Undo/Redo, layer merge) happens mid-session, the state breaks.

The fix loop eventually stopped point-patching and consolidated into a single guard that always auto-commits the session before any destructive operation. Mod C (animation) replayed the same shape, converging on routing every destructive edit path through one unified playback lock.

A QA gate does not merely kill defects; it can turn local fixes into a design-level rule. That only became visible after running the loop a few times.

The per-phase effort backs this up. The phases with more state conflicts (free transform and animation) took more QA and fix rounds (Mod C kept one mid bug for three rounds before dropping to 0).

Compared with no loop

The same four requirement texts go to a separate builder on the same model and settings, but with no QA gate and no fix loop (only a self-survey each time). This is the ordinary “just ask the AI to build it” workflow.

Count the distinct new blocking bugs at each phase, with no double counting. It is 2 at the base, then +1 per phase after. Without the loop none are fixed, so all 5 remain in the end.

No loop: distinct new blocking bugs per phase (no double count)0123+2cum 2Base+1cum 3Mod A+1cum 4Mod B+1cum 5Mod C

Distinct new blocking bugs first appearing at each phase (each counted once, no double count). Without the loop, nothing is fixed, so all 5 remain in the final artifact. With the loop, each phase is fixed to 0. ■ high / ■ mid

Residuals on the final artifact line up as:

ConditionRemaining blocking bugs (high/mid)Runtime
With loop0~3 hours (QA + fixes)
No loop5~73 min (build only)

The five bugs left without the loop (playback vs Undo/Redo, IME double-commit, multitouch drawing, free-transform vs Undo/Redo, eraser composite mode leaking) are the same failure classes the loop’s QA caught and fixed to 0. The only difference is whether a mechanism to fix them was in place.

The manipulated variable is the presence of the loop, but with one trial per condition I cannot claim the whole 5-bug gap is caused by the loop. For this single trial, with the loop high/mid = 0, without it 5 remained.

Limits and takeaway

Under this app, these requirements, this model, this QA rubric, and this fix cap, the loop reached the stop condition with no human intervention. With that said, the line:

  • It is not “requirements only.” The stop condition (high/mid = 0), the severity rubric, the fix cap (4/phase), and the agent setup were all designed by a human in advance. What you design shifts from “a task” to “a loop, including how it stops.”
  • The same independent QA is detector, stop-condition judge, and final evaluator. I cannot rule out that the loop optimized toward what that QA accepts rather than quality itself. A third-party evaluator, execution tests, or E2E in the final check would raise confidence.
  • One trial per condition is a small sample, and generation output varies run to run. The mid vs low split also retains subjectivity.
Once you design the requirements and the stop condition, the build to fix to re-check cycle runs without human judgment and (at least here) converges even on complex modifications. The unit you delegate to an AI rises from "a task" to "a loop with a stop condition." What you design is the goal and how it stops.

Setup: two independent agents on aidoc (a home-built agent platform), builder + QA-auditor, both claude-opus-4-8, memory-unbound, independent workspaces. State carries over via workspace files, not agent memory. The no-loop control used a separate builder on the same plugin set, fed the same four requirements, measured in one trial. 26 total runs, ~3 hours runtime, final 30 files / ~4,100 lines.