Quickstart: Runtime-State Corpus Cutover
Operator + maintainer runbook for the #2816 cutover. (Developer test discipline at the bottom.)
Operator: migrate a corpus manually
# 1. Preview — seeds nothing, flips nothing; shows per-mission would-seed counts.
spec-kitty migrate backfill-runtime-state --dry-run
# 2. Real run — seeds events, verifies count+value parity vs the old reader,
# flips status_phase ONLY for missions that pass. Non-zero exit if any fail.
spec-kitty migrate backfill-runtime-state
# 3. Scope to one mission if needed (mission_id / mid8 / slug).
spec-kitty migrate backfill-runtime-state --mission <handle>
exits non-zero, naming the mismatch. No unverified mission is ever flipped.
- Idempotent: re-running seeds nothing and re-flips nothing.
- Fail-closed: a parity mismatch (or a fault-injected corrupt seed) aborts that mission's flip and
Upgrading user: automatic migration
spec-kitty upgrade runs the runtime-state backfill+verify as an auto-discovered migration:
left in a consistent, non-partially-flipped state. Investigate the named mission, re-run spec-kitty upgrade (or the CLI) after resolving.
- Legacy deployment → corpus is backfilled, verified, and flipped as part of the upgrade.
- Fresh install (no
kitty-specs/or no legacy runtime state) → no-op. - Verify failure → the migration step aborts with an operator-actionable message; the deployment is
Precondition: do not run other spec-kitty runtime commands concurrently with spec-kitty upgrade (the migration closes the new-code-meets-un-backfilled-corpus window inside the upgrade command itself — see research D-02).
What changes for you after cutover
from the event log, not tasks/WP##.md. A runtime transition writes 0 bytes to the WP file.
- Runtime WP state (
shell_pid,agent/assignee,tracker_refs, subtask completion, review) is read - The phase-1
status_phaseflag no longer gates anything — the snapshot is always authority. - Nothing changes for the
lanefield (still frontmatter-authored; separate follow-up).
Verify the end-state
# predicate is gone (expect 0 hits):
grep -rn "phase1_snapshot_authority_active" src/ ; echo "exit $?"
# #2093 invariant passes with an empty tolerated set:
uv run --extra test python -m pytest -p no:cacheprovider tests/architectural/test_2093_authority_invariant.py
# dead-symbol gate green (frozenset un-pinned):
uv run --extra test python -m pytest -p no:cacheprovider tests/architectural/test_no_dead_symbols.py
Developer test discipline (CRITICAL)
sibling checkout and yields false greens.
are NOT this mission's — confirm on the merge-base before attributing a red to this diff.
here we remove the pins (the symbols gain callers), which is the intended un-pin.
- Always
uv run --extra test python -m pytest -p no:cacheprovider <FILE>— barepythonresolves a - Never run the whole
tests/architectural/directory — it hangs. Per-file, each with a timeout. - Pre-existing reds (
SYNC_DISABLE_ENV_VARSarch-adversarial phantom; ADR-2026-07-17-1 known P0s) test_no_dead_symbols.pypins by content hash — editing a pinned symbol's body breaks its pin;