Skip to content
Back to skills

Migrate Module

ASecurity

Port a legacy codebase to the new stack one module at a time, using the legacy code as the spec. First maps the legacy into ordered modules in .claude/migration.md (once per project). Then per module: inventory every legacy behavior with file:line, prove the inventory covers every function and handler, mark each same / fixed / dropped, split it into capabilities with short acceptance criteria, and get one approval. Then build each capability test-first, one commit per capability, pushed to th...

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 11, 2026
ai-agentsrustgoshellgitsecurity

Security analysis

A100/100

Pro scans all 3 files and shows the line behind each finding

Scanned November 11, 2026

npx -y skills add orrrrli/clawd-harness --skill migrate-module --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Migrate Module?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Migrate Module
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/orrrrli-migrate-module/badge)](https://www.skillsdirectory.com/skills/orrrrli-migrate-module)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: migrate-module
stacks: [all]
description: "Port a legacy codebase to the new stack one module at a time, using the legacy code as the spec. First maps the legacy into ordered modules in .claude/migration.md (once per project). Then per module: inventory every legacy behavior with file:line, prove the inventory covers every function and handler, mark each same / fixed / dropped, split it into capabilities with short acceptance criteria, and get one approval. Then build each capability test-first, one commit per capability, pushed to the module's pull request as it closes, so CI validates it while the next capability is built. No GitHub issues: the inventory is the spec and the state. Use when the user says '/migrate-module <module> [capability]', '/migrate-module map', 'migrate the <x> module', 'map the legacy modules', 'next capability of <module>', or 'module status'."
trigger: /migrate-module
---

# /migrate-module [map | <module> [capability]]

The legacy app is the spec. A module is inventoried as a whole so no legacy behavior is lost; it
is delivered one capability (one thing a user can do) at a time. One approval per module, then
build without stopping: push each capability as it closes and let CI run it while the next one is
being built.

## Project config

Everything project-specific lives in `.claude/migration.md`: repo, legacy files, new code paths,
branch and the branch it merges into, decisions doc, conventions, tenant, golden paths, the local
gate, and the ordered module table. This skill calls its values "config". Module docs always live
at `docs/migration/<module>/inventory.md`.

If the user names a module out of order, say which earlier modules are not done and ask.

## Resolve

- `/migrate-module map`, or no `.claude/migration.md` → **Step 0**.
- `.claude/migration.md` with `Status: draft` → show it, STOP for approval.
- Otherwise read `docs/migration/<module>/inventory.md`:
  - No file → **Step 1**.
  - `Status: draft` → show it, STOP for approval.
  - `Status: approved` → **Step 2** on the capability named, or the next one not `done` in
    dependency order.
  - Every capability `done` → **Module close**.

A capability specced before this flow in its own doc (`docs/migration/<module>/C<n>.md`) keeps that
doc as its criteria and task list; finish it with Step 2.

## Step 0 — Map the modules (once per project)

Read `map-modules.md` in this folder and follow it. It writes `.claude/migration.md` and stops for
approval. It never starts Step 1 on its own.

## Step 1 — Inventory and plan (the only stop per module)

Read the module's legacy code end to end. For large files dispatch `Explore` per area, each
returning behaviors with `file:line`; check what they return. Write `inventory.md`:

```
# <Module> migration inventory
Status: draft
Legacy source: <files>

## Behaviors
| ID | Behavior | Legacy | Mark | Decision | Golden | Real data | Capability | State |
| B1 | ... | `<file>:2324` | same / fixed / dropped | 34 | yes / - | pending / - | C1 | pending |

## Coverage
Pattern: `<rg pattern>` over <files and line ranges>. Hits: <n>.
| Hit | Legacy | Row |
| saveGroup | `<file>:2310` | B1 |
| legacyExport | `<file>:2980` | dropped (B9) |
| renderShell | `<file>:120` | out of module (foundation) |

## Capabilities
### C1 — <what the user can do>   (rows B1, B4; depends on -; state pending)
- AC1 (B1). Given ..., When ..., Then ... (concrete values from the legacy)
- AC2 (B4). ...
- New entities or tables, if any (from the config's decisions doc; never invent one).
```

- **Mark:** `same` = ported as is; `fixed` = changes because of a decision (cite it); `dropped` =
  not ported (one-line reason). Never invent behavior. A legacy behavior that contradicts a
  decision is `fixed`, never silently changed.
- **AC:** one or more per row, with the legacy's real branches and error messages as values. A
  pure legacy function can be run from the scratchpad to get the expected output.
- **Golden / Real data:** see `golden-and-real-data.md` in this folder; read it only when a row
  needs it. `Real data: pending` on rows with logic, `-` otherwise.
- **Coverage:** Explore reads, it does not prove completeness. After the rows are written, list
  with `rg -n` every function definition, event handler, route, query and exported entry point in
  the module's legacy area. Pick the pattern for the legacy language (JS: `function \w+`,
  `\w+\s*=\s*(async\s*)?\(`, `addEventListener`, `on\w+=`; adapt for others) and write it down
  so the next session can rerun it. Every hit maps to a row, to a `dropped` row, or to
  `out of module (<module>)`. A hit that maps to nothing becomes a new row. The inventory cannot
  leave `draft` while any hit is unmapped.

