Note 06(GOVERNANCE)

The Escalation Ladder

The hard part of autonomous engineering isn't the happy path — it's what the system does when an agent ships code that doesn't typecheck after a rebase. Most tools have one answer: retry forever, or stall and wait. o8 routes every failed merge down a fixed five-layer ladder, cheap automatic recovery at the bottom, expensive human attention at the top, with a hard ceiling on how much it spends before someone is asked.

01The Failure That Matters(THE WEDGE)

An agent's branch was green when it was written. By the time it merges, main has moved, and the typecheck breaks.

A worker finishes a packet in an isolated worktree. Its branch passed a typecheck when the worker wrote it. But other work has merged in the meantime, so before o8 lands the branch it rebases onto the current main and runs the typecheck again — and this time it fails. A type the worker relied on moved. A signature changed underneath it.

This is the moment that decides whether a fleet is trustworthy. You can't merge it — it's broken. You can't silently drop it — the work is real. And you can't just loop a retry, because a worker that keeps failing the same way will burn money and attention without end. Most tools pick one of those three and live with the consequence. o8 treats the failed merge as a thing that has to go somewhere, and defines exactly where.

A lane never silently stalls. Every failure has a defined next step, and every next step costs more than the one below it.
02The Ladder(FIVE LAYERS)

Cheap and automatic at the bottom. Expensive and human at the top. The lane climbs only as far as it has to.

LayerTriggerWho decidesCost
1Typecheck fails on mergethe systemone worker turn
2Layer 1 also failedsystem → orchestrator$0
3Orchestrator: fix it in placethe orchestratorone cheap steer
4Orchestrator: start overthe orchestratorone fresh worker
5Orchestrator gives upyou$0

The lane climbs from the bottom and stops at the first rung that works. Most failed merges never get past layer 1. The ones that do have already proven they need more than a blind retry, which is exactly when it's worth spending a more expensive kind of attention on them.

03Layer One(AUTO-RERUN)

One automatic retry, and the counter that makes “one” mean one.

When the post-rebase typecheck fails, the system fires a single automatic rerun: it hands the worker the full typecheck output and asks it to fix its own branch. The discipline is in the word single. The retry is capped at one, and the cap is enforced by counting how many auto-retries have already happened since the lane's most recent dispatch— not over all time.

That scoping is the non-obvious bit. If the counter lived on the lane and counted forever, a lane that was reset and re-dispatched would carry stale retry history and refuse a legitimate first attempt. By counting events newer than the last launch, a fresh dispatch always starts the budget over — reset_packetgenuinely resets it — while a single failing run still only ever gets one free retry.

The cost ceiling per failed merge is one extra worker turn. Past that, nothing else automatic happens — the lane asks for a smarter kind of help.
04Layers Two Through Four(ESCALATE)

When the automatic fix fails, the lane stops guessing and hands a decision to the orchestrator.

If layer 1 also fails, the system doesn't try a third time. It moves the lane to awaiting_orchestrator, attaches a structured reason and the full typecheck output as an escalation event, and surfaces it. Now a decision is owed, and the cost of another automatic loop is replaced by the cost of one judgment call.

The orchestrator has two cheaper-to-more-expensive options:

  • Layer 3 — steer the warm session.The worker that wrote the packet still has its full context loaded. The orchestrator can send it a targeted message — “the rebase broke this type, here's the error, fix it where it sits” — reusing that warm thread. One cheap nudge to a model that already understands the change, instead of paying to rebuild all that context from scratch.
  • Layer 4 — fresh redispatch.If steering won't do — the approach was wrong, not just stale — the orchestrator starts a brand-new worker with feedback. A full turn, the most expensive automatic-ish option, reserved for when the diff genuinely needs to be rebuilt.

The order is the point. Steering a warm thread is cheaper and faster than spawning a cold one, so the orchestrator is told to prefer it, and to fall through to a fresh worker only when the session is dead or the diff is fundamentally wrong.

05Layer Five(THE HUMAN)

If the orchestrator can't fix it, it doesn't hide that. It hands you a card that says so.

The top of the ladder is a person. If the orchestrator has tried to steer and to redispatch and the diff is still wrong, it surfaces a card that says, in effect, I tried layers one through four, this one's yours.No silent stall, no infinite spinner — an explicit handoff with the history attached, so you're deciding with the full context instead of discovering a stuck lane an hour later.

The lane states carry the whole story. While the automatic layers run, the lane sits in recovering. On escalation it flips to awaiting_orchestrator. At the top it becomes awaiting_human. A related path, base-moved, handles the case where main advances duringthe approval window — one automatic rebase-and-retry before it, too, bubbles up rather than looping.

06Why It Matters(MOAT)

Autonomy people can live with isn't the absence of failure. It's a failure path with a budget.

Anyone can demo an agent that merges clean code. The thing that makes a fleet safe to leave running is what happens on the bad days — and the honest answer most tools have is “it retries until it works or until you notice.” That's either a runaway bill or a silent stall, and often both.

Recovery here is a budget, not a loop. One automatic turn, then bounded human-or-orchestrator attention, then you. The lane is always somewhere you can name.

The ladder is governance applied to the failure path: the same instinct that puts a human in front of every merge also decides, deliberately and cheaply, what happens when a merge can't land. It's the layer underneath the agents — the part that makes “leave it running” a sentence you can say without flinching.

The five-layer chain is operator-locked — the table and the recovery rules live in CLAUDE.md, and the layer-1 logic in src/lib/lane/worktree-side-merge.ts.

Stampo8 v0.1.431 · commit 099e73ac written 2026-06-22 · updated 2026-06-22CURRENT

This note is a snapshot of how the system worked when it was written. It is not a contract. The substrate moves quickly. If you're modifying any file listed below, please update this page in the same PR or mark it stale so a future reader knows not to trust the numbers.

The roadmap that updates this note is GitHub issues tagged epic-915 on hurttlocker/o8.

diff_against: · src/lib/lane/worktree-side-merge.ts · src/lib/lane/terminal-states.ts · src/lib/orchestrator/scheduling.ts · CLAUDE.md