From 86536aaa108b2f93e4d8260aa49c5c86d69cb62b Mon Sep 17 00:00:00 2001 From: catlog22 Date: Thu, 15 Jan 2026 11:51:19 +0800 Subject: [PATCH] Refactor code structure for improved readability and maintainability --- .claude/commands/workflow/lite-lite-lite.md | 723 ++++---------- .../dashboard-js/views/lite-tasks.js | 941 +++++++++++++++--- 2 files changed, 978 insertions(+), 686 deletions(-) diff --git a/.claude/commands/workflow/lite-lite-lite.md b/.claude/commands/workflow/lite-lite-lite.md index 90d1afe6..75513f89 100644 --- a/.claude/commands/workflow/lite-lite-lite.md +++ b/.claude/commands/workflow/lite-lite-lite.md @@ -10,63 +10,33 @@ allowed-tools: TodoWrite(*), Task(*), AskUserQuestion(*), Read(*), Bash(*), mcp_ ## Quick Start ```bash -# Basic usage /workflow:lite-lite-lite "Fix the login bug" - -# Complex task /workflow:lite-lite-lite "Refactor payment module for multi-gateway support" ``` **Core Philosophy**: Minimal friction, maximum velocity. No files, no artifacts - just analyze and execute. -## What & Why +## Overview -### Core Concept +**Zero-artifact workflow**: Clarify → Select Tools → Multi-Mode Analysis → Decision → Direct Execution -**Zero-artifact workflow**: Clarify requirements → Auto-select tools → Mixed tool analysis → User decision → Direct execution. All state in memory, all decisions via AskUser. - -**vs multi-cli-plan**: -- **multi-cli-plan**: Full artifacts (IMPL_PLAN.md, plan.json, synthesis.json) -- **lite-lite-lite**: No files, direct in-memory flow, immediate execution - -### Value Proposition - -1. **Ultra-Fast**: No file I/O overhead, no session management -2. **Smart Selection**: Auto-select optimal tool combination based on task -3. **Interactive**: Key decisions validated via AskUser -4. **Direct**: Analysis → Execution without intermediate artifacts +**vs multi-cli-plan**: No IMPL_PLAN.md, plan.json, synthesis.json - all state in memory. ## Execution Flow ``` -Phase 1: Clarify Requirements - └─ Parse input → AskUser for missing details (if needed) - -Phase 2: Auto-Select Tools - └─ Analyze task → Match to tool strengths → Confirm selection - -Phase 3: Mixed Tool Analysis - └─ Execute selected tools in parallel → Aggregate results - -Phase 4: User Decision - ├─ Present analysis summary - ├─ AskUser: Execute / Refine / Change tools / Cancel - └─ Loop to Phase 3 if refinement needed - -Phase 5: Direct Execution - └─ Execute solution directly (no plan files) +Phase 1: Clarify Requirements → AskUser for missing details +Phase 2: Select Tools (CLI → Mode → Agent) → 3-step selection +Phase 3: Multi-Mode Analysis → Execute with --resume chaining +Phase 4: User Decision → Execute / Refine / Change / Cancel +Phase 5: Direct Execution → No plan files, immediate implementation ``` -## Phase Details +## Phase 1: Clarify Requirements -### Phase 1: Clarify Requirements - -**Parse Task Description**: ```javascript -// Extract intent from user input const taskDescription = $ARGUMENTS -// Check if clarification needed if (taskDescription.length < 20 || isAmbiguous(taskDescription)) { AskUserQuestion({ questions: [{ @@ -80,173 +50,72 @@ if (taskDescription.length < 20 || isAmbiguous(taskDescription)) { }] }) } -``` -**Quick ACE Context** (optional, for complex tasks): -```javascript -// Only if task seems to need codebase context +// Optional: Quick ACE Context for complex tasks mcp__ace-tool__search_context({ project_root_path: process.cwd(), query: `${taskDescription} implementation patterns` }) ``` -### Phase 2: Auto-Select Analysis Tools +## Phase 2: Select Tools -**Tool Categories**: +### Tool Definitions -| Category | Source | Execution | -|----------|--------|-----------| -| **CLI Tools** | cli-tools.json | `ccw cli -p "..." --tool ` | -| **Sub Agents** | Task tool | `Task({ subagent_type: "...", prompt: "..." })` | - -**Task Analysis Dimensions**: +**CLI Tools** (from cli-tools.json): ```javascript -function analyzeTask(taskDescription) { - return { - complexity: detectComplexity(taskDescription), // simple, medium, complex - taskType: detectTaskType(taskDescription), // bugfix, feature, refactor, analysis, etc. - domain: detectDomain(taskDescription), // frontend, backend, fullstack - needsExecution: detectExecutionNeed(taskDescription) // analysis-only vs needs-write - } -} -``` - -**CLI Tools** (dynamically loaded from cli-tools.json): - -```javascript -// Load CLI tools from config file const cliConfig = JSON.parse(Read("~/.claude/cli-tools.json")) const cliTools = Object.entries(cliConfig.tools) .filter(([_, config]) => config.enabled) .map(([name, config]) => ({ - name, - type: 'cli', + name, type: 'cli', tags: config.tags || [], model: config.primaryModel, toolType: config.type // builtin, cli-wrapper, api-endpoint })) ``` -**Tags** (user-defined in cli-tools.json, no fixed specification): - -Tags are completely user-defined. Users can create any tags that match their workflow needs. - -**Config Example** (cli-tools.json): -```json -{ - "tools": { - "gemini": { - "enabled": true, - "tags": ["architecture", "reasoning", "performance"], - "primaryModel": "gemini-2.5-pro" - }, - "codex": { - "enabled": true, - "tags": ["implementation", "fast"], - "primaryModel": "gpt-5.2" - }, - "qwen": { - "enabled": true, - "tags": ["implementation", "chinese", "documentation"], - "primaryModel": "coder-model" - } - } -} -``` - -**Sub Agents** (predefined, canExecute marks execution capability): - -```javascript -const agents = [ - { name: 'code-developer', type: 'agent', strength: 'Code implementation, test writing', canExecute: true }, - { name: 'Explore', type: 'agent', strength: 'Fast code exploration', canExecute: false }, - { name: 'cli-explore-agent', type: 'agent', strength: 'Dual-source deep analysis', canExecute: false }, - { name: 'cli-discuss-agent', type: 'agent', strength: 'Multi-CLI collaborative verification', canExecute: false }, - { name: 'debug-explore-agent', type: 'agent', strength: 'Hypothesis-driven debugging', canExecute: false }, - { name: 'context-search-agent', type: 'agent', strength: 'Context collection', canExecute: false }, - { name: 'test-fix-agent', type: 'agent', strength: 'Test execution and fixing', canExecute: true }, - { name: 'universal-executor', type: 'agent', strength: 'General multi-step execution', canExecute: true } -] -``` +**Sub Agents**: | Agent | Strengths | canExecute | |-------|-----------|------------| -| **code-developer** | Code implementation, test writing, incremental development | ✅ | -| **Explore** | Fast code exploration, file search, pattern discovery | ❌ | -| **cli-explore-agent** | Dual-source analysis (Bash+CLI), read-only exploration | ❌ | -| **cli-discuss-agent** | Multi-CLI collaboration, cross-verification, solution synthesis | ❌ | -| **debug-explore-agent** | Hypothesis-driven debugging, NDJSON logging, iterative verification | ❌ | -| **context-search-agent** | Multi-layer file discovery, dependency analysis, conflict assessment | ❌ | +| **code-developer** | Code implementation, test writing | ✅ | +| **Explore** | Fast code exploration, pattern discovery | ❌ | +| **cli-explore-agent** | Dual-source analysis (Bash+CLI) | ❌ | +| **cli-discuss-agent** | Multi-CLI collaboration, cross-verification | ❌ | +| **debug-explore-agent** | Hypothesis-driven debugging | ❌ | +| **context-search-agent** | Multi-layer file discovery, dependency analysis | ❌ | | **test-fix-agent** | Test execution, failure diagnosis, code fixing | ✅ | | **universal-executor** | General execution, multi-domain adaptation | ✅ | -**Three-Step Selection Flow** (CLI → Mode → Agent): +**Analysis Modes**: + +| Mode | Pattern | Use Case | minCLIs | +|------|---------|----------|---------| +| **Parallel** | `A \|\| B \|\| C → Aggregate` | Fast multi-perspective | 1+ | +| **Sequential** | `A → B(resume) → C(resume)` | Incremental deepening | 2+ | +| **Collaborative** | `A → B → A → B → Synthesize` | Multi-round refinement | 2+ | +| **Debate** | `A(propose) → B(challenge) → A(defend)` | Adversarial validation | 2 | +| **Challenge** | `A(analyze) → B(challenge)` | Find flaws and risks | 2 | + +### Three-Step Selection Flow ```javascript -// Step 1: Present CLI options from config (multiSelect for multi-CLI modes) -function getCliDescription(cli) { - return cli.tags.length > 0 ? cli.tags.join(', ') : cli.model || 'general' -} - -const cliOptions = cliTools.map(cli => ({ - label: cli.name, - description: getCliDescription(cli) -})) - +// Step 1: Select CLIs (multiSelect) AskUserQuestion({ questions: [{ - question: "Select CLI tools for analysis (select 1-3 for collaboration modes)", + question: "Select CLI tools for analysis (1-3 for collaboration modes)", header: "CLI Tools", - options: cliOptions, - multiSelect: true // Allow multiple selection for collaboration modes + options: cliTools.map(cli => ({ + label: cli.name, + description: cli.tags.length > 0 ? cli.tags.join(', ') : cli.model || 'general' + })), + multiSelect: true }] }) -``` -```javascript -// Step 2: Select Analysis Mode -const analysisModes = [ - { - name: 'parallel', - label: 'Parallel', - description: 'All CLIs analyze simultaneously, aggregate results', - minCLIs: 1, - pattern: 'A || B || C → Aggregate' - }, - { - name: 'sequential', - label: 'Sequential', - description: 'Chain analysis: each CLI builds on previous via --resume', - minCLIs: 2, - pattern: 'A → B(resume A) → C(resume B)' - }, - { - name: 'collaborative', - label: 'Collaborative', - description: 'Multi-round synthesis: CLIs take turns refining analysis', - minCLIs: 2, - pattern: 'A → B(resume A) → A(resume B) → Synthesize' - }, - { - name: 'debate', - label: 'Debate', - description: 'Adversarial: CLI B challenges CLI A findings, A responds', - minCLIs: 2, - pattern: 'A(propose) → B(challenge, resume A) → A(defend, resume B)' - }, - { - name: 'challenge', - label: 'Challenge', - description: 'Stress test: CLI B finds flaws/alternatives in CLI A analysis', - minCLIs: 2, - pattern: 'A(analyze) → B(challenge, resume A) → Evaluate' - } -] - -// Filter modes based on selected CLI count +// Step 2: Select Mode (filtered by CLI count) const availableModes = analysisModes.filter(m => selectedCLIs.length >= m.minCLIs) - AskUserQuestion({ questions: [{ question: "Select analysis mode", @@ -258,43 +127,24 @@ AskUserQuestion({ multiSelect: false }] }) -``` - -```javascript -// Step 3: Present Agent options for execution -const agentOptions = agents.map(agent => ({ - label: agent.name, - description: agent.strength -})) +// Step 3: Select Agent for execution AskUserQuestion({ questions: [{ question: "Select Sub Agent for execution", header: "Agent", - options: agentOptions, + options: agents.map(a => ({ label: a.name, description: a.strength })), multiSelect: false }] }) -``` - -**Selection Summary**: -```javascript -console.log(` -## Selected Configuration - -**CLI Tools**: ${selectedCLIs.map(c => c.name).join(' → ')} -**Analysis Mode**: ${selectedMode.label} - ${selectedMode.pattern} -**Execution Agent**: ${selectedAgent.name} - ${selectedAgent.strength} - -> Mode determines how CLIs collaborate, Agent handles final execution -`) +// Confirm selection AskUserQuestion({ questions: [{ question: "Confirm selection?", header: "Confirm", options: [ - { label: "Confirm and continue", description: `${selectedMode.label} mode with ${selectedCLIs.length} CLIs` }, + { label: "Confirm and continue", description: `${selectedMode.label} with ${selectedCLIs.length} CLIs` }, { label: "Re-select CLIs", description: "Choose different CLI tools" }, { label: "Re-select Mode", description: "Choose different analysis mode" }, { label: "Re-select Agent", description: "Choose different Sub Agent" } @@ -304,409 +154,226 @@ AskUserQuestion({ }) ``` -### Phase 3: Multi-Mode Analysis +## Phase 3: Multi-Mode Analysis -**Mode-Specific Execution Patterns**: +### Universal CLI Prompt Template -#### Mode 1: Parallel (并行) ```javascript -// All CLIs run simultaneously, no resume dependency -async function executeParallel(clis, taskDescription) { - const promises = clis.map(cli => Bash({ - command: `ccw cli -p " -PURPOSE: Analyze and provide solution for: ${taskDescription} -TASK: • Identify affected files • Analyze implementation approach • List specific changes needed +// Unified prompt builder - used by all modes +function buildPrompt({ purpose, tasks, expected, rules, taskDescription }) { + return ` +PURPOSE: ${purpose}: ${taskDescription} +TASK: ${tasks.map(t => `• ${t}`).join(' ')} MODE: analysis CONTEXT: @**/* -EXPECTED: Concise analysis with: 1) Root cause/approach 2) Files to modify 3) Key changes 4) Risks -RULES: $(cat ~/.claude/workflows/cli-templates/protocols/analysis-protocol.md) | Focus on actionable insights -" --tool ${cli.name} --mode analysis`, - run_in_background: true - })) +EXPECTED: ${expected} +RULES: $(cat ~/.claude/workflows/cli-templates/protocols/analysis-protocol.md) | ${rules} +` +} - return await Promise.all(promises) +// Execute CLI with prompt +function execCLI(cli, prompt, options = {}) { + const { resume, background = false } = options + const resumeFlag = resume ? `--resume ${resume}` : '' + return Bash({ + command: `ccw cli -p "${prompt}" --tool ${cli.name} --mode analysis ${resumeFlag}`, + run_in_background: background + }) } ``` -#### Mode 2: Sequential (串联) +### Prompt Presets by Role + +| Role | PURPOSE | TASKS | EXPECTED | RULES | +|------|---------|-------|----------|-------| +| **initial** | Initial analysis | Identify files, Analyze approach, List changes | Root cause, files, changes, risks | Focus on actionable insights | +| **extend** | Build on previous | Review previous, Extend, Add insights | Extended analysis building on findings | Build incrementally, avoid repetition | +| **synthesize** | Refine and synthesize | Review, Identify gaps, Synthesize | Refined synthesis with new perspectives | Add value not repetition | +| **propose** | Propose comprehensive analysis | Analyze thoroughly, Propose solution, State assumptions | Well-reasoned proposal with trade-offs | Be clear about assumptions | +| **challenge** | Challenge and stress-test | Identify weaknesses, Question assumptions, Suggest alternatives | Critique with counter-arguments | Be adversarial but constructive | +| **defend** | Respond to challenges | Address challenges, Defend valid aspects, Propose refined solution | Refined proposal incorporating feedback | Be open to criticism, synthesize | +| **criticize** | Find flaws ruthlessly | Find logical flaws, Identify edge cases, Rate criticisms | Critique with severity: [CRITICAL]/[HIGH]/[MEDIUM]/[LOW] | Be ruthlessly critical | + ```javascript -// Chain analysis: each CLI builds on previous via --resume -async function executeSequential(clis, taskDescription) { +const PROMPTS = { + initial: { purpose: 'Initial analysis', tasks: ['Identify affected files', 'Analyze implementation approach', 'List specific changes'], expected: 'Root cause, files to modify, key changes, risks', rules: 'Focus on actionable insights' }, + extend: { purpose: 'Build on previous analysis', tasks: ['Review previous findings', 'Extend analysis', 'Add new insights'], expected: 'Extended analysis building on previous', rules: 'Build incrementally, avoid repetition' }, + synthesize: { purpose: 'Refine and synthesize', tasks: ['Review previous', 'Identify gaps', 'Add insights', 'Synthesize findings'], expected: 'Refined synthesis with new perspectives', rules: 'Build collaboratively, add value' }, + propose: { purpose: 'Propose comprehensive analysis', tasks: ['Analyze thoroughly', 'Propose solution', 'State assumptions clearly'], expected: 'Well-reasoned proposal with trade-offs', rules: 'Be clear about assumptions' }, + challenge: { purpose: 'Challenge and stress-test', tasks: ['Identify weaknesses', 'Question assumptions', 'Suggest alternatives', 'Highlight overlooked risks'], expected: 'Constructive critique with counter-arguments', rules: 'Be adversarial but constructive' }, + defend: { purpose: 'Respond to challenges', tasks: ['Address each challenge', 'Defend valid aspects', 'Acknowledge valid criticisms', 'Propose refined solution'], expected: 'Refined proposal incorporating alternatives', rules: 'Be open to criticism, synthesize best ideas' }, + criticize: { purpose: 'Stress-test and find weaknesses', tasks: ['Find logical flaws', 'Identify missed edge cases', 'Propose alternatives', 'Rate criticisms (High/Medium/Low)'], expected: 'Detailed critique with severity ratings', rules: 'Be ruthlessly critical, find every flaw' } +} +``` + +### Mode Implementations + +```javascript +// Parallel: All CLIs run simultaneously +async function executeParallel(clis, task) { + return await Promise.all(clis.map(cli => + execCLI(cli, buildPrompt({ ...PROMPTS.initial, taskDescription: task }), { background: true }) + )) +} + +// Sequential: Each CLI builds on previous via --resume +async function executeSequential(clis, task) { const results = [] - let previousSessionId = null - + let prevId = null for (const cli of clis) { - const resumeFlag = previousSessionId ? `--resume ${previousSessionId}` : '' - - const result = await Bash({ - command: `ccw cli -p " -PURPOSE: ${previousSessionId ? 'Build on previous analysis and deepen' : 'Initial analysis'}: ${taskDescription} -TASK: • ${previousSessionId ? 'Review previous findings • Extend analysis • Add new insights' : 'Identify affected files • Analyze implementation approach'} -MODE: analysis -CONTEXT: @**/* -EXPECTED: ${previousSessionId ? 'Extended analysis building on previous findings' : 'Initial analysis with root cause and approach'} -RULES: $(cat ~/.claude/workflows/cli-templates/protocols/analysis-protocol.md) | ${previousSessionId ? 'Build incrementally, avoid repetition' : 'Focus on actionable insights'} -" --tool ${cli.name} --mode analysis ${resumeFlag}`, - run_in_background: false - }) - + const preset = prevId ? PROMPTS.extend : PROMPTS.initial + const result = await execCLI(cli, buildPrompt({ ...preset, taskDescription: task }), { resume: prevId }) results.push(result) - previousSessionId = extractSessionId(result) // Extract session ID for next iteration + prevId = extractSessionId(result) } - return results } -``` -#### Mode 3: Collaborative (协同) -```javascript -// Multi-round synthesis: CLIs take turns refining analysis -async function executeCollaborative(clis, taskDescription, rounds = 2) { +// Collaborative: Multi-round synthesis +async function executeCollaborative(clis, task, rounds = 2) { const results = [] - let previousSessionId = null - - for (let round = 0; round < rounds; round++) { + let prevId = null + for (let r = 0; r < rounds; r++) { for (const cli of clis) { - const resumeFlag = previousSessionId ? `--resume ${previousSessionId}` : '' - const roundContext = round === 0 ? 'Initial analysis' : `Round ${round + 1}: Refine and synthesize` - - const result = await Bash({ - command: `ccw cli -p " -PURPOSE: ${roundContext} for: ${taskDescription} -TASK: • ${round === 0 ? 'Initial analysis of the problem' : 'Review previous analysis • Identify gaps • Add complementary insights • Synthesize findings'} -MODE: analysis -CONTEXT: @**/* -EXPECTED: ${round === 0 ? 'Foundational analysis' : 'Refined synthesis with new perspectives'} -RULES: $(cat ~/.claude/workflows/cli-templates/protocols/analysis-protocol.md) | ${round === 0 ? 'Be thorough' : 'Build collaboratively, add value not repetition'} -" --tool ${cli.name} --mode analysis ${resumeFlag}`, - run_in_background: false - }) - - results.push({ cli: cli.name, round, result }) - previousSessionId = extractSessionId(result) + const preset = !prevId ? PROMPTS.initial : PROMPTS.synthesize + const result = await execCLI(cli, buildPrompt({ ...preset, taskDescription: task }), { resume: prevId }) + results.push({ cli: cli.name, round: r, result }) + prevId = extractSessionId(result) } } - return results } -``` -#### Mode 4: Debate (辩论) -```javascript -// Adversarial: CLI B challenges CLI A findings, A responds -async function executeDebate(clis, taskDescription) { +// Debate: Propose → Challenge → Defend +async function executeDebate(clis, task) { const [cliA, cliB] = clis const results = [] - // Step 1: CLI A proposes initial analysis - const proposeResult = await Bash({ - command: `ccw cli -p " -PURPOSE: Propose comprehensive analysis for: ${taskDescription} -TASK: • Analyze problem thoroughly • Propose solution approach • Identify implementation details • State assumptions clearly -MODE: analysis -CONTEXT: @**/* -EXPECTED: Well-reasoned proposal with clear assumptions and trade-offs stated -RULES: $(cat ~/.claude/workflows/cli-templates/protocols/analysis-protocol.md) | Be clear about assumptions and trade-offs -" --tool ${cliA.name} --mode analysis`, - run_in_background: false - }) - results.push({ phase: 'propose', cli: cliA.name, result: proposeResult }) - const proposeSessionId = extractSessionId(proposeResult) + const propose = await execCLI(cliA, buildPrompt({ ...PROMPTS.propose, taskDescription: task })) + results.push({ phase: 'propose', cli: cliA.name, result: propose }) - // Step 2: CLI B challenges the proposal - const challengeResult = await Bash({ - command: `ccw cli -p " -PURPOSE: Challenge and stress-test the previous analysis for: ${taskDescription} -TASK: • Identify weaknesses in proposed approach • Question assumptions • Suggest alternative approaches • Highlight potential risks overlooked -MODE: analysis -CONTEXT: @**/* -EXPECTED: Constructive critique with specific counter-arguments and alternatives -RULES: $(cat ~/.claude/workflows/cli-templates/protocols/analysis-protocol.md) | Be adversarial but constructive, focus on improving the solution -" --tool ${cliB.name} --mode analysis --resume ${proposeSessionId}`, - run_in_background: false - }) - results.push({ phase: 'challenge', cli: cliB.name, result: challengeResult }) - const challengeSessionId = extractSessionId(challengeResult) + const challenge = await execCLI(cliB, buildPrompt({ ...PROMPTS.challenge, taskDescription: task }), { resume: extractSessionId(propose) }) + results.push({ phase: 'challenge', cli: cliB.name, result: challenge }) - // Step 3: CLI A defends and refines - const defendResult = await Bash({ - command: `ccw cli -p " -PURPOSE: Respond to challenges and refine analysis for: ${taskDescription} -TASK: • Address each challenge point • Defend valid aspects • Acknowledge valid criticisms • Propose refined solution incorporating feedback -MODE: analysis -CONTEXT: @**/* -EXPECTED: Refined proposal that addresses criticisms and incorporates valid alternatives -RULES: $(cat ~/.claude/workflows/cli-templates/protocols/analysis-protocol.md) | Be open to valid criticism, synthesize best ideas -" --tool ${cliA.name} --mode analysis --resume ${challengeSessionId}`, - run_in_background: false - }) - results.push({ phase: 'defend', cli: cliA.name, result: defendResult }) + const defend = await execCLI(cliA, buildPrompt({ ...PROMPTS.defend, taskDescription: task }), { resume: extractSessionId(challenge) }) + results.push({ phase: 'defend', cli: cliA.name, result: defend }) return results } -``` -#### Mode 5: Challenge (挑战) -```javascript -// Stress test: CLI B finds flaws/alternatives in CLI A analysis -async function executeChallenge(clis, taskDescription) { +// Challenge: Analyze → Criticize +async function executeChallenge(clis, task) { const [cliA, cliB] = clis const results = [] - // Step 1: CLI A provides initial analysis - const analyzeResult = await Bash({ - command: `ccw cli -p " -PURPOSE: Provide comprehensive analysis for: ${taskDescription} -TASK: • Deep analysis of problem space • Propose implementation approach • List specific changes • Identify risks -MODE: analysis -CONTEXT: @**/* -EXPECTED: Thorough analysis with clear reasoning -RULES: $(cat ~/.claude/workflows/cli-templates/protocols/analysis-protocol.md) | Be thorough and explicit about reasoning -" --tool ${cliA.name} --mode analysis`, - run_in_background: false - }) - results.push({ phase: 'analyze', cli: cliA.name, result: analyzeResult }) - const analyzeSessionId = extractSessionId(analyzeResult) + const analyze = await execCLI(cliA, buildPrompt({ ...PROMPTS.initial, taskDescription: task })) + results.push({ phase: 'analyze', cli: cliA.name, result: analyze }) - // Step 2: CLI B challenges with focus on finding flaws - const challengeResult = await Bash({ - command: `ccw cli -p " -PURPOSE: Stress-test and find weaknesses in the analysis for: ${taskDescription} -TASK: • Find logical flaws in reasoning • Identify missed edge cases • Propose better alternatives • Rate confidence in each criticism (High/Medium/Low) -MODE: analysis -CONTEXT: @**/* -EXPECTED: Detailed critique with severity ratings: [CRITICAL] [HIGH] [MEDIUM] [LOW] for each issue found -RULES: $(cat ~/.claude/workflows/cli-templates/protocols/analysis-protocol.md) | Be ruthlessly critical, find every possible flaw -" --tool ${cliB.name} --mode analysis --resume ${analyzeSessionId}`, - run_in_background: false - }) - results.push({ phase: 'challenge', cli: cliB.name, result: challengeResult }) + const criticize = await execCLI(cliB, buildPrompt({ ...PROMPTS.criticize, taskDescription: task }), { resume: extractSessionId(analyze) }) + results.push({ phase: 'challenge', cli: cliB.name, result: criticize }) return results } ``` -**Mode Router**: +### Mode Router & Result Aggregation + ```javascript async function executeAnalysis(mode, clis, taskDescription) { switch (mode.name) { - case 'parallel': - return await executeParallel(clis, taskDescription) - case 'sequential': - return await executeSequential(clis, taskDescription) - case 'collaborative': - return await executeCollaborative(clis, taskDescription) - case 'debate': - return await executeDebate(clis, taskDescription) - case 'challenge': - return await executeChallenge(clis, taskDescription) - default: - return await executeParallel(clis, taskDescription) + case 'parallel': return await executeParallel(clis, taskDescription) + case 'sequential': return await executeSequential(clis, taskDescription) + case 'collaborative': return await executeCollaborative(clis, taskDescription) + case 'debate': return await executeDebate(clis, taskDescription) + case 'challenge': return await executeChallenge(clis, taskDescription) } } -// Execute based on selected mode -const analysisResults = await executeAnalysis(selectedMode, selectedCLIs, taskDescription) -``` - -**Result Aggregation** (mode-aware): -```javascript function aggregateResults(mode, results) { - const base = { - mode: mode.name, - pattern: mode.pattern, - tools_used: results.map(r => r.cli || 'unknown') - } + const base = { mode: mode.name, pattern: mode.pattern, tools_used: results.map(r => r.cli || 'unknown') } switch (mode.name) { case 'parallel': - return { - ...base, - findings: results.map(r => parseOutput(r)), - consensus: findCommonPoints(results), - divergences: findDifferences(results) - } - + return { ...base, findings: results.map(parseOutput), consensus: findCommonPoints(results), divergences: findDifferences(results) } case 'sequential': - return { - ...base, - evolution: results.map((r, i) => ({ step: i + 1, analysis: parseOutput(r) })), - finalAnalysis: parseOutput(results[results.length - 1]) - } - + return { ...base, evolution: results.map((r, i) => ({ step: i + 1, analysis: parseOutput(r) })), finalAnalysis: parseOutput(results.at(-1)) } case 'collaborative': - return { - ...base, - rounds: groupByRound(results), - synthesis: extractSynthesis(results[results.length - 1]) - } - + return { ...base, rounds: groupByRound(results), synthesis: extractSynthesis(results.at(-1)) } case 'debate': - return { - ...base, - proposal: parseOutput(results.find(r => r.phase === 'propose')?.result), + return { ...base, proposal: parseOutput(results.find(r => r.phase === 'propose')?.result), challenges: parseOutput(results.find(r => r.phase === 'challenge')?.result), - resolution: parseOutput(results.find(r => r.phase === 'defend')?.result), - confidence: calculateDebateConfidence(results) - } - + resolution: parseOutput(results.find(r => r.phase === 'defend')?.result), confidence: calculateDebateConfidence(results) } case 'challenge': - return { - ...base, - originalAnalysis: parseOutput(results.find(r => r.phase === 'analyze')?.result), - critiques: parseCritiques(results.find(r => r.phase === 'challenge')?.result), - riskScore: calculateRiskScore(results) - } + return { ...base, originalAnalysis: parseOutput(results.find(r => r.phase === 'analyze')?.result), + critiques: parseCritiques(results.find(r => r.phase === 'challenge')?.result), riskScore: calculateRiskScore(results) } } } - -const aggregatedAnalysis = aggregateResults(selectedMode, analysisResults) ``` -### Phase 4: User Decision - -**Present Mode-Specific Summary**: +## Phase 4: User Decision ```javascript -function presentSummary(aggregatedAnalysis) { - const { mode, pattern } = aggregatedAnalysis +function presentSummary(analysis) { + console.log(`## Analysis Result\n**Mode**: ${analysis.mode} (${analysis.pattern})\n**Tools**: ${analysis.tools_used.join(' → ')}`) - console.log(` -## Analysis Result Summary - -**Mode**: ${mode} (${pattern}) -**Tools**: ${aggregatedAnalysis.tools_used.join(' → ')} -`) - - switch (mode) { + switch (analysis.mode) { case 'parallel': - console.log(` -### Consensus Points -${aggregatedAnalysis.consensus.map(c => `- ${c}`).join('\n')} - -### Divergence Points -${aggregatedAnalysis.divergences.map(d => `- ${d}`).join('\n')} -`) + console.log(`### Consensus\n${analysis.consensus.map(c => `- ${c}`).join('\n')}\n### Divergences\n${analysis.divergences.map(d => `- ${d}`).join('\n')}`) break - case 'sequential': - console.log(` -### Analysis Evolution -${aggregatedAnalysis.evolution.map(e => `**Step ${e.step}**: ${e.analysis.summary}`).join('\n')} - -### Final Analysis -${aggregatedAnalysis.finalAnalysis.summary} -`) + console.log(`### Evolution\n${analysis.evolution.map(e => `**Step ${e.step}**: ${e.analysis.summary}`).join('\n')}\n### Final\n${analysis.finalAnalysis.summary}`) break - case 'collaborative': - console.log(` -### Collaboration Rounds -${Object.entries(aggregatedAnalysis.rounds).map(([round, analyses]) => - `**Round ${round}**: ${analyses.map(a => a.cli).join(' + ')}` -).join('\n')} - -### Synthesized Result -${aggregatedAnalysis.synthesis} -`) + console.log(`### Rounds\n${Object.entries(analysis.rounds).map(([r, a]) => `**Round ${r}**: ${a.map(x => x.cli).join(' + ')}`).join('\n')}\n### Synthesis\n${analysis.synthesis}`) break - case 'debate': - console.log(` -### Debate Summary -**Proposal**: ${aggregatedAnalysis.proposal.summary} -**Challenges**: ${aggregatedAnalysis.challenges.points?.length || 0} points raised -**Resolution**: ${aggregatedAnalysis.resolution.summary} -**Confidence**: ${aggregatedAnalysis.confidence}% -`) + console.log(`### Debate\n**Proposal**: ${analysis.proposal.summary}\n**Challenges**: ${analysis.challenges.points?.length || 0} points\n**Resolution**: ${analysis.resolution.summary}\n**Confidence**: ${analysis.confidence}%`) break - case 'challenge': - console.log(` -### Challenge Summary -**Original Analysis**: ${aggregatedAnalysis.originalAnalysis.summary} -**Critiques Found**: ${aggregatedAnalysis.critiques.length} issues -${aggregatedAnalysis.critiques.map(c => `- [${c.severity}] ${c.description}`).join('\n')} -**Risk Score**: ${aggregatedAnalysis.riskScore}/100 -`) + console.log(`### Challenge\n**Original**: ${analysis.originalAnalysis.summary}\n**Critiques**: ${analysis.critiques.length} issues\n${analysis.critiques.map(c => `- [${c.severity}] ${c.description}`).join('\n')}\n**Risk Score**: ${analysis.riskScore}/100`) break } } -presentSummary(aggregatedAnalysis) -``` - -**Decision Options**: -```javascript AskUserQuestion({ questions: [{ question: "How to proceed?", header: "Next Step", options: [ - { label: "Execute directly", description: "Implement immediately based on analysis" }, - { label: "Refine analysis", description: "Provide more constraints, re-analyze" }, - { label: "Change tools", description: "Select different tool combination" }, - { label: "Cancel", description: "End current workflow" } + { label: "Execute directly", description: "Implement immediately" }, + { label: "Refine analysis", description: "Add constraints, re-analyze" }, + { label: "Change tools", description: "Different tool combination" }, + { label: "Cancel", description: "End workflow" } ], multiSelect: false }] }) +// Routing: Execute → Phase 5 | Refine → Phase 3 | Change → Phase 2 | Cancel → End ``` -**Routing Logic**: -- **Execute directly** → Phase 5 -- **Refine analysis** → Collect feedback, return to Phase 3 -- **Change tools** → Return to Phase 2 -- **Cancel** → End workflow +## Phase 5: Direct Execution -### Phase 5: Direct Execution - -**No Artifacts - Direct Implementation**: ```javascript -// Use the aggregated analysis directly -// No IMPL_PLAN.md, no plan.json, no session files - -console.log("Starting direct execution based on analysis...") - -// Execution-capable agents (canExecute: true) +// No IMPL_PLAN.md, no plan.json - direct implementation const executionAgents = agents.filter(a => a.canExecute) - -// Select execution tool: prefer execution-capable agent, fallback to CLI -const executionTool = selectedTools.find(t => - t.type === 'agent' && executionAgents.some(ea => ea.name === t.name) -) || selectedTools.find(t => t.type === 'cli') +const executionTool = selectedAgent.canExecute ? selectedAgent : selectedCLIs[0] if (executionTool.type === 'agent') { - // Use Agent for execution (preferred if available) Task({ subagent_type: executionTool.name, run_in_background: false, description: `Execute: ${taskDescription.slice(0, 30)}`, - prompt: ` -## Task -${taskDescription} - -## Analysis Results (from previous tools) -${JSON.stringify(aggregatedAnalysis, null, 2)} - -## Instructions -Based on the analysis above, implement the solution: -1. Apply changes to identified files -2. Follow the recommended approach -3. Handle identified risks -4. Verify changes work correctly -` + prompt: `## Task\n${taskDescription}\n\n## Analysis Results\n${JSON.stringify(aggregatedAnalysis, null, 2)}\n\n## Instructions\n1. Apply changes to identified files\n2. Follow recommended approach\n3. Handle identified risks\n4. Verify changes work correctly` }) } else { - // Use CLI with write mode Bash({ command: `ccw cli -p " -PURPOSE: Implement the solution based on analysis: ${taskDescription} +PURPOSE: Implement solution: ${taskDescription} TASK: ${extractedTasks.join(' • ')} MODE: write CONTEXT: @${affectedFiles.join(' @')} EXPECTED: Working implementation with all changes applied -RULES: $(cat ~/.claude/workflows/cli-templates/protocols/write-protocol.md) | Apply analysis findings directly +RULES: $(cat ~/.claude/workflows/cli-templates/protocols/write-protocol.md) " --tool ${executionTool.name} --mode write`, run_in_background: false }) @@ -718,81 +385,45 @@ RULES: $(cat ~/.claude/workflows/cli-templates/protocols/write-protocol.md) | Ap ```javascript TodoWrite({ todos: [ { content: "Phase 1: Clarify requirements", status: "in_progress", activeForm: "Clarifying requirements" }, - { content: "Phase 2: Auto-select tools", status: "pending", activeForm: "Analyzing task" }, - { content: "Phase 3: Mixed tool analysis", status: "pending", activeForm: "Running analysis" }, + { content: "Phase 2: Select tools", status: "pending", activeForm: "Selecting tools" }, + { content: "Phase 3: Multi-mode analysis", status: "pending", activeForm: "Running analysis" }, { content: "Phase 4: User decision", status: "pending", activeForm: "Awaiting decision" }, - { content: "Phase 5: Direct execution", status: "pending", activeForm: "Executing implementation" } + { content: "Phase 5: Direct execution", status: "pending", activeForm: "Executing" } ]}) ``` ## Iteration Patterns -### Pattern A: Direct Path (Most Common) -``` -Phase 1 → Phase 2 (auto) → Phase 3 → Phase 4 (execute) → Phase 5 -``` - -### Pattern B: Refinement Loop -``` -Phase 3 → Phase 4 (refine) → Phase 3 → Phase 4 → Phase 5 -``` - -### Pattern C: Tool Adjustment -``` -Phase 2 (adjust) → Phase 3 → Phase 4 → Phase 5 -``` +| Pattern | Flow | +|---------|------| +| **Direct** | Phase 1 → 2 → 3 → 4(execute) → 5 | +| **Refinement** | Phase 3 → 4(refine) → 3 → 4 → 5 | +| **Tool Adjust** | Phase 2(adjust) → 3 → 4 → 5 | ## Error Handling | Error | Resolution | |-------|------------| | CLI timeout | Retry with secondary model | -| No enabled tools | Load cli-tools.json, ask user to enable tools | -| Task type unclear | Default to first available CLI + code-developer | +| No enabled tools | Ask user to enable tools in cli-tools.json | +| Task unclear | Default to first CLI + code-developer | | Ambiguous task | Force clarification via AskUser | | Execution fails | Present error, ask user for direction | -## Analysis Modes Reference - -| Mode | Pattern | Use Case | CLI Count | -|------|---------|----------|-----------| -| **Parallel** | `A \|\| B \|\| C → Aggregate` | Fast multi-perspective analysis | 1+ | -| **Sequential** | `A → B(resume) → C(resume)` | Deep incremental analysis | 2+ | -| **Collaborative** | `A → B → A → B → Synthesize` | Multi-round refinement | 2+ | -| **Debate** | `A(propose) → B(challenge) → A(defend)` | Stress-test solutions | 2 | -| **Challenge** | `A(analyze) → B(challenge)` | Find flaws and risks | 2 | - -## Comparison +## Comparison with multi-cli-plan | Aspect | lite-lite-lite | multi-cli-plan | |--------|----------------|----------------| | **Artifacts** | None | IMPL_PLAN.md, plan.json, synthesis.json | -| **Session** | Stateless (uses --resume for chaining) | Persistent session folder | -| **Tool Selection** | Multi-CLI + Agent via 3-step selection | Config-driven with fixed tools | -| **Analysis Modes** | 5 modes (parallel/sequential/collaborative/debate/challenge) | Fixed synthesis rounds | -| **CLI Collaboration** | Auto --resume chaining | Manual session management | -| **Iteration** | Via AskUser | Via rounds/synthesis | -| **Execution** | Direct | Via lite-execute | -| **Best For** | Quick analysis, adversarial validation, rapid iteration | Complex multi-step implementations | - -## Best Practices - -1. **Be Specific**: Clear task description improves auto-selection accuracy -2. **Trust Auto-Selection**: Algorithm matches task type to tool strengths -3. **Adjust When Needed**: Use "Adjust tools" if auto-selection doesn't fit -4. **Trust Consensus**: When tools agree, confidence is high -5. **Iterate Fast**: Use refinement loop for complex requirements -6. **Direct is Fast**: Skip artifacts when task is straightforward +| **Session** | Stateless (--resume chaining) | Persistent session folder | +| **Tool Selection** | 3-step (CLI → Mode → Agent) | Config-driven fixed tools | +| **Analysis Modes** | 5 modes with --resume | Fixed synthesis rounds | +| **Best For** | Quick analysis, adversarial validation | Complex multi-step implementations | ## Related Commands ```bash -# Full planning workflow -/workflow:multi-cli-plan "complex task" - -# Single CLI planning -/workflow:lite-plan "task" - -# Direct execution -/workflow:lite-execute --in-memory +/workflow:multi-cli-plan "complex task" # Full planning workflow +/workflow:lite-plan "task" # Single CLI planning +/workflow:lite-execute --in-memory # Direct execution ``` diff --git a/ccw/src/templates/dashboard-js/views/lite-tasks.js b/ccw/src/templates/dashboard-js/views/lite-tasks.js index ba149f83..67dcee59 100644 --- a/ccw/src/templates/dashboard-js/views/lite-tasks.js +++ b/ccw/src/templates/dashboard-js/views/lite-tasks.js @@ -347,11 +347,8 @@ function extractTimelineFromSynthesis(synthesis) { return timeline; } -// Track multi-cli toolbar state -let isMultiCliToolbarExpanded = false; - /** - * Show multi-cli detail page with tabs + * Show multi-cli detail page with tabs (same layout as lite-plan) */ function showMultiCliDetailPage(sessionKey) { const session = liteTaskDataStore[sessionKey]; @@ -364,109 +361,80 @@ function showMultiCliDetailPage(sessionKey) { const container = document.getElementById('mainContent'); const metadata = session.metadata || {}; - const discussionTopic = session.discussionTopic || {}; - const latestSynthesis = session.latestSynthesis || discussionTopic; + const plan = session.plan || {}; + const tasks = plan.tasks || []; const roundCount = metadata.roundId || session.roundCount || 1; - const topicTitle = getI18nText(latestSynthesis.title) || session.topicTitle || 'Discussion Topic'; - const status = latestSynthesis.status || session.status || 'analyzing'; + const status = session.status || 'analyzing'; container.innerHTML = ` -
- -
- -
- -
-

