# 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}.md` for 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. ## Step 3.1: Phase File Generation Strategy ```javascript 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: ```javascript 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; // 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: ```javascript 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: ```javascript 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 = Task({\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 ```javascript 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: ```javascript 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}.md` for each phase - **TodoWrite**: Mark Phase 3 completed, Phase 4 in_progress ## Next Phase Return to orchestrator, then auto-continue to [Phase 4: Validation & Integration](04-validation.md).