Migration Plans That Preserve Proof¶
Migration becomes dangerous the moment a team starts treating "change" as the goal and "proof" as cleanup for later.
That is backwards.
A safe migration plan changes one boundary at a time while keeping enough evidence alive to answer a simple question:
what still works, what changed on purpose, and how do we know?
If you are learning this without the live class¶
Read this lesson in five passes:
- name the single boundary you want to move
- identify the proof route you refuse to lose
- design the smallest comparison that can expose drift
- write rollback criteria before you celebrate the new owner
- decide only at the end when the old route can honestly be retired
If you cannot name those five things, you do not have a migration plan yet.
How to use this page¶
Read this page after you can already describe the current repository truth from the previous lesson.
Keep one migration packet beside you as you read:
- one statement of the current contract
- one defect class
- one single-boundary move
- one preserved proof route
- one comparison packet
- one retirement condition
That packet is what turns "cleanup" into something a reviewer can actually approve.
The migration mistake that burns months¶
Teams often discover real pain in an inherited workflow and jump to this conclusion:
the safe path is to replace everything in one cleaner design.
That is almost never the safe path.
A large rewrite can reduce visible mess while destroying your ability to compare:
- old and new publish bundles
- old and new dry-run meaning
- old and new profile behavior
- old and new proof routes
If comparison disappears, regressions get explained away instead of diagnosed.
Start by preserving the questions, not by replacing the implementation¶
Beginners often frame migration as a design exercise:
- what should the repository look like after cleanup
- what architecture feels more modern
- what older surface we want to stop seeing
This page teaches a different frame:
- what questions the current repository can still answer
- what proof routes a reviewer already trusts
- what comparison artifacts must stay available while the boundary moves
That is what makes migration reviewable instead of aspirational.
Preserve the questions before changing the answers¶
Before moving a boundary, identify the questions the current repository can still answer:
- which files are public
- which inputs and parameters cause reruns
- which profiles change policy only
- which proof commands a reviewer already trusts
The migration plan should preserve those questions even if the implementation moves.
A good migration sequence¶
flowchart LR
review["review current truth"] --> preserve["preserve proof route"]
preserve --> move["move one boundary"]
move --> compare["compare old and new behavior"]
compare --> keep["keep or retire the old route explicitly"]
That sequence is plain on purpose. Most unsafe migrations fail by skipping one of those steps.
Move one boundary at a time¶
In Snakemake repositories, the boundaries that often move are:
- publish contract
- sample discovery and DAG shape
- helper-code ownership
- profile and operating-context policy
- workflow module or repository layout
- external system handoff
If a single change tries to move three of these at once, review gets vague very quickly.
A migration card you should be able to fill before editing anything¶
Use a table like this:
| Part | What to record |
|---|---|
| current contract | which files, rules, or review routes must stay trusted |
| defect class | what is actually wrong: contract ambiguity, policy drift, hidden ownership, weak proof, or wrong tool boundary |
| intended move | which single boundary changes next |
| preserved proof | which command or artifact still lets you compare old and new |
| rollback trigger | what would make the move dishonest |
| retirement condition | what must be true before the old route disappears |
If you cannot fill one cell, the step is probably too large.
Start by strengthening proof, not by deleting the old path¶
Suppose a team wants to redesign sample discovery and publish reporting.
A weak migration plan says:
- rewrite discovery
- rewrite report generation
- update downstream notebook paths
- remove the old verification route
A better plan says:
- keep
make verify-reportworking - keep the current file API visible
- add a clearer discovered-sample artifact if needed
- change discovery while comparing dry-run and publish results
- only then adjust reporting or downstream interfaces
That order keeps the public truth alive while the internals move.
Comparison routes should be boring and specific¶
Migration gets safer when you add temporary comparison artifacts or commands.
Examples:
- compare old and new
summary.jsonoutputs - compare dry-run target lists before and after a discovery change
- compare profile-audit bundles before and after an infrastructure move
These routes are not glamorous, but they stop migration review from becoming a debate about confidence and aesthetics.
What goes wrong when a learner trusts the rewrite story¶
Use this card before you praise the new structure:
| If you notice... | The migration is probably hiding... | Smallest repair |
|---|---|---|
| the plan says "modernize" more often than it names boundaries | the move is still a mood, not a step | one one-boundary migration card |
| the old proof route disappears before the new one is trusted | lost comparison | keep the old proof route alive |
| several concerns change in one branch | blurred regression classes | split the move into separate boundaries |
| rollback is not written down | confidence is replacing evidence | write one explicit rollback trigger |
If the smallest repair feels annoying, that usually means it is exactly what the migration needs.
A small example¶
Imagine a repository where:
- downstream readers trust
publish/v1/summary.json - maintainers want to move report generation into a Python package
- the current report rule is hard to test
The safe plan is not "rewrite reporting."
The safe plan is:
- write down which publish files must remain stable
- keep
verify-reportintact - move report logic behind the same declared file contract
- compare old and new report artifacts
- retire the old helper only after comparison stays boring
That is what it means to preserve proof.
One concrete migration scenario¶
Suppose a team wants to:
- move discovery logic into a package
- simplify publish reporting
- change downstream notebook entry points
A weak migration plan treats those as one cleanup project.
A stronger sequence is:
- keep the current publish verification route alive
- compare dry-run target lists before touching downstream readers
- move discovery behind the same contract and compare behavior
- move reporting only after discovery no longer shifts unexpectedly
- change downstream entry points only when the public contract is stable enough to version or preserve
This sequence slows the work down in a useful way. It prevents one broad rewrite from hiding three different classes of regression.
Hybrid stages are usually honest¶
For a while, a migration may leave the repository in a mixed state:
- Snakemake still owns orchestration
- a package now owns one complex implementation surface
- an external platform owns deployment or scheduling policy
This is often healthier than pretending one change should settle everything.
Hybrid stages are fine when the handoff is visible and the proof route still tells a clear story.
The three questions every migration step must answer¶
Before approving one step, write down:
- what exact boundary is moving
- what evidence proves trust is preserved
- what route remains available until the new route earns trust
If the third answer is vague, the step is probably too large.
The rollback test¶
Before you commit a migration step, make sure you can answer:
- what output difference would count as unacceptable
- what consumer breakage would stop the move
- what missing proof would block approval even if the code looks cleaner
- what condition would let you retire the old owner honestly later
If rollback still sounds embarrassing, the migration is not ready. Rollback is part of serious stewardship, not evidence of failure.
The beginner mistake to catch early¶
The most common beginner mistake is saying, "we can restore verification after the new design lands."
That sounds efficient. It is usually how teams lose the comparison route that would have told them the redesign drifted.
The course standard is stricter:
- keep one trusted proof route alive
- add the new route beside it
- compare calmly and repeatedly
- retire the old route only after the new one becomes boring to review
A five-line migration note you should be able to write from memory¶
If this lesson has landed, you should be able to write:
- which exact boundary is moving
- what defect class justifies the move
- which proof route remains alive throughout the step
- what comparison artifact exposes drift
- what must be true before the old route disappears
If you cannot write those five lines, the plan is still too abstract.
Keep this standard¶
Do not approve migration language like "modernize," "clean up," or "move to a better system" unless the proposal also names:
- the boundary being moved
- the proof being preserved
- the comparison route
If those are absent, the plan is still a mood, not a migration.