# Prepare Migration

> Prepare a whole site for migration by orchestrating the prep cascade — a full-inventory crawl (extract --prep), page-type and module-catalog confirmation (direct --prep), archetype prototypes plus design canon (prototype --prep), and asset preparation — with confirmation gates between phases. Builds the typed page inventory, confirmed module catalog, and canon that `migrate` consumes. Use when the user wants to prepare or set up a full-site migration, run migration prep, confirm page types and modules before migrating a site, get a large site ready to migrate, or invokes `$stardust prepare-migration`. Trigger phrases include "prepare the migration", "migration prep", "set up the migration data", "get the site ready to migrate". Redesign-flow only — for same-design migrations `replica` runs its own preserve-mode prep cascade; never chain prepare-migration with replica. Not for running the migration itself (`migrate`) or converting a single page (`deploy`).

- Skill: `adobe/prepare-migration-2` (Agent Skill)
- Install (CLI): `npx skillmds@latest add adobe/prepare-migration-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/adobe/prepare-migration-2/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- License: Apache-2.0
- Author: Adobe (https://skillmd.com/u/adobe), verified publisher
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/adobe/prepare-migration-2

---


# stardust:prepare-migration

Orchestrate the migrate-prep cascade. When the user commits to
migrating an existing site, this skill runs the upstream phases
(`extract`, `direct`, `prototype`) in their `--prep` modes,
sequenced with confirmation gates so the user can confirm or refine
the inferred catalog at each step.

`prepare-migration` is a **thin orchestrator** — it does not
duplicate logic from the underlying skills; it invokes them and
brokers the per-phase summaries. The substantive work lives in:

- `skills/extract/SKILL.md` § Prep mode
- `skills/direct/SKILL.md` § Prep mode
- `skills/prototype/SKILL.md` § Prep mode +
  `reference/canon-extraction.md`

When prep is complete, the user runs `$stardust migrate`
separately. The two-step boundary (`prepare-migration` then
`migrate`) is intentional: it makes "I'm committing to migrate
this site" a conscious gesture and keeps idempotency obvious.

## Inputs

- `--from <phase>` — optional. Resume the cascade from a specific
  phase. Values: `extract | direct | prototype | assets |
  dynamics`. Default starts from the earliest incomplete phase.
- `--skip-confirm` — optional. Skip the per-phase confirmation
  gates. Useful for re-runs where the catalog is already settled.
  Default is to gate at every phase boundary. Hands-off mode
  (`skills/stardust/SKILL.md` § Hands-off mode, i.e.
  `state.json.handsOff: true`) implies `--skip-confirm`.
- `--canon-from <slug>` — optional. Forward to
  `prototype --prep --canon-from <slug>` when that phase runs.
  Override the default canon-author (which is `home`).
- `--refine-module <module-id>` — optional. Re-enter Phase 2's
  module-catalog step for one module — the target of `migrate`'s
  "bespoke slot crossing promotion threshold" hint. Promotes the
  recurring bespoke slot into that module's slot schema
  (`DESIGN.json.extensions.modules[]`), surfaces the change for
  confirmation, then stops; it does not re-run the full cascade.
  Affected pages are stale-flagged content-aware per
  `skills/stardust/reference/state-machine.md`.

## Setup

1. Run the master skill's setup (`skills/stardust/SKILL.md`
   § Setup) — impeccable dep check, context loader, state read.
   **Flow guard.** This is the redesign flow's orchestrator. If
   `state.json.flow` is `replica`, refuse: print "never run
   `prepare-migration` before or after `replica`" and the switch
   command (`$stardust prepare-migration --switch-flow`, which marks
   the replica artefacts stale — master skill § Two migration flows).
   If `flow` is absent, resolve it first: a keep-design phrase in the
   ask ("1:1", "exact replica", "same design", "faithful",
   "re-platform") means this skill does not apply — say so and hand to
   `replica`; a plain migration ask gets the one keep-vs-redesign
   question (hands-off: default `redesign`, recorded in
   `direction.md`); then stamp `flow: "redesign"`
   (`skills/stardust/reference/state-machine.md` § Flow keys).
   (Recorded: "build a 1:1 migration plan" entered here on a plugin
   that already described both flows and ran the redesign cascade for
   two hours before `direct` was asked for an "exact replica".)
2. Verify `stardust/state.json` exists with at least one extracted
   page. If not, recommend `$stardust extract <url>` and stop.
3. Verify `stardust/direction.md` exists with an active direction.
   If not, recommend `$stardust direct` and stop.
4. Determine which phases are already complete by inspecting
   project state:
   - **extract**: every page has a non-null `type` in `state.json`
     and `current/pages/<slug>.json` carries a `slots` block.
   - **direct**: `DESIGN.json.extensions.modules[]` entries all
     have `status: confirmed`; `colorReservations` and `metadata`
     blocks present.
   - **prototype**: every page-type has at least one approved
     archetype; `stardust/canon/` populated;
     `DESIGN.json.extensions.canon` populated.
   - **assets**: favicon variants in
     `stardust/migrated/assets/`; fonts downloaded.
   - **dynamics**: `stardust/dynamic-features.md` present with every
     row carrying a disposition; `helix-query.yaml` present when any
     listing is index-backed (Phase 4.5 records "none" otherwise).

   Resume from the earliest incomplete phase unless `--from`
   overrides.

## Procedure

The cascade runs five phases sequentially. Each phase invokes its
underlying skill via the harness's skill-invocation tool (see the master
skill § Routing for how sub-skills are addressed), surfaces the phase's prep
summary, then waits for user confirmation (unless `--skip-confirm`
or hands-off mode) before advancing.

### Phase 1 — extract --prep

Invoke the stardust `extract` skill with the argument `--prep`.
Claude Code form: `Skill { skill: "stardust:extract", args: "--prep" }`.

The underlying skill runs the standard extract procedure with the
five `--prep` overlays (lift cap, page typing, module candidates,
typed slots, prep summary).

On completion, surface the summary verbatim, name the flow, and gate —
the first interactive gate of the cascade carries the keep-vs-redesign
choice (one recorded migration ran this cascade for 3.5 hours before the
user asked for the keep-design flow, and the work was discarded):

```
Flow: redesign — the design changes while migrating. Say `switch to replica` now if it is to be kept.
Confirm and continue? (yes / refine "<phrase>" / switch to replica)
```

User options:

- **`yes`** — advance to Phase 2.
- **`switch to replica`** — the design is to be kept: stop this cascade
  and run `$stardust replica <url> --switch-flow` (master skill § Two
  migration flows). The extract just produced is reused by replica
  Phase 1; nothing else from this flow is.
- **`refine "<phrase>"`** — re-invoke `extract --prep` with the
  refinement (e.g., "type news/* slugs as listing not article",
  "exclude /search and /404 from inventory"). Re-surface summary;
  loop.

#### Provenance guard (between Phase 1 and Phase 2)

Before invoking `direct --prep`, validate every page in the
inventory via `validateProvenance(page)` per
`skills/stardust/reference/state-machine.md` § Provenance
validation. Abort the cascade with the helper's error if any
page lacks live-render evidence. This is the cascade-level
defense against the failure mode where `extract --prep` (or its
delegated sub-agent) silently synthesized one or more page
records — extract's own write-time refusal is the primary guard,
but the cascade adds a second check between phases so the
synthesis bug recurring under a different rationale cannot
quietly contaminate the rest of the run.

The same guard runs implicitly inside Phase 2, 3, and 4 (each
underlying skill's setup calls `validateProvenance()` per its
own SKILL.md) — but surfacing it here as an explicit cascade
step makes the abort happen *before* the user sees the Phase 2
prep summary, which would otherwise look like a successful run.

Surface in the cascade output:

```
Provenance OK on 127 pages.
```

When the check fails:

```
Provenance check failed on 20 of 127 pages — see error above.
Cascade aborted between Phase 1 and Phase 2.
   → Re-run extract for the affected slugs:
       $stardust extract --refresh <slug-1>
       $stardust extract --refresh <slug-2>
       ...
