claude/plugin-tools/skills/port-plugin/SKILL.md
Converts Agent Alchemy plugins into formats compatible with other AI coding platforms
npx skillsauth add sequenzia/agent-alchemy port-pluginInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Convert Agent Alchemy plugins (skills, agents, hooks, references, MCP configs) into formats compatible with other AI coding platforms using an extensible markdown-based adapter framework, live platform research, and interactive conversion workflows.
CRITICAL: Complete ALL 7 phases. The workflow is not complete until Phase 7: Summary is finished. After completing each phase, immediately proceed to the next phase without waiting for user prompts.
IMPORTANT: You MUST use the AskUserQuestion tool for ALL questions to the user. Never ask questions through regular text output.
Text output should only be used for:
If you need the user to make a choice or provide input, use AskUserQuestion.
NEVER do this (asking via text output):
Which plugin groups would you like to port?
1. core-tools
2. dev-tools
3. sdd-tools
ALWAYS do this (using AskUserQuestion tool):
AskUserQuestion:
questions:
- header: "Plugin Groups"
question: "Which plugin groups would you like to port?"
options:
- label: "core-tools"
description: "3 skills, 2 agents — Deep analysis, codebase analysis, language patterns"
- label: "dev-tools"
description: "6 skills, 4 agents — Feature dev, code review, docs, changelog"
- label: "sdd-tools"
description: "6 skills, 3 agents — Spec creation, task management, execution"
multiSelect: true
CRITICAL: This skill performs an interactive conversion workflow, NOT an implementation plan. When invoked during Claude Code's plan mode:
Execute these phases in order, completing ALL of them:
Goal: Load configuration, parse arguments, and determine the target platform.
Parse $ARGUMENTS for:
--target <platform> — Target platform slug (default: opencode)--dry-run — Preview mode; show expected output without writing filesSet TARGET_PLATFORM from --target value (default: opencode).
Set DRY_RUN from --dry-run flag (default: false).
Check if .claude/agent-alchemy.local.md exists and read for any plugin-tools section with settings:
- **plugin-tools**:
- **default-target**: opencode
- **default-output-dir**: ported/
- **auto-research**: true
If settings exist, apply them as defaults (CLI arguments override settings file values).
Check that an adapter file exists for the target platform:
Glob to check ${CLAUDE_PLUGIN_ROOT}/references/adapters/{TARGET_PLATFORM}.mdADAPTERADAPTER = nullRead the marketplace registry to enumerate available plugin groups:
Read: ${CLAUDE_PLUGIN_ROOT}/../../.claude-plugin/marketplace.json
Parse the plugins array. Each entry has:
name — Full plugin name (e.g., agent-alchemy-core-tools)version — Current versiondescription — Brief descriptionsource — Relative path to plugin directory (e.g., ./core-tools)Build a list of available plugin groups, extracting the short group name from the source path (e.g., core-tools from ./core-tools).
Exclude plugin-tools from the selection list — the porter should not attempt to port itself.
Goal: Guide the user through selecting which plugin groups and individual components to port.
Inform the user of the target platform and configuration:
Target platform: {TARGET_PLATFORM}
Adapter: {adapter file path or "None — research agent will investigate"}
Dry-run: {DRY_RUN}
Present all available plugin groups for selection using AskUserQuestion with multiSelect: true.
For each plugin group, scan its directory to count components:
Glob to count skills: claude/{group}/skills/*/SKILL.mdGlob to count agents: claude/{group}/agents/*.mdGlob to check for hooks: claude/{group}/hooks/hooks.jsonGlob to count reference dirs: claude/{group}/skills/*/references/Glob to check for MCP config: claude/{group}/.mcp.jsonBuild the selection options:
AskUserQuestion:
questions:
- header: "Plugin Group Selection"
question: "Which plugin groups would you like to port to {TARGET_PLATFORM}?"
options:
- label: "{group-name} (v{version})"
description: "{skill_count} skills, {agent_count} agents{, hooks}{, MCP config} — {marketplace description}"
multiSelect: true
Edge case — Empty plugin group: If a scanned group has zero skills, zero agents, no hooks, and no MCP config, skip it from the selection list and note: "Skipped {group}: no portable components found."
Store the selected groups as SELECTED_GROUPS.
If no groups are selected (user cancels or selects nothing), use AskUserQuestion to confirm:
AskUserQuestion:
questions:
- header: "No Selection"
question: "No plugin groups were selected. Would you like to start over or cancel?"
options:
- label: "Start over"
description: "Return to group selection"
- label: "Cancel"
description: "Exit the porter"
multiSelect: false
If "Start over", repeat Step 2. If "Cancel", end the workflow gracefully.
For each selected group, scan and enumerate all individual components, then present for selection.
Component scanning per group:
Skills: For each claude/{group}/skills/*/SKILL.md:
name and descriptionreferences/ subdirectory and count reference filesskill:{group}/{skill-name} with descriptionAgents: For each claude/{group}/agents/*.md:
name, description, and modelagent:{group}/{agent-name} with description and model tierHooks: If claude/{group}/hooks/hooks.json exists:
hooks:{group} with hook count and event typesMCP Config: If claude/{group}/.mcp.json exists:
mcp:{group} with server namesPresent components for each group using AskUserQuestion:
AskUserQuestion:
questions:
- header: "{group-name} Components"
question: "Select components to port from {group-name}:"
options:
- label: "All components"
description: "Port everything in {group-name} ({total_count} components)"
- label: "skill: {skill-name}"
description: "{skill description} ({ref_count} references)"
- label: "agent: {agent-name}"
description: "{agent description} (model: {model})"
- label: "hooks: {group}"
description: "{hook_count} hooks ({event types})"
- label: "mcp: {group}"
description: "MCP config ({server names})"
multiSelect: true
Edge case — "All components" selected: If the user selects "All components", include every component from that group in the selection. Do not present further sub-selection.
Build the final component list as SELECTED_COMPONENTS, a flat list of component identifiers with their types:
[
{ type: "skill", group: "core-tools", name: "deep-analysis", path: "claude/core-tools/skills/deep-analysis/SKILL.md" },
{ type: "agent", group: "core-tools", name: "code-explorer", path: "claude/core-tools/agents/code-explorer.md" },
{ type: "hooks", group: "core-tools", name: "hooks", path: "claude/core-tools/hooks/hooks.json" },
...
]
Present a summary of the selection to the user:
## Selection Summary
**Target platform:** {TARGET_PLATFORM}
**Plugin groups:** {count} selected
**Total components:** {count}
| Group | Skills | Agents | Hooks | MCP | References |
|-------|--------|--------|-------|-----|------------|
| {group} | {n} | {n} | {yes/no} | {yes/no} | {n} files |
Components:
- {component list with types}
Use AskUserQuestion to confirm:
AskUserQuestion:
questions:
- header: "Confirm Selection"
question: "Proceed with this selection?"
options:
- label: "Proceed"
description: "Continue to dependency validation"
- label: "Modify selection"
description: "Go back and change component selection"
- label: "Cancel"
description: "Exit the porter"
multiSelect: false
If "Modify selection", return to Step 2. If "Cancel", end the workflow gracefully.
Goal: Build a full dependency graph from selected components, detect all five dependency types, flag missing references and external dependencies, and produce a dependency-sorted conversion order for Phase 5.
This phase consumes SELECTED_COMPONENTS and SELECTED_GROUPS from Phase 2 and produces DEPENDENCY_GRAPH (including CONVERSION_ORDER) for Phase 5.
For each component in SELECTED_COMPONENTS, read its source file and extract all dependency references. Initialize a flat dependency list:
DEPENDENCIES = [] // each entry: { source, target_type, target_ref, dep_type, raw_pattern, transitive }
Process each component type using the sub-steps below. Apply these error handling rules during scanning:
Error: Unreadable file. If a component file cannot be read (permission error, file missing, I/O error), log a warning and continue scanning the remaining components:
WARNING: Could not read {component.path} -- skipping dependency scan for this component.
Error: Malformed YAML frontmatter. If a component's YAML frontmatter cannot be parsed (invalid YAML between --- delimiters), log a parsing error and fall back to body-only scanning for that component:
WARNING: Malformed YAML frontmatter in {component.path} -- scanning body text only for dependencies.
For each skill component (type: "skill"), read its SKILL.md and scan for all five dependency types:
Dependency Type 1 -- Skill-to-skill references:
Scan the skill body for patterns that load another skill from the same plugin group:
Read ${CLAUDE_PLUGIN_ROOT}/skills/{skill-name}/SKILL.md
For each match, extract {skill-name} and record:
{ source: this_component, target_type: "skill", target_ref: "{this_group}/{skill-name}", dep_type: "skill-to-skill", raw_pattern: "{matched line}", transitive: false }
Dependency Type 2 -- Cross-plugin references:
Scan the body for patterns that reference a different plugin group:
${CLAUDE_PLUGIN_ROOT}/../{source-dir-name}/skills/{skill-name}/SKILL.md
${CLAUDE_PLUGIN_ROOT}/../{source-dir-name}/agents/{agent-name}.md
${CLAUDE_PLUGIN_ROOT}/../{source-dir-name}/
For each match, extract {source-dir-name} and the component name, and record:
{ source: this_component, target_type: "skill" or "agent", target_ref: "{source-dir-name}/{name}", dep_type: "cross-plugin", raw_pattern: "{matched line}", transitive: false }
Dependency Type 3 -- Reference file includes:
Scan the body for patterns that load reference files:
Read ${CLAUDE_PLUGIN_ROOT}/skills/{skill-name}/references/{filename}
${CLAUDE_PLUGIN_ROOT}/skills/{skill-name}/references/{filename}
For each match, determine if the reference belongs to this skill or another skill:
references/ directory are internal by definition and do not create a dependency edgereferences/ directory create a dependency:{ source: this_component, target_type: "reference", target_ref: "{group}/{skill-name}/references/{filename}", dep_type: "reference-include", raw_pattern: "{matched line}", transitive: false }
Dependency Type 4 -- Agent/subagent references:
Scan the body for Task tool invocations that spawn agents:
subagent_type: "{agent-name}"
For each match, record:
{ source: this_component, target_type: "agent", target_ref: "{group}/{agent-name}", dep_type: "skill-to-skill", raw_pattern: "{matched line}", transitive: false }
External dependencies (non-component):
Scan for system-level dependencies that cannot be ported as components:
mcp__{server}__{tool} or the mcp__ prefix in the body or allowed-tools list.sh, .py, .js)For each external dependency found:
{ source: this_component, target_type: "external", target_ref: "{description}", dep_type: "external", raw_pattern: "{matched line}", transitive: false }
For each agent component (type: "agent"), read its .md file:
Dependency Type 5 -- Agent-to-skill references:
Parse the YAML frontmatter and extract the skills: field (array of skill identifiers). For each skill listed:
{ source: this_component, target_type: "skill", target_ref: "{resolved skill reference}", dep_type: "agent-to-skill", raw_pattern: "skills: [{skill}]", transitive: false }
Also scan the agent's markdown body for Read ${CLAUDE_PLUGIN_ROOT} and ${CLAUDE_PLUGIN_ROOT}/../ patterns, applying the same Type 1, Type 2, and Type 3 scans from Step 1a.
Tool dependencies (informational only):
Parse the tools: field from frontmatter. These are Claude Code platform tools classified as System dependencies. They do not create dependency edges but are tracked for the gap report.
For each hooks component (type: "hooks"), read the hooks.json file and parse the JSON:
Dependency Type 4 -- Hook-to-script references:
For each hook entry, extract the command field and scan for:
${CLAUDE_PLUGIN_ROOT}/hooks/scripts/auto-approve.sh).sh, .py, .js, or other executable extensionsFor each script reference:
{ source: this_component, target_type: "script", target_ref: "{script path}", dep_type: "hook-to-script", raw_pattern: "{command value}", transitive: false }
Tool matcher patterns in hooks reference Claude Code tool names -- classify these as System dependencies for informational tracking only.
For each MCP config component (type: "mcp"), read the .mcp.json file:
Each configured MCP server is an external dependency requiring manual porting on the target platform. Record each server:
{ source: this_component, target_type: "external", target_ref: "MCP server: {server_name} ({command})", dep_type: "external", raw_pattern: "{server config snippet}", transitive: false }
Construct a directed dependency graph from the parsed dependencies.
Nodes: All components in SELECTED_COMPONENTS, each identified by {type}:{group}/{name}.
Edges: For each entry in DEPENDENCIES where dep_type is NOT "external" and NOT a system dependency, create a directed edge from the source node to the node matching target_ref.
For each dependency in DEPENDENCIES, determine its classification by checking target_ref against SELECTED_COMPONENTS and SELECTED_GROUPS:
| Classification | Condition |
|---|---|
| Internal | Target component exists in SELECTED_COMPONENTS |
| External-selected | Target component's group is in SELECTED_GROUPS but the specific component was not individually selected |
| External-missing | Target component's group is NOT in SELECTED_GROUPS and not available in the marketplace |
| System | Target is a Claude Code platform feature (built-in tool, MCP protocol feature) |
| External | Target is a non-component dependency (MCP server process, bash script, external service) |
Dependencies can form chains: Skill A loads Skill B, which loads Skill C, which loads Skill D. To ensure the full transitive dependency tree is captured:
transitive: false)SCANNED_COMPONENTS containing all components already processed in Step 1External-missing or External-selected:
a. Determine the file path of the target component on disk (using the component scanning conventions: claude/{group}/skills/{name}/SKILL.md for skills, claude/{group}/agents/{name}.md for agents)
b. If the file exists and the component is NOT in SCANNED_COMPONENTS:
transitive: trueDEPENDENCIESSCANNED_COMPONENTS
c. If the file does not exist, skip it (it will be reported as unresolvable in Step 4)External-missing or External-selected dependenciesWARNING: Dependency chain depth limit (10) reached starting from {root component}. Some transitive dependencies may not be fully resolved.
Run a cycle detection pass on the dependency graph using depth-first search:
CIRCULAR_REFS = [
{ cycle: ["{component_id_1}", "{component_id_2}", ..., "{component_id_1}"], warning: "Circular dependency detected" }
]
Before alerting the user, determine whether the selection has any unresolved dependencies.
Count dependencies by classification:
internal_count -- dependencies already satisfied within the selectionexternal_selected_count -- dependencies in selected groups but not individually selectedexternal_missing_count -- dependencies not in any selected groupexternal_count -- non-component external dependencies (MCP servers, scripts)system_count -- Claude Code platform dependenciesIf external_selected_count == 0 AND external_missing_count == 0 AND external_count == 0:
The selection is fully self-contained. Display a brief confirmation and skip to Step 5:
All dependencies resolved -- no missing cross-plugin references.
{internal_count} internal dependencies found between selected components.
Otherwise, proceed to Step 4.
Present the dependency analysis to the user, organized by category:
## Dependency Analysis
**Components scanned:** {SELECTED_COMPONENTS.length}
**Total dependencies found:** {DEPENDENCIES.length}
**Internal (resolved):** {internal_count}
**Missing component dependencies:** {external_selected_count + external_missing_count}
**External (manual porting needed):** {external_count}
**System (Claude Code platform):** {system_count}
{If external_selected_count + external_missing_count > 0:}
### Missing Component Dependencies
These selected components depend on components not in your selection:
| Source Component | Depends On | Dependency Type | Group | Reference Pattern |
|---|---|---|---|---|
| {source.name} | {target_ref} | {dep_type} | {target_group} | `{raw_pattern snippet}` |
{If any dependency has transitive: true:}
Note: Dependencies marked with (*) are transitive -- discovered by following dependency chains beyond the initial selection.
{If external_count > 0:}
### External Dependencies (Manual Porting Required)
These dependencies cannot be automatically ported and will require manual setup on the target platform:
| Source Component | External Dependency | Type | Notes |
|---|---|---|---|
| {source.name} | {target_ref} | MCP server / bash script | Requires manual configuration |
These will be documented in the gap report with setup instructions.
If there are missing component dependencies (external_selected_count + external_missing_count > 0):
Use AskUserQuestion to let the user decide:
AskUserQuestion:
questions:
- header: "Missing Dependencies"
question: "Some selected components depend on {external_selected_count + external_missing_count} components not in your selection. How would you like to handle this?"
options:
- label: "Add missing dependencies"
description: "Include {count} additional components to resolve all references"
- label: "Proceed without them"
description: "Continue -- missing references will be flagged in the gap report"
- label: "Go back to selection"
description: "Return to component selection to adjust"
multiSelect: false
If "Add missing dependencies":
External-selected dependency: locate the component in its group directory, build its component entry (type, group, name, path), and add to SELECTED_COMPONENTSExternal-missing dependency: scan the component from disk using the component scanning conventions, build its entry, and add to SELECTED_COMPONENTSIf "Go back to selection": Return to Phase 2 Step 2.
If "Proceed without them": Continue to Step 5. Missing dependencies will be tracked as entries in CONVERSION_GAPS during Phase 5.
If circular references were detected (from Step 2d):
Display a warning after the missing dependencies resolution:
### Circular References Detected
WARNING: {CIRCULAR_REFS.length} circular dependency chain(s) found:
{For each cycle in CIRCULAR_REFS:}
- {cycle[0]} -> {cycle[1]} -> ... -> {cycle[0]}
These will be handled during conversion (Phase 5) using topological sort with cycle-breaking.
The component with the fewest incoming dependencies in each cycle will be processed first.
Circular references do not require user action -- they are informational warnings. Proceed to Step 5.
Build the final dependency graph summary and compute the conversion order for Phase 5.
Compute a dependency-sorted conversion order:
{type}:{group}/{name} for deterministic orderingStore the sorted list as CONVERSION_ORDER.
## Dependency Graph
**Components:** {SELECTED_COMPONENTS.length}
**Internal dependencies:** {internal_count}
**External dependencies (to be flagged):** {external_count + external_missing_count}
**Circular references:** {CIRCULAR_REFS.length or "none"}
**System dependencies:** {system_count} Claude Code platform features
Conversion order (dependency-sorted):
1. {component_id} -- no dependencies
2. {component_id} -- depends on: {dep1}, {dep2}
3. {component_id} -- depends on: {dep1}
...
Store the complete graph as DEPENDENCY_GRAPH for consumption by Phase 5:
DEPENDENCY_GRAPH = {
nodes: SELECTED_COMPONENTS,
edges: DEPENDENCIES,
circular_refs: CIRCULAR_REFS,
conversion_order: CONVERSION_ORDER,
external_deps: [entries where dep_type == "external"],
classification_counts: { internal, external_selected, external_missing, external, system }
}
Goal: Spawn a research subagent to investigate the target platform's current plugin architecture, compare findings against the existing adapter file, and produce a merged knowledge base for conversion.
Before spawning the research agent, gather the context it needs:
Count selected components by type from SELECTED_COMPONENTS:
skill_count — number of skill componentsagent_count — number of agent componentshook_count — number of hooks componentsref_count — total reference files across all selected skillsmcp_count — number of MCP config componentsExtract adapter content (if ADAPTER exists):
${CLAUDE_PLUGIN_ROOT}/references/adapters/{TARGET_PLATFORM}.mdADAPTER_CONTENT for inclusion in the research prompttarget_platform_version field from the Adapter Version sectionBuild component summary — a brief list of what is being ported, to help the research agent focus on relevant platform features:
Components to convert:
- Skills: {list of skill names}
- Agents: {list of agent names with model tiers}
- Hooks: {yes/no, with event types if yes}
- References: {count} files
- MCP configs: {yes/no, with server names if yes}
Key features used by these components:
- {e.g., "Task tool for subagent spawning (used by deep-analysis)"}
- {e.g., "AskUserQuestion for interactive workflows (used by create-spec)"}
- {e.g., "Cross-plugin composition via ${CLAUDE_PLUGIN_ROOT}/../ paths"}
Spawn the research agent using the Task tool with subagent_type: "researcher" and model: "sonnet":
Task tool prompt:
"Research the plugin/extension system for: {TARGET_PLATFORM}
You are researching this platform to support converting Agent Alchemy (Claude Code) plugins to {TARGET_PLATFORM} format. The conversion needs to handle {skill_count} skills, {agent_count} agents, {hook_count} hook configs, {ref_count} reference files, and {mcp_count} MCP configs.
{If ADAPTER exists:}
## Existing Adapter File
An adapter file already exists for this platform. Here is its full content:
---BEGIN ADAPTER---
{ADAPTER_CONTENT}
---END ADAPTER---
IMPORTANT: Compare your research findings against every mapping in this adapter file. In your Adapter Comparison section:
- Flag any mappings that appear outdated based on your research
- Identify new platform features or changes not covered by the adapter
- Note the adapter's platform version ({adapter_platform_version}) vs. the current version you find
- For each stale or missing mapping, provide the corrected/new mapping
{If ADAPTER is null:}
## No Existing Adapter
No adapter file exists for this platform yet. Research from scratch and produce a comprehensive platform profile. Your findings will be the primary source of truth for the conversion engine.
## Components Being Ported
{component_summary from Step 1}
## Research Focus Areas
Investigate these areas thoroughly — they directly affect conversion quality:
1. **Plugin directory structure**: Where plugins live, file naming conventions, required files
2. **Configuration format**: YAML, JSON, TOML, or other formats for plugin metadata
3. **Tool/capability equivalents**: What built-in tools does the platform provide? Map against Claude Code's tools (Read, Write, Edit, Glob, Grep, Bash, Task, WebSearch, WebFetch, AskUserQuestion)
4. **Model configuration**: How are AI models specified? Does the platform support model tiers or selection?
5. **Lifecycle hooks**: Does the platform have pre/post execution hooks? Event system?
6. **Composition mechanism**: How do plugins load or reference other plugins? Is there an equivalent to skill composition via prompt injection?
7. **Path resolution**: Equivalent of ${CLAUDE_PLUGIN_ROOT} for resolving plugin-relative paths
8. **Agent/subagent support**: Can plugins spawn sub-tasks or sub-agents? How?
9. **User interaction**: How do plugins prompt the user for input during execution?
10. **MCP integration**: Does the platform support Model Context Protocol servers?
Return a structured platform profile following your output format specification. Include confidence levels for every finding."
Retry logic: If the Task tool call fails (agent error, timeout, or empty response), retry once automatically. If the retry also fails, proceed to the research failure handling in Step 5.
When the research agent returns its platform profile:
Parse the structured platform profile from the response. Extract these sections:
Store as RESEARCH_FINDINGS — the parsed profile is available throughout the remaining phases for the conversion engine to reference.
Merge research with adapter into CONVERSION_KNOWLEDGE:
The conversion engine uses a merged knowledge base called CONVERSION_KNOWLEDGE that combines the adapter file and research findings with clear precedence rules:
| Category | Precedence Rule |
|----------|----------------|
| Tool name mappings | Adapter takes precedence for established mappings; research fills gaps where adapter has null or no entry |
| Model tier mappings | Adapter takes precedence; research supplements with version-specific notes |
| Platform version info | Research always takes precedence (it is fresher) |
| Directory structure | Research takes precedence if it differs from adapter (platform may have changed) |
| Composition patterns | Research takes precedence if it provides more detail; adapter is baseline |
| Lifecycle hooks | Research takes precedence if it finds new hook types; adapter is baseline |
| Known limitations | Union of both — all limitations from adapter AND research are tracked |
| Path resolution | Research takes precedence if adapter mapping is marked as uncertain |
When adapter and research agree on a mapping, mark it as confidence: high.
When only one source provides a mapping, mark it as confidence: medium.
When adapter and research disagree, mark it as confidence: conflict and flag for user resolution in Step 4.
Check for adapter staleness:
Initialize STALENESS_STATUS to track the result for migration guide logging:
STALENESS_STATUS = {
checked: false,
adapter_version: null,
adapter_platform_version: null,
research_platform_version: null,
is_stale: false,
is_unversioned: false,
research_has_version: false,
stale_mappings: [],
new_features: [],
user_decision: null,
error: null
}
Wrap the entire staleness check in error-safe logic. If any step below fails (parsing error, unexpected format, etc.), set STALENESS_STATUS.error to a description of the failure, log a warning ("Staleness check encountered an error: {error}. Proceeding with conversion."), and continue to Step 4. The staleness check must never block the conversion workflow.
If ADAPTER exists:
a. Read adapter version fields from the Adapter Version section of the adapter file:
adapter_version (the adapter file's own version, e.g., 1.0.0)target_platform_version (the platform version the adapter was written for, e.g., 0.0.55)STALENESS_STATUS.checked = trueSTALENESS_STATUS.is_unversioned = true and log a warning: "Adapter file for {TARGET_PLATFORM} has no version fields. Staleness cannot be determined — proceeding with adapter as-is."b. Check if research reported a platform version:
STALENESS_STATUS.research_has_version = false and log a note: "Research did not report a specific platform version for {TARGET_PLATFORM}. Skipping version comparison."STALENESS_STATUS.research_has_version = true and store it in STALENESS_STATUS.research_platform_versionc. Compare versions (only if both adapter and research have version information):
target_platform_version equals research_platform_version exactly, versions match — STALENESS_STATUS.is_stale = false0.0.55, 1.2.3), compare numerically. If research version is newer, set STALENESS_STATUS.is_stale = true0.0.55 but research reports v0.0.55, 0.0.55-beta, or a date-based version), attempt normalization:
v or V prefix-alpha, -beta, -rc.1, etc.) for comparisonSTALENESS_STATUS.is_stale = true (err on the side of warning) and note: "Version format mismatch — adapter: '{adapter_version}', research: '{research_version}'. Treating as potentially stale."d. Collect stale mappings and new features (regardless of version match, if research provides an Adapter Comparison section):
STALE_MAPPINGS and store in STALENESS_STATUS.stale_mappingsNEW_FEATURES and store in STALENESS_STATUS.new_featuresADAPTER_STALE = true (content staleness despite version match)If any mappings in CONVERSION_KNOWLEDGE are marked as confidence: conflict:
Build a conflict list summarizing each disagreement:
Conflicts found between adapter file and research findings:
1. {mapping_name}:
- Adapter says: {adapter_value}
- Research says: {research_value} (source: {url})
- Impact: {which components are affected}
2. {mapping_name}:
...
Present conflicts to user via AskUserQuestion for each conflict (or batch if fewer than 5):
AskUserQuestion:
questions:
- header: "Research Conflict"
question: "The adapter file and fresh research disagree on {mapping_name}. Which should be used for conversion?"
options:
- label: "Use research finding"
description: "{research_value} — from {source}, researched today"
- label: "Use adapter mapping"
description: "{adapter_value} — from adapter file v{adapter_version}"
- label: "Skip this mapping"
description: "Flag as unresolved in the gap report"
multiSelect: false
Apply resolutions to CONVERSION_KNOWLEDGE:
confidence: high, mark source: researchconfidence: high, mark source: adapterconfidence: unresolved, will appear in the gap reportIf there are no conflicts, skip this step entirely.
Display a summary of the research findings and merged knowledge to the user:
## Platform Research: {TARGET_PLATFORM}
**Documentation quality:** {research_summary.documentation_quality}
**Sources consulted:** {research_summary.sources_consulted}
**Overall confidence:** {research_summary.overall_confidence}
### Key Findings
- **Plugin format:** {file_format description}
- **Tool equivalents:** {matched_count}/{total_count} Claude Code tools have equivalents
- **Model support:** {model_tier_summary}
- **Composition:** {composition_patterns summary}
- **Hooks:** {lifecycle_hooks summary — supported/not supported/partial}
- **Agent spawning:** {agent/subagent support summary}
- **User interaction:** {user interaction mechanism summary}
### Knowledge Sources for Conversion
- Adapter file mappings: {count} mappings
- Research-supplemented mappings: {count} new/updated mappings
- Conflicts resolved: {count}
- Unresolved gaps: {count}
{If STALENESS_STATUS.is_unversioned = true:}
### Adapter Version Notice
NOTE: The adapter file for {TARGET_PLATFORM} has no version fields. Staleness cannot be determined. The adapter will be used as-is, supplemented by research findings.
{If STALENESS_STATUS.research_has_version = false AND ADAPTER exists:}
### Research Version Notice
NOTE: Research did not report a specific platform version for {TARGET_PLATFORM}. Version comparison was skipped. The adapter's target_platform_version ({STALENESS_STATUS.adapter_platform_version}) is assumed current.
{If STALENESS_STATUS.error:}
### Staleness Check Notice
NOTE: The staleness check encountered an error: {STALENESS_STATUS.error}. Conversion will proceed using available adapter and research data.
{If ADAPTER_STALE = true:}
### Adapter Staleness Warning
WARNING: The existing adapter file targets {TARGET_PLATFORM} v{STALENESS_STATUS.adapter_platform_version}, but research found the current version is v{STALENESS_STATUS.research_platform_version}.
Stale mappings detected:
{For each stale mapping in STALENESS_STATUS.stale_mappings:}
- {mapping_name}: adapter says "{old_value}", research found "{new_value}"
New platform features not in adapter:
{For each new feature in STALENESS_STATUS.new_features:}
- {feature_name}: {description}
{If no ADAPTER:}
### New Platform Profile
Research produced a fresh platform profile since no adapter file existed.
Consider saving a new adapter file from these findings after conversion.
After displaying the summary, if ADAPTER_STALE = true, present the user with options via AskUserQuestion:
AskUserQuestion:
questions:
- header: "Adapter Staleness"
question: "The adapter file for {TARGET_PLATFORM} appears to be stale (adapter targets v{STALENESS_STATUS.adapter_platform_version}, research found v{STALENESS_STATUS.research_platform_version}). {stale_mapping_count} mappings may be outdated and {new_feature_count} new platform features were found. How would you like to proceed?"
options:
- label: "Proceed with existing adapter"
description: "Continue conversion — research findings will supplement and override stale adapter mappings via CONVERSION_KNOWLEDGE precedence rules"
- label: "Update adapter file first"
description: "Pause conversion to update the adapter file with research findings, then resume"
multiSelect: false
Handle each choice:
"Proceed with existing adapter": Set STALENESS_STATUS.user_decision = "proceed". Continue to Phase 5 using CONVERSION_KNOWLEDGE as already merged (research takes precedence for stale mappings per the precedence rules in Step 3). Log: "User chose to proceed with existing adapter. Research findings will supplement stale mappings during conversion."
"Update adapter file first": Set STALENESS_STATUS.user_decision = "update". Before continuing to Phase 5:
${CLAUDE_PLUGIN_ROOT}/references/adapters/{TARGET_PLATFORM}.mdSTALE_MAPPINGS: update the mapping value in the adapter to match the research findingNEW_FEATURES: add the feature to the appropriate adapter sectiontarget_platform_version field to the research-reported versionlast_updated field to today's dateadapter_version patch number (e.g., 1.0.0 -> 1.0.1)changelog field describing the updateADAPTER and re-merge into CONVERSION_KNOWLEDGEIf STALENESS_STATUS.is_unversioned = true and stale mappings or new features were found, also present the AskUserQuestion above (since content can be stale even without version fields).
Record staleness status for migration guide:
Store STALENESS_STATUS for inclusion in the migration guide output (Phase 6). The migration guide should include a "Platform Adapter Status" section documenting:
If the research agent failed (both initial attempt and retry):
Inform the user of what happened:
The platform research agent was unable to complete its investigation.
Reason: {error_message or "timeout/empty response"}
Offer recovery options via AskUserQuestion:
AskUserQuestion:
questions:
- header: "Research Issue"
question: "The platform research agent encountered an issue: {brief_reason}. How would you like to proceed?"
options:
- label: "Retry research"
description: "Launch the research agent again (attempt {retry_count + 1})"
- label: "Use adapter only"
description: "Proceed with existing adapter file mappings (no fresh research)"
- label: "Cancel"
description: "Exit the porter"
multiSelect: false
Handle each choice:
"Retry research": Return to Step 2 and re-launch the research agent. Allow up to 2 total retries (3 attempts total).
"Use adapter only":
ADAPTER exists: Set RESEARCH_FINDINGS = null. Set CONVERSION_KNOWLEDGE to adapter mappings only with confidence: medium on all entries (no research validation). Inform the user: "Proceeding with adapter file mappings only. Conversion quality may be affected — adapter mappings have not been validated against current platform documentation." Continue to Phase 5.ADAPTER is null: Inform the user: "Cannot proceed — no adapter file exists and research failed. The conversion engine requires at least one source of platform knowledge." Offer:
AskUserQuestion:
questions:
- header: "No Platform Knowledge Available"
question: "Neither an adapter file nor research findings are available. What would you like to do?"
options:
- label: "Retry research"
description: "Try the research agent one more time"
- label: "Cancel"
description: "Exit the porter — conversion cannot proceed without platform knowledge"
multiSelect: false
"Cancel": End the workflow gracefully with a summary of what was completed so far.
Goal: Offer an optional preview of expected conversion output -- showing the target file tree, per-component conversion status, expected issues, and estimated fidelity -- without writing any files or running the full conversion engine.
This phase consumes SELECTED_COMPONENTS, DEPENDENCY_GRAPH (from Phase 3), and CONVERSION_KNOWLEDGE (from Phase 4). It does not modify any of these structures.
If DRY_RUN = true (set via --dry-run flag): Skip the offer and proceed directly to Step 2 (preview is mandatory).
If DRY_RUN = false: Use AskUserQuestion to offer the preview as an optional step:
AskUserQuestion:
questions:
- header: "Dry-Run Preview"
question: "Would you like to preview the expected conversion output before proceeding? This shows the target file tree, per-component status, and expected issues without writing any files."
options:
- label: "Run preview"
description: "Generate and display a dry-run preview of the conversion"
- label: "Skip preview and convert"
description: "Proceed directly to interactive conversion (Phase 5)"
multiSelect: false
If "Skip preview and convert": Skip the rest of Phase 4.5 and proceed directly to Phase 5.
If "Run preview": Continue to Step 2.
Generate the preview by analyzing CONVERSION_KNOWLEDGE mappings against each component in SELECTED_COMPONENTS. This step predicts conversion outcomes without running the full conversion engine.
Wrap the entire preview generation in error-safe logic. If any step below fails (parsing error, unexpected format, etc.), log a warning ("Preview generation encountered an error: {error}. You can still proceed with conversion."), skip to Step 4 (user decision), and offer the option to proceed with conversion despite the preview failure.
For each component in SELECTED_COMPONENTS, predict the output file path using CONVERSION_KNOWLEDGE:
Skills: Map source path claude/{group}/skills/{name}/SKILL.md to target path using directory structure mappings:
CONVERSION_KNOWLEDGE for skill_file_pattern in directory structure mappingsskill_file_pattern is defined (e.g., {name}/SKILL.md): expand the pattern by replacing {name} with the skill name (applying naming_convention), then build path: {plugin_root}/{skill_dir}/{expanded_pattern} (e.g., .opencode/skills/deep-analysis/SKILL.md)skill_file_pattern: apply naming_convention and file_extension for a flat filename, then build path: {plugin_root}/{skill_dir}/{converted_filename}Agents: Map source path claude/{group}/agents/{name}.md to target path:
{plugin_root}/{agent_dir}/{converted_filename}null or alternative): note the mapping strategy (e.g., "merged into skill" or "mapped to fixed type")Hooks: Map claude/{group}/hooks/hooks.json to the target hooks format:
{plugin_root}/{hook_dir}/{target_hook_filename}References: For each reference file in selected skills' references/ directories:
{plugin_root}/{reference_dir}/{filename}none or inline): note as "will be inlined into parent skill"MCP configs: Map claude/{group}/.mcp.json to the target MCP format:
{plugin_root}/{config_dir}/{target_mcp_filename}Store the predicted paths as PREVIEW_FILE_TREE -- a list of entries, each containing: { source_path, target_path, component_type, component_name, mapping_strategy }.
For each component, estimate its conversion status by analyzing how well CONVERSION_KNOWLEDGE covers the component's features:
allowed-tools and body, check how many have non-null mappings in tool name mappings${CLAUDE_PLUGIN_ROOT} patterns, check if composition mechanism is not noneAskUserQuestion references, check if a mapping existssupported (non-null mapping exists), partial (mapping is partial:* or workaround-dependent), and unsupported (mapping is null) featuresoptimistic_score = ((supported + partial) * 1.0 + unsupported * 0.0) / total * 100
pessimistic_score = ((supported * 1.0) + (partial * 0.7) + (unsupported * 0.0)) / total * 100
"Full" -- component is highly portable"Partial" -- component works but with limitations"Unsupported" -- significant gaps, may not be worthwhileStore predictions as PREVIEW_STATUS -- a list of entries, each containing: { component_name, component_type, group, supported_count, partial_count, unsupported_count, total_count, optimistic_score, pessimistic_score, predicted_status }.
For each component, identify expected issues from the mapping analysis:
null in tool name mappingsnull in frontmatter mappingsnone and component uses compositionnull in hook event mappingsAskUserQuestion and the mapping is nullGroup issues by severity:
Store as PREVIEW_ISSUES -- a list of entries, each containing: { component_name, feature, severity, reason, adapter_notes }.
Compute an overall estimated fidelity range across all components:
overall_optimistic = sum(component.optimistic_score * component.weight) / sum(component.weight)
overall_pessimistic = sum(component.pessimistic_score * component.weight) / sum(component.weight)
Where weight is the same as Phase 5 Step 9:
skill = 3, agent = 2, hooks = 1, reference = 1, mcp = 1Round both scores to the nearest integer.
Present the preview in a structured format.
Large plugin group handling: If SELECTED_COMPONENTS has more than 20 components, summarize the file tree by grouping files by directory rather than listing every individual file. Show the directory structure with file counts per directory instead.
## Dry-Run Preview: {TARGET_PLATFORM}
**Components:** {SELECTED_COMPONENTS.length}
**Estimated fidelity:** {overall_pessimistic}% - {overall_optimistic}%
### Target File Tree
{If 20 or fewer components:}
{target_root}/
{For each entry in PREVIEW_FILE_TREE, sorted by target_path:}
{target_path} <- {source_path} [{mapping_strategy}]
{If more than 20 components:}
{target_root}/
{skill_dir}/ ({skill_count} files)
{agent_dir}/ ({agent_count} files)
{hook_dir}/ ({hook_count} files)
{reference_dir}/ ({ref_count} files)
{config_dir}/ ({config_count} files)
### Per-Component Conversion Status
| Component | Type | Group | Status | Fidelity Estimate | Issues |
|-----------|------|-------|--------|-------------------|--------|
{For each entry in PREVIEW_STATUS:}
| {component_name} | {component_type} | {group} | {predicted_status} | {pessimistic_score}% - {optimistic_score}% | {issue_count} |
{If all components have predicted_status == "Unsupported":}
### Warning: All Components Unsupported
All selected components are predicted to have significant conversion gaps on {TARGET_PLATFORM}. The overall estimated fidelity is {overall_pessimistic}% - {overall_optimistic}%. Conversion may not produce useful output. Consider:
- Selecting a different target platform
- Selecting fewer, simpler components
- Reviewing the gap details below before proceeding
### Expected Issues
{If PREVIEW_ISSUES is empty:}
No significant issues detected. All features have direct or partial mappings.
{If PREVIEW_ISSUES is not empty:}
{Group by severity, show critical first:}
**Critical ({critical_count}):**
{For each critical issue:}
- **{component_name}**: `{feature}` -- {reason}{If adapter_notes: " ({adapter_notes})"}
**Functional ({functional_count}):**
{For each functional issue:}
- **{component_name}**: `{feature}` -- {reason}
**Cosmetic ({cosmetic_count}):**
{For each cosmetic issue:}
- **{component_name}**: `{feature}` -- {reason}
### Estimated Fidelity
**Overall:** {overall_pessimistic}% - {overall_optimistic}% (weighted by component complexity)
The fidelity range reflects the best-case (all partial mappings succeed fully) and worst-case (partial mappings contribute reduced fidelity) scenarios. The actual score will be determined during interactive conversion when incompatibilities are resolved.
After displaying the preview, present the user with a decision via AskUserQuestion.
If DRY_RUN = true (invoked with --dry-run flag):
AskUserQuestion:
questions:
- header: "Dry-Run Complete"
question: "The dry-run preview is complete. No files were written. Would you like to proceed with the actual conversion?"
options:
- label: "Proceed with conversion"
description: "Continue to Phase 5 (Interactive Conversion) and convert the selected components"
- label: "Done"
description: "Exit the porter -- preview only"
multiSelect: false
If DRY_RUN = false (preview was offered and accepted):
AskUserQuestion:
questions:
- header: "Preview Complete"
question: "Preview complete. Proceed with interactive conversion?"
options:
- label: "Proceed with conversion"
description: "Continue to Phase 5 and convert the selected components"
- label: "Cancel"
description: "Exit the porter"
multiSelect: false
Handle choices:
DRY_RUN = false (in case it was true). Continue to Phase 5.Porter exited after dry-run preview. No files were written.
Components analyzed: {count}
Estimated fidelity: {overall_pessimistic}% - {overall_optimistic}%
Goal: Convert each selected component using a wave-based agent team, where each port-converter agent (Sonnet) handles a single component in an isolated context. The orchestrator (this skill, Opus) manages session files, spawns agent waves, resolves incompatibilities between waves, and consolidates results.
This phase consumes SELECTED_COMPONENTS, CONVERSION_ORDER, DEPENDENCY_GRAPH, and CONVERSION_KNOWLEDGE from Phases 2-4.
Create the session directory and write shared files that converter agents will read.
mkdir -p .claude/sessions/__port_live__/results
If .claude/sessions/__port_live__/ already exists (stale session from a previous interrupted run):
mv .claude/sessions/__port_live__ .claude/sessions/port-interrupted-{YYYYMMDD}-{HHMMSS}mkdir -p .claude/sessions/__port_live__/resultsWrite CONVERSION_KNOWLEDGE to .claude/sessions/__port_live__/conversion_knowledge.md following the format specified in ${CLAUDE_PLUGIN_ROOT}/skills/port-plugin/references/session-format.md.
The file contains all 9 adapter mapping sections (tool names, model tiers, skill frontmatter, agent frontmatter, hook events, directory structure, composition mechanism, path resolution, known limitations) serialized as markdown tables and key-value sections.
This file is written once and not modified during conversion.
Write DEPENDENCY_GRAPH to .claude/sessions/__port_live__/dependency_graph.md following the session format reference.
Include: conversion order with wave assignments, dependency edges, circular references (if any), external dependencies, and classification counts.
This file is written once and not modified during conversion.
Write an empty resolution cache to .claude/sessions/__port_live__/resolution_cache.md:
# Resolution Cache
## Cached Decisions
| Group Key | Decision Type | Workaround Applied | First Component | Apply Globally |
|-----------|-------------|-------------------|-----------------|---------------|
This file grows between waves as the orchestrator resolves incompatibilities.
Using CONVERSION_ORDER from Phase 3's topological sort, assign each component to a wave:
Cap each wave at 5 concurrent agents (matching the execute-tasks pattern).
If a wave has more than 5 components, split it into sub-waves of up to 5, maintaining the same dependency level.
Present the wave-based execution plan:
## Phase 5: Wave-Based Conversion
**Session directory:** .claude/sessions/__port_live__/
**Total components:** {count}
**Waves:** {wave_count}
**Max concurrent agents per wave:** 5
### Execution Plan
| Wave | Components | Types |
|------|-----------|-------|
| 1 | {component_list} | {type_summary} |
| 2 | {component_list} | {type_summary} |
| ... | ... | ... |
### Session Files Written
- conversion_knowledge.md — {line_count} lines (merged adapter + research)
- dependency_graph.md — {line_count} lines (serialized graph)
- resolution_cache.md — initialized (empty)
- results/ — empty directory for agent output
Process components wave by wave. For each wave, spawn port-converter agents in parallel, then resolve incompatibilities between waves.
For each wave (starting with Wave 1):
Display wave start:
### Wave {n}/{total_waves}: {component_count} component(s)
Spawn converter agents using the Task tool with up to 5 parallel calls in a single turn:
For each component in the current wave, launch a port-converter agent:
Task tool:
subagent_type: "agent-alchemy-plugin-tools:port-converter"
model: "sonnet"
prompt: |
Convert this component to {TARGET_PLATFORM} format.
## Component Details
- **Type:** {component.type}
- **Group:** {component.group}
- **Name:** {component.name}
- **Source path:** {component.path}
- **Component ID:** {component.type}-{component.group}-{component.name}
## Session Directory
{absolute_path_to}/.claude/sessions/__port_live__/
## Target Platform
{TARGET_PLATFORM}
## Converter Reference to Load
{If type == "agent": "${CLAUDE_PLUGIN_ROOT}/references/agent-converter.md"}
{If type == "hooks": "${CLAUDE_PLUGIN_ROOT}/references/hook-converter.md"}
{If type == "reference": "${CLAUDE_PLUGIN_ROOT}/references/reference-converter.md"}
{If type == "mcp": "${CLAUDE_PLUGIN_ROOT}/references/mcp-converter.md"}
{If type == "skill": "None — skill conversion logic is built into the agent"}
## Session Format Reference
Read ${CLAUDE_PLUGIN_ROOT}/skills/port-plugin/references/session-format.md for the result file format specification.
CRITICAL: Launch all agents in a wave as parallel Task tool calls in a single message. Do not wait for one agent to finish before launching the next within the same wave. This is the key to context isolation — each agent gets its own context window.
Wait for all agents in the wave to complete before proceeding.
After all agents in a wave return:
Read all result files from .claude/sessions/__port_live__/results/ for this wave's components:
Read: .claude/sessions/__port_live__/results/result-{component-id}.md
Parse each result file extracting: metadata, converted content, fidelity report, decisions, gaps, and unresolved incompatibilities
Handle missing or error results: If an agent failed to write a result file, or the result file has Status = error:
CONVERTED_COMPONENTS with status = "error" and fidelity_score = 0{ component, feature: "entire_component", reason: "Conversion agent failed", severity: "critical" }After collecting all wave results, process unresolved incompatibilities:
Collect all unresolved incompatibilities from the wave's result files (from the Unresolved Incompatibilities tables)
Group by group_key across all results in the wave
Check resolution cache: Read .claude/sessions/__port_live__/resolution_cache.md. For each group:
group_key found with apply_globally = true: auto-apply the cached decision to the result file's converted content by replacing the inline marker with the resolution. Record with resolution_mode: "cached".apply_globally = false: offer to reuse via AskUserQuestion (see below)Present remaining incompatibilities to user using the resolution flow from ${CLAUDE_PLUGIN_ROOT}/references/incompatibility-resolver.md:
AskUserQuestionFor repeated group_key values (same incompatibility seen in a previous wave):
AskUserQuestion:
questions:
- header: "Repeated Incompatibility"
question: "'{feature_name}' was already resolved in {previous_component} (decision: {decision_type}). Apply the same decision to {current_component}?"
options:
- label: "Apply same decision"
description: "{previous_decision_description}"
- label: "Apply to this and all future occurrences"
description: "Use '{decision_type}' for all remaining '{feature_name}' incompatibilities"
- label: "Choose differently for this component"
description: "Open full resolution options"
multiSelect: false
Apply resolutions to result files: For each resolved incompatibility, update the result file's converted content by replacing the <!-- UNRESOLVED: ... --> inline marker with the applied resolution:
<!-- TODO [{TARGET_PLATFORM}]: {feature_name} -- {reason} -->Use the Edit tool to modify result files in place.
Update resolution cache: Write new decisions to .claude/sessions/__port_live__/resolution_cache.md by appending rows to the Cached Decisions table.
Cascade impact check: Using DEPENDENCY_GRAPH, check whether any resolved incompatibility affects components in later waves. If so, log a note:
Note: Resolution for '{feature_name}' may affect {count} component(s) in later waves: {component_list}
Cached resolutions will propagate automatically to later waves via the resolution cache.
After resolving incompatibilities:
Wave {n} complete: {component_count} component(s) converted
| Component | Type | Fidelity | Band |
|-----------|------|----------|------|
| {name} | {type} | {score}% | {band} |
Incompatibilities: {resolved_count} resolved, {auto_count} auto-resolved, {cached_count} from cache
Decision review checkpoint: If total decisions across all waves so far exceeds 10, or this wave had 3+ individual resolutions, offer a brief decision review summary (informational only — past decisions cannot be changed).
After completing the current wave:
After all waves are complete, consolidate results from all converter agents into the tracking structures that Phase 6 consumes.
Read all result files from .claude/sessions/__port_live__/results/:
Glob: .claude/sessions/__port_live__/results/result-*.md
For each result file, parse:
Assemble the data structures that Phase 6 expects:
CONVERTED_COMPONENTS — list of converted component results, each containing: { component, converted_content, target_path, fidelity_score, band, status, fidelity_report, decisions[], gaps[] }CONVERSION_DECISIONS — flat list of all decisions made across all components (concatenated from all result files), each containing: { component, feature, decision_type, original, converted, rationale, confidence, resolution_mode }CONVERSION_GAPS — flat list of all gaps across all components (concatenated from all result files), each containing: { component, feature, reason, severity, workaround, user_acknowledged }Compute the overall conversion fidelity as a weighted average across all components:
| Component Type | Weight | Rationale |
|----------------|--------|-----------|
| skill | 3 | Most complex — largest content, most features, primary deliverable |
| agent | 2 | Significant complexity — frontmatter, tools, body, model config |
| hooks | 1 | Configuration-oriented, typically fewer features |
| reference | 1 | Supporting content, complexity varies |
| mcp | 1 | Configuration mapping, typically straightforward |
overall_score = sum(component.fidelity_score * component.weight) / sum(component.weight)
Round to the nearest integer. Apply color band classification:
band = "green", label = "High fidelity"band = "yellow", label = "Moderate fidelity"band = "red", label = "Low fidelity"Display the consolidated conversion results:
## Phase 5 Complete: Wave-Based Conversion
**Components converted:** {count}/{total}
**Waves executed:** {wave_count}
**Session directory:** .claude/sessions/__port_live__/
| Component | Type | Group | Fidelity | Band | Status | Gaps |
|-----------|------|-------|----------|------|--------|------|
| {name} | {type} | {group} | {score}% | {Green/Yellow/Red} | {full/partial/limited} | {gap_count} |
**Decisions made:** {total_decision_count}
- Direct mappings: {direct_count}
- Workarounds applied: {workaround_count}
- TODO placeholders: {todo_count}
- Features omitted: {omitted_count}
- Auto-resolved (cosmetic): {auto_count}
- Cached resolutions: {cached_count}
**Overall fidelity:** {overall_score}% ({Green/Yellow/Red} -- {High/Moderate/Low} fidelity)
Proceed to Phase 6.
Goal: Write converted files, migration guide, and gap report to the output directory. This phase consumes CONVERTED_COMPONENTS, CONVERSION_DECISIONS, CONVERSION_GAPS, STALENESS_STATUS, and CONVERSION_KNOWLEDGE from earlier phases. All conversion results come from the session result files consolidated in Phase 5 Step 3. MAPPINGS for directory structure can be re-parsed from .claude/sessions/__port_live__/conversion_knowledge.md if needed.
Dry-run preview is handled in Phase 4.5 (before conversion). If the user chose "Done" or "Cancel" during the dry-run preview, the workflow will have exited before reaching this phase. If Phase 6 is reached, conversion has already been approved.
Build a platform-specific directory suggestion from the adapter's directory structure. The suggestion should reflect where the target platform expects plugin files to live:
Compute the default suggestion:
MAPPINGS.directory_structure.plugin_root is non-null, use it as the base (e.g., .opencode/ for OpenCode){project_root}/{plugin_root}plugin_root is null or the adapter is unavailable, fall back to ported/{TARGET_PLATFORM}/Compute a neutral alternative:
ported/{TARGET_PLATFORM}/ as a project-relative staging directory that avoids overwriting any existing platform configurationAsk the user via AskUserQuestion:
AskUserQuestion:
questions:
- header: "Output Directory"
question: "Where should the converted plugin files be written?"
options:
- label: "{computed_platform_suggestion}"
description: "Target platform's expected plugin location ({MAPPINGS.directory_structure.plugin_root})"
- label: "ported/{TARGET_PLATFORM}/"
description: "Staging directory in the project root (safe -- does not overwrite platform config)"
- label: "Custom path"
description: "Specify a custom output directory"
multiSelect: false
AskUserQuestion:AskUserQuestion:
questions:
- header: "Custom Output Directory"
question: "Enter the path for the output directory (absolute or relative to project root):"
OUTPUT_DIRBefore writing, check whether OUTPUT_DIR already exists and contains files:
Use Glob to check for any existing files at {OUTPUT_DIR}/**/*
If files exist, warn the user via AskUserQuestion:
AskUserQuestion:
questions:
- header: "Existing Files Detected"
question: "The output directory '{OUTPUT_DIR}' already contains {file_count} file(s). Writing converted files may overwrite existing content. How would you like to proceed?"
options:
- label: "Overwrite existing files"
description: "Replace any conflicting files -- non-conflicting files are left untouched"
- label: "Choose a different directory"
description: "Go back and select a different output location"
- label: "Cancel"
description: "Exit the porter without writing files"
multiSelect: false
If all entries in CONVERTED_COMPONENTS have status = "unsupported" or CONVERTED_COMPONENTS is empty (all components had no mappable features):
Inform the user:
No components could be converted to {TARGET_PLATFORM} format. All selected components
are unsupported on the target platform.
Write the gap report only:
OUTPUT_DIR if it does not exist (using Bash: mkdir -p)GAP-REPORT.md to OUTPUT_DIR/GAP-REPORT.md (generated in Step 7)Store WRITE_RESULTS with { files_written: [], files_failed: [], files_renamed: [], gap_report_only: true }
Skip to Step 6.
Build the directory tree following the adapter's directory conventions. The structure is derived from MAPPINGS.directory_structure:
Compute required directories by scanning CONVERTED_COMPONENTS for unique target paths:
REQUIRED_DIRS = set()
For each entry in CONVERTED_COMPONENTS where status != "unsupported":
Extract the directory portion of entry.target_path
Add to REQUIRED_DIRS
Typical directories based on adapter fields:
{OUTPUT_DIR}/{skill_dir} -- for converted skills (e.g., {OUTPUT_DIR}/commands/){OUTPUT_DIR}/{agent_dir} -- for converted agents (if agent_dir is non-null){OUTPUT_DIR}/{hook_dir} -- for converted hooks (if hook_dir is non-null){OUTPUT_DIR}/{reference_dir} -- for standalone reference files (if reference_dir is non-null){OUTPUT_DIR}/{config_dir} -- for configuration files like MCP configs (if config_dir is non-null)Per-skill subdirectories: If MAPPINGS.directory_structure.skill_file_pattern contains a subdirectory separator (e.g., {name}/SKILL.md), create a subdirectory per skill:
{OUTPUT_DIR}/{skill_dir}/{skill-name}/ to REQUIRED_DIRS{name}/SKILL.md with skill deep-analysis adds .opencode/skills/deep-analysis/Instruction-array references: If the adapter defines reference_dir: null and a Config File Format with instruction_key, create a references directory:
{OUTPUT_DIR}/references/ to REQUIRED_DIRSFor adapter fields that are null (e.g., OpenCode has reference_dir: null):
Create directories using Bash: mkdir -p for each entry in REQUIRED_DIRS:
mkdir -p "{OUTPUT_DIR}/{dir1}" "{OUTPUT_DIR}/{dir2}" ...
Error handling: If mkdir -p fails (permission denied, disk full, invalid path):
AskUserQuestion to offer recovery:AskUserQuestion:
questions:
- header: "Directory Creation Failed"
question: "Could not create the output directory structure: {error_message}. How would you like to proceed?"
options:
- label: "Choose a different directory"
description: "Go back and select a different output location"
- label: "Cancel"
description: "Exit the porter without writing files"
multiSelect: false
Initialize tracking for write results:
WRITE_RESULTS = {
files_written: [], // { component, target_path, size_bytes }
files_failed: [], // { component, target_path, error }
files_renamed: [], // { component, original_path, renamed_path, reason }
gap_report_only: false
}
Before writing, scan CONVERTED_COMPONENTS for path conflicts -- multiple components that resolve to the same target_path:
target_path -> [components]CONVERSION_ORDER position) keeps the original path{filename}-{group} or {filename}-{n} where {n} is an incrementing counterdeep-analysis.md and deep-analysis.md from different groups become deep-analysis.md and deep-analysis-dev-tools.mdWRITE_RESULTS.files_renamedCONVERSION_DECISIONS:
{ component, feature: "file_path", decision_type: "renamed", original: "{original_path}", converted: "{renamed_path}", rationale: "Path conflict with {conflicting_component}" }
Process each entry in CONVERTED_COMPONENTS where status != "unsupported", in CONVERSION_ORDER:
Determine the full output path:
OUTPUT_DIR with the component's target_path (which is already relative to the output directory)Handle inlined reference content:
<!-- INLINE: {path} --> markers from Phase 5 composition flattening:
CONVERTED_COMPONENTS<!-- TODO: Could not inline {path} -- file not found or unreadable -->Write the file using the Write tool:
converted_content to the full output pathTrack the result:
WRITE_RESULTS.files_written with { component: component.name, target_path: full_path, size_bytes: content_length }WRITE_RESULTS.files_failed with { component: component.name, target_path: full_path, error: error_message }Display progress for each file:
Writing [{n}/{total}]: {target_path} ({component.type}: {component.name})
After attempting all file writes:
If any files failed (WRITE_RESULTS.files_failed is non-empty):
Display a summary of failures:
WARNING: {failed_count} file(s) could not be written:
| Component | Target Path | Error |
|-----------|-------------|-------|
| {name} | {path} | {error} |
These failures will be included in the migration guide and gap report.
If ALL files failed (no files were successfully written):
Inform the user:
ERROR: No files could be written to {OUTPUT_DIR}. This may indicate a permissions issue
or an invalid output path.
Use AskUserQuestion to offer recovery:
AskUserQuestion:
questions:
- header: "All File Writes Failed"
question: "No converted files could be written to '{OUTPUT_DIR}'. Error: {most_common_error}. How would you like to proceed?"
options:
- label: "Choose a different directory"
description: "Go back and select a different output location"
- label: "Continue without writing files"
description: "Skip file output -- proceed to migration guide and gap report"
- label: "Cancel"
description: "Exit the porter"
multiSelect: false
If the adapter defines a Config File Format section (check CONVERSION_KNOWLEDGE for config_file, config_format, and related fields), generate the unified config file by aggregating fragments from all converted components.
Check for Config File Format: Look for config_file in CONVERSION_KNOWLEDGE. If not defined, skip this step entirely.
Collect config fragments from all result files in {SESSION_DIR}/results/:
result-*.md file's "Config Fragments" sectionMerge into single config object: Deep-merge all fragments, with later entries winning on conflict:
CONFIG = {}
For each fragment in collected_fragments (ordered by CONVERSION_ORDER):
Deep-merge fragment into CONFIG
Merge rules:
agent key — each agent name is a separate sub-key, no conflicts expectedmcp key — each server name is a separate sub-keypermission key — last write wins for each tool nameHandle existing config file: If the config file already exists at the target path (e.g., project already has an opencode.json):
CONVERSION_DECISIONS: "Merged config into existing {config_file}"Write the config file using the Write tool:
{config_file} (relative to project root, as defined in the adapter)config_format (json, jsonc, yaml, toml)Track in WRITE_RESULTS:
{ component: "config", target_path: config_file_path, size_bytes: content_length } to WRITE_RESULTS.files_writtenWRITE_RESULTS.files_failedGenerate the MIGRATION-GUIDE.md file in OUTPUT_DIR. This file documents the entire conversion for the user's reference, including fidelity scores, all decisions made during the incompatibility resolution process, and post-conversion manual steps.
Data sources: This step consumes CONVERTED_COMPONENTS, CONVERSION_DECISIONS, CONVERSION_GAPS, STALENESS_STATUS, WRITE_RESULTS, and FIDELITY_REPORT from earlier phases. All sources are optional -- the guide degrades gracefully when data is missing (see edge case handling below).
Before building the migration guide content, check for special conditions that affect the guide's structure:
Clean conversion (all components Green band, zero gaps):
If every entry in CONVERTED_COMPONENTS has band == "green" and gaps is empty, set CLEAN_CONVERSION = true. The header will include a celebratory note and several sections will be simplified.
Very large conversion (20+ components):
If CONVERTED_COMPONENTS.length > 20, set LARGE_CONVERSION = true. Per-component details will use a condensed table format instead of individual sub-sections to keep the guide readable.
No incompatibility decisions:
If CONVERSION_DECISIONS is empty or undefined (e.g., the incompatibility resolver was skipped, or all features had direct mappings), set NO_DECISIONS = true. The Decisions Log section will be replaced with a brief note.
Missing decision data (resolver skipped):
If CONVERSION_DECISIONS is undefined or null (not just empty), treat it as an empty list. Do not error. Log internally: "Note: CONVERSION_DECISIONS not available -- incompatibility resolver may have been skipped." The migration guide will omit the Decisions Log section with an explanatory note.
Missing staleness data:
If STALENESS_STATUS is undefined or null, skip the Platform Adapter Status section entirely and add a note: "Platform adapter staleness check was not performed during this conversion."
Build the MIGRATION-GUIDE.md with the following sections in order:
Section 1: Header
# Migration Guide: Agent Alchemy to {TARGET_PLATFORM}
**Generated:** {current_date}
**Source:** Agent Alchemy ({SELECTED_COMPONENTS.length} components from {SELECTED_GROUPS.length} plugin groups)
**Target platform:** {TARGET_PLATFORM}
**Overall fidelity:** {overall_score}% ({Band} -- {Label})
{If CLEAN_CONVERSION:}
> All components were converted with high fidelity (80%+ score) and no conversion
> gaps were identified. This is a clean conversion -- the converted plugin should
> work on {TARGET_PLATFORM} with minimal or no manual adjustments.
{If WRITE_RESULTS.gap_report_only:}
> **Note:** Files were not written to disk during this conversion. This guide
> documents what would have been converted. See the gap report for details.
Section 2: Conversion Fidelity
---
## Conversion Fidelity
**Overall score:** {overall_score}% -- {Band} ({Label})
### Per-Component Scores
| Component | Type | Score | Band | Direct | Workaround | TODO | Omitted | Total Features |
|-----------|------|-------|------|--------|------------|------|---------|----------------|
{For each entry in CONVERTED_COMPONENTS:}
| {name} | {type} | {score}% | {Green/Yellow/Red} | {direct_count} | {workaround_count} | {todo_count} | {omitted_count} | {total_features} |
### Score Legend
| Band | Range | Meaning |
|------|-------|---------|
| Green | 80-100% | High fidelity -- minimal manual work needed |
| Yellow | 50-79% | Moderate fidelity -- some manual work needed |
| Red | 0-49% | Low fidelity -- significant manual work needed |
For each component with band == "yellow" or band == "red", add a detailed breakdown sub-section:
{For each component with band == "yellow" or band == "red":}
### {component_name} -- {score}% ({Band})
**Breakdown:**
- Direct mappings: {direct_count}/{total_features} features ({direct_count/total_features*100}%)
- Workarounds: {workaround_count} features (contributing {workaround_count * 0.7} weighted points)
- TODO placeholders: {todo_count} features (contributing {todo_count * 0.2} weighted points)
- Omitted: {omitted_count} features (no contribution)
{If notes exist:}
**Notes:** {notes list}
Section 3: Platform Adapter Status
{If STALENESS_STATUS is defined:}
---
## Platform Adapter Status
| Field | Value |
|-------|-------|
| Staleness check performed | {STALENESS_STATUS.checked ? "yes" : "no"} |
| Adapter version | {STALENESS_STATUS.adapter_version or "unversioned"} |
| Adapter target platform version | {STALENESS_STATUS.adapter_platform_version or "N/A"} |
| Research-reported platform version | {STALENESS_STATUS.research_platform_version or "not reported"} |
| Status | {current / stale / unversioned / check failed} |
| User decision | {STALENESS_STATUS.user_decision or "N/A"} |
| Stale mappings found | {STALENESS_STATUS.stale_mappings.length} |
| New features discovered | {STALENESS_STATUS.new_features.length} |
{If STALENESS_STATUS.stale_mappings.length > 0:}
### Stale Mappings
| Mapping | Adapter Value | Research Value |
|---------|--------------|----------------|
| {name} | {old_value} | {new_value} |
{If STALENESS_STATUS.new_features.length > 0:}
### New Platform Features
{For each feature:}
- {feature_name}: {description}
{If STALENESS_STATUS is undefined or null:}
---
## Platform Adapter Status
Platform adapter staleness check was not performed during this conversion.
Section 4: Conversion Summary
---
## Conversion Summary
| Component | Type | Group | Fidelity | Band | Status | Gaps |
|-----------|------|-------|----------|------|--------|------|
{For each entry in CONVERTED_COMPONENTS:}
| {name} | {type} | {group} | {score}% | {Green/Yellow/Red} | {status} | {gap_count} |
Section 5: Per-Component Details
This section's format depends on the LARGE_CONVERSION flag.
{If LARGE_CONVERSION is false (20 or fewer components):}
Generate a full sub-section for each component:
---
## Per-Component Details
{For each entry in CONVERTED_COMPONENTS:}
### {component.type}: {component.name} ({component.group})
**Fidelity:** {score}% ({band} -- {label})
**Source:** {component.path}
**Target:** {component.target_path}
#### Feature Mapping
| Feature | Category | Original | Converted | Notes |
|---------|----------|----------|-----------|-------|
{For each decision in entry.decisions:}
| {feature} | {decision_type} | {original} | {converted} | {rationale} |
{If entry.decisions is empty:}
All features were directly mapped with no modifications required.
{If entry.gaps is non-empty:}
#### Gaps
| Feature | Reason | Severity | Workaround |
|---------|--------|----------|------------|
{For each gap in entry.gaps:}
| {feature} | {reason} | {severity} | {workaround or "None"} |
{If LARGE_CONVERSION is true (more than 20 components):}
Use a condensed table format for all components, followed by detail sub-sections only for components with band == "yellow" or band == "red":
---
## Per-Component Details
> This conversion included {CONVERTED_COMPONENTS.length} components. Details are
> shown in table format for readability. Components with Yellow or Red fidelity
> bands have expanded detail sections below the table.
### All Components
| Component | Type | Group | Score | Source | Target | Decisions | Gaps |
|-----------|------|-------|-------|--------|--------|-----------|------|
{For each entry in CONVERTED_COMPONENTS:}
| {name} | {type} | {group} | {score}% {band} | {source_path} | {target_path} | {decisions.length} | {gaps.length} |
{For each component with band == "yellow" or band == "red":}
### {component.type}: {component.name} -- {score}% ({band})
**Source:** {component.path}
**Target:** {component.target_path}
| Feature | Category | Original | Converted | Notes |
|---------|----------|----------|-----------|-------|
{For each decision in entry.decisions:}
| {feature} | {decision_type} | {original} | {converted} | {rationale} |
{If entry.gaps is non-empty:}
| Gap Feature | Reason | Severity | Workaround |
|-------------|--------|----------|------------|
{For each gap in entry.gaps:}
| {feature} | {reason} | {severity} | {workaround or "None"} |
Section 6: Decisions Log
This section consolidates all user decisions from the incompatibility resolver into a single reference. It complements the per-component details by providing a cross-cutting view of every decision made during conversion.
{If NO_DECISIONS is true:}
---
## Decisions Log
No incompatibility decisions were required during this conversion. All features
had direct mappings to {TARGET_PLATFORM} equivalents.
{If NO_DECISIONS is false:}
---
## Decisions Log
The following decisions were made during incompatibility resolution. Each entry
records what was asked, what was chosen, and the impact on the converted output.
**Summary:** {total_decisions} decisions -- {direct_count} direct, {workaround_count} workarounds, {todo_count} TODOs, {omitted_count} omitted
### By Resolution Mode
{Count decisions by resolution_mode and display:}
- **Individual**: {individual_count} (resolved one at a time via user prompt)
- **Batch**: {batch_count} (resolved as a group of similar incompatibilities)
- **Cached**: {cached_count} (reused a previous decision for the same feature)
- **Auto**: {auto_count} (auto-resolved cosmetic gaps with high-confidence workarounds)
### Decision Details
| # | Component | Feature | Decision | Resolution Mode | Confidence | Rationale |
|---|-----------|---------|----------|-----------------|------------|-----------|
{For each decision in CONVERSION_DECISIONS, numbered sequentially:}
| {n} | {component} | {feature} | {decision_type} | {resolution_mode or "N/A"} | {confidence or "N/A"} | {rationale} |
If CONVERSION_DECISIONS contains entries but some entries are missing fields (e.g., resolution_mode or confidence are undefined), display "N/A" for those fields rather than erroring.
Section 7: Post-Conversion Steps
This section lists manual actions the user should take after conversion. The steps are derived from three sources:
CONVERSION_GAPS: Any gap with severity: "critical" or severity: "functional" implies a manual stepCONVERSION_DECISIONS: Decisions with decision_type: "todo" indicate features needing manual implementation; decisions with decision_type: "workaround" where confidence is "low" or "uncertain" need verificationSTALENESS_STATUS: If the adapter is stale, recommend verifying converted output against current platform docsBuild the steps using this category-by-decision_type matrix:
| Source | Condition | Manual Step | |--------|-----------|-------------| | CONVERSION_GAPS | severity == "critical" | "Implement {feature} manually -- critical to component function" | | CONVERSION_GAPS | severity == "functional" | "Review {feature} gap in {component} -- may need manual implementation" | | CONVERSION_DECISIONS | decision_type == "todo" | "Complete TODO placeholder for {feature} in {target_path}" | | CONVERSION_DECISIONS | decision_type == "workaround" and confidence in ["low", "uncertain"] | "Verify workaround for {feature} in {component} -- confidence: {confidence}" | | STALENESS_STATUS | status == "stale" | "Adapter may be outdated -- verify converted output against current {TARGET_PLATFORM} documentation" | | WRITE_RESULTS | files_failed is non-empty | "Retry writing failed files or create them manually: {file_list}" | | General | always | "Test the converted plugin on {TARGET_PLATFORM}" | | General | always | "Review all TODO comments in converted files (search for 'TODO [{TARGET_PLATFORM}]')" | | General | mcp components converted | "Configure MCP servers for {TARGET_PLATFORM} environment" | | General | hooks were omitted or converted to workarounds | "Verify hook behavior replacements work as expected" |
---
## Post-Conversion Steps
The following manual steps are recommended after conversion:
### Required Actions
{For each step derived from critical gaps and TODO decisions:}
{n}. **{component}**: {action_description}
- Source: `{source_path}`
- Target: `{target_path}`
{If no required actions:}
No required actions -- all critical features were successfully converted.
### Recommended Verifications
{For each step derived from low-confidence workarounds, functional gaps, and staleness:}
{n}. {verification_description}
### Platform Setup
{For each platform-specific setup step:}
{n}. {setup_instruction}
{General steps always included:}
- Test the converted plugin on {TARGET_PLATFORM} to verify runtime behavior
- Review all TODO comments in converted files (search for `TODO [{TARGET_PLATFORM}]`)
- Consult `GAP-REPORT.md` for a detailed breakdown of all conversion gaps
{If MCP components were converted:}
- Configure MCP servers for your {TARGET_PLATFORM} environment (server URLs, authentication, transport settings)
{If hooks were converted with workarounds or omitted:}
- Verify that hook behavior replacements (or their absence) do not affect your workflow
Section 8: File Inventory
{If WRITE_RESULTS.files_renamed is non-empty:}
---
## File Path Renames
The following files were renamed to avoid path conflicts:
| Component | Original Path | Renamed Path | Reason |
|-----------|--------------|--------------|--------|
{For each rename in WRITE_RESULTS.files_renamed:}
| {component} | {original_path} | {renamed_path} | {reason} |
{If WRITE_RESULTS.files_failed is non-empty:}
---
## Failed File Writes
The following files could not be written:
| Component | Target Path | Error |
|-----------|-------------|-------|
{For each failure in WRITE_RESULTS.files_failed:}
| {component} | {target_path} | {error} |
---
## Output Files
{For each entry in WRITE_RESULTS.files_written:}
- `{target_path}` -- {component.type}: {component.name}
{Always included:}
- `MIGRATION-GUIDE.md` -- this file
- `GAP-REPORT.md` -- conversion gap analysis
After assembling all migration guide sections, append a machine-readable metadata block at the very end of the migration guide content. This block enables the update-ported-plugin skill to detect what was ported and when.
Get the current git commit hash via Bash: git rev-parse HEAD
Append the following HTML comment block to the end of the migration guide content:
<!-- PORT-METADATA
source_commit: {current_HEAD_hash}
port_date: {current_date}
adapter_version: {ADAPTER.adapter_version or "none"}
target_platform: {TARGET_PLATFORM}
target_platform_version: {ADAPTER.target_platform_version or RESEARCH_FINDINGS.platform_version or "unknown"}
components:
{For each entry in CONVERTED_COMPONENTS:}
- source: {component.source_path}
target: {component.target_path}
fidelity: {component.fidelity_score}
PORT-METADATA -->
This block must be the last content in the file. It is parsed by update-ported-plugin to detect source drift and determine which components need re-conversion.
Write the assembled migration guide to {OUTPUT_DIR}/MIGRATION-GUIDE.md using the Write tool.
If the write fails, log the error and continue to Step 7. The migration guide content should still be displayed in the Phase 7 summary output so the user can access it even if the file write failed.
Generate GAP-REPORT.md from CONVERSION_GAPS, CONVERSION_DECISIONS, and CONVERSION_KNOWLEDGE. This report documents every feature that could not be fully converted, providing explanations and workarounds.
Build the gap report data from the tracking structures:
CONVERSION_GAPS (flat list accumulated during Phase 5)CONVERSION_DECISIONS:
component + feature keysdecision_type, rationale, confidence, and resolution_mode from the matching decisioncritical, functional, and cosmetic bucketsfeature names across different components are grouped together for readability (e.g., if SendMessage is a gap in 3 agents, present it once with all affected components listed)Before generating the report, check for special conditions:
No gaps (100% conversion):
If CONVERSION_GAPS is empty, generate a brief report:
# Gap Report
**Source:** Agent Alchemy ({component_count} components)
**Target:** {TARGET_PLATFORM}
**Date:** {current_date}
## Summary
No conversion gaps were identified. All selected components were fully converted
to {TARGET_PLATFORM} format with direct mappings or applied workarounds.
Refer to `MIGRATION-GUIDE.md` for details on any workarounds that were applied
during conversion.
Write this to {output_directory}/GAP-REPORT.md and skip the remaining sub-steps.
All critical gaps:
If every gap has severity: "critical", add a prominent warning to the summary:
> **WARNING**: All identified gaps are critical. The converted plugin may not
> function correctly on {TARGET_PLATFORM} without significant manual work.
> Review each gap below and address the critical items before attempting to
> use the converted plugin.
Many similar gaps (3+ gaps with the same feature name):
Group them into a single entry with a sub-list of affected components rather than repeating the full entry for each. Example:
### SendMessage (Critical) — 4 components affected
- **Components:** code-explorer, code-synthesizer, code-architect (all core-tools), code-reviewer (dev-tools)
- **Why:** No inter-agent messaging equivalent on {TARGET_PLATFORM}
- **Workaround:** Remove inter-agent references; restructure as independent workflows
- **Manual steps:** Refactor each agent to operate independently without message passing
Build the GAP-REPORT.md with the following sections in order:
Section 1: Header and Summary
# Gap Report
**Source:** Agent Alchemy ({component_count} components from {group_names})
**Target:** {TARGET_PLATFORM}
**Date:** {current_date}
**Overall fidelity:** {weighted_average}%
## Summary
| Severity | Count | Description |
|----------|-------|-------------|
| Critical | {critical_count} | Features essential to plugin function — converted plugin may not work without these |
| Functional | {functional_count} | Features that enable specific capabilities — partial functionality loss |
| Cosmetic | {cosmetic_count} | Metadata or documentation features — no behavioral impact |
| **Total** | **{total_count}** | |
{If all critical: insert the all-critical warning from 3b}
### Impact Assessment
{Generate a 2-3 sentence summary based on the gap distribution:}
- If critical_count == 0: "The conversion is high-fidelity. All gaps are functional or cosmetic and the converted plugin should work on {TARGET_PLATFORM} with minor adjustments."
- If critical_count > 0 and critical_count < total_count / 2: "The conversion has {critical_count} critical gap(s) that require manual attention before the converted plugin will function on {TARGET_PLATFORM}. Functional and cosmetic gaps can be addressed incrementally."
- If critical_count >= total_count / 2: "The conversion has significant gaps. Over half of the identified issues are critical, indicating substantial differences between Claude Code and {TARGET_PLATFORM} capabilities. Manual porting effort will be required for core functionality."
### Resolution Breakdown
| Resolution | Count |
|------------|-------|
| Workaround applied | {workaround_count} |
| Feature omitted | {omitted_count} |
| TODO comment added | {todo_count} |
| Auto-resolved | {auto_count} |
Section 2: Gap Details
Generate one entry per gap (or per grouped gap if similar gaps were merged in step 3b). Sort by severity (critical first, then functional, then cosmetic), then alphabetically by feature name within each severity level.
For each gap entry:
## Gaps by Severity
### Critical
#### {feature_name}
| Field | Value |
|-------|-------|
| Component(s) | {component name(s)} |
| Category | {incompatibility category: unmapped tool / unmapped field / unsupported composition / unsupported hook / general gap} |
| Resolution | {decision_type: workaround / omitted / todo} |
| Confidence | {confidence level, if workaround applied} |
**Why it could not be converted:**
{reason — from the gap's `reason` field}
**Suggested workaround or alternative:**
{workaround — from the gap's `workaround` field. If no workaround: "No automated workaround available. Manual implementation required."}
**Manual steps to address:**
{Derive actionable steps from the gap context:}
1. {Step based on decision_type and feature type}
2. {Additional steps as needed}
---
### Functional
{Same entry format as Critical, repeated for each functional gap}
### Cosmetic
{Same entry format as Critical, repeated for each cosmetic gap}
Deriving manual steps: Use the following patterns based on the gap's category and decision type:
| Category | Decision | Manual Steps |
|----------|----------|-------------|
| Unmapped tool (workaround) | workaround | 1. Review the workaround text in the converted file. 2. Test that the alternative tool behaves as expected on {TARGET_PLATFORM}. |
| Unmapped tool (omitted) | omitted | 1. Identify where the tool was used in the original plugin. 2. Implement equivalent functionality using {TARGET_PLATFORM} native tools. 3. Test the component end-to-end. |
| Unmapped tool (todo) | todo | 1. Search for TODO [{TARGET_PLATFORM}] comments in the converted files. 2. Replace each TODO with a working implementation. 3. Test the component. |
| Unmapped field | any | 1. Check if the field's behavior can be configured through {TARGET_PLATFORM} settings. 2. If not, document the behavioral difference for users. |
| Unsupported composition | any | 1. Review the inlined or flattened content in the converted file. 2. Verify the content is complete and correctly placed. 3. If cross-plugin references were involved, ensure all referenced content is available. |
| Unsupported hook | any | 1. Identify the hook's purpose (security, automation, logging). 2. Check {TARGET_PLATFORM} documentation for equivalent lifecycle features. 3. Implement manually or document as a platform limitation. |
| General gap | any | 1. Review the feature's purpose in the original plugin. 2. Check {TARGET_PLATFORM} documentation for any partial equivalent. 3. Implement manually or restructure the workflow to work without this feature. |
Section 3: Platform Comparison
Generate a high-level comparison of Claude Code capabilities vs. the target platform, derived from CONVERSION_KNOWLEDGE (the merged adapter + research data).
## Platform Comparison: Claude Code vs. {TARGET_PLATFORM}
A high-level overview of feature support differences between Claude Code and {TARGET_PLATFORM}.
| Capability | Claude Code | {TARGET_PLATFORM} | Status |
|------------|-------------|---------------------|--------|
| Skills / Custom Commands | YAML frontmatter + markdown body | {target equivalent from CONVERSION_KNOWLEDGE} | {Supported / Partial / Unsupported} |
| Agents | Agent markdown files with model/tools/skills | {target equivalent} | {Supported / Partial / Unsupported} |
| Hooks / Lifecycle Events | hooks.json with PreToolUse, PostToolUse, Stop, etc. | {target equivalent} | {Supported / Partial / Unsupported} |
| Skill Composition | `Read` directive loading skill content | {target equivalent} | {Supported / Partial / Unsupported} |
| Cross-Plugin References | `${CLAUDE_PLUGIN_ROOT}/../{group}/` paths | {target equivalent} | {Supported / Partial / Unsupported} |
| Model Tiering | Per-agent model selection (opus/sonnet/haiku) | {target equivalent} | {Supported / Partial / Unsupported} |
| MCP Server Config | `.mcp.json` with stdio/sse/http transports | {target equivalent} | {Supported / Partial / Unsupported} |
| Interactive Tools | AskUserQuestion with options/multiSelect | {target equivalent} | {Supported / Partial / Unsupported} |
| Task Management | TaskCreate, TaskUpdate, TaskList, TaskGet | {target equivalent} | {Supported / Partial / Unsupported} |
| Team / Multi-Agent | TeamCreate, SendMessage | {target equivalent} | {Supported / Partial / Unsupported} |
| Reference Files | `references/` subdirectories loaded by skills | {target equivalent} | {Supported / Partial / Unsupported} |
**Status legend:**
- **Supported**: Direct equivalent exists on {TARGET_PLATFORM}
- **Partial**: Approximate equivalent exists but with reduced functionality
- **Unsupported**: No equivalent on {TARGET_PLATFORM}
Populate each row by checking CONVERSION_KNOWLEDGE:
If CONVERSION_GAPS is not available or is malformed (e.g., conversion was interrupted before Phase 5 completed):
CONVERSION_DECISIONS has any entries -- if so, infer gaps from decisions with decision_type: "omitted" or decision_type: "todo"# Gap Report
**Source:** Agent Alchemy
**Target:** {TARGET_PLATFORM}
**Date:** {current_date}
## Summary
Gap data is unavailable. The conversion process may have been interrupted
before gap tracking was complete. Refer to the converted files for any
`TODO` comments indicating features that require manual attention.
Write the assembled report to {output_directory}/GAP-REPORT.md using the Write tool.
Display a summary of all files written in this phase:
## Phase 6 Complete: Output & Reporting
**Output directory:** {OUTPUT_DIR}
### Files Written
| File | Size | Status |
|------|------|--------|
{For each entry in WRITE_RESULTS.files_written:}
| {target_path} | {size_bytes} bytes | Written |
{For each entry in WRITE_RESULTS.files_failed:}
| {target_path} | -- | FAILED: {error} |
| {OUTPUT_DIR}/MIGRATION-GUIDE.md | {size} | Written |
| {OUTPUT_DIR}/GAP-REPORT.md | {size} | Written |
**Total files written:** {WRITE_RESULTS.files_written.length + 2 (guide + report)}
**Failed writes:** {WRITE_RESULTS.files_failed.length}
{If WRITE_RESULTS.files_renamed.length > 0:}
**Files renamed (path conflicts):** {WRITE_RESULTS.files_renamed.length}
Proceed to Phase 7.
Goal: Present the conversion results and suggest next steps.
Present a summary of the conversion:
## Conversion Complete
**Source:** Agent Alchemy ({count} components)
**Target:** {TARGET_PLATFORM}
**Output:** {output_directory}
### Results
| Component | Type | Fidelity | Band | Status |
|-----------|------|----------|------|--------|
| {name} | {type} | {score}% | {Green/Yellow/Red} | {full/partial/limited} |
**Overall fidelity:** {weighted_average}% ({Green/Yellow/Red} -- {High/Moderate/Low} fidelity)
**Components converted:** {count}/{total}
**Gaps identified:** {count}
### Files Written
- {output_directory}/MIGRATION-GUIDE.md
- {output_directory}/GAP-REPORT.md
- {list of converted plugin files}
Present recommended next steps:
### Next Steps
1. Review the MIGRATION-GUIDE.md for conversion details and decisions
2. Review the GAP-REPORT.md for features that could not be converted
3. Test the converted plugins on {TARGET_PLATFORM}
4. Address any TODO comments left in converted files
5. Update the adapter file if research revealed new platform features
Archive the live session directory to preserve the conversion record:
port-{TARGET_PLATFORM}-{YYYYMMDD}-{HHMMSS}mv .claude/sessions/__port_live__ .claude/sessions/{archive_name}On error or cancellation: If the workflow is cancelled or fails at any point after the session directory was created (Phase 5 Step 1), still archive the session directory so partial results are preserved for debugging. Use the same archive procedure but append -interrupted to the name: port-{TARGET_PLATFORM}-{YYYYMMDD}-{HHMMSS}-interrupted.
If any phase fails:
AskUserQuestion to ask how to proceed:
AskUserQuestion:
questions:
- header: "Error Recovery"
question: "{Description of what failed}. How would you like to proceed?"
options:
- label: "Retry this phase"
description: "Attempt the failed phase again"
- label: "Skip to next phase"
description: "Continue without this phase's output"
- label: "Cancel"
description: "Exit the porter"
multiSelect: false
${CLAUDE_PLUGIN_ROOT}/references/adapter-format.md — Adapter file format specification (9 mapping sections)${CLAUDE_PLUGIN_ROOT}/references/agent-converter.md — Agent conversion logic (frontmatter mapping, body transformation, gap handling, fidelity scoring)${CLAUDE_PLUGIN_ROOT}/references/hook-converter.md — Hook conversion logic (event mapping, behavioral classification, workaround strategies)${CLAUDE_PLUGIN_ROOT}/references/reference-converter.md — Reference file conversion logic (discovery, path transformation, flattening)${CLAUDE_PLUGIN_ROOT}/references/mcp-converter.md — MCP config conversion logic (server mapping, transport types, tool reference renaming, platform support detection)${CLAUDE_PLUGIN_ROOT}/references/incompatibility-resolver.md — Incompatibility detection, interactive resolution, batch handling, decision tracking (includes agent vs. orchestrator responsibility split)${CLAUDE_PLUGIN_ROOT}/references/adapters/ — Directory for per-platform adapter files (one markdown file per target platform)${CLAUDE_PLUGIN_ROOT}/skills/port-plugin/references/session-format.md — Session file format contract between orchestrator and port-converter agentsdevelopment
Systematic, hypothesis-driven debugging workflow with triage-based track routing. Use when asked to "fix this bug", "debug this", "why is this failing", "this is broken", "investigate this error", "track down this issue", or any debugging situation. Supports --deep flag to force full investigation.
development
Executes diagnostic investigation tasks to test debugging hypotheses. Runs tests, traces execution, checks git history, and reports evidence. (converted from agent)
content-media
Provides architectural pattern knowledge for designing feature implementations including MVC, event-driven, microservices, and CQRS patterns. Use when designing system architecture or choosing implementation patterns.
documentation
Provides Mermaid diagram syntax, best practices, and styling rules for technical visualizations. Use when creating diagrams, flowcharts, sequence diagrams, class diagrams, state diagrams, ER diagrams, architecture diagrams, C4 diagrams, or any visual documentation in markdown.