gz adr demote¶
Demote a feature or foundation ADR back to pool — the inverse of gz adr promote. Strips kind/semver from frontmatter, moves the ADR file from pre-release/ or foundation/ to pool/, deletes the source package directory (briefs, closeout form), and emits an artifact_renamed ledger event with reason="pool_demotion".
Authored under GHI #521 as the Day-0 tooling prerequisite for the get-out-of-jail prequel sweep (GHI #520).
Usage¶
Options¶
| Option | Type | Description |
|---|---|---|
--ghi |
int | Required. GitHub Issue number this demotion is tracked under. Every demotion must be auditable. |
--note |
string | Free-text operator rationale; stored in the ledger event extras. |
--operator |
string | Operator identity (name only; never email per Local Agent Rules). Defaults to omitted. |
--dry-run |
flag | Show planned actions without writing files or ledger events. |
--json |
flag | Emit a structured JSON result payload to stdout. |
--force |
flag | Override both exit-3 safety checks: dependent children (orphans any ADRs whose parent: frontmatter points at the demoted ADR) and live @covers decorators naming REQs from the deleted briefs (GHI #773). |
--on-collision |
choice | How to handle a pre-existing pool file at the target slug. fail (default) blocks; keep-pool deletes the source feature/foundation package and keeps the existing pool ADR — reversing any stale status: Superseded / promoted_to: / promotion-note markers that name the ADR now being demoted (GHI #558), and leaving an unrelated pool file at the same slug untouched; take-demoted writes the demoted ADR's current content to the pool slug, overwriting the retained intake (GHI #775). The ledger event records collision_resolution: "keep-pool" when that path is taken. |
Behavior (Enforced)¶
- Source ADR must be
featureorfoundationkind with a validsemverfield. Pool ADRs are rejected (already pool — nothing to demote). - Pool target id is derived as
ADR-pool.<slug>, where<slug>comes from the source ADR's id (ADR-X.Y.Z-<slug>→<slug>). - Target file path:
docs/design/adr/pool/ADR-pool.<slug>.md. - Collision check. If the pool target file already exists, the demotion is rejected (exit 1) by default. A promote/demote round trip always collides, because
gz adr promoteretains the pool file as historical intake by design — so the choice of policy is the choice of which document survives. Pass--on-collision take-demotedwhen the ADR was worked after promotion: it writes the demoted ADR's current content to the pool slug, so what gets drawn from the queue later is the thinking as it stands.keep-poolis correct only when the promoted ADR did not diverge from its intake — otherwise it exits 0 having silently discarded every decision recorded after promotion (GHI #775). The superseded intake remains in git history either way. Passing--on-collision keep-poolresolves the collision by deleting the source feature/foundation package. If the kept pool ADR'spromoted_to:still names the ADR being demoted (i.e. this demotion reverses that prior promotion), itsstatus/promoted_to/promotion-note markers are reversed to their canonical pre-promotion state (status: Pool,promoted_to:stripped, the> Promoted to ...note removed) — this is the symmetric inverse of whatgz adr promotewrites on the pool side (GHI #558). A pool file colliding on slug but promoted to a different ADR is left untouched. The ledger event records the resolution either way. - Frontmatter strip.
kind,semver, frontmatterdateandpromoted_from(GHI #775) are removed.idis rewritten to the pool id, and so is the id in the body H1 (GHI #776).statusis set toPool. The## OBPI Acceptance Note (Human Acknowledgment)section is stripped (GHI #777). Other fields (lane,parent,inspired_by, etc.) are preserved. - OBPI briefs deleted. Per the 2026-05-23 get-out-of-jail prequel Q1=b decision, pool ADRs carry no OBPIs by doctrine; brief files under
<source-dir>/obpis/are deleted via the source-dir removal. A latergz adr promoteregenerates briefs from the pool's scope and unparks the OBPIs this demotion parked. - Source directory removed. The entire
docs/design/adr/{pre-release,foundation}/<source-id>/directory is deleted (taking the briefs, closeout form, and any other authoring artifacts with it). - Dependent children check (fail-closed). If any other non-pool ADR has
parent: <source-id>in its frontmatter, demotion is rejected with exit 3. Pass--forceto orphan those children deliberately. - Live
@coverscheck (fail-closed, GHI #773). If any@coversdecorator undertests/names a REQ of this ADR's semver, demotion is rejected with exit 3: deleting the briefs would make those test modules fail to import. Remove or retarget the decorators, or pass--force. -
Ledger events. One
artifact_renamedevent is appended withreason="pool_demotion", followed by oneobpi_parkedevent per child OBPI (parked_to: <pool-id>, reversible on re-promotion, GHI #584). The rename carries these extras (pluscollision_resolution: "keep-pool"on that path):
Per state doctrine (Layer 2 ledger = source of truth for state transitions), the demote event is the canonical record of the prior life. Pool files do not carry previously: frontmatter; gz state <pool-id> is the query path.
Exit Codes¶
| Code | Meaning |
|---|---|
| 0 | Demotion completed (or dry-run succeeded). |
| 1 | User/config error: missing --ghi, pool target collision, ADR already pool, missing kind/semver. |
| 2 | System/IO error: frontmatter parse failure, ledger write failure. |
| 3 | Policy breach: dependent children exist, or live @covers decorators name REQs from the briefs being deleted; --force overrides. |
Examples¶
# Preview demotion (mandatory --ghi)
gz adr demote ADR-0.27.0-arb-receipt-system-absorption --ghi 520 --dry-run
# Short-form ADR id resolves the same source
gz adr demote ADR-0.27.0 --ghi 520 --dry-run
# Apply demotion with operator-supplied rationale
gz adr demote ADR-0.27.0 --ghi 520 --note "prequel queue collapse"
# JSON output for scripted sweeps
gz adr demote ADR-0.27.0 --ghi 520 --json
# Override dependent-children safety (orphans the children)
gz adr demote ADR-0.27.0 --ghi 520 --force
# Resolve a pool-slug collision by keeping the existing pool ADR
gz adr demote ADR-0.42.0 --ghi 520 --on-collision keep-pool
# Round-trip an ADR that was worked after promotion: its current content
# becomes the pool file, replacing the retained pre-promotion intake
gz adr demote ADR-0.44.0 --ghi 773 --on-collision take-demoted --operator g0