@curdx/flow 1.1.4 → 1.1.6
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-plugin/marketplace.json +25 -0
- package/.claude-plugin/plugin.json +43 -0
- package/CHANGELOG.md +279 -0
- package/agent-preamble/preamble.md +214 -0
- package/agents/flow-adversary.md +216 -0
- package/agents/flow-architect.md +190 -0
- package/agents/flow-debugger.md +325 -0
- package/agents/flow-edge-hunter.md +273 -0
- package/agents/flow-executor.md +246 -0
- package/agents/flow-planner.md +204 -0
- package/agents/flow-product-designer.md +146 -0
- package/agents/flow-qa-engineer.md +276 -0
- package/agents/flow-researcher.md +155 -0
- package/agents/flow-reviewer.md +280 -0
- package/agents/flow-security-auditor.md +398 -0
- package/agents/flow-triage-analyst.md +290 -0
- package/agents/flow-ui-researcher.md +227 -0
- package/agents/flow-ux-designer.md +247 -0
- package/agents/flow-verifier.md +283 -0
- package/agents/persona-amelia.md +128 -0
- package/agents/persona-david.md +141 -0
- package/agents/persona-emma.md +179 -0
- package/agents/persona-john.md +105 -0
- package/agents/persona-mary.md +95 -0
- package/agents/persona-oliver.md +136 -0
- package/agents/persona-rachel.md +126 -0
- package/agents/persona-serena.md +175 -0
- package/agents/persona-winston.md +117 -0
- package/bin/curdx-flow.js +5 -2
- package/cli/install.js +44 -5
- package/commands/audit.md +170 -0
- package/commands/autoplan.md +184 -0
- package/commands/debug.md +199 -0
- package/commands/design.md +155 -0
- package/commands/discuss.md +162 -0
- package/commands/doctor.md +124 -0
- package/commands/fast.md +128 -0
- package/commands/help.md +119 -0
- package/commands/implement.md +381 -0
- package/commands/index.md +261 -0
- package/commands/init.md +105 -0
- package/commands/install-deps.md +128 -0
- package/commands/party.md +241 -0
- package/commands/plan-ceo.md +117 -0
- package/commands/plan-design.md +107 -0
- package/commands/plan-dx.md +104 -0
- package/commands/plan-eng.md +108 -0
- package/commands/qa.md +118 -0
- package/commands/requirements.md +146 -0
- package/commands/research.md +141 -0
- package/commands/review.md +168 -0
- package/commands/security.md +109 -0
- package/commands/sketch.md +118 -0
- package/commands/spec.md +135 -0
- package/commands/spike.md +181 -0
- package/commands/start.md +189 -0
- package/commands/status.md +139 -0
- package/commands/switch.md +95 -0
- package/commands/tasks.md +189 -0
- package/commands/triage.md +160 -0
- package/commands/verify.md +124 -0
- package/gates/adversarial-review-gate.md +219 -0
- package/gates/coverage-audit-gate.md +184 -0
- package/gates/devex-gate.md +255 -0
- package/gates/edge-case-gate.md +194 -0
- package/gates/karpathy-gate.md +130 -0
- package/gates/security-gate.md +218 -0
- package/gates/tdd-gate.md +188 -0
- package/gates/verification-gate.md +183 -0
- package/hooks/hooks.json +56 -0
- package/hooks/scripts/fail-tracker.sh +31 -0
- package/hooks/scripts/inject-karpathy.sh +52 -0
- package/hooks/scripts/quick-mode-guard.sh +64 -0
- package/hooks/scripts/session-start.sh +76 -0
- package/hooks/scripts/stop-watcher.sh +166 -0
- package/knowledge/atomic-commits.md +262 -0
- package/knowledge/epic-decomposition.md +307 -0
- package/knowledge/execution-strategies.md +278 -0
- package/knowledge/karpathy-guidelines.md +219 -0
- package/knowledge/planning-reviews.md +211 -0
- package/knowledge/poc-first-workflow.md +227 -0
- package/knowledge/spec-driven-development.md +183 -0
- package/knowledge/systematic-debugging.md +384 -0
- package/knowledge/two-stage-review.md +233 -0
- package/knowledge/wave-execution.md +387 -0
- package/package.json +14 -3
- package/schemas/config.schema.json +100 -0
- package/schemas/spec-frontmatter.schema.json +42 -0
- package/schemas/spec-state.schema.json +117 -0
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: implement
|
|
3
|
+
description: Execute spec tasks — the Strategy Router picks linear/subagent/stop-hook/wave based on task characteristics. Atomic commit per task.
|
|
4
|
+
argument-hint: "[spec-name] [--strategy=auto|linear|subagent|stop-hook|wave] [--task=<id>] [--quick]"
|
|
5
|
+
allowed-tools: [Read, Write, Edit, Bash, Task, Grep, Glob]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Flow Implement — Execute Spec
|
|
9
|
+
|
|
10
|
+
@${CLAUDE_PLUGIN_ROOT}/knowledge/execution-strategies.md
|
|
11
|
+
@${CLAUDE_PLUGIN_ROOT}/knowledge/atomic-commits.md
|
|
12
|
+
|
|
13
|
+
Execute spec tasks per tasks.md. Select the best execution strategy based on arguments and task characteristics.
|
|
14
|
+
|
|
15
|
+
## Step 1: Preflight Checks
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
[ ! -d ".flow" ] && { echo "❌ Not a CurDX-Flow project. Run /curdx-flow:init first"; exit 1; }
|
|
19
|
+
|
|
20
|
+
ARGS="$ARGUMENTS"
|
|
21
|
+
SPEC_NAME=""
|
|
22
|
+
STRATEGY="auto"
|
|
23
|
+
TASK_ID=""
|
|
24
|
+
QUICK=0
|
|
25
|
+
|
|
26
|
+
# Simple argument parsing
|
|
27
|
+
for arg in $ARGS; do
|
|
28
|
+
case "$arg" in
|
|
29
|
+
--strategy=*) STRATEGY="${arg#--strategy=}" ;;
|
|
30
|
+
--task=*) TASK_ID="${arg#--task=}" ;;
|
|
31
|
+
--quick) QUICK=1 ;;
|
|
32
|
+
--*) ;; # ignore unknown flags
|
|
33
|
+
*) SPEC_NAME="$arg" ;;
|
|
34
|
+
esac
|
|
35
|
+
done
|
|
36
|
+
|
|
37
|
+
[ -z "$SPEC_NAME" ] && SPEC_NAME=$(cat .flow/.active-spec 2>/dev/null)
|
|
38
|
+
[ -z "$SPEC_NAME" ] && { echo "❌ No active spec. Run /curdx-flow:start first"; exit 1; }
|
|
39
|
+
|
|
40
|
+
DIR=".flow/specs/$SPEC_NAME"
|
|
41
|
+
[ ! -f "$DIR/tasks.md" ] && { echo "❌ Missing tasks.md. Run /curdx-flow:tasks first"; exit 1; }
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Step 2: Parse Task Characteristics from tasks.md
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
TOTAL=$(grep -c "^- \[ \] \*\*" "$DIR/tasks.md")
|
|
48
|
+
DONE=$(grep -c "^- \[x\] \*\*" "$DIR/tasks.md")
|
|
49
|
+
REMAINING=$((TOTAL))
|
|
50
|
+
PARALLEL=$(grep -c "^- \[ \] \*\*.*\[P\]" "$DIR/tasks.md")
|
|
51
|
+
SEQUENTIAL=$(grep -c "^- \[ \] \*\*.*\[SEQUENTIAL\]" "$DIR/tasks.md")
|
|
52
|
+
|
|
53
|
+
echo "Task stats: remaining $REMAINING, done $DONE, [P] parallel $PARALLEL, [SEQUENTIAL] serial $SEQUENTIAL"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Step 3: Strategy Router
|
|
57
|
+
|
|
58
|
+
If `STRATEGY=auto` (default), pick via the decision tree:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
if [ "$STRATEGY" = "auto" ]; then
|
|
62
|
+
if [ $REMAINING -lt 5 ] || [ $SEQUENTIAL -gt $((REMAINING / 2)) ]; then
|
|
63
|
+
STRATEGY="linear"
|
|
64
|
+
elif [ $PARALLEL -ge $((REMAINING * 4 / 10)) ]; then
|
|
65
|
+
STRATEGY="wave"
|
|
66
|
+
elif [ $REMAINING -ge 20 ] && [ $QUICK -eq 1 ]; then
|
|
67
|
+
STRATEGY="stop-hook"
|
|
68
|
+
elif [ $REMAINING -ge 8 ]; then
|
|
69
|
+
STRATEGY="subagent"
|
|
70
|
+
else
|
|
71
|
+
STRATEGY="linear"
|
|
72
|
+
fi
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
echo "✓ Selected strategy: $STRATEGY"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Decision tree explanation**:
|
|
79
|
+
- Few tasks / strong dependencies → `linear` (main agent executes sequentially)
|
|
80
|
+
- Many parallel opportunities → `wave` (parallel Task dispatch within a wave)
|
|
81
|
+
- Long chain + quick mode → `stop-hook` (auto-loop, requires hook support)
|
|
82
|
+
- Medium scale → `subagent` (isolated context per task)
|
|
83
|
+
|
|
84
|
+
## Step 4: Initialize execute_state
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
import json
|
|
88
|
+
p = f'.flow/specs/{SPEC_NAME}/.state.json'
|
|
89
|
+
s = json.load(open(p))
|
|
90
|
+
s['phase'] = 'execute'
|
|
91
|
+
s['strategy'] = STRATEGY
|
|
92
|
+
s.setdefault('phase_status', {})['execute'] = 'in_progress'
|
|
93
|
+
s.setdefault('execute_state', {})
|
|
94
|
+
s['execute_state'].setdefault('task_index', DONE)
|
|
95
|
+
s['execute_state']['total_tasks'] = TOTAL
|
|
96
|
+
s['execute_state'].setdefault('failed_attempts', 0)
|
|
97
|
+
s['execute_state'].setdefault('global_iteration', 1)
|
|
98
|
+
if QUICK:
|
|
99
|
+
s['quickMode'] = True
|
|
100
|
+
json.dump(s, open(p, 'w'), indent=2, ensure_ascii=False)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Step 5: Execution Strategies
|
|
104
|
+
|
|
105
|
+
### Strategy: linear
|
|
106
|
+
|
|
107
|
+
The main agent (you) executes sequentially:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
for task in remaining tasks:
|
|
111
|
+
read task fields (Do/Files/Done-when/Verify/Commit)
|
|
112
|
+
execute per the flow-executor agent rules:
|
|
113
|
+
- follow Karpathy surgical principles
|
|
114
|
+
- Verify must pass
|
|
115
|
+
- atomic commit
|
|
116
|
+
- mark [x]
|
|
117
|
+
- update .progress.md
|
|
118
|
+
output "✓ Task X.Y complete"
|
|
119
|
+
next
|
|
120
|
+
output "ALL_TASKS_COMPLETE" when all tasks are done
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
If there are 5 failures, stop + TASK_FAILED.
|
|
124
|
+
|
|
125
|
+
### Strategy: subagent
|
|
126
|
+
|
|
127
|
+
For each remaining task, dispatch flow-executor:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
Task:
|
|
131
|
+
subagent_type: general-purpose
|
|
132
|
+
description: "Execute $SPEC_NAME task $TASK_ID"
|
|
133
|
+
prompt: |
|
|
134
|
+
You are the flow-executor agent. Full definition at:
|
|
135
|
+
${CLAUDE_PLUGIN_ROOT}/agents/flow-executor.md
|
|
136
|
+
|
|
137
|
+
Execute task:
|
|
138
|
+
spec_name: $SPEC_NAME
|
|
139
|
+
task_id: next (or a specific ID)
|
|
140
|
+
quick_mode: $QUICK
|
|
141
|
+
|
|
142
|
+
Required reading:
|
|
143
|
+
- .flow/specs/$SPEC_NAME/tasks.md (locate the task)
|
|
144
|
+
- .flow/specs/$SPEC_NAME/.state.json
|
|
145
|
+
- .flow/specs/$SPEC_NAME/.progress.md
|
|
146
|
+
- .flow/specs/$SPEC_NAME/design.md (if task references AD-NN)
|
|
147
|
+
- .flow/specs/$SPEC_NAME/requirements.md (if referencing FR/AC)
|
|
148
|
+
|
|
149
|
+
On success output: TASK_COMPLETE: <task_id>
|
|
150
|
+
On failure output: TASK_FAILED: <task_id> + Reason
|
|
151
|
+
|
|
152
|
+
When all tasks are done output: ALL_TASKS_COMPLETE
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
After the agent completes, read the output marker:
|
|
156
|
+
- `TASK_COMPLETE` → continue to the next
|
|
157
|
+
- `TASK_FAILED` → accumulate failures, stop at >= 3
|
|
158
|
+
- `ALL_TASKS_COMPLETE` → mark phase completed
|
|
159
|
+
|
|
160
|
+
### Strategy: wave
|
|
161
|
+
|
|
162
|
+
@${CLAUDE_PLUGIN_ROOT}/knowledge/wave-execution.md
|
|
163
|
+
|
|
164
|
+
**Core**: consecutive `[P]` tasks form a wave, dispatch multiple Tasks in parallel within a single message, serial across waves.
|
|
165
|
+
|
|
166
|
+
#### Step 1: DAG Analysis
|
|
167
|
+
|
|
168
|
+
Read remaining `[ ]` tasks from tasks.md and group per the rules:
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
for task in remaining tasks:
|
|
172
|
+
if task has [SEQUENTIAL] or [VERIFY]:
|
|
173
|
+
→ own wave (breaks parallelism)
|
|
174
|
+
elif task has [P]:
|
|
175
|
+
→ check whether Files conflict with current_wave
|
|
176
|
+
conflict → start a new wave
|
|
177
|
+
no conflict → add to current_wave
|
|
178
|
+
else:
|
|
179
|
+
→ own wave (no [P] = serial)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Output wave list:
|
|
183
|
+
```
|
|
184
|
+
Wave 1 [P×3]: 1.1 1.2 1.3
|
|
185
|
+
Wave 2 [VERIFY]: 1.4
|
|
186
|
+
Wave 3: 1.5
|
|
187
|
+
Wave 4 [P×2]: 1.6 1.7
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
#### Step 2: Pre-Conflict Detection
|
|
191
|
+
|
|
192
|
+
For each wave, verify that Files across all tasks are **disjoint**:
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
for wave in waves:
|
|
196
|
+
all_files = []
|
|
197
|
+
for task in wave:
|
|
198
|
+
if set(task.files) & set(all_files):
|
|
199
|
+
warn(f"Within wave, {task.id} modifies the same file as a prior task")
|
|
200
|
+
# split into the next wave
|
|
201
|
+
all_files.extend(task.files)
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
If the planner mis-tagged `[P]` (modifies the same file), split the wave automatically at execution time rather than failing outright.
|
|
205
|
+
|
|
206
|
+
#### Step 3: Dispatch a Single Wave (**key: within a single response**)
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
# List multiple Task tool calls in one response of the main agent:
|
|
210
|
+
Task(description="Execute 1.1", prompt=<...flow-executor + task_id=1.1...>)
|
|
211
|
+
Task(description="Execute 1.2", prompt=<...flow-executor + task_id=1.2...>)
|
|
212
|
+
Task(description="Execute 1.3", prompt=<...flow-executor + task_id=1.3...>)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Each Task prompt follows a uniform format (similar to subagent strategy):
|
|
216
|
+
|
|
217
|
+
```
|
|
218
|
+
You are the flow-executor agent. Full definition:
|
|
219
|
+
${CLAUDE_PLUGIN_ROOT}/agents/flow-executor.md
|
|
220
|
+
|
|
221
|
+
Execute a single task:
|
|
222
|
+
spec_name: $SPEC_NAME
|
|
223
|
+
task_id: <specific ID, e.g., 1.2>
|
|
224
|
+
quick_mode: $QUICK
|
|
225
|
+
|
|
226
|
+
**You may only modify the following files** (touching anything else is disallowed):
|
|
227
|
+
<task.files>
|
|
228
|
+
|
|
229
|
+
Required reading:
|
|
230
|
+
- .flow/specs/$SPEC_NAME/tasks.md
|
|
231
|
+
- .flow/specs/$SPEC_NAME/.state.json
|
|
232
|
+
- .flow/specs/$SPEC_NAME/design.md (if referencing AD-NN)
|
|
233
|
+
|
|
234
|
+
Output:
|
|
235
|
+
- TASK_COMPLETE: <task_id> or
|
|
236
|
+
- TASK_FAILED: <task_id> + reason
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
**Not allowed**:
|
|
240
|
+
- Splitting multiple Task calls across multiple responses (that is serial degradation)
|
|
241
|
+
- Nesting another Task dispatch inside a Task
|
|
242
|
+
|
|
243
|
+
#### Step 4: Aggregate Wave Results
|
|
244
|
+
|
|
245
|
+
Wait for all Tasks to return:
|
|
246
|
+
|
|
247
|
+
```python
|
|
248
|
+
completed = []; failed = []
|
|
249
|
+
for task, result in zip(wave, results):
|
|
250
|
+
if "TASK_COMPLETE" in result:
|
|
251
|
+
completed.append(task)
|
|
252
|
+
elif "TASK_FAILED" in result:
|
|
253
|
+
failed.append(task)
|
|
254
|
+
|
|
255
|
+
# Post-hoc conflict detection (verify executors did not touch out-of-scope files)
|
|
256
|
+
for task in completed:
|
|
257
|
+
actual_files = git_diff_files_touched_by(task)
|
|
258
|
+
declared = set(task.files)
|
|
259
|
+
unexpected = actual_files - declared
|
|
260
|
+
if unexpected:
|
|
261
|
+
warn(f"Task {task.id} modified undeclared files: {unexpected}")
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### Step 5: Wave Failure Handling
|
|
265
|
+
|
|
266
|
+
```
|
|
267
|
+
len(failed) == 0:
|
|
268
|
+
→ continue to the next wave
|
|
269
|
+
|
|
270
|
+
len(failed) == 1:
|
|
271
|
+
→ failed_attempts += 1
|
|
272
|
+
→ based on config.wave_fail_policy:
|
|
273
|
+
"continue-on-single": continue to the next wave, report failure at the end
|
|
274
|
+
"stop-on-any": stop immediately
|
|
275
|
+
|
|
276
|
+
len(failed) >= 2:
|
|
277
|
+
→ likely environment issue (missing deps/tsc error/permissions)
|
|
278
|
+
→ stop immediately, suggest /curdx-flow:doctor
|
|
279
|
+
|
|
280
|
+
failed_attempts >= 3 (cumulative):
|
|
281
|
+
→ stop, user intervention required
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
#### Step 6: Progress Feedback
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
▶ Wave 2/5 complete
|
|
288
|
+
✓ 1.1 feat(auth): create module skeleton (abc123)
|
|
289
|
+
✓ 1.2 feat(user): create user types (def456)
|
|
290
|
+
✓ 1.3 feat(session): init token module (ghi789)
|
|
291
|
+
|
|
292
|
+
▶ Wave 3/5 starting (VERIFY)...
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
#### Configuration
|
|
296
|
+
|
|
297
|
+
`.flow/config.json`:
|
|
298
|
+
```json
|
|
299
|
+
{
|
|
300
|
+
"execution": {
|
|
301
|
+
"strategy": "wave",
|
|
302
|
+
"max_parallel": 5,
|
|
303
|
+
"wave_fail_policy": "continue-on-single"
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
- `max_parallel`: max N parallel within a wave (to avoid API rate limits, default 5)
|
|
309
|
+
- `wave_fail_policy`: single-task failure behavior
|
|
310
|
+
|
|
311
|
+
#### Pitfalls (see knowledge/wave-execution.md for the detailed version)
|
|
312
|
+
|
|
313
|
+
- Stray `[P]` → conflict detection as a safety net
|
|
314
|
+
- Wave too large → max_parallel auto-splits
|
|
315
|
+
- Implicit read-write dependencies → planner should avoid this kind of `[P]`
|
|
316
|
+
|
|
317
|
+
### Strategy: stop-hook
|
|
318
|
+
|
|
319
|
+
```
|
|
320
|
+
1. Execute 1 task (dispatch flow-executor, wait for completion)
|
|
321
|
+
2. Do not loop manually — rely on the stop-watcher.sh hook
|
|
322
|
+
3. Stop event triggers → hook checks if there are remaining tasks → injects "continue"
|
|
323
|
+
4. Claude auto-starts next round
|
|
324
|
+
5. Repeat until ALL_TASKS_COMPLETE or 3 failures
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Prerequisites:
|
|
328
|
+
- `--quick` must be set (otherwise AskUserQuestion will block the loop)
|
|
329
|
+
- `.flow/config.json` or `.state.json` must have strategy=stop-hook
|
|
330
|
+
|
|
331
|
+
## Step 6: Progress Feedback
|
|
332
|
+
|
|
333
|
+
Every 5 tasks or every wave, print status:
|
|
334
|
+
|
|
335
|
+
```
|
|
336
|
+
═════ Progress ═════
|
|
337
|
+
Spec: $SPEC_NAME
|
|
338
|
+
Strategy: $STRATEGY
|
|
339
|
+
Done: X / $TOTAL
|
|
340
|
+
Recent commits:
|
|
341
|
+
- abc123f feat(auth): ...
|
|
342
|
+
- def456g test(auth): ...
|
|
343
|
+
════════════════════
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
## Step 7: Completion Handling
|
|
347
|
+
|
|
348
|
+
```
|
|
349
|
+
if all tasks done:
|
|
350
|
+
update .state.json:
|
|
351
|
+
phase = "verify"
|
|
352
|
+
phase_status.execute = "completed"
|
|
353
|
+
append .progress.md: "## execute phase complete YYYY-MM-DD"
|
|
354
|
+
output "ALL_TASKS_COMPLETE"
|
|
355
|
+
suggest next step: /curdx-flow:verify
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## Error Recovery
|
|
359
|
+
|
|
360
|
+
- Verify field in tasks.md is "manual" → stop, suggest re-running /curdx-flow:tasks to fix
|
|
361
|
+
- 3 consecutive TASK_FAILED → stop, prompt for user intervention
|
|
362
|
+
- git operation failure → stop immediately, do not continue (avoid state corruption)
|
|
363
|
+
- Test framework not found (npm test not found) → stop, suggest running /curdx-flow:doctor
|
|
364
|
+
|
|
365
|
+
## Output to User
|
|
366
|
+
|
|
367
|
+
```
|
|
368
|
+
✓ execute phase complete: $SPEC_NAME
|
|
369
|
+
|
|
370
|
+
Strategy: $STRATEGY
|
|
371
|
+
Tasks done: N / N
|
|
372
|
+
Commits: M atomic commits
|
|
373
|
+
Verify passed: K / K
|
|
374
|
+
|
|
375
|
+
Next steps:
|
|
376
|
+
- /curdx-flow:verify — goal-driven reverse verification (after Phase 3 ships)
|
|
377
|
+
- If verify is not needed, go directly to /curdx-flow:ship (after Phase 6 ships)
|
|
378
|
+
|
|
379
|
+
Phase 3 (Gates & Review) has not yet shipped.
|
|
380
|
+
You may manually review .flow/specs/$SPEC_NAME/ and git log to confirm quality.
|
|
381
|
+
```
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: index
|
|
3
|
+
description: Codebase index — scan brownfield projects and generate a module/component/API index. Provides the foundation for subsequent /curdx-flow:research.
|
|
4
|
+
argument-hint: "[--force]"
|
|
5
|
+
allowed-tools: [Read, Write, Bash, Grep, Glob]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Flow Index — Codebase Scan and Index
|
|
9
|
+
|
|
10
|
+
Generate an index for **brownfield projects** (existing code) so that flow-researcher and flow-architect can quickly acquire project-structure information.
|
|
11
|
+
|
|
12
|
+
## Applicable Scenarios
|
|
13
|
+
|
|
14
|
+
- Taking over an existing project — run `/curdx-flow:index` first to build understanding
|
|
15
|
+
- Large monorepo requiring indexes of subpackages
|
|
16
|
+
- Want to add a new feature to the current project — index before researching
|
|
17
|
+
|
|
18
|
+
## Not Applicable
|
|
19
|
+
|
|
20
|
+
- Greenfield projects (empty codebase)
|
|
21
|
+
- Micro projects (< 20 files)
|
|
22
|
+
|
|
23
|
+
## Step 1: Preflight
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
[ ! -d ".flow" ] && { echo "❌ Not a CurDX-Flow project. Run /curdx-flow:init first"; exit 1; }
|
|
27
|
+
|
|
28
|
+
INDEX_FILE=".flow/codebase-index.md"
|
|
29
|
+
|
|
30
|
+
# If one exists and --force is not set, ask
|
|
31
|
+
if [ -f "$INDEX_FILE" ] && [ "$ARGUMENTS" != "--force" ]; then
|
|
32
|
+
echo "ℹ Index already exists: $INDEX_FILE"
|
|
33
|
+
# AskUserQuestion: overwrite / incremental / cancel
|
|
34
|
+
fi
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Step 2: Detect Project Type
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Identify project language + build tool
|
|
41
|
+
if [ -f "package.json" ]; then
|
|
42
|
+
PROJECT_TYPE="node"
|
|
43
|
+
FRAMEWORK=$(grep -E "(react|vue|next|nuxt|svelte)" package.json | head -3)
|
|
44
|
+
elif [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
|
|
45
|
+
PROJECT_TYPE="python"
|
|
46
|
+
elif [ -f "Cargo.toml" ]; then
|
|
47
|
+
PROJECT_TYPE="rust"
|
|
48
|
+
elif [ -f "go.mod" ]; then
|
|
49
|
+
PROJECT_TYPE="go"
|
|
50
|
+
fi
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Step 3: Scan Directory Structure
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Top-level directories
|
|
57
|
+
DIRS=$(ls -d */ 2>/dev/null | grep -vE "(node_modules|dist|build|\.git|\.next)")
|
|
58
|
+
|
|
59
|
+
# File statistics
|
|
60
|
+
TOTAL_FILES=$(find . -type f -not -path "*/node_modules/*" -not -path "*/.git/*" | wc -l)
|
|
61
|
+
SRC_FILES=$(find src/ -type f 2>/dev/null | wc -l)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Step 4: Identify Modules
|
|
65
|
+
|
|
66
|
+
Use Grep + Glob to find module boundaries:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# TypeScript / JavaScript: find export default + public API
|
|
70
|
+
# Python: find __init__.py
|
|
71
|
+
# Rust: find mod.rs / lib.rs
|
|
72
|
+
# Go: find package declaration
|
|
73
|
+
|
|
74
|
+
# Typical pattern (Node project):
|
|
75
|
+
Glob: src/**/index.{ts,tsx,js}
|
|
76
|
+
Grep: "^export (default|const|function|class)" in index files
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Step 5: Identify Components / Services / APIs
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# UI components
|
|
83
|
+
Glob: src/**/*.{tsx,jsx,vue,svelte}
|
|
84
|
+
|
|
85
|
+
# API endpoints
|
|
86
|
+
Grep: "router\.\(get\|post\|put\|delete\)" or "app\.(get|post)" or "@app.route"
|
|
87
|
+
|
|
88
|
+
# DB models
|
|
89
|
+
Grep: "@Entity\|Schema\|Model\|prisma\."
|
|
90
|
+
|
|
91
|
+
# Services
|
|
92
|
+
Glob: src/**/*Service.{ts,js}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Step 6: Build the Index Markdown
|
|
96
|
+
|
|
97
|
+
```markdown
|
|
98
|
+
# Codebase Index: <project name>
|
|
99
|
+
|
|
100
|
+
Generated: YYYY-MM-DD
|
|
101
|
+
Project type: Node (TypeScript + React)
|
|
102
|
+
Total files: 234 (189 under src/)
|
|
103
|
+
|
|
104
|
+
## Directory Structure
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
src/
|
|
108
|
+
├── auth/ ← authentication module
|
|
109
|
+
├── user/ ← user management
|
|
110
|
+
├── orders/ ← orders
|
|
111
|
+
├── ui/ ← shared UI components
|
|
112
|
+
├── api/ ← API routes
|
|
113
|
+
├── db/ ← DB layer
|
|
114
|
+
└── utils/ ← utility functions
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Module List
|
|
118
|
+
|
|
119
|
+
### Module: auth
|
|
120
|
+
- Path: src/auth/
|
|
121
|
+
- Entry: src/auth/index.ts
|
|
122
|
+
- Exports:
|
|
123
|
+
- `login(email, password)` - log in
|
|
124
|
+
- `logout(token)` - log out
|
|
125
|
+
- `refreshToken(token)` - refresh
|
|
126
|
+
- Dependencies: bcrypt, jsonwebtoken
|
|
127
|
+
- Tests: src/auth/*.test.ts (15 tests)
|
|
128
|
+
|
|
129
|
+
### Module: user
|
|
130
|
+
- Path: src/user/
|
|
131
|
+
- Entry: src/user/index.ts
|
|
132
|
+
- Exports:
|
|
133
|
+
- `getUser(id)` - fetch user
|
|
134
|
+
- `updateProfile(id, data)` - update profile
|
|
135
|
+
- Dependencies: prisma
|
|
136
|
+
- Tests: src/user/*.test.ts (8 tests)
|
|
137
|
+
|
|
138
|
+
### Module: orders
|
|
139
|
+
...
|
|
140
|
+
|
|
141
|
+
## UI Component List
|
|
142
|
+
|
|
143
|
+
### Shared components (src/ui/)
|
|
144
|
+
|
|
145
|
+
- `<Button>` - src/ui/Button.tsx
|
|
146
|
+
- `<Input>` - src/ui/Input.tsx
|
|
147
|
+
- `<Card>` - src/ui/Card.tsx
|
|
148
|
+
- ...
|
|
149
|
+
|
|
150
|
+
### Page components (src/pages/)
|
|
151
|
+
|
|
152
|
+
- `LoginPage` - src/pages/Login.tsx
|
|
153
|
+
- `DashboardPage` - src/pages/Dashboard.tsx
|
|
154
|
+
- ...
|
|
155
|
+
|
|
156
|
+
## API Endpoints
|
|
157
|
+
|
|
158
|
+
### /auth
|
|
159
|
+
- POST /auth/login → src/api/auth.ts:login
|
|
160
|
+
- POST /auth/logout → src/api/auth.ts:logout
|
|
161
|
+
- POST /auth/refresh → src/api/auth.ts:refresh
|
|
162
|
+
|
|
163
|
+
### /users
|
|
164
|
+
- GET /users/me → src/api/users.ts:getCurrent
|
|
165
|
+
- PUT /users/me → src/api/users.ts:update
|
|
166
|
+
- ...
|
|
167
|
+
|
|
168
|
+
## DB Models
|
|
169
|
+
|
|
170
|
+
- `User` - src/db/models/User.ts
|
|
171
|
+
- `Order` - src/db/models/Order.ts
|
|
172
|
+
- ...
|
|
173
|
+
|
|
174
|
+
## Tech Stack
|
|
175
|
+
|
|
176
|
+
- **Runtime**: Node 20 + TypeScript 5
|
|
177
|
+
- **Framework**: Next.js 14 (App Router)
|
|
178
|
+
- **UI**: React 18 + Tailwind + shadcn/ui
|
|
179
|
+
- **DB**: PostgreSQL + Prisma
|
|
180
|
+
- **Auth**: JWT + bcrypt
|
|
181
|
+
- **Testing**: Vitest + Playwright
|
|
182
|
+
|
|
183
|
+
## Commands
|
|
184
|
+
|
|
185
|
+
From package.json:
|
|
186
|
+
- `npm run dev` - dev server (localhost:3000)
|
|
187
|
+
- `npm test` - tests
|
|
188
|
+
- `npm run build` - production build
|
|
189
|
+
- `npm run lint` - ESLint
|
|
190
|
+
|
|
191
|
+
## Conventions
|
|
192
|
+
|
|
193
|
+
- File naming: PascalCase for components, camelCase for utilities
|
|
194
|
+
- Tests: `*.test.ts` adjacent to source file
|
|
195
|
+
- Types: standalone `types.ts` or inline interface
|
|
196
|
+
- Exports: each module's `index.ts` as the public API
|
|
197
|
+
|
|
198
|
+
## Hot Files (most modified recently)
|
|
199
|
+
|
|
200
|
+
- src/auth/login.ts (12 commits in the past 30 days)
|
|
201
|
+
- src/ui/Button.tsx (8 commits)
|
|
202
|
+
- ...
|
|
203
|
+
|
|
204
|
+
## Tech Debt / TODO
|
|
205
|
+
|
|
206
|
+
Scan for `// TODO:` / `// FIXME:`:
|
|
207
|
+
- src/auth/refresh.ts:28 - "TODO: add rate limiting"
|
|
208
|
+
- src/api/orders.ts:45 - "FIXME: handle concurrent updates"
|
|
209
|
+
- ...
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Step 7: Save + Update .state
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# Write
|
|
216
|
+
echo "$INDEX_CONTENT" > "$INDEX_FILE"
|
|
217
|
+
|
|
218
|
+
# If .flow/config.json exists, record the index time
|
|
219
|
+
python3 -c "
|
|
220
|
+
import json
|
|
221
|
+
c = json.load(open('.flow/config.json'))
|
|
222
|
+
c.setdefault('codebase_index', {})['last_updated'] = '$(date +%Y-%m-%d)'
|
|
223
|
+
json.dump(c, open('.flow/config.json','w'), indent=2, ensure_ascii=False)
|
|
224
|
+
"
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Step 8: Output
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
✓ Codebase index complete
|
|
231
|
+
|
|
232
|
+
File: .flow/codebase-index.md (~N lines)
|
|
233
|
+
|
|
234
|
+
Statistics:
|
|
235
|
+
Modules: M
|
|
236
|
+
UI components: K
|
|
237
|
+
API endpoints: L
|
|
238
|
+
DB models: J
|
|
239
|
+
|
|
240
|
+
You can now:
|
|
241
|
+
- Agents will read this index as context during /curdx-flow:research
|
|
242
|
+
- When running /curdx-flow:start for a new feature, reference this index first to find reusable modules
|
|
243
|
+
- View it manually to understand the project structure
|
|
244
|
+
|
|
245
|
+
Suggestion:
|
|
246
|
+
- Rerun after major code changes: /curdx-flow:index --force
|
|
247
|
+
- No need to run on every change (30-day stability is OK)
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Notes
|
|
251
|
+
|
|
252
|
+
- The index is **not full documentation**, it is a **quick guide**. Details still live in the source code.
|
|
253
|
+
- Large project scans may take 1-2 minutes
|
|
254
|
+
- Does not scan node_modules / dist / build / .git
|
|
255
|
+
- Exclusion list configurable (future enhancement)
|
|
256
|
+
|
|
257
|
+
## Error Recovery
|
|
258
|
+
|
|
259
|
+
- Project too large (10K+ files) → index by module
|
|
260
|
+
- Project type cannot be identified → provide a template for the user to fill in manually
|
|
261
|
+
- Some paths have permission issues → skip and continue with the rest
|