${escapeHtml(session.id)}

-
- multi-cli-plan - ${escapeHtml(status)} -
+
+ +
+ +
+

${escapeHtml(session.id)}

+
+ MULTI-CLI
- - -
-
- ${t('detail.created') || 'Created'} - ${formatDate(metadata.timestamp || session.createdAt)} -
-
- ${t('multiCli.roundCount') || 'Rounds'} - ${roundCount} -
-
- ${t('multiCli.topic') || 'Topic'} - ${escapeHtml(topicTitle)} -
-
- - -
- - - -
- - -
- ${renderMultiCliPlanningTab(session)} -
- -
- -
- ${renderMultiCliToolbar(session)} + +
+
+ ${t('detail.created') || 'Created'} + ${formatDate(metadata.timestamp || session.createdAt)}
+
+ ${t('detail.tasks') || 'Tasks'} + ${tasks.length} ${t('session.tasks') || 'tasks'} +
+
+ + +
+ + + + + +
+ + +
+ ${renderMultiCliTasksTab(session)}
`; - // Initialize icons and collapsible sections + // Initialize icons, collapsible sections, and task click handlers setTimeout(() => { if (typeof lucide !== 'undefined') lucide.createIcons(); initCollapsibleSections(container); + initMultiCliTaskClickHandlers(); }, 50); } -/** - * Toggle multi-cli toolbar expanded/collapsed state - */ -function toggleMultiCliToolbar() { - isMultiCliToolbarExpanded = !isMultiCliToolbarExpanded; - const toolbar = document.getElementById('multiCliToolbar'); - const toggleBtn = toolbar?.querySelector('.toolbar-toggle-btn i'); - - if (toolbar) { - toolbar.classList.toggle('expanded', isMultiCliToolbarExpanded); - toolbar.classList.toggle('collapsed', !isMultiCliToolbarExpanded); - - // Update icon - if (toggleBtn) { - toggleBtn.setAttribute('data-lucide', isMultiCliToolbarExpanded ? 'panel-right-close' : 'panel-right-open'); - if (typeof lucide !== 'undefined') lucide.createIcons(); - } - } -} - /** * Render the multi-cli toolbar content */ @@ -507,10 +475,10 @@ function renderMultiCliToolbar(session) { ${tasks.map((task, idx) => { const taskTitle = task.title || task.summary || `Task ${idx + 1}`; const taskScope = task.scope || ''; - const taskId = `task-${idx}`; + const taskIdValue = task.id || `T${idx + 1}`; return ` -
+
#${idx + 1}
${escapeHtml(taskTitle)} @@ -564,6 +532,13 @@ function scrollToMultiCliTask(taskIdx) { } } +/** + * Open task drawer from toolbar (wrapper for openTaskDrawerForMultiCli) + */ +function openToolbarTaskDrawer(sessionId, taskId) { + openTaskDrawerForMultiCli(sessionId, taskId); +} + /** * Scroll to task element in the DOM */ @@ -672,21 +647,31 @@ function switchMultiCliDetailTab(tabName) { const contentArea = document.getElementById('multiCliDetailTabContent'); switch (tabName) { - case 'planning': - contentArea.innerHTML = renderMultiCliPlanningTab(session); + case 'tasks': + contentArea.innerHTML = renderMultiCliTasksTab(session); + break; + case 'plan': + contentArea.innerHTML = renderMultiCliPlanTab(session); break; case 'discussion': contentArea.innerHTML = renderMultiCliDiscussionSection(session); break; - case 'association': - contentArea.innerHTML = renderMultiCliAssociationSection(session); - break; + case 'context': + loadAndRenderMultiCliContextTab(session, contentArea); + return; // Early return as this is async + case 'summary': + loadAndRenderMultiCliSummaryTab(session, contentArea); + return; // Early return as this is async } // Re-initialize after tab switch setTimeout(() => { if (typeof lucide !== 'undefined') lucide.createIcons(); initCollapsibleSections(contentArea); + // Initialize task click handlers for tasks tab + if (tabName === 'tasks') { + initMultiCliTaskClickHandlers(); + } }, 50); } @@ -694,6 +679,383 @@ function switchMultiCliDetailTab(tabName) { // MULTI-CLI TAB RENDERERS // ============================================ +/** + * Render Tasks tab - displays tasks from plan.json (same style as lite-plan) + */ +function renderMultiCliTasksTab(session) { + const plan = session.plan || {}; + const tasks = plan.tasks || []; + + // Populate drawer tasks for click-to-open functionality + currentDrawerTasks = tasks; + + if (tasks.length === 0) { + return ` +
+
+
${t('empty.noTasks') || 'No Tasks'}
+
${t('empty.noTasksText') || 'No tasks available for this session.'}
+
+ `; + } + + return ` +
+
+ ${tasks.map((task, idx) => renderMultiCliTaskItem(session.id, task, idx)).join('')} +
+
+ `; +} + +/** + * Render Plan tab - displays plan.json content (summary, approach, metadata) + */ +function renderMultiCliPlanTab(session) { + const plan = session.plan; + + if (!plan) { + return ` +
+
+
${t('multiCli.empty.planning') || 'No Plan Data'}
+
${t('multiCli.empty.planningText') || 'No plan.json found for this session.'}
+
+ `; + } + + return ` +
+ + ${plan.summary ? ` +
+

Summary

+

${escapeHtml(plan.summary)}

+
+ ` : ''} + + + ${plan.root_cause ? ` +
+

Root Cause

+

${escapeHtml(plan.root_cause)}

+
+ ` : ''} + + + ${plan.strategy ? ` +
+

Fix Strategy

+

${escapeHtml(plan.strategy)}

+
+ ` : ''} + + + ${plan.approach ? ` +
+

Approach

+

${escapeHtml(plan.approach)}

+
+ ` : ''} + + + ${plan.user_requirements ? ` +
+

User Requirements

+

${escapeHtml(plan.user_requirements)}

+
+ ` : ''} + + + ${plan.focus_paths?.length ? ` +
+

Focus Paths

+
+ ${plan.focus_paths.map(p => `${escapeHtml(p)}`).join('')} +
+
+ ` : ''} + + +
+

Metadata

+
+ ${plan.severity ? `
Severity: ${escapeHtml(plan.severity)}
` : ''} + ${plan.risk_level ? `
Risk Level: ${escapeHtml(plan.risk_level)}
` : ''} + ${plan.estimated_time ? `
Estimated Time: ${escapeHtml(plan.estimated_time)}
` : ''} + ${plan.complexity ? `
Complexity: ${escapeHtml(plan.complexity)}
` : ''} + ${plan.recommended_execution ? `
Execution: ${escapeHtml(plan.recommended_execution)}
` : ''} +
+
+ + +
+
+ + +
+ +
+
+ `; +} + +/** + * Load and render Context tab - displays context-package content + */ +async function loadAndRenderMultiCliContextTab(session, contentArea) { + contentArea.innerHTML = `
${t('common.loading') || 'Loading...'}
`; + + try { + if (window.SERVER_MODE && session.path) { + const response = await fetch(`/api/session-detail?path=${encodeURIComponent(session.path)}&type=context`); + if (response.ok) { + const data = await response.json(); + contentArea.innerHTML = renderMultiCliContextContent(data.context, session); + initCollapsibleSections(contentArea); + if (typeof lucide !== 'undefined') lucide.createIcons(); + return; + } + } + // Fallback: show session context_package if available + contentArea.innerHTML = renderMultiCliContextContent(session.context_package, session); + initCollapsibleSections(contentArea); + if (typeof lucide !== 'undefined') lucide.createIcons(); + } catch (err) { + contentArea.innerHTML = `
Failed to load context: ${err.message}
`; + } +} + +/** + * Render context content for multi-cli + */ +function renderMultiCliContextContent(context, session) { + // Also check for context_package in session + const ctx = context || session.context_package || {}; + + if (!ctx || Object.keys(ctx).length === 0) { + return ` +
+
+
${t('empty.noContext') || 'No Context Data'}
+
${t('empty.noContextText') || 'No context package available for this session.'}
+
+ `; + } + + let sections = []; + + // Task Description + if (ctx.task_description) { + sections.push(` +
+

Task Description

+

${escapeHtml(ctx.task_description)}

+
+ `); + } + + // Constraints + if (ctx.constraints?.length) { + sections.push(` +
+

Constraints

+
    + ${ctx.constraints.map(c => `
  • ${escapeHtml(c)}
  • `).join('')} +
+
+ `); + } + + // Focus Paths + if (ctx.focus_paths?.length) { + sections.push(` +
+

Focus Paths

+
+ ${ctx.focus_paths.map(p => `${escapeHtml(p)}`).join('')} +
+
+ `); + } + + // Relevant Files + if (ctx.relevant_files?.length) { + sections.push(` +
+
+ + +
+ +
+ `); + } + + // Dependencies + if (ctx.dependencies?.length) { + sections.push(` +
+
+ + +
+ +
+ `); + } + + // Conflict Risks + if (ctx.conflict_risks?.length) { + sections.push(` +
+

Conflict Risks

+
    + ${ctx.conflict_risks.map(r => `
  • ${escapeHtml(typeof r === 'string' ? r : r.description || JSON.stringify(r))}
  • `).join('')} +
+
+ `); + } + + // Session ID + if (ctx.session_id) { + sections.push(` +
+

Session ID

+ ${escapeHtml(ctx.session_id)} +
+ `); + } + + // Raw JSON + sections.push(` +
+
+ + +
+ +
+ `); + + return `
${sections.join('')}
`; +} + +/** + * Load and render Summary tab + */ +async function loadAndRenderMultiCliSummaryTab(session, contentArea) { + contentArea.innerHTML = `
${t('common.loading') || 'Loading...'}
`; + + try { + if (window.SERVER_MODE && session.path) { + const response = await fetch(`/api/session-detail?path=${encodeURIComponent(session.path)}&type=summary`); + if (response.ok) { + const data = await response.json(); + contentArea.innerHTML = renderMultiCliSummaryContent(data.summary, session); + initCollapsibleSections(contentArea); + if (typeof lucide !== 'undefined') lucide.createIcons(); + return; + } + } + // Fallback: show synthesis summary + contentArea.innerHTML = renderMultiCliSummaryContent(null, session); + initCollapsibleSections(contentArea); + if (typeof lucide !== 'undefined') lucide.createIcons(); + } catch (err) { + contentArea.innerHTML = `
Failed to load summary: ${err.message}
`; + } +} + +/** + * Render summary content for multi-cli + */ +function renderMultiCliSummaryContent(summary, session) { + const synthesis = session.latestSynthesis || session.discussionTopic || {}; + const plan = session.plan || {}; + + // Use summary from file or build from synthesis + const summaryText = summary || synthesis.convergence?.summary || plan.summary; + + if (!summaryText && !synthesis.solutions?.length) { + return ` +
+
+
${t('empty.noSummary') || 'No Summary'}
+
${t('empty.noSummaryText') || 'No summary available for this session.'}
+
+ `; + } + + let sections = []; + + // Main Summary + if (summaryText) { + const summaryContent = typeof summaryText === 'string' ? summaryText : getI18nText(summaryText); + sections.push(` +
+

Summary

+
${escapeHtml(summaryContent)}
+
+ `); + } + + // Convergence Status + if (synthesis.convergence) { + const conv = synthesis.convergence; + sections.push(` +
+

Convergence

+
+ ${escapeHtml(conv.level || 'unknown')} + ${escapeHtml(conv.recommendation || '')} +
+
+ `); + } + + // Solutions Summary + if (synthesis.solutions?.length) { + sections.push(` +
+
+ + +
+ +
+ `); + } + + return `
${sections.join('')}
`; +} + /** * Render Discussion Topic tab * Shows: title, description, scope, keyQuestions, status, tags @@ -980,53 +1342,12 @@ function renderMultiCliPlanningTab(session) {
- + ${plan.tasks?.length ? `

Tasks (${plan.tasks.length})

-
- ${plan.tasks.map((task, idx) => ` -
-
- - #${idx + 1} - ${escapeHtml(task.title || task.summary || 'Untitled')} - ${task.scope ? `${escapeHtml(task.scope)}` : ''} -
- -
- `).join('')} +
+ ${plan.tasks.map((task, idx) => renderMultiCliTaskItem(session.id, task, idx)).join('')}
` : ''} @@ -1045,6 +1366,346 @@ function renderMultiCliPlanningTab(session) { `; } +/** + * Render a single task item for multi-cli-plan (reuses lite-plan style) + * Supports click to open drawer for details + */ +function renderMultiCliTaskItem(sessionId, task, idx) { + const taskId = task.id || `T${idx + 1}`; + const taskJsonId = `multi-cli-task-${sessionId}-${taskId}`.replace(/[^a-zA-Z0-9-]/g, '-'); + taskJsonStore[taskJsonId] = task; + + // Get preview info + const action = task.action || ''; + const scope = task.scope || task.file || ''; + const modCount = task.modification_points?.length || 0; + const implCount = task.implementation?.length || 0; + const acceptCount = task.acceptance?.length || 0; + + // Escape for data attributes + const safeSessionId = escapeHtml(sessionId); + const safeTaskId = escapeHtml(taskId); + + return ` +
+
+ ${escapeHtml(taskId)} + ${escapeHtml(task.title || task.summary || 'Untitled')} + +
+
+ ${action ? `${escapeHtml(action)}` : ''} + ${scope ? `${escapeHtml(scope)}` : ''} + ${modCount > 0 ? `${modCount} mods` : ''} + ${implCount > 0 ? `${implCount} steps` : ''} + ${acceptCount > 0 ? `${acceptCount} acceptance` : ''} +
+
+ `; +} + +/** + * Initialize click handlers for multi-cli task items + */ +function initMultiCliTaskClickHandlers() { + // Task item click handlers + document.querySelectorAll('.multi-cli-task-item').forEach(item => { + if (!item._clickBound) { + item._clickBound = true; + item.addEventListener('click', function(e) { + // Don't trigger if clicking on JSON button + if (e.target.closest('.btn-view-json')) return; + + const sessionId = this.dataset.sessionId; + const taskId = this.dataset.taskId; + openTaskDrawerForMultiCli(sessionId, taskId); + }); + } + }); + + // JSON button click handlers + document.querySelectorAll('.multi-cli-task-item .btn-view-json').forEach(btn => { + if (!btn._clickBound) { + btn._clickBound = true; + btn.addEventListener('click', function(e) { + e.stopPropagation(); + const taskJsonId = this.dataset.taskJsonId; + const displayId = this.dataset.taskDisplayId; + showJsonModal(taskJsonId, displayId); + }); + } + }); +} + +/** + * Open task drawer for multi-cli task + */ +function openTaskDrawerForMultiCli(sessionId, taskId) { + const session = liteTaskDataStore[currentSessionDetailKey]; + if (!session || !session.plan) return; + + const task = session.plan.tasks?.find(t => (t.id || `T${session.plan.tasks.indexOf(t) + 1}`) === taskId); + if (!task) return; + + // Set current drawer tasks + currentDrawerTasks = session.plan.tasks || []; + window._currentDrawerSession = session; + + document.getElementById('drawerTaskTitle').textContent = task.title || task.summary || taskId; + document.getElementById('drawerContent').innerHTML = renderMultiCliTaskDrawerContent(task, session); + document.getElementById('taskDetailDrawer').classList.add('open'); + document.getElementById('drawerOverlay').classList.add('active'); + + // Re-init lucide icons in drawer + setTimeout(() => { + if (typeof lucide !== 'undefined') lucide.createIcons(); + }, 50); +} + +/** + * Render drawer content for multi-cli task + */ +function renderMultiCliTaskDrawerContent(task, session) { + const taskId = task.id || 'Task'; + const action = task.action || ''; + + return ` + +
+ ${escapeHtml(taskId)} + ${action ? `${escapeHtml(action.toUpperCase())}` : ''} +
+ + +
+ + + + +
+ + +
+ +
+ ${renderMultiCliTaskOverview(task)} +
+ + +
+ ${renderMultiCliTaskImplementation(task)} +
+ + +
+ ${renderMultiCliTaskFiles(task)} +
+ + +
+
${escapeHtml(JSON.stringify(task, null, 2))}
+
+
+ `; +} + +/** + * Switch drawer tab for multi-cli task + */ +function switchMultiCliDrawerTab(tabName) { + document.querySelectorAll('.drawer-tab').forEach(tab => { + tab.classList.toggle('active', tab.dataset.tab === tabName); + }); + document.querySelectorAll('.drawer-panel').forEach(panel => { + panel.classList.toggle('active', panel.dataset.tab === tabName); + }); +} + +/** + * Render multi-cli task overview section + */ +function renderMultiCliTaskOverview(task) { + let sections = []; + + // Description Card + if (task.description) { + sections.push(` +
+
+ 📝 +

Description

+
+
+

${escapeHtml(task.description)}

+
+
+ `); + } + + // Scope Card + if (task.scope || task.file) { + sections.push(` +
+
+ 📂 +

Scope

+
+
+
+ ${escapeHtml(task.scope || task.file)} +
+
+
+ `); + } + + // Acceptance Criteria Card + if (task.acceptance?.length) { + sections.push(` +
+
+ +

Acceptance Criteria

+
+
+
    + ${task.acceptance.map(ac => `
  • ${escapeHtml(ac)}
  • `).join('')} +
+
+
+ `); + } + + // Reference Card + if (task.reference) { + const ref = task.reference; + sections.push(` +
+
+ 📚 +

Reference

+
+
+ ${ref.pattern ? `
PATTERN: ${escapeHtml(ref.pattern)}
` : ''} + ${ref.files?.length ? `
FILES:
${ref.files.map(f => escapeHtml(f)).join('\n')}
` : ''} + ${ref.examples ? `
EXAMPLES: ${escapeHtml(ref.examples)}
` : ''} +
+
+ `); + } + + return sections.length ? sections.join('') : '
No overview data available
'; +} + +/** + * Render multi-cli task implementation section + */ +function renderMultiCliTaskImplementation(task) { + let sections = []; + + // Modification Points + if (task.modification_points?.length) { + sections.push(` +
+

+ + Modification Points +

+
    + ${task.modification_points.map(mp => ` +
  • + ${escapeHtml(mp.file || '')} + ${mp.target ? `→ ${escapeHtml(mp.target)}` : ''} + ${mp.function_name ? `→ ${escapeHtml(mp.function_name)}` : ''} + ${mp.change || mp.change_type ? `(${escapeHtml(mp.change || mp.change_type)})` : ''} +
  • + `).join('')} +
+
+ `); + } + + // Implementation Steps + if (task.implementation?.length) { + sections.push(` +
+

+ + Implementation Steps +

+
    + ${task.implementation.map((step, idx) => ` +
  1. + ${idx + 1} + ${escapeHtml(step)} +
  2. + `).join('')} +
+
+ `); + } + + // Verification + if (task.verification?.length) { + sections.push(` +
+

+ + Verification +

+
    + ${task.verification.map(v => `
  • ${escapeHtml(v)}
  • `).join('')} +
+
+ `); + } + + return sections.length ? sections.join('') : '
No implementation details available
'; +} + +/** + * Render multi-cli task files section + */ +function renderMultiCliTaskFiles(task) { + const files = []; + + // Collect from modification_points + if (task.modification_points) { + task.modification_points.forEach(mp => { + if (mp.file && !files.includes(mp.file)) files.push(mp.file); + }); + } + + // Collect from scope/file + if (task.scope && !files.includes(task.scope)) files.push(task.scope); + if (task.file && !files.includes(task.file)) files.push(task.file); + + // Collect from reference.files + if (task.reference?.files) { + task.reference.files.forEach(f => { + if (f && !files.includes(f)) files.push(f); + }); + } + + if (files.length === 0) { + return '
No files specified
'; + } + + return ` +
+

Target Files

+
    + ${files.map(f => ` +
  • + 📄 + ${escapeHtml(f)} +
  • + `).join('')} +
+
+ `; +} + /** * Render a single requirement item */