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": {
|
||||
"type": "string",
|
||||
"enum": ["cli-lite-planning-agent", "direct-planning"],
|
||||
"description": "规划来源"
|
||||
"enum": ["cli-lite-planning-agent", "direct-planning", "action-planning-agent", "review-cycle-agent", "issue-plan-agent", "tdd-planning-agent"],
|
||||
"description": "规划来源 — 标识产生此 plan 的实际规划引擎"
|
||||
},
|
||||
"planning_mode": {
|
||||
"type": "string",
|
||||
|
||||
@@ -97,6 +97,7 @@ The key innovation is the **Plan Note** architecture — a shared collaborative
|
||||
│ │ ├── TASK-101.json
|
||||
│ │ └── ...
|
||||
│ └── ...
|
||||
├── plan.json # Plan overview (plan-overview-base-schema.json)
|
||||
├── .task/ # ⭐ Merged task JSON files (all domains)
|
||||
│ ├── TASK-001.json
|
||||
│ ├── TASK-101.json
|
||||
@@ -133,6 +134,7 @@ The key innovation is the **Plan Note** architecture — a shared collaborative
|
||||
| Artifact | Purpose |
|
||||
|----------|---------|
|
||||
| `.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 |
|
||||
|
||||
---
|
||||
@@ -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.
|
||||
|
||||
@@ -634,7 +670,7 @@ ${allConflicts.length === 0
|
||||
Write(`${sessionFolder}/plan.md`, planMd)
|
||||
```
|
||||
|
||||
### Step 4.3: Display Completion Summary
|
||||
### Step 4.4: Display Completion Summary
|
||||
|
||||
Present session statistics and next steps.
|
||||
|
||||
|
||||
@@ -157,7 +157,8 @@ Phase Execution (load one phase):
|
||||
|
||||
Post-Phase:
|
||||
├─ 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
|
||||
```
|
||||
|
||||
@@ -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)
|
||||
├─ Output path: .workflow/issues/{issue-id}/.task/TASK-{T-id}.json
|
||||
├─ 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
|
||||
|
||||
@@ -36,14 +36,16 @@ Converts any planning artifact to **`.task/*.json` multi-file format** — the s
|
||||
**Producer 使用的字段集** (plan-converter 输出):
|
||||
|
||||
```
|
||||
IDENTITY (必填): id, title, description
|
||||
CLASSIFICATION (可选): type, priority, effort
|
||||
SCOPE (可选): scope, excludes
|
||||
DEPENDENCIES (必填): depends_on, parallel_group, inputs, outputs
|
||||
CONVERGENCE (必填): convergence.criteria, convergence.verification, convergence.definition_of_done
|
||||
FILES (可选): files[].path, files[].action, files[].changes, files[].conflict_risk
|
||||
CONTEXT (可选): source.tool, source.session_id, source.original_id, evidence, risk_items
|
||||
RUNTIME (执行时填充): status, executed_at, result
|
||||
IDENTITY (必填): id, title, description
|
||||
CLASSIFICATION (可选): type, priority, effort, action
|
||||
SCOPE (可选): scope, excludes, focus_paths
|
||||
DEPENDENCIES (必填): depends_on, parallel_group, inputs, outputs
|
||||
CONVERGENCE (必填): convergence.criteria, convergence.verification, convergence.definition_of_done
|
||||
FILES (可选): files[].path, files[].action, files[].changes, files[].change, files[].target, files[].conflict_risk
|
||||
IMPLEMENTATION (可选): implementation[], test.manual_checks, test.success_metrics
|
||||
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- 等)
|
||||
@@ -237,7 +239,9 @@ function transformPlanNote(parsed) {
|
||||
files: task.files?.map(f => ({
|
||||
path: f.path || f.file,
|
||||
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
|
||||
})),
|
||||
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
|
||||
├─ Each file follows task-schema.json (IDENTITY + CONVERGENCE + FILES required)
|
||||
└─ 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
|
||||
└─ 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-002.json
|
||||
│ └── ...
|
||||
├── plan.json # Plan overview (plan-overview-fix-schema, Phase 7.5)
|
||||
└── fixes/{fix-session-id}/ # Fix results (Phase 6-9)
|
||||
├── partial-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))
|
||||
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) {
|
||||
@@ -435,6 +443,12 @@ ${task.convergence.criteria.map(c => `- [ ] ${c}`).join('\n')}
|
||||
// - Use Grep/Glob/mcp__ace-tool for discovery if needed
|
||||
// - 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
|
||||
const convergenceResults = verifyConvergence(task)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ allowed-tools: AskUserQuestion, Read, Write, Edit, Bash, Glob, Grep, mcp__ace-to
|
||||
|
||||
# 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`
|
||||
|
||||
@@ -91,7 +91,7 @@ Read('phases/02-lite-execute.md')
|
||||
|
||||
## 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`
|
||||
|
||||
@@ -104,7 +104,8 @@ Phase 1 produces `.task/TASK-*.json` (one file per task) — compatible with `co
|
||||
├── explorations-manifest.json # Exploration index
|
||||
├── exploration-notes.md # Synthesized exploration notes
|
||||
├── 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-002.json
|
||||
│ └── ...
|
||||
|
||||
@@ -28,6 +28,7 @@ Serial lightweight planning with CLI-powered exploration and search verification
|
||||
| `explorations-manifest.json` | Index of all exploration files |
|
||||
| `exploration-notes.md` | Synthesized exploration notes (all angles combined) |
|
||||
| `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) |
|
||||
| `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
|
||||
|
||||
Create human-readable summary:
|
||||
@@ -514,7 +547,8 @@ Read `{sessionFolder}/.task/` directory and display summary:
|
||||
├── explorations-manifest.json # Exploration index
|
||||
├── exploration-notes.md # Synthesized exploration notes
|
||||
├── 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-002.json
|
||||
│ └── ...
|
||||
@@ -530,6 +564,7 @@ Read `{sessionFolder}/.task/` directory and display summary:
|
||||
├── explorations-manifest.json
|
||||
├── exploration-notes.md
|
||||
├── requirement-analysis.json
|
||||
├── plan.json
|
||||
├── .task/
|
||||
│ ├── TASK-001.json
|
||||
│ ├── TASK-002.json
|
||||
|
||||
@@ -76,8 +76,8 @@ Phase 2: Context Gathering & Conflict Resolution
|
||||
|
||||
Phase 3: Task Generation
|
||||
└─ Ref: phases/03-task-generation.md
|
||||
└─ Output: IMPL_PLAN.md, task JSONs, TODO_LIST.md
|
||||
└─ Schema: .task/IMPL-*.json follows 6-field superset of task-schema.json
|
||||
└─ Output: plan.json, IMPL_PLAN.md, task JSONs, TODO_LIST.md
|
||||
└─ Schema: plan.json follows plan-overview-base-schema.json; .task/IMPL-*.json follows task-schema.json
|
||||
|
||||
User Decision (or --yes auto):
|
||||
└─ "Start Execution" → Phase 4
|
||||
@@ -225,7 +225,7 @@ Phase 2: context-gather --session sessionId "structured-description"
|
||||
↓
|
||||
Phase 3: task-generate-agent --session sessionId
|
||||
↓ 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
|
||||
↓
|
||||
|
||||
@@ -179,6 +179,7 @@ const userConfig = {
|
||||
│ ├── IMPL-A2.json
|
||||
│ ├── IMPL-B1.json
|
||||
│ └── ...
|
||||
├── plan.json # Output: Plan overview (plan-overview-base-schema.json)
|
||||
├── IMPL_PLAN.md # Output: Implementation plan (grouped by module)
|
||||
└── 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
|
||||
|
||||
- **Files**:
|
||||
- `{projectRoot}/.workflow/active/{sessionId}/plan.json`
|
||||
- `{projectRoot}/.workflow/active/{sessionId}/IMPL_PLAN.md`
|
||||
- `{projectRoot}/.workflow/active/{sessionId}/.task/IMPL-*.json`
|
||||
- `{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.2: Planning - design Red-Green-Refactor cycles
|
||||
└─ 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
|
||||
|
||||
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)
|
||||
|
||||
**Internal validation first, then recommend external verification**
|
||||
@@ -528,7 +567,7 @@ Warning TDD Red Flag: [issue description]
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
# 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 |
|
||||
|---------------|---------------------|---------------|
|
||||
| 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) |
|
||||
| TDD structure | jq sample extraction | Shows red/green/refactor + cli_execution_id |
|
||||
| CLI execution IDs | jq extraction | All tasks have cli_execution_id assigned |
|
||||
@@ -571,6 +611,8 @@ Structure:
|
||||
Plans generated:
|
||||
- Unified Implementation Plan: {projectRoot}/.workflow/active/[sessionId]/IMPL_PLAN.md
|
||||
(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
|
||||
(with internal TDD phase indicators and CLI execution strategies)
|
||||
- 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
|
||||
↓
|
||||
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
|
||||
↓
|
||||
@@ -707,7 +749,7 @@ TDD Workflow Orchestrator
|
||||
│ ├─ Phase 5.1: Discovery - analyze TDD requirements
|
||||
│ ├─ Phase 5.2: Planning - design Red-Green-Refactor cycles
|
||||
│ └─ 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)
|
||||
│
|
||||
└─ Phase 6: TDD Structure Validation
|
||||
|
||||
@@ -46,7 +46,7 @@ Phase 5: Generate Analysis Report
|
||||
|
||||
### Phase 1: Extract Test Tasks
|
||||
```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
|
||||
|
||||
@@ -92,7 +92,7 @@ function TaskMarqueeWidgetComponent({ className }: TaskMarqueeWidgetProps) {
|
||||
{/* Status and Priority badges */}
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<Badge className={cn(statusColors[currentTask.status], 'capitalize')}>
|
||||
{formatMessage({ id: statusLabelKeys[currentTask.status] })}
|
||||
{formatMessage({ id: statusLabelKeys[currentTask.status] ?? 'sessions.status.inProgress' })}
|
||||
</Badge>
|
||||
<Badge className={cn(priorityColors[currentTask.priority], 'capitalize')}>
|
||||
{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 gap-2">
|
||||
<span className="text-sm font-medium text-foreground">
|
||||
{formatMessage({ id: statusLabelKeys[item.status] })}
|
||||
{formatMessage({ id: statusLabelKeys[item.status] ?? 'sessions.status.inProgress' })}
|
||||
</span>
|
||||
<Badge variant="secondary" className="text-xs">
|
||||
{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 className={cn('w-2.5 h-2.5 rounded-full shrink-0', colors.dot)} />
|
||||
<span className="text-xs text-muted-foreground truncate">
|
||||
{formatMessage({ id: statusLabelKeys[item.status] })}
|
||||
{formatMessage({ id: statusLabelKeys[item.status] ?? 'sessions.status.inProgress' })}
|
||||
</span>
|
||||
<span className="text-xs font-medium text-foreground ml-auto">
|
||||
{percentage}%
|
||||
|
||||
@@ -168,7 +168,7 @@ export function SessionDetailPage() {
|
||||
</div>
|
||||
</div>
|
||||
<Badge variant={session.status === 'completed' ? 'success' : 'secondary'}>
|
||||
{formatMessage({ id: statusLabelKeys[session.status] })}
|
||||
{formatMessage({ id: statusLabelKeys[session.status] ?? 'sessions.status.inProgress' })}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user