Skip to main content

axon4to5-migrate-code

Migrate Axon Framework 4 project code and configuration to Axon(iq) Framework 5. Migrates source code and wiring only — NOT stored data (event store contents / stored events, tracking tokens), which are left untouched.

Zur Installation springen

Quellinformationen

Repository
AxonIQ/agent-skills
Letzte Quellaktivität
25. Juli 2026 um 16:07
Erkannte Sprache von SKILL.md
Englisch
Sterne
2
Forks
0

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
86 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
axon4to5-migrate-code
description
Migrate Axon Framework 4 project code and configuration to Axon(iq) Framework 5. Migrates source code and wiring only — NOT stored data (event store contents / stored events, tracking tokens), which are left untouched.
argument-hint
framework=<axon|axoniq> configuration=<native|spring> mode=<single|project> [execution=<inline|subagent>] [source=<class|file|fqn>] [max-subagents=<0..N>] [auto=<true|false>]
disable-model-invocation
true
# axon4to5-migrate-code ## Goal > Fully (or as most as possible) compiling, green-test codebase on AF5, **same architecture as AF4**. > No DCB. No new patterns. Legacy event storage preserved. > > **Scope: code and configuration only.** This skill migrates source code and wiring. It does **NOT** > migrate stored data — the event store contents (stored events) and tracking tokens are left untouched. > Migrating to AF5 with the legacy event-storage layout keeps those stores compatible as-is; moving data > to a new storage layout (e.g. DCB) is out of scope. > The migration preserves the project's existing configuration style: a Spring Boot > project stays on Spring auto-config (recipes use `@Component` / `@Bean` > idioms); a plain framework-configuration project stays on the direct > `Configurer` API (recipes use `EventSourcingConfigurer` / > `MessagingConfigurer` / `CommandHandlingModule` / `EventSourcedEntityModule`). ## Available recipes (auto-listed) Run `bash scripts/list-recipes.sh` from the skill root directory. Output format: ``` - file: references/recipes/<dir>/RECIPE.md id: <id> title: <title> description: <description> applicable: | <applicable section content, or "(none)" if missing> ``` ## Inputs - `framework` (**required**): which Axon flavor to migrate. Currently supported values: `axon`, `axoniq`. Any other value → STOP. - `configuration` (**required**): how the application wires Axon. Currently supported values: `native`, `spring`. Any other value → STOP. - `mode` (required): what gets migrated in one invocation. - `single` — one element (a class, e.g. an Aggregate). Requires `source`. - `project` — the whole application (default: current working directory). `source` ignored. - `execution` (optional, default `inline`): how the orchestrator runs its steps. Only meaningful for `mode=project` — for `mode=single` it has no observable effect. - `inline` — main session does discovery + recipe runs sequentially. No `Agent` tool use. - `subagent` — orchestrator MAY dispatch via the `Agent` tool: discovery → `Explore` subagent, recipe sub-flow per item → `general-purpose` subagent (parallel batches). Useful for `project` mode on large codebases. - `source` (required for `mode=single`): hint identifying the thing to migrate (class name, file path, FQN). - `skip-openrewrite` (optional, default `false`): when `true`, the orchestrator SKIPS Pre-step 2 (the OpenRewrite bulk pass) and goes straight to the mode-specific producer. Use this when (a) OpenRewrite Phase 1 has already been run separately on the tree, (b) the caller is exercising a recipe in isolation, or (c) the project is not built with Maven/Gradle so the OpenRewrite plugin is unreachable. Values: `true` / `false`. Any other value → STOP. The downstream recipe must still tolerate both AF4-shaped and partially-migrated sources (see each recipe's `# Applicable` predicates). - `max-subagents` (optional, default `0`): max parallel `general-purpose` subagents for item processing in the drain loop. `mode=project` only — ignored for `mode=single`. `0` = inline (no subagents, sequential). `N > 0` = dispatch up to N items simultaneously as subagents; **BLOCKER_RESOLUTION always runs in main session** regardless of this value. Any non-integer or value < 0 → STOP. - `auto` (optional, default `false`): when `true`, never calls `AskUserQuestion` — all interactive decisions resolved automatically (see `## Auto mode`). Values: `true` / `false`. Any other value → STOP. ## Auto mode (`auto=true`) Orchestrator makes all decisions without `AskUserQuestion`. Every auto-resolved choice emits `⚙️ auto: <decision>` so the log stays auditable. | Decision point | Auto action | |---|---| | Ambiguous recipe match (`mode=single`) | Pick first candidate by `applicable` score. | | Blocker | Auto-select the Option the recipe marked `(Recommended)`; if none is marked, `skip`. A recommended migration path (e.g. saga `stateful-rewrite`) re-enters the recipe with that option id; `skip`/`revert` resolve in-place. See `BLOCKER_RESOLUTION.md § Auto mode`. | | Resume + selection-args mismatch | Args identical → auto-resume. Args differ → auto-start-over. | | Working tree mismatch on resume | Proceed; record `⚠️ auto: tree mismatch ignored` in `progress.md`. | | OpenRewrite step completes | Immediately continue to mode-specific producer. Do NOT pause or end session. | ## Durability **Load order — see § Recipe sub-flow.** FLOW.md first, then DURABILITY.md (second). Defines state files under `.axon4to5-migration/`, hooks across pre-steps + queue + recipe results + caller decisions, and commit protocol. Reads `progress.md` on entry to decide resume vs fresh. ## Pre-steps (common to every mode) These run **before** any mode-specific logic — independent of whether `mode=single`, `project`, or anything added later. 1. **Parse** — read `framework`, `configuration`, `mode`, `execution`, `skip-openrewrite`, `max-subagents`, `auto` from `$ARGUMENTS`. - If `framework` is missing or ∉ {`axon`, `axoniq`} → STOP and report unsupported framework. - If `configuration` is missing or ∉ {`native`, `spring`} → STOP and report unsupported configuration. - If `mode` is missing or ∉ {`single`, `project`} → STOP and report unsupported mode. - `execution` defaults to `inline` if missing. If present and ∉ {`inline`, `subagent`} → STOP and report unsupported execution. - `skip-openrewrite` defaults to `false` if missing. If present and ∉ {`true`, `false`} → STOP and report unsupported value. - `max-subagents` defaults to `0` if missing. If present and not a non-negative integer → STOP. - `auto` defaults to `false` if missing. If present and ∉ {`true`, `false`} → STOP. 2. **OpenRewrite** — **skipped entirely when `skip-openrewrite=true`.** Otherwise, internally invoke `axon4to5-openrewrite` via the `Skill` tool, passing `--framework $framework --commit false`. Do NOT pass `--commit true` or omit `--commit`; DURABILITY's `on:openrewrite-done` hook owns the single combined commit. This is a step of this orchestrator, not a separate command. Idempotent — safe even on a partially-migrated tree. If it fails → STOP and report the failure (no gap-filling on a broken bulk pass). When skipped, surface that fact in the eventual report (Notes or Learnings) so the caller knows the queue ran against unprocessed AF4 (or already-partially-migrated) sources and the recipes did all the work themselves. **`auto=true`: after this step returns (success or skip), immediately continue to the mode-specific producer — do NOT end the session or pause.** Only after pre-steps complete does the mode-specific producer below run. ## Modes ### `single` Migrate ONE element (one aggregate, one event processor, etc.) using exactly one recipe from the list above. Steps (after the common pre-steps): 1. **Match** — map user's request + `source` to ONE recipe in the auto-listed set. Primary signal: the catalog's `applicable` block (surface predicates against `$SOURCE` — annotations / type markers). Fallback signal: `id` + `title` + `description`. If ambiguous → ask user via `AskUserQuestion` to pick (show `title` to the user; dispatch by `id`). If no `applicable` block matches and description is also unclear → STOP and report. 2. **Execute** — `Read` the chosen recipe file under [`references/recipes/`](references/recipes/) (`<name>/RECIPE.md`) and execute it per the **Recipe sub-flow** ([`FLOW.md`](references/recipes/FLOW.md), already loaded). Recipe-local auxiliary files (examples, fixtures, supporting docs) live alongside it in the same `<name>/` directory. 3. **Verify** — behavior is preserved (no DCB, keep `AggregateBasedEventStorageEngine`, etc.). 4. **Report** — render the report (see Queue flow § Render report). MUST NOT: - Run without all required parameters resolved to a supported value. - Run multiple recipes in one invocation. - Migrate more than the single source named by the user. - Migrate anything outside the supported `(framework, configuration)` matrix — the rest of the codebase stays untouched. - Introduce DCB or swap event storage engine. ### `project` Migrate **everything in the working directory** that any recipe in the catalog declares applicable. `source` is ignored. Steps (after the common pre-steps): **Recipe loop** — iterate recipes in discovery order. For each recipe: 1. **Discover** — evaluate the recipe's `applicable` predicates across the codebase to produce candidate sources. - `execution=inline` → orchestrator scans inline using `Grep` / `Glob` / `Read`. - `execution=subagent` → dispatch one `Explore` subagent for this recipe. Read-only — no edits. - **Scan `.java` AND `.kt`, across all source roots.** JVM projects are mixed and Kotlin files often sit under `src/main/java/` (and vice-versa) — never filter candidates by extension or source directory. Key on the recipe's Axon annotations, not on path. See `DEFAULT.md § Source file conventions` (the `Explore` subagent must be told this too). 2. **Enqueue** — add `(recipe, source)` candidates. Deduplication is recipe's concern. 3. **Drain** — exhaust all pending items for **this recipe** before advancing to the next: - `max-subagents=0` (default) → inline, main session, sequentially. - `max-subagents=N` → main session acts as **coordinator**. Dispatches up to N pending items simultaneously as `general-purpose` subagents (single `Agent` message per batch). Each subagent executes ONE recipe sub-flow and returns a result block (`RESULT:` line + Notes + a `Learnings` field — complete authored entries, or an explicit `none — <why>`). The subagent **authors** the learning prose (it witnessed the run) but MUST NOT write `learnings.md` itself — the coordinator is the single safe writer under parallelism and stamps the date + commit sha, relaying each entry verbatim (see DURABILITY § Proactive Learnings). - ✅ Success / ⏭ Rejected / ❌ Failure → main records result, immediately dispatches next pending item. **No pause.** - 🚧 Blocker → **BLOCKER_RESOLUTION in main session**: `AskUserQuestion` if `auto=false`; auto-skip if `auto=true`. Resolved → re-dispatch same item to a new subagent. Not resolved → mark blocked, dispatch next pending item. - Main session never pauses unless waiting for user input on a blocker (`auto=false`). - **Fallback** — if a subagent cannot be spawned, process inline and continue. 4. **Mark recipe done** — `on:recipe-done` hook records status in `progress.md` Recipe status table. After all recipes drained → **Debugging loop** → **Finalize** → **Report**. **Context hygiene** — after every 5 items drained, emit this tip once (then reset counter): > 💡 Context is growing. Run `/clear` and re-invoke the skill — it resumes automatically from `.axon4to5-migration/progress.md`, no work is lost. MUST NOT: - Spawn a subagent under `execution=inline`. - Pass anything beyond `(recipe path, source, framework, configuration)` to a recipe subagent — context bloat defeats the parallelism win. - Cross repository boundaries during discovery. - Halt the queue on a single Failure — record and drain the rest. - Introduce DCB or swap event storage engine. ## Queue flow `$SOURCE` is referenced throughout the recipe sub-flow as the argument passed to the skill from `source`. > `[[Execute recipe sub-flow]]` = [`references/recipes/FLOW.md`](references/recipes/FLOW.md), loaded at skill start. `[[Resolve blocker]]` = [`references/recipes/BLOCKER_RESOLUTION.md`](references/recipes/BLOCKER_RESOLUTION.md), budget = 1 attempt per item; on exhaustion item is marked blocked and drain continues. ### Single mode flow ```mermaid flowchart TD A[Skill invoked] --> PARSE["<b>Parse</b><br/>framework, configuration, source"] PARSE --> ORW[["<b>OpenRewrite</b><br/>(internal Skill, idempotent)"]] ORW -- fail --> XORW[STOP: bulk-rewrite failed] ORW -- ok --> B["list-recipes (catalog)"] B --> MATCH{"<b>Match</b><br/>request + source → recipe"} MATCH -- ambiguous --> ASK["AskUserQuestion<br/>(show titles, dispatch by id)"] ASK --> EXEC MATCH -- "no match" --> XNOMATCH[STOP: no applicable recipe] MATCH -- matched --> EXEC[["<b>Execute</b> recipe sub-flow<br/>(FLOW.md)"]] EXEC --> R{<b>RESULT?</b>} R -- "Blocker (first attempt)" --> BR[["<b>Resolve blocker</b><br/>(BLOCKER_RESOLUTION.md)"]] BR --> BRQ{"Resolved?<br/>budget = 1"} BRQ -- yes --> EXEC BRQ -- "no / exhausted" --> BLK["mark blocked<br/>(🚧 caller must resolve)"] R -- "Blocker (already retried)" --> BLK R -- "Success / Rejected / Failure" --> VER["<b>Verify</b><br/>behavior preserved<br/>same architecture as AF4"] VER --> RPT["<b>Report</b> &amp; END"] BLK --> RPT ``` ### Project mode flow ```mermaid flowchart TD A[Skill invoked] --> PARSE["<b>Parse</b><br/>framework, configuration, execution"] PARSE --> ORW[["<b>OpenRewrite</b><br/>(internal Skill, idempotent)"]] ORW -- fail --> XORW[STOP: bulk-rewrite failed] ORW -- ok --> B["list-recipes (catalog)"] B --> RL{"<b>Next recipe</b><br/>in order?"} RL -- "yes: &lt;recipe&gt;" --> DISC["<b>Discover</b><br/>execution=inline: Grep/Glob<br/>execution=subagent: 1 Explore<br/>→ <b>Enqueue</b> items"] DISC --> Q[(Recipe queue)] Q --> L{"<b>Drain</b><br/>pending?"} L -- yes --> INP["pick next → in-progress"] INP --> W[["<b>Execute</b> recipe sub-flow<br/>execution=inline: main session<br/>execution=subagent: general-purpose (parallel batch)"]] W --> R{<b>RESULT?</b>} R -- "Blocker (first attempt)" --> BR[["<b>Resolve blocker</b><br/>(BLOCKER_RESOLUTION.md)"]] BR --> BRQ{"Resolved?<br/>budget = 1"} BRQ -- yes --> W BRQ -- "no / exhausted" --> BLK["mark blocked<br/>(🚧 caller must resolve)"] R -- "Blocker (already retried)" --> BLK R -- "Success / Rejected / Failure" --> VER["<b>Verify</b><br/>behavior preserved<br/>same architecture as AF4"] VER --> DONE["mark done in queue"] DONE --> Q BLK --> Q L -- "no (recipe drained)" --> RDONE["<b>on:recipe-done</b><br/>update Recipe status table"] RDONE --> RL RL -- "no more recipes" --> DBG_COMP
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen