1---
2name: meta-migration-assistant
3visibility: experimental
4invocation: experimental_internal
5disable-model-invocation: true
6description: "Use this meta-skill instead of answering directly when the user needs a concrete migration plan that benefits from multi-skill orchestration across migration classification, authoritative guide lookup, optional repo diff inspection, and step-by-step validation planning."
7kind: meta
8meta_priority: 50
9always: false
10final_text_mode: "step:write_plan"
11triggers:
12 - "migration plan"
13 - "migration checklist"
14 - "practical migration checklist"
15 - "migrate from"
16 - "migrate"
17 - "upgrade from"
18 - "CommonJS to native ESM"
19 - "CommonJS to ESM"
20 - "CJS to ESM"
21 - "native ESM"
22 - "rollout risks"
23 - "升级指南"
24 - "迁移方案"
25 - "迁移步骤"
26provenance:
27 origin: opensquilla-original
28 license: Apache-2.0
29composition:
30 steps:
31 - id: migration_intake
32 kind: llm_chat
33 with:
34 system: "You extract migration request boundaries and decide whether clarification is required."
35 task: |
36 Extract the requested migration source, target, version context, and
37 repository scope from the user request. Set NEEDS_CLARIFICATION: yes
38 only when the source or target stack is absent or the request is too
39 generic to classify safely.
40
41 User request:
42 {{ inputs.user_message | xml_escape | truncate(1400) }}
43
44 Return exactly:
45 SOURCE_STACK: <source stack/version, or MISSING_SOURCE_STACK>
46 TARGET_STACK: <target stack/version, or MISSING_TARGET_STACK>
47 VERSION_CONTEXT: <version/runtime/package context, or unknown>
48 REPO_SCOPE: <current diff|current branch|named repo|not specified>
49 NEEDS_CLARIFICATION: <yes|no>
50 MISSING_FIELDS:
51 - <source_stack|target_stack|none>
52 CLARIFY_REASON: <one concise reason, or none>
53 - id: migration_clarify
54 kind: user_input
55 depends_on: [migration_intake]
56 when: "'NEEDS_CLARIFICATION: yes' in outputs.migration_intake"
57 clarify:
58 mode: form
59 intro: |
60 迁移目标还不够明确。请补齐源技术栈和目标技术栈,我再生成可执行迁移清单。
61 nl_extract: true
62 fields:
63 - name: source_stack
64 type: string
65 required: true
66 prompt: "源技术栈/版本 / Source stack or version"
67 max_chars: 160
68 - name: target_stack
69 type: string
70 required: true
71 prompt: "目标技术栈/版本 / Target stack or version"
72 max_chars: 160
73 - name: version_context
74 type: string
75 prompt: "运行时、框架或包版本 / Runtime, framework, or package versions"
76 max_chars: 240
77 - name: repo_scope
78 type: string
79 prompt: "仓库范围 / Repository scope"
80 max_chars: 200
81 cancel_keywords: ["算了", "取消", "cancel", "stop", "abort"]
82 timeout_hours: 24
83 - id: classify
84 kind: llm_classify
85 depends_on: [migration_intake, migration_clarify]
86 output_choices:
87 - PY2_TO_PY3
88 - VUE2_TO_VUE3
89 - REACT_CLASS_TO_HOOKS
90 - OPENAI_V0_TO_V1
91 - CJS_TO_ESM
92 - OTHER
93 with:
94 text: |
95 User said: {{ inputs.user_message | xml_escape | truncate(1400) }}
96
97 Migration intake:
98 {{ outputs.migration_intake | truncate(1200) }}
99
100 Clarification answers (may be empty when not needed):
101 {{ inputs.get('collected', {}).get('migration_clarify', {}) | tojson }}
102
103 Identify the migration kind.
104 Ignore benchmark wrappers, timestamps, locale hints, and generic
105 "return inline" instructions. The actual user request may appear
106 after benchmark constraints; classify from the explicit source and
107 target migration words, not from the preamble.
108
109 Decision rules:
110 - PY2_TO_PY3 → mentions Python 2 → 3 / py2 → py3
111 - VUE2_TO_VUE3 → mentions Vue 2 → Vue 3 / options → composition
112 - REACT_CLASS_TO_HOOKS → React class component → hooks
113 - OPENAI_V0_TO_V1 → openai SDK v0 → v1, ChatCompletion → chat.completions.create
114 - CJS_TO_ESM → any mention of CommonJS, CJS, native ESM,
115 require(), module.exports, exports.*, import/export migration,
116 "from CommonJS to native ESM", or "CJS to ESM"
117 - OTHER → any other migration request
118
119 If the text contains "CommonJS" and "native ESM", return exactly
120 CJS_TO_ESM even if other benchmark/context words appear first.
121 - id: fetch_guide
122 kind: skill_exec
123 skill: multi-search-engine
124 depends_on: [classify, migration_clarify]
125 with:
126 max_results: 8
127 engines:
128 - duckduckgo
129 - brave
130 query: |
131 Authoritative migration guide for the user's actual migration.
132 Classifier verdict: {{ outputs.classify }}.
133 Migration intake:
134 {{ outputs.migration_intake | truncate(1000) }}
135 Clarification answers:
136 {{ inputs.get('collected', {}).get('migration_clarify', {}) | tojson }}
137 If the request mentions CommonJS, CJS, native ESM, require(),
138 module.exports, or import/export migration, search specifically for
139 current CommonJS to native ES Modules migration guidance covering
140 package.json type/exports, extension rules, directory imports,
141 JSON imports/import attributes, createRequire interop, TypeScript
142 NodeNext, test runners, dual publish, and consumer compatibility.
143 Ignore benchmark preambles, timestamps, and unrelated local context.
144
145 User request:
146 {{ inputs.user_message | xml_escape | truncate(500) }}
147 - id: repo_context
148 kind: skill_exec
149 skill: git-diff
150 depends_on: [classify]
151 when: |
152 (
153 'current diff' in (inputs.user_message | lower)
154 or 'this diff' in (inputs.user_message | lower)
155 or 'current branch' in (inputs.user_message | lower)
156 or 'pull request' in (inputs.user_message | lower)
157 or 'merge request' in (inputs.user_message | lower)
158 or 'already changed' in (inputs.user_message | lower)
159 or 'worktree' in (inputs.user_message | lower)
160 or '当前 diff' in inputs.user_message
161 or '当前分支' in inputs.user_message
162 )
163 with:
164 mode: cached_fallback_worktree
165 - id: write_plan
166 kind: llm_chat
167 depends_on: [classify, migration_clarify, fetch_guide, repo_context]
168 with:
169 system: |
170 You write migration checklists. Answer the user's requested
171 migration only. Do not change the migration domain based on locale,
172 timezone, unrelated repository diffs, or general environment
173 context. If the request mentions CommonJS, CJS, native ESM,
174 require/module.exports, or import/export migration, the answer must
175 be exclusively about CommonJS to native ESM. Return Markdown directly;
176 do not wrap the entire answer in a fenced code block.
177 task: |
178 Migration kind: {{ outputs.classify }}
179 Migration intake:
180 {{ outputs.migration_intake | truncate(1200) }}
181 Clarification answers:
182 {{ inputs.get('collected', {}).get('migration_clarify', {}) | tojson }}
183 User request:
184 {{ inputs.user_message | xml_escape | truncate(1200) }}
185
186 Hard override before writing:
187 - If the user request contains CommonJS, CJS, native ESM,
188 require/module.exports, or import/export migration wording, set
189 EFFECTIVE_KIND=CJS_TO_ESM.
190 - If EFFECTIVE_KIND=CJS_TO_ESM, the Summary heading and every
191 section must be about CommonJS to native ES Modules. Do not write
192 about timezone, cloud, Python, Vue, React hooks, OpenAI SDK, or
193 any unrelated migration.
194 - If classifier output conflicts with explicit source/target words
195 in the user request, ignore the classifier output.
196
197 Authoritative guide excerpt:
198 {{ outputs.fetch_guide | truncate(2000) }}
199
200 Optional repository diff context:
201 {{ outputs.repo_context | truncate(3000) }}
202
203 Task lock:
204 - The user's requested migration kind is authoritative. Do not let
205 repository diff context or unrelated local changes redefine the
206 migration. If the user asks for CommonJS/CJS to native ESM, the
207 final answer must be a CommonJS-to-ESM migration checklist.
208 - Apply this final-layer classifier override: if the user request
209 contains CommonJS, CJS, native ESM, require/module.exports, or
210 import/export migration wording, treat the effective migration
211 kind as CJS_TO_ESM even if `outputs.classify` says OTHER.
212 - Do not expose classifier labels such as OTHER, CJS_TO_ESM,
213 VUE2_TO_VUE3, or internal routing decisions in the final answer.
214 - Repository context is optional and only evidentiary. If it does
215 not explicitly show files relevant to the classified migration,
216 ignore it and say repository files were not verified.
217 - Do not invent repo-specific files, package names, scripts, or
218 changes. Use grep commands for discovery instead.
219 - Do not include write/commit commands such as `git add`,
220 `git commit`, `eslint --fix`, or codemods inside validation
221 sections. Validation commands are read-only.
222 - Benchmark/no-write constraint: the final answer must not include
223 file creation or mutation commands in validation or smoke-test
224 sections. Forbidden examples include heredocs, shell redirection
225 (`>`, `>>`), `cat >`, `tee`, `touch`, `mkdir`, `cp`, `mv`,
226 `rm`, `npm init`, config generators, codemods, and `python -c`
227 / `node -e` snippets that write files. If a smoke test normally
228 needs a temporary fixture, describe it as a manual implementation
229 step, not as a validation command.
230 - Do not use unverified concrete entrypoint paths such as
231 `index.js`, `server.js`, or package-specific test commands unless
232 they came from repository evidence. Use discovery commands first
233 and phrase path-specific commands as templates.
234 - If the authoritative guide excerpt is about a different migration
235 domain, ignore it completely. Do not mention that it was ignored.
236 - Do not wrap the whole response in ```markdown fences.
237
238 Produce a concrete migration checklist as Markdown with these sections:
239 ## Summary
240 ## Evidence boundary
241 ## Breaking changes
242 ## Step-by-step
243 ## Repository discovery checklist
244 ## Files likely affected (grep patterns the user can run)
245 ## Validation (tests/checks to confirm the migration)
246 ## Rollout and rollback
247
248 Quality contract:
249 - Keep the answer dense and complete in one response. Target
250 1,200-1,800 words; prefer compact tables and bullets over long
251 explanations or large config snippets.
252 - If repository context is empty, unreadable, or generic, say so
253 clearly; do not invent files or package names.
254 - If repository context is present but about another migration,
255 ignore it and explicitly state that it is unrelated to the user's
256 requested migration.
257 - Prefer `rg` commands for grep patterns and make them copyable.
258 - For CJS_TO_ESM discovery, include these command families:
259 `node -v`, `npm pkg get type main exports scripts`,
260 `git grep -nE "require\(|module\.exports|exports\."`,
261 `git grep -nE "require\([^'\"\`]+\)"`,
262 `git grep -nE "from ['\"]\./[^'\"]+['\"]|import\(['\"]\./[^'\"]+['\"]\)"`,
263 `git grep -nE "\b(__dirname|__filename)\b"`,
264 `git grep -nE "require\.(resolve|cache|main|extensions)"`,
265 `git grep -nE "require\(['\"][^'\"]+\.json['\"]\)"`,
266 `git ls-files '*.cjs' '*.mjs'`, and
267 `git ls-files '**/package.json' | xargs grep -l '"main"\|"type"\|"exports"'`.
268 - Validation should be hypothesis-driven: include separate checks
269 for happy path package load, dynamic require replacement,
270 extension/index-resolution failures, JSON import behavior,
271 test-runner ESM behavior, and downstream consumer import/require
272 smoke tests.
273 - Express validation commands as read-only probes against existing
274 repository files. For example, use `node --check <existing-file>`,
275 `node --input-type=module -e "import('package-name-or-path')"`,
276 `npm test -- --runInBand` only when scripts exist, and
277 `git grep`/`npm pkg get` discovery before any path-specific
278 command. Never ask the user to create `tmp-smoke.*` files.
279 - Include package/publication validation commands when relevant:
280 `npm pack --dry-run`, `npx publint`, and
281 `npx @arethetypeswrong/cli --pack .` for published packages with
282 TypeScript types. Label these as optional if the package is not
283 published.
284 - For rollout, include decision points: ESM-only versus dual publish,
285 semver-major trigger, consumer compatibility scan, canary/internal
286 package release, package-tarball inspection, rollback to previous
287 package version, and keeping `.cjs` escape hatches for tooling.
288 - For CJS_TO_ESM, cover at minimum: `type: module`, extension rules,
289 directory `index.js` imports, `__dirname`/`__filename`, JSON
290 imports, CJS interop/default export shape changes, `exports` map
291 subpath whitelisting and precedence, TypeScript `NodeNext`,
292 Jest/Vitest or node:test, dual-package hazards, downstream
293 consumer smoke tests, release sequencing, and rollback.
294 - Do not say that `exports` deprecates `main`; say that `exports` takes precedence for runtimes that support it and can restrict deep imports.
295 - Mark all validation commands as commands for the user to run; do
296 not imply they were executed.
297 - Include version caveats for Node/tooling-specific behavior.
298 - For JSON imports, avoid claiming one universal syntax. Say that
299 behavior differs by Node version/tooling; verify the target
300 runtime's current JSON-module/import-attributes support, and keep
301 `createRequire(import.meta.url)` as the conservative fallback when
302 needed.
303 - Avoid invented loader placeholders such as
304 `node --loader <your-loader>` unless the repository evidence
305 shows an existing loader. Prefer concrete discovery commands.
306 - Avoid write-implying validation examples such as `eslint --fix`;
307 validation should be read-only unless clearly labeled as a
308 separate codemod/fix step.
309 - Avoid file-creation or config-generation examples unless they are
310 explicitly labeled as implementation work, not validation. Keep
311 the checklist concise and decision-oriented instead of filling it
312 with large generic config snippets.
313 - Do not include brittle placeholder commands such as
314 `node --loader <your-loader>` or `node --check <existing-file>`;
315 write discovery-first templates with clear placeholders only where
316 unavoidable.
317 - Avoid obsolete Node flags such as `--experimental-modules`; prefer
318 current LTS-compatible commands and call out when a command is
319 version-specific.
320---
321
322# Migration Assistant (Meta-Skill)
323
324Take a "help me migrate X → Y" request and produce a concrete, runnable
325checklist. The pipeline does four things:
326
3271. **classify** the migration kind via an LLM tag (one of six tokens).
3282. **fetch_guide** the most authoritative source for THAT migration:
329
330 | Classifier verdict | Best source | Routed skill |
331 |-----------------------------|------------------------|-----------------------|
332 | `OPENAI_V0_TO_V1` | repo release notes | `github` |
333 | `PY2_TO_PY3` | framework migration doc| `multi-search-engine` |
334 | `VUE2_TO_VUE3` | framework migration doc| `multi-search-engine` |
335 | `REACT_CLASS_TO_HOOKS` | framework migration doc| `multi-search-engine` |
336 | `CJS_TO_ESM` | (fuzzy, synthesize) | `multi-search-engine` |
337 | `OTHER` (default) | (synthesize) | `deep-research` |
338
3393. **repo_context** optionally inspects the current repo diff only when the
340 prompt indicates that local repository context should shape the migration.
341
3424. **write_plan** uses a constrained `llm_chat` renderer so explicit source
343 and target terms in the user request remain authoritative even when
344 repository context or retrieved guide text is noisy.
345
346## Fallback
347
348If the orchestration fails: ask the user to specify the migration tag
349manually, run the matching skill yourself, then write the checklist.