Archive schema: incident history behind the migration rules#
AGENTS.md invariant 5 and the new-migration skill state the rules — baseline
v21, migrations freeze on commit, never edit a committed migration. This page
records the two incidents that produced those rules, so the severity is
legible to people who weren't there. Written 2026-08-03.
Why "frozen on commit" and not "frozen on merge"#
Decant is dogfooded from the working tree. Any migration that has ever run —
from a branch, or even uncommitted — has effectively shipped to the
maintainer's live archive (~/.decant/decant.db, ~2.8 GB, contains state
that cannot be rebuilt: manual recommendation state, and sessions whose
source JSONL was pruned). Rebuilding is not a recovery path; repair
migrations are.
Incident 1: migration 18 edited in place (PR #72 review, found 2026-07-29)#
During #72's review, migration 18 was amended in place (ceda91d) after the
dogfooding archive had already applied its earlier revision. The amended
migration never re-ran: the archive said v18 but was missing
recommendation.impact_label / impact_label_checked. Every sweep sync
failed (~every 30–45 s, pegging serve CPU ~95%) and the analytics report
endpoint 500'd. Fix: migration 19 re-issued the guarded ALTERs (PR #73),
and #73 also added the schema-fingerprint gate so drift now fails loudly on
open (SchemaDriftError) instead of corrupting quietly.
Incident 2: stray column from an uncommitted branch (found 2026-07-29)#
The 2026-07-17 context-window research ran a never-committed variant of
migration 11 against the live archive, leaving a stray
session.context_compaction_count column. The fingerprint gate from #73
correctly rejected the archive on open. Fix: migration 21 = guarded
DROP COLUMN (PR #80, merged 2026-07-29), verified on a pristine copy of the
live archive (18→21, all sessions intact) before touching the real one, with
a backup taken first.
The distilled rules#
- Point schema experiments at a scratch DB:
DECANT_DB=/tmp/… --no-sync
(without--no-syncthe watcher fills the scratch archive from the real
~/.claudeand~/.codex). - Review feedback on a committed migration goes in a new version, never an
edit — even on an unmerged branch. - Write migrations guarded (
hasTable/hasColumn) so partially migrated
archives converge instead of throwing. - Repair drift with a guarded migration; verify on a copy of the live archive
first; never "just rebuild".
See .claude/skills/new-migration/SKILL.md for the step-by-step workflow.