```

### Phase 2 — direct --prep

Invoke the stardust `direct` skill with the argument `--prep`.
Claude Code form: `Skill { skill: "stardust:direct", args: "--prep" }`.

The underlying skill runs five `--prep` overlays (type catalog
confirmation, module catalog finalization, color reservations,
direction re-evaluation, brand metadata defaults).

Surface the summary and gate. User options match Phase 1
(`yes` / `refine "<phrase>"`).

### Phase 3 — prototype --prep

Invoke the stardust `prototype` skill with the argument `--prep`, plus
`--canon-from <slug>` when a canon slug is already known.
Claude Code form: `Skill { skill: "stardust:prototype", args: "--prep --canon-from <slug>" }`.

The underlying skill fills page-type gaps (one approved archetype
per type) and writes canon back per
`skills/prototype/reference/canon-extraction.md`. First approval
establishes canon; subsequent approvals extend it (with conflicts
logged as deviations by default).

This phase typically takes the longest — each archetype goes
through the full prototype loop (shape brief, craft, open in
browser, iterate, approve). Stream progress to the user as each
archetype lands.

Surface the summary and gate.

### Phase 4 — assets prep

Generate or download asset variants needed for the migrated site.
This phase has no underlying SKILL — it runs as a small image-
processing + download routine.

1. **Favicon variants.** From the canonical favicon at
   `stardust/current/assets/favicon.<ext>`, generate:
   - `stardust/migrated/assets/favicon-512.png`
   - `stardust/migrated/assets/apple-touch-icon.png` (180×180)
   - `stardust/migrated/assets/icon-192.png`,
     `icon-512.png` (manifest sizes)

2. **Font downloads.** Scan `stardust/canon/canon.css` (and
   `stardust/canon/header.html` / `footer.html`) for `@font-face`
   rules with external URLs. For each:
   - Download the file to
     `stardust/migrated/assets/fonts/<basename-with-hash>.<ext>`.
   - Rewrite the `@font-face` `url(...)` reference in canon files
     to the local path.
   - Skip if already downloaded (sha-compared).
   - Log a warning if download fails (font keeps external URL;
     migrate logs a `metadata-override` warning per page).

3. **Brand-asset audit.** Verify the logo, favicon, and any
   media files referenced by canon module renderings are
   present in `stardust/current/assets/`. Surface missing assets
   to the user.

Surface summary and gate:

```
assets prep complete
====================

