Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .oxcode-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@
"description": "Measure, profile, and optimise code with before-and-after numbers, without guessing or unverified claims.",
"category": "development",
"author": "Oxlo.ai"
},
{
"name": "migrate",
"source": "./plugins/migrate",
"description": "Upgrade dependencies and frameworks where equivalence is proven against tests, with codebase-filtered breaking changes.",
"category": "development",
"author": "Oxlo.ai"
}
]
}
13 changes: 13 additions & 0 deletions plugins/migrate/.oxcode-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "migrate",
"version": "1.0.0",
"description": "Upgrade dependencies and frameworks where equivalence is proven against tests, with codebase-filtered breaking changes.",
"author": {
"name": "Oxlo.ai"
},
"license": "MIT",
"homepage": "https://github.com/Cyborg-Network/oxcode-skills",
"requires": {
"oxcode": ">=0.4.0"
}
}
204 changes: 204 additions & 0 deletions plugins/migrate/skills/migrate/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
---
name: migrate
command: migrate
label: Migrate
hint: Upgrade dependencies and frameworks with proven equivalence
description: >-
Upgrade dependencies and frameworks where equivalence is proven against tests.
Use when updating versions, running codemods, or adapting breaking changes
without unverified claims.
category: development
order: 70
icon: arrow-up-circle
capability: Coding
workspace: required
tools: full
---

You are performing a version, dependency, or framework migration. Your job is to
upgrade software safely by proving behavioural equivalence against an
executable test suite, applying targeted codemods, and stopping at
architectural decisions rather than guessing.

Version and framework upgrades are where AI tooling is most confidently wrong:
it knows the public migration guide and does not know this codebase. It hallucinates
version numbers from memory, applies sweeping unneeded changes from generic
changelogs, and asserts that code is safe without running a test. A migration
built on a remembered version number or an unverified API claim is the most
expensive kind of wrong.

## Verify versions and capabilities by running commands, never from memory

Model memory of package versions, release dates, and API availability is frozen,
incomplete, or hallucinated. Never trust remembered version numbers.

1. **Verify target version existence**: Always run a package manager or
registry command to confirm the target version exists, is published, and is
stable before editing dependency files:
- Node / JS: `npm view <pkg> versions --json` or `pnpm info <pkg> versions`
- Python: `pip index versions <pkg>` or `pip install <pkg>==`
- Rust: `cargo search <pkg>` or `cargo outdated`
- Go: `go list -m -versions <module>`
- Ruby: `gem list -r <gem>`
2. **Verify API shapes empirically**: Never assume a method, parameter, or
configuration key exists in the target version. Inspect the installed package
declarations, run the compiler or type checker (`tsc`, `mypy`, `cargo check`,
`go build`), or execute a one-line evaluation in the terminal.

If network access is unavailable or a remote registry cannot be queried, state
the boundary explicitly:
`"Cannot query remote registry for <pkg> versions because network is unavailable. Proceeding with locally available target <version>."`

## Filter breaking changes to THIS codebase, not the full changelog

Upstream migration guides and release notes list dozens of breaking changes, the
vast majority of which do not apply to this repository. Dumping an upstream
changelog is not a migration plan; it is noise.

- **Scan the codebase**: Search the codebase (using grep or AST search) for each
breaking symbol, deprecated pattern, removed configuration key, or signature
change mentioned upstream.
- **Cite file and line**: The output of a migration audit is a short, filtered
list containing only the breaking changes that actually bite THIS code, with
the exact `file:line` reference where each one hits.
- **Omit unused changes**: If a breaking change in the upstream guide is not
present in this repository, explicitly exclude it. Do not pad the report with
irrelevant upstream notes.

## Prove equivalence with paired before-and-after test runs

Equivalence must be proven by executing the test suite against both versions,
never claimed or asserted. "This change is safe" is a banned assertion without
test proof.

1. **Establish the baseline before touching code**:
- Record the baseline as a set, not a verdict. Run the suite and the type
checker before modifying any file, and record the exact command, the total,
and the NAMES of any tests already failing. A repository with pre-existing
failures is normal and is not a reason to refuse the migration. Equivalence
afterwards means the same named tests fail and no new ones do.
- **STOP** only when the baseline cannot be run at all, or when a test that
already fails covers the code being migrated. Say which test and why it
blocks, rather than refusing on a count.
2. **Execute paired after-tests**:
- Run the exact same test command under the updated version.
- Prove that observable behaviour is preserved: the same named tests fail and
no new ones do.
- Report the before-and-after test counts and status side by side.
3. **Handle missing test coverage**:
- If a breaking API change affects code with no existing test coverage, write
a minimal characterization test proving current behaviour *before* changing
the dependency or code.

## Use ecosystem migration tools and codemods first

Where official codemods, migration scripts, or automated upgrade tools exist,
use them rather than hand-editing what a dedicated tool does deterministically.

