claude-code-workflow 6.3.7 → 6.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -51,51 +51,18 @@ interface Issue {
51
51
  }
52
52
  ```
53
53
 
54
- ## Task Lifecycle (Each Task is Closed-Loop)
54
+ ## Lifecycle Requirements
55
55
 
56
- When `/issue:plan` generates tasks, each task MUST include:
56
+ The `lifecycle_requirements` field guides downstream commands (`/issue:plan`, `/issue:execute`):
57
57
 
58
- ```typescript
59
- interface SolutionTask {
60
- id: string;
61
- title: string;
62
- scope: string;
63
- action: string;
64
-
65
- // Phase 1: Implementation
66
- implementation: string[]; // Step-by-step implementation
67
- modification_points: { file: string; target: string; change: string }[];
68
-
69
- // Phase 2: Testing
70
- test: {
71
- unit?: string[]; // Unit test requirements
72
- integration?: string[]; // Integration test requirements
73
- commands?: string[]; // Test commands to run
74
- coverage_target?: number; // Minimum coverage %
75
- };
76
-
77
- // Phase 3: Regression
78
- regression: string[]; // Regression check commands/points
79
-
80
- // Phase 4: Acceptance
81
- acceptance: {
82
- criteria: string[]; // Testable acceptance criteria
83
- verification: string[]; // How to verify each criterion
84
- manual_checks?: string[]; // Manual verification if needed
85
- };
58
+ | Field | Options | Purpose |
59
+ |-------|---------|---------|
60
+ | `test_strategy` | `unit`, `integration`, `e2e`, `manual`, `auto` | Which test types to generate |
61
+ | `regression_scope` | `affected`, `related`, `full` | Which tests to run for regression |
62
+ | `acceptance_type` | `automated`, `manual`, `both` | How to verify completion |
63
+ | `commit_strategy` | `per-task`, `squash`, `atomic` | Commit granularity |
86
64
 
87
- // Phase 5: Commit
88
- commit: {
89
- type: 'feat' | 'fix' | 'refactor' | 'test' | 'docs' | 'chore';
90
- scope: string; // e.g., "auth", "api"
91
- message_template: string; // Commit message template
92
- breaking?: boolean;
93
- };
94
-
95
- depends_on: string[];
96
- executor: 'codex' | 'gemini' | 'agent' | 'auto';
97
- }
98
- ```
65
+ > **Note**: Task structure (SolutionTask) is defined in `/issue:plan` - see `.claude/commands/issue/plan.md`
99
66
 
100
67
  ## Usage
101
68
 
@@ -9,13 +9,35 @@ allowed-tools: TodoWrite(*), Task(*), SlashCommand(*), AskUserQuestion(*), Bash(
9
9
 
10
10
  ## Overview
11
11
 
12
- Unified planning command using **issue-plan-agent** that combines exploration and planning into a single closed-loop workflow. The agent handles ACE semantic search, solution generation, and task breakdown.
12
+ Unified planning command using **issue-plan-agent** that combines exploration and planning into a single closed-loop workflow.
13
+
14
+ ## Output Requirements
15
+
16
+ **Generate Files:**
17
+ 1. `.workflow/issues/solutions/{issue-id}.jsonl` - Solution with tasks for each issue
18
+
19
+ **Return Summary:**
20
+ ```json
21
+ {
22
+ "bound": [{ "issue_id": "...", "solution_id": "...", "task_count": N }],
23
+ "pending_selection": [{ "issue_id": "...", "solutions": [...] }],
24
+ "conflicts": [{ "file": "...", "issues": [...] }]
25
+ }
26
+ ```
27
+
28
+ **Completion Criteria:**
29
+ - [ ] Solution file generated for each issue
30
+ - [ ] Single solution → auto-bound via `ccw issue bind`
31
+ - [ ] Multiple solutions → returned for user selection
32
+ - [ ] Tasks conform to schema: `cat .claude/workflows/cli-templates/schemas/issue-task-jsonl-schema.json`
33
+ - [ ] Each task has quantified `delivery_criteria`
34
+
35
+ ## Core Capabilities
13
36
 
14
- **Core capabilities:**
15
37
  - **Closed-loop agent**: issue-plan-agent combines explore + plan
16
38
  - Batch processing: 1 agent processes 1-3 issues
17
39
  - ACE semantic search integrated into planning
18
- - Solution with executable tasks and acceptance criteria
40
+ - Solution with executable tasks and delivery criteria
19
41
  - Automatic solution registration and binding
20
42
 
21
43
  ## Storage Structure (Flat JSONL)
@@ -75,26 +97,16 @@ Phase 4: Summary
75
97
 
76
98
  ## Implementation
77
99
 
78
- ### Phase 1: Issue Loading
100
+ ### Phase 1: Issue Loading (IDs Only)
79
101
 
80
102
  ```javascript
