claude-code-workflow 6.3.40 → 6.3.42

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.
@@ -59,7 +59,7 @@ Phase 1: Issue Loading
59
59
  ├─ Parse input (single, comma-separated, or --all-pending)
60
60
  ├─ Fetch issue metadata (ID, title, tags)
61
61
  ├─ Validate issues exist (create if needed)
62
- └─ Group by similarity (shared tags or title keywords, max 3 per batch)
62
+ └─ Create batches by size (max 3 per batch by default)
63
63
 
64
64
  Phase 2: Unified Explore + Plan (issue-plan-agent)
65
65
  ├─ Launch issue-plan-agent per batch
@@ -119,46 +119,17 @@ if (useAllPending) {
119
119
  }
120
120
  // Note: Agent fetches full issue content via `ccw issue status <id> --json`
121
121
 
122
- // Semantic grouping via Gemini CLI (max 4 issues per group)
123
- async function groupBySimilarityGemini(issues) {
124
- const issueSummaries = issues.map(i => ({
125
- id: i.id, title: i.title, tags: i.tags
126
- }));
127
-
128
- const prompt = `
129
- PURPOSE: Group similar issues by semantic similarity for batch processing; maximize within-group coherence; max 4 issues per group
130
- TASK: • Analyze issue titles/tags semantically • Identify functional/architectural clusters • Assign each issue to one group
131
- MODE: analysis
132
- CONTEXT: Issue metadata only
133
- EXPECTED: JSON with groups array, each containing max 4 issue_ids, theme, rationale
134
- CONSTRAINTS: Each issue in exactly one group | Max 4 issues per group | Balance group sizes
135
-
136
- INPUT:
137
- ${JSON.stringify(issueSummaries, null, 2)}
138
-
139
- OUTPUT FORMAT:
140
- {"groups":[{"group_id":1,"theme":"...","issue_ids":["..."],"rationale":"..."}],"ungrouped":[]}
141
- `;
142
-
143
- const taskId = Bash({
144
- command: `ccw cli -p "${prompt}" --tool gemini --mode analysis`,
145
- run_in_background: true, timeout: 600000
146
- });
147
- const output = TaskOutput({ task_id: taskId, block: true });
148
-
149
- // Extract JSON from potential markdown code blocks
150
- function extractJsonFromMarkdown(text) {
151
- const jsonMatch = text.match(/```json\s*\n([\s\S]*?)\n```/) ||
152
- text.match(/```\s*\n([\s\S]*?)\n```/);
153
- return jsonMatch ? jsonMatch[1] : text;
122
+ // Simple size-based batching (max batchSize issues per group)
123
+ function createBatches(issues, batchSize) {
124
+ const batches = [];
125
+ for (let i = 0; i < issues.length; i += batchSize) {
126
+ batches.push(issues.slice(i, i + batchSize));
154
127
  }
155
-
156
- const result = JSON.parse(extractJsonFromMarkdown(output));
157
- return result.groups.map(g => g.issue_ids.map(id => issues.find(i => i.id === id)));
128
+ return batches;
158
129
  }
159
130
 
160
- const batches = await groupBySimilarityGemini(issues);
161
- console.log(`Processing ${issues.length} issues in ${batches.length} batch(es) (max 4 issues/agent)`);
131
+ const batches = createBatches(issues, batchSize);
132
+ console.log(`Processing ${issues.length} issues in ${batches.length} batch(es) (max ${batchSize} issues/agent)`);
162
133
 
163
134
  TodoWrite({
164
135
  todos: batches.map((_, i) => ({
@@ -207,7 +178,9 @@ ${issueList}
207
178
  - Add explicit verification steps to prevent same failure mode
208
179
  6. **If github_url exists**: Add final task to comment on GitHub issue
209
180
  7. Write solution to: .workflow/issues/solutions/{issue-id}.jsonl
210
- 8. Single solution → auto-bind; Multiple → return for selection
181
+ 8. **CRITICAL - Binding Decision**:
182
+ - Single solution → **MUST execute**: ccw issue bind <issue-id> <solution-id>
183
+ - Multiple solutions → Return pending_selection only (no bind)
211
184
 
212
185
  ### Failure-Aware Planning Rules
213
186
  - **Extract failure patterns**: Parse issue.feedback where type='failure' and stage='execute'
@@ -265,35 +238,55 @@ for (let i = 0; i < agentTasks.length; i += MAX_PARALLEL) {
265
238
  }
266
239
  agentResults.push(summary); // Store for Phase 3 conflict aggregation
267
240
 
241
+ // Verify binding for bound issues (agent should have executed bind)
268
242
  for (const item of summary.bound || []) {
269
- console.log(`✓ ${item.issue_id}: ${item.solution_id} (${item.task_count} tasks)`);
243
+ const status = JSON.parse(Bash(`ccw issue status ${item.issue_id} --json`).trim());
244
+ if (status.bound_solution_id === item.solution_id) {
245
+ console.log(`✓ ${item.issue_id}: ${item.solution_id} (${item.task_count} tasks)`);
246
+ } else {
247
+ // Fallback: agent failed to bind, execute here
248
+ Bash(`ccw issue bind ${item.issue_id} ${item.solution_id}`);
249
+ console.log(`✓ ${item.issue_id}: ${item.solution_id} (${item.task_count} tasks) [recovered]`);
250
+ }
270
251
  }
271
- // Collect and notify pending selections
252
+ // Collect pending selections for Phase 3
272
253
  for (const pending of summary.pending_selection || []) {
273
- console.log(`⏳ ${pending.issue_id}: ${pending.solutions.length} solutions → awaiting selection`);
274
254
  pendingSelections.push(pending);
275
255
  }
276
- if (summary.conflicts?.length > 0) {
277
- console.log(`⚠ Conflicts: ${summary.conflicts.length} detected (will resolve in Phase 3)`);
278
- }
279
256
  updateTodo(`Plan batch ${batchIndex + 1}`, 'completed');
280
257
  }
281
258
  }
282
259
  ```
283
260
 
284
- ### Phase 3: Conflict Resolution & Solution Selection
261
+ ### Phase 3: Solution Selection (if pending)
285
262
 
286
- **Conflict Handling:**
287
- - Collect `conflicts` from all agent results
288
- - Low/Medium severity auto-resolve with `recommended_resolution`
289
- - High severity use `AskUserQuestion` to let user choose resolution
263
+ ```javascript
264
+ // Handle multi-solution issues
265
+ for (const pending of pendingSelections) {
266
+ if (pending.solutions.length === 0) continue;
290
267
 
291
- **Multi-Solution Selection:**
292
- - If `pending_selection` contains issues with multiple solutions:
293
- - Use `AskUserQuestion` to present options (solution ID + task count + description)
294
- - Extract selected solution ID from user response
295
- - Verify solution file exists, recover from payload if missing
296
- - Bind selected solution via `ccw issue bind <issue-id> <solution-id>`
268
+ const options = pending.solutions.slice(0, 4).map(sol => ({
269
+ label: `${sol.id} (${sol.task_count} tasks)`,
270
+ description: sol.description || sol.approach || 'No description'
271
+ }));
272
+
273
+ const answer = AskUserQuestion({
274
+ questions: [{
275
+ question: `Issue ${pending.issue_id}: which solution to bind?`,
276
+ header: pending.issue_id,
277
+ options: options,
278
+ multiSelect: false
279
+ }]
280
+ });
281
+
282
+ const selected = answer[Object.keys(answer)[0]];
283
+ if (!selected || selected === 'Other') continue;
284
+
285
+ const solId = selected.split(' ')[0];
286
+ Bash(`ccw issue bind ${pending.issue_id} ${solId}`);
287
+ console.log(`✓ ${pending.issue_id}: ${solId} bound`);
288
+ }
289
+ ```
297
290
 
298
291
  ### Phase 4: Summary
299
292
 
@@ -28,12 +28,13 @@ Queue formation command using **issue-queue-agent** that analyzes all bound solu
28
28
  | Operation | Correct | Incorrect |
29
29
  |-----------|---------|-----------|
30
30
  | List issues (brief) | `ccw issue list --status planned --brief` | `Read('issues.jsonl')` |
31
+ | **Batch solutions (NEW)** | `ccw issue solutions --status planned --brief` | Loop `ccw issue solution <id>` |
31
32
  | List queue (brief) | `ccw issue queue --brief` | `Read('queues/*.json')` |
32
33
  | Read issue details | `ccw issue status <id> --json` | `Read('issues.jsonl')` |
33
34
  | Get next item | `ccw issue next --json` | `Read('queues/*.json')` |
34
35
  | Update status | `ccw issue update <id> --status ...` | Direct file edit |
35
36
  | Sync from queue | `ccw issue update --from-queue` | Direct file edit |
36
- | **Read solution (brief)** | `ccw issue solution <id> --brief` | `Read('solutions/*.jsonl')` |
37
+ | Read solution (single) | `ccw issue solution <id> --brief` | `Read('solutions/*.jsonl')` |
37
38
 
38
39
  **Output Options**:
39
40
  - `--brief`: JSON with minimal fields (id, status, counts)
@@ -131,24 +132,23 @@ Phase 7: Active Queue Check & Decision (REQUIRED)
131
132
  ### Phase 1: Solution Loading & Distribution
132
133
 
133
134
  **Data Loading:**
134
- - Use `ccw issue list --status planned --brief` to get planned issues with `bound_solution_id`
135
- - If no planned issues found display message, suggest `/issue:plan`
136
-
137
- **Solution Brief Loading** (for each planned issue):
138
- ```bash
139
- ccw issue solution <issue-id> --brief
140
- # Returns: [{ solution_id, is_bound, task_count, files_touched[] }]
141
- ```
135
+ - Use `ccw issue solutions --status planned --brief` to get all planned issues with solutions in **one call**
136
+ - Returns: Array of `{ issue_id, solution_id, is_bound, task_count, files_touched[], priority }`
137
+ - If no bound solutions found → display message, suggest `/issue:plan`
142
138
 
143
139
  **Build Solution Objects:**
144
- ```json
145
- {
146
- "issue_id": "ISS-xxx",
147
- "solution_id": "SOL-ISS-xxx-1",
148
- "task_count": 3,
149
- "files_touched": ["src/auth.ts", "src/utils.ts"],
150
- "priority": "medium"
140
+ ```javascript
141
+ // Single CLI call replaces N individual queries
142
+ const result = Bash(`ccw issue solutions --status planned --brief`).trim();
143
+ const solutions = result ? JSON.parse(result) : [];
144
+
145
+ if (solutions.length === 0) {
146
+ console.log('No bound solutions found. Run /issue:plan first.');
147
+ return;
151
148
  }
149
+
150
+ // solutions already in correct format:
151
+ // { issue_id, solution_id, is_bound, task_count, files_touched[], priority }
152
152
  ```
153
153
 
154
154
  **Multi-Queue Distribution** (if `--queues > 1`):