modernize-uplift
Uplift $system from $source_version to $target_version: same stack, newer version.
The code is legacy/$system, often a symlink to where it really lives: say where it points (readlink legacy/$system) in one line before you start. If legacy/$system does not exist, stop and say so: nothing can run without the code, so the fix is /code-modernization:modernize $system --source <path to the code>. Run every subagent in the foreground and wait for its result: never end your turn while one is still running. Stop any server or other process you started (a legacy app on a local port, a watcher) before you finish, and say you did.
This is not transform, which extracts intent and rewrites idiomatically. Here the code is good
and only needs to run on a newer runtime. Preserve structure and make the smallest diffs that compile
and behave identically on the target, driven by the known breaking changes between the two
versions, not by re-deriving business logic. The optional fourth argument $project_pattern scopes the
work to matching projects.
The strong case is a real dual run. If both runtimes execute here, one test suite runs on both and
the equivalence proof is a differential test. It is not always available: .NET can multi-target one
test project (net48;net8.0) but net48 runs only on Windows or Mono; Java 8 to 17 is the whole build
run under two JDK toolchains; Python 2 cannot import an un-rewritten module under Python 3. When both
cannot run here, equivalence falls back, as in transform, to characterization tests pinned to
recorded outputs on the target only. That is fine, but label it honestly (Step 0.3, Step 7).