mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-10 02:24:35 +08:00
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:
@@ -44,6 +44,17 @@ When `--yes` or `-y`: Auto-continue all phases (skip confirmations), use recomme
|
||||
|
||||
When `--with-commit`: Auto-commit after each task completion in Phase 4.
|
||||
|
||||
## Prep Package Integration
|
||||
|
||||
When `plan-prep-package.json` exists at `{projectRoot}/.workflow/.prep/plan-prep-package.json`, the skill consumes it with 6-point validation:
|
||||
|
||||
1. **Phase 1**: Use `task.structured` (GOAL/SCOPE/CONTEXT) for session creation, enrich planning-notes.md with source_refs and quality dimensions
|
||||
2. **Phase 2**: Feed verified source_refs as supplementary docs for exploration agents
|
||||
3. **Phase 3**: Auto-populate Phase 0 User Configuration (execution_method, preferred_cli_tool, supplementary_materials) — skip interactive questions
|
||||
4. **Phase 4**: Apply `execution.with_commit` flag
|
||||
|
||||
Prep packages are generated by the interactive prompt `/prompts:prep-plan`. See [phases/00-prep-checklist.md](phases/00-prep-checklist.md) for schema and validation rules.
|
||||
|
||||
## Execution Flow
|
||||
|
||||
```
|
||||
|
||||
181
.codex/skills/workflow-plan-execute/phases/00-prep-checklist.md
Normal file
181
.codex/skills/workflow-plan-execute/phases/00-prep-checklist.md
Normal file
@@ -0,0 +1,181 @@
|
||||
# Prep Package Schema & Integration Spec
|
||||
|
||||
Schema definition for `plan-prep-package.json` and integration points with the workflow-plan-execute skill.
|
||||
|
||||
## File Location
|
||||
|
||||
```
|
||||
{projectRoot}/.workflow/.prep/plan-prep-package.json
|
||||
```
|
||||
|
||||
Generated by: `/prompts:prep-plan` (interactive prompt)
|
||||
Consumed by: Phase 1 (Session Discovery) → feeds into Phase 2, 3, 4
|
||||
|
||||
## JSON Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"generated_at": "ISO8601",
|
||||
"prep_status": "ready | needs_refinement | blocked",
|
||||
"target_skill": "workflow-plan-execute",
|
||||
|
||||
"environment": {
|
||||
"project_root": "/path/to/project",
|
||||
"prerequisites": {
|
||||
"required_passed": true,
|
||||
"recommended_passed": true,
|
||||
"warnings": ["string"]
|
||||
},
|
||||
"tech_stack": "string",
|
||||
"test_framework": "string",
|
||||
"has_project_tech": true,
|
||||
"has_project_guidelines": true
|
||||
},
|
||||
|
||||
"task": {
|
||||
"original": "raw user input",
|
||||
"structured": {
|
||||
"goal": "GOAL string (objective + success criteria)",
|
||||
"scope": "SCOPE string (boundaries)",
|
||||
"context": "CONTEXT string (constraints + tech context)"
|
||||
},
|
||||
"quality_score": 8,
|
||||
"dimensions": {
|
||||
"objective": { "score": 2, "value": "..." },
|
||||
"success_criteria": { "score": 2, "value": "..." },
|
||||
"scope": { "score": 2, "value": "..." },
|
||||
"constraints": { "score": 1, "value": "..." },
|
||||
"context": { "score": 1, "value": "..." }
|
||||
},
|
||||
"source_refs": [
|
||||
{
|
||||
"path": "docs/prd.md",
|
||||
"type": "local_file | url | auto_detected",
|
||||
"status": "verified | linked | not_found",
|
||||
"preview": "first ~20 lines (local_file only)"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"execution": {
|
||||
"auto_yes": true,
|
||||
"with_commit": true,
|
||||
"execution_method": "agent | cli | hybrid",
|
||||
"preferred_cli_tool": "codex | gemini | qwen | auto",
|
||||
"supplementary_materials": {
|
||||
"type": "none | paths | inline",
|
||||
"content": []
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Validation Rules (6 checks)
|
||||
|
||||
Phase 1 对 plan-prep-package.json 执行 **6 项验证**,全部通过才加载:
|
||||
|
||||
| # | 检查项 | 条件 | 失败处理 |
|
||||
|---|--------|------|----------|
|
||||
| 1 | prep_status | `=== "ready"` | 跳过 prep |
|
||||
| 2 | target_skill | `=== "workflow-plan-execute"` | 跳过 prep(防错误 skill) |
|
||||
| 3 | project_root | 与当前 projectRoot 一致 | 跳过 prep(防错误项目) |
|
||||
| 4 | quality_score | `>= 6` | 跳过 prep(任务质量不达标) |
|
||||
| 5 | 时效性 | generated_at 在 24h 以内 | 跳过 prep(可能过期) |
|
||||
| 6 | 必需字段 | task.structured.goal, execution 全部存在 | 跳过 prep |
|
||||
|
||||
## Phase 1 Integration (Session Discovery)
|
||||
|
||||
After session creation, enrich planning-notes.md with prep data:
|
||||
|
||||
```javascript
|
||||
const prepPath = `${projectRoot}/.workflow/.prep/plan-prep-package.json`
|
||||
let prepPackage = null
|
||||
|
||||
if (fs.existsSync(prepPath)) {
|
||||
const raw = JSON.parse(Read(prepPath))
|
||||
const checks = validatePlanPrepPackage(raw, projectRoot)
|
||||
|
||||
if (checks.valid) {
|
||||
prepPackage = raw
|
||||
// Use structured task for session creation
|
||||
structuredDescription = {
|
||||
goal: prepPackage.task.structured.goal,
|
||||
scope: prepPackage.task.structured.scope,
|
||||
context: prepPackage.task.structured.context
|
||||
}
|
||||
console.log(`✓ Prep package loaded: score=${prepPackage.task.quality_score}/10`)
|
||||
} else {
|
||||
console.warn(`⚠ Prep package validation failed, using defaults`)
|
||||
}
|
||||
}
|
||||
|
||||
// After session created, enrich planning-notes.md:
|
||||
if (prepPackage) {
|
||||
// 1. Add source refs section
|
||||
const sourceRefsSection = prepPackage.task.source_refs
|
||||
?.filter(r => r.status === 'verified' || r.status === 'linked')
|
||||
.map(r => `- **${r.type}**: ${r.path}`)
|
||||
.join('\n') || 'None'
|
||||
|
||||
// 2. Add quality dimensions
|
||||
const dimensionsSection = Object.entries(prepPackage.task.dimensions)
|
||||
.map(([k, v]) => `- **${k}**: ${v.value} (score: ${v.score}/2)`)
|
||||
.join('\n')
|
||||
|
||||
// Append to planning-notes.md under User Intent
|
||||
Edit(planningNotesPath, {
|
||||
old: `- **KEY_CONSTRAINTS**: ${userConstraints}`,
|
||||
new: `- **KEY_CONSTRAINTS**: ${userConstraints}
|
||||
|
||||
### Requirement Sources (from prep)
|
||||
${sourceRefsSection}
|
||||
|
||||
### Quality Dimensions (from prep)
|
||||
${dimensionsSection}`
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## Phase 3 Integration (Task Generation - Phase 0 User Config)
|
||||
|
||||
Prep package auto-populates Phase 0 user configuration:
|
||||
|
||||
```javascript
|
||||
// In Phase 3, Phase 0 (User Configuration):
|
||||
if (prepPackage) {
|
||||
// Auto-answer all Phase 0 questions from prep
|
||||
userConfig = {
|
||||
supplementaryMaterials: prepPackage.execution.supplementary_materials,
|
||||
executionMethod: prepPackage.execution.execution_method,
|
||||
preferredCliTool: prepPackage.execution.preferred_cli_tool,
|
||||
enableResume: true
|
||||
}
|
||||
console.log(`✓ Phase 0 auto-configured from prep: ${userConfig.executionMethod} (${userConfig.preferredCliTool})`)
|
||||
// Skip interactive questions, proceed to Phase 1 (Context Prep)
|
||||
}
|
||||
```
|
||||
|
||||
## Phase 2 Integration (Context Gathering)
|
||||
|
||||
Source refs from prep feed into exploration context:
|
||||
|
||||
```javascript
|
||||
// In Phase 2, Step 2 (spawn explore agents):
|
||||
// Add source_refs as supplementary context for exploration
|
||||
if (prepPackage?.task?.source_refs?.length > 0) {
|
||||
const verifiedRefs = prepPackage.task.source_refs.filter(r => r.status === 'verified')
|
||||
// Include verified local docs in exploration agent prompt
|
||||
explorationAgentPrompt += `\n## SUPPLEMENTARY REQUIREMENT DOCUMENTS\n`
|
||||
explorationAgentPrompt += verifiedRefs.map(r => `Read and analyze: ${r.path}`).join('\n')
|
||||
}
|
||||
```
|
||||
|
||||
## Phase 4 Integration (Execution)
|
||||
|
||||
Commit flag from prep:
|
||||
|
||||
```javascript
|
||||
// In Phase 4:
|
||||
const withCommit = prepPackage?.execution?.with_commit || $ARGUMENTS.includes('--with-commit')
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
@@ -127,6 +127,15 @@ const sessionFolder = `${projectRoot}/.workflow/active/${session_id}/.process`;
|
||||
// 2.2 Launch Parallel Explore Agents (with conflict detection)
|
||||
const explorationAgents = [];
|
||||
|
||||
// Load source_refs from prep-package for supplementary context
|
||||
const prepPath = `${projectRoot}/.workflow/.prep/plan-prep-package.json`
|
||||
const prepSourceRefs = fs.existsSync(prepPath)
|
||||
? (JSON.parse(Read(prepPath))?.task?.source_refs || []).filter(r => r.status === 'verified')
|
||||
: []
|
||||
const sourceRefsDirective = prepSourceRefs.length > 0
|
||||
? `\n## SUPPLEMENTARY REQUIREMENT DOCUMENTS (from prep)\nRead these before exploration:\n${prepSourceRefs.map((r, i) => `${i + 1}. Read: ${r.path} (${r.type})`).join('\n')}\nCross-reference findings against these source documents.\n`
|
||||
: ''
|
||||
|
||||
// Spawn all agents in parallel
|
||||
selectedAngles.forEach((angle, index) => {
|
||||
const agentId = spawn_agent({
|
||||
@@ -144,6 +153,7 @@ selectedAngles.forEach((angle, index) => {
|
||||
Execute **${angle}** exploration for task planning context. Analyze codebase from this specific angle to discover relevant structure, patterns, and constraints.
|
||||
|
||||
**CONFLICT DETECTION**: Additionally detect conflict indicators including module overlaps, breaking changes, incompatible patterns, and scenario boundary ambiguities.
|
||||
${sourceRefsDirective}
|
||||
|
||||
## Assigned Context
|
||||
- **Exploration Angle**: ${angle}
|
||||
|
||||
@@ -78,12 +78,17 @@ Phase 3: Integration (+1 Coordinator, Multi-Module Only)
|
||||
```javascript
|
||||
const autoYes = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y')
|
||||
|
||||
if (autoYes) {
|
||||
console.log(`[--yes] Using defaults: No materials, Agent executor, Codex CLI`)
|
||||
// Check for prep-package auto-configuration (from /prompts:prep-plan)
|
||||
const prepPath = `${projectRoot}/.workflow/.prep/plan-prep-package.json`
|
||||
const prepExec = fs.existsSync(prepPath) ? JSON.parse(Read(prepPath))?.execution : null
|
||||
|
||||
if (autoYes || prepExec) {
|
||||
const source = prepExec ? 'prep-package' : '--yes flag'
|
||||
console.log(`[${source}] Using defaults: ${prepExec?.execution_method || 'agent'} executor, ${prepExec?.preferred_cli_tool || 'codex'} CLI`)
|
||||
userConfig = {
|
||||
supplementaryMaterials: { type: "none", content: [] },
|
||||
executionMethod: "agent",
|
||||
preferredCliTool: "codex",
|
||||
supplementaryMaterials: prepExec?.supplementary_materials || { type: "none", content: [] },
|
||||
executionMethod: prepExec?.execution_method || "agent",
|
||||
preferredCliTool: prepExec?.preferred_cli_tool || "codex",
|
||||
enableResume: true
|
||||
}
|
||||
// Skip to Phase 1
|
||||
|
||||
Reference in New Issue
Block a user