Favicon variants:    favicon-512.png, apple-touch-icon.png, icon-192.png, icon-512.png
Font downloads:      4 files (HarmoniaSans 4 weights)
Brand assets:        all present
```

### Phase 4.5 — Dynamic surface (pre-import gate: `dynamics` Phases 1–3)

Runs after assets prep and **before any bulk import**. Migration-bound:
this is the step that keeps a dynamic site from being imported as a
static one. Delegate to `skills/dynamics/SKILL.md`:

1. **Detect** — re-run `extract --dynamics` if Phase 1 ran without it
   (reach), then `dynamics-detect.mjs --from-state stardust/state.json
   --reach stardust/current` (depth on archetypes).
2. **Classify + triage** — `dynamics-plan.mjs [--target-origin <host>]`
   drafts the four axes per row; curate into
   `stardust/dynamic-features.md` (§ Listings contract with
   `helix-query.yaml`, § Features, § Decision batch, § Register) and
   `stardust/dynamic-features-plan.md`.
3. **Gate** — passes when every row has a disposition. "none" in both
   sections is a valid pass. The gate never blocks the static path; it
   blocks silent regressions.

Summary line: `dynamic surface: N findings · self K · owner batch M ·
host-bound H · listings L dynamic / S static`. Contract:
`skills/dynamics/reference/triage.md`.

### Final report

```
prepare-migration complete
==========================

Phase 1 (extract --prep):      127 pages, 7 types, 8 module candidates
Phase 2 (direct --prep):       types & modules confirmed; metadata set
Phase 3 (prototype --prep):    6 archetypes approved; canon written
Phase 4 (assets prep):         favicon variants + fonts + brand assets ready
Phase 4.5 (dynamic surface):   14 findings · self 6 · owner batch 7 · host-bound 1 · listings 3 index-backed / 1 static

