mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-14 02:42:04 +08:00
feat: update empty state messages and hints in English and Chinese locales
refactor: rename variables for clarity in ReviewSessionPage and SessionsPage fix: update version check logic in SettingsPage chore: remove unused imports in TeamPage and session-detail components fix: enhance error handling in MCP server fix: apply default mode in edit-file tool handler chore: remove tsbuildinfo file docs: add Quick Plan & Execute phase documentation for issue discovery chore: clean up ping output file
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
## Overview
|
||||
|
||||
Serial lightweight planning with CLI-powered exploration and search verification. Produces unified JSONL (`tasks.jsonl`) compatible with `collaborative-plan-with-file` output format, consumable by `unified-execute-with-file`.
|
||||
Serial lightweight planning with CLI-powered exploration and search verification. Produces `.task/TASK-*.json` (one file per task) compatible with `collaborative-plan-with-file` output format, consumable by `unified-execute-with-file`.
|
||||
|
||||
**Core capabilities:**
|
||||
- Intelligent task analysis with automatic exploration detection
|
||||
@@ -10,7 +10,7 @@ Serial lightweight planning with CLI-powered exploration and search verification
|
||||
- Search verification after each CLI exploration (ACE search, Grep, Glob)
|
||||
- Interactive clarification after exploration to gather missing information
|
||||
- Direct planning by Claude (all complexity levels, no agent delegation)
|
||||
- Unified JSONL output (`tasks.jsonl`) with convergence criteria
|
||||
- Unified multi-file task output (`.task/TASK-*.json`) with convergence criteria
|
||||
|
||||
## Parameters
|
||||
|
||||
@@ -28,7 +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 |
|
||||
| `tasks.jsonl` | ⭐ Unified JSONL (collaborative-plan-with-file compatible) |
|
||||
| `.task/TASK-*.json` | Multi-file task output (one JSON file per task) |
|
||||
| `plan.md` | Human-readable summary with execution command |
|
||||
|
||||
**Output Directory**: `{projectRoot}/.workflow/.lite-plan/{session-id}/`
|
||||
@@ -62,10 +62,10 @@ Phase 2: Clarification (optional, multi-round)
|
||||
├─ Deduplicate similar questions
|
||||
└─ ASK_USER (max 4 questions per round, multiple rounds)
|
||||
|
||||
Phase 3: Planning → tasks.jsonl (NO CODE EXECUTION)
|
||||
Phase 3: Planning → .task/*.json (NO CODE EXECUTION)
|
||||
├─ Load exploration notes + clarifications + project context
|
||||
├─ Direct Claude planning (following unified JSONL schema)
|
||||
├─ Generate tasks.jsonl (one task per line)
|
||||
├─ Direct Claude planning (following unified task JSON schema)
|
||||
├─ Generate .task/TASK-*.json (one file per task)
|
||||
└─ Generate plan.md (human-readable summary)
|
||||
|
||||
Phase 4: Confirmation
|
||||
@@ -73,7 +73,7 @@ Phase 4: Confirmation
|
||||
└─ ASK_USER: Allow / Modify / Cancel
|
||||
|
||||
Phase 5: Handoff
|
||||
└─ → unified-execute-with-file with tasks.jsonl
|
||||
└─ → unified-execute-with-file with .task/ directory
|
||||
```
|
||||
|
||||
## Implementation
|
||||
@@ -334,7 +334,7 @@ Aggregated from all exploration angles, deduplicated
|
||||
|
||||
---
|
||||
|
||||
### Phase 3: Planning → tasks.jsonl
|
||||
### Phase 3: Planning → .task/*.json
|
||||
|
||||
**IMPORTANT**: Phase 3 is **planning only** — NO code execution. All implementation happens via unified-execute-with-file.
|
||||
|
||||
@@ -358,9 +358,9 @@ Write(`${sessionFolder}/requirement-analysis.json`, JSON.stringify({
|
||||
}, null, 2))
|
||||
```
|
||||
|
||||
#### Step 3.3: Generate tasks.jsonl
|
||||
#### Step 3.3: Generate .task/*.json
|
||||
|
||||
Direct Claude planning — synthesize exploration findings and clarifications into unified JSONL tasks:
|
||||
Direct Claude planning — synthesize exploration findings and clarifications into individual task JSON files:
|
||||
|
||||
**Task Grouping Rules**:
|
||||
1. **Group by feature**: All changes for one feature = one task (even if 3-5 files)
|
||||
@@ -370,7 +370,7 @@ Direct Claude planning — synthesize exploration findings and clarifications in
|
||||
5. **True dependencies only**: Only use depends_on when Task B cannot start without Task A's output
|
||||
6. **Prefer parallel**: Most tasks should be independent (no depends_on)
|
||||
|
||||
**Unified JSONL Task Format** (one JSON object per line):
|
||||
**Unified Task JSON Format** (one JSON file per task, stored in `.task/` directory):
|
||||
|
||||
```javascript
|
||||
{
|
||||
@@ -406,10 +406,15 @@ Direct Claude planning — synthesize exploration findings and clarifications in
|
||||
}
|
||||
```
|
||||
|
||||
**Write tasks.jsonl**:
|
||||
**Write .task/*.json**:
|
||||
```javascript
|
||||
const jsonlContent = tasks.map(t => JSON.stringify(t)).join('\n')
|
||||
Write(`${sessionFolder}/tasks.jsonl`, jsonlContent)
|
||||
// Create .task/ directory
|
||||
Bash(`mkdir -p ${sessionFolder}/.task`)
|
||||
|
||||
// Write each task as an individual JSON file
|
||||
tasks.forEach(task => {
|
||||
Write(`${sessionFolder}/.task/${task.id}.json`, JSON.stringify(task, null, 2))
|
||||
})
|
||||
```
|
||||
|
||||
#### Step 3.4: Generate plan.md
|
||||
@@ -449,7 +454,7 @@ ${t.convergence.criteria.map(c => \` - ${c}\`).join('\n')}
|
||||
## 执行
|
||||
|
||||
\`\`\`bash
|
||||
$unified-execute-with-file PLAN="${sessionFolder}/tasks.jsonl"
|
||||
$unified-execute-with-file PLAN="${sessionFolder}/.task/"
|
||||
\`\`\`
|
||||
|
||||
**Session artifacts**: \`${sessionFolder}/\`
|
||||
@@ -463,7 +468,7 @@ Write(`${sessionFolder}/plan.md`, planMd)
|
||||
|
||||
#### Step 4.1: Display Plan
|
||||
|
||||
Read `{sessionFolder}/tasks.jsonl` and display summary:
|
||||
Read `{sessionFolder}/.task/` directory and display summary:
|
||||
|
||||
- **Summary**: Overall approach (from requirement understanding)
|
||||
- **Tasks**: Numbered list with ID, title, type, effort
|
||||
@@ -488,7 +493,7 @@ Read `{sessionFolder}/tasks.jsonl` and display summary:
|
||||
|
||||
**Output**: `userSelection` — `{ confirmation: "Allow" | "Modify" | "Cancel" }`
|
||||
|
||||
**Modify Loop**: If "Modify" selected, display current tasks.jsonl content, accept user edits (max 3 rounds), regenerate plan.md, re-confirm.
|
||||
**Modify Loop**: If "Modify" selected, display current `.task/*.json` content, accept user edits (max 3 rounds), regenerate plan.md, re-confirm.
|
||||
|
||||
---
|
||||
|
||||
@@ -509,7 +514,10 @@ Read `{sessionFolder}/tasks.jsonl` and display summary:
|
||||
├── explorations-manifest.json # Exploration index
|
||||
├── exploration-notes.md # Synthesized exploration notes
|
||||
├── requirement-analysis.json # Complexity assessment
|
||||
├── tasks.jsonl # ⭐ Unified JSONL output
|
||||
├── .task/ # ⭐ Task JSON files (one per task)
|
||||
│ ├── TASK-001.json
|
||||
│ ├── TASK-002.json
|
||||
│ └── ...
|
||||
└── plan.md # Human-readable summary
|
||||
```
|
||||
|
||||
@@ -522,7 +530,10 @@ Read `{sessionFolder}/tasks.jsonl` and display summary:
|
||||
├── explorations-manifest.json
|
||||
├── exploration-notes.md
|
||||
├── requirement-analysis.json
|
||||
├── tasks.jsonl
|
||||
├── .task/
|
||||
│ ├── TASK-001.json
|
||||
│ ├── TASK-002.json
|
||||
│ └── ...
|
||||
└── plan.md
|
||||
```
|
||||
|
||||
@@ -543,7 +554,7 @@ Read `{sessionFolder}/tasks.jsonl` and display summary:
|
||||
## Post-Phase Update
|
||||
|
||||
After Phase 1 (Lite Plan) completes:
|
||||
- **Output Created**: `tasks.jsonl` + `plan.md` + exploration artifacts in session folder
|
||||
- **Output Created**: `.task/TASK-*.json` + `plan.md` + exploration artifacts in session folder
|
||||
- **Session Artifacts**: All files in `{projectRoot}/.workflow/.lite-plan/{session-id}/`
|
||||
- **Next Action**: Auto-continue to [Phase 2: Execution Handoff](02-lite-execute.md)
|
||||
- **TodoWrite**: Mark "Lite Plan - Planning" as completed, start "Execution (unified-execute)"
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
## Overview
|
||||
|
||||
消费 Phase 1 产出的统一 JSONL (`tasks.jsonl`),串行执行任务并进行收敛验证,通过 `execution.md` + `execution-events.md` 跟踪进度。
|
||||
消费 Phase 1 产出的 `.task/*.json` (multi-file task definitions),串行执行任务并进行收敛验证,通过 `execution.md` + `execution-events.md` 跟踪进度。
|
||||
|
||||
**Core workflow**: Load JSONL → Validate → Pre-Execution Analysis → Execute → Verify Convergence → Track Progress
|
||||
**Core workflow**: Load .task/*.json → Validate → Pre-Execution Analysis → Execute → Verify Convergence → Track Progress
|
||||
|
||||
**Key features**:
|
||||
- **Single format**: 只消费统一 JSONL (`tasks.jsonl`)
|
||||
- **Single format**: 只消费 `.task/*.json` (one JSON file per task)
|
||||
- **Convergence-driven**: 每个任务执行后验证收敛标准
|
||||
- **Serial execution**: 按拓扑序串行执行,依赖跟踪
|
||||
- **Dual progress tracking**: `execution.md` (概览) + `execution-events.md` (事件流)
|
||||
@@ -17,11 +17,11 @@
|
||||
## Invocation
|
||||
|
||||
```javascript
|
||||
$unified-execute-with-file PLAN="${sessionFolder}/tasks.jsonl"
|
||||
$unified-execute-with-file PLAN="${sessionFolder}/.task/"
|
||||
|
||||
// With options
|
||||
$unified-execute-with-file PLAN="${sessionFolder}/tasks.jsonl" --auto-commit
|
||||
$unified-execute-with-file PLAN="${sessionFolder}/tasks.jsonl" --dry-run
|
||||
$unified-execute-with-file PLAN="${sessionFolder}/.task/" --auto-commit
|
||||
$unified-execute-with-file PLAN="${sessionFolder}/.task/" --dry-run
|
||||
```
|
||||
|
||||
## Output Structure
|
||||
@@ -32,7 +32,7 @@ ${projectRoot}/.workflow/.execution/EXEC-{slug}-{date}-{random}/
|
||||
└── execution-events.md # Unified event log (single source of truth)
|
||||
```
|
||||
|
||||
Additionally, the source `tasks.jsonl` is updated in-place with `_execution` states.
|
||||
Additionally, the source `.task/*.json` files are updated in-place with execution states (`status`, `executed_at`, `result`).
|
||||
|
||||
---
|
||||
|
||||
@@ -51,11 +51,11 @@ let planPath = planMatch ? planMatch[1] : null
|
||||
// Auto-detect if no PLAN specified
|
||||
if (!planPath) {
|
||||
// Search in order (most recent first):
|
||||
// .workflow/.lite-plan/*/tasks.jsonl
|
||||
// .workflow/.req-plan/*/tasks.jsonl
|
||||
// .workflow/.planning/*/tasks.jsonl
|
||||
// .workflow/.analysis/*/tasks.jsonl
|
||||
// .workflow/.brainstorm/*/tasks.jsonl
|
||||
// .workflow/.lite-plan/*/.task/
|
||||
// .workflow/.req-plan/*/.task/
|
||||
// .workflow/.planning/*/.task/
|
||||
// .workflow/.analysis/*/.task/
|
||||
// .workflow/.brainstorm/*/.task/
|
||||
}
|
||||
|
||||
// Resolve path
|
||||
@@ -75,20 +75,19 @@ Bash(`mkdir -p ${sessionFolder}`)
|
||||
|
||||
## Phase 1: Load & Validate
|
||||
|
||||
**Objective**: Parse unified JSONL, validate schema and dependencies, build execution order.
|
||||
**Objective**: Parse `.task/*.json` files, validate schema and dependencies, build execution order.
|
||||
|
||||
### Step 1.1: Parse Unified JSONL
|
||||
### Step 1.1: Parse Task JSON Files
|
||||
|
||||
```javascript
|
||||
const content = Read(planPath)
|
||||
const tasks = content.split('\n')
|
||||
.filter(line => line.trim())
|
||||
.map((line, i) => {
|
||||
try { return JSON.parse(line) }
|
||||
catch (e) { throw new Error(`Line ${i + 1}: Invalid JSON — ${e.message}`) }
|
||||
})
|
||||
// Read all JSON files from .task/ directory
|
||||
const taskFiles = Glob(`${planPath}/*.json`).sort()
|
||||
const tasks = taskFiles.map((file, i) => {
|
||||
try { return JSON.parse(Read(file)) }
|
||||
catch (e) { throw new Error(`File ${file}: Invalid JSON — ${e.message}`) }
|
||||
})
|
||||
|
||||
if (tasks.length === 0) throw new Error('No tasks found in JSONL file')
|
||||
if (tasks.length === 0) throw new Error('No task files found in .task/ directory')
|
||||
```
|
||||
|
||||
### Step 1.2: Validate Schema
|
||||
@@ -300,8 +299,9 @@ for (const taskId of executionOrder) {
|
||||
if (unmetDeps.length) {
|
||||
appendToEvents(task, 'BLOCKED', `Unmet dependencies: ${unmetDeps.join(', ')}`)
|
||||
skippedTasks.add(task.id)
|
||||
task._execution = { status: 'skipped', executed_at: startTime,
|
||||
result: { success: false, error: `Blocked by: ${unmetDeps.join(', ')}` } }
|
||||
task.status = 'skipped'
|
||||
task.executed_at = startTime
|
||||
task.result = { success: false, error: `Blocked by: ${unmetDeps.join(', ')}` }
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -321,8 +321,9 @@ ${task.convergence.criteria.map(c => `- [ ] ${c}`).join('\n')}
|
||||
if (dryRun) {
|
||||
// Simulate: mark as completed without changes
|
||||
appendToEvents(`\n**Status**: ⏭ DRY RUN (no changes)\n\n---\n`)
|
||||
task._execution = { status: 'completed', executed_at: startTime,
|
||||
result: { success: true, summary: 'Dry run — no changes made' } }
|
||||
task.status = 'completed'
|
||||
task.executed_at = startTime
|
||||
task.result = { success: true, summary: 'Dry run — no changes made' }
|
||||
completedTasks.add(task.id)
|
||||
continue
|
||||
}
|
||||
@@ -358,15 +359,14 @@ ${task.convergence.criteria.map((c, i) => `- [${convergenceResults.verified[i] ?
|
||||
|
||||
---
|
||||
`)
|
||||
task._execution = {
|
||||
status: 'completed', executed_at: endTime,
|
||||
result: {
|
||||
task.status = 'completed'
|
||||
task.executed_at = endTime
|
||||
task.result = {
|
||||
success: true,
|
||||
files_modified: filesModified,
|
||||
summary: changeSummary,
|
||||
convergence_verified: convergenceResults.verified
|
||||
}
|
||||
}
|
||||
completedTasks.add(task.id)
|
||||
} else {
|
||||
// 5b. Record FAILURE
|
||||
@@ -374,7 +374,7 @@ ${task.convergence.criteria.map((c, i) => `- [${convergenceResults.verified[i] ?
|
||||
}
|
||||
|
||||
// 6. Auto-commit if enabled
|
||||
if (autoCommit && task._execution.status === 'completed') {
|
||||
if (autoCommit && task.status === 'completed') {
|
||||
autoCommitTask(task, filesModified)
|
||||
}
|
||||
}
|
||||
@@ -440,14 +440,13 @@ ${task.convergence.criteria.map((c, i) => `- [${convergenceResults.verified[i] ?
|
||||
---
|
||||
`)
|
||||
|
||||
task._execution = {
|
||||
status: 'failed', executed_at: endTime,
|
||||
result: {
|
||||
task.status = 'failed'
|
||||
task.executed_at = endTime
|
||||
task.result = {
|
||||
success: false,
|
||||
error: 'Convergence verification failed',
|
||||
convergence_verified: convergenceResults.verified
|
||||
}
|
||||
}
|
||||
failedTasks.add(task.id)
|
||||
|
||||
// Ask user
|
||||
@@ -518,7 +517,7 @@ const summary = `
|
||||
| ID | Title | Status | Convergence | Files Modified |
|
||||
|----|-------|--------|-------------|----------------|
|
||||
${tasks.map(t => {
|
||||
const ex = t._execution || {}
|
||||
const ex = t || {}
|
||||
const convergenceStatus = ex.result?.convergence_verified
|
||||
? `${ex.result.convergence_verified.filter(v => v).length}/${ex.result.convergence_verified.length}`
|
||||
: '-'
|
||||
@@ -529,7 +528,7 @@ ${failedTasks.size > 0 ? `### Failed Tasks
|
||||
|
||||
${[...failedTasks].map(id => {
|
||||
const t = tasks.find(t => t.id === id)
|
||||
return `- **${t.id}**: ${t.title} — ${t._execution?.result?.error || 'Unknown'}`
|
||||
return `- **${t.id}**: ${t.title} — ${t.result?.error || 'Unknown'}`
|
||||
}).join('\n')}
|
||||
` : ''}
|
||||
### Artifacts
|
||||
@@ -555,31 +554,31 @@ appendToEvents(`
|
||||
`)
|
||||
```
|
||||
|
||||
### Step 4.3: Write Back tasks.jsonl with _execution
|
||||
### Step 4.3: Write Back .task/*.json with Execution State
|
||||
|
||||
Update the source JSONL file with execution states:
|
||||
Update each task JSON file in-place with execution state:
|
||||
|
||||
```javascript
|
||||
const updatedJsonl = tasks.map(task => JSON.stringify(task)).join('\n')
|
||||
Write(planPath, updatedJsonl)
|
||||
// Each task now has _execution: { status, executed_at, result }
|
||||
tasks.forEach(task => {
|
||||
const taskFile = `${planPath}/${task.id}.json`
|
||||
Write(taskFile, JSON.stringify(task, null, 2))
|
||||
})
|
||||
// Each task now has status, executed_at, result fields
|
||||
```
|
||||
|
||||
**_execution State** (added to each task):
|
||||
**Execution State** (added to each task JSON file):
|
||||
|
||||
```javascript
|
||||
{
|
||||
// ... original task fields ...
|
||||
_execution: {
|
||||
status: "completed" | "failed" | "skipped",
|
||||
executed_at: "ISO timestamp",
|
||||
result: {
|
||||
success: boolean,
|
||||
files_modified: string[], // list of modified file paths
|
||||
summary: string, // change description
|
||||
convergence_verified: boolean[], // per criterion
|
||||
error: string // if failed
|
||||
}
|
||||
status: "completed" | "failed" | "skipped",
|
||||
executed_at: "ISO timestamp",
|
||||
result: {
|
||||
success: boolean,
|
||||
files_modified: string[], // list of modified file paths
|
||||
summary: string, // change description
|
||||
convergence_verified: boolean[], // per criterion
|
||||
error: string // if failed
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -604,7 +603,7 @@ AskUserQuestion({
|
||||
|
||||
| Selection | Action |
|
||||
|-----------|--------|
|
||||
| Retry Failed | Filter tasks with `_execution.status === 'failed'`, re-execute, append `[RETRY]` events |
|
||||
| Retry Failed | Filter tasks with `status === 'failed'`, re-execute, append `[RETRY]` events |
|
||||
| View Events | Display execution-events.md content |
|
||||
| Create Issue | `$issue:new` from failed task details |
|
||||
| Done | Display artifact paths, end workflow |
|
||||
@@ -615,10 +614,10 @@ AskUserQuestion({
|
||||
|
||||
| Situation | Action | Recovery |
|
||||
|-----------|--------|----------|
|
||||
| JSONL file not found | Report error with path | Check path, verify planning phase output |
|
||||
| Invalid JSON line | Report line number and error | Fix JSONL file manually |
|
||||
| .task/ directory not found | Report error with path | Check path, verify planning phase output |
|
||||
| Invalid JSON file | Report filename and error | Fix task JSON file manually |
|
||||
| Missing convergence | Report validation error | Add convergence fields to tasks |
|
||||
| Circular dependency | Stop, report cycle path | Fix dependencies in JSONL |
|
||||
| Circular dependency | Stop, report cycle path | Fix dependencies in task files |
|
||||
| Task execution fails | Record in events, ask user | Retry, skip, accept, or abort |
|
||||
| Convergence verification fails | Mark task failed, ask user | Fix code and retry, or accept |
|
||||
| Verification command timeout | Mark as unverified | Manual verification needed |
|
||||
|
||||
Reference in New Issue
Block a user