# Command: deep-analyze > CLI Fan-out deep analysis. Splits findings into 2 domain groups, runs parallel CLI agents for root cause / impact / optimization enrichment. ## When to Use - Phase 3 of Reviewer, when `deep_analysis.length > 0` - Requires `deep_analysis[]` array and `sessionFolder` from Phase 2 **Trigger conditions**: - REV-* task in Phase 3 with at least 1 finding triaged for deep analysis ## Strategy ### Delegation Mode **Mode**: CLI Fan-out (max 2 parallel agents, analysis only) ### Tool Fallback Chain ``` gemini (primary) -> qwen (fallback) -> codex (fallback) ``` ### Group Split ``` Group A: Security + Correctness findings -> 1 CLI agent Group B: Performance + Maintainability findings -> 1 CLI agent If either group empty -> skip that agent (run single agent only) ``` ## Execution Steps ### Step 1: Split Findings into Groups ```javascript const groupA = deep_analysis.filter(f => f.dimension === 'security' || f.dimension === 'correctness' ) const groupB = deep_analysis.filter(f => f.dimension === 'performance' || f.dimension === 'maintainability' ) // Collect all affected files for CLI context const collectFiles = (group) => [...new Set( group.map(f => f.location?.file).filter(Boolean) )] const filesA = collectFiles(groupA) const filesB = collectFiles(groupB) ``` ### Step 2: Build CLI Prompts ```javascript function buildPrompt(group, groupLabel, affectedFiles) { const findingsJson = JSON.stringify(group, null, 2) const filePattern = affectedFiles.length <= 20 ? affectedFiles.map(f => `@${f}`).join(' ') : '@**/*.{ts,tsx,js,jsx,py,go,java,rs}' return `PURPOSE: Deep analysis of ${groupLabel} code findings -- root cause, impact, optimization suggestions. TASK: - For each finding: trace root cause (independent issue or symptom of another finding?) - Identify findings sharing the same root cause -> mark related_findings with their IDs - Assess impact scope and affected files (blast_radius: function/module/system) - Propose fix strategy (minimal fix vs refactor) with tradeoff analysis - Identify fix dependencies (which findings must be fixed first?) - For each finding add these enrichment fields: root_cause: { description: string, related_findings: string[], is_symptom: boolean } impact: { scope: "low"|"medium"|"high", affected_files: string[], blast_radius: string } optimization: { approach: string, alternative: string, tradeoff: string } fix_strategy: "minimal" | "refactor" | "skip" fix_complexity: "low" | "medium" | "high" fix_dependencies: string[] (finding IDs that must be fixed first) MODE: analysis CONTEXT: ${filePattern} Findings to analyze: ${findingsJson} EXPECTED: Respond with ONLY a JSON array. Each element is the original finding object with the 6 enrichment fields added. Preserve ALL original fields exactly. CONSTRAINTS: Preserve original finding fields | Only add enrichment fields | Return raw JSON array only | No markdown wrapping` } const promptA = groupA.length > 0 ? buildPrompt(groupA, 'Security + Correctness', filesA) : null const promptB = groupB.length > 0 ? buildPrompt(groupB, 'Performance + Maintainability', filesB) : null ``` ### Step 3: Execute CLI Agents (Parallel) ```javascript function runCli(prompt) { const tools = ['gemini', 'qwen', 'codex'] for (const tool of tools) { try { const out = Bash( `ccw cli -p "${prompt.replace(/"/g, '\\"')}" --tool ${tool} --mode analysis --rule analysis-diagnose-bug-root-cause`, { timeout: 300000 } ) return out } catch { continue } } return null // All tools failed } // Run both groups -- if both present, execute via Bash run_in_background for parallelism let resultA = null, resultB = null if (promptA && promptB) { // Both groups: run in parallel // Group A in background Bash(`ccw cli -p "${promptA.replace(/"/g, '\\"')}" --tool gemini --mode analysis --rule analysis-diagnose-bug-root-cause > "${sessionFolder}/review/_groupA.txt" 2>&1`, { run_in_background: true, timeout: 300000 }) // Group B synchronous (blocks until done) resultB = runCli(promptB) // Wait for Group A to finish, then read output Bash(`sleep 5`) // Brief wait if B finished faster try { resultA = Read(`${sessionFolder}/review/_groupA.txt`) } catch {} // If background failed, try synchronous fallback if (!resultA) resultA = runCli(promptA) } else if (promptA) { resultA = runCli(promptA) } else if (promptB) { resultB = runCli(promptB) } ``` ### Step 4: Parse & Merge Results ```javascript function parseCliOutput(output) { if (!output) return [] try { const match = output.match(/\[[\s\S]*\]/) if (!match) return [] const parsed = JSON.parse(match[0]) // Validate enrichment fields exist return parsed.filter(f => f.id && f.dimension).map(f => ({ ...f, root_cause: f.root_cause || { description: 'Unknown', related_findings: [], is_symptom: false }, impact: f.impact || { scope: 'medium', affected_files: [f.location?.file].filter(Boolean), blast_radius: 'module' }, optimization: f.optimization || { approach: f.suggested_fix || '', alternative: '', tradeoff: '' }, fix_strategy: ['minimal', 'refactor', 'skip'].includes(f.fix_strategy) ? f.fix_strategy : 'minimal', fix_complexity: ['low', 'medium', 'high'].includes(f.fix_complexity) ? f.fix_complexity : 'medium', fix_dependencies: Array.isArray(f.fix_dependencies) ? f.fix_dependencies : [] })) } catch { return [] } } const enrichedA = parseCliOutput(resultA) const enrichedB = parseCliOutput(resultB) // Merge: CLI-enriched findings replace originals, unenriched originals kept as fallback const enrichedMap = new Map() for (const f of [...enrichedA, ...enrichedB]) enrichedMap.set(f.id, f) const enrichedFindings = deep_analysis.map(f => enrichedMap.get(f.id) || { ...f, root_cause: { description: 'Analysis unavailable', related_findings: [], is_symptom: false }, impact: { scope: 'medium', affected_files: [f.location?.file].filter(Boolean), blast_radius: 'unknown' }, optimization: { approach: f.suggested_fix || '', alternative: '', tradeoff: '' }, fix_strategy: 'minimal', fix_complexity: 'medium', fix_dependencies: [] } ) // Write output Write(`${sessionFolder}/review/enriched-findings.json`, JSON.stringify(enrichedFindings, null, 2)) // Cleanup temp files Bash(`rm -f "${sessionFolder}/review/_groupA.txt" "${sessionFolder}/review/_groupB.txt"`) ``` ## Error Handling | Scenario | Resolution | |----------|------------| | gemini CLI fails | Fallback to qwen, then codex | | All CLI tools fail for a group | Use original findings with default enrichment | | CLI output not valid JSON | Attempt regex extraction, else use defaults | | Background task hangs | Synchronous fallback after timeout | | One group fails, other succeeds | Merge partial results with defaults | | Invalid enrichment fields | Apply defaults for missing/invalid fields |