Next: $stardust migrate
```

## Outputs

`prepare-migration` writes nothing directly — every artifact is
written by the underlying skill or by the Phase 4 / 4.5 routines.
After the cascade runs, the project state has:

| Artifact                                                | Phase that wrote it             |
|---------------------------------------------------------|---------------------------------|
| `state.json.pages[].type`                               | extract --prep                  |
| `current/pages/<slug>.json` § slots                     | extract --prep                  |
| `DESIGN.json.extensions.modules[]` (`status: confirmed`)| extract --prep + direct --prep  |
| `DESIGN.json.extensions.colorReservations[]`            | direct --prep                   |
| `DESIGN.json.extensions.metadata`                       | direct --prep                   |
| `stardust/canon/` (header, footer, css, modules/)       | prototype --prep                |
| `DESIGN.json.extensions.canon`                          | prototype --prep                |
| `stardust/migrated/assets/favicon-*`                    | assets prep                     |
| `stardust/migrated/assets/fonts/`                       | assets prep                     |
| `stardust/dynamic-features.md` + `-plan.md` (inventory, four axes, decision batch) | dynamics gate (Phase 4.5) |
| `helix-query.yaml` (scoped indexes, EDS project root)   | dynamics gate (Phase 4.5) |
| `stardust/state.json` (per-page status updates)         | each underlying phase           |

## Failure modes

- **No state.json or no extracted pages.** Recommend
  `$stardust extract <url>` and stop.
- **No active direction.** Recommend `$stardust direct` and stop.
- **User refuses a phase.** Stop the cascade cleanly. State is
  left in a consistent intermediate (the underlying skill's writes
  have landed); the user can resume with
  `$stardust prepare-migration --from <phase>`.
- **Underlying skill fails.** Surface the failure verbatim; do not
  advance. User fixes and re-runs.
- **Phase 3 canon conflict during a non-canon-author approval.**
  Conflicts log as deviations by default per
  `reference/canon-extraction.md`. If the user wants to override
  per-conflict (promote to canon / reject and re-iterate / log as
  deviation), surface during the phase's confirmation gate rather
  than at runtime. A future `--strict-canon` flag could refuse
  approvals that conflict; not in v0.2.
- **Phase 4 asset download failure.** Continue the run; log the
  failure in the assets-prep summary. Migrate later surfaces a
  warning per affected page.

## Concurrency

Per `skills/stardust/reference/state-machine.md` § Concurrency:
`state.json` writes merge by slug, so the cascade's per-page writes
coexist with other parallel lanes. But two concurrent
`prepare-migration` runs on the same project race on the same
top-level artifacts (canon, module catalog) — that remains
last-write-wins with a warning, and is likely to corrupt canon.
Don't run two cascades at once; do not engineer a lock around it.

## Idempotency

Re-running `prepare-migration` after partial completion resumes
from the earliest incomplete phase (or the explicit `--from`
phase). Each underlying skill is itself idempotent — already-
typed pages are not re-typed, already-confirmed modules are not
re-proposed, already-approved archetypes are not re-prototyped,
already-generated favicon variants are not re-generated, and an
existing `dynamic-features.md` is refined rather than rewritten.

Re-running after full completion is a no-op unless inputs
changed (extract found new pages, direction was edited, the
canon-author prototype was re-iterated, etc.).

## References

- `skills/extract/SKILL.md` § Prep mode
- `skills/direct/SKILL.md` § Prep mode
- `skills/prototype/SKILL.md` § Prep mode
- `skills/prototype/reference/canon-extraction.md` — the
  five-step extraction procedure prototype --prep performs on
  approval
- `skills/dynamics/SKILL.md` + `reference/triage.md`,
  `reference/listings.md` — Phase 4.5 is its Phases 1–3
- `skills/migrate/SKILL.md` — the consumer of every data
  structure this cascade prepares
- `notes/migrate-template-canon-refactor.md` — design plan and
  rationale
- `skills/stardust/reference/state-machine.md` — page typing,
  stale-flagging cascade
- `skills/stardust/reference/artifact-map.md` — file structure,
  DESIGN.json.extensions shape

