Human Gates
A human gate is a scoped owner decision that the orchestrator must collect before a destructive or external step. The gate has:
- A scope — what kind of decision (e.g.,
MERGE_APPROVAL). - A reason — human-readable why.
- An approver — non-agent human display name.
- A source — the external channel that delivered the approval.
- A note — bounded justification.
- A subject binding — the exact
subject_shathe gate authorizes against.
The gate is fail-closed: missing or ambiguous provenance rejects the decision.
Scopes
Defined in scripts/goal-runner/scoped_owner_gate.py:
| Scope | Used for | Allowed sources |
|---|---|---|
MERGE_APPROVAL | PR review authorization | github-review-approval, signed-ticket |
TAG_APPROVAL | Git tag authorization | github-review-approval, signed-ticket |
RELEASE_APPROVAL | Release authorization | github-review-approval, signed-ticket |
PHASE_00_RESUME_APPROVAL | Resuming PHASE_00 after pause | github-review-approval, signed-ticket |
PRODUCTION_PROMOTION | Production promotion | github-review-approval, signed-ticket |
PAID_MODEL_DISPATCH_APPROVAL | Dispatch to a paid provider | owner-cli, signed-ticket, github-review-approval |
Allowed sources
EXTERNAL_HUMAN_SOURCES = {github-review-approval, owner-cli, signed-ticket}
owner-cli is intentionally excluded from MERGE_APPROVAL, TAG_APPROVAL, RELEASE_APPROVAL, PHASE_00_RESUME_APPROVAL, and PRODUCTION_PROMOTION. Those high-stakes decisions require an external human channel (GitHub review or signed ticket). PAID_MODEL_DISPATCH_APPROVAL is the only scope where owner-cli is allowed.
Subject binding
Every high-stakes gate records the exact subject_sha it authorizes against. If the runtime later observes a different SHA, the gate is stale and is not consumed. This is enforced by the is_exact_sha predicate in audit_integrity.py and by the orchestrator's pre-dispatch check.
Consumption
Each gate has dispatches_used and max_dispatches. A MERGE_APPROVAL is single-use (max_dispatches = 1). After consumption, the gate transitions to APPROVED and is no longer in the open list. Replaying a consumed gate fails closed.
What does NOT constitute an approval
- A chat message saying "approved" — not a gate.
- A
gh pr review --approveCLI invocation that the orchestrator did not see — not a gate. - A signed ticket whose
subject_shadoes not match the current HEAD — not a gate. - An agent-role identity string in the
approverfield — rejected at write time.
See Human Gates for the full operator-facing reference.