feat: enforce mandatory rationale and role in explore/diagnosis schema output

- Remove oneOf string option from relevant_files/affected_files, require structured objects
- Add required fields: rationale (minLength 10), role/change_type enum
- Add optional fields: discovery_source, key_symbols
- Update all caller commands with new format instructions and success criteria
- Fix consumer code: Map-based dedup, getPath() helper, path extraction
- Fix frontend: f.rationale || f.reason backward-compatible fallback
This commit is contained in:
catlog22
2026-02-13 10:42:37 +08:00
parent 78f1d81516
commit e485f1d69b
16 changed files with 679 additions and 373 deletions

View File

@@ -52,7 +52,7 @@ mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "planner", to
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "planner", to: "coordinator", type: "plan_revision", summary: "已按反馈拆分task-2为两个子任务" })
// 错误上报
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "planner", to: "coordinator", type: "error", summary: "plan-json-schema.json 未找到, 使用默认结构" })
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "planner", to: "coordinator", type: "error", summary: "plan-overview-base-schema.json 未找到, 使用默认结构" })
```
## Execution Process
@@ -73,10 +73,10 @@ Phase 2: Multi-Angle Exploration
└─ Write exploration results to session folder
Phase 3: Plan Generation
├─ Read plan-json-schema.json for structure reference
├─ Read plan-overview-base-schema.json + task-schema.json for structure reference
├─ Low complexity → Direct Claude planning
├─ Medium/High → cli-lite-planning-agent
└─ Output: plan.json
└─ Output: plan.json (overview with task_ids[]) + .task/TASK-*.json (independent task files)
Phase 4: Submit for Approval
├─ SendMessage plan summary to coordinator
@@ -208,6 +208,12 @@ Execute **${angle}** exploration for task planning context.
## Expected Output
Write JSON to: ${sessionFolder}/exploration-${angle}.json
Follow explore-json-schema.json structure with ${angle}-focused findings.
**MANDATORY**: Every file in relevant_files MUST have:
- **rationale** (required): Specific selection basis tied to ${angle} topic (>10 chars, not generic)
- **role** (required): modify_target|dependency|pattern_reference|test_target|type_definition|integration_point|config|context_only
- **discovery_source** (recommended): bash-scan|cli-analysis|ace-search|dependency-trace|manual
- **key_symbols** (recommended): Key functions/classes/types relevant to task
`
})
})
@@ -232,7 +238,7 @@ Write(`${sessionFolder}/explorations-manifest.json`, JSON.stringify(explorationM
```javascript
// Read schema reference
const schema = Bash(`cat ~/.ccw/workflows/cli-templates/schemas/plan-json-schema.json`)
const schema = Bash(`cat ~/.ccw/workflows/cli-templates/schemas/plan-overview-base-schema.json`)
if (complexity === 'Low') {
// Direct Claude planning
@@ -242,18 +248,31 @@ if (complexity === 'Low') {
// Incorporate findings into plan
})
// Generate plan following schema
// Generate task files in .task/ directory
Bash(`mkdir -p ${sessionFolder}/.task`)
const tasks = [/* structured tasks with dependencies, files[].change, convergence.criteria */]
const taskIds = tasks.map(t => t.id)
// Write individual task files following task-schema.json
tasks.forEach(task => {
Write(`${sessionFolder}/.task/${task.id}.json`, JSON.stringify(task, null, 2))
})
// Generate plan overview following plan-overview-base-schema.json
const plan = {
summary: "...",
approach: "...",
tasks: [/* structured tasks with dependencies, modification points, acceptance criteria */],
task_ids: taskIds,
task_count: taskIds.length,
estimated_time: "...",
recommended_execution: "Agent",
complexity: "Low",
_metadata: {
timestamp: new Date().toISOString(),
source: "team-planner",
planning_mode: "direct"
planning_mode: "direct",
plan_type: "feature"
}
}
Write(`${sessionFolder}/plan.json`, JSON.stringify(plan, null, 2))
@@ -264,16 +283,26 @@ if (complexity === 'Low') {
run_in_background: false,
description: "Generate detailed implementation plan",
prompt: `
Generate implementation plan and write plan.json.
Generate implementation plan with two-layer output.
## Output Location
**Session Folder**: ${sessionFolder}
**Output Files**:
- ${sessionFolder}/planning-context.md
- ${sessionFolder}/plan.json
- ${sessionFolder}/plan.json (overview with task_ids[])
- ${sessionFolder}/.task/TASK-*.json (independent task files)
## Output Schema Reference
Execute: cat ~/.ccw/workflows/cli-templates/schemas/plan-json-schema.json
Execute: cat ~/.ccw/workflows/cli-templates/schemas/plan-overview-base-schema.json
Execute: cat ~/.ccw/workflows/cli-templates/schemas/task-schema.json
## Output Format: Two-Layer Structure
- plan.json: Overview with task_ids[] referencing .task/ files (NO tasks[] array)
- .task/TASK-*.json: Independent task files following task-schema.json
plan.json required: summary, approach, task_ids, task_count, _metadata (with plan_type)
Task files required: id, title, description, depends_on, convergence (with criteria[])
Task fields: files[].change (not modification_points), convergence.criteria (not acceptance), test (not verification)
## Task Description
${task.description}
@@ -286,9 +315,9 @@ Path: ${exp.path}`).join('\n\n')}
${complexity}
## Requirements
Generate plan.json following schema. Key constraints:
- tasks: 2-7 structured tasks (group by feature/module, NOT by file)
- Each task: id, title, scope, modification_points, implementation, acceptance, depends_on
Generate plan.json + .task/*.json following schemas. Key constraints:
- 2-7 structured tasks (group by feature/module, NOT by file)
- Each task file: id, title, description, files[].change, convergence.criteria, depends_on
- Prefer parallel tasks (minimize depends_on)
`
})
@@ -301,6 +330,10 @@ Generate plan.json following schema. Key constraints:
// Read generated plan
const plan = JSON.parse(Read(`${sessionFolder}/plan.json`))
// Load tasks from .task/ directory (two-layer format)
const tasks = plan.task_ids.map(id => JSON.parse(Read(`${sessionFolder}/.task/${id}.json`)))
const taskCount = plan.task_count || plan.task_ids.length
// Send plan summary to coordinator
SendMessage({
type: "message",
@@ -309,19 +342,20 @@ SendMessage({
**Task**: ${task.subject}
**Complexity**: ${complexity}
**Tasks**: ${plan.tasks.length}
**Tasks**: ${taskCount}
### Task Summary
${plan.tasks.map((t, i) => `${i+1}. ${t.title} (${t.scope || 'N/A'})`).join('\n')}
${tasks.map((t, i) => `${i+1}. ${t.title} (${t.scope || 'N/A'})`).join('\n')}
### Approach
${plan.approach}
### Plan Location
${sessionFolder}/plan.json
${plan.task_ids ? `Task Files: ${sessionFolder}/.task/` : ''}
Please review and approve or request revisions.`,
summary: `Plan ready: ${plan.tasks.length} tasks`
summary: `Plan ready: ${taskCount} tasks`
})
// Wait for coordinator response
@@ -359,7 +393,11 @@ if (nextTasks.length > 0) {
├── exploration-{angle2}.json
├── explorations-manifest.json # Exploration index
├── planning-context.md # Evidence + understanding (Medium/High)
── plan.json # Implementation plan
── plan.json # Plan overview with task_ids[] (NO embedded tasks[])
└── .task/ # Independent task files
├── TASK-001.json # Task file following task-schema.json
├── TASK-002.json
└── ...
```
## Error Handling

View File

@@ -44,7 +44,8 @@ Intelligent lightweight bug fixing command with dynamic workflow adaptation base
| `diagnosis-{angle}.json` | Per-angle diagnosis results (1-4 files based on severity) |
| `diagnoses-manifest.json` | Index of all diagnosis files |
| `planning-context.md` | Evidence paths + synthesized understanding |
| `fix-plan.json` | Structured fix plan (fix-plan-json-schema.json) |
| `fix-plan.json` | Fix plan overview with `task_ids[]` (plan-overview-fix-schema.json) |
| `.task/FIX-*.json` | Independent fix task files (one per task) |
**Output Directory**: `.workflow/.lite-fix/{bug-slug}-{YYYY-MM-DD}/`
@@ -52,7 +53,7 @@ Intelligent lightweight bug fixing command with dynamic workflow adaptation base
- Low/Medium severity → Direct Claude planning (no agent)
- High/Critical severity → `cli-lite-planning-agent` generates `fix-plan.json`
**Schema Reference**: `~/.ccw/workflows/cli-templates/schemas/fix-plan-json-schema.json`
**Schema Reference**: `~/.ccw/workflows/cli-templates/schemas/plan-overview-fix-schema.json`
## Auto Mode Defaults
@@ -91,7 +92,7 @@ Phase 2: Clarification (optional, multi-round)
Phase 3: Fix Planning (NO CODE EXECUTION - planning only)
+- Decision (based on Phase 1 severity):
|- Low/Medium -> Load schema: cat ~/.ccw/workflows/cli-templates/schemas/fix-plan-json-schema.json -> Direct Claude planning (following schema) -> fix-plan.json -> MUST proceed to Phase 4
|- Low/Medium -> Load schema: cat ~/.ccw/workflows/cli-templates/schemas/plan-overview-fix-schema.json -> Direct Claude planning (following schema) -> fix-plan.json -> MUST proceed to Phase 4
+- High/Critical -> cli-lite-planning-agent -> fix-plan.json -> MUST proceed to Phase 4
Phase 4: Confirmation & Selection
@@ -254,8 +255,12 @@ Execute **${angle}** diagnosis for bug root cause analysis. Analyze codebase fro
**IMPORTANT**: Use structured format:
\`{file: "src/module/file.ts", line_range: "45-60", issue: "Description", confidence: 0.85}\`
- affected_files: Files involved from ${angle} perspective
**IMPORTANT**: Use object format with relevance scores:
\`[{path: "src/file.ts", relevance: 0.85, rationale: "Contains ${angle} logic"}]\`
**MANDATORY**: Every file MUST use structured object format with ALL required fields:
\`[{path: "src/file.ts", relevance: 0.85, rationale: "Contains handleLogin() at line 45 where null check is missing", change_type: "fix_target", discovery_source: "bash-scan", key_symbols: ["handleLogin"]}]\`
- **rationale** (required): Specific reason why this file is affected (>10 chars, not generic)
- **change_type** (required): fix_target|needs_update|test_coverage|reference_only
- **discovery_source** (recommended): bash-scan|cli-analysis|ace-search|dependency-trace|stack-trace|manual
- **key_symbols** (recommended): Key functions/classes related to the bug
- reproduction_steps: Steps to reproduce the bug
- fix_hints: Suggested fix approaches from ${angle} viewpoint
- dependencies: Dependencies relevant to ${angle} diagnosis
@@ -268,7 +273,9 @@ Execute **${angle}** diagnosis for bug root cause analysis. Analyze codebase fro
- [ ] Schema obtained via cat diagnosis-json-schema.json
- [ ] get_modules_by_depth.sh executed
- [ ] Root cause identified with confidence score
- [ ] At least 3 affected files identified with ${angle} rationale
- [ ] At least 3 affected files identified with specific rationale + change_type
- [ ] Every file has rationale >10 chars (not generic like "Contains ${angle} logic")
- [ ] Every file has change_type classification (fix_target/needs_update/etc.)
- [ ] Fix hints are actionable (specific code changes, not generic advice)
- [ ] Reproduction steps are verifiable
- [ ] JSON output follows schema exactly
@@ -426,21 +433,74 @@ if (autoYes) {
**Low/Medium Severity** - Direct planning by Claude:
```javascript
// Step 1: Read schema
const schema = Bash(`cat ~/.ccw/workflows/cli-templates/schemas/fix-plan-json-schema.json`)
const schema = Bash(`cat ~/.ccw/workflows/cli-templates/schemas/plan-overview-fix-schema.json`)
// Step 2: Generate fix-plan following schema (Claude directly, no agent)
// For Medium complexity: include rationale + verification (optional, but recommended)
// Step 2: Generate fix tasks with NEW field names (Claude directly, no agent)
// Field mapping: modification_points -> files, acceptance -> convergence, verification -> test
const fixTasks = [
{
id: "FIX-001",
title: "...",
description: "...",
scope: "...",
action: "Fix|Update|Refactor|Add|Delete",
depends_on: [],
convergence: {
criteria: ["..."] // Quantified acceptance criteria
},
files: [
{ path: "src/module/file.ts", action: "modify", target: "functionName", change: "Description of change" }
],
implementation: ["Step 1: ...", "Step 2: ..."],
test: {
manual_checks: ["Reproduce issue", "Verify fix"],
success_metrics: ["Issue resolved", "No regressions"]
},
complexity: "Low|Medium",
// Medium severity fields (optional for Low, recommended for Medium)
...(severity === "Medium" ? {
rationale: {
chosen_approach: "Direct fix approach",
alternatives_considered: ["Workaround", "Refactor"],
decision_factors: ["Minimal impact", "Quick turnaround"],
tradeoffs: "Doesn't address underlying issue"
},
test: {
unit: ["test_bug_fix_basic"],
integration: [],
manual_checks: ["Reproduce issue", "Verify fix"],
success_metrics: ["Issue resolved", "No regressions"]
}
} : {})
}
// ... additional tasks as needed
]
// Step 3: Write individual task files to .task/ directory
const taskDir = `${sessionFolder}/.task`
Bash(`mkdir -p "${taskDir}"`)
fixTasks.forEach(task => {
Write(`${taskDir}/${task.id}.json`, JSON.stringify(task, null, 2))
})
// Step 4: Generate fix-plan overview (NO embedded tasks[])
const fixPlan = {
summary: "...",
root_cause: "...",
strategy: "immediate_patch|comprehensive_fix|refactor",
tasks: [...], // Each task: { id, title, scope, ..., depends_on, complexity }
approach: "...",
task_ids: fixTasks.map(t => t.id),
task_count: fixTasks.length,
fix_context: {
root_cause: "...",
strategy: "immediate_patch|comprehensive_fix|refactor",
severity: severity,
risk_level: "..."
},
estimated_time: "...",
recommended_execution: "Agent",
severity: severity,
risk_level: "...",
// Medium complexity fields (optional for direct planning, auto-filled for Low)
// Medium complexity fields (optional for Low)
...(severity === "Medium" ? {
design_decisions: [
{
@@ -448,58 +508,22 @@ const fixPlan = {
rationale: "Keeps changes localized and quick to review",
tradeoff: "Defers comprehensive refactoring"
}
],
tasks_with_rationale: {
// Each task gets rationale if Medium
task_rationale_example: {
rationale: {
chosen_approach: "Direct fix approach",
alternatives_considered: ["Workaround", "Refactor"],
decision_factors: ["Minimal impact", "Quick turnaround"],
tradeoffs: "Doesn't address underlying issue"
},
verification: {
unit_tests: ["test_bug_fix_basic"],
integration_tests: [],
manual_checks: ["Reproduce issue", "Verify fix"],
success_metrics: ["Issue resolved", "No regressions"]
}
}
}
]
} : {}),
_metadata: {
timestamp: getUtc8ISOString(),
source: "direct-planning",
planning_mode: "direct",
plan_type: "fix",
complexity: severity === "Medium" ? "Medium" : "Low"
}
}
// Step 3: Merge task rationale into tasks array
if (severity === "Medium") {
fixPlan.tasks = fixPlan.tasks.map(task => ({
...task,
rationale: fixPlan.tasks_with_rationale[task.id]?.rationale || {
chosen_approach: "Standard fix",
alternatives_considered: [],
decision_factors: ["Correctness", "Simplicity"],
tradeoffs: "None"
},
verification: fixPlan.tasks_with_rationale[task.id]?.verification || {
unit_tests: [`test_${task.id}_basic`],
integration_tests: [],
manual_checks: ["Verify fix works"],
success_metrics: ["Test pass"]
}
}))
delete fixPlan.tasks_with_rationale // Clean up temp field
}
// Step 4: Write fix-plan to session folder
// Step 5: Write fix-plan overview to session folder
Write(`${sessionFolder}/fix-plan.json`, JSON.stringify(fixPlan, null, 2))
// Step 5: MUST continue to Phase 4 (Confirmation) - DO NOT execute code here
// Step 6: MUST continue to Phase 4 (Confirmation) - DO NOT execute code here
```
**High/Critical Severity** - Invoke cli-lite-planning-agent:
@@ -510,17 +534,18 @@ Task(
run_in_background=false,
description="Generate detailed fix plan",
prompt=`
Generate fix plan and write fix-plan.json.
Generate fix plan using two-layer output format.
## Output Location
**Session Folder**: ${sessionFolder}
**Output Files**:
- ${sessionFolder}/planning-context.md (evidence + understanding)
- ${sessionFolder}/fix-plan.json (fix plan)
- ${sessionFolder}/fix-plan.json (fix plan overview -- NO embedded tasks[])
- ${sessionFolder}/.task/FIX-*.json (independent fix task files, one per task)
## Output Schema Reference
Execute: cat ~/.ccw/workflows/cli-templates/schemas/fix-plan-json-schema.json (get schema reference before generating plan)
Execute: cat ~/.ccw/workflows/cli-templates/schemas/plan-overview-fix-schema.json (get schema reference before generating plan)
## Project Context (MANDATORY - Read Both Files)
1. Read: .workflow/project-tech.json (technology stack, architecture, key components)
@@ -550,20 +575,49 @@ ${JSON.stringify(clarificationContext) || "None"}
${severity}
## Requirements
Generate fix-plan.json with:
**Output Format**: Two-layer structure:
- fix-plan.json: Overview with task_ids[] referencing .task/ files (NO tasks[] array)
- .task/FIX-*.json: Independent task files following task-schema.json
**fix-plan.json required fields**:
- summary: 2-3 sentence overview of the fix
- root_cause: Consolidated root cause from all diagnoses
- strategy: "immediate_patch" | "comprehensive_fix" | "refactor"
- tasks: 1-5 structured fix tasks (**IMPORTANT: group by fix area, NOT by file**)
- **Task Granularity Principle**: Each task = one complete fix unit
- title: action verb + target (e.g., "Fix token validation edge case")
- scope: module path (src/auth/) or feature name
- action: "Fix" | "Update" | "Refactor" | "Add" | "Delete"
- description
- modification_points: ALL files to modify for this fix (group related changes)
- implementation (2-5 steps covering all modification_points)
- acceptance: Quantified acceptance criteria
- depends_on: task IDs this task depends on (use sparingly)
- approach: Overall fix approach description
- task_ids: Array of task IDs (e.g., ["FIX-001", "FIX-002"])
- task_count: Number of tasks
- fix_context:
- root_cause: Consolidated root cause from all diagnoses
- strategy: "immediate_patch" | "comprehensive_fix" | "refactor"
- severity: ${severity}
- risk_level: "Low" | "Medium" | "High"
- estimated_time, recommended_execution
- data_flow (High/Critical REQUIRED): How data flows through affected code
- diagram: "A -> B -> C" style flow
- stages: [{stage, input, output, component}]
- design_decisions (High/Critical REQUIRED): Global fix decisions
- [{decision, rationale, tradeoff}]
- _metadata:
- timestamp, source, planning_mode
- plan_type: "fix"
- complexity: "High" | "Critical"
- diagnosis_angles: ${JSON.stringify(manifest.diagnoses.map(d => d.angle))}
**Each .task/FIX-*.json required fields**:
- id: "FIX-001" (prefix FIX-, NOT TASK-)
- title: action verb + target (e.g., "Fix token validation edge case")
- description
- scope: module path (src/auth/) or feature name
- action: "Fix" | "Update" | "Refactor" | "Add" | "Delete"
- depends_on: task IDs this task depends on (use sparingly)
- convergence: { criteria: ["Quantified acceptance criterion 1", "..."] }
- files: ALL files to modify for this fix (group related changes)
- [{ path: "src/file.ts", action: "modify|create|delete", target: "component/function", change: "Description of what changes" }]
- implementation: ["Step 1: ...", "Step 2: ..."] (2-5 steps covering all files)
- test:
- unit: ["test names to add/verify"]
- integration: ["integration test names"]
- manual_checks: ["manual verification steps"]
- success_metrics: ["quantified success criteria"]
**High/Critical complexity fields per task** (REQUIRED):
- rationale:
@@ -571,11 +625,6 @@ Generate fix-plan.json with:
- alternatives_considered: Other approaches evaluated
- decision_factors: Key factors influencing choice
- tradeoffs: Known tradeoffs of this approach
- verification:
- unit_tests: Test names to add/verify
- integration_tests: Integration test names
- manual_checks: Manual verification steps
- success_metrics: Quantified success criteria
- risks:
- description: Risk description
- probability: Low|Medium|High
@@ -586,18 +635,10 @@ Generate fix-plan.json with:
- interfaces: [{name, definition, purpose}]
- key_functions: [{signature, purpose, returns}]
**Top-level High/Critical fields** (REQUIRED):
- data_flow: How data flows through affected code
- diagram: "A → B → C" style flow
- stages: [{stage, input, output, component}]
- design_decisions: Global fix decisions
- [{decision, rationale, tradeoff}]
- estimated_time, recommended_execution, severity, risk_level
- _metadata:
- timestamp, source, planning_mode
- complexity: "High" | "Critical"
- diagnosis_angles: ${JSON.stringify(manifest.diagnoses.map(d => d.angle))}
**Field name rules** (do NOT use old names):
- files[].change (NOT modification_points)
- convergence.criteria (NOT acceptance)
- test (NOT verification at task level)
## Task Grouping Rules
1. **Group by fix area**: All changes for one fix = one task (even if 2-3 files)
@@ -605,25 +646,30 @@ Generate fix-plan.json with:
3. **Substantial tasks**: Each task should represent 10-45 minutes of work
4. **True dependencies only**: Only use depends_on when Task B cannot start without Task A's output
5. **Prefer parallel**: Most tasks should be independent (no depends_on)
6. **Task IDs**: Use FIX-001, FIX-002 prefix (NOT TASK-)
## Execution
1. Read ALL diagnosis files for comprehensive context
2. Execute CLI planning using Gemini (Qwen fallback) with --rule planning-fix-strategy template
3. Synthesize findings from multiple diagnosis angles
4. Generate fix-plan with:
- For High/Critical: REQUIRED new fields (rationale, verification, risks, code_skeleton, data_flow, design_decisions)
- Each task MUST have rationale (why this fix), verification (how to verify success), and risks (potential issues)
5. Parse output and structure fix-plan
4. Generate fix tasks (1-5 tasks):
- Each task file written to \`${sessionFolder}/.task/FIX-NNN.json\`
- For High/Critical: REQUIRED fields (rationale, test, risks, code_skeleton)
5. Generate fix-plan overview:
- Written to \`${sessionFolder}/fix-plan.json\`
- Contains task_ids[] referencing .task/ files (NO embedded tasks[])
- For High/Critical: REQUIRED fields (data_flow, design_decisions)
6. **Write**: \`${sessionFolder}/planning-context.md\` (evidence paths + understanding)
7. **Write**: \`${sessionFolder}/fix-plan.json\`
8. Return brief completion summary
7. **Write**: \`${sessionFolder}/.task/FIX-*.json\` (individual task files)
8. **Write**: \`${sessionFolder}/fix-plan.json\` (plan overview with task_ids[])
9. Return brief completion summary
## Output Format for CLI
Include these sections in your fix-plan output:
- Summary, Root Cause, Strategy (existing)
- Summary, Root Cause (in fix_context), Strategy (existing)
- Data Flow: Diagram showing affected code paths
- Design Decisions: Key architectural choices in the fix
- Tasks: Each with rationale (Medium/High), verification (Medium/High), risks (High), code_skeleton (High)
- Task files: Each with convergence, files, test, rationale (High), risks (High), code_skeleton (High)
`
)
```
@@ -638,18 +684,26 @@ Include these sections in your fix-plan output:
```javascript
const fixPlan = JSON.parse(Read(`${sessionFolder}/fix-plan.json`))
// Load tasks from .task/ directory (two-layer format)
const tasks = (fixPlan.task_ids || []).map(id => {
return JSON.parse(Read(`${sessionFolder}/.task/${id}.json`))
})
const taskList = tasks
const fixContext = fixPlan.fix_context || {}
console.log(`
## Fix Plan
**Summary**: ${fixPlan.summary}
**Root Cause**: ${fixPlan.root_cause}
**Strategy**: ${fixPlan.strategy}
**Root Cause**: ${fixContext.root_cause || fixPlan.root_cause}
**Strategy**: ${fixContext.strategy || fixPlan.strategy}
**Tasks** (${fixPlan.tasks.length}):
${fixPlan.tasks.map((t, i) => `${i+1}. ${t.title} (${t.scope})`).join('\n')}
**Tasks** (${taskList.length}):
${taskList.map((t, i) => `${i+1}. ${t.title} (${t.scope})`).join('\n')}
**Severity**: ${fixPlan.severity}
**Risk Level**: ${fixPlan.risk_level}
**Severity**: ${fixContext.severity || fixPlan.severity}
**Risk Level**: ${fixContext.risk_level || fixPlan.risk_level}
**Estimated Time**: ${fixPlan.estimated_time}
**Recommended**: ${fixPlan.recommended_execution}
`)
@@ -679,7 +733,7 @@ if (autoYes) {
userSelection = AskUserQuestion({
questions: [
{
question: `Confirm fix plan? (${fixPlan.tasks.length} tasks, ${fixPlan.severity} severity)`,
question: `Confirm fix plan? (${taskList.length} tasks, ${fixContext.severity || fixPlan.severity} severity)`,
header: "Confirm",
multiSelect: false,
options: [
@@ -695,7 +749,7 @@ if (autoYes) {
options: [
{ label: "Agent", description: "@code-developer agent" },
{ label: "Codex", description: "codex CLI tool" },
{ label: "Auto", description: `Auto: ${fixPlan.severity === 'Low' ? 'Agent' : 'Codex'}` }
{ label: "Auto", description: `Auto: ${(fixContext.severity || fixPlan.severity) === 'Low' ? 'Agent' : 'Codex'}` }
]
},
{
@@ -734,14 +788,21 @@ manifest.diagnoses.forEach(diag => {
const fixPlan = JSON.parse(Read(`${sessionFolder}/fix-plan.json`))
const fixSeverity = fixPlan.fix_context?.severity || fixPlan.severity
executionContext = {
mode: "bugfix",
severity: fixPlan.severity,
severity: fixSeverity,
planObject: {
...fixPlan,
// Ensure complexity is set based on severity for new field consumption
complexity: fixPlan.complexity || (fixPlan.severity === 'Critical' ? 'High' : (fixPlan.severity === 'High' ? 'High' : 'Medium'))
complexity: fixPlan.complexity || (fixSeverity === 'Critical' ? 'High' : (fixSeverity === 'High' ? 'High' : 'Medium'))
},
// Task files from .task/ directory (two-layer format)
taskFiles: (fixPlan.task_ids || []).map(id => ({
id,
path: `${sessionFolder}/.task/${id}.json`
})),
diagnosisContext: diagnoses,
diagnosisAngles: manifest.diagnoses.map(d => d.angle),
diagnosisManifest: manifest,
@@ -758,7 +819,8 @@ executionContext = {
path: diag.path
})),
diagnoses_manifest: `${sessionFolder}/diagnoses-manifest.json`,
fix_plan: `${sessionFolder}/fix-plan.json`
fix_plan: `${sessionFolder}/fix-plan.json`,
task_dir: `${sessionFolder}/.task`
}
}
}
@@ -780,7 +842,11 @@ Skill(skill="workflow:lite-execute", args="--in-memory --mode bugfix")
├── diagnosis-{angle4}.json # Diagnosis angle 4 (if applicable)
├── diagnoses-manifest.json # Diagnosis index
├── planning-context.md # Evidence + understanding
── fix-plan.json # Fix plan
── fix-plan.json # Fix plan overview (task_ids[], NO embedded tasks[])
└── .task/ # Independent fix task files
├── FIX-001.json # Fix task 1
├── FIX-002.json # Fix task 2
└── ... # Additional fix tasks
```
**Example**:
@@ -791,7 +857,10 @@ Skill(skill="workflow:lite-execute", args="--in-memory --mode bugfix")
├── diagnosis-validation.json
├── diagnoses-manifest.json
├── planning-context.md
── fix-plan.json
── fix-plan.json
└── .task/
├── FIX-001.json
└── FIX-002.json
```
## Error Handling

View File

@@ -44,7 +44,8 @@ Intelligent lightweight planning command with dynamic workflow adaptation based
| `exploration-{angle}.json` | Per-angle exploration results (1-4 files based on complexity) |
| `explorations-manifest.json` | Index of all exploration files |
| `planning-context.md` | Evidence paths + synthesized understanding |
| `plan.json` | Structured implementation plan (plan-json-schema.json) |
| `plan.json` | Plan overview with task_ids[] (plan-overview-base-schema.json) |
| `.task/TASK-*.json` | Independent task files (one per task) |
**Output Directory**: `.workflow/.lite-plan/{task-slug}-{YYYY-MM-DD}/`
@@ -52,7 +53,7 @@ Intelligent lightweight planning command with dynamic workflow adaptation based
- Low complexity → Direct Claude planning (no agent)
- Medium/High complexity → `cli-lite-planning-agent` generates `plan.json`
**Schema Reference**: `~/.ccw/workflows/cli-templates/schemas/plan-json-schema.json`
**Schema Reference**: `~/.ccw/workflows/cli-templates/schemas/plan-overview-base-schema.json`
## Auto Mode Defaults
@@ -89,7 +90,7 @@ Phase 2: Clarification (optional, multi-round)
Phase 3: Planning (NO CODE EXECUTION - planning only)
└─ Decision (based on Phase 1 complexity):
├─ Low → Load schema: cat ~/.ccw/workflows/cli-templates/schemas/plan-json-schema.json → Direct Claude planning (following schema) → plan.json
├─ Low → Load schema: cat ~/.ccw/workflows/cli-templates/schemas/plan-overview-base-schema.json → Direct Claude planning (following schema) → plan.json
└─ Medium/High → cli-lite-planning-agent → plan.json (agent internally executes quality check)
Phase 4: Confirmation & Selection
@@ -251,9 +252,13 @@ Execute **${angle}** exploration for task planning context. Analyze codebase fro
**Required Fields** (all ${angle} focused):
- project_structure: Modules/architecture relevant to ${angle}
- relevant_files: Files affected from ${angle} perspective
**IMPORTANT**: Use object format with relevance scores for synthesis:
\`[{path: "src/file.ts", relevance: 0.85, rationale: "Core ${angle} logic"}]\`
Scores: 0.7+ high priority, 0.5-0.7 medium, <0.5 low
**MANDATORY**: Every file MUST use structured object format with ALL required fields:
\`[{path: "src/file.ts", relevance: 0.85, rationale: "Contains AuthService.login() - entry point for JWT token generation", role: "modify_target", discovery_source: "bash-scan", key_symbols: ["AuthService", "login"]}]\`
- **rationale** (required): Specific selection basis tied to ${angle} topic (>10 chars, not generic)
- **role** (required): modify_target|dependency|pattern_reference|test_target|type_definition|integration_point|config|context_only
- **discovery_source** (recommended): bash-scan|cli-analysis|ace-search|dependency-trace|manual
- **key_symbols** (recommended): Key functions/classes/types in the file relevant to the task
- Scores: 0.7+ high priority, 0.5-0.7 medium, <0.5 low
- patterns: ${angle}-related patterns to follow
- dependencies: Dependencies relevant to ${angle}
- integration_points: Where to integrate from ${angle} viewpoint (include file:line locations)
@@ -264,7 +269,9 @@ Execute **${angle}** exploration for task planning context. Analyze codebase fro
## Success Criteria
- [ ] Schema obtained via cat explore-json-schema.json
- [ ] get_modules_by_depth.sh executed
- [ ] At least 3 relevant files identified with ${angle} rationale
- [ ] At least 3 relevant files identified with specific rationale + role
- [ ] Every file has rationale >10 chars (not generic like "Related to ${angle}")
- [ ] Every file has role classification (modify_target/dependency/etc.)
- [ ] Patterns are actionable (code examples, not generic advice)
- [ ] Integration points include file:line locations
- [ ] Constraints are project-specific to ${angle}
@@ -416,7 +423,11 @@ if (autoYes) {
// 2. 默认 → agent
const executorAssignments = {} // { taskId: { executor: 'gemini'|'codex'|'agent', reason: string } }
plan.tasks.forEach(task => {
// Load tasks from .task/ directory for executor assignment
const taskFiles = Glob(`${sessionFolder}/.task/TASK-*.json`)
taskFiles.forEach(taskPath => {
const task = JSON.parse(Read(taskPath))
// Claude 根据上述规则语义分析,为每个 task 分配 executor
executorAssignments[task.id] = { executor: '...', reason: '...' }
})
@@ -425,7 +436,7 @@ plan.tasks.forEach(task => {
**Low Complexity** - Direct planning by Claude:
```javascript
// Step 1: Read schema
const schema = Bash(`cat ~/.ccw/workflows/cli-templates/schemas/plan-json-schema.json`)
const schema = Bash(`cat ~/.ccw/workflows/cli-templates/schemas/plan-overview-base-schema.json`)
// Step 2: ⚠️ MANDATORY - Read and review ALL exploration files
const manifest = JSON.parse(Read(`${sessionFolder}/explorations-manifest.json`))
@@ -434,22 +445,51 @@ manifest.explorations.forEach(exp => {
console.log(`\n### Exploration: ${exp.angle}\n${explorationData}`)
})
// Step 3: Generate plan following schema (Claude directly, no agent)
// ⚠️ Plan MUST incorporate insights from exploration files read in Step 2
// Step 3: Generate task objects (Claude directly, no agent)
// ⚠️ Tasks MUST incorporate insights from exploration files read in Step 2
// Task fields use NEW names: convergence.criteria (not acceptance), files[].change (not modification_points), test (not verification)
const tasks = [
{
id: "TASK-001",
title: "...",
description: "...",
depends_on: [],
convergence: { criteria: ["..."] },
files: [{ path: "...", change: "..." }],
implementation: ["..."],
test: "..."
},
// ... more tasks
]
// Step 4: Write task files to .task/ directory
const taskDir = `${sessionFolder}/.task`
Bash(`mkdir -p "${taskDir}"`)
tasks.forEach(task => {
Write(`${taskDir}/${task.id}.json`, JSON.stringify(task, null, 2))
})
// Step 5: Generate plan overview (NO embedded tasks[])
const plan = {
summary: "...",
approach: "...",
tasks: [...], // Each task: { id, title, scope, ..., depends_on, execution_group, complexity }
task_ids: tasks.map(t => t.id),
task_count: tasks.length,
complexity: "Low",
estimated_time: "...",
recommended_execution: "Agent",
complexity: "Low",
_metadata: { timestamp: getUtc8ISOString(), source: "direct-planning", planning_mode: "direct" }
_metadata: {
timestamp: getUtc8ISOString(),
source: "direct-planning",
planning_mode: "direct",
plan_type: "feature"
}
}
// Step 4: Write plan to session folder
// Step 6: Write plan overview to session folder
Write(`${sessionFolder}/plan.json`, JSON.stringify(plan, null, 2))
// Step 5: MUST continue to Phase 4 (Confirmation) - DO NOT execute code here
// Step 7: MUST continue to Phase 4 (Confirmation) - DO NOT execute code here
```
**Medium/High Complexity** - Invoke cli-lite-planning-agent:
@@ -467,10 +507,11 @@ Generate implementation plan and write plan.json.
**Session Folder**: ${sessionFolder}
**Output Files**:
- ${sessionFolder}/planning-context.md (evidence + understanding)
- ${sessionFolder}/plan.json (implementation plan)
- ${sessionFolder}/plan.json (plan overview -- NO embedded tasks[])
- ${sessionFolder}/.task/TASK-*.json (independent task files, one per task)
## Output Schema Reference
Execute: cat ~/.ccw/workflows/cli-templates/schemas/plan-json-schema.json (get schema reference before generating plan)
Execute: cat ~/.ccw/workflows/cli-templates/schemas/plan-overview-base-schema.json (get schema reference before generating plan)
## Project Context (MANDATORY - Read Both Files)
1. Read: .workflow/project-tech.json (technology stack, architecture, key components)
@@ -500,10 +541,17 @@ ${JSON.stringify(clarificationContext) || "None"}
${complexity}
## Requirements
Generate plan.json following the schema obtained above. Key constraints:
- tasks: 2-7 structured tasks (**group by feature/module, NOT by file**)
Generate plan.json and .task/*.json following the schema obtained above. Key constraints:
- _metadata.exploration_angles: ${JSON.stringify(manifest.explorations.map(e => e.angle))}
**Output Format**: Two-layer structure:
- plan.json: Overview with task_ids[] referencing .task/ files (NO tasks[] array)
- .task/TASK-*.json: Independent task files following task-schema.json
plan.json required fields: summary, approach, task_ids, task_count, _metadata (with plan_type: "feature")
Each task file required fields: id, title, description, depends_on, convergence (with criteria[])
Task fields use: files[].change (not modification_points), convergence.criteria (not acceptance), test (not verification)
## Task Grouping Rules
1. **Group by feature**: All changes for one feature = one task (even if 3-5 files)
2. **Group by context**: Tasks with similar context or related functional changes can be grouped together
@@ -517,10 +565,12 @@ Generate plan.json following the schema obtained above. Key constraints:
1. Read schema file (cat command above)
2. Execute CLI planning using Gemini (Qwen fallback)
3. Read ALL exploration files for comprehensive context
4. Synthesize findings and generate plan following schema
4. Synthesize findings and generate tasks + plan overview
5. **Write**: \`${sessionFolder}/planning-context.md\` (evidence paths + understanding)
6. **Write**: \`${sessionFolder}/plan.json\`
7. Return brief completion summary
6. **Create**: \`${sessionFolder}/.task/\` directory (mkdir -p)
7. **Write**: \`${sessionFolder}/.task/TASK-001.json\`, \`TASK-002.json\`, etc. (one per task)
8. **Write**: \`${sessionFolder}/plan.json\` (overview with task_ids[], NO tasks[])
9. Return brief completion summary
`
)
```
@@ -535,14 +585,21 @@ Generate plan.json following the schema obtained above. Key constraints:
```javascript
const plan = JSON.parse(Read(`${sessionFolder}/plan.json`))
// Load tasks from .task/ directory
const tasks = (plan.task_ids || []).map(id => {
const taskPath = `${sessionFolder}/.task/${id}.json`
return JSON.parse(Read(taskPath))
})
const taskList = tasks
console.log(`
## Implementation Plan
**Summary**: ${plan.summary}
**Approach**: ${plan.approach}
**Tasks** (${plan.tasks.length}):
${plan.tasks.map((t, i) => `${i+1}. ${t.title} (${t.file})`).join('\n')}
**Tasks** (${taskList.length}):
${taskList.map((t, i) => `${i+1}. ${t.title} (${t.scope || t.files?.[0]?.path || ''})`).join('\n')}
**Complexity**: ${plan.complexity}
**Estimated Time**: ${plan.estimated_time}
@@ -575,7 +632,7 @@ if (autoYes) {
userSelection = AskUserQuestion({
questions: [
{
question: `Confirm plan? (${plan.tasks.length} tasks, ${plan.complexity})`,
question: `Confirm plan? (${taskList.length} tasks, ${plan.complexity})`,
header: "Confirm",
multiSelect: false,
options: [
@@ -632,7 +689,11 @@ manifest.explorations.forEach(exp => {
const plan = JSON.parse(Read(`${sessionFolder}/plan.json`))
executionContext = {
planObject: plan,
planObject: plan, // plan overview (no tasks[])
taskFiles: (plan.task_ids || []).map(id => ({
id,
path: `${sessionFolder}/.task/${id}.json`
})),
explorationsContext: explorations,
explorationAngles: manifest.explorations.map(e => e.angle),
explorationManifest: manifest,
@@ -653,7 +714,8 @@ executionContext = {
path: exp.path
})),
explorations_manifest: `${sessionFolder}/explorations-manifest.json`,
plan: `${sessionFolder}/plan.json`
plan: `${sessionFolder}/plan.json`,
task_dir: `${sessionFolder}/.task`
}
}
}
@@ -674,7 +736,12 @@ Skill(skill="workflow:lite-execute", args="--in-memory")
├── exploration-{angle3}.json # Exploration angle 3 (if applicable)
├── exploration-{angle4}.json # Exploration angle 4 (if applicable)
├── explorations-manifest.json # Exploration index
── plan.json # Implementation plan
── planning-context.md # Evidence paths + understanding
├── plan.json # Plan overview (task_ids[])
└── .task/ # Task files directory
├── TASK-001.json
├── TASK-002.json
└── ...
```
**Example**:
@@ -684,7 +751,12 @@ Skill(skill="workflow:lite-execute", args="--in-memory")
├── exploration-auth-patterns.json
├── exploration-security.json
├── explorations-manifest.json
── plan.json
── planning-context.md
├── plan.json
└── .task/
├── TASK-001.json
├── TASK-002.json
└── TASK-003.json
```
## Error Handling

View File

@@ -164,9 +164,13 @@ Execute **${angle}** exploration for task planning context. Analyze codebase fro
**Required Fields** (all ${angle} focused):
- project_structure: Modules/architecture relevant to ${angle}
- relevant_files: Files affected from ${angle} perspective
**IMPORTANT**: Use object format with relevance scores for synthesis:
\`[{path: "src/file.ts", relevance: 0.85, rationale: "Core ${angle} logic"}]\`
Scores: 0.7+ high priority, 0.5-0.7 medium, <0.5 low
**MANDATORY**: Every file MUST use structured object format with ALL required fields:
\`[{path: "src/file.ts", relevance: 0.85, rationale: "Contains AuthService.login() - entry point for JWT token generation", role: "modify_target", discovery_source: "bash-scan", key_symbols: ["AuthService", "login"]}]\`
- **rationale** (required): Specific selection basis tied to ${angle} topic (>10 chars, not generic)
- **role** (required): modify_target|dependency|pattern_reference|test_target|type_definition|integration_point|config|context_only
- **discovery_source** (recommended): bash-scan|cli-analysis|ace-search|dependency-trace|manual
- **key_symbols** (recommended): Key functions/classes/types in the file relevant to the task
- Scores: 0.7+ high priority, 0.5-0.7 medium, <0.5 low
- patterns: ${angle}-related patterns to follow
- dependencies: Dependencies relevant to ${angle}
- integration_points: Where to integrate from ${angle} viewpoint (include file:line locations)