← Phase 3 The Build Loop Next: The Rails →

Home › The Build Loop

The Build Loop

The build loop, explained The continuous middle of an engagement — how every single change gets built, three beats at a time: the idea beside the real example (expand any section for the full method), the complete worked example, and a precise reference.

How it works the idea beside the real example — expand any section for the full method · Example the complete Harbor week · Steps the same procedure, no company, just the plugin · Reference the precise mechanics

The phases open and close the engagement. The middle — usually two to four months, the bulk of the work — isn't a phase at all.

It's one short cycle, repeated for every change: decide what you want, hand it to an agent, prove it before anyone trusts it.

Every idea below is paired with the real thing — one ordinary week of Harbor Mutual, a fictional but fully worked engagement: two features built end to end, a bug caught, a story bounced.

01

Why the middle isn't a phase

If checking waits, it piles up — and a pile never gets checked

A traditional project saves up testing and review for the end. When an AI writes the code, that's fatal: it can produce more in a week than a saved-up review queue will ever clear. So the middle isn't phased. It's a loop, and the checking happens per change.

The idea

The loop is three beats — Intent, Delegate, Discern — run for every piece of work, large or small. Nothing waits. A change is checked before the next one starts, not weeks later in a batch nobody has time for.

There's no gate at the end of a loop pass, because a pass isn't a phase. There's a merge bar every change clears: checks pass, a fresh agent has graded it, and a human who didn't write it has approved it.

At Harbor Mutual

By week four, ten changes had already shipped this way — each one proven before the next began. The week we're watching is deliberately ordinary: nothing on the board is special.

What the loop replaces
"The implementation, testing, and review phases of a traditional SDLC — collapsed into one cycle, run per change."

Phases 0–3 fixed the problem and built the factory. The loop now grows it into the product, spec by spec.

Save the checking for later and…

You get a review queue an AI can outrun by Tuesday. The whole point of the loop is that checking never gets to pile up — it happens on each change, while it's still one change.

Go deeper — the full method

The gated phases open the engagement (0–3) and close it (7–9, C); everything in between — typically 8 to 16 weeks, the bulk of the engagement — runs as this loop. There is no exit gate at the end of a loop pass, because the loop is not a phase. It is how every single change gets built, from the day the Foundation gate closes to the day the backlog is done. It has no batch artifact gate — it has a merge bar that every change clears, and it is left when a human declares the backlog feature-complete.

The loop replaces the implementation, testing, and review phases of a traditional SDLC, collapsed into one cycle and run per change. The moment the pod starts skipping the loop for "small" changes is the moment unchecked work creeps back in. Small and risky is exactly the cheap-to-type, expensive-to-get-wrong case: the worst bugs in agent-built code ship inside changes someone decided were too small to bother checking.

Where we are when the loop starts

Phase 0 fixed the problem. Phase 1 signed the requirements. Phase 2 chose the architecture. Phase 3 built the factory — the harness, the pipeline, the rails — and proved it on the walking skeleton. The loop now runs everything else.

02

The whole loop in one picture

Three beats, every time: Intent → Delegate → Discern

Everything in the middle of the engagement is this one cycle. Each beat answers a different question, and skipping any of them is exactly where agent-built work goes wrong.

Intent

Decide what you want — clearly enough to check — and write it down as a spec. When the agent can build in minutes, how clearly you said it is what decides whether you got what you wanted.

Delegate

An agent builds it, inside bounds a human set, from a plan a human approved. Not "go build it" — it's drawing the box the agent works in, then approving its plan before a line is written.

Discern

Prove it before anyone trusts it. Checks and a non-author confirm it against the spec. Merge deploys it. Written is cheap now; checked is the bar.

"It's too small to bother"

The moment the loop gets skipped for "small" changes is the moment unchecked work creeps back in. Small-and-risky is the cheap-to-type, expensive-to-get-wrong case — the worst bugs in agent-built code ship inside changes someone decided were too small to check.

Go deeper — the full method

The loop is three beats, run for every change, large or small:

  1. Intent — decide what you want, clearly enough to check, and write it down as a spec.
  2. Delegate — an agent builds it, inside bounds a human set, from a plan a human approved.
  3. Discern — checks and a non-author prove it before anyone trusts it; merge deploys it.

The vocabulary the rest of the page leans on: a spec is one feature in one file in the repo (specs/NNNN-name.md) — the goal, scope in/out, testable acceptance checks, a risk tier; the agent builds from it, no spec, no build. A story is that work before it has been made ready. A PR is the proposed change under review: one spec = one branch = one PR. CI is the automated checks (build, tests, lint, coverage) on every PR. The grader is a fresh AI agent that did not write the code and grades it check-by-check against the spec. The Checker is the pod member who approves a change — never its author. The Stop hook refuses to let an agent finish with red tests or a broken build. The rails are the Phase 3 enforcement taken together: CI gates, the grader, branch protection, and the deploy pipeline.

03

Beat one — Intent

Nothing enters the loop as a conversation

A story becomes buildable only by clearing one bar first: the Definition of Ready. The test that does the most work is dead simple — could two people build different things from this line? If yes, the line is a wish, not a check.

The idea — the vague-line test

"Handle errors gracefully" is a wish. "A duplicate submission returns an error with a specific message" is a check. The difference is whether anyone can tell, mechanically, if it's done.

A ready story also states what the change must not touch, answers the silent product decisions (fail open or fail closed? what does a blocked user see?), and names which existing pattern to reuse. A silent decision left unwritten doesn't disappear — the agent makes it for you, fast, unsupervised, and you find out what it chose when something breaks.

At Harbor Mutual

At Monday's triage, three stories were on the table. One failed the vague-line test on the spot:

The story that bounced
"Show adjusters similar past claims."
Why it never reached an agent
"Nobody can write an acceptance check for 'similar' — so nobody can build it. Back to sharpening with Luis. A bounce here costs a conversation; the same vagueness found mid-build costs a redo."

The other two sharpened cleanly into spec 0015 (the fast-path queue) and spec 0016 (duplicate-claim merge).

The highest-leverage hour in the loop

Vague intent doesn't get fixed downstream. It gets built — fast, and wrong. The hour spent making a spec checkable is the hour that decides everything after it.

Go deeper — the full method

Nothing enters the loop as a conversation. A story becomes buildable only by clearing the Definition of Ready at weekly intent triage:

  • Every acceptance criterion passes the vague-line test. "Handle errors gracefully" is a wish; "a duplicate submission returns 409 with { "error": "duplicate claim" }" is a check.
  • Scope in and scope out are both stated. What the change must not touch is as load-bearing as what it must do.
  • The silent decisions are answered. A real product choice left unwritten (fail open or fail closed? what does a blocked user see?) does not disappear — the agent makes it for you, fast, under no supervision, and you find out what it chose when something breaks.
  • A risk tier is assigned by the Pod Lead and recorded in the spec.
  • The harness context the agent will rely on is named — which existing pattern this change reuses, so the agent extends the codebase instead of inventing a second way to do something it already does.

The Orchestrator then writes the spec — one file, in the repo, durable across sessions: Goal, Why, Scope in/out, Acceptance checks, Risk tier, Delegation plan, Checking plan. The spec outlives the chat that produced it; the agent reads it every session, the grader grades against it, and when behavior changes later, the spec changes in the same PR — a stale spec is a lie that misleads the next reader and the next agent.

Intent is the highest-leverage hour anyone spends in the loop. When the agent can produce the code in minutes, what decides whether you get what you wanted is how clearly you said it — vague intent doesn't get fixed downstream, it gets built, fast, wrong.

04

Still in Intent — how much rigor

Not every change deserves the same scrutiny

One review depth for everything fails in both directions: reading a typo fix as hard as an auth change burns the pod's scarce attention, and waving an auth change through on a glance ships an incident. So every spec gets a risk tier — and the tier decides the rigor.

The idea — three tiers
  • HIGH — auth, payments, personal data, schema changes, anything hard to undo. Tight leash on the agent, the full checking ladder, a security pass, a named human signature.
  • MEDIUM — new business logic, integrations, shared services. Standard leash; the grader plus one human checker.
  • LOW — UI inside existing patterns, copy, internal tooling. Lighter look — but the grader and the mechanical checks still run.

The Pod Lead assigns the tier and owns it. Anyone can raise a tier on the spot; lowering one always takes a conversation. Risk escalates up, never quietly down.

At Harbor Mutual

The two ready stories landed on different tiers, and that decided everything that followed:

Spec 0015 — fast-path queue — MEDIUM
New business logic, nothing hard to undo.
Spec 0016 — duplicate-claim merge — HIGH
Merging claim records is hard to undo, and a wrong merge mangles two policyholders' data.

Neither was over- or under-checked. The tier decided the rigor, not the mood.

Go deeper — the full method

The risk taxonomy lives in the harness so agents see it too.

TierWhat lands hereWhat it triggers
HIGHAuth/identity, payments, personal or client data handling, schema migrations, public API contract changes, infrastructure and pipeline changes, AI-behavior changes (prompts, models, tool definitions), anything hard to undoTight agent permissions, the full checking ladder, a security review pass, a named human sign-off in the PR
MEDIUMNew business logic, external integrations, changes to shared internal servicesStandard permissions, grader plus a human Checker
LOWUI within existing patterns, copy, internal tooling, additive CRUD on established railsLighter review; the grader and the mechanical gates still run

The tier is assigned per spec at triage and recorded in the spec. Anyone — human or agent — can raise a tier on the spot; lowering one always takes a discussion with the Pod Lead, who owns the tier. Risk challenges escalate up, never down, without discussion.

05

Beat two — Delegate

Draw the box, approve the plan — then let it build

Delegating is not "go build it." The agent starts in plan mode: it reads the repo and proposes an approach — which files, how it satisfies each check — before it may change anything. A human corrects or approves the plan first.

The idea — three bounds, plus the leash
  • Scope — the files it may touch. Everything else is out: "if something outside this needs to change, stop and ask."
  • Context — the one pattern to reuse, named. An agent not pointed at the existing pattern will cheerfully invent a second one.
  • Permissions — what it may do without asking. Safe commands auto-run; installs, network calls, and gated paths force a human confirm.

