diff --git a/.claude/agents/cli-lite-planning-agent.md b/.claude/agents/cli-lite-planning-agent.md index 19653aec..5ce2a429 100644 --- a/.claude/agents/cli-lite-planning-agent.md +++ b/.claude/agents/cli-lite-planning-agent.md @@ -1,138 +1,115 @@ --- name: cli-lite-planning-agent description: | - Specialized agent for executing CLI planning tools (Gemini/Qwen) to generate detailed implementation plans. Used by lite-plan workflow for Medium/High complexity tasks. + Generic planning agent for lite-plan and lite-fix workflows. Generates structured plan JSON based on provided schema reference. Core capabilities: - - Task decomposition (1-10 tasks with IDs: T1, T2...) - - Dependency analysis (depends_on references) - - Flow control (parallel/sequential phases) - - Multi-angle exploration context integration + - Schema-driven output (plan-json-schema or fix-plan-json-schema) + - Task decomposition with dependency analysis + - CLI execution ID assignment for fork/merge strategies + - Multi-angle context integration (explorations or diagnoses) color: cyan --- -You are a specialized execution agent that bridges CLI planning tools (Gemini/Qwen) with lite-plan workflow. You execute CLI commands for task breakdown, parse structured results, and generate planObject for downstream execution. +You are a generic planning agent that generates structured plan JSON for lite workflows. Output format is determined by the schema reference provided in the prompt. You execute CLI planning tools (Gemini/Qwen), parse results, and generate planObject conforming to the specified schema. -## Output Schema - -**Reference**: `~/.claude/workflows/cli-templates/schemas/plan-json-schema.json` - -**planObject Structure**: -```javascript -{ - summary: string, // 2-3 sentence overview - approach: string, // High-level strategy - tasks: [TaskObject], // 1-10 structured tasks - flow_control: { // Execution phases - execution_order: [{ phase, tasks, type }], - exit_conditions: { success, failure } - }, - focus_paths: string[], // Affected files (aggregated) - estimated_time: string, - recommended_execution: "Agent" | "Codex", - complexity: "Low" | "Medium" | "High", - _metadata: { timestamp, source, planning_mode, exploration_angles, duration_seconds } -} -``` - -**TaskObject Structure**: -```javascript -{ - id: string, // T1, T2, T3... - title: string, // Action verb + target - file: string, // Target file path - action: string, // Create|Update|Implement|Refactor|Add|Delete|Configure|Test|Fix - description: string, // What to implement (1-2 sentences) - modification_points: [{ // Precise changes (optional) - file: string, - target: string, // function:lineRange - change: string - }], - implementation: string[], // 2-7 actionable steps - reference: { // Pattern guidance (optional) - pattern: string, - files: string[], - examples: string - }, - acceptance: string[], // 1-4 quantified criteria - depends_on: string[] // Task IDs: ["T1", "T2"] -} -``` ## Input Context ```javascript { - task_description: string, - explorationsContext: { [angle]: ExplorationResult } | null, - explorationAngles: string[], + // Required + task_description: string, // Task or bug description + schema_path: string, // Schema reference path (plan-json-schema or fix-plan-json-schema) + session: { id, folder, artifacts }, + + // Context (one of these based on workflow) + explorationsContext: { [angle]: ExplorationResult } | null, // From lite-plan + diagnosesContext: { [angle]: DiagnosisResult } | null, // From lite-fix + contextAngles: string[], // Exploration or diagnosis angles + + // Optional clarificationContext: { [question]: answer } | null, - complexity: "Low" | "Medium" | "High", - cli_config: { tool, template, timeout, fallback }, - session: { id, folder, artifacts } + complexity: "Low" | "Medium" | "High", // For lite-plan + severity: "Low" | "Medium" | "High" | "Critical", // For lite-fix + cli_config: { tool, template, timeout, fallback } } ``` +## Schema-Driven Output + +**CRITICAL**: Read the schema reference first to determine output structure: +- `plan-json-schema.json` → Implementation plan with `approach`, `complexity` +- `fix-plan-json-schema.json` → Fix plan with `root_cause`, `severity`, `risk_level` + +```javascript +// Step 1: Always read schema first +const schema = Bash(`cat ${schema_path}`) + +// Step 2: Generate plan conforming to schema +const planObject = generatePlanFromSchema(schema, context) +``` + ## Execution Flow ``` -Phase 1: CLI Execution -├─ Aggregate multi-angle exploration findings +Phase 1: Schema & Context Loading +├─ Read schema reference (plan-json-schema or fix-plan-json-schema) +├─ Aggregate multi-angle context (explorations or diagnoses) +└─ Determine output structure from schema + +Phase 2: CLI Execution ├─ Construct CLI command with planning template ├─ Execute Gemini (fallback: Qwen → degraded mode) └─ Timeout: 60 minutes -Phase 2: Parsing & Enhancement -├─ Parse CLI output sections (Summary, Approach, Tasks, Flow Control) +Phase 3: Parsing & Enhancement +├─ Parse CLI output sections ├─ Validate and enhance task objects -└─ Infer missing fields from exploration context +└─ Infer missing fields from context -Phase 3: planObject Generation -├─ Build planObject from parsed results -├─ Generate flow_control from depends_on if not provided -├─ Aggregate focus_paths from all tasks -└─ Return to orchestrator (lite-plan) +Phase 4: planObject Generation +├─ Build planObject conforming to schema +├─ Assign CLI execution IDs and strategies +├─ Generate flow_control from depends_on +└─ Return to orchestrator ``` ## CLI Command Template ```bash ccw cli exec " -PURPOSE: Generate implementation plan for {complexity} task +PURPOSE: Generate plan for {task_description} TASK: -• Analyze: {task_description} -• Break down into 1-10 tasks with: id, title, file, action, description, modification_points, implementation, reference, acceptance, depends_on -• Identify parallel vs sequential execution phases +• Analyze task/bug description and context +• Break down into tasks following schema structure +• Identify dependencies and execution phases MODE: analysis -CONTEXT: @**/* | Memory: {exploration_summary} +CONTEXT: @**/* | Memory: {context_summary} EXPECTED: -## Implementation Summary +## Summary [overview] -## High-Level Approach -[strategy] - ## Task Breakdown -### T1: [Title] -**File**: [path] +### T1: [Title] (or FIX1 for fix-plan) +**Scope**: [module/feature path] **Action**: [type] **Description**: [what] **Modification Points**: - [file]: [target] - [change] **Implementation**: 1. [step] -**Reference**: - Pattern: [name] - Files: [paths] - Examples: [guidance] -**Acceptance**: - [quantified criterion] +**Acceptance/Verification**: - [quantified criterion] **Depends On**: [] ## Flow Control **Execution Order**: - Phase parallel-1: [T1, T2] (independent) -**Exit Conditions**: - Success: [condition] - Failure: [condition] ## Time Estimate **Total**: [time] RULES: $(cat ~/.claude/workflows/cli-templates/prompts/planning/02-breakdown-task-steps.txt) | -- Acceptance must be quantified (counts, method names, metrics) -- Dependencies use task IDs (T1, T2) +- Follow schema structure from {schema_path} +- Acceptance/verification must be quantified +- Dependencies use task IDs - analysis=READ-ONLY " --tool {cli_tool} --cd {project_root} ``` @@ -279,6 +256,51 @@ function inferFile(task, ctx) { } ``` +### CLI Execution ID Assignment (MANDATORY) + +```javascript +function assignCliExecutionIds(tasks, sessionId) { + const taskMap = new Map(tasks.map(t => [t.id, t])) + const childCount = new Map() + + // Count children for each task + tasks.forEach(task => { + (task.depends_on || []).forEach(depId => { + childCount.set(depId, (childCount.get(depId) || 0) + 1) + }) + }) + + tasks.forEach(task => { + task.cli_execution_id = `${sessionId}-${task.id}` + const deps = task.depends_on || [] + + if (deps.length === 0) { + task.cli_execution = { strategy: "new" } + } else if (deps.length === 1) { + const parent = taskMap.get(deps[0]) + const parentChildCount = childCount.get(deps[0]) || 0 + task.cli_execution = parentChildCount === 1 + ? { strategy: "resume", resume_from: parent.cli_execution_id } + : { strategy: "fork", resume_from: parent.cli_execution_id } + } else { + task.cli_execution = { + strategy: "merge_fork", + merge_from: deps.map(depId => taskMap.get(depId).cli_execution_id) + } + } + }) + return tasks +} +``` + +**Strategy Rules**: +| depends_on | Parent Children | Strategy | CLI Command | +|------------|-----------------|----------|-------------| +| [] | - | `new` | `--id {cli_execution_id}` | +| [T1] | 1 | `resume` | `--resume {resume_from}` | +| [T1] | >1 | `fork` | `--resume {resume_from} --id {cli_execution_id}` | +| [T1,T2] | - | `merge_fork` | `--resume {ids.join(',')} --id {cli_execution_id}` | + ### Flow Control Inference ```javascript @@ -303,21 +325,44 @@ function inferFlowControl(tasks) { ### planObject Generation ```javascript -function generatePlanObject(parsed, enrichedContext, input) { +function generatePlanObject(parsed, enrichedContext, input, schemaType) { const tasks = validateAndEnhanceTasks(parsed.raw_tasks, enrichedContext) + assignCliExecutionIds(tasks, input.session.id) // MANDATORY: Assign CLI execution IDs const flow_control = parsed.flow_control?.execution_order?.length > 0 ? parsed.flow_control : inferFlowControl(tasks) - const focus_paths = [...new Set(tasks.flatMap(t => [t.file, ...t.modification_points.map(m => m.file)]).filter(Boolean))] + const focus_paths = [...new Set(tasks.flatMap(t => [t.file || t.scope, ...t.modification_points.map(m => m.file)]).filter(Boolean))] - return { - summary: parsed.summary || `Implementation plan for: ${input.task_description.slice(0, 100)}`, - approach: parsed.approach || "Step-by-step implementation", + // Base fields (common to both schemas) + const base = { + summary: parsed.summary || `Plan for: ${input.task_description.slice(0, 100)}`, tasks, flow_control, focus_paths, estimated_time: parsed.time_estimate || `${tasks.length * 30} minutes`, - recommended_execution: input.complexity === "Low" ? "Agent" : "Codex", - complexity: input.complexity, - _metadata: { timestamp: new Date().toISOString(), source: "cli-lite-planning-agent", planning_mode: "agent-based", exploration_angles: input.explorationAngles || [], duration_seconds: Math.round((Date.now() - startTime) / 1000) } + recommended_execution: (input.complexity === "Low" || input.severity === "Low") ? "Agent" : "Codex", + _metadata: { + timestamp: new Date().toISOString(), + source: "cli-lite-planning-agent", + planning_mode: "agent-based", + context_angles: input.contextAngles || [], + duration_seconds: Math.round((Date.now() - startTime) / 1000) + } + } + + // Schema-specific fields + if (schemaType === 'fix-plan') { + return { + ...base, + root_cause: parsed.root_cause || "Root cause from diagnosis", + strategy: parsed.strategy || "comprehensive_fix", + severity: input.severity || "Medium", + risk_level: parsed.risk_level || "medium" + } + } else { + return { + ...base, + approach: parsed.approach || "Step-by-step implementation", + complexity: input.complexity || "Medium" + } } } ``` @@ -383,9 +428,12 @@ function validateTask(task) { ## Key Reminders **ALWAYS**: -- Generate task IDs (T1, T2, T3...) +- **Read schema first** to determine output structure +- Generate task IDs (T1/T2 for plan, FIX1/FIX2 for fix-plan) - Include depends_on (even if empty []) -- Quantify acceptance criteria +- **Assign cli_execution_id** (`{sessionId}-{taskId}`) +- **Compute cli_execution strategy** based on depends_on +- Quantify acceptance/verification criteria - Generate flow_control from dependencies - Handle CLI errors with fallback chain @@ -394,3 +442,5 @@ function validateTask(task) { - Use vague acceptance criteria - Create circular dependencies - Skip task validation +- **Skip CLI execution ID assignment** +- **Ignore schema structure** diff --git a/.claude/commands/workflow/lite-fix.md b/.claude/commands/workflow/lite-fix.md index ca5150d4..38683edc 100644 --- a/.claude/commands/workflow/lite-fix.md +++ b/.claude/commands/workflow/lite-fix.md @@ -54,14 +54,6 @@ 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 - +- CLI Execution ID Assignment (MANDATORY for all tasks): - |- Generate cli_execution_id for each task (format: {sessionId}-{task.id}) - +- Compute cli_execution strategy based on depends_on: - |- No deps -> strategy: "new" - |- 1 dep + sequential -> strategy: "resume", resume_from: parent.cli_execution_id - |- 1 dep + parallel children -> strategy: "fork", resume_from: parent.cli_execution_id - |- N deps -> strategy: "merge", merge_from: [parent1.cli_execution_id, ...] - +- N deps + creates branch -> strategy: "merge_fork", merge_from: [...], new ID Phase 4: Confirmation & Selection |- Display fix-plan summary (tasks, severity, estimated time) @@ -389,7 +381,7 @@ const fixPlan = { summary: "...", root_cause: "...", strategy: "immediate_patch|comprehensive_fix|refactor", - tasks: [...], // Each task: { id, title, scope, ..., depends_on, cli_execution_id, cli_execution } + tasks: [...], // Each task: { id, title, scope, ..., depends_on, complexity } estimated_time: "...", recommended_execution: "Agent", severity: severity, @@ -397,66 +389,10 @@ const fixPlan = { _metadata: { timestamp: getUtc8ISOString(), source: "direct-planning", planning_mode: "direct" } } -// Step 3: ⚠️ MANDATORY - Assign CLI Execution IDs and strategies -assignCliExecutionIds(fixPlan.tasks, sessionId) - -// Step 4: Write fix-plan to session folder +// Step 3: 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 -``` - -**CLI Execution ID Assignment Function** (MANDATORY for ALL planning modes): -```javascript -function assignCliExecutionIds(tasks, sessionId) { - // Build dependency graph - const taskMap = new Map(tasks.map(t => [t.id, t])) - const childCount = new Map() // Track how many tasks depend on each task - - tasks.forEach(task => { - (task.depends_on || []).forEach(depId => { - childCount.set(depId, (childCount.get(depId) || 0) + 1) - }) - }) - - tasks.forEach(task => { - // Assign unique CLI execution ID - task.cli_execution_id = `${sessionId}-${task.id}` - - const deps = task.depends_on || [] - - if (deps.length === 0) { - // No dependencies: new conversation - task.cli_execution = { strategy: "new" } - } else if (deps.length === 1) { - const parent = taskMap.get(deps[0]) - const parentChildCount = childCount.get(deps[0]) || 0 - - if (parentChildCount === 1) { - // Single child: resume (continue same conversation) - task.cli_execution = { - strategy: "resume", - resume_from: parent.cli_execution_id - } - } else { - // Multiple children: fork (create new branch) - task.cli_execution = { - strategy: "fork", - resume_from: parent.cli_execution_id - } - } - } else { - // Multiple dependencies: merge - const mergeFrom = deps.map(depId => taskMap.get(depId).cli_execution_id) - task.cli_execution = { - strategy: "merge_fork", // Merge always creates new ID - merge_from: mergeFrom - } - } - }) - - return tasks -} +// Step 4: MUST continue to Phase 4 (Confirmation) - DO NOT execute code here ``` **High/Critical Severity** - Invoke cli-lite-planning-agent: @@ -471,15 +407,6 @@ Generate fix plan and write fix-plan.json. ## Output Schema Reference Execute: cat ~/.claude/workflows/cli-templates/schemas/fix-plan-json-schema.json (get schema reference before generating plan) -## CLI Execution ID Requirements (MANDATORY) -After generating tasks, you MUST assign CLI execution IDs and strategies: -1. Each task needs cli_execution_id: {sessionId}-{task.id} -2. Compute cli_execution.strategy based on depends_on: - - No deps → { strategy: "new" } - - 1 dep (single child) → { strategy: "resume", resume_from: parent.cli_execution_id } - - 1 dep (multiple children) → { strategy: "fork", resume_from: parent.cli_execution_id } - - N deps → { strategy: "merge_fork", merge_from: [parent1.cli_execution_id, ...] } - ## Bug Description ${bug_description} diff --git a/.claude/commands/workflow/lite-plan.md b/.claude/commands/workflow/lite-plan.md index 59837e04..d575869d 100644 --- a/.claude/commands/workflow/lite-plan.md +++ b/.claude/commands/workflow/lite-plan.md @@ -54,14 +54,6 @@ Phase 3: Planning (NO CODE EXECUTION - planning only) └─ Decision (based on Phase 1 complexity): ├─ Low → Load schema: cat ~/.claude/workflows/cli-templates/schemas/plan-json-schema.json → Direct Claude planning (following schema) → plan.json → MUST proceed to Phase 4 └─ Medium/High → cli-lite-planning-agent → plan.json → MUST proceed to Phase 4 - └─ CLI Execution ID Assignment (MANDATORY for all tasks): - ├─ Generate cli_execution_id for each task (format: {sessionId}-T{N}) - └─ Compute cli_execution strategy based on depends_on: - ├─ No deps → strategy: "new" - ├─ 1 dep + sequential → strategy: "resume", resume_from: parent.cli_execution_id - ├─ 1 dep + parallel children → strategy: "fork", resume_from: parent.cli_execution_id - ├─ N deps → strategy: "merge", merge_from: [parent1.cli_execution_id, ...] - └─ N deps + creates branch → strategy: "merge_fork", merge_from: [...], new ID Phase 4: Confirmation & Selection ├─ Display plan summary (tasks, complexity, estimated time) @@ -381,73 +373,17 @@ manifest.explorations.forEach(exp => { const plan = { summary: "...", approach: "...", - tasks: [...], // Each task: { id, title, scope, ..., depends_on, cli_execution_id, cli_execution } + tasks: [...], // Each task: { id, title, scope, ..., depends_on, execution_group, complexity } estimated_time: "...", recommended_execution: "Agent", complexity: "Low", _metadata: { timestamp: getUtc8ISOString(), source: "direct-planning", planning_mode: "direct" } } -// Step 4: ⚠️ MANDATORY - Assign CLI Execution IDs and strategies -assignCliExecutionIds(plan.tasks, sessionId) - -// Step 5: Write plan to session folder +// Step 4: Write plan to session folder Write(`${sessionFolder}/plan.json`, JSON.stringify(plan, null, 2)) -// Step 6: MUST continue to Phase 4 (Confirmation) - DO NOT execute code here -``` - -**CLI Execution ID Assignment Function** (MANDATORY for ALL planning modes): -```javascript -function assignCliExecutionIds(tasks, sessionId) { - // Build dependency graph - const taskMap = new Map(tasks.map(t => [t.id, t])) - const childCount = new Map() // Track how many tasks depend on each task - - tasks.forEach(task => { - (task.depends_on || []).forEach(depId => { - childCount.set(depId, (childCount.get(depId) || 0) + 1) - }) - }) - - tasks.forEach(task => { - // Assign unique CLI execution ID - task.cli_execution_id = `${sessionId}-${task.id}` - - const deps = task.depends_on || [] - - if (deps.length === 0) { - // No dependencies: new conversation - task.cli_execution = { strategy: "new" } - } else if (deps.length === 1) { - const parent = taskMap.get(deps[0]) - const parentChildCount = childCount.get(deps[0]) || 0 - - if (parentChildCount === 1) { - // Single child: resume (continue same conversation) - task.cli_execution = { - strategy: "resume", - resume_from: parent.cli_execution_id - } - } else { - // Multiple children: fork (create new branch) - task.cli_execution = { - strategy: "fork", - resume_from: parent.cli_execution_id - } - } - } else { - // Multiple dependencies: merge - const mergeFrom = deps.map(depId => taskMap.get(depId).cli_execution_id) - task.cli_execution = { - strategy: "merge_fork", // Merge always creates new ID - merge_from: mergeFrom - } - } - }) - - return tasks -} +// Step 5: MUST continue to Phase 4 (Confirmation) - DO NOT execute code here ``` **Medium/High Complexity** - Invoke cli-lite-planning-agent: @@ -462,15 +398,6 @@ Generate implementation plan and write plan.json. ## Output Schema Reference Execute: cat ~/.claude/workflows/cli-templates/schemas/plan-json-schema.json (get schema reference before generating plan) -## CLI Execution ID Requirements (MANDATORY) -After generating tasks, you MUST assign CLI execution IDs and strategies: -1. Each task needs cli_execution_id: {sessionId}-{task.id} -2. Compute cli_execution.strategy based on depends_on: - - No deps → { strategy: "new" } - - 1 dep (single child) → { strategy: "resume", resume_from: parent.cli_execution_id } - - 1 dep (multiple children) → { strategy: "fork", resume_from: parent.cli_execution_id } - - N deps → { strategy: "merge_fork", merge_from: [parent1.cli_execution_id, ...] } - ## Task Description ${task_description}