Home / Projects / Orchestrata Ultimate / Decisions / ADR index / ADR-0002
ADR-0002: Factory gates fail closed; interactive sessions stay fail-open
| field | value |
|---|---|
| Status | Accepted |
| Date | 2026-07-23 |
| Register | factory (docs/adr, 4-digit ids) |
| Source | docs/adr/0002-factory-gates-fail-closed.md — permalink at bdafa201a (unchanged on master since that commit) |
| Wiki register entry | ADR-0002 (wiki status: Accepted) |
The record
- Status: Accepted
- Date: 2026-07-23
- Spec: SPEC-033 §3, §7
Context
The shipping gate (scripts/claude_governance_gate.py) fails open on every error path — malformed
stdin, interceptor exception — by documented design: "a broken plumbing seam must never wedge a live
Claude Code session." That is the correct policy for an interactive session with a human present.
It is the catastrophically wrong policy for an autonomous factory: any transient fault in the fact/graph/Prolog stack silently disables governance for that call, and nothing signals it. A security control that degrades to "allow" precisely under stress is not a control.
Decision
Two explicit modes.
- Interactive mode — fail open (unchanged; preserves the human-present UX rationale).
- Factory mode — fail closed: a gate error is a red gate; the work parks and escalates. Never "allow on error."
The mode is part of the run's identity, not a per-call heuristic.
Alternatives rejected
- Fail open everywhere — the status quo; disables governance under fault.
- Fail closed everywhere — would wedge interactive sessions on any plumbing flake, for no governance benefit when a human is watching.
- Retry-then-open — indistinguishable from fail-open to an adversary who can induce faults.
Consequences
- Introduces a real liveness obligation: a single graph blip could park the factory. Requires distinguishing transient fault (park-and-retry) from real red (escalate) — see ADR-0019.
- Makes the fact store a liveness SPOF; accepted deliberately, with the failure direction chosen to be "halt", never "open".
- Fail-closed is not a free config flip: the existing code's fail-open is load-bearing for its current context, so factory mode is a distinct execution path, not a flag on the same path.
Provenance
Round-1 review (all reviewers, code-verified the documented fail-open). Round-2 Fable made the interactive/factory split the first of its four must-fixes. Round-3 Opus flagged the unaddressed liveness cost, resolved in ADR-0019.
Related ADRs
Rulings cited
None.