Freedom by risk, within one change: loose leash on the parts cheap to undo ("format the log however reads cleanest"), tight leash on the parts expensive to get wrong ("for the keying and the auth check, follow the plan exactly").

At Harbor Mutual

On spec 0016 (HIGH), Sara delegated with two leashes — tight on the matching keys and merge write path, loose on the audit-log formatting. In plan mode she pushed on the one thing the plan glossed:

The decision the plan glossed over
"What exactly is the match key when the policy number is absent?"
The tell, and the fix
"The agent's answer was vague — which is a tell. The plan got an explicit route-to-manual-review path before she approved it. Correcting a plan costs a sentence; correcting a finished build costs a redo."
The box is enforced, not requested

A script — the Stop hook — fires when the agent tries to finish. With a red test or a broken build, it refuses. "Done" stops being the agent's opinion and becomes a fact about the world.

Go deeper — the full method

Delegating is drawing the box the agent works inside, and approving its plan before it starts. Plan first, always. The agent starts in plan mode: it reads the repo and the spec and proposes an approach — which files it will touch, how it will satisfy each acceptance check — before it may write anything. The Orchestrator corrects or approves the plan, and looks for the one decision the plan glosses over ("what is the counter key when the request has no key?"). Correcting a plan costs a sentence; correcting a finished build costs a redo. The most dangerous decisions in agent-built code are the ones nobody noticed being made — plan approval is where they get noticed.

Three bounds, set per spec:

  • Scope — the file patterns the change may touch. Everything else is out, and "if you think something outside this needs to change, stop and ask" is part of the handoff.
  • Context — the one canonical pattern to reuse, named explicitly. An agent not pointed at the existing pattern will happily invent a second one, and now the codebase has two.
  • Permissions — what the agent may do without asking. The harness auto-allows the safe commands (build, test, lint, reads) and forces a human confirm on the rest: package installs, network calls, anything under a gated path like migrations or auth.

Freedom by risk, within one change. The parts cheap to undo get a loose leash ("implement the log throttling however reads cleanest"); the parts expensive to get wrong get a tight one ("for the keying and the auth check, follow the plan exactly — deviate only by asking"). The box is enforced, not requested: the permission rules hold whether or not anyone is watching, and the Stop hook refuses to let the agent finish with failing tests or a broken build. This hook is the single highest-value automation in the standard — it turns "the tests must pass" from a request the agent might rationalize past into a fact about the world.

06

Still in Delegate — one agent or many

Spread out to explore; line up to commit

It's tempting to throw a swarm of agents at a feature to go faster. That's how you get agents clobbering each other's edits. The honest rule is a single question.

The idea

Are the pieces independent, or tangled?

  • Fan out to explore. Three candidate approaches, each written up by its own agent, run in parallel — they touch nothing shared.
  • Single-thread to build. One feature writing into shared code gets exactly one agent, start to finish — parallel agents in the same files overwrite each other.

Spread out to explore, line up to commit. The test is independence, not impatience.

At Harbor Mutual

Both of the week's specs were features writing into shared code paths — the work-queue service, the intake matching service. So each got exactly one agent, start to finish.

Spec 0015 and spec 0016: one agent each. No fan-out — nothing here was independent enough to parallelize without two agents stepping on the same files.

Fanning out would have been faster to start and slower to finish, once the conflicts surfaced.

Go deeper — the full method

One agent or many. Fan out to explore: independent investigations (three candidate approaches, each written up by its own agent) run in parallel because they touch nothing shared. Single-thread to build: one feature writing into shared code paths gets exactly one agent, start to finish, because parallel agents in the same files clobber each other. The test: are the pieces independent (fan out) or tangled (single-thread)? Spread out to explore, line up to commit.

Fanning out a build is one of the named loop failure modes — parallel agents writing the same files clobber each other. Fan out only to explore; one agent writes shared code.

07

Before Intent — when the answer isn't known

You can't write a checkable line about something nobody has checked

Every beat so far assumed a spec exists. Sometimes it can't yet — and writing one anyway is the most expensive mistake in the loop, because it looks like progress.

The idea

When the honest answer is "nobody knows," run a spike.

  • Boxed. A time box or a token box, agreed at triage and written down. A spike that runs until it feels finished is just unsupervised building.
  • Throwaway, and enforced. Spike work lives on a spike/ branch, and a required check refuses any PR opened from one. The code is read, learned from, and deleted.
  • The finding is the deliverable. What was assumed, what was tested against which system, what was found, whether the assumption survived. The write-up is committed; the code is not.

The code is the experiment. The write-up is the result — and it's the only thing that outlives the branch.

At Harbor Mutual

A story kept bouncing at triage: nobody could say whether the carrier's API deduplicated on the idempotency key, or whether a retry quietly created a second claim. Two people wrote two different acceptance lines for it, which is the vague-line test failing out loud.

Not a spec — a spike, boxed at one working day, against the carrier sandbox. The finding: retries do duplicate. The assumption died, the spec became writable, and the duplicate-handling requirement that nobody had thought to ask for went into it.

Guessing that line would have shipped a claim-duplication bug behind a full set of green tests.

Go deeper — the full method

Why a spec can't cover it. Acceptance criteria that pass the vague-line test cannot be written about behavior nobody has verified. There are only two honest responses, and one of them is a lie: write a precise spec about an unknown — which the grader then dutifully grades against fiction — or find out first.

Why the throwaway rule is mechanical. "It started as a spike" is the most natural route by which unchecked code reaches production. Spike code has, by design, climbed none of the checking ladder: no spec to grade against, no coverage bar, no Checker. The enforcement is a required status check (spike-guard) rather than a branch-protection rule, because protection rules govern the branch being merged into and cannot express "refuse this source branch." Unlike the spec gate, it carries no label escape — the route for spike work worth shipping is to write the spec and rebuild it.

Where they come from, where they go. The Pod Lead opens a spike at triage when a story cannot be made ready; the Architect opens one when a design decision has no evidence behind it. The finding closes the decision-list item, unblocks the stuck spec, and — when it invalidates a Phase 2 decision — feeds the ADR revision that follows, as a HIGH-risk spec like any other. Design gets decided at the design gate and stays revisable afterward; the spike is what earns the revision.

Two failure modes worth naming: the spike that ships (throwaway code talked onto main because it "already works"), and the spike with no finding (the code gets deleted, nothing gets written down, and the pod pays twice — once to run it, again the next time somebody wonders the same thing).

08

Beat three — Discern

The author never checks their own work

A change is done when it has been proven against its spec by something other than its author — not when the code exists. That's the whole beat. Three layers stand on every change, and the author is in none of them.

The idea — three layers on every change
  • Mechanical gates — build, tests, lint, coverage. Hard blocks; a red one stops the merge, no judgment involved.
  • An independent grader — a fresh agent that did not write the code, told so plainly, grading check-by-check against the spec. It's required to run; its verdict advises.
  • A non-author human — someone who didn't write it approves the merge. On HIGH risk, also a security pass and a named signature.

Why no author? Their tests prove only what they thought to test. The grader catches the hole the author was blind to — the case they never imagined, so never tested.

At Harbor Mutual

On spec 0016, the agent finished with eleven green tests and a clean build. On an unchecked team, that ships. The grader — a fresh agent — failed it:

The grader's verdict on check 3
"NOT MET. A missing policy number is normalized to "" before keying. Every no-policy claim shares one match bucket — two unrelated phone reporters in the same week WILL be merged into one claim. All 11 tests pass with this bug live."
How it ended
"Fix re-graded clean · security agent passed the data path · Wes signed off by name · checked and merged by Jonah, not the author. The bug existed four hours, all of them on a branch."
Checking theater

The deadliest failure mode is the author grading itself — the agent that wrote the code confirming it works, or the Orchestrator who drove it approving it. It catches nothing the author didn't already think of. Author never approves, no exceptions.

Go deeper — the full method

Written is cheap now; checked is the bar. A change is done when it has been proven against its spec by something other than its author, not when the code exists. The proving climbs a checking ladder — five rungs, each catching what the one below cannot:

RungThe checkWhat it catches that the rung below can't
1The done-rule in the harnessSets the bar ("done means checked, not typed"); persuasion only — it enforces nothing by itself
2The agent re-checks each turnThe agent's own mechanical slips: the broken import, the test it broke two steps back
3The blocking Stop hookThe agent declaring itself done anyway — it cannot finish with red tests or a broken build. But a hook enforces the tests that exist; it cannot enforce a test nobody wrote
4The separate graderThe hole the author was blind to: it grades check-by-check against the spec, not against the tests, so it catches the case the author never thought to test
5The human / security gateThe judgment calls no machine should own: the risk acceptance, the product call, the security sign-off on a HIGH change

Rung 4 is where the bug the author's green test suite hid goes to die — and it only works because Intent wrote checkable acceptance criteria for it to grade against. In the rails, the ladder lands as three layers on every PR: mechanical gates in CI (hard blocks: build, tests, lint, 80% coverage on new code); the grader in CI (required to run, advisory verdict — a fresh agent reads the spec in the diff and posts a check-by-check verdict as a PR comment, and it cannot be skipped but its verdict does not block); and the human Checker (hard block: non-author approval on every PR, plus on HIGH risk a security review pass and a named human sign-off recorded in the PR).

You do not run every change up all five rungs — that recreates the review bottleneck the loop exists to remove. The risk tier sets the climb: LOW stops after the grader's advisory pass and a light human look, MEDIUM gets grader-plus-Checker, HIGH goes all the way up. Merge deploys to the client's dev environment automatically. A true emergency merge past a gate requires the Pod Lead plus one other human, an exception label, and a retro agenda item. Two exceptions in a month means the gate or the specs are wrong.

09

Now watch one change go through

Spec 0016, beat by beat

You've got the three beats; here's a single HIGH-risk change walking through all of them, the way it actually ran at Harbor — from a story on the triage table to deployed in dev, with the grader's catch in the middle. Step through it.

Intent · make it ready

A story clears the Definition of Ready

