writing/blog/2026/07
BlogJul 24, 2026·6 min read

Uncle Bob's AI Workflow: Treat Code Like Compiler Output

Uncle Bob Martin's disciplined agentic engineering treats AI code like compiler output, using Gherkin tests and mutation testing to build reliable AI agents.

When Robert C. Martin — "Uncle Bob" — posted that he doesn't read AI-generated code, thousands of developers responded within 24 hours. His reasoning is sharp: "I don't review the code for the same reason that I don't review the binary generated by the compiler. I have learned to trust, within limits, the output of a properly constrained AI."

This isn't laziness. It's a principled engineering stance that has taken shape over months of working with AI coding agents — and it comes with a rigorous methodology called Disciplined Agentic Engineering (DAE).

The Compiler Analogy

In the late 1970s, Uncle Bob had to write a correction filter for a buggy compiler — checking assembly output line by line. Over decades, the industry built enough trust in compilers that we stopped reading the binary. We validated compilers through tests, formal verification, and accumulated evidence.

Today's AI code generators sit where compilers sat in 1979. You shouldn't blindly trust them — but neither should you manually inspect every function they produce. The path forward is the same: build a test gauntlet that substitutes for manual review.

Uncle Bob puts it plainly: "When I started using AI I checked the code very carefully. But as the weeks and months went by I grew to trust it within certain limits. I learned the circumstances where it could be trusted, and those where other constraints had to be added. Same song. Different day."

The Two Test Streams

The foundation of DAE is two independent streams of tests, written before any production code:

Stream 1 — Acceptance Tests (Gherkin) Written collaboratively by the human engineer and the AI, using Gherkin's Given/When/Then syntax. These form the system's behavioral contract, expressed in business language. The AI is not allowed to change acceptance tests without explicit permission.

Stream 2 — Unit Tests Written entirely by the AI. These validate internal behavior and implementation details.

Why two streams? Having to satisfy two independent perspectives prevents the model from writing code that passes only the tests it remembers writing. The two streams cause the AI to think more deeply about the structure of the code.

The 8-Checkpoint Pipeline

The community has formalized Uncle Bob's approach into an 8-step pipeline:

Checkpoint 0 — Charter and project bootstrap. Define non-negotiable rules: coding style, forbidden patterns, security requirements. The charter is a read-only contract the AI cannot modify.

Checkpoint 1.5 — Feature scope and autonomy level. Each feature gets an explicit autonomy setting, from tight (engineer reviews every decision) to loose (AI proceeds independently). Security-sensitive paths default to tight.

Checkpoint 2 — Acceptance criteria discovery. The engineer and AI brainstorm edge cases, failure modes, and business rules. Output: a structured list of testable criteria.

Checkpoint 3 — Gherkin specification. Criteria become Given/When/Then scenarios. A critical rule called implementation leakage prevention applies here: specifications must use domain language only. Writing "POST to /api/users" is rejected in favor of "user registers with email." This prevents implementation details from polluting the specification layer.

Checkpoint 4 — Architecture planning. The AI proposes a design validated against the charter. Engineers review architecture, not code.

Checkpoint 5 — Implementation. The AI writes production code and unit tests simultaneously against the Gherkin scenarios. Both test streams must pass before continuing.

Checkpoint 6 — Three-lens review. Automated checks for reuse opportunities, code quality metrics, and efficiency. No human eye on the implementation unless a lens fails.

Checkpoint 7 — Architecture fitness and change-risk analysis. Did the implementation drift from the agreed design? Does it introduce unexpected coupling?

Checkpoint 8 — Differential mutation testing. The key innovation: only re-mutates functions whose code, covering tests, or mutation operators changed since the last run. This makes mutation testing fast enough to run on every commit.

Why Mutation Testing Changes Everything

Code coverage tells you which lines were executed. Mutation testing tells you whether your tests can actually detect bugs.

A mutant is a small change to production code — flipping a comparison operator, removing a null check, changing a return value. If your test suite doesn't catch the mutant, the tests aren't validating that behavior.

When you aren't reading AI-generated code, mutation testing becomes your primary quality signal. The DAE pipeline uses differential mutation — caching results across runs and only re-testing what changed. This keeps the feedback loop under 30 seconds for most codebases.

When to Still Read AI Code

Uncle Bob's "don't read" rule has explicit limits:

  • Early in a new context, before trust is established
  • Security-critical paths (always audit these manually)
  • When a test fails in a way that can't be diagnosed from test output alone
  • When working with systems that have real-world consequences (hardware control, financial transactions)

The rule is: trust earned through constraints, revoked when constraints fail.

Practical Steps to Adopt DAE

Start with Gherkin. Before prompting the AI to write anything, write three to five Gherkin scenarios for the feature. Use a features/ directory and a simple Cucumber runner.

Forbid spec-level implementation details. Review every acceptance criterion: if it names a database table, an endpoint path, or a class name, remove it. The spec should read like a product requirement, not a technical design.

Add mutation testing. For JavaScript/TypeScript use Stryker; for Python use mutmut. Start with one module and expand. Track the mutation score as a build metric.

Define your charter. A plain text file listing what the AI may and may not do — dependencies it cannot add, patterns it must follow, files it cannot modify. Reference this at the start of every session.

Set autonomy levels explicitly. Before each feature, decide: tight (you review architecture), medium (you review tests), or loose (AI proceeds end-to-end). Announce it to the AI at the start of the session.

The disciplined-agentic-engineering repository on GitHub formalizes these checkpoints into a Claude Code–compatible workflow with hook scripts and checkpoint validators.

The Bigger Picture

The "vibe coding" era introduced millions of developers to AI-assisted programming. DAE is the correction: not a return to manual everything, but a structured framework where engineers own the specification layer while AI owns the implementation layer.

Uncle Bob's compiler analogy is historically accurate. The industry spent 30 years learning to trust compilers. It will spend far less time learning to trust AI, because we already know what the test gauntlet looks like.

The question isn't whether to read AI-generated code. The question is whether your tests are good enough that you don't need to.