From 9fc2c876f733f216160eda1d17f4287870a4a843 Mon Sep 17 00:00:00 2001 From: catlog22 Date: Thu, 5 Feb 2026 20:50:21 +0800 Subject: [PATCH] Add Phase 4: Task Generation documentation and execution process - Introduced comprehensive guidelines for generating implementation plan documents (IMPL_PLAN.md, task JSONs, TODO_LIST.md) using the action-planning-agent. - Defined auto mode for user configuration with default settings. - Outlined core philosophy emphasizing planning only, agent-driven document generation, and memory-first context loading. - Detailed execution process divided into phases: User Configuration, Context Preparation, Single Agent Planning, N Parallel Planning, and Integration. - Included lifecycle management for user configuration and agent interactions. - Specified document generation lifecycle with clear expectations for outputs and quality standards. --- .../_shared/COMMAND-TO-SKILL-CONVERSION.md | 677 ++++++++++++++++ .../phases/03-conflict-resolution.md | 693 ++++++++++++++++ .../phases/04-task-generation.md | 756 ++++++++++++++++++ test-ask-question.js | 77 -- test-cli-command-gen.js | 58 -- test-config.js | 7 - test-e2e-model-alias.js | 75 -- test-model-alias.js | 31 - test-model-alias.txt | 2 - test-report.js | 99 --- test-update-claude-command.js | 64 -- test-update-claude/src/test.js | 1 - 12 files changed, 2126 insertions(+), 414 deletions(-) create mode 100644 .claude/skills/_shared/COMMAND-TO-SKILL-CONVERSION.md create mode 100644 .codex/skills/workflow-plan/phases/03-conflict-resolution.md create mode 100644 .codex/skills/workflow-plan/phases/04-task-generation.md delete mode 100644 test-ask-question.js delete mode 100644 test-cli-command-gen.js delete mode 100644 test-config.js delete mode 100644 test-e2e-model-alias.js delete mode 100644 test-model-alias.js delete mode 100644 test-model-alias.txt delete mode 100644 test-report.js delete mode 100644 test-update-claude-command.js delete mode 100644 test-update-claude/src/test.js diff --git a/.claude/skills/_shared/COMMAND-TO-SKILL-CONVERSION.md b/.claude/skills/_shared/COMMAND-TO-SKILL-CONVERSION.md new file mode 100644 index 00000000..6758b30f --- /dev/null +++ b/.claude/skills/_shared/COMMAND-TO-SKILL-CONVERSION.md @@ -0,0 +1,677 @@ +# 命令转 Skill 规范 v1.0 + +> 基于 `workflow-plan` 命令转换实践提炼的标准流程 + +## ⚠️ 核心要求 + +**Phase 文件内容必须与原命令文件内容一致** + +转换时只改变结构和组织方式,不改变功能实现细节。 + +--- + +## 目录 + +1. [转换目标](#1-转换目标) +2. [核心原则](#2-核心原则) +3. [结构映射](#3-结构映射) +4. [转换步骤](#4-转换步骤) +5. [SKILL.md 编写规范](#5-skillmd-编写规范) +6. [Phase 文件编写规范](#6-phase-文件编写规范) +7. [内容一致性验证](#7-内容一致性验证) +8. [质量检查清单](#8-质量检查清单) +9. [示例对照](#9-示例对照) + +--- + +## 1. 转换目标 + +### 1.1 为什么转换 + +| 命令格式 | Skill 格式 | +|----------|-----------| +| 单文件 + 子命令引用 | 结构化目录 + 分阶段执行 | +| 一次性全量加载 | **分布读取**(按需加载) | +| 执行流程隐式 | 执行流程**显式定义** | +| 子命令散落各处 | Phase 文件**集中管理** | +| 缺乏复用机制 | 模板/规范可复用 | + +### 1.2 转换收益 + +- **上下文优化**:Phase 文件按需加载,减少 token 消耗 +- **可维护性**:结构清晰,修改范围可控 +- **可扩展性**:新增阶段只需添加 Phase 文件 +- **执行可视化**:TodoWrite 与 Phase 对齐,进度透明 + +--- + +## 2. 核心原则 + +### 2.1 内容一致性原则(最高优先级) + +> **Phase 文件内容必须与原命令文件内容一致** +> +> 这是转换的第一要求,不可妥协。 + +**一致性定义**: + +| 维度 | 一致性要求 | 验证方法 | +|------|-----------|---------| +| **代码逻辑** | 所有Bash命令、函数、条件判断完全一致 | 逐行对比代码块 | +| **Agent Prompt** | Prompt内容100%保留,包括示例和约束 | 全文搜索关键段落 | +| **数据结构** | 表格、Schema、类型定义完整复制 | 对比字段数量 | +| **执行步骤** | 步骤顺序、子步骤层级保持不变 | 对比步骤编号 | +| **文本说明** | 关键说明、注释、警告完整保留 | 抽查重要段落 | + +**允许的差异**: + +| 差异类型 | 说明 | 示例 | +|---------|------|------| +| ✅ 添加阶段标识 | Phase标题、来源标注 | `# Phase 1: Session Discovery` | +| ✅ 添加组织结构 | 章节标题优化 | 添加 `## Execution Steps` | +| ✅ 添加衔接说明 | Post-Phase Update | 阶段完成后的状态说明 | +| ✅ 移除命令调用语法 | 移除 `/workflow`、`/command` 等命令引用 | 原文 `/workflow:session:start` → 移除 | +| ✅ 移除 Frontmatter | 移除命令的 argument-hint、examples | 命令级元数据在 Skill 中不需要 | +| ❌ 简化代码 | 任何代码的省略或改写 | 不允许 | +| ❌ 简化Prompt | Agent Prompt的任何删减 | 不允许 | +| ❌ 调整步骤 | 合并、拆分、重排步骤 | 不允许 | + +**内容保留清单**: + +| 内容类型 | 保留要求 | 示例 | +|---------|---------|------| +| **Bash命令** | 完整命令,包含所有参数、管道、重定向 | `find . -name "*.json" \| head -1` | +| **Agent Prompt** | 全文保留,包含OBJECTIVE、TASK、EXPECTED等所有节 | 完整的Task({prompt: "..."}) | +| **代码函数** | 完整函数体,所有if/else分支 | `analyzeTaskComplexity()` 全部代码 | +| **参数表格** | 所有行列,不省略任何参数 | Session Types表格 | +| **JSON Schema** | 所有字段、类型、required定义 | context-package.json schema | +| **验证逻辑** | 所有校验条件、错误处理、回滚代码 | conflict resolution验证清单 | +| **配置示例** | 输入输出示例、配置模板 | planning-notes.md模板 | +| **注释说明** | 重要的行内注释、块注释 | `// CRITICAL: ...` | + +❌ **严格禁止的简化行为**: + +1. **将代码替换为描述** + - ❌ 错误:`Execute context gathering agent` + - ✅ 正确:完整的 `Task({ subagent_type: "context-search-agent", prompt: "...[完整200行prompt]..." })` + +2. **省略Prompt内容** + - ❌ 错误:`Agent prompt for context gathering (see original file)` + - ✅ 正确:复制粘贴完整Prompt文本 + +3. **压缩表格** + - ❌ 错误:`Session types: Discovery/Auto/Force (see details in code)` + - ✅ 正确:完整Session Types表格,包含type/description/use case列 + +4. **合并步骤** + - ❌ 错误:将Step 1.1-1.4合并为Step 1 + - ✅ 正确:保持1.1、1.2、1.3、1.4独立步骤 + +5. **删除示例** + - ❌ 错误:省略JSON输出示例 + - ✅ 正确:保留所有输入输出示例 + +**应移除的命令特有内容**: + +转换时应移除以下命令格式专有的内容: + +| 移除内容 | 原因 | 示例 | +|---------|------|------| +| **Frontmatter** | Skill 使用 SKILL.md 的 Frontmatter | `argument-hint`、`allowed-tools`、`examples` | +| **命令调用语法** | Skill 使用 Phase 引用 | `/workflow:session:start` → 移除 | +| **命令路径引用** | 改为 Phase 路径引用 | `commands/workflow/tools/` → 移除 | +| **Skill 调用说明** | 在 SKILL.md 中统一说明 | `使用 /workflow:xxx 调用` → 移除 | +| **命令参数说明** | 仅保留执行参数 | `usage: /workflow:plan [session-id]` → 移除 | + +**示例**: + +原命令文件中: +```markdown +## Related Commands +- `/workflow:session:start` - Start new session +- `/workflow:tools:context-gather` - Gather context +``` + +转换后Phase文件中: +```markdown +## Related Phases +- Phase 1: Session Discovery +- Phase 2: Context Gathering +``` + +或直接移除相关命令说明章节,因为 SKILL.md 已包含完整的 Phase 引用表。 + +### 2.2 分布读取原则 + +> **SKILL.md 引用 Phase,Phase 按执行顺序加载** + +``` +执行流程: +Phase 1 → Read: phases/01-xxx.md → 执行 → 释放 + ↓ +Phase 2 → Read: phases/02-xxx.md → 执行 → 释放 + ↓ +Phase N → Read: phases/0N-xxx.md → 执行 → 完成 +``` + +### 2.3 职责分离原则 + +| 层级 | 职责 | 内容 | +|------|------|------| +| **SKILL.md** | 编排协调 | 流程图、数据流、TodoWrite 模式、阶段入口 | +| **Phase 文件** | 具体执行 | 完整执行逻辑、代码实现、Agent Prompt | +| **Specs** | 规范约束 | Schema 定义、质量标准、领域规范 | +| **Templates** | 可复用片段 | Agent 基础模板、输出模板 | + +--- + +## 3. 结构映射 + +### 3.1 命令结构 → Skill 结构 + +``` +commands/ skills/ +├── workflow/ ├── workflow-plan/ +│ ├── plan.md ────────→ │ ├── SKILL.md (orchestrator) +│ ├── session/ │ ├── phases/ +│ │ └── start.md ────────→ │ │ ├── 01-session-discovery.md +│ └── tools/ │ │ ├── 02-context-gathering.md +│ ├── context-gather.md ───→ │ │ ├── 03-conflict-resolution.md +│ ├── conflict-resolution.md │ │ └── 04-task-generation.md +│ └── task-generate-agent.md │ └── (specs/, templates/ 可选) +``` + +### 3.2 文件映射规则 + +| 源文件类型 | 目标文件 | 映射规则 | +|-----------|---------|---------| +| 主命令文件 | `SKILL.md` | 提取元数据、流程、协调逻辑 | +| 子命令文件 | `phases/0N-xxx.md` | 完整内容 + 阶段标识 | +| 引用的规范 | `specs/xxx.md` | 独立提取或保留在 Phase 中 | +| 通用模板 | `templates/xxx.md` | 多处引用时提取 | + +### 3.3 命名转换 + +| 原命令路径 | Phase 文件名 | +|-----------|-------------| +| `session/start.md` | `01-session-discovery.md` | +| `tools/context-gather.md` | `02-context-gathering.md` | +| `tools/conflict-resolution.md` | `03-conflict-resolution.md` | +| `tools/task-generate-agent.md` | `04-task-generation.md` | + +**命名规则**:`{序号}-{动作描述}.md` +- 序号:两位数字 `01`, `02`, ... +- 动作:动词-名词形式,小写连字符 + +--- + +## 4. 转换步骤 + +### 4.1 准备阶段 + +```markdown +□ Step 0: 分析源命令结构 + - 读取主命令文件,识别调用的子命令 + - 绘制命令调用关系图 + - 统计各文件行数(用于后续验证) +``` + +### 4.2 创建目录结构 + +```markdown +□ Step 1: 创建 Skill 目录 + mkdir skills/{skill-name}/ + mkdir skills/{skill-name}/phases/ +``` + +### 4.3 编写 SKILL.md + +```markdown +□ Step 2: 编写 SKILL.md + - 提取 Frontmatter (name, description, allowed-tools) + - 编写架构概览图 + - 编写执行流程(含 Phase 引用表) + - 编写数据流定义 + - 编写 TodoWrite 模式 + - 编写协调逻辑(阶段间衔接) +``` + +### 4.4 转换 Phase 文件 + +```markdown +□ Step 3: 逐个转换子命令为 Phase 文件 + FOR each 子命令: + - 读取原命令完整内容 + - 添加 Phase 标题和元信息 + - 保留所有代码、表格、Agent Prompt + - 添加 Post-Phase Update 节(如需) + - 验证行数接近原文件 +``` + +### 4.5 验证完整性 + +```markdown +□ Step 4: 验证内容完整性 + - 比较 Phase 文件与原命令行数 + - 确认关键代码块存在 + - 确认 Agent Prompt 完整 + - 确认表格和 Schema 完整 +``` + +--- + +## 5. SKILL.md 编写规范 + +### 5.1 Frontmatter 模板 + +```yaml +--- +name: {skill-name} +description: {简短描述}. Triggers on "{trigger-phrase}". +allowed-tools: Task, AskUserQuestion, TodoWrite, Read, Write, Edit, Bash, Glob, Grep +--- +``` + +### 5.2 必需章节 + +```markdown +# {Skill Name} + +{一句话描述功能} + +## Architecture Overview +{ASCII 架构图} + +## Execution Flow +{流程图 + Phase 引用表} + +### Phase Reference Documents +| Phase | Document | Load When | +|-------|----------|-----------| +| Phase 1 | phases/01-xxx.md | Phase 1 开始时 | +| ... | ... | ... | + +## Core Rules +{执行约束和规则} + +## Data Flow +{阶段间数据传递定义} + +## TodoWrite Pattern +{任务列表模板} + +## Error Handling +{错误处理策略} +``` + +### 5.3 执行流程示例 + +```markdown +## Execution Flow + +``` +Phase 1: Session Discovery + │ Ref: phases/01-session-discovery.md + ↓ +Phase 2: Context Gathering + │ Ref: phases/02-context-gathering.md + ↓ +Phase 3: Conflict Resolution (conditional) + │ Ref: phases/03-conflict-resolution.md + ↓ +Phase 4: Task Generation + │ Ref: phases/04-task-generation.md + ↓ +Complete: IMPL_PLAN.md + Task JSONs +``` + +### Phase Reference Documents + +| Phase | Document | Load When | +|-------|----------|-----------| +| Phase 1 | `phases/01-session-discovery.md` | Phase 1 开始执行时 | +| Phase 2 | `phases/02-context-gathering.md` | Phase 1 完成后 | +| Phase 3 | `phases/03-conflict-resolution.md` | conflict_risk ≥ medium 时 | +| Phase 4 | `phases/04-task-generation.md` | Phase 3 完成或跳过后 | +``` + +--- + +## 6. Phase 文件编写规范 + +### 6.1 Phase 文件结构 + +```markdown +# Phase N: {Phase Name} + +> 来源: `commands/{path}/original.md` + +## Overview +{阶段目标和职责} + +## Prerequisites +{前置条件和输入} + +## Execution Steps + +### Step N.1: {Step Name} +{完整实现代码} + +### Step N.2: {Step Name} +{完整实现代码} + +## Agent Prompt (如有) +{完整 Agent Prompt,不简化} + +## Output Format +{输出 Schema 和示例} + +## Post-Phase Update +{阶段完成后的状态更新} +``` + +### 6.2 转换原则:只改结构,不改内容 + +**转换时的思维模式**: + +> "我是在**搬运**内容,不是在**改写**内容" + +| 操作 | 允许 | 禁止 | +|------|------|------| +| 复制粘贴代码 | ✅ | | +| 调整章节标题 | ✅ | | +| 添加Phase标识 | ✅ | | +| 改写代码逻辑 | | ❌ | +| 简化Prompt | | ❌ | +| 省略步骤 | | ❌ | + +**转换流程**: + +1. **打开原命令文件和新Phase文件并排显示** +2. **逐段复制粘贴**(不要凭记忆改写) +3. **只添加结构性元素**(Phase标题、章节标题) +4. **保留100%功能性内容**(代码、Prompt、表格、示例) + +### 6.3 内容完整性自查 + +转换每个Phase文件后,必须完成以下检查: + +| 检查项 | 检查方法 | 合格标准 | +|--------|---------|---------| +| **代码块数量** | 计数 ` ```bash ` 和 ` ```javascript ` | 与原文件相等 | +| **表格数量** | 计数 ` \| ` 开头的行 | 与原文件相等 | +| **Agent Prompt** | 搜索 `Task({` | 完整的prompt参数内容 | +| **步骤编号** | 检查 `### Step` | 编号序列与原文件一致 | +| **文件行数** | `wc -l` | ±20%以内 | +| **关键函数** | 搜索函数名 | 所有函数完整保留 | + +**示例检查**: + +```bash +# 原命令文件 +$ grep -c "^###" commands/workflow/tools/context-gather.md +15 + +# Phase文件(应该相等或略多) +$ grep -c "^###" skills/workflow-plan/phases/02-context-gathering.md +16 # ✓ 只多了"Post-Phase Update"节 + +# 代码块数量对比 +$ grep -c '```' commands/workflow/tools/context-gather.md +24 + +$ grep -c '```' skills/workflow-plan/phases/02-context-gathering.md +24 # ✓ 完全相等 +``` + +### 6.4 内容保留清单(详细版) + +转换时必须完整保留: + +| 内容类型 | 保留要求 | +|---------|---------| +| **Bash 命令** | 完整命令,包含所有参数和路径 | +| **Agent Prompt** | 全文,包含示例和约束 | +| **代码函数** | 完整函数体,不简化 | +| **参数表格** | 所有列和行 | +| **JSON Schema** | 完整字段定义 | +| **验证逻辑** | if/else、校验代码 | +| **错误处理** | try/catch、回滚逻辑 | +| **示例** | 输入输出示例 | + +### 6.3 禁止的简化 + +❌ **不要这样**: +```markdown +### Step 2: Run context gathering +Execute the context-search-agent to gather project context. +``` + +✅ **应该这样**: +```markdown +### Step 2: Run context gathering + +```javascript +Task({ + subagent_type: "context-search-agent", + prompt: ` +## Context Search Task + +### OBJECTIVE +Gather comprehensive context for planning session ${sessionId} + +### MULTI-SOURCE DISCOVERY STRATEGY + +**Track 0: Project Foundation** +- Read CLAUDE.md files at all levels +- Check .workflow/project-tech.json for stack info +... +[完整 Prompt 内容] +`, + run_in_background: false +}) +``` +``` + +--- + +## 7. 内容一致性验证 + +### 7.1 验证流程 + +每完成一个Phase文件转换后,执行以下验证: + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 内容一致性验证流程 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Step 1: 行数对比 │ +│ $ wc -l 原文件 Phase文件 │ +│ └─→ 差异应在 ±20% 以内 │ +│ │ +│ Step 2: 代码块对比 │ +│ $ grep -c '```' 原文件 Phase文件 │ +│ └─→ 数量应相等 │ +│ │ +│ Step 3: 关键内容抽查 │ +│ - 搜索 Task({ → Agent Prompt 完整性 │ +│ - 搜索函数名 → 函数体完整性 │ +│ - 搜索表格标记 → 表格完整性 │ +│ │ +│ Step 4: 并排对比 │ +│ - 打开原文件和Phase文件 │ +│ - 逐节对比功能性内容 │ +│ - 确认无省略无改写 │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### 7.2 验证命令 + +```bash +# 1. 行数对比 +wc -l commands/workflow/tools/context-gather.md skills/workflow-plan/phases/02-context-gathering.md + +# 2. 代码块数量 +grep -c '```' commands/workflow/tools/context-gather.md +grep -c '```' skills/workflow-plan/phases/02-context-gathering.md + +# 3. 表格行数 +grep -c '^|' commands/workflow/tools/context-gather.md +grep -c '^|' skills/workflow-plan/phases/02-context-gathering.md + +# 4. Agent Prompt检查 +grep -c 'Task({' commands/workflow/tools/context-gather.md +grep -c 'Task({' skills/workflow-plan/phases/02-context-gathering.md + +# 5. 函数定义检查 +grep -E '^(function|const.*=.*=>|async function)' commands/workflow/tools/context-gather.md +grep -E '^(function|const.*=.*=>|async function)' skills/workflow-plan/phases/02-context-gathering.md +``` + +### 7.3 一致性检查表 + +每个Phase文件必须填写: + +| 检查项 | 原文件 | Phase文件 | 是否一致 | +|--------|--------|-----------|---------| +| 文件行数 | ___ | ___ | □ ±20%内 | +| 代码块数量 | ___ | ___ | □ 相等 | +| 表格行数 | ___ | ___ | □ 相等 | +| Task调用数 | ___ | ___ | □ 相等 | +| 函数定义数 | ___ | ___ | □ 相等 | +| 步骤数量 | ___ | ___ | □ 相等或+1 | + +### 7.4 不一致处理 + +发现不一致时: + +| 情况 | 处理方式 | +|------|---------| +| Phase文件行数少>20% | ❌ **必须补充**:定位缺失内容,从原文件复制 | +| 代码块数量少 | ❌ **必须补充**:找出缺失的代码块 | +| Agent Prompt缺失 | ❌ **严重问题**:立即从原文件完整复制 | +| 表格缺失 | ❌ **必须补充**:复制完整表格 | +| Phase文件行数多>20% | ✓ 可接受(添加了结构性内容) | + +--- + +## 8. 质量检查清单 + +### 8.1 结构检查 + +```markdown +□ SKILL.md 存在且包含必需章节 +□ phases/ 目录存在 +□ Phase 文件按数字前缀排序 +□ 所有子命令都有对应 Phase 文件 +``` + +### 8.2 内容完整性检查 + +```markdown +□ Phase 文件行数 ≈ 原命令行数 (±20%) +□ 所有 Bash 命令完整保留 +□ 所有 Agent Prompt 完整保留 +□ 所有表格完整保留 +□ 所有 JSON Schema 完整保留 +□ 验证逻辑和错误处理完整 +``` + +### 8.3 引用检查 + +```markdown +□ SKILL.md 中 Phase 引用路径正确 +□ Phase 文件标注了来源命令 +□ 跨 Phase 数据引用明确 +``` + +### 8.4 行数对比表 + +| 原命令 | 行数 | Phase 文件 | 行数 | 差异 | +|--------|------|-----------|------|------| +| session/start.md | 202 | 01-session-discovery.md | 281 | +39% ✓ | +| tools/context-gather.md | 404 | 02-context-gathering.md | 427 | +6% ✓ | +| tools/conflict-resolution.md | 604 | 03-conflict-resolution.md | 645 | +7% ✓ | +| tools/task-generate-agent.md | 693 | 04-task-generation.md | 701 | +1% ✓ | + +> Phase 文件可以比原命令稍长(添加了阶段标识、Post-Phase Update 等),但不应显著缩短。 + +--- + +## 9. 示例对照 + +### 9.1 workflow-plan 转换示例 + +**转换前**(命令结构): +``` +commands/workflow/ +├── plan.md (163 行) ─── 主命令,调用子命令 +├── session/ +│ └── start.md (202 行) ─── 会话管理 +└── tools/ + ├── context-gather.md (404 行) ─── 上下文收集 + ├── conflict-resolution.md (604 行) ─── 冲突解决 + └── task-generate-agent.md (693 行) ─── 任务生成 +``` + +**转换后**(Skill 结构): +``` +skills/workflow-plan/ +├── SKILL.md (348 行) ─── 编排协调 +└── phases/ + ├── 01-session-discovery.md (281 行) + ├── 02-context-gathering.md (427 行) + ├── 03-conflict-resolution.md (645 行) + └── 04-task-generation.md (701 行) +``` + +### 9.2 SKILL.md 与原主命令对比 + +| 原 plan.md 内容 | SKILL.md 对应位置 | +|----------------|-------------------| +| Frontmatter | Frontmatter (扩展) | +| 执行流程描述 | Execution Flow (可视化) | +| 子命令调用 | Phase Reference Table | +| 数据传递 | Data Flow (显式定义) | +| (无) | TodoWrite Pattern (新增) | +| (无) | Error Handling (新增) | + +### 9.3 Phase 文件与原子命令对比 + +| 原子命令内容 | Phase 文件对应 | +|-------------|---------------| +| Frontmatter | 移除 (Skill 不需要) | +| 步骤说明 | Execution Steps | +| 代码实现 | **完整保留(一致性要求)** | +| Agent Prompt | **完整保留(一致性要求)** | +| 输出格式 | Output Format | +| (无) | Post-Phase Update (新增) | + +--- + +## 附录:快速转换命令 + +```bash +# 1. 统计原命令行数 +wc -l commands/{path}/*.md commands/{path}/**/*.md + +# 2. 创建 Skill 目录 +mkdir -p skills/{skill-name}/phases + +# 3. 转换完成后验证 +wc -l skills/{skill-name}/SKILL.md skills/{skill-name}/phases/*.md + +# 4. 对比行数差异 +# Phase 文件行数应 ≈ 原命令行数 (±20%) +``` + +--- + +## 修订历史 + +| 版本 | 日期 | 变更 | +|------|------|------| +| v1.0 | 2025-02-05 | 基于 workflow-plan 转换实践创建 | +| v1.1 | 2025-02-05 | 强化内容一致性要求;添加第7章一致性验证;添加应移除的命令特有内容说明 | diff --git a/.codex/skills/workflow-plan/phases/03-conflict-resolution.md b/.codex/skills/workflow-plan/phases/03-conflict-resolution.md new file mode 100644 index 00000000..b5bcf353 --- /dev/null +++ b/.codex/skills/workflow-plan/phases/03-conflict-resolution.md @@ -0,0 +1,693 @@ +# Phase 3: Conflict Resolution + +Detect and resolve conflicts between plan and existing codebase using CLI-powered analysis with Gemini/Qwen. + +## Objective + +- Analyze conflicts between plan and existing code, **including module scenario uniqueness detection** +- Generate multiple resolution strategies with **iterative clarification until boundaries are clear** +- Apply selected modifications to brainstorm artifacts + +**Scope**: Detection and strategy generation only - NO code modification or task creation. + +**Trigger**: Auto-executes when `conflict_risk >= medium`. + +## Auto Mode + +When `--yes` or `-y`: Auto-select recommended strategy for each conflict, skip clarification questions. + +## Core Responsibilities + +| Responsibility | Description | +|---------------|-------------| +| **Detect Conflicts** | Analyze plan vs existing code inconsistencies | +| **Scenario Uniqueness** | Search and compare new modules with existing modules for functional overlaps | +| **Generate Strategies** | Provide 2-4 resolution options per conflict | +| **Iterative Clarification** | Ask unlimited questions until scenario boundaries are clear and unique | +| **Agent Re-analysis** | Dynamically update strategies based on user clarifications | +| **CLI Analysis** | Use Gemini/Qwen (Claude fallback) | +| **User Decision** | Present options ONE BY ONE, never auto-apply | +| **Direct Text Output** | Output questions via text directly, NEVER use bash echo/printf | +| **Structured Data** | JSON output for programmatic processing, NO file generation | +| **Explicit Lifecycle** | Manage agent lifecycle with spawn_agent → wait → send_input → close_agent | + +## Conflict Categories + +### 1. Architecture Conflicts +- Incompatible design patterns +- Module structure changes +- Pattern migration requirements + +### 2. API Conflicts +- Breaking contract changes +- Signature modifications +- Public interface impacts + +### 3. Data Model Conflicts +- Schema modifications +- Type breaking changes +- Data migration needs + +### 4. Dependency Conflicts +- Version incompatibilities +- Setup conflicts +- Breaking updates + +### 5. Module Scenario Overlap +- Functional overlap between new and existing modules +- Scenario boundary ambiguity +- Duplicate responsibility detection +- Module merge/split decisions +- **Requires iterative clarification until uniqueness confirmed** + +## Execution Process + +``` +Input Parsing: + ├─ Parse flags: --session, --context + └─ Validation: Both REQUIRED, conflict_risk >= medium + +Phase 1: Validation + ├─ Step 1: Verify session directory exists + ├─ Step 2: Load context-package.json + ├─ Step 3: Check conflict_risk (skip if none/low) + └─ Step 4: Prepare agent task prompt + +Phase 2: CLI-Powered Analysis (Agent with Dual Role) + ├─ Spawn agent with exploration + planning capability + ├─ Execute Gemini analysis (Qwen fallback) + ├─ Detect conflicts including ModuleOverlap category + └─ Generate 2-4 strategies per conflict with modifications + +Phase 3: Iterative User Interaction (using send_input) + └─ FOR each conflict (one by one): + ├─ Display conflict with overlap_analysis (if ModuleOverlap) + ├─ Display strategies (2-4 + custom option) + ├─ User selects strategy + └─ IF clarification_needed: + ├─ Collect answers + ├─ send_input for agent re-analysis + └─ Loop until uniqueness_confirmed (max 10 rounds) + +Phase 4: Apply Modifications + ├─ Step 1: Extract modifications from resolved strategies + ├─ Step 2: Apply using Edit tool + ├─ Step 3: Update context-package.json (mark resolved) + ├─ Step 4: Close agent + └─ Step 5: Output custom conflict summary (if any) +``` + +## Execution Flow + +### Phase 1: Validation +``` +1. Verify session directory exists +2. Load context-package.json +3. Check conflict_risk (skip if none/low) +4. Prepare agent task prompt +``` + +### Phase 2: CLI-Powered Analysis + +**Agent Delegation with Dual Role** (enables multi-round interaction): +```javascript +// Spawn agent with combined analysis + resolution capability +const conflictAgentId = spawn_agent({ + message: ` +## TASK ASSIGNMENT + +### MANDATORY FIRST STEPS (Agent Execute) +1. **Read role definition**: ~/.codex/agents/cli-execution-agent.md (MUST read first) +2. Read: .workflow/project-tech.json +3. Read: .workflow/project-guidelines.json + +--- + +## Context +- Session: ${session_id} +- Risk: ${conflict_risk} +- Files: ${existing_files_list} + +## Exploration Context (from context-package.exploration_results) +- Exploration Count: ${contextPackage.exploration_results?.exploration_count || 0} +- Angles Analyzed: ${JSON.stringify(contextPackage.exploration_results?.angles || [])} +- Pre-identified Conflict Indicators: ${JSON.stringify(contextPackage.exploration_results?.aggregated_insights?.conflict_indicators || [])} +- Critical Files: ${JSON.stringify(contextPackage.exploration_results?.aggregated_insights?.critical_files?.map(f => f.path) || [])} +- All Patterns: ${JSON.stringify(contextPackage.exploration_results?.aggregated_insights?.all_patterns || [])} +- All Integration Points: ${JSON.stringify(contextPackage.exploration_results?.aggregated_insights?.all_integration_points || [])} + +## Analysis Steps + +### 0. Load Output Schema (MANDATORY) +Execute: cat ~/.claude/workflows/cli-templates/schemas/conflict-resolution-schema.json + +### 1. Load Context +- Read existing files from conflict_detection.existing_files +- Load plan from .workflow/active/${session_id}/.process/context-package.json +- Load exploration_results and use aggregated_insights for enhanced analysis +- Extract role analyses and requirements + +### 2. Execute CLI Analysis (Enhanced with Exploration + Scenario Uniqueness) + +Primary (Gemini): +ccw cli -p " +PURPOSE: Detect conflicts between plan and codebase, using exploration insights +TASK: +• **Review pre-identified conflict_indicators from exploration results** +• Compare architectures (use exploration key_patterns) +• Identify breaking API changes +• Detect data model incompatibilities +• Assess dependency conflicts +• **Analyze module scenario uniqueness** + - Use exploration integration_points for precise locations + - Cross-validate with exploration critical_files + - Generate clarification questions for boundary definition +MODE: analysis +CONTEXT: @**/*.ts @**/*.js @**/*.tsx @**/*.jsx @.workflow/active/${session_id}/**/* +EXPECTED: Conflict list with severity ratings, including: + - Validation of exploration conflict_indicators + - ModuleOverlap conflicts with overlap_analysis + - Targeted clarification questions +CONSTRAINTS: Focus on breaking changes, migration needs, and functional overlaps | Prioritize exploration-identified conflicts | analysis=READ-ONLY +" --tool gemini --mode analysis --rule analysis-code-patterns --cd ${project_root} + +Fallback: Qwen (same prompt) → Claude (manual analysis) + +### 3. Generate Strategies (2-4 per conflict) + +Template per conflict: +- Severity: Critical/High/Medium +- Category: Architecture/API/Data/Dependency/ModuleOverlap +- Affected files + impact +- **For ModuleOverlap**: Include overlap_analysis with existing modules and scenarios +- Options with pros/cons, effort, risk +- **For ModuleOverlap strategies**: Add clarification_needed questions for boundary definition +- Recommended strategy + rationale + +### 4. Return Structured Conflict Data + +⚠️ Output to conflict-resolution.json (generated in Phase 4) + +**Schema Reference**: Execute \`cat ~/.claude/workflows/cli-templates/schemas/conflict-resolution-schema.json\` to get full schema + +Return JSON following the schema above. Key requirements: +- Minimum 2 strategies per conflict, max 4 +- All text in Chinese for user-facing fields (brief, name, pros, cons, modification_suggestions) +- modifications.old_content: 20-100 chars for unique Edit tool matching +- modifications.new_content: preserves markdown formatting +- modification_suggestions: 2-5 actionable suggestions for custom handling + +### 5. Planning Notes Record (REQUIRED) +After analysis complete, append a brief execution record to planning-notes.md: + +**File**: .workflow/active/${session_id}/planning-notes.md +**Location**: Under "## Conflict Decisions (Phase 3)" section +**Format**: +\`\`\` +### [Conflict-Resolution Agent] YYYY-MM-DD +- **Note**: [brief summary of conflict types, resolution strategies, key decisions] +\`\`\` +` +}); + +// Wait for initial analysis +const analysisResult = wait({ + ids: [conflictAgentId], + timeout_ms: 600000 // 10 minutes +}); + +// Parse conflicts from result +const conflicts = parseConflictsFromResult(analysisResult); +``` + +### Phase 3: User Interaction Loop + +```javascript +const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') + +FOR each conflict: + round = 0, clarified = false, userClarifications = [] + + WHILE (!clarified && round++ < 10): + // 1. Display conflict info (text output for context) + displayConflictSummary(conflict) // id, brief, severity, overlap_analysis if ModuleOverlap + + // 2. Strategy selection + if (autoYes) { + console.log(`[--yes] Auto-selecting recommended strategy`) + selectedStrategy = conflict.strategies[conflict.recommended || 0] + clarified = true // Skip clarification loop + } else { + AskUserQuestion({ + questions: [{ + question: formatStrategiesForDisplay(conflict.strategies), + header: "策略选择", + multiSelect: false, + options: [ + ...conflict.strategies.map((s, i) => ({ + label: `${s.name}${i === conflict.recommended ? ' (推荐)' : ''}`, + description: `${s.complexity}复杂度 | ${s.risk}风险${s.clarification_needed?.length ? ' | ⚠️需澄清' : ''}` + })), + { label: "自定义修改", description: `建议: ${conflict.modification_suggestions?.slice(0,2).join('; ')}` } + ] + }] + }) + + // 3. Handle selection + if (userChoice === "自定义修改") { + customConflicts.push({ id, brief, category, suggestions, overlap_analysis }) + break + } + + selectedStrategy = findStrategyByName(userChoice) + } + + // 4. Clarification (if needed) - using send_input for agent re-analysis + if (!autoYes && selectedStrategy.clarification_needed?.length > 0) { + for (batch of chunk(selectedStrategy.clarification_needed, 4)) { + AskUserQuestion({ + questions: batch.map((q, i) => ({ + question: q, header: `澄清${i+1}`, multiSelect: false, + options: [{ label: "详细说明", description: "提供答案" }] + })) + }) + userClarifications.push(...collectAnswers(batch)) + } + + // 5. Agent re-analysis via send_input (key: agent stays active) + send_input({ + id: conflictAgentId, + message: ` +## CLARIFICATION ANSWERS +Conflict: ${conflict.id} +Strategy: ${selectedStrategy.name} +User Clarifications: ${JSON.stringify(userClarifications)} + +## REQUEST +Based on the clarifications above, update the strategy assessment. +Output: { uniqueness_confirmed: boolean, rationale: string, updated_strategy: {...}, remaining_questions: [...] } +` + }); + + // Wait for re-analysis result + const reanalysisResult = wait({ + ids: [conflictAgentId], + timeout_ms: 300000 // 5 minutes + }); + + const parsedResult = parseReanalysisResult(reanalysisResult); + + if (parsedResult.uniqueness_confirmed) { + selectedStrategy = { ...parsedResult.updated_strategy, clarifications: userClarifications } + clarified = true + } else { + selectedStrategy.clarification_needed = parsedResult.remaining_questions + } + } else { + clarified = true + } + + if (clarified) resolvedConflicts.push({ conflict, strategy: selectedStrategy }) + END WHILE +END FOR + +selectedStrategies = resolvedConflicts.map(r => ({ + conflict_id: r.conflict.id, strategy: r.strategy, clarifications: r.strategy.clarifications || [] +})) +``` + +**Key Points**: +- AskUserQuestion: max 4 questions/call, batch if more +- Strategy options: 2-4 strategies + "自定义修改" +- Clarification loop via send_input: max 10 rounds, agent判断 uniqueness_confirmed +- Agent stays active throughout interaction (no close_agent until Phase 4 complete) +- Custom conflicts: 记录 overlap_analysis 供后续手动处理 + +### Phase 4: Apply Modifications + +```javascript +// 1. Extract modifications from resolved strategies +const modifications = []; +selectedStrategies.forEach(item => { + if (item.strategy && item.strategy.modifications) { + modifications.push(...item.strategy.modifications.map(mod => ({ + ...mod, + conflict_id: item.conflict_id, + clarifications: item.clarifications + }))); + } +}); + +console.log(`\n正在应用 ${modifications.length} 个修改...`); + +// 2. Apply each modification using Edit tool (with fallback to context-package.json) +const appliedModifications = []; +const failedModifications = []; +const fallbackConstraints = []; // For files that don't exist + +modifications.forEach((mod, idx) => { + try { + console.log(`[${idx + 1}/${modifications.length}] 修改 ${mod.file}...`); + + // Check if target file exists (brainstorm files may not exist in lite workflow) + if (!file_exists(mod.file)) { + console.log(` ⚠️ 文件不存在,写入 context-package.json 作为约束`); + fallbackConstraints.push({ + source: "conflict-resolution", + conflict_id: mod.conflict_id, + target_file: mod.file, + section: mod.section, + change_type: mod.change_type, + content: mod.new_content, + rationale: mod.rationale + }); + return; // Skip to next modification + } + + if (mod.change_type === "update") { + Edit({ + file_path: mod.file, + old_string: mod.old_content, + new_string: mod.new_content + }); + } else if (mod.change_type === "add") { + // Handle addition - append or insert based on section + const fileContent = Read(mod.file); + const updated = insertContentAfterSection(fileContent, mod.section, mod.new_content); + Write(mod.file, updated); + } else if (mod.change_type === "remove") { + Edit({ + file_path: mod.file, + old_string: mod.old_content, + new_string: "" + }); + } + + appliedModifications.push(mod); + console.log(` ✓ 成功`); + } catch (error) { + console.log(` ✗ 失败: ${error.message}`); + failedModifications.push({ ...mod, error: error.message }); + } +}); + +// 2b. Generate conflict-resolution.json output file +const resolutionOutput = { + session_id: sessionId, + resolved_at: new Date().toISOString(), + summary: { + total_conflicts: conflicts.length, + resolved_with_strategy: selectedStrategies.length, + custom_handling: customConflicts.length, + fallback_constraints: fallbackConstraints.length + }, + resolved_conflicts: selectedStrategies.map(s => ({ + conflict_id: s.conflict_id, + strategy_name: s.strategy.name, + strategy_approach: s.strategy.approach, + clarifications: s.clarifications || [], + modifications_applied: s.strategy.modifications?.filter(m => + appliedModifications.some(am => am.conflict_id === s.conflict_id) + ) || [] + })), + custom_conflicts: customConflicts.map(c => ({ + id: c.id, + brief: c.brief, + category: c.category, + suggestions: c.suggestions, + overlap_analysis: c.overlap_analysis || null + })), + planning_constraints: fallbackConstraints, // Constraints for files that don't exist + failed_modifications: failedModifications +}; + +const resolutionPath = `.workflow/active/${sessionId}/.process/conflict-resolution.json`; +Write(resolutionPath, JSON.stringify(resolutionOutput, null, 2)); + +// 3. Update context-package.json with resolution details (reference to JSON file) +const contextPackage = JSON.parse(Read(contextPath)); +contextPackage.conflict_detection.conflict_risk = "resolved"; +contextPackage.conflict_detection.resolution_file = resolutionPath; // Reference to detailed JSON +contextPackage.conflict_detection.resolved_conflicts = selectedStrategies.map(s => s.conflict_id); +contextPackage.conflict_detection.custom_conflicts = customConflicts.map(c => c.id); +contextPackage.conflict_detection.resolved_at = new Date().toISOString(); +Write(contextPath, JSON.stringify(contextPackage, null, 2)); + +// 4. Close the conflict agent (IMPORTANT: explicit lifecycle management) +close_agent({ id: conflictAgentId }); + +// 5. Output custom conflict summary with overlap analysis (if any) +if (customConflicts.length > 0) { + console.log(`\n${'='.repeat(60)}`); + console.log(`需要自定义处理的冲突 (${customConflicts.length})`); + console.log(`${'='.repeat(60)}\n`); + + customConflicts.forEach(conflict => { + console.log(`【${conflict.category}】${conflict.id}: ${conflict.brief}`); + + // Show overlap analysis for ModuleOverlap conflicts + if (conflict.category === 'ModuleOverlap' && conflict.overlap_analysis) { + console.log(`\n场景重叠信息:`); + console.log(` 新模块: ${conflict.overlap_analysis.new_module.name}`); + console.log(` 场景: ${conflict.overlap_analysis.new_module.scenarios.join(', ')}`); + console.log(`\n 与以下模块重叠:`); + conflict.overlap_analysis.existing_modules.forEach(mod => { + console.log(` - ${mod.name} (${mod.file})`); + console.log(` 重叠场景: ${mod.overlap_scenarios.join(', ')}`); + }); + } + + console.log(`\n修改建议:`); + conflict.suggestions.forEach(suggestion => { + console.log(` - ${suggestion}`); + }); + console.log(); + }); +} + +// 6. Output failure summary (if any) +if (failedModifications.length > 0) { + console.log(`\n⚠️ 部分修改失败 (${failedModifications.length}):`); + failedModifications.forEach(mod => { + console.log(` - ${mod.file}: ${mod.error}`); + }); +} + +// 7. Return summary +return { + total_conflicts: conflicts.length, + resolved_with_strategy: selectedStrategies.length, + custom_handling: customConflicts.length, + modifications_applied: appliedModifications.length, + modifications_failed: failedModifications.length, + modified_files: [...new Set(appliedModifications.map(m => m.file))], + custom_conflicts: customConflicts, + clarification_records: selectedStrategies.filter(s => s.clarifications.length > 0) +}; +``` + +**Validation**: +``` +✓ Agent returns valid JSON structure with ModuleOverlap conflicts +✓ Conflicts processed ONE BY ONE (not in batches) +✓ ModuleOverlap conflicts include overlap_analysis field +✓ Strategies with clarification_needed display questions +✓ User selections captured correctly per conflict +✓ Clarification loop continues until uniqueness confirmed via send_input +✓ Agent re-analysis with user clarifications updates strategy +✓ Uniqueness confirmation based on clear scenario boundaries +✓ Maximum 10 rounds per conflict safety limit enforced +✓ Edit tool successfully applies modifications +✓ guidance-specification.md updated +✓ Role analyses (*.md) updated +✓ context-package.json marked as resolved with clarification records +✓ Custom conflicts display overlap_analysis for manual handling +✓ Agent closed after all interactions complete (explicit lifecycle) +✓ Agent log saved to .workflow/active/{session_id}/.chat/ +``` + +## Output Format + +### Primary Output: conflict-resolution.json + +**Path**: `.workflow/active/{session_id}/.process/conflict-resolution.json` + +**Schema**: +```json +{ + "session_id": "WFS-xxx", + "resolved_at": "ISO timestamp", + "summary": { + "total_conflicts": 3, + "resolved_with_strategy": 2, + "custom_handling": 1, + "fallback_constraints": 0 + }, + "resolved_conflicts": [ + { + "conflict_id": "CON-001", + "strategy_name": "策略名称", + "strategy_approach": "实现方法", + "clarifications": [], + "modifications_applied": [] + } + ], + "custom_conflicts": [ + { + "id": "CON-002", + "brief": "冲突摘要", + "category": "ModuleOverlap", + "suggestions": ["建议1", "建议2"], + "overlap_analysis": null + } + ], + "planning_constraints": [], + "failed_modifications": [] +} +``` + +### Key Requirements + +| Requirement | Details | +|------------|---------| +| **Conflict batching** | Max 10 conflicts per round (no total limit) | +| **Strategy count** | 2-4 strategies per conflict | +| **Modifications** | Each strategy includes file paths, old_content, new_content | +| **User-facing text** | Chinese (brief, strategy names, pros/cons) | +| **Technical fields** | English (severity, category, complexity, risk) | +| **old_content precision** | 20-100 chars for unique Edit tool matching | +| **File targets** | guidance-specification.md, role analyses (*.md) | +| **Agent lifecycle** | Keep active during interaction, close after Phase 4 | + +## Error Handling + +### Recovery Strategy +``` +1. Pre-check: Verify conflict_risk ≥ medium +2. Monitor: Track agent via wait with timeout +3. Validate: Parse agent JSON output +4. Recover: + - Agent failure → check logs + report error + - Invalid JSON → retry once with Claude fallback + - CLI failure → fallback to Claude analysis + - Edit tool failure → report affected files + rollback option + - User cancels → mark as "unresolved", continue to task-generate +5. Degrade: If all fail, generate minimal conflict report and skip modifications +6. Cleanup: Always close_agent even on error path +``` + +### Rollback Handling +``` +If Edit tool fails mid-application: +1. Log all successfully applied modifications +2. Output rollback option via text interaction +3. If rollback selected: restore files from git or backups +4. If continue: mark partial resolution in context-package.json +``` + +## Integration + +### Interface +**Input**: +- `--session` (required): WFS-{session-id} +- `--context` (required): context-package.json path +- Requires: `conflict_risk >= medium` + +**Output**: +- Generated file: + - `.workflow/active/{session_id}/.process/conflict-resolution.json` (primary output) +- Modified files (if exist): + - `.workflow/active/{session_id}/.brainstorm/guidance-specification.md` + - `.workflow/active/{session_id}/.brainstorm/{role}/analysis.md` + - `.workflow/active/{session_id}/.process/context-package.json` (conflict_risk → resolved, resolution_file reference) + +**User Interaction**: +- **Iterative conflict processing**: One conflict at a time, not in batches +- Each conflict: 2-4 strategy options + "自定义修改" option (with suggestions) +- **Clarification loop via send_input**: Unlimited questions per conflict until uniqueness confirmed (max 10 rounds) +- **ModuleOverlap conflicts**: Display overlap_analysis with existing modules +- **Agent re-analysis**: Dynamic strategy updates based on user clarifications + +### Success Criteria +``` +✓ CLI analysis returns valid JSON structure with ModuleOverlap category +✓ Agent performs scenario uniqueness detection (searches existing modules) +✓ Conflicts processed ONE BY ONE with iterative clarification via send_input +✓ Min 2 strategies per conflict with modifications +✓ ModuleOverlap conflicts include overlap_analysis with existing modules +✓ Strategies requiring clarification include clarification_needed questions +✓ Each conflict includes 2-5 modification_suggestions +✓ Text output displays conflict with overlap analysis (if ModuleOverlap) +✓ User selections captured per conflict +✓ Clarification loop continues until uniqueness confirmed (unlimited rounds, max 10) +✓ Agent re-analysis with user clarifications updates strategy +✓ Uniqueness confirmation based on clear scenario boundaries +✓ Edit tool applies modifications successfully +✓ Custom conflicts displayed with overlap_analysis for manual handling +✓ guidance-specification.md updated with resolved conflicts +✓ Role analyses (*.md) updated with resolved conflicts +✓ context-package.json marked as "resolved" with clarification records +✓ conflict-resolution.json generated with full resolution details +✓ Agent explicitly closed after all interactions +✓ Modification summary includes: + - Total conflicts + - Resolved with strategy (count) + - Custom handling (count) + - Clarification records + - Overlap analysis for custom ModuleOverlap conflicts +✓ Agent log saved to .workflow/active/{session_id}/.chat/ +✓ Error handling robust (validate/retry/degrade) +``` + +## Post-Phase Update + +If Phase 3 was executed, update planning-notes.md: + +```javascript +const conflictResPath = `.workflow/active/${sessionId}/.process/conflict-resolution.json` + +if (file_exists(conflictResPath)) { + const conflictRes = JSON.parse(Read(conflictResPath)) + const resolved = conflictRes.resolved_conflicts || [] + const planningConstraints = conflictRes.planning_constraints || [] + + // Update Phase 3 section + Edit(planningNotesPath, { + old: '## Conflict Decisions (Phase 3)\n(To be filled if conflicts detected)', + new: `## Conflict Decisions (Phase 3) + +- **RESOLVED**: ${resolved.map(r => `${r.conflict_id} → ${r.strategy_name}`).join('; ') || 'None'} +- **CUSTOM_HANDLING**: ${conflictRes.custom_conflicts?.map(c => c.id).join(', ') || 'None'} +- **CONSTRAINTS**: ${planningConstraints.map(c => c.content).join('; ') || 'None'}` + }) + + // Append Phase 3 constraints to consolidated list + if (planningConstraints.length > 0) { + Edit(planningNotesPath, { + old: '## Consolidated Constraints (Phase 4 Input)', + new: `## Consolidated Constraints (Phase 4 Input) +${planningConstraints.map((c, i) => `${constraintCount + i + 1}. [Conflict] ${c.content}`).join('\n')}` + }) + } +} +``` + +## Memory State Check + +After Phase 3 completion, evaluate context window usage. +If memory usage is high (>120K tokens): + +```javascript +// Codex: Use compact command if available +codex compact +``` + +## Output + +- **File**: `.workflow/active/{sessionId}/.process/conflict-resolution.json` +- **Modified files**: brainstorm artifacts (guidance-specification.md, role analyses) +- **Updated**: `context-package.json` with resolved conflict status + +## Next Phase + +Return to orchestrator, then auto-continue to [Phase 4: Task Generation](04-task-generation.md). diff --git a/.codex/skills/workflow-plan/phases/04-task-generation.md b/.codex/skills/workflow-plan/phases/04-task-generation.md new file mode 100644 index 00000000..da9395d3 --- /dev/null +++ b/.codex/skills/workflow-plan/phases/04-task-generation.md @@ -0,0 +1,756 @@ +# Phase 4: Task Generation + +Generate implementation plan documents (IMPL_PLAN.md, task JSONs, TODO_LIST.md) using action-planning-agent - produces planning artifacts, does NOT execute code implementation. + +## Auto Mode + +When `--yes` or `-y`: Skip user questions, use defaults (no materials, Agent executor, Codex CLI tool). + +## Core Philosophy + +- **Planning Only**: Generate planning documents (IMPL_PLAN.md, task JSONs, TODO_LIST.md) - does NOT implement code +- **Agent-Driven Document Generation**: Delegate plan generation to action-planning-agent +- **NO Redundant Context Sorting**: Context priority sorting is ALREADY completed in context-gather Phase 2/3 + - Use `context-package.json.prioritized_context` directly + - DO NOT re-sort files or re-compute priorities + - `priority_tiers` and `dependency_order` are pre-computed and ready-to-use +- **N+1 Parallel Planning**: Auto-detect multi-module projects, enable parallel planning (2+1 or 3+1 mode) +- **Progressive Loading**: Load context incrementally (Core → Selective → On-Demand) due to analysis.md file size +- **Memory-First**: Reuse loaded documents from conversation memory +- **Smart Selection**: Load synthesis_output OR guidance + relevant role analyses, NOT all role analyses +- **MCP-Enhanced**: Use MCP tools for advanced code analysis and research +- **Path Clarity**: All `focus_paths` prefer absolute paths (e.g., `D:\\project\\src\\module`), or clear relative paths from project root (e.g., `./src/module`) +- **Explicit Lifecycle**: Manage subagent lifecycle with spawn_agent → wait → close_agent + +## Execution Process + +``` +Input Parsing: + ├─ Parse flags: --session + └─ Validation: session_id REQUIRED + +Phase 0: User Configuration (Interactive) + ├─ Question 1: Supplementary materials/guidelines? + ├─ Question 2: Execution method preference (Agent/CLI/Hybrid) + ├─ Question 3: CLI tool preference (if CLI selected) + └─ Store: userConfig for agent prompt + +Phase 1: Context Preparation & Module Detection (Command) + ├─ Assemble session paths (metadata, context package, output dirs) + ├─ Provide metadata (session_id, execution_mode, mcp_capabilities) + ├─ Auto-detect modules from context-package + directory structure + └─ Decision: + ├─ modules.length == 1 → Single Agent Mode (Phase 2A) + └─ modules.length >= 2 → Parallel Mode (Phase 2B + Phase 3) + +Phase 2A: Single Agent Planning (Original Flow) + ├─ Spawn action-planning-agent + ├─ Wait for completion + ├─ Close agent + ├─ Outputs: Task JSONs, IMPL_PLAN.md, TODO_LIST.md + └─ Lifecycle: spawn_agent → wait → close_agent + +Phase 2B: N Parallel Planning (Multi-Module) + ├─ Spawn N action-planning-agents simultaneously (one per module) + ├─ Wait for all agents (batch wait) + ├─ Close all agents + ├─ Each generates module-scoped tasks (IMPL-{prefix}{seq}.json) + ├─ Task ID format: IMPL-A1, IMPL-A2... / IMPL-B1, IMPL-B2... + └─ Each module limited to ≤9 tasks + +Phase 3: Integration (+1 Coordinator, Multi-Module Only) + ├─ Spawn coordinator agent + ├─ Wait for completion + ├─ Close agent + ├─ Collect all module task JSONs + ├─ Resolve cross-module dependencies (CROSS::{module}::{pattern} → actual ID) + ├─ Generate unified IMPL_PLAN.md (grouped by module) + └─ Generate TODO_LIST.md (hierarchical: module → tasks) +``` + +## Document Generation Lifecycle + +### Phase 0: User Configuration (Interactive) + +**Purpose**: Collect user preferences before task generation to ensure generated tasks match execution expectations. + +**Auto Mode Check**: +```javascript +const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') + +if (autoYes) { + console.log(`[--yes] Using defaults: No materials, Agent executor, Codex CLI`) + userConfig = { + supplementaryMaterials: { type: "none", content: [] }, + executionMethod: "agent", + preferredCliTool: "codex", + enableResume: true + } + // Skip to Phase 1 +} +``` + +**User Questions** (skipped if autoYes): +```javascript +if (!autoYes) AskUserQuestion({ + questions: [ + { + question: "Do you have supplementary materials or guidelines to include?", + header: "Materials", + multiSelect: false, + options: [ + { label: "No additional materials", description: "Use existing context only" }, + { label: "Provide file paths", description: "I'll specify paths to include" }, + { label: "Provide inline content", description: "I'll paste content directly" } + ] + }, + { + question: "Select execution method for generated tasks:", + header: "Execution", + multiSelect: false, + options: [ + { label: "Agent (Recommended)", description: "Claude agent executes tasks directly" }, + { label: "Hybrid", description: "Agent orchestrates, calls CLI for complex steps" }, + { label: "CLI Only", description: "All execution via CLI tools (codex/gemini/qwen)" } + ] + }, + { + question: "If using CLI, which tool do you prefer?", + header: "CLI Tool", + multiSelect: false, + options: [ + { label: "Codex (Recommended)", description: "Best for implementation tasks" }, + { label: "Gemini", description: "Best for analysis and large context" }, + { label: "Qwen", description: "Alternative analysis tool" }, + { label: "Auto", description: "Let agent decide per-task" } + ] + } + ] +}) +``` + +**Handle Materials Response** (skipped if autoYes): +```javascript +if (!autoYes && userConfig.materials === "Provide file paths") { + // Follow-up question for file paths + const pathsResponse = AskUserQuestion({ + questions: [{ + question: "Enter file paths to include (comma-separated or one per line):", + header: "Paths", + multiSelect: false, + options: [ + { label: "Enter paths", description: "Provide paths in text input" } + ] + }] + }) + userConfig.supplementaryPaths = parseUserPaths(pathsResponse) +} +``` + +**Build userConfig**: +```javascript +const userConfig = { + supplementaryMaterials: { + type: "none|paths|inline", + content: [...], // Parsed paths or inline content + }, + executionMethod: "agent|hybrid|cli", + preferredCliTool: "codex|gemini|qwen|auto", + enableResume: true // Always enable resume for CLI executions +} +``` + +**Pass to Agent**: Include `userConfig` in agent prompt for Phase 2A/2B. + +### Phase 1: Context Preparation & Module Detection (Command Responsibility) + +**Command prepares session paths, metadata, detects module structure. Context priority sorting is NOT performed here - it's already completed in context-gather Phase 2/3.** + +**Session Path Structure**: +``` +.workflow/active/WFS-{session-id}/ +├── workflow-session.json # Session metadata +├── planning-notes.md # Consolidated planning notes +├── .process/ +│ └── context-package.json # Context package with artifact catalog +├── .task/ # Output: Task JSON files +│ ├── IMPL-A1.json # Multi-module: prefixed by module +│ ├── IMPL-A2.json +│ ├── IMPL-B1.json +│ └── ... +├── IMPL_PLAN.md # Output: Implementation plan (grouped by module) +└── TODO_LIST.md # Output: TODO list (hierarchical) +``` + +**Command Preparation**: +1. **Assemble Session Paths** for agent prompt: + - `session_metadata_path` + - `context_package_path` + - Output directory paths + +2. **Provide Metadata** (simple values): + - `session_id` + - `mcp_capabilities` (available MCP tools) + +3. **Auto Module Detection** (determines single vs parallel mode): + ```javascript + function autoDetectModules(contextPackage, projectRoot) { + // === Complexity Gate: Only parallelize for High complexity === + const complexity = contextPackage.metadata?.complexity || 'Medium'; + if (complexity !== 'High') { + // Force single agent mode for Low/Medium complexity + // This maximizes agent context reuse for related tasks + return [{ name: 'main', prefix: '', paths: ['.'] }]; + } + + // Priority 1: Explicit frontend/backend separation + if (exists('src/frontend') && exists('src/backend')) { + return [ + { name: 'frontend', prefix: 'A', paths: ['src/frontend'] }, + { name: 'backend', prefix: 'B', paths: ['src/backend'] } + ]; + } + + // Priority 2: Monorepo structure + if (exists('packages/*') || exists('apps/*')) { + return detectMonorepoModules(); // Returns 2-3 main packages + } + + // Priority 3: Context-package dependency clustering + const modules = clusterByDependencies(contextPackage.dependencies?.internal); + if (modules.length >= 2) return modules.slice(0, 3); + + // Default: Single module (original flow) + return [{ name: 'main', prefix: '', paths: ['.'] }]; + } + ``` + +**Decision Logic**: +- `complexity !== 'High'` → Force Phase 2A (Single Agent, maximize context reuse) +- `modules.length == 1` → Phase 2A (Single Agent, original flow) +- `modules.length >= 2 && complexity == 'High'` → Phase 2B + Phase 3 (N+1 Parallel) + +**Note**: CLI tool usage is now determined semantically by action-planning-agent based on user's task description, not by flags. + +### Phase 2A: Single Agent Planning (Original Flow) + +**Condition**: `modules.length == 1` (no multi-module detected) + +**Purpose**: Generate IMPL_PLAN.md, task JSONs, and TODO_LIST.md - planning documents only, NOT code implementation. + +**Agent Invocation**: +```javascript +// Spawn action-planning-agent +const planningAgentId = spawn_agent({ + message: ` +## TASK ASSIGNMENT + +### MANDATORY FIRST STEPS (Agent Execute) +1. **Read role definition**: ~/.codex/agents/action-planning-agent.md (MUST read first) +2. Read: .workflow/project-tech.json +3. Read: .workflow/project-guidelines.json + +--- + +## TASK OBJECTIVE +Generate implementation planning documents (IMPL_PLAN.md, task JSONs, TODO_LIST.md) for workflow session + +IMPORTANT: This is PLANNING ONLY - you are generating planning documents, NOT implementing code. + +CRITICAL: Follow the progressive loading strategy defined in agent specification (load analysis.md files incrementally due to file size) + +## PLANNING NOTES (PHASE 1-3 CONTEXT) +Load: .workflow/active/${session_id}/planning-notes.md + +This document contains: +- User Intent: Original GOAL and KEY_CONSTRAINTS from Phase 1 +- Context Findings: Critical files, architecture, and constraints from Phase 2 +- Conflict Decisions: Resolved conflicts and planning constraints from Phase 3 +- Consolidated Constraints: All constraints from all phases + +**USAGE**: Read planning-notes.md FIRST. Use Consolidated Constraints list to guide task sequencing and dependencies. + +## SESSION PATHS +Input: + - Session Metadata: .workflow/active/${session_id}/workflow-session.json + - Planning Notes: .workflow/active/${session_id}/planning-notes.md + - Context Package: .workflow/active/${session_id}/.process/context-package.json + +Output: + - Task Dir: .workflow/active/${session_id}/.task/ + - IMPL_PLAN: .workflow/active/${session_id}/IMPL_PLAN.md + - TODO_LIST: .workflow/active/${session_id}/TODO_LIST.md + +## CONTEXT METADATA +Session ID: ${session_id} +MCP Capabilities: {exa_code, exa_web, code_index} + +## USER CONFIGURATION (from Phase 0) +Execution Method: ${userConfig.executionMethod} // agent|hybrid|cli +Preferred CLI Tool: ${userConfig.preferredCliTool} // codex|gemini|qwen|auto +Supplementary Materials: ${userConfig.supplementaryMaterials} + +## EXECUTION METHOD MAPPING +Based on userConfig.executionMethod, set task-level meta.execution_config: + +"agent" → + meta.execution_config = { method: "agent", cli_tool: null, enable_resume: false } + Agent executes implementation_approach steps directly + +"cli" → + meta.execution_config = { method: "cli", cli_tool: userConfig.preferredCliTool, enable_resume: true } + Agent executes pre_analysis, then hands off full context to CLI via buildCliHandoffPrompt() + +"hybrid" → + Per-task decision: Analyze task complexity, set method to "agent" OR "cli" per task + - Simple tasks (≤3 files, straightforward logic) → method: "agent" + - Complex tasks (>3 files, complex logic, refactoring) → method: "cli" + CLI tool: userConfig.preferredCliTool, enable_resume: true + +IMPORTANT: Do NOT add command field to implementation_approach steps. Execution routing is controlled by task-level meta.execution_config.method only. + +## PRIORITIZED CONTEXT (from context-package.prioritized_context) - ALREADY SORTED +Context sorting is ALREADY COMPLETED in context-gather Phase 2/3. DO NOT re-sort. +Direct usage: +- **user_intent**: Use goal/scope/key_constraints for task alignment +- **priority_tiers.critical**: These files are PRIMARY focus for task generation +- **priority_tiers.high**: These files are SECONDARY focus +- **dependency_order**: Use this for task sequencing - already computed +- **sorting_rationale**: Reference for understanding priority decisions + +## EXPLORATION CONTEXT (from context-package.exploration_results) - SUPPLEMENT ONLY +If prioritized_context is incomplete, fall back to exploration_results: +- Load exploration_results from context-package.json +- Use aggregated_insights.critical_files for focus_paths generation +- Apply aggregated_insights.constraints to acceptance criteria +- Reference aggregated_insights.all_patterns for implementation approach +- Use aggregated_insights.all_integration_points for precise modification locations +- Use conflict_indicators for risk-aware task sequencing + +## CONFLICT RESOLUTION CONTEXT (if exists) +- Check context-package.conflict_detection.resolution_file for conflict-resolution.json path +- If exists, load .process/conflict-resolution.json: + - Apply planning_constraints as task constraints (for brainstorm-less workflows) + - Reference resolved_conflicts for implementation approach alignment + - Handle custom_conflicts with explicit task notes + +## EXPECTED DELIVERABLES +1. Task JSON Files (.task/IMPL-*.json) + - 6-field schema (id, title, status, context_package_path, meta, context, flow_control) + - Quantified requirements with explicit counts + - Artifacts integration from context package + - **focus_paths generated directly from prioritized_context.priority_tiers (critical + high)** + - NO re-sorting or re-prioritization - use pre-computed tiers as-is + - Critical files are PRIMARY focus, High files are SECONDARY + - Flow control with pre_analysis steps (use prioritized_context.dependency_order for task sequencing) + - **CLI Execution IDs and strategies (MANDATORY)** + +2. Implementation Plan (IMPL_PLAN.md) + - Context analysis and artifact references + - Task breakdown and execution strategy + - Complete structure per agent definition + +3. TODO List (TODO_LIST.md) + - Hierarchical structure (containers, pending, completed markers) + - Links to task JSONs and summaries + - Matches task JSON hierarchy + +## CLI EXECUTION ID REQUIREMENTS (MANDATORY) +Each task JSON MUST include: +- **cli_execution_id**: Unique ID for CLI execution (format: \`{session_id}-{task_id}\`) +- **cli_execution**: Strategy object based on depends_on: + - No deps → \`{ "strategy": "new" }\` + - 1 dep (single child) → \`{ "strategy": "resume", "resume_from": "parent-cli-id" }\` + - 1 dep (multiple children) → \`{ "strategy": "fork", "resume_from": "parent-cli-id" }\` + - N deps → \`{ "strategy": "merge_fork", "merge_from": ["id1", "id2", ...] }\` + +**CLI Execution Strategy Rules**: +1. **new**: Task has no dependencies - starts fresh CLI conversation +2. **resume**: Task has 1 parent AND that parent has only this child - continues same conversation +3. **fork**: Task has 1 parent BUT parent has multiple children - creates new branch with parent context +4. **merge_fork**: Task has multiple parents - merges all parent contexts into new conversation + +**Execution Command Patterns**: +- new: \`ccw cli -p "[prompt]" --tool [tool] --mode write --id [cli_execution_id]\` +- resume: \`ccw cli -p "[prompt]" --resume [resume_from] --tool [tool] --mode write\` +- fork: \`ccw cli -p "[prompt]" --resume [resume_from] --id [cli_execution_id] --tool [tool] --mode write\` +- merge_fork: \`ccw cli -p "[prompt]" --resume [merge_from.join(',')] --id [cli_execution_id] --tool [tool] --mode write\` + +## QUALITY STANDARDS +Hard Constraints: + - Task count <= 18 (hard limit - request re-scope if exceeded) + - All requirements quantified (explicit counts and enumerated lists) + - Acceptance criteria measurable (include verification commands) + - Artifact references mapped from context package + - All documents follow agent-defined structure + +## SUCCESS CRITERIA +- All planning documents generated successfully: + - Task JSONs valid and saved to .task/ directory + - IMPL_PLAN.md created with complete structure + - TODO_LIST.md generated matching task JSONs +- Return completion status with document count and task breakdown summary + +## PLANNING NOTES RECORD (REQUIRED) +After completing, update planning-notes.md: + +**File**: .workflow/active/${session_id}/planning-notes.md + +1. **Task Generation (Phase 4)**: Task count and key tasks +2. **N+1 Context**: Key decisions (with rationale) + deferred items + +\`\`\`markdown +## Task Generation (Phase 4) +### [Action-Planning Agent] YYYY-MM-DD +- **Tasks**: [count] ([IDs]) + +## N+1 Context +### Decisions +| Decision | Rationale | Revisit? | +|----------|-----------|----------| +| [choice] | [why] | [Yes/No] | + +### Deferred +- [ ] [item] - [reason] +\`\`\` +` +}); + +// Wait for planning agent to complete +const planningResult = wait({ + ids: [planningAgentId], + timeout_ms: 900000 // 15 minutes +}); + +// Close planning agent +close_agent({ id: planningAgentId }); +``` + +### Phase 2B: N Parallel Planning (Multi-Module) + +**Condition**: `modules.length >= 2` (multi-module detected) + +**Purpose**: Launch N action-planning-agents simultaneously, one per module, for parallel task JSON generation. + +**Note**: Phase 2B agents generate Task JSONs ONLY. IMPL_PLAN.md and TODO_LIST.md are generated by Phase 3 Coordinator. + +**Parallel Agent Invocation**: +```javascript +// Spawn N agents in parallel (one per module) +const moduleAgents = []; + +modules.forEach(module => { + const agentId = spawn_agent({ + message: ` +## TASK ASSIGNMENT + +### MANDATORY FIRST STEPS (Agent Execute) +1. **Read role definition**: ~/.codex/agents/action-planning-agent.md (MUST read first) +2. Read: .workflow/project-tech.json +3. Read: .workflow/project-guidelines.json + +--- + +## TASK OBJECTIVE +Generate task JSON files for ${module.name} module within workflow session + +IMPORTANT: This is PLANNING ONLY - generate task JSONs, NOT implementing code. +IMPORTANT: Generate Task JSONs ONLY. IMPL_PLAN.md and TODO_LIST.md by Phase 3 Coordinator. + +CRITICAL: Follow the progressive loading strategy defined in agent specification (load analysis.md files incrementally due to file size) + +## PLANNING NOTES (PHASE 1-3 CONTEXT) +Load: .workflow/active/${session_id}/planning-notes.md + +This document contains consolidated constraints and user intent to guide module-scoped task generation. + +## MODULE SCOPE +- Module: ${module.name} (${module.type}) +- Focus Paths: ${module.paths.join(', ')} +- Task ID Prefix: IMPL-${module.prefix} +- Task Limit: ≤6 tasks (hard limit for this module) +- Other Modules: ${otherModules.join(', ')} (reference only, do NOT generate tasks for them) + +## SESSION PATHS +Input: + - Session Metadata: .workflow/active/${session_id}/workflow-session.json + - Planning Notes: .workflow/active/${session_id}/planning-notes.md + - Context Package: .workflow/active/${session_id}/.process/context-package.json + +Output: + - Task Dir: .workflow/active/${session_id}/.task/ + +## CONTEXT METADATA +Session ID: ${session_id} +MCP Capabilities: {exa_code, exa_web, code_index} + +## USER CONFIGURATION (from Phase 0) +Execution Method: ${userConfig.executionMethod} // agent|hybrid|cli +Preferred CLI Tool: ${userConfig.preferredCliTool} // codex|gemini|qwen|auto +Supplementary Materials: ${userConfig.supplementaryMaterials} + +## EXECUTION METHOD MAPPING +Based on userConfig.executionMethod, set task-level meta.execution_config: + +"agent" → + meta.execution_config = { method: "agent", cli_tool: null, enable_resume: false } + Agent executes implementation_approach steps directly + +"cli" → + meta.execution_config = { method: "cli", cli_tool: userConfig.preferredCliTool, enable_resume: true } + Agent executes pre_analysis, then hands off full context to CLI via buildCliHandoffPrompt() + +"hybrid" → + Per-task decision: Analyze task complexity, set method to "agent" OR "cli" per task + - Simple tasks (≤3 files, straightforward logic) → method: "agent" + - Complex tasks (>3 files, complex logic, refactoring) → method: "cli" + CLI tool: userConfig.preferredCliTool, enable_resume: true + +IMPORTANT: Do NOT add command field to implementation_approach steps. Execution routing is controlled by task-level meta.execution_config.method only. + +## PRIORITIZED CONTEXT (from context-package.prioritized_context) - ALREADY SORTED +Context sorting is ALREADY COMPLETED in context-gather Phase 2/3. DO NOT re-sort. +Filter by module scope (${module.paths.join(', ')}): +- **user_intent**: Use for task alignment within module +- **priority_tiers.critical**: Filter for files in ${module.paths.join(', ')} → PRIMARY focus +- **priority_tiers.high**: Filter for files in ${module.paths.join(', ')} → SECONDARY focus +- **dependency_order**: Use module-relevant entries for task sequencing + +## EXPLORATION CONTEXT (from context-package.exploration_results) - SUPPLEMENT ONLY +If prioritized_context is incomplete for this module, fall back to exploration_results: +- Load exploration_results from context-package.json +- Filter for ${module.name} module: Use aggregated_insights.critical_files matching ${module.paths.join(', ')} +- Apply module-relevant constraints from aggregated_insights.constraints +- Reference aggregated_insights.all_patterns applicable to ${module.name} +- Use aggregated_insights.all_integration_points for precise modification locations within module scope +- Use conflict_indicators for risk-aware task sequencing + +## CONFLICT RESOLUTION CONTEXT (if exists) +- Check context-package.conflict_detection.resolution_file for conflict-resolution.json path +- If exists, load .process/conflict-resolution.json: + - Apply planning_constraints relevant to ${module.name} as task constraints + - Reference resolved_conflicts affecting ${module.name} for implementation approach alignment + - Handle custom_conflicts with explicit task notes + +## CROSS-MODULE DEPENDENCIES +- For dependencies ON other modules: Use placeholder depends_on: ["CROSS::{module}::{pattern}"] +- Example: depends_on: ["CROSS::B::api-endpoint"] (this module depends on B's api-endpoint task) +- Phase 3 Coordinator resolves to actual task IDs +- For dependencies FROM other modules: Document in task context as "provides_for" annotation + +## EXPECTED DELIVERABLES +Task JSON Files (.task/IMPL-${module.prefix}*.json): + - 6-field schema (id, title, status, context_package_path, meta, context, flow_control) + - Task ID format: IMPL-${module.prefix}1, IMPL-${module.prefix}2, ... + - Quantified requirements with explicit counts + - Artifacts integration from context package (filtered for ${module.name}) + - **focus_paths generated directly from prioritized_context.priority_tiers filtered by ${module.paths.join(', ')}** + - NO re-sorting - use pre-computed tiers filtered for this module + - Critical files are PRIMARY focus, High files are SECONDARY + - Flow control with pre_analysis steps (use prioritized_context.dependency_order for module task sequencing) + - **CLI Execution IDs and strategies (MANDATORY)** + - Focus ONLY on ${module.name} module scope + +## CLI EXECUTION ID REQUIREMENTS (MANDATORY) +Each task JSON MUST include: +- **cli_execution_id**: Unique ID for CLI execution (format: \`{session_id}-IMPL-${module.prefix}{seq}\`) +- **cli_execution**: Strategy object based on depends_on: + - No deps → \`{ "strategy": "new" }\` + - 1 dep (single child) → \`{ "strategy": "resume", "resume_from": "parent-cli-id" }\` + - 1 dep (multiple children) → \`{ "strategy": "fork", "resume_from": "parent-cli-id" }\` + - N deps → \`{ "strategy": "merge_fork", "merge_from": ["id1", "id2", ...] }\` + - Cross-module dep → \`{ "strategy": "cross_module_fork", "resume_from": "CROSS::{module}::{pattern}" }\` + +**CLI Execution Strategy Rules**: +1. **new**: Task has no dependencies - starts fresh CLI conversation +2. **resume**: Task has 1 parent AND that parent has only this child - continues same conversation +3. **fork**: Task has 1 parent BUT parent has multiple children - creates new branch with parent context +4. **merge_fork**: Task has multiple parents - merges all parent contexts into new conversation +5. **cross_module_fork**: Task depends on task from another module - Phase 3 resolves placeholder + +**Execution Command Patterns**: +- new: \`ccw cli -p "[prompt]" --tool [tool] --mode write --id [cli_execution_id]\` +- resume: \`ccw cli -p "[prompt]" --resume [resume_from] --tool [tool] --mode write\` +- fork: \`ccw cli -p "[prompt]" --resume [resume_from] --id [cli_execution_id] --tool [tool] --mode write\` +- merge_fork: \`ccw cli -p "[prompt]" --resume [merge_from.join(',')] --id [cli_execution_id] --tool [tool] --mode write\` +- cross_module_fork: (Phase 3 resolves placeholder, then uses fork pattern) + +## QUALITY STANDARDS +Hard Constraints: + - Task count <= 9 for this module (hard limit - coordinate with Phase 3 if exceeded) + - All requirements quantified (explicit counts and enumerated lists) + - Acceptance criteria measurable (include verification commands) + - Artifact references mapped from context package (module-scoped filter) + - Focus paths use absolute paths or clear relative paths from project root + - Cross-module dependencies use CROSS:: placeholder format + +## SUCCESS CRITERIA +- Task JSONs saved to .task/ with IMPL-${module.prefix}* naming +- All task JSONs include cli_execution_id and cli_execution strategy +- Cross-module dependencies use CROSS:: placeholder format consistently +- Focus paths scoped to ${module.paths.join(', ')} only +- Return: task count, task IDs, dependency summary (internal + cross-module) + +## PLANNING NOTES RECORD (REQUIRED) +After completing, append to planning-notes.md: + +\`\`\`markdown +### [${module.name}] YYYY-MM-DD +- **Tasks**: [count] ([IDs]) +- **CROSS deps**: [placeholders used] +\`\`\` + ` + }); + + moduleAgents.push(agentId); +}); + +// Batch wait for all module agents +const moduleResults = wait({ + ids: moduleAgents, + timeout_ms: 900000 // 15 minutes +}); + +// Close all module agents +moduleAgents.forEach(agentId => { + close_agent({ id: agentId }); +}); +``` + +**Output Structure** (direct to .task/): +``` +.task/ +├── IMPL-A1.json # Module A (e.g., frontend) +├── IMPL-A2.json +├── IMPL-B1.json # Module B (e.g., backend) +├── IMPL-B2.json +└── IMPL-C1.json # Module C (e.g., shared) +``` + +**Task ID Naming**: +- Format: `IMPL-{prefix}{seq}.json` +- Prefix: A, B, C... (assigned by detection order) +- Sequence: 1, 2, 3... (per-module increment) + +### Phase 3: Integration (+1 Coordinator Agent, Multi-Module Only) + +**Condition**: Only executed when `modules.length >= 2` + +**Purpose**: Collect all module tasks, resolve cross-module dependencies, generate unified IMPL_PLAN.md and TODO_LIST.md documents. + +**Coordinator Agent Invocation**: +```javascript +// Wait for all Phase 2B agents to complete (already done above) + +// Spawn +1 Coordinator Agent +const coordinatorAgentId = spawn_agent({ + message: ` +## TASK ASSIGNMENT + +### MANDATORY FIRST STEPS (Agent Execute) +1. **Read role definition**: ~/.codex/agents/action-planning-agent.md (MUST read first) +2. Read: .workflow/project-tech.json +3. Read: .workflow/project-guidelines.json + +--- + +## TASK OBJECTIVE +Integrate all module task JSONs, resolve cross-module dependencies, and generate unified IMPL_PLAN.md and TODO_LIST.md + +IMPORTANT: This is INTEGRATION ONLY - consolidate existing task JSONs, NOT creating new tasks. + +## SESSION PATHS +Input: + - Session Metadata: .workflow/active/${session_id}/workflow-session.json + - Context Package: .workflow/active/${session_id}/.process/context-package.json + - Task JSONs: .workflow/active/${session_id}/.task/IMPL-*.json (from Phase 2B) +Output: + - Updated Task JSONs: .workflow/active/${session_id}/.task/IMPL-*.json (resolved dependencies) + - IMPL_PLAN: .workflow/active/${session_id}/IMPL_PLAN.md + - TODO_LIST: .workflow/active/${session_id}/TODO_LIST.md + +## CONTEXT METADATA +Session ID: ${session_id} +Modules: ${modules.map(m => m.name + '(' + m.prefix + ')').join(', ')} +Module Count: ${modules.length} + +## INTEGRATION STEPS +1. Collect all .task/IMPL-*.json, group by module prefix +2. Resolve CROSS:: dependencies → actual task IDs, update task JSONs +3. Generate IMPL_PLAN.md (multi-module format per agent specification) +4. Generate TODO_LIST.md (hierarchical format per agent specification) + +## CROSS-MODULE DEPENDENCY RESOLUTION +- Pattern: CROSS::{module}::{pattern} → IMPL-{module}* matching title/context +- Example: CROSS::B::api-endpoint → IMPL-B1 (if B1 title contains "api-endpoint") +- Log unresolved as warnings + +## EXPECTED DELIVERABLES +1. Updated Task JSONs with resolved dependency IDs +2. IMPL_PLAN.md - multi-module format with cross-dependency section +3. TODO_LIST.md - hierarchical by module with cross-dependency section + +## SUCCESS CRITERIA +- No CROSS:: placeholders remaining in task JSONs +- IMPL_PLAN.md and TODO_LIST.md generated with multi-module structure +- Return: task count, per-module breakdown, resolved dependency count + +## PLANNING NOTES RECORD (REQUIRED) +After integration, update planning-notes.md: + +\`\`\`markdown +### [Coordinator] YYYY-MM-DD +- **Total**: [count] tasks +- **Resolved**: [CROSS:: resolutions] + +## N+1 Context +### Decisions +| Decision | Rationale | Revisit? | +|----------|-----------|----------| +| CROSS::X → IMPL-Y | [why this resolution] | [Yes/No] | + +### Deferred +- [ ] [unresolved CROSS or conflict] - [reason] +\`\`\` + ` +}); + +// Wait for coordinator agent to complete +const coordinatorResult = wait({ + ids: [coordinatorAgentId], + timeout_ms: 600000 // 10 minutes +}); + +// Close coordinator agent +close_agent({ id: coordinatorAgentId }); +``` + +**Dependency Resolution Algorithm**: +```javascript +function resolveCrossModuleDependency(placeholder, allTasks) { + const [, targetModule, pattern] = placeholder.match(/CROSS::(\w+)::(.+)/); + const candidates = allTasks.filter(t => + t.id.startsWith(`IMPL-${targetModule}`) && + (t.title.toLowerCase().includes(pattern.toLowerCase()) || + t.context?.description?.toLowerCase().includes(pattern.toLowerCase())) + ); + return candidates.length > 0 + ? candidates.sort((a, b) => a.id.localeCompare(b.id))[0].id + : placeholder; // Keep for manual resolution +} +``` + +## Output + +- **Files**: + - `.workflow/active/{sessionId}/IMPL_PLAN.md` + - `.workflow/active/{sessionId}/.task/IMPL-*.json` + - `.workflow/active/{sessionId}/TODO_LIST.md` +- **Updated**: `planning-notes.md` with task generation record and N+1 context + +## Next Step + +Return to orchestrator. Present user with action choices: +1. Verify Plan Quality (Recommended) → `workflow:plan-verify` +2. Start Execution → `workflow:execute` +3. Review Status Only → `workflow:status` diff --git a/test-ask-question.js b/test-ask-question.js deleted file mode 100644 index 22a8d069..00000000 --- a/test-ask-question.js +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Test ask_question MCP tool - */ - -import { executeTool } from './ccw/dist/tools/index.js'; - -async function testAskQuestion() { - console.log('Testing ask_question tool...\n'); - - // Test 1: Confirm question - console.log('Test 1: Confirm Question'); - const confirmResult = await executeTool('ask_question', { - question: { - id: 'test-confirm-1', - type: 'confirm', - title: '是否继续执行当前操作?', - message: '这是一个确认对话框测试', - description: '点击确认继续,点击取消终止', - }, - timeout: 30000, // 30 seconds - }); - console.log('Result:', JSON.stringify(confirmResult, null, 2)); - - // Test 2: Select question - console.log('\n\nTest 2: Select Question'); - const selectResult = await executeTool('ask_question', { - question: { - id: 'test-select-1', - type: 'select', - title: '请选择您的偏好颜色', - options: [ - { value: 'red', label: '红色', description: '热情的红色' }, - { value: 'blue', label: '蓝色', description: '冷静的蓝色' }, - { value: 'green', label: '绿色', description: '自然的绿色' }, - ], - }, - timeout: 30000, - }); - console.log('Result:', JSON.stringify(selectResult, null, 2)); - - // Test 3: Input question - console.log('\n\nTest 3: Input Question'); - const inputResult = await executeTool('ask_question', { - question: { - id: 'test-input-1', - type: 'input', - title: '请输入您的名字', - placeholder: '例如: 张三', - required: true, - }, - timeout: 30000, - }); - console.log('Result:', JSON.stringify(inputResult, null, 2)); - - // Test 4: Multi-select question - console.log('\n\nTest 4: Multi-Select Question'); - const multiResult = await executeTool('ask_question', { - question: { - id: 'test-multi-1', - type: 'multi-select', - title: '选择您感兴趣的编程语言(可多选)', - options: [ - { value: 'js', label: 'JavaScript' }, - { value: 'ts', label: 'TypeScript' }, - { value: 'py', label: 'Python' }, - { value: 'go', label: 'Go' }, - ], - }, - timeout: 30000, - }); - console.log('Result:', JSON.stringify(multiResult, null, 2)); - - console.log('\n✅ All tests completed'); -} - -// Run tests -testAskQuestion().catch(console.error); diff --git a/test-cli-command-gen.js b/test-cli-command-gen.js deleted file mode 100644 index 8b7150bd..00000000 --- a/test-cli-command-gen.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Simple test to verify the buildCliCommand function logic - */ -import * as fs from 'fs'; -import * as path from 'path'; -import * as os from 'os'; - -// Simulate buildCliCommand logic -function buildCliCommand(tool, promptFile, model) { - const normalizedPath = promptFile.replace(/\\/g, '/'); - const promptContent = fs.readFileSync(promptFile, 'utf8'); - const escapedPrompt = promptContent.replace(/'/g, "'\\''"); - return `ccw cli -p '${escapedPrompt}' --tool ${tool} --model ${model} --mode write`; -} - -// Test data -const testPromptFile = path.join(os.tmpdir(), 'test-prompt.txt'); -fs.writeFileSync(testPromptFile, 'Test prompt content'); - -console.log('\n=== Build CLI Command Test ===\n'); - -// Test 1: With SECONDARY_MODEL alias -const cmd1 = buildCliCommand('gemini', testPromptFile, 'SECONDARY_MODEL'); -console.log('Test 1: Command with SECONDARY_MODEL alias'); -console.log(' Command:', cmd1.substring(0, 100) + '...'); -console.log(' ✓ Uses ccw cli:', cmd1.includes('ccw cli')); -console.log(' ✓ Has --tool gemini:', cmd1.includes('--tool gemini')); -console.log(' ✓ Has --model SECONDARY_MODEL:', cmd1.includes('--model SECONDARY_MODEL')); -console.log(' ✓ Has --mode write:', cmd1.includes('--mode write')); - -console.log('\n'); - -// Test 2: With explicit model -const cmd2 = buildCliCommand('codex', testPromptFile, 'gpt-5.2'); -console.log('Test 2: Command with explicit model'); -console.log(' Command:', cmd2.substring(0, 100) + '...'); -console.log(' ✓ Uses ccw cli:', cmd2.includes('ccw cli')); -console.log(' ✓ Has --tool codex:', cmd2.includes('--tool codex')); -console.log(' ✓ Has --model gpt-5.2:', cmd2.includes('--model gpt-5.2')); -console.log(' ✓ Has --mode write:', cmd2.includes('--mode write')); - -console.log('\n'); - -// Test 3: Model default fallback logic (simulating execute function) -function getActualModel(userProvidedModel) { - return userProvidedModel || 'SECONDARY_MODEL'; -} - -console.log('Test 3: Model default fallback'); -console.log(' User provides no model:', getActualModel(undefined)); -console.log(' User provides null:', getActualModel(null)); -console.log(' User provides explicit model:', getActualModel('custom-model')); - -// Cleanup -fs.unlinkSync(testPromptFile); - -console.log('\n✅ All command generation tests passed!'); -console.log('\n=== Test Complete ===\n'); diff --git a/test-config.js b/test-config.js deleted file mode 100644 index 103bc32b..00000000 --- a/test-config.js +++ /dev/null @@ -1,7 +0,0 @@ -const { getToolConfig } = require('./ccw/dist/tools/claude-cli-tools.js'); - -const workingDir = 'D:\\Claude_dms3'; -const tool = 'claude'; - -const config = getToolConfig(workingDir, tool); -console.log('Claude tool config:', JSON.stringify(config, null, 2)); diff --git a/test-e2e-model-alias.js b/test-e2e-model-alias.js deleted file mode 100644 index 430cbc22..00000000 --- a/test-e2e-model-alias.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * End-to-end test: Model alias resolution in ccw cli - */ -import { resolveModelAlias, getPrimaryModel, getSecondaryModel } from './ccw/dist/tools/cli-executor-core.js'; -import { getPrimaryModel as getConfigPrimaryModel, getSecondaryModel as getConfigSecondaryModel } from './ccw/dist/tools/claude-cli-tools.js'; - -const testDir = process.cwd(); - -console.log('\n=== End-to-End Model Alias Test ===\n'); - -// Test resolveModelAlias function (this is what ccw cli uses internally) -console.log('Testing resolveModelAlias function:\n'); - -// Test 1: PRIMARY_MODEL for gemini -const result1 = resolveModelAlias('PRIMARY_MODEL', 'gemini', testDir); -const expected1 = getConfigPrimaryModel(testDir, 'gemini'); -console.log('Test 1: PRIMARY_MODEL for gemini'); -console.log(` Input: 'PRIMARY_MODEL'`); -console.log(` Resolved: ${result1}`); -console.log(` Expected: ${expected1}`); -console.log(` ✓ Match: ${result1 === expected1}\n`); - -// Test 2: SECONDARY_MODEL for gemini -const result2 = resolveModelAlias('SECONDARY_MODEL', 'gemini', testDir); -const expected2 = getConfigSecondaryModel(testDir, 'gemini'); -console.log('Test 2: SECONDARY_MODEL for gemini'); -console.log(` Input: 'SECONDARY_MODEL'`); -console.log(` Resolved: ${result2}`); -console.log(` Expected: ${expected2}`); -console.log(` ✓ Match: ${result2 === expected2}\n`); - -// Test 3: SECONDARY_MODEL for claude (different values) -const result3 = resolveModelAlias('SECONDARY_MODEL', 'claude', testDir); -const expected3 = getConfigSecondaryModel(testDir, 'claude'); -console.log('Test 3: SECONDARY_MODEL for claude'); -console.log(` Input: 'SECONDARY_MODEL'`); -console.log(` Resolved: ${result3}`); -console.log(` Expected: ${expected3}`); -console.log(` ✓ Match: ${result3 === expected3}\n`); - -// Test 4: secondary_model (lowercase - should be case-insensitive) -const result4 = resolveModelAlias('secondary_model', 'codex', testDir); -const expected4 = getConfigSecondaryModel(testDir, 'codex'); -console.log('Test 4: secondary_model (lowercase) for codex'); -console.log(` Input: 'secondary_model'`); -console.log(` Resolved: ${result4}`); -console.log(` Expected: ${expected4}`); -console.log(` ✓ Match: ${result4 === expected4}\n`); - -// Test 5: Explicit model (should pass through unchanged) -const result5 = resolveModelAlias('custom-model-123', 'gemini', testDir); -console.log('Test 5: Explicit model name (not an alias)'); -console.log(` Input: 'custom-model-123'`); -console.log(` Resolved: ${result5}`); -console.log(` Expected: 'custom-model-123'`); -console.log(` ✓ Match: ${result5 === 'custom-model-123'}\n`); - -// Test 6: Undefined model (should return undefined) -const result6 = resolveModelAlias(undefined, 'gemini', testDir); -console.log('Test 6: Undefined model'); -console.log(` Input: undefined`); -console.log(` Resolved: ${result6}`); -console.log(` Expected: undefined`); -console.log(` ✓ Match: ${result6 === undefined}\n`); - -// Summary -console.log('Summary:'); -console.log(' ✓ PRIMARY_MODEL alias works'); -console.log(' ✓ SECONDARY_MODEL alias works'); -console.log(' ✓ Case-insensitive matching works'); -console.log(' ✓ Explicit model names pass through'); -console.log(' ✓ Undefined handling works correctly'); - -console.log('\n✅ All end-to-end tests passed!'); -console.log('\n=== Test Complete ===\n'); diff --git a/test-model-alias.js b/test-model-alias.js deleted file mode 100644 index df1c1452..00000000 --- a/test-model-alias.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Test model alias resolution - */ -import { getSecondaryModel, getPrimaryModel } from './ccw/dist/tools/claude-cli-tools.js'; - -const testDir = process.cwd(); - -console.log('\n=== Model Alias Resolution Test ===\n'); - -// Test gemini -const geminiPrimary = getPrimaryModel(testDir, 'gemini'); -const geminiSecondary = getSecondaryModel(testDir, 'gemini'); -console.log('Gemini:'); -console.log(` PRIMARY_MODEL => ${geminiPrimary}`); -console.log(` SECONDARY_MODEL => ${geminiSecondary}`); - -// Test claude -const claudePrimary = getPrimaryModel(testDir, 'claude'); -const claudeSecondary = getSecondaryModel(testDir, 'claude'); -console.log('\nClaude:'); -console.log(` PRIMARY_MODEL => ${claudePrimary}`); -console.log(` SECONDARY_MODEL => ${claudeSecondary}`); - -// Test codex -const codexPrimary = getPrimaryModel(testDir, 'codex'); -const codexSecondary = getSecondaryModel(testDir, 'codex'); -console.log('\nCodex:'); -console.log(` PRIMARY_MODEL => ${codexPrimary}`); -console.log(` SECONDARY_MODEL => ${codexSecondary}`); - -console.log('\n=== Test Complete ===\n'); diff --git a/test-model-alias.txt b/test-model-alias.txt deleted file mode 100644 index d991dd33..00000000 --- a/test-model-alias.txt +++ /dev/null @@ -1,2 +0,0 @@ -Test prompt for model alias resolution. -This should be executed with SECONDARY_MODEL. \ No newline at end of file diff --git a/test-report.js b/test-report.js deleted file mode 100644 index 6c6448bd..00000000 --- a/test-report.js +++ /dev/null @@ -1,99 +0,0 @@ -/** - * Integration Test Summary Report - * Testing model alias resolution feature - */ - -console.log('\n╔════════════════════════════════════════════════════════════════╗'); -console.log('║ Model Alias Resolution - Integration Test Report ║'); -console.log('╚════════════════════════════════════════════════════════════════╝\n'); - -console.log('Test Date:', new Date().toISOString()); -console.log('Project: Claude DMS3 / CCW\n'); - -console.log('─────────────────────────────────────────────────────────────────'); -console.log('📋 Feature Overview'); -console.log('─────────────────────────────────────────────────────────────────\n'); - -console.log('Added support for model aliases in ccw cli:'); -console.log(' • PRIMARY_MODEL → resolves to tool\'s primaryModel'); -console.log(' • SECONDARY_MODEL → resolves to tool\'s secondaryModel'); -console.log(' • Case-insensitive matching (primary_model, PRIMARY_MODEL)'); -console.log(' • Non-alias values pass through unchanged\n'); - -console.log('─────────────────────────────────────────────────────────────────'); -console.log('✅ Test Results - All Passed'); -console.log('─────────────────────────────────────────────────────────────────\n'); - -console.log('Test 1: Configuration Reading'); -console.log(' ✓ getPrimaryModel() reads cli-tools.json correctly'); -console.log(' ✓ getSecondaryModel() reads cli-tools.json correctly'); -console.log(' ✓ Gemini: primary=gemini-2.5-flash, secondary=gemini-2.5-flash'); -console.log(' ✓ Claude: primary=sonnet, secondary=haiku'); -console.log(' ✓ Codex: primary=gpt-5.2, secondary=gpt-5.2\n'); - -console.log('Test 2: Command Generation (update_module_claude)'); -console.log(' ✓ Generates ccw cli commands (not direct tool calls)'); -console.log(' ✓ Uses SECONDARY_MODEL as default when no model specified'); -console.log(' ✓ Includes --mode write parameter'); -console.log(' ✓ Includes --tool parameter'); -console.log(' ✓ Properly escapes prompt content\n'); - -console.log('Test 3: Code Compilation'); -console.log(' ✓ TypeScript compilation successful (backend)'); -console.log(' ✓ resolveModelAlias() function compiled correctly'); -console.log(' ✓ Function called in 2 code paths:'); -console.log(' - Standard tools (gemini, qwen, codex, claude)'); -console.log(' - API endpoints (LiteLLM integration)\n'); - -console.log('─────────────────────────────────────────────────────────────────'); -console.log('📝 Modified Files'); -console.log('─────────────────────────────────────────────────────────────────\n'); - -console.log('1. ccw/src/tools/cli-executor-core.ts'); -console.log(' • Added resolveModelAlias() function'); -console.log(' • Imported getSecondaryModel from claude-cli-tools'); -console.log(' • Applied alias resolution to effectiveModel calculation'); -console.log(' • Applied alias resolution to apiEndpointEffectiveModel\n'); - -console.log('2. ccw/src/tools/update-module-claude.js'); -console.log(' • Removed getSecondaryModel() function (no longer needed)'); -console.log(' • Removed DEFAULT_MODELS constant'); -console.log(' • Changed default model to \'SECONDARY_MODEL\' string'); -console.log(' • Updated buildCliCommand to use ccw cli'); -console.log(' • Updated tool description\n'); - -console.log('3. ccw/src/commands/cli.ts'); -console.log(' • Updated --model help text to mention aliases\n'); - -console.log('─────────────────────────────────────────────────────────────────'); -console.log('💡 Usage Examples'); -console.log('─────────────────────────────────────────────────────────────────\n'); - -console.log('# Use secondary model (via alias)'); -console.log('ccw cli -p "prompt" --tool gemini --model SECONDARY_MODEL --mode write\n'); - -console.log('# Use primary model (via alias)'); -console.log('ccw cli -p "prompt" --tool claude --model PRIMARY_MODEL --mode analysis\n'); - -console.log('# Explicit model (no alias)'); -console.log('ccw cli -p "prompt" --tool codex --model gpt-5.2 --mode write\n'); - -console.log('# Default behavior (uses primary model from config)'); -console.log('ccw cli -p "prompt" --tool gemini --mode analysis\n'); - -console.log('# update_module_claude tool (automatically uses SECONDARY_MODEL)'); -console.log('ccw tool exec update_module_claude \'{"strategy":"multi-layer","tool":"gemini"}\'\n'); - -console.log('─────────────────────────────────────────────────────────────────'); -console.log('🎯 Benefits'); -console.log('─────────────────────────────────────────────────────────────────\n'); - -console.log('✓ Centralized: All model config logic in ccw cli'); -console.log('✓ Simplified: External tools don\'t need to read cli-tools.json'); -console.log('✓ Consistent: Same alias resolution across all tools'); -console.log('✓ Flexible: Supports both aliases and explicit model names'); -console.log('✓ Maintainable: Change models in one place (cli-tools.json)\n'); - -console.log('─────────────────────────────────────────────────────────────────'); -console.log('✅ CONCLUSION: All tests passed, feature ready for use'); -console.log('─────────────────────────────────────────────────────────────────\n'); diff --git a/test-update-claude-command.js b/test-update-claude-command.js deleted file mode 100644 index 832f4485..00000000 --- a/test-update-claude-command.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Test update_module_claude command generation - */ -import { updateModuleClaudeTool } from './ccw/dist/tools/update-module-claude.js'; - -console.log('\n=== Update Module Claude Tool Test ===\n'); - -// Mock execSync to capture the command without executing it -let capturedCommand = null; -const originalExecSync = (await import('child_process')).execSync; - -// Temporarily replace execSync -const childProcess = await import('child_process'); -childProcess.execSync = function(command, options) { - capturedCommand = command; - console.log('Generated Command:'); - console.log(command); - throw new Error('Test mode - command not executed'); -}; - -// Test parameters -const testParams = { - strategy: 'single-layer', - path: './test-update-claude/src', - tool: 'gemini' - // Note: no model specified, should default to SECONDARY_MODEL -}; - -console.log('Test Parameters:'); -console.log(JSON.stringify(testParams, null, 2)); -console.log('\n'); - -try { - await updateModuleClaudeTool.execute(testParams); -} catch (err) { - if (err.message !== 'Test mode - command not executed') { - console.error('Error:', err.message); - } -} - -// Restore original -childProcess.execSync = originalExecSync; - -// Analyze the captured command -if (capturedCommand) { - console.log('\nCommand Analysis:'); - const hasSecondaryModel = capturedCommand.includes('SECONDARY_MODEL'); - const hasCcwCli = capturedCommand.includes('ccw cli'); - const hasModeWrite = capturedCommand.includes('--mode write'); - const hasToolGemini = capturedCommand.includes('--tool gemini'); - - console.log(` ✓ Uses ccw cli: ${hasCcwCli}`); - console.log(` ✓ Has --mode write: ${hasModeWrite}`); - console.log(` ✓ Has --tool gemini: ${hasToolGemini}`); - console.log(` ✓ Uses SECONDARY_MODEL alias: ${hasSecondaryModel}`); - - if (hasCcwCli && hasModeWrite && hasToolGemini && hasSecondaryModel) { - console.log('\n✅ Test PASSED - Command generation is correct!'); - } else { - console.log('\n❌ Test FAILED - Command generation has issues'); - } -} - -console.log('\n=== Test Complete ===\n'); diff --git a/test-update-claude/src/test.js b/test-update-claude/src/test.js deleted file mode 100644 index af2aa014..00000000 --- a/test-update-claude/src/test.js +++ /dev/null @@ -1 +0,0 @@ -// Test file