@curdx/flow 2.0.21 → 2.1.0
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 +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +74 -3
- package/README.zh.md +11 -5
- package/agent-preamble/preamble.md +1 -4
- package/cli/install-bundled-mcps.js +37 -0
- package/cli/install-companions.js +16 -252
- package/cli/install-context7-config.js +97 -0
- package/cli/install-recommended-plugins.js +104 -0
- package/cli/install-required-plugins.js +44 -0
- package/cli/protocols-body.md +3 -2
- package/hooks/scripts/session-start.sh +6 -3
- package/package.json +1 -2
- package/schemas/config.schema.json +1 -1
- package/schemas/spec-state.schema.json +1 -1
- package/skills/debug/SKILL.md +104 -0
- package/{commands/help.md → skills/help/SKILL.md} +14 -5
- package/{commands/implement.md → skills/implement/SKILL.md} +10 -151
- package/skills/implement/references/wave-execution.md +162 -0
- package/{commands/review.md → skills/review/SKILL.md} +36 -2
- package/skills/verify/SKILL.md +98 -0
- package/commands/debug.md +0 -199
- package/commands/verify.md +0 -142
- /package/{commands/fast.md → skills/fast/SKILL.md} +0 -0
- /package/{commands/init.md → skills/init/SKILL.md} +0 -0
- /package/{commands/spec.md → skills/spec/SKILL.md} +0 -0
- /package/{commands/start.md → skills/start/SKILL.md} +0 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install required Claude Code companion plugins (today: context7-plugin).
|
|
3
|
+
* Post-install, dispatches Context7 API-key configuration if applicable.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { addPluginMarketplace, installPlugin } from "./lib/claude-ops.js";
|
|
7
|
+
import { REQUIRED_PLUGINS } from "./registry.js";
|
|
8
|
+
import { color, log, resultLastLine } from "./utils.js";
|
|
9
|
+
import { installContext7Config } from "./install-context7-config.js";
|
|
10
|
+
|
|
11
|
+
export async function installRequiredPlugins({ yes, language, config }) {
|
|
12
|
+
log.blank();
|
|
13
|
+
log.info("Installing required Claude Code plugins...");
|
|
14
|
+
for (const plugin of REQUIRED_PLUGINS) {
|
|
15
|
+
console.log(` ${color.cyan("▸")} Installing ${color.bold(plugin.name)}...`);
|
|
16
|
+
const ma = await addPluginMarketplace(plugin);
|
|
17
|
+
if (ma.code !== 0 && !ma.stderr.includes("already")) {
|
|
18
|
+
log.warn(` marketplace add warning: ${ma.stderr.trim().split("\n")[0]}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const ir = await installPlugin(plugin);
|
|
22
|
+
if (ir.code === 0) {
|
|
23
|
+
console.log(` ${color.green("✓")} ${plugin.name} installed`);
|
|
24
|
+
|
|
25
|
+
if (plugin.requiresConfig && plugin.configType === "apiKey" && !yes) {
|
|
26
|
+
await installContext7Config(plugin, language, config);
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
console.log(
|
|
30
|
+
` ${color.red("✗")} ${plugin.name} install failed: ${resultLastLine(ir)}`
|
|
31
|
+
);
|
|
32
|
+
console.log(
|
|
33
|
+
color.dim(
|
|
34
|
+
` Run manually: claude plugin marketplace add --scope ${plugin.scope} ${plugin.marketplaceSource}`
|
|
35
|
+
)
|
|
36
|
+
);
|
|
37
|
+
console.log(
|
|
38
|
+
color.dim(
|
|
39
|
+
` Then: claude plugin install --scope ${plugin.scope} ${plugin.installSpec}`
|
|
40
|
+
)
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
package/cli/protocols-body.md
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
All operations MUST strictly follow these system constraints:
|
|
4
4
|
|
|
5
5
|
### Language separation
|
|
6
|
-
- **Tool / persistence layer = English**: commit messages, code, comments, file names, function names, PR descriptions,
|
|
6
|
+
- **Tool / persistence layer = English**: commit messages, code, comments, file names, function names, PR descriptions, error messages thrown by code, and any artifact persisted to the repository or consumed by agents / skills / hooks at runtime.
|
|
7
7
|
- **Conversational layer = Simplified Chinese**: chat replies, explanations and reasoning shown directly to the human in a conversation interface (e.g. Claude Code chat).
|
|
8
|
+
- **Installer UX (`cli/` only, narrow carve-out)**: interactive menus printed by the npm-published installer under `cli/**` may present localized Chinese options because they serve a human operator at install time. This carve-out does NOT apply to `agents/`, `skills/`, `commands/`, `gates/`, `hooks/`, `knowledge/`, documentation, or any prose consumed by agents at runtime — those stay English.
|
|
8
9
|
|
|
9
|
-
Rationale: English in the persistence/tool layer aligns with developer-tool industry norms (npm/git/cargo are all English) and keeps
|
|
10
|
+
Rationale: English in the persistence / tool / agent-input layer aligns with developer-tool industry norms (npm/git/cargo are all English) and keeps AI / agent adaptation reliable. Chinese in the conversational layer matches the user's language preference. The installer carve-out reflects the fact that installer menus are a human-to-human interaction surface, not agent input. Mixing the two (e.g. Chinese commit messages, Chinese strings inside agent prompts) is a violation.
|
|
10
11
|
|
|
11
12
|
### Discovery & reasoning
|
|
12
13
|
- **Library / framework / API questions**: query `context7` MCP first. Do not rely on training memory.
|
|
@@ -32,9 +32,12 @@ if [ "$LAST_CHECK" != "$TODAY" ]; then
|
|
|
32
32
|
if command -v claude >/dev/null 2>&1; then
|
|
33
33
|
INSTALLED="$(claude plugin list 2>/dev/null || true)"
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
echo "$INSTALLED" | grep -q '
|
|
35
|
+
# Names must stay in lockstep with cli/registry.js RECOMMENDED_PLUGINS.
|
|
36
|
+
# Drift is guarded by test/registry-session-start-parity.test.js.
|
|
37
|
+
echo "$INSTALLED" | grep -q 'pua' || MISSING+=("pua")
|
|
38
|
+
echo "$INSTALLED" | grep -q 'claude-mem' || MISSING+=("claude-mem")
|
|
39
|
+
echo "$INSTALLED" | grep -q 'frontend-design' || MISSING+=("frontend-design")
|
|
40
|
+
echo "$INSTALLED" | grep -q 'chrome-devtools-mcp' || MISSING+=("chrome-devtools-mcp")
|
|
38
41
|
fi
|
|
39
42
|
|
|
40
43
|
if [ "${#MISSING[@]}" -gt 0 ]; then
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@curdx/flow",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "CLI installer for CurdX-Flow — AI engineering workflow meta-framework for Claude Code",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
".claude-plugin/",
|
|
17
17
|
"agents/",
|
|
18
18
|
"gates/",
|
|
19
|
-
"commands/",
|
|
20
19
|
"hooks/",
|
|
21
20
|
"knowledge/",
|
|
22
21
|
"agent-preamble/",
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: debug
|
|
3
|
+
description: Systematic debugging — 4-phase methodology (root cause → pattern → hypothesis → fix); three failures trigger architectural questioning. Routes to flow-debugger.
|
|
4
|
+
argument-hint: "\"<bug description>\""
|
|
5
|
+
context: fork
|
|
6
|
+
agent: flow-debugger
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Systematic Debug
|
|
10
|
+
|
|
11
|
+
Debug the bug described below using the 4-phase methodology in
|
|
12
|
+
`@${CLAUDE_PLUGIN_ROOT}/knowledge/systematic-debugging.md`. This is NOT
|
|
13
|
+
"retry until green" — each phase has a stop condition.
|
|
14
|
+
|
|
15
|
+
**Bug description**: `$ARGUMENTS`
|
|
16
|
+
|
|
17
|
+
If `$ARGUMENTS` is empty, print `Usage: /curdx-flow:debug "<bug description>"` and stop.
|
|
18
|
+
|
|
19
|
+
## Context to gather before diagnosing
|
|
20
|
+
|
|
21
|
+
- Recent commits: `git log --oneline -20`
|
|
22
|
+
- Uncommitted changes: `git status --short`, `git diff --stat`
|
|
23
|
+
- Active spec (if any): read `.flow/.active-spec`; if set, read
|
|
24
|
+
`.flow/specs/<active>/.progress.md` for related history.
|
|
25
|
+
|
|
26
|
+
## Phase 1 — Root-cause investigation
|
|
27
|
+
|
|
28
|
+
- Read the error carefully (stack trace + message + location).
|
|
29
|
+
- Build a minimal reproduction.
|
|
30
|
+
- Check recent changes that could have introduced the bug.
|
|
31
|
+
- Trace the data flow from cause to symptom.
|
|
32
|
+
- **Exit condition**: state the root cause in **one sentence**.
|
|
33
|
+
"maybe it's..." is not allowed.
|
|
34
|
+
|
|
35
|
+
## Phase 2 — Pattern analysis
|
|
36
|
+
|
|
37
|
+
- Find a working counter-example in the codebase (same path, different
|
|
38
|
+
input or neighboring module that behaves correctly).
|
|
39
|
+
- Pinpoint the difference from the failing case.
|
|
40
|
+
- Classify: **isolated case** (one location) vs. **systemic pattern**
|
|
41
|
+
(multiple siblings). If systemic, Phase 4 must sweep for siblings.
|
|
42
|
+
|
|
43
|
+
## Phase 3 — Hypothesis and test
|
|
44
|
+
|
|
45
|
+
- State ONE hypothesis.
|
|
46
|
+
- Write the smallest test that distinguishes confirm vs. disprove.
|
|
47
|
+
- Run the test in-memory (do not commit yet).
|
|
48
|
+
- If disproved, return to Phase 1 with the new signal.
|
|
49
|
+
|
|
50
|
+
## Phase 4 — Implement the fix
|
|
51
|
+
|
|
52
|
+
1. Write a failing test; confirm it fails. Commit `test(<scope>): red - ...`.
|
|
53
|
+
2. Fix the root cause (not the symptom). Confirm the failing test now
|
|
54
|
+
passes. Commit `fix(<scope>): green - ...`.
|
|
55
|
+
3. Run the full regression suite; no regressions allowed.
|
|
56
|
+
4. If Phase 2 classified as systemic, sweep for sibling occurrences and
|
|
57
|
+
fix them in the same stage. Optional third commit
|
|
58
|
+
`fix(<scope>): sweep - N similar cases`.
|
|
59
|
+
|
|
60
|
+
## Three-failure guard (hard stop)
|
|
61
|
+
|
|
62
|
+
If Phase 4 has tried 3 genuinely different approaches and all failed,
|
|
63
|
+
**stop**. Do not try a 4th. Output the structured failure report:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
⚠ Systematic debug halted after 3 attempts
|
|
67
|
+
|
|
68
|
+
Attempts:
|
|
69
|
+
1. <approach 1>: <why it failed>
|
|
70
|
+
2. <approach 2>: <why it failed>
|
|
71
|
+
3. <approach 3>: <why it failed>
|
|
72
|
+
|
|
73
|
+
Root-issue hypothesis: architecture | dependency | data | unknown
|
|
74
|
+
Recommended next step: <user action — review architecture, ship a
|
|
75
|
+
STATE.md D-NN deferral with @ts-expect-error,
|
|
76
|
+
or request pairing>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Forbidden
|
|
80
|
+
|
|
81
|
+
- Prayer-driven programming (retry without a new hypothesis each round)
|
|
82
|
+
- "Maybe it's ..." as a Phase 1 conclusion
|
|
83
|
+
- A fix commit without a corresponding failing-test commit
|
|
84
|
+
- Masking the root cause with null checks / try-catch
|
|
85
|
+
- Fixing multiple unrelated things in one commit (one task = one commit)
|
|
86
|
+
|
|
87
|
+
## Output to user (on success, ≤ 15 lines)
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
✓ Debug complete
|
|
91
|
+
|
|
92
|
+
Root cause: <Phase 1 — one sentence>
|
|
93
|
+
Pattern: <Phase 2 — isolated or systemic>
|
|
94
|
+
|
|
95
|
+
Fix commits:
|
|
96
|
+
- <sha>: test(<scope>): red - failing test
|
|
97
|
+
- <sha>: fix(<scope>): green - root-cause fix
|
|
98
|
+
- <sha>: fix(<scope>): sweep - N sibling cases (if systemic)
|
|
99
|
+
|
|
100
|
+
Verification: failing test now PASS ✓; full suite green ✓
|
|
101
|
+
|
|
102
|
+
Learnings (candidate for .progress.md):
|
|
103
|
+
- <lesson>
|
|
104
|
+
```
|
|
@@ -48,15 +48,24 @@ Show the 9 core slash commands + 5 auto-invoked skills. Keep the table compact,
|
|
|
48
48
|
|
|
49
49
|
## `<command-name>` — command detail
|
|
50
50
|
|
|
51
|
-
When the argument matches one of the 9
|
|
51
|
+
When the argument matches a slash name — one of the 9 primary workflows or one of the 5 auto-invoked skills — read the corresponding body and present it cleanly. The lookup tries the `skills/` layout first and falls back to the legacy `commands/` layout, which keeps help correct throughout the Phase 3 migration window:
|
|
52
52
|
|
|
53
53
|
```bash
|
|
54
|
-
|
|
55
|
-
CMD
|
|
56
|
-
|
|
54
|
+
CMD="$ARGUMENTS"
|
|
55
|
+
[ -z "$CMD" ] && { echo "Usage: /curdx-flow:help <name>"; exit 1; }
|
|
56
|
+
if [ -f "${CLAUDE_PLUGIN_ROOT}/skills/${CMD}/SKILL.md" ]; then
|
|
57
|
+
cat "${CLAUDE_PLUGIN_ROOT}/skills/${CMD}/SKILL.md"
|
|
58
|
+
elif [ -f "${CLAUDE_PLUGIN_ROOT}/commands/${CMD}.md" ]; then
|
|
59
|
+
cat "${CLAUDE_PLUGIN_ROOT}/commands/${CMD}.md"
|
|
60
|
+
else
|
|
61
|
+
echo "Unknown: ${CMD}"
|
|
62
|
+
echo "Workflows: init start spec implement verify review fast debug help"
|
|
63
|
+
echo "Skills: epic browser-qa ui-sketch security-audit brownfield-index"
|
|
64
|
+
exit 1
|
|
65
|
+
fi
|
|
57
66
|
```
|
|
58
67
|
|
|
59
|
-
If the argument isn't a known
|
|
68
|
+
If the argument isn't a known slash name, the block above prints the 14 candidates.
|
|
60
69
|
|
|
61
70
|
## `workflow` — standard workflow
|
|
62
71
|
|
|
@@ -159,160 +159,19 @@ After the agent completes, read the output marker:
|
|
|
159
159
|
|
|
160
160
|
### Strategy: wave
|
|
161
161
|
|
|
162
|
-
|
|
162
|
+
See `skills/implement/references/wave-execution.md` for the full walkthrough.
|
|
163
|
+
Knowledge-layer canonical algorithm: `@${CLAUDE_PLUGIN_ROOT}/knowledge/wave-execution.md`.
|
|
163
164
|
|
|
164
|
-
**Core**: consecutive `[P]` tasks form a wave
|
|
165
|
+
**Core**: consecutive `[P]` tasks form a wave; dispatch multiple Tasks in parallel within a single response; serial across waves. The execution loop is:
|
|
165
166
|
|
|
166
|
-
|
|
167
|
+
1. **DAG analysis** — group remaining `[ ]` tasks by `[P]` / `[SEQUENTIAL]` / `[VERIFY]` tags; conflicting `Files` sets split into a new wave.
|
|
168
|
+
2. **Pre-conflict detection** — within each wave, assert per-task `Files` are disjoint; auto-split if not.
|
|
169
|
+
3. **Dispatch** — list multiple `Task(...)` tool calls in a single main-agent response (splitting across responses = serial degradation; nested `Task` dispatches forbidden). Each Task prompt follows the subagent strategy's uniform format (see `references/wave-execution.md` Step 3).
|
|
170
|
+
4. **Aggregate** — parse each result for `TASK_COMPLETE` / `TASK_FAILED`; run post-hoc conflict detection via git diff to confirm executors only touched declared files.
|
|
171
|
+
5. **Failure handling** — 0 failed → next wave; 1 failed → `config.wave_fail_policy` (`continue-on-single` or `stop-on-any`); ≥2 failed → likely environment issue, stop immediately; cumulative `failed_attempts >= 3` → stop, user intervention.
|
|
172
|
+
6. **Progress feedback** — print a wave summary after each wave (see `references/wave-execution.md` Step 6).
|
|
167
173
|
|
|
168
|
-
|
|
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 npx @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]`
|
|
174
|
+
Configuration under `.flow/config.json.execution`: `strategy: "wave"`, `max_parallel: 5` (wave-parallel ceiling), `wave_fail_policy: "continue-on-single" | "stop-on-any"`.
|
|
316
175
|
|
|
317
176
|
### Strategy: stop-hook
|
|
318
177
|
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Wave Execution Strategy — Detailed Walkthrough
|
|
2
|
+
|
|
3
|
+
Skill-scoped reference for `skills/implement/SKILL.md`. Loaded only when the
|
|
4
|
+
implement skill routes to the `wave` strategy. The knowledge-layer canonical
|
|
5
|
+
algorithm lives in `@${CLAUDE_PLUGIN_ROOT}/knowledge/wave-execution.md`;
|
|
6
|
+
this file is the walkthrough the skill itself embeds for implementers.
|
|
7
|
+
|
|
8
|
+
**Core**: consecutive `[P]` tasks form a wave, dispatch multiple Tasks in
|
|
9
|
+
parallel within a single message, serial across waves.
|
|
10
|
+
|
|
11
|
+
## Step 1: DAG Analysis
|
|
12
|
+
|
|
13
|
+
Read remaining `[ ]` tasks from tasks.md and group per the rules:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
for task in remaining tasks:
|
|
17
|
+
if task has [SEQUENTIAL] or [VERIFY]:
|
|
18
|
+
→ own wave (breaks parallelism)
|
|
19
|
+
elif task has [P]:
|
|
20
|
+
→ check whether Files conflict with current_wave
|
|
21
|
+
conflict → start a new wave
|
|
22
|
+
no conflict → add to current_wave
|
|
23
|
+
else:
|
|
24
|
+
→ own wave (no [P] = serial)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Output wave list:
|
|
28
|
+
```
|
|
29
|
+
Wave 1 [P×3]: 1.1 1.2 1.3
|
|
30
|
+
Wave 2 [VERIFY]: 1.4
|
|
31
|
+
Wave 3: 1.5
|
|
32
|
+
Wave 4 [P×2]: 1.6 1.7
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Step 2: Pre-Conflict Detection
|
|
36
|
+
|
|
37
|
+
For each wave, verify that Files across all tasks are **disjoint**:
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
for wave in waves:
|
|
41
|
+
all_files = []
|
|
42
|
+
for task in wave:
|
|
43
|
+
if set(task.files) & set(all_files):
|
|
44
|
+
warn(f"Within wave, {task.id} modifies the same file as a prior task")
|
|
45
|
+
# split into the next wave
|
|
46
|
+
all_files.extend(task.files)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
If the planner mis-tagged `[P]` (modifies the same file), split the wave automatically at execution time rather than failing outright.
|
|
50
|
+
|
|
51
|
+
## Step 3: Dispatch a Single Wave (key: within a single response)
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
# List multiple Task tool calls in one response of the main agent:
|
|
55
|
+
Task(description="Execute 1.1", prompt=<...flow-executor + task_id=1.1...>)
|
|
56
|
+
Task(description="Execute 1.2", prompt=<...flow-executor + task_id=1.2...>)
|
|
57
|
+
Task(description="Execute 1.3", prompt=<...flow-executor + task_id=1.3...>)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Each Task prompt follows a uniform format (similar to subagent strategy):
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
You are the flow-executor agent. Full definition:
|
|
64
|
+
${CLAUDE_PLUGIN_ROOT}/agents/flow-executor.md
|
|
65
|
+
|
|
66
|
+
Execute a single task:
|
|
67
|
+
spec_name: $SPEC_NAME
|
|
68
|
+
task_id: <specific ID, e.g., 1.2>
|
|
69
|
+
quick_mode: $QUICK
|
|
70
|
+
|
|
71
|
+
**You may only modify the following files** (touching anything else is disallowed):
|
|
72
|
+
<task.files>
|
|
73
|
+
|
|
74
|
+
Required reading:
|
|
75
|
+
- .flow/specs/$SPEC_NAME/tasks.md
|
|
76
|
+
- .flow/specs/$SPEC_NAME/.state.json
|
|
77
|
+
- .flow/specs/$SPEC_NAME/design.md (if referencing AD-NN)
|
|
78
|
+
|
|
79
|
+
Output:
|
|
80
|
+
- TASK_COMPLETE: <task_id> or
|
|
81
|
+
- TASK_FAILED: <task_id> + reason
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Not allowed**:
|
|
85
|
+
- Splitting multiple Task calls across multiple responses (that is serial degradation)
|
|
86
|
+
- Nesting another Task dispatch inside a Task
|
|
87
|
+
|
|
88
|
+
## Step 4: Aggregate Wave Results
|
|
89
|
+
|
|
90
|
+
Wait for all Tasks to return:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
completed = []; failed = []
|
|
94
|
+
for task, result in zip(wave, results):
|
|
95
|
+
if "TASK_COMPLETE" in result:
|
|
96
|
+
completed.append(task)
|
|
97
|
+
elif "TASK_FAILED" in result:
|
|
98
|
+
failed.append(task)
|
|
99
|
+
|
|
100
|
+
# Post-hoc conflict detection (verify executors did not touch out-of-scope files)
|
|
101
|
+
for task in completed:
|
|
102
|
+
actual_files = git_diff_files_touched_by(task)
|
|
103
|
+
declared = set(task.files)
|
|
104
|
+
unexpected = actual_files - declared
|
|
105
|
+
if unexpected:
|
|
106
|
+
warn(f"Task {task.id} modified undeclared files: {unexpected}")
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Step 5: Wave Failure Handling
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
len(failed) == 0:
|
|
113
|
+
→ continue to the next wave
|
|
114
|
+
|
|
115
|
+
len(failed) == 1:
|
|
116
|
+
→ failed_attempts += 1
|
|
117
|
+
→ based on config.wave_fail_policy:
|
|
118
|
+
"continue-on-single": continue to the next wave, report failure at the end
|
|
119
|
+
"stop-on-any": stop immediately
|
|
120
|
+
|
|
121
|
+
len(failed) >= 2:
|
|
122
|
+
→ likely environment issue (missing deps/tsc error/permissions)
|
|
123
|
+
→ stop immediately, suggest npx @curdx/flow doctor
|
|
124
|
+
|
|
125
|
+
failed_attempts >= 3 (cumulative):
|
|
126
|
+
→ stop, user intervention required
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Step 6: Progress Feedback
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
▶ Wave 2/5 complete
|
|
133
|
+
✓ 1.1 feat(auth): create module skeleton (abc123)
|
|
134
|
+
✓ 1.2 feat(user): create user types (def456)
|
|
135
|
+
✓ 1.3 feat(session): init token module (ghi789)
|
|
136
|
+
|
|
137
|
+
▶ Wave 3/5 starting (VERIFY)...
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Configuration
|
|
141
|
+
|
|
142
|
+
`.flow/config.json`:
|
|
143
|
+
```json
|
|
144
|
+
{
|
|
145
|
+
"execution": {
|
|
146
|
+
"strategy": "wave",
|
|
147
|
+
"max_parallel": 5,
|
|
148
|
+
"wave_fail_policy": "continue-on-single"
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
- `max_parallel`: max N parallel within a wave (to avoid API rate limits, default 5)
|
|
154
|
+
- `wave_fail_policy`: single-task failure behavior
|
|
155
|
+
|
|
156
|
+
## Pitfalls
|
|
157
|
+
|
|
158
|
+
See `@${CLAUDE_PLUGIN_ROOT}/knowledge/wave-execution.md` for the detailed version.
|
|
159
|
+
|
|
160
|
+
- Stray `[P]` → conflict detection as a safety net
|
|
161
|
+
- Wave too large → max_parallel auto-splits
|
|
162
|
+
- Implicit read-write dependencies → planner should avoid this kind of `[P]`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: review
|
|
3
|
-
description: Two-stage code review — Stage 1 spec compliance, Stage 2 code quality. Optional flags add adversarial review
|
|
4
|
-
argument-hint: "[--stage=<1|2|both>] [--adversarial] [--edge-case]"
|
|
3
|
+
description: Two-stage code review — Stage 1 spec compliance, Stage 2 code quality. Optional flags add adversarial review, edge-case hunting, or developer-experience audit.
|
|
4
|
+
argument-hint: "[--stage=<1|2|both>] [--adversarial] [--edge-case] [--devex]"
|
|
5
5
|
allowed-tools: [Read, Bash, Task, Grep, Glob]
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -18,6 +18,7 @@ Distinct from `/curdx-flow:verify`:
|
|
|
18
18
|
| `--stage=<1\|2\|both>` | `both` | Stage 1 = spec compliance only. Stage 2 = code quality only. `both` = sequential. |
|
|
19
19
|
| `--adversarial` | off | Add an adversarial review pass across applicable categories (zero findings requires proof-of-checking, not fabrication). |
|
|
20
20
|
| `--edge-case` | off | Add edge-case hunting across applicable categories. Produces a test-gap checklist. |
|
|
21
|
+
| `--devex` | off | Apply the DevEx audit: naming, comments, structure, error handling, setup, types, tests, and developer loop. Gate: `@${CLAUDE_PLUGIN_ROOT}/gates/devex-gate.md`. |
|
|
21
22
|
|
|
22
23
|
## Preflight
|
|
23
24
|
|
|
@@ -38,6 +39,7 @@ done
|
|
|
38
39
|
FLAG_STAGE=$(echo "$ARGUMENTS" | grep -oP -- '--stage=\K[^\s]+' || echo "both")
|
|
39
40
|
FLAG_ADV=$(echo "$ARGUMENTS" | grep -q -- '--adversarial' && echo 1 || echo 0)
|
|
40
41
|
FLAG_EDGE=$(echo "$ARGUMENTS" | grep -q -- '--edge-case' && echo 1 || echo 0)
|
|
42
|
+
FLAG_DEVEX=$(echo "$ARGUMENTS" | grep -q -- '--devex' && echo 1 || echo 0)
|
|
41
43
|
```
|
|
42
44
|
|
|
43
45
|
## Stage 1 — Spec compliance
|
|
@@ -89,6 +91,27 @@ Dispatch `flow-edge-hunter` across the applicable categories (skip N/A with one-
|
|
|
89
91
|
|
|
90
92
|
Output: test-gap checklist with suggested test cases.
|
|
91
93
|
|
|
94
|
+
## Optional: DevEx audit
|
|
95
|
+
|
|
96
|
+
If `--devex`:
|
|
97
|
+
Pass the DevEx gate at `@${CLAUDE_PLUGIN_ROOT}/gates/devex-gate.md` as
|
|
98
|
+
additional context to `flow-reviewer`. The gate adds these dimensions to
|
|
99
|
+
Stage 2:
|
|
100
|
+
|
|
101
|
+
1. **Naming** — identifier clarity, consistency across modules.
|
|
102
|
+
2. **Comments** — only non-obvious WHY; no redundant WHAT.
|
|
103
|
+
3. **Structure** — file and function sizes, colocation of related code.
|
|
104
|
+
4. **Error handling** — at system boundaries only; no defensive guards inside trusted paths.
|
|
105
|
+
5. **Setup** — `npm install && npm test` green on a fresh clone.
|
|
106
|
+
6. **Types** — strictness, no unexplained `any` / `unknown`.
|
|
107
|
+
7. **Tests** — failure messages, fixture clarity, no flake.
|
|
108
|
+
8. **Dev loop** — time from code-change to feedback.
|
|
109
|
+
|
|
110
|
+
`flow-reviewer` is NOT edited for `--devex` — the gate file is injected
|
|
111
|
+
into the reviewer dispatch prompt as reference context, so the agent
|
|
112
|
+
stays generic. Output: a "DevEx" section in the review report with
|
|
113
|
+
per-dimension verdicts.
|
|
114
|
+
|
|
92
115
|
## Report
|
|
93
116
|
|
|
94
117
|
**Landing check**: sub-agent responses can be truncated. After dispatching review agents, verify the report actually landed on disk:
|
|
@@ -121,6 +144,15 @@ Consolidated output: `.flow/specs/$SPEC_NAME/review-report.md`:
|
|
|
121
144
|
## Edge Cases (if run)
|
|
122
145
|
...
|
|
123
146
|
|
|
147
|
+
## DevEx (if run)
|
|
148
|
+
- Naming: <verdict>
|
|
149
|
+
- Structure: <verdict>
|
|
150
|
+
- Error handling: <verdict>
|
|
151
|
+
- Setup: <verdict>
|
|
152
|
+
- Types: <verdict>
|
|
153
|
+
- Tests: <verdict>
|
|
154
|
+
- Dev loop: <verdict>
|
|
155
|
+
|
|
124
156
|
## Verdict
|
|
125
157
|
- [ ] APPROVED
|
|
126
158
|
- [X] CHANGES REQUIRED — <n> blockers
|
|
@@ -135,6 +167,7 @@ Consolidated output: `.flow/specs/$SPEC_NAME/review-report.md`:
|
|
|
135
167
|
Stage 2 findings: <n>
|
|
136
168
|
Adversarial findings: <n> (if --adversarial)
|
|
137
169
|
Edge-case gaps: <n> (if --edge-case)
|
|
170
|
+
DevEx findings: <n> (if --devex)
|
|
138
171
|
Verdict: CHANGES REQUIRED
|
|
139
172
|
|
|
140
173
|
Report: .flow/specs/<name>/review-report.md
|
|
@@ -149,4 +182,5 @@ Next: address blockers, then re-run /curdx-flow:review.
|
|
|
149
182
|
- `flow-edge-hunter` agent: `@${CLAUDE_PLUGIN_ROOT}/agents/flow-edge-hunter.md`
|
|
150
183
|
- `adversarial-review-gate`: `@${CLAUDE_PLUGIN_ROOT}/gates/adversarial-review-gate.md`
|
|
151
184
|
- `edge-case-gate`: `@${CLAUDE_PLUGIN_ROOT}/gates/edge-case-gate.md`
|
|
185
|
+
- `devex-gate`: `@${CLAUDE_PLUGIN_ROOT}/gates/devex-gate.md`
|
|
152
186
|
- Knowledge: `@${CLAUDE_PLUGIN_ROOT}/knowledge/two-stage-review.md`
|