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:
catlog22
2026-02-13 10:38:37 +08:00
parent 4d1a609aef
commit 78f1d81516
16 changed files with 271 additions and 31 deletions

View File

@@ -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",

View File

@@ -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.

View File

@@ -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

View File

@@ -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: {

View File

@@ -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

View File

@@ -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)

View File

@@ -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
│ └── ... │ └── ...

View File

@@ -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

View File

@@ -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

View File

@@ -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`

View File

@@ -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

View File

@@ -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

View File

@@ -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}` })}

View File

@@ -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}

View File

@@ -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}%

View File

@@ -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>