The migration is a MOVE, so correctness is provable rather than reviewable:
parse the corpus before, migrate, parse after, assert the Record sets are
identical field-for-field with byte-identical rationale.
scripts/migrate_decisions_split.py
166 records -> docs/decisions/records/<area>/<topic>.md (active) or
docs/decisions/archive/<area>/<topic>.md (superseded/retired), 26 directories.
Path is DERIVED from the key, so identity stays the key. Refuses to run if any
record lacks a key, and aborts on a destination collision.
Source files are KEPT, stripped to their narrative -- not deleted. 506 lines of
the corpus sit outside any record: decisions.md's lifecycle-schema header (the
status vocabulary, supersession rules, the edit-token contract) and each topic
file's preamble explaining why those records exist. For most of it that is the
only copy. It also cannot be filed per-area -- topic files hold several areas
and 4 of 23 areas span several files -- so the files themselves stay.
scripts/tests/test_migration_equivalence.py
Runs the real migration against a COPY of the real corpus in tmp_path, never
the working tree. Asserts: all 166 records survive with the same keys, every
metadata field round-trips, titles round-trip from headings, every rationale
body is byte-identical, path matches key, archived records land in the archive
wing, the legacy files keep their narrative, and no parseable record is left
behind in them.
Proven non-vacuous: corrupting one migrated record's prose is caught by the
byte-identical check, and deleting one is caught by the survival check.
One test-authoring note: an early assertion string-matched "## " to prove no
records were left in decisions.md. That is wrong -- the schema header quotes an
illustrative "## 2026-07-17 ..." example in prose. Whether records remain is a
PARSING question, so the parser-based leftover test is the real invariant.