DocumentsDosu Decant
Archive schema: incident history behind the migration rules
Archive schema: incident history behind the migration rules
Type
Document
Status
Published
Created
Aug 3, 2026
Updated
Aug 3, 2026

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-sync the watcher fills the scratch archive from the real
    ~/.claude and ~/.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.