feat: Add interactive pre-flight checklists for ccw-loop and workflow-plan, including validation and task transformation steps

- Implemented `prep-loop.md` for ccw-loop, detailing source discovery, validation, task transformation, and auto-loop configuration.
- Created `prep-plan.md` for workflow planning, covering environment checks, task quality assessment, execution preferences, and final confirmation.
- Defined schemas and integration points for `prep-package.json` in both ccw-loop and workflow-plan skills, ensuring proper validation and task handling.
- Added error handling mechanisms for various scenarios during the preparation phases.
This commit is contained in:
catlog22
2026-02-09 15:02:38 +08:00
parent ef7382ecf5
commit c62d26183b
25 changed files with 1596 additions and 2896 deletions

View File

@@ -9,6 +9,79 @@ Discover existing sessions or start new workflow session with intelligent sessio
- Generate unique session ID (WFS-xxx format)
- Initialize session directory structure
## Step 0.0: Load Prep Package (if exists)
```javascript
// Load plan-prep-package.json (generated by /prompts:prep-plan)
let prepPackage = null
const prepPath = `${projectRoot}/.workflow/.prep/plan-prep-package.json`
if (fs.existsSync(prepPath)) {
const raw = JSON.parse(Read(prepPath))
const checks = validatePlanPrepPackage(raw, projectRoot)
if (checks.valid) {
prepPackage = raw
console.log(`✓ Prep package loaded: score=${prepPackage.task.quality_score}/10, exec=${prepPackage.execution.execution_method}`)
console.log(` Checks passed: ${checks.passed.join(', ')}`)
} else {
console.warn(`⚠ Prep package found but failed validation:`)
checks.failures.forEach(f => console.warn(`${f}`))
console.warn(` → Falling back to default behavior (prep-package ignored)`)
prepPackage = null
}
}
/**
* Validate plan-prep-package.json integrity before consumption.
*/
function validatePlanPrepPackage(prep, projectRoot) {
const passed = []
const failures = []
// Check 1: prep_status
if (prep.prep_status === 'ready') passed.push('status=ready')
else failures.push(`prep_status is "${prep.prep_status}", expected "ready"`)
// Check 2: target_skill
if (prep.target_skill === 'workflow-plan-execute') passed.push('target_skill match')
else failures.push(`target_skill is "${prep.target_skill}", expected "workflow-plan-execute"`)
// Check 3: project_root
if (prep.environment?.project_root === projectRoot) passed.push('project_root match')
else failures.push(`project_root mismatch: "${prep.environment?.project_root}" vs "${projectRoot}"`)
// Check 4: quality_score >= 6
if ((prep.task?.quality_score || 0) >= 6) passed.push(`quality=${prep.task.quality_score}/10`)
else failures.push(`quality_score ${prep.task?.quality_score || 0} < 6`)
// Check 5: generated_at within 24h
const hoursSince = (Date.now() - new Date(prep.generated_at).getTime()) / 3600000
if (hoursSince <= 24) passed.push(`age=${Math.round(hoursSince)}h`)
else failures.push(`prep-package is ${Math.round(hoursSince)}h old (max 24h)`)
// Check 6: required fields
const required = ['task.structured.goal', 'task.structured.scope', 'execution.execution_method']
const missing = required.filter(p => !p.split('.').reduce((o, k) => o?.[k], prep))
if (missing.length === 0) passed.push('fields complete')
else failures.push(`missing: ${missing.join(', ')}`)
return { valid: failures.length === 0, passed, failures }
}
// Build structured description from prep or raw input
let structuredDescription
if (prepPackage) {
structuredDescription = {
goal: prepPackage.task.structured.goal,
scope: prepPackage.task.structured.scope,
context: prepPackage.task.structured.context
}
} else {
structuredDescription = null // Will be parsed from user input later
}
```
## Step 0: Initialize Project State (First-time Only)
**Executed before all modes** - Ensures project-level state files exist by calling `workflow:init`.
@@ -73,23 +146,47 @@ CONTEXT: Existing user database schema, REST API endpoints
### Step 1.4: Initialize Planning Notes
Create `planning-notes.md` with N+1 context support:
Create `planning-notes.md` with N+1 context support, enriched with prep data:
```javascript
const planningNotesPath = `${projectRoot}/.workflow/active/${sessionId}/planning-notes.md`
const userGoal = structuredDescription.goal
const userConstraints = structuredDescription.context || "None specified"
const userGoal = structuredDescription?.goal || taskDescription
const userScope = structuredDescription?.scope || "Not specified"
const userConstraints = structuredDescription?.context || "None specified"
// Build source refs section from prep
const sourceRefsSection = (prepPackage?.task?.source_refs?.length > 0)
? prepPackage.task.source_refs
.filter(r => r.status === 'verified' || r.status === 'linked')
.map(r => `- **${r.type}**: ${r.path}`)
.join('\n')
: 'None'
// Build quality dimensions section from prep
const dimensionsSection = prepPackage?.task?.dimensions
? Object.entries(prepPackage.task.dimensions)
.map(([k, v]) => `- **${k}**: ${v.value} (${v.score}/2)`)
.join('\n')
: ''
Write(planningNotesPath, `# Planning Notes
**Session**: ${sessionId}
**Created**: ${new Date().toISOString()}
${prepPackage ? `**Prep Package**: plan-prep-package.json (score: ${prepPackage.task.quality_score}/10)` : ''}
## User Intent (Phase 1)
- **GOAL**: ${userGoal}
- **SCOPE**: ${userScope}
- **KEY_CONSTRAINTS**: ${userConstraints}
${sourceRefsSection !== 'None' ? `
### Requirement Sources (from prep)
${sourceRefsSection}
` : ''}${dimensionsSection ? `
### Quality Dimensions (from prep)
${dimensionsSection}
` : ''}
---
## Context Findings (Phase 2)