81
- // Parse input and flags
82
- const issuesPath = '.workflow/issues/issues.jsonl';
83
103
  const batchSize = flags.batchSize || 3;
84
-
85
- // Key fields for planning (avoid loading full issue data)
86
- const PLAN_FIELDS = 'id,title,status,context,affected_components,lifecycle_requirements,priority,bound_solution_id';
87
-
88
104
  let issueIds = [];
89
105
 
90
106
  if (flags.allPending) {
91
- // Use jq to filter pending/registered issues - extract only IDs
92
- const pendingIds = Bash(`
93
- cat "${issuesPath}" 2>/dev/null | \\
94
- jq -r 'select(.status == "pending" or .status == "registered") | .id' 2>/dev/null || echo ''
95
- `).trim();
96
-
97
- issueIds = pendingIds ? pendingIds.split('\n').filter(Boolean) : [];
107
+ // Get pending issue IDs directly via CLI
108
+ const ids = Bash(`ccw issue list --status pending,registered --ids`).trim();
109
+ issueIds = ids ? ids.split('\n').filter(Boolean) : [];
98
110
 
99
111
  if (issueIds.length === 0) {
100
112
  console.log('No pending issues found.');
@@ -106,135 +118,66 @@ if (flags.allPending) {
106
118
  issueIds = userInput.includes(',')
107
119
  ? userInput.split(',').map(s => s.trim())
108
120
  : [userInput.trim()];
109
- }
110
121
 
111
- // Load issues using jq to extract only key fields
112
- const issues = [];
113
- for (const id of issueIds) {
114
- // Use jq to find issue by ID and extract only needed fields
115
- const issueJson = Bash(`
116
- cat "${issuesPath}" 2>/dev/null | \\
117
- jq -c 'select(.id == "${id}") | {${PLAN_FIELDS}}' 2>/dev/null | head -1
118
- `).trim();
119
-
120
- let issue;
121
- if (issueJson) {
122
- issue = JSON.parse(issueJson);
123
- } else {
124
- console.log(`Issue ${id} not found. Creating...`);
125
- issue = {
126
- id,
127
- title: `Issue ${id}`,
128
- status: 'registered',
129
- priority: 3,
130
- context: '',
131
- created_at: new Date().toISOString(),
132
- updated_at: new Date().toISOString()
133
- };
134
- // Append to issues.jsonl
135
- Bash(`echo '${JSON.stringify(issue)}' >> "${issuesPath}"`);
122
+ // Create if not exists
123
+ for (const id of issueIds) {
124
+ Bash(`ccw issue init ${id} --title "Issue ${id}" 2>/dev/null || true`);
136
125
  }
137
-
138
- issues.push(issue);
139
126
  }
140
127
 
141
128
  // Group into batches
142
129
  const batches = [];
143
- for (let i = 0; i < issues.length; i += batchSize) {
144
- batches.push(issues.slice(i, i + batchSize));
130
+ for (let i = 0; i < issueIds.length; i += batchSize) {
131
+ batches.push(issueIds.slice(i, i + batchSize));
145
132
  }
146
133
 
147
- console.log(`Processing ${issues.length} issues in ${batches.length} batch(es)`);
134
+ console.log(`Processing ${issueIds.length} issues in ${batches.length} batch(es)`);
148
135
 
149
136
  TodoWrite({
150
- todos: batches.flatMap((batch, i) => [
151
- { content: `Plan batch ${i+1}`, status: 'pending', activeForm: `Planning batch ${i+1}` }
152
- ])
137
+ todos: batches.map((_, i) => ({
138
+ content: `Plan batch ${i+1}`,
139
+ status: 'pending',
140
+ activeForm: `Planning batch ${i+1}`
141
+ }))
153
142
  });
154
143
  ```
155
144
 
156
145
  ### Phase 2: Unified Explore + Plan (issue-plan-agent)
157
146
 
158
147
  ```javascript
159
- // Ensure solutions directory exists
160
148
  Bash(`mkdir -p .workflow/issues/solutions`);
149
+ const pendingSelections = []; // Collect multi-solution issues for user selection
161
150
 
162
151
  for (const [batchIndex, batch] of batches.entries()) {
163
152
  updateTodo(`Plan batch ${batchIndex + 1}`, 'in_progress');
164
153
 
165
- // Build issue prompt for agent - agent writes solutions directly
154
+ // Build minimal prompt - agent handles exploration, planning, and binding
166
155
  const issuePrompt = `
167
- ## Issues to Plan (Closed-Loop Tasks Required)
156
+ ## Plan Issues
168
157
 
169
- ${batch.map((issue, i) => `
170
- ### Issue ${i + 1}: ${issue.id}
171
- **Title**: ${issue.title}
172
- **Context**: ${issue.context || 'No context provided'}
173
- **Affected Components**: ${issue.affected_components?.join(', ') || 'Not specified'}
158
+ **Issue IDs**: ${batch.join(', ')}
159
+ **Project Root**: ${process.cwd()}
174
160
 
175
- **Lifecycle Requirements**:
176
- - Test Strategy: ${issue.lifecycle_requirements?.test_strategy || 'auto'}
177
- - Regression Scope: ${issue.lifecycle_requirements?.regression_scope || 'affected'}
178
- - Commit Strategy: ${issue.lifecycle_requirements?.commit_strategy || 'per-task'}
179
- `).join('\n')}
180
-
181
- ## Project Root
182
- ${process.cwd()}
183
-
184
- ## Output Requirements
161
+ ### Steps
162
+ 1. Fetch: \`ccw issue status <id> --json\`
163
+ 2. Explore (ACE) Plan solution
164
+ 3. Register & bind: \`ccw issue bind <id> --solution <file>\`
185
165
 
186
- **IMPORTANT**: Write solutions DIRECTLY to files, do NOT return full solution content.
166
+ ### Generate Files
167
+ \`.workflow/issues/solutions/{issue-id}.jsonl\` - Solution with tasks (schema: cat .claude/workflows/cli-templates/schemas/issue-task-jsonl-schema.json)
187
168
 
188
- ### 1. Write Solution Files
189
- For each issue, write solution to: \`.workflow/issues/solutions/{issue-id}.jsonl\`
190
- - Append one JSON line per solution
191
- - Solution must include all closed-loop task fields (see Solution Format below)
169
+ ### Binding Rules
170
+ - **Single solution**: Auto-bind via \`ccw issue bind <id> --solution <file>\`
171
+ - **Multiple solutions**: Register only, return for user selection
192
172
 
193
- ### 2. Return Summary Only
194
- After writing solutions, return ONLY a brief JSON summary:
173
+ ### Return Summary
195
174
  \`\`\`json
196
175
  {
197
- "planned": [
198
- { "issue_id": "XXX", "solution_id": "SOL-xxx", "task_count": 3, "description": "Brief description" }
199
- ],
200
- "conflicts": [
201
- { "file": "path/to/file", "issues": ["ID1", "ID2"], "suggested_order": ["ID1", "ID2"] }
202
- ]
176
+ "bound": [{ "issue_id": "...", "solution_id": "...", "task_count": N }],
177
+ "pending_selection": [{ "issue_id": "...", "solutions": [{ "id": "...", "description": "...", "task_count": N }] }],
178
+ "conflicts": [{ "file": "...", "issues": [...] }]
203
179
  }
204
180
  \`\`\`
205
-
206
- ## Closed-Loop Task Requirements
207
-
208
- Each task MUST include ALL lifecycle phases:
209
-
210
- ### 1. Implementation
211
- - implementation: string[] (2-7 concrete steps)
212
- - modification_points: { file, target, change }[]
213
-
214
- ### 2. Test
215
- - test.unit: string[] (unit test requirements)
216
- - test.integration: string[] (integration test requirements if needed)
217
- - test.commands: string[] (actual test commands to run)
218
- - test.coverage_target: number (minimum coverage %)
219
-
220
- ### 3. Regression
221
- - regression: string[] (commands to run for regression check)
222
-
223
- ### 4. Acceptance
224
- - acceptance.criteria: string[] (testable acceptance criteria)
225
- - acceptance.verification: string[] (how to verify each criterion)
226
-
227
- ### 5. Commit
228
- - commit.type: feat|fix|refactor|test|docs|chore
229
- - commit.scope: string (module name)
230
- - commit.message_template: string (full commit message)
231
- - commit.breaking: boolean
232
-
233
- ## Additional Requirements
234
- 1. Use ACE semantic search (mcp__ace-tool__search_context) for exploration
235
- 2. Detect file conflicts if multiple issues
236
- 3. Generate executable test commands based on project's test framework
237
- 4. Infer commit scope from affected files
238
181
  `;
239
182
 
240
183
  // Launch issue-plan-agent - agent writes solutions directly
@@ -245,192 +188,68 @@ Each task MUST include ALL lifecycle phases:
245
188
  prompt=issuePrompt
246
189
  );
247
190
 
248
- // Parse brief summary from agent
191
+ // Parse summary from agent
249
192
  const summary = JSON.parse(result);
250
193
 
251
- // Display planning results
252
- for (const item of summary.planned || []) {
253
- console.log(`✓ ${item.issue_id}: ${item.solution_id} (${item.task_count} tasks) - ${item.description}`);
194
+ // Display auto-bound solutions
195
+ for (const item of summary.bound || []) {
196
+ console.log(`✓ ${item.issue_id}: ${item.solution_id} (${item.task_count} tasks)`);
254
197
  }
255
198
 
256
- // Handle conflicts if any
199
+ // Collect pending selections for Phase 3
200
+ pendingSelections.push(...(summary.pending_selection || []));
201
+
202
+ // Show conflicts
257
203
  if (summary.conflicts?.length > 0) {
258
- console.log(`\n⚠ File conflicts detected:`);
259
- summary.conflicts.forEach(c => {
260
- console.log(` ${c.file}: ${c.issues.join(', ')} → suggested: ${c.suggested_order.join(' → ')}`);
261
- });
204
+ console.log(`⚠ Conflicts: ${summary.conflicts.map(c => c.file).join(', ')}`);
262
205
  }
263
206
 
264
207
  updateTodo(`Plan batch ${batchIndex + 1}`, 'completed');
265
208
  }
266
209
  ```
267
210
 
268
- ### Phase 3: Solution Binding
211
+ ### Phase 3: Multi-Solution Selection
269
212
 
270
213
  ```javascript
271
- // Collect issues needing user selection (multiple solutions)
272
- const needSelection = [];
273
-
274
- for (const issue of issues) {
275
- const solPath = `.workflow/issues/solutions/${issue.id}.jsonl`;
276
-
277
- // Use jq to count solutions
278
- const count = parseInt(Bash(`cat "${solPath}" 2>/dev/null | jq -s 'length' 2>/dev/null || echo '0'`).trim()) || 0;
279
-
280
- if (count === 0) continue; // No solutions - skip silently (agent already reported)
281
-
282
- if (count === 1) {
283
- // Auto-bind single solution
284
- const solId = Bash(`cat "${solPath}" | jq -r '.id' | head -1`).trim();
285
- bindSolution(issue.id, solId);
286
- } else {
287
- // Multiple solutions - collect for batch selection
288
- const options = Bash(`cat "${solPath}" | jq -c '{id, description, task_count: (.tasks | length)}'`).trim();
289
- needSelection.push({ issue, options: options.split('\n').map(s => JSON.parse(s)) });
290
- }
291
- }
292
-
293
- // Batch ask user for multiple-solution issues
294
- if (needSelection.length > 0) {
214
+ // Only handle issues where agent generated multiple solutions
215
+ if (pendingSelections.length > 0) {
295
216
  const answer = AskUserQuestion({
296
- questions: needSelection.map(({ issue, options }) => ({
297
- question: `Select solution for ${issue.id}:`,
298
- header: issue.id,
217
+ questions: pendingSelections.map(({ issue_id, solutions }) => ({
218
+ question: `Select solution for ${issue_id}:`,
219
+ header: issue_id,
299
220
  multiSelect: false,
300
- options: options.map(s => ({
221
+ options: solutions.map(s => ({
301
222
  label: `${s.id} (${s.task_count} tasks)`,
302
- description: s.description || 'Solution'
223
+ description: s.description
303
224
  }))
304
225
  }))
305
226
  });
306
227
 
307
- // Bind selected solutions
308
- for (const { issue } of needSelection) {
309
- const selectedSolId = extractSelectedSolutionId(answer, issue.id);
310
- if (selectedSolId) bindSolution(issue.id, selectedSolId);
228
+ // Bind user-selected solutions
229
+ for (const { issue_id } of pendingSelections) {
230
+ const selectedId = extractSelectedSolutionId(answer, issue_id);
231
+ if (selectedId) {
232
+ Bash(`ccw issue bind ${issue_id} ${selectedId}`);
233
+ console.log(`✓ ${issue_id}: ${selectedId} bound`);
234
+ }
311
235
  }
312
236
  }
313
-
314
- // Helper: bind solution to issue
315
- function bindSolution(issueId, solutionId) {
316
- const now = new Date().toISOString();
317
- const solPath = `.workflow/issues/solutions/${issueId}.jsonl`;
318
-
319
- // Update issue status
320
- Bash(`
321
- tmpfile=$(mktemp) && \\
322
- cat "${issuesPath}" | jq -c 'if .id == "${issueId}" then . + {
323
- bound_solution_id: "${solutionId}", status: "planned",
324
- planned_at: "${now}", updated_at: "${now}"
325
- } else . end' > "$tmpfile" && mv "$tmpfile" "${issuesPath}"
326
- `);
327
-
328
- // Mark solution as bound
329
- Bash(`
330
- tmpfile=$(mktemp) && \\
331
- cat "${solPath}" | jq -c 'if .id == "${solutionId}" then . + {
332
- is_bound: true, bound_at: "${now}"
333
- } else . + {is_bound: false} end' > "$tmpfile" && mv "$tmpfile" "${solPath}"
334
- `);
335
- }
336
237
  ```
337
238
 
338
239
  ### Phase 4: Summary
339
240
 
340
241
  ```javascript
341
- // Brief summary using jq
342
- const stats = Bash(`
343
- cat "${issuesPath}" 2>/dev/null | \\
344
- jq -s '[.[] | select(.status == "planned")] | length' 2>/dev/null || echo '0'
345
- `).trim();
242
+ // Count planned issues via CLI
243
+ const plannedIds = Bash(`ccw issue list --status planned --ids`).trim();
244
+ const plannedCount = plannedIds ? plannedIds.split('\n').length : 0;
346
245
 
347
246
  console.log(`
348
- ## Done: ${issues.length} issues → ${stats} planned
247
+ ## Done: ${issueIds.length} issues → ${plannedCount} planned
349
248
 
350
249
  Next: \`/issue:queue\` → \`/issue:execute\`
351
250
  `);
352
251
  ```
353
252
 
354
- ## Solution Format (Closed-Loop Tasks)
355
-
356
- Each solution line in `solutions/{issue-id}.jsonl`:
357
-
358
- ```json
359
- {
360
- "id": "SOL-20251226-001",
361
- "description": "Direct Implementation",
362
- "tasks": [
363
- {
364
- "id": "T1",
365
- "title": "Create auth middleware",
366
- "scope": "src/middleware/",
367
- "action": "Create",
368
- "description": "Create JWT validation middleware",
369
- "modification_points": [
370
- { "file": "src/middleware/auth.ts", "target": "new file", "change": "Create middleware" }
371
- ],
372
-
373
- "implementation": [
374
- "Create auth.ts file in src/middleware/",
375
- "Implement JWT token validation using jsonwebtoken",
376
- "Add error handling for invalid/expired tokens",
377
- "Export middleware function"
378
- ],
379
-
380
- "test": {
381
- "unit": [
382
- "Test valid token passes through",
383
- "Test invalid token returns 401",
384
- "Test expired token returns 401",
385
- "Test missing token returns 401"
386
- ],
387
- "commands": [
388
- "npm test -- --grep 'auth middleware'",
389
- "npm run test:coverage -- src/middleware/auth.ts"
390
- ],
391
- "coverage_target": 80
392
- },
393
-
394
- "regression": [
395
- "npm test -- --grep 'protected routes'",
396
- "npm run test:integration -- auth"
397
- ],
398
-
399
- "acceptance": {
400
- "criteria": [
401
- "Middleware validates JWT tokens successfully",
402
- "Returns 401 for invalid or missing tokens",
403
- "Passes decoded token to request context"
404
- ],
405
- "verification": [
406
- "curl -H 'Authorization: Bearer valid_token' /api/protected → 200",
407
- "curl /api/protected → 401",
408
- "curl -H 'Authorization: Bearer invalid' /api/protected → 401"
409
- ]
410
- },
411
-
412
- "commit": {
413
- "type": "feat",
414
- "scope": "auth",
415
- "message_template": "feat(auth): add JWT validation middleware\n\n- Implement token validation\n- Add error handling for invalid tokens\n- Export for route protection",
416
- "breaking": false
417
- },
418
-
419
- "depends_on": [],
420
- "estimated_minutes": 30,
421
- "executor": "codex"
422
- }
423
- ],
424
- "exploration_context": {
425
- "relevant_files": ["src/config/auth.ts"],
426
- "patterns": "Follow existing middleware pattern"
427
- },
428
- "is_bound": true,
429
- "created_at": "2025-12-26T10:00:00Z",
430
- "bound_at": "2025-12-26T10:05:00Z"
431
- }
432
- ```
433
-
434
253
  ## Error Handling
435
254
 
436
255
  | Error | Resolution |
@@ -441,17 +260,6 @@ Each solution line in `solutions/{issue-id}.jsonl`:
441
260
  | User cancels selection | Skip issue, continue with others |
442
261
  | File conflicts | Agent detects and suggests resolution order |
443
262
 
444
- ## Agent Integration
445
-
446
- The command uses `issue-plan-agent` which:
447
- 1. Performs ACE semantic search per issue
448
- 2. Identifies modification points and patterns
449
- 3. Generates task breakdown with dependencies
450
- 4. Detects cross-issue file conflicts
451
- 5. Outputs solution JSON for registration
452
-
453
- See `.claude/agents/issue-plan-agent.md` for agent specification.
454
-
455
263
  ## Related Commands
456
264
 
457
265
  - `/issue:queue` - Form execution queue from bound solutions