JJoeven

Reference/Safety

Human approval gates

Approve a digest of tool+args, not a bare id. Mutate never runs on missing/deny/tamper. Stop while waiting.

HUMAN_APPROVAL is a map the model cannot write.

Record

{action_id: {decision: "allow"|"deny", digest: sha256(canonical)}}

Canonical JSON: id, tool, args with sort_keys=True.

execute() outcomes

SituationStatusWorld
no recordneeds_approvalunchanged
denydeniedunchanged
digest mismatchtamperunchanged
allow + matchappliedchanged
unknown toolunknown_toolunchanged

Invariants

  • No mutate without allow + matching digest
  • No auto-allow on sev1
  • Expiry (stale deploy_id / old step)
  • Args still range-checked (replicas 1–10) even if approved
  • Waiting is terminal for this run — write a report, do not spin

Who writes the map

Slack button, UI, or you in a Try it box. Never a tool set_approval.

Dual control

Two allow signatures. Same digest. all(decisions == allow).

Tip:Unit-test the gate with an empty map, a matching allow, and a tampered args object. Three tests, one invariant.