From 0342976c5158419d910f28f497e65e20879b8b7a Mon Sep 17 00:00:00 2001 From: catlog22 Date: Sun, 1 Feb 2026 15:17:03 +0800 Subject: [PATCH] feat: add JSON detection utility for various formats - Implemented a utility function `detectJsonInLine` to identify and parse JSON data from different formats including direct JSON, tool calls, tool results, embedded JSON, and code blocks. - Introduced `JsonDetectionResult` interface to standardize the detection results. - Added a new test results file to track the status of tests. --- .../workflow/collaborative-plan-with-file.md | 1090 ++++++------ .../workflow/unified-execute-with-file.md | 1458 ++++++++--------- .../CliStreamMonitor/utils/jsonDetector.ts | 102 ++ test-results/.last-run.json | 4 + 4 files changed, 1237 insertions(+), 1417 deletions(-) create mode 100644 src/components/shared/CliStreamMonitor/utils/jsonDetector.ts create mode 100644 test-results/.last-run.json diff --git a/.claude/commands/workflow/collaborative-plan-with-file.md b/.claude/commands/workflow/collaborative-plan-with-file.md index 0518e9d0..9ebf6c22 100644 --- a/.claude/commands/workflow/collaborative-plan-with-file.md +++ b/.claude/commands/workflow/collaborative-plan-with-file.md @@ -1,13 +1,13 @@ --- name: workflow:collaborative-plan-with-file -description: Unified collaborative planning with dynamic requirement splitting, parallel sub-agent exploration/understanding/planning, and automatic merge. Each agent maintains process files for full traceability. -argument-hint: "[-y|--yes] [--max-agents=5] [--depth=normal|deep] [--merge-rule=consensus|priority]" +description: Collaborative planning with Plan Note - Understanding agent creates shared plan-note.md template, parallel agents fill pre-allocated sections, conflict detection without merge. Outputs executable plan-note.md. +argument-hint: "[-y|--yes] [--max-agents=5]" allowed-tools: TodoWrite(*), Task(*), AskUserQuestion(*), Read(*), Bash(*), Write(*), Glob(*), Grep(*), mcp__ace-tool__search_context(*) --- ## Auto Mode -When `--yes` or `-y`: Auto-approve splits, use default merge rule, skip confirmations. +When `--yes` or `-y`: Auto-approve splits, skip confirmations. # Collaborative Planning Command @@ -19,72 +19,75 @@ When `--yes` or `-y`: Auto-approve splits, use default merge rule, skip confirma # With options /workflow:collaborative-plan-with-file "Refactor authentication module" --max-agents=4 -/workflow:collaborative-plan-with-file "Add payment gateway support" --depth=deep -/workflow:collaborative-plan-with-file "Migrate to microservices" --merge-rule=priority +/workflow:collaborative-plan-with-file "Add payment gateway support" -y ``` -**Context Source**: ACE semantic search + Per-agent CLI exploration +**Context Source**: Understanding-Agent + Per-agent exploration **Output Directory**: `.workflow/.planning/{session-id}/` **Default Max Agents**: 5 (actual count based on requirement complexity) -**CLI Tools**: cli-lite-planning-agent (internally calls ccw cli with gemini/codex/qwen) -**Schema**: plan-json-schema.json (sub-plans & final plan share same base schema) +**Core Innovation**: Plan Note - shared collaborative document, no merge needed ## Output Artifacts -### Per Sub-Agent (Phase 2) +### Phase 1: Understanding Agent + +| Artifact | Description | +|----------|-------------| +| `plan-note.md` | Shared collaborative document with pre-allocated sections | +| `requirement-analysis.json` | Sub-domain assignments and TASK ID ranges | + +### Phase 2: Per Sub-Agent | Artifact | Description | |----------|-------------| | `planning-context.md` | Evidence paths + synthesized understanding | -| `sub-plan.json` | Sub-plan following plan-json-schema.json | +| `plan.json` | Complete agent plan (detailed implementation) | +| Updates to `plan-note.md` | Agent fills pre-allocated sections | -### Final Output (Phase 4) +### Phase 3: Final Output | Artifact | Description | |----------|-------------| -| `requirement-analysis.json` | Requirement breakdown and sub-agent assignments | -| `conflicts.json` | Detected conflicts between sub-plans | -| `plan.json` | Merged plan (plan-json-schema + merge_metadata) | -| `plan.md` | Human-readable plan summary | - -**Agent**: `cli-lite-planning-agent` with `process_docs: true` for sub-agents +| `plan-note.md` | ⭐ Executable plan with conflict markers | +| `conflicts.json` | Detected conflicts with resolution options | +| `plan.md` | Human-readable summary | ## Overview -Unified collaborative planning workflow that: +Unified collaborative planning workflow using **Plan Note** architecture: -1. **Analyzes** complex requirements and splits into sub-requirements -2. **Spawns** parallel sub-agents, each responsible for one sub-requirement -3. **Each agent** maintains process files: planning-refs.md + sub-plan.json -4. **Merges** all sub-plans into unified plan.json with conflict resolution +1. **Understanding**: Agent analyzes requirements and creates plan-note.md template with pre-allocated sections +2. **Parallel Planning**: Each agent generates plan.json + fills their pre-allocated section in plan-note.md +3. **Conflict Detection**: Scan plan-note.md for conflicts (no merge needed) +4. **Completion**: Generate plan.md summary, ready for execution ``` ┌─────────────────────────────────────────────────────────────────────────┐ -│ COLLABORATIVE PLANNING │ +│ PLAN NOTE COLLABORATIVE PLANNING │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ -│ Phase 1: Requirement Analysis & Splitting │ -│ ├─ Analyze requirement complexity │ -│ ├─ Identify 2-5 sub-requirements (focus areas) │ -│ └─ Write requirement-analysis.json │ +│ Phase 1: Understanding & Template Creation │ +│ ├─ Understanding-Agent analyzes requirements │ +│ ├─ Identify 2-5 sub-domains (focus areas) │ +│ ├─ Create plan-note.md with pre-allocated sections │ +│ └─ Assign TASK ID ranges (no conflicts) │ │ │ -│ Phase 2: Parallel Sub-Agent Execution │ +│ Phase 2: Parallel Agent Execution (No Locks Needed) │ │ ┌──────────────┬──────────────┬──────────────┐ │ │ │ Agent 1 │ Agent 2 │ Agent N │ │ -├──────────────┼──────────────┼──────────────┤ │ -│ │ planning │ planning │ planning │ → planning-context.md│ -│ │ + sub-plan │ + sub-plan │ + sub-plan │ → sub-plan.json │ +│ ├──────────────┼──────────────┼──────────────┤ │ +│ │ Own Section │ Own Section │ Own Section │ ← Pre-allocated │ +│ │ plan.json │ plan.json │ plan.json │ ← Detailed plans │ │ └──────────────┴──────────────┴──────────────┘ │ │ │ -│ Phase 3: Cross-Verification & Conflict Detection │ -│ ├─ Load all sub-plan.json files │ -│ ├─ Detect conflicts (effort, approach, dependencies) │ -│ └─ Write conflicts.json │ +│ Phase 3: Conflict Detection (Single Source) │ +│ ├─ Parse plan-note.md (all sections) │ +│ ├─ Detect file/dependency/strategy conflicts │ +│ └─ Update plan-note.md conflict section │ │ │ -│ Phase 4: Merge & Synthesis │ -│ ├─ Resolve conflicts using merge-rule │ -│ ├─ Merge all sub-plans into unified plan │ -│ └─ Write plan.json + plan.md │ +│ Phase 4: Completion (No Merge) │ +│ ├─ Generate plan.md (human-readable) │ +│ └─ Ready for execution │ │ │ └─────────────────────────────────────────────────────────────────────────┘ ``` @@ -93,152 +96,216 @@ Unified collaborative planning workflow that: ``` .workflow/.planning/{CPLAN-slug-YYYY-MM-DD}/ -├── requirement-analysis.json # Phase 1: Requirement breakdown -├── agents/ # Phase 2: Per-agent process files +├── plan-note.md # ⭐ Core: Requirements + Tasks + Conflicts +├── requirement-analysis.json # Phase 1: Sub-domain assignments +├── agents/ # Phase 2: Per-agent detailed plans │ ├── {focus-area-1}/ │ │ ├── planning-context.md # Evidence + understanding -│ │ └── sub-plan.json # Agent's plan for this focus area +│ │ └── plan.json # Complete agent plan │ ├── {focus-area-2}/ │ │ └── ... │ └── {focus-area-N}/ │ └── ... -├── conflicts.json # Phase 3: Detected conflicts -├── plan.json # Phase 4: Unified merged plan -└── plan.md # Phase 4: Human-readable plan +├── conflicts.json # Phase 3: Conflict details +└── plan.md # Phase 4: Human-readable summary ``` ## Implementation ### Session Initialization +**Objective**: Create session context and directory structure for collaborative planning. + +**Required Actions**: +1. Extract task description from `$ARGUMENTS` +2. Generate session ID with format: `CPLAN-{slug}-{date}` + - slug: lowercase, alphanumeric, max 30 chars + - date: YYYY-MM-DD (UTC+8) +3. Define session folder: `.workflow/.planning/{session-id}` +4. Parse command options: + - `--max-agents=N` (default: 5) + - `-y` or `--yes` for auto-approval mode +5. Create directory structure: `{session-folder}/agents/` + +**Session Variables**: +- `sessionId`: Unique session identifier +- `sessionFolder`: Base directory for all artifacts +- `maxAgents`: Maximum number of parallel agents +- `autoMode`: Boolean for auto-confirmation + +### Phase 1: Understanding & Template Creation + +**Objective**: Analyze requirements and create the plan-note.md template with pre-allocated sections for parallel agents. + +**Prerequisites**: +- Session initialized with valid sessionId and sessionFolder +- Task description available from $ARGUMENTS + +**Workflow Steps**: + +1. **Initialize Progress Tracking** + - Create 4 todo items for workflow phases + - Set Phase 1 status to `in_progress` + +2. **Launch Understanding Agent** + - Agent type: `cli-lite-planning-agent` + - Execution mode: synchronous (run_in_background: false) + +3. **Agent Tasks**: + - **Understand Requirements**: Extract core objective, key points, constraints from task description + - **Form Checklist**: Identify critical questions needing clarification + - **Split Sub-Domains**: Identify 2-{maxAgents} parallelizable focus areas + - **Create Plan Note**: Generate plan-note.md with pre-allocated sections + +**Output Files**: + +| File | Purpose | +|------|---------| +| `{sessionFolder}/plan-note.md` | Collaborative template with pre-allocated sections per agent | +| `{sessionFolder}/requirement-analysis.json` | Sub-domain assignments and TASK ID ranges | + +**requirement-analysis.json Schema**: +- `session_id`: Session identifier +- `original_requirement`: Task description +- `complexity`: Low | Medium | High +- `sub_domains[]`: Array of focus areas with task_id_range and estimated_effort +- `total_agents`: Number of agents to spawn + +**Success Criteria**: +- 2-{maxAgents} clear sub-domains identified +- Each sub-domain can be planned independently +- Plan Note template includes all pre-allocated sections +- TASK ID ranges have no overlap (100 IDs per agent) +- Requirements understanding is comprehensive + +**Completion**: +- Log created artifacts +- Update Phase 1 todo status to `completed` + +**Agent Call**: ```javascript -const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString() +Task( + subagent_type="cli-lite-planning-agent", + run_in_background=false, + description="Understand requirements and create plan template", + prompt=` +## Mission: Create Plan Note Template -const taskDescription = "$ARGUMENTS" -const taskSlug = taskDescription.toLowerCase() - .replace(/[^a-z0-9\u4e00-\u9fa5]+/g, '-') - .substring(0, 30) +### Input Requirements +${taskDescription} -const sessionId = `CPLAN-${taskSlug}-${getUtc8ISOString().substring(0, 10)}` -const sessionFolder = `.workflow/.planning/${sessionId}` +### Tasks +1. **Understand Requirements**: Extract core objective, key points, constraints +2. **Form Checklist**: Identify critical questions needing clarification +3. **Split Sub-Domains**: Identify 2-${maxAgents} parallelizable focus areas +4. **Create Plan Note**: Generate plan-note.md with pre-allocated sections -// Parse options -const maxAgents = parseInt($ARGUMENTS.match(/--max-agents=(\d+)/)?.[1] || '5') -const depth = $ARGUMENTS.match(/--depth=(normal|deep)/)?.[1] || 'normal' -const mergeRule = $ARGUMENTS.match(/--merge-rule=(consensus|priority)/)?.[1] || 'consensus' -const autoMode = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') +### Output Files -Bash(`mkdir -p ${sessionFolder}/agents`) +**File 1**: ${sessionFolder}/plan-note.md + +Structure Requirements: +- YAML frontmatter: session_id, original_requirement, created_at, contributors, sub_domains, agent_sections, agent_task_id_ranges, status +- Section: ## 需求理解 (Core objectives, key points, constraints, split strategy) +- Section: ## 任务池 - {Focus Area 1} (Pre-allocated task section for agent 1, TASK-001 ~ TASK-100) +- Section: ## 任务池 - {Focus Area 2} (Pre-allocated task section for agent 2, TASK-101 ~ TASK-200) +- ... (One task pool section per sub-domain) +- Section: ## 依赖关系 (Auto-generated after all agents complete) +- Section: ## 冲突标记 (Populated in Phase 3) +- Section: ## 上下文证据 - {Focus Area 1} (Evidence for agent 1) +- Section: ## 上下文证据 - {Focus Area 2} (Evidence for agent 2) +- ... (One evidence section per sub-domain) + +**File 2**: ${sessionFolder}/requirement-analysis.json +- session_id, original_requirement, complexity, sub_domains[], total_agents + +### Success Criteria +- [ ] 2-${maxAgents} clear sub-domains identified +- [ ] Each sub-domain can be planned independently +- [ ] Plan Note template includes all pre-allocated sections +- [ ] TASK ID ranges have no overlap (100 IDs per agent) +` +) ``` -### Phase 1: Requirement Analysis & Splitting +### Phase 2: Parallel Sub-Agent Execution -Use CLI to analyze and split requirements: +**Objective**: Launch parallel planning agents to fill their pre-allocated sections in plan-note.md. -**⚠️ CRITICAL - CLI EXECUTION REQUIREMENT**: -- **MUST** wait for CLI execution to fully complete before proceeding -- After launching CLI with `run_in_background: true`, **STOP** and wait for hook callback -- **DO NOT** proceed to Phase 2 until CLI results are fully received -- Minimize scope: Proceed only when 100% result available +**Prerequisites**: +- Phase 1 completed successfully +- `{sessionFolder}/requirement-analysis.json` exists with sub-domain definitions +- `{sessionFolder}/plan-note.md` template created +**Workflow Steps**: + +1. **Load Sub-Domain Configuration** + - Read `{sessionFolder}/requirement-analysis.json` + - Extract sub-domains array with focus_area, description, task_id_range + +2. **Update Progress Tracking** + - Set Phase 2 status to `in_progress` + - Add sub-todo for each agent + +3. **User Confirmation** (unless autoMode) + - Display identified sub-domains with descriptions + - Options: "开始规划" / "调整拆分" / "取消" + - Skip if autoMode enabled + +4. **Create Agent Directories** + - For each sub-domain: `{sessionFolder}/agents/{focus-area}/` + +5. **Launch Parallel Agents** + - Agent type: `cli-lite-planning-agent` + - Execution mode: synchronous (run_in_background: false) + - Launch ALL agents in parallel (single message with multiple Task calls) + +**Per-Agent Context**: +- Focus area name and description +- Assigned TASK ID range (no overlap with other agents) +- Session ID and folder path + +**Per-Agent Tasks**: + +| Task | Output | Description | +|------|--------|-------------| +| Generate plan.json | `{sessionFolder}/agents/{focus-area}/plan.json` | Complete detailed plan following schema | +| Update plan-note.md | Sync to shared file | Fill pre-allocated "任务池" and "上下文证据" sections | + +**Task Summary Format** (for plan-note.md): +- Task header: `### TASK-{ID}: {Title} [{focus-area}]` +- Status, Complexity, Dependencies +- Scope description +- Modification points with file:line references +- Conflict risk assessment + +**Evidence Format** (for plan-note.md): +- Related files with relevance scores +- Existing patterns identified +- Constraints discovered + +**Agent Execution Rules**: +- Each agent modifies ONLY its pre-allocated sections +- Use assigned TASK ID range exclusively +- No locking needed (exclusive sections) +- Include conflict_risk assessment for each task + +**Completion**: +- Wait for all agents to complete +- Log generated artifacts for each agent +- Update Phase 2 todo status to `completed` + +**User Confirmation** (unless autoMode): ```javascript -TodoWrite({ todos: [ - { content: "Phase 1: Requirement Analysis", status: "in_progress", activeForm: "Analyzing requirements" }, - { content: "Phase 2: Parallel Agent Execution", status: "pending", activeForm: "Running agents" }, - { content: "Phase 3: Conflict Detection", status: "pending", activeForm: "Detecting conflicts" }, - { content: "Phase 4: Merge & Synthesis", status: "pending", activeForm: "Merging plans" } -]}) - -// Step 1.1: Use CLI to analyze requirement and propose splits -Bash({ - command: `ccw cli -p " -PURPOSE: Analyze requirement and identify distinct sub-requirements/focus areas -Success: 2-${maxAgents} clearly separated sub-requirements that can be planned independently - -TASK: -• Understand the overall requirement: '${taskDescription}' -• Identify major components, features, or concerns -• Split into 2-${maxAgents} independent sub-requirements -• Each sub-requirement should be: - - Self-contained (can be planned independently) - - Non-overlapping (minimal dependency on other sub-requirements) - - Roughly equal in complexity -• For each sub-requirement, provide: - - focus_area: Short identifier (e.g., 'auth-backend', 'ui-components') - - description: What this sub-requirement covers - - key_concerns: Main challenges or considerations - - suggested_cli_tool: Which CLI tool is best suited (gemini/codex/qwen) - -MODE: analysis - -CONTEXT: @**/* - -EXPECTED: JSON output with structure: -{ - \"original_requirement\": \"...\", - \"complexity\": \"low|medium|high\", - \"sub_requirements\": [ - { - \"index\": 1, - \"focus_area\": \"...\", - \"description\": \"...\", - \"key_concerns\": [\"...\"], - \"suggested_cli_tool\": \"gemini|codex|qwen\", - \"estimated_effort\": \"low|medium|high\" - } - ], - \"dependencies_between_subs\": [ - { \"from\": 1, \"to\": 2, \"reason\": \"...\" } - ], - \"rationale\": \"Why this split was chosen\" -} - -CONSTRAINTS: Maximum ${maxAgents} sub-requirements | Ensure clear boundaries -" --tool gemini --mode analysis`, - run_in_background: true -}) - -// Wait for CLI completion and parse result -// ⚠️ CRITICAL: Must wait for CLI complete - do NOT proceed until results received -// ... (hook callback will provide result) -``` - -**⚠️ STOP POINT**: After launching CLI, stop output immediately. Wait for hook callback to receive complete result before continuing. - -**After CLI completes**: - -```javascript -// Parse CLI output to extract sub-requirements -const analysisResult = parseCLIOutput(cliOutput) -const subRequirements = analysisResult.sub_requirements - -// Write requirement-analysis.json -Write(`${sessionFolder}/requirement-analysis.json`, JSON.stringify({ - session_id: sessionId, - original_requirement: taskDescription, - analysis_timestamp: getUtc8ISOString(), - complexity: analysisResult.complexity, - sub_requirements: subRequirements, - dependencies_between_subs: analysisResult.dependencies_between_subs, - rationale: analysisResult.rationale, - options: { maxAgents, depth, mergeRule } -}, null, 2)) - -// Create agent folders -subRequirements.forEach(sub => { - Bash(`mkdir -p ${sessionFolder}/agents/${sub.focus_area}`) -}) - -// User confirmation (unless auto mode) if (!autoMode) { AskUserQuestion({ questions: [{ - question: `已识别 ${subRequirements.length} 个子需求:\n${subRequirements.map((s, i) => `${i+1}. ${s.focus_area}: ${s.description}`).join('\n')}\n\n确认开始并行规划?`, + question: `已识别 ${subDomains.length} 个子领域:\n${subDomains.map((s, i) => `${i+1}. ${s.focus_area}: ${s.description}`).join('\n')}\n\n确认开始并行规划?`, header: "Confirm Split", multiSelect: false, options: [ { label: "开始规划", description: "启动并行sub-agent" }, - { label: "调整拆分", description: "修改子需求划分" }, + { label: "调整拆分", description: "修改子领域划分" }, { label: "取消", description: "退出规划" } ] }] @@ -246,524 +313,291 @@ if (!autoMode) { } ``` -### Phase 2: Parallel Sub-Agent Execution - -Launch one agent per sub-requirement, each maintaining its own process files: - +**Launch Parallel Agents** (single message, multiple Task calls): ```javascript -TodoWrite({ todos: [ - { content: "Phase 1: Requirement Analysis", status: "completed", activeForm: "Analyzing requirements" }, - { content: "Phase 2: Parallel Agent Execution", status: "in_progress", activeForm: "Running agents" }, - ...subRequirements.map((sub, i) => ({ - content: ` → Agent ${i+1}: ${sub.focus_area}`, - status: "pending", - activeForm: `Planning ${sub.focus_area}` - })), - { content: "Phase 3: Conflict Detection", status: "pending", activeForm: "Detecting conflicts" }, - { content: "Phase 4: Merge & Synthesis", status: "pending", activeForm: "Merging plans" } -]}) +// Create agent directories +subDomains.forEach(sub => { + Bash(`mkdir -p ${sessionFolder}/agents/${sub.focus_area}`) +}) -// Launch all sub-agents in parallel -const agentPromises = subRequirements.map((sub, index) => { - return Task({ - subagent_type: "cli-lite-planning-agent", - run_in_background: false, - description: `Plan: ${sub.focus_area}`, - prompt: ` +// Launch all agents in parallel +subDomains.map(sub => + Task( + subagent_type="cli-lite-planning-agent", + run_in_background=false, + description=`Plan: ${sub.focus_area}`, + prompt=` ## Sub-Agent Context -You are planning ONE sub-requirement. Generate process docs + sub-plan. - **Focus Area**: ${sub.focus_area} **Description**: ${sub.description} -**Key Concerns**: ${sub.key_concerns.join(', ')} -**CLI Tool**: ${sub.suggested_cli_tool} -**Depth**: ${depth} +**TASK ID Range**: ${sub.task_id_range[0]}-${sub.task_id_range[1]} +**Session**: ${sessionId} -## Input Context +## Dual Output Tasks -\`\`\`json -{ - "task_description": "${sub.description}", - "schema_path": "~/.claude/workflows/cli-templates/schemas/plan-json-schema.json", - "session": { "id": "${sessionId}", "folder": "${sessionFolder}" }, - "process_docs": true, - "focus_area": "${sub.focus_area}", - "output_folder": "${sessionFolder}/agents/${sub.focus_area}", - "cli_config": { "tool": "${sub.suggested_cli_tool}" }, - "parent_requirement": "${taskDescription}" -} -\`\`\` +### Task 1: Generate Complete plan.json +Output: ${sessionFolder}/agents/${sub.focus_area}/plan.json +Schema: ~/.claude/workflows/cli-templates/schemas/plan-json-schema.json -## Output Requirements +### Task 2: Sync Summary to plan-note.md -Write 2 files to \`${sessionFolder}/agents/${sub.focus_area}/\`: -1. **planning-context.md** - Evidence paths + synthesized understanding -2. **sub-plan.json** - Plan with \`_metadata.source_agent: "${sub.focus_area}"\` +**Locate Your Sections**: +- Task Pool: "## 任务池 - ${toTitleCase(sub.focus_area)}" +- Evidence: "## 上下文证据 - ${toTitleCase(sub.focus_area)}" -See cli-lite-planning-agent documentation for file formats. +**Task Summary Format**: +- Task header: ### TASK-${sub.task_id_range[0]}: Task Title [${sub.focus_area}] +- Fields: 状态, 复杂度, 依赖, 范围, 修改点, 冲突风险 + +**Evidence Format**: +- 相关文件, 现有模式, 约束 + +## Execution Steps +1. Generate complete plan.json +2. Extract summary from plan.json +3. Read ${sessionFolder}/plan-note.md +4. Locate and replace your task pool section +5. Locate and replace your evidence section +6. Write back plan-note.md + +## Important +- Only modify your pre-allocated sections +- Use assigned TASK ID range: ${sub.task_id_range[0]}-${sub.task_id_range[1]} ` - }) -}) - -// Wait for all agents to complete -const agentResults = await Promise.all(agentPromises) + ) +) ``` -### Phase 3: Cross-Verification & Conflict Detection +### Phase 3: Conflict Detection -Load all sub-plans and detect conflicts: +**Objective**: Analyze plan-note.md for conflicts across all agent contributions without merging files. -```javascript -TodoWrite({ todos: [ - { content: "Phase 1: Requirement Analysis", status: "completed", activeForm: "Analyzing requirements" }, - { content: "Phase 2: Parallel Agent Execution", status: "completed", activeForm: "Running agents" }, - { content: "Phase 3: Conflict Detection", status: "in_progress", activeForm: "Detecting conflicts" }, - { content: "Phase 4: Merge & Synthesis", status: "pending", activeForm: "Merging plans" } -]}) +**Prerequisites**: +- Phase 2 completed successfully +- All agents have updated plan-note.md with their sections +- `{sessionFolder}/plan-note.md` contains all task and evidence sections -// Load all sub-plans -const subPlans = subRequirements.map(sub => { - const planPath = `${sessionFolder}/agents/${sub.focus_area}/sub-plan.json` - const content = Read(planPath) - return { - focus_area: sub.focus_area, - index: sub.index, - plan: JSON.parse(content) - } -}) +**Workflow Steps**: -// Detect conflicts -const conflicts = { - detected_at: getUtc8ISOString(), - total_sub_plans: subPlans.length, - conflicts: [] -} +1. **Update Progress Tracking** + - Set Phase 3 status to `in_progress` -// 1. Effort conflicts (same task estimated differently) -const effortConflicts = detectEffortConflicts(subPlans) -conflicts.conflicts.push(...effortConflicts) +2. **Parse Plan Note** + - Read `{sessionFolder}/plan-note.md` + - Extract YAML frontmatter (session metadata) + - Parse markdown sections by heading levels + - Identify all "任务池" sections -// 2. File conflicts (multiple agents modifying same file) -const fileConflicts = detectFileConflicts(subPlans) -conflicts.conflicts.push(...fileConflicts) +3. **Extract All Tasks** + - For each "任务池" section: + - Extract tasks matching pattern: `### TASK-{ID}: {Title} [{author}]` + - Parse task details: status, complexity, dependencies, modification points, conflict risk + - Consolidate into single task list -// 3. Approach conflicts (different approaches to same problem) -const approachConflicts = detectApproachConflicts(subPlans) -conflicts.conflicts.push(...approachConflicts) +4. **Detect Conflicts** -// 4. Dependency conflicts (circular or missing dependencies) -const dependencyConflicts = detectDependencyConflicts(subPlans) -conflicts.conflicts.push(...dependencyConflicts) + **File Conflicts**: + - Group modification points by file:location + - Identify locations modified by multiple agents + - Record: severity=high, tasks involved, agents involved, suggested resolution -// Write conflicts.json -Write(`${sessionFolder}/conflicts.json`, JSON.stringify(conflicts, null, 2)) + **Dependency Cycles**: + - Build dependency graph from task dependencies + - Detect cycles using depth-first search + - Record: severity=critical, cycle path, suggested resolution -console.log(` -## Conflict Detection Complete + **Strategy Conflicts**: + - Group tasks by files they modify + - Identify files with high/medium conflict risk from multiple agents + - Record: severity=medium, tasks involved, agents involved, suggested resolution -**Total Sub-Plans**: ${subPlans.length} -**Conflicts Found**: ${conflicts.conflicts.length} +5. **Generate Conflict Artifacts** -${conflicts.conflicts.length > 0 ? ` -### Conflicts: -${conflicts.conflicts.map((c, i) => ` -${i+1}. **${c.type}** (${c.severity}) - - Agents: ${c.agents_involved.join(' vs ')} - - Issue: ${c.description} - - Suggested Resolution: ${c.suggested_resolution} -`).join('\n')} -` : '✅ No conflicts detected - sub-plans are compatible'} -`) -``` + **conflicts.json**: + - Write to `{sessionFolder}/conflicts.json` + - Include: detected_at, total_tasks, total_agents, conflicts array + - Each conflict: type, severity, tasks_involved, description, suggested_resolution + + **Update plan-note.md**: + - Locate "## 冲突标记" section + - Generate markdown summary of conflicts + - Replace section content with conflict markdown + +6. **Completion** + - Log conflict detection summary + - Display conflict details if any found + - Update Phase 3 todo status to `completed` + +**Conflict Types**: + +| Type | Severity | Detection Logic | +|------|----------|-----------------| +| file_conflict | high | Same file:location modified by multiple agents | +| dependency_cycle | critical | Circular dependencies in task graph | +| strategy_conflict | medium | Multiple high-risk tasks in same file from different agents | **Conflict Detection Functions**: -```javascript -function detectFileConflicts(subPlans) { - const fileModifications = {} - const conflicts = [] - - subPlans.forEach(sp => { - sp.plan.tasks.forEach(task => { - task.modification_points?.forEach(mp => { - if (!fileModifications[mp.file]) { - fileModifications[mp.file] = [] - } - fileModifications[mp.file].push({ - focus_area: sp.focus_area, - task_id: task.id, - target: mp.target, - change: mp.change - }) - }) - }) - }) - - Object.entries(fileModifications).forEach(([file, mods]) => { - if (mods.length > 1) { - const agents = [...new Set(mods.map(m => m.focus_area))] - if (agents.length > 1) { - conflicts.push({ - type: "file_conflict", - severity: "high", - file: file, - agents_involved: agents, - modifications: mods, - description: `Multiple agents modifying ${file}`, - suggested_resolution: "Sequence modifications or consolidate" - }) - } - } - }) - - return conflicts -} - -function detectEffortConflicts(subPlans) { - // Compare effort estimates across similar tasks - // Return conflicts where estimates differ by >50% - return [] -} - -function detectApproachConflicts(subPlans) { - // Analyze approaches for contradictions - // Return conflicts where approaches are incompatible - return [] -} - -function detectDependencyConflicts(subPlans) { - // Check for circular dependencies - // Check for missing dependencies - return [] -} -``` - -### Phase 4: Merge & Synthesis - -Use cli-lite-planning-agent to merge all sub-plans: - -```javascript -TodoWrite({ todos: [ - { content: "Phase 1: Requirement Analysis", status: "completed", activeForm: "Analyzing requirements" }, - { content: "Phase 2: Parallel Agent Execution", status: "completed", activeForm: "Running agents" }, - { content: "Phase 3: Conflict Detection", status: "completed", activeForm: "Detecting conflicts" }, - { content: "Phase 4: Merge & Synthesis", status: "in_progress", activeForm: "Merging plans" } -]}) - -// Collect all planning context documents for context -const contextDocs = subRequirements.map(sub => { - const path = `${sessionFolder}/agents/${sub.focus_area}/planning-context.md` - return { - focus_area: sub.focus_area, - content: Read(path) - } -}) - -// Invoke planning agent to merge -Task({ - subagent_type: "cli-lite-planning-agent", - run_in_background: false, - description: "Merge sub-plans into unified plan", - prompt: ` -## Mission: Merge Multiple Sub-Plans - -Merge ${subPlans.length} sub-plans into a single unified plan. - -## Schema Reference - -Execute: cat ~/.claude/workflows/cli-templates/schemas/plan-json-schema.json - -The merged plan follows the SAME schema as lite-plan, with ONE additional field: -- \`merge_metadata\`: Object containing merge-specific information - -## Project Context - -1. Read: .workflow/project-tech.json -2. Read: .workflow/project-guidelines.json - -## Original Requirement - -${taskDescription} - -## Sub-Plans to Merge - -${subPlans.map(sp => ` -### Sub-Plan: ${sp.focus_area} -\`\`\`json -${JSON.stringify(sp.plan, null, 2)} -\`\`\` -`).join('\n')} - -## Planning Context Documents - -${contextDocs.map(cd => ` -### Context: ${cd.focus_area} -${cd.content} -`).join('\n')} - -## Detected Conflicts - -\`\`\`json -${JSON.stringify(conflicts, null, 2)} -\`\`\` - -## Merge Rules - -**Rule**: ${mergeRule} -${mergeRule === 'consensus' ? ` -- Equal weight to all sub-plans -- Conflicts resolved by finding middle ground -- Combine overlapping tasks -` : ` -- Priority based on sub-requirement index -- Earlier agents' decisions take precedence -- Later agents adapt to earlier decisions -`} - -## Requirements - -1. **Task Consolidation**: - - Combine tasks that modify same files - - Preserve unique tasks from each sub-plan - - Ensure no task duplication - - Maintain clear task boundaries - -2. **Dependency Resolution**: - - Cross-reference dependencies between sub-plans - - Create global task ordering - - Handle inter-sub-plan dependencies - -3. **Conflict Resolution**: - - Apply ${mergeRule} rule to resolve conflicts - - Document resolution rationale - - Ensure no contradictions in final plan - -4. **Metadata Preservation**: - - Track which sub-plan each task originated from (source_agent field) - - Include merge_metadata with: - - merged_from: list of sub-plan focus areas - - conflicts_resolved: count - - merge_rule: ${mergeRule} - -## Output - -Write to ${sessionFolder}/plan.json following plan-json-schema.json. - -Add ONE extension field for merge tracking: - -\`\`\`json -{ - // ... all standard plan-json-schema fields ... - - "merge_metadata": { - "source_session": "${sessionId}", - "merged_from": ["focus-area-1", "focus-area-2"], - "sub_plan_count": N, - "conflicts_detected": N, - "conflicts_resolved": N, - "merge_rule": "${mergeRule}", - "merged_at": "ISO-timestamp" - } -} -\`\`\` - -Each task should include \`source_agent\` field indicating which sub-plan it originated from. - -## Success Criteria - -- [ ] All sub-plan tasks included (or explicitly merged) -- [ ] Conflicts resolved per ${mergeRule} rule -- [ ] Dependencies form valid DAG (no cycles) -- [ ] merge_metadata present -- [ ] Schema compliance verified -- [ ] plan.json written to ${sessionFolder}/plan.json -` -}) - -// Generate human-readable plan.md -const plan = JSON.parse(Read(`${sessionFolder}/plan.json`)) -const planMd = generatePlanMarkdown(plan, subRequirements, conflicts) -Write(`${sessionFolder}/plan.md`, planMd) -``` - -**Markdown Generation**: - -```javascript -function generatePlanMarkdown(plan, subRequirements, conflicts) { - return `# Collaborative Planning Session - -**Session ID**: ${plan._metadata?.session_id || sessionId} -**Original Requirement**: ${taskDescription} -**Created**: ${getUtc8ISOString()} - ---- - -## Sub-Requirements Analyzed - -${subRequirements.map((sub, i) => ` -### ${i+1}. ${sub.focus_area} -${sub.description} -- **Key Concerns**: ${sub.key_concerns.join(', ')} -- **Estimated Effort**: ${sub.estimated_effort} -`).join('\n')} - ---- - -## Conflict Resolution - -${conflicts.conflicts.length > 0 ? ` -**Conflicts Detected**: ${conflicts.conflicts.length} -**Merge Rule**: ${mergeRule} - -${conflicts.conflicts.map((c, i) => ` -${i+1}. **${c.type}** - ${c.description} - - Resolution: ${c.suggested_resolution} -`).join('\n')} -` : '✅ No conflicts detected'} - ---- - -## Merged Plan - -### Summary -${plan.summary} - -### Approach -${plan.approach} - ---- - -## Tasks - -${plan.tasks.map((task, i) => ` -### ${task.id}: ${task.title} - -**Source**: ${task.source_agent || 'merged'} -**Scope**: ${task.scope} -**Action**: ${task.action} -**Complexity**: ${task.effort?.complexity || 'medium'} - -${task.description} - -**Modification Points**: -${task.modification_points?.map(mp => `- \`${mp.file}\` → ${mp.target}: ${mp.change}`).join('\n') || 'N/A'} - -**Implementation**: -${task.implementation?.map((step, idx) => `${idx+1}. ${step}`).join('\n') || 'N/A'} - -**Acceptance Criteria**: -${task.acceptance?.map(ac => `- ${ac}`).join('\n') || 'N/A'} - -**Dependencies**: ${task.depends_on?.join(', ') || 'None'} - ---- -`).join('\n')} - -## Execution - -\`\`\`bash -# Execute this plan -/workflow:unified-execute-with-file -p ${sessionFolder}/plan.json - -# Or with auto-confirmation -/workflow:unified-execute-with-file -y -p ${sessionFolder}/plan.json -\`\`\` - ---- - -## Agent Process Files - -${subRequirements.map(sub => ` -### ${sub.focus_area} -- Context: \`${sessionFolder}/agents/${sub.focus_area}/planning-context.md\` -- Sub-Plan: \`${sessionFolder}/agents/${sub.focus_area}/sub-plan.json\` -`).join('\n')} - ---- - -**Generated by**: /workflow:collaborative-plan-with-file -**Merge Rule**: ${mergeRule} -` -} -``` - -### Completion - -```javascript -TodoWrite({ todos: [ - { content: "Phase 1: Requirement Analysis", status: "completed", activeForm: "Analyzing requirements" }, - { content: "Phase 2: Parallel Agent Execution", status: "completed", activeForm: "Running agents" }, - { content: "Phase 3: Conflict Detection", status: "completed", activeForm: "Detecting conflicts" }, - { content: "Phase 4: Merge & Synthesis", status: "completed", activeForm: "Merging plans" } -]}) - -console.log(` -✅ Collaborative Planning Complete - -**Session**: ${sessionId} -**Sub-Agents**: ${subRequirements.length} -**Conflicts Resolved**: ${conflicts.conflicts.length} - -## Output Files - -📁 ${sessionFolder}/ -├── requirement-analysis.json # Requirement breakdown -├── agents/ # Per-agent process files -${subRequirements.map(sub => `│ ├── ${sub.focus_area}/ -│ │ ├── planning-context.md -│ │ └── sub-plan.json`).join('\n')} -├── conflicts.json # Detected conflicts -├── plan.json # Unified plan (execution-ready) -└── plan.md # Human-readable plan - -## Next Steps - -Execute the plan: -\`\`\`bash -/workflow:unified-execute-with-file -p ${sessionFolder}/plan.json -\`\`\` - -Review a specific agent's work: -\`\`\`bash -cat ${sessionFolder}/agents/{focus-area}/planning-context.md -\`\`\` -`) -``` +**parsePlanNote(markdown)**: +- Input: Raw markdown content of plan-note.md +- Process: + - Extract YAML frontmatter between `---` markers + - Parse frontmatter as YAML to get session metadata + - Scan for heading patterns `^(#{2,})\s+(.+)$` + - Build sections array with: level, heading, start position, content +- Output: `{ frontmatter: object, sections: array }` + +**extractTasksFromSection(content, sectionHeading)**: +- Input: Section content text, section heading for attribution +- Process: + - Match task pattern: `### (TASK-\d+):\s+(.+?)\s+\[(.+?)\]` + - For each match: extract taskId, title, author + - Call parseTaskDetails for additional fields +- Output: Array of task objects with id, title, author, source_section, ...details + +**parseTaskDetails(content)**: +- Input: Task content block +- Process: + - Extract fields via regex patterns: + - `**状态**:\s*(.+)` → status + - `**复杂度**:\s*(.+)` → complexity + - `**依赖**:\s*(.+)` → depends_on (extract TASK-\d+ references) + - `**冲突风险**:\s*(.+)` → conflict_risk + - Extract modification points: `-\s+\`([^`]+):\s*([^`]+)\`:\s*(.+)` → file, location, summary +- Output: Details object with status, complexity, depends_on[], modification_points[], conflict_risk + +**detectFileConflicts(tasks)**: +- Input: All tasks array +- Process: + - Build fileMap: `{ "file:location": [{ task_id, task_title, source_agent, change }] }` + - For each location with multiple modifications from different agents: + - Create conflict with type='file_conflict', severity='high' + - Include: location, tasks_involved, agents_involved, modifications + - Suggested resolution: 'Coordinate modification order or merge changes' +- Output: Array of file conflict objects + +**detectDependencyCycles(tasks)**: +- Input: All tasks array +- Process: + - Build dependency graph: `{ taskId: [dependsOn_taskIds] }` + - Use DFS with recursion stack to detect cycles + - For each cycle found: + - Create conflict with type='dependency_cycle', severity='critical' + - Include: cycle path as tasks_involved + - Suggested resolution: 'Remove or reorganize dependencies' +- Output: Array of dependency cycle conflict objects + +**detectStrategyConflicts(tasks)**: +- Input: All tasks array +- Process: + - Group tasks by files they modify + - For each file with tasks from multiple agents: + - Filter for high/medium conflict_risk tasks + - If >1 high-risk tasks from different agents: + - Create conflict with type='strategy_conflict', severity='medium' + - Include: file, tasks_involved, agents_involved + - Suggested resolution: 'Review approaches and align on single strategy' +- Output: Array of strategy conflict objects + +**generateConflictMarkdown(conflicts)**: +- Input: Array of conflict objects +- Process: + - If empty: return '✅ 无冲突检测到' + - For each conflict: + - Generate header: `### CONFLICT-{padded_index}: {description}` + - Add fields: 严重程度, 涉及任务, 涉及Agent + - Add 问题详情 based on conflict type + - Add 建议解决方案 + - Add 决策状态: [ ] 待解决 +- Output: Markdown string for plan-note.md "## 冲突标记" section + +**replaceSectionContent(markdown, sectionHeading, newContent)**: +- Input: Original markdown, target section heading, new content +- Process: + - Find section heading position via regex + - Find next heading of same or higher level + - Replace content between heading and next section + - If section not found: append at end +- Output: Updated markdown string + +### Phase 4: Completion + +**Objective**: Generate human-readable plan summary and finalize workflow. + +**Prerequisites**: +- Phase 3 completed successfully +- Conflicts detected and documented in plan-note.md +- All artifacts generated + +**Workflow Steps**: + +1. **Update Progress Tracking** + - Set Phase 4 status to `in_progress` + +2. **Read Final State** + - Read `{sessionFolder}/plan-note.md` + - Extract frontmatter metadata + - Load conflicts from Phase 3 + +3. **Generate plan.md** + - Create human-readable summary including: + - Session metadata + - Requirements understanding + - Sub-domain breakdown + - Task overview by focus area + - Conflict report + - Execution instructions + +4. **Write Summary File** + - Write to `{sessionFolder}/plan.md` + +5. **Display Completion Summary** + - Session statistics + - File structure + - Execution command + - Conflict status + +6. **Update Todo** + - Set Phase 4 status to `completed` + +**plan.md Structure**: + +| Section | Content | +|---------|---------| +| Header | Session ID, created time, original requirement | +| Requirements | Copy from plan-note.md "## 需求理解" section | +| Sub-Domain Split | List each focus area with description and task ID range | +| Task Overview | Tasks grouped by focus area with complexity and dependencies | +| Conflict Report | Summary of detected conflicts or "无冲突" | +| Execution | Command to execute the plan | + +**Required Function** (semantic description): +- **generateHumanReadablePlan**: Extract sections from plan-note.md and format as readable plan.md with session info, requirements, tasks, and conflicts ## Configuration | Flag | Default | Description | |------|---------|-------------| | `--max-agents` | 5 | Maximum sub-agents to spawn | -| `--depth` | normal | Exploration depth: normal or deep | -| `--merge-rule` | consensus | Conflict resolution: consensus or priority | | `-y, --yes` | false | Auto-confirm all decisions | ## Error Handling | Error | Resolution | |-------|------------| -| Requirement too simple | Use single-agent lite-plan instead | -| Agent fails | Retry once, then continue with partial results | -| Merge conflicts unresolvable | Ask user for manual resolution | -| CLI timeout | Use fallback CLI tool | -| File write fails | Retry with alternative path | +| Understanding agent fails | Retry once, provide more context | +| Planning agent fails | Skip failed agent, continue with others | +| Section not found in plan-note | Agent creates section (defensive) | +| Conflict detection fails | Continue with empty conflicts | -## vs Other Planning Commands - -| Command | Use Case | -|---------|----------| -| **collaborative-plan-with-file** | Complex multi-aspect requirements needing parallel exploration | -| lite-plan | Simple single-focus tasks | -| multi-cli-plan | Iterative cross-verification with convergence | ## Best Practices -1. **Be Specific**: Detailed requirements lead to better splits -2. **Review Process Files**: Check planning-context.md for insights -3. **Trust the Merge**: Conflict resolution follows defined rules -4. **Iterate if Needed**: Re-run with different --merge-rule if results unsatisfactory +1. **Clear Requirements**: Detailed requirements → better sub-domain splitting +2. **Review Plan Note**: Check plan-note.md before execution +3. **Resolve Conflicts**: Address high/critical conflicts before execution +4. **Inspect Details**: Use agents/{focus-area}/plan.json for deep dive --- diff --git a/.claude/commands/workflow/unified-execute-with-file.md b/.claude/commands/workflow/unified-execute-with-file.md index 429d89bc..66cbd36d 100644 --- a/.claude/commands/workflow/unified-execute-with-file.md +++ b/.claude/commands/workflow/unified-execute-with-file.md @@ -1,7 +1,7 @@ --- name: unified-execute-with-file description: Universal execution engine for consuming any planning/brainstorm/analysis output with minimal progress tracking, multi-agent coordination, and incremental execution -argument-hint: "[-y|--yes] [-p|--plan ] [-m|--mode sequential|parallel] [\"execution context or task name\"]" +argument-hint: "[-y|--yes] [-p|--plan [,]] [--merge-agents] [--auto-commit] [--commit-prefix \"prefix\"] [-m|--mode sequential|parallel] [\"execution context or task name\"]" allowed-tools: TodoWrite(*), Task(*), AskUserQuestion(*), Read(*), Grep(*), Glob(*), Bash(*), Edit(*), Write(*) --- @@ -9,881 +9,761 @@ allowed-tools: TodoWrite(*), Task(*), AskUserQuestion(*), Read(*), Grep(*), Glob When `--yes` or `-y`: Auto-confirm execution decisions, use default parallel strategy where possible. -# Workflow Unified-Execute-With-File Command (/workflow:unified-execute-with-file) +# Unified Execute-With-File Command + +## Quick Start + +```bash +# Basic usage (auto-detect plan, ask for execution method) +/workflow:unified-execute-with-file + +# Execute with specific plan +/workflow:unified-execute-with-file -p .workflow/plans/auth-plan.md + +# Merge multiple plans +/workflow:unified-execute-with-file -p plan.json,agents/auth/plan.json + +# Collaborative plan execution (auto-discover sub-plans) +/workflow:unified-execute-with-file -p .workflow/.planning/CPLAN-xxx --merge-agents + +# With auto-commit (conventional commits) +/workflow:unified-execute-with-file --auto-commit -p plan.json + +# Sequential execution (no parallelization) +/workflow:unified-execute-with-file -m sequential -p plan.json + +# Auto mode (skip prompts, use Agent for simple tasks, CLI for complex) +/workflow:unified-execute-with-file -y -p plan.json +``` + +**Execution Methods**: +- **Agent**: Task tool with code-developer (recommended for standard tasks) +- **CLI-Codex**: `ccw cli --tool codex` (complex tasks, git-aware) +- **CLI-Gemini**: `ccw cli --tool gemini` (analysis-heavy tasks) +- **Auto**: Select based on task complexity (default in `-y` mode) + +**Context Source**: Plan files (IMPL_PLAN.md, plan.json, synthesis.json, etc.) +**Output Directory**: `.workflow/.execution/{session-id}/` +**Default Mode**: Parallel execution with smart dependency resolution +**Core Innovation**: Unified event log + structured notes + auto-commit + +## Output Artifacts + +### During Execution + +| Artifact | Description | +|----------|-------------| +| `execution.md` | Plan overview, task table, execution timeline | +| `execution-events.md` | ⭐ Unified log (all task executions) - SINGLE SOURCE OF TRUTH | + +### Generated Code + +Files generated directly to project directories (`src/`, `tests/`, `docs/`, etc.), not into execution folder. ## Overview -Universal execution engine that consumes **any** planning/brainstorm/analysis output and executes it with minimal progress tracking. Coordinates multiple agents (subagents or CLI tools), handles dependencies, and maintains execution timeline in a single minimal document. +Universal execution engine consuming **any** planning output and executing it with multi-agent coordination, dependency management, and progress tracking. -**Core workflow**: Load Plan → Parse Tasks → Coordinate Agents → Execute → Track Progress → Verify - -**Key features**: -- **Plan Format Agnostic**: Consumes IMPL_PLAN.md, brainstorm.md, analysis conclusions, debug resolutions -- **execution.md**: Single source of truth for progress, execution timeline, and results -- **Multi-Agent Orchestration**: Parallel execution where possible, sequential where needed -- **Incremental Execution**: Resume from failure point, no re-execution of completed tasks -- **Dependency Management**: Automatic topological sort and wait strategy -- **Real-Time Progress**: TodoWrite integration for live task status - -## Usage - -```bash -/workflow:unified-execute-with-file [FLAGS] [EXECUTION_CONTEXT] - -# Flags --y, --yes Auto-confirm execution decisions, use defaults --p, --plan Explicitly specify plan file (auto-detected if omitted) --m, --mode Execution strategy: sequential (strict order) | parallel (smart dependencies) - -# Arguments -[execution-context] Optional: Task category, module name, or execution focus (for filtering/priority) - -# Examples -/workflow:unified-execute-with-file # Auto-detect and execute latest plan -/workflow:unified-execute-with-file -p .workflow/plans/auth-plan.md # Execute specific plan -/workflow:unified-execute-with-file -y "auth module" # Auto-execute with context focus -/workflow:unified-execute-with-file -m sequential "payment feature" # Sequential execution -``` - -## Execution Process +**Core workflow**: Load Plan → Parse Tasks → Execute → Track → Verify ``` -Plan Detection: - ├─ Check for IMPL_PLAN.md or task JSON files in .workflow/ - ├─ Or use explicit --plan path - ├─ Or auto-detect from git branch/issue context - └─ Load plan metadata and task definitions - -Session Initialization: - ├─ Create .workflow/.execution/{sessionId}/ - ├─ Initialize execution.md with plan summary - ├─ Parse all tasks, identify dependencies - ├─ Determine execution strategy (parallel/sequential) - └─ Initialize progress tracking - -Pre-Execution Validation: - ├─ Check task feasibility (required files exist, tools available) - ├─ Validate dependency graph (detect cycles) - ├─ Ask user to confirm execution (unless --yes) - └─ Display execution plan and timeline estimate - -Task Execution Loop (Parallel/Sequential): - ├─ Select next executable tasks (dependencies satisfied) - ├─ Launch agents in parallel (if strategy=parallel) - ├─ Monitor execution, wait for completion - ├─ Capture outputs, log results - ├─ Update execution.md with progress - ├─ Mark tasks complete/failed - └─ Repeat until all done or max failures reached - -Error Handling: - ├─ Task failure → Ask user: retry|skip|abort - ├─ Dependency failure → Auto-skip dependent tasks - ├─ Output conflict → Ask for resolution - └─ Timeout → Mark as timeout, continue or escalate - -Completion: - ├─ Mark session complete - ├─ Summarize execution results in execution.md - ├─ Generate completion report (statistics, failures, recommendations) - └─ Offer follow-up: review|debug|enhance - -Output: - ├─ .workflow/.execution/{sessionId}/execution.md (plan and overall status) - ├─ .workflow/.execution/{sessionId}/execution-events.md (SINGLE SOURCE OF TRUTH - all task executions) - └─ Generated files in project directories (src/*, tests/*, docs/*, etc.) +┌─────────────────────────────────────────────────────────────────────────┐ +│ UNIFIED EXECUTION WORKFLOW │ +├─────────────────────────────────────────────────────────────────────────┤ +│ │ +│ Phase 1: Plan Detection & Multi-Plan Merging │ +│ ├─ Auto-detect or explicit --plan path │ +│ ├─ Support multiple plans (comma-separated or --merge-agents) │ +│ ├─ Deduplicate tasks (file overlap + 90% title similarity) │ +│ ├─ Assign global IDs: GTASK-{plan-index}-{original-id} │ +│ └─ Remap cross-plan dependencies │ +│ │ +│ Phase 2: Session Initialization │ +│ ├─ Create .workflow/.execution/{sessionId}/ │ +│ ├─ Generate execution.md (plan overview + task table) │ +│ ├─ Initialize execution-events.md (unified log) │ +│ ├─ Validate dependency graph (detect cycles) │ +│ └─ Calculate execution waves (topological sort + conflict check) │ +│ │ +│ Phase 3: Pre-Execution Validation (Agent-Assisted) │ +│ ├─ Launch validation agent to check feasibility │ +│ ├─ Verify file existence, agent availability, file conflicts │ +│ ├─ Generate validation report with recommendations │ +│ └─ Ask user: execution method (Agent/CLI-Codex/CLI-Gemini/Auto) │ +│ │ +│ Phase 4: Wave Execution (Parallel/Sequential) │ +│ ┌──────────────┬──────────────┬──────────────┐ │ +│ │ Wave 1 │ Wave 2 │ Wave N │ │ +│ ├──────────────┼──────────────┼──────────────┤ │ +│ │ Task 1-A ──┐ │ Task 2-A │ Task N-A │ ← Dependencies OK │ +│ │ Task 1-B │ │ Task 2-B │ Task N-B │ ← No file conflicts │ +│ │ Task 1-C ──┘ │ │ │ ← Max 3 parallel │ +│ └──────────────┴──────────────┴──────────────┘ │ +│ │ +│ Phase 5: Per-Task Execution (Agent OR CLI) │ +│ ├─ Extract relevant notes from previous tasks │ +│ ├─ Inject notes into execution context │ +│ ├─ Route to Agent (Task tool) OR CLI (ccw cli command) │ +│ ├─ Generate structured notes for next task │ +│ ├─ Auto-commit if enabled (conventional commit format) │ +│ └─ Append event to unified log │ +│ │ +│ Phase 6: Progress Tracking & Recovery │ +│ ├─ execution-events.md: Single source of truth │ +│ ├─ Each task: read previous events → execute → write event │ +│ ├─ Status indicators: ✅ (completed), ❌ (failed), ⏳ (progress) │ +│ └─ Resume support: --continue flag │ +│ │ +└─────────────────────────────────────────────────────────────────────────┘ ``` +## Output Structure + +``` +.workflow/.execution/{EXEC-slug-YYYY-MM-DD}/ +├── execution.md # Plan overview + task table + timeline +└── execution-events.md # ⭐ Unified log (all task executions) - SINGLE SOURCE OF TRUTH + +# Generated files (direct to project): +src/*, tests/*, docs/* +``` + +**Key Concept**: execution-events.md serves as both human-readable log AND machine-parseable state store. No redundancy, one unified source. + ## Implementation -### Session Setup & Plan Detection +### Session Initialization -```javascript -const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString() +**Objective**: Parse plan paths, create session directory, build unified task graph. -// Plan detection strategy -let planPath = $ARGUMENTS.match(/--plan\s+(\S+)/)?.[1] +**Prerequisites**: None (entry point) -if (!planPath) { - // Auto-detect: check recent workflow artifacts - const candidates = [ - '.workflow/.plan/IMPL_PLAN.md', - '.workflow/plans/IMPL_PLAN.md', - '.workflow/IMPL_PLAN.md', - ] +**Workflow Steps**: - // Find most recent plan - planPath = findMostRecentPlan(candidates) +1. **Parse Command Flags** + - Extract plan paths from `--plan` or `-p` argument + - Detect `--merge-agents` flag for collaborative plan auto-discovery + - Detect `--auto-commit` and `--commit-prefix` for git integration + - Detect `--mode` for execution strategy (parallel/sequential) + - Detect `-y` or `--yes` for auto-confirmation mode - if (!planPath) { - // Check for task JSONs - const taskJsons = glob('.workflow/**/*.json').filter(f => f.includes('IMPL-') || f.includes('task')) - if (taskJsons.length > 0) { - planPath = taskJsons[0] // Primary task - } - } -} +2. **Resolve Plan Paths** -if (!planPath) { - AskUserQuestion({ - questions: [{ - question: "未找到执行规划。请选择方式:", - header: "Plan Source", - multiSelect: false, - options: [ - { label: "浏览文件", description: "从 .workflow 目录选择" }, - { label: "使用最近规划", description: "从git提交消息推断" }, - { label: "手动输入路径", description: "直接指定规划文件路径" } - ] - }] - }) -} + | Input Format | Resolution Strategy | + |--------------|---------------------| + | Comma-separated | Split by comma: `plan1.json,plan2.json` | + | `--merge-agents` | Auto-discover: `plan-note.md` + `agents/**/plan.json` | + | Single path | Direct use | + | No path | Auto-detect from `.workflow/` (IMPL_PLAN.md or task JSONs) | -// Parse plan and extract tasks -const planContent = Read(planPath) -const plan = parsePlan(planContent, planPath) // Format-agnostic parser +3. **Build Unified Graph** + - Parse all plans via format-agnostic `parsePlan()` + - Assign global IDs: `GTASK-{plan-index}-{original-id}` + - Deduplicate tasks (file overlap + 90% title similarity) + - Remap dependencies (handle merged tasks + cross-plan refs) + - Validate (detect cycles), topological sort + - Return: `{ tasks, executionOrder, planSources, metadata }` -const executionId = `EXEC-${plan.slug}-${getUtc8ISOString().substring(0, 10)}-${randomId(4)}` -const executionFolder = `.workflow/.execution/${executionId}` -const executionPath = `${executionFolder}/execution.md` -const eventLogPath = `${executionFolder}/execution-events.md` +4. **Create Session Directory** + - Generate session ID: `EXEC-{slug}-{date}-{random}` + - Create `.workflow/.execution/{sessionId}/` + - Initialize `execution.md` with plan sources and merge statistics + - Initialize `execution-events.md` (empty, will be appended) -bash(`mkdir -p ${executionFolder}`) -``` +**Success Criteria**: +- [ ] All plans parsed successfully +- [ ] No circular dependencies in task graph +- [ ] Session directory created with execution.md template +- [ ] Execution order calculated (topological sort) + +**Completion**: Log session ID and ready for validation phase --- -## Plan Format Parsers +### Pre-Execution Validation (Agent-Assisted) -Support multiple plan sources (all JSON plans follow plan-json-schema.json): +**Objective**: Use validation agent to check execution feasibility, then ask user about execution method. -```javascript -function parsePlan(content, filePath) { - const ext = filePath.split('.').pop() +**Prerequisites**: Session initialized, unified graph built - if (filePath.includes('IMPL_PLAN')) { - return parseImplPlan(content) // From /workflow:plan (markdown) - } else if (filePath.includes('brainstorm')) { - return parseBrainstormPlan(content) // From /workflow:brainstorm-with-file - } else if (filePath.includes('synthesis')) { - return parseSynthesisPlan(content) // From /workflow:brainstorm-with-file synthesis.json - } else if (filePath.includes('conclusions')) { - return parseConclusionsPlan(content) // From /workflow:analyze-with-file conclusions.json - } else if (filePath.endsWith('.json') && content.includes('"tasks"')) { - return parsePlanJson(content) // Standard plan-json-schema (lite-plan, collaborative-plan, sub-plans) - } +**Workflow Steps**: - throw new Error(`Unsupported plan format: ${filePath}`) +1. **Launch Validation Agent** + + ```javascript + Task( + subagent_type="cli-explore-agent", + run_in_background=false, + description="Validate execution plan feasibility", + prompt=` +## Validation Mission + +Analyze the following execution plan and generate a validation report. + +### Plan Summary +- Total Tasks: ${unifiedGraph.tasks.length} +- Plan Sources: ${unifiedGraph.planSources.map(p => p.path).join(', ')} +- Execution Mode: ${executionMode} + +### Tasks to Validate +${unifiedGraph.tasks.slice(0, 10).map(t => `- ${t.id}: ${t.title} (files: ${t.files_to_modify?.join(', ')})`).join('\n')} + +### Validation Checks +1. **File Existence**: Verify files_to_modify exist or will be created +2. **Dependency Resolution**: Check all depends_on targets exist +3. **File Conflicts**: Identify same-file modifications in parallel waves +4. **Complexity Assessment**: Estimate task complexity (Low/Medium/High) +5. **Risk Analysis**: Identify potential issues or blockers + +### Output Format +Generate validation-report.json in ${sessionFolder}: +{ + "status": "pass" | "warn" | "fail", + "file_checks": { "missing": [], "will_create": [] }, + "dependency_issues": [], + "file_conflicts": [{ "file": "", "tasks": [], "wave": 0 }], + "complexity_assessment": { "low": 0, "medium": 0, "high": 0 }, + "risks": [{ "severity": "critical|high|medium|low", "description": "" }], + "recommendations": [] } - -// Standard plan-json-schema parser -// Handles: lite-plan, collaborative-plan, sub-plans (all follow same schema) -function parsePlanJson(content) { - const plan = JSON.parse(content) - - return { - type: plan.merge_metadata ? 'collaborative-plan' : 'lite-plan', - title: plan.summary?.split('.')[0] || 'Untitled Plan', - slug: plan._metadata?.session_id || generateSlug(plan.summary), - summary: plan.summary, - approach: plan.approach, - tasks: plan.tasks.map(task => ({ - id: task.id, - type: inferTaskTypeFromAction(task.action), - title: task.title, - description: task.description, - dependencies: task.depends_on || [], - agent_type: selectAgentFromTask(task), - prompt: buildPromptFromTask(task), - files_to_modify: task.modification_points?.map(mp => mp.file) || [], - expected_output: task.acceptance || [], - priority: task.effort?.complexity === 'high' ? 'high' : 'normal', - estimated_duration: task.effort?.estimated_hours ? `${task.effort.estimated_hours}h` : null, - verification: task.verification, - risks: task.risks, - source_agent: task.source_agent // From collaborative-plan sub-agents - })), - flow_control: plan.flow_control, - data_flow: plan.data_flow, - design_decisions: plan.design_decisions, - estimatedDuration: plan.estimated_time, - recommended_execution: plan.recommended_execution, - complexity: plan.complexity, - merge_metadata: plan.merge_metadata, // Present if from collaborative-plan - _metadata: plan._metadata - } -} - -// IMPL_PLAN.md parser -function parseImplPlan(content) { - // Extract: - // - Overview/summary - // - Phase sections - // - Task list with dependencies - // - Critical files - // - Execution order - - return { - type: 'impl-plan', - title: extractSection(content, 'Overview'), - phases: extractPhases(content), - tasks: extractTasks(content), - criticalFiles: extractCriticalFiles(content), - estimatedDuration: extractEstimate(content) - } -} - -// Brainstorm synthesis.json parser -function parseSynthesisPlan(content) { - const synthesis = JSON.parse(content) - - return { - type: 'brainstorm-synthesis', - title: synthesis.topic, - ideas: synthesis.top_ideas, - tasks: synthesis.top_ideas.map(idea => ({ - id: `IDEA-${slugify(idea.title)}`, - type: 'investigation', - title: idea.title, - description: idea.description, - dependencies: [], - agent_type: 'cli-execution-agent', - prompt: `Implement: ${idea.title}\n${idea.description}`, - expected_output: idea.next_steps - })), - recommendations: synthesis.recommendations - } -} - -// Helper: Infer task type from action field -function inferTaskTypeFromAction(action) { - const actionMap = { - 'Create': 'code', - 'Update': 'code', - 'Implement': 'code', - 'Refactor': 'code', - 'Add': 'code', - 'Delete': 'code', - 'Configure': 'config', - 'Test': 'test', - 'Fix': 'debug' - } - return actionMap[action] || 'code' -} - -// Helper: Select agent based on task properties -function selectAgentFromTask(task) { - if (task.verification?.unit_tests?.length > 0) { - return 'tdd-developer' - } else if (task.action === 'Test') { - return 'test-fix-agent' - } else if (task.action === 'Fix') { - return 'debug-explore-agent' - } else { - return 'code-developer' - } -} - -// Helper: Build prompt from task details -function buildPromptFromTask(task) { - let prompt = `## Task: ${task.title}\n\n${task.description}\n\n` - - if (task.modification_points?.length > 0) { - prompt += `### Modification Points\n` - task.modification_points.forEach(mp => { - prompt += `- **${mp.file}**: ${mp.target} → ${mp.change}\n` - }) - prompt += '\n' - } - - if (task.implementation?.length > 0) { - prompt += `### Implementation Steps\n` - task.implementation.forEach((step, i) => { - prompt += `${i + 1}. ${step}\n` - }) - prompt += '\n' - } - - if (task.acceptance?.length > 0) { - prompt += `### Acceptance Criteria\n` - task.acceptance.forEach(ac => { - prompt += `- ${ac}\n` - }) - } - - return prompt -} -``` - ---- - -### Phase 1: Plan Loading & Validation - -**Step 1.1: Parse Plan and Extract Tasks** - -```javascript -const tasks = plan.tasks || parseTasksFromContent(plan) - -// Normalize task structure -const normalizedTasks = tasks.map(task => ({ - id: task.id || `TASK-${generateId()}`, - title: task.title || task.content, - description: task.description || task.activeForm, - type: task.type || inferTaskType(task), // 'code', 'test', 'doc', 'analysis', 'integration' - agent_type: task.agent_type || selectBestAgent(task), - dependencies: task.dependencies || [], - - // Execution parameters - prompt: task.prompt || task.description, - files_to_modify: task.files_to_modify || [], - expected_output: task.expected_output || [], - - // Metadata - priority: task.priority || 'normal', - parallel_safe: task.parallel_safe !== false, - estimated_duration: task.estimated_duration || null, - - // Status tracking - status: 'pending', - attempts: 0, - max_retries: 2 -})) - -// Validate and detect issues -const validation = { - cycles: detectDependencyCycles(normalizedTasks), - missing_dependencies: findMissingDependencies(normalizedTasks), - file_conflicts: detectOutputConflicts(normalizedTasks), - warnings: [] -} - -if (validation.cycles.length > 0) { - throw new Error(`Circular dependencies detected: ${validation.cycles.join(', ')}`) -} -``` - -**Step 1.2: Create execution.md** - -```markdown -# Execution Progress - -**Execution ID**: ${executionId} -**Plan Source**: ${planPath} -**Started**: ${getUtc8ISOString()} -**Mode**: ${executionMode} - -**Plan Summary**: -- Title: ${plan.title} -- Total Tasks: ${tasks.length} -- Phases: ${plan.phases?.length || 'N/A'} - ---- - -## Execution Plan - -### Task Overview - -| Task ID | Title | Type | Agent | Dependencies | Status | -|---------|-------|------|-------|--------------|--------| -${normalizedTasks.map(t => `| ${t.id} | ${t.title} | ${t.type} | ${t.agent_type} | ${t.dependencies.join(',')} | ${t.status} |`).join('\n')} - -### Dependency Graph - -\`\`\` -${generateDependencyGraph(normalizedTasks)} -\`\`\` - -### Execution Strategy - -- **Mode**: ${executionMode} -- **Parallelization**: ${calculateParallel(normalizedTasks)} -- **Estimated Duration**: ${estimateTotalDuration(normalizedTasks)} - ---- - -## Execution Timeline - -*Updates as execution progresses* - ---- - -## Current Status - -${executionStatus()} -``` - -**Step 1.3: Pre-Execution Confirmation** - -```javascript -const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') - -if (!autoYes) { - AskUserQuestion({ - questions: [{ - question: `准备执行 ${normalizedTasks.length} 个任务,模式: ${executionMode}\n\n关键任务:\n${normalizedTasks.slice(0, 3).map(t => `• ${t.id}: ${t.title}`).join('\n')}\n\n继续?`, - header: "Confirmation", - multiSelect: false, - options: [ - { label: "开始执行", description: "按计划执行" }, - { label: "调整参数", description: "修改执行参数" }, - { label: "查看详情", description: "查看完整任务列表" }, - { label: "取消", description: "退出不执行" } - ] - }] - }) -} -``` - ---- - -## Phase 2: Execution Orchestration - -**Step 2.1: Determine Execution Order** - -```javascript -// Topological sort -const executionOrder = topologicalSort(normalizedTasks) - -// For parallel mode, group tasks into waves -let executionWaves = [] -if (executionMode === 'parallel') { - executionWaves = groupIntoWaves(executionOrder, parallelLimit = 3) -} else { - executionWaves = executionOrder.map(task => [task]) -} - -// Log execution plan to execution.md -// execution-events.md will track actual progress as tasks execute -``` - -**Step 2.2: Execute Task Waves** - -```javascript -let completedCount = 0 -let failedCount = 0 -const results = {} - -for (let waveIndex = 0; waveIndex < executionWaves.length; waveIndex++) { - const wave = executionWaves[waveIndex] - - console.log(`\n=== Wave ${waveIndex + 1}/${executionWaves.length} ===`) - console.log(`Tasks: ${wave.map(t => t.id).join(', ')}`) - - // Launch tasks in parallel - const taskPromises = wave.map(task => executeTask(task, executionFolder)) - - // Wait for wave completion - const waveResults = await Promise.allSettled(taskPromises) - - // Process results - for (let i = 0; i < waveResults.length; i++) { - const result = waveResults[i] - const task = wave[i] - - if (result.status === 'fulfilled') { - results[task.id] = result.value - if (result.value.success) { - completedCount++ - task.status = 'completed' - console.log(`✅ ${task.id}: Completed`) - } else if (result.value.retry) { - console.log(`⚠️ ${task.id}: Will retry`) - task.status = 'pending' - } else { - console.log(`❌ ${task.id}: Failed`) - } - } else { - console.log(`❌ ${task.id}: Execution error`) - } - - // Progress is tracked in execution-events.md (appended by executeTask) - } - - // Update execution.md summary - appendExecutionTimeline(executionPath, waveIndex + 1, wave, waveResults) -} -``` - -**Step 2.3: Execute Individual Task with Unified Event Logging** - -```javascript -async function executeTask(task, executionFolder) { - const eventLogPath = `${executionFolder}/execution-events.md` - const startTime = Date.now() - - try { - // Read previous execution events for context - let previousEvents = '' - if (fs.existsSync(eventLogPath)) { - previousEvents = Read(eventLogPath) - } - - // Select agent based on task type - const agent = selectAgent(task.agent_type) - - // Build execution context including previous agent outputs - const executionContext = ` -## Previous Agent Executions (for reference) - -${previousEvents} - ---- - -## Current Task: ${task.id} - -**Title**: ${task.title} -**Agent**: ${agent} -**Time**: ${getUtc8ISOString()} - -### Description -${task.description} - -### Context -- Modified Files: ${task.files_to_modify.join(', ')} -- Expected Output: ${task.expected_output.join(', ')} -- Previous Artifacts: [list any artifacts from previous tasks] - -### Requirements -${task.requirements || 'Follow the plan'} - -### Constraints -${task.constraints || 'No breaking changes'} ` + ) + ``` - // Execute based on agent type - let result +2. **Process Validation Result** + - Read `{sessionFolder}/validation-report.json` + - Display summary: status, conflicts count, risks count + - If `status === "fail"`: Show blockers, ask to abort/continue + - If `status === "warn"`: Show warnings, ask to proceed/fix - if (agent === 'code-developer' || agent === 'tdd-developer') { - // Code implementation - result = await Task({ - subagent_type: agent, - description: `Execute: ${task.title}`, - prompt: executionContext, - run_in_background: false - }) - } else if (agent === 'cli-execution-agent' || agent === 'universal-executor') { - // CLI-based execution - result = await Bash({ - command: `ccw cli -p "${escapeQuotes(executionContext)}" --tool gemini --mode analysis`, - run_in_background: false - }) - } else if (agent === 'test-fix-agent') { - // Test execution and fixing - result = await Task({ - subagent_type: 'test-fix-agent', - description: `Execute Tests: ${task.title}`, - prompt: executionContext, - run_in_background: false - }) - } else { - // Generic task execution - result = await Task({ - subagent_type: 'universal-executor', - description: task.title, - prompt: executionContext, - run_in_background: false - }) - } +3. **Select Execution Method** (unless `--yes` flag) - // Capture artifacts (code, tests, docs generated by this task) - const artifacts = captureArtifacts(task, executionFolder) + | Method | Description | When to Use | + |--------|-------------|-------------| + | Agent | `Task(subagent_type="code-developer")` | Standard implementation | + | CLI-Codex | `ccw cli --tool codex --mode write` | Complex tasks, git-aware | + | CLI-Gemini | `ccw cli --tool gemini --mode write` | Analysis-heavy tasks | + | Auto | Auto-select by complexity | Default for `--yes` mode | - // Append to unified execution events log - const eventEntry = ` -## Task ${task.id} - COMPLETED ✅ + **User Interaction** (unless `--yes`): + ```javascript + if (autoYes) { + executionMethod = "Auto" + console.log(`[--yes] Auto-selecting execution method: Auto`) + } else { + const selection = AskUserQuestion({ + questions: [{ + question: `选择执行方式 (${unifiedGraph.tasks.length} tasks, complexity: ${avgComplexity}):`, + header: "Execution", + multiSelect: false, + options: [ + { label: "Agent (Recommended)", description: "@code-developer - 标准实现" }, + { label: "CLI-Codex", description: "ccw cli --tool codex - 复杂任务" }, + { label: "CLI-Gemini", description: "ccw cli --tool gemini - 分析型任务" }, + { label: "Auto", description: "按复杂度自动选择" } + ] + }] + }) + executionMethod = selection.execution + } + ``` -**Timestamp**: ${getUtc8ISOString()} -**Duration**: ${calculateDuration(startTime)}ms -**Agent**: ${agent} +4. **Confirm Execution** (unless `--yes` flag) -### Execution Summary + Options: + - "开始执行" → Proceed with selected method + - "更换方式" → Re-select execution method + - "查看详情" → View full validation report + - "取消" → Exit without execution -${generateSummary(result)} +**Success Criteria**: +- [ ] Validation agent completed successfully +- [ ] No critical blockers (or user chose to continue) +- [ ] Execution method selected +- [ ] User confirmed (or auto-mode enabled) -### Key Outputs - -${formatOutputs(result)} - -### Generated Artifacts - -${artifacts.map(a => `- **${a.type}**: \`${a.path}\` (${a.size})`).join('\n')} - -### Notes for Next Agent - -${generateNotesForNextAgent(result, task)} - ---- -` - - appendToEventLog(eventLogPath, eventEntry) - - return { - success: true, - task_id: task.id, - output: result, - artifacts: artifacts, - duration: calculateDuration(startTime) - } - } catch (error) { - // Append failure event to unified log - const failureEntry = ` -## Task ${task.id} - FAILED ❌ - -**Timestamp**: ${getUtc8ISOString()} -**Duration**: ${calculateDuration(startTime)}ms -**Agent**: ${agent} -**Error**: ${error.message} - -### Error Details - -\`\`\` -${error.stack} -\`\`\` - -### Recovery Notes for Next Attempt - -${generateRecoveryNotes(error, task)} - ---- -` - - appendToEventLog(eventLogPath, failureEntry) - - // Handle failure: retry, skip, or abort - task.attempts++ - if (task.attempts < task.max_retries && autoYes) { - console.log(`⚠️ ${task.id}: Failed, retrying (${task.attempts}/${task.max_retries})`) - return { success: false, task_id: task.id, error: error.message, retry: true, duration: calculateDuration(startTime) } - } else if (task.attempts >= task.max_retries && !autoYes) { - const decision = AskUserQuestion({ - questions: [{ - question: `任务失败: ${task.id}\n错误: ${error.message}`, - header: "Decision", - multiSelect: false, - options: [ - { label: "重试", description: "重新执行该任务" }, - { label: "跳过", description: "跳过此任务,继续下一个" }, - { label: "终止", description: "停止整个执行" } - ] - }] - }) - if (decision === 'retry') { - task.attempts = 0 - return { success: false, task_id: task.id, error: error.message, retry: true, duration: calculateDuration(startTime) } - } else if (decision === 'skip') { - task.status = 'skipped' - skipDependentTasks(task.id, normalizedTasks) - } else { - throw new Error('Execution aborted by user') - } - } else { - task.status = 'failed' - skipDependentTasks(task.id, normalizedTasks) - } - - return { - success: false, - task_id: task.id, - error: error.message, - duration: calculateDuration(startTime) - } - } -} - -// Helper function to append to unified event log -function appendToEventLog(logPath, eventEntry) { - if (fs.existsSync(logPath)) { - const currentContent = Read(logPath) - Write(logPath, currentContent + eventEntry) - } else { - Write(logPath, eventEntry) - } -} -``` +**Variables Set**: +- `validationReport`: Parsed validation-report.json +- `executionMethod`: "Agent" | "CLI-Codex" | "CLI-Gemini" | "Auto" --- -## Phase 3: Progress Tracking & Event Logging +### Wave Execution -The `execution-events.md` file is the **single source of truth** for all agent executions: -- Each agent **reads** previous execution events for context -- **Executes** its task (with full knowledge of what was done before) -- **Writes** its execution event (success or failure) in markdown format -- Next agent **reads** all previous events, creating a "knowledge chain" +**Objective**: Execute tasks in waves, respecting dependencies and file conflicts. -**Event log format** (appended entry): -```markdown -## Task {id} - {STATUS} {emoji} +**Prerequisites**: Validation completed, user confirmed -**Timestamp**: {time} -**Duration**: {ms} -**Agent**: {type} +**Workflow Steps**: -### Execution Summary -{What was done} +1. **Calculate Execution Waves** -### Generated Artifacts -- `src/types/auth.ts` (2.3KB) + **Constraints**: + - Tasks with dependencies must wait for completion + - Same file modifications → Sequential (no parallel) + - Max 3 parallel tasks per wave (resource limit) -### Notes for Next Agent -- Key decisions made -- Potential issues -- Ready for: TASK-003 -``` + **Algorithm**: + - Find available tasks (dependencies satisfied, not completed) + - Check file conflicts (task.files_to_modify) + - Group non-conflicting tasks (up to 3 per wave) + - Mark completed, repeat + +2. **Execute Each Wave** + - Launch tasks in parallel via `executeTask()` + - Wait for wave completion via `Promise.allSettled()` + - Process results (mark completed/failed) + - Update execution.md timeline + - Append events to execution-events.md + +3. **Handle Failures** + + | Failure Type | Action | + |--------------|--------| + | Task timeout | Ask: retry/skip/abort | + | Dependency failed | Auto-skip dependent tasks | + | Max retries reached | Ask: retry/skip/abort (unless auto-mode) | + +**Success Criteria**: +- [ ] All waves executed +- [ ] Results captured in execution-events.md +- [ ] Failed tasks handled appropriately --- -## Phase 4: Completion & Summary +### Task Execution -After all tasks complete or max failures reached: +**Objective**: Execute individual task with context awareness, structured notes, and optional auto-commit. -1. **Collect results**: Count completed/failed/skipped tasks -2. **Update execution.md**: Add "Execution Completed" section with statistics -3. **execution-events.md**: Already contains all detailed execution records +**Prerequisites**: Task selected from available wave -```javascript -const statistics = { - total_tasks: normalizedTasks.length, - completed: normalizedTasks.filter(t => t.status === 'completed').length, - failed: normalizedTasks.filter(t => t.status === 'failed').length, - skipped: normalizedTasks.filter(t => t.status === 'skipped').length, - success_rate: (completedCount / normalizedTasks.length * 100).toFixed(1) -} +**Workflow Steps**: -// Update execution.md with final status -appendExecutionSummary(executionPath, statistics) -``` +1. **Extract Relevant Notes** + - Read all notes from execution-events.md + - Filter by file overlap (notes.related_files ∩ task.files_to_modify) + - Always include Critical severity notes + - Sort by severity (Critical → High → Medium → Low) -**Post-Completion Options** (unless --yes): +2. **Build Execution Context** -```javascript -AskUserQuestion({ - questions: [{ - question: "执行完成。是否需要后续操作?", - header: "Next Steps", - multiSelect: true, - options: [ - { label: "查看详情", description: "查看完整执行日志" }, - { label: "调试失败项", description: "对失败任务进行调试" }, - { label: "优化执行", description: "分析执行改进建议" }, - { label: "完成", description: "不需要后续操作" } - ] - }] -}) -``` + ```javascript + const executionContext = ` + ⚠️ Execution Notes from Previous Tasks + ${relevantNotes} // Categorized notes with severity + + Current Task: ${task.id} + - Original ID: ${task.original_id} + - Source Plan: ${task.source_plan} + - Modified Files: ${task.files_to_modify} + + Previous Agent Executions (for reference) + ${previousEvents} // All previous task results + ` + ``` + +3. **Route to Executor** (based on `executionMethod`) + + **Option A: Agent Execution** + + When: `executionMethod === "Agent"` or `Auto + Low Complexity` + + Execute task via Task tool with code-developer agent: + + ```javascript + Task({ + subagent_type: "code-developer", // or other agent types + run_in_background: false, + description: task.title, + prompt: buildAgentPrompt(executionContext, task) + }) + + // buildAgentPrompt generates: + // - Execution context with notes + // - Task details (title, description) + // - Files to modify + // - Dependencies + // - Expected output + ``` + + Agent Type Selection: + + | Agent Type | Use Case | + |------------|----------| + | code-developer | Code implementation | + | tdd-developer | Code with tests | + | test-fix-agent | Test execution and fixing | + | cli-execution-agent | CLI-based tasks | + | debug-explore-agent | Bug diagnosis | + | universal-executor | Generic tasks | + + --- + + **Option B: CLI Execution** + + When: `executionMethod === "CLI-Codex"/"CLI-Gemini"` or `Auto + Medium/High Complexity` + + Execute task via CLI in background mode: + + ```javascript + // Build CLI prompt from execution context + const cliPrompt = buildCliPrompt(task, executionContext) + // Generates: PURPOSE, TASK, MODE, CONTEXT, EXPECTED, CONSTRAINTS + + // Select tool based on execution method + const tool = executionMethod === "CLI-Gemini" ? "gemini" : "codex" + + // Generate fixed execution ID for resume capability + const fixedId = `${sessionId}-${task.id}` + + // Execute in background + Bash({ + command: `ccw cli -p "${cliPrompt}" --tool ${tool} --mode write --id ${fixedId}`, + run_in_background: true, + description: `Execute task ${task.id} via CLI` + }) + + // STOP HERE - CLI executes in background, task hook will notify on completion + ``` + + Resume on Failure: + + ```javascript + if (cliResult.status === 'failed' || cliResult.status === 'timeout') { + console.log(`Task ${task.id} incomplete. Resume with fixed ID: ${fixedId}`) + // Resume command: ccw cli -p "Continue" --resume ${fixedId} --id ${fixedId}-retry + } + ``` + +4. **Generate Structured Notes** + + **Pattern Detection** (auto-generate notes): + - `localStorage|sessionStorage` → WARNING (High): XSS防护提醒 + - `package.json` modified → DEPENDENCY (Medium): npm install提醒 + - `api.*change|breaking` → API_CHANGE (Critical): 兼容性检查 + +5. **Auto-Commit** (if `--auto-commit` enabled) + - Get changed files via `git status --porcelain` + - Filter to task.files_to_modify + - Stage files: `git add` + - Generate conventional commit message: `type(scope): subject` + - Commit: `git commit -m` + +6. **Append to Event Log** + + **Event Format**: + ```markdown + ## Task ${task.id} - COMPLETED ✅ + + **Timestamp**: ${time} + **Duration**: ${ms} + **Agent**: ${agent} + + ### Execution Summary + ${summary} + + ### Generated Artifacts + - `src/auth.ts` (2.3KB) + + ### Git Commit (if --auto-commit) + **Files Committed**: ${files.length} + **Commit Message**: feat(auth): implement user login + + ### 注意事项 (Execution Notes) + **Category**: WARNING + **Severity**: High + **Related Files**: src/auth.ts + **Message**: 使用了localStorage,注意XSS防护 + + --- + ``` + +**Success Criteria**: +- [ ] Task executed successfully +- [ ] Notes generated for next agent +- [ ] Event appended to execution-events.md +- [ ] Auto-commit completed (if enabled) --- -## Session Folder Structure +### Completion -``` -.workflow/.execution/{sessionId}/ -├── execution.md # Execution plan and overall status -└── execution-events.md # 📋 Unified execution log (all agents) - SINGLE SOURCE OF TRUTH - # This is both human-readable AND machine-parseable +**Objective**: Summarize execution results and offer follow-up actions. -# Generated files go directly to project directories (not into execution folder) -# E.g. TASK-001 generates: src/types/auth.ts (not artifacts/src/types/auth.ts) -# execution-events.md records the actual project paths -``` +**Prerequisites**: All waves completed -**Key Concept**: -- **execution-events.md** is the **single source of truth** for execution state -- Human-readable: Clear markdown format with task summaries -- Machine-parseable: Status indicators (✅/❌/⏳) and structured sections -- Progress tracking: Read task count by parsing status indicators -- No redundancy: One unified log for all purposes +**Workflow Steps**: + +1. **Collect Statistics** + - Total tasks: `normalizedTasks.length` + - Completed: `tasks.filter(t => t.status === 'completed').length` + - Failed: `tasks.filter(t => t.status === 'failed').length` + - Skipped: `tasks.filter(t => t.status === 'skipped').length` + - Success rate: `(completed / total * 100).toFixed(1)` + +2. **Update execution.md** + - Append "Execution Completed" section + - Include statistics table + - Link to execution-events.md for details + +3. **Display Summary** + - Show session ID and folder + - Display statistics + - List failed tasks (if any) + +4. **Offer Follow-Up Actions** (unless `--yes`) + + Options: + - "查看详情" → View full execution log + - "调试失败项" → Debug failed tasks + - "优化执行" → Analyze execution improvements + - "完成" → No further action + +**Success Criteria**: +- [ ] Statistics collected and displayed +- [ ] execution.md updated with final status +- [ ] User informed of completion --- -## Agent Selection Strategy +## Helper Functions -```javascript -function selectBestAgent(task) { - if (task.type === 'code' || task.type === 'implementation') { - return task.includes_tests ? 'tdd-developer' : 'code-developer' - } else if (task.type === 'test' || task.type === 'test-fix') { - return 'test-fix-agent' - } else if (task.type === 'doc' || task.type === 'documentation') { - return 'doc-generator' - } else if (task.type === 'analysis' || task.type === 'investigation') { - return 'cli-execution-agent' - } else if (task.type === 'debug') { - return 'debug-explore-agent' - } else { - return 'universal-executor' - } -} -``` +### Multi-Plan Support -## Parallelization Rules +**discoverCollaborativePlans(basePath)**: +- Search for `plan-note.md` or `plan.json` in base path +- Glob `agents/*/plan.json` for sub-plans +- Return: Array of plan paths -```javascript -function calculateParallel(tasks) { - // Group tasks into execution waves - // Constraints: - // - Tasks with same file modifications must be sequential - // - Tasks with dependencies must wait - // - Max 3 parallel tasks per wave (resource constraint) +**buildUnifiedGraph(planPaths)**: +- Parse each plan, assign global IDs +- Deduplicate tasks (file overlap + 90% title similarity via Levenshtein) +- Remap dependencies (merged tasks + cross-plan refs) +- Validate (detect cycles), topological sort +- Return: `{ tasks, executionOrder, planSources, metadata }` - const waves = [] - const completed = new Set() +**Deduplication Logic**: +- Same files + 90%+ title similarity → Merge +- Merge metadata: `source_plans`, `merged_from` - while (completed.size < tasks.length) { - const available = tasks.filter(t => - !completed.has(t.id) && - t.dependencies.every(d => completed.has(d)) - ) +--- - if (available.length === 0) break +### Structured Notes - // Check for file conflicts - const noConflict = [] - const modifiedFiles = new Set() +**Note Categories**: `WARNING`, `DECISION`, `API_CHANGE`, `FILE_CONFLICT`, `DEPENDENCY`, `PATTERN` - for (const task of available) { - const conflicts = task.files_to_modify.some(f => modifiedFiles.has(f)) - if (!conflicts && noConflict.length < 3) { - noConflict.push(task) - task.files_to_modify.forEach(f => modifiedFiles.add(f)) - } else if (!conflicts && noConflict.length < 3) { - waves.push([task]) - completed.add(task.id) - } - } +**Note Severity**: `Critical`, `High`, `Medium`, `Low` - if (noConflict.length > 0) { - waves.push(noConflict) - noConflict.forEach(t => completed.add(t.id)) - } - } +**extractNotesFromEvents(eventLogPath)**: +- Parse structured note blocks from execution-events.md +- Pattern: `**Category**: ... **Severity**: ... **Related Files**: ... **Message**: ...` +- Return: Array of note objects - return waves -} -``` +**filterRelevantNotes(notes, task)**: +- Include: File overlap with task.files_to_modify +- Always include: Critical severity notes +- Sort: By severity (Critical first) + +**generateNotesForNextAgent(result, task)**: +- Pattern detection for common issues +- Auto-generate structured notes +- Return: Markdown-formatted notes + +--- + +### Git Auto-Commit + +**inferCommitType(task)**: +- Check action/title for keywords: fix, refactor, test, doc +- Default: `feat` + +**extractScope(task)**: +- Check files_to_modify for patterns: frontend/, backend/, components/, api/, auth/ +- Return: scope or null + +**generateCommitMessage(task)**: +- Format: `type(scope): subject` +- Footer: `Task-ID: ${task.id}\nPlan: ${plan}` + +**autoCommitTaskChanges(task)**: +- Get changed files, filter to task.files_to_modify +- Stage, commit with conventional message +- Return: `{ files, message }` or null + +--- + +### Plan Format Parsers + +**parsePlan(content, filePath)**: +- Route to appropriate parser based on filename pattern +- Support: IMPL_PLAN.md, plan.json, synthesis.json, conclusions.json + +**parsePlanJson(content)**: +- Handle plan-json-schema (lite-plan, collaborative-plan, sub-plans) +- Map fields: `modification_points → files_to_modify`, `acceptance → expected_output` +- Infer: agent_type, task.type +- Build: prompt from task details + +--- + +### Validation & Execution Method + +**validateExecutionPlan(unifiedGraph, sessionFolder)**: +- Launch validation agent (cli-explore-agent) +- Check file existence, dependencies, file conflicts +- Generate validation-report.json with status/risks/recommendations +- Return: `{ status: "pass"|"warn"|"fail", report: {...} }` + +**selectExecutionMethod(validationReport, autoYes)**: +- If `autoYes === true`: Return "Auto" +- Otherwise: AskUserQuestion with options (Agent/CLI-Codex/CLI-Gemini/Auto) +- Return: Selected execution method + +**resolveExecutor(task, executionMethod, complexity)**: +- If `executionMethod === "Agent"`: Return "agent" +- If `executionMethod === "CLI-Codex"`: Return "cli-codex" +- If `executionMethod === "CLI-Gemini"`: Return "cli-gemini" +- If `executionMethod === "Auto"`: + - Low complexity → "agent" + - Medium/High complexity → "cli-codex" +- Return: Executor type + +--- + +### Agent Selection + +**selectBestAgent(task)**: + +| Task Type | Agent | +|-----------|-------| +| code (with tests) | tdd-developer | +| code | code-developer | +| test | test-fix-agent | +| doc | doc-generator | +| analysis | cli-execution-agent | +| debug | debug-explore-agent | +| default | universal-executor | + +--- + +### Parallelization + +**calculateParallel(tasks)**: + +Group into waves with constraints: +- Same file modifications → Sequential +- Dependencies → Wait for completion +- Max 3 parallel tasks per wave + +Algorithm: Find available → Check conflicts → Group → Repeat + +--- ## Error Handling & Recovery | Situation | Action | |-----------|--------| -| Task timeout | Mark as timeout, ask user: retry/skip/abort | +| Task timeout | Mark timeout, ask: retry/skip/abort | | Missing dependency | Auto-skip dependent tasks, log warning | -| File conflict | Detect before execution, ask for resolution | -| Output mismatch | Validate against expected_output, flag for review | +| File conflict | Detect before execution, ask resolution | +| Output mismatch | Validate vs expected_output, flag review | | Agent unavailable | Fallback to universal-executor | -| Execution interrupted | Support resume with `/workflow:unified-execute-with-file --continue` | +| Execution interrupted | Resume with `--continue` flag | +**Retry Logic**: +- Auto-retry up to `max_retries` (default: 2) in auto-yes mode +- Interactive mode: Ask user after max retries + +**Dependency Handling**: +- Failed task → Auto-skip all dependent tasks +- Log warning with skipped task IDs + +--- ## Session Resume ```bash -/workflow:unified-execute-with-file --continue # Resume last execution -/workflow:unified-execute-with-file --continue EXEC-xxx-2025-01-27-abcd # Resume specific +/workflow:unified-execute-with-file --continue # Resume last +/workflow:unified-execute-with-file --continue EXEC-xxx-2025-01-27 # Resume specific ``` -When resuming: +**Resume Process**: 1. Load execution.md and execution-events.md -2. Parse execution-events.md to identify completed/failed/skipped tasks +2. Parse events to identify completed/failed/skipped tasks (via status indicators) 3. Recalculate remaining dependencies 4. Resume from first incomplete task -5. Append to execution-events.md with "Resumed from [sessionId]" note +5. Append "Resumed from [sessionId]" note to events + +--- + +## Configuration + +| Flag | Default | Description | +|------|---------|-------------| +| `-p, --plan ` | Auto-detect | Plan file(s), comma-separated for multiple | +| `--merge-agents` | false | Auto-discover collaborative plan sub-plans | +| `--auto-commit` | false | Commit after each successful task | +| `--commit-prefix` | null | Custom commit message prefix | +| `-m, --mode` | parallel | Execution strategy: sequential or parallel | +| `-y, --yes` | false | Auto-confirm all decisions | + +--- + +## Best Practices + +1. **Clear Plan Structure**: Well-structured plans → better execution +2. **Review Validation Report**: Check validation-report.json for risks before proceeding +3. **Choose Right Execution Method**: + - **Agent**: Standard tasks, straightforward implementation + - **CLI-Codex**: Complex tasks, requires git-aware context + - **CLI-Gemini**: Analysis-heavy or exploratory tasks + - **Auto**: Let system decide based on complexity +4. **Use Auto-Commit**: Enable `--auto-commit` for automatic progress tracking +5. **Resolve Conflicts Early**: Address file conflicts before execution +6. **Monitor Events Log**: Check execution-events.md for detailed progress +7. **Resume on Failure**: Use `--continue` to resume interrupted executions (Agent) or fixed ID (CLI) +8. **Multi-Plan Merging**: Leverage `--merge-agents` for collaborative plan execution + +--- + +## Advanced Features + +### Multi-Plan Merging + +**Use Cases**: +- Collaborative planning output (plan-note.md + agents/**/plan.json) +- Multiple feature plans to execute together +- Incremental plan additions + +**Edge Cases**: +- Same title, different files → Keep both +- Same files, different title → Merge if 90%+ similarity +- Same task in multiple plans → Merge once + +### Structured Execution Notes + +**Categories & Severity**: +- `WARNING` (High): Security risks, potential issues +- `DECISION` (Medium): Architectural choices +- `API_CHANGE` (Critical): Breaking changes +- `FILE_CONFLICT` (High): Multi-task file modifications +- `DEPENDENCY` (Medium): Package/module changes +- `PATTERN` (Low): Coding patterns established + +**Note Filtering**: +- File overlap: Show notes affecting task.files_to_modify +- Always show: Critical severity (regardless of files) + +### Auto-Commit + +**Conventional Commit Format**: +- Structure: `type(scope): subject` +- Types: feat, fix, refactor, test, docs +- Scope: Inferred from file paths (frontend, backend, ui, api, auth) +- Footer: Task-ID, Plan source + +**Safety**: +- Never commit on task failure +- Never skip hooks (no --no-verify) +- Use heredoc for commit messages (avoid shell injection) + diff --git a/src/components/shared/CliStreamMonitor/utils/jsonDetector.ts b/src/components/shared/CliStreamMonitor/utils/jsonDetector.ts new file mode 100644 index 00000000..ac626ac0 --- /dev/null +++ b/src/components/shared/CliStreamMonitor/utils/jsonDetector.ts @@ -0,0 +1,102 @@ +/** + * JSON Detection Result + */ +export interface JsonDetectionResult { + isJson: boolean; + parsed?: Record; + error?: string; +} + +/** + * Detect if a line contains JSON data + * Supports multiple formats: + * - Direct JSON: {...} or [...] + * - Tool Call: [Tool] toolName({...}) + * - Tool Result: [Tool Result] status: {...} + * - Embedded JSON: trailing JSON object + * - Code block JSON: ```json ... ``` + * + * @param content - The content line to detect JSON in + * @returns Detection result with parsed data if valid JSON found + */ +export function detectJsonInLine(content: string): JsonDetectionResult { + const trimmed = content.trim(); + + // 1. Direct JSON object or array + if (trimmed.startsWith('{') || trimmed.startsWith('[')) { + try { + const parsed = JSON.parse(trimmed); + return { isJson: true, parsed: parsed as Record }; + } catch { + // Continue to other patterns + } + } + + // 2. Tool Call format: [Tool] toolName({...}) + const toolCallMatch = trimmed.match(/^\[Tool\]\s+(\w+)\((.*)\)$/); + if (toolCallMatch) { + const [, toolName, paramsStr] = toolCallMatch; + let parameters: unknown; + + try { + parameters = paramsStr ? JSON.parse(paramsStr) : {}; + } catch { + parameters = paramsStr || null; + } + + return { + isJson: true, + parsed: { + action: 'invoke', + toolName, + parameters, + } as Record, + }; + } + + // 3. Tool Result format: [Tool Result] status: output + const toolResultMatch = trimmed.match(/^\[Tool Result\]\s+(.+?)\s*:\s*(.+)$/); + if (toolResultMatch) { + const [, status, outputStr] = toolResultMatch; + let output: unknown; + + try { + output = outputStr.startsWith('{') ? JSON.parse(outputStr) : outputStr; + } catch { + output = outputStr; + } + + return { + isJson: true, + parsed: { + action: 'result', + status, + output, + } as Record, + }; + } + + // 4. Embedded JSON at end of line + const embeddedJsonMatch = trimmed.match(/\{.*\}$/); + if (embeddedJsonMatch) { + try { + const parsed = JSON.parse(embeddedJsonMatch[0]); + return { isJson: true, parsed: parsed as Record }; + } catch { + // Not valid JSON + } + } + + // 5. Code block JSON + const codeBlockMatch = trimmed.match(/```(?:json)?\s*\n([\s\S]*?)\n```/); + if (codeBlockMatch) { + try { + const parsed = JSON.parse(codeBlockMatch[1]); + return { isJson: true, parsed: parsed as Record }; + } catch { + return { isJson: false, error: 'Invalid JSON in code block' }; + } + } + + return { isJson: false }; +} diff --git a/test-results/.last-run.json b/test-results/.last-run.json new file mode 100644 index 00000000..5fca3f84 --- /dev/null +++ b/test-results/.last-run.json @@ -0,0 +1,4 @@ +{ + "status": "failed", + "failedTests": [] +} \ No newline at end of file