The duplicate-merge story passes the vague-line test, scope-in and scope-out get stated, and a silent decision surfaces — what does the second reporter see? — onto the decision list with the client's two-day clock. The Pod Lead tiers it HIGH.

Intent · write the spec

One file, five testable checks

Once the client answers the silent decision, the Orchestrator writes spec 0016: goal, scope, five acceptance checks each one testable, the risk tier, the delegation plan, the checking plan. The spec lives in the repo — the agent reads it, the grader grades against it.

Delegate · bound it

Three bounds and two leashes

Scope: the matching service and merge path, nothing else. Context: reuse the existing event-log writer. Permissions: standard, with the schema gated. Tight leash on the keys and write path; loose on the audit-log format.

Delegate · approve the plan

The plan gets corrected before a line is written

In plan mode the agent proposes its approach. The Orchestrator pushes on the one thing it glosses — the match key when the policy number is absent. The vague answer is a tell; the explicit route-to-manual-review path goes in before approval.

Delegate · the agent builds

Eleven green tests — and a live bug

The agent builds inside the box. Its own tests pass, the Stop hook lets it stop, CI goes green. But the suite only covers claims that have a policy number. The bug is live and invisible. On an unchecked team, this is where it ships.

Discern · the grader

A fresh agent catches what green tests hid

The grader — told plainly it did not write this code — walks the checks against the spec, not the tests. It fails check 3: empty-string match bucket would merge two unrelated phone reporters. The verdict posts as a PR comment for the human Checker to read.

Discern · the HIGH gate

Fix, security pass, a named signature

The fix routes no-policy claims to manual review and adds the missing test. Re-graded clean. The security agent passes the data path. Wes signs off by name — the named sign-off HIGH risk requires — and a non-author checks and merges.

Discern · merge deploys

Merge ships it to dev, automatically

Merge fires the deploy pipeline; the change lands in Harbor's dev environment with no manual step. The bug lived roughly four hours — all of them on a branch, none of them in dev. The loop is ready for the next change.

1 / 8
Go deeper — the full method

The sequence above is the three beats run end to end on one HIGH-risk change. Intent makes the story ready (vague-line test, scope in/out, the silent decision routed to the decision list on the client clock) and writes the spec — one file, five testable acceptance checks, the risk tier, the delegation and checking plans. Delegate sets the three bounds and the two leashes, then corrects the plan in plan mode before a line is written — the no-policy match key is the decision the plan glossed, and the route-to-manual-review path goes in before approval.

The agent then builds inside the box; the Stop hook holds it to a green suite and CI goes green — but eleven passing tests only cover claims that have a policy number, so the data-mangling bug is live and invisible. Discern is where it dies: the grader, told plainly it did not write the code, grades check-by-check against the spec rather than the tests and fails check 3; the fix re-grades clean; the security-reviewer agent passes the data path; Wes signs off by name (the named HIGH-risk sign-off); and a non-author checks and merges. Merge deploys to dev automatically. The bug lived roughly four hours, all of them on a branch.

10

What keeps the loop honest

Four short meetings — and two numbers that run the week

None of the meetings asks "what did you do yesterday." When agents do the building, that answer is "the agents wrote a lot," and it means nothing. The meetings point at the two things that actually constrain the loop: the clarity going in, and the review queue coming out.

The idea

The daily flow check opens with the queue number — how many changes wait for checking, how long the oldest has waited — not a status round-robin. Weekly intent triage turns stories into ready specs. Retro+ asks of every escaped bug: "which check should have caught it?" and the answer becomes a harness change, not a resolution to try harder.

Two numbers run it. The WIP cap stops the pod opening more changes than it can check. The review-wait tripwire: when the median wait crosses the line, the pod stops starting new work and clears the queue. Review is the loop's real bottleneck — more building can't fix a checking constraint.

At Harbor Mutual

The week's numbers, read at Friday's retro:

79%0.9d specs accepted as-is (11 of 14) → median review wait, under the one-day tripwire

One trend flagged: the security queue's wait was drifting up to 2.1 days — read on its own line, because averaged in with the rest it would hide until something HIGH had quietly waited a week. Maya took it to Dan outside the room.

Ignoring the queue number

Review wait creeps up, everyone keeps starting work, and the loop silts up invisibly until nothing merges. The tripwire exists to make stopping automatic, not heroic.

Go deeper — the full method

Four short meetings replace the ceremony calendar. None of them asks "what did you do yesterday" — when agents do the building, that answer is "the agents wrote a lot," and the number means nothing.

MeetingLengthReplacesWhat it does
Flow check (daily)10–15 minstandupThe queue number first: how many changes wait for checking, how long the oldest has waited. Walk the in-flight changes nearest-done first; every waiting change gets a Checker; vague specs get flagged back to triage; the WIP cap gets enforced; one commitment each.
Intent triage60 minrefinementStories become ready specs: vague lines sharpened, silent decisions surfaced onto the decision list, risk tiers assigned, the backlog ordered.
Retro+60 minretroEvery escaped bug gets the same question — "which check should have caught it?" — and the answer becomes a harness improvement, not a resolution to try harder.
Setup review30–60 min(new)The week's harness changes merge: CLAUDE.md updates, skill and hook improvements, permission tuning — versioned, PR'd, reviewed by the Setup Owner's deputy.

Two numbers run the week. The WIP cap keeps the pod from opening more changes than its checking capacity can clear — agents can always write more code; the constraint is proving it. The review-wait tripwire is the alarm on the same constraint: when the median wait crosses the agreed threshold, the pod stops starting new work and clears the queue. The security queue is read separately at every flow check — it clears slower, and averaged in with the rest it hides until something HIGH has quietly waited a week.

11

Two disciplines that make it work

One spec, one change — and the client sees outcomes, never activity

Two habits keep the loop sustainable: changes stay small (one spec, one branch, one pull request), and the client is shown working software, not numbers an agent can inflate.

The idea

Small changes. One spec is one branch is one pull request. A small change is cheap to read, cheap to grade, and cheap to revert if it's wrong. The discipline is the same at forty lines as at four hundred — "too small to bother" is how unchecked work sneaks in.

Outcomes, not activity. No PR counts, no "AI productivity" claims in anything the client sees — ever. Agents inflate every activity number; demos and outcomes don't lie. Published research backs the caution: measured teams doubled PR volume while actual delivery stayed flat.

At Harbor Mutual

At Friday's 45-minute steering, the adjuster — Gail — drove the demo herself: the fast-path queue and the duplicate-merge flow, live in dev.

The scorecard showed the outcome clock (instrumented, moves at rollout), the stability trend, the accepted-as-is trend, and the decision list. Nobody saw a PR count.

Karen, the sponsor, was told plainly: the production needle moves at rollout, not before. Honest beats impressive.

Go deeper — the full method

The client never sees the loop's internals — they see working software on a steady rhythm:

  • Biweekly steering, 45 minutes: a live demo in the dev environment, the outcome scorecard (their success metric, the delivery-stability trend, the accepted-as-is trend), the decision list needing their answers, and gate status when a phase boundary is near.
  • A weekly five-bullet async summary in between. Written for a busy reader: what shipped, what's next, what we need from you. Claude drafts it from the week's merged work; the Pod Lead corrects and sends it.
  • No activity metrics in client materials, ever. No PR counts, no "AI productivity" claims. Agents inflate every activity number; demos and outcomes don't lie.

The internal dashboard is baseline-and-trend with no vanity targets: accepted-as-is rate (the trust signal), review wait median (the real bottleneck indicator), rework/revert and bounce-back-for-unclear rates (intent quality), escaped bugs (each answered at Retro+), the DORA four as trends, and security-review wait on its own line. Never tracked, never reported: velocity, story points, PR count, lines of code. The decision list is the client-facing edge of Intent: every silent decision surfaced at triage that belongs to the product lands there, with the agreed answer clock; a stalled decision list goes to steering as a delivery risk, not absorbed as quiet guessing.

Quality in the loop is per-change; some concerns only exist at the integration level — performance under load, end-to-end journeys across many features, penetration testing. The Quality Engineer plans and runs them as scheduled hardening passes (typically one mid-Build and one before deployment prep); the first pass is also where the test environment gets added alongside dev. Hardening is scheduled work inside the flow, not a phase that gates everything else.

The loop, in one breath

Say it clearly, bound it tight, let no one check their own work

That's the whole middle of the engagement — Intent, Delegate, Discern, run for every change, with the checking happening per change so it never piles up. The beats are one system: sharp intent is what makes checking possible, and independent checking is what makes speed safe. Where to go next:

01

Not a phase with a stack of inputs — one spec, and the factory Phase 3 built

What the loop receives

Harbor Mutual — a fictional regional insurer — hired a five-person pod to rebuild how property-insurance claims get reported and decided. A claim takes a median of 11.4 days from FNOL (first notice of loss) to a coverage decision; the target is 5 days or less. Foundation closed Friday 2026-04-10 with the walking skeleton live in Harbor's dev environment and the rails proven; Build began the following Monday. Unlike a gated phase, the loop does not swallow a folder of handoff files once and transform it. It takes in one thing, over and over: a single ready spec.

Received once, at Build's start — the factory Foundation built, then left running CLAUDE.md — the adapted rulebook .claude/ — Stop hook, settings, skills, grader agent the five rails — ci · grader · correctness · security · deploy-dev risk-tier-map.md build-handoff.md — the ordered spec backlog
Received again on every trip round the loop — the real, repeating input specs/NNNN-name.md — one ready spec
Why the input is a spec, not a handoff

A gated phase eats the previous phase's whole output, transforms it, and hands the next phase a bundle at a gate. The Build loop has no such shape. The factory built in Phase 3 — the rulebook, the Stop hook, the grader, the five rails — sits still and runs. What moves is one spec at a time: a story that cleared the Definition of Ready at triage, written to specs/NNNN-name.md, durable across sessions.

The spec outlives the chat that produced it. The agent re-reads it every session; the grader grades against it; when behavior changes later, the spec changes in the same PR. Everything this page shows happens to one spec — then repeats.

The week this page watches

