Quickstart — reproduce (red) and verify (green)

All commands use the branch venv, never bare uv run (it destroys the .venv). Prefix PWHEADLESS=1.

FR-001/FR-002 — migrate preserves a customised template (#4961)

Red-first (before fix) / green (after): focused unit + integration.

# Focused classifier probe (fast): a customised shipped template must NOT be a raw-deletable disposition.
PWHEADLESS=1 .venv/bin/python -m pytest tests/upgrade/test_migrate_integration.py -q -p no:xdist \
  -k "superseded or customized or version_skew or preserve"

Expected after fix: a .kittify/templates/spec-template.md that differs from the package default is preserved (in place / overrides / reported backup); migrate --dry-run labels it customised, not "superseded"; a byte-identical default is still removed.

FR-003 — first-install never deletes a pre-existing pack (#4960)

PWHEADLESS=1 .venv/bin/python -m pytest tests/specify_cli/doctrine/test_sources.py -q -p no:xdist \
  -k "TestGitSource and (first_install or preexisting or refuse or checkout)"

Expected after fix: with a non-empty local_path that is not a clone of url and a failing clone, the hand-authored files survive; only a fetch-created temp is ever removed.

FR-004 — update preserves local edits and advances (#4989)

PWHEADLESS=1 .venv/bin/python -m pytest tests/specify_cli/doctrine/test_sources.py -q -p no:xdist \
  -k "TestGitSource and (update or dirty or advance or origin)"

Expected after fix: dirty/committed local edits are preserved/backed up before any reset; a ref: main update targets origin/main and the pack advances.

FR-005 — the class stays closed (arch gate)

PWHEADLESS=1 .venv/bin/python -m pytest \
  tests/architectural/test_destructive_op_routing.py \
  tests/architectural/test_mutation_ownership_routing.py -q -p no:xdist

Expected after fix: green with both product modules in the scanned set. Fail-ability: adding an un-rationalised raw destructive literal to either module reds the gate (verified in review).

Blast-radius battery (pre-merge, over the combined tip)

PWHEADLESS=1 .venv/bin/python -m pytest tests/upgrade/ tests/specify_cli/doctrine/ tests/architectural/ tests/ci/ -q

Baseline-red gotcha applies: classify any failure per CLAUDE.md before attributing it to this mission.

Mutation-testing spot-check (review gate)

For each fixed site, hand-mutate the guard back to the raw destroy (e.g. restore path.unlink(), restore the unconditional rmtree, restore bare-<ref> reset), confirm a test goes RED, then revert. A site whose mutant stays green is unprotected — reject.