diff --git a/.claude/skills/team-issue/SKILL.md b/.claude/skills/team-issue/SKILL.md new file mode 100644 index 00000000..d9a76837 --- /dev/null +++ b/.claude/skills/team-issue/SKILL.md @@ -0,0 +1,389 @@ +--- +name: team-issue +description: Unified team skill for issue resolution. All roles invoke this skill with --role arg for role-specific execution. Triggers on "team issue". +allowed-tools: TeamCreate(*), TeamDelete(*), SendMessage(*), TaskCreate(*), TaskUpdate(*), TaskList(*), TaskGet(*), Task(*), AskUserQuestion(*), Read(*), Write(*), Edit(*), Bash(*), Glob(*), Grep(*) +--- + +# Team Issue Resolution + +Unified team skill for issue processing pipeline. All team members invoke this skill with `--role=xxx` for role-specific execution. + +**Scope**: Issue 处理流程(plan → queue → execute)。Issue 创建/发现由 `issue-discover` 独立处理,CRUD 管理由 `issue-manage` 独立处理。 + +## Architecture Overview + +``` +┌───────────────────────────────────────────┐ +│ Skill(skill="team-issue") │ +│ args="--role=xxx [issue-ids] [--mode=M]" │ +└───────────────┬───────────────────────────┘ + │ Role Router + ┌───────────┼───────────┬───────────┬───────────┬───────────┐ + ↓ ↓ ↓ ↓ ↓ ↓ +┌──────────┐┌──────────┐┌──────────┐┌──────────┐┌──────────┐┌──────────┐ +│coordinator││explorer ││planner ││reviewer ││integrator││implementer│ +│ 编排调度 ││EXPLORE-* ││SOLVE-* ││AUDIT-* ││MARSHAL-* ││BUILD-* │ +└──────────┘└──────────┘└──────────┘└──────────┘└──────────┘└──────────┘ +``` + +## Command Architecture + +``` +roles/ +├── coordinator.md # Pipeline 编排(Phase 1/5 inline, Phase 2-4 core logic) +├── explorer.md # 上下文分析(ACE + cli-explore-agent) +├── planner.md # 方案设计(wraps issue-plan-agent) +├── reviewer.md # 方案审查(技术可行性 + 风险评估) +├── integrator.md # 队列编排(wraps issue-queue-agent) +└── implementer.md # 代码实现(wraps code-developer) +``` + +## Role Router + +### Input Parsing + +Parse `$ARGUMENTS` to extract `--role`: + +```javascript +const args = "$ARGUMENTS" +const roleMatch = args.match(/--role[=\s]+(\w+)/) + +if (!roleMatch) { + // No --role: this is a coordinator entry point + // Extract issue IDs and mode from args directly + // → Read roles/coordinator.md and execute + Read("roles/coordinator.md") + return +} + +const role = roleMatch[1] +const teamName = "issue" +``` + +### Role Dispatch + +```javascript +const VALID_ROLES = { + "coordinator": { file: "roles/coordinator.md", prefix: null }, + "explorer": { file: "roles/explorer.md", prefix: "EXPLORE" }, + "planner": { file: "roles/planner.md", prefix: "SOLVE" }, + "reviewer": { file: "roles/reviewer.md", prefix: "AUDIT" }, + "integrator": { file: "roles/integrator.md", prefix: "MARSHAL" }, + "implementer": { file: "roles/implementer.md", prefix: "BUILD" } +} + +if (!VALID_ROLES[role]) { + throw new Error(`Unknown role: ${role}. Available: ${Object.keys(VALID_ROLES).join(', ')}`) +} + +// Read and execute role-specific logic +Read(VALID_ROLES[role].file) +// → Execute the 5-phase process defined in that file +``` + +### Available Roles + +| Role | Task Prefix | Responsibility | Reuses Agent | Role File | +|------|-------------|----------------|--------------|-----------| +| `coordinator` | N/A | Pipeline 编排、模式选择、任务分派 | - | [roles/coordinator.md](roles/coordinator.md) | +| `explorer` | EXPLORE-* | 上下文分析、影响面评估 | cli-explore-agent | [roles/explorer.md](roles/explorer.md) | +| `planner` | SOLVE-* | 方案设计、任务分解 | issue-plan-agent | [roles/planner.md](roles/planner.md) | +| `reviewer` | AUDIT-* | 方案审查、风险评估 | - (新角色) | [roles/reviewer.md](roles/reviewer.md) | +| `integrator` | MARSHAL-* | 冲突检测、队列编排 | issue-queue-agent | [roles/integrator.md](roles/integrator.md) | +| `implementer` | BUILD-* | 代码实现、结果提交 | code-developer | [roles/implementer.md](roles/implementer.md) | + +## Shared Infrastructure + +### Role Isolation Rules + +**核心原则**: 每个角色仅能执行自己职责范围内的工作。 + +#### Output Tagging(强制) + +所有角色的输出必须带 `[role_name]` 标识前缀: + +```javascript +// SendMessage — content 和 summary 都必须带标识 +SendMessage({ + content: `## [${role}] ...`, + summary: `[${role}] ...` +}) + +// team_msg — summary 必须带标识 +mcp__ccw-tools__team_msg({ + summary: `[${role}] ...` +}) +``` + +#### Coordinator 隔离 + +| 允许 | 禁止 | +|------|------| +| 需求澄清 (AskUserQuestion) | ❌ 直接编写/修改代码 | +| 创建任务链 (TaskCreate) | ❌ 调用 issue-plan-agent 等实现类 agent | +| 分发任务给 worker | ❌ 直接执行分析/审查 | +| 监控进度 (消息总线) | ❌ 绕过 worker 自行完成任务 | +| 汇报结果给用户 | ❌ 修改源代码或产物文件 | + +#### Worker 隔离 + +| 允许 | 禁止 | +|------|------| +| 处理自己前缀的任务 | ❌ 处理其他角色前缀的任务 | +| SendMessage 给 coordinator | ❌ 直接与其他 worker 通信 | +| 使用 Toolbox 中声明的工具 | ❌ 为其他角色创建任务 (TaskCreate) | +| 委派给复用的 agent | ❌ 修改不属于本职责的资源 | + +### Team Configuration + +```javascript +const TEAM_CONFIG = { + name: "issue", + sessionDir: ".workflow/.team-plan/issue/", + msgDir: ".workflow/.team-msg/issue/", + issueDataDir: ".workflow/issues/" +} +``` + +### Message Bus (All Roles) + +Every SendMessage **before**, must call `mcp__ccw-tools__team_msg` to log: + +```javascript +mcp__ccw-tools__team_msg({ + operation: "log", + team: "issue", + from: role, // current role name + to: "coordinator", + type: "", + summary: "[role] ", + ref: "" // optional +}) +``` + +**Message types by role**: + +| Role | Types | +|------|-------| +| coordinator | `task_assigned`, `pipeline_update`, `escalation`, `shutdown`, `error` | +| explorer | `context_ready`, `impact_assessed`, `error` | +| planner | `solution_ready`, `multi_solution`, `error` | +| reviewer | `approved`, `rejected`, `concerns`, `error` | +| integrator | `queue_ready`, `conflict_found`, `error` | +| implementer | `impl_complete`, `impl_failed`, `error` | + +### CLI 回退 + +当 `mcp__ccw-tools__team_msg` MCP 不可用时: + +```javascript +Bash(`ccw team log --team "issue" --from "${role}" --to "coordinator" --type "" --summary "<摘要>" --json`) +``` + +### Task Lifecycle (All Roles) + +```javascript +// Standard task lifecycle every role follows +// Phase 1: Discovery +const tasks = TaskList() +const myTasks = tasks.filter(t => + t.subject.startsWith(`${VALID_ROLES[role].prefix}-`) && + t.owner === role && + t.status === 'pending' && + t.blockedBy.length === 0 +) +if (myTasks.length === 0) return // idle +const task = TaskGet({ taskId: myTasks[0].id }) +TaskUpdate({ taskId: task.id, status: 'in_progress' }) + +// Phase 2-4: Role-specific (see roles/{role}.md) + +// Phase 5: Report + Loop — 所有输出必须带 [role] 标识 +mcp__ccw-tools__team_msg({ operation: "log", team: "issue", from: role, to: "coordinator", type: "...", summary: `[${role}] ...` }) +SendMessage({ type: "message", recipient: "coordinator", content: `## [${role}] ...`, summary: `[${role}] ...` }) +TaskUpdate({ taskId: task.id, status: 'completed' }) +// Check for next task → back to Phase 1 +``` + +## Pipeline Modes + +``` +Quick Mode (1-2 simple issues): + EXPLORE-001 → SOLVE-001 → MARSHAL-001 → BUILD-001 + +Full Mode (complex issues, with review): + EXPLORE-001 → SOLVE-001 → AUDIT-001 ─┬─(approved)→ MARSHAL-001 → BUILD-001..N(parallel) + └─(rejected)→ SOLVE-fix → AUDIT-002(re-review, max 2x) + +Batch Mode (5-100 issues): + EXPLORE-001..N(batch≤5) → SOLVE-001..N(batch≤3) → AUDIT-001(batch) → MARSHAL-001 → BUILD-001..M(DAG parallel) +``` + +### Mode Auto-Detection + +```javascript +function detectMode(issueIds, userMode) { + if (userMode) return userMode // 用户显式指定 + + const count = issueIds.length + if (count <= 2) { + // Check complexity via issue priority + const issues = issueIds.map(id => JSON.parse(Bash(`ccw issue status ${id} --json`))) + const hasHighPriority = issues.some(i => i.priority >= 4) + return hasHighPriority ? 'full' : 'quick' + } + return 'batch' +} +``` + +## Coordinator Spawn Template + +```javascript +TeamCreate({ team_name: "issue" }) + +// Explorer +Task({ + subagent_type: "general-purpose", + team_name: "issue", + name: "explorer", + prompt: `你是 team "issue" 的 EXPLORER。 + +当你收到 EXPLORE-* 任务时,调用 Skill(skill="team-issue", args="--role=explorer") 执行。 + +当前需求: ${taskDescription} +约束: ${constraints} + +## 角色准则(强制) +- 你只能处理 EXPLORE-* 前缀的任务,不得执行其他角色的工作 +- 所有输出(SendMessage、team_msg)必须带 [explorer] 标识前缀 +- 仅与 coordinator 通信,不得直接联系其他 worker +- 不得使用 TaskCreate 为其他角色创建任务 + +## 消息总线(必须) +每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。 + +工作流程: +1. TaskList → 找到 EXPLORE-* 任务 +2. Skill(skill="team-issue", args="--role=explorer") 执行 +3. team_msg log + SendMessage 结果给 coordinator(带 [explorer] 标识) +4. TaskUpdate completed → 检查下一个任务` +}) + +// Planner +Task({ + subagent_type: "general-purpose", + team_name: "issue", + name: "planner", + prompt: `你是 team "issue" 的 PLANNER。 + +当你收到 SOLVE-* 任务时,调用 Skill(skill="team-issue", args="--role=planner") 执行。 + +当前需求: ${taskDescription} +约束: ${constraints} + +## 角色准则(强制) +- 你只能处理 SOLVE-* 前缀的任务 +- 所有输出必须带 [planner] 标识前缀 +- 仅与 coordinator 通信 + +## 消息总线(必须) +每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。 + +工作流程: +1. TaskList → 找到 SOLVE-* 任务 +2. Skill(skill="team-issue", args="--role=planner") 执行 +3. team_msg log + SendMessage 结果给 coordinator +4. TaskUpdate completed → 检查下一个任务` +}) + +// Reviewer +Task({ + subagent_type: "general-purpose", + team_name: "issue", + name: "reviewer", + prompt: `你是 team "issue" 的 REVIEWER。 + +当你收到 AUDIT-* 任务时,调用 Skill(skill="team-issue", args="--role=reviewer") 执行。 + +当前需求: ${taskDescription} +约束: ${constraints} + +## 角色准则(强制) +- 你只能处理 AUDIT-* 前缀的任务 +- 所有输出必须带 [reviewer] 标识前缀 +- 仅与 coordinator 通信 +- 你是质量门控角色,审查方案但不修改代码 + +## 消息总线(必须) +每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。 + +工作流程: +1. TaskList → 找到 AUDIT-* 任务 +2. Skill(skill="team-issue", args="--role=reviewer") 执行 +3. team_msg log + SendMessage 结果给 coordinator +4. TaskUpdate completed → 检查下一个任务` +}) + +// Integrator +Task({ + subagent_type: "general-purpose", + team_name: "issue", + name: "integrator", + prompt: `你是 team "issue" 的 INTEGRATOR。 + +当你收到 MARSHAL-* 任务时,调用 Skill(skill="team-issue", args="--role=integrator") 执行。 + +当前需求: ${taskDescription} +约束: ${constraints} + +## 角色准则(强制) +- 你只能处理 MARSHAL-* 前缀的任务 +- 所有输出必须带 [integrator] 标识前缀 +- 仅与 coordinator 通信 + +## 消息总线(必须) +每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。 + +工作流程: +1. TaskList → 找到 MARSHAL-* 任务 +2. Skill(skill="team-issue", args="--role=integrator") 执行 +3. team_msg log + SendMessage 结果给 coordinator +4. TaskUpdate completed → 检查下一个任务` +}) + +// Implementer +Task({ + subagent_type: "general-purpose", + team_name: "issue", + name: "implementer", + prompt: `你是 team "issue" 的 IMPLEMENTER。 + +当你收到 BUILD-* 任务时,调用 Skill(skill="team-issue", args="--role=implementer") 执行。 + +当前需求: ${taskDescription} +约束: ${constraints} + +## 角色准则(强制) +- 你只能处理 BUILD-* 前缀的任务 +- 所有输出必须带 [implementer] 标识前缀 +- 仅与 coordinator 通信 + +## 消息总线(必须) +每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。 + +工作流程: +1. TaskList → 找到 BUILD-* 任务 +2. Skill(skill="team-issue", args="--role=implementer") 执行 +3. team_msg log + SendMessage 结果给 coordinator +4. TaskUpdate completed → 检查下一个任务` +}) +``` + +## Error Handling + +| Scenario | Resolution | +|----------|------------| +| Unknown --role value | Error with available role list | +| Missing --role arg | Default to coordinator role | +| Role file not found | Error with expected path (roles/{name}.md) | +| Task prefix conflict | Log warning, proceed | diff --git a/.claude/skills/team-issue/roles/coordinator.md b/.claude/skills/team-issue/roles/coordinator.md new file mode 100644 index 00000000..c8d591f7 --- /dev/null +++ b/.claude/skills/team-issue/roles/coordinator.md @@ -0,0 +1,373 @@ +# Role: coordinator + +Team coordinator. Orchestrates the issue resolution pipeline: requirement clarification → mode selection → team creation → task chain → dispatch → monitoring → reporting. + +## Role Identity + +- **Name**: `coordinator` +- **Task Prefix**: N/A (coordinator creates tasks, doesn't receive them) +- **Responsibility**: Orchestration +- **Communication**: SendMessage to all teammates +- **Output Tag**: `[coordinator]` + +## Role Boundaries + +### MUST + +- 所有输出(SendMessage、team_msg、日志)必须带 `[coordinator]` 标识 +- 仅负责需求澄清、模式选择、任务创建/分发、进度监控、结果汇报 +- 通过 TaskCreate 创建任务并分配给 worker 角色 +- 通过消息总线监控 worker 进度并路由消息 + +### MUST NOT + +- ❌ **直接执行任何业务任务**(代码编写、方案设计、审查等) +- ❌ 直接调用 issue-plan-agent、issue-queue-agent、code-developer 等 agent +- ❌ 直接修改源代码或生成产物文件 +- ❌ 绕过 worker 角色自行完成应委派的工作 +- ❌ 在输出中省略 `[coordinator]` 标识 + +> **核心原则**: coordinator 是指挥者,不是执行者。所有实际工作必须通过 TaskCreate 委派给 worker 角色。 + +## Message Types + +| Type | Direction | Trigger | Description | +|------|-----------|---------|-------------| +| `task_assigned` | coordinator → worker | Task dispatched | 通知 worker 有新任务 | +| `pipeline_update` | coordinator → user | Progress milestone | 流水线进度更新 | +| `escalation` | coordinator → user | Unresolvable issue | 升级到用户决策 | +| `shutdown` | coordinator → all | Team dissolved | 团队关闭 | + +## Execution + +### Phase 0: Session Resume + +```javascript +// Check for existing team session +const existingMsgs = mcp__ccw-tools__team_msg({ operation: "list", team: "issue" }) +if (existingMsgs && existingMsgs.length > 0) { + // Resume: check pending tasks and continue coordination loop + // Skip Phase 1-3, go directly to Phase 4 +} +``` + +### Phase 1: Requirement Clarification + +Parse `$ARGUMENTS` for issue IDs and mode. + +```javascript +const args = "$ARGUMENTS" + +// Extract issue IDs (GH-xxx, ISS-xxx formats) +const issueIds = args.match(/(?:GH-\d+|ISS-\d{8}-\d{6})/g) || [] + +// Extract mode +const modeMatch = args.match(/--mode[=\s]+(quick|full|batch)/) +const explicitMode = modeMatch ? modeMatch[1] : null + +// If --all-pending, load all pending issues +if (args.includes('--all-pending')) { + const pendingList = Bash(`ccw issue list --status registered,pending --json`) + const pending = JSON.parse(pendingList) + issueIds.push(...pending.map(i => i.id)) +} + +if (issueIds.length === 0) { + // Ask user for issue IDs + const answer = AskUserQuestion({ + questions: [{ + question: "请提供要处理的 issue ID(支持多个,逗号分隔)", + header: "Issue IDs", + multiSelect: false, + options: [ + { label: "输入 ID", description: "手动输入 issue ID(GH-123 或 ISS-20260215-120000)" }, + { label: "全部 pending", description: "处理所有 registered/pending 状态的 issue" } + ] + }] + }) +} + +// Auto-detect mode +const mode = detectMode(issueIds, explicitMode) +``` + +**Mode Auto-Detection**: +```javascript +function detectMode(issueIds, userMode) { + if (userMode) return userMode + const count = issueIds.length + if (count <= 2) { + const issues = issueIds.map(id => JSON.parse(Bash(`ccw issue status ${id} --json`))) + const hasHighPriority = issues.some(i => i.priority >= 4) + return hasHighPriority ? 'full' : 'quick' + } + return count <= 5 ? 'full' : 'batch' +} +``` + +### Phase 2: Create Team + Spawn Workers + +```javascript +TeamCreate({ team_name: "issue" }) + +// Spawn workers based on mode +const workersToSpawn = mode === 'quick' + ? ['explorer', 'planner', 'integrator', 'implementer'] // No reviewer in quick mode + : ['explorer', 'planner', 'reviewer', 'integrator', 'implementer'] + +for (const workerName of workersToSpawn) { + Task({ + subagent_type: "general-purpose", + team_name: "issue", + name: workerName, + prompt: `你是 team "issue" 的 ${workerName.toUpperCase()}。 +当你收到任务时,调用 Skill(skill="team-issue", args="--role=${workerName}") 执行。 +当前需求: 处理 issue ${issueIds.join(', ')},模式: ${mode} +约束: CLI-first data access, 所有 issue 操作通过 ccw issue 命令 + +## 角色准则(强制) +- 所有输出必须带 [${workerName}] 标识前缀 +- 仅与 coordinator 通信 +- 每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录 + +工作流程: +1. TaskList → 找到分配给你的任务 +2. Skill(skill="team-issue", args="--role=${workerName}") 执行 +3. team_msg log + SendMessage 结果给 coordinator +4. TaskUpdate completed → 检查下一个任务` + }) +} +``` + +### Phase 3: Create Task Chain + +**Quick Mode**: +```javascript +// EXPLORE → SOLVE → MARSHAL → BUILD +for (const issueId of issueIds) { + const exploreId = TaskCreate({ + subject: `EXPLORE-001: Analyze context for ${issueId}`, + description: `Explore codebase context for issue ${issueId}. Load issue via ccw issue status ${issueId} --json, then perform ACE semantic search and impact analysis.`, + activeForm: `Exploring ${issueId}`, + owner: "explorer" + }) + + const solveId = TaskCreate({ + subject: `SOLVE-001: Design solution for ${issueId}`, + description: `Design solution for issue ${issueId} using issue-plan-agent. Context report from EXPLORE-001.`, + activeForm: `Planning ${issueId}`, + owner: "planner", + addBlockedBy: [exploreId] + }) + + const marshalId = TaskCreate({ + subject: `MARSHAL-001: Form queue for ${issueId}`, + description: `Form execution queue for issue ${issueId} solution using issue-queue-agent.`, + activeForm: `Forming queue`, + owner: "integrator", + addBlockedBy: [solveId] + }) + + TaskCreate({ + subject: `BUILD-001: Implement solution for ${issueId}`, + description: `Implement solution for issue ${issueId}. Load via ccw issue detail , execute tasks, report via ccw issue done.`, + activeForm: `Implementing ${issueId}`, + owner: "implementer", + addBlockedBy: [marshalId] + }) +} +``` + +**Full Mode** (adds AUDIT between SOLVE and MARSHAL): +```javascript +for (const issueId of issueIds) { + const exploreId = TaskCreate({ + subject: `EXPLORE-001: Analyze context for ${issueId}`, + description: `Explore codebase context for issue ${issueId}.`, + activeForm: `Exploring ${issueId}`, + owner: "explorer" + }) + + const solveId = TaskCreate({ + subject: `SOLVE-001: Design solution for ${issueId}`, + description: `Design solution for issue ${issueId} using issue-plan-agent.`, + activeForm: `Planning ${issueId}`, + owner: "planner", + addBlockedBy: [exploreId] + }) + + const auditId = TaskCreate({ + subject: `AUDIT-001: Review solution for ${issueId}`, + description: `Review solution quality, technical feasibility, and risks for issue ${issueId}. Read solution from .workflow/issues/solutions/${issueId}.jsonl.`, + activeForm: `Reviewing ${issueId}`, + owner: "reviewer", + addBlockedBy: [solveId] + }) + + const marshalId = TaskCreate({ + subject: `MARSHAL-001: Form queue for ${issueId}`, + description: `Form execution queue after review approval.`, + activeForm: `Forming queue`, + owner: "integrator", + addBlockedBy: [auditId] + }) + + TaskCreate({ + subject: `BUILD-001: Implement solution for ${issueId}`, + description: `Implement approved solution for issue ${issueId}.`, + activeForm: `Implementing ${issueId}`, + owner: "implementer", + addBlockedBy: [marshalId] + }) +} +``` + +**Batch Mode** (parallel EXPLORE and SOLVE batches): +```javascript +// Group issues into batches +const exploreBatches = chunkArray(issueIds, 5) // max 5 parallel +const solveBatches = chunkArray(issueIds, 3) // max 3 parallel + +// Create EXPLORE tasks (parallel within batch) +const exploreTaskIds = [] +for (const [batchIdx, batch] of exploreBatches.entries()) { + for (const issueId of batch) { + const id = TaskCreate({ + subject: `EXPLORE-${String(exploreTaskIds.length + 1).padStart(3, '0')}: Context for ${issueId}`, + description: `Batch ${batchIdx + 1}: Explore codebase context for issue ${issueId}.`, + activeForm: `Exploring ${issueId}`, + owner: "explorer", + addBlockedBy: batchIdx > 0 ? [exploreTaskIds[exploreTaskIds.length - 1]] : [] + }) + exploreTaskIds.push(id) + } +} + +// Create SOLVE tasks (blocked by corresponding EXPLORE) +const solveTaskIds = [] +for (const [i, issueId] of issueIds.entries()) { + const id = TaskCreate({ + subject: `SOLVE-${String(i + 1).padStart(3, '0')}: Solution for ${issueId}`, + description: `Design solution for issue ${issueId}.`, + activeForm: `Planning ${issueId}`, + owner: "planner", + addBlockedBy: [exploreTaskIds[i]] + }) + solveTaskIds.push(id) +} + +// AUDIT as batch review (blocked by all SOLVE tasks) +const auditId = TaskCreate({ + subject: `AUDIT-001: Batch review all solutions`, + description: `Review all ${issueIds.length} solutions for quality and conflicts.`, + activeForm: `Batch reviewing`, + owner: "reviewer", + addBlockedBy: solveTaskIds +}) + +// MARSHAL (blocked by AUDIT) +const marshalId = TaskCreate({ + subject: `MARSHAL-001: Form execution queue`, + description: `Form DAG-based execution queue for all approved solutions.`, + activeForm: `Forming queue`, + owner: "integrator", + addBlockedBy: [auditId] +}) + +// BUILD tasks created dynamically after MARSHAL completes (based on DAG) +``` + +### Phase 4: Coordination Loop + +Receive teammate messages, dispatch based on type. + +| Received Message | Action | +|-----------------|--------| +| `context_ready` from explorer | Unblock SOLVE-* tasks for this issue | +| `solution_ready` from planner | Quick: create MARSHAL-*; Full: create AUDIT-* | +| `multi_solution` from planner | AskUserQuestion for solution selection, then ccw issue bind | +| `approved` from reviewer | Unblock MARSHAL-* task | +| `rejected` from reviewer | Create SOLVE-fix task with feedback (max 2 rounds) | +| `concerns` from reviewer | Log concerns, proceed to MARSHAL (non-blocking) | +| `queue_ready` from integrator | Create BUILD-* tasks based on DAG parallel batches | +| `conflict_found` from integrator | AskUserQuestion for conflict resolution | +| `impl_complete` from implementer | Refresh DAG, create next BUILD-* batch or complete | +| `impl_failed` from implementer | CP-5 escalation: retry / skip / abort | +| `error` from any worker | Assess severity → retry or escalate to user | + +**Review-Fix Cycle (CP-2)** — max 2 rounds: +```javascript +let auditRound = 0 +const MAX_AUDIT_ROUNDS = 2 + +// On rejected message: +if (msg.type === 'rejected' && auditRound < MAX_AUDIT_ROUNDS) { + auditRound++ + TaskCreate({ + subject: `SOLVE-fix-${auditRound}: Revise solution based on review`, + description: `Fix solution per reviewer feedback:\n${msg.data.findings}\n\nThis is revision round ${auditRound}/${MAX_AUDIT_ROUNDS}.`, + owner: "planner" + }) + // After SOLVE-fix completes → create AUDIT-{round+1} +} else if (auditRound >= MAX_AUDIT_ROUNDS) { + // Escalate to user: solution cannot pass review after 2 rounds + AskUserQuestion({ + questions: [{ + question: `Solution for ${issueId} rejected ${MAX_AUDIT_ROUNDS} times. How to proceed?`, + header: "Escalation", + options: [ + { label: "Force approve", description: "Skip review, proceed to execution" }, + { label: "Manual fix", description: "User will fix the solution" }, + { label: "Skip issue", description: "Skip this issue, continue with others" } + ] + }] + }) +} +``` + +### Phase 5: Report + Handoff + +```javascript +// Summarize results +const summary = { + mode, + issues_processed: issueIds.length, + solutions_approved: approvedCount, + builds_completed: completedBuilds, + builds_failed: failedBuilds +} + +// Report to user +mcp__ccw-tools__team_msg({ + operation: "log", team: "issue", from: "coordinator", + to: "user", type: "pipeline_update", + summary: `[coordinator] Pipeline complete: ${summary.issues_processed} issues processed` +}) + +// Ask for next action +AskUserQuestion({ + questions: [{ + question: "Issue 处理完成。下一步:", + header: "Next", + multiSelect: false, + options: [ + { label: "新一批 issue", description: "提交新的 issue ID 给当前团队处理" }, + { label: "查看结果", description: "查看实现结果和 git 变更" }, + { label: "关闭团队", description: "关闭所有 teammate 并清理" } + ] + }] +}) +// 新一批 → 回到 Phase 1 +// 关闭 → shutdown → TeamDelete() +``` + +## Error Handling + +| Scenario | Resolution | +|----------|------------| +| No issue IDs provided | AskUserQuestion for IDs | +| Issue not found | Skip with warning, continue others | +| Worker unresponsive | Send follow-up, 2x → respawn | +| Review rejected 2+ times | Escalate to user (CP-5 L3) | +| Build failed | Retry once, then escalate | +| All workers error | Shutdown team, report to user | diff --git a/.claude/skills/team-issue/roles/explorer.md b/.claude/skills/team-issue/roles/explorer.md new file mode 100644 index 00000000..c6025876 --- /dev/null +++ b/.claude/skills/team-issue/roles/explorer.md @@ -0,0 +1,234 @@ +# Role: explorer + +Issue 上下文分析、代码探索、依赖识别、影响面评估。为 planner 和 reviewer 提供共享的 context report。 + +## Role Identity + +- **Name**: `explorer` +- **Task Prefix**: `EXPLORE-*` +- **Responsibility**: Orchestration (context gathering) +- **Communication**: SendMessage to coordinator only +- **Output Tag**: `[explorer]` + +## Role Boundaries + +### MUST + +- 仅处理 `EXPLORE-*` 前缀的任务 +- 所有输出必须带 `[explorer]` 标识 +- 仅通过 SendMessage 与 coordinator 通信 +- 产出 context-report 供后续角色(planner, reviewer)使用 + +### MUST NOT + +- ❌ 设计解决方案(planner 职责) +- ❌ 审查方案质量(reviewer 职责) +- ❌ 修改任何源代码 +- ❌ 直接与其他 worker 通信 +- ❌ 为其他角色创建任务 + +## Message Types + +| Type | Direction | Trigger | Description | +|------|-----------|---------|-------------| +| `context_ready` | explorer → coordinator | Context analysis complete | 上下文报告就绪 | +| `impact_assessed` | explorer → coordinator | Impact scope determined | 影响面评估完成 | +| `error` | explorer → coordinator | Blocking error | 无法完成探索 | + +## Toolbox + +### Subagent Capabilities + +| Agent Type | Purpose | +|------------|---------| +| `cli-explore-agent` | Deep codebase exploration with module analysis | + +### CLI Capabilities + +| CLI Command | Purpose | +|-------------|---------| +| `ccw issue status --json` | Load full issue details | +| `ccw tool exec get_modules_by_depth '{}'` | Get project module structure | + +## Execution (5-Phase) + +### Phase 1: Task Discovery + +```javascript +const tasks = TaskList() +const myTasks = tasks.filter(t => + t.subject.startsWith('EXPLORE-') && + t.owner === 'explorer' && + t.status === 'pending' && + t.blockedBy.length === 0 +) + +if (myTasks.length === 0) return // idle + +const task = TaskGet({ taskId: myTasks[0].id }) +TaskUpdate({ taskId: task.id, status: 'in_progress' }) +``` + +### Phase 2: Issue Loading & Context Setup + +```javascript +// Extract issue ID from task description +const issueIdMatch = task.description.match(/(?:GH-\d+|ISS-\d{8}-\d{6})/) +const issueId = issueIdMatch ? issueIdMatch[0] : null + +if (!issueId) { + // Report error + mcp__ccw-tools__team_msg({ operation: "log", team: "issue", from: "explorer", to: "coordinator", type: "error", summary: "[explorer] No issue ID found in task" }) + SendMessage({ type: "message", recipient: "coordinator", content: "## [explorer] Error\nNo issue ID in task description", summary: "[explorer] error: no issue ID" }) + return +} + +// Load issue details +const issueJson = Bash(`ccw issue status ${issueId} --json`) +const issue = JSON.parse(issueJson) +``` + +### Phase 3: Codebase Exploration & Impact Analysis + +```javascript +// Complexity assessment determines exploration depth +function assessComplexity(issue) { + let score = 0 + if (/refactor|architect|restructure|module|system/i.test(issue.context)) score += 2 + if (/multiple|across|cross/i.test(issue.context)) score += 2 + if (/integrate|api|database/i.test(issue.context)) score += 1 + if (issue.priority >= 4) score += 1 + return score >= 4 ? 'High' : score >= 2 ? 'Medium' : 'Low' +} + +const complexity = assessComplexity(issue) + +if (complexity === 'Low') { + // Direct ACE search + const results = mcp__ace-tool__search_context({ + project_root_path: projectRoot, + query: `${issue.title}. ${issue.context}. Keywords: ${issue.labels?.join(', ') || ''}` + }) + // Build context from ACE results +} else { + // Deep exploration via cli-explore-agent + Task({ + subagent_type: "cli-explore-agent", + run_in_background: false, + description: `Explore context for ${issueId}`, + prompt: ` +## Issue Context +ID: ${issueId} +Title: ${issue.title} +Description: ${issue.context} +Priority: ${issue.priority} + +## MANDATORY FIRST STEPS +1. Run: ccw tool exec get_modules_by_depth '{}' +2. Execute ACE searches based on issue keywords +3. Read: .workflow/project-tech.json (if exists) + +## Exploration Focus +- Identify files directly related to this issue +- Map dependencies and integration points +- Assess impact scope (how many modules/files affected) +- Find existing patterns relevant to the fix +- Check for previous related changes (git log) + +## Output +Write findings to: .workflow/.team-plan/issue/context-${issueId}.json + +Schema: { + issue_id, relevant_files[], dependencies[], impact_scope, + existing_patterns[], related_changes[], key_findings[], + complexity_assessment, _metadata +} +` + }) +} +``` + +### Phase 4: Context Report Generation + +```javascript +// Read exploration results +const contextPath = `.workflow/.team-plan/issue/context-${issueId}.json` +let contextReport +try { + contextReport = JSON.parse(Read(contextPath)) +} catch { + // Build minimal report from ACE results + contextReport = { + issue_id: issueId, + relevant_files: [], + key_findings: [], + complexity_assessment: complexity + } +} + +// Enrich with issue metadata +contextReport.issue = { + id: issue.id, + title: issue.title, + priority: issue.priority, + status: issue.status, + labels: issue.labels, + feedback: issue.feedback // Previous failure history +} +``` + +### Phase 5: Report to Coordinator + +```javascript +mcp__ccw-tools__team_msg({ + operation: "log", + team: "issue", + from: "explorer", + to: "coordinator", + type: "context_ready", + summary: `[explorer] Context ready for ${issueId}: ${contextReport.relevant_files?.length || 0} files, complexity=${complexity}`, + ref: contextPath +}) + +SendMessage({ + type: "message", + recipient: "coordinator", + content: `## [explorer] Context Analysis Results + +**Issue**: ${issueId} - ${issue.title} +**Complexity**: ${complexity} +**Files Identified**: ${contextReport.relevant_files?.length || 0} +**Impact Scope**: ${contextReport.impact_scope || 'unknown'} + +### Key Findings +${(contextReport.key_findings || []).map(f => `- ${f}`).join('\n')} + +### Context Report +Saved to: ${contextPath}`, + summary: `[explorer] EXPLORE complete: ${issueId}` +}) + +TaskUpdate({ taskId: task.id, status: 'completed' }) + +// Check for next task +const nextTasks = TaskList().filter(t => + t.subject.startsWith('EXPLORE-') && + t.owner === 'explorer' && + t.status === 'pending' && + t.blockedBy.length === 0 +) + +if (nextTasks.length > 0) { + // Continue with next task → back to Phase 1 +} +``` + +## Error Handling + +| Scenario | Resolution | +|----------|------------| +| No EXPLORE-* tasks available | Idle, wait for coordinator assignment | +| Issue ID not found in ccw | Notify coordinator with error | +| ACE search returns no results | Fallback to Glob/Grep, report limited context | +| cli-explore-agent failure | Retry once with simplified prompt, then report partial results | +| Context file write failure | Report via SendMessage with inline context | diff --git a/.claude/skills/team-issue/roles/implementer.md b/.claude/skills/team-issue/roles/implementer.md new file mode 100644 index 00000000..b6cd2469 --- /dev/null +++ b/.claude/skills/team-issue/roles/implementer.md @@ -0,0 +1,272 @@ +# Role: implementer + +代码实现、测试验证、结果提交。内部调用 code-developer agent 进行实际代码编写。 + +## Role Identity + +- **Name**: `implementer` +- **Task Prefix**: `BUILD-*` +- **Responsibility**: Code generation (implementation) +- **Communication**: SendMessage to coordinator only +- **Output Tag**: `[implementer]` + +## Role Boundaries + +### MUST + +- 仅处理 `BUILD-*` 前缀的任务 +- 所有输出必须带 `[implementer]` 标识 +- 按照队列中的 solution plan 执行实现 +- 每个 solution 完成后通知 coordinator + +### MUST NOT + +- ❌ 修改解决方案(planner 职责) +- ❌ 审查其他实现结果(reviewer 职责) +- ❌ 修改执行队列(integrator 职责) +- ❌ 直接与其他 worker 通信 +- ❌ 为其他角色创建任务 + +## Message Types + +| Type | Direction | Trigger | Description | +|------|-----------|---------|-------------| +| `impl_complete` | implementer → coordinator | Implementation and tests pass | 实现完成 | +| `impl_failed` | implementer → coordinator | Implementation failed after retries | 实现失败 | +| `error` | implementer → coordinator | Blocking error | 执行错误 | + +## Toolbox + +### Subagent Capabilities + +| Agent Type | Purpose | +|------------|---------| +| `code-developer` | Pure code execution with test-driven development | + +### Direct Capabilities + +| Tool | Purpose | +|------|---------| +| `Read` | 读取 solution plan 和队列文件 | +| `Write` | 写入实现产物 | +| `Edit` | 编辑源代码 | +| `Bash` | 运行测试、git 操作 | + +### CLI Capabilities + +| CLI Command | Purpose | +|-------------|---------| +| `ccw issue status --json` | 查看 issue 状态 | +| `ccw issue solutions --json` | 加载 bound solution | +| `ccw issue update --status in-progress` | 更新 issue 状态 | +| `ccw issue update --status resolved` | 标记 issue 已解决 | + +## Execution (5-Phase) + +### Phase 1: Task Discovery + +```javascript +const tasks = TaskList() +const myTasks = tasks.filter(t => + t.subject.startsWith('BUILD-') && + t.owner === 'implementer' && + t.status === 'pending' && + t.blockedBy.length === 0 +) + +if (myTasks.length === 0) return // idle + +const task = TaskGet({ taskId: myTasks[0].id }) +TaskUpdate({ taskId: task.id, status: 'in_progress' }) +``` + +### Phase 2: Load Solution Plan + +```javascript +// Extract issue ID from task description +const issueIdMatch = task.description.match(/(?:GH-\d+|ISS-\d{8}-\d{6})/) +const issueId = issueIdMatch ? issueIdMatch[0] : null + +if (!issueId) { + mcp__ccw-tools__team_msg({ + operation: "log", team: "issue", from: "implementer", to: "coordinator", + type: "error", + summary: "[implementer] No issue ID found in task" + }) + SendMessage({ + type: "message", recipient: "coordinator", + content: "## [implementer] Error\nNo issue ID in task description", + summary: "[implementer] error: no issue ID" + }) + return +} + +// Load solution plan +const solJson = Bash(`ccw issue solutions ${issueId} --json`) +const solution = JSON.parse(solJson) + +if (!solution.bound) { + mcp__ccw-tools__team_msg({ + operation: "log", team: "issue", from: "implementer", to: "coordinator", + type: "error", + summary: `[implementer] No bound solution for ${issueId}` + }) + return +} + +// Load queue info for dependency checking +let queueInfo = null +try { + const queueJson = Read(`.workflow/issues/queue/execution-queue.json`) + const queue = JSON.parse(queueJson) + queueInfo = queue.queue?.find(q => q.issue_id === issueId) +} catch { + // Queue info not available, proceed without +} + +// Update issue status +Bash(`ccw issue update ${issueId} --status in-progress`) +``` + +### Phase 3: Implementation via code-developer + +```javascript +// Determine complexity for agent prompt +const taskCount = solution.bound.task_count || solution.bound.tasks?.length || 0 +const isComplex = taskCount > 3 + +// Load explorer context for implementation guidance +let explorerContext = null +try { + const contextPath = `.workflow/.team-plan/issue/context-${issueId}.json` + explorerContext = JSON.parse(Read(contextPath)) +} catch { + // No explorer context +} + +// Invoke code-developer agent +const implResult = Task({ + subagent_type: "code-developer", + run_in_background: false, + description: `Implement solution for ${issueId}`, + prompt: ` +## Issue +ID: ${issueId} +Title: ${solution.bound.title || 'N/A'} + +## Solution Plan +${JSON.stringify(solution.bound, null, 2)} + +${explorerContext ? ` +## Codebase Context (from explorer) +Relevant files: ${explorerContext.relevant_files?.map(f => f.path || f).slice(0, 10).join(', ')} +Existing patterns: ${explorerContext.existing_patterns?.join('; ') || 'N/A'} +Dependencies: ${explorerContext.dependencies?.join(', ') || 'N/A'} +` : ''} + +## Implementation Requirements + +1. Follow the solution plan tasks in order +2. Write clean, minimal code following existing patterns +3. Run tests after each significant change +4. Ensure all existing tests still pass +5. Do NOT over-engineer — implement exactly what the solution specifies + +## Quality Checklist +- [ ] All solution tasks implemented +- [ ] No TypeScript/linting errors +- [ ] Existing tests pass +- [ ] New tests added where appropriate +- [ ] No security vulnerabilities introduced +` +}) +``` + +### Phase 4: Verify & Commit + +```javascript +// Verify implementation +const testResult = Bash(`npm test 2>&1 || echo "TEST_FAILED"`) +const testPassed = !testResult.includes('TEST_FAILED') && !testResult.includes('FAIL') + +if (!testPassed) { + // Implementation failed — report to coordinator + mcp__ccw-tools__team_msg({ + operation: "log", team: "issue", from: "implementer", to: "coordinator", + type: "impl_failed", + summary: `[implementer] Tests failing for ${issueId} after implementation` + }) + + SendMessage({ + type: "message", recipient: "coordinator", + content: `## [implementer] Implementation Failed + +**Issue**: ${issueId} +**Status**: Tests failing after implementation +**Test Output**: (truncated) +${testResult.slice(0, 500)} + +**Action**: May need manual intervention or solution revision.`, + summary: `[implementer] impl_failed: ${issueId}` + }) + + TaskUpdate({ taskId: task.id, status: 'completed' }) + return +} + +// Update issue status to resolved +Bash(`ccw issue update ${issueId} --status resolved`) +``` + +### Phase 5: Report to Coordinator + +```javascript +mcp__ccw-tools__team_msg({ + operation: "log", + team: "issue", + from: "implementer", + to: "coordinator", + type: "impl_complete", + summary: `[implementer] Implementation complete for ${issueId}, tests passing` +}) + +SendMessage({ + type: "message", + recipient: "coordinator", + content: `## [implementer] Implementation Complete + +**Issue**: ${issueId} +**Solution**: ${solution.bound.id} +**Status**: All tests passing +**Issue Status**: Updated to resolved + +### Summary +Implementation completed following the solution plan. All existing tests pass and issue has been marked as resolved.`, + summary: `[implementer] BUILD complete: ${issueId}` +}) + +TaskUpdate({ taskId: task.id, status: 'completed' }) + +// Check for next task (parallel BUILD tasks) +const nextTasks = TaskList().filter(t => + t.subject.startsWith('BUILD-') && + t.owner === 'implementer' && + t.status === 'pending' && + t.blockedBy.length === 0 +) + +if (nextTasks.length > 0) { + // Continue with next task → back to Phase 1 +} +``` + +## Error Handling + +| Scenario | Resolution | +|----------|------------| +| No BUILD-* tasks available | Idle, wait for coordinator | +| Solution plan not found | Report to coordinator with error | +| code-developer agent failure | Retry once, then report impl_failed | +| Tests failing after implementation | Report impl_failed with test output | +| Issue status update failure | Log warning, continue with report | +| Dependency not yet complete | Wait — task is blocked by blockedBy | diff --git a/.claude/skills/team-issue/roles/integrator.md b/.claude/skills/team-issue/roles/integrator.md new file mode 100644 index 00000000..d22c4332 --- /dev/null +++ b/.claude/skills/team-issue/roles/integrator.md @@ -0,0 +1,260 @@ +# Role: integrator + +队列编排、冲突检测、执行顺序优化。内部调用 issue-queue-agent 进行智能队列形成。 + +## Role Identity + +- **Name**: `integrator` +- **Task Prefix**: `MARSHAL-*` +- **Responsibility**: Orchestration (queue formation) +- **Communication**: SendMessage to coordinator only +- **Output Tag**: `[integrator]` + +## Role Boundaries + +### MUST + +- 仅处理 `MARSHAL-*` 前缀的任务 +- 所有输出必须带 `[integrator]` 标识 +- 使用 issue-queue-agent 进行队列编排 +- 确保所有 issue 都有 bound solution 才能编排 + +### MUST NOT + +- ❌ 修改解决方案(planner 职责) +- ❌ 审查方案质量(reviewer 职责) +- ❌ 实现代码(implementer 职责) +- ❌ 直接与其他 worker 通信 +- ❌ 为其他角色创建任务 + +## Message Types + +| Type | Direction | Trigger | Description | +|------|-----------|---------|-------------| +| `queue_ready` | integrator → coordinator | Queue formed successfully | 队列就绪,可执行 | +| `conflict_found` | integrator → coordinator | File conflicts detected, user input needed | 发现冲突需要人工决策 | +| `error` | integrator → coordinator | Blocking error | 队列编排失败 | + +## Toolbox + +### Subagent Capabilities + +| Agent Type | Purpose | +|------------|---------| +| `issue-queue-agent` | Receives solutions from bound issues, uses Gemini for conflict detection, produces ordered execution queue | + +### CLI Capabilities + +| CLI Command | Purpose | +|-------------|---------| +| `ccw issue status --json` | Load issue details | +| `ccw issue solutions --json` | Verify bound solution | +| `ccw issue list --status planned --json` | List planned issues | + +## Execution (5-Phase) + +### Phase 1: Task Discovery + +```javascript +const tasks = TaskList() +const myTasks = tasks.filter(t => + t.subject.startsWith('MARSHAL-') && + t.owner === 'integrator' && + t.status === 'pending' && + t.blockedBy.length === 0 +) + +if (myTasks.length === 0) return // idle + +const task = TaskGet({ taskId: myTasks[0].id }) +TaskUpdate({ taskId: task.id, status: 'in_progress' }) +``` + +### Phase 2: Collect Bound Solutions + +```javascript +// Extract issue IDs from task description +const issueIds = task.description.match(/(?:GH-\d+|ISS-\d{8}-\d{6})/g) || [] + +// Verify all issues have bound solutions +const unbound = [] +const boundIssues = [] + +for (const issueId of issueIds) { + const solJson = Bash(`ccw issue solutions ${issueId} --json`) + const sol = JSON.parse(solJson) + + if (sol.bound) { + boundIssues.push({ id: issueId, solution: sol.bound }) + } else { + unbound.push(issueId) + } +} + +if (unbound.length > 0) { + mcp__ccw-tools__team_msg({ + operation: "log", team: "issue", from: "integrator", to: "coordinator", + type: "error", + summary: `[integrator] Unbound issues: ${unbound.join(', ')} — cannot form queue` + }) + SendMessage({ + type: "message", recipient: "coordinator", + content: `## [integrator] Error: Unbound Issues\n\nThe following issues have no bound solution:\n${unbound.map(id => `- ${id}`).join('\n')}\n\nPlanner must create solutions before queue formation.`, + summary: `[integrator] error: ${unbound.length} unbound issues` + }) + return +} +``` + +### Phase 3: Queue Formation via issue-queue-agent + +```javascript +// Invoke issue-queue-agent for intelligent queue formation +const agentResult = Task({ + subagent_type: "issue-queue-agent", + run_in_background: false, + description: `Form queue for ${issueIds.length} issues`, + prompt: ` +## Issues to Queue + +Issue IDs: ${issueIds.join(', ')} + +## Bound Solutions + +${boundIssues.map(bi => `- ${bi.id}: Solution ${bi.solution.id} (${bi.solution.task_count} tasks)`).join('\n')} + +## Instructions + +1. Load all bound solutions from .workflow/issues/solutions/ +2. Analyze file conflicts between solutions using Gemini CLI +3. Determine optimal execution order (DAG-based) +4. Produce ordered execution queue + +## Expected Output + +Write queue to: .workflow/issues/queue/execution-queue.json + +Schema: { + queue: [{ issue_id, solution_id, order, depends_on[], estimated_files[] }], + conflicts: [{ issues: [id1, id2], files: [...], resolution }], + parallel_groups: [{ group: N, issues: [...] }] +} +` +}) + +// Parse queue result +const queuePath = `.workflow/issues/queue/execution-queue.json` +let queueResult +try { + queueResult = JSON.parse(Read(queuePath)) +} catch { + queueResult = null +} +``` + +### Phase 4: Conflict Resolution + +```javascript +if (!queueResult) { + // Queue formation failed + mcp__ccw-tools__team_msg({ + operation: "log", team: "issue", from: "integrator", to: "coordinator", + type: "error", + summary: `[integrator] Queue formation failed — no output from issue-queue-agent` + }) + SendMessage({ + type: "message", recipient: "coordinator", + content: `## [integrator] Error\n\nQueue formation failed. issue-queue-agent produced no output.`, + summary: `[integrator] error: queue formation failed` + }) + return +} + +// Check for unresolved conflicts +const unresolvedConflicts = (queueResult.conflicts || []).filter(c => c.resolution === 'unresolved') + +if (unresolvedConflicts.length > 0) { + mcp__ccw-tools__team_msg({ + operation: "log", team: "issue", from: "integrator", to: "coordinator", + type: "conflict_found", + summary: `[integrator] ${unresolvedConflicts.length} unresolved conflicts in queue` + }) + + SendMessage({ + type: "message", recipient: "coordinator", + content: `## [integrator] Conflicts Found + +**Unresolved Conflicts**: ${unresolvedConflicts.length} + +${unresolvedConflicts.map((c, i) => `### Conflict ${i + 1} +- **Issues**: ${c.issues.join(' vs ')} +- **Files**: ${c.files.join(', ')} +- **Recommendation**: User decision needed — which issue takes priority`).join('\n\n')} + +**Action Required**: Coordinator should present conflicts to user for resolution, then re-trigger MARSHAL.`, + summary: `[integrator] conflict_found: ${unresolvedConflicts.length} conflicts` + }) + return +} +``` + +### Phase 5: Report to Coordinator + +```javascript +const queueSize = queueResult.queue?.length || 0 +const parallelGroups = queueResult.parallel_groups?.length || 1 + +mcp__ccw-tools__team_msg({ + operation: "log", + team: "issue", + from: "integrator", + to: "coordinator", + type: "queue_ready", + summary: `[integrator] Queue ready: ${queueSize} items in ${parallelGroups} parallel groups`, + ref: queuePath +}) + +SendMessage({ + type: "message", + recipient: "coordinator", + content: `## [integrator] Queue Ready + +**Queue Size**: ${queueSize} items +**Parallel Groups**: ${parallelGroups} +**Resolved Conflicts**: ${(queueResult.conflicts || []).filter(c => c.resolution !== 'unresolved').length} + +### Execution Order +${(queueResult.queue || []).map((q, i) => `${i + 1}. ${q.issue_id} (Solution: ${q.solution_id})${q.depends_on?.length ? ` — depends on: ${q.depends_on.join(', ')}` : ''}`).join('\n')} + +### Parallel Groups +${(queueResult.parallel_groups || []).map(g => `- Group ${g.group}: ${g.issues.join(', ')}`).join('\n')} + +**Queue File**: ${queuePath} +**Status**: Ready for BUILD phase`, + summary: `[integrator] MARSHAL complete: ${queueSize} items queued` +}) + +TaskUpdate({ taskId: task.id, status: 'completed' }) + +// Check for next task +const nextTasks = TaskList().filter(t => + t.subject.startsWith('MARSHAL-') && + t.owner === 'integrator' && + t.status === 'pending' && + t.blockedBy.length === 0 +) + +if (nextTasks.length > 0) { + // Continue with next task → back to Phase 1 +} +``` + +## Error Handling + +| Scenario | Resolution | +|----------|------------| +| No MARSHAL-* tasks available | Idle, wait for coordinator | +| Issues without bound solutions | Report to coordinator, block queue formation | +| issue-queue-agent failure | Retry once, then report error | +| Unresolved file conflicts | Escalate to coordinator for user decision (CP-5) | +| Single issue (no conflict possible) | Create trivial queue with one entry | diff --git a/.claude/skills/team-issue/roles/planner.md b/.claude/skills/team-issue/roles/planner.md new file mode 100644 index 00000000..53b7d3eb --- /dev/null +++ b/.claude/skills/team-issue/roles/planner.md @@ -0,0 +1,209 @@ +# Role: planner + +解决方案设计、任务分解。内部调用 issue-plan-agent 进行 ACE 探索和方案生成。 + +## Role Identity + +- **Name**: `planner` +- **Task Prefix**: `SOLVE-*` +- **Responsibility**: Orchestration (solution design) +- **Communication**: SendMessage to coordinator only +- **Output Tag**: `[planner]` + +## Role Boundaries + +### MUST + +- 仅处理 `SOLVE-*` 前缀的任务 +- 所有输出必须带 `[planner]` 标识 +- 使用 issue-plan-agent 进行方案设计 +- 参考 explorer 的 context-report 丰富方案上下文 + +### MUST NOT + +- ❌ 执行代码实现(implementer 职责) +- ❌ 审查方案质量(reviewer 职责) +- ❌ 编排执行队列(integrator 职责) +- ❌ 直接与其他 worker 通信 + +## Message Types + +| Type | Direction | Trigger | Description | +|------|-----------|---------|-------------| +| `solution_ready` | planner → coordinator | Solution designed and bound | 单方案就绪 | +| `multi_solution` | planner → coordinator | Multiple solutions, needs selection | 多方案待选 | +| `error` | planner → coordinator | Blocking error | 方案设计失败 | + +## Toolbox + +### Subagent Capabilities + +| Agent Type | Purpose | +|------------|---------| +| `issue-plan-agent` | Closed-loop planning: ACE exploration + solution generation + binding | + +### CLI Capabilities + +| CLI Command | Purpose | +|-------------|---------| +| `ccw issue status --json` | Load issue details | +| `ccw issue bind ` | Bind solution to issue | + +## Execution (5-Phase) + +### Phase 1: Task Discovery + +```javascript +const tasks = TaskList() +const myTasks = tasks.filter(t => + t.subject.startsWith('SOLVE-') && + t.owner === 'planner' && + t.status === 'pending' && + t.blockedBy.length === 0 +) + +if (myTasks.length === 0) return // idle + +const task = TaskGet({ taskId: myTasks[0].id }) +TaskUpdate({ taskId: task.id, status: 'in_progress' }) +``` + +### Phase 2: Context Loading + +```javascript +// Extract issue ID +const issueIdMatch = task.description.match(/(?:GH-\d+|ISS-\d{8}-\d{6})/) +const issueId = issueIdMatch ? issueIdMatch[0] : null + +// Load explorer's context report (if available) +const contextPath = `.workflow/.team-plan/issue/context-${issueId}.json` +let explorerContext = null +try { + explorerContext = JSON.parse(Read(contextPath)) +} catch { + // Explorer context not available, issue-plan-agent will do its own exploration +} + +// Check if this is a revision task (SOLVE-fix-N) +const isRevision = task.subject.includes('SOLVE-fix') +let reviewFeedback = null +if (isRevision) { + // Extract reviewer feedback from task description + reviewFeedback = task.description +} +``` + +### Phase 3: Solution Generation via issue-plan-agent + +```javascript +// Invoke issue-plan-agent +const agentResult = Task({ + subagent_type: "issue-plan-agent", + run_in_background: false, + description: `Plan solution for ${issueId}`, + prompt: ` +issue_ids: ["${issueId}"] +project_root: "${projectRoot}" + +${explorerContext ? ` +## Explorer Context (pre-gathered) +Relevant files: ${explorerContext.relevant_files?.map(f => f.path || f).join(', ')} +Key findings: ${explorerContext.key_findings?.join('; ')} +Complexity: ${explorerContext.complexity_assessment} +` : ''} + +${reviewFeedback ? ` +## Revision Required +Previous solution was rejected by reviewer. Feedback: +${reviewFeedback} + +Design an ALTERNATIVE approach that addresses the reviewer's concerns. +` : ''} +` +}) + +// Parse agent result +// Expected: { bound: [{issue_id, solution_id, task_count}], pending_selection: [{issue_id, solutions: [...]}] } +``` + +### Phase 4: Solution Selection & Binding + +```javascript +const result = agentResult // from Phase 3 + +if (result.bound && result.bound.length > 0) { + // Single solution auto-bound + const bound = result.bound[0] + + mcp__ccw-tools__team_msg({ + operation: "log", team: "issue", from: "planner", to: "coordinator", + type: "solution_ready", + summary: `[planner] Solution ${bound.solution_id} bound to ${bound.issue_id} (${bound.task_count} tasks)` + }) + + SendMessage({ + type: "message", recipient: "coordinator", + content: `## [planner] Solution Ready + +**Issue**: ${bound.issue_id} +**Solution**: ${bound.solution_id} +**Tasks**: ${bound.task_count} +**Status**: Auto-bound (single solution) + +Solution written to: .workflow/issues/solutions/${bound.issue_id}.jsonl`, + summary: `[planner] SOLVE complete: ${bound.issue_id}` + }) +} else if (result.pending_selection && result.pending_selection.length > 0) { + // Multiple solutions need user selection + const pending = result.pending_selection[0] + + mcp__ccw-tools__team_msg({ + operation: "log", team: "issue", from: "planner", to: "coordinator", + type: "multi_solution", + summary: `[planner] ${pending.solutions.length} solutions for ${pending.issue_id}, user selection needed` + }) + + SendMessage({ + type: "message", recipient: "coordinator", + content: `## [planner] Multiple Solutions + +**Issue**: ${pending.issue_id} +**Solutions**: ${pending.solutions.length} options + +${pending.solutions.map((s, i) => `### Option ${i + 1}: ${s.id} +${s.description} +Tasks: ${s.task_count}`).join('\n\n')} + +**Action Required**: Coordinator should present options to user for selection.`, + summary: `[planner] multi_solution: ${pending.issue_id}` + }) +} +``` + +### Phase 5: Report to Coordinator + +```javascript +TaskUpdate({ taskId: task.id, status: 'completed' }) + +// Check for next task +const nextTasks = TaskList().filter(t => + t.subject.startsWith('SOLVE-') && + t.owner === 'planner' && + t.status === 'pending' && + t.blockedBy.length === 0 +) + +if (nextTasks.length > 0) { + // Continue with next task → back to Phase 1 +} +``` + +## Error Handling + +| Scenario | Resolution | +|----------|------------| +| No SOLVE-* tasks available | Idle, wait for coordinator | +| Issue not found | Notify coordinator with error | +| issue-plan-agent failure | Retry once, then report error | +| Explorer context missing | Proceed without — agent does its own exploration | +| Solution binding failure | Report to coordinator for manual binding | diff --git a/.claude/skills/team-issue/roles/reviewer.md b/.claude/skills/team-issue/roles/reviewer.md new file mode 100644 index 00000000..94800d74 --- /dev/null +++ b/.claude/skills/team-issue/roles/reviewer.md @@ -0,0 +1,305 @@ +# Role: reviewer + +方案审查、技术可行性验证、风险评估。**新增质量门控角色**,填补当前 plan → execute 直接执行无审查的缺口。 + +## Role Identity + +- **Name**: `reviewer` +- **Task Prefix**: `AUDIT-*` +- **Responsibility**: Read-only analysis (solution review) +- **Communication**: SendMessage to coordinator only +- **Output Tag**: `[reviewer]` + +## Role Boundaries + +### MUST + +- 仅处理 `AUDIT-*` 前缀的任务 +- 所有输出必须带 `[reviewer]` 标识 +- 仅通过 SendMessage 与 coordinator 通信 +- 参考 explorer 的 context-report 验证方案覆盖度 +- 对每个方案给出明确的 approved / rejected / concerns 结论 + +### MUST NOT + +- ❌ 修改解决方案(planner 职责) +- ❌ 修改任何源代码 +- ❌ 编排执行队列(integrator 职责) +- ❌ 直接与其他 worker 通信 +- ❌ 为其他角色创建任务 + +## Message Types + +| Type | Direction | Trigger | Description | +|------|-----------|---------|-------------| +| `approved` | reviewer → coordinator | Solution passes all checks | 方案审批通过 | +| `rejected` | reviewer → coordinator | Critical issues found | 方案被拒,需修订 | +| `concerns` | reviewer → coordinator | Minor issues noted | 有顾虑但不阻塞 | +| `error` | reviewer → coordinator | Blocking error | 审查失败 | + +## Toolbox + +### Direct Capabilities + +| Tool | Purpose | +|------|---------| +| `Read` | 读取方案文件和上下文报告 | +| `Bash` | 执行 ccw issue 命令查看 issue/solution 详情 | +| `Glob` | 查找相关文件 | +| `Grep` | 搜索代码模式 | +| `mcp__ace-tool__search_context` | 语义搜索验证方案引用的代码 | + +### CLI Capabilities + +| CLI Command | Purpose | +|-------------|---------| +| `ccw issue status --json` | 加载 issue 详情 | +| `ccw issue solutions --json` | 查看已绑定的方案 | + +## Review Criteria + +### Technical Feasibility (权重 40%) + +| Criterion | Check | +|-----------|-------| +| File Coverage | 方案是否涵盖所有受影响的文件 | +| Dependency Awareness | 是否考虑到依赖变更的级联影响 | +| API Compatibility | 是否保持向后兼容 | +| Pattern Conformance | 是否遵循现有代码模式 | + +### Risk Assessment (权重 30%) + +| Criterion | Check | +|-----------|-------| +| Scope Creep | 方案是否超出 issue 的边界 | +| Breaking Changes | 是否引入破坏性变更 | +| Side Effects | 是否有未预见的副作用 | +| Rollback Path | 出问题时能否回退 | + +### Completeness (权重 30%) + +| Criterion | Check | +|-----------|-------| +| All Tasks Defined | 任务分解是否完整 | +| Test Coverage | 是否包含测试计划 | +| Edge Cases | 是否考虑边界情况 | +| Documentation | 关键变更是否有说明 | + +### Verdict Rules + +| Score | Verdict | Action | +|-------|---------|--------| +| ≥ 80% | `approved` | 可直接进入 MARSHAL 阶段 | +| 60-79% | `concerns` | 附带建议,不阻塞流程 | +| < 60% | `rejected` | 需要 planner 修订方案 | + +## Execution (5-Phase) + +### Phase 1: Task Discovery + +```javascript +const tasks = TaskList() +const myTasks = tasks.filter(t => + t.subject.startsWith('AUDIT-') && + t.owner === 'reviewer' && + t.status === 'pending' && + t.blockedBy.length === 0 +) + +if (myTasks.length === 0) return // idle + +const task = TaskGet({ taskId: myTasks[0].id }) +TaskUpdate({ taskId: task.id, status: 'in_progress' }) +``` + +### Phase 2: Context & Solution Loading + +```javascript +// Extract issue IDs from task description +const issueIds = task.description.match(/(?:GH-\d+|ISS-\d{8}-\d{6})/g) || [] + +// Load explorer context reports +const contexts = {} +for (const issueId of issueIds) { + const contextPath = `.workflow/.team-plan/issue/context-${issueId}.json` + try { + contexts[issueId] = JSON.parse(Read(contextPath)) + } catch { + contexts[issueId] = null // No explorer context + } +} + +// Load solution plans +const solutions = {} +for (const issueId of issueIds) { + const solJson = Bash(`ccw issue solutions ${issueId} --json`) + solutions[issueId] = JSON.parse(solJson) +} +``` + +### Phase 3: Multi-Dimensional Review + +```javascript +const reviewResults = [] + +for (const issueId of issueIds) { + const context = contexts[issueId] + const solution = solutions[issueId] + + if (!solution || !solution.bound) { + reviewResults.push({ + issueId, + verdict: 'error', + reason: 'No bound solution found' + }) + continue + } + + const review = { + issueId, + solutionId: solution.bound.id, + technical_feasibility: { score: 0, findings: [] }, + risk_assessment: { score: 0, findings: [] }, + completeness: { score: 0, findings: [] } + } + + // 1. Technical Feasibility — verify solution references real files + if (context && context.relevant_files) { + const solutionFiles = solution.bound.tasks?.flatMap(t => t.files || []) || [] + const contextFiles = context.relevant_files.map(f => f.path || f) + const uncovered = contextFiles.filter(f => !solutionFiles.some(sf => sf.includes(f))) + + if (uncovered.length === 0) { + review.technical_feasibility.score = 100 + } else { + review.technical_feasibility.score = Math.max(40, 100 - uncovered.length * 15) + review.technical_feasibility.findings.push( + `Uncovered files: ${uncovered.join(', ')}` + ) + } + } else { + review.technical_feasibility.score = 70 // No context to validate against + review.technical_feasibility.findings.push('Explorer context not available for cross-validation') + } + + // 2. Risk Assessment — check for breaking changes, scope + const taskCount = solution.bound.task_count || solution.bound.tasks?.length || 0 + if (taskCount > 10) { + review.risk_assessment.score = 50 + review.risk_assessment.findings.push(`High task count (${taskCount}) indicates possible scope creep`) + } else { + review.risk_assessment.score = 90 + } + + // 3. Completeness — check task definitions + if (taskCount > 0) { + review.completeness.score = 85 + } else { + review.completeness.score = 30 + review.completeness.findings.push('No tasks defined in solution') + } + + // Calculate weighted score + const totalScore = Math.round( + review.technical_feasibility.score * 0.4 + + review.risk_assessment.score * 0.3 + + review.completeness.score * 0.3 + ) + + // Determine verdict + let verdict + if (totalScore >= 80) verdict = 'approved' + else if (totalScore >= 60) verdict = 'concerns' + else verdict = 'rejected' + + review.total_score = totalScore + review.verdict = verdict + reviewResults.push(review) +} +``` + +### Phase 4: Compile Review Report + +```javascript +// Determine overall verdict +const hasRejected = reviewResults.some(r => r.verdict === 'rejected') +const hasConcerns = reviewResults.some(r => r.verdict === 'concerns') +const overallVerdict = hasRejected ? 'rejected' : hasConcerns ? 'concerns' : 'approved' + +// Build feedback for rejected solutions +const rejectedFeedback = reviewResults + .filter(r => r.verdict === 'rejected') + .map(r => `### ${r.issueId} (Score: ${r.total_score}%) +${r.technical_feasibility.findings.map(f => `- [Technical] ${f}`).join('\n')} +${r.risk_assessment.findings.map(f => `- [Risk] ${f}`).join('\n')} +${r.completeness.findings.map(f => `- [Completeness] ${f}`).join('\n')}`) + .join('\n\n') + +// Write review report +const reportPath = `.workflow/.team-plan/issue/audit-report.json` +Write(reportPath, JSON.stringify({ + timestamp: new Date().toISOString(), + overall_verdict: overallVerdict, + reviews: reviewResults +}, null, 2)) +``` + +### Phase 5: Report to Coordinator + +```javascript +// Choose message type based on verdict +const msgType = overallVerdict // 'approved' | 'rejected' | 'concerns' + +mcp__ccw-tools__team_msg({ + operation: "log", + team: "issue", + from: "reviewer", + to: "coordinator", + type: msgType, + summary: `[reviewer] ${overallVerdict.toUpperCase()}: ${reviewResults.length} solutions reviewed, score avg=${Math.round(reviewResults.reduce((a,r) => a + (r.total_score || 0), 0) / reviewResults.length)}%`, + ref: reportPath +}) + +SendMessage({ + type: "message", + recipient: "coordinator", + content: `## [reviewer] Audit Results — ${overallVerdict.toUpperCase()} + +**Overall**: ${overallVerdict} +**Solutions Reviewed**: ${reviewResults.length} + +${reviewResults.map(r => `### ${r.issueId} — ${r.verdict} (${r.total_score}%) +- Technical: ${r.technical_feasibility.score}% +- Risk: ${r.risk_assessment.score}% +- Completeness: ${r.completeness.score}% +${r.verdict === 'rejected' ? `\n**Rejection Reasons**:\n${[...r.technical_feasibility.findings, ...r.risk_assessment.findings, ...r.completeness.findings].map(f => '- ' + f).join('\n')}` : ''}`).join('\n\n')} + +${overallVerdict === 'rejected' ? `\n**Action Required**: Coordinator should create SOLVE-fix task for planner to revise rejected solutions.` : ''} +**Report**: ${reportPath}`, + summary: `[reviewer] AUDIT ${overallVerdict}: ${reviewResults.length} solutions` +}) + +TaskUpdate({ taskId: task.id, status: 'completed' }) + +// Check for next task +const nextTasks = TaskList().filter(t => + t.subject.startsWith('AUDIT-') && + t.owner === 'reviewer' && + t.status === 'pending' && + t.blockedBy.length === 0 +) + +if (nextTasks.length > 0) { + // Continue with next task → back to Phase 1 +} +``` + +## Error Handling + +| Scenario | Resolution | +|----------|------------| +| No AUDIT-* tasks available | Idle, wait for coordinator | +| Solution file not found | Check ccw issue solutions, report error if missing | +| Explorer context missing | Proceed with limited review (lower technical score) | +| All solutions rejected | Report to coordinator for CP-2 review-fix cycle | +| Review timeout | Report partial results with available data | diff --git a/.claude/skills/team-issue/specs/team-config.json b/.claude/skills/team-issue/specs/team-config.json new file mode 100644 index 00000000..02820175 --- /dev/null +++ b/.claude/skills/team-issue/specs/team-config.json @@ -0,0 +1,70 @@ +{ + "team_name": "issue", + "team_display_name": "Issue Resolution", + "description": "Unified team skill for issue processing pipeline (plan → queue → execute). Issue creation handled by issue-discover, CRUD by issue-manage.", + "version": "1.0.0", + + "roles": { + "coordinator": { + "task_prefix": null, + "responsibility": "Pipeline orchestration, mode selection, task chain creation, progress monitoring", + "message_types": ["task_assigned", "pipeline_update", "escalation", "shutdown", "error"] + }, + "explorer": { + "task_prefix": "EXPLORE", + "responsibility": "Issue context analysis, codebase exploration, dependency identification, impact assessment", + "message_types": ["context_ready", "impact_assessed", "error"], + "reuses_agent": "cli-explore-agent" + }, + "planner": { + "task_prefix": "SOLVE", + "responsibility": "Solution design, task decomposition via issue-plan-agent", + "message_types": ["solution_ready", "multi_solution", "error"], + "reuses_agent": "issue-plan-agent" + }, + "reviewer": { + "task_prefix": "AUDIT", + "responsibility": "Solution review, technical feasibility validation, risk assessment", + "message_types": ["approved", "rejected", "concerns", "error"], + "reuses_agent": null + }, + "integrator": { + "task_prefix": "MARSHAL", + "responsibility": "Queue formation, conflict detection, execution order optimization via issue-queue-agent", + "message_types": ["queue_ready", "conflict_found", "error"], + "reuses_agent": "issue-queue-agent" + }, + "implementer": { + "task_prefix": "BUILD", + "responsibility": "Code implementation, test verification, result submission via code-developer", + "message_types": ["impl_complete", "impl_failed", "error"], + "reuses_agent": "code-developer" + } + }, + + "pipelines": { + "quick": { + "description": "Simple issues, skip review", + "task_chain": ["EXPLORE-001", "SOLVE-001", "MARSHAL-001", "BUILD-001"] + }, + "full": { + "description": "Complex issues, with CP-2 review cycle (max 2 rounds)", + "task_chain": ["EXPLORE-001", "SOLVE-001", "AUDIT-001", "MARSHAL-001", "BUILD-001"] + }, + "batch": { + "description": "Batch processing 5-100 issues with parallel exploration and execution", + "task_chain": "EXPLORE-001..N(batch≤5) → SOLVE-001..N(batch≤3) → AUDIT-001 → MARSHAL-001 → BUILD-001..M(DAG parallel)" + } + }, + + "collaboration_patterns": ["CP-1", "CP-2", "CP-3", "CP-5"], + + "session_dirs": { + "base": ".workflow/.team-plan/issue/", + "context": ".workflow/.team-plan/issue/context-{issueId}.json", + "audit": ".workflow/.team-plan/issue/audit-report.json", + "queue": ".workflow/issues/queue/execution-queue.json", + "solutions": ".workflow/issues/solutions/", + "messages": ".workflow/.team-msg/issue/" + } +} diff --git a/.claude/skills/team-lifecycle/SKILL.md b/.claude/skills/team-lifecycle/SKILL.md index d66e9b06..b895e730 100644 --- a/.claude/skills/team-lifecycle/SKILL.md +++ b/.claude/skills/team-lifecycle/SKILL.md @@ -159,6 +159,45 @@ Full-lifecycle: [Spec pipeline] → PLAN-001(blockedBy: DISCUSS-006) → IMPL-001 → TEST-001 + REVIEW-001 ``` +## Unified Session Directory + +All session artifacts are stored under a single session folder: + +``` +.workflow/.team/TLS-{slug}-{YYYY-MM-DD}/ +├── team-session.json # Session state (status, progress, completed_tasks) +├── spec/ # Spec artifacts (analyst, writer, reviewer output) +│ ├── spec-config.json +│ ├── discovery-context.json +│ ├── product-brief.md +│ ├── requirements/ # _index.md + REQ-*.md + NFR-*.md +│ ├── architecture/ # _index.md + ADR-*.md +│ ├── epics/ # _index.md + EPIC-*.md +│ ├── readiness-report.md +│ └── spec-summary.md +├── discussions/ # Discussion records (discussant output) +│ └── discuss-001..006.md +└── plan/ # Plan artifacts (planner output) + ├── exploration-{angle}.json + ├── explorations-manifest.json + ├── plan.json + └── .task/ + └── TASK-*.json +``` + +Messages remain at `.workflow/.team-msg/{team-name}/` (unchanged). + +## Session Resume + +Coordinator supports `--resume` / `--continue` flags to resume interrupted sessions: + +1. Scans `.workflow/.team/TLS-*/team-session.json` for `status: "active"` or `"paused"` +2. Multiple matches → `AskUserQuestion` for user selection +3. Loads session state: `teamName`, `mode`, `sessionFolder`, `completed_tasks` +4. Rebuilds team (`TeamCreate` + worker spawns) +5. Creates only uncompleted tasks in the task chain +6. Jumps to Phase 4 coordination loop + ## Coordinator Spawn Template When coordinator creates teammates: @@ -237,6 +276,7 @@ Task({ 当你收到 PLAN-* 任务时,调用 Skill(skill="team-lifecycle", args="--role=planner") 执行。 当前需求: ${taskDescription} 约束: ${constraints} +Session: ${sessionFolder} ## 消息总线(必须) 每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。 diff --git a/.claude/skills/team-lifecycle/roles/analyst.md b/.claude/skills/team-lifecycle/roles/analyst.md index 13c09068..ebc6b1ed 100644 --- a/.claude/skills/team-lifecycle/roles/analyst.md +++ b/.claude/skills/team-lifecycle/roles/analyst.md @@ -23,7 +23,7 @@ Before every `SendMessage`, MUST call `mcp__ccw-tools__team_msg` to log: ```javascript // Research complete -mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "analyst", to: "coordinator", type: "research_ready", summary: "Research done: 5 exploration dimensions", ref: `${sessionFolder}/discovery-context.json` }) +mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "analyst", to: "coordinator", type: "research_ready", summary: "Research done: 5 exploration dimensions", ref: `${sessionFolder}/spec/discovery-context.json` }) // Error report mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "analyst", to: "coordinator", type: "error", summary: "Codebase access failed" }) @@ -61,7 +61,7 @@ TaskUpdate({ taskId: task.id, status: 'in_progress' }) ```javascript // Extract session folder from task description const sessionMatch = task.description.match(/Session:\s*(.+)/) -const sessionFolder = sessionMatch ? sessionMatch[1].trim() : '.workflow/.spec-team/default' +const sessionFolder = sessionMatch ? sessionMatch[1].trim() : '.workflow/.team/default' // Parse topic from task description const topicLines = task.description.split('\n').filter(l => !l.startsWith('Session:') && !l.startsWith('输出:') && l.trim()) @@ -135,7 +135,7 @@ const specConfig = { session_folder: sessionFolder, discussion_depth: task.description.match(/讨论深度:\s*(.+)/)?.[1] || "standard" } -Write(`${sessionFolder}/spec-config.json`, JSON.stringify(specConfig, null, 2)) +Write(`${sessionFolder}/spec/spec-config.json`, JSON.stringify(specConfig, null, 2)) // Generate discovery-context.json const discoveryContext = { @@ -155,7 +155,7 @@ const discoveryContext = { codebase_context: codebaseContext, recommendations: { focus_areas: [], risks: [], open_questions: [] } } -Write(`${sessionFolder}/discovery-context.json`, JSON.stringify(discoveryContext, null, 2)) +Write(`${sessionFolder}/spec/discovery-context.json`, JSON.stringify(discoveryContext, null, 2)) ``` ### Phase 5: Report to Coordinator @@ -191,8 +191,8 @@ ${(discoveryContext.seed_analysis.target_users || []).map(u => '- ' + u).join('\ ${(discoveryContext.seed_analysis.exploration_dimensions || []).map((d, i) => (i+1) + '. ' + d).join('\n')} ### 输出位置 -- Config: ${sessionFolder}/spec-config.json -- Context: ${sessionFolder}/discovery-context.json +- Config: ${sessionFolder}/spec/spec-config.json +- Context: ${sessionFolder}/spec/discovery-context.json 研究已就绪,可进入讨论轮次 DISCUSS-001。`, summary: `研究就绪: ${dimensionCount}维度, ${specConfig.complexity}` diff --git a/.claude/skills/team-lifecycle/roles/coordinator.md b/.claude/skills/team-lifecycle/roles/coordinator.md index 44a63c90..db6d94e7 100644 --- a/.claude/skills/team-lifecycle/roles/coordinator.md +++ b/.claude/skills/team-lifecycle/roles/coordinator.md @@ -22,6 +22,74 @@ Team lifecycle coordinator. Orchestrates the full pipeline across three modes: s ## Execution +### Phase 0: Session Resume Check + +Before any new session setup, check if resuming an existing session: + +```javascript +const args = "$ARGUMENTS" +const isResume = /--resume|--continue/.test(args) + +if (isResume) { + // Scan for active/paused sessions + const sessionDirs = Glob({ pattern: '.workflow/.team/TLS-*/team-session.json' }) + const resumable = sessionDirs.map(f => { + try { + const session = JSON.parse(Read(f)) + if (session.status === 'active' || session.status === 'paused') return session + } catch {} + return null + }).filter(Boolean) + + if (resumable.length === 0) { + // No resumable sessions → fall through to Phase 1 + } else if (resumable.length === 1) { + var resumedSession = resumable[0] + } else { + // Multiple matches → user selects + AskUserQuestion({ + questions: [{ + question: "检测到多个可恢复的会话,请选择:", + header: "Resume", + multiSelect: false, + options: resumable.slice(0, 4).map(s => ({ + label: s.session_id, + description: `${s.topic} (${s.current_phase}, ${s.status})` + })) + }] + }) + var resumedSession = resumable.find(s => s.session_id === userChoice) + } + + if (resumedSession) { + // Restore session state + const teamName = resumedSession.team_name + const mode = resumedSession.mode + const sessionFolder = `.workflow/.team/${resumedSession.session_id}` + const taskDescription = resumedSession.topic + + // Rebuild team + TeamCreate({ team_name: teamName }) + // Spawn workers based on mode (see Phase 2) + + // Update session status + resumedSession.status = 'active' + resumedSession.resumed_at = new Date().toISOString() + resumedSession.updated_at = new Date().toISOString() + Write(`${sessionFolder}/team-session.json`, JSON.stringify(resumedSession, null, 2)) + + // Create only uncompleted tasks from pipeline + const completedTasks = new Set(resumedSession.completed_tasks || []) + const pipeline = resumedSession.mode === 'spec-only' ? SPEC_CHAIN + : resumedSession.mode === 'impl-only' ? IMPL_CHAIN + : [...SPEC_CHAIN, ...IMPL_CHAIN] + const remainingTasks = pipeline.filter(t => !completedTasks.has(t)) + + // → Skip to Phase 3 with remainingTasks, then Phase 4 coordination loop + } +} +``` + ### Phase 1: Requirement Clarification Parse `$ARGUMENTS` to extract `--team-name` and task description. @@ -30,7 +98,7 @@ Parse `$ARGUMENTS` to extract `--team-name` and task description. const args = "$ARGUMENTS" const teamNameMatch = args.match(/--team-name[=\s]+([\w-]+)/) const teamName = teamNameMatch ? teamNameMatch[1] : `lifecycle-${Date.now().toString(36)}` -const taskDescription = args.replace(/--team-name[=\s]+[\w-]+/, '').replace(/--role[=\s]+\w+/, '').trim() +const taskDescription = args.replace(/--team-name[=\s]+[\w-]+/, '').replace(/--role[=\s]+\w+/, '').replace(/--resume|--continue/, '').trim() ``` Use AskUserQuestion to collect mode and constraints: @@ -97,18 +165,42 @@ Simple tasks can skip clarification. ```javascript TeamCreate({ team_name: teamName }) -// Session setup +// Unified session setup const topicSlug = taskDescription.toLowerCase().replace(/[^a-z0-9]+/g, '-').substring(0, 40) const dateStr = new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString().substring(0, 10) -const specSessionFolder = `.workflow/.spec-team/${topicSlug}-${dateStr}` -const implSessionFolder = `.workflow/.team-plan/${topicSlug}-${dateStr}` +const sessionId = `TLS-${topicSlug}-${dateStr}` +const sessionFolder = `.workflow/.team/${sessionId}` +// Create unified directory structure if (mode === 'spec-only' || mode === 'full-lifecycle') { - Bash(`mkdir -p ${specSessionFolder}/discussions`) + Bash(`mkdir -p "${sessionFolder}/spec" "${sessionFolder}/discussions"`) } if (mode === 'impl-only' || mode === 'full-lifecycle') { - Bash(`mkdir -p ${implSessionFolder}`) + Bash(`mkdir -p "${sessionFolder}/plan"`) } + +// Create team-session.json +const teamSession = { + session_id: sessionId, + team_name: teamName, + topic: taskDescription, + mode: mode, + status: "active", + created_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + paused_at: null, + resumed_at: null, + completed_at: null, + current_phase: mode === 'impl-only' ? 'plan' : 'spec', + completed_tasks: [], + pipeline_progress: { + spec: mode !== 'impl-only' ? { total: 12, completed: 0 } : null, + impl: mode !== 'spec-only' ? { total: 4, completed: 0 } : null + }, + user_preferences: { scope: scope || '', focus: focus || '', discussion_depth: discussionDepth || '' }, + messages_team: teamName +} +Write(`${sessionFolder}/team-session.json`, JSON.stringify(teamSession, null, 2)) ``` **Conditional spawn based on mode** (see SKILL.md Coordinator Spawn Template for full prompts): @@ -129,51 +221,51 @@ Task chain creation depends on the selected mode. ```javascript // RESEARCH Phase -TaskCreate({ subject: "RESEARCH-001: 主题发现与上下文研究", description: `${taskDescription}\n\nSession: ${specSessionFolder}\n输出: ${specSessionFolder}/spec-config.json + discovery-context.json`, activeForm: "研究中" }) +TaskCreate({ subject: "RESEARCH-001: 主题发现与上下文研究", description: `${taskDescription}\n\nSession: ${sessionFolder}\n输出: ${sessionFolder}/spec/spec-config.json + spec/discovery-context.json`, activeForm: "研究中" }) TaskUpdate({ taskId: researchId, owner: "analyst" }) // DISCUSS-001: 范围讨论 (blockedBy RESEARCH-001) -TaskCreate({ subject: "DISCUSS-001: 研究结果讨论 - 范围确认与方向调整", description: `讨论 RESEARCH-001 的发现结果\n\nSession: ${specSessionFolder}\n输入: ${specSessionFolder}/discovery-context.json\n输出: ${specSessionFolder}/discussions/discuss-001-scope.md\n\n讨论维度: 范围确认、方向调整、风险预判、探索缺口`, activeForm: "讨论范围中" }) +TaskCreate({ subject: "DISCUSS-001: 研究结果讨论 - 范围确认与方向调整", description: `讨论 RESEARCH-001 的发现结果\n\nSession: ${sessionFolder}\n输入: ${sessionFolder}/spec/discovery-context.json\n输出: ${sessionFolder}/discussions/discuss-001-scope.md\n\n讨论维度: 范围确认、方向调整、风险预判、探索缺口`, activeForm: "讨论范围中" }) TaskUpdate({ taskId: discuss1Id, owner: "discussant", addBlockedBy: [researchId] }) // DRAFT-001: Product Brief (blockedBy DISCUSS-001) -TaskCreate({ subject: "DRAFT-001: 撰写 Product Brief", description: `基于研究和讨论共识撰写产品简报\n\nSession: ${specSessionFolder}\n输入: discovery-context.json + discuss-001-scope.md\n输出: ${specSessionFolder}/product-brief.md\n\n使用多视角分析: 产品/技术/用户`, activeForm: "撰写 Brief 中" }) +TaskCreate({ subject: "DRAFT-001: 撰写 Product Brief", description: `基于研究和讨论共识撰写产品简报\n\nSession: ${sessionFolder}\n输入: discovery-context.json + discuss-001-scope.md\n输出: ${sessionFolder}/product-brief.md\n\n使用多视角分析: 产品/技术/用户`, activeForm: "撰写 Brief 中" }) TaskUpdate({ taskId: draft1Id, owner: "writer", addBlockedBy: [discuss1Id] }) // DISCUSS-002: Brief 评审 (blockedBy DRAFT-001) -TaskCreate({ subject: "DISCUSS-002: Product Brief 多视角评审", description: `评审 Product Brief 文档\n\nSession: ${specSessionFolder}\n输入: ${specSessionFolder}/product-brief.md\n输出: ${specSessionFolder}/discussions/discuss-002-brief.md\n\n讨论维度: 产品定位、目标用户、成功指标、竞品差异`, activeForm: "评审 Brief 中" }) +TaskCreate({ subject: "DISCUSS-002: Product Brief 多视角评审", description: `评审 Product Brief 文档\n\nSession: ${sessionFolder}\n输入: ${sessionFolder}/spec/product-brief.md\n输出: ${sessionFolder}/discussions/discuss-002-brief.md\n\n讨论维度: 产品定位、目标用户、成功指标、竞品差异`, activeForm: "评审 Brief 中" }) TaskUpdate({ taskId: discuss2Id, owner: "discussant", addBlockedBy: [draft1Id] }) // DRAFT-002: Requirements/PRD (blockedBy DISCUSS-002) -TaskCreate({ subject: "DRAFT-002: 撰写 Requirements/PRD", description: `基于 Brief 和讨论反馈撰写需求文档\n\nSession: ${specSessionFolder}\n输入: product-brief.md + discuss-002-brief.md\n输出: ${specSessionFolder}/requirements/\n\n包含: 功能需求(REQ-*) + 非功能需求(NFR-*) + MoSCoW 优先级`, activeForm: "撰写 PRD 中" }) +TaskCreate({ subject: "DRAFT-002: 撰写 Requirements/PRD", description: `基于 Brief 和讨论反馈撰写需求文档\n\nSession: ${sessionFolder}\n输入: product-brief.md + discuss-002-brief.md\n输出: ${sessionFolder}/requirements/\n\n包含: 功能需求(REQ-*) + 非功能需求(NFR-*) + MoSCoW 优先级`, activeForm: "撰写 PRD 中" }) TaskUpdate({ taskId: draft2Id, owner: "writer", addBlockedBy: [discuss2Id] }) // DISCUSS-003: 需求完整性 (blockedBy DRAFT-002) -TaskCreate({ subject: "DISCUSS-003: 需求完整性与优先级讨论", description: `讨论 PRD 需求完整性\n\nSession: ${specSessionFolder}\n输入: ${specSessionFolder}/requirements/_index.md\n输出: ${specSessionFolder}/discussions/discuss-003-requirements.md\n\n讨论维度: 需求遗漏、MoSCoW合理性、验收标准可测性、非功能需求充分性`, activeForm: "讨论需求中" }) +TaskCreate({ subject: "DISCUSS-003: 需求完整性与优先级讨论", description: `讨论 PRD 需求完整性\n\nSession: ${sessionFolder}\n输入: ${sessionFolder}/spec/requirements/_index.md\n输出: ${sessionFolder}/discussions/discuss-003-requirements.md\n\n讨论维度: 需求遗漏、MoSCoW合理性、验收标准可测性、非功能需求充分性`, activeForm: "讨论需求中" }) TaskUpdate({ taskId: discuss3Id, owner: "discussant", addBlockedBy: [draft2Id] }) // DRAFT-003: Architecture (blockedBy DISCUSS-003) -TaskCreate({ subject: "DRAFT-003: 撰写 Architecture Document", description: `基于需求和讨论反馈撰写架构文档\n\nSession: ${specSessionFolder}\n输入: requirements/ + discuss-003-requirements.md\n输出: ${specSessionFolder}/architecture/\n\n包含: 架构风格 + 组件图 + 技术选型 + ADR-* + 数据模型`, activeForm: "撰写架构中" }) +TaskCreate({ subject: "DRAFT-003: 撰写 Architecture Document", description: `基于需求和讨论反馈撰写架构文档\n\nSession: ${sessionFolder}\n输入: requirements/ + discuss-003-requirements.md\n输出: ${sessionFolder}/architecture/\n\n包含: 架构风格 + 组件图 + 技术选型 + ADR-* + 数据模型`, activeForm: "撰写架构中" }) TaskUpdate({ taskId: draft3Id, owner: "writer", addBlockedBy: [discuss3Id] }) // DISCUSS-004: 技术可行性 (blockedBy DRAFT-003) -TaskCreate({ subject: "DISCUSS-004: 架构决策与技术可行性讨论", description: `讨论架构设计合理性\n\nSession: ${specSessionFolder}\n输入: ${specSessionFolder}/architecture/_index.md\n输出: ${specSessionFolder}/discussions/discuss-004-architecture.md\n\n讨论维度: 技术选型风险、可扩展性、安全架构、ADR替代方案`, activeForm: "讨论架构中" }) +TaskCreate({ subject: "DISCUSS-004: 架构决策与技术可行性讨论", description: `讨论架构设计合理性\n\nSession: ${sessionFolder}\n输入: ${sessionFolder}/spec/architecture/_index.md\n输出: ${sessionFolder}/discussions/discuss-004-architecture.md\n\n讨论维度: 技术选型风险、可扩展性、安全架构、ADR替代方案`, activeForm: "讨论架构中" }) TaskUpdate({ taskId: discuss4Id, owner: "discussant", addBlockedBy: [draft3Id] }) // DRAFT-004: Epics & Stories (blockedBy DISCUSS-004) -TaskCreate({ subject: "DRAFT-004: 撰写 Epics & Stories", description: `基于架构和讨论反馈撰写史诗和用户故事\n\nSession: ${specSessionFolder}\n输入: architecture/ + discuss-004-architecture.md\n输出: ${specSessionFolder}/epics/\n\n包含: EPIC-* + STORY-* + 依赖图 + MVP定义 + 执行顺序`, activeForm: "撰写 Epics 中" }) +TaskCreate({ subject: "DRAFT-004: 撰写 Epics & Stories", description: `基于架构和讨论反馈撰写史诗和用户故事\n\nSession: ${sessionFolder}\n输入: architecture/ + discuss-004-architecture.md\n输出: ${sessionFolder}/epics/\n\n包含: EPIC-* + STORY-* + 依赖图 + MVP定义 + 执行顺序`, activeForm: "撰写 Epics 中" }) TaskUpdate({ taskId: draft4Id, owner: "writer", addBlockedBy: [discuss4Id] }) // DISCUSS-005: 执行就绪 (blockedBy DRAFT-004) -TaskCreate({ subject: "DISCUSS-005: 执行计划与MVP范围讨论", description: `讨论执行计划就绪性\n\nSession: ${specSessionFolder}\n输入: ${specSessionFolder}/epics/_index.md\n输出: ${specSessionFolder}/discussions/discuss-005-epics.md\n\n讨论维度: Epic粒度、故事估算、MVP范围、执行顺序、依赖风险`, activeForm: "讨论执行计划中" }) +TaskCreate({ subject: "DISCUSS-005: 执行计划与MVP范围讨论", description: `讨论执行计划就绪性\n\nSession: ${sessionFolder}\n输入: ${sessionFolder}/spec/epics/_index.md\n输出: ${sessionFolder}/discussions/discuss-005-epics.md\n\n讨论维度: Epic粒度、故事估算、MVP范围、执行顺序、依赖风险`, activeForm: "讨论执行计划中" }) TaskUpdate({ taskId: discuss5Id, owner: "discussant", addBlockedBy: [draft4Id] }) // QUALITY-001: Readiness Check (blockedBy DISCUSS-005) -TaskCreate({ subject: "QUALITY-001: 规格就绪度检查", description: `全文档交叉验证和质量评分\n\nSession: ${specSessionFolder}\n输入: 全部文档\n输出: ${specSessionFolder}/readiness-report.md + spec-summary.md\n\n评分维度: 完整性(20%) + 一致性(20%) + 可追溯性(20%) + 深度(20%) + 需求覆盖率(20%)`, activeForm: "质量检查中" }) +TaskCreate({ subject: "QUALITY-001: 规格就绪度检查", description: `全文档交叉验证和质量评分\n\nSession: ${sessionFolder}\n输入: 全部文档\n输出: ${sessionFolder}/spec/readiness-report.md + spec/spec-summary.md\n\n评分维度: 完整性(20%) + 一致性(20%) + 可追溯性(20%) + 深度(20%) + 需求覆盖率(20%)`, activeForm: "质量检查中" }) TaskUpdate({ taskId: qualityId, owner: "reviewer", addBlockedBy: [discuss5Id] }) // DISCUSS-006: 最终签收 (blockedBy QUALITY-001) -TaskCreate({ subject: "DISCUSS-006: 最终签收与交付确认", description: `最终讨论和签收\n\nSession: ${specSessionFolder}\n输入: ${specSessionFolder}/readiness-report.md\n输出: ${specSessionFolder}/discussions/discuss-006-final.md\n\n讨论维度: 质量报告审查、遗留问题处理、交付确认、下一步建议`, activeForm: "最终签收讨论中" }) +TaskCreate({ subject: "DISCUSS-006: 最终签收与交付确认", description: `最终讨论和签收\n\nSession: ${sessionFolder}\n输入: ${sessionFolder}/spec/readiness-report.md\n输出: ${sessionFolder}/discussions/discuss-006-final.md\n\n讨论维度: 质量报告审查、遗留问题处理、交付确认、下一步建议`, activeForm: "最终签收讨论中" }) TaskUpdate({ taskId: discuss6Id, owner: "discussant", addBlockedBy: [qualityId] }) ``` @@ -181,11 +273,11 @@ TaskUpdate({ taskId: discuss6Id, owner: "discussant", addBlockedBy: [qualityId] ```javascript // PLAN-001 -TaskCreate({ subject: "PLAN-001: 探索和规划实现", description: `${taskDescription}\n\n写入: ${implSessionFolder}/`, activeForm: "规划中" }) +TaskCreate({ subject: "PLAN-001: 探索和规划实现", description: `${taskDescription}\n\nSession: ${sessionFolder}\n写入: ${sessionFolder}/plan/`, activeForm: "规划中" }) TaskUpdate({ taskId: planId, owner: "planner" }) // IMPL-001 (blockedBy PLAN-001) -TaskCreate({ subject: "IMPL-001: 实现已批准的计划", description: `${taskDescription}\n\nPlan: ${implSessionFolder}/plan.json`, activeForm: "实现中" }) +TaskCreate({ subject: "IMPL-001: 实现已批准的计划", description: `${taskDescription}\n\nSession: ${sessionFolder}\nPlan: ${sessionFolder}/plan/plan.json`, activeForm: "实现中" }) TaskUpdate({ taskId: implId, owner: "executor", addBlockedBy: [planId] }) // TEST-001 (blockedBy IMPL-001) @@ -193,7 +285,7 @@ TaskCreate({ subject: "TEST-001: 测试修复循环", description: `${taskDescri TaskUpdate({ taskId: testId, owner: "tester", addBlockedBy: [implId] }) // REVIEW-001 (blockedBy IMPL-001, parallel with TEST-001) -TaskCreate({ subject: "REVIEW-001: 代码审查与需求验证", description: `${taskDescription}\n\nPlan: ${implSessionFolder}/plan.json`, activeForm: "审查中" }) +TaskCreate({ subject: "REVIEW-001: 代码审查与需求验证", description: `${taskDescription}\n\nSession: ${sessionFolder}\nPlan: ${sessionFolder}/plan/plan.json`, activeForm: "审查中" }) TaskUpdate({ taskId: reviewId, owner: "reviewer", addBlockedBy: [implId] }) ``` @@ -204,7 +296,7 @@ Create both spec and impl chains, with PLAN-001 blockedBy DISCUSS-006: ```javascript // [All spec-only tasks as above] // Then: -TaskCreate({ subject: "PLAN-001: 探索和规划实现", description: `${taskDescription}\n\nSpec: ${specSessionFolder}\n写入: ${implSessionFolder}/`, activeForm: "规划中" }) +TaskCreate({ subject: "PLAN-001: 探索和规划实现", description: `${taskDescription}\n\nSession: ${sessionFolder}\n写入: ${sessionFolder}/plan/`, activeForm: "规划中" }) TaskUpdate({ taskId: planId, owner: "planner", addBlockedBy: [discuss6Id] }) // [Rest of impl-only tasks as above] ``` @@ -248,7 +340,7 @@ When receiving `research_ready` from analyst, confirm extracted requirements wit ```javascript if (msgType === 'research_ready') { - const discoveryContext = JSON.parse(Read(`${specSessionFolder}/discovery-context.json`)) + const discoveryContext = JSON.parse(Read(`${sessionFolder}/spec/discovery-context.json`)) const dimensions = discoveryContext.seed_analysis?.exploration_dimensions || [] const constraints = discoveryContext.seed_analysis?.constraints || [] const problemStatement = discoveryContext.seed_analysis?.problem_statement || '' @@ -271,7 +363,7 @@ if (msgType === 'research_ready') { // User provides additional requirements via free text // Merge into discovery-context.json, then unblock DISCUSS-001 discoveryContext.seed_analysis.user_supplements = userInput - Write(`${specSessionFolder}/discovery-context.json`, JSON.stringify(discoveryContext, null, 2)) + Write(`${sessionFolder}/spec/discovery-context.json`, JSON.stringify(discoveryContext, null, 2)) } else if (userChoice === '需要重新研究') { // Reset RESEARCH-001 to pending, notify analyst TaskUpdate({ taskId: researchId, status: 'pending' }) @@ -341,13 +433,13 @@ if (userChoice === '交付执行') { }) // 读取 spec 文档 - const specConfig = JSON.parse(Read(`${specSessionFolder}/spec-config.json`)) - const specSummary = Read(`${specSessionFolder}/spec-summary.md`) - const productBrief = Read(`${specSessionFolder}/product-brief.md`) - const requirementsIndex = Read(`${specSessionFolder}/requirements/_index.md`) - const architectureIndex = Read(`${specSessionFolder}/architecture/_index.md`) - const epicsIndex = Read(`${specSessionFolder}/epics/_index.md`) - const epicFiles = Glob(`${specSessionFolder}/epics/EPIC-*.md`) + const specConfig = JSON.parse(Read(`${sessionFolder}/spec/spec-config.json`)) + const specSummary = Read(`${sessionFolder}/spec/spec-summary.md`) + const productBrief = Read(`${sessionFolder}/spec/product-brief.md`) + const requirementsIndex = Read(`${sessionFolder}/spec/requirements/_index.md`) + const architectureIndex = Read(`${sessionFolder}/spec/architecture/_index.md`) + const epicsIndex = Read(`${sessionFolder}/spec/epics/_index.md`) + const epicFiles = Glob(`${sessionFolder}/spec/epics/EPIC-*.md`) if (handoffChoice === 'lite-plan') { // 读取首个 MVP Epic → 调用 lite-plan @@ -368,7 +460,7 @@ if (userChoice === '交付执行') { // Step A: 构建结构化描述 const structuredDesc = `GOAL: ${specConfig.seed_analysis?.problem_statement || specConfig.topic} SCOPE: ${specConfig.complexity} complexity -CONTEXT: Generated from spec team session ${specConfig.session_id}. Source: ${specSessionFolder}/` +CONTEXT: Generated from spec team session ${specConfig.session_id}. Source: ${sessionFolder}/` // Step B: 创建 WFS session Skill({ skill: "workflow:session:start", args: `--auto "${structuredDesc}"` }) @@ -384,7 +476,7 @@ CONTEXT: Generated from spec team session ${specConfig.session_id}. Source: ${sp **Source**: spec-team session ${specConfig.session_id} **Generated**: ${new Date().toISOString()} -**Spec Directory**: ${specSessionFolder} +**Spec Directory**: ${sessionFolder} ## 1. Project Positioning & Goals ${extractSection(productBrief, "Vision")} @@ -407,11 +499,11 @@ ${extractSection(epicsIndex, "Traceability Matrix")} ## Appendix: Source Documents | Document | Path | Description | |----------|------|-------------| -| Product Brief | ${specSessionFolder}/product-brief.md | Vision, goals, scope | -| Requirements | ${specSessionFolder}/requirements/ | _index.md + REQ-*.md + NFR-*.md | -| Architecture | ${specSessionFolder}/architecture/ | _index.md + ADR-*.md | -| Epics | ${specSessionFolder}/epics/ | _index.md + EPIC-*.md | -| Readiness Report | ${specSessionFolder}/readiness-report.md | Quality validation | +| Product Brief | ${sessionFolder}/spec/product-brief.md | Vision, goals, scope | +| Requirements | ${sessionFolder}/spec/requirements/ | _index.md + REQ-*.md + NFR-*.md | +| Architecture | ${sessionFolder}/spec/architecture/ | _index.md + ADR-*.md | +| Epics | ${sessionFolder}/spec/epics/ | _index.md + EPIC-*.md | +| Readiness Report | ${sessionFolder}/spec/readiness-report.md | Quality validation | `) // C.2: feature-index.json(EPIC → Feature 映射) @@ -501,30 +593,58 @@ function parseYAML(yamlStr) { } ``` +## Session State Tracking + +At each key transition, update `team-session.json`: + +```javascript +// Helper: update session state +function updateSession(sessionFolder, updates) { + const session = JSON.parse(Read(`${sessionFolder}/team-session.json`)) + Object.assign(session, updates, { updated_at: new Date().toISOString() }) + Write(`${sessionFolder}/team-session.json`, JSON.stringify(session, null, 2)) +} + +// On task completion: +updateSession(sessionFolder, { + completed_tasks: [...session.completed_tasks, taskPrefix], + pipeline_progress: { ...session.pipeline_progress, + [phase]: { ...session.pipeline_progress[phase], completed: session.pipeline_progress[phase].completed + 1 } + } +}) + +// On phase transition (spec → plan): +updateSession(sessionFolder, { current_phase: 'plan' }) + +// On completion: +updateSession(sessionFolder, { status: 'completed', completed_at: new Date().toISOString() }) + +// On user closes team: +updateSession(sessionFolder, { status: 'completed', completed_at: new Date().toISOString() }) +``` + ## Session File Structure ``` -# Spec session -.workflow/.spec-team/{topic-slug}-{YYYY-MM-DD}/ -├── spec-config.json -├── discovery-context.json -├── product-brief.md -├── requirements/ -├── architecture/ -├── epics/ -├── readiness-report.md -├── spec-summary.md -└── discussions/ - └── discuss-001..006.md - -# Impl session -.workflow/.team-plan/{task-slug}-{YYYY-MM-DD}/ -├── exploration-*.json -├── explorations-manifest.json -├── planning-context.md -├── plan.json -└── .task/ - └── TASK-*.json +.workflow/.team/TLS-{slug}-{YYYY-MM-DD}/ +├── team-session.json # Session state (resume support) +├── spec/ # Spec artifacts +│ ├── spec-config.json +│ ├── discovery-context.json +│ ├── product-brief.md +│ ├── requirements/ # _index.md + REQ-*.md + NFR-*.md +│ ├── architecture/ # _index.md + ADR-*.md +│ ├── epics/ # _index.md + EPIC-*.md +│ ├── readiness-report.md +│ └── spec-summary.md +├── discussions/ # Discussion records +│ └── discuss-001..006.md +└── plan/ # Plan artifacts + ├── exploration-{angle}.json + ├── explorations-manifest.json + ├── plan.json + └── .task/ + └── TASK-*.json ``` ## Error Handling diff --git a/.claude/skills/team-lifecycle/roles/discussant.md b/.claude/skills/team-lifecycle/roles/discussant.md index 7560eb8f..1cc84fd5 100644 --- a/.claude/skills/team-lifecycle/roles/discussant.md +++ b/.claude/skills/team-lifecycle/roles/discussant.md @@ -92,12 +92,12 @@ const roundMatch = task.subject.match(/DISCUSS-(\d+)/) const roundNumber = roundMatch ? parseInt(roundMatch[1]) : 0 const roundConfig = { - 1: { artifact: 'discovery-context.json', type: 'json', outputFile: 'discuss-001-scope.md', perspectives: ['product', 'risk', 'coverage'], label: '范围讨论' }, - 2: { artifact: 'product-brief.md', type: 'md', outputFile: 'discuss-002-brief.md', perspectives: ['product', 'technical', 'quality', 'coverage'], label: 'Brief评审' }, - 3: { artifact: 'requirements/_index.md', type: 'md', outputFile: 'discuss-003-requirements.md', perspectives: ['quality', 'product', 'coverage'], label: '需求讨论' }, - 4: { artifact: 'architecture/_index.md', type: 'md', outputFile: 'discuss-004-architecture.md', perspectives: ['technical', 'risk'], label: '架构讨论' }, - 5: { artifact: 'epics/_index.md', type: 'md', outputFile: 'discuss-005-epics.md', perspectives: ['product', 'technical', 'quality', 'coverage'], label: 'Epics讨论' }, - 6: { artifact: 'readiness-report.md', type: 'md', outputFile: 'discuss-006-final.md', perspectives: ['product', 'technical', 'quality', 'risk', 'coverage'], label: '最终签收' } + 1: { artifact: 'spec/discovery-context.json', type: 'json', outputFile: 'discuss-001-scope.md', perspectives: ['product', 'risk', 'coverage'], label: '范围讨论' }, + 2: { artifact: 'spec/product-brief.md', type: 'md', outputFile: 'discuss-002-brief.md', perspectives: ['product', 'technical', 'quality', 'coverage'], label: 'Brief评审' }, + 3: { artifact: 'spec/requirements/_index.md', type: 'md', outputFile: 'discuss-003-requirements.md', perspectives: ['quality', 'product', 'coverage'], label: '需求讨论' }, + 4: { artifact: 'spec/architecture/_index.md', type: 'md', outputFile: 'discuss-004-architecture.md', perspectives: ['technical', 'risk'], label: '架构讨论' }, + 5: { artifact: 'spec/epics/_index.md', type: 'md', outputFile: 'discuss-005-epics.md', perspectives: ['product', 'technical', 'quality', 'coverage'], label: 'Epics讨论' }, + 6: { artifact: 'spec/readiness-report.md', type: 'md', outputFile: 'discuss-006-final.md', perspectives: ['product', 'technical', 'quality', 'risk', 'coverage'], label: '最终签收' } } const config = roundConfig[roundNumber] diff --git a/.claude/skills/team-lifecycle/roles/executor.md b/.claude/skills/team-lifecycle/roles/executor.md index ccfea816..1b2a9cd7 100644 --- a/.claude/skills/team-lifecycle/roles/executor.md +++ b/.claude/skills/team-lifecycle/roles/executor.md @@ -59,7 +59,7 @@ const task = TaskGet({ taskId: myTasks[0].id }) TaskUpdate({ taskId: task.id, status: 'in_progress' }) // Extract plan path from task description -const planPathMatch = task.description.match(/\.workflow\/\.team-plan\/[^\s]+\/plan\.json/) +const planPathMatch = task.description.match(/\.workflow\/\.team\/[^\s]+\/plan\/plan\.json/) const planPath = planPathMatch ? planPathMatch[0] : null if (!planPath) { diff --git a/.claude/skills/team-lifecycle/roles/planner.md b/.claude/skills/team-lifecycle/roles/planner.md index e1d51a33..d13b2c79 100644 --- a/.claude/skills/team-lifecycle/roles/planner.md +++ b/.claude/skills/team-lifecycle/roles/planner.md @@ -24,7 +24,7 @@ Before every `SendMessage`, MUST call `mcp__ccw-tools__team_msg` to log: ```javascript // Plan ready -mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "planner", to: "coordinator", type: "plan_ready", summary: "Plan ready: 3 tasks, Medium complexity", ref: `${sessionFolder}/plan.json` }) +mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "planner", to: "coordinator", type: "plan_ready", summary: "Plan ready: 3 tasks, Medium complexity", ref: `${sessionFolder}/plan/plan.json` }) // Plan revision mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "planner", to: "coordinator", type: "plan_revision", summary: "Split task-2 into two subtasks per feedback" }) @@ -38,7 +38,7 @@ mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "planner", to When `mcp__ccw-tools__team_msg` MCP is unavailable: ```javascript -Bash(`ccw team log --team "${teamName}" --from "planner" --to "coordinator" --type "plan_ready" --summary "Plan ready: 3 tasks" --ref "${sessionFolder}/plan.json" --json`) +Bash(`ccw team log --team "${teamName}" --from "planner" --to "coordinator" --type "plan_ready" --summary "Plan ready: 3 tasks" --ref "${sessionFolder}/plan/plan.json" --json`) ``` ## Execution (5-Phase) @@ -60,14 +60,30 @@ const task = TaskGet({ taskId: myTasks[0].id }) TaskUpdate({ taskId: task.id, status: 'in_progress' }) ``` +### Phase 1.5: Load Spec Context (Full-Lifecycle Mode) + +```javascript +// Extract session folder from task description (set by coordinator) +const sessionMatch = task.description.match(/Session:\s*(.+)/) +const sessionFolder = sessionMatch ? sessionMatch[1].trim() : `.workflow/.team/default` +const planDir = `${sessionFolder}/plan` +Bash(`mkdir -p ${planDir}`) + +// Check if spec directory exists (full-lifecycle mode) +const specDir = `${sessionFolder}/spec` +let specContext = null +try { + const reqIndex = Read(`${specDir}/requirements/_index.md`) + const archIndex = Read(`${specDir}/architecture/_index.md`) + const epicsIndex = Read(`${specDir}/epics/_index.md`) + const specConfig = JSON.parse(Read(`${specDir}/spec-config.json`)) + specContext = { reqIndex, archIndex, epicsIndex, specConfig } +} catch { /* impl-only mode has no spec */ } +``` + ### Phase 2: Multi-Angle Exploration ```javascript -// Session setup -const taskSlug = task.subject.toLowerCase().replace(/[^a-z0-9]+/g, '-').substring(0, 40) -const dateStr = new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString().substring(0, 10) -const sessionFolder = `.workflow/.team-plan/${taskSlug}-${dateStr}` -Bash(`mkdir -p ${sessionFolder}`) // Complexity assessment function assessComplexity(desc) { @@ -110,7 +126,7 @@ if (complexity === 'Low') { project_root_path: projectRoot, query: task.description }) - Write(`${sessionFolder}/exploration-${selectedAngles[0]}.json`, JSON.stringify({ + Write(`${planDir}/exploration-${selectedAngles[0]}.json`, JSON.stringify({ project_structure: "...", relevant_files: [], patterns: [], @@ -133,11 +149,12 @@ Execute **${angle}** exploration for task planning context. ## Output Location **Session Folder**: ${sessionFolder} -**Output File**: ${sessionFolder}/exploration-${angle}.json +**Output File**: ${planDir}/exploration-${angle}.json ## Assigned Context - **Exploration Angle**: ${angle} - **Task Description**: ${task.description} +- **Spec Context**: ${specContext ? 'Available — use spec/requirements, spec/architecture, spec/epics for informed exploration' : 'Not available (impl-only mode)'} - **Exploration Index**: ${index + 1} of ${selectedAngles.length} ## MANDATORY FIRST STEPS @@ -146,7 +163,7 @@ Execute **${angle}** exploration for task planning context. 3. Read: .workflow/project-tech.json (if exists - technology stack) ## Expected Output -Write JSON to: ${sessionFolder}/exploration-${angle}.json +Write JSON to: ${planDir}/exploration-${angle}.json Follow explore-json-schema.json structure with ${angle}-focused findings. **MANDATORY**: Every file in relevant_files MUST have: @@ -168,10 +185,10 @@ const explorationManifest = { explorations: selectedAngles.map(angle => ({ angle: angle, file: `exploration-${angle}.json`, - path: `${sessionFolder}/exploration-${angle}.json` + path: `${planDir}/exploration-${angle}.json` })) } -Write(`${sessionFolder}/explorations-manifest.json`, JSON.stringify(explorationManifest, null, 2)) +Write(`${planDir}/explorations-manifest.json`, JSON.stringify(explorationManifest, null, 2)) ``` ### Phase 3: Plan Generation @@ -182,7 +199,7 @@ const schema = Bash(`cat ~/.ccw/workflows/cli-templates/schemas/plan-overview-ba if (complexity === 'Low') { // Direct Claude planning - Bash(`mkdir -p ${sessionFolder}/.task`) + Bash(`mkdir -p ${planDir}/.task`) // Generate plan.json + .task/TASK-*.json following schemas } else { // Use cli-lite-planning-agent for Medium/High @@ -191,11 +208,16 @@ if (complexity === 'Low') { run_in_background: false, description: "Generate detailed implementation plan", prompt: `Generate implementation plan. -Output: ${sessionFolder}/plan.json + ${sessionFolder}/.task/TASK-*.json +Output: ${planDir}/plan.json + ${planDir}/.task/TASK-*.json Schema: cat ~/.ccw/workflows/cli-templates/schemas/plan-overview-base-schema.json Task Description: ${task.description} Explorations: ${explorationManifest} Complexity: ${complexity} +${specContext ? `Spec Context: +- Requirements: ${specContext.reqIndex.substring(0, 500)} +- Architecture: ${specContext.archIndex.substring(0, 500)} +- Epics: ${specContext.epicsIndex.substring(0, 500)} +Reference REQ-* IDs, follow ADR decisions, reuse Epic/Story decomposition.` : ''} Requirements: 2-7 tasks, each with id, title, files[].change, convergence.criteria, depends_on` }) } @@ -204,8 +226,8 @@ Requirements: 2-7 tasks, each with id, title, files[].change, convergence.criter ### Phase 4: Submit for Approval ```javascript -const plan = JSON.parse(Read(`${sessionFolder}/plan.json`)) -const planTasks = plan.task_ids.map(id => JSON.parse(Read(`${sessionFolder}/.task/${id}.json`))) +const plan = JSON.parse(Read(`${planDir}/plan.json`)) +const planTasks = plan.task_ids.map(id => JSON.parse(Read(`${planDir}/.task/${id}.json`))) const taskCount = plan.task_count || plan.task_ids.length mcp__ccw-tools__team_msg({ @@ -213,7 +235,7 @@ mcp__ccw-tools__team_msg({ from: "planner", to: "coordinator", type: "plan_ready", summary: `Plan就绪: ${taskCount}个task, ${complexity}复杂度`, - ref: `${sessionFolder}/plan.json` + ref: `${planDir}/plan.json` }) SendMessage({ @@ -232,8 +254,8 @@ ${planTasks.map((t, i) => (i+1) + '. ' + t.title).join('\n')} ${plan.approach} ### Plan Location -${sessionFolder}/plan.json -Task Files: ${sessionFolder}/.task/ +${planDir}/plan.json +Task Files: ${planDir}/.task/ Please review and approve or request revisions.`, summary: `Plan ready: ${taskCount} tasks` @@ -253,7 +275,7 @@ TaskUpdate({ taskId: task.id, status: 'completed' }) ## Session Files ``` -.workflow/.team-plan/{task-slug}-{YYYY-MM-DD}/ +{sessionFolder}/plan/ ├── exploration-{angle}.json ├── explorations-manifest.json ├── planning-context.md @@ -262,6 +284,8 @@ TaskUpdate({ taskId: task.id, status: 'completed' }) └── TASK-*.json ``` +> **Note**: `sessionFolder` is extracted from task description (`Session: .workflow/.team/TLS-xxx`). Plan outputs go to `plan/` subdirectory. In full-lifecycle mode, spec products are available at `../spec/`. + ## Error Handling | Scenario | Resolution | diff --git a/.claude/skills/team-lifecycle/roles/reviewer.md b/.claude/skills/team-lifecycle/roles/reviewer.md index fb3e3fc4..f81cbbfc 100644 --- a/.claude/skills/team-lifecycle/roles/reviewer.md +++ b/.claude/skills/team-lifecycle/roles/reviewer.md @@ -73,7 +73,7 @@ const reviewMode = task.subject.startsWith('REVIEW-') ? 'code' : 'spec' ```javascript if (reviewMode === 'code') { // Load plan for acceptance criteria - const planPathMatch = task.description.match(/\.workflow\/\.team-plan\/[^\s]+\/plan\.json/) + const planPathMatch = task.description.match(/\.workflow\/\.team\/[^\s]+\/plan\/plan\.json/) let plan = null if (planPathMatch) { try { plan = JSON.parse(Read(planPathMatch[0])) } catch {} @@ -112,18 +112,18 @@ if (reviewMode === 'spec') { adrs: [], epicsIndex: null, epics: [], discussions: [] } - try { documents.config = JSON.parse(Read(`${sessionFolder}/spec-config.json`)) } catch {} - try { documents.discoveryContext = JSON.parse(Read(`${sessionFolder}/discovery-context.json`)) } catch {} - try { documents.productBrief = Read(`${sessionFolder}/product-brief.md`) } catch {} - try { documents.requirementsIndex = Read(`${sessionFolder}/requirements/_index.md`) } catch {} - try { documents.architectureIndex = Read(`${sessionFolder}/architecture/_index.md`) } catch {} - try { documents.epicsIndex = Read(`${sessionFolder}/epics/_index.md`) } catch {} + try { documents.config = JSON.parse(Read(`${sessionFolder}/spec/spec-config.json`)) } catch {} + try { documents.discoveryContext = JSON.parse(Read(`${sessionFolder}/spec/discovery-context.json`)) } catch {} + try { documents.productBrief = Read(`${sessionFolder}/spec/product-brief.md`) } catch {} + try { documents.requirementsIndex = Read(`${sessionFolder}/spec/requirements/_index.md`) } catch {} + try { documents.architectureIndex = Read(`${sessionFolder}/spec/architecture/_index.md`) } catch {} + try { documents.epicsIndex = Read(`${sessionFolder}/spec/epics/_index.md`) } catch {} // Load individual documents - Glob({ pattern: `${sessionFolder}/requirements/REQ-*.md` }).forEach(f => { try { documents.requirements.push(Read(f)) } catch {} }) - Glob({ pattern: `${sessionFolder}/requirements/NFR-*.md` }).forEach(f => { try { documents.requirements.push(Read(f)) } catch {} }) - Glob({ pattern: `${sessionFolder}/architecture/ADR-*.md` }).forEach(f => { try { documents.adrs.push(Read(f)) } catch {} }) - Glob({ pattern: `${sessionFolder}/epics/EPIC-*.md` }).forEach(f => { try { documents.epics.push(Read(f)) } catch {} }) + Glob({ pattern: `${sessionFolder}/spec/requirements/REQ-*.md` }).forEach(f => { try { documents.requirements.push(Read(f)) } catch {} }) + Glob({ pattern: `${sessionFolder}/spec/requirements/NFR-*.md` }).forEach(f => { try { documents.requirements.push(Read(f)) } catch {} }) + Glob({ pattern: `${sessionFolder}/spec/architecture/ADR-*.md` }).forEach(f => { try { documents.adrs.push(Read(f)) } catch {} }) + Glob({ pattern: `${sessionFolder}/spec/epics/EPIC-*.md` }).forEach(f => { try { documents.epics.push(Read(f)) } catch {} }) Glob({ pattern: `${sessionFolder}/discussions/discuss-*.md` }).forEach(f => { try { documents.discussions.push(Read(f)) } catch {} }) const docInventory = { @@ -473,7 +473,7 @@ ${allSpecIssues.map(i => '- ' + i).join('\n') || 'None'} ## Document Inventory ${Object.entries(docInventory).map(([k, v]) => '- ' + k + ': ' + (v === true ? '✓' : v === false ? '✗' : v)).join('\n')} ` - Write(`${sessionFolder}/readiness-report.md`, readinessReport) + Write(`${sessionFolder}/spec/readiness-report.md`, readinessReport) // Generate spec-summary.md const specSummary = `--- @@ -503,7 +503,7 @@ ${qualityGate === 'PASS' ? '- Ready for handoff to execution workflows' : qualityGate === 'REVIEW' ? '- Address review items, then proceed to execution' : '- Fix critical issues before proceeding'} ` - Write(`${sessionFolder}/spec-summary.md`, specSummary) + Write(`${sessionFolder}/spec/spec-summary.md`, specSummary) } ``` @@ -590,8 +590,8 @@ ${allSpecIssues.map(i => '- ' + i).join('\n') || '无问题'} ${Object.entries(docInventory).map(([k, v]) => '- ' + k + ': ' + (typeof v === 'boolean' ? (v ? '✓' : '✗') : v)).join('\n')} ### 输出位置 -- 就绪报告: ${sessionFolder}/readiness-report.md -- 执行摘要: ${sessionFolder}/spec-summary.md +- 就绪报告: ${sessionFolder}/spec/readiness-report.md +- 执行摘要: ${sessionFolder}/spec/spec-summary.md ${qualityGate === 'PASS' ? '质量达标,可进入最终讨论轮次 DISCUSS-006。' : qualityGate === 'REVIEW' ? '质量基本达标但有改进空间,建议在讨论中审查。' : diff --git a/.claude/skills/team-lifecycle/roles/writer.md b/.claude/skills/team-lifecycle/roles/writer.md index b6348263..3349aba5 100644 --- a/.claude/skills/team-lifecycle/roles/writer.md +++ b/.claude/skills/team-lifecycle/roles/writer.md @@ -69,7 +69,7 @@ const sessionFolder = sessionMatch ? sessionMatch[1].trim() : '' // Load session config let specConfig = null -try { specConfig = JSON.parse(Read(`${sessionFolder}/spec-config.json`)) } catch {} +try { specConfig = JSON.parse(Read(`${sessionFolder}/spec/spec-config.json`)) } catch {} // Determine document type from task subject const docType = task.subject.includes('Product Brief') ? 'product-brief' @@ -91,16 +91,16 @@ try { discussionFeedback = Read(`${sessionFolder}/${discussionFiles[docType]}`) // Load prior documents progressively const priorDocs = {} if (docType !== 'product-brief') { - try { priorDocs.discoveryContext = Read(`${sessionFolder}/discovery-context.json`) } catch {} + try { priorDocs.discoveryContext = Read(`${sessionFolder}/spec/discovery-context.json`) } catch {} } if (['requirements', 'architecture', 'epics'].includes(docType)) { - try { priorDocs.productBrief = Read(`${sessionFolder}/product-brief.md`) } catch {} + try { priorDocs.productBrief = Read(`${sessionFolder}/spec/product-brief.md`) } catch {} } if (['architecture', 'epics'].includes(docType)) { - try { priorDocs.requirementsIndex = Read(`${sessionFolder}/requirements/_index.md`) } catch {} + try { priorDocs.requirementsIndex = Read(`${sessionFolder}/spec/requirements/_index.md`) } catch {} } if (docType === 'epics') { - try { priorDocs.architectureIndex = Read(`${sessionFolder}/architecture/_index.md`) } catch {} + try { priorDocs.architectureIndex = Read(`${sessionFolder}/spec/architecture/_index.md`) } catch {} } ``` @@ -246,8 +246,8 @@ dependencies: // 填充 template 中所有 section: Vision, Problem Statement, Target Users, Goals, Scope // 应用 document-standards.md 格式规范 - Write(`${sessionFolder}/product-brief.md`, `${frontmatter}\n\n${filledContent}`) - outputPath = 'product-brief.md' + Write(`${sessionFolder}/spec/product-brief.md`, `${frontmatter}\n\n${filledContent}`) + outputPath = 'spec/product-brief.md' } ``` @@ -299,7 +299,7 @@ CONSTRAINTS: Every requirement must be specific enough to estimate and test. No } // === 生成 requirements/ 目录 === - Bash(`mkdir -p "${sessionFolder}/requirements"`) + Bash(`mkdir -p "${sessionFolder}/spec/requirements"`) const timestamp = new Date().toISOString() @@ -330,7 +330,7 @@ ${req.user_story} ## Acceptance Criteria ${req.acceptance_criteria.map((ac, i) => `${i+1}. ${ac}`).join('\n')} ` - Write(`${sessionFolder}/requirements/REQ-${req.id}-${req.slug}.md`, reqContent) + Write(`${sessionFolder}/spec/requirements/REQ-${req.id}-${req.slug}.md`, reqContent) }) // 写入独立 NFR-*.md 文件 @@ -353,7 +353,7 @@ ${nfr.requirement} ## Metric & Target ${nfr.metric} — Target: ${nfr.target} ` - Write(`${sessionFolder}/requirements/NFR-${nfr.type}-${nfr.id}-${nfr.slug}.md`, nfrContent) + Write(`${sessionFolder}/spec/requirements/NFR-${nfr.type}-${nfr.id}-${nfr.slug}.md`, nfrContent) }) // 写入 _index.md(汇总 + 链接) @@ -390,8 +390,8 @@ ${nfReqs.map(n => `| [NFR-${n.type}-${n.id}](NFR-${n.type}-${n.id}-${n.slug}.md) - **Could**: ${funcReqs.filter(r => r.priority === 'Could').length} - **Won't**: ${funcReqs.filter(r => r.priority === "Won't").length} ` - Write(`${sessionFolder}/requirements/_index.md`, indexContent) - outputPath = 'requirements/_index.md' + Write(`${sessionFolder}/spec/requirements/_index.md`, indexContent) + outputPath = 'spec/requirements/_index.md' } ``` @@ -485,7 +485,7 @@ CONSTRAINTS: Be genuinely critical, not just validating. Focus on actionable imp } // === 生成 architecture/ 目录 === - Bash(`mkdir -p "${sessionFolder}/architecture"`) + Bash(`mkdir -p "${sessionFolder}/spec/architecture"`) const timestamp = new Date().toISOString() const adrs = parseADRs(geminiArchitectureOutput, codexReviewOutput) @@ -518,7 +518,7 @@ ${adr.consequences} ## Review Feedback ${adr.reviewFeedback || 'N/A'} ` - Write(`${sessionFolder}/architecture/ADR-${adr.id}-${adr.slug}.md`, adrContent) + Write(`${sessionFolder}/spec/architecture/ADR-${adr.id}-${adr.slug}.md`, adrContent) }) // 写入 _index.md(含 Mermaid 组件图 + ER图 + 链接) @@ -535,8 +535,8 @@ dependencies: ---` // 包含: system overview, component diagram (Mermaid), tech stack table, // ADR links table, data model (Mermaid erDiagram), API design, security controls - Write(`${sessionFolder}/architecture/_index.md`, archIndexContent) - outputPath = 'architecture/_index.md' + Write(`${sessionFolder}/spec/architecture/_index.md`, archIndexContent) + outputPath = 'spec/architecture/_index.md' } ``` @@ -596,7 +596,7 @@ CONSTRAINTS: Every Must-have requirement must appear in at least one Story. Stor } // === 生成 epics/ 目录 === - Bash(`mkdir -p "${sessionFolder}/epics"`) + Bash(`mkdir -p "${sessionFolder}/spec/epics"`) const timestamp = new Date().toISOString() const epicsList = parseEpics(cliOutput) @@ -643,7 +643,7 @@ ${epic.reqs.map(r => `- [${r}](../requirements/${r}.md)`).join('\n')} ## Architecture ${epic.adrs.map(a => `- [${a}](../architecture/${a}.md)`).join('\n')} ` - Write(`${sessionFolder}/epics/EPIC-${epic.id}-${epic.slug}.md`, epicContent) + Write(`${sessionFolder}/spec/epics/EPIC-${epic.id}-${epic.slug}.md`, epicContent) }) // 写入 _index.md(含 Mermaid 依赖图 + MVP + 链接) @@ -660,8 +660,8 @@ dependencies: ---` // 包含: Epic overview table (with links), dependency Mermaid diagram, // execution order, MVP scope, traceability matrix - Write(`${sessionFolder}/epics/_index.md`, epicsIndexContent) - outputPath = 'epics/_index.md' + Write(`${sessionFolder}/spec/epics/_index.md`, epicsIndexContent) + outputPath = 'spec/epics/_index.md' } ``` diff --git a/.claude/skills/team-lifecycle/specs/team-config.json b/.claude/skills/team-lifecycle/specs/team-config.json index 478637ef..0ecf0ec6 100644 --- a/.claude/skills/team-lifecycle/specs/team-config.json +++ b/.claude/skills/team-lifecycle/specs/team-config.json @@ -71,8 +71,10 @@ "collaboration_patterns": ["CP-1", "CP-2", "CP-4", "CP-5", "CP-6", "CP-10"], "session_dirs": { - "spec": ".workflow/.spec-team/{topic-slug}-{YYYY-MM-DD}/", - "impl": ".workflow/.team-plan/{task-slug}-{YYYY-MM-DD}/", + "base": ".workflow/.team/TLS-{slug}-{YYYY-MM-DD}/", + "spec": "spec/", + "discussions": "discussions/", + "plan": "plan/", "messages": ".workflow/.team-msg/{team-name}/" } } diff --git a/.claude/skills/workflow-lite-plan/SKILL.md b/.claude/skills/workflow-lite-plan/SKILL.md index f3484d18..7ba205c6 100644 --- a/.claude/skills/workflow-lite-plan/SKILL.md +++ b/.claude/skills/workflow-lite-plan/SKILL.md @@ -21,7 +21,7 @@ Unified lightweight planning and execution skill. Routes to lite-plan (planning ┌───────────┐ ┌───────────┐ │ lite-plan │ │lite-execute│ │ Phase 1 │ │ Phase 2 │ - │ Plan+Exec │──handoff─→│ Standalone │ + │ Plan+Exec │─direct──→│ Standalone │ └───────────┘ └───────────┘ ``` @@ -44,9 +44,65 @@ function detectMode() { | `workflow:lite-plan` | plan | [phases/01-lite-plan.md](phases/01-lite-plan.md) | Full planning pipeline (explore → plan → confirm → execute) | | `workflow:lite-execute` | execute | [phases/02-lite-execute.md](phases/02-lite-execute.md) | Standalone execution (in-memory / prompt / file) | +## Interactive Preference Collection + +Before dispatching, collect workflow preferences via AskUserQuestion: + +```javascript +if (mode === 'plan') { + const prefResponse = AskUserQuestion({ + questions: [ + { + question: "是否跳过所有确认步骤(自动模式)?", + header: "Auto Mode", + multiSelect: false, + options: [ + { label: "Interactive (Recommended)", description: "交互模式,包含确认步骤" }, + { label: "Auto", description: "跳过所有确认,自动执行" } + ] + }, + { + question: "是否强制执行代码探索阶段?", + header: "Exploration", + multiSelect: false, + options: [ + { label: "Auto-detect (Recommended)", description: "智能判断是否需要探索" }, + { label: "Force explore", description: "强制执行代码探索" } + ] + } + ] + }) + workflowPreferences = { + autoYes: prefResponse.autoMode === 'Auto', + forceExplore: prefResponse.exploration === 'Force explore' + } +} else { + // Execute mode (standalone, not in-memory) + const prefResponse = AskUserQuestion({ + questions: [ + { + question: "是否跳过所有确认步骤(自动模式)?", + header: "Auto Mode", + multiSelect: false, + options: [ + { label: "Interactive (Recommended)", description: "交互模式,包含确认步骤" }, + { label: "Auto", description: "跳过所有确认,自动执行" } + ] + } + ] + }) + workflowPreferences = { + autoYes: prefResponse.autoMode === 'Auto', + forceExplore: false + } +} +``` + +**workflowPreferences** is passed to phase execution as context variable, referenced as `workflowPreferences.autoYes` and `workflowPreferences.forceExplore` within phases. + ## Prompt Enhancement -Before dispatching to the target phase, enhance context: +After collecting preferences, enhance context and dispatch: ```javascript // Step 1: Check for project context files @@ -61,7 +117,7 @@ if (hasProjectGuidelines) { console.log('Project guidelines available: .workflow/project-guidelines.json') } -// Step 3: Dispatch to phase +// Step 3: Dispatch to phase (workflowPreferences available as context) if (mode === 'plan') { // Read phases/01-lite-plan.md and execute } else { @@ -71,20 +127,20 @@ if (mode === 'plan') { ## Execution Flow -### Plan Mode (workflow:lite-plan) +### Plan Mode ``` -1. Parse flags (-y/--yes, -e/--explore) and task description +1. Collect preferences via AskUserQuestion (autoYes, forceExplore) 2. Enhance prompt with project context availability 3. Read phases/01-lite-plan.md 4. Execute lite-plan pipeline (Phase 1-5 within the phase doc) -5. lite-plan Phase 5 internally calls workflow:lite-execute via Skill handoff +5. lite-plan Phase 5 directly reads and executes Phase 2 (lite-execute) with executionContext ``` -### Execute Mode (workflow:lite-execute) +### Execute Mode ``` -1. Parse flags (--in-memory, -y/--yes) and input +1. Collect preferences via AskUserQuestion (autoYes) 2. Enhance prompt with project context availability 3. Read phases/02-lite-execute.md 4. Execute lite-execute pipeline (input detection → execution → review) @@ -92,17 +148,10 @@ if (mode === 'plan') { ## Usage -```bash -# Plan mode -/workflow:lite-plan "实现JWT认证" # Interactive -/workflow:lite-plan --yes "实现JWT认证" # Auto mode -/workflow:lite-plan -y -e "优化数据库查询性能" # Auto + force exploration +Plan mode and execute mode are triggered by skill name routing (see Mode Detection). Workflow preferences (auto mode, force explore) are collected interactively via AskUserQuestion before dispatching to phases. -# Execute mode (standalone) -/workflow:lite-execute "Add unit tests for auth" # Prompt description -/workflow:lite-execute plan.json # File input -/workflow:lite-execute --in-memory # Called by lite-plan internally -``` +**Plan mode**: Task description provided as arguments → interactive preference collection → planning pipeline +**Execute mode**: Task description, file path, or in-memory context → interactive preference collection → execution pipeline ## Phase Reference Documents diff --git a/.claude/skills/workflow-lite-plan/phases/01-lite-plan.md b/.claude/skills/workflow-lite-plan/phases/01-lite-plan.md index 8b90c901..5c3731fe 100644 --- a/.claude/skills/workflow-lite-plan/phases/01-lite-plan.md +++ b/.claude/skills/workflow-lite-plan/phases/01-lite-plan.md @@ -2,8 +2,6 @@ Complete planning pipeline: task analysis, multi-angle exploration, clarification, adaptive planning, confirmation, and execution handoff. -**Source**: Converted from `.claude/commands/workflow/lite-plan.md` - all execution detail preserved verbatim. - --- ## Overview @@ -18,23 +16,13 @@ Intelligent lightweight planning command with dynamic workflow adaptation based - Two-step confirmation: plan display → multi-dimensional input collection - Execution handoff with complete context to lite-execute -## Usage +## Input -```bash -/workflow:lite-plan [FLAGS] - -# Flags --y, --yes Skip all confirmations (auto mode) --e, --explore Force code exploration phase (overrides auto-detection) - -# Arguments - Task description or path to .md file (required) - -# Examples -/workflow:lite-plan "实现JWT认证" # Interactive mode -/workflow:lite-plan --yes "实现JWT认证" # Auto mode (no confirmations) -/workflow:lite-plan -y -e "优化数据库查询性能" # Auto mode + force exploration ``` + Task description or path to .md file (required) +``` + +Workflow preferences (`autoYes`, `forceExplore`) are collected by SKILL.md via AskUserQuestion and passed as `workflowPreferences` context variable. ## Output Artifacts @@ -56,25 +44,19 @@ Intelligent lightweight planning command with dynamic workflow adaptation based ## Auto Mode Defaults -When `--yes` or `-y` flag is used: +When `workflowPreferences.autoYes === true`: - **Clarification Questions**: Skipped (no clarification phase) - **Plan Confirmation**: Auto-selected "Allow" - **Execution Method**: Auto-selected "Auto" - **Code Review**: Auto-selected "Skip" -**Flag Parsing**: -```javascript -const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') -const forceExplore = $ARGUMENTS.includes('--explore') || $ARGUMENTS.includes('-e') -``` - ## Execution Process ``` Phase 1: Task Analysis & Exploration ├─ Parse input (description or .md file) ├─ intelligent complexity assessment (Low/Medium/High) - ├─ Exploration decision (auto-detect or --explore flag) + ├─ Exploration decision (auto-detect or workflowPreferences.forceExplore) ├─ Context protection: If file reading ≥50k chars → force cli-explore-agent └─ Decision: ├─ needsExploration=true → Launch parallel cli-explore-agents (1-4 based on complexity) @@ -101,7 +83,7 @@ Phase 4: Confirmation & Selection Phase 5: Execute ├─ Build executionContext (plan + explorations + clarifications + selections) - └─ Skill(skill="workflow:lite-execute", args="--in-memory") + └─ Direct handoff: Read phases/02-lite-execute.md → Execute with executionContext (Mode 1) ``` ## Implementation @@ -125,7 +107,7 @@ bash(`mkdir -p ${sessionFolder} && test -d ${sessionFolder} && echo "SUCCESS: ${ **Exploration Decision Logic**: ```javascript needsExploration = ( - flags.includes('--explore') || flags.includes('-e') || + workflowPreferences.forceExplore || task.mentions_specific_files || task.requires_codebase_context || task.needs_architecture_understanding || @@ -368,12 +350,11 @@ explorations.forEach(exp => { // - Produce dedupedClarifications with unique intents only const dedupedClarifications = intelligentMerge(allClarifications) -// Parse --yes flag -const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') +const autoYes = workflowPreferences.autoYes if (autoYes) { // Auto mode: Skip clarification phase - console.log(`[--yes] Skipping ${dedupedClarifications.length} clarification questions`) + console.log(`[Auto] Skipping ${dedupedClarifications.length} clarification questions`) console.log(`Proceeding to planning with exploration results...`) // Continue to Phase 3 } else if (dedupedClarifications.length > 0) { @@ -608,14 +589,13 @@ ${taskList.map((t, i) => `${i+1}. ${t.title} (${t.scope || t.files?.[0]?.path || **Step 4.2: Collect Confirmation** ```javascript -// Parse --yes flag -const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') +const autoYes = workflowPreferences.autoYes let userSelection if (autoYes) { // Auto mode: Use defaults - console.log(`[--yes] Auto-confirming plan:`) + console.log(`[Auto] Auto-confirming plan:`) console.log(` - Confirmation: Allow`) console.log(` - Execution: Auto`) console.log(` - Review: Skip`) @@ -723,7 +703,10 @@ executionContext = { **Step 5.2: Handoff** ```javascript -Skill(skill="workflow:lite-execute", args="--in-memory") +// Direct phase handoff: Read and execute Phase 2 (lite-execute) with in-memory context +// No Skill routing needed - executionContext is already set in Step 5.1 +Read("phases/02-lite-execute.md") +// Execute Phase 2 with executionContext (Mode 1: In-Memory Plan) ``` ## Session Folder Structure diff --git a/.claude/skills/workflow-lite-plan/phases/02-lite-execute.md b/.claude/skills/workflow-lite-plan/phases/02-lite-execute.md index 9b7447da..647d4444 100644 --- a/.claude/skills/workflow-lite-plan/phases/02-lite-execute.md +++ b/.claude/skills/workflow-lite-plan/phases/02-lite-execute.md @@ -2,8 +2,6 @@ Complete execution engine: multi-mode input, task grouping, batch execution, code review, and development index update. -**Source**: Converted from `.claude/commands/workflow/lite-execute.md` - all execution detail preserved verbatim. - --- ## Overview @@ -20,22 +18,19 @@ Flexible task execution command supporting three input modes: in-memory plan (fr ## Usage -### Command Syntax -```bash -/workflow:lite-execute [FLAGS] - -# Flags ---in-memory Use plan from memory (called by lite-plan) - -# Arguments +### Input +``` Task description string, or path to file (required) ``` +Mode 1 (In-Memory) is triggered by lite-plan direct handoff when `executionContext` is available. +Workflow preferences (`autoYes`) are passed from SKILL.md via `workflowPreferences` context variable. + ## Input Modes ### Mode 1: In-Memory Plan -**Trigger**: Called by lite-plan after Phase 4 approval with `--in-memory` flag +**Trigger**: Called by lite-plan direct handoff after Phase 4 approval (executionContext available) **Input Source**: `executionContext` global variable set by lite-plan @@ -61,14 +56,13 @@ Flexible task execution command supporting three input modes: in-memory plan (fr **User Interaction**: ```javascript -// Parse --yes flag -const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') +const autoYes = workflowPreferences.autoYes let userSelection if (autoYes) { // Auto mode: Use defaults - console.log(`[--yes] Auto-confirming execution:`) + console.log(`[Auto] Auto-confirming execution:`) console.log(` - Execution method: Auto`) console.log(` - Code review: Skip`) @@ -180,7 +174,7 @@ function getTasks(planObject) { ``` Input Parsing: └─ Decision (mode detection): - ├─ --in-memory flag → Mode 1: Load executionContext → Skip user selection + ├─ executionContext exists → Mode 1: Load executionContext → Skip user selection ├─ Ends with .md/.json/.txt → Mode 3: Read file → Detect format │ ├─ Valid plan.json → Use planObject → User selects method + review │ └─ Not plan.json → Treat as prompt → User selects method + review @@ -672,7 +666,7 @@ console.log(`✓ Development index: [${category}] ${entry.title}`) | Error | Cause | Resolution | |-------|-------|------------| -| Missing executionContext | --in-memory without context | Error: "No execution context found. Only available when called by lite-plan." | +| Missing executionContext | In-memory mode without context | Error: "No execution context found. Only available when called by lite-plan." | | File not found | File path doesn't exist | Error: "File not found: {path}. Check file path." | | Empty file | File exists but no content | Error: "File is empty: {path}. Provide task description." | | Invalid Enhanced Task JSON | JSON missing required fields | Warning: "Missing required fields. Treating as plain text." | diff --git a/.claude/skills/workflow-multi-cli-plan/SKILL.md b/.claude/skills/workflow-multi-cli-plan/SKILL.md index 23c32677..73a85a14 100644 --- a/.claude/skills/workflow-multi-cli-plan/SKILL.md +++ b/.claude/skills/workflow-multi-cli-plan/SKILL.md @@ -44,9 +44,54 @@ function detectMode() { | `workflow:multi-cli-plan` | plan | [phases/01-multi-cli-plan.md](phases/01-multi-cli-plan.md) | Multi-CLI collaborative planning (ACE context → discussion → plan → execute) | | `workflow:lite-execute` | execute | [phases/02-lite-execute.md](phases/02-lite-execute.md) | Standalone execution (in-memory / prompt / file) | +## Interactive Preference Collection + +Before dispatching, collect workflow preferences via AskUserQuestion: + +```javascript +if (mode === 'plan') { + const prefResponse = AskUserQuestion({ + questions: [ + { + question: "是否跳过所有确认步骤(自动模式)?", + header: "Auto Mode", + multiSelect: false, + options: [ + { label: "Interactive (Recommended)", description: "交互模式,包含确认步骤" }, + { label: "Auto", description: "跳过所有确认,自动执行" } + ] + } + ] + }) + workflowPreferences = { + autoYes: prefResponse.autoMode === 'Auto' + } +} else { + // Execute mode + const prefResponse = AskUserQuestion({ + questions: [ + { + question: "是否跳过所有确认步骤(自动模式)?", + header: "Auto Mode", + multiSelect: false, + options: [ + { label: "Interactive (Recommended)", description: "交互模式,包含确认步骤" }, + { label: "Auto", description: "跳过所有确认,自动执行" } + ] + } + ] + }) + workflowPreferences = { + autoYes: prefResponse.autoMode === 'Auto' + } +} +``` + +**workflowPreferences** is passed to phase execution as context variable, referenced as `workflowPreferences.autoYes` within phases. + ## Prompt Enhancement -Before dispatching to the target phase, enhance context: +After collecting preferences, enhance context and dispatch: ```javascript // Step 1: Check for project context files @@ -61,7 +106,7 @@ if (hasProjectGuidelines) { console.log('Project guidelines available: .workflow/project-guidelines.json') } -// Step 3: Dispatch to phase +// Step 3: Dispatch to phase (workflowPreferences available as context) if (mode === 'plan') { // Read phases/01-multi-cli-plan.md and execute } else { @@ -74,17 +119,17 @@ if (mode === 'plan') { ### Plan Mode (workflow:multi-cli-plan) ``` -1. Parse flags (-y/--yes, --max-rounds, --tools, --mode) and task description +1. Collect preferences via AskUserQuestion (autoYes) 2. Enhance prompt with project context availability 3. Read phases/01-multi-cli-plan.md 4. Execute multi-cli-plan pipeline (Phase 1-5 within the phase doc) -5. Phase 5 internally calls workflow:lite-execute via Skill handoff +5. Phase 5 directly reads and executes Phase 2 (lite-execute) with executionContext ``` ### Execute Mode (workflow:lite-execute) ``` -1. Parse flags (--in-memory, -y/--yes) and input +1. Collect preferences via AskUserQuestion (autoYes) 2. Enhance prompt with project context availability 3. Read phases/02-lite-execute.md 4. Execute lite-execute pipeline (input detection → execution → review) @@ -92,17 +137,10 @@ if (mode === 'plan') { ## Usage -```bash -# Multi-CLI plan mode -/workflow:multi-cli-plan "Implement user authentication" -/workflow:multi-cli-plan --yes "Add dark mode support" -/workflow:multi-cli-plan "Refactor payment module" --max-rounds=3 --tools=gemini,codex +Plan mode and execute mode are triggered by skill name routing (see Mode Detection). Workflow preferences (auto mode) are collected interactively via AskUserQuestion before dispatching to phases. -# Execute mode (standalone) -/workflow:lite-execute "Add unit tests for auth" # Prompt description -/workflow:lite-execute plan.json # File input -/workflow:lite-execute --in-memory # Called by multi-cli-plan internally -``` +**Plan mode**: Task description provided as arguments → interactive preference collection → multi-CLI planning pipeline +**Execute mode**: Task description, file path, or in-memory context → interactive preference collection → execution pipeline ## Phase Reference Documents diff --git a/.claude/skills/workflow-multi-cli-plan/phases/01-multi-cli-plan.md b/.claude/skills/workflow-multi-cli-plan/phases/01-multi-cli-plan.md index 06a1a8ee..3781a1f6 100644 --- a/.claude/skills/workflow-multi-cli-plan/phases/01-multi-cli-plan.md +++ b/.claude/skills/workflow-multi-cli-plan/phases/01-multi-cli-plan.md @@ -2,11 +2,9 @@ Complete multi-CLI collaborative planning pipeline with ACE context gathering and iterative cross-verification. This phase document preserves the full content of the original `workflow:multi-cli-plan` command. -> **Source**: Converted from `.claude/commands/workflow/multi-cli-plan.md`. Frontmatter moved to SKILL.md. - ## Auto Mode -When `--yes` or `-y`: Auto-approve plan, use recommended solution and execution method (Agent, Skip review). +When `workflowPreferences.autoYes` is true: Auto-approve plan, use recommended solution and execution method (Agent, Skip review). # Multi-CLI Collaborative Planning Command @@ -448,8 +446,9 @@ executionContext = { **Step 4: Hand off to Execution**: ```javascript -// Execute to lite-execute with in-memory context -Skill(skill="workflow:lite-execute", args="--in-memory") +// Direct phase handoff: Read and execute Phase 2 (lite-execute) with in-memory context +Read("phases/02-lite-execute.md") +// Execute Phase 2 with executionContext (Mode 1: In-Memory Plan) ``` ## Output File Structure diff --git a/.claude/skills/workflow-multi-cli-plan/phases/02-lite-execute.md b/.claude/skills/workflow-multi-cli-plan/phases/02-lite-execute.md index 35202707..cd998b3d 100644 --- a/.claude/skills/workflow-multi-cli-plan/phases/02-lite-execute.md +++ b/.claude/skills/workflow-multi-cli-plan/phases/02-lite-execute.md @@ -1,10 +1,11 @@ # Phase 2: Lite Execute -Complete execution engine supporting multiple input modes: in-memory plan, prompt description, or file content. This phase document preserves the full content of the original `workflow:lite-execute` command. +Complete execution engine supporting multiple input modes: in-memory plan, prompt description, or file content. -> **Source**: Converted from `.claude/commands/workflow/lite-execute.md`. Frontmatter moved to SKILL.md. +## Objective -# Workflow Lite-Execute Command (/workflow:lite-execute) +- Execute implementation tasks from in-memory plan, prompt description, or file content +- Support batch execution with grouped tasks and code review ## Overview @@ -61,14 +62,14 @@ Flexible task execution command supporting three input modes: in-memory plan (fr **User Interaction**: ```javascript -// Parse --yes flag -const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') +// Reference workflowPreferences (set by SKILL.md via AskUserQuestion) +const autoYes = workflowPreferences.autoYes let userSelection if (autoYes) { // Auto mode: Use defaults - console.log(`[--yes] Auto-confirming execution:`) + console.log(`[Auto] Auto-confirming execution:`) console.log(` - Execution method: Auto`) console.log(` - Code review: Skip`) @@ -753,7 +754,7 @@ Appended to `previousExecutionResults` array for context continuity in multi-exe ## Post-Completion Expansion -完成后询问用户是否扩展为issue(test/enhance/refactor/doc),选中项调用 `/issue:new "{summary} - {dimension}"` +完成后询问用户是否扩展为issue(test/enhance/refactor/doc),选中项调用 `Skill(skill="issue:new", args="{summary} - {dimension}")` **Fixed ID Pattern**: `${sessionId}-${groupId}` enables predictable lookup without auto-generated timestamps. diff --git a/.claude/skills/workflow-plan/SKILL.md b/.claude/skills/workflow-plan/SKILL.md index 82d5ed8c..f1b294ba 100644 --- a/.claude/skills/workflow-plan/SKILL.md +++ b/.claude/skills/workflow-plan/SKILL.md @@ -47,9 +47,49 @@ Unified planning skill combining 4-phase planning workflow, plan quality verific 5. **Auto-Continue**: After each phase completes, automatically execute next pending phase 6. **Accumulated State**: planning-notes.md carries context across phases for N+1 decisions -## Auto Mode +## Interactive Preference Collection -When `--yes` or `-y`: Auto-continue all phases (skip confirmations), use recommended conflict resolutions, use safe defaults for replan. +Before dispatching to phase execution, collect workflow preferences via AskUserQuestion: + +```javascript +const prefResponse = AskUserQuestion({ + questions: [ + { + question: "是否跳过所有确认步骤(自动模式)?", + header: "Auto Mode", + multiSelect: false, + options: [ + { label: "Interactive (Recommended)", description: "交互模式,包含确认步骤" }, + { label: "Auto", description: "跳过所有确认,自动执行" } + ] + } + ] +}) + +workflowPreferences = { + autoYes: prefResponse.autoMode === 'Auto' +} + +// For replan mode, also collect interactive preference +if (mode === 'replan') { + const replanPref = AskUserQuestion({ + questions: [ + { + question: "是否使用交互式澄清模式?", + header: "Replan Mode", + multiSelect: false, + options: [ + { label: "Standard (Recommended)", description: "使用安全默认值" }, + { label: "Interactive", description: "通过提问交互式澄清修改范围" } + ] + } + ] + }) + workflowPreferences.interactive = replanPref.replanMode === 'Interactive' +} +``` + +**workflowPreferences** is passed to phase execution as context variable, referenced as `workflowPreferences.autoYes`, `workflowPreferences.interactive` within phases. ## Mode Detection @@ -326,18 +366,18 @@ See phase files for detailed update code. - **If user selects Verify**: Read phases/05-plan-verify.md, execute Phase 5 in-process - **If user selects Execute**: Skill(skill="workflow-execute") - **If user selects Review**: Route to /workflow:status -- **Auto mode (--yes)**: Auto-select "Verify Plan Quality", then auto-continue to execute if PROCEED +- **Auto mode (workflowPreferences.autoYes)**: Auto-select "Verify Plan Quality", then auto-continue to execute if PROCEED - Update TodoWrite after each phase - After each phase, automatically continue to next phase based on TodoList status ### Verify Mode -- Detect/validate session (from --session flag or auto-detect) +- Detect/validate session (auto-detect from active sessions) - Initialize TodoWrite with single verification task - Execute Phase 5 verification agent - Present quality gate result and next step options ### Replan Mode -- Parse flags (--session, --interactive, task-id) +- Parse task ID from $ARGUMENTS (IMPL-N format, if present) - Detect operation mode (task vs session) - Initialize TodoWrite with replan-specific tasks - Execute Phase 6 through all sub-phases (clarification → impact → backup → apply → verify) diff --git a/.claude/skills/workflow-plan/phases/02-context-gathering.md b/.claude/skills/workflow-plan/phases/02-context-gathering.md index 47d7e8a3..1653ea7f 100644 --- a/.claude/skills/workflow-plan/phases/02-context-gathering.md +++ b/.claude/skills/workflow-plan/phases/02-context-gathering.md @@ -1,6 +1,6 @@ # Phase 2: Context Gathering -Gather project context and analyze codebase via context-gather tool. +Gather project context and analyze codebase via context-search-agent with parallel exploration. ## Objective @@ -9,42 +9,344 @@ Gather project context and analyze codebase via context-gather tool. - Detect conflict risk level for Phase 3 decision - Update planning-notes.md with findings +## Core Philosophy + +- **Agent Delegation**: Delegate all discovery to `context-search-agent` for autonomous execution +- **Detection-First**: Check for existing context-package before executing +- **Plan Mode**: Full comprehensive analysis (vs lightweight brainstorm mode) +- **Standardized Output**: Generate `.workflow/active/{session}/.process/context-package.json` + ## Execution -### Step 2.1: Execute Context Gathering +### Step 2.1: Context-Package Detection + +**Execute First** - Check if valid package already exists: ```javascript -Skill(skill="workflow:tools:context-gather", args="--session [sessionId] \"[structured-task-description]\"") +const contextPackagePath = `.workflow/active/${sessionId}/.process/context-package.json`; + +if (file_exists(contextPackagePath)) { + const existing = Read(contextPackagePath); + + // Validate package belongs to current session + if (existing?.metadata?.session_id === sessionId) { + console.log("Valid context-package found for session:", sessionId); + console.log("Stats:", existing.statistics); + console.log("Conflict Risk:", existing.conflict_detection.risk_level); + // Skip execution, store variables and proceed to Step 2.5 + contextPath = contextPackagePath; + conflictRisk = existing.conflict_detection.risk_level; + return; // Early exit - skip Steps 2.2-2.4 + } +} ``` -**Use Same Structured Description**: Pass the same structured format from Phase 1 +### Step 2.2: Complexity Assessment & Parallel Explore -**Input**: `sessionId` from Phase 1 +**Only execute if Step 2.1 finds no valid package** -**Parse Output**: -- Extract: context-package.json path (store as `contextPath`) -- Typical pattern: `.workflow/active/[sessionId]/.process/context-package.json` +```javascript +// 2.2.1 Complexity Assessment +function analyzeTaskComplexity(taskDescription) { + const text = taskDescription.toLowerCase(); + if (/architect|refactor|restructure|modular|cross-module/.test(text)) return 'High'; + if (/multiple|several|integrate|migrate|extend/.test(text)) return 'Medium'; + return 'Low'; +} -**Validation**: -- Context package path extracted -- File exists and is valid JSON -- `prioritized_context` field exists +const ANGLE_PRESETS = { + architecture: ['architecture', 'dependencies', 'modularity', 'integration-points'], + security: ['security', 'auth-patterns', 'dataflow', 'validation'], + performance: ['performance', 'bottlenecks', 'caching', 'data-access'], + bugfix: ['error-handling', 'dataflow', 'state-management', 'edge-cases'], + feature: ['patterns', 'integration-points', 'testing', 'dependencies'], + refactor: ['architecture', 'patterns', 'dependencies', 'testing'] +}; -### TodoWrite Update (Phase 2 Skill executed - tasks attached) +function selectAngles(taskDescription, complexity) { + const text = taskDescription.toLowerCase(); + let preset = 'feature'; + if (/refactor|architect|restructure/.test(text)) preset = 'architecture'; + else if (/security|auth|permission/.test(text)) preset = 'security'; + else if (/performance|slow|optimi/.test(text)) preset = 'performance'; + else if (/fix|bug|error|issue/.test(text)) preset = 'bugfix'; + + const count = complexity === 'High' ? 4 : (complexity === 'Medium' ? 3 : 1); + return ANGLE_PRESETS[preset].slice(0, count); +} + +const complexity = analyzeTaskComplexity(task_description); +const selectedAngles = selectAngles(task_description, complexity); +const sessionFolder = `.workflow/active/${sessionId}/.process`; + +// 2.2.2 Launch Parallel Explore Agents +const explorationTasks = selectedAngles.map((angle, index) => + Task( + subagent_type="cli-explore-agent", + run_in_background=false, + description=`Explore: ${angle}`, + prompt=` +## Task Objective +Execute **${angle}** exploration for task planning context. Analyze codebase from this specific angle to discover relevant structure, patterns, and constraints. + +## Assigned Context +- **Exploration Angle**: ${angle} +- **Task Description**: ${task_description} +- **Session ID**: ${sessionId} +- **Exploration Index**: ${index + 1} of ${selectedAngles.length} +- **Output File**: ${sessionFolder}/exploration-${angle}.json + +## MANDATORY FIRST STEPS (Execute by Agent) +1. Run: ccw tool exec get_modules_by_depth '{}' (project structure) +2. Run: rg -l "{keyword_from_task}" --type ts (locate relevant files) +3. Execute: cat ~/.ccw/workflows/cli-templates/schemas/explore-json-schema.json (get output schema reference) + +## Exploration Strategy (${angle} focus) + +**Step 1: Structural Scan** (Bash) +- get_modules_by_depth.sh -> identify modules related to ${angle} +- find/rg -> locate files relevant to ${angle} aspect +- Analyze imports/dependencies from ${angle} perspective + +**Step 2: Semantic Analysis** (Gemini CLI) +- How does existing code handle ${angle} concerns? +- What patterns are used for ${angle}? +- Where would new code integrate from ${angle} viewpoint? + +**Step 3: Write Output** +- Consolidate ${angle} findings into JSON +- Identify ${angle}-specific clarification needs + +## Expected Output + +**File**: ${sessionFolder}/exploration-${angle}.json + +**Schema Reference**: Schema obtained in MANDATORY FIRST STEPS step 3, follow schema exactly + +**Required Fields** (all ${angle} focused): +- project_structure: Modules/architecture relevant to ${angle} +- relevant_files: Files affected from ${angle} perspective + **MANDATORY**: Every file MUST use structured object format with ALL required fields: + [{path: "src/file.ts", relevance: 0.85, rationale: "Contains AuthService.login()", role: "modify_target", discovery_source: "bash-scan", key_symbols: ["AuthService", "login"]}] + - **rationale** (required): Specific selection basis tied to ${angle} topic (>10 chars, not generic) + - **role** (required): modify_target|dependency|pattern_reference|test_target|type_definition|integration_point|config|context_only + - **discovery_source** (recommended): bash-scan|cli-analysis|ace-search|dependency-trace|manual + - **key_symbols** (recommended): Key functions/classes/types in the file relevant to the task + - Scores: 0.7+ high priority, 0.5-0.7 medium, <0.5 low +- patterns: ${angle}-related patterns to follow +- dependencies: Dependencies relevant to ${angle} +- integration_points: Where to integrate from ${angle} viewpoint (include file:line locations) +- constraints: ${angle}-specific limitations/conventions +- clarification_needs: ${angle}-related ambiguities (options array + recommended index) +- _metadata.exploration_angle: "${angle}" + +## Success Criteria +- [ ] Schema obtained via cat explore-json-schema.json +- [ ] get_modules_by_depth.sh executed +- [ ] At least 3 relevant files identified with ${angle} rationale +- [ ] Patterns are actionable (code examples, not generic advice) +- [ ] Integration points include file:line locations +- [ ] Constraints are project-specific to ${angle} +- [ ] JSON output follows schema exactly +- [ ] clarification_needs includes options + recommended + +## Output +Write: ${sessionFolder}/exploration-${angle}.json +Return: 2-3 sentence summary of ${angle} findings +` + ) +); + +// 2.2.3 Generate Manifest after all complete +const explorationFiles = bash(`find ${sessionFolder} -name "exploration-*.json" -type f`).split('\n').filter(f => f.trim()); +const explorationManifest = { + session_id: sessionId, + task_description, + timestamp: new Date().toISOString(), + complexity, + exploration_count: selectedAngles.length, + angles_explored: selectedAngles, + explorations: explorationFiles.map(file => { + const data = JSON.parse(Read(file)); + return { angle: data._metadata.exploration_angle, file: file.split('/').pop(), path: file, index: data._metadata.exploration_index }; + }) +}; +Write(`${sessionFolder}/explorations-manifest.json`, JSON.stringify(explorationManifest, null, 2)); +``` + +### Step 2.3: Invoke Context-Search Agent + +**Only execute after Step 2.2 completes** + +```javascript +// Load user intent from planning-notes.md (from Phase 1) +const planningNotesPath = `.workflow/active/${sessionId}/planning-notes.md`; +let userIntent = { goal: task_description, key_constraints: "None specified" }; + +if (file_exists(planningNotesPath)) { + const notesContent = Read(planningNotesPath); + const goalMatch = notesContent.match(/\*\*GOAL\*\*:\s*(.+)/); + const constraintsMatch = notesContent.match(/\*\*KEY_CONSTRAINTS\*\*:\s*(.+)/); + if (goalMatch) userIntent.goal = goalMatch[1].trim(); + if (constraintsMatch) userIntent.key_constraints = constraintsMatch[1].trim(); +} + +Task( + subagent_type="context-search-agent", + run_in_background=false, + description="Gather comprehensive context for plan", + prompt=` +## Execution Mode +**PLAN MODE** (Comprehensive) - Full Phase 1-3 execution with priority sorting + +## Session Information +- **Session ID**: ${sessionId} +- **Task Description**: ${task_description} +- **Output Path**: .workflow/${sessionId}/.process/context-package.json + +## User Intent (from Phase 1 - Planning Notes) +**GOAL**: ${userIntent.goal} +**KEY_CONSTRAINTS**: ${userIntent.key_constraints} + +This is the PRIMARY context source - all subsequent analysis must align with user intent. + +## Exploration Input (from Step 2.2) +- **Manifest**: ${sessionFolder}/explorations-manifest.json +- **Exploration Count**: ${explorationManifest.exploration_count} +- **Angles**: ${explorationManifest.angles_explored.join(', ')} +- **Complexity**: ${complexity} + +## Mission +Execute complete context-search-agent workflow for implementation planning: + +### Phase 1: Initialization & Pre-Analysis +1. **Project State Loading**: + - Read and parse .workflow/project-tech.json. Use its overview section as the foundational project_context. + - Read and parse .workflow/project-guidelines.json. Load conventions, constraints, and learnings into a project_guidelines section. + - If files don't exist, proceed with fresh analysis. +2. **Detection**: Check for existing context-package (early exit if valid) +3. **Foundation**: Initialize CodexLens, get project structure, load docs +4. **Analysis**: Extract keywords, determine scope, classify complexity + +### Phase 2: Multi-Source Context Discovery +Execute all discovery tracks (WITH USER INTENT INTEGRATION): +- **Track -1**: User Intent & Priority Foundation (EXECUTE FIRST) + - Load user intent (GOAL, KEY_CONSTRAINTS) from session input + - Map user requirements to codebase entities (files, modules, patterns) + - Establish baseline priority scores based on user goal alignment + - Output: user_intent_mapping.json with preliminary priority scores + +- **Track 0**: Exploration Synthesis (load explorations-manifest.json, prioritize critical_files, deduplicate patterns/integration_points) +- **Track 1**: Historical archive analysis (query manifest.json for lessons learned) +- **Track 2**: Reference documentation (CLAUDE.md, architecture docs) +- **Track 3**: Web examples (use Exa MCP for unfamiliar tech/APIs) +- **Track 4**: Codebase analysis (5-layer discovery: files, content, patterns, deps, config/tests) + +### Phase 3: Synthesis, Assessment & Packaging +1. Apply relevance scoring and build dependency graph +2. **Synthesize 5-source data**: Merge findings from all sources + - Priority order: User Intent > Archive > Docs > Exploration > Code > Web + - **Prioritize the context from project-tech.json** for architecture and tech stack +3. **Context Priority Sorting**: + a. Combine scores from Track -1 (user intent alignment) + relevance scores + exploration critical_files + b. Classify files into priority tiers: + - **Critical** (score >= 0.85): Directly mentioned in user goal OR exploration critical_files + - **High** (0.70-0.84): Key dependencies, patterns required for goal + - **Medium** (0.50-0.69): Supporting files, indirect dependencies + - **Low** (< 0.50): Contextual awareness only + c. Generate dependency_order: Based on dependency graph + user goal sequence + d. Document sorting_rationale: Explain prioritization logic +4. **Populate project_context**: Directly use the overview from project-tech.json +5. **Populate project_guidelines**: Load from project-guidelines.json +6. Integrate brainstorm artifacts (if .brainstorming/ exists, read content) +7. Perform conflict detection with risk assessment +8. **Inject historical conflicts** from archive analysis into conflict_detection +9. **Generate prioritized_context section**: + { + "prioritized_context": { + "user_intent": { "goal": "...", "scope": "...", "key_constraints": ["..."] }, + "priority_tiers": { + "critical": [{ "path": "...", "relevance": 0.95, "rationale": "..." }], + "high": [...], "medium": [...], "low": [...] + }, + "dependency_order": ["module1", "module2", "module3"], + "sorting_rationale": "Based on user goal alignment, exploration critical files, and dependency graph" + } + } +10. Generate and validate context-package.json with prioritized_context field + +## Output Requirements +Complete context-package.json with: +- **metadata**: task_description, keywords, complexity, tech_stack, session_id +- **project_context**: description, technology_stack, architecture, key_components (from project-tech.json) +- **project_guidelines**: {conventions, constraints, quality_rules, learnings} (from project-guidelines.json) +- **assets**: {documentation[], source_code[], config[], tests[]} with relevance scores +- **dependencies**: {internal[], external[]} with dependency graph +- **brainstorm_artifacts**: {guidance_specification, role_analyses[], synthesis_output} with content +- **conflict_detection**: {risk_level, risk_factors, affected_modules[], mitigation_strategy, historical_conflicts[]} +- **exploration_results**: {manifest_path, exploration_count, angles, explorations[], aggregated_insights} +- **prioritized_context**: {user_intent, priority_tiers{critical, high, medium, low}, dependency_order[], sorting_rationale} + +## Quality Validation +Before completion verify: +- [ ] Valid JSON format with all required fields +- [ ] File relevance accuracy >80% +- [ ] Dependency graph complete (max 2 transitive levels) +- [ ] Conflict risk level calculated correctly +- [ ] No sensitive data exposed +- [ ] Total files <= 50 (prioritize high-relevance) + +## Planning Notes Record (REQUIRED) +After completing context-package.json, append to planning-notes.md: + +**File**: .workflow/active/${sessionId}/planning-notes.md +**Location**: Under "## Context Findings (Phase 2)" section +**Format**: +### [Context-Search Agent] YYYY-MM-DD +- **Note**: [Brief summary of key findings] + +Execute autonomously following agent documentation. +Report completion with statistics. +` +) +``` + +### Step 2.4: Output Verification + +After agent completes, verify output: + +```javascript +// Verify file was created +const outputPath = `.workflow/active/${sessionId}/.process/context-package.json`; +if (!file_exists(outputPath)) { + throw new Error("Agent failed to generate context-package.json"); +} + +// Store variables for subsequent phases +contextPath = outputPath; + +// Verify exploration_results included +const pkg = JSON.parse(Read(outputPath)); +if (pkg.exploration_results?.exploration_count > 0) { + console.log(`Exploration results aggregated: ${pkg.exploration_results.exploration_count} angles`); +} + +conflictRisk = pkg.conflict_detection?.risk_level || 'low'; +``` + +### TodoWrite Update (Phase 2 in progress - tasks attached) ```json [ {"content": "Phase 1: Session Discovery", "status": "completed", "activeForm": "Executing session discovery"}, {"content": "Phase 2: Context Gathering", "status": "in_progress", "activeForm": "Executing context gathering"}, - {"content": " → Analyze codebase structure", "status": "in_progress", "activeForm": "Analyzing codebase structure"}, - {"content": " → Identify integration points", "status": "pending", "activeForm": "Identifying integration points"}, - {"content": " → Generate context package", "status": "pending", "activeForm": "Generating context package"}, + {"content": " -> Analyze codebase structure", "status": "in_progress", "activeForm": "Analyzing codebase structure"}, + {"content": " -> Identify integration points", "status": "pending", "activeForm": "Identifying integration points"}, + {"content": " -> Generate context package", "status": "pending", "activeForm": "Generating context package"}, {"content": "Phase 4: Task Generation", "status": "pending", "activeForm": "Executing task generation"} ] ``` -**Note**: Skill execute **attaches** context-gather's 3 tasks. Orchestrator **executes** these tasks sequentially. - ### TodoWrite Update (Phase 2 completed - tasks collapsed) ```json @@ -55,9 +357,7 @@ Skill(skill="workflow:tools:context-gather", args="--session [sessionId] \"[stru ] ``` -**Note**: Phase 2 tasks completed and collapsed to summary. - -### Step 2.2: Update Planning Notes +### Step 2.5: Update Planning Notes After context gathering completes, update planning-notes.md with findings: @@ -101,5 +401,5 @@ ${constraints.map((c, i) => `${i + 2}. [Context] ${c}`).join('\n')}` ## Next Phase Return to orchestrator. Orchestrator checks `conflictRisk`: -- If `conflictRisk >= medium` → [Phase 3: Conflict Resolution](03-conflict-resolution.md) -- If `conflictRisk < medium` → [Phase 4: Task Generation](04-task-generation.md) +- If `conflictRisk >= medium` -> [Phase 3: Conflict Resolution](03-conflict-resolution.md) +- If `conflictRisk < medium` -> [Phase 4: Task Generation](04-task-generation.md) diff --git a/.claude/skills/workflow-plan/phases/03-conflict-resolution.md b/.claude/skills/workflow-plan/phases/03-conflict-resolution.md index 8b0af401..785297c6 100644 --- a/.claude/skills/workflow-plan/phases/03-conflict-resolution.md +++ b/.claude/skills/workflow-plan/phases/03-conflict-resolution.md @@ -5,6 +5,7 @@ Detect and resolve conflicts with CLI analysis. This phase is **conditional** - ## Objective - Detect conflicts between planned changes and existing codebase +- Detect module scenario uniqueness (functional overlaps) - Present conflicts to user with resolution strategies - Apply selected resolution strategies - Update planning-notes.md with conflict decisions @@ -14,46 +15,336 @@ Detect and resolve conflicts with CLI analysis. This phase is **conditional** - Only execute when context-package.json indicates `conflict_risk` is "medium" or "high". If `conflict_risk` is "none" or "low", skip directly to Phase 4. +## Conflict Categories + +| Category | Description | +|----------|-------------| +| **Architecture** | Incompatible design patterns, module structure changes | +| **API** | Breaking contract changes, signature modifications | +| **Data Model** | Schema modifications, type breaking changes | +| **Dependency** | Version incompatibilities, setup conflicts | +| **ModuleOverlap** | Functional overlap, scenario boundary ambiguity, duplicate responsibility | + ## Execution -### Step 3.1: Execute Conflict Resolution +### Step 3.1: Validation ```javascript -Skill(skill="workflow:tools:conflict-resolution", args="--session [sessionId] --context [contextPath]") +// 1. Verify session directory exists +const sessionDir = `.workflow/active/${sessionId}`; +if (!file_exists(sessionDir)) { + throw new Error(`Session directory not found: ${sessionDir}`); +} + +// 2. Load context-package.json +const contextPackage = JSON.parse(Read(contextPath)); + +// 3. Check conflict_risk (skip if none/low) +const conflictRisk = contextPackage.conflict_detection?.risk_level || 'low'; +if (conflictRisk === 'none' || conflictRisk === 'low') { + console.log("No significant conflicts detected, proceeding to task generation"); + // Skip directly to Phase 4 + return; +} ``` -**Input**: -- sessionId from Phase 1 -- contextPath from Phase 2 -- conflict_risk from context-package.json +### Step 3.2: CLI-Powered Conflict Analysis -**Parse Output**: -- Extract: Execution status (success/skipped/failed) -- Verify: conflict-resolution.json file path (if executed) +**Agent Delegation**: -**Validation**: -- File `.workflow/active/[sessionId]/.process/conflict-resolution.json` exists (if executed) +```javascript +Task(subagent_type="cli-execution-agent", run_in_background=false, prompt=` + ## Context + - Session: ${sessionId} + - Risk: ${conflictRisk} + - Files: ${existing_files_list} -**Skip Behavior**: -- If conflict_risk is "none" or "low", skip directly to Phase 4 -- Display: "No significant conflicts detected, proceeding to task generation" + ## 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 || [])} -### TodoWrite Update (Phase 3 Skill executed - tasks attached, if conflict_risk >= medium) + ## Analysis Steps + + ### 0. Load Output Schema (MANDATORY) + Execute: cat ~/.ccw/workflows/cli-templates/schemas/conflict-resolution-schema.json + + ### 1. Load Context + - Read existing files from conflict_detection.existing_files + - Load plan from .workflow/active/${sessionId}/.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/${sessionId}/**/* + 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 ~/.ccw/workflows/cli-templates/schemas/conflict-resolution-schema.json to get full schema + + Return JSON following the schema. 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 to planning-notes.md: + + **File**: .workflow/active/${sessionId}/planning-notes.md + **Location**: Under "## Conflict Decisions (Phase 3)" section + **Format**: + ### [Conflict-Resolution Agent] YYYY-MM-DD + - **Note**: [Brief summary of conflict types, strategies, key decisions] +`) +``` + +### Step 3.3: Iterative User Interaction + +```javascript +const autoYes = workflowPreferences?.autoYes || false; + +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(`[autoYes] Auto-selecting recommended strategy`) + selectedStrategy = conflict.strategies[conflict.recommended || 0] + clarified = true // Skip clarification loop + } else { + AskUserQuestion({ + questions: [{ + question: formatStrategiesForDisplay(conflict.strategies), + header: "Strategy", + multiSelect: false, + options: [ + ...conflict.strategies.map((s, i) => ({ + label: `${s.name}${i === conflict.recommended ? ' (Recommended)' : ''}`, + description: `${s.complexity} complexity | ${s.risk} risk${s.clarification_needed?.length ? ' | Needs clarification' : ''}` + })), + { label: "Custom modification", description: `Suggestions: ${conflict.modification_suggestions?.slice(0,2).join('; ')}` } + ] + }] + }) + + // 3. Handle selection + if (userChoice === "Custom modification") { + customConflicts.push({ id, brief, category, suggestions, overlap_analysis }) + break + } + + selectedStrategy = findStrategyByName(userChoice) + } + + // 4. Clarification (if needed) - batched max 4 per call + if (!autoYes && selectedStrategy.clarification_needed?.length > 0) { + for (batch of chunk(selectedStrategy.clarification_needed, 4)) { + AskUserQuestion({ + questions: batch.map((q, i) => ({ + question: q, header: `Clarify${i+1}`, multiSelect: false, + options: [{ label: "Provide details", description: "Enter answer" }] + })) + }) + userClarifications.push(...collectAnswers(batch)) + } + + // 5. Agent re-analysis + reanalysisResult = Task({ + subagent_type: "cli-execution-agent", + run_in_background: false, + prompt: `Conflict: ${conflict.id}, Strategy: ${selectedStrategy.name} +User Clarifications: ${JSON.stringify(userClarifications)} +Output: { uniqueness_confirmed, rationale, updated_strategy, remaining_questions }` + }) + + if (reanalysisResult.uniqueness_confirmed) { + selectedStrategy = { ...reanalysisResult.updated_strategy, clarifications: userClarifications } + clarified = true + } else { + selectedStrategy.clarification_needed = reanalysisResult.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 || [] +})) +``` + +### Step 3.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(`Applying ${modifications.length} modifications...`); + +// 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}] Modifying ${mod.file}...`); + + // Check if target file exists (brainstorm files may not exist in lite workflow) + if (!file_exists(mod.file)) { + console.log(` File not found, writing to context-package.json as constraint`); + 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") { + 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(` Success`); + } catch (error) { + console.log(` Failed: ${error.message}`); + failedModifications.push({ ...mod, error: error.message }); + } +}); + +// 3. 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, + failed_modifications: failedModifications +}; + +const resolutionPath = `.workflow/active/${sessionId}/.process/conflict-resolution.json`; +Write(resolutionPath, JSON.stringify(resolutionOutput, null, 2)); + +// 4. Update context-package.json with resolution details +const contextPkg = JSON.parse(Read(contextPath)); +contextPkg.conflict_detection.conflict_risk = "resolved"; +contextPkg.conflict_detection.resolution_file = resolutionPath; +contextPkg.conflict_detection.resolved_conflicts = selectedStrategies.map(s => s.conflict_id); +contextPkg.conflict_detection.custom_conflicts = customConflicts.map(c => c.id); +contextPkg.conflict_detection.resolved_at = new Date().toISOString(); +Write(contextPath, JSON.stringify(contextPkg, null, 2)); + +// 5. Output custom conflict summary with overlap analysis (if any) +if (customConflicts.length > 0) { + customConflicts.forEach(conflict => { + console.log(`[${conflict.category}] ${conflict.id}: ${conflict.brief}`); + if (conflict.category === 'ModuleOverlap' && conflict.overlap_analysis) { + console.log(`Overlap info: New module: ${conflict.overlap_analysis.new_module.name}`); + } + conflict.suggestions.forEach(s => console.log(` - ${s}`)); + }); +} +``` + +### TodoWrite Update (Phase 3 in progress, if conflict_risk >= medium) ```json [ {"content": "Phase 1: Session Discovery", "status": "completed", "activeForm": "Executing session discovery"}, {"content": "Phase 2: Context Gathering", "status": "completed", "activeForm": "Executing context gathering"}, {"content": "Phase 3: Conflict Resolution", "status": "in_progress", "activeForm": "Resolving conflicts"}, - {"content": " → Detect conflicts with CLI analysis", "status": "in_progress", "activeForm": "Detecting conflicts"}, - {"content": " → Present conflicts to user", "status": "pending", "activeForm": "Presenting conflicts"}, - {"content": " → Apply resolution strategies", "status": "pending", "activeForm": "Applying resolution strategies"}, + {"content": " -> Detect conflicts with CLI analysis", "status": "in_progress", "activeForm": "Detecting conflicts"}, + {"content": " -> Present conflicts to user", "status": "pending", "activeForm": "Presenting conflicts"}, + {"content": " -> Apply resolution strategies", "status": "pending", "activeForm": "Applying resolution strategies"}, {"content": "Phase 4: Task Generation", "status": "pending", "activeForm": "Executing task generation"} ] ``` -**Note**: Skill execute **attaches** conflict-resolution's 3 tasks. Orchestrator **executes** these tasks sequentially. - ### TodoWrite Update (Phase 3 completed - tasks collapsed) ```json @@ -65,37 +356,34 @@ Skill(skill="workflow:tools:conflict-resolution", args="--session [sessionId] -- ] ``` -**Note**: Phase 3 tasks completed and collapsed to summary. - -### Step 3.2: Update Planning Notes +### Step 3.5: Update Planning Notes After conflict resolution completes (if executed), update planning-notes.md: ```javascript -// If Phase 3 was executed, update planning-notes.md if (conflictRisk === 'medium' || conflictRisk === 'high') { - const conflictResPath = `.workflow/active/${sessionId}/.process/conflict-resolution.json` + const conflictResPath = `.workflow/active/${sessionId}/.process/conflict-resolution.json`; - if (fs.existsSync(conflictResPath)) { - const conflictRes = JSON.parse(Read(conflictResPath)) - const resolved = conflictRes.resolved_conflicts || [] - const modifiedArtifacts = conflictRes.modified_artifacts || [] - const planningConstraints = conflictRes.planning_constraints || [] + if (file_exists(conflictResPath)) { + const conflictRes = JSON.parse(Read(conflictResPath)); + const resolved = conflictRes.resolved_conflicts || []; + const modifiedArtifacts = conflictRes.modified_artifacts || []; + 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.type} → ${r.strategy}`).join('; ') || 'None'} +- **RESOLVED**: ${resolved.map(r => `${r.type} -> ${r.strategy}`).join('; ') || 'None'} - **MODIFIED_ARTIFACTS**: ${modifiedArtifacts.join(', ') || 'None'} - **CONSTRAINTS**: ${planningConstraints.join('; ') || 'None'}` }) // Append Phase 3 constraints to consolidated list if (planningConstraints.length > 0) { - const currentNotes = Read(planningNotesPath) - const constraintCount = (currentNotes.match(/^\d+\./gm) || []).length + const currentNotes = Read(planningNotesPath); + const constraintCount = (currentNotes.match(/^\d+\./gm) || []).length; Edit(planningNotesPath, { old: '## Consolidated Constraints (Phase 4 Input)', @@ -109,9 +397,9 @@ ${planningConstraints.map((c, i) => `${constraintCount + i + 1}. [Conflict] ${c} **Auto-Continue**: Return to user showing conflict resolution results and selected strategies, then auto-continue. -**Auto Mode (--yes)**: When `--yes` flag is active, conflict-resolution sub-command automatically applies recommended resolution strategies without user confirmation. The orchestrator passes the `--yes` flag through to `workflow:tools:conflict-resolution`. +**Auto Mode**: When `workflowPreferences.autoYes` is true, conflict-resolution automatically applies recommended resolution strategies without user confirmation. -### Step 3.3: Memory State Check +### Step 3.6: Memory State Check Evaluate current context window usage and memory state: diff --git a/.claude/skills/workflow-plan/phases/04-task-generation.md b/.claude/skills/workflow-plan/phases/04-task-generation.md index d8b564d7..99d03d3a 100644 --- a/.claude/skills/workflow-plan/phases/04-task-generation.md +++ b/.claude/skills/workflow-plan/phases/04-task-generation.md @@ -17,30 +17,395 @@ Generate implementation plan and task JSONs via action-planning-agent. - Task generation translates high-level role analyses into concrete, actionable work items - **Intent priority**: Current user prompt > role analysis.md files > guidance-specification.md +## 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 + ## Execution -### Step 4.1: Execute Task Generation +### Step 4.0: User Configuration (Interactive) +**Auto Mode Check**: ```javascript -Skill(skill="workflow:tools:task-generate-agent", args="--session [sessionId]") +const autoYes = workflowPreferences?.autoYes || false; + +if (autoYes) { + console.log(`[autoYes] Using defaults: No materials, Agent executor, Codex CLI`) + userConfig = { + supplementaryMaterials: { type: "none", content: [] }, + executionMethod: "agent", + preferredCliTool: "codex", + enableResume: true + } + // Skip to Step 4.1 +} ``` -**CLI Execution Note**: CLI tool usage is now determined semantically by action-planning-agent based on user's task description. If user specifies "use Codex/Gemini/Qwen for X", CLI tool usage is controlled by `meta.execution_config.method` per task, not by `command` fields in implementation steps. +**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" } + ] + } + ] +}) +``` -**Input**: -- `sessionId` from Phase 1 -- **planning-notes.md**: Consolidated constraints from all phases (Phase 1-3) - - Path: `.workflow/active/[sessionId]/planning-notes.md` - - Contains: User intent, context findings, conflict decisions, consolidated constraints - - **Purpose**: Provides structured, minimal context summary to action-planning-agent +### Step 4.1: Context Preparation & Module Detection -**Validation**: -- `.workflow/active/[sessionId]/plan.json` exists (structured plan overview) -- `.workflow/active/[sessionId]/IMPL_PLAN.md` exists -- `.workflow/active/[sessionId]/.task/IMPL-*.json` exists (at least one) -- `.workflow/active/[sessionId]/TODO_LIST.md` exists +**Command prepares session paths, metadata, detects module structure. Context priority sorting is NOT performed here.** -### TodoWrite Update (Phase 4 Skill executed - agent task attached) +```javascript +// 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 +// ├── .task/ # Output: Task JSON files +// ├── plan.json # Output: Structured plan overview +// ├── IMPL_PLAN.md # Output: Implementation plan +// └── TODO_LIST.md # Output: TODO list + +// Auto Module Detection (determines single vs parallel mode) +function autoDetectModules(contextPackage, projectRoot) { + // Complexity Gate: Only parallelize for High complexity + const complexity = contextPackage.metadata?.complexity || 'Medium'; + if (complexity !== 'High') { + 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(); + } + + // 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) +// modules.length == 1 -> Phase 2A (Single Agent, original flow) +// modules.length >= 2 && complexity == 'High' -> Phase 2B + Phase 3 (N+1 Parallel) +``` + +### Step 4.2A: Single Agent Planning (modules.length == 1) + +**Purpose**: Generate IMPL_PLAN.md, task JSONs, and TODO_LIST.md - planning documents only, NOT code implementation. + +```javascript +Task( + subagent_type="action-planning-agent", + run_in_background=false, + description="Generate planning documents (IMPL_PLAN.md, task JSONs, TODO_LIST.md)", + prompt=` +## 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 + +## PLANNING NOTES (PHASE 1-3 CONTEXT) +Load: .workflow/active/${sessionId}/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/${sessionId}/workflow-session.json + - Planning Notes: .workflow/active/${sessionId}/planning-notes.md + - Context Package: .workflow/active/${sessionId}/.process/context-package.json + +Output: + - Task Dir: .workflow/active/${sessionId}/.task/ + - IMPL_PLAN: .workflow/active/${sessionId}/IMPL_PLAN.md + - TODO_LIST: .workflow/active/${sessionId}/TODO_LIST.md + +## CONTEXT METADATA +Session ID: ${sessionId} +MCP Capabilities: {exa_code, exa_web, code_index} + +## FEATURE SPECIFICATIONS (conditional) +If context-package has brainstorm_artifacts.feature_index_path: + Feature Index: [from context-package] + Feature Spec Dir: [from context-package] +Else if .workflow/active/${sessionId}/.brainstorming/feature-specs/ exists: + Feature Index: .workflow/active/${sessionId}/.brainstorming/feature-specs/feature-index.json + Feature Spec Dir: .workflow/active/${sessionId}/.brainstorming/feature-specs/ + +Use feature-index.json to: +- Map features to implementation tasks (feature_id -> task alignment) +- Reference individual feature spec files (spec_path) for detailed requirements +- Identify cross-cutting concerns that span multiple tasks +- Align task priorities with feature priorities + +If the directory does not exist, skip this section. + +## USER CONFIGURATION (from Step 4.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 } + +"cli" -> + meta.execution_config = { method: "cli", cli_tool: userConfig.preferredCliTool, enable_resume: true } + +"hybrid" -> + Per-task decision: Simple tasks (<=3 files) -> "agent", Complex tasks (>3 files) -> "cli" + +IMPORTANT: Do NOT add command field to implementation 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**: PRIMARY focus for task generation +- **priority_tiers.high**: SECONDARY focus +- **dependency_order**: Use 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: +- 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 + +## 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 + - Reference resolved_conflicts for implementation approach alignment + - Handle custom_conflicts with explicit task notes + +## EXPECTED DELIVERABLES +1. Task JSON Files (.task/IMPL-*.json) + - Unified flat schema (task-schema.json) + - Quantified requirements with explicit counts + - Artifacts integration from context package + - **focus_paths from prioritized_context.priority_tiers (critical + high)** + - Pre-analysis steps (use 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 + +3. Plan Overview (plan.json) + - Structured plan overview (plan-overview-base-schema) + - Machine-readable task IDs, shared context, metadata + +4. TODO List (TODO_LIST.md) + - Hierarchical structure + - Links to task JSONs and summaries + +## CLI EXECUTION ID REQUIREMENTS (MANDATORY) +Each task JSON MUST include: +- **cli_execution.id**: Unique ID (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", ...] } + +## QUALITY STANDARDS +Hard Constraints: + - Task count <= 18 (hard limit) + - All requirements quantified + - Acceptance criteria measurable + - Artifact references mapped from context package + +## PLANNING NOTES RECORD (REQUIRED) +After completing, update planning-notes.md: + +## 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] +` +) +``` + +### Step 4.2B: N Parallel Planning (modules.length >= 2) + +**Condition**: `modules.length >= 2` (multi-module detected) + +**Purpose**: Launch N action-planning-agents simultaneously, one per module. + +```javascript +// Launch N agents in parallel (one per module) +const planningTasks = modules.map(module => + Task( + subagent_type="action-planning-agent", + run_in_background=false, + description=`Generate ${module.name} module task JSONs`, + prompt=` +## 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. + +## PLANNING NOTES (PHASE 1-3 CONTEXT) +Load: .workflow/active/${sessionId}/planning-notes.md + +## 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) + +## SESSION PATHS +Input: + - Session Metadata: .workflow/active/${sessionId}/workflow-session.json + - Planning Notes: .workflow/active/${sessionId}/planning-notes.md + - Context Package: .workflow/active/${sessionId}/.process/context-package.json +Output: + - Task Dir: .workflow/active/${sessionId}/.task/ + +## CROSS-MODULE DEPENDENCIES +- For dependencies ON other modules: Use placeholder depends_on: ["CROSS::{module}::{pattern}"] +- Example: depends_on: ["CROSS::B::api-endpoint"] +- Phase 3 Coordinator resolves to actual task IDs + +## CLI EXECUTION ID REQUIREMENTS (MANDATORY) +Each task JSON MUST include: +- **cli_execution.id**: Unique ID (format: {session_id}-IMPL-${module.prefix}{seq}) +- Cross-module dep -> { "strategy": "cross_module_fork", "resume_from": "CROSS::{module}::{pattern}" } + +## QUALITY STANDARDS + - Task count <= 9 for this module + - Focus paths scoped to ${module.paths.join(', ')} only + - Cross-module dependencies use CROSS:: placeholder format + +## PLANNING NOTES RECORD (REQUIRED) +### [${module.name}] YYYY-MM-DD +- **Tasks**: [count] ([IDs]) +- **CROSS deps**: [placeholders used] + ` + ) +); + +// Execute all in parallel +await Promise.all(planningTasks); +``` + +### Step 4.3: Integration (+1 Coordinator, Multi-Module Only) + +**Condition**: Only executed when `modules.length >= 2` + +```javascript +Task( + subagent_type="action-planning-agent", + run_in_background=false, + description="Integrate module tasks and generate unified documents", + prompt=` +## 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/${sessionId}/workflow-session.json + - Context Package: .workflow/active/${sessionId}/.process/context-package.json + - Task JSONs: .workflow/active/${sessionId}/.task/IMPL-*.json (from Phase 2B) +Output: + - Updated Task JSONs: .workflow/active/${sessionId}/.task/IMPL-*.json (resolved dependencies) + - IMPL_PLAN: .workflow/active/${sessionId}/IMPL_PLAN.md + - TODO_LIST: .workflow/active/${sessionId}/TODO_LIST.md + +## 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) +4. Generate TODO_LIST.md (hierarchical format) + +## CROSS-MODULE DEPENDENCY RESOLUTION +- Pattern: CROSS::{module}::{pattern} -> IMPL-{module}* matching title/context +- Log unresolved as warnings + +## PLANNING NOTES RECORD (REQUIRED) +### [Coordinator] YYYY-MM-DD +- **Total**: [count] tasks +- **Resolved**: [CROSS:: resolutions] + ` +) +``` + +### TodoWrite Update (Phase 4 in progress) ```json [ @@ -50,8 +415,6 @@ Skill(skill="workflow:tools:task-generate-agent", args="--session [sessionId]") ] ``` -**Note**: Single agent task attached. Agent autonomously completes discovery, planning, and output generation internally. - ### TodoWrite Update (Phase 4 completed) ```json @@ -62,9 +425,7 @@ Skill(skill="workflow:tools:task-generate-agent", args="--session [sessionId]") ] ``` -**Note**: Agent task completed. No collapse needed (single task). - -### Step 4.2: Plan Confirmation (User Decision Gate) +### Step 4.4: Plan Confirmation (User Decision Gate) After Phase 4 completes, present user with action choices: @@ -84,15 +445,15 @@ const userChoice = AskUserQuestion({ options: [ { label: "Verify Plan Quality (Recommended)", - description: "Run quality verification to catch issues before execution. Checks plan structure, task dependencies, and completeness." + description: "Run quality verification to catch issues before execution." }, { label: "Start Execution", - description: "Begin implementing tasks immediately. Use this if you've already reviewed the plan or want to start quickly." + description: "Begin implementing tasks immediately." }, { label: "Review Status Only", - description: "View task breakdown and session status without taking further action. You can decide what to do next manually." + description: "View task breakdown and session status without taking further action." } ] }] @@ -102,7 +463,6 @@ const userChoice = AskUserQuestion({ if (userChoice.answers["Next Action"] === "Verify Plan Quality (Recommended)") { console.log("\nStarting plan verification...\n"); // Route to Phase 5 (plan-verify) within this skill - // Orchestrator reads phases/05-plan-verify.md and executes } else if (userChoice.answers["Next Action"] === "Start Execution") { console.log("\nStarting task execution...\n"); Skill(skill="workflow-execute", args="--session " + sessionId); @@ -112,12 +472,12 @@ if (userChoice.answers["Next Action"] === "Verify Plan Quality (Recommended)") { } ``` -**Auto Mode (--yes)**: Auto-select "Verify Plan Quality", then auto-continue to execute if quality gate is PROCEED. +**Auto Mode**: When `workflowPreferences.autoYes` is true, auto-select "Verify Plan Quality", then auto-continue to execute if quality gate is PROCEED. **Return to Orchestrator**: Based on user's choice: -- **Verify** → Orchestrator reads phases/05-plan-verify.md and executes Phase 5 in-process -- **Execute** → Skill(skill="workflow-execute") -- **Review** → Route to /workflow:status +- **Verify** -> Orchestrator reads phases/05-plan-verify.md and executes Phase 5 in-process +- **Execute** -> Skill(skill="workflow-execute") +- **Review** -> Route to /workflow:status ## Output @@ -130,6 +490,6 @@ if (userChoice.answers["Next Action"] === "Verify Plan Quality (Recommended)") { ## Next Phase (Conditional) Based on user's plan confirmation choice: -- If "Verify" → [Phase 5: Plan Verification](05-plan-verify.md) -- If "Execute" → Skill(skill="workflow-execute") -- If "Review" → External: /workflow:status +- If "Verify" -> [Phase 5: Plan Verification](05-plan-verify.md) +- If "Execute" -> Skill(skill="workflow-execute") +- If "Review" -> External: /workflow:status diff --git a/.claude/skills/workflow-plan/phases/05-plan-verify.md b/.claude/skills/workflow-plan/phases/05-plan-verify.md index c536aa38..1eae37ce 100644 --- a/.claude/skills/workflow-plan/phases/05-plan-verify.md +++ b/.claude/skills/workflow-plan/phases/05-plan-verify.md @@ -332,15 +332,16 @@ console.log(`Report: ${process_dir}/PLAN_VERIFICATION.md\n${recommendation} | C: ### Step 5.6: Next Step Selection ```javascript -const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') +// Reference workflowPreferences (set by SKILL.md via AskUserQuestion) +const autoYes = workflowPreferences.autoYes const canExecute = recommendation !== 'BLOCK_EXECUTION' // Auto mode if (autoYes) { if (canExecute) { - Skill(skill="workflow-execute", args="--yes --resume-session=\"${session_id}\"") + Skill(skill="workflow-execute", args="--resume-session=\"${session_id}\"") } else { - console.log(`[--yes] BLOCK_EXECUTION - Fix ${critical_count} critical issues first.`) + console.log(`[Auto] BLOCK_EXECUTION - Fix ${critical_count} critical issues first.`) } return } @@ -371,7 +372,9 @@ const selection = AskUserQuestion({ if (selection.includes("Execute")) { Skill(skill="workflow-execute", args="--resume-session=\"${session_id}\"") } else if (selection === "Re-verify") { - Skill(skill="workflow:plan-verify", args="--session ${session_id}") + // Direct phase re-execution: re-read and execute this phase + Read("phases/05-plan-verify.md") + // Re-execute with current session context } ``` diff --git a/.claude/skills/workflow-plan/phases/06-replan.md b/.claude/skills/workflow-plan/phases/06-replan.md index 24b615d9..95b9433c 100644 --- a/.claude/skills/workflow-plan/phases/06-replan.md +++ b/.claude/skills/workflow-plan/phases/06-replan.md @@ -12,37 +12,26 @@ Interactive workflow replanning with session-level artifact updates and boundary ## Entry Point -Triggered via `/workflow:replan` (Replan Mode). +Triggered via Replan Mode routing in SKILL.md. -## Operation Modes +## Input -### Session Replan Mode +Replan accepts requirements text as arguments. Session and mode preferences are provided via `workflowPreferences` context variables (set by SKILL.md via AskUserQuestion). -```bash -# Auto-detect active session -/workflow:replan "requirements text" - -# Explicit session -/workflow:replan --session WFS-oauth "requirements text" - -# File-based input -/workflow:replan --session WFS-oauth requirements-update.md - -# Interactive mode -/workflow:replan --interactive +``` +Input: requirements text (positional argument) +Context: workflowPreferences.autoYes, workflowPreferences.interactive +Session: auto-detected from .workflow/active/ or specified via workflowPreferences.sessionId ``` ### Task Replan Mode -```bash +```text # Direct task update -/workflow:replan IMPL-1 "requirements text" +Replan input: IMPL-1 "requirements text" -# Task with explicit session -/workflow:replan --session WFS-oauth IMPL-2 "requirements text" - -# Interactive mode -/workflow:replan IMPL-1 --interactive +# Interactive mode (workflowPreferences.interactive = true) +Replan input: IMPL-1 "requirements text" ``` ## Language Convention @@ -53,10 +42,11 @@ Interactive question options use Chinese (user-facing UI text) with English iden ### Input Parsing -**Parse flags**: +**Parse input**: ```javascript -const sessionFlag = $ARGUMENTS.match(/--session\s+(\S+)/)?.[1] -const interactive = $ARGUMENTS.includes('--interactive') +// Reference workflowPreferences (set by SKILL.md via AskUserQuestion) +const sessionFlag = workflowPreferences.sessionId +const interactive = workflowPreferences.interactive const taskIdMatch = $ARGUMENTS.match(/\b(IMPL-\d+(?:\.\d+)?)\b/) const taskId = taskIdMatch?.[1] ``` @@ -117,10 +107,11 @@ const taskId = taskIdMatch?.[1] ### Auto Mode Support -When `--yes` or `-y` flag is used, the command skips interactive clarification and uses safe defaults: +When `workflowPreferences.autoYes === true`, the phase skips interactive clarification and uses safe defaults: ```javascript -const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') +// Reference workflowPreferences (set by SKILL.md via AskUserQuestion) +const autoYes = workflowPreferences.autoYes ``` **Auto Mode Defaults**: @@ -130,7 +121,7 @@ const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') - **Dependency Changes**: `no` (preserve existing dependencies) - **User Confirmation**: Auto-confirm execution -**Note**: `--interactive` flag overrides `--yes` flag (forces interactive mode). +**Note**: `workflowPreferences.interactive` overrides `workflowPreferences.autoYes` (forces interactive mode). --- @@ -142,7 +133,7 @@ const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') ```javascript if (autoYes && !interactive) { // Use defaults and skip to Step 6.3 - console.log(`[--yes] Using safe defaults for replan:`) + console.log(`[Auto] Using safe defaults for replan:`) console.log(` - Scope: tasks_only`) console.log(` - Changes: update_only`) console.log(` - Dependencies: preserve existing`) @@ -264,12 +255,12 @@ interface ImpactAnalysis { **Step 6.3.3: User Confirmation** ```javascript -// Parse --yes flag -const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') +// Reference workflowPreferences (set by SKILL.md via AskUserQuestion) +const autoYes = workflowPreferences.autoYes if (autoYes) { // Auto mode: Auto-confirm execution - console.log(`[--yes] Auto-confirming replan execution`) + console.log(`[Auto] Auto-confirming replan execution`) userConfirmation = 'confirm' // Proceed to Step 6.4 } else { @@ -480,7 +471,7 @@ Available sessions: [list] # No changes specified WARNING: No modifications specified -Use --interactive mode or provide requirements +Provide requirements text or use interactive mode ``` ### Task Errors @@ -537,8 +528,8 @@ Backup preserved, rolling back changes ### Session Replan - Add Feature -```bash -/workflow:replan "Add 2FA support" +``` +Replan input: "Add 2FA support" # Interactive clarification Q: Modification scope? diff --git a/.claude/skills/workflow-skill-designer/SKILL.md b/.claude/skills/workflow-skill-designer/SKILL.md index c1793cf2..dbd2f17b 100644 --- a/.claude/skills/workflow-skill-designer/SKILL.md +++ b/.claude/skills/workflow-skill-designer/SKILL.md @@ -106,6 +106,55 @@ SCOPE: [boundaries] CONTEXT: [background/constraints] ``` +### Pattern 6: Interactive Preference Collection (SKILL.md Responsibility) + +Workflow preferences (auto mode, force explore, etc.) MUST be collected via AskUserQuestion in SKILL.md **before** dispatching to phases. Phases reference these as `workflowPreferences.{key}` context variables. + +**Anti-Pattern**: Command-line flags (`--yes`, `-e`, `--explore`) parsed within phase files via `$ARGUMENTS.includes(...)`. + +```javascript +// CORRECT: In SKILL.md (before phase dispatch) +const prefResponse = AskUserQuestion({ + questions: [ + { question: "是否跳过确认?", header: "Auto Mode", options: [ + { label: "Interactive (Recommended)", description: "交互模式" }, + { label: "Auto", description: "跳过所有确认" } + ]} + ] +}) +workflowPreferences = { autoYes: prefResponse.autoMode === 'Auto' } + +// CORRECT: In phase files (reference only) +const autoYes = workflowPreferences.autoYes + +// WRONG: In phase files (flag parsing) +const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') +``` + +### Pattern 7: Direct Phase Handoff + +When one phase needs to invoke another phase within the same skill, read and execute the phase document directly. Do NOT use Skill() routing back through SKILL.md. + +```javascript +// CORRECT: Direct handoff (executionContext already set) +Read("phases/02-lite-execute.md") +// Execute with executionContext (Mode 1) + +// WRONG: Skill routing (unnecessary round-trip) +Skill(skill="workflow:lite-execute", args="--in-memory") +``` + +### Pattern 8: Phase File Hygiene + +Phase files are internal execution documents. They MUST NOT contain: + +| Prohibited | Reason | Correct Location | +|------------|--------|------------------| +| Flag parsing (`$ARGUMENTS.includes(...)`) | Preferences collected in SKILL.md | SKILL.md via AskUserQuestion | +| Invocation syntax (`/skill-name "..."`) | Not user-facing docs | Removed or SKILL.md only | +| Conversion provenance (`Source: Converted from...`) | Implementation detail | Removed | +| Skill routing for inter-phase (`Skill(skill="...")`) | Use direct phase read | Direct `Read("phases/...")` | + ## Execution Flow ``` @@ -221,9 +270,14 @@ allowed-tools: {tools} 1. **{Principle}**: {Description} ... -## Auto Mode +## Interactive Preference Collection -When `--yes` or `-y`: {auto-mode behavior}. +Collect workflow preferences via AskUserQuestion before dispatching to phases: +{AskUserQuestion code with preference derivation → workflowPreferences} + +## Auto Mode Defaults + +When `workflowPreferences.autoYes === true`: {auto-mode behavior}. ## Execution Flow @@ -316,4 +370,5 @@ When designing a new workflow skill, answer these questions: | What's the TodoWrite granularity? | TodoWrite Pattern | Some phases have sub-tasks, others are atomic | | Is there a planning notes pattern? | Post-Phase Updates | Accumulated state document across phases | | What's the error recovery? | Error Handling | Retry once then report, vs rollback | -| Does it need auto mode? | Auto Mode section | Skip confirmations with --yes flag | +| Does it need preference collection? | Interactive Preference Collection | Collect via AskUserQuestion in SKILL.md, pass as workflowPreferences | +| Does phase N hand off to phase M? | Direct Phase Handoff (Pattern 7) | Read phase doc directly, not Skill() routing | diff --git a/.claude/skills/workflow-skill-designer/phases/01-requirements-analysis.md b/.claude/skills/workflow-skill-designer/phases/01-requirements-analysis.md index 1f83aff0..db3cd8db 100644 --- a/.claude/skills/workflow-skill-designer/phases/01-requirements-analysis.md +++ b/.claude/skills/workflow-skill-designer/phases/01-requirements-analysis.md @@ -304,7 +304,7 @@ const workflowConfig = { // Features features: { - hasAutoMode: true, // --yes flag support + hasAutoMode: true, // Interactive preference collection (AskUserQuestion) hasConditionalPhases: true, // some phases may be skipped hasTodoWriteSubTasks: true, // phases expand into sub-tasks hasPlanningNotes: true, // accumulated state document diff --git a/.claude/skills/workflow-skill-designer/phases/02-orchestrator-design.md b/.claude/skills/workflow-skill-designer/phases/02-orchestrator-design.md index f164885f..a4d15391 100644 --- a/.claude/skills/workflow-skill-designer/phases/02-orchestrator-design.md +++ b/.claude/skills/workflow-skill-designer/phases/02-orchestrator-design.md @@ -267,10 +267,11 @@ Extract from source orchestrator or generate from config: function generateOrchestratorSections(config, sourceContent) { const sections = []; - // Auto Mode (if feature enabled) + // Interactive Preference Collection + Auto Mode (if feature enabled) if (config.features.hasAutoMode) { - sections.push(extractOrGenerate(sourceContent, 'Auto Mode', - '## Auto Mode\n\nWhen `--yes` or `-y`: Auto-continue all phases, use recommended defaults.\n')); + sections.push(generateInteractivePreferenceCollection(config)); + sections.push(extractOrGenerate(sourceContent, 'Auto Mode Defaults', + '## Auto Mode Defaults\n\nWhen `workflowPreferences.autoYes === true`: Auto-continue all phases, use recommended defaults.\n')); } // Core Rules @@ -334,7 +335,69 @@ function generateDefaultErrorHandling() { } ``` -## Step 2.8: Assemble SKILL.md +## Step 2.8: Generate Interactive Preference Collection + +When the skill has configurable behaviors (auto mode, force options, etc.), generate the AskUserQuestion-based preference collection section for SKILL.md: + +```javascript +function generateInteractivePreferenceCollection(config) { + if (!config.features.hasAutoMode && !config.preferenceQuestions?.length) { + return ''; + } + + let section = '## Interactive Preference Collection\n\n'; + section += 'Collect workflow preferences via AskUserQuestion before dispatching to phases:\n\n'; + section += '```javascript\n'; + section += 'const prefResponse = AskUserQuestion({\n'; + section += ' questions: [\n'; + + // Always include auto mode question if feature enabled + if (config.features.hasAutoMode) { + section += ' {\n'; + section += ' question: "是否跳过所有确认步骤(自动模式)?",\n'; + section += ' header: "Auto Mode",\n'; + section += ' multiSelect: false,\n'; + section += ' options: [\n'; + section += ' { label: "Interactive (Recommended)", description: "交互模式,包含确认步骤" },\n'; + section += ' { label: "Auto", description: "跳过所有确认,自动执行" }\n'; + section += ' ]\n'; + section += ' },\n'; + } + + // Add custom preference questions + for (const pq of (config.preferenceQuestions || [])) { + section += ` {\n`; + section += ` question: "${pq.question}",\n`; + section += ` header: "${pq.header}",\n`; + section += ` multiSelect: false,\n`; + section += ` options: [\n`; + for (const opt of pq.options) { + section += ` { label: "${opt.label}", description: "${opt.description}" },\n`; + } + section += ` ]\n`; + section += ` },\n`; + } + + section += ' ]\n'; + section += '})\n\n'; + section += '// Derive workflowPreferences from user selection\n'; + section += 'workflowPreferences = {\n'; + if (config.features.hasAutoMode) { + section += ' autoYes: prefResponse.autoMode === "Auto",\n'; + } + for (const pq of (config.preferenceQuestions || [])) { + section += ` ${pq.key}: prefResponse.${pq.header.toLowerCase().replace(/\\s+/g, '')} === "${pq.activeValue}",\n`; + } + section += '}\n'; + section += '```\n\n'; + section += '**workflowPreferences** is passed to phase execution as context variable.\n'; + section += 'Phases reference as `workflowPreferences.autoYes`, `workflowPreferences.{key}`, etc.\n'; + + return section; +} +``` + +## Step 2.9: Assemble SKILL.md ```javascript function assembleSkillMd(config, sourceContent) { diff --git a/.claude/skills/workflow-skill-designer/phases/03-phase-design.md b/.claude/skills/workflow-skill-designer/phases/03-phase-design.md index 7796888f..f29976bf 100644 --- a/.claude/skills/workflow-skill-designer/phases/03-phase-design.md +++ b/.claude/skills/workflow-skill-designer/phases/03-phase-design.md @@ -25,6 +25,98 @@ Generate phase files in `phases/` directory, preserving full execution detail fr **Anti-Pattern**: Creating a phase file that says "See original command for details" or "Execute the agent with appropriate parameters" - this defeats the purpose of the skill structure. The phase file must be self-contained. +## Phase File Content Restrictions + +Phase files are internal execution documents. They MUST NOT contain the following prohibited content: + +| Prohibited Pattern | Detection | Correct Location | +|-------------------|-----------|-----------------| +| Flag parsing (`$ARGUMENTS.includes(...)`) | Grep: `\$ARGUMENTS\.includes` | SKILL.md via AskUserQuestion → `workflowPreferences` | +| Invocation syntax (`/skill-name "..."`) | Grep: `\/\w+[\-:]\w+\s+"` | Removed entirely (phase files are not user-facing) | +| Conversion provenance (`Source: Converted from...`) | Grep: `Source:.*Converted from` | Removed entirely (implementation detail) | +| Skill routing for inter-phase (`Skill(skill="...")`) | Grep: `Skill\(skill=` | Direct `Read("phases/0N-xxx.md")` | + +### Preference Reference Pattern + +Phase files may **reference** workflow preferences but must NOT **parse** them from arguments: + +```javascript +// CORRECT: Reference workflowPreferences (set by SKILL.md) +const autoYes = workflowPreferences.autoYes +const forceExplore = workflowPreferences.forceExplore + +// WRONG: Parse from $ARGUMENTS +const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y') +const forceExplore = $ARGUMENTS.includes('--explore') || $ARGUMENTS.includes('-e') +``` + +### Inter-Phase Handoff Pattern + +When phase N needs to invoke phase M, use direct phase reading: + +```javascript +// CORRECT: Direct handoff (executionContext already set) +Read("phases/02-lite-execute.md") +// Execute with executionContext (Mode 1) + +// WRONG: Skill routing (unnecessary round-trip) +Skill(skill="workflow:lite-execute", args="--in-memory") +``` + +### Content Restriction Enforcement + +When extracting from commands (Step 3.2), apply content sanitization after verbatim extraction: + +```javascript +function sanitizePhaseContent(content) { + let sanitized = content; + + // Remove flag parsing blocks + sanitized = sanitized.replace( + /\/\/.*flag.*parsing[\s\S]*?\n(?=\n)/gi, '' + ); + + // Remove invocation syntax examples + sanitized = sanitized.replace( + /^.*\/\w+[\-:]\w+\s+"[^"]*".*$/gm, '' + ); + + // Remove conversion provenance notes + sanitized = sanitized.replace( + /^\*\*Source\*\*:.*Converted from.*$/gm, '' + ); + + // Replace all $ARGUMENTS.includes patterns with workflowPreferences reference + // Handles any flag name, not just --yes/-y + sanitized = sanitized.replace( + /\$ARGUMENTS\.includes\(['"]--?([^"']+)['"]\)/g, + (match, flagName) => { + // Map common flag names to workflowPreferences keys + const flagMap = { + 'yes': 'workflowPreferences.autoYes', + 'y': 'workflowPreferences.autoYes', + 'explore': 'workflowPreferences.forceExplore', + 'e': 'workflowPreferences.forceExplore' + }; + return flagMap[flagName] || `workflowPreferences.${flagName}`; + } + ); + // Also clean up residual || chains from multi-flag expressions + sanitized = sanitized.replace( + /workflowPreferences\.(\w+)\s*\|\|\s*workflowPreferences\.\1/g, + 'workflowPreferences.$1' + ); + + // Replace Skill() inter-phase routing with direct Read (with or without args) + sanitized = sanitized.replace( + /Skill\(skill=["']([^"']+)["'](?:,\s*args=["']([^"']+)["'])?\)/g, + (match, skillName) => `Read("phases/0N-xxx.md")\n// Execute with context` + ); + + return sanitized; +} +``` + ## Step 3.1: Phase File Generation Strategy ```javascript @@ -77,6 +169,16 @@ function extractPhaseFromCommand(phase, config) { phaseContent += bodyContent; + // 2.5. Ensure Objective section exists + if (!bodyContent.includes('## Objective')) { + // Insert Objective after phase header, before main content + const objectiveSection = `## Objective\n\n- ${phase.description}\n`; + phaseContent = phaseContent.replace( + `${phase.description}.\n\n${bodyContent}`, + `${phase.description}.\n\n${objectiveSection}\n${bodyContent}` + ); + } + // 3. Ensure Output section exists if (!bodyContent.includes('## Output')) { phaseContent += '\n## Output\n\n'; diff --git a/.claude/skills/workflow-skill-designer/phases/04-validation.md b/.claude/skills/workflow-skill-designer/phases/04-validation.md index af54a5c0..fbb954f7 100644 --- a/.claude/skills/workflow-skill-designer/phases/04-validation.md +++ b/.claude/skills/workflow-skill-designer/phases/04-validation.md @@ -231,7 +231,8 @@ function validateSkillMdSections(config) { // Conditional sections const conditionalSections = [ - { name: 'Auto Mode', pattern: /## Auto Mode/, condition: config.features.hasAutoMode }, + { name: 'Interactive Preference Collection', pattern: /## Interactive Preference Collection/, condition: config.features.hasAutoMode }, + { name: 'Auto Mode Defaults', pattern: /## Auto Mode Defaults/, condition: config.features.hasAutoMode }, { name: 'Post-Phase Updates', pattern: /## Post-Phase Updates/, condition: config.features.hasPostPhaseUpdates } ]; @@ -257,7 +258,77 @@ function validateSkillMdSections(config) { } ``` -## Step 4.6: Aggregate Results and Report +## Step 4.6: Phase File Hygiene + +Scan generated phase files for prohibited content patterns. Phase files are internal execution documents and must not contain user-facing syntax, flag parsing, or inter-phase routing. + +```javascript +function validatePhaseFileHygiene(config) { + const skillDir = `.claude/skills/${config.skillName}`; + const results = { errors: [], warnings: [], info: [] }; + + const prohibitedPatterns = [ + { + name: 'Flag parsing ($ARGUMENTS)', + regex: /\$ARGUMENTS\.includes/g, + severity: 'error', + fix: 'Replace with workflowPreferences.{key} reference' + }, + { + name: 'Invocation syntax (/skill-name)', + regex: /\/\w+[\-:]\w+\s+["']/g, + severity: 'warning', + fix: 'Remove (phase files are not user-facing docs)' + }, + { + name: 'Conversion provenance (Source: Converted from)', + regex: /Source:.*Converted from/g, + severity: 'warning', + fix: 'Remove (implementation detail)' + }, + { + name: 'Skill routing for inter-phase (Skill(skill=...)', + regex: /Skill\(skill=/g, + severity: 'error', + fix: 'Replace with direct Read("phases/0N-xxx.md")' + }, + { + name: 'CLI flag definitions (--flag)', + regex: /^\s*-\w,\s+--\w+\s+/gm, + severity: 'warning', + fix: 'Move flag definitions to SKILL.md Interactive Preference Collection' + } + ]; + + for (const phase of config.phases) { + const filename = `${String(phase.number).padStart(2, '0')}-${phase.slug}.md`; + const filepath = `${skillDir}/phases/${filename}`; + if (!fileExists(filepath)) continue; + + const content = Read(filepath); + + for (const pattern of prohibitedPatterns) { + const matches = content.match(pattern.regex); + if (matches && matches.length > 0) { + const msg = `Phase ${phase.number} (${filename}): ${pattern.name} found (${matches.length} occurrence(s)). Fix: ${pattern.fix}`; + if (pattern.severity === 'error') { + results.errors.push(msg); + } else { + results.warnings.push(msg); + } + } + } + } + + if (results.errors.length === 0 && results.warnings.length === 0) { + results.info.push('Phase file hygiene: All phase files clean ✓'); + } + + return results; +} +``` + +## Step 4.7: Aggregate Results and Report ```javascript function generateValidationReport(config) { @@ -266,6 +337,7 @@ function generateValidationReport(config) { const content = validateContentQuality(config); const dataFlow = validateDataFlow(config); const sections = validateSkillMdSections(config); + const hygiene = validatePhaseFileHygiene(config); // Aggregate const allErrors = [ @@ -273,21 +345,24 @@ function generateValidationReport(config) { ...references.errors, ...content.errors, ...dataFlow.errors, - ...sections.errors + ...sections.errors, + ...hygiene.errors ]; const allWarnings = [ ...structural.warnings, ...references.warnings, ...content.warnings, ...dataFlow.warnings, - ...sections.warnings + ...sections.warnings, + ...hygiene.warnings ]; const allInfo = [ ...structural.info, ...references.info, ...content.info, ...dataFlow.info, - ...sections.info + ...sections.info, + ...hygiene.info ]; // Quality gate @@ -325,7 +400,7 @@ ${allInfo.length > 0 ? `Info:\n${allInfo.map(i => ` ℹ ${i}`).join('\n')}` : ' } ``` -## Step 4.7: Error Recovery +## Step 4.8: Error Recovery If validation fails, offer recovery options: @@ -356,7 +431,7 @@ if (report.gate === 'FAIL') { } ``` -## Step 4.8: Integration Summary +## Step 4.9: Integration Summary ```javascript function displayIntegrationSummary(config) { @@ -367,21 +442,20 @@ Integration Complete: Usage: Trigger: ${config.triggers.map(t => `"${t}"`).join(', ')} - Auto: /${config.triggers[0]} --yes "task description" - Design Patterns Applied: ✓ Progressive phase loading (Ref: markers) ✓ Phase Reference Documents table + ✓ Phase file hygiene (no flag parsing, no invocation syntax) ${config.features.hasTodoWriteSubTasks ? '✓' : '○'} TodoWrite attachment/collapse ${config.features.hasConditionalPhases ? '✓' : '○'} Conditional phase execution - ${config.features.hasAutoMode ? '✓' : '○'} Auto mode (--yes flag) + ${config.features.hasAutoMode ? '✓' : '○'} Interactive preference collection (AskUserQuestion) ${config.features.hasPostPhaseUpdates ? '✓' : '○'} Post-phase state updates ${config.features.hasPlanningNotes ? '✓' : '○'} Accumulated planning notes Next Steps: 1. Review SKILL.md orchestrator logic 2. Review each phase file for completeness - 3. Test skill invocation: /${config.triggers[0]} "test task" + 3. Test skill invocation with trigger phrase 4. Iterate based on execution results `); } diff --git a/.claude/skills/workflow-tdd/SKILL.md b/.claude/skills/workflow-tdd/SKILL.md index 9a3552c2..c2c6ae41 100644 --- a/.claude/skills/workflow-tdd/SKILL.md +++ b/.claude/skills/workflow-tdd/SKILL.md @@ -47,9 +47,31 @@ Unified TDD workflow skill combining TDD planning (Red-Green-Refactor task chain 5. **Auto-Continue**: After each phase completes, automatically execute next pending phase 6. **TDD Iron Law**: NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST - enforced in task structure -## Auto Mode +## Interactive Preference Collection -When `--yes` or `-y`: Auto-continue all phases (skip confirmations), use recommended conflict resolutions, auto-select "Verify Plan Quality" after plan completion. +Before dispatching to phase execution, collect workflow preferences via AskUserQuestion: + +```javascript +const prefResponse = AskUserQuestion({ + questions: [ + { + question: "是否跳过所有确认步骤(自动模式)?", + header: "Auto Mode", + multiSelect: false, + options: [ + { label: "Interactive (Recommended)", description: "交互模式,包含确认步骤" }, + { label: "Auto", description: "跳过所有确认,自动执行" } + ] + } + ] +}) + +workflowPreferences = { + autoYes: prefResponse.autoMode === 'Auto' +} +``` + +**workflowPreferences** is passed to phase execution as context variable, referenced as `workflowPreferences.autoYes` within phases. ## Mode Detection @@ -426,7 +448,7 @@ Similar to workflow-plan, a `planning-notes.md` can accumulate context across ph - **If user selects Verify**: Read phases/07-tdd-verify.md, execute Phase 7 in-process - **If user selects Execute**: Skill(skill="workflow-execute") - **If user selects Review**: Route to /workflow:status -- **Auto mode (--yes)**: Auto-select "Verify TDD Compliance", then auto-continue to execute if APPROVED +- **Auto mode (workflowPreferences.autoYes)**: Auto-select "Verify TDD Compliance", then auto-continue to execute if APPROVED - Update TaskCreate/TaskUpdate after each phase - After each phase, automatically continue to next phase based on TaskList status diff --git a/.claude/skills/workflow-tdd/phases/02-context-gathering.md b/.claude/skills/workflow-tdd/phases/02-context-gathering.md index 23d2b4df..ec87932b 100644 --- a/.claude/skills/workflow-tdd/phases/02-context-gathering.md +++ b/.claude/skills/workflow-tdd/phases/02-context-gathering.md @@ -1,53 +1,407 @@ # Phase 2: Context Gathering -Gather project context and analyze codebase for TDD planning. +Gather project context and analyze codebase via context-search-agent with parallel exploration for TDD planning. ## Objective -- Gather project context via context-search agents -- Generate context-package.json with codebase analysis -- Extract conflictRisk to determine Phase 4 execution +- Gather project context using context-search-agent +- Identify critical files, architecture patterns, and constraints +- Detect conflict risk level for Phase 4 decision +- Update planning-notes.md with findings + +## Core Philosophy + +- **Agent Delegation**: Delegate all discovery to `context-search-agent` for autonomous execution +- **Detection-First**: Check for existing context-package before executing +- **Plan Mode**: Full comprehensive analysis (vs lightweight brainstorm mode) +- **Standardized Output**: Generate `.workflow/active/{session}/.process/context-package.json` ## Execution -### Step 2.1: Execute Context Gathering +### Step 2.1: Context-Package Detection + +**Execute First** - Check if valid package already exists: ```javascript -Skill(skill="workflow:tools:context-gather", args="--session [sessionId] \"TDD: [structured-description]\"") +const contextPackagePath = `.workflow/active/${sessionId}/.process/context-package.json`; + +if (file_exists(contextPackagePath)) { + const existing = Read(contextPackagePath); + + // Validate package belongs to current session + if (existing?.metadata?.session_id === sessionId) { + console.log("Valid context-package found for session:", sessionId); + console.log("Stats:", existing.statistics); + console.log("Conflict Risk:", existing.conflict_detection.risk_level); + // Skip execution, store variables and proceed to Step 2.5 + contextPath = contextPackagePath; + conflictRisk = existing.conflict_detection.risk_level; + return; // Early exit - skip Steps 2.2-2.4 + } +} ``` -**Use Same Structured Description**: Pass the same structured format from Phase 1. +### Step 2.2: Complexity Assessment & Parallel Explore -**Input**: `sessionId` from Phase 1 - -### Step 2.2: Parse Output - -- Extract: context-package.json path (store as `contextPath`) -- Typical pattern: `.workflow/active/[sessionId]/.process/context-package.json` - -**Validation**: -- Context package path extracted -- File exists and is valid JSON - -### Step 2.3: Extract conflictRisk +**Only execute if Step 2.1 finds no valid package** ```javascript -const contextPackage = Read(contextPath) -const conflictRisk = contextPackage.conflict_risk // "none" | "low" | "medium" | "high" +// 2.2.1 Complexity Assessment +function analyzeTaskComplexity(taskDescription) { + const text = taskDescription.toLowerCase(); + if (/architect|refactor|restructure|modular|cross-module/.test(text)) return 'High'; + if (/multiple|several|integrate|migrate|extend/.test(text)) return 'Medium'; + return 'Low'; +} + +const ANGLE_PRESETS = { + architecture: ['architecture', 'dependencies', 'modularity', 'integration-points'], + security: ['security', 'auth-patterns', 'dataflow', 'validation'], + performance: ['performance', 'bottlenecks', 'caching', 'data-access'], + bugfix: ['error-handling', 'dataflow', 'state-management', 'edge-cases'], + feature: ['patterns', 'integration-points', 'testing', 'dependencies'], + refactor: ['architecture', 'patterns', 'dependencies', 'testing'] +}; + +function selectAngles(taskDescription, complexity) { + const text = taskDescription.toLowerCase(); + let preset = 'feature'; + if (/refactor|architect|restructure/.test(text)) preset = 'architecture'; + else if (/security|auth|permission/.test(text)) preset = 'security'; + else if (/performance|slow|optimi/.test(text)) preset = 'performance'; + else if (/fix|bug|error|issue/.test(text)) preset = 'bugfix'; + + const count = complexity === 'High' ? 4 : (complexity === 'Medium' ? 3 : 1); + return ANGLE_PRESETS[preset].slice(0, count); +} + +const complexity = analyzeTaskComplexity(task_description); +const selectedAngles = selectAngles(task_description, complexity); +const sessionFolder = `.workflow/active/${sessionId}/.process`; + +// 2.2.2 Launch Parallel Explore Agents +const explorationTasks = selectedAngles.map((angle, index) => + Task( + subagent_type="cli-explore-agent", + run_in_background=false, + description=`Explore: ${angle}`, + prompt=` +## Task Objective +Execute **${angle}** exploration for TDD task planning context. Analyze codebase from this specific angle to discover relevant structure, patterns, and constraints. + +## Assigned Context +- **Exploration Angle**: ${angle} +- **Task Description**: ${task_description} +- **Session ID**: ${sessionId} +- **Exploration Index**: ${index + 1} of ${selectedAngles.length} +- **Output File**: ${sessionFolder}/exploration-${angle}.json + +## MANDATORY FIRST STEPS (Execute by Agent) +1. Run: ccw tool exec get_modules_by_depth '{}' (project structure) +2. Run: rg -l "{keyword_from_task}" --type ts (locate relevant files) +3. Execute: cat ~/.ccw/workflows/cli-templates/schemas/explore-json-schema.json (get output schema reference) + +## Exploration Strategy (${angle} focus) + +**Step 1: Structural Scan** (Bash) +- get_modules_by_depth.sh -> identify modules related to ${angle} +- find/rg -> locate files relevant to ${angle} aspect +- Analyze imports/dependencies from ${angle} perspective + +**Step 2: Semantic Analysis** (Gemini CLI) +- How does existing code handle ${angle} concerns? +- What patterns are used for ${angle}? +- Where would new code integrate from ${angle} viewpoint? + +**Step 3: Write Output** +- Consolidate ${angle} findings into JSON +- Identify ${angle}-specific clarification needs + +## Expected Output + +**File**: ${sessionFolder}/exploration-${angle}.json + +**Schema Reference**: Schema obtained in MANDATORY FIRST STEPS step 3, follow schema exactly + +**Required Fields** (all ${angle} focused): +- project_structure: Modules/architecture relevant to ${angle} +- relevant_files: Files affected from ${angle} perspective + **MANDATORY**: Every file MUST use structured object format with ALL required fields: + [{path: "src/file.ts", relevance: 0.85, rationale: "Contains AuthService.login()", role: "modify_target", discovery_source: "bash-scan", key_symbols: ["AuthService", "login"]}] + - **rationale** (required): Specific selection basis tied to ${angle} topic (>10 chars, not generic) + - **role** (required): modify_target|dependency|pattern_reference|test_target|type_definition|integration_point|config|context_only + - **discovery_source** (recommended): bash-scan|cli-analysis|ace-search|dependency-trace|manual + - **key_symbols** (recommended): Key functions/classes/types in the file relevant to the task + - Scores: 0.7+ high priority, 0.5-0.7 medium, <0.5 low +- patterns: ${angle}-related patterns to follow +- dependencies: Dependencies relevant to ${angle} +- integration_points: Where to integrate from ${angle} viewpoint (include file:line locations) +- constraints: ${angle}-specific limitations/conventions +- clarification_needs: ${angle}-related ambiguities (options array + recommended index) +- _metadata.exploration_angle: "${angle}" + +## Success Criteria +- [ ] Schema obtained via cat explore-json-schema.json +- [ ] get_modules_by_depth.sh executed +- [ ] At least 3 relevant files identified with ${angle} rationale +- [ ] Patterns are actionable (code examples, not generic advice) +- [ ] Integration points include file:line locations +- [ ] Constraints are project-specific to ${angle} +- [ ] JSON output follows schema exactly +- [ ] clarification_needs includes options + recommended + +## Output +Write: ${sessionFolder}/exploration-${angle}.json +Return: 2-3 sentence summary of ${angle} findings +` + ) +); + +// 2.2.3 Generate Manifest after all complete +const explorationFiles = bash(`find ${sessionFolder} -name "exploration-*.json" -type f`).split('\n').filter(f => f.trim()); +const explorationManifest = { + session_id: sessionId, + task_description, + timestamp: new Date().toISOString(), + complexity, + exploration_count: selectedAngles.length, + angles_explored: selectedAngles, + explorations: explorationFiles.map(file => { + const data = JSON.parse(Read(file)); + return { angle: data._metadata.exploration_angle, file: file.split('/').pop(), path: file, index: data._metadata.exploration_index }; + }) +}; +Write(`${sessionFolder}/explorations-manifest.json`, JSON.stringify(explorationManifest, null, 2)); ``` -**Note**: conflictRisk determines whether Phase 4 (Conflict Resolution) will execute. +### Step 2.3: Invoke Context-Search Agent -**TodoWrite**: Mark phase 2 completed, phase 3 in_progress +**Only execute after Step 2.2 completes** -**After Phase 2**: Return to user showing Phase 2 results, then auto-continue to Phase 3 +```javascript +// Load user intent from planning-notes.md (from Phase 1) +const planningNotesPath = `.workflow/active/${sessionId}/planning-notes.md`; +let userIntent = { goal: task_description, key_constraints: "None specified" }; + +if (file_exists(planningNotesPath)) { + const notesContent = Read(planningNotesPath); + const goalMatch = notesContent.match(/\*\*GOAL\*\*:\s*(.+)/); + const constraintsMatch = notesContent.match(/\*\*KEY_CONSTRAINTS\*\*:\s*(.+)/); + if (goalMatch) userIntent.goal = goalMatch[1].trim(); + if (constraintsMatch) userIntent.key_constraints = constraintsMatch[1].trim(); +} + +Task( + subagent_type="context-search-agent", + run_in_background=false, + description="Gather comprehensive context for TDD plan", + prompt=` +## Execution Mode +**PLAN MODE** (Comprehensive) - Full Phase 1-3 execution with priority sorting + +## Session Information +- **Session ID**: ${sessionId} +- **Task Description**: ${task_description} +- **Output Path**: .workflow/${sessionId}/.process/context-package.json + +## User Intent (from Phase 1 - Planning Notes) +**GOAL**: ${userIntent.goal} +**KEY_CONSTRAINTS**: ${userIntent.key_constraints} + +This is the PRIMARY context source - all subsequent analysis must align with user intent. + +## Exploration Input (from Step 2.2) +- **Manifest**: ${sessionFolder}/explorations-manifest.json +- **Exploration Count**: ${explorationManifest.exploration_count} +- **Angles**: ${explorationManifest.angles_explored.join(', ')} +- **Complexity**: ${complexity} + +## Mission +Execute complete context-search-agent workflow for TDD implementation planning: + +### Phase 1: Initialization & Pre-Analysis +1. **Project State Loading**: + - Read and parse .workflow/project-tech.json. Use its overview section as the foundational project_context. + - Read and parse .workflow/project-guidelines.json. Load conventions, constraints, and learnings into a project_guidelines section. + - If files don't exist, proceed with fresh analysis. +2. **Detection**: Check for existing context-package (early exit if valid) +3. **Foundation**: Initialize CodexLens, get project structure, load docs +4. **Analysis**: Extract keywords, determine scope, classify complexity + +### Phase 2: Multi-Source Context Discovery +Execute all discovery tracks (WITH USER INTENT INTEGRATION): +- **Track -1**: User Intent & Priority Foundation (EXECUTE FIRST) + - Load user intent (GOAL, KEY_CONSTRAINTS) from session input + - Map user requirements to codebase entities (files, modules, patterns) + - Establish baseline priority scores based on user goal alignment + - Output: user_intent_mapping.json with preliminary priority scores + +- **Track 0**: Exploration Synthesis (load explorations-manifest.json, prioritize critical_files, deduplicate patterns/integration_points) +- **Track 1**: Historical archive analysis (query manifest.json for lessons learned) +- **Track 2**: Reference documentation (CLAUDE.md, architecture docs) +- **Track 3**: Web examples (use Exa MCP for unfamiliar tech/APIs) +- **Track 4**: Codebase analysis (5-layer discovery: files, content, patterns, deps, config/tests) + +### Phase 3: Synthesis, Assessment & Packaging +1. Apply relevance scoring and build dependency graph +2. **Synthesize 5-source data**: Merge findings from all sources + - Priority order: User Intent > Archive > Docs > Exploration > Code > Web + - **Prioritize the context from project-tech.json** for architecture and tech stack +3. **Context Priority Sorting**: + a. Combine scores from Track -1 (user intent alignment) + relevance scores + exploration critical_files + b. Classify files into priority tiers: + - **Critical** (score >= 0.85): Directly mentioned in user goal OR exploration critical_files + - **High** (0.70-0.84): Key dependencies, patterns required for goal + - **Medium** (0.50-0.69): Supporting files, indirect dependencies + - **Low** (< 0.50): Contextual awareness only + c. Generate dependency_order: Based on dependency graph + user goal sequence + d. Document sorting_rationale: Explain prioritization logic +4. **Populate project_context**: Directly use the overview from project-tech.json +5. **Populate project_guidelines**: Load from project-guidelines.json +6. Integrate brainstorm artifacts (if .brainstorming/ exists, read content) +7. Perform conflict detection with risk assessment +8. **Inject historical conflicts** from archive analysis into conflict_detection +9. **Generate prioritized_context section**: + { + "prioritized_context": { + "user_intent": { "goal": "...", "scope": "...", "key_constraints": ["..."] }, + "priority_tiers": { + "critical": [{ "path": "...", "relevance": 0.95, "rationale": "..." }], + "high": [...], "medium": [...], "low": [...] + }, + "dependency_order": ["module1", "module2", "module3"], + "sorting_rationale": "Based on user goal alignment, exploration critical files, and dependency graph" + } + } +10. Generate and validate context-package.json with prioritized_context field + +## Output Requirements +Complete context-package.json with: +- **metadata**: task_description, keywords, complexity, tech_stack, session_id +- **project_context**: description, technology_stack, architecture, key_components (from project-tech.json) +- **project_guidelines**: {conventions, constraints, quality_rules, learnings} (from project-guidelines.json) +- **assets**: {documentation[], source_code[], config[], tests[]} with relevance scores +- **dependencies**: {internal[], external[]} with dependency graph +- **brainstorm_artifacts**: {guidance_specification, role_analyses[], synthesis_output} with content +- **conflict_detection**: {risk_level, risk_factors, affected_modules[], mitigation_strategy, historical_conflicts[]} +- **exploration_results**: {manifest_path, exploration_count, angles, explorations[], aggregated_insights} +- **prioritized_context**: {user_intent, priority_tiers{critical, high, medium, low}, dependency_order[], sorting_rationale} + +## Quality Validation +Before completion verify: +- [ ] Valid JSON format with all required fields +- [ ] File relevance accuracy >80% +- [ ] Dependency graph complete (max 2 transitive levels) +- [ ] Conflict risk level calculated correctly +- [ ] No sensitive data exposed +- [ ] Total files <= 50 (prioritize high-relevance) + +## Planning Notes Record (REQUIRED) +After completing context-package.json, append to planning-notes.md: + +**File**: .workflow/active/${sessionId}/planning-notes.md +**Location**: Under "## Context Findings (Phase 2)" section +**Format**: +### [Context-Search Agent] YYYY-MM-DD +- **Note**: [Brief summary of key findings] + +Execute autonomously following agent documentation. +Report completion with statistics. +` +) +``` + +### Step 2.4: Output Verification + +After agent completes, verify output: + +```javascript +// Verify file was created +const outputPath = `.workflow/active/${sessionId}/.process/context-package.json`; +if (!file_exists(outputPath)) { + throw new Error("Agent failed to generate context-package.json"); +} + +// Store variables for subsequent phases +contextPath = outputPath; + +// Verify exploration_results included +const pkg = JSON.parse(Read(outputPath)); +if (pkg.exploration_results?.exploration_count > 0) { + console.log(`Exploration results aggregated: ${pkg.exploration_results.exploration_count} angles`); +} + +conflictRisk = pkg.conflict_detection?.risk_level || 'low'; +``` + +### TodoWrite Update (Phase 2 in progress - tasks attached) + +```json +[ + {"content": "Phase 1: Session Discovery", "status": "completed", "activeForm": "Executing session discovery"}, + {"content": "Phase 2: Context Gathering", "status": "in_progress", "activeForm": "Executing context gathering"}, + {"content": " -> Analyze codebase structure", "status": "in_progress", "activeForm": "Analyzing codebase structure"}, + {"content": " -> Identify integration points", "status": "pending", "activeForm": "Identifying integration points"}, + {"content": " -> Generate context package", "status": "pending", "activeForm": "Generating context package"}, + {"content": "Phase 3: Test Coverage Analysis", "status": "pending", "activeForm": "Executing test coverage analysis"}, + {"content": "Phase 5: TDD Task Generation", "status": "pending", "activeForm": "Executing TDD task generation"}, + {"content": "Phase 6: TDD Structure Validation", "status": "pending", "activeForm": "Validating TDD structure"} +] +``` + +### TodoWrite Update (Phase 2 completed - tasks collapsed) + +```json +[ + {"content": "Phase 1: Session Discovery", "status": "completed", "activeForm": "Executing session discovery"}, + {"content": "Phase 2: Context Gathering", "status": "completed", "activeForm": "Executing context gathering"}, + {"content": "Phase 3: Test Coverage Analysis", "status": "pending", "activeForm": "Executing test coverage analysis"}, + {"content": "Phase 5: TDD Task Generation", "status": "pending", "activeForm": "Executing TDD task generation"}, + {"content": "Phase 6: TDD Structure Validation", "status": "pending", "activeForm": "Validating TDD structure"} +] +``` + +### Step 2.5: Update Planning Notes + +After context gathering completes, update planning-notes.md with findings: + +```javascript +// Read context-package to extract key findings +const contextPackage = JSON.parse(Read(contextPath)) +const conflictRisk = contextPackage.conflict_detection?.risk_level || 'low' +const criticalFiles = (contextPackage.exploration_results?.aggregated_insights?.critical_files || []) + .slice(0, 5).map(f => f.path) +const archPatterns = contextPackage.project_context?.architecture_patterns || [] +const constraints = contextPackage.exploration_results?.aggregated_insights?.constraints || [] + +// Append Phase 2 findings to planning-notes.md +Edit(planningNotesPath, { + old: '## Context Findings (Phase 2)\n(To be filled by context-gather)', + new: `## Context Findings (Phase 2) + +- **CRITICAL_FILES**: ${criticalFiles.join(', ') || 'None identified'} +- **ARCHITECTURE**: ${archPatterns.join(', ') || 'Not detected'} +- **CONFLICT_RISK**: ${conflictRisk} +- **CONSTRAINTS**: ${constraints.length > 0 ? constraints.join('; ') : 'None'}` +}) + +// Append Phase 2 constraints to consolidated list +Edit(planningNotesPath, { + old: '## Consolidated Constraints (Phase 4 Input)', + new: `## Consolidated Constraints (Phase 4 Input) +${constraints.map((c, i) => `${i + 2}. [Context] ${c}`).join('\n')}` +}) +``` + +**Auto-Continue**: Return to user showing Phase 2 results, then auto-continue to Phase 3. ## Output - **Variable**: `contextPath` (path to context-package.json) -- **Variable**: `conflictRisk` ("none" | "low" | "medium" | "high") -- **TodoWrite**: Mark Phase 2 completed, Phase 3 in_progress +- **Variable**: `conflictRisk` (none/low/medium/high) +- **File**: `context-package.json` +- **TodoWrite**: Mark Phase 2 completed, determine Phase 3 or Phase 4 ## Next Phase -Return to orchestrator, then auto-continue to [Phase 3: Test Coverage Analysis](03-test-coverage-analysis.md). +Return to orchestrator. Orchestrator continues to [Phase 3: Test Coverage Analysis](03-test-coverage-analysis.md). diff --git a/.claude/skills/workflow-tdd/phases/03-test-coverage-analysis.md b/.claude/skills/workflow-tdd/phases/03-test-coverage-analysis.md index 1fb799cd..b9bfe358 100644 --- a/.claude/skills/workflow-tdd/phases/03-test-coverage-analysis.md +++ b/.claude/skills/workflow-tdd/phases/03-test-coverage-analysis.md @@ -9,27 +9,121 @@ Analyze existing test coverage, detect test framework, and identify coverage gap - Identify related components and integration points - Generate test-context-package.json +## Core Philosophy + +- **Agent Delegation**: Delegate all test coverage analysis to `test-context-search-agent` for autonomous execution +- **Detection-First**: Check for existing test-context-package before executing +- **Coverage-First**: Analyze existing test coverage before planning new tests +- **Source Context Loading**: Import implementation summaries from source session +- **Standardized Output**: Generate `.workflow/active/{session}/.process/test-context-package.json` + ## Execution -### Step 3.1: Execute Test Context Gathering +### Step 3.1: Test-Context-Package Detection + +**Execute First** - Check if valid package already exists: ```javascript -Skill(skill="workflow:tools:test-context-gather", args="--session [sessionId]") +const testContextPath = `.workflow/active/${sessionId}/.process/test-context-package.json`; + +if (file_exists(testContextPath)) { + const existing = Read(testContextPath); + + // Validate package belongs to current session + if (existing?.metadata?.test_session_id === sessionId) { + console.log("Valid test-context-package found for session:", sessionId); + console.log("Coverage Stats:", existing.test_coverage.coverage_stats); + console.log("Framework:", existing.test_framework.framework); + console.log("Missing Tests:", existing.test_coverage.missing_tests.length); + // Skip execution, store variable and proceed + testContextPath_var = testContextPath; + return; // Early exit - skip Steps 3.2-3.3 + } +} ``` -**Purpose**: Analyze existing codebase for: -- Existing test patterns and conventions -- Current test coverage -- Related components and integration points -- Test framework detection +### Step 3.2: Invoke Test-Context-Search Agent -### Step 3.2: Parse Output +**Only execute if Step 3.1 finds no valid package** -- Extract: testContextPath (`.workflow/active/[sessionId]/.process/test-context-package.json`) +```javascript +Task( + subagent_type="test-context-search-agent", + run_in_background=false, + description="Gather test coverage context", + prompt=` -**Validation**: -- test-context-package.json exists and is valid JSON -- Contains framework detection results +## Execution Mode +**PLAN MODE** (Comprehensive) - Full Phase 1-3 execution + +## Session Information +- **Test Session ID**: ${sessionId} +- **Output Path**: .workflow/active/${sessionId}/.process/test-context-package.json + +## Mission +Execute complete test-context-search-agent workflow for test generation planning: + +### Phase 1: Session Validation & Source Context Loading +1. **Detection**: Check for existing test-context-package (early exit if valid) +2. **Test Session Validation**: Load test session metadata, extract source_session reference +3. **Source Context Loading**: Load source session implementation summaries, changed files, tech stack + +### Phase 2: Test Coverage Analysis +Execute coverage discovery: +- **Track 1**: Existing test discovery (find *.test.*, *.spec.* files) +- **Track 2**: Coverage gap analysis (match implementation files to test files) +- **Track 3**: Coverage statistics (calculate percentages, identify gaps by module) + +### Phase 3: Framework Detection & Packaging +1. Framework identification from package.json/requirements.txt +2. Convention analysis from existing test patterns +3. Generate and validate test-context-package.json + +## Output Requirements +Complete test-context-package.json with: +- **metadata**: test_session_id, source_session_id, task_type, complexity +- **source_context**: implementation_summaries, tech_stack, project_patterns +- **test_coverage**: existing_tests[], missing_tests[], coverage_stats +- **test_framework**: framework, version, test_pattern, conventions +- **assets**: implementation_summary[], existing_test[], source_code[] with priorities +- **focus_areas**: Test generation guidance based on coverage gaps + +## Quality Validation +Before completion verify: +- [ ] Valid JSON format with all required fields +- [ ] Source session context loaded successfully +- [ ] Test coverage gaps identified +- [ ] Test framework detected (or marked as 'unknown') +- [ ] Coverage percentage calculated correctly +- [ ] Missing tests catalogued with priority +- [ ] Execution time < 30 seconds (< 60s for large codebases) + +Execute autonomously following agent documentation. +Report completion with coverage statistics. +` +) +``` + +### Step 3.3: Output Verification + +After agent completes, verify output: + +```javascript +// Verify file was created +const outputPath = `.workflow/active/${sessionId}/.process/test-context-package.json`; +if (!file_exists(outputPath)) { + throw new Error("Agent failed to generate test-context-package.json"); +} + +// Load and display summary +const testContext = JSON.parse(Read(outputPath)); +console.log("Test context package generated successfully"); +console.log("Coverage:", testContext.test_coverage.coverage_stats.coverage_percentage + "%"); +console.log("Tests to generate:", testContext.test_coverage.missing_tests.length); + +// Store variable for subsequent phases +testContextPath_var = outputPath; +``` ### TodoWrite Update (Phase 3 Skill executed - tasks attached) @@ -38,17 +132,17 @@ Skill(skill="workflow:tools:test-context-gather", args="--session [sessionId]") {"content": "Phase 1: Session Discovery", "status": "completed", "activeForm": "Executing session discovery"}, {"content": "Phase 2: Context Gathering", "status": "completed", "activeForm": "Executing context gathering"}, {"content": "Phase 3: Test Coverage Analysis", "status": "in_progress", "activeForm": "Executing test coverage analysis"}, - {"content": " → Detect test framework and conventions", "status": "in_progress", "activeForm": "Detecting test framework"}, - {"content": " → Analyze existing test coverage", "status": "pending", "activeForm": "Analyzing test coverage"}, - {"content": " → Identify coverage gaps", "status": "pending", "activeForm": "Identifying coverage gaps"}, + {"content": " -> Detect test framework and conventions", "status": "in_progress", "activeForm": "Detecting test framework"}, + {"content": " -> Analyze existing test coverage", "status": "pending", "activeForm": "Analyzing test coverage"}, + {"content": " -> Identify coverage gaps", "status": "pending", "activeForm": "Identifying coverage gaps"}, {"content": "Phase 5: TDD Task Generation", "status": "pending", "activeForm": "Executing TDD task generation"}, {"content": "Phase 6: TDD Structure Validation", "status": "pending", "activeForm": "Validating TDD structure"} ] ``` -**Note**: Skill execute **attaches** test-context-gather's 3 tasks. Orchestrator **executes** these tasks. +**Note**: Agent execution **attaches** test-context-search's 3 tasks. Orchestrator **executes** these tasks. -**Next Action**: Tasks attached → **Execute Phase 3.1-3.3** sequentially +**Next Action**: Tasks attached -> **Execute Phase 3.1-3.3** sequentially ### TodoWrite Update (Phase 3 completed - tasks collapsed) @@ -74,5 +168,5 @@ Skill(skill="workflow:tools:test-context-gather", args="--session [sessionId]") ## Next Phase Based on `conflictRisk` from Phase 2: -- If conflictRisk ≥ medium → [Phase 4: Conflict Resolution](04-conflict-resolution.md) -- If conflictRisk < medium → Skip to [Phase 5: TDD Task Generation](05-tdd-task-generation.md) +- If conflictRisk >= medium -> [Phase 4: Conflict Resolution](04-conflict-resolution.md) +- If conflictRisk < medium -> Skip to [Phase 5: TDD Task Generation](05-tdd-task-generation.md) diff --git a/.claude/skills/workflow-tdd/phases/04-conflict-resolution.md b/.claude/skills/workflow-tdd/phases/04-conflict-resolution.md index e15ef286..e5526525 100644 --- a/.claude/skills/workflow-tdd/phases/04-conflict-resolution.md +++ b/.claude/skills/workflow-tdd/phases/04-conflict-resolution.md @@ -1,41 +1,337 @@ # Phase 4: Conflict Resolution (Conditional) -Detect and resolve conflicts when conflict risk is medium or high. +Detect and resolve conflicts with CLI analysis. This phase is **conditional** - only executes when `conflict_risk >= medium`. ## Objective -- Execute conflict detection and resolution only when conflictRisk ≥ medium -- Generate conflict-resolution.json with resolution strategies -- Skip directly to Phase 5 if conflictRisk is none/low +- Detect conflicts between planned changes and existing codebase +- Detect module scenario uniqueness (functional overlaps) +- Present conflicts to user with resolution strategies +- Apply selected resolution strategies +- Update planning-notes.md with conflict decisions ## Trigger Condition -**Only execute when**: `context-package.json` indicates `conflict_risk` is "medium" or "high" +Only execute when context-package.json indicates `conflict_risk` is "medium" or "high". +If `conflict_risk` is "none" or "low", skip directly to Phase 5. -**Skip Behavior**: If conflict_risk is "none" or "low", skip directly to Phase 5. Display: "No significant conflicts detected, proceeding to TDD task generation" +## Conflict Categories + +| Category | Description | +|----------|-------------| +| **Architecture** | Incompatible design patterns, module structure changes | +| **API** | Breaking contract changes, signature modifications | +| **Data Model** | Schema modifications, type breaking changes | +| **Dependency** | Version incompatibilities, setup conflicts | +| **ModuleOverlap** | Functional overlap, scenario boundary ambiguity, duplicate responsibility | ## Execution -### Step 4.1: Execute Conflict Resolution +### Step 4.1: Validation ```javascript -Skill(skill="workflow:tools:conflict-resolution", args="--session [sessionId] --context [contextPath]") +// 1. Verify session directory exists +const sessionDir = `.workflow/active/${sessionId}`; +if (!file_exists(sessionDir)) { + throw new Error(`Session directory not found: ${sessionDir}`); +} + +// 2. Load context-package.json +const contextPackage = JSON.parse(Read(contextPath)); + +// 3. Check conflict_risk (skip if none/low) +const conflictRisk = contextPackage.conflict_detection?.risk_level || 'low'; +if (conflictRisk === 'none' || conflictRisk === 'low') { + console.log("No significant conflicts detected, proceeding to TDD task generation"); + // Skip directly to Phase 5 + return; +} ``` -**Input**: -- sessionId from Phase 1 -- contextPath from Phase 2 -- conflict_risk from context-package.json +### Step 4.2: CLI-Powered Conflict Analysis -### Step 4.2: Parse Output +**Agent Delegation**: -- Extract: Execution status (success/skipped/failed) -- Verify: conflict-resolution.json file path (if executed) +```javascript +Task(subagent_type="cli-execution-agent", run_in_background=false, prompt=` + ## Context + - Session: ${sessionId} + - Risk: ${conflictRisk} + - Files: ${existing_files_list} -**Validation**: -- File `.workflow/active/[sessionId]/.process/conflict-resolution.json` exists (if executed) + ## 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 || [])} -### TodoWrite Update (Phase 4 Skill executed - tasks attached, if conflict_risk ≥ medium) + ## Analysis Steps + + ### 0. Load Output Schema (MANDATORY) + Execute: cat ~/.ccw/workflows/cli-templates/schemas/conflict-resolution-schema.json + + ### 1. Load Context + - Read existing files from conflict_detection.existing_files + - Load plan from .workflow/active/${sessionId}/.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/${sessionId}/**/* + 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 ~/.ccw/workflows/cli-templates/schemas/conflict-resolution-schema.json to get full schema + + Return JSON following the schema. 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 to planning-notes.md: + + **File**: .workflow/active/${sessionId}/planning-notes.md + **Location**: Under "## Conflict Decisions (Phase 3)" section + **Format**: + ### [Conflict-Resolution Agent] YYYY-MM-DD + - **Note**: [Brief summary of conflict types, strategies, key decisions] +`) +``` + +### Step 4.3: Iterative User Interaction + +```javascript +const autoYes = workflowPreferences?.autoYes || false; + +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(`[autoYes] Auto-selecting recommended strategy`) + selectedStrategy = conflict.strategies[conflict.recommended || 0] + clarified = true // Skip clarification loop + } else { + AskUserQuestion({ + questions: [{ + question: formatStrategiesForDisplay(conflict.strategies), + header: "Strategy", + multiSelect: false, + options: [ + ...conflict.strategies.map((s, i) => ({ + label: `${s.name}${i === conflict.recommended ? ' (Recommended)' : ''}`, + description: `${s.complexity} complexity | ${s.risk} risk${s.clarification_needed?.length ? ' | Needs clarification' : ''}` + })), + { label: "Custom modification", description: `Suggestions: ${conflict.modification_suggestions?.slice(0,2).join('; ')}` } + ] + }] + }) + + // 3. Handle selection + if (userChoice === "Custom modification") { + customConflicts.push({ id, brief, category, suggestions, overlap_analysis }) + break + } + + selectedStrategy = findStrategyByName(userChoice) + } + + // 4. Clarification (if needed) - batched max 4 per call + if (!autoYes && selectedStrategy.clarification_needed?.length > 0) { + for (batch of chunk(selectedStrategy.clarification_needed, 4)) { + AskUserQuestion({ + questions: batch.map((q, i) => ({ + question: q, header: `Clarify${i+1}`, multiSelect: false, + options: [{ label: "Provide details", description: "Enter answer" }] + })) + }) + userClarifications.push(...collectAnswers(batch)) + } + + // 5. Agent re-analysis + reanalysisResult = Task({ + subagent_type: "cli-execution-agent", + run_in_background: false, + prompt: `Conflict: ${conflict.id}, Strategy: ${selectedStrategy.name} +User Clarifications: ${JSON.stringify(userClarifications)} +Output: { uniqueness_confirmed, rationale, updated_strategy, remaining_questions }` + }) + + if (reanalysisResult.uniqueness_confirmed) { + selectedStrategy = { ...reanalysisResult.updated_strategy, clarifications: userClarifications } + clarified = true + } else { + selectedStrategy.clarification_needed = reanalysisResult.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 || [] +})) +``` + +### Step 4.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(`Applying ${modifications.length} modifications...`); + +// 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}] Modifying ${mod.file}...`); + + // Check if target file exists (brainstorm files may not exist in lite workflow) + if (!file_exists(mod.file)) { + console.log(` File not found, writing to context-package.json as constraint`); + 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") { + 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(` Success`); + } catch (error) { + console.log(` Failed: ${error.message}`); + failedModifications.push({ ...mod, error: error.message }); + } +}); + +// 3. 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, + failed_modifications: failedModifications +}; + +const resolutionPath = `.workflow/active/${sessionId}/.process/conflict-resolution.json`; +Write(resolutionPath, JSON.stringify(resolutionOutput, null, 2)); + +// 4. Update context-package.json with resolution details +const contextPkg = JSON.parse(Read(contextPath)); +contextPkg.conflict_detection.conflict_risk = "resolved"; +contextPkg.conflict_detection.resolution_file = resolutionPath; +contextPkg.conflict_detection.resolved_conflicts = selectedStrategies.map(s => s.conflict_id); +contextPkg.conflict_detection.custom_conflicts = customConflicts.map(c => c.id); +contextPkg.conflict_detection.resolved_at = new Date().toISOString(); +Write(contextPath, JSON.stringify(contextPkg, null, 2)); + +// 5. Output custom conflict summary with overlap analysis (if any) +if (customConflicts.length > 0) { + customConflicts.forEach(conflict => { + console.log(`[${conflict.category}] ${conflict.id}: ${conflict.brief}`); + if (conflict.category === 'ModuleOverlap' && conflict.overlap_analysis) { + console.log(`Overlap info: New module: ${conflict.overlap_analysis.new_module.name}`); + } + conflict.suggestions.forEach(s => console.log(` - ${s}`)); + }); +} +``` + +### TodoWrite Update (Phase 4 in progress - tasks attached, if conflict_risk >= medium) ```json [ @@ -43,18 +339,14 @@ Skill(skill="workflow:tools:conflict-resolution", args="--session [sessionId] -- {"content": "Phase 2: Context Gathering", "status": "completed", "activeForm": "Executing context gathering"}, {"content": "Phase 3: Test Coverage Analysis", "status": "completed", "activeForm": "Executing test coverage analysis"}, {"content": "Phase 4: Conflict Resolution", "status": "in_progress", "activeForm": "Executing conflict resolution"}, - {"content": " → Detect conflicts with CLI analysis", "status": "in_progress", "activeForm": "Detecting conflicts"}, - {"content": " → Log and analyze detected conflicts", "status": "pending", "activeForm": "Analyzing conflicts"}, - {"content": " → Apply resolution strategies", "status": "pending", "activeForm": "Applying resolution strategies"}, + {"content": " -> Detect conflicts with CLI analysis", "status": "in_progress", "activeForm": "Detecting conflicts"}, + {"content": " -> Present conflicts to user", "status": "pending", "activeForm": "Presenting conflicts"}, + {"content": " -> Apply resolution strategies", "status": "pending", "activeForm": "Applying resolution strategies"}, {"content": "Phase 5: TDD Task Generation", "status": "pending", "activeForm": "Executing TDD task generation"}, {"content": "Phase 6: TDD Structure Validation", "status": "pending", "activeForm": "Validating TDD structure"} ] ``` -**Note**: Skill execute **attaches** conflict-resolution's 3 tasks. Orchestrator **executes** these tasks. - -**Next Action**: Tasks attached → **Execute Phase 4.1-4.3** sequentially - ### TodoWrite Update (Phase 4 completed - tasks collapsed) ```json @@ -68,26 +360,65 @@ Skill(skill="workflow:tools:conflict-resolution", args="--session [sessionId] -- ] ``` -**Note**: Phase 4 tasks completed and collapsed to summary. +### Step 4.5: Update Planning Notes -**After Phase 4**: Return to user showing conflict resolution results and selected strategies, then auto-continue to Phase 5 +After conflict resolution completes (if executed), update planning-notes.md: -### Memory State Check +```javascript +if (conflictRisk === 'medium' || conflictRisk === 'high') { + 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 modifiedArtifacts = conflictRes.modified_artifacts || []; + const planningConstraints = conflictRes.planning_constraints || []; + + // Update Phase 4 section + Edit(planningNotesPath, { + old: '## Conflict Decisions (Phase 4)\n(To be filled if conflicts detected)', + new: `## Conflict Decisions (Phase 4) + +- **RESOLVED**: ${resolved.map(r => `${r.type} -> ${r.strategy}`).join('; ') || 'None'} +- **MODIFIED_ARTIFACTS**: ${modifiedArtifacts.join(', ') || 'None'} +- **CONSTRAINTS**: ${planningConstraints.join('; ') || 'None'}` + }) + + // Append Phase 4 constraints to consolidated list + if (planningConstraints.length > 0) { + const currentNotes = Read(planningNotesPath); + const constraintCount = (currentNotes.match(/^\d+\./gm) || []).length; + + Edit(planningNotesPath, { + old: '## Consolidated Constraints (Phase 5 Input)', + new: `## Consolidated Constraints (Phase 5 Input) +${planningConstraints.map((c, i) => `${constraintCount + i + 1}. [Conflict] ${c}`).join('\n')}` + }) + } + } +} +``` + +**Auto-Continue**: Return to user showing conflict resolution results and selected strategies, then auto-continue. + +**Auto Mode**: When `workflowPreferences.autoYes` is true, conflict-resolution automatically applies recommended resolution strategies without user confirmation. + +### Step 4.6: Memory State Check + +Evaluate current context window usage and memory state: -After Phase 4, evaluate current context window usage and memory state: - If memory usage is high (>110K tokens or approaching context limits): - ```javascript - Skill(skill="compact") - ``` +```javascript +Skill(skill="compact") +``` - - This optimizes memory before proceeding to Phase 5 - Memory compaction is particularly important after analysis phase which may generate extensive documentation - Ensures optimal performance and prevents context overflow ## Output -- **File**: `.workflow/active/[sessionId]/.process/conflict-resolution.json` (if executed) +- **File**: `conflict-resolution.json` (if conflicts resolved) - **TodoWrite**: Mark Phase 4 completed, Phase 5 in_progress ## Next Phase diff --git a/.claude/skills/workflow-tdd/phases/05-tdd-task-generation.md b/.claude/skills/workflow-tdd/phases/05-tdd-task-generation.md index 23526a13..9431d2ba 100644 --- a/.claude/skills/workflow-tdd/phases/05-tdd-task-generation.md +++ b/.claude/skills/workflow-tdd/phases/05-tdd-task-generation.md @@ -8,12 +8,351 @@ Generate TDD tasks with Red-Green-Refactor cycles via action-planning-agent. - Each task contains internal Red-Green-Refactor cycle - Include Phase 0 user configuration (execution method, CLI tool preference) +## Core Philosophy + +- **Agent-Driven**: Delegate execution to action-planning-agent for autonomous operation +- **Two-Phase Flow**: Discovery (context gathering) -> Output (document generation) +- **Memory-First**: Reuse loaded documents from conversation memory +- **MCP-Enhanced**: Use MCP tools for advanced code analysis and research +- **Semantic CLI Selection**: CLI tool usage determined from user's task description, not flags +- **Path Clarity**: All `focus_paths` prefer absolute paths or clear relative paths from project root +- **TDD-First**: Every feature starts with a failing test (Red phase) +- **Feature-Complete Tasks**: Each task contains complete Red-Green-Refactor cycle +- **Quantification-Enforced**: All test cases, coverage requirements, and implementation scope MUST include explicit counts and enumerations + +## Task Strategy + +### Optimized Task Structure +- **1 feature = 1 task** containing complete TDD cycle internally +- Each task executes Red-Green-Refactor phases sequentially +- Task count = Feature count (typically 5 features = 5 tasks) + +### When to Use Subtasks +- Feature complexity >2500 lines or >6 files per TDD cycle +- Multiple independent sub-features needing parallel execution +- Strong technical dependency blocking (e.g., API before UI) +- Different tech stacks or domains within feature + +### Task Limits +- **Maximum 18 tasks** (hard limit for TDD workflows) +- **Feature-based**: Complete functional units with internal TDD cycles +- **Hierarchy**: Flat (<=5 simple features) | Two-level (6-10 for complex features with sub-features) +- **Re-scope**: If >18 tasks needed, break project into multiple TDD workflow sessions + ## Execution -### Step 5.1: Execute TDD Task Generation +### Phase 0: User Configuration (Interactive) + +**Purpose**: Collect user preferences before TDD task generation. ```javascript -Skill(skill="workflow:tools:task-generate-tdd", args="--session [sessionId]") +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 TDD tasks:", + header: "Execution", + multiSelect: false, + options: [ + { label: "Agent (Recommended)", description: "Claude agent executes Red-Green-Refactor cycles directly" }, + { label: "Hybrid", description: "Agent orchestrates, calls CLI for complex steps (Red/Green phases)" }, + { label: "CLI Only", description: "All TDD cycles 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 TDD Red-Green-Refactor cycles" }, + { 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**: +```javascript +if (userConfig.materials === "Provide 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: [...], + }, + executionMethod: "agent|hybrid|cli", + preferredCliTool: "codex|gemini|qwen|auto", + enableResume: true // Always enable resume for CLI executions +} +``` + +**Auto Mode**: When `--yes` or `-y`: Skip user questions, use defaults (no materials, Agent executor). + +--- + +### Phase 1: Context Preparation & Discovery + +**Memory-First Rule**: Skip file loading if documents already in conversation memory + +**Progressive Loading Strategy**: Load context incrementally: +- **Core**: session metadata + context-package.json (always load) +- **Selective**: synthesis_output OR (guidance + relevant role analyses) - NOT all role analyses +- **On-Demand**: conflict resolution (if conflict_risk >= medium), test context + +**Session Path Structure** (provided to agent): +``` +.workflow/active/WFS-{session-id}/ +├── workflow-session.json # Session metadata +├── .process/ +│ ├── context-package.json # Context package with artifact catalog +│ ├── test-context-package.json # Test coverage analysis +│ └── conflict-resolution.json # Conflict resolution (if exists) +├── .task/ # Output: Task JSON files +│ ├── IMPL-1.json +│ ├── IMPL-2.json +│ └── ... +├── plan.json # Output: Structured plan overview (TDD variant) +├── IMPL_PLAN.md # Output: TDD implementation plan +└── TODO_LIST.md # Output: TODO list with TDD phases +``` + +**Discovery Actions**: + +1. **Load Session Context** (if not in memory) + ```javascript + if (!memory.has("workflow-session.json")) { + Read(`.workflow/active/${sessionId}/workflow-session.json`) + } + ``` + +2. **Load Context Package** (if not in memory) + ```javascript + if (!memory.has("context-package.json")) { + Read(`.workflow/active/${sessionId}/.process/context-package.json`) + } + ``` + +3. **Load Test Context Package** (if not in memory) + ```javascript + if (!memory.has("test-context-package.json")) { + Read(`.workflow/active/${sessionId}/.process/test-context-package.json`) + } + ``` + +4. **Extract & Load Role Analyses** (from context-package.json) + ```javascript + const roleAnalysisPaths = contextPackage.brainstorm_artifacts.role_analyses + .flatMap(role => role.files.map(f => f.path)); + roleAnalysisPaths.forEach(path => Read(path)); + ``` + +5. **Load Conflict Resolution** (if exists) + ```javascript + if (contextPackage.conflict_detection?.resolution_file) { + Read(contextPackage.conflict_detection.resolution_file) + } else if (contextPackage.brainstorm_artifacts?.conflict_resolution?.exists) { + Read(contextPackage.brainstorm_artifacts.conflict_resolution.path) + } + ``` + +6. **Code Analysis with Native Tools** (optional) + ```bash + find . -name "*test*" -type f + rg "describe|it\(|test\(" -g "*.ts" + ``` + +7. **MCP External Research** (optional) + ```javascript + mcp__exa__get_code_context_exa( + query="TypeScript TDD best practices Red-Green-Refactor", + tokensNum="dynamic" + ) + ``` + +--- + +### Step 5.1: Execute TDD Task Generation (Agent Invocation) + +```javascript +Task( + subagent_type="action-planning-agent", + run_in_background=false, + description="Generate TDD planning documents (IMPL_PLAN.md, task JSONs, TODO_LIST.md)", + prompt=` +## TASK OBJECTIVE +Generate TDD 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 (load analysis.md files incrementally due to file size): +- **Core**: session metadata + context-package.json (always) +- **Selective**: synthesis_output OR (guidance + relevant role analyses) - NOT all +- **On-Demand**: conflict resolution (if conflict_risk >= medium), test context + +## SESSION PATHS +Input: + - Session Metadata: .workflow/active/${sessionId}/workflow-session.json + - Context Package: .workflow/active/${sessionId}/.process/context-package.json + - Test Context: .workflow/active/${sessionId}/.process/test-context-package.json + +Output: + - Task Dir: .workflow/active/${sessionId}/.task/ + - IMPL_PLAN: .workflow/active/${sessionId}/IMPL_PLAN.md + - TODO_LIST: .workflow/active/${sessionId}/TODO_LIST.md + +## CONTEXT METADATA +Session ID: ${sessionId} +Workflow Type: TDD +MCP Capabilities: {exa_code, exa_web, code_index} + +## USER CONFIGURATION (from Phase 0) +Execution Method: ${userConfig.executionMethod} +Preferred CLI Tool: ${userConfig.preferredCliTool} +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 Red-Green-Refactor phases 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 TDD cycle complexity, set method to "agent" OR "cli" per task + - Simple cycles (<=5 test cases, <=3 files) -> method: "agent" + - Complex cycles (>5 test cases, >3 files, integration tests) -> method: "cli" + CLI tool: userConfig.preferredCliTool, enable_resume: true + +IMPORTANT: Do NOT add command field to implementation steps. Execution routing is controlled by task-level meta.execution_config.method only. + +## EXPLORATION CONTEXT (from context-package.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 + +## TEST CONTEXT INTEGRATION +- Load test-context-package.json for existing test patterns and coverage analysis +- Extract test framework configuration (Jest/Pytest/etc.) +- Identify existing test conventions and patterns +- Map coverage gaps to TDD Red phase test targets + +## TDD DOCUMENT GENERATION TASK + +### TDD-Specific Requirements Summary + +#### Task Structure Philosophy +- **1 feature = 1 task** containing complete TDD cycle internally +- Each task executes Red-Green-Refactor phases sequentially +- Task count = Feature count (typically 5 features = 5 tasks) +- Subtasks only when complexity >2500 lines or >6 files per cycle +- **Maximum 18 tasks** (hard limit for TDD workflows) + +#### TDD Cycle Mapping +- **Simple features**: IMPL-N with internal Red-Green-Refactor phases +- **Complex features**: IMPL-N (container) + IMPL-N.M (subtasks) +- Each cycle includes: test_count, test_cases array, implementation_scope, expected_coverage + +#### Required Outputs Summary + +##### 1. TDD Task JSON Files (.task/IMPL-*.json) +- **Location**: .workflow/active/${sessionId}/.task/ +- **Schema**: Unified flat schema (task-schema.json) with TDD-specific metadata + - meta.tdd_workflow: true (REQUIRED) + - meta.max_iterations: 3 (Green phase test-fix cycle limit) + - cli_execution.id: Unique CLI execution ID (format: {session_id}-{task_id}) + - cli_execution: Strategy object (new|resume|fork|merge_fork) + - tdd_cycles: Array with quantified test cases and coverage + - focus_paths: Absolute or clear relative paths (enhanced with exploration critical_files) + - implementation: Exactly 3 steps with tdd_phase field + 1. Red Phase (tdd_phase: "red"): Write failing tests + 2. Green Phase (tdd_phase: "green"): Implement to pass tests + 3. Refactor Phase (tdd_phase: "refactor"): Improve code quality + - pre_analysis: Include exploration integration_points analysis + - meta.execution_config: Set per userConfig.executionMethod (agent/cli/hybrid) + +##### 2. IMPL_PLAN.md (TDD Variant) +- **Location**: .workflow/active/${sessionId}/IMPL_PLAN.md +- **Template**: ~/.ccw/workflows/cli-templates/prompts/workflow/impl-plan-template.txt +- **TDD-Specific Frontmatter**: workflow_type="tdd", tdd_workflow=true, feature_count, task_breakdown + +##### 3. TODO_LIST.md +- **Location**: .workflow/active/${sessionId}/TODO_LIST.md +- **Format**: Hierarchical task list with internal TDD phase indicators (Red -> Green -> Refactor) + +### 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", "resume_from": ["id1", "id2", ...] } + +### Quantification Requirements (MANDATORY) + +**Core Rules**: +1. **Explicit Test Case Counts**: Red phase specifies exact number with enumerated list +2. **Quantified Coverage**: Acceptance includes measurable percentage (e.g., ">=85%") +3. **Detailed Implementation Scope**: Green phase enumerates files, functions, line counts +4. **Enumerated Refactoring Targets**: Refactor phase lists specific improvements with counts + +**TDD Phase Formats**: +- **Red Phase**: "Write N test cases: [test1, test2, ...]" +- **Green Phase**: "Implement N functions in file lines X-Y: [func1() X1-Y1, func2() X2-Y2, ...]" +- **Refactor Phase**: "Apply N refactorings: [improvement1 (details), improvement2 (details), ...]" +- **Acceptance**: "All N tests pass with >=X% coverage: verify by [test command]" + +## SUCCESS CRITERIA +- All planning documents generated successfully: + - Task JSONs valid and saved to .task/ directory with cli_execution.id + - IMPL_PLAN.md created with complete TDD structure + - TODO_LIST.md generated matching task JSONs +- CLI execution strategies assigned based on task dependencies +- Return completion status with document count and task breakdown summary +` +) ``` **Note**: Phase 0 now includes: @@ -46,15 +385,15 @@ Extract: feature count, task count, CLI execution IDs assigned - User configuration applied: - If executionMethod == "cli" or "hybrid": command field added to steps - CLI tool preference reflected in execution guidance -- Task count ≤18 (compliance with hard limit) +- Task count <=18 (compliance with hard limit) ### Red Flag Detection (Non-Blocking Warnings) -- Task count >18: `⚠️ Task count exceeds hard limit - request re-scope` -- Missing cli_execution.id: `⚠️ Task lacks CLI execution ID for resume support` -- Missing test-fix-cycle: `⚠️ Green phase lacks auto-revert configuration` -- Generic task names: `⚠️ Vague task names suggest unclear TDD cycles` -- Missing focus_paths: `⚠️ Task lacks clear file scope for implementation` +- Task count >18: `WARNING: Task count exceeds hard limit - request re-scope` +- Missing cli_execution.id: `WARNING: Task lacks CLI execution ID for resume support` +- Missing test-fix-cycle: `WARNING: Green phase lacks auto-revert configuration` +- Generic task names: `WARNING: Vague task names suggest unclear TDD cycles` +- Missing focus_paths: `WARNING: Task lacks clear file scope for implementation` **Action**: Log warnings to `.workflow/active/[sessionId]/.process/tdd-warnings.log` (non-blocking) @@ -66,16 +405,16 @@ Extract: feature count, task count, CLI execution IDs assigned {"content": "Phase 2: Context Gathering", "status": "completed", "activeForm": "Executing context gathering"}, {"content": "Phase 3: Test Coverage Analysis", "status": "completed", "activeForm": "Executing test coverage analysis"}, {"content": "Phase 5: TDD Task Generation", "status": "in_progress", "activeForm": "Executing TDD task generation"}, - {"content": " → Discovery - analyze TDD requirements", "status": "in_progress", "activeForm": "Analyzing TDD requirements"}, - {"content": " → Planning - design Red-Green-Refactor cycles", "status": "pending", "activeForm": "Designing TDD cycles"}, - {"content": " → Output - generate IMPL tasks with internal TDD phases", "status": "pending", "activeForm": "Generating TDD tasks"}, + {"content": " -> Discovery - analyze TDD requirements", "status": "in_progress", "activeForm": "Analyzing TDD requirements"}, + {"content": " -> Planning - design Red-Green-Refactor cycles", "status": "pending", "activeForm": "Designing TDD cycles"}, + {"content": " -> Output - generate IMPL tasks with internal TDD phases", "status": "pending", "activeForm": "Generating TDD tasks"}, {"content": "Phase 6: TDD Structure Validation", "status": "pending", "activeForm": "Validating TDD structure"} ] ``` -**Note**: Skill execute **attaches** task-generate-tdd's 3 tasks. Orchestrator **executes** these tasks. Each generated IMPL task will contain internal Red-Green-Refactor cycle. +**Note**: Agent execution **attaches** task-generate-tdd's 3 tasks. Orchestrator **executes** these tasks. Each generated IMPL task will contain internal Red-Green-Refactor cycle. -**Next Action**: Tasks attached → **Execute Phase 5.1-5.3** sequentially +**Next Action**: Tasks attached -> **Execute Phase 5.1-5.3** sequentially ### TodoWrite Update (Phase 5 completed - tasks collapsed) @@ -91,6 +430,70 @@ Extract: feature count, task count, CLI execution IDs assigned **Note**: Phase 5 tasks completed and collapsed to summary. Each generated IMPL task contains complete Red-Green-Refactor cycle internally. +## TDD Task Structure Reference + +**Quick Reference**: +- Each TDD task contains complete Red-Green-Refactor cycle +- Task ID format: `IMPL-N` (simple) or `IMPL-N.M` (complex subtasks) +- Required metadata: + - `meta.tdd_workflow: true` + - `meta.max_iterations: 3` + - `cli_execution.id: "{session_id}-{task_id}"` + - `cli_execution: { "strategy": "new|resume|fork|merge_fork", ... }` +- `tdd_cycles` array with quantified test cases and coverage: + ```javascript + tdd_cycles: [ + { + test_count: 5, + test_cases: ["case1", "case2"], + implementation_scope: "...", + expected_coverage: ">=85%" + } + ] + ``` +- `focus_paths` use absolute or clear relative paths +- `implementation`: Exactly 3 steps with `tdd_phase` field ("red", "green", "refactor") +- `pre_analysis`: includes exploration integration_points analysis +- **meta.execution_config**: Set per `userConfig.executionMethod` (agent/cli/hybrid) + +## Output Files Structure + +``` +.workflow/active/{session-id}/ +├── plan.json # Structured plan overview (TDD variant) +├── IMPL_PLAN.md # Unified plan with TDD Implementation Tasks section +├── TODO_LIST.md # Progress tracking with internal TDD phase indicators +├── .task/ +│ ├── IMPL-1.json # Complete TDD task (Red-Green-Refactor internally) +│ ├── IMPL-2.json # Complete TDD task +│ ├── IMPL-3.json # Complex feature container (if needed) +│ ├── IMPL-3.1.json # Complex feature subtask (if needed) +│ ├── IMPL-3.2.json # Complex feature subtask (if needed) +│ └── ... +└── .process/ + ├── conflict-resolution.json # Conflict resolution results (if conflict_risk >= medium) + ├── test-context-package.json # Test coverage analysis + ├── context-package.json # Input from context-gather + └── tdd-warnings.log # Non-blocking warnings +``` + +## Validation Rules + +### Task Completeness +- Every IMPL-N must contain complete TDD workflow in `implementation` +- Each task must have 3 steps with `tdd_phase`: "red", "green", "refactor" +- Every task must have `meta.tdd_workflow: true` + +### Dependency Enforcement +- Sequential features: IMPL-N depends_on ["IMPL-(N-1)"] if needed +- Complex feature subtasks: IMPL-N.M depends_on ["IMPL-N.(M-1)"] or parent dependencies +- No circular dependencies allowed + +### Task Limits +- Maximum 18 total tasks (simple + subtasks) - hard limit for TDD workflows +- Flat hierarchy (<=5 tasks) or two-level (6-18 tasks with containers) +- Re-scope requirements if >18 tasks needed + ## Output - **File**: `plan.json` (structured plan overview) diff --git a/.claude/skills/workflow-tdd/phases/06-tdd-structure-validation.md b/.claude/skills/workflow-tdd/phases/06-tdd-structure-validation.md index 7b661934..70cdd141 100644 --- a/.claude/skills/workflow-tdd/phases/06-tdd-structure-validation.md +++ b/.claude/skills/workflow-tdd/phases/06-tdd-structure-validation.md @@ -163,7 +163,7 @@ if (userChoice === "Verify TDD Compliance (Recommended)") { } ``` -**Auto Mode (--yes)**: Auto-select "Verify TDD Compliance", then auto-continue to execute if quality gate is APPROVED. +**Auto Mode**: When `workflowPreferences.autoYes` is true, auto-select "Verify TDD Compliance", then auto-continue to execute if quality gate is APPROVED. ## Output diff --git a/.claude/skills/workflow-tdd/phases/07-tdd-verify.md b/.claude/skills/workflow-tdd/phases/07-tdd-verify.md index 084db1c8..174c3d9c 100644 --- a/.claude/skills/workflow-tdd/phases/07-tdd-verify.md +++ b/.claude/skills/workflow-tdd/phases/07-tdd-verify.md @@ -12,7 +12,7 @@ Full TDD compliance verification with quality gate reporting. Generates comprehe ## Operating Constraints **ORCHESTRATOR MODE**: -- This phase coordinates sub-steps and `/workflow:tools:tdd-coverage-analysis` +- This phase coordinates sub-steps and inline TDD coverage analysis - MAY write output files: TDD_COMPLIANCE_REPORT.md (primary report), .process/*.json (intermediate artifacts) - MUST NOT modify source task files or implementation code - MUST NOT create or delete tasks in the workflow @@ -120,9 +120,183 @@ Calculate: ### Step 7.3: Coverage & Cycle Analysis -**Call Coverage Analysis Sub-command**: -```javascript -Skill(skill="workflow:tools:tdd-coverage-analysis", args="--session {session_id}") +**Execute TDD Coverage Analysis**: + +#### Phase 3a: Extract Test Tasks + +```bash +# Find TEST task files and extract focus_paths +find .workflow/active/{session_id}/.task/ -name 'TEST-*.json' -exec jq -r '.context.focus_paths[]' {} \; +``` + +**Output**: List of test directories/files from all TEST tasks + +#### Phase 3b: Run Test Suite + +```bash +# Auto-detect test framework from project +if [ -f "package.json" ] && grep -q "jest\|mocha\|vitest" package.json; then + TEST_CMD="npm test -- --coverage --json" +elif [ -f "pytest.ini" ] || [ -f "setup.py" ]; then + TEST_CMD="pytest --cov --json-report" +elif [ -f "Cargo.toml" ]; then + TEST_CMD="cargo test -- --test-threads=1 --nocapture" +elif [ -f "go.mod" ]; then + TEST_CMD="go test -coverprofile=coverage.out -json ./..." +else + TEST_CMD="echo 'No supported test framework found'" +fi + +# Execute test suite with coverage +$TEST_CMD > .workflow/active/{session_id}/.process/test-results.json +``` + +**Output**: test-results.json with coverage data + +#### Phase 3c: Parse Coverage Data + +```bash +jq '.coverage' .workflow/active/{session_id}/.process/test-results.json > .workflow/active/{session_id}/.process/coverage-report.json +``` + +**Extract**: +- Line coverage percentage +- Branch coverage percentage +- Function coverage percentage +- Uncovered lines/branches + +#### Phase 3d: Verify TDD Cycle + +For each TDD chain (TEST-N.M -> IMPL-N.M -> REFACTOR-N.M): + +**1. Red Phase Verification** +```bash +cat .workflow/active/{session_id}/.summaries/TEST-N.M-summary.md +``` + +Verify: +- Tests were created +- Tests failed initially +- Failure messages were clear + +**2. Green Phase Verification** +```bash +cat .workflow/active/{session_id}/.summaries/IMPL-N.M-summary.md +``` + +Verify: +- Implementation was completed +- Tests now pass +- Implementation was minimal + +**3. Refactor Phase Verification** +```bash +cat .workflow/active/{session_id}/.summaries/REFACTOR-N.M-summary.md +``` + +Verify: +- Refactoring was completed +- Tests still pass +- Code quality improved + +#### TDD Cycle Verification Algorithm + +``` +For each feature N: + 1. Load TEST-N.M-summary.md + IF summary missing: + Mark: "Red phase incomplete" + SKIP to next feature + + CHECK: Contains "test" AND "fail" + IF NOT found: + Mark: "Red phase verification failed" + ELSE: + Mark: "Red phase [PASS]" + + 2. Load IMPL-N.M-summary.md + IF summary missing: + Mark: "Green phase incomplete" + SKIP to next feature + + CHECK: Contains "pass" OR "green" + IF NOT found: + Mark: "Green phase verification failed" + ELSE: + Mark: "Green phase [PASS]" + + 3. Load REFACTOR-N.M-summary.md + IF summary missing: + Mark: "Refactor phase incomplete" + CONTINUE (refactor is optional) + + CHECK: Contains "refactor" AND "pass" + IF NOT found: + Mark: "Refactor phase verification failed" + ELSE: + Mark: "Refactor phase [PASS]" + + 4. Calculate chain score: + - Red + Green + Refactor all [PASS] = 100% + - Red + Green [PASS], Refactor missing = 80% + - Red [PASS], Green missing = 40% + - All missing = 0% +``` + +#### Phase 3e: Generate Analysis Report + +Create `.workflow/active/{session_id}/.process/tdd-cycle-report.md`: + +```markdown +# TDD Cycle Analysis - {Session ID} + +## Coverage Metrics +- **Line Coverage**: {percentage}% +- **Branch Coverage**: {percentage}% +- **Function Coverage**: {percentage}% + +## Coverage Details +### Covered +- {covered_lines} lines +- {covered_branches} branches +- {covered_functions} functions + +### Uncovered +- Lines: {uncovered_line_numbers} +- Branches: {uncovered_branch_locations} + +## TDD Cycle Verification + +### Feature 1: {Feature Name} +**Chain**: TEST-1.1 -> IMPL-1.1 -> REFACTOR-1.1 + +- [PASS] **Red Phase**: Tests created and failed initially +- [PASS] **Green Phase**: Implementation made tests pass +- [PASS] **Refactor Phase**: Refactoring maintained green tests + +[Repeat for all features] + +## TDD Compliance Summary +- **Total Chains**: {N} +- **Complete Cycles**: {N} +- **Incomplete Cycles**: {0} +- **Compliance Score**: {score}/100 + +## Gaps Identified +- {gap descriptions} + +## Recommendations +- {improvement suggestions} +``` + +#### Coverage Metrics Calculation + +```bash +line_coverage=$(jq '.coverage.lineCoverage' test-results.json) +branch_coverage=$(jq '.coverage.branchCoverage' test-results.json) +function_coverage=$(jq '.coverage.functionCoverage' test-results.json) + +overall_score=$(echo "($line_coverage + $branch_coverage + $function_coverage) / 3" | bc) ``` **Parse Output Files**: @@ -432,7 +606,7 @@ Next: Review full report for detailed findings |-------|-------|------------| | Coverage tool missing | No test framework | Configure testing first | | Tests fail to run | Code errors | Fix errors before verify | -| Sub-command fails | tdd-coverage-analysis error | Check sub-command logs | +| Coverage analysis fails | Test framework or coverage tool error | Check test framework configuration | ## Output @@ -445,9 +619,9 @@ Next: Review full report for detailed findings .workflow/active/WFS-{session-id}/ ├── TDD_COMPLIANCE_REPORT.md # Comprehensive compliance report ⭐ └── .process/ - ├── test-results.json # From tdd-coverage-analysis - ├── coverage-report.json # From tdd-coverage-analysis - └── tdd-cycle-report.md # From tdd-coverage-analysis + ├── test-results.json # From coverage analysis (Step 7.3) + ├── coverage-report.json # From coverage analysis (Step 7.3) + └── tdd-cycle-report.md # From coverage analysis (Step 7.3) ``` ## Next Steps Decision Table diff --git a/.claude/skills/workflow-test-fix/SKILL.md b/.claude/skills/workflow-test-fix/SKILL.md index cf160195..f61bed5f 100644 --- a/.claude/skills/workflow-test-fix/SKILL.md +++ b/.claude/skills/workflow-test-fix/SKILL.md @@ -69,9 +69,31 @@ Task Pipeline (generated in Phase 4, executed in Phase 5): /workflow:test-cycle-execute --max-iterations=15 ``` -## Auto Mode +## Interactive Preference Collection -When `--yes` or `-y`: Auto-select first active session, skip confirmations, auto-complete on success. +Before dispatching to phase execution, collect workflow preferences via AskUserQuestion: + +```javascript +const prefResponse = AskUserQuestion({ + questions: [ + { + question: "是否跳过所有确认步骤(自动模式)?", + header: "Auto Mode", + multiSelect: false, + options: [ + { label: "Interactive (Recommended)", description: "交互模式,包含确认步骤" }, + { label: "Auto", description: "跳过所有确认,自动执行" } + ] + } + ] +}) + +workflowPreferences = { + autoYes: prefResponse.autoMode === 'Auto' +} +``` + +**workflowPreferences** is passed to phase execution as context variable, referenced as `workflowPreferences.autoYes` within phases. ## Execution Flow diff --git a/.claude/skills/workflow-test-fix/phases/02-test-context-gather.md b/.claude/skills/workflow-test-fix/phases/02-test-context-gather.md index 7aae42cc..39cdc2f2 100644 --- a/.claude/skills/workflow-test-fix/phases/02-test-context-gather.md +++ b/.claude/skills/workflow-test-fix/phases/02-test-context-gather.md @@ -11,14 +11,441 @@ Gather test context via coverage analysis or codebase scan. ### Step 1.2: Gather Test Context -``` -// Session Mode - gather from source session -Skill(skill="workflow:tools:test-context-gather", args="--session [testSessionId]") +Two modes are available depending on whether a source session exists: -// Prompt Mode - gather from codebase -Skill(skill="workflow:tools:context-gather", args="--session [testSessionId] \"[task_description]\"") +--- + +### Mode A: Session Mode (gather from source session) + +Collect test coverage context using test-context-search-agent and package into standardized test-context JSON. + +#### Core Philosophy + +- **Agent Delegation**: Delegate all test coverage analysis to `test-context-search-agent` for autonomous execution +- **Detection-First**: Check for existing test-context-package before executing +- **Coverage-First**: Analyze existing test coverage before planning new tests +- **Source Context Loading**: Import implementation summaries from source session +- **Standardized Output**: Generate `.workflow/active/{test_session_id}/.process/test-context-package.json` + +#### Step A.1: Test-Context-Package Detection + +**Execute First** - Check if valid package already exists: + +```javascript +const testContextPath = `.workflow/${test_session_id}/.process/test-context-package.json`; + +if (file_exists(testContextPath)) { + const existing = Read(testContextPath); + + // Validate package belongs to current test session + if (existing?.metadata?.test_session_id === test_session_id) { + console.log("Valid test-context-package found for session:", test_session_id); + console.log("Coverage Stats:", existing.test_coverage.coverage_stats); + console.log("Framework:", existing.test_framework.framework); + console.log("Missing Tests:", existing.test_coverage.missing_tests.length); + return existing; // Skip execution, return existing + } else { + console.warn("Invalid test_session_id in existing package, re-generating..."); + } +} ``` +#### Step A.2: Invoke Test-Context-Search Agent + +**Only execute if Step A.1 finds no valid package** + +```javascript +Task( + subagent_type="test-context-search-agent", + run_in_background=false, + description="Gather test coverage context", + prompt=` + +## Execution Mode +**PLAN MODE** (Comprehensive) - Full Phase 1-3 execution + +## Session Information +- **Test Session ID**: ${test_session_id} +- **Output Path**: .workflow/${test_session_id}/.process/test-context-package.json + +## Mission +Execute complete test-context-search-agent workflow for test generation planning: + +### Phase 1: Session Validation & Source Context Loading +1. **Detection**: Check for existing test-context-package (early exit if valid) +2. **Test Session Validation**: Load test session metadata, extract source_session reference +3. **Source Context Loading**: Load source session implementation summaries, changed files, tech stack + +### Phase 2: Test Coverage Analysis +Execute coverage discovery: +- **Track 1**: Existing test discovery (find *.test.*, *.spec.* files) +- **Track 2**: Coverage gap analysis (match implementation files to test files) +- **Track 3**: Coverage statistics (calculate percentages, identify gaps by module) + +### Phase 3: Framework Detection & Packaging +1. Framework identification from package.json/requirements.txt +2. Convention analysis from existing test patterns +3. Generate and validate test-context-package.json + +## Output Requirements +Complete test-context-package.json with: +- **metadata**: test_session_id, source_session_id, task_type, complexity +- **source_context**: implementation_summaries, tech_stack, project_patterns +- **test_coverage**: existing_tests[], missing_tests[], coverage_stats +- **test_framework**: framework, version, test_pattern, conventions +- **assets**: implementation_summary[], existing_test[], source_code[] with priorities +- **focus_areas**: Test generation guidance based on coverage gaps + +## Quality Validation +Before completion verify: +- [ ] Valid JSON format with all required fields +- [ ] Source session context loaded successfully +- [ ] Test coverage gaps identified +- [ ] Test framework detected (or marked as 'unknown') +- [ ] Coverage percentage calculated correctly +- [ ] Missing tests catalogued with priority +- [ ] Execution time < 30 seconds (< 60s for large codebases) + +Execute autonomously following agent documentation. +Report completion with coverage statistics. +` +) +``` + +#### Step A.3: Output Verification + +After agent completes, verify output: + +```javascript +// Verify file was created +const outputPath = `.workflow/${test_session_id}/.process/test-context-package.json`; +if (!file_exists(outputPath)) { + throw new Error("Agent failed to generate test-context-package.json"); +} + +// Load and display summary +const testContext = Read(outputPath); +console.log("Test context package generated successfully"); +console.log("Coverage:", testContext.test_coverage.coverage_stats.coverage_percentage + "%"); +console.log("Tests to generate:", testContext.test_coverage.missing_tests.length); +``` + +--- + +### Mode B: Prompt Mode (gather from codebase) + +Intelligently collect project context using context-search-agent based on task description, packages into standardized JSON. + +#### Core Philosophy + +- **Agent Delegation**: Delegate all discovery to `context-search-agent` for autonomous execution +- **Detection-First**: Check for existing context-package before executing +- **Plan Mode**: Full comprehensive analysis (vs lightweight brainstorm mode) +- **Standardized Output**: Generate `.workflow/active/{session}/.process/context-package.json` + +#### Step B.1: Context-Package Detection + +**Execute First** - Check if valid package already exists: + +```javascript +const contextPackagePath = `.workflow/${session_id}/.process/context-package.json`; + +if (file_exists(contextPackagePath)) { + const existing = Read(contextPackagePath); + + // Validate package belongs to current session + if (existing?.metadata?.session_id === session_id) { + console.log("Valid context-package found for session:", session_id); + console.log("Stats:", existing.statistics); + console.log("Conflict Risk:", existing.conflict_detection.risk_level); + return existing; // Skip execution, return existing + } else { + console.warn("Invalid session_id in existing package, re-generating..."); + } +} +``` + +#### Step B.2: Complexity Assessment & Parallel Explore + +**Only execute if Step B.1 finds no valid package** + +```javascript +// B.2.1 Complexity Assessment +function analyzeTaskComplexity(taskDescription) { + const text = taskDescription.toLowerCase(); + if (/architect|refactor|restructure|modular|cross-module/.test(text)) return 'High'; + if (/multiple|several|integrate|migrate|extend/.test(text)) return 'Medium'; + return 'Low'; +} + +const ANGLE_PRESETS = { + architecture: ['architecture', 'dependencies', 'modularity', 'integration-points'], + security: ['security', 'auth-patterns', 'dataflow', 'validation'], + performance: ['performance', 'bottlenecks', 'caching', 'data-access'], + bugfix: ['error-handling', 'dataflow', 'state-management', 'edge-cases'], + feature: ['patterns', 'integration-points', 'testing', 'dependencies'], + refactor: ['architecture', 'patterns', 'dependencies', 'testing'] +}; + +function selectAngles(taskDescription, complexity) { + const text = taskDescription.toLowerCase(); + let preset = 'feature'; + if (/refactor|architect|restructure/.test(text)) preset = 'architecture'; + else if (/security|auth|permission/.test(text)) preset = 'security'; + else if (/performance|slow|optimi/.test(text)) preset = 'performance'; + else if (/fix|bug|error|issue/.test(text)) preset = 'bugfix'; + + const count = complexity === 'High' ? 4 : (complexity === 'Medium' ? 3 : 1); + return ANGLE_PRESETS[preset].slice(0, count); +} + +const complexity = analyzeTaskComplexity(task_description); +const selectedAngles = selectAngles(task_description, complexity); +const sessionFolder = `.workflow/active/${session_id}/.process`; + +// B.2.2 Launch Parallel Explore Agents +const explorationTasks = selectedAngles.map((angle, index) => + Task( + subagent_type="cli-explore-agent", + run_in_background=false, + description=`Explore: ${angle}`, + prompt=` +## Task Objective +Execute **${angle}** exploration for task planning context. Analyze codebase from this specific angle to discover relevant structure, patterns, and constraints. + +## Assigned Context +- **Exploration Angle**: ${angle} +- **Task Description**: ${task_description} +- **Session ID**: ${session_id} +- **Exploration Index**: ${index + 1} of ${selectedAngles.length} +- **Output File**: ${sessionFolder}/exploration-${angle}.json + +## MANDATORY FIRST STEPS (Execute by Agent) +1. Run: ccw tool exec get_modules_by_depth '{}' (project structure) +2. Run: rg -l "{keyword_from_task}" --type ts (locate relevant files) +3. Execute: cat ~/.ccw/workflows/cli-templates/schemas/explore-json-schema.json (get output schema reference) + +## Exploration Strategy (${angle} focus) + +**Step 1: Structural Scan** (Bash) +- get_modules_by_depth.sh -> identify modules related to ${angle} +- find/rg -> locate files relevant to ${angle} aspect +- Analyze imports/dependencies from ${angle} perspective + +**Step 2: Semantic Analysis** (Gemini CLI) +- How does existing code handle ${angle} concerns? +- What patterns are used for ${angle}? +- Where would new code integrate from ${angle} viewpoint? + +**Step 3: Write Output** +- Consolidate ${angle} findings into JSON +- Identify ${angle}-specific clarification needs + +## Expected Output + +**File**: ${sessionFolder}/exploration-${angle}.json + +**Schema Reference**: Schema obtained in MANDATORY FIRST STEPS step 3, follow schema exactly + +**Required Fields** (all ${angle} focused): +- project_structure: Modules/architecture relevant to ${angle} +- relevant_files: Files affected from ${angle} perspective + **MANDATORY**: Every file MUST use structured object format with ALL required fields: + [{path: "src/file.ts", relevance: 0.85, rationale: "Contains AuthService.login() - entry point for JWT token generation", role: "modify_target", discovery_source: "bash-scan", key_symbols: ["AuthService", "login"]}] + - **rationale** (required): Specific selection basis tied to ${angle} topic (>10 chars, not generic) + - **role** (required): modify_target|dependency|pattern_reference|test_target|type_definition|integration_point|config|context_only + - **discovery_source** (recommended): bash-scan|cli-analysis|ace-search|dependency-trace|manual + - **key_symbols** (recommended): Key functions/classes/types in the file relevant to the task + - Scores: 0.7+ high priority, 0.5-0.7 medium, <0.5 low +- patterns: ${angle}-related patterns to follow +- dependencies: Dependencies relevant to ${angle} +- integration_points: Where to integrate from ${angle} viewpoint (include file:line locations) +- constraints: ${angle}-specific limitations/conventions +- clarification_needs: ${angle}-related ambiguities (options array + recommended index) +- _metadata.exploration_angle: "${angle}" + +## Success Criteria +- [ ] Schema obtained via cat explore-json-schema.json +- [ ] get_modules_by_depth.sh executed +- [ ] At least 3 relevant files identified with ${angle} rationale +- [ ] Patterns are actionable (code examples, not generic advice) +- [ ] Integration points include file:line locations +- [ ] Constraints are project-specific to ${angle} +- [ ] JSON output follows schema exactly +- [ ] clarification_needs includes options + recommended + +## Output +Write: ${sessionFolder}/exploration-${angle}.json +Return: 2-3 sentence summary of ${angle} findings +` + ) +); + +// B.2.3 Generate Manifest after all complete +const explorationFiles = bash(`find ${sessionFolder} -name "exploration-*.json" -type f`).split('\n').filter(f => f.trim()); +const explorationManifest = { + session_id, + task_description, + timestamp: new Date().toISOString(), + complexity, + exploration_count: selectedAngles.length, + angles_explored: selectedAngles, + explorations: explorationFiles.map(file => { + const data = JSON.parse(Read(file)); + return { angle: data._metadata.exploration_angle, file: file.split('/').pop(), path: file, index: data._metadata.exploration_index }; + }) +}; +Write(`${sessionFolder}/explorations-manifest.json`, JSON.stringify(explorationManifest, null, 2)); +``` + +#### Step B.3: Invoke Context-Search Agent + +**Only execute after Step B.2 completes** + +```javascript +// Load user intent from planning-notes.md (from Phase 1) +const planningNotesPath = `.workflow/active/${session_id}/planning-notes.md`; +let userIntent = { goal: task_description, key_constraints: "None specified" }; + +if (file_exists(planningNotesPath)) { + const notesContent = Read(planningNotesPath); + const goalMatch = notesContent.match(/\*\*GOAL\*\*:\s*(.+)/); + const constraintsMatch = notesContent.match(/\*\*KEY_CONSTRAINTS\*\*:\s*(.+)/); + if (goalMatch) userIntent.goal = goalMatch[1].trim(); + if (constraintsMatch) userIntent.key_constraints = constraintsMatch[1].trim(); +} + +Task( + subagent_type="context-search-agent", + run_in_background=false, + description="Gather comprehensive context for plan", + prompt=` +## Execution Mode +**PLAN MODE** (Comprehensive) - Full Phase 1-3 execution with priority sorting + +## Session Information +- **Session ID**: ${session_id} +- **Task Description**: ${task_description} +- **Output Path**: .workflow/${session_id}/.process/context-package.json + +## User Intent (from Phase 1 - Planning Notes) +**GOAL**: ${userIntent.goal} +**KEY_CONSTRAINTS**: ${userIntent.key_constraints} + +This is the PRIMARY context source - all subsequent analysis must align with user intent. + +## Exploration Input (from Step B.2) +- **Manifest**: ${sessionFolder}/explorations-manifest.json +- **Exploration Count**: ${explorationManifest.exploration_count} +- **Angles**: ${explorationManifest.angles_explored.join(', ')} +- **Complexity**: ${complexity} + +## Mission +Execute complete context-search-agent workflow for implementation planning: + +### Phase 1: Initialization & Pre-Analysis +1. **Project State Loading**: + - Read and parse .workflow/project-tech.json. Use its overview section as the foundational project_context. + - Read and parse .workflow/project-guidelines.json. Load conventions, constraints, and learnings into a project_guidelines section. + - If files don't exist, proceed with fresh analysis. +2. **Detection**: Check for existing context-package (early exit if valid) +3. **Foundation**: Initialize CodexLens, get project structure, load docs +4. **Analysis**: Extract keywords, determine scope, classify complexity based on task description and project state + +### Phase 2: Multi-Source Context Discovery +Execute all discovery tracks (WITH USER INTENT INTEGRATION): +- **Track -1**: User Intent & Priority Foundation (EXECUTE FIRST) + - Load user intent (GOAL, KEY_CONSTRAINTS) from session input + - Map user requirements to codebase entities (files, modules, patterns) + - Establish baseline priority scores based on user goal alignment + - Output: user_intent_mapping.json with preliminary priority scores + +- **Track 0**: Exploration Synthesis (load explorations-manifest.json, prioritize critical_files, deduplicate patterns/integration_points) +- **Track 1**: Historical archive analysis (query manifest.json for lessons learned) +- **Track 2**: Reference documentation (CLAUDE.md, architecture docs) +- **Track 3**: Web examples (use Exa MCP for unfamiliar tech/APIs) +- **Track 4**: Codebase analysis (5-layer discovery: files, content, patterns, deps, config/tests) + +### Phase 3: Synthesis, Assessment & Packaging +1. Apply relevance scoring and build dependency graph +2. **Synthesize 5-source data** (including Track -1): Merge findings from all sources + - Priority order: User Intent > Archive > Docs > Exploration > Code > Web + - **Prioritize the context from project-tech.json** for architecture and tech stack unless code analysis reveals it's outdated +3. **Context Priority Sorting**: + a. Combine scores from Track -1 (user intent alignment) + relevance scores + exploration critical_files + b. Classify files into priority tiers: + - **Critical** (score >= 0.85): Directly mentioned in user goal OR exploration critical_files + - **High** (0.70-0.84): Key dependencies, patterns required for goal + - **Medium** (0.50-0.69): Supporting files, indirect dependencies + - **Low** (< 0.50): Contextual awareness only + c. Generate dependency_order: Based on dependency graph + user goal sequence + d. Document sorting_rationale: Explain prioritization logic +4. **Populate project_context**: Directly use the overview from project-tech.json +5. **Populate project_guidelines**: Load from project-guidelines.json +6. Integrate brainstorm artifacts (if .brainstorming/ exists, read content) +7. Perform conflict detection with risk assessment +8. **Inject historical conflicts** from archive analysis into conflict_detection +9. **Generate prioritized_context section**: + { + "prioritized_context": { + "user_intent": { "goal": "...", "scope": "...", "key_constraints": ["..."] }, + "priority_tiers": { + "critical": [{ "path": "...", "relevance": 0.95, "rationale": "..." }], + "high": [...], "medium": [...], "low": [...] + }, + "dependency_order": ["module1", "module2", "module3"], + "sorting_rationale": "Based on user goal alignment, exploration critical files, and dependency graph" + } + } +10. Generate and validate context-package.json with prioritized_context field + +## Output Requirements +Complete context-package.json with: +- **metadata**: task_description, keywords, complexity, tech_stack, session_id +- **project_context**: description, technology_stack, architecture, key_components (from project-tech.json) +- **project_guidelines**: {conventions, constraints, quality_rules, learnings} (from project-guidelines.json) +- **assets**: {documentation[], source_code[], config[], tests[]} with relevance scores +- **dependencies**: {internal[], external[]} with dependency graph +- **brainstorm_artifacts**: {guidance_specification, role_analyses[], synthesis_output} with content +- **conflict_detection**: {risk_level, risk_factors, affected_modules[], mitigation_strategy, historical_conflicts[]} +- **exploration_results**: {manifest_path, exploration_count, angles, explorations[], aggregated_insights} +- **prioritized_context**: {user_intent, priority_tiers{critical, high, medium, low}, dependency_order[], sorting_rationale} + +## Quality Validation +Before completion verify: +- [ ] Valid JSON format with all required fields +- [ ] File relevance accuracy >80% +- [ ] Dependency graph complete (max 2 transitive levels) +- [ ] Conflict risk level calculated correctly +- [ ] No sensitive data exposed +- [ ] Total files <= 50 (prioritize high-relevance) + +Execute autonomously following agent documentation. +Report completion with statistics. +` +) +``` + +#### Step B.4: Output Verification + +After agent completes, verify output: + +```javascript +// Verify file was created +const outputPath = `.workflow/${session_id}/.process/context-package.json`; +if (!file_exists(outputPath)) { + throw new Error("Agent failed to generate context-package.json"); +} + +// Verify exploration_results included +const pkg = JSON.parse(Read(outputPath)); +if (pkg.exploration_results?.exploration_count > 0) { + console.log(`Exploration results aggregated: ${pkg.exploration_results.exploration_count} angles`); +} +``` + +--- + **Input**: `testSessionId` from Phase 1 **Parse Output**: @@ -34,13 +461,13 @@ Skill(skill="workflow:tools:context-gather", args="--session [testSessionId] \"[ ```json [ {"content": "Phase 1: Test Generation", "status": "in_progress"}, - {"content": " → Create test session", "status": "completed"}, - {"content": " → Gather test context", "status": "in_progress"}, - {"content": " → Load source/codebase context", "status": "in_progress"}, - {"content": " → Analyze test coverage", "status": "pending"}, - {"content": " → Generate context package", "status": "pending"}, - {"content": " → Test analysis (Gemini)", "status": "pending"}, - {"content": " → Generate test tasks", "status": "pending"}, + {"content": " -> Create test session", "status": "completed"}, + {"content": " -> Gather test context", "status": "in_progress"}, + {"content": " -> Load source/codebase context", "status": "in_progress"}, + {"content": " -> Analyze test coverage", "status": "pending"}, + {"content": " -> Generate context package", "status": "pending"}, + {"content": " -> Test analysis (Gemini)", "status": "pending"}, + {"content": " -> Generate test tasks", "status": "pending"}, {"content": "Phase 2: Test Cycle Execution", "status": "pending"} ] ``` @@ -49,10 +476,10 @@ Skill(skill="workflow:tools:context-gather", args="--session [testSessionId] \"[ ```json [ {"content": "Phase 1: Test Generation", "status": "in_progress"}, - {"content": " → Create test session", "status": "completed"}, - {"content": " → Gather test context", "status": "completed"}, - {"content": " → Test analysis (Gemini)", "status": "pending"}, - {"content": " → Generate test tasks", "status": "pending"}, + {"content": " -> Create test session", "status": "completed"}, + {"content": " -> Gather test context", "status": "completed"}, + {"content": " -> Test analysis (Gemini)", "status": "pending"}, + {"content": " -> Generate test tasks", "status": "pending"}, {"content": "Phase 2: Test Cycle Execution", "status": "pending"} ] ``` diff --git a/.claude/skills/workflow-test-fix/phases/03-test-concept-enhanced.md b/.claude/skills/workflow-test-fix/phases/03-test-concept-enhanced.md index 2613bc6c..ed02edf9 100644 --- a/.claude/skills/workflow-test-fix/phases/03-test-concept-enhanced.md +++ b/.claude/skills/workflow-test-fix/phases/03-test-concept-enhanced.md @@ -9,13 +9,95 @@ Analyze test requirements with Gemini using progressive L0-L3 test layers. - Generate multi-layered test requirements (L0-L3) - Scan for AI code issues +## Core Philosophy + +- **Coverage-Driven**: Focus on identified test gaps from context analysis +- **Pattern-Based**: Learn from existing tests and project conventions +- **Gemini-Powered**: Use Gemini for test requirement analysis and strategy design +- **Single-Round Analysis**: Comprehensive test analysis in one execution +- **No Code Generation**: Strategy and planning only, actual test generation happens in task execution + +## Core Responsibilities + +- Coordinate test analysis workflow using cli-execution-agent +- Validate test-context-package.json prerequisites +- Execute Gemini analysis via agent for test strategy generation +- Validate agent outputs (gemini-test-analysis.md, TEST_ANALYSIS_RESULTS.md) + ## Execution ### Step 1.3: Test Generation Analysis +#### Phase 1: Context Preparation + +**Command prepares session context and validates prerequisites.** + +1. **Session Validation** + - Load `.workflow/active/{test_session_id}/workflow-session.json` + - Verify test session type is "test-gen" + - Extract source session reference + +2. **Context Package Validation** + - Read `test-context-package.json` + - Validate required sections: metadata, source_context, test_coverage, test_framework + - Extract coverage gaps and framework details + +3. **Strategy Determination** + - **Simple** (1-3 files): Single Gemini analysis + - **Medium** (4-6 files): Comprehensive analysis + - **Complex** (>6 files): Modular analysis approach + +#### Phase 2: Test Analysis Execution + +**Purpose**: Analyze test coverage gaps and generate comprehensive test strategy. + +```javascript +Task( + subagent_type="cli-execution-agent", + run_in_background=false, + description="Analyze test coverage gaps and generate test strategy", + prompt=` +## TASK OBJECTIVE +Analyze test requirements and generate comprehensive test generation strategy using Gemini CLI + +## EXECUTION CONTEXT +Session: {test_session_id} +Source Session: {source_session_id} +Working Dir: .workflow/active/{test_session_id}/.process +Template: ~/.ccw/workflows/cli-templates/prompts/test/test-concept-analysis.txt + +## EXECUTION STEPS +1. Execute Gemini analysis: + ccw cli -p "..." --tool gemini --mode write --rule test-test-concept-analysis --cd .workflow/active/{test_session_id}/.process + +2. Generate TEST_ANALYSIS_RESULTS.md: + Synthesize gemini-test-analysis.md into standardized format for task generation + Include: coverage assessment, test framework, test requirements, generation strategy, implementation targets + +## EXPECTED OUTPUTS +1. gemini-test-analysis.md - Raw Gemini analysis +2. TEST_ANALYSIS_RESULTS.md - Standardized test requirements document + +## QUALITY VALIDATION +- Both output files exist and are complete +- All required sections present in TEST_ANALYSIS_RESULTS.md +- Test requirements are actionable and quantified +- Test scenarios cover happy path, errors, edge cases +- Dependencies and mocks clearly identified +` +) ``` -Skill(skill="workflow:tools:test-concept-enhanced", args="--session [testSessionId] --context [contextPath]") -``` + +**Output Files**: +- `.workflow/active/{test_session_id}/.process/gemini-test-analysis.md` +- `.workflow/active/{test_session_id}/.process/TEST_ANALYSIS_RESULTS.md` + +#### Phase 3: Output Validation + +- Verify `gemini-test-analysis.md` exists and is complete +- Validate `TEST_ANALYSIS_RESULTS.md` generated by agent +- Check required sections present +- Confirm test requirements are actionable **Input**: - `testSessionId` from Phase 1 @@ -40,7 +122,24 @@ Skill(skill="workflow:tools:test-concept-enhanced", args="--session [testSession - Quality Assurance Criteria - Success Criteria -**Note**: Detailed specifications for project types, L0-L3 layers, and AI issue detection are defined in `/workflow:tools:test-concept-enhanced`. +## Error Handling + +### Validation Errors +| Error | Resolution | +|-------|------------| +| Missing context package | Run test-context-gather first | +| No coverage gaps | Skip test generation, proceed to execution | +| No test framework detected | Configure test framework | +| Invalid source session | Complete implementation first | + +### Execution Errors +| Error | Recovery | +|-------|----------| +| Gemini timeout | Reduce scope, analyze by module | +| Output incomplete | Retry with focused analysis | +| No output file | Check directory permissions | + +**Fallback Strategy**: Generate basic TEST_ANALYSIS_RESULTS.md from context package if Gemini fails ## Output diff --git a/.claude/skills/workflow-test-fix/phases/04-test-task-generate.md b/.claude/skills/workflow-test-fix/phases/04-test-task-generate.md index 76576369..5c4d3b77 100644 --- a/.claude/skills/workflow-test-fix/phases/04-test-task-generate.md +++ b/.claude/skills/workflow-test-fix/phases/04-test-task-generate.md @@ -1,6 +1,6 @@ # Phase 4: Test Task Generate (test-task-generate) -Generate test task JSONs via action-planning-agent. +Generate test task JSONs via test-action-planning-agent. ## Objective @@ -11,13 +11,282 @@ Generate test task JSONs via action-planning-agent. ### Step 1.4: Generate Test Tasks +#### Phase 1: Context Preparation + +**Purpose**: Assemble test session paths, load test analysis context, and create test-planning-notes.md. + +**Execution Steps**: +1. Parse `--session` flag to get test session ID +2. Load `workflow-session.json` for session metadata +3. Verify `TEST_ANALYSIS_RESULTS.md` exists (from test-concept-enhanced) +4. Load `test-context-package.json` for coverage data +5. Create `test-planning-notes.md` with initial context + +**After Phase 1**: Initialize test-planning-notes.md + +```javascript +// Create test-planning-notes.md with N+1 context support +const testPlanningNotesPath = `.workflow/active/${testSessionId}/test-planning-notes.md` +const sessionMetadata = JSON.parse(Read(`.workflow/active/${testSessionId}/workflow-session.json`)) +const testAnalysis = Read(`.workflow/active/${testSessionId}/.process/TEST_ANALYSIS_RESULTS.md`) +const sourceSessionId = sessionMetadata.source_session_id || 'N/A' + +// Extract key info from TEST_ANALYSIS_RESULTS.md +const projectType = testAnalysis.match(/Project Type:\s*(.+)/)?.[1] || 'Unknown' +const testFramework = testAnalysis.match(/Test Framework:\s*(.+)/)?.[1] || 'Unknown' +const coverageTarget = testAnalysis.match(/Coverage Target:\s*(.+)/)?.[1] || '80%' + +Write(testPlanningNotesPath, `# Test Planning Notes + +**Session**: ${testSessionId} +**Source Session**: ${sourceSessionId} +**Created**: ${new Date().toISOString()} + +## Test Intent (Phase 1) + +- **PROJECT_TYPE**: ${projectType} +- **TEST_FRAMEWORK**: ${testFramework} +- **COVERAGE_TARGET**: ${coverageTarget} +- **SOURCE_SESSION**: ${sourceSessionId} + +--- + +## Context Findings (Phase 1) + +### Files with Coverage Gaps +(Extracted from TEST_ANALYSIS_RESULTS.md) + +### Test Framework & Conventions +- Framework: ${testFramework} +- Coverage Target: ${coverageTarget} + +--- + +## Gemini Enhancement (Phase 1.5) +(To be filled by Gemini analysis) + +### Enhanced Test Suggestions +- **L1 (Unit)**: (Pending) +- **L2.1 (Integration)**: (Pending) +- **L2.2 (API Contracts)**: (Pending) +- **L2.4 (External APIs)**: (Pending) +- **L2.5 (Failure Modes)**: (Pending) + +### Gemini Analysis Summary +(Pending enrichment) + +--- + +## Consolidated Test Requirements (Phase 2 Input) +1. [Context] ${testFramework} framework conventions +2. [Context] ${coverageTarget} coverage target + +--- + +## Task Generation (Phase 2) +(To be filled by test-action-planning-agent) + +## N+1 Context +### Decisions +| Decision | Rationale | Revisit? | +|----------|-----------|----------| + +### Deferred +- [ ] (For N+1) +`) ``` -Skill(skill="workflow:tools:test-task-generate", args="--session [testSessionId]") + +--- + +#### Phase 1.5: Gemini Test Enhancement + +**Purpose**: Enrich test specifications with comprehensive test suggestions and record to test-planning-notes.md. + +**Execution Steps**: +1. Load TEST_ANALYSIS_RESULTS.md from `.workflow/active/{test-session-id}/.process/` +2. Invoke `cli-execution-agent` with Gemini for test enhancement analysis +3. Use template: `~/.ccw/workflows/cli-templates/prompts/test-suggestions-enhancement.txt` +4. Gemini generates enriched test suggestions across L1-L3 layers -> gemini-enriched-suggestions.md +5. Record enriched suggestions to test-planning-notes.md (Gemini Enhancement section) + +```javascript +Task( + subagent_type="cli-execution-agent", + run_in_background=false, + description="Enhance test specifications with Gemini analysis", + prompt=` +## Task Objective +Analyze TEST_ANALYSIS_RESULTS.md and generate enriched test suggestions using Gemini CLI + +## Input Files +- Read: .workflow/active/{test-session-id}/.process/TEST_ANALYSIS_RESULTS.md +- Extract: Project type, test framework, coverage gaps, identified files + +## Gemini Analysis Execution +Execute Gemini with comprehensive test enhancement prompt: + ccw cli -p "[comprehensive test prompt]" --tool gemini --mode analysis --rule analysis-test-strategy-enhancement --cd .workflow/active/{test-session-id}/.process + +## Expected Output +Generate gemini-enriched-suggestions.md with structured test enhancements: + - L1 (Unit Tests): Edge cases, boundaries, error paths + - L2.1 (Integration): Module interactions, dependency injection + - L2.2 (API Contracts): Request/response, validation, error responses + - L2.4 (External APIs): Mock strategies, failure scenarios, timeouts + - L2.5 (Failure Modes): Exception handling, error propagation, recovery + +## Validation +- gemini-enriched-suggestions.md created and complete +- Suggestions are actionable and specific (not generic) +- All L1-L3 layers covered +` +) +``` + +**Output**: gemini-enriched-suggestions.md (complete Gemini analysis) + +**After Phase 1.5**: Update test-planning-notes.md with Gemini enhancement findings + +```javascript +// Read enriched suggestions from gemini-enriched-suggestions.md +const enrichedSuggestionsPath = `.workflow/active/${testSessionId}/.process/gemini-enriched-suggestions.md` +const enrichedSuggestions = Read(enrichedSuggestionsPath) + +// Update Phase 1.5 section in test-planning-notes.md with full enriched suggestions +Edit(testPlanningNotesPath, { + old: '## Gemini Enhancement (Phase 1.5)\n(To be filled by Gemini analysis)\n\n### Enhanced Test Suggestions\n- **L1 (Unit)**: (Pending)\n- **L2.1 (Integration)**: (Pending)\n- **L2.2 (API Contracts)**: (Pending)\n- **L2.4 (External APIs)**: (Pending)\n- **L2.5 (Failure Modes)**: (Pending)\n\n### Gemini Analysis Summary\n(Pending enrichment)', + new: `## Gemini Enhancement (Phase 1.5) + +**Analysis Timestamp**: ${new Date().toISOString()} +**Template**: test-suggestions-enhancement.txt +**Output File**: .process/gemini-enriched-suggestions.md + +### Enriched Test Suggestions (Complete Gemini Analysis) + +${enrichedSuggestions} + +### Gemini Analysis Summary +- **Status**: Enrichment complete +- **Layers Covered**: L1, L2.1, L2.2, L2.4, L2.5 +- **Focus Areas**: API contracts, integration patterns, error scenarios, edge cases +- **Output Stored**: Full analysis in gemini-enriched-suggestions.md` +}) + +// Append Gemini constraints to consolidated test requirements +const geminiConstraints = [ + '[Gemini] Implement all suggested L1 edge cases and boundary tests', + '[Gemini] Apply L2.1 module interaction patterns from analysis', + '[Gemini] Follow L2.2 API contract test matrix from analysis', + '[Gemini] Use L2.4 external API mock strategies from analysis', + '[Gemini] Cover L2.5 error scenarios from analysis' +] + +const currentNotes = Read(testPlanningNotesPath) +const constraintCount = (currentNotes.match(/^\d+\./gm) || []).length + +Edit(testPlanningNotesPath, { + old: '## Consolidated Test Requirements (Phase 2 Input)', + new: `## Consolidated Test Requirements (Phase 2 Input) +1. [Context] ${testFramework} framework conventions +2. [Context] ${coverageTarget} coverage target +${geminiConstraints.map((c, i) => `${i + 3}. ${c}`).join('\n')}` +}) +``` + +--- + +#### Phase 2: Test Document Generation (Agent) + +**Agent Specialization**: This invokes `@test-action-planning-agent` - a specialized variant of action-planning-agent with: +- Progressive L0-L3 test layers (Static, Unit, Integration, E2E) +- AI code issue detection (L0.5) with severity levels +- Project type templates (React, Node API, CLI, Library, Monorepo) +- Test anti-pattern detection with quality gates +- Layer completeness thresholds and coverage targets + +**See**: `d:\Claude_dms3\.claude\agents\test-action-planning-agent.md` for complete test specifications. + +```javascript +Task( + subagent_type="test-action-planning-agent", + run_in_background=false, + description="Generate test planning documents", + prompt=` +## TASK OBJECTIVE +Generate test planning documents (IMPL_PLAN.md, task JSONs, TODO_LIST.md) for test workflow session + +IMPORTANT: This is TEST PLANNING ONLY - you are generating planning documents, NOT executing tests. + +## SESSION PATHS +Input: + - Session Metadata: .workflow/active/{test-session-id}/workflow-session.json + - TEST_ANALYSIS_RESULTS: .workflow/active/{test-session-id}/.process/TEST_ANALYSIS_RESULTS.md (REQUIRED) + - Test Planning Notes: .workflow/active/{test-session-id}/test-planning-notes.md (REQUIRED - contains Gemini enhancement findings) + - Test Context Package: .workflow/active/{test-session-id}/.process/test-context-package.json + - Context Package: .workflow/active/{test-session-id}/.process/context-package.json + - Enriched Suggestions: .workflow/active/{test-session-id}/.process/gemini-enriched-suggestions.md (for reference) + - Source Session Summaries: .workflow/active/{source-session-id}/.summaries/IMPL-*.md (if exists) + +Output: + - Task Dir: .workflow/active/{test-session-id}/.task/ + - IMPL_PLAN: .workflow/active/{test-session-id}/IMPL_PLAN.md + - TODO_LIST: .workflow/active/{test-session-id}/TODO_LIST.md + +## CONTEXT METADATA +Session ID: {test-session-id} +Workflow Type: test_session +Source Session: {source-session-id} (if exists) +MCP Capabilities: {exa_code, exa_web, code_index} + +## CONSOLIDATED CONTEXT +**From test-planning-notes.md**: +- Test Intent: Project type, test framework, coverage target +- Context Findings: Coverage gaps, file analysis +- Gemini Enhancement: Complete enriched test suggestions (L1-L3 layers) + * Full analysis embedded in planning-notes.md + * API contracts, integration patterns, error scenarios +- Consolidated Requirements: Combined constraints from all phases + +## YOUR SPECIFICATIONS +You are @test-action-planning-agent. Your complete test specifications are defined in: + d:\Claude_dms3\.claude\agents\test-action-planning-agent.md + +This includes: + - Progressive Test Layers (L0-L3) with L0.1-L0.5, L1.1-L1.5, L2.1-L2.5, L3.1-L3.4 + - AI Code Issue Detection (L0.5) with 7 categories and severity levels + - Project Type Detection & Templates (6 project types) + - Test Anti-Pattern Detection (5 categories) + - Layer Completeness & Quality Metrics (thresholds and gate decisions) + - Task JSON structure requirements (minimum 4 tasks) + - Quality validation rules + +**Follow your specification exactly** when generating test task JSONs. + +## EXPECTED DELIVERABLES +1. Test Task JSON Files (.task/IMPL-*.json) - Minimum 4: + - IMPL-001.json: Test generation (L1-L3 layers per spec) + - IMPL-001.3-validation.json: Code validation gate (L0 + AI issues per spec) + - IMPL-001.5-review.json: Test quality gate (anti-patterns + coverage per spec) + - IMPL-002.json: Test execution & fix cycle + +2. IMPL_PLAN.md: Test implementation plan with quality gates + +3. TODO_LIST.md: Hierarchical task list with test phase indicators + +## SUCCESS CRITERIA +- All test planning documents generated successfully +- Task count: minimum 4 (expandable for complex projects) +- Test framework: {detected from project} +- Coverage targets: L0 zero errors, L1 80%+, L2 70%+ +- L0-L3 layers explicitly defined per spec +- AI issue detection configured per spec +- Quality gates with measurable thresholds +` +) ``` **Input**: `testSessionId` from Phase 1 -**Note**: test-task-generate invokes action-planning-agent to generate test-specific IMPL_PLAN.md and task JSONs based on TEST_ANALYSIS_RESULTS.md. +**Note**: test-action-planning-agent generates test-specific IMPL_PLAN.md and task JSONs based on TEST_ANALYSIS_RESULTS.md. **Expected Output** (minimum 4 tasks): @@ -36,6 +305,37 @@ Skill(skill="workflow:tools:test-task-generate", args="--session [testSessionId] - `.workflow/active/[testSessionId]/IMPL_PLAN.md` exists - `.workflow/active/[testSessionId]/TODO_LIST.md` exists +## Test-Specific Execution Modes + +### Test Generation (IMPL-001) +- **Agent Mode** (default): @code-developer generates tests within agent context +- **CLI Mode**: Use CLI tools when `command` field present in implementation_approach + +### Test Execution & Fix (IMPL-002+) +- **Agent Mode** (default): Gemini diagnosis -> agent applies fixes +- **CLI Mode**: Gemini diagnosis -> CLI applies fixes (when `command` field present) + +**CLI Tool Selection**: Determined semantically from user's task description (e.g., "use Codex for fixes") + +## Output Directory Structure + +``` +.workflow/active/WFS-test-[session]/ +|-- workflow-session.json # Session metadata +|-- IMPL_PLAN.md # Test implementation plan +|-- TODO_LIST.md # Task checklist +|-- test-planning-notes.md # Consolidated planning notes with full Gemini analysis +|-- .task/ +| |-- IMPL-001.json # Test generation (L1-L3) +| |-- IMPL-001.3-validation.json # Code validation gate (L0 + AI) +| |-- IMPL-001.5-review.json # Test quality gate +| +-- IMPL-002.json # Test execution & fix cycle ++-- .process/ + |-- test-context-package.json # Test coverage and patterns + |-- gemini-enriched-suggestions.md # Gemini-generated test enhancements + +-- TEST_ANALYSIS_RESULTS.md # L0-L3 requirements (from test-concept-enhanced) +``` + ## Output - **Files**: IMPL_PLAN.md, IMPL-*.json (4+), TODO_LIST.md