This is week four of Build (Mon 2026-05-04 to Fri 2026-05-08), picked because it is deliberately ordinary. Ten specs merged in the first three weeks; nothing on this week's board is special. Two stories clear triage into ready specs — 0015 (fast-path queue, MEDIUM) and 0016 (duplicate-claim merge, HIGH) — and a third bounces for vagueness. We follow 0016, the HIGH one, all the way round, because it exercises every beat and every rail.

The spec that rides the loop this week
0016 — duplicate-claim merge (D-07) · Risk: HIGH. The same loss reported twice becomes one claim — never a rejection, never two claims adjusted in parallel.

Our pod

Maya ChenPod Lead — owns the risk tiers and the cadences
Rob FeldSetup Owner — owns the harness; runs setup review
Jonah KimOrchestrator / Checker — Rob's deputy
Sara WhitfieldOrchestrator / Checker — delegates and checks 0016
Nadia BrooksQuality Engineer — runs the hardening passes

Harbor Mutual

Luis OrtegaProduct owner — answers silent decisions on a 2-day clock
Wes CarterLead engineer — the named HIGH-risk sign-off
Dan KowalskiIT security — owns the security queue
Dee AlvarezIntake supervisor — the source of check 3's realism
Gail Tran, Marcus WebbSenior adjusters — drive the demo
Karen VossVP Claims Ops — sponsor; sees outcomes at steering
The ID codes, decoded

Every object in this engagement carries a stable identifier, so a decision made in week two can still be traced in month nine. On this page you'll see:

PrefixMeansBorn inExample here
NNNNA spec — one change, one branch, one PRBuild (triage)0015 fast-path queue · 0016 duplicate merge
D-NNA logged product decision the PO ownsPhase 0/1D-07 merge rule · D-09 the fast path
C-NNA constraint — a hard limit the build honorsPhase 0C-04 the 15-business-day regulatory clock
REQ-NNN / NFR-NNA functional / non-functional requirementPhase 1NFR-07 audit-logged claim actions
ADR-NNNAn architecture decision record — a signed choicePhase 2ADR-001 the replica-staleness contract
Q-NNAn open question with an owner and a due dateanycarried on the decision list into Build
risk:highA PR label — not an ID, but it fires the security rail and forces a named sign-offBuild0016 wears it

Unlike the numbered phases, the loop mints only one new ID kind of its own — the spec NNNN. Everything else it inherits and honors: a Build spec traces back to a D-, a C-, a REQ-, or an ADR- from an earlier phase, or it is scope that crept in.

02

Three beats, every change, every time — the heart of the whole method

The loop, beat by beat

This is not a calendar of days — it is the same three beats every change runs: Intent (decide and write), Delegate (bound and build), Discern (prove, then merge). Below, each beat is braided four ways: what the human does, what the agent does, what the harness enforces, and what lands on disk. Follow spec 0016 — the HIGH-risk one — through all three. Step through it.

Legend a command does it — and writes the file a person does it — and it is recorded a person does it — and nothing records it
Beat 1 — Intent · decide, tier, and write — nothing enters the loop as a conversation

Turn a story into a checkable spec — or bounce it

A story becomes buildable only by clearing the Definition of Ready at weekly intent triage. The human checks that every acceptance criterion passes the vague-line test ("could two people build different things from this line?"), states scope in and scope out, surfaces every silent product decision onto the decision list with an owner and an answer clock, and — the Pod Lead's call, never the agent's — assigns a risk tier. The agent drafts candidate specs from the kit template in-session and proposes a tier for a human to confirm. The harness runs check_spec.py: the mechanical floor (required sections, a valid tier, scope both ways, no placeholders) plus a vague-line lint, and it checks that the Checking Plan's ladder depth equals the risk tier. A spec it reports NOT READY does not enter the loop.

Tooling /sdlc-spec new_spec.py allocates the next NNNN check_spec.py the Definition of Ready the risk tier — a human call
On disk specs/0016-duplicate-claim-merge.md .sdlc/metrics/spec-log.jsonl — +1 line, the DoR result
At Harbor — three stories, three fates

"Show adjusters similar past claims" fails the vague-line test — nobody can write a check for "similar," so it bounces back to Luis and the agents never see it. The fast-path work queue (Gail and Marcus's demo feedback) sharpens into spec 0015, MEDIUM. Duplicate-claim merge (D-07) becomes spec 0016; Maya tiers it HIGH — a wrong merge mangles two policyholders' data. Triage surfaces the silent decision — what does the second reporter see? — and routes it to Luis on his 2-day clock rather than letting the agent quietly decide it.

Delegate · Beat 2 · draw the box, approve the plan — then let it build

An agent builds inside bounds a human set, from a plan a human approved

Delegating is not "go build it." The human (the Orchestrator) makes the agent start in plan mode — it proposes which files it will touch and how it meets each check before writing a line — then corrects or approves, hunting the one decision the plan glosses. They draw three bounds: Scope (the file patterns it may touch), Context (the one existing pattern to reuse, named), Permissions (what it may run without asking). Freedom scales with risk: a loose leash on what's cheap to undo, a tight one on what's expensive to get wrong. The agent builds from the approved plan, writing the failing test first when TDD applies. The harness enforces the box: the blocking Stop hook refuses to let the agent finish with red tests or a broken build — "the tests must pass" becomes a fact about the world, not a request it can rationalize past.

Tooling none — the loop runs on the rails, not commands: plan mode, then the blocking Stop hook the approved plan — a human call in the session
On disk a branch + draft PR — the code and its tests the approved plan — corrected in the session, held in the PR, not a standalone file
The one thing here that leaves no receipt

Plan approval is the highest-leverage moment in the loop — it is where the dangerous decision nobody noticed being made gets noticed and corrected. Yet the approved plan is not written to a durable artifact of its own; it lives in the PR thread and the session. The spec and the grader's verdict get files; the plan correction that prevented the bug does not.

At Harbor

Sara finalizes 0016. The check that matters most is written from Dee Alvarez's intake reality — phone reporters often don't have their policy number. She delegates with two leashes: tight on the matching keys and merge write path ("follow the plan exactly; deviate only by asking"), loose on the audit-log formatting ("your call"). In plan mode she pushes on the one thing the plan glosses — what exactly is the match key when the policy number is absent? — the agent's answer is vague, which is a tell, and the plan gets the explicit route-to-manual-review path before she approves it. Both of the week's specs get one agent each: they write into shared code, so fanning out would only clobber files. Spread out to explore; line up to commit.

Discern · Beat 3 · prove it against the spec by someone other than the author, then merge

Written is cheap now; checked is the bar

A change is done when it has been proven against its spec by something other than its author. The proving climbs a five-rung checking ladder, and in the rails it lands as three layers on the PR. The harness runs the mechanical gates in CI (build, tests, lint, 80% coverage — a hard block) and the grader — a fresh agent, told plainly it did not write the code, that walks the acceptance checks and posts a check-by-check verdict as a PR comment. It is required to run but only advises. The human Checker reads that verdict and makes the call — a non-author approval on every PR, because the author never approves their own work. A risk:high change adds the security rail and a named human sign-off. Merge deploys to dev automatically. What lands on disk: the grader's finding gets memory and a disposition in findings-log.jsonl; the merge gets a spec_merged line in loop-events.jsonl.

Tooling record_findings.py findings-log.jsonl scorecard.py record loop-events.jsonl the Checker's judgment — a human call at the merge bar
On disk the grader's verdict — a PR comment .sdlc/metrics/findings-log.jsonl — +1 line .sdlc/metrics/loop-events.jsonl — +1 line, spec_merged the non-author approval + named sign-off — required, no engagement file
Green tests are not done

The agent finishes 0016 with eleven green tests and a clean build; the Stop hook lets it stop; CI goes green. On an unchecked team, this is where it ships. The grader fails it on check 3: the code normalizes a missing policy number to an empty string before the matcher runs, so every no-policy phone claim in a 7-day window shares one bucket — two unrelated storm-week reporters would be merged into one claim. The eleven tests only cover claims that have a policy number. Rung 4 is where the bug the author's own suite hid goes to die — and it only works because Intent wrote a checkable criterion for it to grade against.

At Harbor — the fix, and the merge bar cleared

The fix routes no-policy claims to manual review before the matcher and adds a test for that path; re-graded clean. The security-reviewer agent passes the data-handling. Wes signs off by name — the HIGH-risk requirement — and Jonah, not Sara, checks and merges; deploy-dev ships it. The bug existed for roughly four hours, all of them on a branch. At the setup review, last week's Retro+ item lands: a UTC-timestamp escaped bug (C-04's regulatory clock) was answered with "which check should have caught it?", so the test-writer skill now drafts timezone-boundary cases into every suite that touches a business-read date.

1 / 3
03

Everything spec 0016 left behind — the receipts of one merge

What one trip round the loop produces

A gated phase's ledger is the pile of artifacts it produces once. The loop's ledger is smaller and it repeats: this is what a single spec's journey leaves on disk. Blue rows are written by a command or the rails, at a real path. Amber rows are the merge bar's human judgments — required on every change, recorded only in the PR's own state, with no file in the engagement's record.

ArtifactWhat it actually isWritten bySigned byLives atFeeds
specs/0016-….mdThe change itself, as intent: goal, scope in/out, five testable checks, risk tier, delegation plan, checking plan. Durable across sessions — the agent's brief and the grader's rubric/sdlc-spec scaffolds; the Orchestrator writesOrchestrator (Sara)specs/The agent every session; the grader
the merged changeThe code on the main branch, deployed to Harbor's dev environment through the real pipelinedeploy-dev.yml on mergemain branch + Harbor dev envThe running product; the outcome clock
the grader verdictA check-by-check pass/fail against the spec, pinned to the changed lines. The verdict that caught check 3grader.yml — a fresh agentthe PR (durable copy → findings-log)The human Checker's call
spec-log.jsonlOne appended line: this spec's Definition-of-Ready result at Intent — tier, author, checkercheck_spec.py.sdlc/metrics/spec-log.jsonlHarness calibration (never client-facing)
findings-log.jsonlOne appended line per grader finding, with its severity and disposition — giving the verdict memory across re-gradesrecord_findings.py.sdlc/metrics/findings-log.jsonlOpen-HIGH-debt count at the merge bar
loop-events.jsonlOne appended spec_merged event — the raw material the biweekly scorecard is computed fromscorecard.py record.sdlc/metrics/loop-events.jsonlThe steering scorecard trend
the non-author approvalThe core merge-bar rule: a human who did not write the code approved it. The author never approves their own workA human Checker (Jonah)Checkerno path — nothing writes itThe merge
the named HIGH-risk sign-offThe risk:high requirement: a named human accepted the risk of merging this changeA named human (Wes Carter)Wes Carterno path — nothing writes itThe merge, HIGH tier
Only two amber rows — and that is the point

