# Feature: Autopilot Circuit-Breaker

**Pattern**: autopilot runs with zero interaction, which is exactly when a silent failure loop is most expensive  -  an agent can burn a budget re-attempting the same broken fix, or thrash between two phases, with nobody watching. A circuit-breaker converts "keep going no matter what" into "keep going until a defined unsafe condition, then halt and hand back to the user." This is the sanctioned autopilot pause (same class as the Phase 7 channels pause): the run stops, records why, and waits for an explicit `resume`.

**Gated by `prefs.global.autopilotCircuitBreaker`** (default: enabled; thresholds tunable). Halting is always safe, so the breaker itself defaults on. Disable per-run only with an explicit override. Complements, does not replace, the existing autopilot safety rules (build-fail max 3 retries, Phase 4 blocking-finding rework, destructive-op confirmations).

## Trip conditions

Any one trips the breaker. All are evaluated from `agent-state.json` + telemetry, no extra model calls.

| # | Trigger | Detection | Default threshold |
|---|---|---|---|
| 1 | **No-progress stall** | two consecutive phase checkpoints with no forward transition (same `phase` + `step` + `reworkCount`, no new artifact/commit) | 2 checkpoints |
| 2 | **Identical repeated failure** | same normalized build-error signature, or the same Phase 4 finding fingerprint, recurs across consecutive Phase 3 rework cycles | 2 cycles |
| 3 | **Rework storm** | Phase 4 -> Phase 3 rework cycles exceed the cap (distinct from the build-retry cap) | `maxReworkCycles` = 3 |
| 4 | **Cost drift** | cumulative spend crosses the `costBudget` ceiling, or the projected next-phase spend would exceed it, after model-fallback has already downgraded | `costBudget` ceiling |
| 5 | **Merge/rebase conflict** | Phase 6 push blocked by a conflict that requires history reconciliation | any conflict |

Trigger 2 is the key addition over the plain build-retry cap: a build can "fail differently" three times (legitimate iteration) or "fail identically" twice (stuck). Only the identical-failure case is a stall; the retry cap catches the rest.

## Action on trip

1. Set `agent-state.json.circuitBreaker = {tripped: true, trigger: <#>, detail, checkpoint}` and flip `autopilot` handling to paused (the run does not continue unattended).
2. Emit one actionable line per the progress contract: what tripped, the evidence (error signature / cycle count / spend vs ceiling), and the single next action (`resume #N` after a fix, or `kill #N`).
3. Never auto-resolve the underlying cause  -  no force-anything, no conflict auto-merge, no budget self-raise. The breaker hands control back; it does not paper over the problem.
4. `resume #N` clears the tripped flag and continues from the recorded checkpoint. If the same trigger fires again immediately, the breaker re-trips (no silent bypass).

## Why this is the right autopilot exception

Autopilot's contract is "no interaction on the happy path." The circuit-breaker fires only off the happy path, where continuing unattended is the *less* safe choice: repeating a proven-broken action, or spending past a ceiling the user set, is not autonomy, it is a runaway. Halting with a precise reason is cheaper than the tokens (and trust) a silent loop burns.

Inspired by autonomous-loop operators that gate on explicit stop conditions (no-progress, identical-stack-trace repetition, cost drift, conflict blocking), adapted to this pipeline's phase/rework/state model.
