---
name: build-loop
description: "Drive a captured goal to 100% completion through a bounded implement-verify loop with hard caps and halt-on-ambiguity. Use when the user says loop until done, keep building, autonomous build, drive to completion, don't stop until it's done. Requires .lovable/goal.json. Not for defining the goal or acceptance criteria: run goal-capture first."
license: MIT
metadata:
  author: TechTide AI (Alex Cinovoj)
  provenance: original
  category: Agent Ops & Meta
---

# build-loop

Drive an explicit, verifiable goal to completion, one criterion per iteration, with external verification and hard budgets. The loop never decides what done means: goal-capture did that. The loop only implements, verifies, and halts honestly.

## Preconditions

1. `.lovable/goal.json` exists and matches the schema in the goal-capture skill (see its references/goal-schema.md). If missing, run goal-capture first. Never infer the goal.
2. Every criterion has a `roadmap_id` pointing at an existing roadmap item.
3. The user explicitly asked the loop to run. Never auto-trigger.

## Step 0: Preview and confirm (mandatory)

Never enter the loop cold. Read `.lovable/goal.json` and print a compact summary: the one-sentence goal, numbered criteria (id, description, verify clause, current passes, attempts used), non-goals, guardrails (`do_not_touch`, `ask_before`), and budget (`max_iterations`, `max_attempts_per_criterion`, `ask_on_ambiguity`).

Then ask one confirmation question with three options: **Start loop**, **Edit goal** (hand back to goal-capture, then re-preview), **Cancel** (halt, zero iterations). Do not iterate until the user picks Start loop. Re-run this step any time the goal changes mid-loop.

## The loop

```text
read .lovable/goal.json
loop:
  if every criterion passes === true:            STOP, declare done
  if iteration_count >= budget.max_iterations:   HALT, summarize remaining, ask user
  pick next = lowest-priority-number criterion where passes === false
  if next.attempts >= budget.max_attempts_per_criterion: HALT, surface failure, ask user
  set roadmap[next.roadmap_id].status = in_progress
  smoke-test current build (catch regressions before blaming this iteration)
  implement ONE criterion (small, reversible edits)
  verify END-TO-END against next.verify, as written
  if pass:
      set passes = true in goal.json
      set roadmap status = done
      write iteration log
  else:
      increment next.attempts
      write one-line reflexion to next.last_failure (what failed + what to try next)
      if attempts >= max: HALT, ask user
  loop
```

## Hard rules

- **Verification is external to the implementer's claim.** Run the `verify` clause exactly as written. "I checked, it works" is not acceptance.
- **One criterion per iteration.** Never batch. Iterations are the unit of reflection.
- **Roadmap mirrors goal.json in the same turn.** Never let them drift.
- **Reversibility.** Small edits the user can undo between iterations. Never bundle unrelated changes.
- **No acceptance-loosening.** If a criterion fails, fix the code or halt. Never rewrite `verify` to be more permissive. Never delete tests.
- **Honor workspace gates.** rls-security-gate, money-path-halt-go, supabase-schema-discipline, and any other active gate skills stay in force inside the loop.
- **Reflexion before retry.** Write `last_failure` before retrying, it prevents oscillating between two wrong fixes.
- **The loop only writes `passes`, `attempts`, `last_failure`.** Goal and criteria text belong to goal-capture.

## Stop conditions

| Condition | Action |
|---|---|
| All criteria pass | STOP, announce, suggest publish |
| Iteration budget exhausted | HALT, ask whether to extend |
| One criterion failed max attempts | HALT, surface the failure trace |
| Destructive action needed (drop column, rotate secret, paid API) | HALT, ask user |
| Criterion meaning ambiguous | HALT, ask with concrete options |
| A workspace gate fires | HALT, defer to that skill |
| User picks Cancel at preview | STOP, zero iterations |

## What to surface

Loop start: goal, criteria count, budget. Each iteration: one line (criterion, pass/fail, attempts left). Halt: which condition fired and what decision is needed. Completion: criteria with evidence, publish suggestion. Keep chatter tight, the loop's log is its own output.

## Good vs bad

Bad: criterion "checkout completes" fails twice, so the loop edits `verify` from "end-to-end purchase succeeds" to "checkout page renders" and marks it passed.

Good: after the second failure, `last_failure` reads "webhook signature mismatch, try raw-body middleware next", attempt 3 fixes the middleware, the original verify clause passes end-to-end.

## Verification

After any iteration marks a criterion passed, re-run its `verify` clause from a clean state (fresh page load or fresh session). Expect the same pass. If it fails clean, the pass was environmental: revert `passes` to false, increment attempts, log the reflexion.

## Completion checklist

- [ ] Step 0 preview shown and user picked Start loop before iteration 1
- [ ] Every passed criterion verified by running its verify clause, not by claim
- [ ] goal.json and roadmap in sync at every transition
- [ ] No verify clause weakened, no test deleted, at any point
- [ ] Every failure has a last_failure reflexion line
- [ ] Halt reasons reported honestly with the pending decision

Any box unchecked: not done. Fix or say so.

## Footguns

- **Entering the loop without preview.** The user discovers a wrong goal 8 iterations in. Fix: Step 0 is unskippable.
- **Batching two criteria "because they're related".** A joint failure is undebuggable. Fix: one per iteration, always.
- **Retrying without reflexion.** The loop ping-pongs between the same two wrong fixes. Fix: write last_failure first.
- **Counting a smoke-test regression against the current criterion.** Fix: smoke-test before implementing, so regressions are attributed to the past.

## Red flags

Halt if you catch yourself saying:

- "The verify clause is stricter than it needs to be"
- "This basically passes"
- "I'll mark it done and circle back"
- "These two criteria are really one change"
- "The user probably meant something looser"

Every one of these is acceptance-loosening in disguise. The clause runs as written or the loop halts and asks.
