mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-10 02:24:35 +08:00
Remove Phase 3: Lite Fix documentation and add regression test for CSRF token fallback mechanism
This commit is contained in:
@@ -670,58 +670,206 @@ close_agent({ id: planningAgentId })
|
||||
|
||||
**Refine Exploration Notes** (auto-executed after Plan completes):
|
||||
|
||||
**Purpose**: Refine exploration-notes.md based on actual tasks in plan.json, keeping only execution-relevant content
|
||||
**Purpose**: Generate a self-contained execution reference from exploration-notes.md + plan.json. Execution agents should be able to implement tasks **without re-reading source files**.
|
||||
|
||||
**Key Principle**: Each file entry must include enough structural detail (exports, key functions, types, line ranges) that an execution agent can write correct code (imports, function signatures, integration points) without opening the file.
|
||||
|
||||
```javascript
|
||||
// Step 1: Load plan and exploration notes
|
||||
// Step 1: Load plan, exploration notes, and exploration JSON files
|
||||
const plan = JSON.parse(Read(`${sessionFolder}/plan.json`))
|
||||
const explorationLog = Read(`${sessionFolder}/exploration-notes.md`)
|
||||
const manifest = JSON.parse(Read(`${sessionFolder}/explorations-manifest.json`))
|
||||
const explorations = manifest.explorations.map(exp => ({
|
||||
angle: exp.angle,
|
||||
data: JSON.parse(Read(exp.path))
|
||||
}))
|
||||
|
||||
// Step 2: Extract files and modules from plan
|
||||
// Step 2: Extract ALL files referenced in plan (modification_points + reference.files)
|
||||
const planFiles = new Set()
|
||||
const planScopes = new Set()
|
||||
const fileTaskMap = {} // file → [taskIds] mapping for cross-reference
|
||||
|
||||
plan.tasks.forEach(task => {
|
||||
if (task.scope) planScopes.add(task.scope)
|
||||
const taskFiles = []
|
||||
if (task.modification_points) {
|
||||
task.modification_points.forEach(mp => planFiles.add(mp.file))
|
||||
task.modification_points.forEach(mp => {
|
||||
planFiles.add(mp.file)
|
||||
taskFiles.push(mp.file)
|
||||
})
|
||||
}
|
||||
if (task.reference?.files) {
|
||||
task.reference.files.forEach(f => planFiles.add(f))
|
||||
task.reference.files.forEach(f => {
|
||||
planFiles.add(f)
|
||||
taskFiles.push(f)
|
||||
})
|
||||
}
|
||||
taskFiles.forEach(f => {
|
||||
if (!fileTaskMap[f]) fileTaskMap[f] = []
|
||||
fileTaskMap[f].push(task.id)
|
||||
})
|
||||
})
|
||||
|
||||
// Step 3: Read each plan-referenced file and extract structural details
|
||||
const fileProfiles = {}
|
||||
|
||||
Array.from(planFiles).forEach(filePath => {
|
||||
try {
|
||||
const content = Read(filePath)
|
||||
const lines = content.split('\n')
|
||||
const totalLines = lines.length
|
||||
|
||||
// Extract exports (named + default)
|
||||
const namedExports = []
|
||||
const defaultExport = []
|
||||
lines.forEach((line, idx) => {
|
||||
if (/^export\s+(function|const|class|interface|type|enum|async\s+function)\s+(\w+)/.test(line)) {
|
||||
const match = line.match(/^export\s+(?:async\s+)?(?:function|const|class|interface|type|enum)\s+(\w+)/)
|
||||
if (match) namedExports.push({ name: match[1], line: idx + 1, declaration: line.trim().substring(0, 120) })
|
||||
}
|
||||
if (/^export\s+default/.test(line)) {
|
||||
defaultExport.push({ line: idx + 1, declaration: line.trim().substring(0, 120) })
|
||||
}
|
||||
})
|
||||
|
||||
// Extract imports (first 30 lines typically)
|
||||
const imports = []
|
||||
lines.slice(0, 50).forEach((line, idx) => {
|
||||
if (/^import\s/.test(line)) {
|
||||
imports.push({ line: idx + 1, statement: line.trim() })
|
||||
}
|
||||
})
|
||||
|
||||
// Extract key function/class signatures (non-exported too)
|
||||
const signatures = []
|
||||
lines.forEach((line, idx) => {
|
||||
// Function declarations
|
||||
if (/^\s*(async\s+)?function\s+\w+/.test(line) || /^\s*(export\s+)?(async\s+)?function\s+\w+/.test(line)) {
|
||||
signatures.push({ line: idx + 1, signature: line.trim().substring(0, 150) })
|
||||
}
|
||||
// Class declarations
|
||||
if (/^\s*(export\s+)?class\s+\w+/.test(line)) {
|
||||
signatures.push({ line: idx + 1, signature: line.trim().substring(0, 150) })
|
||||
}
|
||||
// Arrow function assignments (const foo = ...)
|
||||
if (/^\s*(export\s+)?(const|let)\s+\w+\s*=\s*(async\s+)?\(/.test(line)) {
|
||||
signatures.push({ line: idx + 1, signature: line.trim().substring(0, 150) })
|
||||
}
|
||||
})
|
||||
|
||||
// Extract modification points context (±5 lines around each modification_points.line)
|
||||
const modificationContexts = []
|
||||
plan.tasks.forEach(task => {
|
||||
if (task.modification_points) {
|
||||
task.modification_points.filter(mp => mp.file === filePath && mp.line).forEach(mp => {
|
||||
const startLine = Math.max(0, mp.line - 6)
|
||||
const endLine = Math.min(totalLines, mp.line + 5)
|
||||
modificationContexts.push({
|
||||
taskId: task.id,
|
||||
taskTitle: task.title,
|
||||
line: mp.line,
|
||||
description: mp.description || '',
|
||||
context: lines.slice(startLine, endLine).map((l, i) => `${startLine + i + 1}: ${l}`).join('\n')
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
fileProfiles[filePath] = {
|
||||
totalLines,
|
||||
imports,
|
||||
namedExports,
|
||||
defaultExport,
|
||||
signatures,
|
||||
modificationContexts,
|
||||
relatedTasks: fileTaskMap[filePath] || []
|
||||
}
|
||||
} catch (e) {
|
||||
fileProfiles[filePath] = { error: `Failed to read: ${e.message}`, relatedTasks: fileTaskMap[filePath] || [] }
|
||||
}
|
||||
})
|
||||
|
||||
// Step 3: Build refined exploration notes
|
||||
// Step 4: Build refined exploration notes with full file profiles
|
||||
const refinedLog = `# Exploration Notes (Refined): ${task_description.slice(0, 60)}
|
||||
|
||||
**Generated**: ${getUtc8ISOString()}
|
||||
**Task**: ${task_description}
|
||||
**Plan Tasks**: ${plan.tasks.length}
|
||||
**Refined For**: Execution phase consumption
|
||||
**Referenced Files**: ${planFiles.size}
|
||||
**Refined For**: Execution phase — self-contained, no need to re-read source files
|
||||
|
||||
---
|
||||
|
||||
## Execution-Relevant File Index
|
||||
## Part 1: File Profiles (Execution Reference)
|
||||
|
||||
The following files are directly related to plan.json tasks, prioritize these during execution:
|
||||
> Each profile contains enough detail for execution agents to write correct imports,
|
||||
> call correct functions, and integrate at the right locations WITHOUT opening the file.
|
||||
|
||||
${Array.from(planFiles).map(f => `- \`${f}\``).join('\n')}
|
||||
${Array.from(planFiles).map(filePath => {
|
||||
const profile = fileProfiles[filePath]
|
||||
if (!profile || profile.error) {
|
||||
return `### \`${filePath}\`\n\n⚠️ ${profile?.error || 'File not found'}\n**Related Tasks**: ${(profile?.relatedTasks || []).join(', ')}`
|
||||
}
|
||||
|
||||
return `### \`${filePath}\`
|
||||
|
||||
**Lines**: ${profile.totalLines} | **Related Tasks**: ${profile.relatedTasks.join(', ')}
|
||||
|
||||
**Imports**:
|
||||
\`\`\`
|
||||
${profile.imports.map(i => i.statement).join('\n') || '(none)'}
|
||||
\`\`\`
|
||||
|
||||
**Exports** (named):
|
||||
${profile.namedExports.length > 0
|
||||
? profile.namedExports.map(e => `- L${e.line}: \`${e.declaration}\``).join('\n')
|
||||
: '(none)'}
|
||||
${profile.defaultExport.length > 0
|
||||
? `\n**Default Export**: L${profile.defaultExport[0].line}: \`${profile.defaultExport[0].declaration}\``
|
||||
: ''}
|
||||
|
||||
**Key Signatures**:
|
||||
${profile.signatures.slice(0, 15).map(s => `- L${s.line}: \`${s.signature}\``).join('\n') || '(none)'}
|
||||
|
||||
${profile.modificationContexts.length > 0 ? `**Modification Points** (with surrounding code):
|
||||
${profile.modificationContexts.map(mc => `
|
||||
#### → Task ${mc.taskId}: ${mc.taskTitle}
|
||||
**Target Line ${mc.line}**: ${mc.description}
|
||||
\`\`\`
|
||||
${mc.context}
|
||||
\`\`\`
|
||||
`).join('\n')}` : ''}
|
||||
`
|
||||
}).join('\n---\n')}
|
||||
|
||||
---
|
||||
|
||||
## Part 1: Task-Relevant Exploration Context
|
||||
## Part 2: Task-Specific Execution Context
|
||||
|
||||
${plan.tasks.map(task => {
|
||||
// Extract content relevant to this task from original exploration notes
|
||||
return `### Task: ${task.title}
|
||||
const taskFiles = []
|
||||
if (task.modification_points) taskFiles.push(...task.modification_points.map(mp => mp.file))
|
||||
if (task.reference?.files) taskFiles.push(...task.reference.files)
|
||||
const uniqueFiles = [...new Set(taskFiles)]
|
||||
|
||||
return `### Task ${task.id}: ${task.title}
|
||||
|
||||
**Scope**: \`${task.scope}\`
|
||||
**Files**: ${task.modification_points?.map(mp => mp.file).join(', ') || 'N/A'}
|
||||
**Complexity**: ${task.complexity || 'N/A'}
|
||||
**Depends On**: ${task.depends_on?.join(', ') || 'None (parallel-safe)'}
|
||||
|
||||
**Files to Modify**:
|
||||
${uniqueFiles.map(f => {
|
||||
const profile = fileProfiles[f]
|
||||
if (!profile || profile.error) return `- \`${f}\` — ⚠️ ${profile?.error || 'not profiled'}`
|
||||
return `- \`${f}\` (${profile.totalLines} lines, ${profile.namedExports.length} exports)`
|
||||
}).join('\n')}
|
||||
|
||||
**Relevant Exploration Findings**:
|
||||
${extractRelevantExploration(explorationLog, task)}
|
||||
|
||||
**Reference Patterns**:
|
||||
${task.reference?.pattern || 'See exploration notes Part 1 patterns'}
|
||||
${task.reference?.pattern || 'Follow existing patterns in referenced files'}
|
||||
|
||||
**Risk Notes**:
|
||||
${extractRelevantRisks(explorationLog, task)}
|
||||
@@ -730,16 +878,7 @@ ${extractRelevantRisks(explorationLog, task)}
|
||||
|
||||
---
|
||||
|
||||
## Part 2: Condensed Code Reference
|
||||
|
||||
${Array.from(planFiles).slice(0, 8).map(filePath => {
|
||||
// Extract file deep-dive from original exploration notes Part 2
|
||||
return extractFileDeepDive(explorationLog, filePath) || `### ${filePath}\n\n(See original exploration notes for details)`
|
||||
}).join('\n---\n')}
|
||||
|
||||
---
|
||||
|
||||
## Part 3: Execution Notes
|
||||
## Part 3: Cross-Cutting Concerns
|
||||
|
||||
### Key Constraints (from exploration)
|
||||
${extractConstraints(explorationLog)}
|
||||
@@ -747,32 +886,48 @@ ${extractConstraints(explorationLog)}
|
||||
### Integration Points (plan-task related)
|
||||
${extractIntegrationPoints(explorationLog, planFiles)}
|
||||
|
||||
### Dependencies
|
||||
### Dependencies (external packages & internal modules)
|
||||
${extractDependencies(explorationLog, planFiles)}
|
||||
|
||||
### Shared Patterns Across Tasks
|
||||
${explorations.map(exp => {
|
||||
if (exp.data.patterns) {
|
||||
return `- **${exp.angle}**: ${typeof exp.data.patterns === 'string' ? exp.data.patterns.substring(0, 200) : JSON.stringify(exp.data.patterns).substring(0, 200)}`
|
||||
}
|
||||
return null
|
||||
}).filter(Boolean).join('\n') || '(none extracted)'}
|
||||
|
||||
---
|
||||
|
||||
## Appendix: Full Exploration Notes Location
|
||||
## Appendix: Quick Lookup
|
||||
|
||||
Original full exploration notes: \`${sessionFolder}/exploration-notes.md\`
|
||||
### File → Task Mapping
|
||||
|
||||
For additional context, refer to:
|
||||
- Part 3: Architecture Reasoning Chains
|
||||
- Part 4: Potential Risks and Mitigations
|
||||
- Part 5: Clarification Questions Summary
|
||||
| File | Tasks | Exports Count | Lines |
|
||||
|------|-------|---------------|-------|
|
||||
${Array.from(planFiles).map(f => {
|
||||
const p = fileProfiles[f]
|
||||
if (!p || p.error) return `| \`${f}\` | ${(p?.relatedTasks || []).join(', ')} | — | — |`
|
||||
return `| \`${f}\` | ${p.relatedTasks.join(', ')} | ${p.namedExports.length} | ${p.totalLines} |`
|
||||
}).join('\n')}
|
||||
|
||||
### Original Exploration Notes
|
||||
|
||||
Full exploration notes: \`${sessionFolder}/exploration-notes.md\`
|
||||
`
|
||||
|
||||
// Step 4: Write refined exploration notes
|
||||
// Step 5: Write refined exploration notes
|
||||
Write(`${sessionFolder}/exploration-notes-refined.md`, refinedLog)
|
||||
|
||||
// Step 5: Update session artifacts
|
||||
// Step 6: Update session artifacts
|
||||
console.log(`
|
||||
## Exploration Notes Refined
|
||||
|
||||
Original: ${sessionFolder}/exploration-notes.md (full version, for Plan reference)
|
||||
Refined: ${sessionFolder}/exploration-notes-refined.md (condensed, for Execute consumption)
|
||||
Refined: ${sessionFolder}/exploration-notes-refined.md (self-contained, for Execute consumption)
|
||||
|
||||
Refined for ${plan.tasks.length} tasks, ${planFiles.size} files
|
||||
File profiles: ${Object.keys(fileProfiles).length} files with structural details
|
||||
Modification contexts: ${Object.values(fileProfiles).reduce((sum, p) => sum + (p.modificationContexts?.length || 0), 0)} code snippets
|
||||
`)
|
||||
```
|
||||
|
||||
|
||||
@@ -1,548 +0,0 @@
|
||||
# Phase 2: Multi-CLI Plan
|
||||
|
||||
## Auto Mode
|
||||
|
||||
When `--yes` or `-y`: Auto-approve plan, use recommended solution and execution method (Agent, Skip review).
|
||||
|
||||
## Overview
|
||||
|
||||
Multi-CLI collaborative planning with ACE context gathering and iterative cross-verification. Uses cli-discuss-agent for Gemini+Codex+Claude analysis to converge on optimal execution plan.
|
||||
|
||||
## Quick Start
|
||||
|
||||
**Parameters**:
|
||||
- `<task-description>` (required): Task description
|
||||
- `--max-rounds` (optional): Maximum discussion rounds (default: 3)
|
||||
- `--tools` (optional): CLI tools for analysis (default: gemini,codex)
|
||||
- `--mode` (optional): Execution mode: parallel or 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 Phase 4: Lite Execute (phases/04-lite-execute.md) 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 (via @cli-lite-planning-agent)
|
||||
├─ Build executionContext with user selections
|
||||
└─ Hand off to Phase 4: Lite Execute (phases/04-lite-execute.md) --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, plan.json generation following schema |
|
||||
|
||||
## 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** (Codex subagent pattern):
|
||||
```javascript
|
||||
// Step 1: Create discussion agent
|
||||
const discussAgentId = spawn_agent({
|
||||
message: `
|
||||
## TASK ASSIGNMENT
|
||||
|
||||
### MANDATORY FIRST STEPS (Agent Execute)
|
||||
1. **Read role definition**: ~/.codex/agents/cli-discuss-agent.md (MUST read first)
|
||||
2. Read: .workflow/project-tech.json
|
||||
3. Read: .workflow/project-guidelines.json
|
||||
|
||||
---
|
||||
|
||||
## Input Context
|
||||
- task_description: ${taskDescription}
|
||||
- round_number: ${currentRound}
|
||||
- session: { id: "${sessionId}", folder: "${sessionFolder}" }
|
||||
- ace_context: ${JSON.stringify(contextPackage)}
|
||||
- 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
|
||||
`
|
||||
})
|
||||
|
||||
// Step 2: Wait for discussion completion
|
||||
const discussResult = wait({
|
||||
ids: [discussAgentId],
|
||||
timeout_ms: 600000 // 10 minutes
|
||||
})
|
||||
|
||||
// Step 3: Close discussion agent
|
||||
close_agent({ id: discussAgentId })
|
||||
```
|
||||
|
||||
**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))
|
||||
```
|
||||
|
||||
**Step 2: Invoke Planning Agent** (Codex subagent pattern):
|
||||
```javascript
|
||||
// Step 1: Create planning agent
|
||||
const planningAgentId = spawn_agent({
|
||||
message: `
|
||||
## TASK ASSIGNMENT
|
||||
|
||||
### MANDATORY FIRST STEPS (Agent Execute)
|
||||
1. **Read role definition**: ~/.codex/agents/cli-lite-planning-agent.md (MUST read first)
|
||||
2. Read: .workflow/project-tech.json
|
||||
3. Read: .workflow/project-guidelines.json
|
||||
|
||||
---
|
||||
|
||||
## Schema Reference
|
||||
Execute: cat ~/.claude/workflows/cli-templates/schemas/plan-json-schema.json
|
||||
|
||||
## Context-Package (from orchestrator)
|
||||
${JSON.stringify(contextPackage, null, 2)}
|
||||
|
||||
## Execution Process
|
||||
1. Read plan-json-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 detailed acceptance criteria
|
||||
7. Generate plan.json following schema exactly
|
||||
|
||||
## Output
|
||||
- ${sessionFolder}/plan.json
|
||||
|
||||
## Completion Checklist
|
||||
- [ ] plan.json preserves task dependencies from implementation_plan
|
||||
- [ ] Task execution order follows execution_flow
|
||||
- [ ] Key_points reflected in task descriptions
|
||||
- [ ] User constraints applied to implementation
|
||||
- [ ] Acceptance criteria are testable
|
||||
- [ ] Schema fields match plan-json-schema.json exactly
|
||||
`
|
||||
})
|
||||
|
||||
// Step 2: Wait for planning completion
|
||||
const planResult = wait({
|
||||
ids: [planningAgentId],
|
||||
timeout_ms: 900000 // 15 minutes
|
||||
})
|
||||
|
||||
// Step 3: Close planning agent
|
||||
close_agent({ id: planningAgentId })
|
||||
```
|
||||
|
||||
**Step 3: Build executionContext**:
|
||||
```javascript
|
||||
// After plan.json is generated by cli-lite-planning-agent
|
||||
const plan = JSON.parse(Read(`${sessionFolder}/plan.json`))
|
||||
|
||||
// Build executionContext (same structure as lite-plan)
|
||||
executionContext = {
|
||||
planObject: plan,
|
||||
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`,
|
||||
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
|
||||
// Hand off to Phase 4: Lite Execute (phases/04-lite-execute.md) with in-memory context
|
||||
// executionContext is passed in-memory to the execution phase
|
||||
```
|
||||
|
||||
## 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 # Structured plan (cli-lite-planning-agent)
|
||||
```
|
||||
|
||||
**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 | Structured tasks for lite-execute |
|
||||
|
||||
## 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 Phases
|
||||
|
||||
- Simpler single-round planning: [Phase 1: Lite Plan](01-lite-plan.md)
|
||||
- Shared execution engine: [Phase 4: Lite Execute](04-lite-execute.md)
|
||||
- Full planning workflow: [workflow-plan/SKILL.md](../../workflow-plan/SKILL.md)
|
||||
|
||||
---
|
||||
|
||||
## Post-Phase Update
|
||||
|
||||
After Phase 2 (Multi-CLI Plan) completes:
|
||||
- **Output Created**: `executionContext` with plan.json, synthesis rounds, context-package, user selections
|
||||
- **Session Artifacts**: All files in `.workflow/.multi-cli-plan/{session-id}/`
|
||||
- **Next Action**: Auto-continue to [Phase 4: Lite Execute](04-lite-execute.md) with --in-memory
|
||||
- **TodoWrite**: Mark "Multi-CLI Plan - Planning" as completed, start "Execution (Phase 4)"
|
||||
@@ -1,799 +0,0 @@
|
||||
# Phase 3: Lite Fix
|
||||
|
||||
## Overview
|
||||
|
||||
Intelligent lightweight bug fixing command with dynamic workflow adaptation based on severity assessment. Focuses on diagnosis phases (root cause analysis, impact assessment, fix planning, confirmation) and delegates execution to Phase 4: Lite Execute (phases/04-lite-execute.md).
|
||||
|
||||
**Core capabilities:**
|
||||
- Intelligent bug analysis with automatic severity detection
|
||||
- Dynamic code diagnosis (cli-explore-agent) for root cause identification
|
||||
- Interactive clarification after diagnosis to gather missing information
|
||||
- Adaptive fix planning strategy (direct Claude vs cli-lite-planning-agent) based on complexity
|
||||
- Two-step confirmation: fix-plan display -> multi-dimensional input collection
|
||||
- Execution handoff with complete context to Phase 4: Lite Execute (phases/04-lite-execute.md)
|
||||
|
||||
## Parameters
|
||||
|
||||
- `-y, --yes`: Skip all confirmations (auto mode)
|
||||
- `--hotfix, -h`: Production hotfix mode (minimal diagnosis, fast fix)
|
||||
- `<bug-description>` (required): Bug description, error message, or path to .md file
|
||||
|
||||
## Output Artifacts
|
||||
|
||||
| Artifact | Description |
|
||||
|----------|-------------|
|
||||
| `diagnosis-{angle}.json` | Per-angle diagnosis results (1-4 files based on severity) |
|
||||
| `diagnoses-manifest.json` | Index of all diagnosis files |
|
||||
| `planning-context.md` | Evidence paths + synthesized understanding |
|
||||
| `fix-plan.json` | Structured fix plan (fix-plan-json-schema.json) |
|
||||
|
||||
**Output Directory**: `.workflow/.lite-fix/{bug-slug}-{YYYY-MM-DD}/`
|
||||
|
||||
**Agent Usage**:
|
||||
- Low/Medium severity → Direct Claude planning (no agent)
|
||||
- High/Critical severity → `cli-lite-planning-agent` generates `fix-plan.json`
|
||||
|
||||
**Schema Reference**: `~/.claude/workflows/cli-templates/schemas/fix-plan-json-schema.json`
|
||||
|
||||
## Auto Mode Defaults
|
||||
|
||||
When `--yes` or `-y` flag is used:
|
||||
- **Clarification Questions**: Skipped (no clarification phase)
|
||||
- **Fix Plan Confirmation**: Auto-selected "Allow"
|
||||
- **Execution Method**: Auto-selected "Auto"
|
||||
- **Code Review**: Auto-selected "Skip"
|
||||
- **Severity**: Uses auto-detected severity (no manual override)
|
||||
- **Hotfix Mode**: Respects --hotfix flag if present, otherwise normal mode
|
||||
|
||||
**Flag Parsing**:
|
||||
```javascript
|
||||
const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y')
|
||||
const hotfixMode = $ARGUMENTS.includes('--hotfix') || $ARGUMENTS.includes('-h')
|
||||
```
|
||||
|
||||
## Execution Process
|
||||
|
||||
```
|
||||
Phase 1: Bug Analysis & Diagnosis
|
||||
|- Parse input (description, error message, or .md file)
|
||||
|- Intelligent severity pre-assessment (Low/Medium/High/Critical)
|
||||
|- Diagnosis decision (auto-detect or --hotfix flag)
|
||||
|- Context protection: If file reading >=50k chars -> force cli-explore-agent
|
||||
+- Decision:
|
||||
|- needsDiagnosis=true -> Launch parallel cli-explore-agents (1-4 based on severity)
|
||||
+- needsDiagnosis=false (hotfix) -> Skip directly to Phase 3 (Fix Planning)
|
||||
|
||||
Phase 2: Clarification (optional, multi-round)
|
||||
|- Aggregate clarification_needs from all diagnosis angles
|
||||
|- Deduplicate similar questions
|
||||
+- Decision:
|
||||
|- Has clarifications -> AskUserQuestion (max 4 questions per round, multiple rounds allowed)
|
||||
+- No clarifications -> Skip to Phase 3
|
||||
|
||||
Phase 3: Fix Planning (NO CODE EXECUTION - planning only)
|
||||
+- Decision (based on Phase 1 severity):
|
||||
|- Low/Medium -> Load schema: cat ~/.claude/workflows/cli-templates/schemas/fix-plan-json-schema.json -> Direct Claude planning (following schema) -> fix-plan.json -> MUST proceed to Phase 4
|
||||
+- High/Critical -> cli-lite-planning-agent -> fix-plan.json -> MUST proceed to Phase 4
|
||||
|
||||
Phase 4: Confirmation & Selection
|
||||
|- Display fix-plan summary (tasks, severity, estimated time)
|
||||
+- AskUserQuestion:
|
||||
|- Confirm: Allow / Modify / Cancel
|
||||
|- Execution: Agent / Codex / Auto
|
||||
+- Review: Gemini / Agent / Skip
|
||||
|
||||
Phase 5: Execute
|
||||
|- Build executionContext (fix-plan + diagnoses + clarifications + selections)
|
||||
+- Hand off to Phase 4: Lite Execute (phases/04-lite-execute.md) --in-memory --mode bugfix
|
||||
```
|
||||
|
||||
## Implementation
|
||||
|
||||
### Phase 1: Intelligent Multi-Angle Diagnosis
|
||||
|
||||
**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 bugSlug = bug_description.toLowerCase().replace(/[^a-z0-9]+/g, '-').substring(0, 40)
|
||||
const dateStr = getUtc8ISOString().substring(0, 10) // Format: 2025-11-29
|
||||
|
||||
const sessionId = `${bugSlug}-${dateStr}` // e.g., "user-avatar-upload-fails-2025-11-29"
|
||||
const sessionFolder = `.workflow/.lite-fix/${sessionId}`
|
||||
|
||||
bash(`mkdir -p ${sessionFolder} && test -d ${sessionFolder} && echo "SUCCESS: ${sessionFolder}" || echo "FAILED: ${sessionFolder}"`)
|
||||
```
|
||||
|
||||
**Diagnosis Decision Logic**:
|
||||
```javascript
|
||||
const hotfixMode = $ARGUMENTS.includes('--hotfix') || $ARGUMENTS.includes('-h')
|
||||
|
||||
needsDiagnosis = (
|
||||
!hotfixMode &&
|
||||
(
|
||||
bug.lacks_specific_error_message ||
|
||||
bug.requires_codebase_context ||
|
||||
bug.needs_execution_tracing ||
|
||||
bug.root_cause_unclear
|
||||
)
|
||||
)
|
||||
|
||||
if (!needsDiagnosis) {
|
||||
// Skip to Phase 2 (Clarification) or Phase 3 (Fix Planning)
|
||||
proceed_to_next_phase()
|
||||
}
|
||||
```
|
||||
|
||||
**Context Protection**: File reading >=50k chars -> force `needsDiagnosis=true` (delegate to cli-explore-agent)
|
||||
|
||||
**Severity Pre-Assessment** (Intelligent Analysis):
|
||||
```javascript
|
||||
// Analyzes bug severity based on:
|
||||
// - Symptoms: Error messages, crash reports, user complaints
|
||||
// - Scope: How many users/features are affected?
|
||||
// - Urgency: Production down vs minor inconvenience
|
||||
// - Impact: Data loss, security, business impact
|
||||
|
||||
const severity = analyzeBugSeverity(bug_description)
|
||||
// Returns: 'Low' | 'Medium' | 'High' | 'Critical'
|
||||
// Low: Minor UI issue, localized, no data impact
|
||||
// Medium: Multiple users affected, degraded functionality
|
||||
// High: Significant functionality broken, many users affected
|
||||
// Critical: Production down, data loss risk, security issue
|
||||
|
||||
// Angle assignment based on bug type (orchestrator decides, not agent)
|
||||
const DIAGNOSIS_ANGLE_PRESETS = {
|
||||
runtime_error: ['error-handling', 'dataflow', 'state-management', 'edge-cases'],
|
||||
performance: ['performance', 'bottlenecks', 'caching', 'data-access'],
|
||||
security: ['security', 'auth-patterns', 'dataflow', 'validation'],
|
||||
data_corruption: ['data-integrity', 'state-management', 'transactions', 'validation'],
|
||||
ui_bug: ['state-management', 'event-handling', 'rendering', 'data-binding'],
|
||||
integration: ['api-contracts', 'error-handling', 'timeouts', 'fallbacks']
|
||||
}
|
||||
|
||||
function selectDiagnosisAngles(bugDescription, count) {
|
||||
const text = bugDescription.toLowerCase()
|
||||
let preset = 'runtime_error' // default
|
||||
|
||||
if (/slow|timeout|performance|lag|hang/.test(text)) preset = 'performance'
|
||||
else if (/security|auth|permission|access|token/.test(text)) preset = 'security'
|
||||
else if (/corrupt|data|lost|missing|inconsistent/.test(text)) preset = 'data_corruption'
|
||||
else if (/ui|display|render|style|click|button/.test(text)) preset = 'ui_bug'
|
||||
else if (/api|integration|connect|request|response/.test(text)) preset = 'integration'
|
||||
|
||||
return DIAGNOSIS_ANGLE_PRESETS[preset].slice(0, count)
|
||||
}
|
||||
|
||||
const selectedAngles = selectDiagnosisAngles(bug_description, severity === 'Critical' ? 4 : (severity === 'High' ? 3 : (severity === 'Medium' ? 2 : 1)))
|
||||
|
||||
console.log(`
|
||||
## Diagnosis Plan
|
||||
|
||||
Bug Severity: ${severity}
|
||||
Selected Angles: ${selectedAngles.join(', ')}
|
||||
|
||||
Launching ${selectedAngles.length} parallel diagnoses...
|
||||
`)
|
||||
```
|
||||
|
||||
**Launch Parallel Diagnoses** - Orchestrator assigns angle to each agent:
|
||||
|
||||
```javascript
|
||||
// Launch agents with pre-assigned diagnosis angles
|
||||
const diagnosisTasks = selectedAngles.map((angle, index) =>
|
||||
Task(
|
||||
subagent_type="cli-explore-agent",
|
||||
run_in_background=false,
|
||||
description=`Diagnose: ${angle}`,
|
||||
prompt=`
|
||||
## Task Objective
|
||||
Execute **${angle}** diagnosis for bug root cause analysis. Analyze codebase from this specific angle to discover root cause, affected paths, and fix hints.
|
||||
|
||||
## Output Location
|
||||
|
||||
**Session Folder**: ${sessionFolder}
|
||||
**Output File**: ${sessionFolder}/diagnosis-${angle}.json
|
||||
|
||||
## Assigned Context
|
||||
- **Diagnosis Angle**: ${angle}
|
||||
- **Bug Description**: ${bug_description}
|
||||
- **Diagnosis 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 "{error_keyword_from_bug}" --type ts (locate relevant files)
|
||||
3. Execute: cat ~/.claude/workflows/cli-templates/schemas/diagnosis-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)
|
||||
|
||||
## Diagnosis Strategy (${angle} focus)
|
||||
|
||||
**Step 1: Error Tracing** (Bash)
|
||||
- rg for error messages, stack traces, log patterns
|
||||
- git log --since='2 weeks ago' for recent changes
|
||||
- Trace execution path in affected modules
|
||||
|
||||
**Step 2: Root Cause Analysis** (Gemini CLI)
|
||||
- What code paths lead to this ${angle} issue?
|
||||
- What edge cases are not handled from ${angle} perspective?
|
||||
- What recent changes might have introduced this bug?
|
||||
|
||||
**Step 3: Write Output**
|
||||
- Consolidate ${angle} findings into JSON
|
||||
- Identify ${angle}-specific clarification needs
|
||||
- Provide fix hints based on ${angle} analysis
|
||||
|
||||
## Expected Output
|
||||
|
||||
**Schema Reference**: Schema obtained in MANDATORY FIRST STEPS step 3, follow schema exactly
|
||||
|
||||
**Required Fields** (all ${angle} focused):
|
||||
- symptom: Bug symptoms and error messages
|
||||
- root_cause: Root cause hypothesis from ${angle} perspective
|
||||
**IMPORTANT**: Use structured format:
|
||||
\`{file: "src/module/file.ts", line_range: "45-60", issue: "Description", confidence: 0.85}\`
|
||||
- affected_files: Files involved from ${angle} perspective
|
||||
**IMPORTANT**: Use object format with relevance scores:
|
||||
\`[{path: "src/file.ts", relevance: 0.85, rationale: "Contains ${angle} logic"}]\`
|
||||
- reproduction_steps: Steps to reproduce the bug
|
||||
- fix_hints: Suggested fix approaches from ${angle} viewpoint
|
||||
- dependencies: Dependencies relevant to ${angle} diagnosis
|
||||
- constraints: ${angle}-specific limitations affecting fix
|
||||
- clarification_needs: ${angle}-related ambiguities (options array + recommended index)
|
||||
- _metadata.diagnosis_angle: "${angle}"
|
||||
- _metadata.diagnosis_index: ${index + 1}
|
||||
|
||||
## Success Criteria
|
||||
- [ ] Schema obtained via cat diagnosis-json-schema.json
|
||||
- [ ] get_modules_by_depth.sh executed
|
||||
- [ ] Root cause identified with confidence score
|
||||
- [ ] At least 3 affected files identified with ${angle} rationale
|
||||
- [ ] Fix hints are actionable (specific code changes, not generic advice)
|
||||
- [ ] Reproduction steps are verifiable
|
||||
- [ ] JSON output follows schema exactly
|
||||
- [ ] clarification_needs includes options + recommended
|
||||
|
||||
## Execution
|
||||
**Write**: \`${sessionFolder}/diagnosis-${angle}.json\`
|
||||
**Return**: 2-3 sentence summary of ${angle} diagnosis findings
|
||||
`
|
||||
)
|
||||
)
|
||||
|
||||
// Execute all diagnosis tasks in parallel
|
||||
```
|
||||
|
||||
**Auto-discover Generated Diagnosis Files**:
|
||||
```javascript
|
||||
// After diagnoses complete, auto-discover all diagnosis-*.json files
|
||||
const diagnosisFiles = bash(`find ${sessionFolder} -name "diagnosis-*.json" -type f`)
|
||||
.split('\n')
|
||||
.filter(f => f.trim())
|
||||
|
||||
// Read metadata to build manifest
|
||||
const diagnosisManifest = {
|
||||
session_id: sessionId,
|
||||
bug_description: bug_description,
|
||||
timestamp: getUtc8ISOString(),
|
||||
severity: severity,
|
||||
diagnosis_count: diagnosisFiles.length,
|
||||
diagnoses: diagnosisFiles.map(file => {
|
||||
const data = JSON.parse(Read(file))
|
||||
const filename = path.basename(file)
|
||||
return {
|
||||
angle: data._metadata.diagnosis_angle,
|
||||
file: filename,
|
||||
path: file,
|
||||
index: data._metadata.diagnosis_index
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Write(`${sessionFolder}/diagnoses-manifest.json`, JSON.stringify(diagnosisManifest, null, 2))
|
||||
|
||||
console.log(`
|
||||
## Diagnosis Complete
|
||||
|
||||
Generated diagnosis files in ${sessionFolder}:
|
||||
${diagnosisManifest.diagnoses.map(d => `- diagnosis-${d.angle}.json (angle: ${d.angle})`).join('\n')}
|
||||
|
||||
Manifest: diagnoses-manifest.json
|
||||
Angles diagnosed: ${diagnosisManifest.diagnoses.map(d => d.angle).join(', ')}
|
||||
`)
|
||||
```
|
||||
|
||||
**Output**:
|
||||
- `${sessionFolder}/diagnosis-{angle1}.json`
|
||||
- `${sessionFolder}/diagnosis-{angle2}.json`
|
||||
- ... (1-4 files based on severity)
|
||||
- `${sessionFolder}/diagnoses-manifest.json`
|
||||
|
||||
---
|
||||
|
||||
### Phase 2: Clarification (Optional, Multi-Round)
|
||||
|
||||
**Skip if**: No diagnosis or `clarification_needs` is empty across all diagnoses
|
||||
|
||||
**⚠️ 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 diagnosis angles**:
|
||||
```javascript
|
||||
// Load manifest and all diagnosis files
|
||||
const manifest = JSON.parse(Read(`${sessionFolder}/diagnoses-manifest.json`))
|
||||
const diagnoses = manifest.diagnoses.map(diag => ({
|
||||
angle: diag.angle,
|
||||
data: JSON.parse(Read(diag.path))
|
||||
}))
|
||||
|
||||
// Aggregate clarification needs from all diagnoses
|
||||
const allClarifications = []
|
||||
diagnoses.forEach(diag => {
|
||||
if (diag.data.clarification_needs?.length > 0) {
|
||||
diag.data.clarification_needs.forEach(need => {
|
||||
allClarifications.push({
|
||||
...need,
|
||||
source_angle: diag.angle
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Deduplicate by question similarity
|
||||
function deduplicateClarifications(clarifications) {
|
||||
const unique = []
|
||||
clarifications.forEach(c => {
|
||||
const isDuplicate = unique.some(u =>
|
||||
u.question.toLowerCase() === c.question.toLowerCase()
|
||||
)
|
||||
if (!isDuplicate) unique.push(c)
|
||||
})
|
||||
return unique
|
||||
}
|
||||
|
||||
const uniqueClarifications = deduplicateClarifications(allClarifications)
|
||||
|
||||
// Parse --yes flag
|
||||
const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y')
|
||||
|
||||
if (autoYes) {
|
||||
// Auto mode: Skip clarification phase
|
||||
console.log(`[--yes] Skipping ${uniqueClarifications.length} clarification questions`)
|
||||
console.log(`Proceeding to fix planning with diagnosis results...`)
|
||||
// Continue to Phase 3
|
||||
} else if (uniqueClarifications.length > 0) {
|
||||
// Interactive mode: Multi-round clarification
|
||||
// ⚠️ MUST execute ALL rounds until uniqueClarifications exhausted
|
||||
const BATCH_SIZE = 4
|
||||
const totalRounds = Math.ceil(uniqueClarifications.length / BATCH_SIZE)
|
||||
|
||||
for (let i = 0; i < uniqueClarifications.length; i += BATCH_SIZE) {
|
||||
const batch = uniqueClarifications.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,
|
||||
multiSelect: false,
|
||||
options: need.options.map((opt, index) => {
|
||||
const isRecommended = need.recommended === index
|
||||
return {
|
||||
label: isRecommended ? `${opt} ★` : opt,
|
||||
description: isRecommended ? `Use ${opt} approach (Recommended)` : `Use ${opt} approach`
|
||||
}
|
||||
})
|
||||
}))
|
||||
})
|
||||
|
||||
// Store batch responses in clarificationContext before next round
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Output**: `clarificationContext` (in-memory)
|
||||
|
||||
---
|
||||
|
||||
### Phase 3: Fix Planning
|
||||
|
||||
**Planning Strategy Selection** (based on Phase 1 severity):
|
||||
|
||||
**IMPORTANT**: Phase 3 is **planning only** - NO code execution. All execution happens in Phase 5 via lite-execute.
|
||||
|
||||
**Low/Medium Severity** - Direct planning by Claude:
|
||||
```javascript
|
||||
// Step 1: Read schema
|
||||
const schema = Bash(`cat ~/.claude/workflows/cli-templates/schemas/fix-plan-json-schema.json`)
|
||||
|
||||
// Step 2: Generate fix-plan following schema (Claude directly, no agent)
|
||||
// For Medium complexity: include rationale + verification (optional, but recommended)
|
||||
const fixPlan = {
|
||||
summary: "...",
|
||||
root_cause: "...",
|
||||
strategy: "immediate_patch|comprehensive_fix|refactor",
|
||||
tasks: [...], // Each task: { id, title, scope, ..., depends_on, complexity }
|
||||
estimated_time: "...",
|
||||
recommended_execution: "Agent",
|
||||
severity: severity,
|
||||
risk_level: "...",
|
||||
|
||||
// Medium complexity fields (optional for direct planning, auto-filled for Low)
|
||||
...(severity === "Medium" ? {
|
||||
design_decisions: [
|
||||
{
|
||||
decision: "Use immediate_patch strategy for minimal risk",
|
||||
rationale: "Keeps changes localized and quick to review",
|
||||
tradeoff: "Defers comprehensive refactoring"
|
||||
}
|
||||
],
|
||||
tasks_with_rationale: {
|
||||
// Each task gets rationale if Medium
|
||||
task_rationale_example: {
|
||||
rationale: {
|
||||
chosen_approach: "Direct fix approach",
|
||||
alternatives_considered: ["Workaround", "Refactor"],
|
||||
decision_factors: ["Minimal impact", "Quick turnaround"],
|
||||
tradeoffs: "Doesn't address underlying issue"
|
||||
},
|
||||
verification: {
|
||||
unit_tests: ["test_bug_fix_basic"],
|
||||
integration_tests: [],
|
||||
manual_checks: ["Reproduce issue", "Verify fix"],
|
||||
success_metrics: ["Issue resolved", "No regressions"]
|
||||
}
|
||||
}
|
||||
}
|
||||
} : {}),
|
||||
|
||||
_metadata: {
|
||||
timestamp: getUtc8ISOString(),
|
||||
source: "direct-planning",
|
||||
planning_mode: "direct",
|
||||
complexity: severity === "Medium" ? "Medium" : "Low"
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: Merge task rationale into tasks array
|
||||
if (severity === "Medium") {
|
||||
fixPlan.tasks = fixPlan.tasks.map(task => ({
|
||||
...task,
|
||||
rationale: fixPlan.tasks_with_rationale[task.id]?.rationale || {
|
||||
chosen_approach: "Standard fix",
|
||||
alternatives_considered: [],
|
||||
decision_factors: ["Correctness", "Simplicity"],
|
||||
tradeoffs: "None"
|
||||
},
|
||||
verification: fixPlan.tasks_with_rationale[task.id]?.verification || {
|
||||
unit_tests: [`test_${task.id}_basic`],
|
||||
integration_tests: [],
|
||||
manual_checks: ["Verify fix works"],
|
||||
success_metrics: ["Test pass"]
|
||||
}
|
||||
}))
|
||||
delete fixPlan.tasks_with_rationale // Clean up temp field
|
||||
}
|
||||
|
||||
// Step 4: Write fix-plan to session folder
|
||||
Write(`${sessionFolder}/fix-plan.json`, JSON.stringify(fixPlan, null, 2))
|
||||
|
||||
// Step 5: MUST continue to Phase 4 (Confirmation) - DO NOT execute code here
|
||||
```
|
||||
|
||||
**High/Critical Severity** - Invoke cli-lite-planning-agent:
|
||||
|
||||
```javascript
|
||||
Task(
|
||||
subagent_type="cli-lite-planning-agent",
|
||||
run_in_background=false,
|
||||
description="Generate detailed fix plan",
|
||||
prompt=`
|
||||
Generate fix plan and write fix-plan.json.
|
||||
|
||||
## Output Location
|
||||
|
||||
**Session Folder**: ${sessionFolder}
|
||||
**Output Files**:
|
||||
- ${sessionFolder}/planning-context.md (evidence + understanding)
|
||||
- ${sessionFolder}/fix-plan.json (fix plan)
|
||||
|
||||
## Output Schema Reference
|
||||
Execute: cat ~/.claude/workflows/cli-templates/schemas/fix-plan-json-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 fix tasks MUST comply with constraints in project-guidelines.json
|
||||
|
||||
## Bug Description
|
||||
${bug_description}
|
||||
|
||||
## Multi-Angle Diagnosis Context
|
||||
|
||||
${manifest.diagnoses.map(diag => `### Diagnosis: ${diag.angle} (${diag.file})
|
||||
Path: ${diag.path}
|
||||
|
||||
Read this file for detailed ${diag.angle} analysis.`).join('\n\n')}
|
||||
|
||||
Total diagnoses: ${manifest.diagnosis_count}
|
||||
Angles covered: ${manifest.diagnoses.map(d => d.angle).join(', ')}
|
||||
|
||||
Manifest: ${sessionFolder}/diagnoses-manifest.json
|
||||
|
||||
## User Clarifications
|
||||
${JSON.stringify(clarificationContext) || "None"}
|
||||
|
||||
## Severity Level
|
||||
${severity}
|
||||
|
||||
## Requirements
|
||||
Generate fix-plan.json with:
|
||||
- summary: 2-3 sentence overview of the fix
|
||||
- root_cause: Consolidated root cause from all diagnoses
|
||||
- strategy: "immediate_patch" | "comprehensive_fix" | "refactor"
|
||||
- tasks: 1-5 structured fix tasks (**IMPORTANT: group by fix area, NOT by file**)
|
||||
- **Task Granularity Principle**: Each task = one complete fix unit
|
||||
- title: action verb + target (e.g., "Fix token validation edge case")
|
||||
- scope: module path (src/auth/) or feature name
|
||||
- action: "Fix" | "Update" | "Refactor" | "Add" | "Delete"
|
||||
- description
|
||||
- modification_points: ALL files to modify for this fix (group related changes)
|
||||
- implementation (2-5 steps covering all modification_points)
|
||||
- acceptance: Quantified acceptance criteria
|
||||
- depends_on: task IDs this task depends on (use sparingly)
|
||||
|
||||
**High/Critical complexity fields per task** (REQUIRED):
|
||||
- rationale:
|
||||
- chosen_approach: Why this fix approach (not alternatives)
|
||||
- alternatives_considered: Other approaches evaluated
|
||||
- decision_factors: Key factors influencing choice
|
||||
- tradeoffs: Known tradeoffs of this approach
|
||||
- verification:
|
||||
- unit_tests: Test names to add/verify
|
||||
- integration_tests: Integration test names
|
||||
- manual_checks: Manual verification steps
|
||||
- success_metrics: Quantified success criteria
|
||||
- risks:
|
||||
- description: Risk description
|
||||
- probability: Low|Medium|High
|
||||
- impact: Low|Medium|High
|
||||
- mitigation: How to mitigate
|
||||
- fallback: Fallback if fix fails
|
||||
- code_skeleton (optional): Key interfaces/functions to implement
|
||||
- interfaces: [{name, definition, purpose}]
|
||||
- key_functions: [{signature, purpose, returns}]
|
||||
|
||||
**Top-level High/Critical fields** (REQUIRED):
|
||||
- data_flow: How data flows through affected code
|
||||
- diagram: "A → B → C" style flow
|
||||
- stages: [{stage, input, output, component}]
|
||||
- design_decisions: Global fix decisions
|
||||
- [{decision, rationale, tradeoff}]
|
||||
|
||||
- estimated_time, recommended_execution, severity, risk_level
|
||||
- _metadata:
|
||||
- timestamp, source, planning_mode
|
||||
- complexity: "High" | "Critical"
|
||||
- diagnosis_angles: ${JSON.stringify(manifest.diagnoses.map(d => d.angle))}
|
||||
|
||||
## Task Grouping Rules
|
||||
1. **Group by fix area**: All changes for one fix = one task (even if 2-3 files)
|
||||
2. **Avoid file-per-task**: Do NOT create separate tasks for each file
|
||||
3. **Substantial tasks**: Each task should represent 10-45 minutes of work
|
||||
4. **True dependencies only**: Only use depends_on when Task B cannot start without Task A's output
|
||||
5. **Prefer parallel**: Most tasks should be independent (no depends_on)
|
||||
|
||||
## Execution
|
||||
1. Read ALL diagnosis files for comprehensive context
|
||||
2. Execute CLI planning using Gemini (Qwen fallback) with --rule planning-fix-strategy template
|
||||
3. Synthesize findings from multiple diagnosis angles
|
||||
4. Generate fix-plan with:
|
||||
- For High/Critical: REQUIRED new fields (rationale, verification, risks, code_skeleton, data_flow, design_decisions)
|
||||
- Each task MUST have rationale (why this fix), verification (how to verify success), and risks (potential issues)
|
||||
5. Parse output and structure fix-plan
|
||||
6. **Write**: \`${sessionFolder}/planning-context.md\` (evidence paths + understanding)
|
||||
7. **Write**: \`${sessionFolder}/fix-plan.json\`
|
||||
8. Return brief completion summary
|
||||
|
||||
## Output Format for CLI
|
||||
Include these sections in your fix-plan output:
|
||||
- Summary, Root Cause, Strategy (existing)
|
||||
- Data Flow: Diagram showing affected code paths
|
||||
- Design Decisions: Key architectural choices in the fix
|
||||
- Tasks: Each with rationale (Medium/High), verification (Medium/High), risks (High), code_skeleton (High)
|
||||
`
|
||||
)
|
||||
```
|
||||
|
||||
**Output**: `${sessionFolder}/fix-plan.json`
|
||||
|
||||
---
|
||||
|
||||
### Phase 4: Task Confirmation & Execution Selection
|
||||
|
||||
**Step 4.1: Display Fix Plan**
|
||||
```javascript
|
||||
const fixPlan = JSON.parse(Read(`${sessionFolder}/fix-plan.json`))
|
||||
|
||||
console.log(`
|
||||
## Fix Plan
|
||||
|
||||
**Summary**: ${fixPlan.summary}
|
||||
**Root Cause**: ${fixPlan.root_cause}
|
||||
**Strategy**: ${fixPlan.strategy}
|
||||
|
||||
**Tasks** (${fixPlan.tasks.length}):
|
||||
${fixPlan.tasks.map((t, i) => `${i+1}. ${t.title} (${t.scope})`).join('\n')}
|
||||
|
||||
**Severity**: ${fixPlan.severity}
|
||||
**Risk Level**: ${fixPlan.risk_level}
|
||||
**Estimated Time**: ${fixPlan.estimated_time}
|
||||
**Recommended**: ${fixPlan.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 fix 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
|
||||
userSelection = AskUserQuestion({
|
||||
questions: [
|
||||
{
|
||||
question: `Confirm fix plan? (${fixPlan.tasks.length} tasks, ${fixPlan.severity} severity)`,
|
||||
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: ${fixPlan.severity === 'Low' ? 'Agent' : 'Codex'}` }
|
||||
]
|
||||
},
|
||||
{
|
||||
question: "Code review after fix?",
|
||||
header: "Review",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: "Gemini Review", description: "Gemini CLI" },
|
||||
{ label: "Agent Review", description: "@code-reviewer" },
|
||||
{ label: "Skip", description: "No review" }
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Phase 5: Execute to Execution
|
||||
|
||||
**CRITICAL**: lite-fix NEVER executes code directly. ALL execution MUST go through lite-execute.
|
||||
|
||||
**Step 5.1: Build executionContext**
|
||||
|
||||
```javascript
|
||||
// Load manifest and all diagnosis files
|
||||
const manifest = JSON.parse(Read(`${sessionFolder}/diagnoses-manifest.json`))
|
||||
const diagnoses = {}
|
||||
|
||||
manifest.diagnoses.forEach(diag => {
|
||||
if (file_exists(diag.path)) {
|
||||
diagnoses[diag.angle] = JSON.parse(Read(diag.path))
|
||||
}
|
||||
})
|
||||
|
||||
const fixPlan = JSON.parse(Read(`${sessionFolder}/fix-plan.json`))
|
||||
|
||||
executionContext = {
|
||||
mode: "bugfix",
|
||||
severity: fixPlan.severity,
|
||||
planObject: {
|
||||
...fixPlan,
|
||||
// Ensure complexity is set based on severity for new field consumption
|
||||
complexity: fixPlan.complexity || (fixPlan.severity === 'Critical' ? 'High' : (fixPlan.severity === 'High' ? 'High' : 'Medium'))
|
||||
},
|
||||
diagnosisContext: diagnoses,
|
||||
diagnosisAngles: manifest.diagnoses.map(d => d.angle),
|
||||
diagnosisManifest: manifest,
|
||||
clarificationContext: clarificationContext || null,
|
||||
executionMethod: userSelection.execution_method,
|
||||
codeReviewTool: userSelection.code_review_tool,
|
||||
originalUserInput: bug_description,
|
||||
session: {
|
||||
id: sessionId,
|
||||
folder: sessionFolder,
|
||||
artifacts: {
|
||||
diagnoses: manifest.diagnoses.map(diag => ({
|
||||
angle: diag.angle,
|
||||
path: diag.path
|
||||
})),
|
||||
diagnoses_manifest: `${sessionFolder}/diagnoses-manifest.json`,
|
||||
fix_plan: `${sessionFolder}/fix-plan.json`
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Step 5.2: Execute**
|
||||
|
||||
```javascript
|
||||
// Hand off to Phase 4: Lite Execute (phases/04-lite-execute.md) --in-memory --mode bugfix
|
||||
// executionContext is passed in-memory to the execution phase
|
||||
```
|
||||
|
||||
## Session Folder Structure
|
||||
|
||||
```
|
||||
.workflow/.lite-fix/{bug-slug}-{YYYY-MM-DD}/
|
||||
├── diagnosis-{angle1}.json # Diagnosis angle 1
|
||||
├── diagnosis-{angle2}.json # Diagnosis angle 2
|
||||
├── diagnosis-{angle3}.json # Diagnosis angle 3 (if applicable)
|
||||
├── diagnosis-{angle4}.json # Diagnosis angle 4 (if applicable)
|
||||
├── diagnoses-manifest.json # Diagnosis index
|
||||
├── planning-context.md # Evidence + understanding
|
||||
└── fix-plan.json # Fix plan
|
||||
```
|
||||
|
||||
**Example**:
|
||||
```
|
||||
.workflow/.lite-fix/user-avatar-upload-fails-413-2025-11-25/
|
||||
├── diagnosis-error-handling.json
|
||||
├── diagnosis-dataflow.json
|
||||
├── diagnosis-validation.json
|
||||
├── diagnoses-manifest.json
|
||||
├── planning-context.md
|
||||
└── fix-plan.json
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Resolution |
|
||||
|-------|------------|
|
||||
| Diagnosis agent failure | Skip diagnosis, continue with bug description only |
|
||||
| Planning agent failure | Fallback to direct planning by Claude |
|
||||
| Clarification timeout | Use diagnosis findings as-is |
|
||||
| Confirmation timeout | Save context, display resume instructions |
|
||||
| Modify loop > 3 times | Suggest breaking task or using full planning workflow (workflow-plan/SKILL.md) |
|
||||
| Root cause unclear | Extend diagnosis time or use broader angles |
|
||||
| Too complex for lite-fix | Escalate to full planning workflow (workflow-plan/SKILL.md) |
|
||||
|
||||
---
|
||||
|
||||
## Post-Phase Update
|
||||
|
||||
After Phase 3 (Lite Fix) completes:
|
||||
- **Output Created**: `executionContext` with fix-plan.json, diagnoses, clarifications, user selections
|
||||
- **Session Artifacts**: All files in `.workflow/.lite-fix/{session-id}/`
|
||||
- **Next Action**: Auto-continue to [Phase 4: Lite Execute](04-lite-execute.md) with --in-memory --mode bugfix
|
||||
- **TodoWrite**: Mark "Lite Fix - Planning" as completed, start "Execution (Phase 4)"
|
||||
Reference in New Issue
Block a user