diff --git a/.claude/commands/issue/plan.md b/.claude/commands/issue/plan.md index df8843e4..fbfa2c51 100644 --- a/.claude/commands/issue/plan.md +++ b/.claude/commands/issue/plan.md @@ -59,7 +59,7 @@ Phase 1: Issue Loading ├─ Parse input (single, comma-separated, or --all-pending) ├─ Fetch issue metadata (ID, title, tags) ├─ Validate issues exist (create if needed) - └─ Group by similarity (shared tags or title keywords, max 3 per batch) + └─ Create batches by size (max 3 per batch by default) Phase 2: Unified Explore + Plan (issue-plan-agent) ├─ Launch issue-plan-agent per batch @@ -119,46 +119,17 @@ if (useAllPending) { } // Note: Agent fetches full issue content via `ccw issue status --json` -// Semantic grouping via Gemini CLI (max 4 issues per group) -async function groupBySimilarityGemini(issues) { - const issueSummaries = issues.map(i => ({ - id: i.id, title: i.title, tags: i.tags - })); - - const prompt = ` -PURPOSE: Group similar issues by semantic similarity for batch processing; maximize within-group coherence; max 4 issues per group -TASK: • Analyze issue titles/tags semantically • Identify functional/architectural clusters • Assign each issue to one group -MODE: analysis -CONTEXT: Issue metadata only -EXPECTED: JSON with groups array, each containing max 4 issue_ids, theme, rationale -CONSTRAINTS: Each issue in exactly one group | Max 4 issues per group | Balance group sizes - -INPUT: -${JSON.stringify(issueSummaries, null, 2)} - -OUTPUT FORMAT: -{"groups":[{"group_id":1,"theme":"...","issue_ids":["..."],"rationale":"..."}],"ungrouped":[]} -`; - - const taskId = Bash({ - command: `ccw cli -p "${prompt}" --tool gemini --mode analysis`, - run_in_background: true, timeout: 600000 - }); - const output = TaskOutput({ task_id: taskId, block: true }); - - // Extract JSON from potential markdown code blocks - function extractJsonFromMarkdown(text) { - const jsonMatch = text.match(/```json\s*\n([\s\S]*?)\n```/) || - text.match(/```\s*\n([\s\S]*?)\n```/); - return jsonMatch ? jsonMatch[1] : text; +// Simple size-based batching (max batchSize issues per group) +function createBatches(issues, batchSize) { + const batches = []; + for (let i = 0; i < issues.length; i += batchSize) { + batches.push(issues.slice(i, i + batchSize)); } - - const result = JSON.parse(extractJsonFromMarkdown(output)); - return result.groups.map(g => g.issue_ids.map(id => issues.find(i => i.id === id))); + return batches; } -const batches = await groupBySimilarityGemini(issues); -console.log(`Processing ${issues.length} issues in ${batches.length} batch(es) (max 4 issues/agent)`); +const batches = createBatches(issues, batchSize); +console.log(`Processing ${issues.length} issues in ${batches.length} batch(es) (max ${batchSize} issues/agent)`); TodoWrite({ todos: batches.map((_, i) => ({ @@ -207,7 +178,9 @@ ${issueList} - Add explicit verification steps to prevent same failure mode 6. **If github_url exists**: Add final task to comment on GitHub issue 7. Write solution to: .workflow/issues/solutions/{issue-id}.jsonl -8. Single solution → auto-bind; Multiple → return for selection +8. **CRITICAL - Binding Decision**: + - Single solution → **MUST execute**: ccw issue bind + - Multiple solutions → Return pending_selection only (no bind) ### Failure-Aware Planning Rules - **Extract failure patterns**: Parse issue.feedback where type='failure' and stage='execute' @@ -265,35 +238,55 @@ for (let i = 0; i < agentTasks.length; i += MAX_PARALLEL) { } agentResults.push(summary); // Store for Phase 3 conflict aggregation + // Verify binding for bound issues (agent should have executed bind) for (const item of summary.bound || []) { - console.log(`✓ ${item.issue_id}: ${item.solution_id} (${item.task_count} tasks)`); + const status = JSON.parse(Bash(`ccw issue status ${item.issue_id} --json`).trim()); + if (status.bound_solution_id === item.solution_id) { + console.log(`✓ ${item.issue_id}: ${item.solution_id} (${item.task_count} tasks)`); + } else { + // Fallback: agent failed to bind, execute here + Bash(`ccw issue bind ${item.issue_id} ${item.solution_id}`); + console.log(`✓ ${item.issue_id}: ${item.solution_id} (${item.task_count} tasks) [recovered]`); + } } - // Collect and notify pending selections + // Collect pending selections for Phase 3 for (const pending of summary.pending_selection || []) { - console.log(`⏳ ${pending.issue_id}: ${pending.solutions.length} solutions → awaiting selection`); pendingSelections.push(pending); } - if (summary.conflicts?.length > 0) { - console.log(`⚠ Conflicts: ${summary.conflicts.length} detected (will resolve in Phase 3)`); - } updateTodo(`Plan batch ${batchIndex + 1}`, 'completed'); } } ``` -### Phase 3: Conflict Resolution & Solution Selection +### Phase 3: Solution Selection (if pending) -**Conflict Handling:** -- Collect `conflicts` from all agent results -- Low/Medium severity → auto-resolve with `recommended_resolution` -- High severity → use `AskUserQuestion` to let user choose resolution +```javascript +// Handle multi-solution issues +for (const pending of pendingSelections) { + if (pending.solutions.length === 0) continue; -**Multi-Solution Selection:** -- If `pending_selection` contains issues with multiple solutions: - - Use `AskUserQuestion` to present options (solution ID + task count + description) - - Extract selected solution ID from user response - - Verify solution file exists, recover from payload if missing - - Bind selected solution via `ccw issue bind ` + const options = pending.solutions.slice(0, 4).map(sol => ({ + label: `${sol.id} (${sol.task_count} tasks)`, + description: sol.description || sol.approach || 'No description' + })); + + const answer = AskUserQuestion({ + questions: [{ + question: `Issue ${pending.issue_id}: which solution to bind?`, + header: pending.issue_id, + options: options, + multiSelect: false + }] + }); + + const selected = answer[Object.keys(answer)[0]]; + if (!selected || selected === 'Other') continue; + + const solId = selected.split(' ')[0]; + Bash(`ccw issue bind ${pending.issue_id} ${solId}`); + console.log(`✓ ${pending.issue_id}: ${solId} bound`); +} +``` ### Phase 4: Summary diff --git a/.claude/commands/issue/queue.md b/.claude/commands/issue/queue.md index 4474dff8..0df575f2 100644 --- a/.claude/commands/issue/queue.md +++ b/.claude/commands/issue/queue.md @@ -28,12 +28,13 @@ Queue formation command using **issue-queue-agent** that analyzes all bound solu | Operation | Correct | Incorrect | |-----------|---------|-----------| | List issues (brief) | `ccw issue list --status planned --brief` | `Read('issues.jsonl')` | +| **Batch solutions (NEW)** | `ccw issue solutions --status planned --brief` | Loop `ccw issue solution ` | | List queue (brief) | `ccw issue queue --brief` | `Read('queues/*.json')` | | Read issue details | `ccw issue status --json` | `Read('issues.jsonl')` | | Get next item | `ccw issue next --json` | `Read('queues/*.json')` | | Update status | `ccw issue update --status ...` | Direct file edit | | Sync from queue | `ccw issue update --from-queue` | Direct file edit | -| **Read solution (brief)** | `ccw issue solution --brief` | `Read('solutions/*.jsonl')` | +| Read solution (single) | `ccw issue solution --brief` | `Read('solutions/*.jsonl')` | **Output Options**: - `--brief`: JSON with minimal fields (id, status, counts) @@ -131,24 +132,23 @@ Phase 7: Active Queue Check & Decision (REQUIRED) ### Phase 1: Solution Loading & Distribution **Data Loading:** -- Use `ccw issue list --status planned --brief` to get planned issues with `bound_solution_id` -- If no planned issues found → display message, suggest `/issue:plan` - -**Solution Brief Loading** (for each planned issue): -```bash -ccw issue solution --brief -# Returns: [{ solution_id, is_bound, task_count, files_touched[] }] -``` +- Use `ccw issue solutions --status planned --brief` to get all planned issues with solutions in **one call** +- Returns: Array of `{ issue_id, solution_id, is_bound, task_count, files_touched[], priority }` +- If no bound solutions found → display message, suggest `/issue:plan` **Build Solution Objects:** -```json -{ - "issue_id": "ISS-xxx", - "solution_id": "SOL-ISS-xxx-1", - "task_count": 3, - "files_touched": ["src/auth.ts", "src/utils.ts"], - "priority": "medium" +```javascript +// Single CLI call replaces N individual queries +const result = Bash(`ccw issue solutions --status planned --brief`).trim(); +const solutions = result ? JSON.parse(result) : []; + +if (solutions.length === 0) { + console.log('No bound solutions found. Run /issue:plan first.'); + return; } + +// solutions already in correct format: +// { issue_id, solution_id, is_bound, task_count, files_touched[], priority } ``` **Multi-Queue Distribution** (if `--queues > 1`): diff --git a/.claude/commands/workflow/develop-with-file.md b/.claude/commands/workflow/develop-with-file.md new file mode 100644 index 00000000..80a091b4 --- /dev/null +++ b/.claude/commands/workflow/develop-with-file.md @@ -0,0 +1,1040 @@ +--- +name: develop-with-file +description: Multi-agent development workflow with documented progress, Gemini-guided planning, and incremental iteration support +argument-hint: "\"feature description or task file.md\"" +allowed-tools: TodoWrite(*), Task(*), AskUserQuestion(*), Read(*), Grep(*), Glob(*), Bash(*), Edit(*), Write(*) +--- + +# Workflow Develop-With-File Command (/workflow:develop-with-file) + +## Overview + +Production-grade development workflow with **2-document state tracking**. Combines multi-agent parallel exploration, Gemini-assisted planning/verification, and incremental iteration in a single coherent workflow. + +**Core workflow**: Explore → Plan → Execute → Verify → Iterate + +**Key features**: +- **progress.md**: Single source of truth for exploration, planning, execution timeline +- **plan.json**: Current execution plan (derived from progress.md) +- **Multi-agent exploration**: Parallel cli-explore-agents from multiple angles +- **Multi-CLI execution**: Support gemini/codex/agent per task +- **Gemini-guided planning**: Intelligent task decomposition and validation +- **Gemini verification**: Post-execution review and correction +- **Incremental iteration**: Resume from any phase, add new tasks dynamically + +## Usage + +```bash +/workflow:develop-with-file [FLAGS] + +# Flags +-e, --explore Force exploration phase +--resume Resume existing session + +# Arguments + Feature description or path to .md file (required) +``` + +## Execution Process + +``` +Session Detection: + ├─ Check if session exists (--resume or auto-detect) + ├─ EXISTS → Continue mode (read progress.md for current phase) + └─ NOT_FOUND → Explore mode + +Explore Mode (Multi-Agent): + ├─ Assess task complexity (Low/Medium/High) + ├─ Launch 1-4 parallel cli-explore-agents (angle-based) + ├─ Aggregate exploration results + ├─ Document in progress.md → Exploration section + └─ Transition → Plan mode + +Plan Mode (Gemini-Guided): + ├─ Read progress.md exploration findings + ├─ Invoke Gemini for task decomposition + ├─ Generate plan.json (2-7 tasks with dependencies) + ├─ Assign executor per task (gemini/codex/agent) + ├─ Document in progress.md → Planning section + ├─ User confirmation (Allow/Modify/Cancel) + └─ Transition → Execute mode + +Execute Mode (Multi-Agent/CLI): + ├─ For each task in plan.json: + │ ├─ Check dependencies (wait if needed) + │ ├─ Execute via assigned executor (agent/gemini/codex) + │ ├─ Document progress in progress.md → Execution section + │ └─ Handle failures (retry/skip/abort) + ├─ Aggregate execution results + └─ Transition → Verify mode + +Verify Mode (Gemini-Assisted): + ├─ Invoke Gemini CLI for code review + ├─ Analyze: correctness, style, potential issues + ├─ Document in progress.md → Verification section + ├─ Decision: + │ ├─ All passed → Complete + │ ├─ Minor issues → Document corrections, iterate + │ └─ Major issues → Rollback, re-plan + └─ Transition → Iterate or Complete + +Iterate Mode (Incremental): + ├─ User provides new requirements or fixes + ├─ Read progress.md for current state + ├─ Gemini analyzes delta (what changed?) + ├─ Generate incremental tasks, append to plan.json + ├─ Update progress.md → New iteration section + └─ Transition → Execute mode (incremental tasks only) +``` + +## Implementation + +### Session Setup & Mode Detection + +```javascript +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) + +const sessionId = flags.resume || `DEV-${taskSlug}-${dateStr}` +const sessionFolder = `.workflow/.develop/${sessionId}` +const progressPath = `${sessionFolder}/progress.md` +const planPath = `${sessionFolder}/plan.json` + +// Auto-detect mode +const sessionExists = fs.existsSync(sessionFolder) +const hasProgress = sessionExists && fs.existsSync(progressPath) +const hasPlan = sessionExists && fs.existsSync(planPath) + +let mode = 'explore' +if (hasProgress) { + const progress = Read(progressPath) + // Parse progress.md to determine current phase + if (progress.includes('## Verification Results')) mode = 'iterate' + else if (progress.includes('## Execution Timeline')) mode = 'verify' + else if (progress.includes('## Planning Results')) mode = 'execute' + else if (progress.includes('## Exploration Results')) mode = 'plan' +} + +if (!sessionExists) { + bash(`mkdir -p ${sessionFolder}`) +} + +console.log(` +## Session Info +- Session ID: ${sessionId} +- Mode: ${mode} +- Folder: ${sessionFolder} +`) +``` + +--- + +### Explore Mode (Multi-Agent Parallel) + +**Step 1.1: Complexity Assessment** + +```javascript +// Analyze task complexity based on: +// - Scope: How many systems/modules 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' (1 angle) | 'Medium' (2-3 angles) | 'High' (4 angles) + +const ANGLE_PRESETS = { + architecture: ['architecture', 'dependencies', 'modularity', 'integration-points'], + feature: ['patterns', 'integration-points', 'testing', 'dependencies'], + bugfix: ['error-handling', 'dataflow', 'state-management', 'edge-cases'], + refactor: ['code-quality', 'patterns', 'dependencies', 'testing'] +} + +function selectAngles(taskDescription, complexity) { + const text = taskDescription.toLowerCase() + let preset = 'feature' // default + + if (/refactor|architect|restructure/.test(text)) preset = 'architecture' + else if (/fix|bug|error|issue/.test(text)) preset = 'bugfix' + else if (/clean|improve|simplify/.test(text)) preset = 'refactor' + + const count = complexity === 'High' ? 4 : (complexity === 'Medium' ? 3 : 1) + return ANGLE_PRESETS[preset].slice(0, count) +} + +const selectedAngles = selectAngles(task_description, complexity) +``` + +**Step 1.2: Launch Parallel Explorations** + +```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 development planning context. + +## Assigned Context +- **Exploration Angle**: ${angle} +- **Task Description**: ${task_description} +- **Output File**: ${sessionFolder}/exploration-${angle}.json + +## MANDATORY FIRST STEPS +1. cat ~/.claude/workflows/cli-templates/schemas/explore-json-schema.json (schema) +2. ccw tool exec get_modules_by_depth '{}' (project structure) +3. Read .workflow/project-tech.json (tech stack) +4. Read .workflow/project-guidelines.json (constraints) + +## Exploration Strategy (${angle} focus) + +**Structural Scan** (Bash): +- get_modules_by_depth.sh → modules related to ${angle} +- rg -l "{keywords}" --type ts → locate relevant files +- Analyze imports/dependencies from ${angle} perspective + +**Semantic Analysis** (Gemini CLI): +- ccw cli -p "PURPOSE: Analyze ${angle} aspect for: ${task_description} + TASK: • Identify ${angle} patterns • Locate integration points • List constraints + MODE: analysis + CONTEXT: @**/* | Task: ${task_description} + EXPECTED: ${angle} findings with file:line references + CONSTRAINTS: Focus on ${angle}" --tool gemini --mode analysis + +**Output**: ${sessionFolder}/exploration-${angle}.json (follow schema) + +## Required Fields +- project_structure: ${angle}-relevant modules +- relevant_files: [{path, relevance (0-1), rationale}] +- patterns: ${angle} patterns with code examples +- integration_points: Where to integrate (file:line) +- constraints: ${angle}-specific limitations +- clarification_needs: [{question, context, options, recommended}] +- _metadata.exploration_angle: "${angle}" + +## Success Criteria +- Schema validated +- ≥3 relevant files with rationale +- Integration points with file:line +- Actionable patterns (code examples) +- JSON output matches schema +` + ) +) + +// Execute all explorations +``` + +**Step 1.3: Aggregate Exploration Results** + +```javascript +// Auto-discover exploration files +const explorationFiles = bash(`find ${sessionFolder} -name "exploration-*.json" -type f`) + .split('\n') + .filter(f => f.trim()) + +const explorations = explorationFiles.map(file => { + const data = JSON.parse(Read(file)) + return { + angle: data._metadata.exploration_angle, + data: data + } +}) + +// Aggregate clarification needs +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 +const dedupedClarifications = intelligentMerge(allClarifications) + +// Multi-round clarification (max 4 questions per round) +if (dedupedClarifications.length > 0) { + const BATCH_SIZE = 4 + for (let i = 0; i < dedupedClarifications.length; i += BATCH_SIZE) { + const batch = dedupedClarifications.slice(i, i + BATCH_SIZE) + AskUserQuestion({ + questions: batch.map(need => ({ + question: `[${need.source_angle}] ${need.question}`, + header: need.source_angle.substring(0, 12), + multiSelect: false, + options: need.options.map((opt, idx) => ({ + label: need.recommended === idx ? `${opt} ★` : opt, + description: need.recommended === idx ? "Recommended" : `Use ${opt}` + })) + })) + }) + } +} +``` + +**Step 1.4: Document in progress.md** + +Create or update `progress.md`: + +```markdown +# Development Progress + +**Session ID**: ${sessionId} +**Task Description**: ${task_description} +**Started**: ${getUtc8ISOString()} +**Complexity**: ${complexity} + +--- + +## Exploration Results + +### Exploration Summary (${getUtc8ISOString()}) + +**Angles Explored**: ${selectedAngles.join(', ')} +**Exploration Count**: ${explorations.length} + +${explorations.map(exp => ` +#### ${exp.angle.toUpperCase()} + +**Relevant Files** (top 5): +${exp.data.relevant_files.slice(0, 5).map(f => + `- ${f.path} (${(f.relevance * 100).toFixed(0)}%) - ${f.rationale}` +).join('\n')} + +**Integration Points**: +${exp.data.integration_points.map(p => `- ${p}`).join('\n')} + +**Patterns**: +${exp.data.patterns.map(p => `- ${p}`).join('\n')} + +**Constraints**: +${exp.data.constraints.map(c => `- ${c}`).join('\n')} +`).join('\n')} + +### Clarifications Collected + +${dedupedClarifications.length > 0 ? dedupedClarifications.map((c, i) => ` +${i+1}. **[${c.source_angle}]** ${c.question} + - Answer: ${c.user_answer || 'Pending'} +`).join('\n') : 'No clarifications needed'} + +--- + +## Current State + +**Phase**: Exploration complete, ready for planning +**Next Steps**: Invoke Gemini for task decomposition +``` + +--- + +### Plan Mode (Gemini-Guided) + +**Step 2.1: Gemini-Assisted Planning** + +```bash +ccw cli -p " +PURPOSE: Generate implementation plan for: ${task_description} +Success criteria: 2-7 structured tasks with clear dependencies, executor assignments + +TASK: +• Read progress.md exploration findings (all angles) +• Analyze task requirements and constraints +• Decompose into 2-7 substantial tasks (15-60min each) +• Assign executor per task (gemini/codex/agent) based on: + - User explicit mention (\"use gemini for X\") + - Task nature (analysis → gemini, implementation → agent, git-aware → codex) + - Default → agent +• Define true dependencies only (Task B needs Task A's output) +• Group by feature/module, NOT by file + +MODE: analysis + +CONTEXT: @${progressPath} | Exploration findings in progress.md + +EXPECTED: +- plan.json following schema (cat ~/.claude/workflows/cli-templates/schemas/plan-json-schema.json) +- tasks: [{id, title, description, files, executor (gemini/codex/agent), depends_on, complexity}] +- executorAssignments: {taskId: {executor, reason}} +- estimated_time, complexity, summary, approach + +CONSTRAINTS: +- Respect project-guidelines.json constraints +- Prefer parallel tasks (minimal depends_on) +- Group related changes into single task +- Explicit executor rationale +" --tool gemini --mode analysis --rule planning-breakdown-task-steps +``` + +**Step 2.2: Parse Gemini Output → plan.json** + +```javascript +// Gemini returns plan structure +const planFromGemini = parseGeminiOutput() + +const plan = { + summary: planFromGemini.summary, + approach: planFromGemini.approach, + tasks: planFromGemini.tasks.map(t => ({ + id: t.id, + title: t.title, + description: t.description, + files: t.files, + executor: t.executor || 'agent', // gemini/codex/agent + depends_on: t.depends_on || [], + complexity: t.complexity, + status: 'pending' // pending/in_progress/completed/failed + })), + executorAssignments: planFromGemini.executorAssignments || {}, + estimated_time: planFromGemini.estimated_time, + complexity: complexity, + _metadata: { + timestamp: getUtc8ISOString(), + source: 'gemini-planning', + exploration_angles: selectedAngles + } +} + +Write(planPath, JSON.stringify(plan, null, 2)) +``` + +**Step 2.3: Update progress.md** + +Append to `progress.md`: + +```markdown +## Planning Results + +### Plan Generated (${getUtc8ISOString()}) + +**Summary**: ${plan.summary} +**Approach**: ${plan.approach} +**Estimated Time**: ${plan.estimated_time} +**Complexity**: ${plan.complexity} + +**Tasks** (${plan.tasks.length}): + +${plan.tasks.map((t, i) => ` +${i+1}. **${t.id}**: ${t.title} + - Files: ${t.files.join(', ')} + - Executor: ${t.executor} + - Depends on: ${t.depends_on.join(', ') || 'None'} + - Complexity: ${t.complexity} +`).join('\n')} + +**Executor Assignments**: +${Object.entries(plan.executorAssignments).map(([id, assign]) => + `- ${id}: ${assign.executor} (Reason: ${assign.reason})` +).join('\n')} + +**Gemini Insights**: +${planFromGemini.gemini_insights || 'N/A'} + +--- + +## Current State + +**Phase**: Planning complete, awaiting user confirmation +**Next Steps**: User confirms → Execute tasks +``` + +**Step 2.4: User Confirmation** + +```javascript +AskUserQuestion({ + questions: [ + { + question: `Confirm plan? (${plan.tasks.length} tasks, ${plan.complexity})`, + header: "Confirm", + multiSelect: false, + options: [ + { label: "Allow", description: "Proceed as-is" }, + { label: "Modify", description: "Adjust tasks/executors" }, + { label: "Cancel", description: "Abort workflow" } + ] + } + ] +}) + +// If Modify → allow editing plan.json, re-confirm +// If Allow → proceed to Execute mode +``` + +--- + +### Execute Mode (Multi-Agent/CLI) + +**Step 3.1: Task Execution Loop** + +```javascript +const plan = JSON.parse(Read(planPath)) +const completedTasks = [] +const failedTasks = [] + +for (const task of plan.tasks) { + // Check dependencies + const depsCompleted = task.depends_on.every(depId => + completedTasks.some(t => t.id === depId) + ) + + if (!depsCompleted) { + console.log(`⏸️ Task ${task.id} waiting for dependencies: ${task.depends_on.join(', ')}`) + continue + } + + console.log(`\n## Executing Task: ${task.id} (${task.executor})\n`) + + // Update progress.md + appendToProgress(` +### Task ${task.id} - ${task.title} (${getUtc8ISOString()}) + +**Status**: In Progress +**Executor**: ${task.executor} +**Files**: ${task.files.join(', ')} +`) + + // Execute based on assigned executor + try { + if (task.executor === 'gemini') { + // Gemini CLI execution + bash(`ccw cli -p " +PURPOSE: ${task.description} +TASK: Implement changes in: ${task.files.join(', ')} +MODE: write +CONTEXT: @${task.files.join(' @')} | Memory: Task ${task.id} from ${sessionId} +EXPECTED: Code implementation following project patterns +CONSTRAINTS: ${task.constraints || 'Follow project-guidelines.json'} +" --tool gemini --mode write --cd ${sessionFolder}`, run_in_background=true) + + // Wait for callback + + } else if (task.executor === 'codex') { + // Codex CLI execution + bash(`ccw cli -p " +${task.description} + +Files to modify: ${task.files.join(', ')} +" --tool codex --mode write`, run_in_background=true) + + // Wait for callback + + } else { + // Agent execution + Task( + subagent_type="code-developer", + run_in_background=false, + description=`Execute task ${task.id}`, + prompt=` +## Task: ${task.title} + +${task.description} + +## Context from Exploration +Read ${progressPath} for exploration findings relevant to: +${task.files.map(f => `- ${f}`).join('\n')} + +## Files to Modify +${task.files.join('\n')} + +## Constraints +- Follow patterns identified in exploration +- Respect project-guidelines.json +- Write tests if applicable + +## Success Criteria +- Code compiles without errors +- Tests pass (if applicable) +- Follows existing code style +` + ) + } + + // Mark completed + task.status = 'completed' + completedTasks.push(task) + + appendToProgress(` +**Status**: ✅ Completed +**Output**: ${task.output || 'Code changes applied'} +`) + + } catch (error) { + task.status = 'failed' + failedTasks.push(task) + + appendToProgress(` +**Status**: ❌ Failed +**Error**: ${error.message} +`) + + // Ask user: retry/skip/abort + AskUserQuestion({ + questions: [{ + question: `Task ${task.id} failed. How to proceed?`, + header: "Error", + multiSelect: false, + options: [ + { label: "Retry", description: "Retry with same executor" }, + { label: "Skip", description: "Skip and continue" }, + { label: "Abort", description: "Stop workflow" } + ] + }] + }) + } + + // Update plan.json + Write(planPath, JSON.stringify(plan, null, 2)) +} + +// Final summary +appendToProgress(` +--- + +## Execution Summary (${getUtc8ISOString()}) + +**Total Tasks**: ${plan.tasks.length} +**Completed**: ${completedTasks.length} +**Failed**: ${failedTasks.length} + +${failedTasks.length > 0 ? ` +**Failed Tasks**: +${failedTasks.map(t => `- ${t.id}: ${t.title}`).join('\n')} +` : ''} + +--- + +## Current State + +**Phase**: Execution complete, ready for verification +**Next Steps**: Invoke Gemini for code review +`) +``` + +--- + +### Verify Mode (Gemini-Assisted) + +**Step 4.1: Gemini Code Review** + +```bash +ccw cli -p " +PURPOSE: Review code changes from development session ${sessionId} +Success criteria: Identify issues, validate correctness, suggest improvements + +TASK: +• Review all modified files from execution +• Check: correctness, style consistency, potential bugs, test coverage +• Validate against project-guidelines.json +• Provide actionable feedback with file:line references + +MODE: review + +CONTEXT: @${progressPath} | Execution results in progress.md + +EXPECTED: +- Review report with severity levels (Critical/High/Medium/Low) +- Issues with file:line references and fix suggestions +- Overall quality score (1-10) +- Recommendations for improvements + +CONSTRAINTS: Evidence-based feedback only +" --tool gemini --mode review +``` + +**Step 4.2: Parse Review Results** + +```javascript +const reviewResults = parseGeminiReview() + +const hasBlockers = reviewResults.issues.some(i => i.severity === 'Critical') +const hasMajorIssues = reviewResults.issues.some(i => i.severity === 'High') +``` + +**Step 4.3: Update progress.md** + +Append to `progress.md`: + +```markdown +## Verification Results + +### Code Review (${getUtc8ISOString()}) + +**Reviewer**: Gemini +**Quality Score**: ${reviewResults.quality_score}/10 + +**Issues Found** (${reviewResults.issues.length}): + +${reviewResults.issues.map(issue => ` +#### ${issue.severity}: ${issue.title} +- **File**: ${issue.file}:${issue.line} +- **Description**: ${issue.description} +- **Suggested Fix**: +\`\`\`${issue.language || 'typescript'} +${issue.suggested_fix} +\`\`\` +`).join('\n')} + +${reviewResults.issues.length === 0 ? '✅ No issues found. Code review passed.' : ''} + +**Recommendations**: +${reviewResults.recommendations.map(r => `- ${r}`).join('\n')} + +**Gemini Analysis**: +${reviewResults.gemini_analysis} + +--- + +## Current State + +**Phase**: Verification complete +**Decision**: ${hasBlockers ? 'BLOCKERS FOUND - Fix required' : (hasMajorIssues ? 'Major issues - Recommend fixing' : 'PASSED - Ready to commit')} +``` + +**Step 4.4: Decision** + +```javascript +if (hasBlockers) { + // Critical issues → must fix before commit + console.log(` +❌ Critical issues found. Transitioning to Iterate mode for fixes. + `) + mode = 'iterate' + +} else if (hasMajorIssues) { + // Ask user + AskUserQuestion({ + questions: [{ + question: "High severity issues found. How to proceed?", + header: "Review", + multiSelect: false, + options: [ + { label: "Fix Issues", description: "Iterate to fix high severity issues" }, + { label: "Accept As-Is", description: "Proceed despite issues" }, + { label: "Manual Review", description: "Stop and review manually" } + ] + }] + }) + +} else { + // All passed + console.log(` +✅ Code review passed. Development complete. + +Session artifacts saved in: ${sessionFolder} +- progress.md: Full development timeline +- plan.json: Execution plan + +Run \`/workflow:develop-with-file --resume ${sessionId}\` to iterate. + `) +} +``` + +--- + +### Iterate Mode (Incremental) + +**Step 5.1: Analyze Delta** + +User provides new requirements or fix instructions: + +```bash +ccw cli -p " +PURPOSE: Analyze incremental changes for session ${sessionId} +Success criteria: Identify minimal tasks to address new requirements + +TASK: +• Read progress.md for current state +• Compare new requirements with existing implementation +• Identify delta (what changed?) +• Generate incremental tasks (append to existing plan) + +MODE: analysis + +CONTEXT: +@${progressPath} +@${planPath} +| New requirements: ${new_requirements} + +EXPECTED: +- Delta analysis (what's new, what needs changing) +- Incremental tasks [{id, title, description, files, executor}] +- Updated plan.json with new tasks + +CONSTRAINTS: Minimal changes, preserve existing work +" --tool gemini --mode analysis --rule planning-breakdown-task-steps +``` + +**Step 5.2: Append Incremental Tasks** + +```javascript +const plan = JSON.parse(Read(planPath)) +const incrementalTasks = parseGeminiDelta() + +// Assign new task IDs +const maxId = Math.max(...plan.tasks.map(t => parseInt(t.id.replace('T', '')))) +incrementalTasks.forEach((task, i) => { + task.id = `T${maxId + i + 1}` + task.status = 'pending' + plan.tasks.push(task) +}) + +Write(planPath, JSON.stringify(plan, null, 2)) +``` + +**Step 5.3: Update progress.md** + +Append new iteration section: + +```markdown +--- + +## Iteration ${iteration_number} (${getUtc8ISOString()}) + +### New Requirements +${new_requirements} + +### Delta Analysis +${incrementalTasks.delta_analysis} + +### Incremental Tasks +${incrementalTasks.tasks.map(t => ` +- **${t.id}**: ${t.title} + - Files: ${t.files.join(', ')} + - Executor: ${t.executor} +`).join('\n')} + +--- + +## Current State + +**Phase**: Iteration planning complete +**Next Steps**: Execute incremental tasks +``` + +**Step 5.4: Execute Incremental Tasks** + +Re-enter Execute Mode, but only process tasks with `status: 'pending'`. + +--- + +## Session Folder Structure + +``` +.workflow/.develop/{session-id}/ +├── progress.md # Timeline: exploration → planning → execution → verification +├── plan.json # Current execution plan (tasks, statuses, executors) +└── exploration-{angle}.json # Temporary exploration results (optional, can delete after planning) +``` + +**Example**: +``` +.workflow/.develop/DEV-implement-jwt-refresh-2025-01-23/ +├── progress.md +├── plan.json +├── exploration-architecture.json +├── exploration-patterns.json +└── exploration-testing.json +``` + +## Progress.md Template + +```markdown +# Development Progress + +**Session ID**: DEV-xxx-2025-01-23 +**Task Description**: [original description] +**Started**: 2025-01-23T10:00:00+08:00 +**Complexity**: Medium + +--- + +## Exploration Results + +### Exploration Summary (2025-01-23 10:05) +... + +### Clarifications Collected +... + +--- + +## Planning Results + +### Plan Generated (2025-01-23 10:15) +... + +--- + +## Execution Timeline + +### Task T1 - ... (2025-01-23 10:20) +**Status**: ✅ Completed +... + +### Task T2 - ... (2025-01-23 10:35) +**Status**: ✅ Completed +... + +--- + +## Verification Results + +### Code Review (2025-01-23 11:00) +... + +--- + +## Iteration 2 (2025-01-23 14:00) + +### New Requirements +... + +### Delta Analysis +... + +--- + +## Current State + +**Phase**: Complete +**Quality Score**: 8/10 +**Artifacts**: progress.md, plan.json +``` + +## Plan.json Schema + +```json +{ + "summary": "Implementation summary", + "approach": "Technical approach description", + "tasks": [ + { + "id": "T1", + "title": "Task title", + "description": "Detailed description", + "files": ["src/file1.ts", "src/file2.ts"], + "executor": "agent", // gemini/codex/agent + "depends_on": [], + "complexity": "Medium", + "status": "completed" // pending/in_progress/completed/failed + } + ], + "executorAssignments": { + "T1": { + "executor": "agent", + "reason": "Standard implementation task, agent handles well" + } + }, + "estimated_time": "2-3 hours", + "complexity": "Medium", + "_metadata": { + "timestamp": "2025-01-23T10:15:00+08:00", + "source": "gemini-planning", + "exploration_angles": ["architecture", "patterns", "testing"] + } +} +``` + +## Gemini Integration Points + +### 1. Planning (Plan Mode) + +**Purpose**: Intelligent task decomposition with executor assignment + +**Prompt Pattern**: +``` +PURPOSE: Generate implementation plan + executor assignments +TASK: Analyze exploration → decompose → assign executors (gemini/codex/agent) +CONTEXT: @progress.md (exploration findings) +EXPECTED: plan.json with tasks, executorAssignments, rationale +``` + +### 2. Verification (Verify Mode) + +**Purpose**: Post-execution code review and quality check + +**Prompt Pattern**: +``` +PURPOSE: Review code changes + validate quality +TASK: Check correctness, style, bugs → severity levels → fix suggestions +CONTEXT: @progress.md (execution results) +EXPECTED: Review report with issues (Critical/High/Medium/Low), quality score +``` + +### 3. Iteration (Iterate Mode) + +**Purpose**: Analyze delta and generate incremental tasks + +**Prompt Pattern**: +``` +PURPOSE: Analyze incremental changes + minimal tasks +TASK: Compare new requirements with current state → delta → incremental tasks +CONTEXT: @progress.md @plan.json | New requirements +EXPECTED: Delta analysis + incremental tasks +``` + +## Error Correction Mechanism + +### Correction Format in progress.md + +When verification finds issues: + +```markdown +### Corrected Understanding (Iteration 2) + +- ~~Assumed API returns array~~ → API returns object with data array + - Why wrong: Misread API response structure + - Evidence: Runtime error "map is not a function" + - Fix applied: Changed `response.map` to `response.data.map` + +- ~~Thought validation was client-side~~ → Validation is server-side + - Why wrong: Only checked frontend code + - Evidence: Backend validation logic found in exploration + - Fix applied: Removed redundant client validation +``` + +## Error Handling + +| Situation | Action | +|-----------|--------| +| Exploration agent failure | Skip angle, continue with remaining explorations | +| Gemini planning unavailable | Fallback to direct Claude planning (Low complexity mode) | +| Task execution failure | Ask user: Retry/Skip/Abort | +| Verification finds blockers | Force iteration mode, cannot proceed | +| plan.json corrupted | Regenerate from progress.md + Gemini | +| >5 iterations | Suggest breaking into sub-sessions | + +## Comparison with /workflow:lite-plan + +| Feature | /workflow:lite-plan | /workflow:develop-with-file | +|---------|---------------------|----------------------------| +| State tracking | In-memory → lite-execute | progress.md (persistent) | +| Exploration | Multi-agent parallel | ✅ Same | +| Planning | cli-lite-planning-agent | Gemini CLI (more flexible) | +| Execution | Delegated to lite-execute | Built-in (multi-agent/CLI) | +| Verification | None | ✅ Gemini code review | +| Iteration support | ❌ | ✅ Incremental tasks | +| Document continuity | ❌ (session ends) | ✅ (progress.md timeline) | +| Executor assignment | Global only | ✅ Per-task | + +## Usage Recommendations + +Use `/workflow:develop-with-file` when: +- Complex features requiring multiple phases (explore → plan → execute → verify) +- Need persistent progress tracking across sessions +- Want Gemini-assisted planning and verification +- Anticipate multiple iterations/refinements +- Team needs to understand development rationale + +Use `/workflow:lite-plan` when: +- Quick one-off tasks +- Simple features (Low complexity) +- Don't need verification +- Session-level documentation not needed diff --git a/ccw/src/commands/issue.ts b/ccw/src/commands/issue.ts index b4f9c724..feee422d 100644 --- a/ccw/src/commands/issue.ts +++ b/ccw/src/commands/issue.ts @@ -1220,6 +1220,81 @@ async function solutionAction(issueId: string | undefined, options: IssueOptions } } +/** + * solutions - Batch query solutions for multiple issues + * Usage: ccw issue solutions --status planned --brief + */ +async function solutionsAction(options: IssueOptions): Promise { + // Get issues filtered by status + const issues = readIssues(); + let targetIssues = issues; + + if (options.status) { + const statuses = options.status.split(',').map((s: string) => s.trim()); + targetIssues = issues.filter((i: Issue) => statuses.includes(i.status)); + } + + // Filter to only issues with bound_solution_id + const boundIssues = targetIssues.filter((i: Issue) => i.bound_solution_id); + + if (boundIssues.length === 0) { + if (options.json || options.brief) { + console.log('[]'); + } else { + console.log(chalk.yellow('No bound solutions found')); + } + return; + } + + // Collect solutions for all bound issues + const allSolutions: Array<{ + issue_id: string; + solution_id: string; + is_bound: boolean; + task_count: number; + files_touched: string[]; + priority?: number; + }> = []; + + for (const issue of boundIssues) { + const solutions = readSolutions(issue.id); + const boundSolution = solutions.find(s => s.id === issue.bound_solution_id); + + if (boundSolution) { + const filesTouched = new Set(); + for (const task of boundSolution.tasks) { + if (task.modification_points) { + for (const mp of task.modification_points) { + if (mp.file) filesTouched.add(mp.file); + } + } + } + + allSolutions.push({ + issue_id: issue.id, + solution_id: boundSolution.id, + is_bound: true, + task_count: boundSolution.tasks.length, + files_touched: Array.from(filesTouched), + priority: issue.priority + }); + } + } + + // Brief mode: already minimal + if (options.brief || options.json) { + console.log(JSON.stringify(allSolutions, null, 2)); + return; + } + + // Human-readable output + console.log(chalk.bold.cyan(`\nBound Solutions (${allSolutions.length}):\n`)); + for (const sol of allSolutions) { + console.log(`${chalk.green('◉')} ${sol.issue_id} → ${sol.solution_id}`); + console.log(chalk.gray(` Tasks: ${sol.task_count}, Files: ${sol.files_touched.length}`)); + } +} + /** * init - Initialize a new issue (manual ID) */ @@ -2832,6 +2907,9 @@ export async function issueCommand( case 'solution': await solutionAction(argsArray[0], options); break; + case 'solutions': + await solutionsAction(options); + break; case 'init': await initAction(argsArray[0], options); break; diff --git a/ccw/src/core/routes/.gitignore b/ccw/src/core/routes/.gitignore new file mode 100644 index 00000000..b4a7d405 --- /dev/null +++ b/ccw/src/core/routes/.gitignore @@ -0,0 +1 @@ +.ace-tool/