Files
catlog22 54c3234d84 fix: 为所有 skill 的 .workflow/ 路径添加 projectRoot 前缀
从子目录执行 skill 时,相对路径 .workflow/ 会导致产物落到错误位置。
通过 git rev-parse --show-toplevel || pwd 检测项目根目录,
所有 .workflow/ 路径引用统一加上 {projectRoot} 前缀确保路径正确。

涉及 72 个文件,覆盖 20+ 个 skill。
2026-02-08 13:46:48 +08:00

6.4 KiB

Action: COMPLETE

Complete CCW Loop session and generate summary report.

Purpose

  • Generate completion report
  • Aggregate all phase results
  • Provide follow-up recommendations
  • Offer expansion to issues
  • Mark status as completed

Preconditions

  • state.status === 'running'
  • state.skill_state !== null

Execution Steps

Step 1: Verify Control Signals

const state = JSON.parse(Read(`${projectRoot}/.workflow/.loop/${loopId}.json`))

if (state.status !== 'running') {
  return {
    action: 'COMPLETE',
    status: 'failed',
    message: `Cannot complete: status is ${state.status}`,
    next_action: state.status === 'paused' ? 'PAUSED' : 'STOPPED'
  }
}

Step 2: Aggregate Statistics

const stats = {
  // Time statistics
  duration: Date.now() - new Date(state.created_at).getTime(),
  iterations: state.current_iteration,

  // Development statistics
  develop: {
    total_tasks: state.skill_state.develop.total,
    completed_tasks: state.skill_state.develop.completed,
    completion_rate: state.skill_state.develop.total > 0
      ? ((state.skill_state.develop.completed / state.skill_state.develop.total) * 100).toFixed(1)
      : 0
  },

  // Debug statistics
  debug: {
    iterations: state.skill_state.debug.iteration,
    hypotheses_tested: state.skill_state.debug.hypotheses.length,
    root_cause_found: state.skill_state.debug.confirmed_hypothesis !== null
  },

  // Validation statistics
  validate: {
    runs: state.skill_state.validate.test_results.length,
    passed: state.skill_state.validate.passed,
    coverage: state.skill_state.validate.coverage,
    failed_tests: state.skill_state.validate.failed_tests.length
  }
}

Step 3: Generate Summary Report

const timestamp = getUtc8ISOString()

const summaryReport = `# CCW Loop Session Summary

**Loop ID**: ${loopId}
**Task**: ${state.description}
**Started**: ${state.created_at}
**Completed**: ${timestamp}
**Duration**: ${formatDuration(stats.duration)}

---

## Executive Summary

${state.skill_state.validate.passed
  ? 'All tests passed, validation successful'
  : state.skill_state.develop.completed === state.skill_state.develop.total
    ? 'Development complete, validation not passed - needs debugging'
    : 'Task partially complete - pending items remain'}

---

## Development Phase

| Metric | Value |
|--------|-------|
| Total Tasks | ${stats.develop.total_tasks} |
| Completed | ${stats.develop.completed_tasks} |
| Completion Rate | ${stats.develop.completion_rate}% |

### Completed Tasks

${state.skill_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.skill_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.skill_state.debug.confirmed_hypothesis}: ${state.skill_state.debug.hypotheses.find(h => h.id === state.skill_state.debug.confirmed_hypothesis)?.description}
` : ''}

---

## 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} |

---

## Recommendations

${generateRecommendations(stats, state)}

---

## Session Artifacts

| File | Description |
|------|-------------|
| \`develop.md\` | Development progress timeline |
| \`debug.md\` | Debug exploration and learnings |
| \`validate.md\` | Validation report |
| \`test-results.json\` | Test execution results |

---

*Generated by CCW Loop at ${timestamp}*
`

Write(`${progressDir}/summary.md`, summaryReport)

Step 4: Update State to Completed

state.status = 'completed'
state.completed_at = timestamp
state.updated_at = timestamp
state.skill_state.last_action = 'COMPLETE'
state.skill_state.summary = stats

Write(`${projectRoot}/.workflow/.loop/${loopId}.json`, JSON.stringify(state, null, 2))

Output Format

ACTION_RESULT:
- action: COMPLETE
- status: success
- message: Loop completed. Duration: {duration}, Iterations: {N}
- state_updates: {
    "status": "completed",
    "completed_at": "{timestamp}"
  }

FILES_UPDATED:
- {projectRoot}/.workflow/.loop/{loopId}.json: Status set to completed
- {projectRoot}/.workflow/.loop/{loopId}.progress/summary.md: Summary report generated

NEXT_ACTION_NEEDED: COMPLETED

Expansion Options

After completion, offer expansion to issues:

## Expansion Options

Would you like to create follow-up issues?

1. [test] Add more test cases
2. [enhance] Feature enhancements
3. [refactor] Code refactoring
4. [doc] Documentation updates
5. [none] No expansion needed

Select options (comma-separated) or 'none':

Helper Functions

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('- Complete remaining development tasks')
  }

  if (!stats.validate.passed) {
    recommendations.push('- Fix failing tests')
  }

  if (stats.validate.coverage && stats.validate.coverage < 80) {
    recommendations.push(`- Improve test coverage (current: ${stats.validate.coverage}%)`)
  }

  if (recommendations.length === 0) {
    recommendations.push('- Consider code review')
    recommendations.push('- Update documentation')
    recommendations.push('- Prepare for deployment')
  }

  return recommendations.join('\n')
}

Error Handling

Error Type Recovery
Report generation failed Show basic stats, skip file write
Issue creation failed Log error, continue completion

Next Actions

  • None (terminal state)
  • To continue: Use /ccw-loop --loop-id={loopId} to reopen (will set status back to running)