archflow-migrate · git:20260911.a26fb9f · 2026-09-11 · sha256 0449faf17a498019
archflow-migrate git:20260911.a26fb9fA
Immutable. This exact content is served forever at /api/v1/blob/0449faf17a498019.
---
name: archflow-migrate
description: "Use ONLY when the user asks for /archflow-migrate or \"archflow migrate\". Upgrade a v1.0 archflow-onboarded project (sprints) to schema v2.0 (releases) — dry-run first, then apply"
---
> Arguments are the text after the skill name.
# /archflow-migrate — Migrate a project from schema v1.0 to v2.0
Transforms an existing Archflow project's v1.0 roadmap into the v2.0 multi-file **release** model,
using a deterministic engine (`scripts/migrate.py` in the plugin) — reconstructing real releases from git shipping
evidence, not from sprints. Standalone command (NOT part of `onboard`).
**Load-bearing idea: a sprint is NOT a release.** v1 sprints were agile time-boxes; many shipped
nothing. The engine reconstructs releases from **git evidence** (deploy-pipeline landing, prod-branch
merges, tags) and routes everything else to the backlog. Validated against real 3.4k–5.8k-line roadmaps.
## When it runs
- **Manually:** the user runs `/archflow-migrate`.
- **Auto-detected (prompt only, never auto-run):** any session where `.archflow/roadmap.yaml` has a
`phases:` OR `sprints:` key, OR `schema_version` is absent/`"1.0"`:
> "This project uses roadmap schema v1.0. Run `/archflow-migrate` to upgrade to v2.0."
If `roadmap.yaml` already has `schema_version: "2.1"`, say it's already migrated and stop.
## How to run it (the deterministic engine)
The migration is performed by **`.github/archflow/scripts/migrate.py`**, which
ships with the plugin. It requires `python3` + `pyyaml`. Run it against the target project root.
**1. DRY RUN first (writes nothing) — reconstruct + show the plan:**
```bash
python3 .github/archflow/scripts/migrate.py --path <project-root> --dry-run
```
It prints: detected v1 variant, git deploy boundary, prod branch/release events, the reconstructed
release timeline (baseline + discrete/rolling releases with story counts), the proposed active
release, backlog size, and warnings (e.g. multiple `in_progress` sprints, git-dating coverage).
**2. PRESENT the plan to the user; get confirmation / adjustments (MANDATORY).**
- If it warns of **multiple `in_progress` sprints**, ask which one is truly being built and pass it as
`--active <sprint-id>`.
- The user can also plan to merge/rename reconstructed releases *after* migration via `/archflow-release`.
- Do not proceed to apply until the user confirms.
**3. APPLY — back up and write the v2.0 layout:**
```bash
python3 .github/archflow/scripts/migrate.py --path <project-root> --apply --active <sprint-id>
```
It backs up v1 to `.archflow/backup-v1/`, then writes `roadmap.yaml` (index), `backlog.yaml`,
`releases/{active}.yaml`, `releases/archive/{slug}.yaml` per reconstructed release, and `history.yaml`.
**4. Review the written files, then commit** (the engine does NOT commit):
```bash
git add .archflow/ && git commit -m "chore: migrate roadmap to schema v2.0 (releases reconstructed from git)"
```
Point the user at `.archflow/backup-v1/` for rollback; note `/archflow-release` and `/archflow-mode`.
## What the engine does (reference)
- **Variant handling:** canonical (epics/phases → sprints) AND top-level `sprints:` with inline
stories, no epics/phases (the common real-world shape). Does not assume `^sprint-[0-9]+$` IDs.
- **Status normalization:** maps `done/completed→done`, `in_progress/partial-done→in_progress`,
`review→review`, `backlog/planned/deferred→ready`; infers a sprint's status from its stories when
missing; warns on unknown values.
- **Release reconstruction (from git):**
- *Deploy boundary* = first-commit date of strong CD infra (`buildspec`, `cloudbuild`,
`kubernetes/**/deployment`, `helm`, `/eks`, `infra/**prod**`, `docker-compose.prod`, `kustomize`) —
NOT test CI. Work before it → a `baseline` release.
- *Release events* = prod-branch merges (`from */staging`, `staging into prod`), coalesced within
~5 days. None → continuous deploy: `baseline` + one rolling release. (Git tags are not read.)
- *Story dating* from `S{n}-{m}` commit subjects; undated done work → `baseline`.
- **Routing:** `done` → reconstructed `releases/archive/` + `shipped` ledger + `history.yaml`; the ONE
current `in_progress` sprint → the active `in_progress` release; everything else → `backlog.yaml` as
**`ready` DETAILED stories** (ACs/subtasks kept, not stripped), with `target` = source sprint theme.
- **Normalization:** `priority` and story `status` mapped to the v2 enums; `acceptance_criteria`/
`subtasks` coerced to `{text,met}`/`{text,completed}`; non-`S{n}-{m}` ids skipped+warned.
- **Fill-ins:** epic labels synthesized from `S{n}-` prefixes; per-story `gates` from scope
(`assigned` + any `design-artifacts/{id}/`); archived-release `version` = `v0-{slug}` (never null;
git tags are not read); `mode: full`; `active_release` set in `roadmap.yaml` + `current-phase.yaml`
(omitted when nothing is in progress).
- **Invariant:** at most one `in_progress` release — refuses to guess when >1 in_progress sprint exists
(requires `--active`).
## Guarantees
- **Non-destructive to source code** — only `.archflow/` changes.
- **Reversible** — v1 preserved under `.archflow/backup-v1/`.
- **Dry-run by default** — nothing is written without `--apply`, and only after human confirmation.
- **A story lands in exactly one place** — a release file OR backlog, never both.
- **Sprints are not releases** — releases come from shipping evidence; unshipped work → backlog.