- **Check for official tooling**:
- React / Next.js: `npx @next/codemod <transform>`, `npx react-codemod <transform>`
- TypeScript / JS: `npx ts-migrate`, framework upgrade CLIs
- Python / Django: `django-upgrade`, `pyupgrade`, `libcst` codemods
- Rust: `cargo fix --edition`, `cargo fix --allow-no-vcs`
- Go: `go fix ./...`
- **Inspect tool output**: State the exact command executed, name the files the
codemod changed and the transformation applied to each, and run the test suite
immediately after.
- Never hand-edit hundreds of lines of mechanical AST transformations when the
framework authors provide a tested codemod.

## Separate mechanical changes from judgement calls, and stop at decisions

Upgrades contain two distinct classes of changes:

1. **Mechanical changes**: Deterministic 1-to-1 replacements with identical
semantics (e.g. import path renames, deprecated argument renames, codemod
outputs, straightforward syntax updates).
- Apply these changes in small, atomic steps.
- Re-run tests between steps to verify each transformation.
2. **Judgement calls / Semantic decisions**: Deprecations or architectural
shifts with multiple valid solutions:
- A removed library requiring a choice between competing replacement libraries.
- A change from synchronous callbacks to async/await, streams, or promises
where error propagation strategy must be decided.
- Changed security defaults (e.g. strict CORS, disabled automatic deserialization,
new authentication requirements).
- Altered lifecycle hooks requiring business logic redesign.

**Hard stopping rule**: Never make a judgement call or architectural choice on
the user's behalf. When a migration hits a decision point, stop. Present the
alternatives, the trade-offs, and the affected `file:line` locations, and await
instruction before making modifications.

## The migration sequence

1. **Baseline**: Run test suite and type check on current code; record exact
command, total count, and the names of any failing tests.
2. **Version verification**: Run registry/package command to verify target
version exists and can be installed.
3. **Impact audit**: Grep codebase for breaking symbols and list only those that
hit this codebase, with `file:line` citations.
4. **Automated codemods**: Run ecosystem migration CLI or codemod if available;
state files changed and transformations applied, then run tests.
5. **Mechanical edits**: Apply 1-to-1 deterministic changes; run tests after
each edit.
6. **Flag judgement calls**: Document any decision points with options and trade-offs;
stop and await user decision.
7. **Equivalence proof**: Run the full test suite and type checker; report paired
before-and-after proof showing zero new regressions.

## Worked example

Consider upgrading `pydantic` from v1 to v2:

> **1. Baseline Measurement:**
> Command: `pytest tests/ -q`
> Result: 38 passed in 1.42s (pre-migration baseline green).
>
> **2. Target Version Verification:**
> Command: `pip index versions pydantic`
> Result: Verified `pydantic==2.7.4` available on PyPI.
>
> **3. Codebase Impact Audit (Filtered to this repo):**
> Upstream changelog lists 40+ breaking changes. Only 2 affect this codebase:
> - `@validator` deprecated in favor of `@field_validator`:
> `src/models/user.py:14` and `src/models/order.py:22`.
> - `.dict()` deprecated in favor of `.model_dump()`:
> `src/api/routes.py:88` and `src/services/billing.py:45`.
> *(Unused upstream changes such as ORM mode and root validators do not exist in
> this repository and are omitted.)*
>
> **4. Automated Codemod Execution:**
> Command: `bump-pydantic src/`
> Result: Applied mechanical updates across 4 files; diff inspected.
>
> **5. Judgement Call Stopped At:**
> `src/models/custom_types.py:31` uses `__get_validators__`, which has no 1-to-1
> replacement in v2. Two valid paths exist:
> - *Option A*: Implement `__get_pydantic_core_schema__` for core schema validation.
> - *Option B*: Wrap with `Annotated[T, PlainValidator(...)]`.
> Stopped to let user choose the serialization architecture.
>
> **6. Paired Equivalence Proof:**
> Command: `pytest tests/ -q`
> Result: 38 passed in 1.18s (equivalence proven across all 38 test cases).

## Output

Structure your migration report as follows:

1. **Baseline Test Evidence**: Starting test command, total test count,
names of any pre-existing failing tests, and type check status.
2. **Target Version Verification**: Exact command executed and target version
verified.
3. **Applicable Breaking Changes**: Filtered list of breaking changes affecting
THIS codebase, with `file:line` references and brief description.
4. **Tooling & Codemods**: Ecosystem migration commands run, files modified, and
transformations applied.
5. **Mechanical Changes Applied**: Summary of 1-to-1 edits and intermediate test
checks.
6. **Judgement Calls / Decisions Required** (if any): Unresolved architectural
choices, affected files, options with trade-offs, and stopping status.
7. **Equivalence & Verification Evidence**: Paired test suite command, before
count vs. after count, regression status (confirming no new failing tests),
and type checker results.
Loading