Compare this with the design phase, where six of fourteen outputs had nowhere to live. The Build loop is the best-instrumented stretch of the engagement: the spec, the verdict, and three metrics lines all land at real paths, automatically. The only human work without a file is the pair of merge-bar judgments — the non-author approval and the named sign-off — and even those live in the PR's own approval state. Human work is not the problem; human work without a receipt is — and here there is almost none.

Deliberately not produced on a trip round the loop: a batch design document, a separate test plan, a "specification document" duplicating the spec library, and — above all — any exit-gate artifact bundle. There is no batch to gate, because the checking already happened, per change, inside the loop.

04

The input reproduced whole — one file in the repo

Spec 0016, as merged

This is the whole of what the loop received for this trip: the thing the agent read, the Orchestrator bounded, and the grader graded against, line by line. Everything in Beat 3 traces back to a numbered check below — check 3 is the one the green tests hid and the grader caught.

# 0016 — Duplicate-claim detection and merge

## Goal
The same loss reported twice becomes one claim — never a rejection, never two
claims adjusted in parallel (D-07).

## Why
Storm weeks produce duplicate reports across channels (portal, phone, email).
Today they become separate claims and get reconciled by hand at adjudication —
or not at all.

## Scope
- In: candidate matching at intake, the merge write path, the merge audit log,
  the second reporter's confirmation experience (per Luis's decision 5/6).
- Out: cross-policy fraud detection, retroactive merging of pre-Build claims,
  adjuster-initiated manual merges. Not now.

## Acceptance checks (each one is testable)
1. A second FNOL for the same policy number with a loss date inside a 7-day
   window of an open claim joins that claim; the event log records both
   reports with their channels and timestamps.
2. The second reporter receives "your report has been added to an existing
   claim for this loss" — a confirmation, never a rejection (D-07).
3. Matching is keyed per policy number plus the 7-day loss window,
   independently — one policy's candidate matches never affect another's. A
   claim arriving without a policy number is never auto-merged; it routes to
   the manual-review queue.
4. A merge is recorded in the append-only event log with both source reports;
   the merged claim's audit trail reconstructs who reported what, when, from
   which channel (NFR-07).
5. Merging never deletes a report. Un-merge (splitting a wrong merge) is out
   of scope for v1, which is exactly why auto-merge must be conservative:
   when in doubt, manual review.

## Risk: HIGH
Merging claim records is hard to undo and touches policyholder data. Full
ladder: tight permissions, security-reviewer pass, named human sign-off (Wes).

## Delegation plan
May touch: the intake matching service, the merge write path, their tests.
Gated: the claim schema (any migration is its own spec), the event log
contract. Reuse the existing event-log writer — do not invent a second one.

## Checking plan
All five rungs. Grader against every check; security-reviewer on the data
path; Wes's named sign-off before merge.

One file, seven headings, five checks — and it is simultaneously the agent's brief, the grader's rubric, the Checker's yardstick, and the durable record after the chat is gone. A stale spec is a lie to the next reader, so it changes in the same PR as the behavior.

05

Rung 4, verbatim — the fresh agent that grades against the spec, not the tests

The grader's verdict, in full

On 0016's first build the agent finished with eleven green tests and a clean build. The grader — a fresh agent, told plainly it did not write the code — walked the five checks and failed it on check 3. The full PR comment, posted by the rails (grader.yml), verbatim:

VERDICT: FAIL

Check 1 (same policy + 7-day window joins the claim): MET — covered by
  tests/merge.candidate.test (4 cases, including window boundaries).
