mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-14 02:42:04 +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:
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}` 重新打开会话
|
||||
Reference in New Issue
Block a user