Every decision a fleet hits is classified before anyone answers. Governance is below the model: policy is enforced, not requested.
- Worker gate: a worker's blocking
ask→decision_gatemessage. Times out (~10 min), re-asks under a NEW id. Answer the CURRENT id withreply --id <msg_id> --body "<answer>". On CLI fleets this often writes nodecision_gatestable row — reply by message id. - DAG gate: coordinator
gate-create --task <id> --question "<text>"(both flags required) → auto-blocks the task;gate-resolveinjects the resolution into the task's next dispatch preamble.
- Live worker
ask: the worker CLI blocks until reply/timeout; the task usually staysdispatched(notblocked). An ask with no thread reply while the unit is still dispatched is always current inbox work — reply by message id immediately. Do not wait for task statusblocked. Do not use the unread bit alone (checkmarks read on receive). - Historical unanswered ask: unit already terminal, no waiting worker — retained evidence that no answer was stored, not a reason to stall the fleet.
gate-create: task isblockeduntil resolve — true DAG hold.
Recorded gate lifecycle (pending / resolved / unanswered) is not the same as "the coordinator must act now." Full DAG context: orca-dag-semantics.md.
| Class | Test | Resolver |
|---|---|---|
| Mechanical | one defensible answer (tooling with a repo precedent, naming, retry-on-transient) | coordinator auto-resolves; append the DECISIONS log (ledger-contract.md) |
| Taste | reasonable disagreement, reversible (API shape, copy, structure within spec) | pick recommendation (or Lane B); log DECISIONS; human may veto |
| One-way | hard/impossible to reverse or out-of-authority: merge to default, deploy, rollback, deletion, spend, scope change, secret rotation, real credentials | HUMAN ONLY. Never auto-resolved. Never defaulted on timeout. |
| Lane | When | Action |
|---|---|---|
| A — implement | Safe to ship on testnet/fixtures; reversible code | Full PR-per-unit pipeline |
| B — draft-and-gate | Genuine product/brand/policy fork (two defensible directions) | Draft both options fully; stop at a one-way human gate; do not pick silently |
| 0 — refuse-and-surface | Credential provisioning, live money/prod, engine boundary the fleet must not cross | Do not implement; record OPS/Lane-0 item (CODE_CLOSED only if code landed and verify is OPS — ledger-contract.md) |
When build-change.md's irreversibility stop-list applies, classification happens before
code: the PLAN artifact is the decision surface. Approving "proceed as planned" on reversible
testnet/fixtures → Lane A (mechanical/taste as usual). Approving a hard-to-reverse path →
one-way human. Rejecting → Lane 0 or rewrite the plan. Coding before the gate resolves is a
protocol breach — park the unit and re-dispatch.
When the fleet's analysis concludes the USER's stated direction should change, that is never auto-decided. The user's direction is the default; the fleet must make the case for change, name its blind spots, and the cost if wrong. This is gstack's User-Challenge, adopted verbatim.
ask is agent-to-agent (worker→coordinator); a terminal handle is not a human. To reach a human:
- interactive session → put the decision to them in-session; record the answer.
- unattended → PARK: ledger HUMAN-queue line +
gate-createhold; the run continues elsewhere or winds down. NEVER label an agent-to-agent message as human approval.
One-way doors override any never-ask preference. The --admin merge and BASE→default promotion are
one-way: they require a recorded human grant, always.