mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-05 01:50:27 +08:00
- Introduced Phase 2.5: Consolidation Agent to summarize analysis outputs and generate design overviews. - Added Phase 4: Document Assembly to create index-style documents linking chapter files. - Implemented Phase 5: Compliance Review & Iterative Refinement for CPCC compliance checks and updates. - Established CPCC Compliance Requirements document outlining mandatory sections and validation functions. - Created a base template for analysis agents to ensure consistency and efficiency in execution.
475 lines
12 KiB
Markdown
475 lines
12 KiB
Markdown
# 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 }
|
||
}
|
||
```
|