mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-15 02:42:45 +08:00
fix: add nullish fallback for dynamic statusLabelKeys lookup in formatMessage
Prevents @formatjs/intl crash when session.status has an unexpected value not present in the statusLabelKeys map, causing formatMessage to receive undefined as the id.
This commit is contained in:
@@ -129,8 +129,8 @@
|
|||||||
},
|
},
|
||||||
"source": {
|
"source": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["cli-lite-planning-agent", "direct-planning"],
|
"enum": ["cli-lite-planning-agent", "direct-planning", "action-planning-agent", "review-cycle-agent", "issue-plan-agent", "tdd-planning-agent"],
|
||||||
"description": "规划来源"
|
"description": "规划来源 — 标识产生此 plan 的实际规划引擎"
|
||||||
},
|
},
|
||||||
"planning_mode": {
|
"planning_mode": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ The key innovation is the **Plan Note** architecture — a shared collaborative
|
|||||||
│ │ ├── TASK-101.json
|
│ │ ├── TASK-101.json
|
||||||
│ │ └── ...
|
│ │ └── ...
|
||||||
│ └── ...
|
│ └── ...
|
||||||
|
├── plan.json # Plan overview (plan-overview-base-schema.json)
|
||||||
├── .task/ # ⭐ Merged task JSON files (all domains)
|
├── .task/ # ⭐ Merged task JSON files (all domains)
|
||||||
│ ├── TASK-001.json
|
│ ├── TASK-001.json
|
||||||
│ ├── TASK-101.json
|
│ ├── TASK-101.json
|
||||||
@@ -133,6 +134,7 @@ The key innovation is the **Plan Note** architecture — a shared collaborative
|
|||||||
| Artifact | Purpose |
|
| Artifact | Purpose |
|
||||||
|----------|---------|
|
|----------|---------|
|
||||||
| `.task/TASK-*.json` | Merged task JSON files from all domains (consumable by unified-execute) |
|
| `.task/TASK-*.json` | Merged task JSON files from all domains (consumable by unified-execute) |
|
||||||
|
| `plan.json` | Plan overview following plan-overview-base-schema.json |
|
||||||
| `plan.md` | Human-readable summary with requirements, tasks, and conflicts |
|
| `plan.md` | Human-readable summary with requirements, tasks, and conflicts |
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -575,7 +577,41 @@ for (const sub of subDomains) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Step 4.2: Generate plan.md
|
### Step 4.2: Generate plan.json
|
||||||
|
|
||||||
|
Generate a plan overview following the plan-overview-base-schema.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Generate plan.json (plan-overview-base-schema)
|
||||||
|
const allTaskFiles = Glob(`${sessionFolder}/.task/TASK-*.json`)
|
||||||
|
const taskIds = allTaskFiles.map(f => JSON.parse(Read(f)).id).sort()
|
||||||
|
|
||||||
|
// Guard: skip plan.json if no tasks generated
|
||||||
|
if (taskIds.length === 0) {
|
||||||
|
console.warn('No tasks generated; skipping plan.json')
|
||||||
|
} else {
|
||||||
|
|
||||||
|
const planOverview = {
|
||||||
|
summary: `Collaborative plan for: ${taskDescription}`,
|
||||||
|
approach: `Multi-domain planning across ${subDomains.length} sub-domains: ${subDomains.map(s => s.focus_area).join(', ')}`,
|
||||||
|
task_ids: taskIds,
|
||||||
|
task_count: taskIds.length,
|
||||||
|
complexity: complexity,
|
||||||
|
recommended_execution: "Agent",
|
||||||
|
_metadata: {
|
||||||
|
timestamp: getUtc8ISOString(),
|
||||||
|
source: "direct-planning",
|
||||||
|
planning_mode: "direct",
|
||||||
|
plan_type: "collaborative",
|
||||||
|
schema_version: "2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Write(`${sessionFolder}/plan.json`, JSON.stringify(planOverview, null, 2))
|
||||||
|
|
||||||
|
} // end guard
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4.3: Generate plan.md
|
||||||
|
|
||||||
Create a human-readable summary from plan-note.md content.
|
Create a human-readable summary from plan-note.md content.
|
||||||
|
|
||||||
@@ -634,7 +670,7 @@ ${allConflicts.length === 0
|
|||||||
Write(`${sessionFolder}/plan.md`, planMd)
|
Write(`${sessionFolder}/plan.md`, planMd)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Step 4.3: Display Completion Summary
|
### Step 4.4: Display Completion Summary
|
||||||
|
|
||||||
Present session statistics and next steps.
|
Present session statistics and next steps.
|
||||||
|
|
||||||
|
|||||||
@@ -157,7 +157,8 @@ Phase Execution (load one phase):
|
|||||||
|
|
||||||
Post-Phase:
|
Post-Phase:
|
||||||
├─ Export to Task JSON (optional, with --export-tasks flag)
|
├─ Export to Task JSON (optional, with --export-tasks flag)
|
||||||
│ └─ For each solution.tasks[] → write .task/TASK-{T-id}.json
|
│ ├─ For each solution.tasks[] → write .task/TASK-{T-id}.json
|
||||||
|
│ └─ Generate plan.json (plan-overview-base-schema) from exported tasks
|
||||||
└─ Summary + Next steps recommendation
|
└─ Summary + Next steps recommendation
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -292,7 +293,36 @@ User Input (issue IDs / artifact path / session ID / flags)
|
|||||||
│ └─ solution.task.priority → priority (1→critical, 2→high, 3→medium, 4-5→low)
|
│ └─ solution.task.priority → priority (1→critical, 2→high, 3→medium, 4-5→low)
|
||||||
├─ Output path: .workflow/issues/{issue-id}/.task/TASK-{T-id}.json
|
├─ Output path: .workflow/issues/{issue-id}/.task/TASK-{T-id}.json
|
||||||
├─ Each file follows task-schema.json (IDENTITY + CONVERGENCE + FILES required)
|
├─ Each file follows task-schema.json (IDENTITY + CONVERGENCE + FILES required)
|
||||||
└─ source.tool = "issue-resolve", source.issue_id = {issue-id}
|
├─ source.tool = "issue-resolve", source.issue_id = {issue-id}
|
||||||
|
│
|
||||||
|
└─ Generate plan.json (after all TASK-*.json exported):
|
||||||
|
const issueDir = `.workflow/issues/${issueId}`
|
||||||
|
const taskFiles = Glob(`${issueDir}/.task/TASK-*.json`)
|
||||||
|
const taskIds = taskFiles.map(f => JSON.parse(Read(f)).id).sort()
|
||||||
|
|
||||||
|
// Guard: skip plan.json if no tasks generated
|
||||||
|
if (taskIds.length === 0) {
|
||||||
|
console.warn('No tasks generated; skipping plan.json')
|
||||||
|
} else {
|
||||||
|
|
||||||
|
const planOverview = {
|
||||||
|
summary: `Issue resolution plan for ${issueId}: ${issueTitle}`,
|
||||||
|
approach: solution.approach || "AI-explored resolution strategy",
|
||||||
|
task_ids: taskIds,
|
||||||
|
task_count: taskIds.length,
|
||||||
|
complexity: taskIds.length > 5 ? "High" : taskIds.length > 2 ? "Medium" : "Low",
|
||||||
|
_metadata: {
|
||||||
|
timestamp: getUtc8ISOString(),
|
||||||
|
source: "issue-plan-agent",
|
||||||
|
planning_mode: "agent-based",
|
||||||
|
plan_type: "feature",
|
||||||
|
schema_version: "2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Write(`${issueDir}/plan.json`, JSON.stringify(planOverview, null, 2))
|
||||||
|
|
||||||
|
} // end guard
|
||||||
|
Output path: .workflow/issues/{issue-id}/plan.json
|
||||||
```
|
```
|
||||||
|
|
||||||
## Task Tracking Pattern
|
## Task Tracking Pattern
|
||||||
|
|||||||
@@ -36,14 +36,16 @@ Converts any planning artifact to **`.task/*.json` multi-file format** — the s
|
|||||||
**Producer 使用的字段集** (plan-converter 输出):
|
**Producer 使用的字段集** (plan-converter 输出):
|
||||||
|
|
||||||
```
|
```
|
||||||
IDENTITY (必填): id, title, description
|
IDENTITY (必填): id, title, description
|
||||||
CLASSIFICATION (可选): type, priority, effort
|
CLASSIFICATION (可选): type, priority, effort, action
|
||||||
SCOPE (可选): scope, excludes
|
SCOPE (可选): scope, excludes, focus_paths
|
||||||
DEPENDENCIES (必填): depends_on, parallel_group, inputs, outputs
|
DEPENDENCIES (必填): depends_on, parallel_group, inputs, outputs
|
||||||
CONVERGENCE (必填): convergence.criteria, convergence.verification, convergence.definition_of_done
|
CONVERGENCE (必填): convergence.criteria, convergence.verification, convergence.definition_of_done
|
||||||
FILES (可选): files[].path, files[].action, files[].changes, files[].conflict_risk
|
FILES (可选): files[].path, files[].action, files[].changes, files[].change, files[].target, files[].conflict_risk
|
||||||
CONTEXT (可选): source.tool, source.session_id, source.original_id, evidence, risk_items
|
IMPLEMENTATION (可选): implementation[], test.manual_checks, test.success_metrics
|
||||||
RUNTIME (执行时填充): status, executed_at, result
|
PLANNING (可选): reference, rationale, risks
|
||||||
|
CONTEXT (可选): source.tool, source.session_id, source.original_id, evidence, risk_items
|
||||||
|
RUNTIME (执行时填充): status, executed_at, result
|
||||||
```
|
```
|
||||||
|
|
||||||
**文件命名**: `TASK-{id}.json` (保留原有 ID 前缀: L0-, T1-, IDEA- 等)
|
**文件命名**: `TASK-{id}.json` (保留原有 ID 前缀: L0-, T1-, IDEA- 等)
|
||||||
@@ -237,7 +239,9 @@ function transformPlanNote(parsed) {
|
|||||||
files: task.files?.map(f => ({
|
files: task.files?.map(f => ({
|
||||||
path: f.path || f.file,
|
path: f.path || f.file,
|
||||||
action: f.action || 'modify',
|
action: f.action || 'modify',
|
||||||
changes: f.changes || [f.change],
|
changes: f.changes || (f.change ? [f.change] : undefined),
|
||||||
|
change: f.change,
|
||||||
|
target: f.target,
|
||||||
conflict_risk: f.conflict_risk
|
conflict_risk: f.conflict_risk
|
||||||
})),
|
})),
|
||||||
source: {
|
source: {
|
||||||
|
|||||||
@@ -173,6 +173,47 @@ Phase 7.5: Export to Task JSON (auto with --fix, or explicit --export-tasks)
|
|||||||
├─ Output path: {projectRoot}/.workflow/active/WFS-{id}/.review/.task/FIX-{seq}.json
|
├─ Output path: {projectRoot}/.workflow/active/WFS-{id}/.review/.task/FIX-{seq}.json
|
||||||
├─ Each file follows task-schema.json (IDENTITY + CONVERGENCE + FILES required)
|
├─ Each file follows task-schema.json (IDENTITY + CONVERGENCE + FILES required)
|
||||||
└─ source.tool = "review-cycle", source.session_id = WFS-{id}
|
└─ source.tool = "review-cycle", source.session_id = WFS-{id}
|
||||||
|
│
|
||||||
|
├─ Generate plan.json (plan-overview-fix-schema) after FIX task export:
|
||||||
|
│ ```javascript
|
||||||
|
│ const fixTaskFiles = Glob(`${reviewDir}/.task/FIX-*.json`)
|
||||||
|
│ const taskIds = fixTaskFiles.map(f => JSON.parse(Read(f)).id).sort()
|
||||||
|
│
|
||||||
|
│ // Guard: skip plan.json if no fix tasks generated
|
||||||
|
│ if (taskIds.length === 0) {
|
||||||
|
│ console.warn('No fix tasks generated; skipping plan.json')
|
||||||
|
│ } else {
|
||||||
|
│
|
||||||
|
│ const planOverview = {
|
||||||
|
│ summary: `Fix plan from review cycle: ${reviewSummary}`,
|
||||||
|
│ approach: "Review-driven fix pipeline",
|
||||||
|
│ task_ids: taskIds,
|
||||||
|
│ task_count: taskIds.length,
|
||||||
|
│ complexity: taskIds.length > 5 ? "High" : taskIds.length > 2 ? "Medium" : "Low",
|
||||||
|
│ fix_context: {
|
||||||
|
│ root_cause: "Multiple review findings",
|
||||||
|
│ strategy: "comprehensive_fix",
|
||||||
|
│ severity: aggregatedFindings.maxSeverity || "Medium", // Derived from max finding severity
|
||||||
|
│ risk_level: aggregatedFindings.overallRisk || "medium" // Derived from combined risk assessment
|
||||||
|
│ },
|
||||||
|
│ test_strategy: {
|
||||||
|
│ scope: "unit",
|
||||||
|
│ specific_tests: [],
|
||||||
|
│ manual_verification: ["Verify all review findings addressed"]
|
||||||
|
│ },
|
||||||
|
│ _metadata: {
|
||||||
|
│ timestamp: getUtc8ISOString(),
|
||||||
|
│ source: "review-cycle-agent",
|
||||||
|
│ planning_mode: "agent-based",
|
||||||
|
│ plan_type: "fix",
|
||||||
|
│ schema_version: "2.0"
|
||||||
|
│ }
|
||||||
|
│ }
|
||||||
|
│ Write(`${reviewDir}/plan.json`, JSON.stringify(planOverview, null, 2))
|
||||||
|
│
|
||||||
|
│ } // end guard
|
||||||
|
│ ```
|
||||||
|
└─ Output path: {reviewDir}/plan.json
|
||||||
|
|
||||||
Phase 8: Fix Execution
|
Phase 8: Fix Execution
|
||||||
└─ Ref: phases/08-fix-execution.md
|
└─ Ref: phases/08-fix-execution.md
|
||||||
@@ -409,6 +450,7 @@ Gemini → Qwen → Codex → degraded mode
|
|||||||
│ ├── FIX-001.json # Per-finding task (task-schema.json)
|
│ ├── FIX-001.json # Per-finding task (task-schema.json)
|
||||||
│ ├── FIX-002.json
|
│ ├── FIX-002.json
|
||||||
│ └── ...
|
│ └── ...
|
||||||
|
├── plan.json # Plan overview (plan-overview-fix-schema, Phase 7.5)
|
||||||
└── fixes/{fix-session-id}/ # Fix results (Phase 6-9)
|
└── fixes/{fix-session-id}/ # Fix results (Phase 6-9)
|
||||||
├── partial-plan-*.json
|
├── partial-plan-*.json
|
||||||
├── fix-plan.json
|
├── fix-plan.json
|
||||||
|
|||||||
@@ -210,6 +210,14 @@ tasks.forEach((task, i) => {
|
|||||||
if (task.flow_control.target_files && !Array.isArray(task.flow_control.target_files))
|
if (task.flow_control.target_files && !Array.isArray(task.flow_control.target_files))
|
||||||
errors.push(`${task.id}: flow_control.target_files must be array`)
|
errors.push(`${task.id}: flow_control.target_files must be array`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New unified schema fields (backward compatible addition)
|
||||||
|
if (task.focus_paths && !Array.isArray(task.focus_paths))
|
||||||
|
errors.push(`${task.id}: focus_paths must be array`)
|
||||||
|
if (task.implementation && !Array.isArray(task.implementation))
|
||||||
|
errors.push(`${task.id}: implementation must be array`)
|
||||||
|
if (task.files && !Array.isArray(task.files))
|
||||||
|
errors.push(`${task.id}: files must be array`)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (errors.length) {
|
if (errors.length) {
|
||||||
@@ -435,6 +443,12 @@ ${task.convergence.criteria.map(c => `- [ ] ${c}`).join('\n')}
|
|||||||
// - Use Grep/Glob/mcp__ace-tool for discovery if needed
|
// - Use Grep/Glob/mcp__ace-tool for discovery if needed
|
||||||
// - Use Bash for build/test commands
|
// - Use Bash for build/test commands
|
||||||
|
|
||||||
|
// Dual-path field access (supports both unified and legacy 6-field schema)
|
||||||
|
// const targetFiles = task.files?.map(f => f.path) || task.flow_control?.target_files || []
|
||||||
|
// const acceptanceCriteria = task.convergence?.criteria || task.context?.acceptance || []
|
||||||
|
// const requirements = task.implementation || task.context?.requirements || []
|
||||||
|
// const focusPaths = task.focus_paths || task.context?.focus_paths || []
|
||||||
|
|
||||||
// 4. Verify convergence
|
// 4. Verify convergence
|
||||||
const convergenceResults = verifyConvergence(task)
|
const convergenceResults = verifyConvergence(task)
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ allowed-tools: AskUserQuestion, Read, Write, Edit, Bash, Glob, Grep, mcp__ace-to
|
|||||||
|
|
||||||
# Planning Workflow
|
# Planning Workflow
|
||||||
|
|
||||||
Lite Plan produces `.task/TASK-*.json` (one file per task) implementation plan via serial CLI exploration and direct planning, then hands off to unified-execute-with-file for task execution.
|
Lite Plan produces `plan.json` (plan overview) + `.task/TASK-*.json` (one file per task) implementation plan via serial CLI exploration and direct planning, then hands off to unified-execute-with-file for task execution.
|
||||||
|
|
||||||
> **Schema**: `cat ~/.ccw/workflows/cli-templates/schemas/task-schema.json`
|
> **Schema**: `cat ~/.ccw/workflows/cli-templates/schemas/task-schema.json`
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ Read('phases/02-lite-execute.md')
|
|||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Phase 1 produces `.task/TASK-*.json` (one file per task) — compatible with `collaborative-plan-with-file` and consumable by `unified-execute-with-file`.
|
Phase 1 produces `plan.json` (plan overview, following `plan-overview-base-schema.json`) + `.task/TASK-*.json` (one file per task) — compatible with `collaborative-plan-with-file` and consumable by `unified-execute-with-file`.
|
||||||
|
|
||||||
> **Schema**: `cat ~/.ccw/workflows/cli-templates/schemas/task-schema.json`
|
> **Schema**: `cat ~/.ccw/workflows/cli-templates/schemas/task-schema.json`
|
||||||
|
|
||||||
@@ -104,7 +104,8 @@ Phase 1 produces `.task/TASK-*.json` (one file per task) — compatible with `co
|
|||||||
├── explorations-manifest.json # Exploration index
|
├── explorations-manifest.json # Exploration index
|
||||||
├── exploration-notes.md # Synthesized exploration notes
|
├── exploration-notes.md # Synthesized exploration notes
|
||||||
├── requirement-analysis.json # Complexity assessment
|
├── requirement-analysis.json # Complexity assessment
|
||||||
├── .task/ # ⭐ Task JSON files (one per task)
|
├── plan.json # ⭐ Plan overview (plan-overview-base-schema.json)
|
||||||
|
├── .task/ # Task JSON files (one per task)
|
||||||
│ ├── TASK-001.json # Individual task definition
|
│ ├── TASK-001.json # Individual task definition
|
||||||
│ ├── TASK-002.json
|
│ ├── TASK-002.json
|
||||||
│ └── ...
|
│ └── ...
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ Serial lightweight planning with CLI-powered exploration and search verification
|
|||||||
| `explorations-manifest.json` | Index of all exploration files |
|
| `explorations-manifest.json` | Index of all exploration files |
|
||||||
| `exploration-notes.md` | Synthesized exploration notes (all angles combined) |
|
| `exploration-notes.md` | Synthesized exploration notes (all angles combined) |
|
||||||
| `requirement-analysis.json` | Complexity assessment and session metadata |
|
| `requirement-analysis.json` | Complexity assessment and session metadata |
|
||||||
|
| `plan.json` | Plan overview (plan-overview-base-schema) |
|
||||||
| `.task/TASK-*.json` | Multi-file task output (one JSON file per task) |
|
| `.task/TASK-*.json` | Multi-file task output (one JSON file per task) |
|
||||||
| `plan.md` | Human-readable summary with execution command |
|
| `plan.md` | Human-readable summary with execution command |
|
||||||
|
|
||||||
@@ -417,6 +418,38 @@ tasks.forEach(task => {
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Step 3.3.5: Generate plan.json (plan-overview-base-schema)
|
||||||
|
|
||||||
|
Generate plan overview as structured index for `.task/` directory:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Guard: skip plan.json if no tasks generated
|
||||||
|
if (tasks.length === 0) {
|
||||||
|
console.warn('No tasks generated; skipping plan.json')
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Build plan overview following plan-overview-base-schema.json
|
||||||
|
const planOverview = {
|
||||||
|
summary: requirementUnderstanding, // 2-3 sentence overview from exploration synthesis
|
||||||
|
approach: approach, // High-level implementation strategy
|
||||||
|
task_ids: tasks.map(t => t.id), // ["TASK-001", "TASK-002", ...]
|
||||||
|
task_count: tasks.length,
|
||||||
|
complexity: complexity, // "Low" | "Medium" | "High"
|
||||||
|
recommended_execution: "Agent",
|
||||||
|
_metadata: {
|
||||||
|
timestamp: getUtc8ISOString(),
|
||||||
|
source: "direct-planning",
|
||||||
|
planning_mode: "direct",
|
||||||
|
plan_type: "feature",
|
||||||
|
schema_version: "2.0",
|
||||||
|
exploration_angles: selectedAngles
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Write(`${sessionFolder}/plan.json`, JSON.stringify(planOverview, null, 2))
|
||||||
|
|
||||||
|
} // end guard
|
||||||
|
```
|
||||||
|
|
||||||
#### Step 3.4: Generate plan.md
|
#### Step 3.4: Generate plan.md
|
||||||
|
|
||||||
Create human-readable summary:
|
Create human-readable summary:
|
||||||
@@ -514,7 +547,8 @@ Read `{sessionFolder}/.task/` directory and display summary:
|
|||||||
├── explorations-manifest.json # Exploration index
|
├── explorations-manifest.json # Exploration index
|
||||||
├── exploration-notes.md # Synthesized exploration notes
|
├── exploration-notes.md # Synthesized exploration notes
|
||||||
├── requirement-analysis.json # Complexity assessment
|
├── requirement-analysis.json # Complexity assessment
|
||||||
├── .task/ # ⭐ Task JSON files (one per task)
|
├── plan.json # ⭐ Plan overview (plan-overview-base-schema.json)
|
||||||
|
├── .task/ # Task JSON files (one per task)
|
||||||
│ ├── TASK-001.json
|
│ ├── TASK-001.json
|
||||||
│ ├── TASK-002.json
|
│ ├── TASK-002.json
|
||||||
│ └── ...
|
│ └── ...
|
||||||
@@ -530,6 +564,7 @@ Read `{sessionFolder}/.task/` directory and display summary:
|
|||||||
├── explorations-manifest.json
|
├── explorations-manifest.json
|
||||||
├── exploration-notes.md
|
├── exploration-notes.md
|
||||||
├── requirement-analysis.json
|
├── requirement-analysis.json
|
||||||
|
├── plan.json
|
||||||
├── .task/
|
├── .task/
|
||||||
│ ├── TASK-001.json
|
│ ├── TASK-001.json
|
||||||
│ ├── TASK-002.json
|
│ ├── TASK-002.json
|
||||||
|
|||||||
@@ -76,8 +76,8 @@ Phase 2: Context Gathering & Conflict Resolution
|
|||||||
|
|
||||||
Phase 3: Task Generation
|
Phase 3: Task Generation
|
||||||
└─ Ref: phases/03-task-generation.md
|
└─ Ref: phases/03-task-generation.md
|
||||||
└─ Output: IMPL_PLAN.md, task JSONs, TODO_LIST.md
|
└─ Output: plan.json, IMPL_PLAN.md, task JSONs, TODO_LIST.md
|
||||||
└─ Schema: .task/IMPL-*.json follows 6-field superset of task-schema.json
|
└─ Schema: plan.json follows plan-overview-base-schema.json; .task/IMPL-*.json follows task-schema.json
|
||||||
|
|
||||||
User Decision (or --yes auto):
|
User Decision (or --yes auto):
|
||||||
└─ "Start Execution" → Phase 4
|
└─ "Start Execution" → Phase 4
|
||||||
@@ -225,7 +225,7 @@ Phase 2: context-gather --session sessionId "structured-description"
|
|||||||
↓
|
↓
|
||||||
Phase 3: task-generate-agent --session sessionId
|
Phase 3: task-generate-agent --session sessionId
|
||||||
↓ Input: sessionId + planning-notes.md + context-package.json + brainstorm artifacts
|
↓ Input: sessionId + planning-notes.md + context-package.json + brainstorm artifacts
|
||||||
↓ Output: IMPL_PLAN.md, task JSONs, TODO_LIST.md
|
↓ Output: plan.json, IMPL_PLAN.md, task JSONs, TODO_LIST.md
|
||||||
↓
|
↓
|
||||||
User Decision: "Start Execution" / --yes auto
|
User Decision: "Start Execution" / --yes auto
|
||||||
↓
|
↓
|
||||||
|
|||||||
@@ -179,6 +179,7 @@ const userConfig = {
|
|||||||
│ ├── IMPL-A2.json
|
│ ├── IMPL-A2.json
|
||||||
│ ├── IMPL-B1.json
|
│ ├── IMPL-B1.json
|
||||||
│ └── ...
|
│ └── ...
|
||||||
|
├── plan.json # Output: Plan overview (plan-overview-base-schema.json)
|
||||||
├── IMPL_PLAN.md # Output: Implementation plan (grouped by module)
|
├── IMPL_PLAN.md # Output: Implementation plan (grouped by module)
|
||||||
└── TODO_LIST.md # Output: TODO list (hierarchical)
|
└── TODO_LIST.md # Output: TODO list (hierarchical)
|
||||||
```
|
```
|
||||||
@@ -741,9 +742,44 @@ function resolveCrossModuleDependency(placeholder, allTasks) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Generate plan.json (plan-overview-base-schema)
|
||||||
|
|
||||||
|
After all task JSONs and IMPL_PLAN.md are generated (both single-agent and multi-module paths), generate `plan.json` as structured index:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Scan generated task files
|
||||||
|
const taskFiles = Glob(`${sessionFolder}/.task/IMPL-*.json`)
|
||||||
|
const taskIds = taskFiles.map(f => JSON.parse(Read(f)).id).sort()
|
||||||
|
|
||||||
|
// Guard: skip plan.json if no tasks generated
|
||||||
|
if (taskIds.length === 0) {
|
||||||
|
console.warn('No tasks generated; skipping plan.json')
|
||||||
|
} else {
|
||||||
|
|
||||||
|
const planOverview = {
|
||||||
|
summary: implPlanSummary, // From IMPL_PLAN.md overview section
|
||||||
|
approach: implPlanApproach, // From IMPL_PLAN.md approach/strategy
|
||||||
|
task_ids: taskIds, // ["IMPL-001", "IMPL-002", ...] or ["IMPL-A1", "IMPL-B1", ...]
|
||||||
|
task_count: taskIds.length,
|
||||||
|
complexity: complexity, // From Phase 1 assessment
|
||||||
|
recommended_execution: userConfig.executionMethod === "cli" ? "Codex" : "Agent",
|
||||||
|
_metadata: {
|
||||||
|
timestamp: getUtc8ISOString(),
|
||||||
|
source: "action-planning-agent",
|
||||||
|
planning_mode: "agent-based",
|
||||||
|
plan_type: "feature",
|
||||||
|
schema_version: "2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Write(`${sessionFolder}/plan.json`, JSON.stringify(planOverview, null, 2))
|
||||||
|
|
||||||
|
} // end guard
|
||||||
|
```
|
||||||
|
|
||||||
## Output
|
## Output
|
||||||
|
|
||||||
- **Files**:
|
- **Files**:
|
||||||
|
- `{projectRoot}/.workflow/active/{sessionId}/plan.json`
|
||||||
- `{projectRoot}/.workflow/active/{sessionId}/IMPL_PLAN.md`
|
- `{projectRoot}/.workflow/active/{sessionId}/IMPL_PLAN.md`
|
||||||
- `{projectRoot}/.workflow/active/{sessionId}/.task/IMPL-*.json`
|
- `{projectRoot}/.workflow/active/{sessionId}/.task/IMPL-*.json`
|
||||||
- `{projectRoot}/.workflow/active/{sessionId}/TODO_LIST.md`
|
- `{projectRoot}/.workflow/active/{sessionId}/TODO_LIST.md`
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ Phase 5: TDD Task Generation ← ATTACHED (3 tasks)
|
|||||||
├─ Phase 5.1: Discovery - analyze TDD requirements
|
├─ Phase 5.1: Discovery - analyze TDD requirements
|
||||||
├─ Phase 5.2: Planning - design Red-Green-Refactor cycles
|
├─ Phase 5.2: Planning - design Red-Green-Refactor cycles
|
||||||
└─ Phase 5.3: Output - generate IMPL tasks with internal TDD phases
|
└─ Phase 5.3: Output - generate IMPL tasks with internal TDD phases
|
||||||
└─ Output: IMPL-*.json, IMPL_PLAN.md ← COLLAPSED
|
└─ Output: IMPL-*.json, IMPL_PLAN.md, plan.json ← COLLAPSED
|
||||||
└─ Schema: .task/IMPL-*.json follows 6-field superset of task-schema.json
|
└─ Schema: .task/IMPL-*.json follows 6-field superset of task-schema.json
|
||||||
|
|
||||||
Phase 6: TDD Structure Validation (inline)
|
Phase 6: TDD Structure Validation (inline)
|
||||||
@@ -486,6 +486,45 @@ Read and execute: `phases/02-task-generate-tdd.md` with `--session [sessionId]`
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Step 5.4: Generate plan.json** (plan-overview-base-schema)
|
||||||
|
|
||||||
|
After task generation completes, generate `plan.json` as a machine-readable plan overview:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Generate plan.json after task generation
|
||||||
|
const sessionFolder = `${projectRoot}/.workflow/active/${sessionId}`
|
||||||
|
const taskFiles = Glob(`${sessionFolder}/.task/IMPL-*.json`)
|
||||||
|
const taskIds = taskFiles.map(f => JSON.parse(Read(f)).id).sort()
|
||||||
|
|
||||||
|
// Guard: skip plan.json if no tasks generated
|
||||||
|
if (taskIds.length === 0) {
|
||||||
|
console.warn('No tasks generated; skipping plan.json')
|
||||||
|
} else {
|
||||||
|
|
||||||
|
const planOverview = {
|
||||||
|
summary: `TDD plan for: ${taskDescription}`,
|
||||||
|
approach: `Red-Green-Refactor cycles across ${taskIds.length} implementation tasks`,
|
||||||
|
task_ids: taskIds,
|
||||||
|
task_count: taskIds.length,
|
||||||
|
complexity: complexity,
|
||||||
|
recommended_execution: "Agent",
|
||||||
|
_metadata: {
|
||||||
|
timestamp: getUtc8ISOString(),
|
||||||
|
source: "tdd-planning-agent",
|
||||||
|
planning_mode: "agent-based",
|
||||||
|
plan_type: "tdd",
|
||||||
|
schema_version: "2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Write(`${sessionFolder}/plan.json`, JSON.stringify(planOverview, null, 2))
|
||||||
|
|
||||||
|
} // end guard
|
||||||
|
```
|
||||||
|
|
||||||
|
**Validate**: `plan.json` exists and contains valid JSON with `task_ids` matching generated IMPL-*.json files.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### Phase 6: TDD Structure Validation & Action Plan Verification (RECOMMENDED)
|
### Phase 6: TDD Structure Validation & Action Plan Verification (RECOMMENDED)
|
||||||
|
|
||||||
**Internal validation first, then recommend external verification**
|
**Internal validation first, then recommend external verification**
|
||||||
@@ -528,7 +567,7 @@ Warning TDD Red Flag: [issue description]
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Verify session artifacts exist
|
# Verify session artifacts exist
|
||||||
ls -la ${projectRoot}/.workflow/active/[sessionId]/{IMPL_PLAN.md,TODO_LIST.md}
|
ls -la ${projectRoot}/.workflow/active/[sessionId]/{IMPL_PLAN.md,TODO_LIST.md,plan.json}
|
||||||
ls -la ${projectRoot}/.workflow/active/[sessionId]/.task/IMPL-*.json
|
ls -la ${projectRoot}/.workflow/active/[sessionId]/.task/IMPL-*.json
|
||||||
|
|
||||||
# Count generated artifacts
|
# Count generated artifacts
|
||||||
@@ -543,6 +582,7 @@ jq '{id, tdd: .meta.tdd_workflow, cli_id: .meta.cli_execution_id, phases: [.flow
|
|||||||
| Evidence Type | Verification Method | Pass Criteria |
|
| Evidence Type | Verification Method | Pass Criteria |
|
||||||
|---------------|---------------------|---------------|
|
|---------------|---------------------|---------------|
|
||||||
| File existence | `ls -la` artifacts | All files present |
|
| File existence | `ls -la` artifacts | All files present |
|
||||||
|
| Plan overview | `jq .task_count plan.json` | plan.json exists with valid task_ids |
|
||||||
| Task count | Count IMPL-*.json | Count matches claims (<=18) |
|
| Task count | Count IMPL-*.json | Count matches claims (<=18) |
|
||||||
| TDD structure | jq sample extraction | Shows red/green/refactor + cli_execution_id |
|
| TDD structure | jq sample extraction | Shows red/green/refactor + cli_execution_id |
|
||||||
| CLI execution IDs | jq extraction | All tasks have cli_execution_id assigned |
|
| CLI execution IDs | jq extraction | All tasks have cli_execution_id assigned |
|
||||||
@@ -571,6 +611,8 @@ Structure:
|
|||||||
Plans generated:
|
Plans generated:
|
||||||
- Unified Implementation Plan: {projectRoot}/.workflow/active/[sessionId]/IMPL_PLAN.md
|
- Unified Implementation Plan: {projectRoot}/.workflow/active/[sessionId]/IMPL_PLAN.md
|
||||||
(includes TDD Implementation Tasks section with workflow_type: "tdd")
|
(includes TDD Implementation Tasks section with workflow_type: "tdd")
|
||||||
|
- Plan Overview: {projectRoot}/.workflow/active/[sessionId]/plan.json
|
||||||
|
(plan-overview-base-schema with task IDs, complexity, and execution metadata)
|
||||||
- Task List: {projectRoot}/.workflow/active/[sessionId]/TODO_LIST.md
|
- Task List: {projectRoot}/.workflow/active/[sessionId]/TODO_LIST.md
|
||||||
(with internal TDD phase indicators and CLI execution strategies)
|
(with internal TDD phase indicators and CLI execution strategies)
|
||||||
- Task JSONs: {projectRoot}/.workflow/active/[sessionId]/.task/IMPL-*.json
|
- Task JSONs: {projectRoot}/.workflow/active/[sessionId]/.task/IMPL-*.json
|
||||||
@@ -634,7 +676,7 @@ Phase 4: conflict-resolution [AUTO-TRIGGERED if conflict_risk >= medium]
|
|||||||
↓ Skip if conflict_risk is none/low → proceed directly to Phase 5
|
↓ Skip if conflict_risk is none/low → proceed directly to Phase 5
|
||||||
↓
|
↓
|
||||||
Phase 5: task-generate-tdd --session sessionId
|
Phase 5: task-generate-tdd --session sessionId
|
||||||
↓ Output: IMPL_PLAN.md, task JSONs, TODO_LIST.md
|
↓ Output: IMPL_PLAN.md, task JSONs, TODO_LIST.md, plan.json
|
||||||
↓
|
↓
|
||||||
Phase 6: Internal validation + summary
|
Phase 6: Internal validation + summary
|
||||||
↓
|
↓
|
||||||
@@ -707,7 +749,7 @@ TDD Workflow Orchestrator
|
|||||||
│ ├─ Phase 5.1: Discovery - analyze TDD requirements
|
│ ├─ Phase 5.1: Discovery - analyze TDD requirements
|
||||||
│ ├─ Phase 5.2: Planning - design Red-Green-Refactor cycles
|
│ ├─ Phase 5.2: Planning - design Red-Green-Refactor cycles
|
||||||
│ └─ Phase 5.3: Output - generate IMPL tasks with internal TDD phases
|
│ └─ Phase 5.3: Output - generate IMPL tasks with internal TDD phases
|
||||||
│ └─ Returns: IMPL-*.json, IMPL_PLAN.md ← COLLAPSED
|
│ └─ Returns: IMPL-*.json, IMPL_PLAN.md, plan.json ← COLLAPSED
|
||||||
│ (Each IMPL task contains internal Red-Green-Refactor cycle)
|
│ (Each IMPL task contains internal Red-Green-Refactor cycle)
|
||||||
│
|
│
|
||||||
└─ Phase 6: TDD Structure Validation
|
└─ Phase 6: TDD Structure Validation
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ Phase 5: Generate Analysis Report
|
|||||||
|
|
||||||
### Phase 1: Extract Test Tasks
|
### Phase 1: Extract Test Tasks
|
||||||
```bash
|
```bash
|
||||||
find ${projectRoot}/.workflow/active/{session_id}/.task/ -name 'TEST-*.json' -exec jq -r '.context.focus_paths[]' {} \;
|
find ${projectRoot}/.workflow/active/{session_id}/.task/ -name 'TEST-*.json' -exec jq -r '(.focus_paths // .context.focus_paths // [])[]' {} \;
|
||||||
```
|
```
|
||||||
|
|
||||||
**Output**: List of test directories/files from all TEST tasks
|
**Output**: List of test directories/files from all TEST tasks
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ function TaskMarqueeWidgetComponent({ className }: TaskMarqueeWidgetProps) {
|
|||||||
{/* Status and Priority badges */}
|
{/* Status and Priority badges */}
|
||||||
<div className="flex items-center gap-2 flex-wrap">
|
<div className="flex items-center gap-2 flex-wrap">
|
||||||
<Badge className={cn(statusColors[currentTask.status], 'capitalize')}>
|
<Badge className={cn(statusColors[currentTask.status], 'capitalize')}>
|
||||||
{formatMessage({ id: statusLabelKeys[currentTask.status] })}
|
{formatMessage({ id: statusLabelKeys[currentTask.status] ?? 'sessions.status.inProgress' })}
|
||||||
</Badge>
|
</Badge>
|
||||||
<Badge className={cn(priorityColors[currentTask.priority], 'capitalize')}>
|
<Badge className={cn(priorityColors[currentTask.priority], 'capitalize')}>
|
||||||
{formatMessage({ id: `common.priority.${currentTask.priority}` })}
|
{formatMessage({ id: `common.priority.${currentTask.priority}` })}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ function WorkflowStatusProgressWidgetComponent({ className }: WorkflowStatusProg
|
|||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="text-sm font-medium text-foreground">
|
<span className="text-sm font-medium text-foreground">
|
||||||
{formatMessage({ id: statusLabelKeys[item.status] })}
|
{formatMessage({ id: statusLabelKeys[item.status] ?? 'sessions.status.inProgress' })}
|
||||||
</span>
|
</span>
|
||||||
<Badge variant="secondary" className="text-xs">
|
<Badge variant="secondary" className="text-xs">
|
||||||
{item.count}
|
{item.count}
|
||||||
|
|||||||
@@ -595,7 +595,7 @@ function WorkflowTaskWidgetComponent({ className }: WorkflowTaskWidgetProps) {
|
|||||||
<div key={item.status} className="flex items-center gap-1.5 min-w-0">
|
<div key={item.status} className="flex items-center gap-1.5 min-w-0">
|
||||||
<div className={cn('w-2.5 h-2.5 rounded-full shrink-0', colors.dot)} />
|
<div className={cn('w-2.5 h-2.5 rounded-full shrink-0', colors.dot)} />
|
||||||
<span className="text-xs text-muted-foreground truncate">
|
<span className="text-xs text-muted-foreground truncate">
|
||||||
{formatMessage({ id: statusLabelKeys[item.status] })}
|
{formatMessage({ id: statusLabelKeys[item.status] ?? 'sessions.status.inProgress' })}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-xs font-medium text-foreground ml-auto">
|
<span className="text-xs font-medium text-foreground ml-auto">
|
||||||
{percentage}%
|
{percentage}%
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ export function SessionDetailPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Badge variant={session.status === 'completed' ? 'success' : 'secondary'}>
|
<Badge variant={session.status === 'completed' ? 'success' : 'secondary'}>
|
||||||
{formatMessage({ id: statusLabelKeys[session.status] })}
|
{formatMessage({ id: statusLabelKeys[session.status] ?? 'sessions.status.inProgress' })}
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user