Report in the user's language: counts per mark, coverage hits and how many became new rows, every
`fixed` and `dropped` row, the capability list, and open questions. **STOP for approval.** On
approval set `Status: approved` and commit (`docs(<module>): Add migration inventory`).

## Step 2 — Build a capability (no stop)

1. Read its criteria and the code it touches.
2. Write the tests first, one or more per AC, plus the negative and boundary cases they imply.
   Expected values come from the AC, never from the new code. If the config names a tenant,
   every capability that reads or writes tenant data includes an isolation test: tenant A never
   sees or changes tenant B's rows. Run only these new tests with the config's `Local gate` and
   confirm each one fails for the missing behavior. A test that already passes proves nothing:
   fix it before implementing.
3. Implement the minimum that makes them pass (ponytail), running only the new tests. Follow the
   config's conventions.
4. Check the work locally without running the full suite: only the config's `Local gate` (compile,
   typecheck, format, the new tests). The full suite is CI's job unless the config says otherwise.
   Commit:
   `git add` only this capability's files, `feat(<MODULE>-<C>): <Imperative summary>`. Subject only,
   no body, no AI trailer. Include the inventory edit setting the capability and its rows to `done`
   in the same commit.
5. Push the commit to the config's module branch. The module has one pull request into the branch
   that `Branch` names as its merge target: open it on the first push if it is missing, and push
   every later capability to the same PR so the review and the CI history stay in one place.
6. Start the next capability immediately, without waiting for CI. When a run for a finished
   capability comes back red, stop the capability in progress and fix that failure first; never
   stack a capability on a red run.

Stop only when:
- a criterion is ambiguous, or the legacy contradicts a decision in the config's decisions doc;
- the work needs a new entity, table, dependency, or architecture choice not in the inventory;
- a behavior turns up that is not in the inventory (add the row, show it, then build it);
- CI fails on a capability already pushed (fix it before starting anything else).

Report one line per finished capability with its CI state (running, green, red), and name the
capability being built next.

## Module close

When every row is `done` or `dropped`: report counts, list the `dropped` rows for a final OK,
set `Status: closed (<date>)` and commit (`docs(<module>): Close the migration module`), then push
it, rewrite the PR body with the final counts, and name the next module. The last capability's CI
run must be green before the module closes; the user merges. Rows still `Real data: pending` are
listed as open, not blocking.

After the last module in the config's table, run one full `security-auditor` pass over the new
code paths before anything ships: tenant isolation, auth, sessions, permissions, untrusted input.

## Rules

- Legacy files are read-only. Write only in the config's new code paths, `docs/` and
  `.claude/migration.md`.
- No real data in git: examples are synthetic; real records stay in gitignored local paths.
- Never edit, skip or weaken a test to get green.
- The inventory is the state: a new session resumes from it, never from memory.
- Commits go on the config's module branch and reach it through one PR into its merge target. Push
  each capability as it closes; the next one starts while CI runs. A red run stops the work.
- The full test suite runs in CI. Locally run only the config's `Local gate` (compile, typecheck,
  the capability's new tests); never report a capability as verified on the strength of a local
  run, and never run the full suite when the config says CI owns it.
- Reports and questions in the user's language; docs and code in English.

Files in this skill

  • SKILL.md8.5 KB
  • golden-and-real-data.md2.5 KB
  • map-modules.md3.3 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

View all in ai-agents →

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.