mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-10 02:24:35 +08:00
feat: Add comprehensive tests for CCW Loop System flow state
- Implemented loop control tasks in JSON format for testing. - Created comprehensive test scripts for loop flow and standalone tests. - Developed a shell script to automate the testing of the entire loop system flow, including mock endpoints and state transitions. - Added error handling and execution history tests to ensure robustness. - Established variable substitution and success condition evaluations in tests. - Set up cleanup and workspace management for test environments.
This commit is contained in:
303
.claude/skills/ccw-loop/README.md
Normal file
303
.claude/skills/ccw-loop/README.md
Normal file
@@ -0,0 +1,303 @@
|
||||
# CCW Loop Skill
|
||||
|
||||
无状态迭代开发循环工作流,支持开发 (Develop)、调试 (Debug)、验证 (Validate) 三个阶段,每个阶段都有独立的文件记录进展。
|
||||
|
||||
## Overview
|
||||
|
||||
CCW Loop 是一个自主模式 (Autonomous) 的 Skill,通过文件驱动的无状态循环,帮助开发者系统化地完成开发任务。
|
||||
|
||||
### 核心特性
|
||||
|
||||
1. **无状态循环**: 每次执行从文件读取状态,不依赖内存
|
||||
2. **文件驱动**: 所有进度记录在 Markdown 文件中,可审计、可回顾
|
||||
3. **Gemini 辅助**: 关键决策点使用 CLI 工具进行深度分析
|
||||
4. **可恢复**: 任何时候中断后可继续
|
||||
5. **双模式**: 支持交互式和自动循环
|
||||
|
||||
### 三大阶段
|
||||
|
||||
- **Develop**: 任务分解 → 代码实现 → 进度记录
|
||||
- **Debug**: 假设生成 → 证据收集 → 根因分析 → 修复验证
|
||||
- **Validate**: 测试执行 → 覆盖率检查 → 质量评估
|
||||
|
||||
## Installation
|
||||
|
||||
已包含在 `.claude/skills/ccw-loop/`,无需额外安装。
|
||||
|
||||
## Usage
|
||||
|
||||
### 基本用法
|
||||
|
||||
```bash
|
||||
# 启动新循环
|
||||
/ccw-loop "实现用户认证功能"
|
||||
|
||||
# 继续现有循环
|
||||
/ccw-loop --resume LOOP-auth-2026-01-22
|
||||
|
||||
# 自动循环模式
|
||||
/ccw-loop --auto "修复登录bug并添加测试"
|
||||
```
|
||||
|
||||
### 交互式流程
|
||||
|
||||
```
|
||||
1. 启动: /ccw-loop "任务描述"
|
||||
2. 初始化: 自动分析任务并生成子任务列表
|
||||
3. 显示菜单:
|
||||
- 📝 继续开发 (Develop)
|
||||
- 🔍 开始调试 (Debug)
|
||||
- ✅ 运行验证 (Validate)
|
||||
- 📊 查看详情 (Status)
|
||||
- 🏁 完成循环 (Complete)
|
||||
- 🚪 退出 (Exit)
|
||||
4. 执行选择的动作
|
||||
5. 重复步骤 3-4 直到完成
|
||||
```
|
||||
|
||||
### 自动循环流程
|
||||
|
||||
```
|
||||
Develop (所有任务) → Debug (如有需要) → Validate → 完成
|
||||
```
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
.workflow/.loop/{session-id}/
|
||||
├── meta.json # 会话元数据 (不可修改)
|
||||
├── state.json # 当前状态 (每次更新)
|
||||
├── summary.md # 完成报告 (结束时生成)
|
||||
├── develop/
|
||||
│ ├── progress.md # 开发进度时间线
|
||||
│ ├── tasks.json # 任务列表
|
||||
│ └── changes.log # 代码变更日志 (NDJSON)
|
||||
├── debug/
|
||||
│ ├── understanding.md # 理解演变文档
|
||||
│ ├── hypotheses.json # 假设历史
|
||||
│ └── debug.log # 调试日志 (NDJSON)
|
||||
└── validate/
|
||||
├── validation.md # 验证报告
|
||||
├── test-results.json # 测试结果
|
||||
└── coverage.json # 覆盖率数据
|
||||
```
|
||||
|
||||
## Action Reference
|
||||
|
||||
| Action | 描述 | 触发条件 |
|
||||
|--------|------|----------|
|
||||
| action-init | 初始化会话 | 首次启动 |
|
||||
| action-menu | 显示操作菜单 | 交互模式下每次循环 |
|
||||
| action-develop-with-file | 执行开发任务 | 有待处理任务 |
|
||||
| action-debug-with-file | 假设驱动调试 | 需要调试 |
|
||||
| action-validate-with-file | 运行测试验证 | 需要验证 |
|
||||
| action-complete | 完成并生成报告 | 所有任务完成 |
|
||||
|
||||
详细说明见 [specs/action-catalog.md](specs/action-catalog.md)
|
||||
|
||||
## CLI Integration
|
||||
|
||||
CCW Loop 在关键决策点集成 CLI 工具:
|
||||
|
||||
### 任务分解 (action-init)
|
||||
```bash
|
||||
ccw cli -p "PURPOSE: 分解开发任务..."
|
||||
--tool gemini
|
||||
--mode analysis
|
||||
--rule planning-breakdown-task-steps
|
||||
```
|
||||
|
||||
### 代码实现 (action-develop)
|
||||
```bash
|
||||
ccw cli -p "PURPOSE: 实现功能代码..."
|
||||
--tool gemini
|
||||
--mode write
|
||||
--rule development-implement-feature
|
||||
```
|
||||
|
||||
### 假设生成 (action-debug - 探索)
|
||||
```bash
|
||||
ccw cli -p "PURPOSE: Generate debugging hypotheses..."
|
||||
--tool gemini
|
||||
--mode analysis
|
||||
--rule analysis-diagnose-bug-root-cause
|
||||
```
|
||||
|
||||
### 证据分析 (action-debug - 分析)
|
||||
```bash
|
||||
ccw cli -p "PURPOSE: Analyze debug log evidence..."
|
||||
--tool gemini
|
||||
--mode analysis
|
||||
--rule analysis-diagnose-bug-root-cause
|
||||
```
|
||||
|
||||
### 质量评估 (action-validate)
|
||||
```bash
|
||||
ccw cli -p "PURPOSE: Analyze test results and coverage..."
|
||||
--tool gemini
|
||||
--mode analysis
|
||||
--rule analysis-review-code-quality
|
||||
```
|
||||
|
||||
## State Management
|
||||
|
||||
### State Schema
|
||||
|
||||
参见 [phases/state-schema.md](phases/state-schema.md)
|
||||
|
||||
### State Transitions
|
||||
|
||||
```
|
||||
pending → running → completed
|
||||
↓
|
||||
user_exit
|
||||
↓
|
||||
failed
|
||||
```
|
||||
|
||||
### State Recovery
|
||||
|
||||
如果 `state.json` 损坏,可从其他文件重建:
|
||||
- develop/tasks.json → develop.*
|
||||
- debug/hypotheses.json → debug.*
|
||||
- validate/test-results.json → validate.*
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1: 功能开发
|
||||
|
||||
```bash
|
||||
# 1. 启动循环
|
||||
/ccw-loop "Add user profile page"
|
||||
|
||||
# 2. 系统初始化,生成任务:
|
||||
# - task-001: Create profile component
|
||||
# - task-002: Add API endpoints
|
||||
# - task-003: Implement tests
|
||||
|
||||
# 3. 选择 "继续开发"
|
||||
# → 执行 task-001 (Gemini 辅助实现)
|
||||
# → 更新 progress.md
|
||||
|
||||
# 4. 重复开发直到所有任务完成
|
||||
|
||||
# 5. 选择 "运行验证"
|
||||
# → 运行测试
|
||||
# → 检查覆盖率
|
||||
# → 生成 validation.md
|
||||
|
||||
# 6. 选择 "完成循环"
|
||||
# → 生成 summary.md
|
||||
# → 询问是否扩展为 Issue
|
||||
```
|
||||
|
||||
### Example 2: Bug 修复
|
||||
|
||||
```bash
|
||||
# 1. 启动循环
|
||||
/ccw-loop "Fix login timeout issue"
|
||||
|
||||
# 2. 选择 "开始调试"
|
||||
# → 输入 bug 描述: "Login times out after 30s"
|
||||
# → Gemini 生成假设 (H1, H2, H3)
|
||||
# → 添加 NDJSON 日志
|
||||
# → 提示复现 bug
|
||||
|
||||
# 3. 复现 bug (在应用中操作)
|
||||
|
||||
# 4. 再次选择 "开始调试"
|
||||
# → 解析 debug.log
|
||||
# → Gemini 分析证据
|
||||
# → H2 确认为根因
|
||||
# → 生成修复代码
|
||||
# → 更新 understanding.md
|
||||
|
||||
# 5. 选择 "运行验证"
|
||||
# → 测试通过
|
||||
|
||||
# 6. 完成
|
||||
```
|
||||
|
||||
## Templates
|
||||
|
||||
- [progress-template.md](templates/progress-template.md): 开发进度文档模板
|
||||
- [understanding-template.md](templates/understanding-template.md): 调试理解文档模板
|
||||
- [validation-template.md](templates/validation-template.md): 验证报告模板
|
||||
|
||||
## Specifications
|
||||
|
||||
- [loop-requirements.md](specs/loop-requirements.md): 循环需求规范
|
||||
- [action-catalog.md](specs/action-catalog.md): 动作目录
|
||||
|
||||
## Integration
|
||||
|
||||
### Dashboard Integration
|
||||
|
||||
CCW Loop 与 Dashboard Loop Monitor 集成:
|
||||
- Dashboard 创建 Loop → 触发此 Skill
|
||||
- state.json → Dashboard 实时显示
|
||||
- 任务列表双向同步
|
||||
- 控制按钮映射到 actions
|
||||
|
||||
### Issue System Integration
|
||||
|
||||
完成后可扩展为 Issue:
|
||||
- 维度: test, enhance, refactor, doc
|
||||
- 自动调用 `/issue:new`
|
||||
- 上下文自动填充
|
||||
|
||||
## Error Handling
|
||||
|
||||
| 情况 | 处理 |
|
||||
|------|------|
|
||||
| Session 不存在 | 创建新会话 |
|
||||
| state.json 损坏 | 从文件重建 |
|
||||
| CLI 工具失败 | 回退到手动模式 |
|
||||
| 测试失败 | 循环回到 develop/debug |
|
||||
| >10 迭代 | 警告用户,建议拆分 |
|
||||
|
||||
## Limitations
|
||||
|
||||
1. **单会话限制**: 同一时间只能有一个活跃会话
|
||||
2. **迭代限制**: 建议不超过 10 次迭代
|
||||
3. **CLI 依赖**: 部分功能依赖 Gemini CLI 可用性
|
||||
4. **测试框架**: 需要 package.json 中定义测试脚本
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Q: 如何查看当前会话状态?
|
||||
|
||||
A: 在菜单中选择 "查看详情 (Status)"
|
||||
|
||||
### Q: 如何恢复中断的会话?
|
||||
|
||||
A: 使用 `--resume` 参数:
|
||||
```bash
|
||||
/ccw-loop --resume LOOP-xxx-2026-01-22
|
||||
```
|
||||
|
||||
### Q: 如果 CLI 工具失败怎么办?
|
||||
|
||||
A: Skill 会自动降级到手动模式,提示用户手动输入
|
||||
|
||||
### Q: 如何添加自定义 action?
|
||||
|
||||
A: 参见 [specs/action-catalog.md](specs/action-catalog.md) 的 "Action Extensions" 部分
|
||||
|
||||
## Contributing
|
||||
|
||||
添加新功能:
|
||||
1. 创建 action 文件在 `phases/actions/`
|
||||
2. 更新 orchestrator 决策逻辑
|
||||
3. 添加到 action-catalog.md
|
||||
4. 更新 action-menu.md
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
---
|
||||
|
||||
**Version**: 1.0.0
|
||||
**Last Updated**: 2026-01-22
|
||||
**Author**: CCW Team
|
||||
259
.claude/skills/ccw-loop/SKILL.md
Normal file
259
.claude/skills/ccw-loop/SKILL.md
Normal file
@@ -0,0 +1,259 @@
|
||||
---
|
||||
name: ccw-loop
|
||||
description: Stateless iterative development loop workflow with documented progress. Supports develop, debug, and validate phases with file-based state tracking. Triggers on "ccw-loop", "dev loop", "development loop", "开发循环", "迭代开发".
|
||||
allowed-tools: Task(*), AskUserQuestion(*), Read(*), Grep(*), Glob(*), Bash(*), Edit(*), Write(*), TodoWrite(*)
|
||||
---
|
||||
|
||||
# CCW Loop - Stateless Iterative Development Workflow
|
||||
|
||||
无状态迭代开发循环工作流,支持开发 (develop)、调试 (debug)、验证 (validate) 三个阶段,每个阶段都有独立的文件记录进展。
|
||||
|
||||
## Arguments
|
||||
|
||||
| Arg | Required | Description |
|
||||
|-----|----------|-------------|
|
||||
| task | No | Task description (for new loop, mutually exclusive with --loop-id) |
|
||||
| --loop-id | No | Existing loop ID to continue (from API or previous session) |
|
||||
| --auto | No | Auto-cycle mode (develop → debug → validate → complete) |
|
||||
|
||||
## Unified Architecture (API + Skill Integration)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Dashboard (UI) │
|
||||
│ [Create] [Start] [Pause] [Resume] [Stop] [View Progress] │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ loop-v2-routes.ts (Control Plane) │
|
||||
│ │
|
||||
│ State: .loop/{loopId}.json (MASTER) │
|
||||
│ Tasks: .loop/{loopId}.tasks.jsonl │
|
||||
│ │
|
||||
│ /start → Trigger ccw-loop skill with --loop-id │
|
||||
│ /pause → Set status='paused' (skill checks before action) │
|
||||
│ /stop → Set status='failed' (skill terminates) │
|
||||
│ /resume → Set status='running' (skill continues) │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ ccw-loop Skill (Execution Plane) │
|
||||
│ │
|
||||
│ Reads/Writes: .loop/{loopId}.json (unified state) │
|
||||
│ Writes: .loop/{loopId}.progress/* (progress files) │
|
||||
│ │
|
||||
│ BEFORE each action: │
|
||||
│ → Check status: paused/stopped → exit gracefully │
|
||||
│ → running → continue with action │
|
||||
│ │
|
||||
│ Actions: init → develop → debug → validate → complete │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Key Design Principles
|
||||
|
||||
1. **统一状态**: API 和 Skill 共享 `.loop/{loopId}.json` 状态文件
|
||||
2. **控制信号**: Skill 每个 Action 前检查 status 字段 (paused/stopped)
|
||||
3. **文件驱动**: 所有进度、理解、结果都记录在 `.loop/{loopId}.progress/`
|
||||
4. **可恢复**: 任何时候可以继续之前的循环 (`--loop-id`)
|
||||
5. **双触发**: 支持 API 触发 (`--loop-id`) 和直接调用 (task description)
|
||||
6. **Gemini 辅助**: 使用 CLI 工具进行深度分析和假设验证
|
||||
|
||||
## Execution Modes
|
||||
|
||||
### Mode 1: Interactive (交互式)
|
||||
|
||||
用户手动选择每个动作,适合复杂任务。
|
||||
|
||||
```
|
||||
用户 → 选择动作 → 执行 → 查看结果 → 选择下一动作
|
||||
```
|
||||
|
||||
### Mode 2: Auto-Loop (自动循环)
|
||||
|
||||
按预设顺序自动执行,适合标准开发流程。
|
||||
|
||||
```
|
||||
Develop → Debug → Validate → (如有问题) → Develop → ...
|
||||
```
|
||||
|
||||
## Session Structure (Unified Location)
|
||||
|
||||
```
|
||||
.loop/
|
||||
├── {loopId}.json # 主状态文件 (API + Skill 共享)
|
||||
├── {loopId}.tasks.jsonl # 任务列表 (API 管理)
|
||||
└── {loopId}.progress/ # Skill 进度文件
|
||||
├── develop.md # 开发进度记录
|
||||
├── debug.md # 理解演变文档
|
||||
├── validate.md # 验证报告
|
||||
├── changes.log # 代码变更日志 (NDJSON)
|
||||
└── debug.log # 调试日志 (NDJSON)
|
||||
```
|
||||
|
||||
## Directory Setup
|
||||
|
||||
```javascript
|
||||
// loopId 来源:
|
||||
// 1. API 触发时: 从 --loop-id 参数获取
|
||||
// 2. 直接调用时: 生成新的 loop-v2-{timestamp}-{random}
|
||||
|
||||
const loopId = args['--loop-id'] || generateLoopId()
|
||||
const loopFile = `.loop/${loopId}.json`
|
||||
const progressDir = `.loop/${loopId}.progress`
|
||||
|
||||
// 创建进度目录
|
||||
Bash(`mkdir -p "${progressDir}"`)
|
||||
```
|
||||
|
||||
## Action Catalog
|
||||
|
||||
| Action | Purpose | Output Files | CLI Integration |
|
||||
|--------|---------|--------------|-----------------|
|
||||
| [action-init](phases/actions/action-init.md) | 初始化循环会话 | meta.json, state.json | - |
|
||||
| [action-develop-with-file](phases/actions/action-develop-with-file.md) | 开发任务执行 | progress.md, tasks.json | gemini --mode write |
|
||||
| [action-debug-with-file](phases/actions/action-debug-with-file.md) | 假设驱动调试 | understanding.md, hypotheses.json | gemini --mode analysis |
|
||||
| [action-validate-with-file](phases/actions/action-validate-with-file.md) | 测试与验证 | validation.md, test-results.json | gemini --mode analysis |
|
||||
| [action-complete](phases/actions/action-complete.md) | 完成循环 | summary.md | - |
|
||||
| [action-menu](phases/actions/action-menu.md) | 显示操作菜单 | - | - |
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# 启动新循环 (直接调用)
|
||||
/ccw-loop "实现用户认证功能"
|
||||
|
||||
# 继续现有循环 (API 触发或手动恢复)
|
||||
/ccw-loop --loop-id loop-v2-20260122-abc123
|
||||
|
||||
# 自动循环模式
|
||||
/ccw-loop --auto "修复登录bug并添加测试"
|
||||
|
||||
# API 触发自动循环
|
||||
/ccw-loop --loop-id loop-v2-20260122-abc123 --auto
|
||||
```
|
||||
|
||||
## Execution Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ /ccw-loop [<task> | --loop-id <id>] [--auto] │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 1. Parameter Detection: │
|
||||
│ ├─ IF --loop-id provided: │
|
||||
│ │ ├─ Read .loop/{loopId}.json │
|
||||
│ │ ├─ Validate status === 'running' │
|
||||
│ │ └─ Continue from skill_state.current_action │
|
||||
│ └─ ELSE (task description): │
|
||||
│ ├─ Generate new loopId │
|
||||
│ ├─ Create .loop/{loopId}.json │
|
||||
│ └─ Initialize with action-init │
|
||||
│ │
|
||||
│ 2. Orchestrator Loop: │
|
||||
│ ├─ Read state from .loop/{loopId}.json │
|
||||
│ ├─ Check control signals: │
|
||||
│ │ ├─ status === 'paused' → Exit (wait for resume) │
|
||||
│ │ ├─ status === 'failed' → Exit with error │
|
||||
│ │ └─ status === 'running' → Continue │
|
||||
│ ├─ Show menu / auto-select next action │
|
||||
│ ├─ Execute action │
|
||||
│ ├─ Update .loop/{loopId}.progress/{action}.md │
|
||||
│ ├─ Update .loop/{loopId}.json (skill_state) │
|
||||
│ └─ Loop or exit based on user choice / completion │
|
||||
│ │
|
||||
│ 3. Action Execution: │
|
||||
│ ├─ BEFORE: checkControlSignals() → exit if paused/stopped │
|
||||
│ ├─ Develop: Plan → Implement → Document progress │
|
||||
│ ├─ Debug: Hypothesize → Instrument → Analyze → Fix │
|
||||
│ ├─ Validate: Test → Check → Report │
|
||||
│ └─ AFTER: Update skill_state in .loop/{loopId}.json │
|
||||
│ │
|
||||
│ 4. Termination: │
|
||||
│ ├─ Control signal: paused (graceful exit, wait resume) │
|
||||
│ ├─ Control signal: stopped (failed state) │
|
||||
│ ├─ User exits (interactive mode) │
|
||||
│ ├─ All tasks completed (status → completed) │
|
||||
│ └─ Max iterations reached │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Reference Documents
|
||||
|
||||
| Document | Purpose |
|
||||
|----------|---------|
|
||||
| [phases/orchestrator.md](phases/orchestrator.md) | 编排器:状态读取 + 动作选择 |
|
||||
| [phases/state-schema.md](phases/state-schema.md) | 状态结构定义 |
|
||||
| [specs/loop-requirements.md](specs/loop-requirements.md) | 循环需求规范 |
|
||||
| [specs/action-catalog.md](specs/action-catalog.md) | 动作目录 |
|
||||
| [templates/progress-template.md](templates/progress-template.md) | 进度文档模板 |
|
||||
| [templates/understanding-template.md](templates/understanding-template.md) | 理解文档模板 |
|
||||
|
||||
## Integration with Loop Monitor (Dashboard)
|
||||
|
||||
此 Skill 与 CCW Dashboard 的 Loop Monitor 实现 **控制平面 + 执行平面** 分离架构:
|
||||
|
||||
### Control Plane (Dashboard/API → loop-v2-routes.ts)
|
||||
|
||||
1. **创建循环**: `POST /api/loops/v2` → 创建 `.loop/{loopId}.json`
|
||||
2. **启动执行**: `POST /api/loops/v2/:loopId/start` → 触发 `/ccw-loop --loop-id {loopId} --auto`
|
||||
3. **暂停执行**: `POST /api/loops/v2/:loopId/pause` → 设置 `status='paused'` (Skill 下次检查时退出)
|
||||
4. **恢复执行**: `POST /api/loops/v2/:loopId/resume` → 设置 `status='running'` → 重新触发 Skill
|
||||
5. **停止执行**: `POST /api/loops/v2/:loopId/stop` → 设置 `status='failed'`
|
||||
|
||||
### Execution Plane (ccw-loop Skill)
|
||||
|
||||
1. **读取状态**: 从 `.loop/{loopId}.json` 读取 API 设置的状态
|
||||
2. **检查控制**: 每个 Action 前检查 `status` 字段
|
||||
3. **执行动作**: develop → debug → validate → complete
|
||||
4. **更新进度**: 写入 `.loop/{loopId}.progress/*.md` 和更新 `skill_state`
|
||||
5. **状态同步**: Dashboard 通过读取 `.loop/{loopId}.json` 获取进度
|
||||
|
||||
## CLI Integration Points
|
||||
|
||||
### Develop Phase
|
||||
```bash
|
||||
ccw cli -p "PURPOSE: Implement {task}...
|
||||
TASK: • Analyze requirements • Write code • Update progress
|
||||
MODE: write
|
||||
CONTEXT: @progress.md @tasks.json
|
||||
EXPECTED: Implementation + updated progress.md
|
||||
" --tool gemini --mode write --rule development-implement-feature
|
||||
```
|
||||
|
||||
### Debug Phase
|
||||
```bash
|
||||
ccw cli -p "PURPOSE: Generate debugging hypotheses...
|
||||
TASK: • Analyze error • Generate hypotheses • Add instrumentation
|
||||
MODE: analysis
|
||||
CONTEXT: @understanding.md @debug.log
|
||||
EXPECTED: Hypotheses + instrumentation plan
|
||||
" --tool gemini --mode analysis --rule analysis-diagnose-bug-root-cause
|
||||
```
|
||||
|
||||
### Validate Phase
|
||||
```bash
|
||||
ccw cli -p "PURPOSE: Validate implementation...
|
||||
TASK: • Run tests • Check coverage • Verify requirements
|
||||
MODE: analysis
|
||||
CONTEXT: @validation.md @test-results.json
|
||||
EXPECTED: Validation report
|
||||
" --tool gemini --mode analysis --rule analysis-review-code-quality
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Situation | Action |
|
||||
|-----------|--------|
|
||||
| Session not found | Create new session |
|
||||
| State file corrupted | Rebuild from file contents |
|
||||
| CLI tool fails | Fallback to manual analysis |
|
||||
| Tests fail | Loop back to develop/debug |
|
||||
| >10 iterations | Warn user, suggest break |
|
||||
|
||||
## Post-Completion Expansion
|
||||
|
||||
完成后询问用户是否扩展为 issue (test/enhance/refactor/doc),选中项调用 `/issue:new "{summary} - {dimension}"`
|
||||
320
.claude/skills/ccw-loop/phases/actions/action-complete.md
Normal file
320
.claude/skills/ccw-loop/phases/actions/action-complete.md
Normal file
@@ -0,0 +1,320 @@
|
||||
# Action: Complete
|
||||
|
||||
完成 CCW Loop 会话,生成总结报告。
|
||||
|
||||
## Purpose
|
||||
|
||||
- 生成完成报告
|
||||
- 汇总所有阶段成果
|
||||
- 提供后续建议
|
||||
- 询问是否扩展为 Issue
|
||||
|
||||
## Preconditions
|
||||
|
||||
- [ ] state.initialized === true
|
||||
- [ ] state.status === 'running'
|
||||
|
||||
## Execution
|
||||
|
||||
### Step 1: 汇总统计
|
||||
|
||||
```javascript
|
||||
const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString()
|
||||
|
||||
const sessionFolder = `.workflow/.loop/${state.session_id}`
|
||||
|
||||
const stats = {
|
||||
// 时间统计
|
||||
duration: Date.now() - new Date(state.created_at).getTime(),
|
||||
iterations: state.iteration_count,
|
||||
|
||||
// 开发统计
|
||||
develop: {
|
||||
total_tasks: state.develop.total_count,
|
||||
completed_tasks: state.develop.completed_count,
|
||||
completion_rate: state.develop.total_count > 0
|
||||
? (state.develop.completed_count / state.develop.total_count * 100).toFixed(1)
|
||||
: 0
|
||||
},
|
||||
|
||||
// 调试统计
|
||||
debug: {
|
||||
iterations: state.debug.iteration,
|
||||
hypotheses_tested: state.debug.hypotheses.length,
|
||||
root_cause_found: state.debug.confirmed_hypothesis !== null
|
||||
},
|
||||
|
||||
// 验证统计
|
||||
validate: {
|
||||
runs: state.validate.test_results.length,
|
||||
passed: state.validate.passed,
|
||||
coverage: state.validate.coverage,
|
||||
failed_tests: state.validate.failed_tests.length
|
||||
}
|
||||
}
|
||||
|
||||
console.log('\n生成完成报告...')
|
||||
```
|
||||
|
||||
### Step 2: 生成总结报告
|
||||
|
||||
```javascript
|
||||
const summaryReport = `# CCW Loop Session Summary
|
||||
|
||||
**Session ID**: ${state.session_id}
|
||||
**Task**: ${state.task_description}
|
||||
**Started**: ${state.created_at}
|
||||
**Completed**: ${getUtc8ISOString()}
|
||||
**Duration**: ${formatDuration(stats.duration)}
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
${state.validate.passed
|
||||
? '✅ **任务成功完成** - 所有测试通过,验证成功'
|
||||
: state.develop.completed_count === state.develop.total_count
|
||||
? '⚠️ **开发完成,验证未通过** - 需要进一步调试'
|
||||
: '⏸️ **任务部分完成** - 仍有待处理项'}
|
||||
|
||||
---
|
||||
|
||||
## Development Phase
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Total Tasks | ${stats.develop.total_tasks} |
|
||||
| Completed | ${stats.develop.completed_tasks} |
|
||||
| Completion Rate | ${stats.develop.completion_rate}% |
|
||||
|
||||
### Completed Tasks
|
||||
|
||||
${state.develop.tasks.filter(t => t.status === 'completed').map(t => `
|
||||
- ✅ ${t.description}
|
||||
- Files: ${t.files_changed?.join(', ') || 'N/A'}
|
||||
- Completed: ${t.completed_at}
|
||||
`).join('\n')}
|
||||
|
||||
### Pending Tasks
|
||||
|
||||
${state.develop.tasks.filter(t => t.status !== 'completed').map(t => `
|
||||
- ⏳ ${t.description}
|
||||
`).join('\n') || '_None_'}
|
||||
|
||||
---
|
||||
|
||||
## Debug Phase
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Iterations | ${stats.debug.iterations} |
|
||||
| Hypotheses Tested | ${stats.debug.hypotheses_tested} |
|
||||
| Root Cause Found | ${stats.debug.root_cause_found ? 'Yes' : 'No'} |
|
||||
|
||||
${stats.debug.root_cause_found ? `
|
||||
### Confirmed Root Cause
|
||||
|
||||
**${state.debug.confirmed_hypothesis}**: ${state.debug.hypotheses.find(h => h.id === state.debug.confirmed_hypothesis)?.description || 'N/A'}
|
||||
` : ''}
|
||||
|
||||
### Hypothesis Summary
|
||||
|
||||
${state.debug.hypotheses.map(h => `
|
||||
- **${h.id}**: ${h.status.toUpperCase()}
|
||||
- ${h.description}
|
||||
`).join('\n') || '_No hypotheses tested_'}
|
||||
|
||||
---
|
||||
|
||||
## Validation Phase
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Test Runs | ${stats.validate.runs} |
|
||||
| Status | ${stats.validate.passed ? 'PASSED' : 'FAILED'} |
|
||||
| Coverage | ${stats.validate.coverage || 'N/A'}% |
|
||||
| Failed Tests | ${stats.validate.failed_tests} |
|
||||
|
||||
${stats.validate.failed_tests > 0 ? `
|
||||
### Failed Tests
|
||||
|
||||
${state.validate.failed_tests.map(t => `- ❌ ${t}`).join('\n')}
|
||||
` : ''}
|
||||
|
||||
---
|
||||
|
||||
## Files Modified
|
||||
|
||||
${listModifiedFiles(sessionFolder)}
|
||||
|
||||
---
|
||||
|
||||
## Key Learnings
|
||||
|
||||
${state.debug.iteration > 0 ? `
|
||||
### From Debugging
|
||||
|
||||
${extractLearnings(state.debug.hypotheses)}
|
||||
` : ''}
|
||||
|
||||
---
|
||||
|
||||
## Recommendations
|
||||
|
||||
${generateRecommendations(stats, state)}
|
||||
|
||||
---
|
||||
|
||||
## Session Artifacts
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| \`develop/progress.md\` | Development progress timeline |
|
||||
| \`develop/tasks.json\` | Task list with status |
|
||||
| \`debug/understanding.md\` | Debug exploration and learnings |
|
||||
| \`debug/hypotheses.json\` | Hypothesis history |
|
||||
| \`validate/validation.md\` | Validation report |
|
||||
| \`validate/test-results.json\` | Test execution results |
|
||||
|
||||
---
|
||||
|
||||
*Generated by CCW Loop at ${getUtc8ISOString()}*
|
||||
`
|
||||
|
||||
Write(`${sessionFolder}/summary.md`, summaryReport)
|
||||
console.log(`\n报告已保存: ${sessionFolder}/summary.md`)
|
||||
```
|
||||
|
||||
### Step 3: 询问后续扩展
|
||||
|
||||
```javascript
|
||||
console.log('\n' + '═'.repeat(60))
|
||||
console.log(' 任务已完成')
|
||||
console.log('═'.repeat(60))
|
||||
|
||||
const expansionResponse = await AskUserQuestion({
|
||||
questions: [{
|
||||
question: "是否将发现扩展为 Issue?",
|
||||
header: "扩展选项",
|
||||
multiSelect: true,
|
||||
options: [
|
||||
{ label: "测试 (Test)", description: "添加更多测试用例" },
|
||||
{ label: "增强 (Enhance)", description: "功能增强建议" },
|
||||
{ label: "重构 (Refactor)", description: "代码重构建议" },
|
||||
{ label: "文档 (Doc)", description: "文档更新需求" },
|
||||
{ label: "否,直接完成", description: "不创建 Issue" }
|
||||
]
|
||||
}]
|
||||
})
|
||||
|
||||
const selectedExpansions = expansionResponse["扩展选项"]
|
||||
|
||||
if (selectedExpansions && !selectedExpansions.includes("否,直接完成")) {
|
||||
for (const expansion of selectedExpansions) {
|
||||
const dimension = expansion.split(' ')[0].toLowerCase()
|
||||
const issueSummary = `${state.task_description} - ${dimension}`
|
||||
|
||||
console.log(`\n创建 Issue: ${issueSummary}`)
|
||||
|
||||
// 调用 /issue:new 创建 issue
|
||||
await Bash({
|
||||
command: `/issue:new "${issueSummary}"`,
|
||||
run_in_background: false
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4: 最终输出
|
||||
|
||||
```javascript
|
||||
console.log(`
|
||||
═══════════════════════════════════════════════════════════
|
||||
✅ CCW Loop 会话完成
|
||||
═══════════════════════════════════════════════════════════
|
||||
|
||||
会话 ID: ${state.session_id}
|
||||
用时: ${formatDuration(stats.duration)}
|
||||
迭代: ${stats.iterations}
|
||||
|
||||
开发: ${stats.develop.completed_tasks}/${stats.develop.total_tasks} 任务完成
|
||||
调试: ${stats.debug.iterations} 次迭代
|
||||
验证: ${stats.validate.passed ? '通过 ✅' : '未通过 ❌'}
|
||||
|
||||
报告: ${sessionFolder}/summary.md
|
||||
|
||||
═══════════════════════════════════════════════════════════
|
||||
`)
|
||||
```
|
||||
|
||||
## State Updates
|
||||
|
||||
```javascript
|
||||
return {
|
||||
stateUpdates: {
|
||||
status: 'completed',
|
||||
completed_at: getUtc8ISOString(),
|
||||
summary: stats
|
||||
},
|
||||
continue: false,
|
||||
message: `会话 ${state.session_id} 已完成`
|
||||
}
|
||||
```
|
||||
|
||||
## Helper Functions
|
||||
|
||||
```javascript
|
||||
function formatDuration(ms) {
|
||||
const seconds = Math.floor(ms / 1000)
|
||||
const minutes = Math.floor(seconds / 60)
|
||||
const hours = Math.floor(minutes / 60)
|
||||
|
||||
if (hours > 0) {
|
||||
return `${hours}h ${minutes % 60}m`
|
||||
} else if (minutes > 0) {
|
||||
return `${minutes}m ${seconds % 60}s`
|
||||
} else {
|
||||
return `${seconds}s`
|
||||
}
|
||||
}
|
||||
|
||||
function generateRecommendations(stats, state) {
|
||||
const recommendations = []
|
||||
|
||||
if (stats.develop.completion_rate < 100) {
|
||||
recommendations.push('- 完成剩余开发任务')
|
||||
}
|
||||
|
||||
if (!stats.validate.passed) {
|
||||
recommendations.push('- 修复失败的测试')
|
||||
}
|
||||
|
||||
if (stats.validate.coverage && stats.validate.coverage < 80) {
|
||||
recommendations.push(`- 提高测试覆盖率 (当前: ${stats.validate.coverage}%)`)
|
||||
}
|
||||
|
||||
if (stats.debug.iterations > 3 && !stats.debug.root_cause_found) {
|
||||
recommendations.push('- 考虑代码重构以简化调试')
|
||||
}
|
||||
|
||||
if (recommendations.length === 0) {
|
||||
recommendations.push('- 考虑代码审查')
|
||||
recommendations.push('- 更新相关文档')
|
||||
recommendations.push('- 准备部署')
|
||||
}
|
||||
|
||||
return recommendations.join('\n')
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error Type | Recovery |
|
||||
|------------|----------|
|
||||
| 报告生成失败 | 显示基本统计,跳过文件写入 |
|
||||
| Issue 创建失败 | 记录错误,继续完成 |
|
||||
|
||||
## Next Actions
|
||||
|
||||
- 无 (终止状态)
|
||||
- 如需继续: 使用 `ccw-loop --resume {session-id}` 重新打开会话
|
||||
485
.claude/skills/ccw-loop/phases/actions/action-debug-with-file.md
Normal file
485
.claude/skills/ccw-loop/phases/actions/action-debug-with-file.md
Normal file
@@ -0,0 +1,485 @@
|
||||
# Action: Debug With File
|
||||
|
||||
假设驱动调试,记录理解演变到 understanding.md,支持 Gemini 辅助分析和假设生成。
|
||||
|
||||
## Purpose
|
||||
|
||||
执行假设驱动的调试流程,包括:
|
||||
- 定位错误源
|
||||
- 生成可测试假设
|
||||
- 添加 NDJSON 日志
|
||||
- 分析日志证据
|
||||
- 纠正错误理解
|
||||
- 应用修复
|
||||
|
||||
## Preconditions
|
||||
|
||||
- [ ] state.initialized === true
|
||||
- [ ] state.status === 'running'
|
||||
|
||||
## Session Setup
|
||||
|
||||
```javascript
|
||||
const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString()
|
||||
|
||||
const sessionFolder = `.workflow/.loop/${state.session_id}`
|
||||
const debugFolder = `${sessionFolder}/debug`
|
||||
const understandingPath = `${debugFolder}/understanding.md`
|
||||
const hypothesesPath = `${debugFolder}/hypotheses.json`
|
||||
const debugLogPath = `${debugFolder}/debug.log`
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Mode Detection
|
||||
|
||||
```javascript
|
||||
// 自动检测模式
|
||||
const understandingExists = fs.existsSync(understandingPath)
|
||||
const logHasContent = fs.existsSync(debugLogPath) && fs.statSync(debugLogPath).size > 0
|
||||
|
||||
const debugMode = logHasContent ? 'analyze' : (understandingExists ? 'continue' : 'explore')
|
||||
|
||||
console.log(`Debug mode: ${debugMode}`)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Explore Mode (首次调试)
|
||||
|
||||
### Step 1.1: 定位错误源
|
||||
|
||||
```javascript
|
||||
if (debugMode === 'explore') {
|
||||
// 询问用户 bug 描述
|
||||
const bugInput = await AskUserQuestion({
|
||||
questions: [{
|
||||
question: "请描述遇到的 bug 或错误信息:",
|
||||
header: "Bug 描述",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: "手动输入", description: "输入错误描述或堆栈" },
|
||||
{ label: "从测试失败", description: "从验证阶段的失败测试中获取" }
|
||||
]
|
||||
}]
|
||||
})
|
||||
|
||||
const bugDescription = bugInput["Bug 描述"]
|
||||
|
||||
// 提取关键词并搜索
|
||||
const searchResults = await Task({
|
||||
subagent_type: 'Explore',
|
||||
run_in_background: false,
|
||||
prompt: `Search codebase for error patterns related to: ${bugDescription}`
|
||||
})
|
||||
|
||||
// 分析搜索结果,识别受影响的位置
|
||||
const affectedLocations = analyzeSearchResults(searchResults)
|
||||
}
|
||||
```
|
||||
|
||||
### Step 1.2: 记录初始理解
|
||||
|
||||
```javascript
|
||||
// 创建 understanding.md
|
||||
const initialUnderstanding = `# Understanding Document
|
||||
|
||||
**Session ID**: ${state.session_id}
|
||||
**Bug Description**: ${bugDescription}
|
||||
**Started**: ${getUtc8ISOString()}
|
||||
|
||||
---
|
||||
|
||||
## Exploration Timeline
|
||||
|
||||
### Iteration 1 - Initial Exploration (${getUtc8ISOString()})
|
||||
|
||||
#### Current Understanding
|
||||
|
||||
Based on bug description and initial code search:
|
||||
|
||||
- Error pattern: ${errorPattern}
|
||||
- Affected areas: ${affectedLocations.map(l => l.file).join(', ')}
|
||||
- Initial hypothesis: ${initialThoughts}
|
||||
|
||||
#### Evidence from Code Search
|
||||
|
||||
${searchResults.map(r => `
|
||||
**Keyword: "${r.keyword}"**
|
||||
- Found in: ${r.files.join(', ')}
|
||||
- Key findings: ${r.insights}
|
||||
`).join('\n')}
|
||||
|
||||
#### Next Steps
|
||||
|
||||
- Generate testable hypotheses
|
||||
- Add instrumentation
|
||||
- Await reproduction
|
||||
|
||||
---
|
||||
|
||||
## Current Consolidated Understanding
|
||||
|
||||
${initialConsolidatedUnderstanding}
|
||||
`
|
||||
|
||||
Write(understandingPath, initialUnderstanding)
|
||||
```
|
||||
|
||||
### Step 1.3: Gemini 辅助假设生成
|
||||
|
||||
```bash
|
||||
ccw cli -p "
|
||||
PURPOSE: Generate debugging hypotheses for: ${bugDescription}
|
||||
Success criteria: Testable hypotheses with clear evidence criteria
|
||||
|
||||
TASK:
|
||||
• Analyze error pattern and code search results
|
||||
• Identify 3-5 most likely root causes
|
||||
• For each hypothesis, specify:
|
||||
- What might be wrong
|
||||
- What evidence would confirm/reject it
|
||||
- Where to add instrumentation
|
||||
• Rank by likelihood
|
||||
|
||||
MODE: analysis
|
||||
|
||||
CONTEXT: @${understandingPath} | Search results in understanding.md
|
||||
|
||||
EXPECTED:
|
||||
- Structured hypothesis list (JSON format)
|
||||
- Each hypothesis with: id, description, testable_condition, logging_point, evidence_criteria
|
||||
- Likelihood ranking (1=most likely)
|
||||
|
||||
CONSTRAINTS: Focus on testable conditions
|
||||
" --tool gemini --mode analysis --rule analysis-diagnose-bug-root-cause
|
||||
```
|
||||
|
||||
### Step 1.4: 保存假设
|
||||
|
||||
```javascript
|
||||
const hypotheses = {
|
||||
iteration: 1,
|
||||
timestamp: getUtc8ISOString(),
|
||||
bug_description: bugDescription,
|
||||
hypotheses: [
|
||||
{
|
||||
id: "H1",
|
||||
description: "...",
|
||||
testable_condition: "...",
|
||||
logging_point: "file.ts:func:42",
|
||||
evidence_criteria: {
|
||||
confirm: "...",
|
||||
reject: "..."
|
||||
},
|
||||
likelihood: 1,
|
||||
status: "pending"
|
||||
}
|
||||
// ...
|
||||
],
|
||||
gemini_insights: "...",
|
||||
corrected_assumptions: []
|
||||
}
|
||||
|
||||
Write(hypothesesPath, JSON.stringify(hypotheses, null, 2))
|
||||
```
|
||||
|
||||
### Step 1.5: 添加 NDJSON 日志
|
||||
|
||||
```javascript
|
||||
// 为每个假设添加日志点
|
||||
for (const hypothesis of hypotheses.hypotheses) {
|
||||
const [file, func, line] = hypothesis.logging_point.split(':')
|
||||
|
||||
const logStatement = `console.log(JSON.stringify({
|
||||
hid: "${hypothesis.id}",
|
||||
ts: Date.now(),
|
||||
func: "${func}",
|
||||
data: { /* 相关数据 */ }
|
||||
}))`
|
||||
|
||||
// 使用 Edit 工具添加日志
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Analyze Mode (有日志后)
|
||||
|
||||
### Step 2.1: 解析调试日志
|
||||
|
||||
```javascript
|
||||
if (debugMode === 'analyze') {
|
||||
// 读取 NDJSON 日志
|
||||
const logContent = Read(debugLogPath)
|
||||
const entries = logContent.split('\n')
|
||||
.filter(l => l.trim())
|
||||
.map(l => JSON.parse(l))
|
||||
|
||||
// 按假设分组
|
||||
const byHypothesis = groupBy(entries, 'hid')
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2.2: Gemini 辅助证据分析
|
||||
|
||||
```bash
|
||||
ccw cli -p "
|
||||
PURPOSE: Analyze debug log evidence to validate/correct hypotheses for: ${bugDescription}
|
||||
Success criteria: Clear verdict per hypothesis + corrected understanding
|
||||
|
||||
TASK:
|
||||
• Parse log entries by hypothesis
|
||||
• Evaluate evidence against expected criteria
|
||||
• Determine verdict: confirmed | rejected | inconclusive
|
||||
• Identify incorrect assumptions from previous understanding
|
||||
• Suggest corrections to understanding
|
||||
|
||||
MODE: analysis
|
||||
|
||||
CONTEXT:
|
||||
@${debugLogPath}
|
||||
@${understandingPath}
|
||||
@${hypothesesPath}
|
||||
|
||||
EXPECTED:
|
||||
- Per-hypothesis verdict with reasoning
|
||||
- Evidence summary
|
||||
- List of incorrect assumptions with corrections
|
||||
- Updated consolidated understanding
|
||||
- Root cause if confirmed, or next investigation steps
|
||||
|
||||
CONSTRAINTS: Evidence-based reasoning only, no speculation
|
||||
" --tool gemini --mode analysis --rule analysis-diagnose-bug-root-cause
|
||||
```
|
||||
|
||||
### Step 2.3: 更新理解文档
|
||||
|
||||
```javascript
|
||||
// 追加新迭代到 understanding.md
|
||||
const iteration = state.debug.iteration + 1
|
||||
|
||||
const analysisEntry = `
|
||||
### Iteration ${iteration} - Evidence Analysis (${getUtc8ISOString()})
|
||||
|
||||
#### Log Analysis Results
|
||||
|
||||
${results.map(r => `
|
||||
**${r.id}**: ${r.verdict.toUpperCase()}
|
||||
- Evidence: ${JSON.stringify(r.evidence)}
|
||||
- Reasoning: ${r.reason}
|
||||
`).join('\n')}
|
||||
|
||||
#### Corrected Understanding
|
||||
|
||||
Previous misunderstandings identified and corrected:
|
||||
|
||||
${corrections.map(c => `
|
||||
- ~~${c.wrong}~~ → ${c.corrected}
|
||||
- Why wrong: ${c.reason}
|
||||
- Evidence: ${c.evidence}
|
||||
`).join('\n')}
|
||||
|
||||
#### New Insights
|
||||
|
||||
${newInsights.join('\n- ')}
|
||||
|
||||
#### Gemini Analysis
|
||||
|
||||
${geminiAnalysis}
|
||||
|
||||
${confirmedHypothesis ? `
|
||||
#### Root Cause Identified
|
||||
|
||||
**${confirmedHypothesis.id}**: ${confirmedHypothesis.description}
|
||||
|
||||
Evidence supporting this conclusion:
|
||||
${confirmedHypothesis.supportingEvidence}
|
||||
` : `
|
||||
#### Next Steps
|
||||
|
||||
${nextSteps}
|
||||
`}
|
||||
|
||||
---
|
||||
|
||||
## Current Consolidated Understanding (Updated)
|
||||
|
||||
### What We Know
|
||||
|
||||
- ${validUnderstanding1}
|
||||
- ${validUnderstanding2}
|
||||
|
||||
### What Was Disproven
|
||||
|
||||
- ~~${wrongAssumption}~~ (Evidence: ${disproofEvidence})
|
||||
|
||||
### Current Investigation Focus
|
||||
|
||||
${currentFocus}
|
||||
|
||||
### Remaining Questions
|
||||
|
||||
- ${openQuestion1}
|
||||
- ${openQuestion2}
|
||||
`
|
||||
|
||||
const existingContent = Read(understandingPath)
|
||||
Write(understandingPath, existingContent + analysisEntry)
|
||||
```
|
||||
|
||||
### Step 2.4: 更新假设状态
|
||||
|
||||
```javascript
|
||||
const hypothesesData = JSON.parse(Read(hypothesesPath))
|
||||
|
||||
// 更新假设状态
|
||||
hypothesesData.hypotheses = hypothesesData.hypotheses.map(h => ({
|
||||
...h,
|
||||
status: results.find(r => r.id === h.id)?.verdict || h.status,
|
||||
evidence: results.find(r => r.id === h.id)?.evidence || h.evidence,
|
||||
verdict_reason: results.find(r => r.id === h.id)?.reason || h.verdict_reason
|
||||
}))
|
||||
|
||||
hypothesesData.iteration++
|
||||
hypothesesData.timestamp = getUtc8ISOString()
|
||||
|
||||
Write(hypothesesPath, JSON.stringify(hypothesesData, null, 2))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Fix & Verification
|
||||
|
||||
### Step 3.1: 应用修复
|
||||
|
||||
```javascript
|
||||
if (confirmedHypothesis) {
|
||||
console.log(`\n根因确认: ${confirmedHypothesis.description}`)
|
||||
console.log('准备应用修复...')
|
||||
|
||||
// 使用 Gemini 生成修复代码
|
||||
const fixPrompt = `
|
||||
PURPOSE: Fix the identified root cause
|
||||
Root Cause: ${confirmedHypothesis.description}
|
||||
Evidence: ${confirmedHypothesis.supportingEvidence}
|
||||
|
||||
TASK:
|
||||
• Generate fix code
|
||||
• Ensure backward compatibility
|
||||
• Add tests if needed
|
||||
|
||||
MODE: write
|
||||
|
||||
CONTEXT: @${confirmedHypothesis.logging_point.split(':')[0]}
|
||||
|
||||
EXPECTED: Fixed code + verification steps
|
||||
`
|
||||
|
||||
await Bash({
|
||||
command: `ccw cli -p "${fixPrompt}" --tool gemini --mode write --rule development-debug-runtime-issues`,
|
||||
run_in_background: false
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3.2: 记录解决方案
|
||||
|
||||
```javascript
|
||||
const resolutionEntry = `
|
||||
### Resolution (${getUtc8ISOString()})
|
||||
|
||||
#### Fix Applied
|
||||
|
||||
- Modified files: ${modifiedFiles.join(', ')}
|
||||
- Fix description: ${fixDescription}
|
||||
- Root cause addressed: ${rootCause}
|
||||
|
||||
#### Verification Results
|
||||
|
||||
${verificationResults}
|
||||
|
||||
#### Lessons Learned
|
||||
|
||||
1. ${lesson1}
|
||||
2. ${lesson2}
|
||||
|
||||
#### Key Insights for Future
|
||||
|
||||
- ${insight1}
|
||||
- ${insight2}
|
||||
`
|
||||
|
||||
const existingContent = Read(understandingPath)
|
||||
Write(understandingPath, existingContent + resolutionEntry)
|
||||
```
|
||||
|
||||
### Step 3.3: 清理日志
|
||||
|
||||
```javascript
|
||||
// 移除调试日志
|
||||
// (可选,根据用户选择)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## State Updates
|
||||
|
||||
```javascript
|
||||
return {
|
||||
stateUpdates: {
|
||||
debug: {
|
||||
current_bug: bugDescription,
|
||||
hypotheses: hypothesesData.hypotheses,
|
||||
confirmed_hypothesis: confirmedHypothesis?.id || null,
|
||||
iteration: hypothesesData.iteration,
|
||||
last_analysis_at: getUtc8ISOString(),
|
||||
understanding_updated: true
|
||||
},
|
||||
last_action: 'action-debug-with-file'
|
||||
},
|
||||
continue: true,
|
||||
message: confirmedHypothesis
|
||||
? `根因确认: ${confirmedHypothesis.description}\n修复已应用,请验证`
|
||||
: `分析完成,需要更多证据\n请复现 bug 后再次执行`
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error Type | Recovery |
|
||||
|------------|----------|
|
||||
| 空 debug.log | 提示用户复现 bug |
|
||||
| 所有假设被否定 | 使用 Gemini 生成新假设 |
|
||||
| 修复无效 | 记录失败尝试,迭代 |
|
||||
| >5 迭代 | 建议升级到 /workflow:lite-fix |
|
||||
| Gemini 不可用 | 回退到手动分析 |
|
||||
|
||||
## Understanding Document Template
|
||||
|
||||
参考 [templates/understanding-template.md](../../templates/understanding-template.md)
|
||||
|
||||
## CLI Integration
|
||||
|
||||
### 假设生成
|
||||
```bash
|
||||
ccw cli -p "PURPOSE: Generate debugging hypotheses..." --tool gemini --mode analysis --rule analysis-diagnose-bug-root-cause
|
||||
```
|
||||
|
||||
### 证据分析
|
||||
```bash
|
||||
ccw cli -p "PURPOSE: Analyze debug log evidence..." --tool gemini --mode analysis --rule analysis-diagnose-bug-root-cause
|
||||
```
|
||||
|
||||
### 生成修复
|
||||
```bash
|
||||
ccw cli -p "PURPOSE: Fix the identified root cause..." --tool gemini --mode write --rule development-debug-runtime-issues
|
||||
```
|
||||
|
||||
## Next Actions (Hints)
|
||||
|
||||
- 根因确认: `action-validate-with-file` (验证修复)
|
||||
- 需要更多证据: 等待用户复现,再次执行此动作
|
||||
- 所有假设否定: 重新执行此动作生成新假设
|
||||
- 用户选择: `action-menu` (返回菜单)
|
||||
@@ -0,0 +1,365 @@
|
||||
# Action: Develop With File
|
||||
|
||||
增量开发任务执行,记录进度到 progress.md,支持 Gemini 辅助实现。
|
||||
|
||||
## Purpose
|
||||
|
||||
执行开发任务并记录进度,包括:
|
||||
- 分析任务需求
|
||||
- 使用 Gemini/CLI 实现代码
|
||||
- 记录代码变更
|
||||
- 更新进度文档
|
||||
|
||||
## Preconditions
|
||||
|
||||
- [ ] state.status === 'running'
|
||||
- [ ] state.skill_state !== null
|
||||
- [ ] state.skill_state.develop.tasks.some(t => t.status === 'pending')
|
||||
|
||||
## Session Setup (Unified Location)
|
||||
|
||||
```javascript
|
||||
const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString()
|
||||
|
||||
// 统一位置: .loop/{loopId}
|
||||
const loopId = state.loop_id
|
||||
const loopFile = `.loop/${loopId}.json`
|
||||
const progressDir = `.loop/${loopId}.progress`
|
||||
const progressPath = `${progressDir}/develop.md`
|
||||
const changesLogPath = `${progressDir}/changes.log`
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execution
|
||||
|
||||
### Step 0: Check Control Signals (CRITICAL)
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* CRITICAL: 每个 Action 必须在开始时检查控制信号
|
||||
* 如果 API 设置了 paused/stopped,Skill 应立即退出
|
||||
*/
|
||||
function checkControlSignals(loopId) {
|
||||
const state = JSON.parse(Read(`.loop/${loopId}.json`))
|
||||
|
||||
switch (state.status) {
|
||||
case 'paused':
|
||||
console.log('⏸️ Loop paused by API. Exiting action.')
|
||||
return { continue: false, reason: 'paused' }
|
||||
|
||||
case 'failed':
|
||||
console.log('⏹️ Loop stopped by API. Exiting action.')
|
||||
return { continue: false, reason: 'stopped' }
|
||||
|
||||
case 'running':
|
||||
return { continue: true, reason: 'running' }
|
||||
|
||||
default:
|
||||
return { continue: false, reason: 'unknown_status' }
|
||||
}
|
||||
}
|
||||
|
||||
// Execute check
|
||||
const control = checkControlSignals(loopId)
|
||||
if (!control.continue) {
|
||||
return {
|
||||
skillStateUpdates: { current_action: null },
|
||||
continue: false,
|
||||
message: `Action terminated: ${control.reason}`
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 1: 加载任务列表
|
||||
|
||||
```javascript
|
||||
// 读取任务列表 (从 skill_state)
|
||||
let tasks = state.skill_state?.develop?.tasks || []
|
||||
|
||||
// 如果任务列表为空,询问用户创建
|
||||
if (tasks.length === 0) {
|
||||
// 使用 Gemini 分析任务描述,生成任务列表
|
||||
const analysisPrompt = `
|
||||
PURPOSE: 分析开发任务并分解为可执行步骤
|
||||
Success: 生成 3-7 个具体、可验证的子任务
|
||||
|
||||
TASK:
|
||||
• 分析任务描述: ${state.task_description}
|
||||
• 识别关键功能点
|
||||
• 分解为独立子任务
|
||||
• 为每个子任务指定工具和模式
|
||||
|
||||
MODE: analysis
|
||||
|
||||
CONTEXT: @package.json @src/**/*.ts | Memory: 项目结构
|
||||
|
||||
EXPECTED:
|
||||
JSON 格式:
|
||||
{
|
||||
"tasks": [
|
||||
{
|
||||
"id": "task-001",
|
||||
"description": "任务描述",
|
||||
"tool": "gemini",
|
||||
"mode": "write",
|
||||
"files": ["src/xxx.ts"]
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
const result = await Task({
|
||||
subagent_type: 'cli-execution-agent',
|
||||
run_in_background: false,
|
||||
prompt: `Execute Gemini CLI with prompt: ${analysisPrompt}`
|
||||
})
|
||||
|
||||
tasks = JSON.parse(result).tasks
|
||||
}
|
||||
|
||||
// 找到第一个待处理任务
|
||||
const currentTask = tasks.find(t => t.status === 'pending')
|
||||
|
||||
if (!currentTask) {
|
||||
return {
|
||||
skillStateUpdates: {
|
||||
develop: { ...state.skill_state.develop, current_task: null }
|
||||
},
|
||||
continue: true,
|
||||
message: '所有开发任务已完成'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: 执行开发任务
|
||||
|
||||
```javascript
|
||||
console.log(`\n执行任务: ${currentTask.description}`)
|
||||
|
||||
// 更新任务状态
|
||||
currentTask.status = 'in_progress'
|
||||
|
||||
// 使用 Gemini 实现
|
||||
const implementPrompt = `
|
||||
PURPOSE: 实现开发任务
|
||||
Task: ${currentTask.description}
|
||||
Success criteria: 代码实现完成,测试通过
|
||||
|
||||
TASK:
|
||||
• 分析现有代码结构
|
||||
• 实现功能代码
|
||||
• 添加必要的类型定义
|
||||
• 确保代码风格一致
|
||||
|
||||
MODE: write
|
||||
|
||||
CONTEXT: @${currentTask.files?.join(' @') || 'src/**/*.ts'}
|
||||
|
||||
EXPECTED:
|
||||
- 完整的代码实现
|
||||
- 代码变更列表
|
||||
- 简要实现说明
|
||||
|
||||
CONSTRAINTS: 遵循现有代码风格 | 不破坏现有功能
|
||||
`
|
||||
|
||||
const implementResult = await Bash({
|
||||
command: `ccw cli -p "${implementPrompt}" --tool gemini --mode write --rule development-implement-feature`,
|
||||
run_in_background: false
|
||||
})
|
||||
|
||||
// 记录代码变更
|
||||
const timestamp = getUtc8ISOString()
|
||||
const changeEntry = {
|
||||
timestamp,
|
||||
task_id: currentTask.id,
|
||||
description: currentTask.description,
|
||||
files_changed: currentTask.files || [],
|
||||
result: 'success'
|
||||
}
|
||||
|
||||
// 追加到 changes.log (NDJSON 格式)
|
||||
const changesContent = Read(changesLogPath) || ''
|
||||
Write(changesLogPath, changesContent + JSON.stringify(changeEntry) + '\n')
|
||||
```
|
||||
|
||||
### Step 3: 更新进度文档
|
||||
|
||||
```javascript
|
||||
const timestamp = getUtc8ISOString()
|
||||
const iteration = state.develop.completed_count + 1
|
||||
|
||||
// 读取现有进度文档
|
||||
let progressContent = Read(progressPath) || ''
|
||||
|
||||
// 如果是新文档,添加头部
|
||||
if (!progressContent) {
|
||||
progressContent = `# Development Progress
|
||||
|
||||
**Session ID**: ${state.session_id}
|
||||
**Task**: ${state.task_description}
|
||||
**Started**: ${timestamp}
|
||||
|
||||
---
|
||||
|
||||
## Progress Timeline
|
||||
|
||||
`
|
||||
}
|
||||
|
||||
// 追加本次进度
|
||||
const progressEntry = `
|
||||
### Iteration ${iteration} - ${currentTask.description} (${timestamp})
|
||||
|
||||
#### Task Details
|
||||
|
||||
- **ID**: ${currentTask.id}
|
||||
- **Tool**: ${currentTask.tool}
|
||||
- **Mode**: ${currentTask.mode}
|
||||
|
||||
#### Implementation Summary
|
||||
|
||||
${implementResult.summary || '实现完成'}
|
||||
|
||||
#### Files Changed
|
||||
|
||||
${currentTask.files?.map(f => `- \`${f}\``).join('\n') || '- No files specified'}
|
||||
|
||||
#### Status: COMPLETED
|
||||
|
||||
---
|
||||
|
||||
`
|
||||
|
||||
Write(progressPath, progressContent + progressEntry)
|
||||
|
||||
// 更新任务状态
|
||||
currentTask.status = 'completed'
|
||||
currentTask.completed_at = timestamp
|
||||
```
|
||||
|
||||
### Step 4: 更新任务列表文件
|
||||
|
||||
```javascript
|
||||
// 更新 tasks.json
|
||||
const updatedTasks = tasks.map(t =>
|
||||
t.id === currentTask.id ? currentTask : t
|
||||
)
|
||||
|
||||
Write(tasksPath, JSON.stringify(updatedTasks, null, 2))
|
||||
```
|
||||
|
||||
## State Updates
|
||||
|
||||
```javascript
|
||||
return {
|
||||
stateUpdates: {
|
||||
develop: {
|
||||
tasks: updatedTasks,
|
||||
current_task_id: null,
|
||||
completed_count: state.develop.completed_count + 1,
|
||||
total_count: updatedTasks.length,
|
||||
last_progress_at: getUtc8ISOString()
|
||||
},
|
||||
last_action: 'action-develop-with-file'
|
||||
},
|
||||
continue: true,
|
||||
message: `任务完成: ${currentTask.description}\n进度: ${state.develop.completed_count + 1}/${updatedTasks.length}`
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error Type | Recovery |
|
||||
|------------|----------|
|
||||
| Gemini CLI 失败 | 提示用户手动实现,记录到 progress.md |
|
||||
| 文件写入失败 | 重试一次,失败则记录错误 |
|
||||
| 任务解析失败 | 询问用户手动输入任务 |
|
||||
|
||||
## Progress Document Template
|
||||
|
||||
```markdown
|
||||
# Development Progress
|
||||
|
||||
**Session ID**: LOOP-xxx-2026-01-22
|
||||
**Task**: 实现用户认证功能
|
||||
**Started**: 2026-01-22T10:00:00+08:00
|
||||
|
||||
---
|
||||
|
||||
## Progress Timeline
|
||||
|
||||
### Iteration 1 - 分析登录组件 (2026-01-22T10:05:00+08:00)
|
||||
|
||||
#### Task Details
|
||||
|
||||
- **ID**: task-001
|
||||
- **Tool**: gemini
|
||||
- **Mode**: analysis
|
||||
|
||||
#### Implementation Summary
|
||||
|
||||
分析了现有登录组件结构,识别了需要修改的文件和依赖关系。
|
||||
|
||||
#### Files Changed
|
||||
|
||||
- `src/components/Login.tsx`
|
||||
- `src/hooks/useAuth.ts`
|
||||
|
||||
#### Status: COMPLETED
|
||||
|
||||
---
|
||||
|
||||
### Iteration 2 - 实现登录 API (2026-01-22T10:15:00+08:00)
|
||||
|
||||
...
|
||||
|
||||
---
|
||||
|
||||
## Current Statistics
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Total Tasks | 5 |
|
||||
| Completed | 2 |
|
||||
| In Progress | 1 |
|
||||
| Pending | 2 |
|
||||
| Progress | 40% |
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [ ] 完成剩余任务
|
||||
- [ ] 运行测试
|
||||
- [ ] 代码审查
|
||||
```
|
||||
|
||||
## CLI Integration
|
||||
|
||||
### 任务分析
|
||||
```bash
|
||||
ccw cli -p "PURPOSE: 分解开发任务为子任务
|
||||
TASK: • 分析任务描述 • 识别功能点 • 生成任务列表
|
||||
MODE: analysis
|
||||
CONTEXT: @package.json @src/**/*
|
||||
EXPECTED: JSON 任务列表
|
||||
" --tool gemini --mode analysis --rule planning-breakdown-task-steps
|
||||
```
|
||||
|
||||
### 代码实现
|
||||
```bash
|
||||
ccw cli -p "PURPOSE: 实现功能代码
|
||||
TASK: • 分析需求 • 编写代码 • 添加类型
|
||||
MODE: write
|
||||
CONTEXT: @src/xxx.ts
|
||||
EXPECTED: 完整实现
|
||||
" --tool gemini --mode write --rule development-implement-feature
|
||||
```
|
||||
|
||||
## Next Actions (Hints)
|
||||
|
||||
- 所有任务完成: `action-debug-with-file` (开始调试)
|
||||
- 任务失败: `action-develop-with-file` (重试或下一个任务)
|
||||
- 用户选择: `action-menu` (返回菜单)
|
||||
200
.claude/skills/ccw-loop/phases/actions/action-init.md
Normal file
200
.claude/skills/ccw-loop/phases/actions/action-init.md
Normal file
@@ -0,0 +1,200 @@
|
||||
# Action: Initialize
|
||||
|
||||
初始化 CCW Loop 会话,创建目录结构和初始状态。
|
||||
|
||||
## Purpose
|
||||
|
||||
- 创建会话目录结构
|
||||
- 初始化状态文件
|
||||
- 分析任务描述生成初始任务列表
|
||||
- 准备执行环境
|
||||
|
||||
## Preconditions
|
||||
|
||||
- [ ] state.status === 'pending'
|
||||
- [ ] state.initialized === false
|
||||
|
||||
## Execution
|
||||
|
||||
### Step 1: 创建目录结构
|
||||
|
||||
```javascript
|
||||
const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString()
|
||||
|
||||
const taskSlug = state.task_description.toLowerCase().replace(/[^a-z0-9]+/g, '-').substring(0, 30)
|
||||
const dateStr = getUtc8ISOString().substring(0, 10)
|
||||
const sessionId = `LOOP-${taskSlug}-${dateStr}`
|
||||
const sessionFolder = `.workflow/.loop/${sessionId}`
|
||||
|
||||
Bash(`mkdir -p "${sessionFolder}/develop"`)
|
||||
Bash(`mkdir -p "${sessionFolder}/debug"`)
|
||||
Bash(`mkdir -p "${sessionFolder}/validate"`)
|
||||
|
||||
console.log(`Session created: ${sessionId}`)
|
||||
console.log(`Location: ${sessionFolder}`)
|
||||
```
|
||||
|
||||
### Step 2: 创建元数据文件
|
||||
|
||||
```javascript
|
||||
const meta = {
|
||||
session_id: sessionId,
|
||||
task_description: state.task_description,
|
||||
created_at: getUtc8ISOString(),
|
||||
mode: state.mode || 'interactive'
|
||||
}
|
||||
|
||||
Write(`${sessionFolder}/meta.json`, JSON.stringify(meta, null, 2))
|
||||
```
|
||||
|
||||
### Step 3: 分析任务生成开发任务列表
|
||||
|
||||
```javascript
|
||||
// 使用 Gemini 分析任务描述
|
||||
console.log('\n分析任务描述...')
|
||||
|
||||
const analysisPrompt = `
|
||||
PURPOSE: 分析开发任务并分解为可执行步骤
|
||||
Success: 生成 3-7 个具体、可验证的子任务
|
||||
|
||||
TASK:
|
||||
• 分析任务描述: ${state.task_description}
|
||||
• 识别关键功能点
|
||||
• 分解为独立子任务
|
||||
• 为每个子任务指定工具和模式
|
||||
|
||||
MODE: analysis
|
||||
|
||||
CONTEXT: @package.json @src/**/*.ts (如存在)
|
||||
|
||||
EXPECTED:
|
||||
JSON 格式:
|
||||
{
|
||||
"tasks": [
|
||||
{
|
||||
"id": "task-001",
|
||||
"description": "任务描述",
|
||||
"tool": "gemini",
|
||||
"mode": "write",
|
||||
"priority": 1
|
||||
}
|
||||
],
|
||||
"estimated_complexity": "low|medium|high",
|
||||
"key_files": ["file1.ts", "file2.ts"]
|
||||
}
|
||||
|
||||
CONSTRAINTS: 生成实际可执行的任务
|
||||
`
|
||||
|
||||
const result = await Bash({
|
||||
command: `ccw cli -p "${analysisPrompt}" --tool gemini --mode analysis --rule planning-breakdown-task-steps`,
|
||||
run_in_background: false
|
||||
})
|
||||
|
||||
const analysis = JSON.parse(result.stdout)
|
||||
const tasks = analysis.tasks.map((t, i) => ({
|
||||
...t,
|
||||
id: t.id || `task-${String(i + 1).padStart(3, '0')}`,
|
||||
status: 'pending',
|
||||
created_at: getUtc8ISOString(),
|
||||
completed_at: null,
|
||||
files_changed: []
|
||||
}))
|
||||
|
||||
// 保存任务列表
|
||||
Write(`${sessionFolder}/develop/tasks.json`, JSON.stringify(tasks, null, 2))
|
||||
```
|
||||
|
||||
### Step 4: 初始化进度文档
|
||||
|
||||
```javascript
|
||||
const progressInitial = `# Development Progress
|
||||
|
||||
**Session ID**: ${sessionId}
|
||||
**Task**: ${state.task_description}
|
||||
**Started**: ${getUtc8ISOString()}
|
||||
**Estimated Complexity**: ${analysis.estimated_complexity}
|
||||
|
||||
---
|
||||
|
||||
## Task List
|
||||
|
||||
${tasks.map((t, i) => `${i + 1}. [ ] ${t.description}`).join('\n')}
|
||||
|
||||
## Key Files
|
||||
|
||||
${analysis.key_files?.map(f => `- \`${f}\``).join('\n') || '- To be determined'}
|
||||
|
||||
---
|
||||
|
||||
## Progress Timeline
|
||||
|
||||
`
|
||||
|
||||
Write(`${sessionFolder}/develop/progress.md`, progressInitial)
|
||||
```
|
||||
|
||||
### Step 5: 显示初始化结果
|
||||
|
||||
```javascript
|
||||
console.log(`\n✅ 会话初始化完成`)
|
||||
console.log(`\n任务列表 (${tasks.length} 项):`)
|
||||
tasks.forEach((t, i) => {
|
||||
console.log(` ${i + 1}. ${t.description} [${t.tool}/${t.mode}]`)
|
||||
})
|
||||
console.log(`\n预估复杂度: ${analysis.estimated_complexity}`)
|
||||
console.log(`\n执行 'develop' 开始开发,或 'menu' 查看更多选项`)
|
||||
```
|
||||
|
||||
## State Updates
|
||||
|
||||
```javascript
|
||||
return {
|
||||
stateUpdates: {
|
||||
session_id: sessionId,
|
||||
status: 'running',
|
||||
initialized: true,
|
||||
develop: {
|
||||
tasks: tasks,
|
||||
current_task_id: null,
|
||||
completed_count: 0,
|
||||
total_count: tasks.length,
|
||||
last_progress_at: null
|
||||
},
|
||||
debug: {
|
||||
current_bug: null,
|
||||
hypotheses: [],
|
||||
confirmed_hypothesis: null,
|
||||
iteration: 0,
|
||||
last_analysis_at: null,
|
||||
understanding_updated: false
|
||||
},
|
||||
validate: {
|
||||
test_results: [],
|
||||
coverage: null,
|
||||
passed: false,
|
||||
failed_tests: [],
|
||||
last_run_at: null
|
||||
},
|
||||
context: {
|
||||
estimated_complexity: analysis.estimated_complexity,
|
||||
key_files: analysis.key_files
|
||||
}
|
||||
},
|
||||
continue: true,
|
||||
message: `会话 ${sessionId} 已初始化\n${tasks.length} 个开发任务待执行`
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error Type | Recovery |
|
||||
|------------|----------|
|
||||
| 目录创建失败 | 检查权限,重试 |
|
||||
| Gemini 分析失败 | 提示用户手动输入任务 |
|
||||
| 任务解析失败 | 使用默认任务列表 |
|
||||
|
||||
## Next Actions
|
||||
|
||||
- 成功: `action-menu` (显示操作菜单) 或 `action-develop-with-file` (直接开始开发)
|
||||
- 失败: 报错退出
|
||||
192
.claude/skills/ccw-loop/phases/actions/action-menu.md
Normal file
192
.claude/skills/ccw-loop/phases/actions/action-menu.md
Normal file
@@ -0,0 +1,192 @@
|
||||
# Action: Menu
|
||||
|
||||
显示交互式操作菜单,让用户选择下一步操作。
|
||||
|
||||
## Purpose
|
||||
|
||||
- 显示当前状态摘要
|
||||
- 提供操作选项
|
||||
- 接收用户选择
|
||||
- 返回下一个动作
|
||||
|
||||
## Preconditions
|
||||
|
||||
- [ ] state.initialized === true
|
||||
- [ ] state.status === 'running'
|
||||
|
||||
## Execution
|
||||
|
||||
### Step 1: 生成状态摘要
|
||||
|
||||
```javascript
|
||||
const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString()
|
||||
|
||||
// 开发进度
|
||||
const developProgress = state.develop.total_count > 0
|
||||
? `${state.develop.completed_count}/${state.develop.total_count} (${(state.develop.completed_count / state.develop.total_count * 100).toFixed(0)}%)`
|
||||
: '未开始'
|
||||
|
||||
// 调试状态
|
||||
const debugStatus = state.debug.confirmed_hypothesis
|
||||
? `✅ 已确认根因`
|
||||
: state.debug.iteration > 0
|
||||
? `🔍 迭代 ${state.debug.iteration}`
|
||||
: '未开始'
|
||||
|
||||
// 验证状态
|
||||
const validateStatus = state.validate.passed
|
||||
? `✅ 通过`
|
||||
: state.validate.test_results.length > 0
|
||||
? `❌ ${state.validate.failed_tests.length} 个失败`
|
||||
: '未运行'
|
||||
|
||||
const statusSummary = `
|
||||
═══════════════════════════════════════════════════════════
|
||||
CCW Loop - ${state.session_id}
|
||||
═══════════════════════════════════════════════════════════
|
||||
|
||||
任务: ${state.task_description}
|
||||
迭代: ${state.iteration_count}
|
||||
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ 开发 (Develop) │ ${developProgress.padEnd(20)} │
|
||||
│ 调试 (Debug) │ ${debugStatus.padEnd(20)} │
|
||||
│ 验证 (Validate) │ ${validateStatus.padEnd(20)} │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
|
||||
═══════════════════════════════════════════════════════════
|
||||
`
|
||||
|
||||
console.log(statusSummary)
|
||||
```
|
||||
|
||||
### Step 2: 显示操作选项
|
||||
|
||||
```javascript
|
||||
const options = [
|
||||
{
|
||||
label: "📝 继续开发 (Develop)",
|
||||
description: state.develop.completed_count < state.develop.total_count
|
||||
? `执行下一个开发任务`
|
||||
: "所有任务已完成,可添加新任务",
|
||||
action: "action-develop-with-file"
|
||||
},
|
||||
{
|
||||
label: "🔍 开始调试 (Debug)",
|
||||
description: state.debug.iteration > 0
|
||||
? "继续假设驱动调试"
|
||||
: "开始新的调试会话",
|
||||
action: "action-debug-with-file"
|
||||
},
|
||||
{
|
||||
label: "✅ 运行验证 (Validate)",
|
||||
description: "运行测试并检查覆盖率",
|
||||
action: "action-validate-with-file"
|
||||
},
|
||||
{
|
||||
label: "📊 查看详情 (Status)",
|
||||
description: "查看详细进度和文件",
|
||||
action: "action-status"
|
||||
},
|
||||
{
|
||||
label: "🏁 完成循环 (Complete)",
|
||||
description: "结束当前循环",
|
||||
action: "action-complete"
|
||||
},
|
||||
{
|
||||
label: "🚪 退出 (Exit)",
|
||||
description: "保存状态并退出",
|
||||
action: "exit"
|
||||
}
|
||||
]
|
||||
|
||||
const response = await AskUserQuestion({
|
||||
questions: [{
|
||||
question: "选择下一步操作:",
|
||||
header: "操作",
|
||||
multiSelect: false,
|
||||
options: options.map(o => ({
|
||||
label: o.label,
|
||||
description: o.description
|
||||
}))
|
||||
}]
|
||||
})
|
||||
|
||||
const selectedLabel = response["操作"]
|
||||
const selectedOption = options.find(o => o.label === selectedLabel)
|
||||
const nextAction = selectedOption?.action || 'action-menu'
|
||||
```
|
||||
|
||||
### Step 3: 处理特殊选项
|
||||
|
||||
```javascript
|
||||
if (nextAction === 'exit') {
|
||||
console.log('\n保存状态并退出...')
|
||||
return {
|
||||
stateUpdates: {
|
||||
status: 'user_exit'
|
||||
},
|
||||
continue: false,
|
||||
message: '会话已保存,使用 --resume 可继续'
|
||||
}
|
||||
}
|
||||
|
||||
if (nextAction === 'action-status') {
|
||||
// 显示详细状态
|
||||
const sessionFolder = `.workflow/.loop/${state.session_id}`
|
||||
|
||||
console.log('\n=== 开发进度 ===')
|
||||
const progress = Read(`${sessionFolder}/develop/progress.md`)
|
||||
console.log(progress?.substring(0, 500) + '...')
|
||||
|
||||
console.log('\n=== 调试状态 ===')
|
||||
if (state.debug.hypotheses.length > 0) {
|
||||
state.debug.hypotheses.forEach(h => {
|
||||
console.log(` ${h.id}: ${h.status} - ${h.description.substring(0, 50)}...`)
|
||||
})
|
||||
} else {
|
||||
console.log(' 尚未开始调试')
|
||||
}
|
||||
|
||||
console.log('\n=== 验证结果 ===')
|
||||
if (state.validate.test_results.length > 0) {
|
||||
const latest = state.validate.test_results[state.validate.test_results.length - 1]
|
||||
console.log(` 最近运行: ${latest.timestamp}`)
|
||||
console.log(` 通过率: ${latest.summary.pass_rate}%`)
|
||||
} else {
|
||||
console.log(' 尚未运行验证')
|
||||
}
|
||||
|
||||
// 返回菜单
|
||||
return {
|
||||
stateUpdates: {},
|
||||
continue: true,
|
||||
nextAction: 'action-menu',
|
||||
message: ''
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## State Updates
|
||||
|
||||
```javascript
|
||||
return {
|
||||
stateUpdates: {
|
||||
// 不更新状态,仅返回下一个动作
|
||||
},
|
||||
continue: true,
|
||||
nextAction: nextAction,
|
||||
message: `执行: ${selectedOption?.label || nextAction}`
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error Type | Recovery |
|
||||
|------------|----------|
|
||||
| 用户取消 | 返回菜单 |
|
||||
| 无效选择 | 重新显示菜单 |
|
||||
|
||||
## Next Actions
|
||||
|
||||
根据用户选择动态决定下一个动作。
|
||||
@@ -0,0 +1,307 @@
|
||||
# Action: Validate With File
|
||||
|
||||
运行测试并验证实现,记录结果到 validation.md,支持 Gemini 辅助分析测试覆盖率和质量。
|
||||
|
||||
## Purpose
|
||||
|
||||
执行测试验证流程,包括:
|
||||
- 运行单元测试
|
||||
- 运行集成测试
|
||||
- 检查代码覆盖率
|
||||
- 生成验证报告
|
||||
- 分析失败原因
|
||||
|
||||
## Preconditions
|
||||
|
||||
- [ ] state.initialized === true
|
||||
- [ ] state.status === 'running'
|
||||
- [ ] state.develop.completed_count > 0 || state.debug.confirmed_hypothesis !== null
|
||||
|
||||
## Session Setup
|
||||
|
||||
```javascript
|
||||
const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString()
|
||||
|
||||
const sessionFolder = `.workflow/.loop/${state.session_id}`
|
||||
const validateFolder = `${sessionFolder}/validate`
|
||||
const validationPath = `${validateFolder}/validation.md`
|
||||
const testResultsPath = `${validateFolder}/test-results.json`
|
||||
const coveragePath = `${validateFolder}/coverage.json`
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execution
|
||||
|
||||
### Step 1: 运行测试
|
||||
|
||||
```javascript
|
||||
console.log('\n运行测试...')
|
||||
|
||||
// 检测测试框架
|
||||
const packageJson = JSON.parse(Read('package.json'))
|
||||
const testScript = packageJson.scripts?.test || 'npm test'
|
||||
|
||||
// 运行测试并捕获输出
|
||||
const testResult = await Bash({
|
||||
command: testScript,
|
||||
timeout: 300000 // 5分钟
|
||||
})
|
||||
|
||||
// 解析测试输出
|
||||
const testResults = parseTestOutput(testResult.stdout)
|
||||
```
|
||||
|
||||
### Step 2: 检查覆盖率
|
||||
|
||||
```javascript
|
||||
// 运行覆盖率检查
|
||||
let coverageData = null
|
||||
|
||||
if (packageJson.scripts?.['test:coverage']) {
|
||||
const coverageResult = await Bash({
|
||||
command: 'npm run test:coverage',
|
||||
timeout: 300000
|
||||
})
|
||||
|
||||
// 解析覆盖率报告
|
||||
coverageData = parseCoverageReport(coverageResult.stdout)
|
||||
|
||||
Write(coveragePath, JSON.stringify(coverageData, null, 2))
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: Gemini 辅助分析
|
||||
|
||||
```bash
|
||||
ccw cli -p "
|
||||
PURPOSE: Analyze test results and coverage
|
||||
Success criteria: Identify quality issues and suggest improvements
|
||||
|
||||
TASK:
|
||||
• Analyze test execution results
|
||||
• Review code coverage metrics
|
||||
• Identify missing test cases
|
||||
• Suggest quality improvements
|
||||
• Verify requirements coverage
|
||||
|
||||
MODE: analysis
|
||||
|
||||
CONTEXT:
|
||||
@${testResultsPath}
|
||||
@${coveragePath}
|
||||
@${sessionFolder}/develop/progress.md
|
||||
|
||||
EXPECTED:
|
||||
- Quality assessment report
|
||||
- Failed tests analysis
|
||||
- Coverage gaps identification
|
||||
- Improvement recommendations
|
||||
- Pass/Fail decision with rationale
|
||||
|
||||
CONSTRAINTS: Evidence-based quality assessment
|
||||
" --tool gemini --mode analysis --rule analysis-review-code-quality
|
||||
```
|
||||
|
||||
### Step 4: 生成验证报告
|
||||
|
||||
```javascript
|
||||
const timestamp = getUtc8ISOString()
|
||||
const iteration = (state.validate.test_results?.length || 0) + 1
|
||||
|
||||
const validationReport = `# Validation Report
|
||||
|
||||
**Session ID**: ${state.session_id}
|
||||
**Task**: ${state.task_description}
|
||||
**Validated**: ${timestamp}
|
||||
|
||||
---
|
||||
|
||||
## Iteration ${iteration} - Validation Run
|
||||
|
||||
### Test Execution Summary
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Total Tests | ${testResults.total} |
|
||||
| Passed | ${testResults.passed} |
|
||||
| Failed | ${testResults.failed} |
|
||||
| Skipped | ${testResults.skipped} |
|
||||
| Duration | ${testResults.duration_ms}ms |
|
||||
| **Pass Rate** | **${(testResults.passed / testResults.total * 100).toFixed(1)}%** |
|
||||
|
||||
### Coverage Report
|
||||
|
||||
${coverageData ? `
|
||||
| File | Statements | Branches | Functions | Lines |
|
||||
|------|------------|----------|-----------|-------|
|
||||
${coverageData.files.map(f => `| ${f.path} | ${f.statements}% | ${f.branches}% | ${f.functions}% | ${f.lines}% |`).join('\n')}
|
||||
|
||||
**Overall Coverage**: ${coverageData.overall.statements}%
|
||||
` : '_No coverage data available_'}
|
||||
|
||||
### Failed Tests
|
||||
|
||||
${testResults.failed > 0 ? `
|
||||
${testResults.failures.map(f => `
|
||||
#### ${f.test_name}
|
||||
|
||||
- **Suite**: ${f.suite}
|
||||
- **Error**: ${f.error_message}
|
||||
- **Stack**:
|
||||
\`\`\`
|
||||
${f.stack_trace}
|
||||
\`\`\`
|
||||
`).join('\n')}
|
||||
` : '_All tests passed_'}
|
||||
|
||||
### Gemini Quality Analysis
|
||||
|
||||
${geminiAnalysis}
|
||||
|
||||
### Recommendations
|
||||
|
||||
${recommendations.map(r => `- ${r}`).join('\n')}
|
||||
|
||||
---
|
||||
|
||||
## Validation Decision
|
||||
|
||||
**Result**: ${testResults.passed === testResults.total ? '✅ PASS' : '❌ FAIL'}
|
||||
|
||||
**Rationale**: ${validationDecision}
|
||||
|
||||
${testResults.passed !== testResults.total ? `
|
||||
### Next Actions
|
||||
|
||||
1. Review failed tests
|
||||
2. Debug failures using action-debug-with-file
|
||||
3. Fix issues and re-run validation
|
||||
` : `
|
||||
### Next Actions
|
||||
|
||||
1. Consider code review
|
||||
2. Prepare for deployment
|
||||
3. Update documentation
|
||||
`}
|
||||
`
|
||||
|
||||
// 写入验证报告
|
||||
Write(validationPath, validationReport)
|
||||
```
|
||||
|
||||
### Step 5: 保存测试结果
|
||||
|
||||
```javascript
|
||||
const testResultsData = {
|
||||
iteration,
|
||||
timestamp,
|
||||
summary: {
|
||||
total: testResults.total,
|
||||
passed: testResults.passed,
|
||||
failed: testResults.failed,
|
||||
skipped: testResults.skipped,
|
||||
pass_rate: (testResults.passed / testResults.total * 100).toFixed(1),
|
||||
duration_ms: testResults.duration_ms
|
||||
},
|
||||
tests: testResults.tests,
|
||||
failures: testResults.failures,
|
||||
coverage: coverageData?.overall || null
|
||||
}
|
||||
|
||||
Write(testResultsPath, JSON.stringify(testResultsData, null, 2))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## State Updates
|
||||
|
||||
```javascript
|
||||
const validationPassed = testResults.failed === 0 && testResults.passed > 0
|
||||
|
||||
return {
|
||||
stateUpdates: {
|
||||
validate: {
|
||||
test_results: [...(state.validate.test_results || []), testResultsData],
|
||||
coverage: coverageData?.overall.statements || null,
|
||||
passed: validationPassed,
|
||||
failed_tests: testResults.failures.map(f => f.test_name),
|
||||
last_run_at: getUtc8ISOString()
|
||||
},
|
||||
last_action: 'action-validate-with-file'
|
||||
},
|
||||
continue: true,
|
||||
message: validationPassed
|
||||
? `验证通过 ✅\n测试: ${testResults.passed}/${testResults.total}\n覆盖率: ${coverageData?.overall.statements || 'N/A'}%`
|
||||
: `验证失败 ❌\n失败: ${testResults.failed}/${testResults.total}\n建议进入调试模式`
|
||||
}
|
||||
```
|
||||
|
||||
## Test Output Parsers
|
||||
|
||||
### Jest/Vitest Parser
|
||||
|
||||
```javascript
|
||||
function parseJestOutput(stdout) {
|
||||
const testPattern = /Tests:\s+(\d+) passed.*?(\d+) failed.*?(\d+) total/
|
||||
const match = stdout.match(testPattern)
|
||||
|
||||
return {
|
||||
total: parseInt(match[3]),
|
||||
passed: parseInt(match[1]),
|
||||
failed: parseInt(match[2]),
|
||||
// ... parse individual test results
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Pytest Parser
|
||||
|
||||
```javascript
|
||||
function parsePytestOutput(stdout) {
|
||||
const summaryPattern = /(\d+) passed.*?(\d+) failed.*?(\d+) error/
|
||||
// ... implementation
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error Type | Recovery |
|
||||
|------------|----------|
|
||||
| Tests don't run | 检查测试脚本配置,提示用户 |
|
||||
| All tests fail | 建议进入 debug 模式 |
|
||||
| Coverage tool missing | 跳过覆盖率检查,仅运行测试 |
|
||||
| Timeout | 增加超时时间或拆分测试 |
|
||||
|
||||
## Validation Report Template
|
||||
|
||||
参考 [templates/validation-template.md](../../templates/validation-template.md)
|
||||
|
||||
## CLI Integration
|
||||
|
||||
### 质量分析
|
||||
```bash
|
||||
ccw cli -p "PURPOSE: Analyze test results and coverage...
|
||||
TASK: • Review results • Identify gaps • Suggest improvements
|
||||
MODE: analysis
|
||||
CONTEXT: @test-results.json @coverage.json
|
||||
EXPECTED: Quality assessment
|
||||
" --tool gemini --mode analysis --rule analysis-review-code-quality
|
||||
```
|
||||
|
||||
### 测试生成 (如覆盖率低)
|
||||
```bash
|
||||
ccw cli -p "PURPOSE: Generate missing test cases...
|
||||
TASK: • Analyze uncovered code • Write tests
|
||||
MODE: write
|
||||
CONTEXT: @coverage.json @src/**/*
|
||||
EXPECTED: Test code
|
||||
" --tool gemini --mode write --rule development-generate-tests
|
||||
```
|
||||
|
||||
## Next Actions (Hints)
|
||||
|
||||
- 验证通过: `action-complete` (完成循环)
|
||||
- 验证失败: `action-debug-with-file` (调试失败测试)
|
||||
- 覆盖率低: `action-develop-with-file` (添加测试)
|
||||
- 用户选择: `action-menu` (返回菜单)
|
||||
486
.claude/skills/ccw-loop/phases/orchestrator.md
Normal file
486
.claude/skills/ccw-loop/phases/orchestrator.md
Normal file
@@ -0,0 +1,486 @@
|
||||
# Orchestrator
|
||||
|
||||
根据当前状态选择并执行下一个动作,实现无状态循环工作流。与 API (loop-v2-routes.ts) 协作实现控制平面/执行平面分离。
|
||||
|
||||
## Role
|
||||
|
||||
检查控制信号 → 读取文件状态 → 选择动作 → 执行 → 更新文件 → 循环,直到完成或被外部暂停/停止。
|
||||
|
||||
## State Management (Unified Location)
|
||||
|
||||
### 读取状态
|
||||
|
||||
```javascript
|
||||
const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString()
|
||||
|
||||
/**
|
||||
* 读取循环状态 (统一位置)
|
||||
* @param loopId - Loop ID (e.g., "loop-v2-20260122-abc123")
|
||||
*/
|
||||
function readLoopState(loopId) {
|
||||
const stateFile = `.loop/${loopId}.json`
|
||||
|
||||
if (!fs.existsSync(stateFile)) {
|
||||
return null
|
||||
}
|
||||
|
||||
const state = JSON.parse(Read(stateFile))
|
||||
return state
|
||||
}
|
||||
```
|
||||
|
||||
### 更新状态
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* 更新循环状态 (只更新 skill_state 部分,不修改 API 字段)
|
||||
* @param loopId - Loop ID
|
||||
* @param updates - 更新内容 (skill_state 字段)
|
||||
*/
|
||||
function updateLoopState(loopId, updates) {
|
||||
const stateFile = `.loop/${loopId}.json`
|
||||
const currentState = readLoopState(loopId)
|
||||
|
||||
if (!currentState) {
|
||||
throw new Error(`Loop state not found: ${loopId}`)
|
||||
}
|
||||
|
||||
// 只更新 skill_state 和 updated_at
|
||||
const newState = {
|
||||
...currentState,
|
||||
updated_at: getUtc8ISOString(),
|
||||
skill_state: {
|
||||
...currentState.skill_state,
|
||||
...updates
|
||||
}
|
||||
}
|
||||
|
||||
Write(stateFile, JSON.stringify(newState, null, 2))
|
||||
return newState
|
||||
}
|
||||
```
|
||||
|
||||
### 创建新循环状态 (直接调用时)
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* 创建新的循环状态 (仅在直接调用时使用,API 触发时状态已存在)
|
||||
*/
|
||||
function createLoopState(loopId, taskDescription) {
|
||||
const stateFile = `.loop/${loopId}.json`
|
||||
const now = getUtc8ISOString()
|
||||
|
||||
const state = {
|
||||
// API 兼容字段
|
||||
loop_id: loopId,
|
||||
title: taskDescription.substring(0, 100),
|
||||
description: taskDescription,
|
||||
max_iterations: 10,
|
||||
status: 'running', // 直接调用时设为 running
|
||||
current_iteration: 0,
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
|
||||
// Skill 扩展字段
|
||||
skill_state: null // 由 action-init 初始化
|
||||
}
|
||||
|
||||
// 确保目录存在
|
||||
Bash(`mkdir -p ".loop"`)
|
||||
Bash(`mkdir -p ".loop/${loopId}.progress"`)
|
||||
|
||||
Write(stateFile, JSON.stringify(state, null, 2))
|
||||
return state
|
||||
}
|
||||
```
|
||||
|
||||
## Control Signal Checking
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* 检查 API 控制信号
|
||||
* 必须在每个 Action 开始前调用
|
||||
* @returns { continue: boolean, reason: string }
|
||||
*/
|
||||
function checkControlSignals(loopId) {
|
||||
const state = readLoopState(loopId)
|
||||
|
||||
if (!state) {
|
||||
return { continue: false, reason: 'state_not_found' }
|
||||
}
|
||||
|
||||
switch (state.status) {
|
||||
case 'paused':
|
||||
// API 暂停了循环,Skill 应退出等待 resume
|
||||
console.log(`⏸️ Loop paused by API. Waiting for resume...`)
|
||||
return { continue: false, reason: 'paused' }
|
||||
|
||||
case 'failed':
|
||||
// API 停止了循环 (用户手动停止)
|
||||
console.log(`⏹️ Loop stopped by API.`)
|
||||
return { continue: false, reason: 'stopped' }
|
||||
|
||||
case 'completed':
|
||||
// 已完成
|
||||
console.log(`✅ Loop already completed.`)
|
||||
return { continue: false, reason: 'completed' }
|
||||
|
||||
case 'created':
|
||||
// API 创建但未启动 (不应该走到这里)
|
||||
console.log(`⚠️ Loop not started by API.`)
|
||||
return { continue: false, reason: 'not_started' }
|
||||
|
||||
case 'running':
|
||||
// 正常继续
|
||||
return { continue: true, reason: 'running' }
|
||||
|
||||
default:
|
||||
console.log(`⚠️ Unknown status: ${state.status}`)
|
||||
return { continue: false, reason: 'unknown_status' }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Decision Logic
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* 选择下一个 Action (基于 skill_state)
|
||||
*/
|
||||
function selectNextAction(state, mode = 'interactive') {
|
||||
const skillState = state.skill_state
|
||||
|
||||
// 1. 终止条件检查 (API status)
|
||||
if (state.status === 'completed') return null
|
||||
if (state.status === 'failed') return null
|
||||
if (state.current_iteration >= state.max_iterations) {
|
||||
console.warn(`已达到最大迭代次数 (${state.max_iterations})`)
|
||||
return 'action-complete'
|
||||
}
|
||||
|
||||
// 2. 初始化检查
|
||||
if (!skillState || !skillState.current_action) {
|
||||
return 'action-init'
|
||||
}
|
||||
|
||||
// 3. 模式判断
|
||||
if (mode === 'interactive') {
|
||||
return 'action-menu' // 显示菜单让用户选择
|
||||
}
|
||||
|
||||
// 4. 自动模式:基于状态自动选择
|
||||
if (mode === 'auto') {
|
||||
// 按优先级:develop → debug → validate
|
||||
|
||||
// 如果有待开发任务
|
||||
const hasPendingDevelop = skillState.develop?.tasks?.some(t => t.status === 'pending')
|
||||
if (hasPendingDevelop) {
|
||||
return 'action-develop-with-file'
|
||||
}
|
||||
|
||||
// 如果开发完成但未调试
|
||||
if (skillState.last_action === 'action-develop-with-file') {
|
||||
const needsDebug = skillState.develop?.completed < skillState.develop?.total
|
||||
if (needsDebug) {
|
||||
return 'action-debug-with-file'
|
||||
}
|
||||
}
|
||||
|
||||
// 如果调试完成但未验证
|
||||
if (skillState.last_action === 'action-debug-with-file' ||
|
||||
skillState.debug?.confirmed_hypothesis) {
|
||||
return 'action-validate-with-file'
|
||||
}
|
||||
|
||||
// 如果验证失败,回到开发
|
||||
if (skillState.last_action === 'action-validate-with-file') {
|
||||
if (!skillState.validate?.passed) {
|
||||
return 'action-develop-with-file'
|
||||
}
|
||||
}
|
||||
|
||||
// 全部通过,完成
|
||||
if (skillState.validate?.passed && !hasPendingDevelop) {
|
||||
return 'action-complete'
|
||||
}
|
||||
|
||||
// 默认:开发
|
||||
return 'action-develop-with-file'
|
||||
}
|
||||
|
||||
// 5. 默认完成
|
||||
return 'action-complete'
|
||||
}
|
||||
```
|
||||
|
||||
## Execution Loop
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* 运行编排器
|
||||
* @param options.loopId - 现有 Loop ID (API 触发时)
|
||||
* @param options.task - 任务描述 (直接调用时)
|
||||
* @param options.mode - 'interactive' | 'auto'
|
||||
*/
|
||||
async function runOrchestrator(options = {}) {
|
||||
const { loopId: existingLoopId, task, mode = 'interactive' } = options
|
||||
|
||||
console.log('=== CCW Loop Orchestrator Started ===')
|
||||
|
||||
// 1. 确定 loopId
|
||||
let loopId
|
||||
let state
|
||||
|
||||
if (existingLoopId) {
|
||||
// API 触发:使用现有 loopId
|
||||
loopId = existingLoopId
|
||||
state = readLoopState(loopId)
|
||||
|
||||
if (!state) {
|
||||
console.error(`Loop not found: ${loopId}`)
|
||||
return { status: 'error', message: 'Loop not found' }
|
||||
}
|
||||
|
||||
console.log(`Resuming loop: ${loopId}`)
|
||||
console.log(`Status: ${state.status}`)
|
||||
|
||||
} else if (task) {
|
||||
// 直接调用:创建新 loopId
|
||||
const timestamp = getUtc8ISOString().replace(/[-:]/g, '').split('.')[0]
|
||||
const random = Math.random().toString(36).substring(2, 10)
|
||||
loopId = `loop-v2-${timestamp}-${random}`
|
||||
|
||||
console.log(`Creating new loop: ${loopId}`)
|
||||
console.log(`Task: ${task}`)
|
||||
|
||||
state = createLoopState(loopId, task)
|
||||
|
||||
} else {
|
||||
console.error('Either --loop-id or task description is required')
|
||||
return { status: 'error', message: 'Missing loopId or task' }
|
||||
}
|
||||
|
||||
const progressDir = `.loop/${loopId}.progress`
|
||||
|
||||
// 2. 主循环
|
||||
let iteration = state.current_iteration || 0
|
||||
|
||||
while (iteration < state.max_iterations) {
|
||||
iteration++
|
||||
|
||||
// ========================================
|
||||
// CRITICAL: Check control signals first
|
||||
// ========================================
|
||||
const control = checkControlSignals(loopId)
|
||||
if (!control.continue) {
|
||||
console.log(`\n🛑 Loop terminated: ${control.reason}`)
|
||||
break
|
||||
}
|
||||
|
||||
// 重新读取状态 (可能被 API 更新)
|
||||
state = readLoopState(loopId)
|
||||
|
||||
console.log(`\n[Iteration ${iteration}] Status: ${state.status}`)
|
||||
|
||||
// 选择下一个动作
|
||||
const actionId = selectNextAction(state, mode)
|
||||
|
||||
if (!actionId) {
|
||||
console.log('No action selected, terminating.')
|
||||
break
|
||||
}
|
||||
|
||||
console.log(`[Iteration ${iteration}] Executing: ${actionId}`)
|
||||
|
||||
// 更新 current_iteration
|
||||
state = {
|
||||
...state,
|
||||
current_iteration: iteration,
|
||||
updated_at: getUtc8ISOString()
|
||||
}
|
||||
Write(`.loop/${loopId}.json`, JSON.stringify(state, null, 2))
|
||||
|
||||
// 执行动作
|
||||
try {
|
||||
const actionPromptFile = `.claude/skills/ccw-loop/phases/actions/${actionId}.md`
|
||||
|
||||
if (!fs.existsSync(actionPromptFile)) {
|
||||
console.error(`Action file not found: ${actionPromptFile}`)
|
||||
continue
|
||||
}
|
||||
|
||||
const actionPrompt = Read(actionPromptFile)
|
||||
|
||||
// 构建 Agent 提示
|
||||
const agentPrompt = `
|
||||
[LOOP CONTEXT]
|
||||
Loop ID: ${loopId}
|
||||
State File: .loop/${loopId}.json
|
||||
Progress Dir: ${progressDir}
|
||||
|
||||
[CURRENT STATE]
|
||||
${JSON.stringify(state, null, 2)}
|
||||
|
||||
[ACTION INSTRUCTIONS]
|
||||
${actionPrompt}
|
||||
|
||||
[TASK]
|
||||
You are executing ${actionId} for loop: ${state.title || state.description}
|
||||
|
||||
[CONTROL SIGNALS]
|
||||
Before executing, check if status is still 'running'.
|
||||
If status is 'paused' or 'failed', exit gracefully.
|
||||
|
||||
[RETURN]
|
||||
Return JSON with:
|
||||
- skillStateUpdates: Object with skill_state fields to update
|
||||
- continue: Boolean indicating if loop should continue
|
||||
- message: String with user message
|
||||
`
|
||||
|
||||
const result = await Task({
|
||||
subagent_type: 'universal-executor',
|
||||
run_in_background: false,
|
||||
description: `Execute ${actionId}`,
|
||||
prompt: agentPrompt
|
||||
})
|
||||
|
||||
// 解析结果
|
||||
const actionResult = JSON.parse(result)
|
||||
|
||||
// 更新状态 (只更新 skill_state)
|
||||
updateLoopState(loopId, {
|
||||
current_action: null,
|
||||
last_action: actionId,
|
||||
completed_actions: [
|
||||
...(state.skill_state?.completed_actions || []),
|
||||
actionId
|
||||
],
|
||||
...actionResult.skillStateUpdates
|
||||
})
|
||||
|
||||
// 显示消息
|
||||
if (actionResult.message) {
|
||||
console.log(`\n${actionResult.message}`)
|
||||
}
|
||||
|
||||
// 检查是否继续
|
||||
if (actionResult.continue === false) {
|
||||
console.log('Action requested termination.')
|
||||
break
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Error executing ${actionId}: ${error.message}`)
|
||||
|
||||
// 错误处理
|
||||
updateLoopState(loopId, {
|
||||
current_action: null,
|
||||
errors: [
|
||||
...(state.skill_state?.errors || []),
|
||||
{
|
||||
action: actionId,
|
||||
message: error.message,
|
||||
timestamp: getUtc8ISOString()
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (iteration >= state.max_iterations) {
|
||||
console.log(`\n⚠️ Reached maximum iterations (${state.max_iterations})`)
|
||||
console.log('Consider breaking down the task or taking a break.')
|
||||
}
|
||||
|
||||
console.log('\n=== CCW Loop Orchestrator Finished ===')
|
||||
|
||||
// 返回最终状态
|
||||
const finalState = readLoopState(loopId)
|
||||
return {
|
||||
status: finalState.status,
|
||||
loop_id: loopId,
|
||||
iterations: iteration,
|
||||
final_state: finalState
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Action Catalog
|
||||
|
||||
| Action | Purpose | Preconditions | Effects |
|
||||
|--------|---------|---------------|---------|
|
||||
| [action-init](actions/action-init.md) | 初始化会话 | status=pending | initialized=true |
|
||||
| [action-menu](actions/action-menu.md) | 显示操作菜单 | initialized=true | 用户选择下一动作 |
|
||||
| [action-develop-with-file](actions/action-develop-with-file.md) | 开发任务 | initialized=true | 更新 progress.md |
|
||||
| [action-debug-with-file](actions/action-debug-with-file.md) | 假设调试 | initialized=true | 更新 understanding.md |
|
||||
| [action-validate-with-file](actions/action-validate-with-file.md) | 测试验证 | initialized=true | 更新 validation.md |
|
||||
| [action-complete](actions/action-complete.md) | 完成循环 | validation_passed=true | status=completed |
|
||||
|
||||
## Termination Conditions
|
||||
|
||||
1. **API 暂停**: `state.status === 'paused'` (Skill 退出,等待 resume)
|
||||
2. **API 停止**: `state.status === 'failed'` (Skill 终止)
|
||||
3. **任务完成**: `state.status === 'completed'`
|
||||
4. **迭代限制**: `state.current_iteration >= state.max_iterations`
|
||||
5. **Action 请求终止**: `actionResult.continue === false`
|
||||
|
||||
## Error Recovery
|
||||
|
||||
| Error Type | Recovery Strategy |
|
||||
|------------|-------------------|
|
||||
| 动作执行失败 | 记录错误,增加 error_count,继续下一动作 |
|
||||
| 状态文件损坏 | 从其他文件重建状态 (progress.md, understanding.md 等) |
|
||||
| 用户中止 | 保存当前状态,允许 --resume 恢复 |
|
||||
| CLI 工具失败 | 回退到手动分析模式 |
|
||||
|
||||
## Mode Strategies
|
||||
|
||||
### Interactive Mode (默认)
|
||||
|
||||
每次显示菜单,让用户选择动作:
|
||||
|
||||
```
|
||||
当前状态: 开发中
|
||||
可用操作:
|
||||
1. 继续开发 (develop)
|
||||
2. 开始调试 (debug)
|
||||
3. 运行验证 (validate)
|
||||
4. 查看进度 (status)
|
||||
5. 退出 (exit)
|
||||
|
||||
请选择:
|
||||
```
|
||||
|
||||
### Auto Mode (自动循环)
|
||||
|
||||
按预设流程自动执行:
|
||||
|
||||
```
|
||||
Develop → Debug → Validate →
|
||||
↓ (如验证失败)
|
||||
Develop (修复) → Debug → Validate → 完成
|
||||
```
|
||||
|
||||
## State Machine (API Status)
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> created: API creates loop
|
||||
created --> running: API /start → Trigger Skill
|
||||
running --> paused: API /pause → Set status
|
||||
running --> completed: action-complete
|
||||
running --> failed: API /stop OR error
|
||||
paused --> running: API /resume → Re-trigger Skill
|
||||
completed --> [*]
|
||||
failed --> [*]
|
||||
|
||||
note right of paused
|
||||
Skill checks status before each action
|
||||
If paused, Skill exits gracefully
|
||||
end note
|
||||
|
||||
note right of running
|
||||
Skill executes: init → develop → debug → validate
|
||||
end note
|
||||
```
|
||||
474
.claude/skills/ccw-loop/phases/state-schema.md
Normal file
474
.claude/skills/ccw-loop/phases/state-schema.md
Normal file
@@ -0,0 +1,474 @@
|
||||
# State Schema
|
||||
|
||||
CCW Loop 的状态结构定义(统一版本)。
|
||||
|
||||
## 状态文件
|
||||
|
||||
**位置**: `.loop/{loopId}.json` (统一位置,API + Skill 共享)
|
||||
|
||||
**旧版本位置** (仅向后兼容): `.workflow/.loop/{session-id}/state.json`
|
||||
|
||||
## 结构定义
|
||||
|
||||
### 统一状态接口 (Unified Loop State)
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* Unified Loop State - API 和 Skill 共享的状态结构
|
||||
* API (loop-v2-routes.ts) 拥有状态的主控权
|
||||
* Skill (ccw-loop) 读取和更新此状态
|
||||
*/
|
||||
interface LoopState {
|
||||
// =====================================================
|
||||
// API FIELDS (from loop-v2-routes.ts)
|
||||
// 这些字段由 API 管理,Skill 只读
|
||||
// =====================================================
|
||||
|
||||
loop_id: string // Loop ID, e.g., "loop-v2-20260122-abc123"
|
||||
title: string // Loop 标题
|
||||
description: string // Loop 描述
|
||||
max_iterations: number // 最大迭代次数
|
||||
status: 'created' | 'running' | 'paused' | 'completed' | 'failed'
|
||||
current_iteration: number // 当前迭代次数
|
||||
created_at: string // 创建时间 (ISO8601)
|
||||
updated_at: string // 最后更新时间 (ISO8601)
|
||||
completed_at?: string // 完成时间 (ISO8601)
|
||||
failure_reason?: string // 失败原因
|
||||
|
||||
// =====================================================
|
||||
// SKILL EXTENSION FIELDS
|
||||
// 这些字段由 Skill 管理,API 只读
|
||||
// =====================================================
|
||||
|
||||
skill_state?: {
|
||||
// 当前执行动作
|
||||
current_action: 'init' | 'develop' | 'debug' | 'validate' | 'complete' | null
|
||||
last_action: string | null
|
||||
completed_actions: string[]
|
||||
mode: 'interactive' | 'auto'
|
||||
|
||||
// === 开发阶段 ===
|
||||
develop: {
|
||||
total: number
|
||||
completed: number
|
||||
current_task?: string
|
||||
tasks: DevelopTask[]
|
||||
last_progress_at: string | null
|
||||
}
|
||||
|
||||
// === 调试阶段 ===
|
||||
debug: {
|
||||
active_bug?: string
|
||||
hypotheses_count: number
|
||||
hypotheses: Hypothesis[]
|
||||
confirmed_hypothesis: string | null
|
||||
iteration: number
|
||||
last_analysis_at: string | null
|
||||
}
|
||||
|
||||
// === 验证阶段 ===
|
||||
validate: {
|
||||
pass_rate: number // 测试通过率 (0-100)
|
||||
coverage: number // 覆盖率 (0-100)
|
||||
test_results: TestResult[]
|
||||
passed: boolean
|
||||
failed_tests: string[]
|
||||
last_run_at: string | null
|
||||
}
|
||||
|
||||
// === 错误追踪 ===
|
||||
errors: Array<{
|
||||
action: string
|
||||
message: string
|
||||
timestamp: string
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
interface DevelopTask {
|
||||
id: string
|
||||
description: string
|
||||
tool: 'gemini' | 'qwen' | 'codex' | 'bash'
|
||||
mode: 'analysis' | 'write'
|
||||
status: 'pending' | 'in_progress' | 'completed' | 'failed'
|
||||
files_changed: string[]
|
||||
created_at: string
|
||||
completed_at: string | null
|
||||
}
|
||||
|
||||
interface Hypothesis {
|
||||
id: string // H1, H2, ...
|
||||
description: string
|
||||
testable_condition: string
|
||||
logging_point: string
|
||||
evidence_criteria: {
|
||||
confirm: string
|
||||
reject: string
|
||||
}
|
||||
likelihood: number // 1 = 最可能
|
||||
status: 'pending' | 'confirmed' | 'rejected' | 'inconclusive'
|
||||
evidence: Record<string, any> | null
|
||||
verdict_reason: string | null
|
||||
}
|
||||
|
||||
interface TestResult {
|
||||
test_name: string
|
||||
suite: string
|
||||
status: 'passed' | 'failed' | 'skipped'
|
||||
duration_ms: number
|
||||
error_message: string | null
|
||||
stack_trace: string | null
|
||||
}
|
||||
```
|
||||
|
||||
## 初始状态
|
||||
|
||||
### 由 API 创建时 (Dashboard 触发)
|
||||
|
||||
```json
|
||||
{
|
||||
"loop_id": "loop-v2-20260122-abc123",
|
||||
"title": "Implement user authentication",
|
||||
"description": "Add login/logout functionality",
|
||||
"max_iterations": 10,
|
||||
"status": "created",
|
||||
"current_iteration": 0,
|
||||
"created_at": "2026-01-22T10:00:00+08:00",
|
||||
"updated_at": "2026-01-22T10:00:00+08:00"
|
||||
}
|
||||
```
|
||||
|
||||
### 由 Skill 初始化后 (action-init)
|
||||
|
||||
```json
|
||||
{
|
||||
"loop_id": "loop-v2-20260122-abc123",
|
||||
"title": "Implement user authentication",
|
||||
"description": "Add login/logout functionality",
|
||||
"max_iterations": 10,
|
||||
"status": "running",
|
||||
"current_iteration": 0,
|
||||
"created_at": "2026-01-22T10:00:00+08:00",
|
||||
"updated_at": "2026-01-22T10:00:05+08:00",
|
||||
|
||||
"skill_state": {
|
||||
"current_action": "init",
|
||||
"last_action": null,
|
||||
"completed_actions": [],
|
||||
"mode": "auto",
|
||||
|
||||
"develop": {
|
||||
"total": 3,
|
||||
"completed": 0,
|
||||
"current_task": null,
|
||||
"tasks": [
|
||||
{ "id": "task-001", "description": "Create auth component", "status": "pending" }
|
||||
],
|
||||
"last_progress_at": null
|
||||
},
|
||||
|
||||
"debug": {
|
||||
"active_bug": null,
|
||||
"hypotheses_count": 0,
|
||||
"hypotheses": [],
|
||||
"confirmed_hypothesis": null,
|
||||
"iteration": 0,
|
||||
"last_analysis_at": null
|
||||
},
|
||||
|
||||
"validate": {
|
||||
"pass_rate": 0,
|
||||
"coverage": 0,
|
||||
"test_results": [],
|
||||
"passed": false,
|
||||
"failed_tests": [],
|
||||
"last_run_at": null
|
||||
},
|
||||
|
||||
"errors": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 控制信号检查 (Control Signals)
|
||||
|
||||
Skill 在每个 Action 开始前必须检查控制信号:
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* 检查 API 控制信号
|
||||
* @returns { continue: boolean, action: 'pause_exit' | 'stop_exit' | 'continue' }
|
||||
*/
|
||||
function checkControlSignals(loopId) {
|
||||
const state = JSON.parse(Read(`.loop/${loopId}.json`))
|
||||
|
||||
switch (state.status) {
|
||||
case 'paused':
|
||||
// API 暂停了循环,Skill 应退出等待 resume
|
||||
return { continue: false, action: 'pause_exit' }
|
||||
|
||||
case 'failed':
|
||||
// API 停止了循环 (用户手动停止)
|
||||
return { continue: false, action: 'stop_exit' }
|
||||
|
||||
case 'running':
|
||||
// 正常继续
|
||||
return { continue: true, action: 'continue' }
|
||||
|
||||
default:
|
||||
// 异常状态
|
||||
return { continue: false, action: 'stop_exit' }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 在 Action 中使用
|
||||
|
||||
```markdown
|
||||
## Execution
|
||||
|
||||
### Step 1: Check Control Signals
|
||||
|
||||
\`\`\`javascript
|
||||
const control = checkControlSignals(loopId)
|
||||
if (!control.continue) {
|
||||
// 输出退出原因
|
||||
console.log(`Loop ${control.action}: status = ${state.status}`)
|
||||
|
||||
// 如果是 pause_exit,保存当前进度
|
||||
if (control.action === 'pause_exit') {
|
||||
updateSkillState(loopId, { current_action: 'paused' })
|
||||
}
|
||||
|
||||
return // 退出 Action
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Step 2: Execute Action Logic
|
||||
...
|
||||
```
|
||||
|
||||
## 状态转换规则
|
||||
|
||||
### 1. 初始化 (action-init)
|
||||
|
||||
```javascript
|
||||
// Skill 初始化后
|
||||
{
|
||||
// API 字段更新
|
||||
status: 'created' → 'running', // 或保持 'running' 如果 API 已设置
|
||||
updated_at: timestamp,
|
||||
|
||||
// Skill 字段初始化
|
||||
skill_state: {
|
||||
current_action: 'init',
|
||||
mode: 'auto',
|
||||
develop: {
|
||||
tasks: [...parsed_tasks],
|
||||
total: N,
|
||||
completed: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 开发进行中 (action-develop-with-file)
|
||||
|
||||
```javascript
|
||||
// 开发任务执行后
|
||||
{
|
||||
updated_at: timestamp,
|
||||
current_iteration: state.current_iteration + 1,
|
||||
|
||||
skill_state: {
|
||||
current_action: 'develop',
|
||||
last_action: 'action-develop-with-file',
|
||||
completed_actions: [...state.skill_state.completed_actions, 'action-develop-with-file'],
|
||||
develop: {
|
||||
current_task: 'task-xxx',
|
||||
completed: N+1,
|
||||
last_progress_at: timestamp
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 调试进行中 (action-debug-with-file)
|
||||
|
||||
```javascript
|
||||
// 调试执行后
|
||||
{
|
||||
updated_at: timestamp,
|
||||
current_iteration: state.current_iteration + 1,
|
||||
|
||||
skill_state: {
|
||||
current_action: 'debug',
|
||||
last_action: 'action-debug-with-file',
|
||||
debug: {
|
||||
active_bug: '...',
|
||||
hypotheses_count: N,
|
||||
hypotheses: [...new_hypotheses],
|
||||
iteration: N+1,
|
||||
last_analysis_at: timestamp
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 验证完成 (action-validate-with-file)
|
||||
|
||||
```javascript
|
||||
// 验证执行后
|
||||
{
|
||||
updated_at: timestamp,
|
||||
current_iteration: state.current_iteration + 1,
|
||||
|
||||
skill_state: {
|
||||
current_action: 'validate',
|
||||
last_action: 'action-validate-with-file',
|
||||
validate: {
|
||||
test_results: [...results],
|
||||
pass_rate: 95.5,
|
||||
coverage: 85.0,
|
||||
passed: true | false,
|
||||
failed_tests: ['test1', 'test2'],
|
||||
last_run_at: timestamp
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 完成 (action-complete)
|
||||
|
||||
```javascript
|
||||
// 循环完成后
|
||||
{
|
||||
status: 'running' → 'completed',
|
||||
completed_at: timestamp,
|
||||
updated_at: timestamp,
|
||||
|
||||
skill_state: {
|
||||
current_action: 'complete',
|
||||
last_action: 'action-complete'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 状态派生字段
|
||||
|
||||
以下字段可从状态计算得出,不需要存储:
|
||||
|
||||
```javascript
|
||||
// 开发完成度
|
||||
const developProgress = state.develop.total_count > 0
|
||||
? (state.develop.completed_count / state.develop.total_count) * 100
|
||||
: 0
|
||||
|
||||
// 是否有待开发任务
|
||||
const hasPendingDevelop = state.develop.tasks.some(t => t.status === 'pending')
|
||||
|
||||
// 调试是否完成
|
||||
const debugCompleted = state.debug.confirmed_hypothesis !== null
|
||||
|
||||
// 验证是否通过
|
||||
const validationPassed = state.validate.passed && state.validate.test_results.length > 0
|
||||
|
||||
// 整体进度
|
||||
const overallProgress = (
|
||||
(developProgress * 0.5) +
|
||||
(debugCompleted ? 25 : 0) +
|
||||
(validationPassed ? 25 : 0)
|
||||
)
|
||||
```
|
||||
|
||||
## 文件同步
|
||||
|
||||
### 统一位置 (Unified Location)
|
||||
|
||||
状态与文件的对应关系:
|
||||
|
||||
| 状态字段 | 同步文件 | 同步时机 |
|
||||
|----------|----------|----------|
|
||||
| 整个 LoopState | `.loop/{loopId}.json` | 每次状态变更 (主文件) |
|
||||
| `skill_state.develop` | `.loop/{loopId}.progress/develop.md` | 每次开发操作后 |
|
||||
| `skill_state.debug` | `.loop/{loopId}.progress/debug.md` | 每次调试操作后 |
|
||||
| `skill_state.validate` | `.loop/{loopId}.progress/validate.md` | 每次验证操作后 |
|
||||
| 代码变更日志 | `.loop/{loopId}.progress/changes.log` | 每次文件修改 (NDJSON) |
|
||||
| 调试日志 | `.loop/{loopId}.progress/debug.log` | 每次调试日志 (NDJSON) |
|
||||
|
||||
### 文件结构示例
|
||||
|
||||
```
|
||||
.loop/
|
||||
├── loop-v2-20260122-abc123.json # 主状态文件 (API + Skill)
|
||||
├── loop-v2-20260122-abc123.tasks.jsonl # 任务列表 (API 管理)
|
||||
└── loop-v2-20260122-abc123.progress/ # Skill 进度文件
|
||||
├── develop.md # 开发进度
|
||||
├── debug.md # 调试理解
|
||||
├── validate.md # 验证报告
|
||||
├── changes.log # 代码变更 (NDJSON)
|
||||
└── debug.log # 调试日志 (NDJSON)
|
||||
```
|
||||
|
||||
## 状态恢复
|
||||
|
||||
如果主状态文件 `.loop/{loopId}.json` 损坏,可以从进度文件重建 skill_state:
|
||||
|
||||
```javascript
|
||||
function rebuildSkillStateFromProgress(loopId) {
|
||||
const progressDir = `.loop/${loopId}.progress`
|
||||
|
||||
// 尝试从进度文件解析状态
|
||||
const skill_state = {
|
||||
develop: parseProgressFile(`${progressDir}/develop.md`),
|
||||
debug: parseProgressFile(`${progressDir}/debug.md`),
|
||||
validate: parseProgressFile(`${progressDir}/validate.md`)
|
||||
}
|
||||
|
||||
return skill_state
|
||||
}
|
||||
|
||||
// 解析进度 Markdown 文件
|
||||
function parseProgressFile(filePath) {
|
||||
const content = Read(filePath)
|
||||
if (!content) return null
|
||||
|
||||
// 从 Markdown 表格和结构中提取数据
|
||||
// ... implementation
|
||||
}
|
||||
```
|
||||
|
||||
### 恢复策略
|
||||
|
||||
1. **API 字段**: 无法恢复 - 需要从 API 重新获取或用户手动输入
|
||||
2. **skill_state 字段**: 可以从 `.progress/` 目录的 Markdown 文件解析
|
||||
3. **任务列表**: 从 `.loop/{loopId}.tasks.jsonl` 恢复
|
||||
|
||||
## 状态验证
|
||||
|
||||
```javascript
|
||||
function validateState(state) {
|
||||
const errors = []
|
||||
|
||||
// 必需字段
|
||||
if (!state.session_id) errors.push('Missing session_id')
|
||||
if (!state.task_description) errors.push('Missing task_description')
|
||||
|
||||
// 状态一致性
|
||||
if (state.initialized && state.status === 'pending') {
|
||||
errors.push('Inconsistent: initialized but status is pending')
|
||||
}
|
||||
|
||||
if (state.status === 'completed' && !state.validate.passed) {
|
||||
errors.push('Inconsistent: completed but validation not passed')
|
||||
}
|
||||
|
||||
// 开发任务一致性
|
||||
const completedTasks = state.develop.tasks.filter(t => t.status === 'completed').length
|
||||
if (completedTasks !== state.develop.completed_count) {
|
||||
errors.push('Inconsistent: completed_count mismatch')
|
||||
}
|
||||
|
||||
return { valid: errors.length === 0, errors }
|
||||
}
|
||||
```
|
||||
300
.claude/skills/ccw-loop/specs/action-catalog.md
Normal file
300
.claude/skills/ccw-loop/specs/action-catalog.md
Normal file
@@ -0,0 +1,300 @@
|
||||
# Action Catalog
|
||||
|
||||
CCW Loop 所有可用动作的目录和说明。
|
||||
|
||||
## Available Actions
|
||||
|
||||
| Action | Purpose | Preconditions | Effects | CLI Integration |
|
||||
|--------|---------|---------------|---------|-----------------|
|
||||
| [action-init](../phases/actions/action-init.md) | 初始化会话 | status=pending, initialized=false | status→running, initialized→true, 创建目录和任务列表 | Gemini 任务分解 |
|
||||
| [action-menu](../phases/actions/action-menu.md) | 显示操作菜单 | initialized=true, status=running | 返回用户选择的动作 | - |
|
||||
| [action-develop-with-file](../phases/actions/action-develop-with-file.md) | 执行开发任务 | initialized=true, pending tasks > 0 | 更新 progress.md, 完成一个任务 | Gemini 代码实现 |
|
||||
| [action-debug-with-file](../phases/actions/action-debug-with-file.md) | 假设驱动调试 | initialized=true | 更新 understanding.md, hypotheses.json | Gemini 假设生成和证据分析 |
|
||||
| [action-validate-with-file](../phases/actions/action-validate-with-file.md) | 运行测试验证 | initialized=true, develop > 0 or debug confirmed | 更新 validation.md, test-results.json | Gemini 质量分析 |
|
||||
| [action-complete](../phases/actions/action-complete.md) | 完成循环 | initialized=true | status→completed, 生成 summary.md | - |
|
||||
|
||||
## Action Dependencies Graph
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
START([用户启动 /ccw-loop]) --> INIT[action-init]
|
||||
INIT --> MENU[action-menu]
|
||||
|
||||
MENU --> DEVELOP[action-develop-with-file]
|
||||
MENU --> DEBUG[action-debug-with-file]
|
||||
MENU --> VALIDATE[action-validate-with-file]
|
||||
MENU --> STATUS[action-status]
|
||||
MENU --> COMPLETE[action-complete]
|
||||
MENU --> EXIT([退出])
|
||||
|
||||
DEVELOP --> MENU
|
||||
DEBUG --> MENU
|
||||
VALIDATE --> MENU
|
||||
STATUS --> MENU
|
||||
COMPLETE --> END([结束])
|
||||
EXIT --> END
|
||||
|
||||
style INIT fill:#e1f5fe
|
||||
style MENU fill:#fff3e0
|
||||
style DEVELOP fill:#e8f5e9
|
||||
style DEBUG fill:#fce4ec
|
||||
style VALIDATE fill:#f3e5f5
|
||||
style COMPLETE fill:#c8e6c9
|
||||
```
|
||||
|
||||
## Action Execution Matrix
|
||||
|
||||
### Interactive Mode
|
||||
|
||||
| State | Auto-Selected Action | User Options |
|
||||
|-------|---------------------|--------------|
|
||||
| pending | action-init | - |
|
||||
| running, !initialized | action-init | - |
|
||||
| running, initialized | action-menu | All actions |
|
||||
|
||||
### Auto Mode
|
||||
|
||||
| Condition | Selected Action |
|
||||
|-----------|----------------|
|
||||
| pending_develop_tasks > 0 | action-develop-with-file |
|
||||
| last_action=develop, !debug_completed | action-debug-with-file |
|
||||
| last_action=debug, !validation_completed | action-validate-with-file |
|
||||
| validation_failed | action-develop-with-file (fix) |
|
||||
| validation_passed, no pending | action-complete |
|
||||
|
||||
## Action Inputs/Outputs
|
||||
|
||||
### action-init
|
||||
|
||||
**Inputs**:
|
||||
- state.task_description
|
||||
- User input (optional)
|
||||
|
||||
**Outputs**:
|
||||
- meta.json
|
||||
- state.json (初始化)
|
||||
- develop/tasks.json
|
||||
- develop/progress.md
|
||||
|
||||
**State Changes**:
|
||||
```javascript
|
||||
{
|
||||
status: 'pending' → 'running',
|
||||
initialized: false → true,
|
||||
develop.tasks: [] → [task1, task2, ...]
|
||||
}
|
||||
```
|
||||
|
||||
### action-develop-with-file
|
||||
|
||||
**Inputs**:
|
||||
- state.develop.tasks
|
||||
- User selection (如有多个待处理任务)
|
||||
|
||||
**Outputs**:
|
||||
- develop/progress.md (追加)
|
||||
- develop/tasks.json (更新)
|
||||
- develop/changes.log (追加)
|
||||
|
||||
**State Changes**:
|
||||
```javascript
|
||||
{
|
||||
develop.current_task_id: null → 'task-xxx' → null,
|
||||
develop.completed_count: N → N+1,
|
||||
last_action: X → 'action-develop-with-file'
|
||||
}
|
||||
```
|
||||
|
||||
### action-debug-with-file
|
||||
|
||||
**Inputs**:
|
||||
- Bug description (用户输入或从测试失败获取)
|
||||
- debug.log (如已有)
|
||||
|
||||
**Outputs**:
|
||||
- debug/understanding.md (追加)
|
||||
- debug/hypotheses.json (更新)
|
||||
- Code changes (添加日志或修复)
|
||||
|
||||
**State Changes**:
|
||||
```javascript
|
||||
{
|
||||
debug.current_bug: null → 'bug description',
|
||||
debug.hypotheses: [...updated],
|
||||
debug.iteration: N → N+1,
|
||||
debug.confirmed_hypothesis: null → 'H1' (如确认)
|
||||
}
|
||||
```
|
||||
|
||||
### action-validate-with-file
|
||||
|
||||
**Inputs**:
|
||||
- 测试脚本 (从 package.json)
|
||||
- 覆盖率工具 (可选)
|
||||
|
||||
**Outputs**:
|
||||
- validate/validation.md (追加)
|
||||
- validate/test-results.json (更新)
|
||||
- validate/coverage.json (更新)
|
||||
|
||||
**State Changes**:
|
||||
```javascript
|
||||
{
|
||||
validate.test_results: [...new results],
|
||||
validate.coverage: null → 85.5,
|
||||
validate.passed: false → true,
|
||||
validate.failed_tests: ['test1', 'test2'] → []
|
||||
}
|
||||
```
|
||||
|
||||
### action-complete
|
||||
|
||||
**Inputs**:
|
||||
- state (完整状态)
|
||||
- User choices (扩展选项)
|
||||
|
||||
**Outputs**:
|
||||
- summary.md
|
||||
- Issues (如选择扩展)
|
||||
|
||||
**State Changes**:
|
||||
```javascript
|
||||
{
|
||||
status: 'running' → 'completed',
|
||||
completed_at: null → timestamp
|
||||
}
|
||||
```
|
||||
|
||||
## Action Sequences
|
||||
|
||||
### Typical Happy Path
|
||||
|
||||
```
|
||||
action-init
|
||||
→ action-develop-with-file (task 1)
|
||||
→ action-develop-with-file (task 2)
|
||||
→ action-develop-with-file (task 3)
|
||||
→ action-validate-with-file
|
||||
→ PASS
|
||||
→ action-complete
|
||||
```
|
||||
|
||||
### Debug Iteration Path
|
||||
|
||||
```
|
||||
action-init
|
||||
→ action-develop-with-file (task 1)
|
||||
→ action-validate-with-file
|
||||
→ FAIL
|
||||
→ action-debug-with-file (探索)
|
||||
→ action-debug-with-file (分析)
|
||||
→ Root cause found
|
||||
→ action-validate-with-file
|
||||
→ PASS
|
||||
→ action-complete
|
||||
```
|
||||
|
||||
### Multi-Iteration Path
|
||||
|
||||
```
|
||||
action-init
|
||||
→ action-develop-with-file (task 1)
|
||||
→ action-debug-with-file
|
||||
→ action-develop-with-file (task 2)
|
||||
→ action-validate-with-file
|
||||
→ FAIL
|
||||
→ action-debug-with-file
|
||||
→ action-validate-with-file
|
||||
→ PASS
|
||||
→ action-complete
|
||||
```
|
||||
|
||||
## Error Scenarios
|
||||
|
||||
### CLI Tool Failure
|
||||
|
||||
```
|
||||
action-develop-with-file
|
||||
→ Gemini CLI fails
|
||||
→ Fallback to manual implementation
|
||||
→ Prompt user for code
|
||||
→ Continue
|
||||
```
|
||||
|
||||
### Test Failure
|
||||
|
||||
```
|
||||
action-validate-with-file
|
||||
→ Tests fail
|
||||
→ Record failed tests
|
||||
→ Suggest action-debug-with-file
|
||||
→ User chooses debug or manual fix
|
||||
```
|
||||
|
||||
### Max Iterations Reached
|
||||
|
||||
```
|
||||
state.iteration_count >= 10
|
||||
→ Warning message
|
||||
→ Suggest break or task split
|
||||
→ Allow continue or exit
|
||||
```
|
||||
|
||||
## Action Extensions
|
||||
|
||||
### Adding New Actions
|
||||
|
||||
To add a new action:
|
||||
|
||||
1. Create `phases/actions/action-{name}.md`
|
||||
2. Define preconditions, execution, state updates
|
||||
3. Add to this catalog
|
||||
4. Update orchestrator.md decision logic
|
||||
5. Add to action-menu.md options
|
||||
|
||||
### Action Template
|
||||
|
||||
```markdown
|
||||
# Action: {Name}
|
||||
|
||||
{Brief description}
|
||||
|
||||
## Purpose
|
||||
|
||||
{Detailed purpose}
|
||||
|
||||
## Preconditions
|
||||
|
||||
- [ ] condition1
|
||||
- [ ] condition2
|
||||
|
||||
## Execution
|
||||
|
||||
### Step 1: {Step Name}
|
||||
|
||||
\`\`\`javascript
|
||||
// code
|
||||
\`\`\`
|
||||
|
||||
## State Updates
|
||||
|
||||
\`\`\`javascript
|
||||
return {
|
||||
stateUpdates: {
|
||||
// updates
|
||||
},
|
||||
continue: true,
|
||||
message: "..."
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error Type | Recovery |
|
||||
|------------|----------|
|
||||
| ... | ... |
|
||||
|
||||
## Next Actions (Hints)
|
||||
|
||||
- condition: next_action
|
||||
```
|
||||
192
.claude/skills/ccw-loop/specs/loop-requirements.md
Normal file
192
.claude/skills/ccw-loop/specs/loop-requirements.md
Normal file
@@ -0,0 +1,192 @@
|
||||
# Loop Requirements Specification
|
||||
|
||||
CCW Loop 的核心需求和约束定义。
|
||||
|
||||
## Core Requirements
|
||||
|
||||
### 1. 无状态循环
|
||||
|
||||
**Requirement**: 每次执行从文件读取状态,执行后写回文件,不依赖内存状态。
|
||||
|
||||
**Rationale**: 支持随时中断和恢复,状态持久化。
|
||||
|
||||
**Validation**:
|
||||
- [ ] 每个 action 开始时从文件读取状态
|
||||
- [ ] 每个 action 结束时将状态写回文件
|
||||
- [ ] 无全局变量或内存状态依赖
|
||||
|
||||
### 2. 文件驱动进度
|
||||
|
||||
**Requirement**: 所有进度、理解、验证结果都记录在专用 Markdown 文件中。
|
||||
|
||||
**Rationale**: 可审计、可回顾、团队可见。
|
||||
|
||||
**Validation**:
|
||||
- [ ] develop/progress.md 记录开发进度
|
||||
- [ ] debug/understanding.md 记录理解演变
|
||||
- [ ] validate/validation.md 记录验证结果
|
||||
- [ ] 所有文件使用 Markdown 格式,易读
|
||||
|
||||
### 3. CLI 工具集成
|
||||
|
||||
**Requirement**: 关键决策点使用 Gemini/CLI 进行深度分析。
|
||||
|
||||
**Rationale**: 利用 LLM 能力提高质量。
|
||||
|
||||
**Validation**:
|
||||
- [ ] 任务分解使用 Gemini
|
||||
- [ ] 假设生成使用 Gemini
|
||||
- [ ] 证据分析使用 Gemini
|
||||
- [ ] 质量评估使用 Gemini
|
||||
|
||||
### 4. 用户控制循环
|
||||
|
||||
**Requirement**: 支持交互式和自动循环两种模式,用户可随时介入。
|
||||
|
||||
**Rationale**: 灵活性,适应不同场景。
|
||||
|
||||
**Validation**:
|
||||
- [ ] 交互模式:每步显示菜单
|
||||
- [ ] 自动模式:按预设流程执行
|
||||
- [ ] 用户可随时退出
|
||||
- [ ] 状态可恢复
|
||||
|
||||
### 5. 可恢复性
|
||||
|
||||
**Requirement**: 任何时候中断后,可以从上次位置继续。
|
||||
|
||||
**Rationale**: 长时间任务支持,意外中断恢复。
|
||||
|
||||
**Validation**:
|
||||
- [ ] 状态保存在 state.json
|
||||
- [ ] 使用 --resume 可继续
|
||||
- [ ] 历史记录完整保留
|
||||
|
||||
## Quality Standards
|
||||
|
||||
### Completeness
|
||||
|
||||
| Dimension | Threshold |
|
||||
|-----------|-----------|
|
||||
| 进度文档完整性 | 每个任务都有记录 |
|
||||
| 理解文档演变 | 每次迭代都有更新 |
|
||||
| 验证报告详尽 | 包含所有测试结果 |
|
||||
|
||||
### Consistency
|
||||
|
||||
| Dimension | Threshold |
|
||||
|-----------|-----------|
|
||||
| 文件格式一致 | 所有 Markdown 文件使用相同模板 |
|
||||
| 状态同步一致 | state.json 与文件内容匹配 |
|
||||
| 时间戳格式 | 统一使用 ISO8601 格式 |
|
||||
|
||||
### Usability
|
||||
|
||||
| Dimension | Threshold |
|
||||
|-----------|-----------|
|
||||
| 菜单易用性 | 选项清晰,描述准确 |
|
||||
| 进度可见性 | 随时可查看当前状态 |
|
||||
| 错误提示 | 错误消息清晰,提供恢复建议 |
|
||||
|
||||
## Constraints
|
||||
|
||||
### 1. 文件结构约束
|
||||
|
||||
```
|
||||
.workflow/.loop/{session-id}/
|
||||
├── meta.json # 只写一次,不再修改
|
||||
├── state.json # 每次 action 后更新
|
||||
├── develop/
|
||||
│ ├── progress.md # 只追加,不删除
|
||||
│ ├── tasks.json # 任务状态更新
|
||||
│ └── changes.log # NDJSON 格式,只追加
|
||||
├── debug/
|
||||
│ ├── understanding.md # 只追加,记录时间线
|
||||
│ ├── hypotheses.json # 更新假设状态
|
||||
│ └── debug.log # NDJSON 格式
|
||||
└── validate/
|
||||
├── validation.md # 每次验证追加
|
||||
├── test-results.json # 累积测试结果
|
||||
└── coverage.json # 最新覆盖率
|
||||
```
|
||||
|
||||
### 2. 命名约束
|
||||
|
||||
- Session ID: `LOOP-{slug}-{YYYY-MM-DD}`
|
||||
- Task ID: `task-{NNN}` (三位数字)
|
||||
- Hypothesis ID: `H{N}` (单字母+数字)
|
||||
|
||||
### 3. 状态转换约束
|
||||
|
||||
```
|
||||
pending → running → completed
|
||||
↓
|
||||
user_exit
|
||||
↓
|
||||
failed
|
||||
```
|
||||
|
||||
Only allow: `pending→running`, `running→completed/user_exit/failed`
|
||||
|
||||
### 4. 错误限制约束
|
||||
|
||||
- 最大错误次数: 3
|
||||
- 超过 3 次错误 → 自动终止
|
||||
- 每次错误 → 记录到 state.errors[]
|
||||
|
||||
### 5. 迭代限制约束
|
||||
|
||||
- 最大迭代次数: 10 (警告)
|
||||
- 超过 10 次 → 警告用户,但不强制停止
|
||||
- 建议拆分任务或休息
|
||||
|
||||
## Integration Requirements
|
||||
|
||||
### 1. Dashboard 集成
|
||||
|
||||
**Requirement**: 与 CCW Dashboard Loop Monitor 无缝集成。
|
||||
|
||||
**Specification**:
|
||||
- Dashboard 创建 Loop → 调用此 Skill
|
||||
- state.json → Dashboard 实时显示
|
||||
- 任务列表双向同步
|
||||
- 状态控制按钮映射到 actions
|
||||
|
||||
### 2. Issue 系统集成
|
||||
|
||||
**Requirement**: 完成后可扩展为 Issue。
|
||||
|
||||
**Specification**:
|
||||
- 支持维度: test, enhance, refactor, doc
|
||||
- 调用 `/issue:new "{summary} - {dimension}"`
|
||||
- 自动填充上下文
|
||||
|
||||
### 3. CLI 工具集成
|
||||
|
||||
**Requirement**: 使用 CCW CLI 工具进行分析和实现。
|
||||
|
||||
**Specification**:
|
||||
- 任务分解: `--rule planning-breakdown-task-steps`
|
||||
- 代码实现: `--rule development-implement-feature`
|
||||
- 根因分析: `--rule analysis-diagnose-bug-root-cause`
|
||||
- 质量评估: `--rule analysis-review-code-quality`
|
||||
|
||||
## Non-Functional Requirements
|
||||
|
||||
### Performance
|
||||
|
||||
- Session 初始化: < 5s
|
||||
- Action 执行: < 30s (不含 CLI 调用)
|
||||
- 状态读写: < 1s
|
||||
|
||||
### Reliability
|
||||
|
||||
- 状态文件损坏恢复: 支持从其他文件重建
|
||||
- CLI 工具失败降级: 回退到手动模式
|
||||
- 错误重试: 支持一次自动重试
|
||||
|
||||
### Maintainability
|
||||
|
||||
- 文档化: 所有 action 都有清晰说明
|
||||
- 模块化: 每个 action 独立可测
|
||||
- 可扩展: 易于添加新 action
|
||||
175
.claude/skills/ccw-loop/templates/progress-template.md
Normal file
175
.claude/skills/ccw-loop/templates/progress-template.md
Normal file
@@ -0,0 +1,175 @@
|
||||
# Progress Document Template
|
||||
|
||||
开发进度文档的标准模板。
|
||||
|
||||
## Template Structure
|
||||
|
||||
```markdown
|
||||
# Development Progress
|
||||
|
||||
**Session ID**: {{session_id}}
|
||||
**Task**: {{task_description}}
|
||||
**Started**: {{started_at}}
|
||||
**Estimated Complexity**: {{complexity}}
|
||||
|
||||
---
|
||||
|
||||
## Task List
|
||||
|
||||
{{#each tasks}}
|
||||
{{@index}}. [{{#if completed}}x{{else}} {{/if}}] {{description}}
|
||||
{{/each}}
|
||||
|
||||
## Key Files
|
||||
|
||||
{{#each key_files}}
|
||||
- `{{this}}`
|
||||
{{/each}}
|
||||
|
||||
---
|
||||
|
||||
## Progress Timeline
|
||||
|
||||
{{#each iterations}}
|
||||
### Iteration {{@index}} - {{task_name}} ({{timestamp}})
|
||||
|
||||
#### Task Details
|
||||
|
||||
- **ID**: {{task_id}}
|
||||
- **Tool**: {{tool}}
|
||||
- **Mode**: {{mode}}
|
||||
|
||||
#### Implementation Summary
|
||||
|
||||
{{summary}}
|
||||
|
||||
#### Files Changed
|
||||
|
||||
{{#each files_changed}}
|
||||
- `{{this}}`
|
||||
{{/each}}
|
||||
|
||||
#### Status: {{status}}
|
||||
|
||||
---
|
||||
{{/each}}
|
||||
|
||||
## Current Statistics
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Total Tasks | {{total_tasks}} |
|
||||
| Completed | {{completed_tasks}} |
|
||||
| In Progress | {{in_progress_tasks}} |
|
||||
| Pending | {{pending_tasks}} |
|
||||
| Progress | {{progress_percentage}}% |
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
{{#each next_steps}}
|
||||
- [ ] {{this}}
|
||||
{{/each}}
|
||||
```
|
||||
|
||||
## Template Variables
|
||||
|
||||
| Variable | Type | Source | Description |
|
||||
|----------|------|--------|-------------|
|
||||
| `session_id` | string | state.session_id | 会话 ID |
|
||||
| `task_description` | string | state.task_description | 任务描述 |
|
||||
| `started_at` | string | state.created_at | 开始时间 |
|
||||
| `complexity` | string | state.context.estimated_complexity | 预估复杂度 |
|
||||
| `tasks` | array | state.develop.tasks | 任务列表 |
|
||||
| `key_files` | array | state.context.key_files | 关键文件 |
|
||||
| `iterations` | array | 从文件解析 | 迭代历史 |
|
||||
| `total_tasks` | number | state.develop.total_count | 总任务数 |
|
||||
| `completed_tasks` | number | state.develop.completed_count | 已完成数 |
|
||||
|
||||
## Usage Example
|
||||
|
||||
```javascript
|
||||
const progressTemplate = Read('.claude/skills/ccw-loop/templates/progress-template.md')
|
||||
|
||||
function renderProgress(state) {
|
||||
let content = progressTemplate
|
||||
|
||||
// 替换简单变量
|
||||
content = content.replace('{{session_id}}', state.session_id)
|
||||
content = content.replace('{{task_description}}', state.task_description)
|
||||
content = content.replace('{{started_at}}', state.created_at)
|
||||
content = content.replace('{{complexity}}', state.context?.estimated_complexity || 'unknown')
|
||||
|
||||
// 替换任务列表
|
||||
const taskList = state.develop.tasks.map((t, i) => {
|
||||
const checkbox = t.status === 'completed' ? 'x' : ' '
|
||||
return `${i + 1}. [${checkbox}] ${t.description}`
|
||||
}).join('\n')
|
||||
content = content.replace('{{#each tasks}}...{{/each}}', taskList)
|
||||
|
||||
// 替换统计
|
||||
content = content.replace('{{total_tasks}}', state.develop.total_count)
|
||||
content = content.replace('{{completed_tasks}}', state.develop.completed_count)
|
||||
// ...
|
||||
|
||||
return content
|
||||
}
|
||||
```
|
||||
|
||||
## Section Templates
|
||||
|
||||
### Task Entry
|
||||
|
||||
```markdown
|
||||
### Iteration {{N}} - {{task_name}} ({{timestamp}})
|
||||
|
||||
#### Task Details
|
||||
|
||||
- **ID**: {{task_id}}
|
||||
- **Tool**: {{tool}}
|
||||
- **Mode**: {{mode}}
|
||||
|
||||
#### Implementation Summary
|
||||
|
||||
{{summary}}
|
||||
|
||||
#### Files Changed
|
||||
|
||||
{{#each files}}
|
||||
- `{{this}}`
|
||||
{{/each}}
|
||||
|
||||
#### Status: COMPLETED
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
### Statistics Table
|
||||
|
||||
```markdown
|
||||
## Current Statistics
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Total Tasks | {{total}} |
|
||||
| Completed | {{completed}} |
|
||||
| In Progress | {{in_progress}} |
|
||||
| Pending | {{pending}} |
|
||||
| Progress | {{percentage}}% |
|
||||
```
|
||||
|
||||
### Next Steps
|
||||
|
||||
```markdown
|
||||
## Next Steps
|
||||
|
||||
{{#if all_completed}}
|
||||
- [ ] Run validation tests
|
||||
- [ ] Code review
|
||||
- [ ] Update documentation
|
||||
{{else}}
|
||||
- [ ] Complete remaining {{pending}} tasks
|
||||
- [ ] Review completed work
|
||||
{{/if}}
|
||||
```
|
||||
303
.claude/skills/ccw-loop/templates/understanding-template.md
Normal file
303
.claude/skills/ccw-loop/templates/understanding-template.md
Normal file
@@ -0,0 +1,303 @@
|
||||
# Understanding Document Template
|
||||
|
||||
调试理解演变文档的标准模板。
|
||||
|
||||
## Template Structure
|
||||
|
||||
```markdown
|
||||
# Understanding Document
|
||||
|
||||
**Session ID**: {{session_id}}
|
||||
**Bug Description**: {{bug_description}}
|
||||
**Started**: {{started_at}}
|
||||
|
||||
---
|
||||
|
||||
## Exploration Timeline
|
||||
|
||||
{{#each iterations}}
|
||||
### Iteration {{number}} - {{title}} ({{timestamp}})
|
||||
|
||||
{{#if is_exploration}}
|
||||
#### Current Understanding
|
||||
|
||||
Based on bug description and initial code search:
|
||||
|
||||
- Error pattern: {{error_pattern}}
|
||||
- Affected areas: {{affected_areas}}
|
||||
- Initial hypothesis: {{initial_thoughts}}
|
||||
|
||||
#### Evidence from Code Search
|
||||
|
||||
{{#each search_results}}
|
||||
**Keyword: "{{keyword}}"**
|
||||
- Found in: {{files}}
|
||||
- Key findings: {{insights}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
|
||||
{{#if has_hypotheses}}
|
||||
#### Hypotheses Generated (Gemini-Assisted)
|
||||
|
||||
{{#each hypotheses}}
|
||||
**{{id}}** (Likelihood: {{likelihood}}): {{description}}
|
||||
- Logging at: {{logging_point}}
|
||||
- Testing: {{testable_condition}}
|
||||
- Evidence to confirm: {{confirm_criteria}}
|
||||
- Evidence to reject: {{reject_criteria}}
|
||||
{{/each}}
|
||||
|
||||
**Gemini Insights**: {{gemini_insights}}
|
||||
{{/if}}
|
||||
|
||||
{{#if is_analysis}}
|
||||
#### Log Analysis Results
|
||||
|
||||
{{#each results}}
|
||||
**{{id}}**: {{verdict}}
|
||||
- Evidence: {{evidence}}
|
||||
- Reasoning: {{reason}}
|
||||
{{/each}}
|
||||
|
||||
#### Corrected Understanding
|
||||
|
||||
Previous misunderstandings identified and corrected:
|
||||
|
||||
{{#each corrections}}
|
||||
- ~~{{wrong}}~~ → {{corrected}}
|
||||
- Why wrong: {{reason}}
|
||||
- Evidence: {{evidence}}
|
||||
{{/each}}
|
||||
|
||||
#### New Insights
|
||||
|
||||
{{#each insights}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
|
||||
#### Gemini Analysis
|
||||
|
||||
{{gemini_analysis}}
|
||||
{{/if}}
|
||||
|
||||
{{#if root_cause_found}}
|
||||
#### Root Cause Identified
|
||||
|
||||
**{{hypothesis_id}}**: {{description}}
|
||||
|
||||
Evidence supporting this conclusion:
|
||||
{{supporting_evidence}}
|
||||
{{else}}
|
||||
#### Next Steps
|
||||
|
||||
{{next_steps}}
|
||||
{{/if}}
|
||||
|
||||
---
|
||||
{{/each}}
|
||||
|
||||
## Current Consolidated Understanding
|
||||
|
||||
### What We Know
|
||||
|
||||
{{#each valid_understandings}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
|
||||
### What Was Disproven
|
||||
|
||||
{{#each disproven}}
|
||||
- ~~{{assumption}}~~ (Evidence: {{evidence}})
|
||||
{{/each}}
|
||||
|
||||
### Current Investigation Focus
|
||||
|
||||
{{current_focus}}
|
||||
|
||||
### Remaining Questions
|
||||
|
||||
{{#each questions}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
```
|
||||
|
||||
## Template Variables
|
||||
|
||||
| Variable | Type | Source | Description |
|
||||
|----------|------|--------|-------------|
|
||||
| `session_id` | string | state.session_id | 会话 ID |
|
||||
| `bug_description` | string | state.debug.current_bug | Bug 描述 |
|
||||
| `iterations` | array | 从文件解析 | 迭代历史 |
|
||||
| `hypotheses` | array | state.debug.hypotheses | 假设列表 |
|
||||
| `valid_understandings` | array | 从 Gemini 分析 | 有效理解 |
|
||||
| `disproven` | array | 从假设状态 | 被否定的假设 |
|
||||
|
||||
## Section Templates
|
||||
|
||||
### Exploration Section
|
||||
|
||||
```markdown
|
||||
### Iteration {{N}} - Initial Exploration ({{timestamp}})
|
||||
|
||||
#### Current Understanding
|
||||
|
||||
Based on bug description and initial code search:
|
||||
|
||||
- Error pattern: {{pattern}}
|
||||
- Affected areas: {{areas}}
|
||||
- Initial hypothesis: {{thoughts}}
|
||||
|
||||
#### Evidence from Code Search
|
||||
|
||||
{{#each search_results}}
|
||||
**Keyword: "{{keyword}}"**
|
||||
- Found in: {{files}}
|
||||
- Key findings: {{insights}}
|
||||
{{/each}}
|
||||
|
||||
#### Next Steps
|
||||
|
||||
- Generate testable hypotheses
|
||||
- Add instrumentation
|
||||
- Await reproduction
|
||||
```
|
||||
|
||||
### Hypothesis Section
|
||||
|
||||
```markdown
|
||||
#### Hypotheses Generated (Gemini-Assisted)
|
||||
|
||||
| ID | Description | Likelihood | Status |
|
||||
|----|-------------|------------|--------|
|
||||
{{#each hypotheses}}
|
||||
| {{id}} | {{description}} | {{likelihood}} | {{status}} |
|
||||
{{/each}}
|
||||
|
||||
**Details:**
|
||||
|
||||
{{#each hypotheses}}
|
||||
**{{id}}**: {{description}}
|
||||
- Logging at: `{{logging_point}}`
|
||||
- Testing: {{testable_condition}}
|
||||
- Confirm: {{evidence_criteria.confirm}}
|
||||
- Reject: {{evidence_criteria.reject}}
|
||||
{{/each}}
|
||||
```
|
||||
|
||||
### Analysis Section
|
||||
|
||||
```markdown
|
||||
### Iteration {{N}} - Evidence Analysis ({{timestamp}})
|
||||
|
||||
#### Log Analysis Results
|
||||
|
||||
{{#each results}}
|
||||
**{{id}}**: **{{verdict}}**
|
||||
- Evidence: \`{{evidence}}\`
|
||||
- Reasoning: {{reason}}
|
||||
{{/each}}
|
||||
|
||||
#### Corrected Understanding
|
||||
|
||||
| Previous Assumption | Corrected To | Reason |
|
||||
|---------------------|--------------|--------|
|
||||
{{#each corrections}}
|
||||
| ~~{{wrong}}~~ | {{corrected}} | {{reason}} |
|
||||
{{/each}}
|
||||
|
||||
#### Gemini Analysis
|
||||
|
||||
{{gemini_analysis}}
|
||||
```
|
||||
|
||||
### Consolidated Understanding Section
|
||||
|
||||
```markdown
|
||||
## Current Consolidated Understanding
|
||||
|
||||
### What We Know
|
||||
|
||||
{{#each valid}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
|
||||
### What Was Disproven
|
||||
|
||||
{{#each disproven}}
|
||||
- ~~{{this.assumption}}~~ (Evidence: {{this.evidence}})
|
||||
{{/each}}
|
||||
|
||||
### Current Investigation Focus
|
||||
|
||||
{{focus}}
|
||||
|
||||
### Remaining Questions
|
||||
|
||||
{{#each questions}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
```
|
||||
|
||||
### Resolution Section
|
||||
|
||||
```markdown
|
||||
### Resolution ({{timestamp}})
|
||||
|
||||
#### Fix Applied
|
||||
|
||||
- Modified files: {{files}}
|
||||
- Fix description: {{description}}
|
||||
- Root cause addressed: {{root_cause}}
|
||||
|
||||
#### Verification Results
|
||||
|
||||
{{verification}}
|
||||
|
||||
#### Lessons Learned
|
||||
|
||||
{{#each lessons}}
|
||||
{{@index}}. {{this}}
|
||||
{{/each}}
|
||||
|
||||
#### Key Insights for Future
|
||||
|
||||
{{#each insights}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
```
|
||||
|
||||
## Consolidation Rules
|
||||
|
||||
更新 "Current Consolidated Understanding" 时遵循以下规则:
|
||||
|
||||
1. **简化被否定项**: 移到 "What Was Disproven",只保留单行摘要
|
||||
2. **保留有效见解**: 将确认的发现提升到 "What We Know"
|
||||
3. **避免重复**: 不在合并部分重复时间线细节
|
||||
4. **关注当前状态**: 描述现在知道什么,而不是过程
|
||||
5. **保留关键纠正**: 保留重要的 wrong→right 转换供学习
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
**错误示例 (冗余)**:
|
||||
```markdown
|
||||
## Current Consolidated Understanding
|
||||
|
||||
In iteration 1 we thought X, but in iteration 2 we found Y, then in iteration 3...
|
||||
Also we checked A and found B, and then we checked C...
|
||||
```
|
||||
|
||||
**正确示例 (精简)**:
|
||||
```markdown
|
||||
## Current Consolidated Understanding
|
||||
|
||||
### What We Know
|
||||
- Error occurs during runtime update, not initialization
|
||||
- Config value is None (not missing key)
|
||||
|
||||
### What Was Disproven
|
||||
- ~~Initialization error~~ (Timing evidence)
|
||||
- ~~Missing key hypothesis~~ (Key exists)
|
||||
|
||||
### Current Investigation Focus
|
||||
Why is config value None during update?
|
||||
```
|
||||
258
.claude/skills/ccw-loop/templates/validation-template.md
Normal file
258
.claude/skills/ccw-loop/templates/validation-template.md
Normal file
@@ -0,0 +1,258 @@
|
||||
# Validation Report Template
|
||||
|
||||
验证报告的标准模板。
|
||||
|
||||
## Template Structure
|
||||
|
||||
```markdown
|
||||
# Validation Report
|
||||
|
||||
**Session ID**: {{session_id}}
|
||||
**Task**: {{task_description}}
|
||||
**Validated**: {{timestamp}}
|
||||
|
||||
---
|
||||
|
||||
## Iteration {{iteration}} - Validation Run
|
||||
|
||||
### Test Execution Summary
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Total Tests | {{total_tests}} |
|
||||
| Passed | {{passed_tests}} |
|
||||
| Failed | {{failed_tests}} |
|
||||
| Skipped | {{skipped_tests}} |
|
||||
| Duration | {{duration}}ms |
|
||||
| **Pass Rate** | **{{pass_rate}}%** |
|
||||
|
||||
### Coverage Report
|
||||
|
||||
{{#if has_coverage}}
|
||||
| File | Statements | Branches | Functions | Lines |
|
||||
|------|------------|----------|-----------|-------|
|
||||
{{#each coverage_files}}
|
||||
| {{path}} | {{statements}}% | {{branches}}% | {{functions}}% | {{lines}}% |
|
||||
{{/each}}
|
||||
|
||||
**Overall Coverage**: {{overall_coverage}}%
|
||||
{{else}}
|
||||
_No coverage data available_
|
||||
{{/if}}
|
||||
|
||||
### Failed Tests
|
||||
|
||||
{{#if has_failures}}
|
||||
{{#each failures}}
|
||||
#### {{test_name}}
|
||||
|
||||
- **Suite**: {{suite}}
|
||||
- **Error**: {{error_message}}
|
||||
- **Stack**:
|
||||
\`\`\`
|
||||
{{stack_trace}}
|
||||
\`\`\`
|
||||
{{/each}}
|
||||
{{else}}
|
||||
_All tests passed_
|
||||
{{/if}}
|
||||
|
||||
### Gemini Quality Analysis
|
||||
|
||||
{{gemini_analysis}}
|
||||
|
||||
### Recommendations
|
||||
|
||||
{{#each recommendations}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
|
||||
---
|
||||
|
||||
## Validation Decision
|
||||
|
||||
**Result**: {{#if passed}}✅ PASS{{else}}❌ FAIL{{/if}}
|
||||
|
||||
**Rationale**: {{rationale}}
|
||||
|
||||
{{#if not_passed}}
|
||||
### Next Actions
|
||||
|
||||
1. Review failed tests
|
||||
2. Debug failures using action-debug-with-file
|
||||
3. Fix issues and re-run validation
|
||||
{{else}}
|
||||
### Next Actions
|
||||
|
||||
1. Consider code review
|
||||
2. Prepare for deployment
|
||||
3. Update documentation
|
||||
{{/if}}
|
||||
```
|
||||
|
||||
## Template Variables
|
||||
|
||||
| Variable | Type | Source | Description |
|
||||
|----------|------|--------|-------------|
|
||||
| `session_id` | string | state.session_id | 会话 ID |
|
||||
| `task_description` | string | state.task_description | 任务描述 |
|
||||
| `timestamp` | string | 当前时间 | 验证时间 |
|
||||
| `iteration` | number | 从文件计算 | 验证迭代次数 |
|
||||
| `total_tests` | number | 测试输出 | 总测试数 |
|
||||
| `passed_tests` | number | 测试输出 | 通过数 |
|
||||
| `failed_tests` | number | 测试输出 | 失败数 |
|
||||
| `pass_rate` | number | 计算得出 | 通过率 |
|
||||
| `coverage_files` | array | 覆盖率报告 | 文件覆盖率 |
|
||||
| `failures` | array | 测试输出 | 失败测试详情 |
|
||||
| `gemini_analysis` | string | Gemini CLI | 质量分析 |
|
||||
| `recommendations` | array | Gemini CLI | 建议列表 |
|
||||
|
||||
## Section Templates
|
||||
|
||||
### Test Summary
|
||||
|
||||
```markdown
|
||||
### Test Execution Summary
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Total Tests | {{total}} |
|
||||
| Passed | {{passed}} |
|
||||
| Failed | {{failed}} |
|
||||
| Skipped | {{skipped}} |
|
||||
| Duration | {{duration}}ms |
|
||||
| **Pass Rate** | **{{rate}}%** |
|
||||
```
|
||||
|
||||
### Coverage Table
|
||||
|
||||
```markdown
|
||||
### Coverage Report
|
||||
|
||||
| File | Statements | Branches | Functions | Lines |
|
||||
|------|------------|----------|-----------|-------|
|
||||
{{#each files}}
|
||||
| `{{path}}` | {{statements}}% | {{branches}}% | {{functions}}% | {{lines}}% |
|
||||
{{/each}}
|
||||
|
||||
**Overall Coverage**: {{overall}}%
|
||||
|
||||
**Coverage Thresholds**:
|
||||
- ✅ Good: ≥ 80%
|
||||
- ⚠️ Warning: 60-79%
|
||||
- ❌ Poor: < 60%
|
||||
```
|
||||
|
||||
### Failed Test Details
|
||||
|
||||
```markdown
|
||||
### Failed Tests
|
||||
|
||||
{{#each failures}}
|
||||
#### ❌ {{test_name}}
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Suite | {{suite}} |
|
||||
| Error | {{error_message}} |
|
||||
| Duration | {{duration}}ms |
|
||||
|
||||
**Stack Trace**:
|
||||
\`\`\`
|
||||
{{stack_trace}}
|
||||
\`\`\`
|
||||
|
||||
**Possible Causes**:
|
||||
{{#each possible_causes}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
|
||||
---
|
||||
{{/each}}
|
||||
```
|
||||
|
||||
### Quality Analysis
|
||||
|
||||
```markdown
|
||||
### Gemini Quality Analysis
|
||||
|
||||
#### Code Quality Assessment
|
||||
|
||||
| Dimension | Score | Status |
|
||||
|-----------|-------|--------|
|
||||
| Correctness | {{correctness}}/10 | {{correctness_status}} |
|
||||
| Completeness | {{completeness}}/10 | {{completeness_status}} |
|
||||
| Reliability | {{reliability}}/10 | {{reliability_status}} |
|
||||
| Maintainability | {{maintainability}}/10 | {{maintainability_status}} |
|
||||
|
||||
#### Key Findings
|
||||
|
||||
{{#each findings}}
|
||||
- **{{severity}}**: {{description}}
|
||||
{{/each}}
|
||||
|
||||
#### Recommendations
|
||||
|
||||
{{#each recommendations}}
|
||||
{{@index}}. {{this}}
|
||||
{{/each}}
|
||||
```
|
||||
|
||||
### Decision Section
|
||||
|
||||
```markdown
|
||||
## Validation Decision
|
||||
|
||||
**Result**: {{#if passed}}✅ PASS{{else}}❌ FAIL{{/if}}
|
||||
|
||||
**Rationale**:
|
||||
{{rationale}}
|
||||
|
||||
**Confidence Level**: {{confidence}}
|
||||
|
||||
### Decision Matrix
|
||||
|
||||
| Criteria | Status | Weight | Score |
|
||||
|----------|--------|--------|-------|
|
||||
| All tests pass | {{tests_pass}} | 40% | {{tests_score}} |
|
||||
| Coverage ≥ 80% | {{coverage_pass}} | 30% | {{coverage_score}} |
|
||||
| No critical issues | {{no_critical}} | 20% | {{critical_score}} |
|
||||
| Quality analysis pass | {{quality_pass}} | 10% | {{quality_score}} |
|
||||
| **Total** | | 100% | **{{total_score}}** |
|
||||
|
||||
**Threshold**: 70% to pass
|
||||
|
||||
### Next Actions
|
||||
|
||||
{{#if passed}}
|
||||
1. ✅ Code review (recommended)
|
||||
2. ✅ Update documentation
|
||||
3. ✅ Prepare for deployment
|
||||
{{else}}
|
||||
1. ❌ Review failed tests
|
||||
2. ❌ Debug failures
|
||||
3. ❌ Fix issues and re-run
|
||||
{{/if}}
|
||||
```
|
||||
|
||||
## Historical Comparison
|
||||
|
||||
```markdown
|
||||
## Validation History
|
||||
|
||||
| Iteration | Date | Pass Rate | Coverage | Status |
|
||||
|-----------|------|-----------|----------|--------|
|
||||
{{#each history}}
|
||||
| {{iteration}} | {{date}} | {{pass_rate}}% | {{coverage}}% | {{status}} |
|
||||
{{/each}}
|
||||
|
||||
### Trend Analysis
|
||||
|
||||
{{#if improving}}
|
||||
📈 **Improving**: Pass rate increased from {{previous_rate}}% to {{current_rate}}%
|
||||
{{else if declining}}
|
||||
📉 **Declining**: Pass rate decreased from {{previous_rate}}% to {{current_rate}}%
|
||||
{{else}}
|
||||
➡️ **Stable**: Pass rate remains at {{current_rate}}%
|
||||
{{/if}}
|
||||
```
|
||||
Reference in New Issue
Block a user