claude-code-workflow 7.2.14 → 7.2.15
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.
- package/.claude/commands/workflow/analyze-with-file.md +7 -0
- package/.codex/skills/analyze-with-file/SKILL.md +1181 -1182
- package/.codex/skills/brainstorm/SKILL.md +723 -725
- package/.codex/skills/brainstorm-with-file/SKILL.md +10 -5
- package/.codex/skills/clean/SKILL.md +33 -26
- package/.codex/skills/collaborative-plan-with-file/SKILL.md +830 -831
- package/.codex/skills/csv-wave-pipeline/SKILL.md +906 -906
- package/.codex/skills/issue-discover/SKILL.md +57 -50
- package/.codex/skills/issue-discover/phases/01-issue-new.md +18 -11
- package/.codex/skills/issue-discover/phases/02-discover.md +31 -26
- package/.codex/skills/issue-discover/phases/03-discover-by-prompt.md +13 -11
- package/.codex/skills/issue-discover/phases/04-quick-execute.md +32 -27
- package/.codex/skills/parallel-dev-cycle/SKILL.md +402 -402
- package/.codex/skills/project-documentation-workflow/SKILL.md +13 -3
- package/.codex/skills/roadmap-with-file/SKILL.md +901 -897
- package/.codex/skills/session-sync/SKILL.md +222 -212
- package/.codex/skills/spec-add/SKILL.md +620 -613
- package/.codex/skills/spec-generator/SKILL.md +2 -2
- package/.codex/skills/spec-generator/phases/01-5-requirement-clarification.md +10 -10
- package/.codex/skills/spec-generator/phases/01-discovery.md +11 -18
- package/.codex/skills/spec-generator/phases/02-product-brief.md +5 -5
- package/.codex/skills/spec-generator/phases/03-requirements.md +7 -7
- package/.codex/skills/spec-generator/phases/04-architecture.md +4 -4
- package/.codex/skills/spec-generator/phases/05-epics-stories.md +5 -6
- package/.codex/skills/spec-generator/phases/06-readiness-check.md +10 -17
- package/.codex/skills/spec-generator/phases/07-issue-export.md +326 -329
- package/.codex/skills/spec-setup/SKILL.md +669 -657
- package/.codex/skills/team-arch-opt/SKILL.md +50 -50
- package/.codex/skills/team-arch-opt/agents/completion-handler.md +3 -3
- package/.codex/skills/team-brainstorm/SKILL.md +724 -725
- package/.codex/skills/team-coordinate/SKILL.md +51 -51
- package/.codex/skills/team-coordinate/agents/completion-handler.md +3 -3
- package/.codex/skills/team-coordinate/agents/plan-reviewer.md +4 -4
- package/.codex/skills/team-designer/SKILL.md +691 -691
- package/.codex/skills/team-designer/agents/requirement-clarifier.md +11 -12
- package/.codex/skills/team-executor/SKILL.md +45 -45
- package/.codex/skills/team-frontend/SKILL.md +45 -45
- package/.codex/skills/team-frontend/agents/completion-handler.md +3 -3
- package/.codex/skills/team-frontend/agents/qa-gate-reviewer.md +4 -4
- package/.codex/skills/team-frontend-debug/SKILL.md +50 -50
- package/.codex/skills/team-frontend-debug/agents/completion-handler.md +3 -3
- package/.codex/skills/team-frontend-debug/agents/conditional-skip-gate.md +4 -4
- package/.codex/skills/team-issue/SKILL.md +751 -740
- package/.codex/skills/team-iterdev/SKILL.md +825 -826
- package/.codex/skills/team-lifecycle-v4/SKILL.md +775 -775
- package/.codex/skills/team-lifecycle-v4/agents/quality-gate.md +165 -165
- package/.codex/skills/team-lifecycle-v4/agents/requirement-clarifier.md +163 -163
- package/.codex/skills/team-perf-opt/SKILL.md +50 -50
- package/.codex/skills/team-perf-opt/agents/completion-handler.md +3 -3
- package/.codex/skills/team-planex-v2/SKILL.md +652 -637
- package/.codex/skills/team-quality-assurance/SKILL.md +51 -52
- package/.codex/skills/team-review/SKILL.md +40 -40
- package/.codex/skills/team-roadmap-dev/SKILL.md +51 -51
- package/.codex/skills/team-roadmap-dev/agents/roadmap-discusser.md +8 -8
- package/.codex/skills/team-tech-debt/SKILL.md +50 -50
- package/.codex/skills/team-tech-debt/agents/plan-approver.md +5 -5
- package/.codex/skills/team-testing/SKILL.md +51 -52
- package/.codex/skills/team-uidesign/SKILL.md +40 -40
- package/.codex/skills/team-uidesign/agents/completion-handler.md +177 -177
- package/.codex/skills/team-ultra-analyze/SKILL.md +786 -787
- package/.codex/skills/team-ultra-analyze/agents/discussion-feedback.md +8 -8
- package/.codex/skills/team-ux-improve/SKILL.md +51 -52
- package/.codex/skills/team-ux-improve/agents/ux-designer.md +2 -2
- package/.codex/skills/team-ux-improve/agents/ux-explorer.md +1 -1
- package/.codex/skills/unified-execute-with-file/SKILL.md +797 -796
- package/.codex/skills/workflow-execute/SKILL.md +1117 -1118
- package/.codex/skills/workflow-lite-planex/SKILL.md +1144 -1141
- package/.codex/skills/workflow-plan/SKILL.md +631 -636
- package/.codex/skills/workflow-tdd-plan/SKILL.md +753 -759
- package/.codex/skills/workflow-test-fix-cycle/SKILL.md +402 -392
- package/README.md +25 -0
- package/ccw/dist/commands/install.d.ts.map +1 -1
- package/ccw/dist/commands/install.js +12 -0
- package/ccw/dist/commands/install.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,725 +1,723 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: brainstorm
|
|
3
|
-
description: |
|
|
4
|
-
Dual-mode brainstorming pipeline. Auto mode: framework generation → parallel role analysis
|
|
5
|
-
(spawn_agents_on_csv) → cross-role synthesis. Single role mode: individual role analysis.
|
|
6
|
-
CSV-driven parallel coordination with NDJSON discovery board.
|
|
7
|
-
argument-hint: "[-y|--yes] [--count N] [--session ID] [--skip-questions] [--style-skill PKG] \"topic\" | <role-name> [--session ID]"
|
|
8
|
-
allowed-tools: spawn_agents_on_csv, spawn_agent, wait, send_input, close_agent,
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## Auto Mode
|
|
12
|
-
|
|
13
|
-
When `--yes` or `-y`: Auto-select auto mode, auto-select recommended roles, skip all clarification questions, use defaults.
|
|
14
|
-
|
|
15
|
-
# Brainstorm
|
|
16
|
-
|
|
17
|
-
## Usage
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
$brainstorm "Build real-time collaboration platform" --count 3
|
|
21
|
-
$brainstorm -y "Design payment system" --count 5
|
|
22
|
-
$brainstorm "Build notification system" --style-skill material-design
|
|
23
|
-
$brainstorm system-architect --session WFS-xxx
|
|
24
|
-
$brainstorm ux-expert --include-questions
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
**Flags**:
|
|
28
|
-
- `-y, --yes`: Skip all confirmations (auto mode)
|
|
29
|
-
- `--count N`: Number of roles to select (default: 3, max: 9)
|
|
30
|
-
- `--session ID`: Use existing session
|
|
31
|
-
- `--skip-questions / --include-questions`: Control interactive Q&A per role
|
|
32
|
-
- `--style-skill PKG`: Style skill package for ui-designer
|
|
33
|
-
- `--update`: Update existing role analysis
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## Overview
|
|
38
|
-
|
|
39
|
-
Dual-mode brainstorming with CSV-driven parallel role analysis. Auto mode runs a full pipeline; single role mode runs one role analysis independently.
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
┌──────────────────────────────────────────────────────────────────┐
|
|
43
|
-
│ BRAINSTORM PIPELINE │
|
|
44
|
-
├──────────────────────────────────────────────────────────────────┤
|
|
45
|
-
│ │
|
|
46
|
-
│ Phase 1: Mode Detection & Routing │
|
|
47
|
-
│ ├─ Parse flags and arguments │
|
|
48
|
-
│ └─ Route to Auto Mode or Single Role Mode │
|
|
49
|
-
│ │
|
|
50
|
-
│ ═══ Auto Mode ═══ │
|
|
51
|
-
│ │
|
|
52
|
-
│ Phase 2: Interactive Framework Generation │
|
|
53
|
-
│ ├─ Context collection → Topic analysis → Role selection │
|
|
54
|
-
│ ├─ Generate guidance-specification.md │
|
|
55
|
-
│ ├─ Generate roles.csv (1 row per selected role) │
|
|
56
|
-
│ └─ User validates (skip if -y) │
|
|
57
|
-
│ │
|
|
58
|
-
│ Phase 3: Wave Role Analysis (spawn_agents_on_csv) │
|
|
59
|
-
│ ├─ spawn_agents_on_csv(role instruction template) │
|
|
60
|
-
│ ├─ Each role agent produces analysis.md + sub-documents │
|
|
61
|
-
│ └─ discoveries.ndjson shared across role agents │
|
|
62
|
-
│ │
|
|
63
|
-
│ Phase 4: Synthesis Integration │
|
|
64
|
-
│ ├─ Read all role analyses (read-only) │
|
|
65
|
-
│ ├─ Cross-role analysis → conflict detection │
|
|
66
|
-
│ ├─ Feature spec generation │
|
|
67
|
-
│ └─ Output: feature-specs/ + feature-index.json │
|
|
68
|
-
│ │
|
|
69
|
-
│ ═══ Single Role Mode ═══ │
|
|
70
|
-
│ │
|
|
71
|
-
│ Phase 3S: Single Role Analysis (spawn_agent) │
|
|
72
|
-
│ ├─ spawn_agent(conceptual-planning-agent) │
|
|
73
|
-
│ └─ Output: {role}/analysis*.md │
|
|
74
|
-
│ │
|
|
75
|
-
└──────────────────────────────────────────────────────────────────┘
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
---
|
|
79
|
-
|
|
80
|
-
## Context Flow
|
|
81
|
-
|
|
82
|
-
```
|
|
83
|
-
roles.csv feature-specs/
|
|
84
|
-
┌──────────────┐ ┌──────────────────┐
|
|
85
|
-
│ R1: sys-arch │──findings───→│ F-001-auth.md │
|
|
86
|
-
│ analysis.md │ │ (cross-role spec) │
|
|
87
|
-
├──────────────┤ ├──────────────────┤
|
|
88
|
-
│ R2: ui-design│──findings───→│ F-002-ui.md │
|
|
89
|
-
│ analysis.md │ │ (cross-role spec) │
|
|
90
|
-
├──────────────┤ ├──────────────────┤
|
|
91
|
-
│ R3: test-str │──findings───→│ F-003-test.md │
|
|
92
|
-
│ analysis.md │ │ (cross-role spec) │
|
|
93
|
-
└──────────────┘ └──────────────────┘
|
|
94
|
-
|
|
95
|
-
Two context channels:
|
|
96
|
-
1. Directed: role findings → synthesis → feature specs
|
|
97
|
-
2. Broadcast: discoveries.ndjson (append-only shared board)
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
---
|
|
101
|
-
|
|
102
|
-
## CSV Schema
|
|
103
|
-
|
|
104
|
-
### roles.csv
|
|
105
|
-
|
|
106
|
-
```csv
|
|
107
|
-
id,role,title,focus,deps,wave,status,findings,output_files,error
|
|
108
|
-
"R1","system-architect","系统架构师","Technical architecture, scalability","","1","pending","","",""
|
|
109
|
-
"R2","ui-designer","UI设计师","Visual design, mockups","","1","pending","","",""
|
|
110
|
-
"R3","test-strategist","测试策略师","Test strategy, quality","","1","pending","","",""
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
**Columns**:
|
|
114
|
-
|
|
115
|
-
| Column | Phase | Description |
|
|
116
|
-
|--------|-------|-------------|
|
|
117
|
-
| `id` | Input | Role ID: R1, R2, ... |
|
|
118
|
-
| `role` | Input | Role identifier (e.g., system-architect) |
|
|
119
|
-
| `title` | Input | Role display title |
|
|
120
|
-
| `focus` | Input | Role focus areas and keywords |
|
|
121
|
-
| `deps` | Input | Dependency IDs (usually empty — all wave 1) |
|
|
122
|
-
| `wave` | Computed | Wave number (usually 1 for all roles) |
|
|
123
|
-
| `status` | Output | `pending` → `completed` / `failed` |
|
|
124
|
-
| `findings` | Output | Key discoveries (max 800 chars) |
|
|
125
|
-
| `output_files` | Output | Generated analysis files (semicolon-separated) |
|
|
126
|
-
| `error` | Output | Error message if failed |
|
|
127
|
-
|
|
128
|
-
---
|
|
129
|
-
|
|
130
|
-
## Available Roles
|
|
131
|
-
|
|
132
|
-
| Role ID | Title | Focus Area |
|
|
133
|
-
|---------|-------|------------|
|
|
134
|
-
| `data-architect` | 数据架构师 | Data models, storage strategies, data flow |
|
|
135
|
-
| `product-manager` | 产品经理 | Product strategy, roadmap, prioritization |
|
|
136
|
-
| `product-owner` | 产品负责人 | Backlog management, user stories, acceptance criteria |
|
|
137
|
-
| `scrum-master` | 敏捷教练 | Process facilitation, impediment removal |
|
|
138
|
-
| `subject-matter-expert` | 领域专家 | Domain knowledge, business rules, compliance |
|
|
139
|
-
| `system-architect` | 系统架构师 | Technical architecture, scalability, integration |
|
|
140
|
-
| `test-strategist` | 测试策略师 | Test strategy, quality assurance |
|
|
141
|
-
| `ui-designer` | UI设计师 | Visual design, mockups, design systems |
|
|
142
|
-
| `ux-expert` | UX专家 | User research, information architecture, journey |
|
|
143
|
-
|
|
144
|
-
---
|
|
145
|
-
|
|
146
|
-
## Session Structure
|
|
147
|
-
|
|
148
|
-
```
|
|
149
|
-
.workflow/active/WFS-{topic}/
|
|
150
|
-
├── workflow-session.json # Session metadata
|
|
151
|
-
├── .process/
|
|
152
|
-
│ └── context-package.json # Phase 0 context
|
|
153
|
-
├── roles.csv # Role analysis state (Phase 2-3)
|
|
154
|
-
├── discoveries.ndjson # Shared discovery board
|
|
155
|
-
└── .brainstorming/
|
|
156
|
-
├── guidance-specification.md # Framework (Phase 2)
|
|
157
|
-
├── feature-index.json # Feature index (Phase 4)
|
|
158
|
-
├── synthesis-changelog.md # Synthesis audit trail (Phase 4)
|
|
159
|
-
├── feature-specs/ # Feature specs (Phase 4)
|
|
160
|
-
│ ├── F-001-{slug}.md
|
|
161
|
-
│ └── F-00N-{slug}.md
|
|
162
|
-
└── {role}/ # Role analyses (Phase 3, immutable)
|
|
163
|
-
├── {role}-context.md # Interactive Q&A
|
|
164
|
-
├── analysis.md # Main/index document
|
|
165
|
-
├── analysis-cross-cutting.md # Cross-feature
|
|
166
|
-
└── analysis-F-{id}-{slug}.md # Per-feature
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
---
|
|
170
|
-
|
|
171
|
-
## Implementation
|
|
172
|
-
|
|
173
|
-
### Session Initialization
|
|
174
|
-
|
|
175
|
-
```javascript
|
|
176
|
-
const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString()
|
|
177
|
-
|
|
178
|
-
// Parse flags
|
|
179
|
-
const AUTO_YES = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y')
|
|
180
|
-
const countMatch = $ARGUMENTS.match(/--count\s+(\d+)/)
|
|
181
|
-
const roleCount = countMatch ? Math.min(parseInt(countMatch[1]), 9) : 3
|
|
182
|
-
const sessionMatch = $ARGUMENTS.match(/--session\s+(\S+)/)
|
|
183
|
-
const existingSessionId = sessionMatch ? sessionMatch[1] : null
|
|
184
|
-
const skipQuestions = $ARGUMENTS.includes('--skip-questions')
|
|
185
|
-
const includeQuestions = $ARGUMENTS.includes('--include-questions')
|
|
186
|
-
const styleSkillMatch = $ARGUMENTS.match(/--style-skill\s+(\S+)/)
|
|
187
|
-
const styleSkill = styleSkillMatch ? styleSkillMatch[1] : null
|
|
188
|
-
const updateMode = $ARGUMENTS.includes('--update')
|
|
189
|
-
|
|
190
|
-
// Role detection
|
|
191
|
-
const VALID_ROLES = [
|
|
192
|
-
'data-architect', 'product-manager', 'product-owner', 'scrum-master',
|
|
193
|
-
'subject-matter-expert', 'system-architect', 'test-strategist',
|
|
194
|
-
'ui-designer', 'ux-expert'
|
|
195
|
-
]
|
|
196
|
-
const cleanArgs = $ARGUMENTS
|
|
197
|
-
.replace(/--yes|-y|--count\s+\d+|--session\s+\S+|--skip-questions|--include-questions|--style-skill\s+\S+|--update/g, '')
|
|
198
|
-
.trim()
|
|
199
|
-
const firstArg = cleanArgs.split(/\s+/)[0]
|
|
200
|
-
const isRole = VALID_ROLES.includes(firstArg)
|
|
201
|
-
|
|
202
|
-
// Mode detection
|
|
203
|
-
let executionMode
|
|
204
|
-
if (AUTO_YES) {
|
|
205
|
-
executionMode = 'auto'
|
|
206
|
-
} else if (isRole) {
|
|
207
|
-
executionMode = 'single-role'
|
|
208
|
-
} else if (cleanArgs) {
|
|
209
|
-
executionMode = 'auto'
|
|
210
|
-
} else {
|
|
211
|
-
executionMode = null // Ask user
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
const topic = isRole
|
|
215
|
-
? cleanArgs.replace(firstArg, '').trim()
|
|
216
|
-
: cleanArgs.replace(/^["']|["']$/g, '')
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
---
|
|
220
|
-
|
|
221
|
-
### Phase 1: Mode Detection & Routing
|
|
222
|
-
|
|
223
|
-
**Objective**: Parse arguments, determine execution mode, prepare session.
|
|
224
|
-
|
|
225
|
-
**Steps**:
|
|
226
|
-
|
|
227
|
-
1. **Detect Mode**
|
|
228
|
-
|
|
229
|
-
```javascript
|
|
230
|
-
if (executionMode === null) {
|
|
231
|
-
const modeAnswer =
|
|
232
|
-
questions: [{
|
|
233
|
-
question: "Choose brainstorming mode:",
|
|
234
|
-
header: "Mode",
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
{ label: "
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
- `executionMode === '
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
•
|
|
299
|
-
•
|
|
300
|
-
•
|
|
301
|
-
•
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
console.log(
|
|
319
|
-
console.log(`
|
|
320
|
-
console.log(
|
|
321
|
-
console.log(
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
console.log(
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
{ label: "
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
##
|
|
366
|
-
${
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
})
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
**
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
##
|
|
476
|
-
${
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
-
|
|
490
|
-
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
- \`
|
|
508
|
-
- \`
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
{
|
|
519
|
-
"
|
|
520
|
-
"
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
const
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
**
|
|
547
|
-
**
|
|
548
|
-
|
|
549
|
-
${
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
${
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
})
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
const
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
})
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
###
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
const
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
const
|
|
687
|
-
const
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
|
711
|
-
|
|
712
|
-
|
|
|
713
|
-
|
|
|
714
|
-
|
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
>
|
|
723
|
-
> - Phase
|
|
724
|
-
> - Phase 3: Re-read `roles.csv` for progress state
|
|
725
|
-
> - Phase 4: Re-read `feature-index.json` and `roles.csv`
|
|
1
|
+
---
|
|
2
|
+
name: brainstorm
|
|
3
|
+
description: |
|
|
4
|
+
Dual-mode brainstorming pipeline. Auto mode: framework generation → parallel role analysis
|
|
5
|
+
(spawn_agents_on_csv) → cross-role synthesis. Single role mode: individual role analysis.
|
|
6
|
+
CSV-driven parallel coordination with NDJSON discovery board.
|
|
7
|
+
argument-hint: "[-y|--yes] [--count N] [--session ID] [--skip-questions] [--style-skill PKG] \"topic\" | <role-name> [--session ID]"
|
|
8
|
+
allowed-tools: spawn_agents_on_csv, spawn_agent, wait, send_input, close_agent, request_user_input, Read, Write, Edit, Bash, Glob, Grep
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Auto Mode
|
|
12
|
+
|
|
13
|
+
When `--yes` or `-y`: Auto-select auto mode, auto-select recommended roles, skip all clarification questions, use defaults. **This skill is brainstorming-only — it produces analysis and feature specs but NEVER executes code or modifies source files.**
|
|
14
|
+
|
|
15
|
+
# Brainstorm
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
$brainstorm "Build real-time collaboration platform" --count 3
|
|
21
|
+
$brainstorm -y "Design payment system" --count 5
|
|
22
|
+
$brainstorm "Build notification system" --style-skill material-design
|
|
23
|
+
$brainstorm system-architect --session WFS-xxx
|
|
24
|
+
$brainstorm ux-expert --include-questions
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Flags**:
|
|
28
|
+
- `-y, --yes`: Skip all confirmations (auto mode)
|
|
29
|
+
- `--count N`: Number of roles to select (default: 3, max: 9)
|
|
30
|
+
- `--session ID`: Use existing session
|
|
31
|
+
- `--skip-questions / --include-questions`: Control interactive Q&A per role
|
|
32
|
+
- `--style-skill PKG`: Style skill package for ui-designer
|
|
33
|
+
- `--update`: Update existing role analysis
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Overview
|
|
38
|
+
|
|
39
|
+
Dual-mode brainstorming with CSV-driven parallel role analysis. Auto mode runs a full pipeline; single role mode runs one role analysis independently.
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
┌──────────────────────────────────────────────────────────────────┐
|
|
43
|
+
│ BRAINSTORM PIPELINE │
|
|
44
|
+
├──────────────────────────────────────────────────────────────────┤
|
|
45
|
+
│ │
|
|
46
|
+
│ Phase 1: Mode Detection & Routing │
|
|
47
|
+
│ ├─ Parse flags and arguments │
|
|
48
|
+
│ └─ Route to Auto Mode or Single Role Mode │
|
|
49
|
+
│ │
|
|
50
|
+
│ ═══ Auto Mode ═══ │
|
|
51
|
+
│ │
|
|
52
|
+
│ Phase 2: Interactive Framework Generation │
|
|
53
|
+
│ ├─ Context collection → Topic analysis → Role selection │
|
|
54
|
+
│ ├─ Generate guidance-specification.md │
|
|
55
|
+
│ ├─ Generate roles.csv (1 row per selected role) │
|
|
56
|
+
│ └─ User validates (skip if -y) │
|
|
57
|
+
│ │
|
|
58
|
+
│ Phase 3: Wave Role Analysis (spawn_agents_on_csv) │
|
|
59
|
+
│ ├─ spawn_agents_on_csv(role instruction template) │
|
|
60
|
+
│ ├─ Each role agent produces analysis.md + sub-documents │
|
|
61
|
+
│ └─ discoveries.ndjson shared across role agents │
|
|
62
|
+
│ │
|
|
63
|
+
│ Phase 4: Synthesis Integration │
|
|
64
|
+
│ ├─ Read all role analyses (read-only) │
|
|
65
|
+
│ ├─ Cross-role analysis → conflict detection │
|
|
66
|
+
│ ├─ Feature spec generation │
|
|
67
|
+
│ └─ Output: feature-specs/ + feature-index.json │
|
|
68
|
+
│ │
|
|
69
|
+
│ ═══ Single Role Mode ═══ │
|
|
70
|
+
│ │
|
|
71
|
+
│ Phase 3S: Single Role Analysis (spawn_agent) │
|
|
72
|
+
│ ├─ spawn_agent(conceptual-planning-agent) │
|
|
73
|
+
│ └─ Output: {role}/analysis*.md │
|
|
74
|
+
│ │
|
|
75
|
+
└──────────────────────────────────────────────────────────────────┘
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Context Flow
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
roles.csv feature-specs/
|
|
84
|
+
┌──────────────┐ ┌──────────────────┐
|
|
85
|
+
│ R1: sys-arch │──findings───→│ F-001-auth.md │
|
|
86
|
+
│ analysis.md │ │ (cross-role spec) │
|
|
87
|
+
├──────────────┤ ├──────────────────┤
|
|
88
|
+
│ R2: ui-design│──findings───→│ F-002-ui.md │
|
|
89
|
+
│ analysis.md │ │ (cross-role spec) │
|
|
90
|
+
├──────────────┤ ├──────────────────┤
|
|
91
|
+
│ R3: test-str │──findings───→│ F-003-test.md │
|
|
92
|
+
│ analysis.md │ │ (cross-role spec) │
|
|
93
|
+
└──────────────┘ └──────────────────┘
|
|
94
|
+
|
|
95
|
+
Two context channels:
|
|
96
|
+
1. Directed: role findings → synthesis → feature specs
|
|
97
|
+
2. Broadcast: discoveries.ndjson (append-only shared board)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## CSV Schema
|
|
103
|
+
|
|
104
|
+
### roles.csv
|
|
105
|
+
|
|
106
|
+
```csv
|
|
107
|
+
id,role,title,focus,deps,wave,status,findings,output_files,error
|
|
108
|
+
"R1","system-architect","系统架构师","Technical architecture, scalability","","1","pending","","",""
|
|
109
|
+
"R2","ui-designer","UI设计师","Visual design, mockups","","1","pending","","",""
|
|
110
|
+
"R3","test-strategist","测试策略师","Test strategy, quality","","1","pending","","",""
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Columns**:
|
|
114
|
+
|
|
115
|
+
| Column | Phase | Description |
|
|
116
|
+
|--------|-------|-------------|
|
|
117
|
+
| `id` | Input | Role ID: R1, R2, ... |
|
|
118
|
+
| `role` | Input | Role identifier (e.g., system-architect) |
|
|
119
|
+
| `title` | Input | Role display title |
|
|
120
|
+
| `focus` | Input | Role focus areas and keywords |
|
|
121
|
+
| `deps` | Input | Dependency IDs (usually empty — all wave 1) |
|
|
122
|
+
| `wave` | Computed | Wave number (usually 1 for all roles) |
|
|
123
|
+
| `status` | Output | `pending` → `completed` / `failed` |
|
|
124
|
+
| `findings` | Output | Key discoveries (max 800 chars) |
|
|
125
|
+
| `output_files` | Output | Generated analysis files (semicolon-separated) |
|
|
126
|
+
| `error` | Output | Error message if failed |
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Available Roles
|
|
131
|
+
|
|
132
|
+
| Role ID | Title | Focus Area |
|
|
133
|
+
|---------|-------|------------|
|
|
134
|
+
| `data-architect` | 数据架构师 | Data models, storage strategies, data flow |
|
|
135
|
+
| `product-manager` | 产品经理 | Product strategy, roadmap, prioritization |
|
|
136
|
+
| `product-owner` | 产品负责人 | Backlog management, user stories, acceptance criteria |
|
|
137
|
+
| `scrum-master` | 敏捷教练 | Process facilitation, impediment removal |
|
|
138
|
+
| `subject-matter-expert` | 领域专家 | Domain knowledge, business rules, compliance |
|
|
139
|
+
| `system-architect` | 系统架构师 | Technical architecture, scalability, integration |
|
|
140
|
+
| `test-strategist` | 测试策略师 | Test strategy, quality assurance |
|
|
141
|
+
| `ui-designer` | UI设计师 | Visual design, mockups, design systems |
|
|
142
|
+
| `ux-expert` | UX专家 | User research, information architecture, journey |
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Session Structure
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
.workflow/active/WFS-{topic}/
|
|
150
|
+
├── workflow-session.json # Session metadata
|
|
151
|
+
├── .process/
|
|
152
|
+
│ └── context-package.json # Phase 0 context
|
|
153
|
+
├── roles.csv # Role analysis state (Phase 2-3)
|
|
154
|
+
├── discoveries.ndjson # Shared discovery board
|
|
155
|
+
└── .brainstorming/
|
|
156
|
+
├── guidance-specification.md # Framework (Phase 2)
|
|
157
|
+
├── feature-index.json # Feature index (Phase 4)
|
|
158
|
+
├── synthesis-changelog.md # Synthesis audit trail (Phase 4)
|
|
159
|
+
├── feature-specs/ # Feature specs (Phase 4)
|
|
160
|
+
│ ├── F-001-{slug}.md
|
|
161
|
+
│ └── F-00N-{slug}.md
|
|
162
|
+
└── {role}/ # Role analyses (Phase 3, immutable)
|
|
163
|
+
├── {role}-context.md # Interactive Q&A
|
|
164
|
+
├── analysis.md # Main/index document
|
|
165
|
+
├── analysis-cross-cutting.md # Cross-feature
|
|
166
|
+
└── analysis-F-{id}-{slug}.md # Per-feature
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Implementation
|
|
172
|
+
|
|
173
|
+
### Session Initialization
|
|
174
|
+
|
|
175
|
+
```javascript
|
|
176
|
+
const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString()
|
|
177
|
+
|
|
178
|
+
// Parse flags
|
|
179
|
+
const AUTO_YES = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y')
|
|
180
|
+
const countMatch = $ARGUMENTS.match(/--count\s+(\d+)/)
|
|
181
|
+
const roleCount = countMatch ? Math.min(parseInt(countMatch[1]), 9) : 3
|
|
182
|
+
const sessionMatch = $ARGUMENTS.match(/--session\s+(\S+)/)
|
|
183
|
+
const existingSessionId = sessionMatch ? sessionMatch[1] : null
|
|
184
|
+
const skipQuestions = $ARGUMENTS.includes('--skip-questions')
|
|
185
|
+
const includeQuestions = $ARGUMENTS.includes('--include-questions')
|
|
186
|
+
const styleSkillMatch = $ARGUMENTS.match(/--style-skill\s+(\S+)/)
|
|
187
|
+
const styleSkill = styleSkillMatch ? styleSkillMatch[1] : null
|
|
188
|
+
const updateMode = $ARGUMENTS.includes('--update')
|
|
189
|
+
|
|
190
|
+
// Role detection
|
|
191
|
+
const VALID_ROLES = [
|
|
192
|
+
'data-architect', 'product-manager', 'product-owner', 'scrum-master',
|
|
193
|
+
'subject-matter-expert', 'system-architect', 'test-strategist',
|
|
194
|
+
'ui-designer', 'ux-expert'
|
|
195
|
+
]
|
|
196
|
+
const cleanArgs = $ARGUMENTS
|
|
197
|
+
.replace(/--yes|-y|--count\s+\d+|--session\s+\S+|--skip-questions|--include-questions|--style-skill\s+\S+|--update/g, '')
|
|
198
|
+
.trim()
|
|
199
|
+
const firstArg = cleanArgs.split(/\s+/)[0]
|
|
200
|
+
const isRole = VALID_ROLES.includes(firstArg)
|
|
201
|
+
|
|
202
|
+
// Mode detection
|
|
203
|
+
let executionMode
|
|
204
|
+
if (AUTO_YES) {
|
|
205
|
+
executionMode = 'auto'
|
|
206
|
+
} else if (isRole) {
|
|
207
|
+
executionMode = 'single-role'
|
|
208
|
+
} else if (cleanArgs) {
|
|
209
|
+
executionMode = 'auto'
|
|
210
|
+
} else {
|
|
211
|
+
executionMode = null // Ask user
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const topic = isRole
|
|
215
|
+
? cleanArgs.replace(firstArg, '').trim()
|
|
216
|
+
: cleanArgs.replace(/^["']|["']$/g, '')
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
### Phase 1: Mode Detection & Routing
|
|
222
|
+
|
|
223
|
+
**Objective**: Parse arguments, determine execution mode, prepare session.
|
|
224
|
+
|
|
225
|
+
**Steps**:
|
|
226
|
+
|
|
227
|
+
1. **Detect Mode**
|
|
228
|
+
|
|
229
|
+
```javascript
|
|
230
|
+
if (executionMode === null) {
|
|
231
|
+
const modeAnswer = request_user_input({
|
|
232
|
+
questions: [{
|
|
233
|
+
question: "Choose brainstorming mode:",
|
|
234
|
+
header: "Mode",
|
|
235
|
+
options: [
|
|
236
|
+
{ label: "Auto Mode (Recommended)", description: "Full pipeline: framework → parallel roles → synthesis" },
|
|
237
|
+
{ label: "Single Role", description: "Run one role analysis independently" }
|
|
238
|
+
]
|
|
239
|
+
}]
|
|
240
|
+
})
|
|
241
|
+
executionMode = modeAnswer.Mode.startsWith('Auto') ? 'auto' : 'single-role'
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
2. **Session Setup**
|
|
246
|
+
|
|
247
|
+
```javascript
|
|
248
|
+
let sessionId, sessionFolder
|
|
249
|
+
|
|
250
|
+
if (existingSessionId) {
|
|
251
|
+
sessionId = existingSessionId
|
|
252
|
+
sessionFolder = `.workflow/active/${sessionId}`
|
|
253
|
+
} else if (executionMode === 'auto') {
|
|
254
|
+
const slug = topic.toLowerCase().replace(/[^a-z0-9\u4e00-\u9fa5]+/g, '-').substring(0, 40)
|
|
255
|
+
sessionId = `WFS-${slug}`
|
|
256
|
+
sessionFolder = `.workflow/active/${sessionId}`
|
|
257
|
+
Bash(`mkdir -p "${sessionFolder}/.brainstorming" "${sessionFolder}/.process"`)
|
|
258
|
+
|
|
259
|
+
// Initialize workflow-session.json
|
|
260
|
+
Write(`${sessionFolder}/workflow-session.json`, JSON.stringify({
|
|
261
|
+
session_id: sessionId,
|
|
262
|
+
topic: topic,
|
|
263
|
+
status: 'brainstorming',
|
|
264
|
+
execution_mode: executionMode,
|
|
265
|
+
created_at: getUtc8ISOString()
|
|
266
|
+
}, null, 2))
|
|
267
|
+
} else {
|
|
268
|
+
// Single role mode requires existing session
|
|
269
|
+
const existing = Bash(`ls -d .workflow/active/WFS-* 2>/dev/null | head -1`).trim()
|
|
270
|
+
if (!existing) {
|
|
271
|
+
console.log('ERROR: No active session found. Run auto mode first to create a session.')
|
|
272
|
+
return
|
|
273
|
+
}
|
|
274
|
+
sessionId = existing.split('/').pop()
|
|
275
|
+
sessionFolder = existing
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**Route**:
|
|
280
|
+
- `executionMode === 'auto'` → Phase 2
|
|
281
|
+
- `executionMode === 'single-role'` → Phase 3S
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
### Phase 2: Interactive Framework Generation (Auto Mode)
|
|
286
|
+
|
|
287
|
+
**Objective**: Analyze topic, select roles, generate guidance-specification.md and roles.csv.
|
|
288
|
+
|
|
289
|
+
**Steps**:
|
|
290
|
+
|
|
291
|
+
1. **Analyze Topic & Select Roles**
|
|
292
|
+
|
|
293
|
+
```javascript
|
|
294
|
+
Bash({
|
|
295
|
+
command: `ccw cli -p "PURPOSE: Analyze brainstorming topic and recommend ${roleCount} expert roles for multi-perspective analysis. Success = well-matched roles with clear focus areas.
|
|
296
|
+
TASK:
|
|
297
|
+
• Analyze topic domain, complexity, and key dimensions
|
|
298
|
+
• Select ${roleCount} roles from: data-architect, product-manager, product-owner, scrum-master, subject-matter-expert, system-architect, test-strategist, ui-designer, ux-expert
|
|
299
|
+
• For each role: define focus area, key questions, and analysis scope
|
|
300
|
+
• Identify potential cross-role conflicts or synergies
|
|
301
|
+
• Generate feature decomposition if topic has distinct components
|
|
302
|
+
MODE: analysis
|
|
303
|
+
CONTEXT: @**/*
|
|
304
|
+
EXPECTED: JSON: {analysis: {domain, complexity, dimensions[]}, roles: [{id, role, title, focus, key_questions[]}], features: [{id, title, description}]}
|
|
305
|
+
CONSTRAINTS: Select exactly ${roleCount} roles | Each role must have distinct perspective | Roles must cover topic comprehensively
|
|
306
|
+
|
|
307
|
+
TOPIC: ${topic}" --tool gemini --mode analysis --rule planning-breakdown-task-steps`,
|
|
308
|
+
run_in_background: true
|
|
309
|
+
})
|
|
310
|
+
// Wait for CLI completion → { analysis, roles[], features[] }
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
2. **User Validation** (skip if AUTO_YES)
|
|
314
|
+
|
|
315
|
+
```javascript
|
|
316
|
+
if (!AUTO_YES) {
|
|
317
|
+
console.log(`\n## Brainstorm Framework\n`)
|
|
318
|
+
console.log(`Topic: ${topic}`)
|
|
319
|
+
console.log(`Domain: ${analysis.domain} | Complexity: ${analysis.complexity}`)
|
|
320
|
+
console.log(`\nSelected Roles (${roles.length}):`)
|
|
321
|
+
roles.forEach(r => console.log(` - [${r.id}] ${r.title}: ${r.focus}`))
|
|
322
|
+
if (features.length > 0) {
|
|
323
|
+
console.log(`\nFeatures (${features.length}):`)
|
|
324
|
+
features.forEach(f => console.log(` - [${f.id}] ${f.title}`))
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const answer = request_user_input({
|
|
328
|
+
questions: [{
|
|
329
|
+
question: "Approve brainstorm framework?",
|
|
330
|
+
header: "Validate",
|
|
331
|
+
options: [
|
|
332
|
+
{ label: "Approve", description: "Proceed with role analysis" },
|
|
333
|
+
{ label: "Modify Roles", description: "Change role selection" },
|
|
334
|
+
{ label: "Cancel", description: "Abort" }
|
|
335
|
+
]
|
|
336
|
+
}]
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
if (answer.Validate === "Cancel") return
|
|
340
|
+
if (answer.Validate === "Modify Roles") {
|
|
341
|
+
// Allow user to adjust via request_user_input
|
|
342
|
+
const roleAnswer = request_user_input({
|
|
343
|
+
questions: [{
|
|
344
|
+
question: "Select roles for analysis:",
|
|
345
|
+
header: "Roles",
|
|
346
|
+
options: VALID_ROLES.map(r => ({
|
|
347
|
+
label: r,
|
|
348
|
+
description: roles.find(sel => sel.role === r)?.focus || ''
|
|
349
|
+
}))
|
|
350
|
+
}]
|
|
351
|
+
})
|
|
352
|
+
// Rebuild roles[] from selection
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
3. **Generate Guidance Specification**
|
|
358
|
+
|
|
359
|
+
```javascript
|
|
360
|
+
const guidanceContent = `# Guidance Specification
|
|
361
|
+
|
|
362
|
+
## Topic
|
|
363
|
+
${topic}
|
|
364
|
+
|
|
365
|
+
## Analysis
|
|
366
|
+
- **Domain**: ${analysis.domain}
|
|
367
|
+
- **Complexity**: ${analysis.complexity}
|
|
368
|
+
- **Dimensions**: ${analysis.dimensions.join(', ')}
|
|
369
|
+
|
|
370
|
+
## Selected Roles
|
|
371
|
+
${roles.map(r => `### ${r.title} (${r.role})
|
|
372
|
+
- **Focus**: ${r.focus}
|
|
373
|
+
- **Key Questions**: ${r.key_questions.join('; ')}`).join('\n\n')}
|
|
374
|
+
|
|
375
|
+
## Features
|
|
376
|
+
${features.map(f => `- **[${f.id}] ${f.title}**: ${f.description}`).join('\n')}
|
|
377
|
+
`
|
|
378
|
+
Write(`${sessionFolder}/.brainstorming/guidance-specification.md`, guidanceContent)
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
4. **Generate roles.csv**
|
|
382
|
+
|
|
383
|
+
```javascript
|
|
384
|
+
const header = 'id,role,title,focus,deps,wave,status,findings,output_files,error'
|
|
385
|
+
const rows = roles.map(r =>
|
|
386
|
+
[r.id, r.role, r.title, r.focus, '', '1', 'pending', '', '', '']
|
|
387
|
+
.map(v => `"${String(v).replace(/"/g, '""')}"`)
|
|
388
|
+
.join(',')
|
|
389
|
+
)
|
|
390
|
+
Write(`${sessionFolder}/roles.csv`, [header, ...rows].join('\n'))
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
Update workflow-session.json with selected_roles.
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
### Phase 3: Wave Role Analysis (spawn_agents_on_csv) — Auto Mode
|
|
398
|
+
|
|
399
|
+
**Objective**: Execute parallel role analysis via `spawn_agents_on_csv`. Each role agent produces analysis documents.
|
|
400
|
+
|
|
401
|
+
**Steps**:
|
|
402
|
+
|
|
403
|
+
1. **Role Analysis Wave**
|
|
404
|
+
|
|
405
|
+
```javascript
|
|
406
|
+
const rolesCSV = parseCsv(Read(`${sessionFolder}/roles.csv`))
|
|
407
|
+
|
|
408
|
+
console.log(`\n## Phase 3: Parallel Role Analysis (${rolesCSV.length} roles)\n`)
|
|
409
|
+
|
|
410
|
+
spawn_agents_on_csv({
|
|
411
|
+
csv_path: `${sessionFolder}/roles.csv`,
|
|
412
|
+
id_column: "id",
|
|
413
|
+
instruction: buildRoleInstruction(sessionFolder, topic, features),
|
|
414
|
+
max_concurrency: Math.min(rolesCSV.length, 4),
|
|
415
|
+
max_runtime_seconds: 600,
|
|
416
|
+
output_csv_path: `${sessionFolder}/roles-results.csv`,
|
|
417
|
+
output_schema: {
|
|
418
|
+
type: "object",
|
|
419
|
+
properties: {
|
|
420
|
+
id: { type: "string" },
|
|
421
|
+
status: { type: "string", enum: ["completed", "failed"] },
|
|
422
|
+
findings: { type: "string" },
|
|
423
|
+
output_files: { type: "array", items: { type: "string" } },
|
|
424
|
+
error: { type: "string" }
|
|
425
|
+
},
|
|
426
|
+
required: ["id", "status", "findings"]
|
|
427
|
+
}
|
|
428
|
+
})
|
|
429
|
+
|
|
430
|
+
// Merge results into roles.csv
|
|
431
|
+
const roleResults = parseCsv(Read(`${sessionFolder}/roles-results.csv`))
|
|
432
|
+
for (const result of roleResults) {
|
|
433
|
+
updateMasterCsvRow(`${sessionFolder}/roles.csv`, result.id, {
|
|
434
|
+
status: result.status,
|
|
435
|
+
findings: result.findings || '',
|
|
436
|
+
output_files: Array.isArray(result.output_files) ? result.output_files.join(';') : (result.output_files || ''),
|
|
437
|
+
error: result.error || ''
|
|
438
|
+
})
|
|
439
|
+
console.log(` [${result.id}] ${result.status === 'completed' ? '✓' : '✗'} ${rolesCSV.find(r => r.id === result.id)?.role}`)
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
Bash(`rm -f "${sessionFolder}/roles-results.csv"`)
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
2. **Role Instruction Template**
|
|
446
|
+
|
|
447
|
+
```javascript
|
|
448
|
+
function buildRoleInstruction(sessionFolder, topic, features) {
|
|
449
|
+
const featureList = features.length > 0
|
|
450
|
+
? features.map(f => `- [${f.id}] ${f.title}: ${f.description}`).join('\n')
|
|
451
|
+
: 'No feature decomposition — analyze topic holistically.'
|
|
452
|
+
|
|
453
|
+
return `
|
|
454
|
+
## ROLE ANALYSIS ASSIGNMENT
|
|
455
|
+
|
|
456
|
+
### MANDATORY FIRST STEPS
|
|
457
|
+
1. Read guidance specification: ${sessionFolder}/.brainstorming/guidance-specification.md
|
|
458
|
+
2. Read shared discoveries: ${sessionFolder}/discoveries.ndjson (if exists)
|
|
459
|
+
3. Read project context: .workflow/project-tech.json (if exists)
|
|
460
|
+
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
## Your Role
|
|
464
|
+
|
|
465
|
+
**Role ID**: {id}
|
|
466
|
+
**Role**: {role}
|
|
467
|
+
**Title**: {title}
|
|
468
|
+
**Focus**: {focus}
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
## Topic
|
|
473
|
+
${topic}
|
|
474
|
+
|
|
475
|
+
## Features to Analyze
|
|
476
|
+
${featureList}
|
|
477
|
+
|
|
478
|
+
---
|
|
479
|
+
|
|
480
|
+
## Analysis Protocol
|
|
481
|
+
|
|
482
|
+
1. **Read guidance**: Load guidance-specification.md for full context
|
|
483
|
+
2. **Read discoveries**: Load discoveries.ndjson for shared findings from other roles
|
|
484
|
+
3. **Analyze from your perspective**: Apply your role expertise to the topic
|
|
485
|
+
4. **Per-feature analysis** (if features exist):
|
|
486
|
+
- Create \`${sessionFolder}/.brainstorming/{role}/analysis-{feature-id}-{slug}.md\` per feature
|
|
487
|
+
- Create \`${sessionFolder}/.brainstorming/{role}/analysis-cross-cutting.md\` for cross-feature concerns
|
|
488
|
+
5. **Create index document**: \`${sessionFolder}/.brainstorming/{role}/analysis.md\`
|
|
489
|
+
- Summary of all findings
|
|
490
|
+
- Links to sub-documents
|
|
491
|
+
- Key recommendations
|
|
492
|
+
6. **Share discoveries**: Append findings to shared board:
|
|
493
|
+
\`\`\`bash
|
|
494
|
+
echo '{"ts":"<ISO8601>","worker":"{id}","type":"<type>","data":{...}}' >> ${sessionFolder}/discoveries.ndjson
|
|
495
|
+
\`\`\`
|
|
496
|
+
7. **Report result**: Return JSON via report_agent_job_result
|
|
497
|
+
|
|
498
|
+
### Document Constraints
|
|
499
|
+
- Main analysis.md: < 3000 words
|
|
500
|
+
- Sub-documents: < 2000 words each, max 5
|
|
501
|
+
- Total per role: < 15000 words
|
|
502
|
+
|
|
503
|
+
### Discovery Types to Share
|
|
504
|
+
- \`design_pattern\`: {name, rationale, applicability} — recommended patterns
|
|
505
|
+
- \`risk\`: {area, severity, mitigation} — identified risks
|
|
506
|
+
- \`requirement\`: {title, priority, source} — derived requirements
|
|
507
|
+
- \`constraint\`: {type, description, impact} — discovered constraints
|
|
508
|
+
- \`synergy\`: {roles[], area, description} — cross-role opportunities
|
|
509
|
+
|
|
510
|
+
---
|
|
511
|
+
|
|
512
|
+
## Output (report_agent_job_result)
|
|
513
|
+
|
|
514
|
+
Return JSON:
|
|
515
|
+
{
|
|
516
|
+
"id": "{id}",
|
|
517
|
+
"status": "completed" | "failed",
|
|
518
|
+
"findings": "Key insights from {role} perspective (max 800 chars)",
|
|
519
|
+
"output_files": ["path/to/analysis.md", "path/to/analysis-F-001.md"],
|
|
520
|
+
"error": ""
|
|
521
|
+
}
|
|
522
|
+
`
|
|
523
|
+
}
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
---
|
|
527
|
+
|
|
528
|
+
### Phase 3S: Single Role Analysis (spawn_agent) — Single Role Mode
|
|
529
|
+
|
|
530
|
+
**Objective**: Run one role analysis via spawn_agent with optional interactive Q&A.
|
|
531
|
+
|
|
532
|
+
```javascript
|
|
533
|
+
if (executionMode === 'single-role') {
|
|
534
|
+
const roleName = firstArg
|
|
535
|
+
const roleDir = `${sessionFolder}/.brainstorming/${roleName}`
|
|
536
|
+
Bash(`mkdir -p "${roleDir}"`)
|
|
537
|
+
|
|
538
|
+
const agentId = spawn_agent({
|
|
539
|
+
agent: `~/.codex/agents/conceptual-planning-agent.md`,
|
|
540
|
+
instruction: `
|
|
541
|
+
Perform a ${roleName} analysis for the brainstorming session.
|
|
542
|
+
|
|
543
|
+
**Session**: ${sessionFolder}
|
|
544
|
+
**Role**: ${roleName}
|
|
545
|
+
**Topic**: Read from ${sessionFolder}/.brainstorming/guidance-specification.md
|
|
546
|
+
${includeQuestions ? '**Mode**: Interactive — ask clarification questions before analysis' : ''}
|
|
547
|
+
${skipQuestions ? '**Mode**: Skip questions — proceed directly to analysis' : ''}
|
|
548
|
+
${styleSkill ? `**Style Skill**: ${styleSkill} — load .claude/skills/style-${styleSkill}/ for design reference` : ''}
|
|
549
|
+
${updateMode ? '**Update Mode**: Read existing analysis and enhance/update it' : ''}
|
|
550
|
+
|
|
551
|
+
**Output**: Create analysis documents in ${roleDir}/
|
|
552
|
+
- ${roleDir}/analysis.md (main index)
|
|
553
|
+
- ${roleDir}/analysis-*.md (sub-documents as needed)
|
|
554
|
+
|
|
555
|
+
Follow the same analysis protocol as wave role analysis but with interactive refinement.
|
|
556
|
+
`
|
|
557
|
+
})
|
|
558
|
+
|
|
559
|
+
wait({ id: agentId })
|
|
560
|
+
close_agent({ id: agentId })
|
|
561
|
+
|
|
562
|
+
console.log(`\n✓ ${roleName} analysis complete: ${roleDir}/analysis.md`)
|
|
563
|
+
}
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
---
|
|
567
|
+
|
|
568
|
+
### Phase 4: Synthesis Integration (Auto Mode)
|
|
569
|
+
|
|
570
|
+
**Objective**: Read all role analyses, cross-reference, generate feature specs.
|
|
571
|
+
|
|
572
|
+
**Steps**:
|
|
573
|
+
|
|
574
|
+
1. **Collect Role Findings**
|
|
575
|
+
|
|
576
|
+
```javascript
|
|
577
|
+
const rolesCSV = parseCsv(Read(`${sessionFolder}/roles.csv`))
|
|
578
|
+
const completedRoles = rolesCSV.filter(r => r.status === 'completed')
|
|
579
|
+
|
|
580
|
+
// Read all analysis.md index files (optimized: skip sub-docs for token efficiency)
|
|
581
|
+
const roleAnalyses = {}
|
|
582
|
+
for (const role of completedRoles) {
|
|
583
|
+
const indexPath = `${sessionFolder}/.brainstorming/${role.role}/analysis.md`
|
|
584
|
+
const content = Read(indexPath)
|
|
585
|
+
if (content) roleAnalyses[role.role] = content
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// Read discoveries
|
|
589
|
+
const discoveriesPath = `${sessionFolder}/discoveries.ndjson`
|
|
590
|
+
const discoveries = Read(discoveriesPath) || ''
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
2. **Synthesis via Agent**
|
|
594
|
+
|
|
595
|
+
```javascript
|
|
596
|
+
const synthesisAgent = spawn_agent({
|
|
597
|
+
agent: `~/.codex/agents/conceptual-planning-agent.md`,
|
|
598
|
+
instruction: `
|
|
599
|
+
## SYNTHESIS ASSIGNMENT
|
|
600
|
+
|
|
601
|
+
Synthesize ${completedRoles.length} role analyses into unified feature specifications.
|
|
602
|
+
|
|
603
|
+
**Session**: ${sessionFolder}
|
|
604
|
+
**Role Analyses**: ${completedRoles.map(r => `${sessionFolder}/.brainstorming/${r.role}/analysis.md`).join(', ')}
|
|
605
|
+
**Discoveries**: ${discoveriesPath}
|
|
606
|
+
|
|
607
|
+
### Synthesis Protocol
|
|
608
|
+
|
|
609
|
+
1. **Read all role analyses** (analysis.md files only — these are index documents)
|
|
610
|
+
2. **Cross-reference findings**: Identify agreements, conflicts, and unique insights
|
|
611
|
+
3. **Generate feature specs**: For each feature in guidance-specification.md:
|
|
612
|
+
- Create ${sessionFolder}/.brainstorming/feature-specs/F-{id}-{slug}.md
|
|
613
|
+
- Consolidate perspectives from all relevant roles
|
|
614
|
+
- Note conflicts and recommended resolutions
|
|
615
|
+
4. **Generate feature index**: ${sessionFolder}/.brainstorming/feature-index.json
|
|
616
|
+
- Array of {id, title, slug, roles_contributing[], conflict_count, priority}
|
|
617
|
+
5. **Generate changelog**: ${sessionFolder}/.brainstorming/synthesis-changelog.md
|
|
618
|
+
- Decisions made, conflicts resolved, trade-offs accepted
|
|
619
|
+
|
|
620
|
+
### Complexity Assessment
|
|
621
|
+
Evaluate complexity score (0-8):
|
|
622
|
+
- Feature count (≤2: 0, 3-4: 1, ≥5: 2)
|
|
623
|
+
- Unresolved conflicts (0: 0, 1-2: 1, ≥3: 2)
|
|
624
|
+
- Participating roles (≤2: 0, 3-4: 1, ≥5: 2)
|
|
625
|
+
- Cross-feature dependencies (0: 0, 1-2: 1, ≥3: 2)
|
|
626
|
+
|
|
627
|
+
### Output Files
|
|
628
|
+
- feature-specs/F-{id}-{slug}.md (one per feature)
|
|
629
|
+
- feature-index.json
|
|
630
|
+
- synthesis-changelog.md
|
|
631
|
+
`
|
|
632
|
+
})
|
|
633
|
+
|
|
634
|
+
wait({ id: synthesisAgent })
|
|
635
|
+
close_agent({ id: synthesisAgent })
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
3. **Completion Summary**
|
|
639
|
+
|
|
640
|
+
```javascript
|
|
641
|
+
const featureIndex = JSON.parse(Read(`${sessionFolder}/.brainstorming/feature-index.json`) || '[]')
|
|
642
|
+
|
|
643
|
+
console.log(`
|
|
644
|
+
## Brainstorm Complete
|
|
645
|
+
|
|
646
|
+
Session: ${sessionId}
|
|
647
|
+
Roles analyzed: ${completedRoles.length}
|
|
648
|
+
Features synthesized: ${featureIndex.length}
|
|
649
|
+
|
|
650
|
+
### Feature Specs
|
|
651
|
+
${featureIndex.map(f => ` - [${f.id}] ${f.title} (${f.roles_contributing?.length || 0} roles, ${f.conflict_count || 0} conflicts)`).join('\n')}
|
|
652
|
+
|
|
653
|
+
### Next Steps
|
|
654
|
+
Brainstorming complete. To continue, run one of:
|
|
655
|
+
- /workflow-plan --session ${sessionId} → Generate implementation plan
|
|
656
|
+
- Review: ${sessionFolder}/.brainstorming/feature-specs/
|
|
657
|
+
`)
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
---
|
|
661
|
+
|
|
662
|
+
## Utility Functions
|
|
663
|
+
|
|
664
|
+
### CSV Parser
|
|
665
|
+
|
|
666
|
+
```javascript
|
|
667
|
+
function parseCsv(content) {
|
|
668
|
+
const lines = content.trim().split('\n')
|
|
669
|
+
if (lines.length < 2) return []
|
|
670
|
+
const headers = parseCSVLine(lines[0])
|
|
671
|
+
return lines.slice(1).map(line => {
|
|
672
|
+
const values = parseCSVLine(line)
|
|
673
|
+
const row = {}
|
|
674
|
+
headers.forEach((h, i) => row[h] = values[i] || '')
|
|
675
|
+
return row
|
|
676
|
+
})
|
|
677
|
+
}
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
### CSV Row Updater
|
|
681
|
+
|
|
682
|
+
```javascript
|
|
683
|
+
function updateMasterCsvRow(csvPath, id, updates) {
|
|
684
|
+
const content = Read(csvPath)
|
|
685
|
+
const lines = content.trim().split('\n')
|
|
686
|
+
const headers = parseCSVLine(lines[0])
|
|
687
|
+
const idIdx = headers.indexOf('id')
|
|
688
|
+
|
|
689
|
+
for (let i = 1; i < lines.length; i++) {
|
|
690
|
+
const values = parseCSVLine(lines[i])
|
|
691
|
+
if (values[idIdx]?.replace(/"/g, '') === id) {
|
|
692
|
+
Object.entries(updates).forEach(([key, val]) => {
|
|
693
|
+
const idx = headers.indexOf(key)
|
|
694
|
+
if (idx >= 0) values[idx] = `"${String(val).replace(/"/g, '""')}"`
|
|
695
|
+
})
|
|
696
|
+
lines[i] = values.join(',')
|
|
697
|
+
break
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
Write(csvPath, lines.join('\n'))
|
|
701
|
+
}
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
---
|
|
705
|
+
|
|
706
|
+
## Error Handling
|
|
707
|
+
|
|
708
|
+
| Error | Recovery |
|
|
709
|
+
|-------|----------|
|
|
710
|
+
| Invalid role name | Show valid roles list, prompt again |
|
|
711
|
+
| No active session (single role) | Guide user to run auto mode first |
|
|
712
|
+
| Role agent failure | Mark failed in roles.csv, continue with remaining |
|
|
713
|
+
| Synthesis overflow (>100KB) | Read only analysis.md index files |
|
|
714
|
+
| Context compression | Re-read guidance-specification.md and roles.csv |
|
|
715
|
+
|
|
716
|
+
---
|
|
717
|
+
|
|
718
|
+
## Compact Protection
|
|
719
|
+
|
|
720
|
+
> **COMPACT DIRECTIVE**: If context compression occurs mid-execution, re-read the current phase's state:
|
|
721
|
+
> - Phase 2: Re-read `guidance-specification.md`
|
|
722
|
+
> - Phase 3: Re-read `roles.csv` for progress state
|
|
723
|
+
> - Phase 4: Re-read `feature-index.json` and `roles.csv`
|