diff --git a/.claude/skills/workflow-lite-plan/SKILL.md b/.claude/skills/workflow-lite-plan/SKILL.md new file mode 100644 index 00000000..f3484d18 --- /dev/null +++ b/.claude/skills/workflow-lite-plan/SKILL.md @@ -0,0 +1,112 @@ +--- +name: workflow-lite-plan +description: Lightweight planning and execution skill - route to lite-plan or lite-execute with prompt enhancement. Triggers on "workflow:lite-plan", "workflow:lite-execute". +allowed-tools: Skill, Task, AskUserQuestion, TodoWrite, Read, Write, Edit, Bash, Glob, Grep +--- + +# Workflow Lite-Plan + +Unified lightweight planning and execution skill. Routes to lite-plan (planning pipeline) or lite-execute (execution engine) based on trigger, with prompt enhancement for both modes. + +## Architecture Overview + +``` +┌─────────────────────────────────────────────────────┐ +│ SKILL.md (Router + Prompt Enhancement) │ +│ → Detect mode → Enhance prompt → Dispatch to phase │ +└──────────────────────┬──────────────────────────────┘ + │ + ┌───────────┼───────────┐ + ↓ ↓ + ┌───────────┐ ┌───────────┐ + │ lite-plan │ │lite-execute│ + │ Phase 1 │ │ Phase 2 │ + │ Plan+Exec │──handoff─→│ Standalone │ + └───────────┘ └───────────┘ +``` + +## Mode Detection & Routing + +```javascript +const args = $ARGUMENTS +const mode = detectMode() + +function detectMode() { + if (skillName === 'workflow:lite-execute') return 'execute' + return 'plan' // default: workflow:lite-plan +} +``` + +**Routing Table**: + +| Trigger | Mode | Phase Document | Description | +|---------|------|----------------|-------------| +| `workflow:lite-plan` | plan | [phases/01-lite-plan.md](phases/01-lite-plan.md) | Full planning pipeline (explore → plan → confirm → execute) | +| `workflow:lite-execute` | execute | [phases/02-lite-execute.md](phases/02-lite-execute.md) | Standalone execution (in-memory / prompt / file) | + +## Prompt Enhancement + +Before dispatching to the target phase, enhance context: + +```javascript +// Step 1: Check for project context files +const hasProjectTech = fileExists('.workflow/project-tech.json') +const hasProjectGuidelines = fileExists('.workflow/project-guidelines.json') + +// Step 2: Log available context +if (hasProjectTech) { + console.log('Project tech context available: .workflow/project-tech.json') +} +if (hasProjectGuidelines) { + console.log('Project guidelines available: .workflow/project-guidelines.json') +} + +// Step 3: Dispatch to phase +if (mode === 'plan') { + // Read phases/01-lite-plan.md and execute +} else { + // Read phases/02-lite-execute.md and execute +} +``` + +## Execution Flow + +### Plan Mode (workflow:lite-plan) + +``` +1. Parse flags (-y/--yes, -e/--explore) and task description +2. Enhance prompt with project context availability +3. Read phases/01-lite-plan.md +4. Execute lite-plan pipeline (Phase 1-5 within the phase doc) +5. lite-plan Phase 5 internally calls workflow:lite-execute via Skill handoff +``` + +### Execute Mode (workflow:lite-execute) + +``` +1. Parse flags (--in-memory, -y/--yes) and input +2. Enhance prompt with project context availability +3. Read phases/02-lite-execute.md +4. Execute lite-execute pipeline (input detection → execution → review) +``` + +## Usage + +```bash +# Plan mode +/workflow:lite-plan "实现JWT认证" # Interactive +/workflow:lite-plan --yes "实现JWT认证" # Auto mode +/workflow:lite-plan -y -e "优化数据库查询性能" # Auto + force exploration + +# Execute mode (standalone) +/workflow:lite-execute "Add unit tests for auth" # Prompt description +/workflow:lite-execute plan.json # File input +/workflow:lite-execute --in-memory # Called by lite-plan internally +``` + +## Phase Reference Documents + +| Phase | Document | Purpose | +|-------|----------|---------| +| 1 | [phases/01-lite-plan.md](phases/01-lite-plan.md) | Complete planning pipeline: exploration, clarification, planning, confirmation, handoff | +| 2 | [phases/02-lite-execute.md](phases/02-lite-execute.md) | Complete execution engine: input modes, task grouping, batch execution, code review | diff --git a/.claude/skills/workflow-lite-plan/phases/01-lite-plan.md b/.claude/skills/workflow-lite-plan/phases/01-lite-plan.md new file mode 100644 index 00000000..8b90c901 --- /dev/null +++ b/.claude/skills/workflow-lite-plan/phases/01-lite-plan.md @@ -0,0 +1,773 @@ +# Phase 1: Lite-Plan + +Complete planning pipeline: task analysis, multi-angle exploration, clarification, adaptive planning, confirmation, and execution handoff. + +**Source**: Converted from `.claude/commands/workflow/lite-plan.md` - all execution detail preserved verbatim. + +--- + +## Overview + +Intelligent lightweight planning command with dynamic workflow adaptation based on task complexity. Focuses on planning phases (exploration, clarification, planning, confirmation) and delegates execution to Phase 2 (lite-execute). + +**Core capabilities:** +- Intelligent task analysis with automatic exploration detection +- Dynamic code exploration (cli-explore-agent) when codebase understanding needed +- Interactive clarification after exploration to gather missing information +- Adaptive planning: Low complexity → Direct Claude; Medium/High → cli-lite-planning-agent +- Two-step confirmation: plan display → multi-dimensional input collection +- Execution handoff with complete context to lite-execute + +## Usage + +```bash +/workflow:lite-plan [FLAGS] + +# Flags +-y, --yes Skip all confirmations (auto mode) +-e, --explore Force code exploration phase (overrides auto-detection) + +# Arguments + Task description or path to .md file (required) + +# Examples +/workflow:lite-plan "实现JWT认证" # Interactive mode +/workflow:lite-plan --yes "实现JWT认证" # Auto mode (no confirmations) +/workflow:lite-plan -y -e "优化数据库查询性能" # Auto mode + force exploration +``` + +## Output Artifacts + +| Artifact | Description | +|----------|-------------| +| `exploration-{angle}.json` | Per-angle exploration results (1-4 files based on complexity) | +| `explorations-manifest.json` | Index of all exploration files | +| `planning-context.md` | Evidence paths + synthesized understanding | +| `plan.json` | Plan overview with task_ids[] (plan-overview-base-schema.json) | +| `.task/TASK-*.json` | Independent task files (one per task) | + +**Output Directory**: `.workflow/.lite-plan/{task-slug}-{YYYY-MM-DD}/` + +**Agent Usage**: +- Low complexity → Direct Claude planning (no agent) +- Medium/High complexity → `cli-lite-planning-agent` generates `plan.json` + +**Schema Reference**: `~/.ccw/workflows/cli-templates/schemas/plan-overview-base-schema.json` + +## Auto Mode Defaults + +When `--yes` or `-y` flag is used: +- **Clarification Questions**: Skipped (no clarification phase) +- **Plan Confirmation**: Auto-selected "Allow" +- **Execution Method**: Auto-selected "Auto" +- **Code Review**: Auto-selected "Skip" + +**Flag Parsing**: +```javascript +const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') +const forceExplore = $ARGUMENTS.includes('--explore') || $ARGUMENTS.includes('-e') +``` + +## Execution Process + +``` +Phase 1: Task Analysis & Exploration + ├─ Parse input (description or .md file) + ├─ intelligent complexity assessment (Low/Medium/High) + ├─ Exploration decision (auto-detect or --explore flag) + ├─ Context protection: If file reading ≥50k chars → force cli-explore-agent + └─ Decision: + ├─ needsExploration=true → Launch parallel cli-explore-agents (1-4 based on complexity) + └─ needsExploration=false → Skip to Phase 2/3 + +Phase 2: Clarification (optional, multi-round) + ├─ Aggregate clarification_needs from all exploration angles + ├─ Deduplicate similar questions + └─ Decision: + ├─ Has clarifications → AskUserQuestion (max 4 questions per round, multiple rounds allowed) + └─ No clarifications → Skip to Phase 3 + +Phase 3: Planning (NO CODE EXECUTION - planning only) + └─ Decision (based on Phase 1 complexity): + ├─ Low → Load schema: cat ~/.ccw/workflows/cli-templates/schemas/plan-overview-base-schema.json → Direct Claude planning (following schema) → plan.json + └─ Medium/High → cli-lite-planning-agent → plan.json (agent internally executes quality check) + +Phase 4: Confirmation & Selection + ├─ Display plan summary (tasks, complexity, estimated time) + └─ AskUserQuestion: + ├─ Confirm: Allow / Modify / Cancel + ├─ Execution: Agent / Codex / Auto + └─ Review: Gemini / Agent / Skip + +Phase 5: Execute + ├─ Build executionContext (plan + explorations + clarifications + selections) + └─ Skill(skill="workflow:lite-execute", args="--in-memory") +``` + +## Implementation + +### Phase 1: Intelligent Multi-Angle Exploration + +**Session Setup** (MANDATORY - follow exactly): +```javascript +// Helper: Get UTC+8 (China Standard Time) ISO string +const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString() + +const taskSlug = task_description.toLowerCase().replace(/[^a-z0-9]+/g, '-').substring(0, 40) +const dateStr = getUtc8ISOString().substring(0, 10) // Format: 2025-11-29 + +const sessionId = `${taskSlug}-${dateStr}` // e.g., "implement-jwt-refresh-2025-11-29" +const sessionFolder = `.workflow/.lite-plan/${sessionId}` + +bash(`mkdir -p ${sessionFolder} && test -d ${sessionFolder} && echo "SUCCESS: ${sessionFolder}" || echo "FAILED: ${sessionFolder}"`) +``` + +**Exploration Decision Logic**: +```javascript +needsExploration = ( + flags.includes('--explore') || flags.includes('-e') || + task.mentions_specific_files || + task.requires_codebase_context || + task.needs_architecture_understanding || + task.modifies_existing_code +) + +if (!needsExploration) { + // Skip to Phase 2 (Clarification) or Phase 3 (Planning) + proceed_to_next_phase() +} +``` + +**⚠️ Context Protection**: File reading ≥50k chars → force `needsExploration=true` (delegate to cli-explore-agent) + +**Complexity Assessment** (Intelligent Analysis): +```javascript +// analyzes task complexity based on: +// - Scope: How many systems/modules are affected? +// - Depth: Surface change vs architectural impact? +// - Risk: Potential for breaking existing functionality? +// - Dependencies: How interconnected is the change? + +const complexity = analyzeTaskComplexity(task_description) +// Returns: 'Low' | 'Medium' | 'High' +// Low: Single file, isolated change, minimal risk +// Medium: Multiple files, some dependencies, moderate risk +// High: Cross-module, architectural, high risk + +// Angle assignment based on task type (orchestrator decides, not agent) +const ANGLE_PRESETS = { + architecture: ['architecture', 'dependencies', 'modularity', 'integration-points'], + security: ['security', 'auth-patterns', 'dataflow', 'validation'], + performance: ['performance', 'bottlenecks', 'caching', 'data-access'], + bugfix: ['error-handling', 'dataflow', 'state-management', 'edge-cases'], + feature: ['patterns', 'integration-points', 'testing', 'dependencies'] +} + +function selectAngles(taskDescription, count) { + const text = taskDescription.toLowerCase() + let preset = 'feature' // default + + if (/refactor|architect|restructure|modular/.test(text)) preset = 'architecture' + else if (/security|auth|permission|access/.test(text)) preset = 'security' + else if (/performance|slow|optimi|cache/.test(text)) preset = 'performance' + else if (/fix|bug|error|issue|broken/.test(text)) preset = 'bugfix' + + return ANGLE_PRESETS[preset].slice(0, count) +} + +const selectedAngles = selectAngles(task_description, complexity === 'High' ? 4 : (complexity === 'Medium' ? 3 : 1)) + +// Planning strategy determination +const planningStrategy = complexity === 'Low' + ? 'Direct Claude Planning' + : 'cli-lite-planning-agent' + +console.log(` +## Exploration Plan + +Task Complexity: ${complexity} +Selected Angles: ${selectedAngles.join(', ')} +Planning Strategy: ${planningStrategy} + +Launching ${selectedAngles.length} parallel explorations... +`) +``` + +**Launch Parallel Explorations** - Orchestrator assigns angle to each agent: + +**⚠️ CRITICAL - NO BACKGROUND EXECUTION**: +- **MUST NOT use `run_in_background: true`** - exploration results are REQUIRED before planning + + +```javascript +// Launch agents with pre-assigned angles +const explorationTasks = selectedAngles.map((angle, index) => + Task( + subagent_type="cli-explore-agent", + run_in_background=false, // ⚠️ MANDATORY: Must wait for results + description=`Explore: ${angle}`, + prompt=` +## Task Objective +Execute **${angle}** exploration for task planning context. Analyze codebase from this specific angle to discover relevant structure, patterns, and constraints. + +## Output Location + +**Session Folder**: ${sessionFolder} +**Output File**: ${sessionFolder}/exploration-${angle}.json + +## Assigned Context +- **Exploration Angle**: ${angle} +- **Task Description**: ${task_description} +- **Exploration Index**: ${index + 1} of ${selectedAngles.length} + +## MANDATORY FIRST STEPS (Execute by Agent) +**You (cli-explore-agent) MUST execute these steps in order:** +1. Run: ccw tool exec get_modules_by_depth '{}' (project structure) +2. Run: rg -l "{keyword_from_task}" --type ts (locate relevant files) +3. Execute: cat ~/.ccw/workflows/cli-templates/schemas/explore-json-schema.json (get output schema reference) +4. Read: .workflow/project-tech.json (technology stack and architecture context) +5. Read: .workflow/project-guidelines.json (user-defined constraints and conventions) + +## Exploration Strategy (${angle} focus) + +**Step 1: Structural Scan** (Bash) +- get_modules_by_depth.sh → identify modules related to ${angle} +- find/rg → locate files relevant to ${angle} aspect +- Analyze imports/dependencies from ${angle} perspective + +**Step 2: Semantic Analysis** (Gemini CLI) +- How does existing code handle ${angle} concerns? +- What patterns are used for ${angle}? +- Where would new code integrate from ${angle} viewpoint? + +**Step 3: Write Output** +- Consolidate ${angle} findings into JSON +- Identify ${angle}-specific clarification needs + +## Expected Output + +**Schema Reference**: Schema obtained in MANDATORY FIRST STEPS step 3, follow schema exactly + +**Required Fields** (all ${angle} focused): +- project_structure: Modules/architecture relevant to ${angle} +- relevant_files: Files affected from ${angle} perspective + **MANDATORY**: Every file MUST use structured object format with ALL required fields: + \`[{path: "src/file.ts", relevance: 0.85, rationale: "Contains AuthService.login() - entry point for JWT token generation", role: "modify_target", discovery_source: "bash-scan", key_symbols: ["AuthService", "login"]}]\` + - **rationale** (required): Specific selection basis tied to ${angle} topic (>10 chars, not generic) + - **role** (required): modify_target|dependency|pattern_reference|test_target|type_definition|integration_point|config|context_only + - **discovery_source** (recommended): bash-scan|cli-analysis|ace-search|dependency-trace|manual + - **key_symbols** (recommended): Key functions/classes/types in the file relevant to the task + - Scores: 0.7+ high priority, 0.5-0.7 medium, <0.5 low +- patterns: ${angle}-related patterns to follow +- dependencies: Dependencies relevant to ${angle} +- integration_points: Where to integrate from ${angle} viewpoint (include file:line locations) +- constraints: ${angle}-specific limitations/conventions +- clarification_needs: ${angle}-related ambiguities (options array + recommended index) +- _metadata.exploration_angle: "${angle}" + +## Success Criteria +- [ ] Schema obtained via cat explore-json-schema.json +- [ ] get_modules_by_depth.sh executed +- [ ] At least 3 relevant files identified with specific rationale + role +- [ ] Every file has rationale >10 chars (not generic like "Related to ${angle}") +- [ ] Every file has role classification (modify_target/dependency/etc.) +- [ ] Patterns are actionable (code examples, not generic advice) +- [ ] Integration points include file:line locations +- [ ] Constraints are project-specific to ${angle} +- [ ] JSON output follows schema exactly +- [ ] clarification_needs includes options + recommended + +## Execution +**Write**: \`${sessionFolder}/exploration-${angle}.json\` +**Return**: 2-3 sentence summary of ${angle} findings +` + ) +) + +// Execute all exploration tasks in parallel +``` + +**Auto-discover Generated Exploration Files**: +```javascript +// After explorations complete, auto-discover all exploration-*.json files +const explorationFiles = bash(`find ${sessionFolder} -name "exploration-*.json" -type f`) + .split('\n') + .filter(f => f.trim()) + +// Read metadata to build manifest +const explorationManifest = { + session_id: sessionId, + task_description: task_description, + timestamp: getUtc8ISOString(), + complexity: complexity, + exploration_count: explorationCount, + explorations: explorationFiles.map(file => { + const data = JSON.parse(Read(file)) + const filename = path.basename(file) + return { + angle: data._metadata.exploration_angle, + file: filename, + path: file, + index: data._metadata.exploration_index + } + }) +} + +Write(`${sessionFolder}/explorations-manifest.json`, JSON.stringify(explorationManifest, null, 2)) + +console.log(` +## Exploration Complete + +Generated exploration files in ${sessionFolder}: +${explorationManifest.explorations.map(e => `- exploration-${e.angle}.json (angle: ${e.angle})`).join('\n')} + +Manifest: explorations-manifest.json +Angles explored: ${explorationManifest.explorations.map(e => e.angle).join(', ')} +`) +``` + +**Output**: +- `${sessionFolder}/exploration-{angle1}.json` +- `${sessionFolder}/exploration-{angle2}.json` +- ... (1-4 files based on complexity) +- `${sessionFolder}/explorations-manifest.json` + +--- + +### Phase 2: Clarification (Optional, Multi-Round) + +**Skip if**: No exploration or `clarification_needs` is empty across all explorations + +**⚠️ CRITICAL**: AskUserQuestion tool limits max 4 questions per call. **MUST execute multiple rounds** to exhaust all clarification needs - do NOT stop at round 1. + +**Aggregate clarification needs from all exploration angles**: +```javascript +// Load manifest and all exploration files +const manifest = JSON.parse(Read(`${sessionFolder}/explorations-manifest.json`)) +const explorations = manifest.explorations.map(exp => ({ + angle: exp.angle, + data: JSON.parse(Read(exp.path)) +})) + +// Aggregate clarification needs from all explorations +const allClarifications = [] +explorations.forEach(exp => { + if (exp.data.clarification_needs?.length > 0) { + exp.data.clarification_needs.forEach(need => { + allClarifications.push({ + ...need, + source_angle: exp.angle + }) + }) + } +}) + +// Intelligent deduplication: analyze allClarifications by intent +// - Identify questions with similar intent across different angles +// - Merge similar questions: combine options, consolidate context +// - Produce dedupedClarifications with unique intents only +const dedupedClarifications = intelligentMerge(allClarifications) + +// Parse --yes flag +const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') + +if (autoYes) { + // Auto mode: Skip clarification phase + console.log(`[--yes] Skipping ${dedupedClarifications.length} clarification questions`) + console.log(`Proceeding to planning with exploration results...`) + // Continue to Phase 3 +} else if (dedupedClarifications.length > 0) { + // Interactive mode: Multi-round clarification + const BATCH_SIZE = 4 + const totalRounds = Math.ceil(dedupedClarifications.length / BATCH_SIZE) + + for (let i = 0; i < dedupedClarifications.length; i += BATCH_SIZE) { + const batch = dedupedClarifications.slice(i, i + BATCH_SIZE) + const currentRound = Math.floor(i / BATCH_SIZE) + 1 + + console.log(`### Clarification Round ${currentRound}/${totalRounds}`) + + AskUserQuestion({ + questions: batch.map(need => ({ + question: `[${need.source_angle}] ${need.question}\n\nContext: ${need.context}`, + header: need.source_angle.substring(0, 12), + multiSelect: false, + options: need.options.map((opt, index) => ({ + label: need.recommended === index ? `${opt} ★` : opt, + description: need.recommended === index ? `Recommended` : `Use ${opt}` + })) + })) + }) + + // Store batch responses in clarificationContext before next round + } +} +``` + +**Output**: `clarificationContext` (in-memory) + +--- + +### Phase 3: Planning + +**Planning Strategy Selection** (based on Phase 1 complexity): + +**IMPORTANT**: Phase 3 is **planning only** - NO code execution. All execution happens in Phase 5 via lite-execute. + +**Executor Assignment** (Claude 智能分配,plan 生成后执行): + +```javascript +// 分配规则(优先级从高到低): +// 1. 用户明确指定:"用 gemini 分析..." → gemini, "codex 实现..." → codex +// 2. 默认 → agent + +const executorAssignments = {} // { taskId: { executor: 'gemini'|'codex'|'agent', reason: string } } + +// Load tasks from .task/ directory for executor assignment +const taskFiles = Glob(`${sessionFolder}/.task/TASK-*.json`) +taskFiles.forEach(taskPath => { + const task = JSON.parse(Read(taskPath)) + // Claude 根据上述规则语义分析,为每个 task 分配 executor + executorAssignments[task.id] = { executor: '...', reason: '...' } +}) +``` + +**Low Complexity** - Direct planning by Claude: +```javascript +// Step 1: Read schema +const schema = Bash(`cat ~/.ccw/workflows/cli-templates/schemas/plan-overview-base-schema.json`) + +// Step 2: ⚠️ MANDATORY - Read and review ALL exploration files +const manifest = JSON.parse(Read(`${sessionFolder}/explorations-manifest.json`)) +manifest.explorations.forEach(exp => { + const explorationData = Read(exp.path) + console.log(`\n### Exploration: ${exp.angle}\n${explorationData}`) +}) + +// Step 3: Generate task objects (Claude directly, no agent) +// ⚠️ Tasks MUST incorporate insights from exploration files read in Step 2 +// Task fields use NEW names: convergence.criteria (not acceptance), files[].change (not modification_points), test (not verification) +const tasks = [ + { + id: "TASK-001", + title: "...", + description: "...", + depends_on: [], + convergence: { criteria: ["..."] }, + files: [{ path: "...", change: "..." }], + implementation: ["..."], + test: "..." + }, + // ... more tasks +] + +// Step 4: Write task files to .task/ directory +const taskDir = `${sessionFolder}/.task` +Bash(`mkdir -p "${taskDir}"`) +tasks.forEach(task => { + Write(`${taskDir}/${task.id}.json`, JSON.stringify(task, null, 2)) +}) + +// Step 5: Generate plan overview (NO embedded tasks[]) +const plan = { + summary: "...", + approach: "...", + task_ids: tasks.map(t => t.id), + task_count: tasks.length, + complexity: "Low", + estimated_time: "...", + recommended_execution: "Agent", + _metadata: { + timestamp: getUtc8ISOString(), + source: "direct-planning", + planning_mode: "direct", + plan_type: "feature" + } +} + +// Step 6: Write plan overview to session folder +Write(`${sessionFolder}/plan.json`, JSON.stringify(plan, null, 2)) + +// Step 7: MUST continue to Phase 4 (Confirmation) - DO NOT execute code here +``` + +**Medium/High Complexity** - Invoke cli-lite-planning-agent: + +```javascript +Task( + subagent_type="cli-lite-planning-agent", + run_in_background=false, + description="Generate detailed implementation plan", + prompt=` +Generate implementation plan and write plan.json. + +## Output Location + +**Session Folder**: ${sessionFolder} +**Output Files**: +- ${sessionFolder}/planning-context.md (evidence + understanding) +- ${sessionFolder}/plan.json (plan overview -- NO embedded tasks[]) +- ${sessionFolder}/.task/TASK-*.json (independent task files, one per task) + +## Output Schema Reference +Execute: cat ~/.ccw/workflows/cli-templates/schemas/plan-overview-base-schema.json (get schema reference before generating plan) + +## Project Context (MANDATORY - Read Both Files) +1. Read: .workflow/project-tech.json (technology stack, architecture, key components) +2. Read: .workflow/project-guidelines.json (user-defined constraints and conventions) + +**CRITICAL**: All generated tasks MUST comply with constraints in project-guidelines.json + +## Task Description +${task_description} + +## Multi-Angle Exploration Context + +${manifest.explorations.map(exp => `### Exploration: ${exp.angle} (${exp.file}) +Path: ${exp.path} + +Read this file for detailed ${exp.angle} analysis.`).join('\n\n')} + +Total explorations: ${manifest.exploration_count} +Angles covered: ${manifest.explorations.map(e => e.angle).join(', ')} + +Manifest: ${sessionFolder}/explorations-manifest.json + +## User Clarifications +${JSON.stringify(clarificationContext) || "None"} + +## Complexity Level +${complexity} + +## Requirements +Generate plan.json and .task/*.json following the schema obtained above. Key constraints: +- _metadata.exploration_angles: ${JSON.stringify(manifest.explorations.map(e => e.angle))} + +**Output Format**: Two-layer structure: +- plan.json: Overview with task_ids[] referencing .task/ files (NO tasks[] array) +- .task/TASK-*.json: Independent task files following task-schema.json + +plan.json required fields: summary, approach, task_ids, task_count, _metadata (with plan_type: "feature") +Each task file required fields: id, title, description, depends_on, convergence (with criteria[]) +Task fields use: files[].change (not modification_points), convergence.criteria (not acceptance), test (not verification) + +## Task Grouping Rules +1. **Group by feature**: All changes for one feature = one task (even if 3-5 files) +2. **Group by context**: Tasks with similar context or related functional changes can be grouped together +3. **Minimize agent count**: Simple, unrelated tasks can also be grouped to reduce agent execution overhead +4. **Avoid file-per-task**: Do NOT create separate tasks for each file +5. **Substantial tasks**: Each task should represent 15-60 minutes of work +6. **True dependencies only**: Only use depends_on when Task B cannot start without Task A's output +7. **Prefer parallel**: Most tasks should be independent (no depends_on) + +## Execution +1. Read schema file (cat command above) +2. Execute CLI planning using Gemini (Qwen fallback) +3. Read ALL exploration files for comprehensive context +4. Synthesize findings and generate tasks + plan overview +5. **Write**: \`${sessionFolder}/planning-context.md\` (evidence paths + understanding) +6. **Create**: \`${sessionFolder}/.task/\` directory (mkdir -p) +7. **Write**: \`${sessionFolder}/.task/TASK-001.json\`, \`TASK-002.json\`, etc. (one per task) +8. **Write**: \`${sessionFolder}/plan.json\` (overview with task_ids[], NO tasks[]) +9. Return brief completion summary +` +) +``` + +**Output**: `${sessionFolder}/plan.json` + +--- + +### Phase 4: Task Confirmation & Execution Selection + +**Step 4.1: Display Plan** +```javascript +const plan = JSON.parse(Read(`${sessionFolder}/plan.json`)) + +// Load tasks from .task/ directory +const tasks = (plan.task_ids || []).map(id => { + const taskPath = `${sessionFolder}/.task/${id}.json` + return JSON.parse(Read(taskPath)) +}) +const taskList = tasks + +console.log(` +## Implementation Plan + +**Summary**: ${plan.summary} +**Approach**: ${plan.approach} + +**Tasks** (${taskList.length}): +${taskList.map((t, i) => `${i+1}. ${t.title} (${t.scope || t.files?.[0]?.path || ''})`).join('\n')} + +**Complexity**: ${plan.complexity} +**Estimated Time**: ${plan.estimated_time} +**Recommended**: ${plan.recommended_execution} +`) +``` + +**Step 4.2: Collect Confirmation** +```javascript +// Parse --yes flag +const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') + +let userSelection + +if (autoYes) { + // Auto mode: Use defaults + console.log(`[--yes] Auto-confirming plan:`) + console.log(` - Confirmation: Allow`) + console.log(` - Execution: Auto`) + console.log(` - Review: Skip`) + + userSelection = { + confirmation: "Allow", + execution_method: "Auto", + code_review_tool: "Skip" + } +} else { + // Interactive mode: Ask user + // Note: Execution "Other" option allows specifying CLI tools from ~/.claude/cli-tools.json + userSelection = AskUserQuestion({ + questions: [ + { + question: `Confirm plan? (${taskList.length} tasks, ${plan.complexity})`, + header: "Confirm", + multiSelect: false, + options: [ + { label: "Allow", description: "Proceed as-is" }, + { label: "Modify", description: "Adjust before execution" }, + { label: "Cancel", description: "Abort workflow" } + ] + }, + { + question: "Execution method:", + header: "Execution", + multiSelect: false, + options: [ + { label: "Agent", description: "@code-developer agent" }, + { label: "Codex", description: "codex CLI tool" }, + { label: "Auto", description: `Auto: ${plan.complexity === 'Low' ? 'Agent' : 'Codex'}` } + ] + }, + { + question: "Code review after execution?", + header: "Review", + multiSelect: false, + options: [ + { label: "Gemini Review", description: "Gemini CLI review" }, + { label: "Codex Review", description: "Git-aware review (prompt OR --uncommitted)" }, + { label: "Agent Review", description: "@code-reviewer agent" }, + { label: "Skip", description: "No review" } + ] + } + ] + }) +} +``` + +--- + +### Phase 5: Handoff to Execution + +**CRITICAL**: lite-plan NEVER executes code directly. ALL execution MUST go through lite-execute. + +**Step 5.1: Build executionContext** + +```javascript +// Load manifest and all exploration files +const manifest = JSON.parse(Read(`${sessionFolder}/explorations-manifest.json`)) +const explorations = {} + +manifest.explorations.forEach(exp => { + if (file_exists(exp.path)) { + explorations[exp.angle] = JSON.parse(Read(exp.path)) + } +}) + +const plan = JSON.parse(Read(`${sessionFolder}/plan.json`)) + +executionContext = { + planObject: plan, // plan overview (no tasks[]) + taskFiles: (plan.task_ids || []).map(id => ({ + id, + path: `${sessionFolder}/.task/${id}.json` + })), + explorationsContext: explorations, + explorationAngles: manifest.explorations.map(e => e.angle), + explorationManifest: manifest, + clarificationContext: clarificationContext || null, + executionMethod: userSelection.execution_method, // 全局默认,可被 executorAssignments 覆盖 + codeReviewTool: userSelection.code_review_tool, + originalUserInput: task_description, + + // 任务级 executor 分配(优先于全局 executionMethod) + executorAssignments: executorAssignments, // { taskId: { executor, reason } } + + session: { + id: sessionId, + folder: sessionFolder, + artifacts: { + explorations: manifest.explorations.map(exp => ({ + angle: exp.angle, + path: exp.path + })), + explorations_manifest: `${sessionFolder}/explorations-manifest.json`, + plan: `${sessionFolder}/plan.json`, + task_dir: `${sessionFolder}/.task` + } + } +} +``` + +**Step 5.2: Handoff** + +```javascript +Skill(skill="workflow:lite-execute", args="--in-memory") +``` + +## Session Folder Structure + +``` +.workflow/.lite-plan/{task-slug}-{YYYY-MM-DD}/ +├── exploration-{angle1}.json # Exploration angle 1 +├── exploration-{angle2}.json # Exploration angle 2 +├── exploration-{angle3}.json # Exploration angle 3 (if applicable) +├── exploration-{angle4}.json # Exploration angle 4 (if applicable) +├── explorations-manifest.json # Exploration index +├── planning-context.md # Evidence paths + understanding +├── plan.json # Plan overview (task_ids[]) +└── .task/ # Task files directory + ├── TASK-001.json + ├── TASK-002.json + └── ... +``` + +**Example**: +``` +.workflow/.lite-plan/implement-jwt-refresh-2025-11-25-14-30-25/ +├── exploration-architecture.json +├── exploration-auth-patterns.json +├── exploration-security.json +├── explorations-manifest.json +├── planning-context.md +├── plan.json +└── .task/ + ├── TASK-001.json + ├── TASK-002.json + └── TASK-003.json +``` + +## Error Handling + +| Error | Resolution | +|-------|------------| +| Exploration agent failure | Skip exploration, continue with task description only | +| Planning agent failure | Fallback to direct planning by Claude | +| Clarification timeout | Use exploration findings as-is | +| Confirmation timeout | Save context, display resume instructions | +| Modify loop > 3 times | Suggest breaking task or using /workflow:plan | + +## Next Phase + +After Phase 5 handoff, execution continues in [Phase 2: Lite-Execute](02-lite-execute.md). diff --git a/.claude/skills/workflow-lite-plan/phases/02-lite-execute.md b/.claude/skills/workflow-lite-plan/phases/02-lite-execute.md new file mode 100644 index 00000000..9b7447da --- /dev/null +++ b/.claude/skills/workflow-lite-plan/phases/02-lite-execute.md @@ -0,0 +1,767 @@ +# Phase 2: Lite-Execute + +Complete execution engine: multi-mode input, task grouping, batch execution, code review, and development index update. + +**Source**: Converted from `.claude/commands/workflow/lite-execute.md` - all execution detail preserved verbatim. + +--- + +## Overview + +Flexible task execution command supporting three input modes: in-memory plan (from lite-plan), direct prompt description, or file content. Handles execution orchestration, progress tracking, and optional code review. + +**Core capabilities:** +- Multi-mode input (in-memory plan, prompt description, or file path) +- Execution orchestration (Agent or Codex) with full context +- Live progress tracking via TodoWrite at execution call level +- Optional code review with selected tool (Gemini, Agent, or custom) +- Context continuity across multiple executions +- Intelligent format detection (Enhanced Task JSON vs plain text) + +## Usage + +### Command Syntax +```bash +/workflow:lite-execute [FLAGS] + +# Flags +--in-memory Use plan from memory (called by lite-plan) + +# Arguments + Task description string, or path to file (required) +``` + +## Input Modes + +### Mode 1: In-Memory Plan + +**Trigger**: Called by lite-plan after Phase 4 approval with `--in-memory` flag + +**Input Source**: `executionContext` global variable set by lite-plan + +**Content**: Complete execution context (see Data Structures section) + +**Behavior**: +- Skip execution method selection (already set by lite-plan) +- Directly proceed to execution with full context +- All planning artifacts available (exploration, clarifications, plan) + +### Mode 2: Prompt Description + +**Trigger**: User calls with task description string + +**Input**: Simple task description (e.g., "Add unit tests for auth module") + +**Behavior**: +- Store prompt as `originalUserInput` +- Create simple execution plan from prompt +- AskUserQuestion: Select execution method (Agent/Codex/Auto) +- AskUserQuestion: Select code review tool (Skip/Gemini/Agent/Other) +- Proceed to execution with `originalUserInput` included + +**User Interaction**: +```javascript +// Parse --yes flag +const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') + +let userSelection + +if (autoYes) { + // Auto mode: Use defaults + console.log(`[--yes] Auto-confirming execution:`) + console.log(` - Execution method: Auto`) + console.log(` - Code review: Skip`) + + userSelection = { + execution_method: "Auto", + code_review_tool: "Skip" + } +} else { + // Interactive mode: Ask user + userSelection = AskUserQuestion({ + questions: [ + { + question: "Select execution method:", + header: "Execution", + multiSelect: false, + options: [ + { label: "Agent", description: "@code-developer agent" }, + { label: "Codex", description: "codex CLI tool" }, + { label: "Auto", description: "Auto-select based on complexity" } + ] + }, + { + question: "Enable code review after execution?", + header: "Code Review", + multiSelect: false, + options: [ + { label: "Skip", description: "No review" }, + { label: "Gemini Review", description: "Gemini CLI tool" }, + { label: "Codex Review", description: "Git-aware review (prompt OR --uncommitted)" }, + { label: "Agent Review", description: "Current agent review" } + ] + } + ] + }) +} +``` + +### Mode 3: File Content + +**Trigger**: User calls with file path + +**Input**: Path to file containing task description or plan.json + +**Step 1: Read and Detect Format** + +```javascript +fileContent = Read(filePath) + +// Attempt JSON parsing +try { + jsonData = JSON.parse(fileContent) + + // Check if plan.json from lite-plan session (two-layer format: task_ids[]) + if (jsonData.summary && jsonData.approach && jsonData.task_ids) { + planObject = jsonData + originalUserInput = jsonData.summary + isPlanJson = true + + // Load tasks from .task/*.json files + const planDir = filePath.replace(/[/\\][^/\\]+$/, '') // parent directory + planObject._loadedTasks = loadTaskFiles(planDir, jsonData.task_ids) + } else { + // Valid JSON but not plan.json - treat as plain text + originalUserInput = fileContent + isPlanJson = false + } +} catch { + // Not valid JSON - treat as plain text prompt + originalUserInput = fileContent + isPlanJson = false +} +``` + +**Step 2: Create Execution Plan** + +If `isPlanJson === true`: +- Use `planObject` directly +- User selects execution method and code review + +If `isPlanJson === false`: +- Treat file content as prompt (same behavior as Mode 2) +- Create simple execution plan from content + +**Step 3: User Interaction** + +- AskUserQuestion: Select execution method (Agent/Codex/Auto) +- AskUserQuestion: Select code review tool +- Proceed to execution with full context + +## Helper Functions + +```javascript +// Load task files from .task/ directory (two-layer format) +function loadTaskFiles(planDir, taskIds) { + return taskIds.map(id => { + const taskPath = `${planDir}/.task/${id}.json` + return JSON.parse(Read(taskPath)) + }) +} + +// Get tasks array from loaded .task/*.json files +function getTasks(planObject) { + return planObject._loadedTasks || [] +} +``` + +## Execution Process + +``` +Input Parsing: + └─ Decision (mode detection): + ├─ --in-memory flag → Mode 1: Load executionContext → Skip user selection + ├─ Ends with .md/.json/.txt → Mode 3: Read file → Detect format + │ ├─ Valid plan.json → Use planObject → User selects method + review + │ └─ Not plan.json → Treat as prompt → User selects method + review + └─ Other → Mode 2: Prompt description → User selects method + review + +Execution: + ├─ Step 1: Initialize result tracking (previousExecutionResults = []) + ├─ Step 2: Task grouping & batch creation + │ ├─ Extract explicit depends_on (no file/keyword inference) + │ ├─ Group: independent tasks → single parallel batch (maximize utilization) + │ ├─ Group: dependent tasks → sequential phases (respect dependencies) + │ └─ Create TodoWrite list for batches + ├─ Step 3: Launch execution + │ ├─ Phase 1: All independent tasks (⚡ single batch, concurrent) + │ └─ Phase 2+: Dependent tasks by dependency order + ├─ Step 4: Track progress (TodoWrite updates per batch) + └─ Step 5: Code review (if codeReviewTool ≠ "Skip") + +Output: + └─ Execution complete with results in previousExecutionResults[] +``` + +## Detailed Execution Steps + +### Step 1: Initialize Execution Tracking + +**Operations**: +- Initialize result tracking for multi-execution scenarios +- Set up `previousExecutionResults` array for context continuity +- **In-Memory Mode**: Echo execution strategy from lite-plan for transparency + +```javascript +// Initialize result tracking +previousExecutionResults = [] + +// In-Memory Mode: Echo execution strategy (transparency before execution) +if (executionContext) { + console.log(` +📋 Execution Strategy (from lite-plan): + Method: ${executionContext.executionMethod} + Review: ${executionContext.codeReviewTool} + Tasks: ${getTasks(executionContext.planObject).length} + Complexity: ${executionContext.planObject.complexity} +${executionContext.executorAssignments ? ` Assignments: ${JSON.stringify(executionContext.executorAssignments)}` : ''} + `) +} +``` + +### Step 2: Task Grouping & Batch Creation + +**Dependency Analysis & Grouping Algorithm**: +```javascript +// Use explicit depends_on from plan.json (no inference from file/keywords) +function extractDependencies(tasks) { + const taskIdToIndex = {} + tasks.forEach((t, i) => { taskIdToIndex[t.id] = i }) + + return tasks.map((task, i) => { + // Only use explicit depends_on from plan.json + const deps = (task.depends_on || []) + .map(depId => taskIdToIndex[depId]) + .filter(idx => idx !== undefined && idx < i) + return { ...task, taskIndex: i, dependencies: deps } + }) +} + +// Group into batches: maximize parallel execution +function createExecutionCalls(tasks, executionMethod) { + const tasksWithDeps = extractDependencies(tasks) + const processed = new Set() + const calls = [] + + // Phase 1: All independent tasks → single parallel batch (maximize utilization) + const independentTasks = tasksWithDeps.filter(t => t.dependencies.length === 0) + if (independentTasks.length > 0) { + independentTasks.forEach(t => processed.add(t.taskIndex)) + calls.push({ + method: executionMethod, + executionType: "parallel", + groupId: "P1", + taskSummary: independentTasks.map(t => t.title).join(' | '), + tasks: independentTasks + }) + } + + // Phase 2: Dependent tasks → sequential batches (respect dependencies) + let sequentialIndex = 1 + let remaining = tasksWithDeps.filter(t => !processed.has(t.taskIndex)) + + while (remaining.length > 0) { + // Find tasks whose dependencies are all satisfied + const ready = remaining.filter(t => + t.dependencies.every(d => processed.has(d)) + ) + + if (ready.length === 0) { + console.warn('Circular dependency detected, forcing remaining tasks') + ready.push(...remaining) + } + + // Group ready tasks (can run in parallel within this phase) + ready.forEach(t => processed.add(t.taskIndex)) + calls.push({ + method: executionMethod, + executionType: ready.length > 1 ? "parallel" : "sequential", + groupId: ready.length > 1 ? `P${calls.length + 1}` : `S${sequentialIndex++}`, + taskSummary: ready.map(t => t.title).join(ready.length > 1 ? ' | ' : ' → '), + tasks: ready + }) + + remaining = remaining.filter(t => !processed.has(t.taskIndex)) + } + + return calls +} + +executionCalls = createExecutionCalls(getTasks(planObject), executionMethod).map(c => ({ ...c, id: `[${c.groupId}]` })) + +TodoWrite({ + todos: executionCalls.map(c => ({ + content: `${c.executionType === "parallel" ? "⚡" : "→"} ${c.id} (${c.tasks.length} tasks)`, + status: "pending", + activeForm: `Executing ${c.id}` + })) +}) +``` + +### Step 3: Launch Execution + +**Executor Resolution** (任务级 executor 优先于全局设置): +```javascript +// 获取任务的 executor(优先使用 executorAssignments,fallback 到全局 executionMethod) +function getTaskExecutor(task) { + const assignments = executionContext?.executorAssignments || {} + if (assignments[task.id]) { + return assignments[task.id].executor // 'gemini' | 'codex' | 'agent' + } + // Fallback: 全局 executionMethod 映射 + const method = executionContext?.executionMethod || 'Auto' + if (method === 'Agent') return 'agent' + if (method === 'Codex') return 'codex' + // Auto: 根据复杂度 + return planObject.complexity === 'Low' ? 'agent' : 'codex' +} + +// 按 executor 分组任务 +function groupTasksByExecutor(tasks) { + const groups = { gemini: [], codex: [], agent: [] } + tasks.forEach(task => { + const executor = getTaskExecutor(task) + groups[executor].push(task) + }) + return groups +} +``` + +**Execution Flow**: Parallel batches concurrently → Sequential batches in order +```javascript +const parallel = executionCalls.filter(c => c.executionType === "parallel") +const sequential = executionCalls.filter(c => c.executionType === "sequential") + +// Phase 1: Launch all parallel batches (single message with multiple tool calls) +if (parallel.length > 0) { + TodoWrite({ todos: executionCalls.map(c => ({ status: c.executionType === "parallel" ? "in_progress" : "pending" })) }) + parallelResults = await Promise.all(parallel.map(c => executeBatch(c))) + previousExecutionResults.push(...parallelResults) + TodoWrite({ todos: executionCalls.map(c => ({ status: parallel.includes(c) ? "completed" : "pending" })) }) +} + +// Phase 2: Execute sequential batches one by one +for (const call of sequential) { + TodoWrite({ todos: executionCalls.map(c => ({ status: c === call ? "in_progress" : "..." })) }) + result = await executeBatch(call) + previousExecutionResults.push(result) + TodoWrite({ todos: executionCalls.map(c => ({ status: "completed" or "pending" })) }) +} +``` + +### Unified Task Prompt Builder + +**Task Formatting Principle**: Each task is a self-contained checklist. The executor only needs to know what THIS task requires. Same template for Agent and CLI. + +```javascript +function buildExecutionPrompt(batch) { + // Task template (6 parts: Files → Why → How → Reference → Risks → Done) + const formatTask = (t) => ` +## ${t.title} + +**Scope**: \`${t.scope}\` | **Action**: ${t.action} + +### Files +${(t.files || []).map(f => `- **${f.path}** → \`${f.target || ''}\`: ${f.change || (f.changes || []).join(', ') || ''}`).join('\n')} + +${t.rationale ? ` +### Why this approach (Medium/High) +${t.rationale.chosen_approach} +${t.rationale.decision_factors?.length > 0 ? `\nKey factors: ${t.rationale.decision_factors.join(', ')}` : ''} +${t.rationale.tradeoffs ? `\nTradeoffs: ${t.rationale.tradeoffs}` : ''} +` : ''} + +### How to do it +${t.description} + +${t.implementation.map(step => `- ${step}`).join('\n')} + +${t.code_skeleton ? ` +### Code skeleton (High) +${t.code_skeleton.interfaces?.length > 0 ? `**Interfaces**: ${t.code_skeleton.interfaces.map(i => `\`${i.name}\` - ${i.purpose}`).join(', ')}` : ''} +${t.code_skeleton.key_functions?.length > 0 ? `\n**Functions**: ${t.code_skeleton.key_functions.map(f => `\`${f.signature}\` - ${f.purpose}`).join(', ')}` : ''} +${t.code_skeleton.classes?.length > 0 ? `\n**Classes**: ${t.code_skeleton.classes.map(c => `\`${c.name}\` - ${c.purpose}`).join(', ')}` : ''} +` : ''} + +### Reference +- Pattern: ${t.reference?.pattern || 'N/A'} +- Files: ${t.reference?.files?.join(', ') || 'N/A'} +${t.reference?.examples ? `- Notes: ${t.reference.examples}` : ''} + +${t.risks?.length > 0 ? ` +### Risk mitigations (High) +${t.risks.map(r => `- ${r.description} → **${r.mitigation}**`).join('\n')} +` : ''} + +### Done when +${(t.convergence?.criteria || []).map(c => `- [ ] ${c}`).join('\n')} +${(t.test?.success_metrics || []).length > 0 ? `\n**Success metrics**: ${t.test.success_metrics.join(', ')}` : ''}` + + // Build prompt + const sections = [] + + if (originalUserInput) sections.push(`## Goal\n${originalUserInput}`) + + sections.push(`## Tasks\n${batch.tasks.map(formatTask).join('\n\n---\n')}`) + + // Context (reference only) + const context = [] + if (previousExecutionResults.length > 0) { + context.push(`### Previous Work\n${previousExecutionResults.map(r => `- ${r.tasksSummary}: ${r.status}`).join('\n')}`) + } + if (clarificationContext) { + context.push(`### Clarifications\n${Object.entries(clarificationContext).map(([q, a]) => `- ${q}: ${a}`).join('\n')}`) + } + if (executionContext?.planObject?.data_flow?.diagram) { + context.push(`### Data Flow\n${executionContext.planObject.data_flow.diagram}`) + } + if (executionContext?.session?.artifacts?.plan) { + context.push(`### Artifacts\nPlan: ${executionContext.session.artifacts.plan}`) + } + // Project guidelines (user-defined constraints from /workflow:session:solidify) + context.push(`### Project Guidelines\n@.workflow/project-guidelines.json`) + if (context.length > 0) sections.push(`## Context\n${context.join('\n\n')}`) + + sections.push(`Complete each task according to its "Done when" checklist.`) + + return sections.join('\n\n') +} +``` + +**Option A: Agent Execution** + +When to use: +- `getTaskExecutor(task) === "agent"` +- 或 `executionMethod = "Agent"` (全局 fallback) +- 或 `executionMethod = "Auto" AND complexity = "Low"` (全局 fallback) + +```javascript +Task( + subagent_type="code-developer", + run_in_background=false, + description=batch.taskSummary, + prompt=buildExecutionPrompt(batch) +) +``` + +**Result Collection**: After completion, collect result following `executionResult` structure (see Data Structures section) + +**Option B: CLI Execution (Codex)** + +When to use: +- `getTaskExecutor(task) === "codex"` +- 或 `executionMethod = "Codex"` (全局 fallback) +- 或 `executionMethod = "Auto" AND complexity = "Medium/High"` (全局 fallback) + +```bash +ccw cli -p "${buildExecutionPrompt(batch)}" --tool codex --mode write +``` + +**Execution with fixed IDs** (predictable ID pattern): +```javascript +// Launch CLI in background, wait for task hook callback +// Generate fixed execution ID: ${sessionId}-${groupId} +const sessionId = executionContext?.session?.id || 'standalone' +const fixedExecutionId = `${sessionId}-${batch.groupId}` // e.g., "implement-auth-2025-12-13-P1" + +// Check if resuming from previous failed execution +const previousCliId = batch.resumeFromCliId || null + +// Build command with fixed ID (and optional resume for continuation) +const cli_command = previousCliId + ? `ccw cli -p "${buildExecutionPrompt(batch)}" --tool codex --mode write --id ${fixedExecutionId} --resume ${previousCliId}` + : `ccw cli -p "${buildExecutionPrompt(batch)}" --tool codex --mode write --id ${fixedExecutionId}` + +// Execute in background, stop output and wait for task hook callback +Bash( + command=cli_command, + run_in_background=true +) +// STOP HERE - CLI executes in background, task hook will notify on completion +``` + +**Resume on Failure** (with fixed ID): +```javascript +// If execution failed or timed out, offer resume option +if (bash_result.status === 'failed' || bash_result.status === 'timeout') { + console.log(` +⚠️ Execution incomplete. Resume available: + Fixed ID: ${fixedExecutionId} + Lookup: ccw cli detail ${fixedExecutionId} + Resume: ccw cli -p "Continue tasks" --resume ${fixedExecutionId} --tool codex --mode write --id ${fixedExecutionId}-retry +`) + + // Store for potential retry in same session + batch.resumeFromCliId = fixedExecutionId +} +``` + +**Result Collection**: After completion, analyze output and collect result following `executionResult` structure (include `cliExecutionId` for resume capability) + +**Option C: CLI Execution (Gemini)** + +When to use: `getTaskExecutor(task) === "gemini"` (分析类任务) + +```bash +# 使用统一的 buildExecutionPrompt,切换 tool 和 mode +ccw cli -p "${buildExecutionPrompt(batch)}" --tool gemini --mode analysis --id ${sessionId}-${batch.groupId} +``` + +### Step 4: Progress Tracking + +Progress tracked at batch level (not individual task level). Icons: ⚡ (parallel, concurrent), → (sequential, one-by-one) + +### Step 5: Code Review (Optional) + +**Skip Condition**: Only run if `codeReviewTool ≠ "Skip"` + +**Review Focus**: Verify implementation against plan convergence criteria and test requirements +- Read plan.json + .task/*.json for task convergence criteria and test checklist +- Check each convergence criterion is fulfilled +- Verify success metrics from test field (Medium/High complexity) +- Run unit/integration tests specified in test field +- Validate code quality and identify issues +- Ensure alignment with planned approach and risk mitigations + +**Operations**: +- Agent Review: Current agent performs direct review +- Gemini Review: Execute gemini CLI with review prompt +- Codex Review: Two options - (A) with prompt for complex reviews, (B) `--uncommitted` flag only for quick reviews +- Custom tool: Execute specified CLI tool (qwen, etc.) + +**Unified Review Template** (All tools use same standard): + +**Review Criteria**: +- **Convergence Criteria**: Verify each criterion from task convergence.criteria +- **Test Checklist** (Medium/High): Check unit, integration, success_metrics from task test +- **Code Quality**: Analyze quality, identify issues, suggest improvements +- **Plan Alignment**: Validate implementation matches planned approach and risk mitigations + +**Shared Prompt Template** (used by all CLI tools): +``` +PURPOSE: Code review for implemented changes against plan convergence criteria and test requirements +TASK: • Verify plan convergence criteria fulfillment • Check test requirements (unit, integration, success_metrics) • Analyze code quality • Identify issues • Suggest improvements • Validate plan adherence and risk mitigations +MODE: analysis +CONTEXT: @**/* @{plan.json} @{.task/*.json} [@{exploration.json}] | Memory: Review lite-execute changes against plan requirements including test checklist +EXPECTED: Quality assessment with: + - Convergence criteria verification (all tasks from .task/*.json) + - Test checklist validation (Medium/High: unit, integration, success_metrics) + - Issue identification + - Recommendations + Explicitly check each convergence criterion and test item from .task/*.json files. +CONSTRAINTS: Focus on plan convergence criteria, test requirements, and plan adherence | analysis=READ-ONLY +``` + +**Tool-Specific Execution** (Apply shared prompt template above): + +```bash +# Method 1: Agent Review (current agent) +# - Read plan.json: ${executionContext.session.artifacts.plan} +# - Apply unified review criteria (see Shared Prompt Template) +# - Report findings directly + +# Method 2: Gemini Review (recommended) +ccw cli -p "[Shared Prompt Template with artifacts]" --tool gemini --mode analysis +# CONTEXT includes: @**/* @${plan.json} [@${exploration.json}] + +# Method 3: Qwen Review (alternative) +ccw cli -p "[Shared Prompt Template with artifacts]" --tool qwen --mode analysis +# Same prompt as Gemini, different execution engine + +# Method 4: Codex Review (git-aware) - Two mutually exclusive options: + +# Option A: With custom prompt (reviews uncommitted by default) +ccw cli -p "[Shared Prompt Template with artifacts]" --tool codex --mode review +# Use for complex reviews with specific focus areas + +# Option B: Target flag only (no prompt allowed) +ccw cli --tool codex --mode review --uncommitted +# Quick review of uncommitted changes without custom instructions + +# ⚠️ IMPORTANT: -p prompt and target flags (--uncommitted/--base/--commit) are MUTUALLY EXCLUSIVE +``` + +**Multi-Round Review with Fixed IDs**: +```javascript +// Generate fixed review ID +const reviewId = `${sessionId}-review` + +// First review pass with fixed ID +const reviewResult = Bash(`ccw cli -p "[Review prompt]" --tool gemini --mode analysis --id ${reviewId}`) + +// If issues found, continue review dialog with fixed ID chain +if (hasUnresolvedIssues(reviewResult)) { + // Resume with follow-up questions + Bash(`ccw cli -p "Clarify the security concerns you mentioned" --resume ${reviewId} --tool gemini --mode analysis --id ${reviewId}-followup`) +} +``` + +**Implementation Note**: Replace `[Shared Prompt Template with artifacts]` placeholder with actual template content, substituting: +- `@{plan.json}` → `@${executionContext.session.artifacts.plan}` +- `[@{exploration.json}]` → exploration files from artifacts (if exists) + +### Step 6: Update Development Index + +**Trigger**: After all executions complete (regardless of code review) + +**Skip Condition**: Skip if `.workflow/project-tech.json` does not exist + +**Operations**: +```javascript +const projectJsonPath = '.workflow/project-tech.json' +if (!fileExists(projectJsonPath)) return // Silent skip + +const projectJson = JSON.parse(Read(projectJsonPath)) + +// Initialize if needed +if (!projectJson.development_index) { + projectJson.development_index = { feature: [], enhancement: [], bugfix: [], refactor: [], docs: [] } +} + +// Detect category from keywords +function detectCategory(text) { + text = text.toLowerCase() + if (/\b(fix|bug|error|issue|crash)\b/.test(text)) return 'bugfix' + if (/\b(refactor|cleanup|reorganize)\b/.test(text)) return 'refactor' + if (/\b(doc|readme|comment)\b/.test(text)) return 'docs' + if (/\b(add|new|create|implement)\b/.test(text)) return 'feature' + return 'enhancement' +} + +// Detect sub_feature from task file paths +function detectSubFeature(tasks) { + const dirs = tasks.map(t => t.file?.split('/').slice(-2, -1)[0]).filter(Boolean) + const counts = dirs.reduce((a, d) => { a[d] = (a[d] || 0) + 1; return a }, {}) + return Object.entries(counts).sort((a, b) => b[1] - a[1])[0]?.[0] || 'general' +} + +const category = detectCategory(`${planObject.summary} ${planObject.approach}`) +const entry = { + title: planObject.summary.slice(0, 60), + sub_feature: detectSubFeature(getTasks(planObject)), + date: new Date().toISOString().split('T')[0], + description: planObject.approach.slice(0, 100), + status: previousExecutionResults.every(r => r.status === 'completed') ? 'completed' : 'partial', + session_id: executionContext?.session?.id || null +} + +projectJson.development_index[category].push(entry) +projectJson.statistics.last_updated = new Date().toISOString() +Write(projectJsonPath, JSON.stringify(projectJson, null, 2)) + +console.log(`✓ Development index: [${category}] ${entry.title}`) +``` + +## Best Practices + +**Input Modes**: In-memory (lite-plan), prompt (standalone), file (JSON/text) +**Task Grouping**: Based on explicit depends_on only; independent tasks run in single parallel batch +**Execution**: All independent tasks launch concurrently via single Claude message with multiple tool calls + +## Error Handling + +| Error | Cause | Resolution | +|-------|-------|------------| +| Missing executionContext | --in-memory without context | Error: "No execution context found. Only available when called by lite-plan." | +| File not found | File path doesn't exist | Error: "File not found: {path}. Check file path." | +| Empty file | File exists but no content | Error: "File is empty: {path}. Provide task description." | +| Invalid Enhanced Task JSON | JSON missing required fields | Warning: "Missing required fields. Treating as plain text." | +| Malformed JSON | JSON parsing fails | Treat as plain text (expected for non-JSON files) | +| Execution failure | Agent/Codex crashes | Display error, use fixed ID `${sessionId}-${groupId}` for resume: `ccw cli -p "Continue" --resume --id -retry` | +| Execution timeout | CLI exceeded timeout | Use fixed ID for resume with extended timeout | +| Codex unavailable | Codex not installed | Show installation instructions, offer Agent execution | +| Fixed ID not found | Custom ID lookup failed | Check `ccw cli history`, verify date directories | + +## Data Structures + +### executionContext (Input - Mode 1) + +Passed from lite-plan via global variable: + +```javascript +{ + planObject: { + summary: string, + approach: string, + task_ids: string[], // Task IDs referencing .task/*.json files + task_count: number, // Number of tasks + _loadedTasks: [...], // Populated at runtime from .task/*.json files + estimated_time: string, + recommended_execution: string, + complexity: string + }, + // Task file paths (populated for two-layer format) + taskFiles: [{id: string, path: string}] | null, + explorationsContext: {...} | null, // Multi-angle explorations + explorationAngles: string[], // List of exploration angles + explorationManifest: {...} | null, // Exploration manifest + clarificationContext: {...} | null, + executionMethod: "Agent" | "Codex" | "Auto", // 全局默认 + codeReviewTool: "Skip" | "Gemini Review" | "Agent Review" | string, + originalUserInput: string, + + // 任务级 executor 分配(优先于 executionMethod) + executorAssignments: { + [taskId]: { executor: "gemini" | "codex" | "agent", reason: string } + }, + + // Session artifacts location (saved by lite-plan) + session: { + id: string, // Session identifier: {taskSlug}-{shortTimestamp} + folder: string, // Session folder path: .workflow/.lite-plan/{session-id} + artifacts: { + explorations: [{angle, path}], // exploration-{angle}.json paths + explorations_manifest: string, // explorations-manifest.json path + plan: string // plan.json path (always present) + } + } +} +``` + +**Artifact Usage**: +- Artifact files contain detailed planning context +- Pass artifact paths to CLI tools and agents for enhanced context +- See execution options below for usage examples + +### executionResult (Output) + +Collected after each execution call completes: + +```javascript +{ + executionId: string, // e.g., "[Agent-1]", "[Codex-1]" + status: "completed" | "partial" | "failed", + tasksSummary: string, // Brief description of tasks handled + completionSummary: string, // What was completed + keyOutputs: string, // Files created/modified, key changes + notes: string, // Important context for next execution + fixedCliId: string | null // Fixed CLI execution ID (e.g., "implement-auth-2025-12-13-P1") +} +``` + +Appended to `previousExecutionResults` array for context continuity in multi-execution scenarios. + +## Post-Completion Expansion + +完成后询问用户是否扩展为issue(test/enhance/refactor/doc),选中项调用 `/issue:new "{summary} - {dimension}"` + +**Fixed ID Pattern**: `${sessionId}-${groupId}` enables predictable lookup without auto-generated timestamps. + +**Resume Usage**: If `status` is "partial" or "failed", use `fixedCliId` to resume: +```bash +# Lookup previous execution +ccw cli detail ${fixedCliId} + +# Resume with new fixed ID for retry +ccw cli -p "Continue from where we left off" --resume ${fixedCliId} --tool codex --mode write --id ${fixedCliId}-retry +``` diff --git a/.claude/skills/workflow-multi-cli-plan/SKILL.md b/.claude/skills/workflow-multi-cli-plan/SKILL.md new file mode 100644 index 00000000..23c32677 --- /dev/null +++ b/.claude/skills/workflow-multi-cli-plan/SKILL.md @@ -0,0 +1,112 @@ +--- +name: workflow-multi-cli-plan +description: Multi-CLI collaborative planning and execution skill - route to multi-cli-plan or lite-execute with prompt enhancement. Triggers on "workflow:multi-cli-plan", "workflow:lite-execute". +allowed-tools: Skill, Task, AskUserQuestion, TodoWrite, Read, Write, Edit, Bash, Glob, Grep, mcp__ace-tool__search_context +--- + +# Workflow Multi-CLI Plan + +Unified multi-CLI collaborative planning and execution skill. Routes to multi-cli-plan (ACE context + multi-CLI discussion + plan generation) or lite-execute (execution engine) based on trigger, with prompt enhancement for both modes. + +## Architecture Overview + +``` +┌─────────────────────────────────────────────────────────┐ +│ SKILL.md (Router + Prompt Enhancement) │ +│ → Detect mode → Enhance prompt → Dispatch to phase │ +└──────────────────────┬──────────────────────────────────┘ + │ + ┌───────────┼───────────┐ + ↓ ↓ + ┌──────────────┐ ┌───────────┐ + │multi-cli-plan│ │lite-execute│ + │ Phase 1 │ │ Phase 2 │ + │ Plan+Exec │─handoff→│ Standalone │ + └──────────────┘ └───────────┘ +``` + +## Mode Detection & Routing + +```javascript +const args = $ARGUMENTS +const mode = detectMode() + +function detectMode() { + if (skillName === 'workflow:lite-execute') return 'execute' + return 'plan' // default: workflow:multi-cli-plan +} +``` + +**Routing Table**: + +| Trigger | Mode | Phase Document | Description | +|---------|------|----------------|-------------| +| `workflow:multi-cli-plan` | plan | [phases/01-multi-cli-plan.md](phases/01-multi-cli-plan.md) | Multi-CLI collaborative planning (ACE context → discussion → plan → execute) | +| `workflow:lite-execute` | execute | [phases/02-lite-execute.md](phases/02-lite-execute.md) | Standalone execution (in-memory / prompt / file) | + +## Prompt Enhancement + +Before dispatching to the target phase, enhance context: + +```javascript +// Step 1: Check for project context files +const hasProjectTech = fileExists('.workflow/project-tech.json') +const hasProjectGuidelines = fileExists('.workflow/project-guidelines.json') + +// Step 2: Log available context +if (hasProjectTech) { + console.log('Project tech context available: .workflow/project-tech.json') +} +if (hasProjectGuidelines) { + console.log('Project guidelines available: .workflow/project-guidelines.json') +} + +// Step 3: Dispatch to phase +if (mode === 'plan') { + // Read phases/01-multi-cli-plan.md and execute +} else { + // Read phases/02-lite-execute.md and execute +} +``` + +## Execution Flow + +### Plan Mode (workflow:multi-cli-plan) + +``` +1. Parse flags (-y/--yes, --max-rounds, --tools, --mode) and task description +2. Enhance prompt with project context availability +3. Read phases/01-multi-cli-plan.md +4. Execute multi-cli-plan pipeline (Phase 1-5 within the phase doc) +5. Phase 5 internally calls workflow:lite-execute via Skill handoff +``` + +### Execute Mode (workflow:lite-execute) + +``` +1. Parse flags (--in-memory, -y/--yes) and input +2. Enhance prompt with project context availability +3. Read phases/02-lite-execute.md +4. Execute lite-execute pipeline (input detection → execution → review) +``` + +## Usage + +```bash +# Multi-CLI plan mode +/workflow:multi-cli-plan "Implement user authentication" +/workflow:multi-cli-plan --yes "Add dark mode support" +/workflow:multi-cli-plan "Refactor payment module" --max-rounds=3 --tools=gemini,codex + +# Execute mode (standalone) +/workflow:lite-execute "Add unit tests for auth" # Prompt description +/workflow:lite-execute plan.json # File input +/workflow:lite-execute --in-memory # Called by multi-cli-plan internally +``` + +## Phase Reference Documents + +| Phase | Document | Purpose | +|-------|----------|---------| +| 1 | [phases/01-multi-cli-plan.md](phases/01-multi-cli-plan.md) | Complete multi-CLI planning pipeline: ACE context, iterative discussion, options, user decision, plan generation, handoff | +| 2 | [phases/02-lite-execute.md](phases/02-lite-execute.md) | Complete execution engine: input modes, task grouping, batch execution, code review | diff --git a/.claude/skills/workflow-multi-cli-plan/phases/01-multi-cli-plan.md b/.claude/skills/workflow-multi-cli-plan/phases/01-multi-cli-plan.md new file mode 100644 index 00000000..06a1a8ee --- /dev/null +++ b/.claude/skills/workflow-multi-cli-plan/phases/01-multi-cli-plan.md @@ -0,0 +1,605 @@ +# Phase 1: Multi-CLI Collaborative Planning + +Complete multi-CLI collaborative planning pipeline with ACE context gathering and iterative cross-verification. This phase document preserves the full content of the original `workflow:multi-cli-plan` command. + +> **Source**: Converted from `.claude/commands/workflow/multi-cli-plan.md`. Frontmatter moved to SKILL.md. + +## Auto Mode + +When `--yes` or `-y`: Auto-approve plan, use recommended solution and execution method (Agent, Skip review). + +# Multi-CLI Collaborative Planning Command + +## Quick Start + +```bash +# Basic usage +/workflow:multi-cli-plan "Implement user authentication" + +# With options +/workflow:multi-cli-plan "Add dark mode support" --max-rounds=3 +/workflow:multi-cli-plan "Refactor payment module" --tools=gemini,codex,claude +/workflow:multi-cli-plan "Fix memory leak" --mode=serial +``` + +**Context Source**: ACE semantic search + Multi-CLI analysis +**Output Directory**: `.workflow/.multi-cli-plan/{session-id}/` +**Default Max Rounds**: 3 (convergence may complete earlier) +**CLI Tools**: @cli-discuss-agent (analysis), @cli-lite-planning-agent (plan generation) +**Execution**: Auto-hands off to `/workflow:lite-execute --in-memory` after plan approval + +## What & Why + +### Core Concept + +Multi-CLI collaborative planning with **three-phase architecture**: ACE context gathering → Iterative multi-CLI discussion → Plan generation. Orchestrator delegates analysis to agents, only handles user decisions and session management. + +**Process**: +- **Phase 1**: ACE semantic search gathers codebase context +- **Phase 2**: cli-discuss-agent orchestrates Gemini/Codex/Claude for cross-verified analysis +- **Phase 3-5**: User decision → Plan generation → Execution handoff + +**vs Single-CLI Planning**: +- **Single**: One model perspective, potential blind spots +- **Multi-CLI**: Cross-verification catches inconsistencies, builds consensus on solutions + +### Value Proposition + +1. **Multi-Perspective Analysis**: Gemini + Codex + Claude analyze from different angles +2. **Cross-Verification**: Identify agreements/disagreements, build confidence +3. **User-Driven Decisions**: Every round ends with user decision point +4. **Iterative Convergence**: Progressive refinement until consensus reached + +### Orchestrator Boundary (CRITICAL) + +- **ONLY command** for multi-CLI collaborative planning +- Manages: Session state, user decisions, agent delegation, phase transitions +- Delegates: CLI execution to @cli-discuss-agent, plan generation to @cli-lite-planning-agent + +### Execution Flow + +``` +Phase 1: Context Gathering + └─ ACE semantic search, extract keywords, build context package + +Phase 2: Multi-CLI Discussion (Iterative, via @cli-discuss-agent) + ├─ Round N: Agent executes Gemini + Codex + Claude + ├─ Cross-verify findings, synthesize solutions + ├─ Write synthesis.json to rounds/{N}/ + └─ Loop until convergence or max rounds + +Phase 3: Present Options + └─ Display solutions with trade-offs from agent output + +Phase 4: User Decision + ├─ Select solution approach + ├─ Select execution method (Agent/Codex/Auto) + ├─ Select code review tool (Skip/Gemini/Codex/Agent) + └─ Route: + ├─ Approve → Phase 5 + ├─ Need More Analysis → Return to Phase 2 + └─ Cancel → Save session + +Phase 5: Plan Generation & Execution Handoff + ├─ Generate plan.json + .task/*.json (via @cli-lite-planning-agent, two-layer output) + ├─ Build executionContext with user selections and taskFiles + └─ Execute to /workflow:lite-execute --in-memory +``` + +### Agent Roles + +| Agent | Responsibility | +|-------|---------------| +| **Orchestrator** | Session management, ACE context, user decisions, phase transitions, executionContext assembly | +| **@cli-discuss-agent** | Multi-CLI execution (Gemini/Codex/Claude), cross-verification, solution synthesis, synthesis.json output | +| **@cli-lite-planning-agent** | Task decomposition, two-layer output: plan.json (overview with task_ids[]) + .task/*.json (task files) | + +## Core Responsibilities + +### Phase 1: Context Gathering + +**Session Initialization**: +```javascript +const sessionId = `MCP-${taskSlug}-${date}` +const sessionFolder = `.workflow/.multi-cli-plan/${sessionId}` +Bash(`mkdir -p ${sessionFolder}/rounds`) +``` + +**ACE Context Queries**: +```javascript +const aceQueries = [ + `Project architecture related to ${keywords}`, + `Existing implementations of ${keywords[0]}`, + `Code patterns for ${keywords} features`, + `Integration points for ${keywords[0]}` +] +// Execute via mcp__ace-tool__search_context +``` + +**Context Package** (passed to agent): +- `relevant_files[]` - Files identified by ACE +- `detected_patterns[]` - Code patterns found +- `architecture_insights` - Structure understanding + +### Phase 2: Agent Delegation + +**Core Principle**: Orchestrator only delegates and reads output - NO direct CLI execution. + +**⚠️ CRITICAL - CLI EXECUTION REQUIREMENT**: +- **MUST** execute CLI calls via `Bash` with `run_in_background: true` +- **MUST** wait for hook callback to receive complete results +- **MUST NOT** proceed with next phase until CLI execution fully completes +- Do NOT use `TaskOutput` polling during CLI execution - wait passively for results +- Minimize scope: Proceed only when 100% result available + +**Agent Invocation**: +```javascript +Task({ + subagent_type: "cli-discuss-agent", + run_in_background: false, + description: `Discussion round ${currentRound}`, + prompt: ` +## Input Context +- task_description: ${taskDescription} +- round_number: ${currentRound} +- session: { id: "${sessionId}", folder: "${sessionFolder}" } +- ace_context: ${JSON.stringify(contextPackageage)} +- previous_rounds: ${JSON.stringify(analysisResults)} +- user_feedback: ${userFeedback || 'None'} +- cli_config: { tools: ["gemini", "codex"], mode: "parallel", fallback_chain: ["gemini", "codex", "claude"] } + +## Execution Process +1. Parse input context (handle JSON strings) +2. Check if ACE supplementary search needed +3. Build CLI prompts with context +4. Execute CLIs (parallel or serial per cli_config.mode) +5. Parse CLI outputs, handle failures with fallback +6. Perform cross-verification between CLI results +7. Synthesize solutions, calculate scores +8. Calculate convergence, generate clarification questions +9. Write synthesis.json + +## Output +Write: ${sessionFolder}/rounds/${currentRound}/synthesis.json + +## Completion Checklist +- [ ] All configured CLI tools executed (or fallback triggered) +- [ ] Cross-verification completed with agreements/disagreements +- [ ] 2-3 solutions generated with file:line references +- [ ] Convergence score calculated (0.0-1.0) +- [ ] synthesis.json written with all Primary Fields +` +}) +``` + +**Read Agent Output**: +```javascript +const synthesis = JSON.parse(Read(`${sessionFolder}/rounds/${round}/synthesis.json`)) +// Access top-level fields: solutions, convergence, cross_verification, clarification_questions +``` + +**Convergence Decision**: +```javascript +if (synthesis.convergence.recommendation === 'converged') { + // Proceed to Phase 3 +} else if (synthesis.convergence.recommendation === 'user_input_needed') { + // Collect user feedback, return to Phase 2 +} else { + // Continue to next round if new_insights && round < maxRounds +} +``` + +### Phase 3: Present Options + +**Display from Agent Output** (no processing): +```javascript +console.log(` +## Solution Options + +${synthesis.solutions.map((s, i) => ` +**Option ${i+1}: ${s.name}** +Source: ${s.source_cli.join(' + ')} +Effort: ${s.effort} | Risk: ${s.risk} + +Pros: ${s.pros.join(', ')} +Cons: ${s.cons.join(', ')} + +Files: ${s.affected_files.slice(0,3).map(f => `${f.file}:${f.line}`).join(', ')} +`).join('\n')} + +## Cross-Verification +Agreements: ${synthesis.cross_verification.agreements.length} +Disagreements: ${synthesis.cross_verification.disagreements.length} +`) +``` + +### Phase 4: User Decision + +**Decision Options**: +```javascript +AskUserQuestion({ + questions: [ + { + question: "Which solution approach?", + header: "Solution", + multiSelect: false, + options: solutions.map((s, i) => ({ + label: `Option ${i+1}: ${s.name}`, + description: `${s.effort} effort, ${s.risk} risk` + })).concat([ + { label: "Need More Analysis", description: "Return to Phase 2" } + ]) + }, + { + question: "Execution method:", + header: "Execution", + multiSelect: false, + options: [ + { label: "Agent", description: "@code-developer agent" }, + { label: "Codex", description: "codex CLI tool" }, + { label: "Auto", description: "Auto-select based on complexity" } + ] + }, + { + question: "Code review after execution?", + header: "Review", + multiSelect: false, + options: [ + { label: "Skip", description: "No review" }, + { label: "Gemini Review", description: "Gemini CLI tool" }, + { label: "Codex Review", description: "codex review --uncommitted" }, + { label: "Agent Review", description: "Current agent review" } + ] + } + ] +}) +``` + +**Routing**: +- Approve + execution method → Phase 5 +- Need More Analysis → Phase 2 with feedback +- Cancel → Save session for resumption + +### Phase 5: Plan Generation & Execution Handoff + +**Step 1: Build Context-Package** (Orchestrator responsibility): +```javascript +// Extract key information from user decision and synthesis +const contextPackage = { + // Core solution details + solution: { + name: selectedSolution.name, + source_cli: selectedSolution.source_cli, + feasibility: selectedSolution.feasibility, + effort: selectedSolution.effort, + risk: selectedSolution.risk, + summary: selectedSolution.summary + }, + // Implementation plan (tasks, flow, milestones) + implementation_plan: selectedSolution.implementation_plan, + // Dependencies + dependencies: selectedSolution.dependencies || { internal: [], external: [] }, + // Technical concerns + technical_concerns: selectedSolution.technical_concerns || [], + // Consensus from cross-verification + consensus: { + agreements: synthesis.cross_verification.agreements, + resolved_conflicts: synthesis.cross_verification.resolution + }, + // User constraints (from Phase 4 feedback) + constraints: userConstraints || [], + // Task context + task_description: taskDescription, + session_id: sessionId +} + +// Write context-package for traceability +Write(`${sessionFolder}/context-package.json`, JSON.stringify(contextPackage, null, 2)) +``` + +**Context-Package Schema**: + +| Field | Type | Description | +|-------|------|-------------| +| `solution` | object | User-selected solution from synthesis | +| `solution.name` | string | Solution identifier | +| `solution.feasibility` | number | Viability score (0-1) | +| `solution.summary` | string | Brief analysis summary | +| `implementation_plan` | object | Task breakdown with flow and dependencies | +| `implementation_plan.approach` | string | High-level technical strategy | +| `implementation_plan.tasks[]` | array | Discrete tasks with id, name, depends_on, files | +| `implementation_plan.execution_flow` | string | Task sequence (e.g., "T1 → T2 → T3") | +| `implementation_plan.milestones` | string[] | Key checkpoints | +| `dependencies` | object | Module and package dependencies | +| `technical_concerns` | string[] | Risks and blockers | +| `consensus` | object | Cross-verified agreements from multi-CLI | +| `constraints` | string[] | User-specified constraints from Phase 4 | + +```json +{ + "solution": { + "name": "Strategy Pattern Refactoring", + "source_cli": ["gemini", "codex"], + "feasibility": 0.88, + "effort": "medium", + "risk": "low", + "summary": "Extract payment gateway interface, implement strategy pattern for multi-gateway support" + }, + "implementation_plan": { + "approach": "Define interface → Create concrete strategies → Implement factory → Migrate existing code", + "tasks": [ + {"id": "T1", "name": "Define PaymentGateway interface", "depends_on": [], "files": [{"file": "src/types/payment.ts", "line": 1, "action": "create"}], "key_point": "Include all existing Stripe methods"}, + {"id": "T2", "name": "Implement StripeGateway", "depends_on": ["T1"], "files": [{"file": "src/payment/stripe.ts", "line": 1, "action": "create"}], "key_point": "Wrap existing logic"}, + {"id": "T3", "name": "Create GatewayFactory", "depends_on": ["T1"], "files": [{"file": "src/payment/factory.ts", "line": 1, "action": "create"}], "key_point": null}, + {"id": "T4", "name": "Migrate processor to use factory", "depends_on": ["T2", "T3"], "files": [{"file": "src/payment/processor.ts", "line": 45, "action": "modify"}], "key_point": "Backward compatible"} + ], + "execution_flow": "T1 → (T2 | T3) → T4", + "milestones": ["Interface defined", "Gateway implementations complete", "Migration done"] + }, + "dependencies": { + "internal": ["@/lib/payment-gateway", "@/types/payment"], + "external": ["stripe@^14.0.0"] + }, + "technical_concerns": ["Existing tests must pass", "No breaking API changes"], + "consensus": { + "agreements": ["Use strategy pattern", "Keep existing API"], + "resolved_conflicts": "Factory over DI for simpler integration" + }, + "constraints": ["backward compatible", "no breaking changes to PaymentResult type"], + "task_description": "Refactor payment processing for multi-gateway support", + "session_id": "MCP-payment-refactor-2026-01-14" +} +``` + +**Step 2: Invoke Planning Agent**: +```javascript +Task({ + subagent_type: "cli-lite-planning-agent", + run_in_background: false, + description: "Generate implementation plan", + prompt: ` +## Schema Reference +Execute: cat ~/.ccw/workflows/cli-templates/schemas/plan-overview-base-schema.json +Execute: cat ~/.ccw/workflows/cli-templates/schemas/task-schema.json + +## Output Format: Two-Layer Structure +- plan.json: Overview with task_ids[] referencing .task/ files (NO tasks[] array) +- .task/TASK-*.json: Independent task files following task-schema.json + +plan.json required: summary, approach, task_ids, task_count, _metadata (with plan_type) +Task files required: id, title, description, depends_on, convergence (with criteria[]) +Task fields: files[].change (not modification_points), convergence.criteria (not acceptance), test (not verification) + +## Context-Package (from orchestrator) +${JSON.stringify(contextPackage, null, 2)} + +## Execution Process +1. Read plan-overview-base-schema.json + task-schema.json for output structure +2. Read project-tech.json and project-guidelines.json +3. Parse context-package fields: + - solution: name, feasibility, summary + - implementation_plan: tasks[], execution_flow, milestones + - dependencies: internal[], external[] + - technical_concerns: risks/blockers + - consensus: agreements, resolved_conflicts + - constraints: user requirements +4. Use implementation_plan.tasks[] as task foundation +5. Preserve task dependencies (depends_on) and execution_flow +6. Expand tasks with convergence.criteria (testable completion conditions) +7. Create .task/ directory and write individual TASK-*.json files +8. Generate plan.json with task_ids[] referencing .task/ files + +## Output +- ${sessionFolder}/plan.json (overview with task_ids[]) +- ${sessionFolder}/.task/TASK-*.json (independent task files) + +## Completion Checklist +- [ ] plan.json has task_ids[] and task_count (NO embedded tasks[]) +- [ ] .task/*.json files preserve task dependencies from implementation_plan +- [ ] Task execution order follows execution_flow +- [ ] Key_points reflected in task descriptions +- [ ] User constraints applied to implementation +- [ ] convergence.criteria are testable +- [ ] plan.json follows plan-overview-base-schema.json +- [ ] Task files follow task-schema.json +` +}) +``` + +**Step 3: Build executionContext**: +```javascript +// After plan.json is generated by cli-lite-planning-agent +const plan = JSON.parse(Read(`${sessionFolder}/plan.json`)) + +// Load task files from .task/ directory (two-layer format) +const taskFiles = plan.task_ids.map(id => `${sessionFolder}/.task/${id}.json`) + +// Build executionContext (same structure as lite-plan) +executionContext = { + planObject: plan, + taskFiles: taskFiles, // Paths to .task/*.json files (two-layer format) + explorationsContext: null, // Multi-CLI doesn't use exploration files + explorationAngles: [], // No exploration angles + explorationManifest: null, // No manifest + clarificationContext: null, // Store user feedback from Phase 2 if exists + executionMethod: userSelection.execution_method, // From Phase 4 + codeReviewTool: userSelection.code_review_tool, // From Phase 4 + originalUserInput: taskDescription, + + // Optional: Task-level executor assignments + executorAssignments: null, // Could be enhanced in future + + session: { + id: sessionId, + folder: sessionFolder, + artifacts: { + explorations: [], // No explorations in multi-CLI workflow + explorations_manifest: null, + plan: `${sessionFolder}/plan.json`, + task_dir: plan.task_ids ? `${sessionFolder}/.task/` : null, + synthesis_rounds: Array.from({length: currentRound}, (_, i) => + `${sessionFolder}/rounds/${i+1}/synthesis.json` + ), + context_package: `${sessionFolder}/context-package.json` + } + } +} +``` + +**Step 4: Hand off to Execution**: +```javascript +// Execute to lite-execute with in-memory context +Skill(skill="workflow:lite-execute", args="--in-memory") +``` + +## Output File Structure + +``` +.workflow/.multi-cli-plan/{MCP-task-slug-YYYY-MM-DD}/ +├── session-state.json # Session tracking (orchestrator) +├── rounds/ +│ ├── 1/synthesis.json # Round 1 analysis (cli-discuss-agent) +│ ├── 2/synthesis.json # Round 2 analysis (cli-discuss-agent) +│ └── .../ +├── context-package.json # Extracted context for planning (orchestrator) +├── plan.json # Plan overview with task_ids[] (NO embedded tasks[]) +└── .task/ # Independent task files + ├── TASK-001.json # Task file following task-schema.json + ├── TASK-002.json + └── ... +``` + +**File Producers**: + +| File | Producer | Content | +|------|----------|---------| +| `session-state.json` | Orchestrator | Session metadata, rounds, decisions | +| `rounds/*/synthesis.json` | cli-discuss-agent | Solutions, convergence, cross-verification | +| `context-package.json` | Orchestrator | Extracted solution, dependencies, consensus for planning | +| `plan.json` | cli-lite-planning-agent | Plan overview with task_ids[] referencing .task/ files | +| `.task/*.json` | cli-lite-planning-agent | Independent task files following task-schema.json | + +## synthesis.json Schema + +```json +{ + "round": 1, + "solutions": [{ + "name": "Solution Name", + "source_cli": ["gemini", "codex"], + "feasibility": 0.85, + "effort": "low|medium|high", + "risk": "low|medium|high", + "summary": "Brief analysis summary", + "implementation_plan": { + "approach": "High-level technical approach", + "tasks": [ + {"id": "T1", "name": "Task", "depends_on": [], "files": [], "key_point": "..."} + ], + "execution_flow": "T1 → T2 → T3", + "milestones": ["Checkpoint 1", "Checkpoint 2"] + }, + "dependencies": {"internal": [], "external": []}, + "technical_concerns": ["Risk 1", "Blocker 2"] + }], + "convergence": { + "score": 0.85, + "new_insights": false, + "recommendation": "converged|continue|user_input_needed" + }, + "cross_verification": { + "agreements": [], + "disagreements": [], + "resolution": "..." + }, + "clarification_questions": [] +} +``` + +**Key Planning Fields**: + +| Field | Purpose | +|-------|---------| +| `feasibility` | Viability score (0-1) | +| `implementation_plan.tasks[]` | Discrete tasks with dependencies | +| `implementation_plan.execution_flow` | Task sequence visualization | +| `implementation_plan.milestones` | Key checkpoints | +| `technical_concerns` | Risks and blockers | + +**Note**: Solutions ranked by internal scoring (array order = priority) + +## TodoWrite Structure + +**Initialization**: +```javascript +TodoWrite({ todos: [ + { content: "Phase 1: Context Gathering", status: "in_progress", activeForm: "Gathering context" }, + { content: "Phase 2: Multi-CLI Discussion", status: "pending", activeForm: "Running discussion" }, + { content: "Phase 3: Present Options", status: "pending", activeForm: "Presenting options" }, + { content: "Phase 4: User Decision", status: "pending", activeForm: "Awaiting decision" }, + { content: "Phase 5: Plan Generation", status: "pending", activeForm: "Generating plan" } +]}) +``` + +**During Discussion Rounds**: +```javascript +TodoWrite({ todos: [ + { content: "Phase 1: Context Gathering", status: "completed", activeForm: "Gathering context" }, + { content: "Phase 2: Multi-CLI Discussion", status: "in_progress", activeForm: "Running discussion" }, + { content: " → Round 1: Initial analysis", status: "completed", activeForm: "Analyzing" }, + { content: " → Round 2: Deep verification", status: "in_progress", activeForm: "Verifying" }, + { content: "Phase 3: Present Options", status: "pending", activeForm: "Presenting options" }, + // ... +]}) +``` + +## Error Handling + +| Error | Resolution | +|-------|------------| +| ACE search fails | Fall back to Glob/Grep for file discovery | +| Agent fails | Retry once, then present partial results | +| CLI timeout (in agent) | Agent uses fallback: gemini → codex → claude | +| No convergence | Present best options, flag uncertainty | +| synthesis.json parse error | Request agent retry | +| User cancels | Save session for later resumption | + +## Configuration + +| Flag | Default | Description | +|------|---------|-------------| +| `--max-rounds` | 3 | Maximum discussion rounds | +| `--tools` | gemini,codex | CLI tools for analysis | +| `--mode` | parallel | Execution mode: parallel or serial | +| `--auto-execute` | false | Auto-execute after approval | + +## Best Practices + +1. **Be Specific**: Detailed task descriptions improve ACE context quality +2. **Provide Feedback**: Use clarification rounds to refine requirements +3. **Trust Cross-Verification**: Multi-CLI consensus indicates high confidence +4. **Review Trade-offs**: Consider pros/cons before selecting solution +5. **Check synthesis.json**: Review agent output for detailed analysis +6. **Iterate When Needed**: Don't hesitate to request more analysis + +## Related Commands + +```bash +# Simpler single-round planning +/workflow:lite-plan "task description" + +# Issue-driven discovery +/issue:discover-by-prompt "find issues" + +# View session files +cat .workflow/.multi-cli-plan/{session-id}/plan.json +cat .workflow/.multi-cli-plan/{session-id}/rounds/1/synthesis.json +cat .workflow/.multi-cli-plan/{session-id}/context-package.json + +# Direct execution (if you have plan.json) +/workflow:lite-execute plan.json +``` + +## Next Phase + +Return to orchestrator, then auto-continue to [Phase 2: Lite Execute](02-lite-execute.md) via Skill handoff. diff --git a/.claude/skills/workflow-multi-cli-plan/phases/02-lite-execute.md b/.claude/skills/workflow-multi-cli-plan/phases/02-lite-execute.md new file mode 100644 index 00000000..35202707 --- /dev/null +++ b/.claude/skills/workflow-multi-cli-plan/phases/02-lite-execute.md @@ -0,0 +1,767 @@ +# Phase 2: Lite Execute + +Complete execution engine supporting multiple input modes: in-memory plan, prompt description, or file content. This phase document preserves the full content of the original `workflow:lite-execute` command. + +> **Source**: Converted from `.claude/commands/workflow/lite-execute.md`. Frontmatter moved to SKILL.md. + +# Workflow Lite-Execute Command (/workflow:lite-execute) + +## Overview + +Flexible task execution command supporting three input modes: in-memory plan (from lite-plan), direct prompt description, or file content. Handles execution orchestration, progress tracking, and optional code review. + +**Core capabilities:** +- Multi-mode input (in-memory plan, prompt description, or file path) +- Execution orchestration (Agent or Codex) with full context +- Live progress tracking via TodoWrite at execution call level +- Optional code review with selected tool (Gemini, Agent, or custom) +- Context continuity across multiple executions +- Intelligent format detection (Enhanced Task JSON vs plain text) + +## Usage + +### Command Syntax +```bash +/workflow:lite-execute [FLAGS] + +# Flags +--in-memory Use plan from memory (called by lite-plan) + +# Arguments + Task description string, or path to file (required) +``` + +## Input Modes + +### Mode 1: In-Memory Plan + +**Trigger**: Called by lite-plan after Phase 4 approval with `--in-memory` flag + +**Input Source**: `executionContext` global variable set by lite-plan + +**Content**: Complete execution context (see Data Structures section) + +**Behavior**: +- Skip execution method selection (already set by lite-plan) +- Directly proceed to execution with full context +- All planning artifacts available (exploration, clarifications, plan) + +### Mode 2: Prompt Description + +**Trigger**: User calls with task description string + +**Input**: Simple task description (e.g., "Add unit tests for auth module") + +**Behavior**: +- Store prompt as `originalUserInput` +- Create simple execution plan from prompt +- AskUserQuestion: Select execution method (Agent/Codex/Auto) +- AskUserQuestion: Select code review tool (Skip/Gemini/Agent/Other) +- Proceed to execution with `originalUserInput` included + +**User Interaction**: +```javascript +// Parse --yes flag +const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') + +let userSelection + +if (autoYes) { + // Auto mode: Use defaults + console.log(`[--yes] Auto-confirming execution:`) + console.log(` - Execution method: Auto`) + console.log(` - Code review: Skip`) + + userSelection = { + execution_method: "Auto", + code_review_tool: "Skip" + } +} else { + // Interactive mode: Ask user + userSelection = AskUserQuestion({ + questions: [ + { + question: "Select execution method:", + header: "Execution", + multiSelect: false, + options: [ + { label: "Agent", description: "@code-developer agent" }, + { label: "Codex", description: "codex CLI tool" }, + { label: "Auto", description: "Auto-select based on complexity" } + ] + }, + { + question: "Enable code review after execution?", + header: "Code Review", + multiSelect: false, + options: [ + { label: "Skip", description: "No review" }, + { label: "Gemini Review", description: "Gemini CLI tool" }, + { label: "Codex Review", description: "Git-aware review (prompt OR --uncommitted)" }, + { label: "Agent Review", description: "Current agent review" } + ] + } + ] + }) +} +``` + +### Mode 3: File Content + +**Trigger**: User calls with file path + +**Input**: Path to file containing task description or plan.json + +**Step 1: Read and Detect Format** + +```javascript +fileContent = Read(filePath) + +// Attempt JSON parsing +try { + jsonData = JSON.parse(fileContent) + + // Check if plan.json from lite-plan session (two-layer format: task_ids[]) + if (jsonData.summary && jsonData.approach && jsonData.task_ids) { + planObject = jsonData + originalUserInput = jsonData.summary + isPlanJson = true + + // Load tasks from .task/*.json files + const planDir = filePath.replace(/[/\\][^/\\]+$/, '') // parent directory + planObject._loadedTasks = loadTaskFiles(planDir, jsonData.task_ids) + } else { + // Valid JSON but not plan.json - treat as plain text + originalUserInput = fileContent + isPlanJson = false + } +} catch { + // Not valid JSON - treat as plain text prompt + originalUserInput = fileContent + isPlanJson = false +} +``` + +**Step 2: Create Execution Plan** + +If `isPlanJson === true`: +- Use `planObject` directly +- User selects execution method and code review + +If `isPlanJson === false`: +- Treat file content as prompt (same behavior as Mode 2) +- Create simple execution plan from content + +**Step 3: User Interaction** + +- AskUserQuestion: Select execution method (Agent/Codex/Auto) +- AskUserQuestion: Select code review tool +- Proceed to execution with full context + +## Helper Functions + +```javascript +// Load task files from .task/ directory (two-layer format) +function loadTaskFiles(planDir, taskIds) { + return taskIds.map(id => { + const taskPath = `${planDir}/.task/${id}.json` + return JSON.parse(Read(taskPath)) + }) +} + +// Get tasks array from loaded .task/*.json files +function getTasks(planObject) { + return planObject._loadedTasks || [] +} +``` + +## Execution Process + +``` +Input Parsing: + └─ Decision (mode detection): + ├─ --in-memory flag → Mode 1: Load executionContext → Skip user selection + ├─ Ends with .md/.json/.txt → Mode 3: Read file → Detect format + │ ├─ Valid plan.json → Use planObject → User selects method + review + │ └─ Not plan.json → Treat as prompt → User selects method + review + └─ Other → Mode 2: Prompt description → User selects method + review + +Execution: + ├─ Step 1: Initialize result tracking (previousExecutionResults = []) + ├─ Step 2: Task grouping & batch creation + │ ├─ Extract explicit depends_on (no file/keyword inference) + │ ├─ Group: independent tasks → single parallel batch (maximize utilization) + │ ├─ Group: dependent tasks → sequential phases (respect dependencies) + │ └─ Create TodoWrite list for batches + ├─ Step 3: Launch execution + │ ├─ Phase 1: All independent tasks (⚡ single batch, concurrent) + │ └─ Phase 2+: Dependent tasks by dependency order + ├─ Step 4: Track progress (TodoWrite updates per batch) + └─ Step 5: Code review (if codeReviewTool ≠ "Skip") + +Output: + └─ Execution complete with results in previousExecutionResults[] +``` + +## Detailed Execution Steps + +### Step 1: Initialize Execution Tracking + +**Operations**: +- Initialize result tracking for multi-execution scenarios +- Set up `previousExecutionResults` array for context continuity +- **In-Memory Mode**: Echo execution strategy from lite-plan for transparency + +```javascript +// Initialize result tracking +previousExecutionResults = [] + +// In-Memory Mode: Echo execution strategy (transparency before execution) +if (executionContext) { + console.log(` +📋 Execution Strategy (from lite-plan): + Method: ${executionContext.executionMethod} + Review: ${executionContext.codeReviewTool} + Tasks: ${getTasks(executionContext.planObject).length} + Complexity: ${executionContext.planObject.complexity} +${executionContext.executorAssignments ? ` Assignments: ${JSON.stringify(executionContext.executorAssignments)}` : ''} + `) +} +``` + +### Step 2: Task Grouping & Batch Creation + +**Dependency Analysis & Grouping Algorithm**: +```javascript +// Use explicit depends_on from plan.json (no inference from file/keywords) +function extractDependencies(tasks) { + const taskIdToIndex = {} + tasks.forEach((t, i) => { taskIdToIndex[t.id] = i }) + + return tasks.map((task, i) => { + // Only use explicit depends_on from plan.json + const deps = (task.depends_on || []) + .map(depId => taskIdToIndex[depId]) + .filter(idx => idx !== undefined && idx < i) + return { ...task, taskIndex: i, dependencies: deps } + }) +} + +// Group into batches: maximize parallel execution +function createExecutionCalls(tasks, executionMethod) { + const tasksWithDeps = extractDependencies(tasks) + const processed = new Set() + const calls = [] + + // Phase 1: All independent tasks → single parallel batch (maximize utilization) + const independentTasks = tasksWithDeps.filter(t => t.dependencies.length === 0) + if (independentTasks.length > 0) { + independentTasks.forEach(t => processed.add(t.taskIndex)) + calls.push({ + method: executionMethod, + executionType: "parallel", + groupId: "P1", + taskSummary: independentTasks.map(t => t.title).join(' | '), + tasks: independentTasks + }) + } + + // Phase 2: Dependent tasks → sequential batches (respect dependencies) + let sequentialIndex = 1 + let remaining = tasksWithDeps.filter(t => !processed.has(t.taskIndex)) + + while (remaining.length > 0) { + // Find tasks whose dependencies are all satisfied + const ready = remaining.filter(t => + t.dependencies.every(d => processed.has(d)) + ) + + if (ready.length === 0) { + console.warn('Circular dependency detected, forcing remaining tasks') + ready.push(...remaining) + } + + // Group ready tasks (can run in parallel within this phase) + ready.forEach(t => processed.add(t.taskIndex)) + calls.push({ + method: executionMethod, + executionType: ready.length > 1 ? "parallel" : "sequential", + groupId: ready.length > 1 ? `P${calls.length + 1}` : `S${sequentialIndex++}`, + taskSummary: ready.map(t => t.title).join(ready.length > 1 ? ' | ' : ' → '), + tasks: ready + }) + + remaining = remaining.filter(t => !processed.has(t.taskIndex)) + } + + return calls +} + +executionCalls = createExecutionCalls(getTasks(planObject), executionMethod).map(c => ({ ...c, id: `[${c.groupId}]` })) + +TodoWrite({ + todos: executionCalls.map(c => ({ + content: `${c.executionType === "parallel" ? "⚡" : "→"} ${c.id} (${c.tasks.length} tasks)`, + status: "pending", + activeForm: `Executing ${c.id}` + })) +}) +``` + +### Step 3: Launch Execution + +**Executor Resolution** (任务级 executor 优先于全局设置): +```javascript +// 获取任务的 executor(优先使用 executorAssignments,fallback 到全局 executionMethod) +function getTaskExecutor(task) { + const assignments = executionContext?.executorAssignments || {} + if (assignments[task.id]) { + return assignments[task.id].executor // 'gemini' | 'codex' | 'agent' + } + // Fallback: 全局 executionMethod 映射 + const method = executionContext?.executionMethod || 'Auto' + if (method === 'Agent') return 'agent' + if (method === 'Codex') return 'codex' + // Auto: 根据复杂度 + return planObject.complexity === 'Low' ? 'agent' : 'codex' +} + +// 按 executor 分组任务 +function groupTasksByExecutor(tasks) { + const groups = { gemini: [], codex: [], agent: [] } + tasks.forEach(task => { + const executor = getTaskExecutor(task) + groups[executor].push(task) + }) + return groups +} +``` + +**Execution Flow**: Parallel batches concurrently → Sequential batches in order +```javascript +const parallel = executionCalls.filter(c => c.executionType === "parallel") +const sequential = executionCalls.filter(c => c.executionType === "sequential") + +// Phase 1: Launch all parallel batches (single message with multiple tool calls) +if (parallel.length > 0) { + TodoWrite({ todos: executionCalls.map(c => ({ status: c.executionType === "parallel" ? "in_progress" : "pending" })) }) + parallelResults = await Promise.all(parallel.map(c => executeBatch(c))) + previousExecutionResults.push(...parallelResults) + TodoWrite({ todos: executionCalls.map(c => ({ status: parallel.includes(c) ? "completed" : "pending" })) }) +} + +// Phase 2: Execute sequential batches one by one +for (const call of sequential) { + TodoWrite({ todos: executionCalls.map(c => ({ status: c === call ? "in_progress" : "..." })) }) + result = await executeBatch(call) + previousExecutionResults.push(result) + TodoWrite({ todos: executionCalls.map(c => ({ status: "completed" or "pending" })) }) +} +``` + +### Unified Task Prompt Builder + +**Task Formatting Principle**: Each task is a self-contained checklist. The executor only needs to know what THIS task requires. Same template for Agent and CLI. + +```javascript +function buildExecutionPrompt(batch) { + // Task template (6 parts: Files → Why → How → Reference → Risks → Done) + const formatTask = (t) => ` +## ${t.title} + +**Scope**: \`${t.scope}\` | **Action**: ${t.action} + +### Files +${(t.files || []).map(f => `- **${f.path}** → \`${f.target || ''}\`: ${f.change || (f.changes || []).join(', ') || ''}`).join('\n')} + +${t.rationale ? ` +### Why this approach (Medium/High) +${t.rationale.chosen_approach} +${t.rationale.decision_factors?.length > 0 ? `\nKey factors: ${t.rationale.decision_factors.join(', ')}` : ''} +${t.rationale.tradeoffs ? `\nTradeoffs: ${t.rationale.tradeoffs}` : ''} +` : ''} + +### How to do it +${t.description} + +${t.implementation.map(step => `- ${step}`).join('\n')} + +${t.code_skeleton ? ` +### Code skeleton (High) +${t.code_skeleton.interfaces?.length > 0 ? `**Interfaces**: ${t.code_skeleton.interfaces.map(i => `\`${i.name}\` - ${i.purpose}`).join(', ')}` : ''} +${t.code_skeleton.key_functions?.length > 0 ? `\n**Functions**: ${t.code_skeleton.key_functions.map(f => `\`${f.signature}\` - ${f.purpose}`).join(', ')}` : ''} +${t.code_skeleton.classes?.length > 0 ? `\n**Classes**: ${t.code_skeleton.classes.map(c => `\`${c.name}\` - ${c.purpose}`).join(', ')}` : ''} +` : ''} + +### Reference +- Pattern: ${t.reference?.pattern || 'N/A'} +- Files: ${t.reference?.files?.join(', ') || 'N/A'} +${t.reference?.examples ? `- Notes: ${t.reference.examples}` : ''} + +${t.risks?.length > 0 ? ` +### Risk mitigations (High) +${t.risks.map(r => `- ${r.description} → **${r.mitigation}**`).join('\n')} +` : ''} + +### Done when +${(t.convergence?.criteria || []).map(c => `- [ ] ${c}`).join('\n')} +${(t.test?.success_metrics || []).length > 0 ? `\n**Success metrics**: ${t.test.success_metrics.join(', ')}` : ''}` + + // Build prompt + const sections = [] + + if (originalUserInput) sections.push(`## Goal\n${originalUserInput}`) + + sections.push(`## Tasks\n${batch.tasks.map(formatTask).join('\n\n---\n')}`) + + // Context (reference only) + const context = [] + if (previousExecutionResults.length > 0) { + context.push(`### Previous Work\n${previousExecutionResults.map(r => `- ${r.tasksSummary}: ${r.status}`).join('\n')}`) + } + if (clarificationContext) { + context.push(`### Clarifications\n${Object.entries(clarificationContext).map(([q, a]) => `- ${q}: ${a}`).join('\n')}`) + } + if (executionContext?.planObject?.data_flow?.diagram) { + context.push(`### Data Flow\n${executionContext.planObject.data_flow.diagram}`) + } + if (executionContext?.session?.artifacts?.plan) { + context.push(`### Artifacts\nPlan: ${executionContext.session.artifacts.plan}`) + } + // Project guidelines (user-defined constraints from /workflow:session:solidify) + context.push(`### Project Guidelines\n@.workflow/project-guidelines.json`) + if (context.length > 0) sections.push(`## Context\n${context.join('\n\n')}`) + + sections.push(`Complete each task according to its "Done when" checklist.`) + + return sections.join('\n\n') +} +``` + +**Option A: Agent Execution** + +When to use: +- `getTaskExecutor(task) === "agent"` +- 或 `executionMethod = "Agent"` (全局 fallback) +- 或 `executionMethod = "Auto" AND complexity = "Low"` (全局 fallback) + +```javascript +Task( + subagent_type="code-developer", + run_in_background=false, + description=batch.taskSummary, + prompt=buildExecutionPrompt(batch) +) +``` + +**Result Collection**: After completion, collect result following `executionResult` structure (see Data Structures section) + +**Option B: CLI Execution (Codex)** + +When to use: +- `getTaskExecutor(task) === "codex"` +- 或 `executionMethod = "Codex"` (全局 fallback) +- 或 `executionMethod = "Auto" AND complexity = "Medium/High"` (全局 fallback) + +```bash +ccw cli -p "${buildExecutionPrompt(batch)}" --tool codex --mode write +``` + +**Execution with fixed IDs** (predictable ID pattern): +```javascript +// Launch CLI in background, wait for task hook callback +// Generate fixed execution ID: ${sessionId}-${groupId} +const sessionId = executionContext?.session?.id || 'standalone' +const fixedExecutionId = `${sessionId}-${batch.groupId}` // e.g., "implement-auth-2025-12-13-P1" + +// Check if resuming from previous failed execution +const previousCliId = batch.resumeFromCliId || null + +// Build command with fixed ID (and optional resume for continuation) +const cli_command = previousCliId + ? `ccw cli -p "${buildExecutionPrompt(batch)}" --tool codex --mode write --id ${fixedExecutionId} --resume ${previousCliId}` + : `ccw cli -p "${buildExecutionPrompt(batch)}" --tool codex --mode write --id ${fixedExecutionId}` + +// Execute in background, stop output and wait for task hook callback +Bash( + command=cli_command, + run_in_background=true +) +// STOP HERE - CLI executes in background, task hook will notify on completion +``` + +**Resume on Failure** (with fixed ID): +```javascript +// If execution failed or timed out, offer resume option +if (bash_result.status === 'failed' || bash_result.status === 'timeout') { + console.log(` +⚠️ Execution incomplete. Resume available: + Fixed ID: ${fixedExecutionId} + Lookup: ccw cli detail ${fixedExecutionId} + Resume: ccw cli -p "Continue tasks" --resume ${fixedExecutionId} --tool codex --mode write --id ${fixedExecutionId}-retry +`) + + // Store for potential retry in same session + batch.resumeFromCliId = fixedExecutionId +} +``` + +**Result Collection**: After completion, analyze output and collect result following `executionResult` structure (include `cliExecutionId` for resume capability) + +**Option C: CLI Execution (Gemini)** + +When to use: `getTaskExecutor(task) === "gemini"` (分析类任务) + +```bash +# 使用统一的 buildExecutionPrompt,切换 tool 和 mode +ccw cli -p "${buildExecutionPrompt(batch)}" --tool gemini --mode analysis --id ${sessionId}-${batch.groupId} +``` + +### Step 4: Progress Tracking + +Progress tracked at batch level (not individual task level). Icons: ⚡ (parallel, concurrent), → (sequential, one-by-one) + +### Step 5: Code Review (Optional) + +**Skip Condition**: Only run if `codeReviewTool ≠ "Skip"` + +**Review Focus**: Verify implementation against plan convergence criteria and test requirements +- Read plan.json + .task/*.json for task convergence criteria and test checklist +- Check each convergence criterion is fulfilled +- Verify success metrics from test field (Medium/High complexity) +- Run unit/integration tests specified in test field +- Validate code quality and identify issues +- Ensure alignment with planned approach and risk mitigations + +**Operations**: +- Agent Review: Current agent performs direct review +- Gemini Review: Execute gemini CLI with review prompt +- Codex Review: Two options - (A) with prompt for complex reviews, (B) `--uncommitted` flag only for quick reviews +- Custom tool: Execute specified CLI tool (qwen, etc.) + +**Unified Review Template** (All tools use same standard): + +**Review Criteria**: +- **Convergence Criteria**: Verify each criterion from task convergence.criteria +- **Test Checklist** (Medium/High): Check unit, integration, success_metrics from task test +- **Code Quality**: Analyze quality, identify issues, suggest improvements +- **Plan Alignment**: Validate implementation matches planned approach and risk mitigations + +**Shared Prompt Template** (used by all CLI tools): +``` +PURPOSE: Code review for implemented changes against plan convergence criteria and test requirements +TASK: • Verify plan convergence criteria fulfillment • Check test requirements (unit, integration, success_metrics) • Analyze code quality • Identify issues • Suggest improvements • Validate plan adherence and risk mitigations +MODE: analysis +CONTEXT: @**/* @{plan.json} @{.task/*.json} [@{exploration.json}] | Memory: Review lite-execute changes against plan requirements including test checklist +EXPECTED: Quality assessment with: + - Convergence criteria verification (all tasks from .task/*.json) + - Test checklist validation (Medium/High: unit, integration, success_metrics) + - Issue identification + - Recommendations + Explicitly check each convergence criterion and test item from .task/*.json files. +CONSTRAINTS: Focus on plan convergence criteria, test requirements, and plan adherence | analysis=READ-ONLY +``` + +**Tool-Specific Execution** (Apply shared prompt template above): + +```bash +# Method 1: Agent Review (current agent) +# - Read plan.json: ${executionContext.session.artifacts.plan} +# - Apply unified review criteria (see Shared Prompt Template) +# - Report findings directly + +# Method 2: Gemini Review (recommended) +ccw cli -p "[Shared Prompt Template with artifacts]" --tool gemini --mode analysis +# CONTEXT includes: @**/* @${plan.json} [@${exploration.json}] + +# Method 3: Qwen Review (alternative) +ccw cli -p "[Shared Prompt Template with artifacts]" --tool qwen --mode analysis +# Same prompt as Gemini, different execution engine + +# Method 4: Codex Review (git-aware) - Two mutually exclusive options: + +# Option A: With custom prompt (reviews uncommitted by default) +ccw cli -p "[Shared Prompt Template with artifacts]" --tool codex --mode review +# Use for complex reviews with specific focus areas + +# Option B: Target flag only (no prompt allowed) +ccw cli --tool codex --mode review --uncommitted +# Quick review of uncommitted changes without custom instructions + +# ⚠️ IMPORTANT: -p prompt and target flags (--uncommitted/--base/--commit) are MUTUALLY EXCLUSIVE +``` + +**Multi-Round Review with Fixed IDs**: +```javascript +// Generate fixed review ID +const reviewId = `${sessionId}-review` + +// First review pass with fixed ID +const reviewResult = Bash(`ccw cli -p "[Review prompt]" --tool gemini --mode analysis --id ${reviewId}`) + +// If issues found, continue review dialog with fixed ID chain +if (hasUnresolvedIssues(reviewResult)) { + // Resume with follow-up questions + Bash(`ccw cli -p "Clarify the security concerns you mentioned" --resume ${reviewId} --tool gemini --mode analysis --id ${reviewId}-followup`) +} +``` + +**Implementation Note**: Replace `[Shared Prompt Template with artifacts]` placeholder with actual template content, substituting: +- `@{plan.json}` → `@${executionContext.session.artifacts.plan}` +- `[@{exploration.json}]` → exploration files from artifacts (if exists) + +### Step 6: Update Development Index + +**Trigger**: After all executions complete (regardless of code review) + +**Skip Condition**: Skip if `.workflow/project-tech.json` does not exist + +**Operations**: +```javascript +const projectJsonPath = '.workflow/project-tech.json' +if (!fileExists(projectJsonPath)) return // Silent skip + +const projectJson = JSON.parse(Read(projectJsonPath)) + +// Initialize if needed +if (!projectJson.development_index) { + projectJson.development_index = { feature: [], enhancement: [], bugfix: [], refactor: [], docs: [] } +} + +// Detect category from keywords +function detectCategory(text) { + text = text.toLowerCase() + if (/\b(fix|bug|error|issue|crash)\b/.test(text)) return 'bugfix' + if (/\b(refactor|cleanup|reorganize)\b/.test(text)) return 'refactor' + if (/\b(doc|readme|comment)\b/.test(text)) return 'docs' + if (/\b(add|new|create|implement)\b/.test(text)) return 'feature' + return 'enhancement' +} + +// Detect sub_feature from task file paths +function detectSubFeature(tasks) { + const dirs = tasks.map(t => t.file?.split('/').slice(-2, -1)[0]).filter(Boolean) + const counts = dirs.reduce((a, d) => { a[d] = (a[d] || 0) + 1; return a }, {}) + return Object.entries(counts).sort((a, b) => b[1] - a[1])[0]?.[0] || 'general' +} + +const category = detectCategory(`${planObject.summary} ${planObject.approach}`) +const entry = { + title: planObject.summary.slice(0, 60), + sub_feature: detectSubFeature(getTasks(planObject)), + date: new Date().toISOString().split('T')[0], + description: planObject.approach.slice(0, 100), + status: previousExecutionResults.every(r => r.status === 'completed') ? 'completed' : 'partial', + session_id: executionContext?.session?.id || null +} + +projectJson.development_index[category].push(entry) +projectJson.statistics.last_updated = new Date().toISOString() +Write(projectJsonPath, JSON.stringify(projectJson, null, 2)) + +console.log(`✓ Development index: [${category}] ${entry.title}`) +``` + +## Best Practices + +**Input Modes**: In-memory (lite-plan), prompt (standalone), file (JSON/text) +**Task Grouping**: Based on explicit depends_on only; independent tasks run in single parallel batch +**Execution**: All independent tasks launch concurrently via single Claude message with multiple tool calls + +## Error Handling + +| Error | Cause | Resolution | +|-------|-------|------------| +| Missing executionContext | --in-memory without context | Error: "No execution context found. Only available when called by lite-plan." | +| File not found | File path doesn't exist | Error: "File not found: {path}. Check file path." | +| Empty file | File exists but no content | Error: "File is empty: {path}. Provide task description." | +| Invalid Enhanced Task JSON | JSON missing required fields | Warning: "Missing required fields. Treating as plain text." | +| Malformed JSON | JSON parsing fails | Treat as plain text (expected for non-JSON files) | +| Execution failure | Agent/Codex crashes | Display error, use fixed ID `${sessionId}-${groupId}` for resume: `ccw cli -p "Continue" --resume --id -retry` | +| Execution timeout | CLI exceeded timeout | Use fixed ID for resume with extended timeout | +| Codex unavailable | Codex not installed | Show installation instructions, offer Agent execution | +| Fixed ID not found | Custom ID lookup failed | Check `ccw cli history`, verify date directories | + +## Data Structures + +### executionContext (Input - Mode 1) + +Passed from lite-plan via global variable: + +```javascript +{ + planObject: { + summary: string, + approach: string, + task_ids: string[], // Task IDs referencing .task/*.json files + task_count: number, // Number of tasks + _loadedTasks: [...], // Populated at runtime from .task/*.json files + estimated_time: string, + recommended_execution: string, + complexity: string + }, + // Task file paths (populated for two-layer format) + taskFiles: [{id: string, path: string}] | null, + explorationsContext: {...} | null, // Multi-angle explorations + explorationAngles: string[], // List of exploration angles + explorationManifest: {...} | null, // Exploration manifest + clarificationContext: {...} | null, + executionMethod: "Agent" | "Codex" | "Auto", // 全局默认 + codeReviewTool: "Skip" | "Gemini Review" | "Agent Review" | string, + originalUserInput: string, + + // 任务级 executor 分配(优先于 executionMethod) + executorAssignments: { + [taskId]: { executor: "gemini" | "codex" | "agent", reason: string } + }, + + // Session artifacts location (saved by lite-plan) + session: { + id: string, // Session identifier: {taskSlug}-{shortTimestamp} + folder: string, // Session folder path: .workflow/.lite-plan/{session-id} + artifacts: { + explorations: [{angle, path}], // exploration-{angle}.json paths + explorations_manifest: string, // explorations-manifest.json path + plan: string // plan.json path (always present) + } + } +} +``` + +**Artifact Usage**: +- Artifact files contain detailed planning context +- Pass artifact paths to CLI tools and agents for enhanced context +- See execution options below for usage examples + +### executionResult (Output) + +Collected after each execution call completes: + +```javascript +{ + executionId: string, // e.g., "[Agent-1]", "[Codex-1]" + status: "completed" | "partial" | "failed", + tasksSummary: string, // Brief description of tasks handled + completionSummary: string, // What was completed + keyOutputs: string, // Files created/modified, key changes + notes: string, // Important context for next execution + fixedCliId: string | null // Fixed CLI execution ID (e.g., "implement-auth-2025-12-13-P1") +} +``` + +Appended to `previousExecutionResults` array for context continuity in multi-execution scenarios. + +## Post-Completion Expansion + +完成后询问用户是否扩展为issue(test/enhance/refactor/doc),选中项调用 `/issue:new "{summary} - {dimension}"` + +**Fixed ID Pattern**: `${sessionId}-${groupId}` enables predictable lookup without auto-generated timestamps. + +**Resume Usage**: If `status` is "partial" or "failed", use `fixedCliId` to resume: +```bash +# Lookup previous execution +ccw cli detail ${fixedCliId} + +# Resume with new fixed ID for retry +ccw cli -p "Continue from where we left off" --resume ${fixedCliId} --tool codex --mode write --id ${fixedCliId}-retry +```