open_decision
Open a new dated decision doc in the target repo’s docs/decisions/. Creates a PR adding a single file conforming to the repo’s decision-doc template. The doc is opened in ‘open’ status with sign-off block awaiting human countersign.
Upholds: MR-4 · MR-7
Side effects: Creates a branch petrova/open-decision/
Constraints
Section titled “Constraints”REPO_IN_REGISTRY— target_repo must appear in registry.yaml.SLUG_KEBAB_LOWERCASE_LE6_WORDS— slug must match ^[a-z0-9]+(-[a-z0-9]+){0,5}$ — kebab-case, lowercase, ≤6 hyphen-delimited segments.DATE_MATCHES_TODAY— date must be the current UTC date at execution time. Backdating decision docs is forbidden by MR-4 / MR-7.ALTERNATIVES_GE_2— alternatives_considered array must contain ≥2 entries (decision-doc convention).FILE_DOES_NOT_EXIST— target path docs/decisions/- .md must not already exist in target_repo’s default_branch. SUPERSEDES_RESOLVES— If supersedes is non-empty, every path listed must exist in target_repo and reference a closed or superseded decision doc.
Input shape
Section titled “Input shape”titlestring(required)slugstring(required)date→IsoDate(required)supersedesarraycontextstring(required)decisionstring(required)alternatives_consideredarray(required)- items:
namestring(required)rejection_reasonstring(required)
- items:
consequencesobjectcodearraydocsarrayphasesarrayinvariantsarray
referencesarraystatusstringenum:open,closed— Almost always ‘open’ at creation time. ‘closed’ only allowed when caller has the human countersign already and includes it in sign_off.sign_offobjectsubagentstringhumanstring
Output shape
Section titled “Output shape”decision_doc_pathstringpr→PRRefdiff_preview→DiffPreview
Example
Section titled “Example”Input:
{ "envelope": { "verb": "open_decision", "target_repo": "kahn-hq", "idempotency_key": "a3f29c4b1e8d76024b5a8c7f1e2d3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f", "dry_run": true, "actor": "human:alex@devarno.com", "triggered_by": { "kind": "phase_close", "ref": "Phase-7" } }, "params": { "title": "Phase 7 close-out", "slug": "phase-7-close", "date": "2026-04-29", "context": "Phase 7 (SPA consumer-readiness) implementation closed 2026-04-28; this doc records the close-out classification of friction surfaced in M7.8.1.", "decision": "Phase 7 closes with M7.8.2 (operator-driven re-probe) deferred to Phase 8. Five hot gaps delivered; cold/n-a gaps stay candidate.", "alternatives_considered": [ { "name": "Extend Phase 7 to absorb M7.8.2 friction", "rejection_reason": "Violates MR-2 — friction surfaced in a phase becomes the next phase's input, not a retrofit." }, { "name": "Close Phase 7 without verification round", "rejection_reason": "Violates MR-10 — verification round is mandatory at phase close." } ], "consequences": { "phases": [ "Phase 7 closed", "Phase 8 opens with M7.8.2 input" ], "invariants": [] } }}Output (output_dry_run):
{ "envelope": { "verb": "open_decision", "status": "dry_run", "idempotency_key": "a3f29c4b1e8d76024b5a8c7f1e2d3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f", "mr_citations": [ "MR-4", "MR-7" ] }, "result": { "decision_doc_path": "docs/decisions/2026-04-29-phase-7-close.md", "diff_preview": { "files": [ { "path": "docs/decisions/2026-04-29-phase-7-close.md", "operation": "create", "size_bytes": 1842 } ], "branch": "petrova/open-decision/phase-7-close", "commit_message": "decision: phase-7-close (idempotency: a3f29c4b1e8d7602)" } }}Recipe
Section titled “Recipe”Schema: spec/verbs/open_decision.schema.json
Upholds: MR-4 (ISO dates), MR-7 (append-only).
Emits: PR adding docs/decisions/<today>-<slug>.md to target repo.
When to use
Section titled “When to use”- Recording any architectural call, scope change, supersession, or
phase transition’s decision portion (paired with
start_phase/close_phasefor those). - Any change that needs a paper trail beyond a commit message.
Required params
Section titled “Required params”{ "title": "<Imperative phrasing of the decision>", "slug": "<kebab-case-le-6-words>", "context": "<What surfaced the decision. Cite the trigger.>", "decision": "<What was decided. One paragraph.>", "alternatives_considered": [ {"name": "<alt-1>", "rejection_reason": "<one sentence>"}, {"name": "<alt-2>", "rejection_reason": "<one sentence>"} ]}Optional:
consequences:{ code: [], docs: [], phases: [], invariants: [] }references:[ "<doc path or external URL>" ]supersedes:[ "<docs/decisions/YYYY-MM-DD-old-slug.md>" ]sign_off:{ subagent, human }— usually defer; doc opens inopenstatus.
Constraints (verb will fail if violated)
Section titled “Constraints (verb will fail if violated)”slugmust match^[a-z0-9]+(-[a-z0-9]+){0,5}$.alternatives_consideredlength ≥ 2.date(auto-derived) must be today’s UTC date.docs/decisions/<date>-<slug>.mdmust not exist on default branch (live check on apply).
Worked dry-run
Section titled “Worked dry-run”cat > /tmp/petrova-input.json <<'JSON'{ "title": "Switch RLS enforcement to Postgres policies", "slug": "rls-via-postgres-policies", "context": "RLS via app-layer middleware drifts from auth tables; 2026-04-29 finding 20260429-1100-rls-drift.md surfaced 3 missed checks.", "decision": "Move RLS enforcement to Postgres policies on a per-tenant basis. Middleware retains read-only audit trail.", "alternatives_considered": [ {"name": "Status quo (middleware-only RLS)", "rejection_reason": "Drift incidents already in production."}, {"name": "Reverse: drop middleware, policies-only", "rejection_reason": "Loses audit trail useful for incident review."} ], "consequences": { "code": ["backend/auth/middleware.ts simplifies to read-only", "migrations 0042-0045 add policies"], "docs": ["docs/decisions/2026-04-29-rls-via-postgres-policies.md (this doc)"] }}JSONpetrova open_decision kahn-hq --input /tmp/petrova-input.jsonOn apply
Section titled “On apply”The doc opens in open status with <<pending>> sign-off. Closing the
decision requires the human to countersign — either by editing the file
(creates a follow-up commit on the PR) or by re-invoking
open_decision with status: "closed" + sign_off.human populated.