Check 2 (second reporter sees confirmation, never rejection): MET.
Check 3 (per-policy independence; no-policy-number claims never auto-merge):
  NOT MET. intake/matching.service normalizes a missing policy number to ""
  before keying candidate matches. Every claim without a policy number
  therefore shares one match bucket: two unrelated phone reporters with loss
  dates in the same 7-day window WILL be auto-merged into one claim. The
  test suite only exercises claims that have a policy number, so all 11
  tests pass with this bug live.
  Fix: route claims with no policy number to the manual-review queue before
  the matcher runs (the spec's stated path), and add a no-policy-number test.
Check 4 (append-only audit of merges): MET.
Check 5 (no deletion; conservative auto-merge): AT RISK via check 3 — the
  empty-string bucket makes auto-merge aggressive for exactly the claims the
  spec says to treat conservatively.

The tests prove what they test. They do not test the spec's claim of
per-policy independence for the no-policy path.

The trail after the fix, recorded in the PR: re-grade PASS (all five checks, including the new no-policy-path test) · security-reviewer agent pass on the data path · signed off: Wes Carter (named HIGH-risk sign-off) · checked and merged by Jonah Kim (non-author) · deploy-dev green. record_findings.py appended the finding and its FIXED disposition to findings-log.jsonl, so the catch survives past this PR. The bug existed for roughly four hours, all of them on a branch.

Green tests are not done

Eleven passing tests, a green build, a satisfied Stop hook — and a live data-mangling bug. The author's tests prove what the author thought to test. That is why the author is never the only approver, human or agent, and why the grader reads the spec rather than the test suite.

06

Three stories, three fates — decided by tier and clarity, not mood

The tier sets the climb, not the mood

The same triage produced a bounce, a MEDIUM, and a HIGH — and each fate was decided mechanically. Neither ready spec was over- or under-checked; the tier on the spec set the climb, and the vague-line test decided whether a story became a spec at all.

The one that bounced

"Show adjusters similar past claims" never reached an agent. Nobody can write an acceptance check for "similar," so nobody can build it. It went back to Luis for sharpening; the agents never saw it. A bounce at triage costs a conversation; the same vagueness found at the PR costs a redo.

The two that cleared, at different depths
Spec 0015 — fast-path queue — MEDIUM
New business logic, nothing hard to undo. The climb: grader plus one non-author Checker, cleared in a day. Jonah authored it, Sara checked it, deploy-dev shipped it. Accepted as-is.
Spec 0016 — duplicate-claim merge — HIGH
Merging claim records is hard to undo and touches policyholder data. The full ladder: tight permissions, the security-reviewer pass, and Wes's named sign-off.
Why both specs got one agent, not many

Each of the week's specs wrote into shared code — the work-queue service, the intake matching service — so each got exactly one agent, start to finish. Nothing here was independent enough to fan out; parallel agents in the same files clobber each other. Fanning out would have been faster to start and slower to finish, once the conflicts surfaced. Spread out to explore; line up to commit.

07

What the pod read Friday — and what the client saw instead

One change, and the client sees outcomes — never activity

The loop's numbers are baseline-and-trend, no vanity targets. What the pod's internal dashboard showed Friday:

NumberThis weekRead as
Accepted-as-is11 of 14 specs (79%)Trust rising — intent and bounds are working
Review wait (median)0.9 daysUnder the one-working-day tripwire; no stop triggered
Security-review wait (median)2.1 daysDrifting up — flagged at Retro+, Maya owns it with Dan
Bounce-backs at triage1 ("similar claims")The cheap place caught it
Escaped bugs0 (1 last week: the UTC clock)Last week's answered with a harness change, merged Thursday
WIP5 of 6 capHeadroom held all week

Every number here is computed from loop-events.jsonl by scorecard.py, which refuses to record velocity, story points, PR count, or lines of code, and reads "no data" rather than a fabricated zero. What steering saw instead: the live demo, the outcome clock (instrumented, moves at rollout), the stability and accepted-as-is trends, and the decision list. What steering never sees: PR counts, lines of code, story points, "AI productivity."

The tooling behind the week

Build is the least plugin-driven stretch of the engagement — most days carry no slash command at all. What actually ran, on the claude-code-sdlc plugin, the kit's rails, and the paired skills:

What got producedHow
Flow-check queue numbers/sdlc-status at the daily flow check; the security queue read on its own line
Ready specs (0015, 0016)Triage is humans; /sdlc-spec scaffolds from the kit template (new_spec.py allocates NNNN); the Pod Lead tiers them
Definition-of-Ready check per speccheck_spec.py — mechanical floor + vague-line lint; appends the result to .sdlc/metrics/spec-log.jsonl
Spec 0015 (MEDIUM), end to endRides the loop: plan mode under bounds, Stop hook, ci.yml + grader.yml on the PR, non-author Checker, deploy-dev.yml on merge
Spec 0016 (HIGH), end to endSame loop plus the HIGH path: risk:high label → security.yml → the security-reviewer agent; Wes's named sign-off in the PR
The 0016 catch, given memorygrader.yml posts the check-by-check verdict as a PR comment; record_findings.py appends it (with disposition) to .sdlc/metrics/findings-log.jsonl
The merge event + scorecardscorecard.py record logs spec_merged to .sdlc/metrics/loop-events.jsonl; the biweekly scorecard is computed from it
Harness improvement (timezone checks)Last week's Retro+ answer; the test-writer skill updated by reviewed PR, merged at the setup review (Rob + Jonah)
Steering demo narrative + scorecard visuals/visual-explainer; Gail drives the live demo herself

Those three .sdlc/metrics/*.jsonl receipts are real files this loop writes on every trip — and the narrative docs never name them. All names, numbers, and IDs are invented but internally consistent: the 11.4-day baseline, the spec sequence, and the D-/Q-/C-/ADR- IDs trace back through every earlier phase example.

08

No batch gate — a bar every change clears, and a declaration to leave

The merge bar

The other phases end at a gate: a batch of artifacts, checked once, a human sign-off, advance. The Build loop has no batch artifact gate. Checking does not accumulate to the end — it happens per change, at a merge bar every single change clears. The harness knows this: the loop is the one phase flagged continuous: true, and the gate script says so out loud — "Build is feature-complete by human declaration, not by this count."

That does not mean nothing closes it. Leaving the loop has exactly two conditions, and one of them is a person: a human declares the backlog feature-complete, and phase7-handoff.md exists and is complete. Nothing advances without both.

The bar every change clears
  • CI green — build, tests, lint, 80% coverage on new code
  • The grader has run — required to run, its verdict advisory
  • Correctness passed, or a named-human override recorded
  • A non-author approval — the author never approves their own work, no exceptions; this rule survives every collapse of pod size

A risk:high change adds two more: the security workflow passes, and a named human signs off in the PR. That is the whole of it — there is nothing further to clear at the end of a loop pass, because every pass already cleared this.

How the loop is left

A human declares the backlog feature-complete — every story the engagement committed to has ridden the loop and merged. No checker can make that call, because it is a judgment about scope, not about code. The declaration is what triggers the loop's one required output:

The single required output — written after the declaration, then checked phase7-handoff.md

phase7-handoff.md names what was built, the state of the system in dev, the open questions carried under their original IDs, the deferred items with rationale, and what Documentation must cover. It is the entry package for Phase 7 — and it is checked: advance_phase.py requires it to exist and be free of placeholders, and will not move the engagement forward without --confirmed, a named person's sign-off.

So the distinction is precise. No batch of deliverables piles up to be graded at the end — that is the failure mode this method exists to kill. One handoff document, and a human who says the work is done.

How the harness models this

phase-registry.yaml flags build with continuous: true and describes it in its own words: "there is no artifact exit gate — checking happens per change, and a human declares the backlog feature-complete to leave." Its first exit condition is a check: string rather than an artifact — "Build backlog is feature-complete (human declaration — no batch artifact gate)." phase_model.is_continuous() reads that flag, and check_gates.py branches on it twice: it reports the spec backlog as information only, and states plainly that "Build is feature-complete by human declaration, not by this count."

The mechanism and the method agree, exactly. This is the one place in the whole reconciliation where the harness encodes a human judgment as a human judgment — and refuses to let a count stand in for it.

Why no batch gate? Because a gate batches checking — write everything, then review everything — and batched checking is the exact failure mode this loop exists to kill. When an agent can produce code in minutes, the constraint is never building; it is proving. So the proving moves to per-change, inside the loop, on the bar above — and the moment the pod starts skipping the loop for a "small" change is the moment unchecked work creeps back in.

You've been handed a piece of work and told to run it through the loop. This page is what you actually type, in order, and what you do between the typing.

The loop is not a phase. It has no end date and no exit gate — it repeats, once per change, from the day the Foundation gate closes to the day the backlog is done. One trip takes hours or days, not weeks. Read this once end to end, then run one change through it.

Before you type anything

What you need first

Two of these are software and two are people. The people are the ones that stop you at 4pm on a Friday, so sort them out first.

  • The plugin, installed. If /sdlc-spec isn't in your slash command list, run /plugin marketplace add MCKRUZ/claude-code-sdlc then /plugin install claude-code-sdlc@mckruz.
  • uv installed (the plugin runs its Python scripts through it). pip install uv or brew install uv.
  • The rails, already built and proven. Phase 3 installed them: CI, branch protection, the Stop hook, the deploy. The loop runs on them — you do not build them here. If .claude/hooks/stop-gate.ps1 and .github/workflows/ci.yml aren't in the repo, you're not ready to start.
  • A story that came out of intent triage — with a risk tier a human assigned and one named existing pattern to reuse. A story that hasn't been through triage is a conversation, not work.
  • A second human, lined up. You cannot finish a change alone. Somebody who did not write it has to approve it. Know who that is before you start, not when the pull request is already open and everyone's gone home.
The mistake new people make

Typing the wish straight at the agent — "add rate limiting, go" — and skipping straight to step 3. You'll get something plausible and fast, and the case you never described is the one it gets wrong. It also won't merge: the spec-gate check fails any pull request that touches source code and carries no spec file in its diff.

01

Beat 1: Intent — type this, once per change

Write the spec

You type /sdlc-spec

What happens: the whole Intent beat runs as one command. It scaffolds specs/NNNN-name.md (the script new_spec.py allocates the next four-digit id, so you never pick one), then walks you through the Definition of Ready — the goal, why it matters, what's in scope and out, the acceptance checks, the one existing pattern this change reuses, and any product decision nobody has made yet. Then it proposes a risk tier with one sentence of reasoning and stops to ask you. Last, it runs check_spec.py, which must report READY.

What you do: answer as the person who decided, not the person guessing. Confirm or override the tier — Claude proposes tiers, it never assigns them. Raising a tier needs no permission from anyone; lowering one is a conversation with the Pod Lead, who owns it.

Two flags worth knowing: --repo <path> writes a spec in a repo with no .sdlc/ at all, and --spec <path> validates and finishes a spec that already exists instead of scaffolding a new one.

You now have specs/NNNN-name.md — in the repo, in version control a risk tier, confirmed by a human status: ready

Don't move on until: check_spec.py reads READY. A spec it reports NOT READY does not enter the loop — building from one is exactly the failure this beat exists to prevent.

02

Still Intent — nothing to type, and this is the part that pays

Read your own spec back

You type nothing — ten minutes of your own judgment

check_spec.py checked the shape of the spec: the sections are there, the tier is valid, scope in and out are both filled, no placeholder text is left. It cannot check the meaning. Only you can.

What you do: run the vague-line test on every acceptance check, out loud: "could two people build different things from this line?" If yes, it's a wish, not a check. "Handle errors gracefully" is a wish. "A duplicate submission returns 409 with body { "error": "duplicate claim" }" is a check.

Then the two things beginners leave blank. Scope out — what this change must not touch is as load-bearing as what it must do. And the decision list — every real product choice nobody has answered (fail open or fail closed? what does a blocked user actually see?). An unanswered decision doesn't wait for you. The agent makes it, fast, unsupervised, and you find out what it picked when something breaks.

The lint advises — you decide

check_spec.py reports two kinds of finding: BLOCK, which you must fix, and ADVISE, which is its vague-line lint flagging a line that smells. The lint is a hint, not a verdict — a spec can read READY and still be hopelessly vague. Nothing downstream fixes vague intent. It doesn't get caught later; it gets built, fast, wrong.

If this change is a bug fix: set type: bugfix in the spec's frontmatter and label the pull request type:bugfix later. That label switches on an extra gate in step 5 — leave it off and the gate silently doesn't apply.

03

Beat 2: Delegate — the first of two mandatory human stops

Approve the plan before any code exists

You type git checkout -b spec/NNNN-name

Then, in Claude Code, start the agent in plan mode and point it at the spec file. One spec = one branch = one pull request.

What happens: in plan mode the agent can read the repo and the spec but cannot change a file. It comes back with an approach — which files it will touch, how it will satisfy each acceptance check.

What you do: read the plan hunting for the one decision it glossed over. Not "does this look reasonable" — "what did it quietly decide?" ("What's the counter key when the request has no key?") Correct it, then approve. Correcting a plan costs you a sentence; correcting a finished build costs a redo.

What runs this beat no command — Intent has /sdlc-spec, Delegate is you and the agent
This stop is not optional and nothing enforces it

The spec's Delegation Plan says plan approval is required before any code on MEDIUM and HIGH changes. No hook and no CI check verifies you actually did it — the machinery cannot see the difference between a plan you read and a plan you waved through. The most dangerous decisions in agent-built code are the ones nobody noticed being made, and this is the only moment they're cheap to catch.

04

Still Delegate — the agent works, you watch the right things

Let it build inside the box

You type nothing — the bounds are already written in the spec

What the box is, and it's three things, all set in the spec's Delegation Plan: scope (the file patterns it may touch — everything else is out, and "if something outside this needs changing, stop and ask" is part of the handoff), context (the one canonical pattern to reuse, named — an agent not pointed at the existing pattern will cheerfully invent a second one), and permissions (build, test, lint and reads run freely; installs, network calls, and gated paths like auth or migrations force a human confirm).

What you do: stay out of the keystrokes on the parts that are cheap to undo; stay in the big calls on the parts that are expensive to get wrong. Use one agent. Fan out to explore a question three ways; never fan out to build — parallel agents writing the same files clobber each other.

If this is a bug fix, the order is fixed: the regression test first, proven failing against the broken code, then the fix. Not because it's tidier — because step 5 mechanically checks you did it that way.

The Stop hook is doing work you can't see

stop-gate.ps1 fires every time the agent tries to end its turn. If the build is broken or a test is red, it refuses to let it stop and hands the reason back to the model. That turns "the tests must pass" from a request the agent can rationalise past into a fact about the world. Its limit is worth knowing: it enforces the tests that exist. It cannot enforce a test nobody wrote — that's what the next two steps are for.

05

Beat 3: Discern — type this, then let the machines run

Push, open the pull request, and let CI grind

You type git push -u origin spec/NNNN-name

Then open the pull request and label it from the spec: risk:high if the tier is HIGH, type:bugfix if it's a fix. The labels are not decoration — they're what switches the extra gates on.

What happens: the mechanical gates run and hard-block the merge.

CheckWhat it refuses
build-and-testA broken build, a failing test, a lint error, or new code under the 80% coverage floor
spec-gateA pull request that touches source and carries no spec file in its diff. Recorded escape: the no-spec:chore label, with the reason stated in the description
repro-gateBug fixes only. It rebuilds the code as it was before your fix, drops your new test on top, and runs it. If it passes, your test doesn't reproduce the bug
risk-signoffrisk:high pull requests with no line reading SIGNED-OFF-BY: <name> — <sentence>
spike-guardAny pull request opened from a spike/ branch (see step 10)

What you do: fix what's red and push again. Never suppress a check to go green — skipping a flaky test to get past the gate is the rail lying to you.

Two ways step 5 surprises people

The push gets refused. That's review-gate, a hook that blocks git push and gh pr create until per-commit review receipts exist. Run your review (/code-review and /simplify by default), save the receipt with save-review-receipt, then push. It only fires for pushes made through Claude Code — a human pushing from their own terminal isn't gated at all, which is exactly why the CI checks above exist as well.

repro-gate fails and you don't see why. Coverage proves a test exists. It does not prove the test would have caught the bug. A fix can satisfy the 80% floor with a test that passes before and after — decoration that protects nothing while every gate stays green. There is no label escape on this one: a test that cannot fail cannot protect anything.

06

Still Discern — nothing to type, but read it properly

The grader posts its verdict

You type nothing — the Grader workflow runs on the pull request

What happens: a fresh agent that did not write the code reads the spec out of the diff and posts a check-by-check verdict as a pull request comment. It is required to run — "the grader has run" is a required status check — but its verdict is advisory. It doesn't block. A human reads it and decides.

What you do: read every line of it, especially where it disagrees with you. The grader grades against the spec, not against your tests — which means it is looking for exactly the case you never thought to test. A grader complaint on a check you were sure was covered is the single most valuable thing the loop produces. Fix it, or write down why you didn't.

This is where step 2 gets paid back or punished. Vague acceptance checks give the grader nothing to test against, it returns a shrug, and the bug ships. The grader is only ever as sharp as the spec you wrote.

07

Still Discern — the second mandatory human stop

Someone who isn't you approves it

You type nothing — another person approves in the pull request

The merge bar, which every change clears regardless of size:

  • CI green — build, tests, lint, coverage
  • The grader has run
  • Correctness passed, or a named-human override recorded
  • A non-author approval

A risk:high change adds two more: a security review pass, and a named human sign-off recorded in the pull request as SIGNED-OFF-BY: <name> — <sentence>. The sentence is required, not a formality — a bare name is the thumbs-up this rung exists to reject.

What you do: get a Checker assigned at the daily flow check. You are not eligible — you wrote it.

The author never approves their own work

No exceptions. Not when the pod is down to two people, not when it's a one-line change, not at 6pm on a release day. The agent that wrote the code confirming it works, or you approving your own pull request, is checking theater — it catches nothing you hadn't already thought of. This rule survives every collapse of pod size.

How deep the review goes is set by the tier, not by mood: LOW gets the grader's advisory pass and a light human look, MEDIUM gets grader plus Checker, HIGH goes all the way up. check_spec.py already enforced back at step 1 that the spec's Checking Plan matches its tier — a HIGH spec declaring a LOW climb fails the Definition of Ready.

08

Merge — and the loop starts again

What happens after the merge button

You type gh pr merge

What happens: merge deploys to the client's dev environment automatically — that's the pipeline Phase 3 built, not something you trigger. The spec's status frontmatter moves to merged. Because the spec files are the tracker, track_specs.py derives the backlog straight from them — counts by status and risk, what's in flight, whether the WIP cap has been breached — so there is no separate progress file to drift out of date.

What you do: now, and only now, pick up the next spec. Don't start a new one while one you own is half-built — finishing what's in flight before starting the next is how the loop avoids compounding half-done work across sessions.

Forever after: when this behavior changes later, the spec changes in the same pull request as the code. A spec left rotting is a lie that misleads the next human and the next agent, and the grader will happily grade a future change against it.

There is no gate here, and that's the whole point

You will look for the phase gate. There isn't one. The loop has no artifact exit gate because checking already happened, per change, at steps 5 through 7. The loop ends only when a human declares the backlog feature-complete, which produces phase7-handoff.md. Running /sdlc-gate for this phase checks that one file exists and is complete — it does not re-check the build.

09

Nothing to type — this is a calendar, not a command

The cadences running around the loop

One trip through steps 1–8 is your day. These four meetings are the week they sit inside. None of them asks what you did yesterday — when agents do the building, "the agents wrote a lot" is a number that means nothing.

MeetingLengthWhat actually happens
Flow check (daily)10–15 minThe queue number first: how many changes are waiting to be checked, how long the oldest has waited. Every waiting change gets a Checker named. The WIP cap gets enforced. Vague specs get bounced back to triage. The security queue is read on its own line — it clears slower, and averaged in with the rest it hides.
Intent triage (weekly)60 minStories become ready specs: vague lines sharpened, silent decisions surfaced with named owners, risk tiers assigned, the backlog ordered. This is where the work you'll run through step 1 comes from.
Retro+ (weekly)60 minEvery bug that escaped gets one question — "which check should have caught it?" — and the answer becomes a change to the harness, not a resolution to try harder.
Setup review (weekly)30–60 minThe week's harness changes merge: CLAUDE.md updates, hook and skill improvements, permission tuning — reviewed like any other change.

Two numbers run the week. The WIP cap stops the pod opening more changes than it can check — agents can always write more code; proving it is the constraint. The review-wait tripwire is the alarm on the same constraint: when the median wait crosses the agreed threshold, the pod stops starting new work and clears the queue.

Never tracked, never reported: velocity, story points, pull request count, lines of code. Agents inflate all of them — scorecard.py refuses to record them, which is deliberate.

10

When step 1 is impossible — type this instead

The spike: when nobody knows the answer yet

You type /sdlc-spike

Sometimes a story fails the Definition of Ready not because it's badly written, but because nobody knows. The integration's real behavior is undocumented; the assumption the design rests on has never been tested. You cannot write an acceptance check about something nobody understands.

What happens: it opens spikes/NNNN-name.md and demands two things from a named human it will not invent for you — the box (a time box or a token box) and who opened it. Then you work on a spike/NNNN-name branch. Normal quality bars don't apply; this code is going to be deleted.

What you do: state the unknown precisely before you start — not "look into the carrier API" but "does the carrier API deduplicate on our idempotency key, or do retries create duplicate claims?" Then write the finding, including when the answer is "we still don't know". Recording what you ruled out saves the next attempt. Commit the finding, delete the branch.

Spike code can never merge, and that's mechanical

spike-guard fails any pull request whose head branch matches spike/, and unlike spec-gate there is no label escape. "It started as a spike" is the most natural route by which unchecked code reaches production — spike code has climbed none of the ladder, with no spec to grade against and no Checker. If the work turns out to be worth shipping, you write the spec and rebuild it under the loop.

Don't use a spike to start building without a spec. If the answer is known and the work just feels large, that's a spec — possibly several.

Keep these handy

Commands you'll use constantly

Type thisWhen
/sdlc-specEvery single change, before any code. No spec, no build.
/sdlc-spikeA story can't be made ready because nobody knows the answer yet.
/sdlc-statusAny time you're lost. Shows where the project stands.
/sdlcStart of every work session. Tells you what to do next.
/sdlc-reviewDesign-heavy work, before /sdlc-gate. Multi-perspective review (council, adversarial, or edge-cases) — advisory, doesn't block.
/sdlc-coachYou're stuck and want walking through conversationally instead of following a list.

Rule of thumb for the whole loop: written is cheap, checked is the bar. A change is done when something other than its author has proven it against its spec — not when the code exists. Everything on this page is machinery for that one sentence, and the two human stops (step 3 and step 7) are the parts no machine can do for you.

01

Reference · The Build Loop

If checking waits, it piles up — and a pile never gets checked

The gated phases open the engagement (0–3) and close it (7–9, C). Everything in between — typically 8 to 16 weeks, the bulk of the engagement — runs as this loop. There is no exit gate at the end of a loop pass; the loop is how every change gets built, from the day the Foundation gate closes to the day the backlog is done. It has no batch artifact gate — it has a merge bar that every change clears, and it is left when a human declares the backlog feature-complete.

The precise mechanics — the three beats in full, the Definition of Ready, the risk taxonomy, the checking ladder, the cadences, and the metrics. The full prose method sits under each section's “Go deeper” on the How it works tab; for the complete Harbor week with every ID and verdict, see Example.

02

The whole loop in one picture

Three beats, every time: Intent → Delegate → Discern

  1. Intent — decide what you want, clearly enough to check, and write it down as a spec.
  2. Delegate — an agent builds it, inside bounds a human set, from a plan a human approved.
  3. Discern — checks and a non-author prove it before anyone trusts it; merge deploys it.

Run for every change, large or small. Skipping the loop for "small" changes is the moment unchecked work creeps back in — small and risky is the cheap-to-type, expensive-to-get-wrong case.

Who is involved — our side

PersonLoadIn the loop
Pod Lead50–70%Owns triage: stories become ready specs, risk tiers assigned, the WIP cap holds. Routes decision-list items to the client. Runs cadences and steering. First escalation when the queue grows.
Orchestrators90–100%Run the loop all day: author specs, set bounds, approve plans, drive agents, and check each other's changes. The craft is in the bounds and the checking, not the keystrokes.
Quality Engineer60–80%Owns the checking: the checking plan per spec, the rails' health, the escaped-bug answer at every retro, the scheduled hardening passes.
Setup Owner30–50%Keeps the harness a product through Build: CLAUDE.md current, skills and hooks improved by reviewed PR, the deputy reviewing every harness change, token spend watched.

Client side

PersonNeeded forHow much
Product OwnerThe decision list — every silent product decision gets their named answer on the agreed clock; acceptance of what demos showSteady weekly hours, agreed in the SOW
Domain expertsPulled into intent when a spec touches their ground truthAs specs demand
SecurityThe named sign-off on every HIGH-risk change; their queue tracked separatelyPer HIGH change
SponsorThe biweekly steering: a live demo and the outcome scorecard, not activity reports45 minutes biweekly

Claude's role in the loop

Claude does most of the building and much of the checking — but never both on the same change.

  • Builds, bounded. From an approved plan, inside the scope, context, and permissions set per spec. The Stop hook means it cannot call its own work finished with a red test or a broken build.
  • Grades, as a separate agent. The grader is a fresh agent that did not write the change, told so plainly, grading check-by-check against the spec.
  • Drafts the connective tissue. Candidate specs from triaged stories, test suites from acceptance checks, the weekly client summary from merged work. Humans correct and own all of it.

What Claude never does: merge, approve its own work, assign a risk tier, answer a decision-list item, or downgrade a risk challenge. Risk escalates up without discussion; lowering a tier always takes a conversation with the Pod Lead.

03

Beat one — Intent

Nothing enters the loop as a conversation

A story becomes buildable only by clearing this bar at weekly intent triage:

  • Every acceptance criterion passes the vague-line test — "could two people build different things from this line?" "Handle errors gracefully" is a wish; "a duplicate submission returns 409 with a specific error body" is a check.
  • Scope in and scope out are both stated. What the change must not touch is as load-bearing as what it must do.
  • The silent decisions are answered — fail open or fail closed? what does a blocked user see? An unwritten product choice gets made by the agent, fast, unsupervised.
  • A risk tier is assigned by the Pod Lead and recorded in the spec.
  • The harness context is named — which existing pattern this change reuses.

The Orchestrator then writes the spec — one file in the repo: Goal, Why, Scope in/out, Acceptance checks, Risk tier, Delegation plan, Checking plan. When behavior changes later, the spec changes in the same PR — a stale spec is a lie that misleads the next reader and the next agent.

04

Still in Intent — how much rigor

Not every change deserves the same scrutiny

The tier lives in the harness so agents see it too.

TierWhat lands hereWhat it triggers
HIGHAuth/identity, payments, personal or client data handling, schema migrations, public API contract changes, infrastructure and pipeline changes, AI-behavior changes (prompts, models, tool definitions), anything hard to undoTight agent permissions, the full checking ladder, a security review pass, a named human sign-off in the PR
MEDIUMNew business logic, external integrations, changes to shared internal servicesStandard permissions, grader plus a human Checker
LOWUI within existing patterns, copy, internal tooling, additive CRUD on established railsLighter review; the grader and the mechanical gates still run
05

Beat two — Delegate

Draw the box, approve the plan — then let it build

The agent starts in plan mode — it reads the repo and proposes an approach before it may write anything. A human approves the plan first, looking for the one decision it glosses. Three bounds are set per spec:

BoundWhat it fixes
ScopeThe file patterns the change may touch. Everything else is out, and "if something outside this needs to change, stop and ask" is part of the handoff.
ContextThe one canonical pattern to reuse, named explicitly — or the agent invents a second way to do what the codebase already does.
PermissionsWhat the agent may do without asking. Safe commands (build, test, lint, reads) auto-allow; package installs, network calls, and gated paths force a human confirm.

Freedom by risk, within one change: loose leash on the cheap-to-undo parts, tight leash on the expensive-to-get-wrong parts. The box is enforced, not requested — the Stop hook refuses to let the agent finish with failing tests or a broken build.

06

Still in Delegate — one agent or many

Spread out to explore; line up to commit

Fan out to explore: independent investigations (three candidate approaches, each written up by its own agent) run in parallel because they touch nothing shared. Single-thread to build: one feature writing into shared code gets exactly one agent, start to finish, because parallel agents in the same files clobber each other. The test: are the pieces independent (fan out) or tangled (single-thread)? Spread out to explore, line up to commit.

07

Beat three — Discern

The author never checks their own work

Five rungs, each catching what the one below cannot. The risk tier sets how high a change climbs.

RungThe checkWhat it catches that the rung below can't
1The done-rule in the harnessSets the bar ("done means checked, not typed"); persuasion only — it enforces nothing by itself
2The agent re-checks each turnThe agent's own mechanical slips: the broken import, the test it broke two steps back
3The blocking Stop hookThe agent declaring itself done anyway — it cannot finish with red tests or a broken build. But it enforces only the tests that exist
4The separate graderThe hole the author was blind to: it grades check-by-check against the spec, not the tests, so it catches the case the author never thought to test
5The human / security gateThe judgment calls no machine should own: the risk acceptance, the product call, the security sign-off on a HIGH change

In the rails, the ladder lands as three layers on every PR:

  • Mechanical gates in CI (hard blocks): build, tests, lint, 80% coverage on new code.
  • The grader in CI (required to run, advisory verdict): a fresh agent reads the spec in the diff and posts a check-by-check verdict as a PR comment. It cannot be skipped — "the grader has run" is a required status check — but its verdict does not block. A failed check goes back to the same Orchestrator, who fixes it on the same branch; every gate re-runs on the updated PR before merge.
  • The human Checker (hard block): non-author approval on every PR. On HIGH risk, also a security review pass and a named human sign-off recorded in the PR.

You don't run every change up all five rungs — that recreates the bottleneck the loop exists to remove. LOW stops after the grader's advisory pass and a light human look; MEDIUM gets grader-plus-Checker; HIGH goes all the way up. Merge deploys to the client's dev environment automatically. A true emergency merge past a gate requires the Pod Lead plus one other human, an exception label, and a retro item. Two exceptions in a month means the gate or the specs are wrong.

08

The beats as a sequence

Spec 0016, beat by beat

One HIGH-risk change run end to end, as it appears in the rails:

BeatStepWhat runs
IntentMake ready & specVague-line test, scope in/out, the silent decision routed to the decision list on the client clock; the Orchestrator writes the spec — goal, five testable checks, risk tier, delegation & checking plans.
DelegateBound & planThree bounds (scope, context, permissions) and two leashes; plan mode corrects the one decision the plan glosses before a line is written.
DelegateBuildThe agent builds inside the box; the Stop hook holds it to a green suite; CI goes green — but a green suite can still hide a live bug.
DiscernGradeThe grader, told it did not write the code, grades check-by-check against the spec and posts a PR-comment verdict for the human Checker.
DiscernHIGH gateFix re-graded clean; the security-reviewer agent passes the data path; a named human signs off; a non-author checks and merges.
DiscernMergeMerge fires the deploy pipeline; the change lands in dev automatically, with no manual step.
09

What keeps the loop honest

Four short meetings — and two numbers that run the week

MeetingLengthReplacesWhat it does
Flow check (daily)10–15 minstandupThe queue number first: how many changes wait for checking, how long the oldest waited. Walk the in-flight work nearest-done first; every waiting change gets a Checker; vague specs flagged back to triage; the WIP cap enforced; one commitment each.
Intent triage60 minrefinementStories become ready specs: vague lines sharpened, silent decisions surfaced onto the decision list, risk tiers assigned, the backlog ordered.
Retro+60 minretroEvery escaped bug gets the same question — "which check should have caught it?" — and the answer becomes a harness improvement, not a resolution to try harder.
Setup review30–60 min(new)The week's harness changes merge: CLAUDE.md updates, skill and hook improvements, permission tuning — versioned, PR'd, reviewed by the Setup Owner's deputy.

Two numbers run the week. The WIP cap keeps the pod from opening more changes than its checking capacity can clear. The review-wait tripwire is the alarm on the same constraint: when the median wait crosses the agreed threshold, the pod stops starting new work and clears the queue. The security queue is read separately at every flow check — it clears slower, and averaged in with the rest it hides until something HIGH has quietly waited a week.

The client's view

RhythmWhat the client sees
Biweekly steering (45 min)A live demo in the dev environment, the outcome scorecard (their success metric, the delivery-stability trend, the accepted-as-is trend), the decision list needing answers, and gate status when a phase boundary is near.
Weekly five-bullet async summaryWritten for a busy reader: what shipped, what's next, what we need from you. Claude drafts it from merged work; the Pod Lead corrects and sends.
Never, everNo PR counts, no "AI productivity" claims. Agents inflate every activity number; demos and outcomes don't lie.
10

Two disciplines, the numbers, and what goes wrong

One spec, one change — and the client sees outcomes, never activity

One spec is one branch is one pull request. A small change is cheap to read, grade, and revert. The internal dashboard is baseline-and-trend, no vanity targets:

  • Accepted-as-is rate — agent work merged without rework. The trust signal: rising means intent and bounds are working.
  • Review wait (median) — the real bottleneck indicator. If it grows, stop opening streams; more building throughput cannot fix a checking constraint.
  • Rework / revert rate and bounce-back-for-unclear rate — intent quality signals. A spec that bounces as unbuildable is a triage miss, not an agent failure.
  • Escaped bugs — every one answered at Retro+ with "which check should have caught it?"
  • The DORA four — deploy frequency, lead time, change-fail rate, time-to-recover, watched as trends.
  • Security-review wait — on its own line, always.

Never tracked, never reported: velocity, story points, PR count, lines of code. Agents inflate all of them, and the published research backs the caution — measured teams doubled PR volume while actual delivery stayed flat.

Hardening passes

Quality in the loop is per-change; some concerns only exist at the integration level — performance under load, end-to-end journeys across many features, penetration testing. The Quality Engineer plans and runs them as scheduled hardening passes — typically one mid-Build and one before deployment prep — using the end-to-end and security tooling. The first pass is also where the test environment gets added alongside dev. Hardening is scheduled work inside the flow, not a phase that gates everything else.

What goes wrong in the loop

  • Skipping Intent. Typing the wish straight to the agent ("add rate limiting, go"). The agent builds something plausible and fast, and the undescribed case is the one it gets wrong. Everything enters through a ready spec.
  • The author grading itself. Checking theater — it catches nothing the author didn't already think of. Author never approves, no exceptions.
  • One review depth for everything. Gating every typo recreates the bottleneck; waving auth changes through ships the incident. The tier sets the climb.
  • "Too small to bother." The loop skipped for small changes. Small and risky is the expensive case; the discipline is the same at forty lines as at four hundred.
  • The unbounded handoff. No scope, no named pattern, no permissions — the agent fills every gap with a guess and touches three things nobody wanted touched.
  • Fanning out a build. Parallel agents writing the same files clobber each other. Fan out only to explore; one agent writes shared code.
  • The rotting spec. Behavior changes, the spec doesn't, and the source of truth lies to the next agent and human. The spec changes in the same PR as the behavior.
  • A hook that passes by hiding the failure. Skipping the flaky test to go green is the rail lying to you. Fix the cause; never suppress the check.
  • Ignoring the queue number. Review wait creeps up, everyone keeps starting work, and the loop silts up until nothing merges. The tripwire makes stopping automatic, not heroic.
  • Quiet gate exceptions. Emergency merges that stop being emergencies. Two in a month means the gate or the specs are wrong — fix the system, don't normalize the bypass.