
Workflow Skill Designer
- 76 installs
- 2.1k repo stars
- Updated June 18, 2026
- catlog22/claude-code-workflow
Design and scaffold new Claude Code skills
About
Guides creation of new Claude Code skills with proper structure and patterns. Generates boilerplate code, validates conventions, and ensures platform compatibility.
- Skill scaffolding
- Template generation
- Best practices
Workflow Skill Designer by the numbers
- 76 all-time installs (skills.sh)
- Ranked #912 of 2,715 Automation & Workflows skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/catlog22/claude-code-workflow --skill workflow-skill-designerAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 76 |
|---|---|
| repo stars | ★ 2.1k |
| Last updated | June 18, 2026 |
| Repository | catlog22/claude-code-workflow ↗ |
What it does
Design and scaffold new Claude Code skills
What you get
- implementation plan
- test suite
- passing tests
Files
Workflow Skill Designer
Meta-skill for creating structured workflow skills following the orchestrator + phases pattern. Generates complete skill packages with SKILL.md as coordinator and phases/ folder for execution details.
Architecture Overview
┌─────────────────────────────────────────────────────────────────┐
│ Workflow Skill Designer │
│ → Analyze requirements → Design orchestrator → Generate phases │
└───────────────┬─────────────────────────────────────────────────┘
│
┌───────────┼───────────┬───────────┐
↓ ↓ ↓ ↓
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ Phase 1 │ │ Phase 2 │ │ Phase 3 │ │ Phase 4 │
│ Require │ │ Orch │ │ Phases │ │ Valid │
│ Analysis│ │ Design │ │ Design │ │ & Integ │
└─────────┘ └─────────┘ └─────────┘ └─────────┘
↓ ↓ ↓ ↓
workflow SKILL.md phases/ Complete
config generated 0N-*.md skill pkgTarget Output Structure
The skill this meta-skill produces follows this structure:
.claude/skills/{skill-name}/
├── SKILL.md # Orchestrator: coordination, data flow, TodoWrite
├── phases/
│ ├── 01-{phase-name}.md # Phase execution detail (full content)
│ ├── 02-{phase-name}.md
│ ├── ...
│ └── 0N-{phase-name}.md
├── specs/ # [Optional] Domain specifications
└── templates/ # [Optional] Reusable templatesCore Design Patterns
Patterns extracted from successful workflow skill implementations (workflow-plan, project-analyze, etc.):
Pattern 1: Orchestrator + Progressive Loading
SKILL.md = Pure coordinator. Contains:
- Architecture diagram (ASCII)
- Execution flow with
Ref: phases/0N-xxx.mdmarkers - Phase Reference Documents table (read on-demand)
- Data flow between phases
- Core rules and error handling
Phase files = Full execution detail. Contains:
- Complete agent prompts, bash commands, code implementations
- Validation checklists, error handling
- Input/Output specification
- Next Phase link
Key Rule: SKILL.md references phase docs via Ref: markers. Phase docs are read only when that phase executes, not all at once.
Pattern 2: TodoWrite Attachment/Collapse
Phase starts:
→ Sub-tasks ATTACHED to TodoWrite (in_progress + pending)
→ Orchestrator executes sub-tasks sequentially
Phase ends:
→ Sub-tasks COLLAPSED back to high-level summary (completed)
→ Next phase beginsPattern 3: Inter-Phase Data Flow
Phase N output → stored in memory/variable → Phase N+1 input
└─ or written to session file for persistenceEach phase receives outputs from prior phases via:
- In-memory variables (sessionId, contextPath, etc.)
- Session directory files (.workflow/active/{sessionId}/...)
- Planning notes (accumulated constraints document)
Pattern 4: Conditional Phase Execution
Phase N output contains condition flag
├─ condition met → Execute Phase N+1
└─ condition not met → Skip to Phase N+2Pattern 5: Input Structuring
User input (free text) → Structured format before Phase 1:
GOAL: [objective]
SCOPE: [boundaries]
CONTEXT: [background/constraints]Pattern 6: Interactive Preference Collection (SKILL.md Responsibility)
Workflow preferences (auto mode, force explore, etc.) MUST be collected via AskUserQuestion in SKILL.md before dispatching to phases. Phases reference these as workflowPreferences.{key} context variables.
Anti-Pattern: Command-line flags (--yes, -e, --explore) parsed within phase files via $ARGUMENTS.includes(...).
// CORRECT: In SKILL.md (before phase dispatch)
const prefResponse = AskUserQuestion({
questions: [
{ question: "是否跳过确认?", header: "Auto Mode", options: [
{ label: "Interactive (Recommended)", description: "交互模式" },
{ label: "Auto", description: "跳过所有确认" }
]}
]
})
workflowPreferences = { autoYes: prefResponse.autoMode === 'Auto' }
// CORRECT: In phase files (reference only)
const autoYes = workflowPreferences.autoYes
// WRONG: In phase files (flag parsing)
const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y')Pattern 7: Direct Phase Handoff
When one phase needs to invoke another phase within the same skill, read and execute the phase document directly. Do NOT use Skill() routing back through SKILL.md.
// CORRECT: Direct handoff (executionContext already set)
Read("phases/02-lite-execute.md")
// Execute with executionContext (Mode 1)
// WRONG: Skill routing (unnecessary round-trip)
Skill(skill="workflow-lite-plan", args="--in-memory")Pattern 8: Phase File Hygiene
Phase files are internal execution documents. They MUST NOT contain:
| Prohibited | Reason | Correct Location |
|---|---|---|
Flag parsing ($ARGUMENTS.includes(...)) | Preferences collected in SKILL.md | SKILL.md via AskUserQuestion |
Invocation syntax (/skill-name "...") | Not user-facing docs | Removed or SKILL.md only |
Conversion provenance (Source: Converted from...) | Implementation detail | Removed |
Skill routing for inter-phase (Skill(skill="...")) | Use direct phase read | Direct Read("phases/...") |
Pattern 9: Compact Recovery (Phase Persistence)
Multi-phase workflows span long conversations. Context compression (compact) will naturally summarize earlier phase documents. The strategy uses 双重保险: TodoWrite 跟踪 active phase 保护其不被压缩,sentinel 作为兜底在压缩发生时触发恢复。
Design principle: TodoWrite in_progress = active phase → protect from compact | Sentinel = re-read fallback if protection fails.
Double insurance mechanism:
| Layer | Role | Mechanism |
|---|---|---|
| 1. Active Phase Protection | 预防 | TodoWrite in_progress 标记当前 phase → compact 时保留该 phase 完整内容,不压缩 |
| 2. Sentinel Re-read | 恢复 | Phase 文件嵌入标识符 → 若仍被压缩,检测到 sentinel-only 状态时立即 re-read |
When to apply: 任何通过 direct handoff (Pattern 7) 跨 phase 执行的场景,尤其是后续 phase 包含复杂执行协议(多 Step、agent 调度、CLI 编排)时。
---
Layer 1: Active Phase Protection (TodoWrite 联动)
TodoWrite 已经跟踪每个 phase 的执行状态。利用此信息驱动 compact 策略:
TodoWrite status → Compact behavior:
┌─ completed → ✅ 可压缩(已完成,不再需要完整内容)
├─ in_progress → 🛡️ 禁止压缩(正在执行,必须保留完整协议)
└─ pending → ✅ 可压缩(尚未加载,无内容)SKILL.md Execution Flow 中标注 compact 联动:
## Execution Flow
> **⚠️ COMPACT DIRECTIVE**: Context compression MUST check TodoWrite phase status.
> The phase currently marked `in_progress` is the active execution phase — preserve its FULL content.
> Only compress phases marked `completed` or `pending`.
Phase 1: Requirements Analysis ← TodoWrite tracks status
└─ Ref: phases/01-xxx.md
Phase 2: Execution Engine ← TodoWrite tracks status
└─ Ref: phases/02-xxx.md
...TodoWrite 状态转换 时自动更新 compact 保护范围:
Phase 1: in_progress 🛡️ → completed ✅ (compact 可压缩 Phase 1)
Phase 2: pending ✅ → in_progress 🛡️ (compact 保护 Phase 2)---
Layer 2: Sentinel Re-read (兜底恢复)
即使有 Layer 1 保护,compact 仍可能在极端场景(超长上下文、多轮 agent 调度)下压缩 active phase。Sentinel 确保恢复能力:
Phase 文件顶部嵌入 sentinel:
> **📌 COMPACT SENTINEL [Phase N: {phase-name}]**
> This phase contains {M} execution steps (Step N.1 — N.{M}).
> If you can read this sentinel but cannot find the full Step protocol below, context has been compressed.
> Recovery: `Read("phases/0N-xxx.md")`Sentinel 设计特点:
- 结构化、醒目 → compact 会将其作为关键信息保留在摘要中
- 包含 step 数量 → 提供自检依据("应该看到 M 个 Step,但只有摘要")
- 包含 re-read 路径 → 无需查表即可恢复
---
Phase Reference Table (整合双重保险)
| Phase | Document | Purpose | Compact |
|-------|----------|---------|---------|
| 1 | phases/01-xxx.md | Planning | TodoWrite 驱动 |
| 2 | phases/02-xxx.md | Execution | TodoWrite 驱动 + 🔄 sentinel |
**Compact Rules**:
1. **TodoWrite `in_progress`** → 保留完整内容,禁止压缩
2. **TodoWrite `completed`** → 可压缩为摘要
3. **🔄 sentinel fallback** → 带此标记的 phase 包含 compact sentinel;若 compact 后仅存 sentinel 而无完整 Step 协议,**必须立即 `Read("phases/0N-xxx.md")` 恢复后再继续**---
Checkpoint (执行步骤前双重验证)
> **⚠️ CHECKPOINT**: Before proceeding, verify:
> 1. This phase is TodoWrite `in_progress` (active phase protection)
> 2. Full protocol (Step N.X — N.{M}) is in active memory, not just sentinel
> If only sentinel remains → `Read("phases/0N-xxx.md")` now.Handoff 注释
// Phase N is tracked by TodoWrite — active phase protection applies.
// Sentinel fallback: if compressed despite protection, re-read triggers automatically.
Read("phases/0N-xxx.md")Execution Flow
Phase 1: Requirements Analysis
└─ Ref: phases/01-requirements-analysis.md
├─ Input source: commands, descriptions, user interaction
└─ Output: workflowConfig (phases, data flow, agents, conditions)
Phase 2: Orchestrator Design (SKILL.md)
└─ Ref: phases/02-orchestrator-design.md
├─ Input: workflowConfig
└─ Output: .claude/skills/{name}/SKILL.md
Phase 3: Phase Files Design
└─ Ref: phases/03-phase-design.md
├─ Input: workflowConfig + source content
└─ Output: .claude/skills/{name}/phases/0N-*.md
Phase 4: Validation & Integration
└─ Ref: phases/04-validation.md
└─ Output: Validated skill packagePhase Reference Documents (read on-demand):
| Phase | Document | Purpose |
|---|---|---|
| 1 | phases/01-requirements-analysis.md | Analyze workflow requirements from various sources |
| 2 | phases/02-orchestrator-design.md | Generate SKILL.md with orchestration patterns |
| 3 | phases/03-phase-design.md | Generate phase files preserving full execution detail |
| 4 | phases/04-validation.md | Validate structure, references, and integration |
Input Sources
This meta-skill accepts workflow definitions from multiple sources:
| Source | Description | Example |
|---|---|---|
| Existing commands | Convert .claude/commands/ orchestrator + sub-commands | plan.md + session/start.md + tools/*.md |
| Text description | User describes workflow in natural language | "Create a 3-phase code review workflow" |
| Requirements doc | Structured requirements file | requirements.md with phases/agents/outputs |
| Existing skill | Refactor/redesign an existing skill | Restructure a flat skill into phases |
Frontmatter Conversion Rules
When converting from command format to skill format:
| Command Field | Skill Field | Transformation |
|---|---|---|
name | name | Prefix with group: plan → workflow-plan |
description | description | Append trigger phrase: Triggers on "xxx" |
argument-hint | _(removed)_ | Arguments handled in Input Processing section |
examples | _(removed)_ | Examples moved to inline documentation |
allowed-tools | allowed-tools | Expand wildcards: Skill(*) → Skill, add commonly needed tools |
group | _(removed)_ | Embedded in name prefix |
Orchestrator Content Mapping
What goes into SKILL.md vs what goes into phase files:
SKILL.md (Coordinator)
| Section | Content | Source |
|---|---|---|
| Frontmatter | name, description, allowed-tools | Command frontmatter (converted) |
| Architecture Overview | ASCII diagram of phase flow | Derived from execution structure |
| Key Design Principles | Coordination rules | Extracted from command coordinator role |
| Execution Flow | Phase sequence with Ref: markers + Phase Reference table | Command execution process |
| Core Rules | Orchestration constraints | Command core rules |
| Input Processing | Structured format conversion | Command input processing |
| Data Flow | Inter-phase data passing | Command data flow |
| TodoWrite Pattern | Attachment/collapse lifecycle | Command TodoWrite sections |
| Post-Phase Updates | Planning notes / state updates between phases | Command inter-phase update code |
| Error Handling | Failure recovery | Command error handling |
| Coordinator Checklist | Pre/post phase actions | Command coordinator checklist |
| Related Commands | Prerequisites and follow-ups | Command related commands |
Phase Files (Execution Detail)
| Content | Rule |
|---|---|
| Full agent prompts | Preserve verbatim from source command |
| Bash command blocks | Preserve verbatim |
| Code implementations | Preserve verbatim |
| Validation checklists | Preserve verbatim |
| Error handling details | Preserve verbatim |
| Input/Output spec | Add if not present in source |
| Phase header | Add # Phase N: {Name} |
| Objective section | Add ## Objective with bullet points |
| Next Phase link | Add ## Next Phase with link to next |
Critical Rule: Phase files must be content-faithful to their source. Do NOT summarize, abbreviate, or simplify. The phase file IS the execution instruction - every bash command, every agent prompt, every validation step must be preserved.
SKILL.md Template
---
name: {skill-name}
description: {description}. Triggers on "{trigger1}", "{trigger2}".
allowed-tools: {tools}
---
# {Title}
{One-paragraph description of what this skill does and what it produces.}
## Architecture Overview
{ASCII diagram showing phases and data flow}
## Key Design Principles
1. **{Principle}**: {Description}
...
## Interactive Preference Collection
Collect workflow preferences via AskUserQuestion before dispatching to phases:
{AskUserQuestion code with preference derivation → workflowPreferences}
## Auto Mode Defaults
When `workflowPreferences.autoYes === true`: {auto-mode behavior}.
## Execution Flow
{Phase sequence with Ref: markers}
**Phase Reference Documents** (read on-demand when phase executes):
| Phase | Document | Purpose | Compact |
|-------|----------|---------|---------|
| 1 | [phases/01-xxx.md](phases/01-xxx.md) | ... | TodoWrite 驱动 |
| N | [phases/0N-xxx.md](phases/0N-xxx.md) | ... | TodoWrite 驱动 + 🔄 sentinel |
...
**Compact Rules**:
1. **TodoWrite `in_progress`** → 保留完整内容,禁止压缩
2. **TodoWrite `completed`** → 可压缩为摘要
3. **🔄 sentinel fallback** → 带此标记的 phase 包含 compact sentinel;若 compact 后仅存 sentinel 而无完整 Step 协议,必须立即 `Read()` 恢复
## Core Rules
1. {Rule}
...
## Input Processing
{How user input is converted to structured format}
## Data Flow
{Inter-phase data passing diagram}
## TodoWrite Pattern
{Attachment/collapse lifecycle description with examples}
## Post-Phase Updates
{State updates between phases}
## Error Handling
{Failure recovery rules}
## Coordinator Checklist
{Pre/post phase action list}
## Related Commands
{Prerequisites and follow-ups}Phase File Template
# Phase N: {Phase Name}
> **📌 COMPACT SENTINEL [Phase N: {phase-name}]**
> This phase contains {M} execution steps (Step N.1 — N.{M}).
> If you can read this sentinel but cannot find the full Step protocol below, context has been compressed.
> Recovery: `Read("phases/0N-xxx.md")`
> _(Include for phases marked 🔄 in SKILL.md Phase Reference table — see Pattern 9)_
{One-sentence description of this phase's goal.}
## Objective
- {Goal 1}
- {Goal 2}
## Execution
### Step N.1: {Step Name}
{Full execution detail: commands, agent prompts, code}
### Step N.2: {Step Name}
> **⚠️ CHECKPOINT**: Before proceeding, verify:
> 1. This phase is TodoWrite `in_progress` (active phase protection)
> 2. Full protocol (Step N.X — N.{M}) is in active memory, not just sentinel
> If only sentinel remains → `Read("phases/0N-xxx.md")` now.
> _(Add checkpoints before critical execution steps: agent dispatch, CLI launch, review — see Pattern 9)_
{Full execution detail}
## Output
- **Variable**: `{variableName}` (e.g., `sessionId`)
- **File**: `{output file path}`
- **TodoWrite**: Mark Phase N completed, Phase N+1 in_progress
## Next Phase
Return to orchestrator, then auto-continue to [Phase N+1: xxx](0N+1-xxx.md).Design Decision Framework
When designing a new workflow skill, answer these questions:
| Question | Impact | Example |
|---|---|---|
| How many phases? | Directory structure | 3-7 phases typical |
| Which phases are conditional? | Orchestrator logic | "Phase 3 only if conflict_risk >= medium" |
| What data flows between phases? | Data Flow section | sessionId, contextPath, configFlags |
| Which phases use agents? | Phase file complexity | Agent prompts need verbatim preservation |
| What's the TodoWrite granularity? | TodoWrite Pattern | Some phases have sub-tasks, others are atomic |
| Is there a planning notes pattern? | Post-Phase Updates | Accumulated state document across phases |
| What's the error recovery? | Error Handling | Retry once then report, vs rollback |
| Does it need preference collection? | Interactive Preference Collection | Collect via AskUserQuestion in SKILL.md, pass as workflowPreferences |
| Does phase N hand off to phase M? | Direct Phase Handoff (Pattern 7) | Read phase doc directly, not Skill() routing |
| Will later phases run after long context? | Compact Recovery (Pattern 9) | Add sentinel + checkpoints, mark 🔄 in Phase Reference table |
Phase 1: Requirements Analysis
Analyze workflow requirements from various sources (commands, descriptions, requirements docs) to build a structured workflow configuration.
Objective
- Identify all phases/steps in the workflow
- Map data flow between phases
- Identify agents, tools, and conditional logic
- Detect source type and extract content accordingly
- Produce
workflowConfigobject for subsequent phases
Step 1.1: Identify Input Source
// Determine what the user provided
const inputType = detectInputType(userInput);
// Returns: 'command_set' | 'text_description' | 'requirements_doc' | 'existing_skill'Source Type Detection
| Indicator | Type | Action |
|---|---|---|
Path to .claude/commands/**/*.md | command_set | Read orchestrator + discover sub-commands |
| Free text describing workflow | text_description | Interactive requirements gathering |
Path to .md or .json requirements | requirements_doc | Parse structured requirements |
Path to .claude/skills/**/*.md | existing_skill | Analyze and restructure |
Step 1.2: Source-Specific Analysis
Mode A: Command Set Analysis
When source is an existing orchestrator command + sub-commands:
// Step A.1: Read orchestrator command
const orchestratorPath = userInput; // e.g., ".claude/commands/workflow/plan.md"
const orchestratorContent = Read(orchestratorPath);
// Step A.2: Extract frontmatter
const frontmatter = extractYAMLFrontmatter(orchestratorContent);
// Fields: name, description, argument-hint, examples, allowed-tools, group
// Step A.3: Discover sub-commands by scanning Skill() calls
const skillCalls = orchestratorContent.match(/Skill\(skill="([^"]+)"/g);
// e.g., ["workflow:session:start", "workflow:tools:context-gather", ...]
// Step A.4: Map Skill() calls to file paths
// Pattern: "workflow:session:start" → ".claude/commands/workflow/session/start.md"
// "workflow:tools:context-gather" → ".claude/commands/workflow/tools/context-gather.md"
const subCommandPaths = skillCalls.map(call => {
const parts = call.replace('Skill(skill="', '').replace('"', '').split(':');
return `.claude/commands/${parts.join('/')}.md`;
});
// Step A.5: Read all sub-commands
const subCommands = [];
for (const path of subCommandPaths) {
const content = Read(path);
const fm = extractYAMLFrontmatter(content);
subCommands.push({
path: path,
content: content,
frontmatter: fm,
skillCallName: extractSkillCallName(path),
bodyContent: removeYAMLFrontmatter(content)
});
}
// Step A.6: Identify phase ordering from orchestrator execution flow
// Look for patterns like:
// "Phase 1: ..." → first Skill() call
// "Phase 2: ..." → second Skill() call
// Conditional logic (if/else) → conditional phases
const phaseOrder = extractPhaseOrder(orchestratorContent, skillCalls);Key Extraction Points from Orchestrator:
| Section | What to Extract | Maps to |
|---|---|---|
| Coordinator Role / Overview | Workflow description, execution model | SKILL.md description + Architecture |
| Core Rules | Orchestration constraints | SKILL.md Core Rules |
| Execution Process | Phase sequence + conditions | SKILL.md Execution Flow |
| Data Flow | Inter-phase variables | SKILL.md Data Flow |
| TodoWrite Pattern | Attachment/collapse examples | SKILL.md TodoWrite Pattern |
| Input Processing | Structured format rules | SKILL.md Input Processing |
| Error Handling | Recovery strategies | SKILL.md Error Handling |
| Coordinator Checklist | Pre/post actions | SKILL.md Coordinator Checklist |
| Related Commands | Prerequisites/follow-ups | SKILL.md Related Commands |
| Phase N sections | Phase-specific orchestrator instructions | SKILL.md inline (brief), Phase files (detail) |
Key Extraction Points from Sub-Commands:
| Section | What to Extract | Maps to |
|---|---|---|
| Full body content | Complete execution detail | Phase file (preserved verbatim) |
| Agent prompts (Task calls) | Agent delegation logic | Phase file agent sections |
| Bash command blocks | Shell execution steps | Phase file step sections |
| Validation/Output sections | Phase outputs | Phase file Output section |
| Frontmatter | Tools, description | Phase file header context |
Mode B: Text Description Analysis
When source is a natural language workflow description:
// Interactive requirements gathering
const basicInfo = AskUserQuestion({
questions: [
{
question: "What is this workflow skill's name? (kebab-case)",
header: "Name",
multiSelect: false,
options: [
{ label: "Custom name", description: "Enter a custom skill name" },
{ label: "Auto-generate", description: "Generate from workflow description" }
]
},
{
question: "How many main phases does this workflow have?",
header: "Phases",
multiSelect: false,
options: [
{ label: "3 phases", description: "Simple linear workflow" },
{ label: "4 phases", description: "Standard workflow with validation" },
{ label: "5+ phases", description: "Complex workflow with conditions" }
]
}
]
});
// For each phase, gather details
const phases = [];
for (let i = 0; i < phaseCount; i++) {
const phaseInfo = AskUserQuestion({
questions: [
{
question: `Phase ${i+1}: What does this phase do?`,
header: `Phase ${i+1}`,
multiSelect: false,
options: [
{ label: "Session/Init", description: "Initialize session or state" },
{ label: "Context/Gather", description: "Collect information or analyze" },
{ label: "Process/Transform", description: "Process data or generate artifacts" },
{ label: "Validate/Review", description: "Quality check or user review" }
]
},
{
question: `Phase ${i+1}: Does it use agents?`,
header: "Agents",
multiSelect: false,
options: [
{ label: "No agents", description: "Direct execution only" },
{ label: "Single agent", description: "Delegates to one agent" },
{ label: "Multiple agents", description: "Parallel or sequential agents" }
]
}
]
});
phases.push(phaseInfo);
}
// Gather conditional logic
const conditions = AskUserQuestion({
questions: [{
question: "Are any phases conditional (skipped based on previous results)?",
header: "Conditions",
multiSelect: false,
options: [
{ label: "No conditions", description: "All phases always execute" },
{ label: "Has conditions", description: "Some phases execute conditionally" }
]
}]
});Mode C: Requirements Document
When source is a structured requirements document:
// Read and parse requirements
const reqContent = Read(requirementsPath);
// Extract structured fields
// Expected format: Markdown with ## sections for each phase
// Or JSON with phases array
const requirements = parseRequirements(reqContent);Mode D: Existing Skill Restructure
When source is an existing skill to refactor:
// Read existing SKILL.md
const existingSkill = Read(skillPath);
// Scan for phase files
const existingPhases = Glob(`${skillDir}/phases/*.md`);
// Analyze current structure for improvement
const analysis = analyzeExistingStructure(existingSkill, existingPhases);Step 1.3: Build Workflow Configuration
Regardless of source type, produce a unified workflowConfig:
const workflowConfig = {
// Metadata
skillName: "workflow-plan", // kebab-case
title: "Workflow Plan", // Human-readable
description: "5-phase planning...", // One-line description
triggers: ["workflow-plan"], // Trigger phrases
allowedTools: ["Agent", "AskUserQuestion", "TodoWrite", "Read", "Write", "Edit", "Bash", "Glob", "Grep", "Skill"],
// Source information
source: {
type: "command_set", // input source type
orchestratorPath: "...", // original orchestrator file
subCommandPaths: ["..."] // original sub-command files
},
// Phase definitions
phases: [
{
number: 1,
name: "Session Discovery",
slug: "session-discovery", // for filename: 01-session-discovery.md
description: "Create or discover workflow session",
sourcePath: ".claude/commands/workflow/session/start.md",
isConditional: false,
condition: null,
usesAgents: false,
agentTypes: [],
todoWriteSubTasks: [], // no sub-tasks (atomic phase)
outputVariables: ["sessionId"],
outputFiles: ["planning-notes.md"]
},
{
number: 2,
name: "Context Gathering",
slug: "context-gathering",
description: "Gather project context via agents",
sourcePath: ".claude/commands/workflow/tools/context-gather.md",
isConditional: false,
condition: null,
usesAgents: true,
agentTypes: ["cli-explore-agent", "context-search-agent"],
todoWriteSubTasks: [
"Analyze codebase structure",
"Identify integration points",
"Generate context package"
],
outputVariables: ["contextPath", "conflictRisk"],
outputFiles: ["context-package.json"]
},
{
number: 3,
name: "Conflict Resolution",
slug: "conflict-resolution",
description: "Detect and resolve conflicts",
sourcePath: ".claude/commands/workflow/tools/conflict-resolution.md",
isConditional: true,
condition: "conflictRisk >= 'medium'",
usesAgents: true,
agentTypes: ["cli-execution-agent"],
todoWriteSubTasks: [
"Detect conflicts with CLI analysis",
"Present conflicts to user",
"Apply resolution strategies"
],
outputVariables: [],
outputFiles: ["conflict-resolution.json"]
},
{
number: 4,
name: "Task Generation",
slug: "task-generation",
description: "Generate implementation plan and task JSONs",
sourcePath: ".claude/commands/workflow/tools/task-generate-agent.md",
isConditional: false,
condition: null,
usesAgents: true,
agentTypes: ["action-planning-agent"],
todoWriteSubTasks: [], // single agent task
outputVariables: [],
outputFiles: ["IMPL_PLAN.md", "IMPL-*.json", "TODO_LIST.md"]
}
],
// Data flow
dataFlow: [
{ from: "input", to: "phase1", variables: ["structuredDescription"] },
{ from: "phase1", to: "phase2", variables: ["sessionId"] },
{ from: "phase2", to: "phase3", variables: ["contextPath", "conflictRisk"] },
{ from: "phase2", to: "phase4", variables: ["contextPath"] },
{ from: "phase3", to: "phase4", variables: ["resolvedArtifacts"] }
],
// Features
features: {
hasAutoMode: true, // Interactive preference collection (AskUserQuestion)
hasConditionalPhases: true, // some phases may be skipped
hasTodoWriteSubTasks: true, // phases expand into sub-tasks
hasPlanningNotes: true, // accumulated state document
hasPostPhaseUpdates: true, // state updates between phases
hasMemoryCompaction: true, // compact after heavy phases
hasUserDecisionGate: true // user choice after final phase
}
};Step 1.4: User Confirmation
Present the analyzed structure to the user for confirmation:
// Display summary
console.log(`
Workflow Analysis Complete:
Name: ${workflowConfig.skillName}
Phases: ${workflowConfig.phases.length}
${workflowConfig.phases.map(p =>
` ${p.number}. ${p.name}${p.isConditional ? ' (conditional)' : ''}${p.usesAgents ? ` [${p.agentTypes.join(', ')}]` : ''}`
).join('\n')}
Data Flow: ${workflowConfig.dataFlow.length} connections
Features: ${Object.entries(workflowConfig.features).filter(([,v]) => v).map(([k]) => k).join(', ')}
`);
const confirm = AskUserQuestion({
questions: [{
question: "Proceed with this workflow structure?",
header: "Confirm",
multiSelect: false,
options: [
{ label: "Yes, proceed", description: "Generate skill with this structure" },
{ label: "Modify phases", description: "Adjust phase count or ordering" },
{ label: "Add features", description: "Enable additional patterns (auto mode, conditions, etc.)" }
]
}]
});Output
- Variable:
workflowConfig(structured configuration object) - TodoWrite: Mark Phase 1 completed, Phase 2 in_progress
Next Phase
Return to orchestrator, then auto-continue to Phase 2: Orchestrator Design.
Phase 2: Orchestrator Design
Generate the SKILL.md orchestrator file from workflowConfig, applying all coordination patterns (progressive loading, TodoWrite, data flow, conditional execution).
Objective
- Create
.claude/skills/{skillName}/SKILL.mdas pure coordinator - Apply frontmatter conversion rules
- Generate architecture diagram from phase structure
- Build execution flow with
Ref:markers and phase reference table - Generate data flow diagram
- Build TodoWrite attachment/collapse patterns from phase definitions
- Include all orchestrator-level sections
Step 2.1: Create Directory Structure
skillDir=".claude/skills/${workflowConfig.skillName}"
mkdir -p "${skillDir}/phases"
# Optional directories based on features
# mkdir -p "${skillDir}/specs" # if has domain specifications
# mkdir -p "${skillDir}/templates" # if has reusable templatesStep 2.2: Generate Frontmatter
function generateFrontmatter(config) {
return `---
name: ${config.skillName}
description: ${config.description}. Triggers on ${config.triggers.map(t => `"${t}"`).join(', ')}.
allowed-tools: ${config.allowedTools.join(', ')}
---`;
}Conversion from command frontmatter:
// If source is command_set, convert fields:
function convertCommandFrontmatter(commandFm, config) {
return {
name: commandFm.group
? `${commandFm.group}-${commandFm.name}` // "workflow" + "plan" → "workflow-plan"
: commandFm.name,
description: commandFm.description,
// argument-hint → removed (handled in Input Processing section)
// examples → removed (moved to inline docs)
// group → embedded in name prefix
allowedTools: expandToolWildcards(commandFm['allowed-tools'])
// "Skill(*), TodoWrite(*), Read(*)" → "Task, AskUserQuestion, TodoWrite, Read, Write, Edit, Bash, Glob, Grep, Skill"
};
}
// Expand tool wildcards
function expandToolWildcards(toolsStr) {
const expanded = toolsStr
.replace(/Skill\(\*\)/g, 'Skill')
.replace(/TodoWrite\(\*\)/g, 'TodoWrite')
.replace(/Read\(\*\)/g, 'Read')
.replace(/Bash\(\*\)/g, 'Bash')
.replace(/Glob\(\*\)/g, 'Glob')
.replace(/Grep\(\*\)/g, 'Grep')
.replace(/Task\(\*\)/g, 'Task');
// Add commonly needed tools if not present
const baseTools = ['Task', 'AskUserQuestion', 'TodoWrite', 'Read', 'Write', 'Edit', 'Bash', 'Glob', 'Grep'];
const current = expanded.split(',').map(t => t.trim());
const merged = [...new Set([...current, ...baseTools])];
return merged;
}Step 2.3: Generate Architecture Diagram
function generateArchitectureDiagram(config) {
const phases = config.phases;
const maxWidth = 65;
let diagram = '```\n';
diagram += '┌' + '─'.repeat(maxWidth) + '┐\n';
diagram += `│ ${config.title} Orchestrator (SKILL.md)${' '.repeat(maxWidth - config.title.length - 30)}│\n`;
diagram += `│ → Pure coordinator: Execute phases, parse outputs, pass context${' '.repeat(maxWidth - 64)}│\n`;
diagram += '└' + '─'.repeat(Math.floor(maxWidth/2)) + '┬' + '─'.repeat(maxWidth - Math.floor(maxWidth/2) - 1) + '┘\n';
// Phase boxes
diagram += ' │\n';
diagram += ' ' + phases.map(() => '┌─────────┐').join(' ') + '\n';
diagram += ' ' + phases.map((p, i) => {
const label = `Phase ${p.number}`.padEnd(9);
return `│${label}│`;
}).join(' ') + '\n';
diagram += ' ' + phases.map(p => {
const name = p.name.substring(0, 9).padEnd(9);
return `│${name}│`;
}).join(' ') + '\n';
diagram += ' ' + phases.map(() => '└─────────┘').join(' ') + '\n';
// Output labels
diagram += ' ' + phases.map(p => {
const vars = p.outputVariables.join(', ').substring(0, 11).padEnd(11);
return ` ${vars}`;
}).join('') + '\n';
diagram += '```';
return diagram;
}Step 2.4: Generate Execution Flow
The execution flow uses Ref: markers to point to phase documents, with a Phase Reference Documents table inline.
function generateExecutionFlow(config) {
let flow = '## Execution Flow\n\n```\n';
flow += 'Input Parsing:\n';
flow += ' └─ Convert user input to structured format (GOAL/SCOPE/CONTEXT)\n\n';
for (const phase of config.phases) {
flow += `Phase ${phase.number}: ${phase.name}\n`;
if (phase.isConditional) {
flow += ` └─ Decision (${phase.condition}):\n`;
flow += ` ├─ condition met → Ref: phases/${String(phase.number).padStart(2, '0')}-${phase.slug}.md\n`;
if (phase.todoWriteSubTasks.length > 0) {
flow += ` │ ├─ Tasks attached: ${phase.todoWriteSubTasks.join(' → ')}\n`;
}
flow += ` │ └─ Output: ${phase.outputFiles.join(', ') || phase.outputVariables.join(', ')}\n`;
flow += ` └─ condition not met → Skip to Phase ${phase.number + 1}\n`;
} else {
flow += ` └─ Ref: phases/${String(phase.number).padStart(2, '0')}-${phase.slug}.md\n`;
if (phase.todoWriteSubTasks.length > 0) {
flow += ` ├─ Tasks attached: ${phase.todoWriteSubTasks.join(' → ')}\n`;
}
flow += ` └─ Output: ${[...phase.outputVariables, ...phase.outputFiles].join(', ')}\n`;
}
flow += '\n';
}
flow += 'Return:\n └─ Summary with recommended next steps\n';
flow += '```\n\n';
// Phase Reference Documents table
flow += '**Phase Reference Documents** (read on-demand when phase executes):\n\n';
flow += '| Phase | Document | Purpose |\n';
flow += '|-------|----------|---------|\n';
for (const phase of config.phases) {
const filename = `${String(phase.number).padStart(2, '0')}-${phase.slug}.md`;
flow += `| ${phase.number} | [phases/${filename}](phases/${filename}) | ${phase.description} |\n`;
}
return flow;
}Step 2.5: Generate Data Flow Section
function generateDataFlow(config) {
let section = '## Data Flow\n\n```\n';
section += 'User Input (task description)\n';
section += ' ↓\n';
section += '[Convert to Structured Format]\n';
for (const phase of config.phases) {
const inputVars = config.dataFlow
.filter(d => d.to === `phase${phase.number}`)
.flatMap(d => d.variables);
const outputVars = [...phase.outputVariables, ...phase.outputFiles];
section += ' ↓\n';
section += `Phase ${phase.number}: ${phase.name}\n`;
if (inputVars.length > 0) {
section += ` ↓ Input: ${inputVars.join(' + ')}\n`;
}
if (outputVars.length > 0) {
section += ` ↓ Output: ${outputVars.join(' + ')}\n`;
}
if (phase.isConditional) {
section += ` ↓ Skip if ${phase.condition} is false → proceed to Phase ${phase.number + 1}\n`;
}
}
section += ' ↓\n';
section += 'Return summary to user\n';
section += '```\n';
return section;
}Step 2.6: Generate TodoWrite Pattern
function generateTodoWritePattern(config) {
let section = '## TodoWrite Pattern\n\n';
section += '**Core Concept**: Dynamic task attachment and collapse for real-time visibility.\n\n';
section += '### Key Principles\n\n';
section += '1. **Task Attachment** (when phase executed):\n';
section += ' - Sub-tasks are **attached** to orchestrator\'s TodoWrite\n';
// Identify which phases have sub-tasks
const phasesWithSubTasks = config.phases.filter(p => p.todoWriteSubTasks.length > 0);
const phasesWithoutSubTasks = config.phases.filter(p => p.todoWriteSubTasks.length === 0);
if (phasesWithSubTasks.length > 0) {
section += ` - **${phasesWithSubTasks.map(p => `Phase ${p.number}`).join(', ')}**: Multiple sub-tasks attached\n`;
}
if (phasesWithoutSubTasks.length > 0) {
section += ` - **${phasesWithoutSubTasks.map(p => `Phase ${p.number}`).join(', ')}**: Single task (atomic)\n`;
}
section += '\n2. **Task Collapse** (after sub-tasks complete):\n';
if (phasesWithSubTasks.length > 0) {
section += ` - **Applies to ${phasesWithSubTasks.map(p => `Phase ${p.number}`).join(', ')}**: Remove sub-tasks, collapse to summary\n`;
}
section += ' - Maintains clean orchestrator-level view\n';
section += '\n3. **Continuous Execution**: After completion, automatically proceed to next phase\n\n';
// Generate TodoWrite examples for phases with sub-tasks
for (const phase of phasesWithSubTasks) {
section += `### Phase ${phase.number} (Tasks Attached):\n`;
section += '```json\n[\n';
// Previous phases completed
for (const prev of config.phases.filter(p => p.number < phase.number)) {
section += ` {"content": "Phase ${prev.number}: ${prev.name}", "status": "completed"},\n`;
}
// Current phase in_progress with sub-tasks
section += ` {"content": "Phase ${phase.number}: ${phase.name}", "status": "in_progress"},\n`;
phase.todoWriteSubTasks.forEach((task, i) => {
const status = i === 0 ? 'in_progress' : 'pending';
section += ` {"content": " → ${task}", "status": "${status}"},\n`;
});
// Remaining phases pending
for (const next of config.phases.filter(p => p.number > phase.number && !p.isConditional)) {
section += ` {"content": "Phase ${next.number}: ${next.name}", "status": "pending"},\n`;
}
section += ']\n```\n\n';
// Collapsed version
section += `### Phase ${phase.number} (Collapsed):\n`;
section += '```json\n[\n';
for (const p of config.phases.filter(pp => !pp.isConditional || pp.number <= phase.number)) {
const status = p.number <= phase.number ? 'completed' : 'pending';
section += ` {"content": "Phase ${p.number}: ${p.name}", "status": "${status}"},\n`;
}
section += ']\n```\n\n';
}
return section;
}Step 2.7: Generate Remaining Sections
Extract from source orchestrator or generate from config:
function generateOrchestratorSections(config, sourceContent) {
const sections = [];
// Interactive Preference Collection + Auto Mode (if feature enabled)
if (config.features.hasAutoMode) {
sections.push(generateInteractivePreferenceCollection(config));
sections.push(extractOrGenerate(sourceContent, 'Auto Mode Defaults',
'## Auto Mode Defaults\n\nWhen `workflowPreferences.autoYes === true`: Auto-continue all phases, use recommended defaults.\n'));
}
// Core Rules
sections.push(extractOrGenerate(sourceContent, 'Core Rules',
generateDefaultCoreRules(config)));
// Input Processing
sections.push(extractOrGenerate(sourceContent, 'Input Processing',
generateDefaultInputProcessing(config)));
// Post-Phase Updates (if feature enabled)
if (config.features.hasPostPhaseUpdates) {
sections.push(extractOrGenerate(sourceContent, 'Post-Phase Updates',
generatePostPhaseUpdates(config)));
}
// Error Handling
sections.push(extractOrGenerate(sourceContent, 'Error Handling',
generateDefaultErrorHandling()));
// Coordinator Checklist
sections.push(extractOrGenerate(sourceContent, 'Coordinator Checklist',
generateCoordinatorChecklist(config)));
// Related Commands
sections.push(extractOrGenerate(sourceContent, 'Related Commands',
generateRelatedCommands(config)));
return sections.join('\n\n');
}
// Extract section from source if exists, otherwise generate default
function extractOrGenerate(sourceContent, sectionName, defaultContent) {
if (sourceContent) {
const extracted = extractSection(sourceContent, sectionName);
if (extracted) return extracted;
}
return defaultContent;
}
// Default Core Rules template
function generateDefaultCoreRules(config) {
return `## Core Rules
1. **Start Immediately**: First action is TodoWrite initialization, second action is Phase 1 execution
2. **No Preliminary Analysis**: Do not read files or gather context before Phase 1
3. **Parse Every Output**: Extract required data from each phase for next phase
4. **Auto-Continue**: Check TodoList status to execute next pending phase automatically
5. **Track Progress**: Update TodoWrite dynamically with task attachment/collapse pattern
6. **Progressive Phase Loading**: Read phase docs ONLY when that phase is about to execute
7. **DO NOT STOP**: Continuous multi-phase workflow until all phases complete`;
}
// Default Error Handling template
function generateDefaultErrorHandling() {
return `## Error Handling
- **Parsing Failure**: If output parsing fails, retry once, then report error
- **Validation Failure**: Report which file/data is missing
- **Command Failure**: Keep phase \`in_progress\`, report error, do not proceed`;
}Step 2.8: Generate Interactive Preference Collection
When the skill has configurable behaviors (auto mode, force options, etc.), generate the AskUserQuestion-based preference collection section for SKILL.md:
function generateInteractivePreferenceCollection(config) {
if (!config.features.hasAutoMode && !config.preferenceQuestions?.length) {
return '';
}
let section = '## Interactive Preference Collection\n\n';
section += 'Collect workflow preferences via AskUserQuestion before dispatching to phases:\n\n';
section += '```javascript\n';
section += 'const prefResponse = AskUserQuestion({\n';
section += ' questions: [\n';
// Always include auto mode question if feature enabled
if (config.features.hasAutoMode) {
section += ' {\n';
section += ' question: "是否跳过所有确认步骤(自动模式)?",\n';
section += ' header: "Auto Mode",\n';
section += ' multiSelect: false,\n';
section += ' options: [\n';
section += ' { label: "Interactive (Recommended)", description: "交互模式,包含确认步骤" },\n';
section += ' { label: "Auto", description: "跳过所有确认,自动执行" }\n';
section += ' ]\n';
section += ' },\n';
}
// Add custom preference questions
for (const pq of (config.preferenceQuestions || [])) {
section += ` {\n`;
section += ` question: "${pq.question}",\n`;
section += ` header: "${pq.header}",\n`;
section += ` multiSelect: false,\n`;
section += ` options: [\n`;
for (const opt of pq.options) {
section += ` { label: "${opt.label}", description: "${opt.description}" },\n`;
}
section += ` ]\n`;
section += ` },\n`;
}
section += ' ]\n';
section += '})\n\n';
section += '// Derive workflowPreferences from user selection\n';
section += 'workflowPreferences = {\n';
if (config.features.hasAutoMode) {
section += ' autoYes: prefResponse.autoMode === "Auto",\n';
}
for (const pq of (config.preferenceQuestions || [])) {
section += ` ${pq.key}: prefResponse.${pq.header.toLowerCase().replace(/\\s+/g, '')} === "${pq.activeValue}",\n`;
}
section += '}\n';
section += '```\n\n';
section += '**workflowPreferences** is passed to phase execution as context variable.\n';
section += 'Phases reference as `workflowPreferences.autoYes`, `workflowPreferences.{key}`, etc.\n';
return section;
}Step 2.9: Assemble SKILL.md
function assembleSkillMd(config, sourceContent) {
const parts = [
generateFrontmatter(config),
'',
`# ${config.title}`,
'',
config.description,
'',
generateArchitectureDiagram(config),
'',
generateDesignPrinciples(config),
'',
generateExecutionFlow(config),
'',
generateDataFlow(config),
'',
generateTodoWritePattern(config),
'',
generateOrchestratorSections(config, sourceContent)
];
const skillMdContent = parts.join('\n');
Write(`${skillDir}/SKILL.md`, skillMdContent);
}Critical Quality Rules:
1. SKILL.md must NOT contain full execution detail (agent prompts, bash commands) 2. SKILL.md MUST contain Ref: markers pointing to phase files 3. SKILL.md MUST contain Phase Reference Documents table 4. Every phase mentioned in Execution Flow must have a corresponding phase file 5. Data flow variables must be consistent across sections
Output
- File:
.claude/skills/{skillName}/SKILL.md - TodoWrite: Mark Phase 2 completed, Phase 3 in_progress
Next Phase
Return to orchestrator, then auto-continue to Phase 3: Phase Files Design.
Phase 3: Phase Files Design
Generate phase files in phases/ directory, preserving full execution detail from source content. Each phase file is a complete execution instruction.
Objective
- Create
phases/0N-{slug}.mdfor each phase in workflowConfig - Preserve full source content (agent prompts, bash commands, code, validation)
- Add standard phase structure (header, objective, output, next phase)
- Handle different source types (command extraction vs new generation)
Critical Rule
Content Fidelity: Phase files must be content-faithful to their source. Do NOT summarize, abbreviate, or simplify execution detail. The phase file IS the execution instruction.
| Content Type | Rule |
|---|---|
| Agent prompts (Task calls) | Preserve verbatim including all prompt text, variables, constraints |
| Bash command blocks | Preserve verbatim including all flags, paths, error handling |
| Code implementations | Preserve verbatim including all functions, validation logic |
| Validation checklists | Preserve verbatim including all check items |
| Error handling details | Preserve verbatim including recovery strategies |
| Tables and specifications | Preserve verbatim including all rows and columns |
| Comments and notes | Preserve verbatim including inline documentation |
Anti-Pattern: Creating a phase file that says "See original command for details" or "Execute the agent with appropriate parameters" - this defeats the purpose of the skill structure. The phase file must be self-contained.
Phase File Content Restrictions
Phase files are internal execution documents. They MUST NOT contain the following prohibited content:
| Prohibited Pattern | Detection | Correct Location |
|---|---|---|
Flag parsing ($ARGUMENTS.includes(...)) | Grep: \$ARGUMENTS\.includes | SKILL.md via AskUserQuestion → workflowPreferences |
Invocation syntax (/skill-name "...") | Grep: \/\w+[\-:]\w+\s+" | Removed entirely (phase files are not user-facing) |
Conversion provenance (Source: Converted from...) | Grep: Source:.*Converted from | Removed entirely (implementation detail) |
Skill routing for inter-phase (Skill(skill="...")) | Grep: Skill\(skill= | Direct Read("phases/0N-xxx.md") |
Preference Reference Pattern
Phase files may reference workflow preferences but must NOT parse them from arguments:
// CORRECT: Reference workflowPreferences (set by SKILL.md)
const autoYes = workflowPreferences.autoYes
const forceExplore = workflowPreferences.forceExplore
// WRONG: Parse from $ARGUMENTS
const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y')
const forceExplore = $ARGUMENTS.includes('--explore') || $ARGUMENTS.includes('-e')Inter-Phase Handoff Pattern
When phase N needs to invoke phase M, use direct phase reading:
// CORRECT: Direct handoff (executionContext already set)
Read("phases/02-lite-execute.md")
// Execute with executionContext (Mode 1)
// WRONG: Skill routing (unnecessary round-trip)
Skill(skill="workflow-lite-plan", args="--in-memory")Content Restriction Enforcement
When extracting from commands (Step 3.2), apply content sanitization after verbatim extraction:
function sanitizePhaseContent(content) {
let sanitized = content;
// Remove flag parsing blocks
sanitized = sanitized.replace(
/\/\/.*flag.*parsing[\s\S]*?\n(?=\n)/gi, ''
);
// Remove invocation syntax examples
sanitized = sanitized.replace(
/^.*\/\w+[\-:]\w+\s+"[^"]*".*$/gm, ''
);
// Remove conversion provenance notes
sanitized = sanitized.replace(
/^\*\*Source\*\*:.*Converted from.*$/gm, ''
);
// Replace all $ARGUMENTS.includes patterns with workflowPreferences reference
// Handles any flag name, not just --yes/-y
sanitized = sanitized.replace(
/\$ARGUMENTS\.includes\(['"]--?([^"']+)['"]\)/g,
(match, flagName) => {
// Map common flag names to workflowPreferences keys
const flagMap = {
'yes': 'workflowPreferences.autoYes',
'y': 'workflowPreferences.autoYes',
'explore': 'workflowPreferences.forceExplore',
'e': 'workflowPreferences.forceExplore'
};
return flagMap[flagName] || `workflowPreferences.${flagName}`;
}
);
// Also clean up residual || chains from multi-flag expressions
sanitized = sanitized.replace(
/workflowPreferences\.(\w+)\s*\|\|\s*workflowPreferences\.\1/g,
'workflowPreferences.$1'
);
// Replace Skill() inter-phase routing with direct Read (with or without args)
sanitized = sanitized.replace(
/Skill\(skill=["']([^"']+)["'](?:,\s*args=["']([^"']+)["'])?\)/g,
(match, skillName) => `Read("phases/0N-xxx.md")\n// Execute with context`
);
return sanitized;
}Step 3.1: Phase File Generation Strategy
function selectGenerationStrategy(phase, config) {
if (config.source.type === 'command_set' && phase.sourcePath) {
return 'extract'; // Extract from existing command file
} else if (config.source.type === 'text_description') {
return 'generate'; // Generate from requirements
} else if (config.source.type === 'existing_skill') {
return 'restructure'; // Restructure existing content
}
return 'generate';
}Step 3.2: Mode A - Extract from Command
When source is an existing command file, transform its content into phase file format:
function extractPhaseFromCommand(phase, config) {
const sourceContent = Read(phase.sourcePath);
const sourceFrontmatter = extractYAMLFrontmatter(sourceContent);
const sourceBody = removeYAMLFrontmatter(sourceContent);
// Phase file structure:
// 1. Phase header (new)
// 2. Source body content (preserved verbatim)
// 3. Output section (extracted or added)
// 4. Next Phase link (new)
let phaseContent = '';
// 1. Phase header
phaseContent += `# Phase ${phase.number}: ${phase.name}\n\n`;
phaseContent += `${phase.description}.\n\n`;
// 2. Source body content - PRESERVED VERBATIM
// Only modifications:
// a. Remove original H1 title (replaced by phase header)
// b. Remove command-specific frontmatter references
// c. Preserve everything else as-is
// Remove original H1 title line(s)
let bodyContent = sourceBody;
bodyContent = bodyContent.replace(/^# .+\n+/, '');
// Remove command-specific overview if it just restates what the phase header says
// But KEEP any overview content that adds execution detail
phaseContent += bodyContent;
// 2.5. Ensure Objective section exists
if (!bodyContent.includes('## Objective')) {
// Insert Objective after phase header, before main content
const objectiveSection = `## Objective\n\n- ${phase.description}\n`;
phaseContent = phaseContent.replace(
`${phase.description}.\n\n${bodyContent}`,
`${phase.description}.\n\n${objectiveSection}\n${bodyContent}`
);
}
// 3. Ensure Output section exists
if (!bodyContent.includes('## Output')) {
phaseContent += '\n## Output\n\n';
if (phase.outputVariables.length > 0) {
phaseContent += phase.outputVariables.map(v => `- **Variable**: \`${v}\``).join('\n') + '\n';
}
if (phase.outputFiles.length > 0) {
phaseContent += phase.outputFiles.map(f => `- **File**: \`${f}\``).join('\n') + '\n';
}
phaseContent += `- **TodoWrite**: Mark Phase ${phase.number} completed, Phase ${phase.number + 1} in_progress\n`;
}
// 4. Ensure Next Phase link exists
if (!bodyContent.includes('## Next Phase')) {
const nextPhase = config.phases.find(p => p.number === phase.number + 1);
if (nextPhase) {
const nextFilename = `${String(nextPhase.number).padStart(2, '0')}-${nextPhase.slug}.md`;
phaseContent += `\n## Next Phase\n\n`;
phaseContent += `Return to orchestrator, then auto-continue to [Phase ${nextPhase.number}: ${nextPhase.name}](${nextFilename}).\n`;
}
}
return phaseContent;
}Content Preservation Checklist
When extracting from commands, verify these content types are preserved:
function verifyContentPreservation(sourceContent, phaseContent) {
const checks = {
// Count code blocks
sourceCodeBlocks: (sourceContent.match(/```/g) || []).length / 2,
phaseCodeBlocks: (phaseContent.match(/```/g) || []).length / 2,
// Count Task/Agent calls
sourceAgentCalls: (sourceContent.match(/Task\(/g) || []).length,
phaseAgentCalls: (phaseContent.match(/Task\(/g) || []).length,
// Count bash commands
sourceBashBlocks: (sourceContent.match(/```bash/g) || []).length,
phaseBashBlocks: (phaseContent.match(/```bash/g) || []).length,
// Count tables
sourceTables: (sourceContent.match(/\|.*\|.*\|/g) || []).length,
phaseTables: (phaseContent.match(/\|.*\|.*\|/g) || []).length,
// Count AskUserQuestion calls
sourceAUQ: (sourceContent.match(/AskUserQuestion/g) || []).length,
phaseAUQ: (phaseContent.match(/AskUserQuestion/g) || []).length,
// Line count comparison (phase should be >= source minus frontmatter)
sourceLines: sourceContent.split('\n').length,
phaseLines: phaseContent.split('\n').length
};
const issues = [];
if (checks.phaseCodeBlocks < checks.sourceCodeBlocks) {
issues.push(`Missing code blocks: source=${checks.sourceCodeBlocks}, phase=${checks.phaseCodeBlocks}`);
}
if (checks.phaseAgentCalls < checks.sourceAgentCalls) {
issues.push(`Missing agent calls: source=${checks.sourceAgentCalls}, phase=${checks.phaseAgentCalls}`);
}
if (checks.phaseBashBlocks < checks.sourceBashBlocks) {
issues.push(`Missing bash blocks: source=${checks.sourceBashBlocks}, phase=${checks.phaseBashBlocks}`);
}
if (checks.phaseTables < checks.sourceTables * 0.8) {
issues.push(`Missing tables: source=${checks.sourceTables}, phase=${checks.phaseTables}`);
}
if (checks.phaseAUQ < checks.sourceAUQ) {
issues.push(`Missing AskUserQuestion: source=${checks.sourceAUQ}, phase=${checks.phaseAUQ}`);
}
return { checks, issues, passed: issues.length === 0 };
}Handling Orchestrator-Level Content in Source Commands
Some commands mix orchestrator-level instructions (coordination, TodoWrite) with execution detail. Separation rules:
| Content in Source Command | Goes To | Rule |
|---|---|---|
| Phase execution steps, agent prompts, bash commands | Phase file | Preserve verbatim |
| TodoWrite update examples specific to this phase | Phase file (optional) | Keep if useful for context |
| Inter-phase data passing code | SKILL.md Post-Phase Updates | Extract to orchestrator |
| Coordinator instructions ("after this phase, auto-continue") | SKILL.md Core Rules | Extract to orchestrator |
| Conditional logic ("if conflict_risk >= medium") | SKILL.md Execution Flow | Extract to orchestrator |
When in doubt, keep content in the phase file. It's better to have slight overlap than to lose execution detail.
Step 3.3: Mode B - Generate from Requirements
When source is a text description, generate phase files interactively:
function generatePhaseFromRequirements(phase, config) {
let phaseContent = '';
// Phase header
phaseContent += `# Phase ${phase.number}: ${phase.name}\n\n`;
phaseContent += `${phase.description}.\n\n`;
// Objective
phaseContent += `## Objective\n\n`;
phaseContent += `- ${phase.description}\n`;
if (phase.outputVariables.length > 0) {
phaseContent += `- Produce: ${phase.outputVariables.join(', ')}\n`;
}
if (phase.outputFiles.length > 0) {
phaseContent += `- Generate: ${phase.outputFiles.join(', ')}\n`;
}
phaseContent += '\n';
// Execution steps
phaseContent += `## Execution\n\n`;
if (phase.usesAgents) {
// Generate agent delegation skeleton
for (const agentType of phase.agentTypes) {
phaseContent += `### Step: ${agentType} Delegation\n\n`;
phaseContent += '```javascript\n';
phaseContent += `const result = Agent({\n`;
phaseContent += ` subagent_type: "${mapAgentType(agentType)}",\n`;
phaseContent += ` prompt: \`\n`;
phaseContent += ` [ROLE] ${agentType}\n`;
phaseContent += ` [TASK] ${phase.description}\n`;
phaseContent += ` [INPUT] \${inputData}\n`;
phaseContent += ` [OUTPUT] \${outputPath}\n`;
phaseContent += ` \`,\n`;
phaseContent += ` run_in_background: false\n`;
phaseContent += `});\n`;
phaseContent += '```\n\n';
}
} else {
// Generate direct execution skeleton
phaseContent += `### Step ${phase.number}.1: Execute\n\n`;
phaseContent += `TODO: Add execution detail for ${phase.name}\n\n`;
}
// Output
phaseContent += `## Output\n\n`;
phase.outputVariables.forEach(v => {
phaseContent += `- **Variable**: \`${v}\`\n`;
});
phase.outputFiles.forEach(f => {
phaseContent += `- **File**: \`${f}\`\n`;
});
phaseContent += `- **TodoWrite**: Mark Phase ${phase.number} completed\n\n`;
// Next Phase
const nextPhase = config.phases.find(p => p.number === phase.number + 1);
if (nextPhase) {
const nextFilename = `${String(nextPhase.number).padStart(2, '0')}-${nextPhase.slug}.md`;
phaseContent += `## Next Phase\n\n`;
phaseContent += `Return to orchestrator, then auto-continue to [Phase ${nextPhase.number}: ${nextPhase.name}](${nextFilename}).\n`;
}
return phaseContent;
}
// Map custom agent type names to Task subagent_types
function mapAgentType(agentType) {
const mapping = {
'cli-explore-agent': 'cli-explore-agent',
'context-search-agent': 'context-search-agent',
'cli-execution-agent': 'cli-execution-agent',
'action-planning-agent': 'action-planning-agent',
'code-developer': 'code-developer',
'test-fix-agent': 'test-fix-agent',
'general-purpose': 'general-purpose',
'Explore': 'Explore'
};
return mapping[agentType] || 'general-purpose';
}Step 3.4: Write Phase Files
function writePhaseFiles(config) {
const skillDir = `.claude/skills/${config.skillName}`;
for (const phase of config.phases) {
const filename = `${String(phase.number).padStart(2, '0')}-${phase.slug}.md`;
const filepath = `${skillDir}/phases/${filename}`;
const strategy = selectGenerationStrategy(phase, config);
let content;
switch (strategy) {
case 'extract':
content = extractPhaseFromCommand(phase, config);
// Verify content preservation
const sourceContent = Read(phase.sourcePath);
const verification = verifyContentPreservation(sourceContent, content);
if (!verification.passed) {
console.warn(`⚠️ Content preservation issues for Phase ${phase.number}:`);
verification.issues.forEach(issue => console.warn(` - ${issue}`));
// Re-extract with more aggressive preservation
content = extractPhaseFromCommand(phase, config, { aggressive: true });
}
break;
case 'generate':
content = generatePhaseFromRequirements(phase, config);
break;
case 'restructure':
content = restructureExistingPhase(phase, config);
break;
}
Write(filepath, content);
console.log(`✓ Generated: ${filepath} (${content.split('\n').length} lines)`);
}
}Step 3.5: Cross-Phase Consistency Check
After generating all phase files, verify cross-phase consistency:
function checkCrossPhaseConsistency(config) {
const skillDir = `.claude/skills/${config.skillName}`;
const issues = [];
for (const phase of config.phases) {
const filename = `${String(phase.number).padStart(2, '0')}-${phase.slug}.md`;
const content = Read(`${skillDir}/phases/${filename}`);
// Check: Next Phase links point to correct file
const nextPhaseMatch = content.match(/\[Phase (\d+): (.+?)\]\((.+?)\)/);
if (nextPhaseMatch) {
const nextNum = parseInt(nextPhaseMatch[1]);
const nextPhase = config.phases.find(p => p.number === nextNum);
if (!nextPhase) {
issues.push(`Phase ${phase.number}: Next Phase link points to non-existent Phase ${nextNum}`);
}
}
// Check: Output variables match config
for (const varName of phase.outputVariables) {
if (!content.includes(varName)) {
issues.push(`Phase ${phase.number}: Output variable '${varName}' not mentioned in content`);
}
}
}
return issues;
}Size Comparison Reference
Expected phase file sizes relative to their source commands:
| Scenario | Phase File Size vs Source | Reason |
|---|---|---|
| Command extraction | ≥ 90% of source | Minor removals (H1 title, frontmatter) |
| New generation (with agents) | 50-200 lines | Agent prompt skeletons |
| New generation (direct) | 30-80 lines | Step skeletons |
| Restructure | ~100% of source | Content reorganization only |
Red Flag: If a phase file is significantly smaller than its source (< 70%), content was likely lost during extraction. Re-check with verifyContentPreservation().
Output
- Files:
.claude/skills/{skillName}/phases/0N-{slug}.mdfor each phase - TodoWrite: Mark Phase 3 completed, Phase 4 in_progress
Next Phase
Return to orchestrator, then auto-continue to Phase 4: Validation & Integration.
Phase 4: Validation & Integration
Validate the generated skill package for structural completeness, reference integrity, and content quality. Produce a validation report and integration summary.
Objective
- Verify all required files exist
- Validate SKILL.md references match actual phase files
- Check content preservation (for command extraction source)
- Verify cross-phase data flow consistency
- Report validation results to user
Step 4.1: Structural Validation
function validateStructure(config) {
const skillDir = `.claude/skills/${config.skillName}`;
const results = { errors: [], warnings: [], info: [] };
// Check SKILL.md exists
const skillMdExists = fileExists(`${skillDir}/SKILL.md`);
if (!skillMdExists) {
results.errors.push('SKILL.md not found');
}
// Check all phase files exist
for (const phase of config.phases) {
const filename = `${String(phase.number).padStart(2, '0')}-${phase.slug}.md`;
const filepath = `${skillDir}/phases/${filename}`;
if (!fileExists(filepath)) {
results.errors.push(`Phase file missing: ${filepath}`);
}
}
// Check SKILL.md frontmatter
if (skillMdExists) {
const skillMd = Read(`${skillDir}/SKILL.md`);
const fm = extractYAMLFrontmatter(skillMd);
if (!fm.name) results.errors.push('Frontmatter missing: name');
if (!fm.description) results.errors.push('Frontmatter missing: description');
if (!fm['allowed-tools']) results.errors.push('Frontmatter missing: allowed-tools');
// Check description has trigger phrase
if (fm.description && !fm.description.includes('Triggers on')) {
results.warnings.push('Description missing trigger phrase (Triggers on "...")');
}
}
return results;
}Step 4.2: Reference Integrity
function validateReferences(config) {
const skillDir = `.claude/skills/${config.skillName}`;
const results = { errors: [], warnings: [], info: [] };
const skillMd = Read(`${skillDir}/SKILL.md`);
// Extract all Ref: markers from SKILL.md
const refMarkers = skillMd.match(/Ref: phases\/\S+\.md/g) || [];
const linkedFiles = skillMd.match(/\[phases\/\S+\.md\]\(phases\/\S+\.md\)/g) || [];
// Collect all referenced phase files
const referencedFiles = new Set();
for (const ref of refMarkers) {
referencedFiles.add(ref.replace('Ref: ', ''));
}
for (const link of linkedFiles) {
const match = link.match(/\(phases\/\S+\.md\)/);
if (match) referencedFiles.add(match[0].replace(/[()]/g, ''));
}
// Check each referenced file exists
for (const refFile of referencedFiles) {
if (!fileExists(`${skillDir}/${refFile}`)) {
results.errors.push(`Referenced file not found: ${refFile}`);
}
}
// Check each phase file is referenced in SKILL.md
for (const phase of config.phases) {
const filename = `phases/${String(phase.number).padStart(2, '0')}-${phase.slug}.md`;
if (!referencedFiles.has(filename)) {
results.warnings.push(`Phase file not referenced in SKILL.md: ${filename}`);
}
}
// Check Phase Reference Documents table exists
if (!skillMd.includes('Phase Reference Documents')) {
results.errors.push('SKILL.md missing Phase Reference Documents table');
}
// Check Phase Reference Documents table has entries for all phases
for (const phase of config.phases) {
const filename = `${String(phase.number).padStart(2, '0')}-${phase.slug}.md`;
if (!skillMd.includes(filename)) {
results.errors.push(`Phase Reference table missing entry for: ${filename}`);
}
}
return results;
}Step 4.3: Content Quality (Command Extraction Only)
function validateContentQuality(config) {
const skillDir = `.claude/skills/${config.skillName}`;
const results = { errors: [], warnings: [], info: [] };
if (config.source.type !== 'command_set') {
results.info.push('Content quality check skipped (not command extraction)');
return results;
}
for (const phase of config.phases) {
if (!phase.sourcePath) continue;
const sourceContent = Read(phase.sourcePath);
const sourceBody = removeYAMLFrontmatter(sourceContent);
const filename = `${String(phase.number).padStart(2, '0')}-${phase.slug}.md`;
const phaseContent = Read(`${skillDir}/phases/${filename}`);
// Line count comparison
const sourceLines = sourceBody.split('\n').length;
const phaseLines = phaseContent.split('\n').length;
const ratio = phaseLines / sourceLines;
if (ratio < 0.7) {
results.errors.push(
`Phase ${phase.number} content loss: source=${sourceLines} lines, phase=${phaseLines} lines (${Math.round(ratio * 100)}%)`
);
} else if (ratio < 0.9) {
results.warnings.push(
`Phase ${phase.number} possible content reduction: source=${sourceLines}, phase=${phaseLines} (${Math.round(ratio * 100)}%)`
);
} else {
results.info.push(
`Phase ${phase.number} content preserved: source=${sourceLines}, phase=${phaseLines} (${Math.round(ratio * 100)}%)`
);
}
// Code block count comparison
const sourceBlocks = (sourceBody.match(/```/g) || []).length / 2;
const phaseBlocks = (phaseContent.match(/```/g) || []).length / 2;
if (phaseBlocks < sourceBlocks) {
results.warnings.push(
`Phase ${phase.number} missing code blocks: source=${sourceBlocks}, phase=${phaseBlocks}`
);
}
// Agent prompt preservation
const sourceAgents = (sourceBody.match(/Task\(|subagent_type/g) || []).length;
const phaseAgents = (phaseContent.match(/Task\(|subagent_type/g) || []).length;
if (phaseAgents < sourceAgents) {
results.errors.push(
`Phase ${phase.number} missing agent calls: source=${sourceAgents}, phase=${phaseAgents}`
);
}
}
return results;
}Step 4.4: Data Flow Consistency
function validateDataFlow(config) {
const skillDir = `.claude/skills/${config.skillName}`;
const results = { errors: [], warnings: [], info: [] };
const skillMd = Read(`${skillDir}/SKILL.md`);
// Check all data flow variables are mentioned in SKILL.md
for (const flow of config.dataFlow) {
for (const variable of flow.variables) {
if (!skillMd.includes(variable)) {
results.warnings.push(
`Data flow variable '${variable}' (${flow.from} → ${flow.to}) not found in SKILL.md`
);
}
}
}
// Check conditional phases have their condition in SKILL.md
for (const phase of config.phases) {
if (phase.isConditional && phase.condition) {
// Extract the key variable from condition
const condVar = phase.condition.match(/\w+/)?.[0];
if (condVar && !skillMd.includes(condVar)) {
results.errors.push(
`Conditional Phase ${phase.number} condition variable '${condVar}' not found in SKILL.md`
);
}
}
}
return results;
}Step 4.5: SKILL.md Section Completeness
function validateSkillMdSections(config) {
const skillDir = `.claude/skills/${config.skillName}`;
const results = { errors: [], warnings: [], info: [] };
const skillMd = Read(`${skillDir}/SKILL.md`);
// Required sections
const requiredSections = [
{ name: 'Architecture Overview', pattern: /## Architecture Overview/ },
{ name: 'Execution Flow', pattern: /## Execution Flow/ },
{ name: 'Core Rules', pattern: /## Core Rules/ },
{ name: 'Data Flow', pattern: /## Data Flow/ },
{ name: 'Error Handling', pattern: /## Error Handling/ }
];
// Recommended sections
const recommendedSections = [
{ name: 'Key Design Principles', pattern: /## Key Design Principles/ },
{ name: 'Input Processing', pattern: /## Input Processing/ },
{ name: 'TodoWrite Pattern', pattern: /## TodoWrite Pattern/ },
{ name: 'Coordinator Checklist', pattern: /## Coordinator Checklist/ },
{ name: 'Related Commands', pattern: /## Related Commands/ }
];
// Conditional sections
const conditionalSections = [
{ name: 'Interactive Preference Collection', pattern: /## Interactive Preference Collection/, condition: config.features.hasAutoMode },
{ name: 'Auto Mode Defaults', pattern: /## Auto Mode Defaults/, condition: config.features.hasAutoMode },
{ name: 'Post-Phase Updates', pattern: /## Post-Phase Updates/, condition: config.features.hasPostPhaseUpdates }
];
for (const section of requiredSections) {
if (!section.pattern.test(skillMd)) {
results.errors.push(`Missing required section: ${section.name}`);
}
}
for (const section of recommendedSections) {
if (!section.pattern.test(skillMd)) {
results.warnings.push(`Missing recommended section: ${section.name}`);
}
}
for (const section of conditionalSections) {
if (section.condition && !section.pattern.test(skillMd)) {
results.warnings.push(`Missing conditional section: ${section.name} (feature enabled but section absent)`);
}
}
return results;
}Step 4.6: Phase File Hygiene
Scan generated phase files for prohibited content patterns. Phase files are internal execution documents and must not contain user-facing syntax, flag parsing, or inter-phase routing.
function validatePhaseFileHygiene(config) {
const skillDir = `.claude/skills/${config.skillName}`;
const results = { errors: [], warnings: [], info: [] };
const prohibitedPatterns = [
{
name: 'Flag parsing ($ARGUMENTS)',
regex: /\$ARGUMENTS\.includes/g,
severity: 'error',
fix: 'Replace with workflowPreferences.{key} reference'
},
{
name: 'Invocation syntax (/skill-name)',
regex: /\/\w+[\-:]\w+\s+["']/g,
severity: 'warning',
fix: 'Remove (phase files are not user-facing docs)'
},
{
name: 'Conversion provenance (Source: Converted from)',
regex: /Source:.*Converted from/g,
severity: 'warning',
fix: 'Remove (implementation detail)'
},
{
name: 'Skill routing for inter-phase (Skill(skill=...)',
regex: /Skill\(skill=/g,
severity: 'error',
fix: 'Replace with direct Read("phases/0N-xxx.md")'
},
{
name: 'CLI flag definitions (--flag)',
regex: /^\s*-\w,\s+--\w+\s+/gm,
severity: 'warning',
fix: 'Move flag definitions to SKILL.md Interactive Preference Collection'
}
];
for (const phase of config.phases) {
const filename = `${String(phase.number).padStart(2, '0')}-${phase.slug}.md`;
const filepath = `${skillDir}/phases/${filename}`;
if (!fileExists(filepath)) continue;
const content = Read(filepath);
for (const pattern of prohibitedPatterns) {
const matches = content.match(pattern.regex);
if (matches && matches.length > 0) {
const msg = `Phase ${phase.number} (${filename}): ${pattern.name} found (${matches.length} occurrence(s)). Fix: ${pattern.fix}`;
if (pattern.severity === 'error') {
results.errors.push(msg);
} else {
results.warnings.push(msg);
}
}
}
}
if (results.errors.length === 0 && results.warnings.length === 0) {
results.info.push('Phase file hygiene: All phase files clean ✓');
}
return results;
}Step 4.7: Aggregate Results and Report
function generateValidationReport(config) {
const structural = validateStructure(config);
const references = validateReferences(config);
const content = validateContentQuality(config);
const dataFlow = validateDataFlow(config);
const sections = validateSkillMdSections(config);
const hygiene = validatePhaseFileHygiene(config);
// Aggregate
const allErrors = [
...structural.errors,
...references.errors,
...content.errors,
...dataFlow.errors,
...sections.errors,
...hygiene.errors
];
const allWarnings = [
...structural.warnings,
...references.warnings,
...content.warnings,
...dataFlow.warnings,
...sections.warnings,
...hygiene.warnings
];
const allInfo = [
...structural.info,
...references.info,
...content.info,
...dataFlow.info,
...sections.info,
...hygiene.info
];
// Quality gate
const gate = allErrors.length === 0 ? 'PASS' :
allErrors.length <= 2 ? 'REVIEW' : 'FAIL';
// Display report
const skillDir = `.claude/skills/${config.skillName}`;
console.log(`
╔══════════════════════════════════════╗
║ Workflow Skill Validation Report ║
╠══════════════════════════════════════╣
║ Skill: ${config.skillName.padEnd(28)}║
║ Gate: ${gate.padEnd(28)}║
╚══════════════════════════════════════╝
Structure:
${skillDir}/
├── SKILL.md ${fileExists(`${skillDir}/SKILL.md`) ? '✓' : '✗'}
└── phases/
${config.phases.map(p => {
const fn = `${String(p.number).padStart(2, '0')}-${p.slug}.md`;
return ` ├── ${fn.padEnd(30)} ${fileExists(`${skillDir}/phases/${fn}`) ? '✓' : '✗'}`;
}).join('\n')}
${allErrors.length > 0 ? `Errors (${allErrors.length}):\n${allErrors.map(e => ` ✗ ${e}`).join('\n')}` : 'Errors: None ✓'}
${allWarnings.length > 0 ? `Warnings (${allWarnings.length}):\n${allWarnings.map(w => ` ⚠ ${w}`).join('\n')}` : 'Warnings: None ✓'}
${allInfo.length > 0 ? `Info:\n${allInfo.map(i => ` ℹ ${i}`).join('\n')}` : ''}
`);
return { gate, errors: allErrors, warnings: allWarnings, info: allInfo };
}Step 4.8: Error Recovery
If validation fails, offer recovery options:
if (report.gate === 'FAIL') {
const recovery = AskUserQuestion({
questions: [{
question: `Validation found ${report.errors.length} errors. How to proceed?`,
header: "Recovery",
multiSelect: false,
options: [
{ label: "Auto-fix", description: "Attempt automatic fixes for common issues" },
{ label: "Regenerate phases", description: "Re-run Phase 3 with stricter preservation" },
{ label: "Accept as-is", description: "Proceed despite errors (manual fix later)" }
]
}]
});
if (recovery === 'Auto-fix') {
// Common auto-fixes:
// 1. Missing Next Phase links → add them
// 2. Missing Output sections → add from config
// 3. Missing Phase Reference table → generate from config
autoFixCommonIssues(config, report.errors);
// Re-validate
return generateValidationReport(config);
}
}Step 4.9: Integration Summary
function displayIntegrationSummary(config) {
console.log(`
Integration Complete:
Location: .claude/skills/${config.skillName}/
Files: ${config.phases.length + 1} (SKILL.md + ${config.phases.length} phases)
Usage:
Trigger: ${config.triggers.map(t => `"${t}"`).join(', ')}
Design Patterns Applied:
✓ Progressive phase loading (Ref: markers)
✓ Phase Reference Documents table
✓ Phase file hygiene (no flag parsing, no invocation syntax)
${config.features.hasTodoWriteSubTasks ? '✓' : '○'} TodoWrite attachment/collapse
${config.features.hasConditionalPhases ? '✓' : '○'} Conditional phase execution
${config.features.hasAutoMode ? '✓' : '○'} Interactive preference collection (AskUserQuestion)
${config.features.hasPostPhaseUpdates ? '✓' : '○'} Post-phase state updates
${config.features.hasPlanningNotes ? '✓' : '○'} Accumulated planning notes
Next Steps:
1. Review SKILL.md orchestrator logic
2. Review each phase file for completeness
3. Test skill invocation with trigger phrase
4. Iterate based on execution results
`);
}Output
- Report: Validation results with quality gate (PASS/REVIEW/FAIL)
- TodoWrite: Mark Phase 4 completed (all tasks done)
Completion
Workflow Skill Designer has completed. The generated skill package is ready at .claude/skills/{skillName}/.