Transform My Repo
Migrations die from optimism: the equivalent library that doesn't exist, the
runtime behavior nobody knew was load-bearing, the big-bang rewrite that
never ships. This skill plans transformations the evidence-first way — and
its most valuable possible output is a well-argued "don't."
Division of labor: this skill answers whether to migrate, how hard, in
what order, and with what safety net. The detailed implementation plan for
each migration phase is a deep-plan run — do not duplicate that work here.
The Prime Directive (family rule)
No claim without evidence — on BOTH sides. Source facts need
file:line. Target-stack facts (a library exists, a mechanism behaves a
certain way) need a registry/docs citation with version, checked NOW —
training-data memory of an ecosystem is not evidence, and "surely Python
has an equivalent" is how migrations lose months.
Progress checklist
Copy this into your response and check items off:
Transform Progress:
- [ ] Step 0: Frame — source → target, driver, constraints, non-goals, feasibility questions
- [ ] Step 1: Source census — inventory + dependency, platform-coupling, operational censuses
- [ ] Step 2: Target ground truth — every dependency & mechanism verified in target ecosystem
- [ ] Step 3: Gap analysis — semantic gaps + per-module difficulty heatmap
- [ ] Step 4: Verdict — GO / PARTIAL / NO-GO as a 10–20 line brief ⛔ user gate
- [ ] Step 5: Strategy — code + data parity, pattern, bridge, rollback, ONE-WAY tags, data migration plan, modernization sequenced separately
- [ ] Step 6: Assessment document — skeleton-first roadmap, spikes for unknowns, pre-mortem risks
- [ ] Step 7: Self-check + report
Step 0 — Frame the transformation
Use the arguments provided with the invocation (some platforms substitute
them as $ARGUMENTS — [source → target] [project-root] [driver/reason]);
otherwise infer from the repo and ask. Treat the given project-root as the
source repo for every step; state which root you used in the report.
Pin down, before analyzing anything:
- Source → target, precisely (language+version, framework, deployment model).
- The driver — WHY migrate: performance, hiring, maintenance, licensing,
business model (SaaS)? The verdict is only meaningful relative to the
driver; "Go is nicer" and "PHP hosting blocks our SaaS pricing" produce
different verdicts on identical code.
- Constraints: team skills, downtime tolerance, budget/deadline, data that
must not be re-migrated twice.
- Non-goals: what explicitly stays as-is.
- Feasibility Questions — a numbered list of what the verdict needs
answered ("does the target ecosystem cover the ORM?", "does the target
runtime actually serve the perf driver?", "is there a seam where old and
new can coexist?"). Steps 1–3 exist to answer this list: each finding
cites the question number it answers, questions discovered mid-census are
appended, and research is complete when every question is answered with
evidence or explicitly tagged
UNVERIFIED — not when every file has
been read.
- Identify which transformation type(s) apply — see
references/transformation-catalog.md;
each type has its own extra checklist. Combinations (port AND SaaS-ify)
multiply risk: recommend sequencing them, not doing both at once.
Step 1 — Source census
Inventory the source repo (reuse the know-my-repo discipline if that skill
is available; otherwise a deep read: structure, data flow, wiring, tests,
git trajectory). On top of that, three censuses specific to migration:
- Dependency census — every runtime dependency with its role and how
deeply its API is woven in (call-site count).
- Platform-coupling census — every use of source-platform-specific
behavior: runtime model (e.g. PHP's request-per-process state reset),
language constructs with no direct target equivalent, OS/FFI calls,
framework magic, numeric/string/encoding semantics the code relies on.
- Operational census — deploy pipeline, environments, real data scale
(row counts, traffic — migrating 100 rows and 100M rows are different
plans), and background jobs (cron/queue) touching the paths that move.
Migrations fail on ops as often as on code; this census feeds the
coexistence bridge and cutover math in Step 5.
Everything with file:line. Also record test coverage per module — it
determines parity-harness cost in Step 5.
Step 2 — Target ground truth
For EVERY census entry, verify in the target ecosystem — registry, official
docs, source — with URL + version, fetched now:
| Census entry |
Target equivalent |
Coverage |
Evidence |
| <library / mechanism> |
<package / built-in / none> |
full / partial / missing |
<registry or docs URL + version> |
Rules:
- "Partial" must say what is missing (features, maturity, maintenance
status — a last-commit-3-years-ago port counts as missing).
- Missing entries are the headline finding, each with its realistic
options: write it yourself (estimate), keep a sidecar in the source
language, change approach, or verdict-blocker.
- Verify the target's runtime model actually serves the driver (e.g. if the
driver is performance, find benchmarks or write a spike — do not assume).
- No web access in this session? Degrade honestly: verify what local
evidence allows (installed target toolchains, lockfiles, vendored source,
offline docs), tag everything else
UNVERIFIED — needs web check, and
say plainly that the verdict is provisional until those are checked.
Never fill the Evidence column from memory.
Step 3 — Gap analysis and difficulty heatmap
- Semantic gaps: behaviors that will silently differ after a faithful
line-by-line port — typing discipline, concurrency model, error handling
idioms, numeric precision, string/encoding, lifecycle/state model,
transaction semantics. Each gap: where it bites (
file:line) and how it
will be handled or tested.
- Difficulty heatmap: score every module with the rubric in
references/feasibility-rubric.md
(size, dependency density, platform coupling, test coverage, churn).
Output a ranked table — this answers "what will be hard" concretely and
later dictates migration order.
Step 4 — The verdict ⛔
Apply the rubric and present, BEFORE designing anything further:
- GO — coverage and gaps manageable; expected cost proportionate to the driver.
- PARTIAL — migrate these modules, keep/bridge those; say which and why.
- NO-GO — the evidence says the driver is better served another way;
name the alternative (targeted refactor, optimization, extraction,
different target). A NO-GO with evidence is a successful outcome of this
skill, not a failure.
Present it as a Verdict Brief — 10–20 lines in chat, not a document:
the verdict, dependency coverage stats, worst gaps, heatmap top rows,
estimated magnitude (S/M/L/XL per module group), the three worth-it
answers, and any feasibility question still UNVERIFIED. Ask for the
decision once. Stop and let the user decide. Only continue to
Step 5 on an accepted GO/PARTIAL.
If the user cannot respond (headless/CI run), degrade honestly: on GO or
PARTIAL, continue but tag the verdict UNCONFIRMED — awaiting user in the
document's Verdict section; on NO-GO, write the assessment with the
strategy and roadmap sections marked "not applicable — NO-GO" — designing
a migration nobody approved is waste.
Step 5 — Migration strategy
Design the safety net before the route:
- Behavioral parity harness first. Before any porting, pin current
behavior: characterization/golden-master tests on the source for every
module about to move, at its seams (HTTP responses, DB writes, file
outputs). Untested behavior cannot be proven preserved — budget this
honestly; it is often the largest single line item. This proves code
parity; data parity is a separate gate (item 6) — code that behaves
identically on top of silently corrupted data is not a successful migration.
- Migration pattern — decide, don't menu: default is incremental
with coexistence (strangler fig at a routing/API seam,
branch-by-abstraction, module-by-module with an interop bridge).
A big-bang rewrite requires proof it is unavoidable (tiny codebase, or
no viable seam), not preference.
- Coexistence bridge: how old and new run together during migration —
API seam, message queue, sidecar, FFI — and how data stays consistent
across both (single writer? sync? cutover-per-table?).
- Cutover and rollback: per phase — shadow/dual-run with output
diffing where feasible, feature flags, the exact rollback trigger and
procedure. A phase without a rollback path is not a phase; it is a bet.
- Classify every cutover action REVERSIBLE or ONE-WAY. ONE-WAY =
undo cost rivals do cost: in-place/destructive data conversion,
decommissioning the old system, a cutover after which the two stores
diverge, a public API contract change. Each ONE-WAY action needs
explicit user confirmation before its phase runs — in headless runs,
carry it into the document marked
UNCONFIRMED. REVERSIBLE actions
just need their rollback path named.
- Data migration plan — whenever the data's shape or owner changes, not
just on a database swap. A language port, a SaaS-ification, or a
monolith split can all reshape or re-own data while the engine stays put.
Plan four things, each with
file:line/schema evidence:
- Field-level mapping — old shape → new shape, column by column;
name every default, type coercion, and split/merge. A renamed or
restructured schema (see Modernization vs. parity below) makes this
mandatory, not optional.
- Backfill & dirty-data handling — legacy data almost never satisfies
the new constraints: bad encodings, orphaned rows, duplicates, values
that violate the target's types or NOT NULLs. Census the offenders and
decide per class (clean, quarantine, or reject) — silently dropping them
is data loss.
- Move mechanism — dump/restore vs dual-write vs CDC, chosen by
volume × allowable downtime (Type G in the catalog).
- Reconciliation gate (data parity) — the bulk check that proves the
move was faithful: row counts match, checksums/aggregates agree,
referential integrity holds, a sample diff is clean. This is distinct
from the code parity harness and MUST pass before an old store is
decommissioned. Name its rollback: how the source stays authoritative
until reconciliation is green.
Modernization vs. parity
Legacy source is often a mess — vanilla code with SQL scattered across files,
cryptic table/column names, dead branches. The temptation is to clean it up
while porting. Resist: mixing cleanup into the port destroys parity-testing
(you can no longer tell whether a behavior changed because of the port or the
cleanup). The rule:
- Port to parity first, carrying the mess faithfully; prove code + data
parity; then modernize as a separate, deliberate phase on the roadmap.
- Following the target's standards/idiom is part of the port, not
optional cleanup (a port that fights the idiom fails review forever) — but
cosmetic/structural cleanup (renaming, re-layering, dead-code removal) is
the separate phase.
- Renaming schema/tables/columns uses expand-contract, never a rename at
cutover: add the new name → backfill → dual-write both → switch readers →
drop the old name. Record every rename in a rename map so the data
migration plan (item 6) can map old rows to new shape.
Step 6 — Write the assessment document
Write to docs/TRANSFORM.md (or user-chosen path) following
references/assessment-template.md:
verdict + evidence, censuses, gaps, heatmap, strategy, and a phased roadmap
where each phase is sized to be one deep-plan run, ordered by the
heatmap (start with a low-risk, representative module to calibrate real
cost — never the hardest one), each with parity gate + rollback point.
Two roadmap non-negotiables:
- Phase 1 is a walking skeleton, not a code drop: the calibrator
module runs end-to-end in the target stack — built, deployed through
the real pipeline, serving traffic through the actual coexistence
bridge. "Ported and unit-tested" parks the integration risk (build,
deploy, bridge, data) at the end of the migration, which is where
migrations die.
- Every
UNVERIFIED tag and every missing census entry that survives
into the roadmap becomes a named, timeboxed spike task placed FIRST in
the phase that depends on it (e.g. "Spike: prove handles
— 1 day"). No unknown may sit silently under a migration phase.
Step 7 — Self-check and report
- Every target-ecosystem claim has URL + version. Every source claim has
file:line. Zero "surely the target has this" — grep the document for
UNVERIFIED and verify the count matches section 10.
- Every Step 0 feasibility question is answered with evidence or listed as
UNVERIFIED in the document — and every surviving UNVERIFIED/missing
entry has a named spike task first in the phase that depends on it.
- The verdict follows from the evidence shown, not from enthusiasm either
way — and it was presented as a Verdict Brief (or, headless, tagged
UNCONFIRMED).
- Every ONE-WAY cutover action is user-confirmed or marked
UNCONFIRMED;
every REVERSIBLE action names its rollback path.
- If the data's shape or owner changes, the document has a data migration
plan (field mapping, dirty-data handling, move mechanism, reconciliation
gate) — not just a "migrate the data" bullet. Data parity (row
counts/checksums/integrity) is a named gate, separate from code parity.
- Any cleanup/renaming is sequenced as its own phase AFTER parity, with a
rename map and expand-contract migrations — never folded into the port.
- The risk register came from the pre-mortem — no risk that could be
pasted into a different migration's assessment unchanged.
- Roadmap Phase 1 is a walking skeleton (deployed end-to-end through the
bridge), and the operational census (deploy, data scale, background
jobs) is reflected in the cutover plan.
- The user could hand Phase 1 of the roadmap to deep-plan right now.
- Report: verdict, top 3 hardest things (per the heatmap), missing
equivalents, and the recommended first slice.
When things go wrong
| Situation |
Response |
| Target ecosystem unreachable (no web access) |
Degrade honestly (Step 2): verify what local evidence allows (installed toolchains, lockfiles, vendored source, offline docs), tag everything else UNVERIFIED — needs web check, state plainly verdict is provisional. Never fill Evidence column from memory. |
| Dependency has no target equivalent and no acceptable workaround |
Missing entry becomes headline finding (Step 2). Realistic options: write it yourself (estimate), keep sidecar in source language, change approach, or verdict-blocker. If blocker touches core → NO-GO. |
| User cannot respond to Verdict Brief (headless/CI run) |
Degrade honestly (Step 4): on GO/PARTIAL continue but tag verdict UNCONFIRMED — awaiting user in document; on NO-GO write assessment with strategy/roadmap marked "not applicable — NO-GO". Never design migration nobody approved. |
| Feasibility question remains unanswered after Step 3 |
Tag UNVERIFIED explicitly (Step 0 rule), list in document section 10, create named timeboxed spike task FIRST in the phase that depends on it (Step 6). No unknown may sit silently under a migration phase. |
| ONE-WAY cutover action needed but user unavailable for confirmation |
Mark UNCONFIRMED in document (Step 5). Carry into roadmap phase with confirmation status visible. Never execute destructive action without explicit user sign-off. |
| Migration stalls at 60%, both stacks running forever |
Classic risk — gets explicit trigger and answer in risk register (Step 6). Define DONE criterion up front (e.g. "no direct mysqli_query outside repository layer"); strangler must finish strangling. |
1---2name: transform-my-repo3description: Feasibility analysis and migration strategy for architecture transformations: language ports (PHP to Python, Rust to Go), framework migrations (Vue or React SPA to Next.js), major version upgrades, monolith to microservices and back, database migrations, cloud/container/ serverless re-hosting, sync to event-driven, REST to GraphQL/gRPC, UI platform shifts, standalone to SaaS, and vanilla to framework. Produces an evidence-based GO/PARTIAL/NO-GO verdict with a worth-it test against the do-nothing baseline (dependency census verified in the target ecosystem, semantic gap analysis, per-module difficulty heatmap), then a migration roadmap with behavioral parity gates and rollback points. Allowed to recommend NOT migrating. Use when the user asks to migrate, port, rewrite, re-platform, upgrade a major version, split or merge services, switch databases or API paradigms, asks whether a migration is worth it, or mentions transform-my-repo or /transform-my-repo.4license: MIT5---67# Transform My Repo89Migrations die from optimism: the equivalent library that doesn't exist, the10runtime behavior nobody knew was load-bearing, the big-bang rewrite that11never ships. This skill plans transformations the evidence-first way — and12its most valuable possible output is a well-argued **"don't."**1314Division of labor: this skill answers **whether to migrate, how hard, in15what order, and with what safety net**. The detailed implementation plan for16each migration phase is a **deep-plan** run — do not duplicate that work here.1718## The Prime Directive (family rule)1920> **No claim without evidence — on BOTH sides.** Source facts need21> `file:line`. Target-stack facts (a library exists, a mechanism behaves a22> certain way) need a registry/docs citation with version, checked NOW —23> training-data memory of an ecosystem is not evidence, and "surely Python24> has an equivalent" is how migrations lose months.2526## Progress checklist2728Copy this into your response and check items off:2930```31Transform Progress:32- [ ] Step 0: Frame — source → target, driver, constraints, non-goals, feasibility questions33- [ ] Step 1: Source census — inventory + dependency, platform-coupling, operational censuses34- [ ] Step 2: Target ground truth — every dependency & mechanism verified in target ecosystem35- [ ] Step 3: Gap analysis — semantic gaps + per-module difficulty heatmap36- [ ] Step 4: Verdict — GO / PARTIAL / NO-GO as a 10–20 line brief ⛔ user gate37- [ ] Step 5: Strategy — code + data parity, pattern, bridge, rollback, ONE-WAY tags, data migration plan, modernization sequenced separately38- [ ] Step 6: Assessment document — skeleton-first roadmap, spikes for unknowns, pre-mortem risks39- [ ] Step 7: Self-check + report40```4142## Step 0 — Frame the transformation4344Use the arguments provided with the invocation (some platforms substitute45them as `$ARGUMENTS` — `[source → target] [project-root] [driver/reason]`);46otherwise infer from the repo and ask. Treat the given project-root as the47source repo for every step; state which root you used in the report.4849Pin down, before analyzing anything:5051- **Source → target**, precisely (language+version, framework, deployment model).52- **The driver** — WHY migrate: performance, hiring, maintenance, licensing,53 business model (SaaS)? The verdict is only meaningful relative to the54 driver; "Go is nicer" and "PHP hosting blocks our SaaS pricing" produce55 different verdicts on identical code.56- Constraints: team skills, downtime tolerance, budget/deadline, data that57 must not be re-migrated twice.58- Non-goals: what explicitly stays as-is.59- **Feasibility Questions** — a numbered list of what the verdict needs60 answered ("does the target ecosystem cover the ORM?", "does the target61 runtime actually serve the perf driver?", "is there a seam where old and62 new can coexist?"). Steps 1–3 exist to answer this list: each finding63 cites the question number it answers, questions discovered mid-census are64 appended, and research is complete when every question is answered with65 evidence or explicitly tagged `UNVERIFIED` — **not** when every file has66 been read.67- Identify which transformation type(s) apply — see68 [references/transformation-catalog.md](references/transformation-catalog.md);69 each type has its own extra checklist. Combinations (port AND SaaS-ify)70 multiply risk: recommend sequencing them, not doing both at once.7172## Step 1 — Source census7374Inventory the source repo (reuse the know-my-repo discipline if that skill75is available; otherwise a deep read: structure, data flow, wiring, tests,76git trajectory). On top of that, three censuses specific to migration:77781. **Dependency census** — every runtime dependency with its role and how79 deeply its API is woven in (call-site count).802. **Platform-coupling census** — every use of source-platform-specific81 behavior: runtime model (e.g. PHP's request-per-process state reset),82 language constructs with no direct target equivalent, OS/FFI calls,83 framework magic, numeric/string/encoding semantics the code relies on.843. **Operational census** — deploy pipeline, environments, real data scale85 (row counts, traffic — migrating 100 rows and 100M rows are different86 plans), and background jobs (cron/queue) touching the paths that move.87 Migrations fail on ops as often as on code; this census feeds the88 coexistence bridge and cutover math in Step 5.8990Everything with `file:line`. Also record test coverage per module — it91determines parity-harness cost in Step 5.9293## Step 2 — Target ground truth9495For EVERY census entry, verify in the target ecosystem — registry, official96docs, source — with URL + version, fetched now:9798| Census entry | Target equivalent | Coverage | Evidence |99|--------------|-------------------|----------|----------|100| <library / mechanism> | <package / built-in / none> | full / partial / **missing** | <registry or docs URL + version> |101102Rules:103104- "Partial" must say what is missing (features, maturity, maintenance105 status — a last-commit-3-years-ago port counts as missing).106- **Missing entries are the headline finding**, each with its realistic107 options: write it yourself (estimate), keep a sidecar in the source108 language, change approach, or verdict-blocker.109- Verify the target's runtime model actually serves the driver (e.g. if the110 driver is performance, find benchmarks or write a spike — do not assume).111- **No web access in this session?** Degrade honestly: verify what local112 evidence allows (installed target toolchains, lockfiles, vendored source,113 offline docs), tag everything else `UNVERIFIED — needs web check`, and114 say plainly that the verdict is provisional until those are checked.115 Never fill the Evidence column from memory.116117## Step 3 — Gap analysis and difficulty heatmap118119- **Semantic gaps:** behaviors that will silently differ after a faithful120 line-by-line port — typing discipline, concurrency model, error handling121 idioms, numeric precision, string/encoding, lifecycle/state model,122 transaction semantics. Each gap: where it bites (`file:line`) and how it123 will be handled or tested.124- **Difficulty heatmap:** score every module with the rubric in125 [references/feasibility-rubric.md](references/feasibility-rubric.md)126 (size, dependency density, platform coupling, test coverage, churn).127 Output a ranked table — this answers "what will be hard" concretely and128 later dictates migration order.129130## Step 4 — The verdict ⛔131132Apply the rubric and present, BEFORE designing anything further:133134- **GO** — coverage and gaps manageable; expected cost proportionate to the driver.135- **PARTIAL** — migrate these modules, keep/bridge those; say which and why.136- **NO-GO** — the evidence says the driver is better served another way;137 name the alternative (targeted refactor, optimization, extraction,138 different target). A NO-GO with evidence is a successful outcome of this139 skill, not a failure.140141Present it as a **Verdict Brief** — 10–20 lines in chat, not a document:142the verdict, dependency coverage stats, worst gaps, heatmap top rows,143estimated magnitude (S/M/L/XL per module group), the three worth-it144answers, and any feasibility question still `UNVERIFIED`. Ask for the145decision **once**. **Stop and let the user decide.** Only continue to146Step 5 on an accepted GO/PARTIAL.147148If the user cannot respond (headless/CI run), degrade honestly: on GO or149PARTIAL, continue but tag the verdict `UNCONFIRMED — awaiting user` in the150document's Verdict section; on NO-GO, write the assessment with the151strategy and roadmap sections marked "not applicable — NO-GO" — designing152a migration nobody approved is waste.153154## Step 5 — Migration strategy155156Design the safety net before the route:1571581. **Behavioral parity harness first.** Before any porting, pin current159 behavior: characterization/golden-master tests on the source for every160 module about to move, at its seams (HTTP responses, DB writes, file161 outputs). Untested behavior cannot be proven preserved — budget this162 honestly; it is often the largest single line item. This proves **code163 parity**; **data parity** is a separate gate (item 6) — code that behaves164 identically on top of silently corrupted data is not a successful migration.1652. **Migration pattern — decide, don't menu:** default is **incremental166 with coexistence** (strangler fig at a routing/API seam,167 branch-by-abstraction, module-by-module with an interop bridge).168 A big-bang rewrite requires proof it is unavoidable (tiny codebase, or169 no viable seam), not preference.1703. **Coexistence bridge:** how old and new run together during migration —171 API seam, message queue, sidecar, FFI — and how data stays consistent172 across both (single writer? sync? cutover-per-table?).1734. **Cutover and rollback:** per phase — shadow/dual-run with output174 diffing where feasible, feature flags, the exact rollback trigger and175 procedure. A phase without a rollback path is not a phase; it is a bet.1765. **Classify every cutover action REVERSIBLE or ONE-WAY.** ONE-WAY =177 undo cost rivals do cost: in-place/destructive data conversion,178 decommissioning the old system, a cutover after which the two stores179 diverge, a public API contract change. Each ONE-WAY action needs180 explicit user confirmation before its phase runs — in headless runs,181 carry it into the document marked `UNCONFIRMED`. REVERSIBLE actions182 just need their rollback path named.1836. **Data migration plan — whenever the data's shape or owner changes, not184 just on a database swap.** A language port, a SaaS-ification, or a185 monolith split can all reshape or re-own data while the engine stays put.186 Plan four things, each with `file:line`/schema evidence:187 - **Field-level mapping** — old shape → new shape, column by column;188 name every default, type coercion, and split/merge. A renamed or189 restructured schema (see *Modernization vs. parity* below) makes this190 mandatory, not optional.191 - **Backfill & dirty-data handling** — legacy data almost never satisfies192 the new constraints: bad encodings, orphaned rows, duplicates, values193 that violate the target's types or NOT NULLs. Census the offenders and194 decide per class (clean, quarantine, or reject) — silently dropping them195 is data loss.196 - **Move mechanism** — dump/restore vs dual-write vs CDC, chosen by197 volume × allowable downtime (Type G in the catalog).198 - **Reconciliation gate (data parity)** — the bulk check that proves the199 move was faithful: row counts match, checksums/aggregates agree,200 referential integrity holds, a sample diff is clean. This is distinct201 from the code parity harness and MUST pass before an old store is202 decommissioned. Name its rollback: how the source stays authoritative203 until reconciliation is green.204205## Modernization vs. parity206207Legacy source is often a mess — vanilla code with SQL scattered across files,208cryptic table/column names, dead branches. The temptation is to clean it up209*while* porting. Resist: mixing cleanup into the port destroys parity-testing210(you can no longer tell whether a behavior changed because of the port or the211cleanup). The rule:212213- **Port to parity first**, carrying the mess faithfully; prove code + data214 parity; then modernize as a **separate, deliberate phase** on the roadmap.215- Following the **target's standards/idiom** is part of the port, not216 optional cleanup (a port that fights the idiom fails review forever) — but217 *cosmetic/structural* cleanup (renaming, re-layering, dead-code removal) is218 the separate phase.219- **Renaming schema/tables/columns uses expand-contract**, never a rename at220 cutover: add the new name → backfill → dual-write both → switch readers →221 drop the old name. Record every rename in a **rename map** so the data222 migration plan (item 6) can map old rows to new shape.223224## Step 6 — Write the assessment document225226Write to `docs/TRANSFORM.md` (or user-chosen path) following227[references/assessment-template.md](references/assessment-template.md):228verdict + evidence, censuses, gaps, heatmap, strategy, and a phased roadmap229where **each phase is sized to be one deep-plan run**, ordered by the230heatmap (start with a low-risk, representative module to calibrate real231cost — never the hardest one), each with parity gate + rollback point.232233Two roadmap non-negotiables:234235- **Phase 1 is a walking skeleton, not a code drop:** the calibrator236 module runs **end-to-end in the target stack** — built, deployed through237 the real pipeline, serving traffic through the actual coexistence238 bridge. "Ported and unit-tested" parks the integration risk (build,239 deploy, bridge, data) at the end of the migration, which is where240 migrations die.241- **Every `UNVERIFIED` tag and every `missing` census entry that survives242 into the roadmap becomes a named, timeboxed spike task** placed FIRST in243 the phase that depends on it (e.g. "Spike: prove <target lib> handles244 <feature> — 1 day"). No unknown may sit silently under a migration phase.245246## Step 7 — Self-check and report247248- Every target-ecosystem claim has URL + version. Every source claim has249 `file:line`. Zero "surely the target has this" — grep the document for250 `UNVERIFIED` and verify the count matches section 10.251- Every Step 0 feasibility question is answered with evidence or listed as252 `UNVERIFIED` in the document — and every surviving `UNVERIFIED`/`missing`253 entry has a named spike task first in the phase that depends on it.254- The verdict follows from the evidence shown, not from enthusiasm either255 way — and it was presented as a Verdict Brief (or, headless, tagged256 `UNCONFIRMED`).257- Every ONE-WAY cutover action is user-confirmed or marked `UNCONFIRMED`;258 every REVERSIBLE action names its rollback path.259- If the data's shape or owner changes, the document has a data migration260 plan (field mapping, dirty-data handling, move mechanism, reconciliation261 gate) — not just a "migrate the data" bullet. Data parity (row262 counts/checksums/integrity) is a named gate, separate from code parity.263- Any cleanup/renaming is sequenced as its own phase AFTER parity, with a264 rename map and expand-contract migrations — never folded into the port.265- The risk register came from the pre-mortem — no risk that could be266 pasted into a different migration's assessment unchanged.267- Roadmap Phase 1 is a walking skeleton (deployed end-to-end through the268 bridge), and the operational census (deploy, data scale, background269 jobs) is reflected in the cutover plan.270- The user could hand Phase 1 of the roadmap to deep-plan right now.271- Report: verdict, top 3 hardest things (per the heatmap), missing272 equivalents, and the recommended first slice.273274## When things go wrong275276| Situation | Response |277|-----------|----------|278| Target ecosystem unreachable (no web access) | Degrade honestly (Step 2): verify what local evidence allows (installed toolchains, lockfiles, vendored source, offline docs), tag everything else `UNVERIFIED — needs web check`, state plainly verdict is provisional. Never fill Evidence column from memory. |279| Dependency has no target equivalent and no acceptable workaround | Missing entry becomes headline finding (Step 2). Realistic options: write it yourself (estimate), keep sidecar in source language, change approach, or verdict-blocker. If blocker touches core → NO-GO. |280| User cannot respond to Verdict Brief (headless/CI run) | Degrade honestly (Step 4): on GO/PARTIAL continue but tag verdict `UNCONFIRMED — awaiting user` in document; on NO-GO write assessment with strategy/roadmap marked "not applicable — NO-GO". Never design migration nobody approved. |281| Feasibility question remains unanswered after Step 3 | Tag `UNVERIFIED` explicitly (Step 0 rule), list in document section 10, create named timeboxed spike task FIRST in the phase that depends on it (Step 6). No unknown may sit silently under a migration phase. |282| ONE-WAY cutover action needed but user unavailable for confirmation | Mark `UNCONFIRMED` in document (Step 5). Carry into roadmap phase with confirmation status visible. Never execute destructive action without explicit user sign-off. |283| Migration stalls at 60%, both stacks running forever | Classic risk — gets explicit trigger and answer in risk register (Step 6). Define DONE criterion up front (e.g. "no direct mysqli_query outside repository layer"); strangler must finish strangling. |