diff --git a/plugins/code-modernization/.claude-plugin/plugin.json b/plugins/code-modernization/.claude-plugin/plugin.json index 9bc35ac..431fe9b 100644 --- a/plugins/code-modernization/.claude-plugin/plugin.json +++ b/plugins/code-modernization/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "code-modernization", - "description": "Modernize legacy codebases (COBOL, legacy Java/C++, monolith web apps) with a structured preflight / assess / map / extract-rules / brief / reimagine / transform / harden workflow, an interactive topology viewer, and specialist review agents", + "description": "Modernize legacy codebases (COBOL, legacy Java/C++/.NET, monolith web apps) with a structured preflight / assess / map / extract-rules / brief / (reimagine | transform | uplift) / harden / status workflow. Cross-stack rewrites, greenfield reimagining, and same-stack version uplifts (e.g. .NET Framework → .NET 8); an interactive topology viewer; specialist agents; and optional dynamic-workflow orchestration with adversarial verification.", "author": { "name": "Anthropic", "email": "support@anthropic.com" diff --git a/plugins/code-modernization/README.md b/plugins/code-modernization/README.md index a56aaa3..2a1e180 100644 --- a/plugins/code-modernization/README.md +++ b/plugins/code-modernization/README.md @@ -12,7 +12,7 @@ preflight → assess → map → extract-rules → brief → reimagine | transfo The three build paths are different *methods*, chosen by the brief's recommended pattern: **`transform`** (cross-stack rewrite from extracted intent), **`reimagine`** (greenfield rebuild), and **`uplift`** (same-stack version bump — e.g. .NET Framework → .NET 8 — that preserves the code and fixes only the version deltas). -The discovery commands (`assess`, `map`, `extract-rules`) build artifacts under `analysis//`. The `brief` command synthesizes them into an approval gate. The build commands (`reimagine`, `transform`, `uplift`) write new code under `modernized/`. The `harden` command audits the legacy system and produces a reviewable remediation patch. Each step has a dedicated slash command, and specialist agents (legacy analyst, business rules extractor, architecture critic, security auditor, test engineer) are invoked from within those commands — or directly — to keep the work honest. +The discovery commands (`assess`, `map`, `extract-rules`) build artifacts under `analysis//`. The `brief` command synthesizes them into an approval gate. The build commands (`reimagine`, `transform`, `uplift`) write new code under `modernized/`. The `harden` command audits the legacy system and produces a reviewable remediation patch. Each step has a dedicated slash command, and specialist agents (such as legacy analyst, business rules extractor, architecture critic, security auditor, test engineer, version delta analyst, scaffolder) are invoked from within those commands — or directly — to keep the work honest. ## Expected layout @@ -27,13 +27,13 @@ mkdir -p legacy && ln -s /path/to/your/legacy/codebase legacy/billing The commands degrade gracefully, but each of these makes the output meaningfully better — run `/modernize-preflight ` to check all of them at once and get a readiness report: - **Analysis tools**: [`scc`](https://github.com/boyter/scc) (LOC + complexity + COCOMO) or [`cloc`](https://github.com/AlDanial/cloc); [`lizard`](https://github.com/terryyin/lizard) for portfolio mode. Without them, metrics fall back to `find`/`wc` and get coarser. -- **A working build toolchain** for the legacy stack (e.g. GnuCOBOL for COBOL) — required before `/modernize-transform` can prove behavioral equivalence, and verified by preflight with a real smoke compile against your code. +- **A working build toolchain** for the legacy stack (e.g. GnuCOBOL for COBOL) — it enables `/modernize-transform`'s *strongest* equivalence proof (live dual execution), and is verified by preflight with a real smoke compile. It is not strictly required: when the legacy stack can't build locally (common for CICS/IMS, or .NET Framework on Linux), equivalence falls back to recorded-trace / golden-master tests, and preflight reports Ready-with-gaps rather than blocking. - **The whole system in the tree**: deployment descriptors (JCL, CICS definitions, route configs), copybooks/includes, and DDL/schemas. Entry-point detection and data lineage in `/modernize-map` are guesswork without them. - **Production telemetry** (optional): an observability MCP server or batch job logs enable the runtime overlay in `/modernize-assess` and timing annotations on critical paths. ## Dynamic workflow orchestration -On Claude Code builds that ship the **Workflow tool**, four commands upgrade +On Claude Code builds that ship the **Workflow tool**, five commands upgrade from "spawn a few agents and merge by hand" to scripted orchestration (`workflows/*.js` in this plugin). The commands detect the tool and fall back to direct subagent fan-out on older builds — no configuration needed. @@ -50,10 +50,14 @@ These fan out more agents than the fallback path (tens, on a large estate) — the commands state the expected count before launching. Invoking the slash command is the opt-in. -A structural security property comes with the conversion: workflow extraction -agents return **schema-validated data**, and only the orchestrating session -writes artifacts. Analysis agents never touch disk. See the next two sections -for why that matters. +A useful property comes with the conversion: workflow extraction agents return +**schema-validated data**, and the orchestrating session is what writes the +artifacts — so analysis output flows through a typed boundary, not a +free-form file write. Note this is a *workflow-shape* property, not a tool-lock: +the analysis agents still carry `Bash` (they need `grep`/`scc`/`npm audit`), +so "read-only" is enforced by their system prompt + the data-only return value, +not by removing write tools. The real injection boundary is the fence and the +typed return — see the next two sections. ## Untrusted code & prompt injection @@ -64,22 +68,25 @@ steering what lands in `BUSINESS_RULES.md` or `SECURITY_FINDINGS.md` — which downstream commands treat as trusted. Defenses, in layers: every agent's system prompt pins file content as data-never-instructions and reports instruction-shaped text as a finding (`injectionFlags` in workflow results — -surfaced prominently when non-empty); analysis agents are read-only, with -artifact writes happening only in the orchestrating session; citation +surfaced prominently when non-empty); analysis agents are instructed read-only +and return typed data, with artifact writes happening in the orchestrating +session (prompt- and shape-enforced — they retain `Bash` for `grep`/`scc`, so +this is discipline, not a tool lock); citation referees refute any rule or finding supported by comments rather than executable code; agent-produced text is **fenced as untrusted data** when it flows into a downstream agent's prompt (referees re-derive claims from the cited code rather than trusting the finder's description — second-order injection); workflow inputs that become filesystem paths are validated against a strict name pattern; the one write-capable workflow agent -(`scaffolder`) runs with an explicit minimal tool list and a write scope of -exactly its own service directory; and `/modernize-brief` remains a human +(`scaffolder`) is told to write only within its own service directory (enforce +this with the workspace `settings.json` below — the instruction alone is not a +sandbox); and `/modernize-brief` remains a human approval gate before anything is executed against. Treat discovery artifacts from code you don't trust with the same skepticism as the code itself. ## Secret handling -Legacy systems routinely contain live credentials, and assessment artifacts get committed and shared. **Every agent in this plugin masks credential values** — findings, rule-card parameters, architecture notes, and test fixtures cite `file:line` with a masked preview (`AKIA****`), never the value. When credentials are found, a per-credential inventory (type, location, blast radius, rotation recommendation) is written to `analysis//SECRETS.local.md`, which the commands gitignore before writing; on non-git projects the quarantine file goes to `~/.modernize//` instead. `/modernize-harden` splits its remediation diff so credential-removal hunks (which necessarily contain the raw value) land in a gitignored `security_remediation.local.patch`, never the shareable patch. Pass `--show-secrets` to include raw values in the quarantine file (and only there). If you ran an earlier version of this plugin on a real system, check whether `analysis/` artifacts containing credentials were committed or shared, and rotate anything that was. +Legacy systems routinely contain live credentials, and assessment artifacts get committed and shared. **Every agent in this plugin keeps credential values out of shared artifacts.** The analysis agents mask-and-cite — `file:line` with a masked preview (`AKIA****`), never the value — in findings, rule-card parameters, and architecture notes. The code-writing agents (`test-engineer`, `scaffolder`) never carry a legacy credential into a fixture at all: they substitute fake same-shape values and env-var placeholders. When credentials are found, a per-credential inventory (type, location, blast radius, rotation recommendation) is written to `analysis//SECRETS.local.md`, which the commands gitignore before writing; on non-git projects the quarantine file goes to `~/.modernize//` instead. `/modernize-harden` splits its remediation diff so credential-removal hunks (which necessarily contain the raw value) land in a gitignored `security_remediation.local.patch`, never the shareable patch. Pass `--show-secrets` to include raw values in the quarantine file (and only there). If you ran an earlier version of this plugin on a real system, check whether `analysis/` artifacts containing credentials were committed or shared, and rotate anything that was. ## Commands @@ -103,10 +110,10 @@ Build a dependency and topology map of the **legacy** system: program/module cal Mine the business rules embedded in the legacy code — calculations, validations, eligibility, state transitions, policies — into Given/When/Then "Rule Cards" with `file:line` citations and confidence ratings. Spawns three `business-rules-extractor` agents in parallel (calculations, validations, lifecycle). Produces `analysis//BUSINESS_RULES.md` and `analysis//DATA_OBJECTS.md`. ### `/modernize-brief [target-stack]` -Synthesize the discovery artifacts into a phased **Modernization Brief** — the single document a steering committee approves and engineering executes: target architecture, strangler-fig phase plan with entry/exit criteria, persona-based business walkthroughs (the section non-technical approvers actually read), behavior contract, validation strategy, open questions, and an approval block. Reads `ASSESSMENT.md`, `TOPOLOGY.html`, and `BUSINESS_RULES.md` and **stops if any are missing** — run the discovery commands first. Produces `analysis//MODERNIZATION_BRIEF.md` and enters plan mode as a human-in-the-loop gate. +Synthesize the discovery artifacts into a phased **Modernization Brief** — the single document a steering committee approves and engineering executes: target architecture, strangler-fig phase plan with entry/exit criteria, persona-based business walkthroughs (the section non-technical approvers actually read), behavior contract, validation strategy, open questions, and an approval block. Reads `ASSESSMENT.md`, `topology.json` (not the `TOPOLOGY.html` viewer — the brief parses the JSON, whose `flows` drive the persona walkthroughs), and `BUSINESS_RULES.md`, and **stops if any are missing** — run the discovery commands first. Produces `analysis//MODERNIZATION_BRIEF.md` and enters plan mode as a human-in-the-loop gate. ### `/modernize-reimagine ` -Greenfield rebuild from extracted intent rather than a structural port. Mines a spec (`analysis//AI_NATIVE_SPEC.md`), designs a target architecture and has it adversarially reviewed (`analysis//REIMAGINED_ARCHITECTURE.md`), then **scaffolds services with executable acceptance tests** under `modernized/-reimagined/` and writes a `CLAUDE.md` knowledge handoff for the new system. Two human-in-the-loop checkpoints. Spawns `business-rules-extractor`, `legacy-analyst` (×2), `architecture-critic`, and general-purpose scaffolding agents. +Greenfield rebuild from extracted intent rather than a structural port. Mines a spec (`analysis//AI_NATIVE_SPEC.md`), designs a target architecture and has it adversarially reviewed (`analysis//REIMAGINED_ARCHITECTURE.md`), then **scaffolds services with executable acceptance tests** under `modernized/-reimagined/` and writes a `CLAUDE.md` knowledge handoff for the new system. Two human-in-the-loop checkpoints. Spawns `business-rules-extractor`, `legacy-analyst` (×2), `architecture-critic`, and the `scaffolder` agent (Phase E). ### `/modernize-transform ` Surgical, single-module strangler-fig rewrite. Plans first (HITL gate), then writes characterization tests via `test-engineer`, then an idiomatic target implementation under `modernized///`, proves equivalence by running the tests, and produces `TRANSFORMATION_NOTES.md` mapping legacy → modern with deliberate deviations called out. Reviewed by `architecture-critic`. @@ -128,7 +135,7 @@ Security hardening pass on the **legacy** system: OWASP/CWE scan, dependency CVE - **`security-auditor`** — Reviews code for auth, input validation, secret handling, and dependency CVEs. Tuned for the kinds of issues that appear when translating security primitives across stacks (e.g., session handling from servlet to stateless JWT). Used by `assess` and `harden`. - **`test-engineer`** — Writes characterization, contract, and equivalence tests that pin legacy behavior so transformation can be proven correct. Flags tests that exercise code paths without asserting outcomes. Used by `transform` and `uplift`. - **`version-delta-analyst`** — For **same-stack uplifts**: finds the breaking/behavioral changes between two versions of one stack that actually bite a given codebase, and drives the ecosystem migration tool. Produces a delta catalog (API-removed / silent-behavioral / project-system / dependency), preserving the code rather than redesigning it. Used by `uplift`. -- **`scaffolder`** — Builds one service of a reimagined system from the approved architecture and spec: skeleton, domain model, API stubs, executable acceptance tests. Write scope is exactly its own `modernized/...//` directory; treats the spec's imperative-sounding content as data, since the spec derives from untrusted legacy code. Used by `reimagine` (Phase E). +- **`scaffolder`** — Builds one service of a reimagined system from the approved architecture and spec: skeleton, domain model, API stubs, executable acceptance tests. Instructed to write only within its own `modernized/...//` directory (enforce with the workspace `settings.json` below); treats the spec's imperative-sounding content as data, since the spec derives from untrusted legacy code. Used by `reimagine` (Phase E). ## Installation diff --git a/plugins/code-modernization/agents/version-delta-analyst.md b/plugins/code-modernization/agents/version-delta-analyst.md index 91aa5f3..0a2fde4 100644 --- a/plugins/code-modernization/agents/version-delta-analyst.md +++ b/plugins/code-modernization/agents/version-delta-analyst.md @@ -1,6 +1,6 @@ --- name: version-delta-analyst -description: Identifies the breaking changes between two versions of the SAME stack (e.g. .NET Framework 4.8 → .NET 8, Spring Boot 2 → 3, Python 2 → 3) that actually bite a given codebase, and drives the ecosystem's migration tooling. Use for same-stack uplifts, where code is preserved and tweaked — not rewritten from intent. +description: Identifies the breaking changes between two versions of the SAME stack (e.g. .NET Framework 4.8 → .NET 8, Java 8 → 17/21, Spring Boot 2 → 3) that actually bite a given codebase, and drives the ecosystem's migration tooling. Use for same-stack uplifts, where code is preserved and tweaked — not rewritten from intent. (Note: some "same-stack" bumps are really rewrites — Python 2 → 3 with pervasive str/bytes, AngularJS → Angular — where minimal-diff fails; flag those for /modernize-transform.) tools: Read, Glob, Grep, Bash --- @@ -26,38 +26,70 @@ delta for this migration; report only what bites *here*, with `file:line`. ## Lean on the ecosystem's tooling — do not reinvent it -Mature, well-tested migration tools already exist for most stacks. **Detect and -run the right one, then own the residue** (the judgment calls and silent -behavioral changes it can't make). Examples: +Mature, well-tested migration tools already exist for most stacks. **Detect the +right one, run it if it can run here, then own the residue** (the judgment calls +and silent behavioral changes it can't make). -- **.NET**: `dotnet tool` → `upgrade-assistant`; the .NET **Portability Analyzer** (`apiport`); `try-convert` (project-system → SDK-style). -- **Java / Spring**: **OpenRewrite** recipes (Spring Boot 2→3, Jakarta EE, JUnit 4→5); `jdeprscan`; `jdeps`. -- **Python**: `pyupgrade`, `2to3`, `python-modernize`. -- **JS/TS / Angular**: `ng update`, framework codemods, `npx @angular/cli`. -- **Node**: package-specific codemods, `npx` codemod runners. +Distinguish three states and report which applies — **present**, **runnable +here**, **actually ran**. Most of these tools need a working restore + build +(and often network) to load the project; a read-only/offline sandbox usually +has none of that, so "installed" ≠ "produced findings". **Never fold a tool's +findings into the catalog unless it actually ran** — instead record "coverage +lost: needs restore+network, unavailable here". -Run the tool if it's installed, capture its raw output, and fold its findings -into the catalog. Where no tool exists or the tool punts, that residue is -exactly your value-add. **Never present a hand-built catalog as complete if a -standard tool for this stack exists and was not run** — say it wasn't available -and what coverage was lost. +- **.NET**: `dotnet upgrade-assistant` (loads + restores the project; also + *applies* in place). `try-convert` (project-system → SDK-style). The + **Portability Analyzer** (`apiport`) analyzes *compiled assemblies*, not + source, and is Windows-centric/archived — optional, not primary, and useless + on a source tree in a Linux sandbox. +- **Java / Spring**: **OpenRewrite** — `mvn rewrite:dryRun` is genuinely + headless and emits a patch (the most reliable of these; lean on it). + `jdeprscan`, `jdeps` for the analysis side. +- **Python**: `pyupgrade` (source-level, runnable). `2to3` is deprecated and + removed in Python 3.13; `python-modernize` is abandoned — do not rely on them. +- **JS/TS / Angular**: `ng update` (edits in place, needs a clean git tree + + `node_modules`; no real report-only mode). + +Where no tool exists, the tool punts, or it can't run here, that residue is +exactly your value-add — but say so explicitly rather than implying full +coverage. ## Delta categories (cover each) -- **API removed / changed** — types, methods, signatures gone or altered in the - target (e.g. .NET `AppDomain`, Remoting, WCF server, `System.Web`/WebForms, - `BinaryFormatter`; Jakarta `javax.*` → `jakarta.*`). +The catalog uses four top-level buckets, but the highest-blast-radius landmines +hide *inside* them — name them explicitly when you find them, don't let them +disappear into a one-liner: + +- **API removed / changed** — types, methods, signatures gone or altered (e.g. + .NET `AppDomain`, Remoting, WCF server, `System.Web`/WebForms, + `BinaryFormatter`; Jakarta `javax.*` → `jakarta.*`, removed JDK APIs). **Also + in this bucket: reflection & strong-encapsulation breakage** — Java 17 JPMS + strong encapsulation (`--illegal-access` gone → `InaccessibleObjectException` + at runtime for `setAccessible`/deep reflection; bites old Jackson/Hibernate/ + Spring); .NET trimming/AOT/single-file breaking `Type.GetType(string)`, DI, + and serializers. These fail *at runtime on the code path*, so flag them + test-before-touch. - **Silent behavioral** — compiles and runs, *different result*. The dangerous - class, because nothing fails loudly: default culture/encoding, TLS defaults, - serialization formats, `DateTime`/timezone handling, floating-point, async - context, collection ordering. Flag every one of these as **test-before-touch**. + class, nothing fails loudly. Call out **globalization/locale** specifically: + .NET 5+ switched to **ICU** (vs NLS), silently changing `string.Compare`, + casing, sort order, and `DateTime` parsing — the canonical Framework→.NET + trap. Plus: default encoding, TLS defaults, serialization formats, + `DateTime`/timezone, floating-point, async context, collection ordering. + Flag every one as **test-before-touch**. - **Project-system / build** — `packages.config` → `PackageReference`, - non-SDK → SDK-style `.csproj`, `app.config`/`web.config` → - `appsettings.json`, target-framework monikers, build props. + non-SDK → SDK-style `.csproj`, target-framework monikers, build props. **Also: + the hosting / runtime-config model** — `Global.asax`/IIS → `Program.cs`/ + Kestrel; `web.config`/`ConfigurationManager.AppSettings` → `appsettings.json`/ + `IConfiguration` (not just a file-format move — it's an access-pattern API + delta touching every config read). And **analyzer/compiler tightening** that + produces *new build failures*: nullable reference types, warnings-as-errors, + implicit usings, blocked internal JDK APIs under `--release`. - **Dependency** — packages with no target-version support, packages needing a major bump that carries its *own* breaking changes (e.g. EF6 → EF Core), or packages with no equivalent on the target. **Dependency deltas are where - same-stack migrations most often stall — never under-report them.** + same-stack migrations most often stall — never under-report them**, and note + that a mid-graph major bump (EF6→EF Core, `javax`→`jakarta`) forces a + coordinated cut across all consumers, not a leaf-by-leaf fix. ## Delta Card format diff --git a/plugins/code-modernization/assets/topology-viewer.html b/plugins/code-modernization/assets/topology-viewer.html index 70575d5..e2d2253 100644 --- a/plugins/code-modernization/assets/topology-viewer.html +++ b/plugins/code-modernization/assets/topology-viewer.html @@ -3,6 +3,10 @@ + + System topology