Retire the line-level append-only mechanic (ersatztv#303 H9) in favor of the lifecycle validator built in Tasks 1-5. .claude/hooks/decisions-guard.sh is now a thin fail-open shim around scripts/decisions_validate.py; .husky/pre-commit calls it for the structural (working-tree) checks, .husky/commit-msg drops the old staged/[decisions-edit]-deletion block and keeps only the Co-Authored-By check. The Gitea decisions-guard job is renamed "decisions lifecycle" and now runs decisions_validate.py --base/--head (structural + body-diff + no-vanish) and build_decisions_catalog.py --check (active catalog drift), with actions/setup-python@v5 added since the bare `small` lane doesn't guarantee python3; the old 1800-line consolidation-floor step is removed (replaced by the validator's aggregate active-corpus budget). docs/decisions.md's header is rewritten from append-only to lifecycle framing (metadata schema, statuses, generated catalog, archive, same-PR supersession); [decisions-edit] is re-scoped (not removed) to rationale-prose edits/factual corrections only. docs/ci-cd.md's release ritual and hook/job descriptions are rewritten to match. Also fixes a pre-existing validator false-positive surfaced while sanity-checking against origin/main: Task 6's #303 H9/H3 split (commit d09be57e) renamed the archived record's heading away from the pre-split original, which the validator's heading-based relocation check reads as "removed without an archive copy." Restored the archived heading to match the original text (functionally unchanged — still status: superseded, same key) and updated the two prose cross-references (migration-map.md, release-ci-governance.md) that pointed at the old anchor. PR1 scope only (per brief): does NOT wire the kickoff-guard CI step or touch the kickoff/README/select-queue docs — that's Task 8/PR2. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3.4 KiB
Archived — release/CI/merge-governance records superseded by the #521 lifecycle schema
Records relocated verbatim (rationale prose unchanged) from docs/decisions/release-ci-governance.md
during the #521 decision-lifecycle migration. See docs/decisions/archive/README.md for what this
directory is and docs/decisions/migration-map.md for the full mapping.
docs.append-only-guard(below) — thedocs/decisions.md-is-append-only-by-construction half of #303 H9/H3. Superseded bydocs.decision-lifecycle(active, indocs/decisions.md) — the lifecycle validator (scripts/decisions_validate.py) that this very PR introduces replaces line-level append-only enforcement with record-level lifecycle checks. The companion H3 root-screenshot guard was split out (#521) into its own still-active record,ci.root-screenshot-guard, indocs/decisions/release-ci-governance.md— it is not covered by this supersession and was never archived.
2026-07-12 — decisions.md is append-only, enforced; root-screenshot guard (#303 H9/H3)
key: docs.append-only-guard · status: superseded · since: 2026-07-12 · supersedes: none · superseded-by: docs.decision-lifecycle@2026-07-21
Rule: (superseded) docs/decisions.md is append-only, enforced by hook + CI.
Signals: decisions-guard hook · paths: .claude/hooks/decisions-guard.sh, .husky/commit-msg · issues: #303 (H9)
Mechanics: superseded by scripts/decisions_validate.py (ersatztv#521); see docs/decisions.md → docs.decision-lifecycle
This log is append-only by construction, not just by convention. A commit or PR that deletes or
modifies an existing line of docs/decisions.md is blocked — by the Husky commit-msg hook
(.claude/hooks/decisions-guard.sh staged) locally and the blocking decisions-guard CI job (same
script, range mode) on PRs. Shared detection, deliberately different granularity: the Husky hook
gates each commit (its own message must carry the token); CI gates the PR-wide net diff
(token in any commit of the range suffices), so the local hook is the stricter primary gate and CI the
push/bypass backstop. Insertions anywhere are always allowed, so a normal new entry (TOC line
near the top + a block appended at the bottom, both pure insertions) passes untouched. Detection is
git diff --numstat deleted-count > 0, which is robust to markdown - list markers (a byte-level -
prefix would false-match). The block is lifted only by the literal [decisions-edit] token in the
commit message, reserved for two cases: fixing a factual error, and superseding a reversed decision
(add the new entry, prepend a > **Superseded …** banner to the old one, tag its Index line
(superseded) — keep the old rationale, never silently rewrite). Consolidation of superseded
entries is a release-checklist step (docs/ci-cd.md → Versioning & releases), backstopped by a
non-blocking 1800-line size floor in the decisions-guard job (the read-cost point past which the
log no longer fits one default agent Read), so append-only doesn't accrete contradictory or
unreadably-large history between releases (Timothy's call, 2026-07-12: mark-and-keep on reversal,
consolidate at each milestone, size-floor backstop).
The companion H3 root-screenshot guard was split out during the #521 migration to the active record
ci.root-screenshot-guard in docs/decisions/release-ci-governance.md.