specflow-cc 1.22.0 → 1.22.2

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/CHANGELOG.md CHANGED
@@ -5,6 +5,20 @@ All notable changes to SpecFlow will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.22.2] - 2026-05-22
9
+
10
+ ### Fixed
11
+
12
+ - **Installed `/sf:*` commands broken on user projects** — every `/sf:*` command shipped in `commands/sf/*.md` is now safe to run from a project directory with no local `bin/`. Two bugs fixed:
13
+ 1. **Bare `bin/sf-tools.cjs` paths in 15 command files** (`audit.md`, `autopilot.md`, `discuss.md`, `done.md`, `fix.md`, `health.md`, `help.md`, `pause.md`, `review.md`, `revise.md`, `run.md`, `show.md`, `split.md`, `status.md`, `verify.md`) were rewritten to `~/.claude/specflow-cc/bin/sf-tools.cjs`. The installer rewrites this literal prefix to the actual install location, so every invocation now resolves correctly. Previously these lines errored with `Cannot find module '/path/to/project/bin/sf-tools.cjs'`.
14
+ 2. **Unsafe `state resolve $ARGUMENTS` in 8 commands** (`audit.md`, `autopilot.md`, `done.md`, `fix.md`, `pause.md`, `review.md`, `run.md`, `verify.md`) was replaced with a SPEC-ID parsing guard: `$ARGUMENTS` is split into `FIRST_TOKEN` (matched against `^SPEC-\d{3,}$`) and a per-command scope variable (`FIX_SCOPE`, `DONE_SCOPE`, `AUDIT_SCOPE`, …). Previously `/sf:fix all`, `/sf:done --apply=minor`, etc. produced spurious `SPEC_NOT_ACTIVE` errors because the scope/mode flag was passed to the resolver as if it were a SPEC-ID.
15
+
16
+ ## [1.22.1] - 2026-05-20
17
+
18
+ ### Fixed
19
+
20
+ - `todo next-id` now scans `.specflow/specs/` and `.specflow/archive/` for `source: TODO-XXX` frontmatter entries, preventing reissue of retired IDs. Previously, a TODO file deleted during promotion to a spec could have its ID reassigned to an unrelated new TODO, leaving downstream `/sf:plan` unable to operate on the new TODO (it rejects the ID as "already promoted").
21
+
8
22
  ## [1.22.0] - 2026-05-19
9
23
 
10
24
  ### Added
package/bin/lib/todo.cjs CHANGED
@@ -183,6 +183,8 @@ function cmdTodoList(cwd, raw, { showAll } = {}) {
183
183
  * Scans:
184
184
  * 1. .specflow/todos/TODO-*.md filenames using fs.readdirSync() + JS regex
185
185
  * 2. .specflow/todos/TODO.md for legacy IDs using fs.readFileSync() + /TODO-(\d+)/g
186
+ * 3. .specflow/specs/*.md and .specflow/archive/*.md for `source: TODO-XXX`
187
+ * frontmatter entries (retired IDs from promoted TODOs).
186
188
  *
187
189
  * NOTE: Does NOT use grep -oP (GNU-only, unavailable on macOS).
188
190
  *
@@ -222,6 +224,31 @@ function cmdTodoNextId(cwd, raw) {
222
224
  // file may not exist — skip
223
225
  }
224
226
 
227
+ // Scan promoted-spec frontmatter for retired TODO IDs.
228
+ // On promotion, the source TODO file is deleted; the only surviving
229
+ // record is `source: TODO-XXX` in the spec's frontmatter. Without this
230
+ // scan, next-id can reissue a retired ID and downstream `/sf:plan` will
231
+ // reject the new TODO because the archive still records the old promotion.
232
+ for (const sub of ['specs', 'archive']) {
233
+ const dir = path.join(cwd, '.specflow', sub);
234
+ let files;
235
+ try {
236
+ files = fs.readdirSync(dir).filter(f => f.endsWith('.md'));
237
+ } catch (e) { continue; }
238
+ for (const file of files) {
239
+ let content;
240
+ try {
241
+ content = fs.readFileSync(path.join(dir, file), 'utf8');
242
+ } catch (e) { continue; }
243
+ const regex = /(?:^|\n)source:\s*TODO-(\d+)/g;
244
+ let match;
245
+ while ((match = regex.exec(content)) !== null) {
246
+ const num = parseInt(match[1], 10);
247
+ if (num > maxNum) maxNum = num;
248
+ }
249
+ }
250
+ }
251
+
225
252
  const nextNumber = maxNum + 1;
226
253
  const nextId = 'TODO-' + String(nextNumber).padStart(3, '0');
227
254
 
@@ -43,7 +43,22 @@ Exit.
43
43
 
44
44
  ## Step 2: Resolve Active Specification
45
45
 
46
- Call `node bin/sf-tools.cjs state resolve $ARGUMENTS` (pass the optional SPEC-XXX arg if provided).
46
+ Parse `$ARGUMENTS`:
47
+ - Let `FIRST_TOKEN` = first whitespace-separated token of `$ARGUMENTS`.
48
+ - If `FIRST_TOKEN` matches `^SPEC-\d{3,}$`:
49
+ - Set `SPEC_ARG="$FIRST_TOKEN"`
50
+ - Set `AUDIT_SCOPE` = remainder of `$ARGUMENTS` after `FIRST_TOKEN` (trimmed)
51
+ - Else:
52
+ - Set `SPEC_ARG=""` (resolver uses Active Specifications table)
53
+ - Set `AUDIT_SCOPE="$ARGUMENTS"`
54
+
55
+ Call:
56
+
57
+ ```bash
58
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state resolve $SPEC_ARG
59
+ ```
60
+
61
+ Use `AUDIT_SCOPE` in the subsequent argument-parsing step (Step 3.5).
47
62
 
48
63
  Parse the JSON response:
49
64
  - `{"action":"use","id":"SPEC-XXX"}` → proceed with SPEC-XXX
@@ -77,7 +92,7 @@ Exit.
77
92
 
78
93
  ## Step 3.5: Check for --import Flag
79
94
 
80
- Parse arguments for `--import "feedback text"` pattern.
95
+ Parse `AUDIT_SCOPE` for `--import "feedback text"` pattern.
81
96
 
82
97
  **If --import flag present:** Go to Step 4-IMPORT
83
98
  **Otherwise:** Continue to Step 4 (internal audit)
@@ -156,7 +171,7 @@ In spec frontmatter, set: `status: revision_requested`
156
171
 
157
172
  Update STATE.md via CLI:
158
173
  ```bash
159
- node bin/sf-tools.cjs state add-active SPEC-XXX external_review /sf:revise
174
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state add-active SPEC-XXX external_review /sf:revise
160
175
  ```
161
176
  Add decision: "Imported external feedback for SPEC-XXX"
162
177
 
@@ -299,7 +314,7 @@ Tip: `/clear` recommended — executor needs fresh context for implementation
299
314
 
300
315
  ### If APPROVED (with optional recommendations):
301
316
 
302
- The `Recommendation:` line is emitted by the auditor agent (Step 7.5 in `agents/spec-auditor.md`) using `node bin/sf-tools.cjs recommend --source audit --critical 0 --minor N`. The STATE.md Next Step remains `/sf:run` (without the `--apply=minor` suffix) — the suffix is advisory here only.
317
+ The `Recommendation:` line is emitted by the auditor agent (Step 7.5 in `agents/spec-auditor.md`) using `node ~/.claude/specflow-cc/bin/sf-tools.cjs recommend --source audit --critical 0 --minor N`. The STATE.md Next Step remains `/sf:run` (without the `--apply=minor` suffix) — the suffix is advisory here only.
303
318
 
304
319
  ```
305
320
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@@ -50,7 +50,22 @@ Parse the command argument to determine execution mode:
50
50
 
51
51
  **CRITICAL — N>1 guard (autopilot must be unambiguous):**
52
52
 
53
- Call `node bin/sf-tools.cjs state resolve $SPEC_ID_ARG` (pass SPEC-ID arg if provided; omit if not).
53
+ Parse `$ARGUMENTS`:
54
+ - Let `FIRST_TOKEN` = first whitespace-separated token of `$ARGUMENTS`.
55
+ - If `FIRST_TOKEN` matches `^SPEC-\d{3,}$`:
56
+ - Set `SPEC_ARG="$FIRST_TOKEN"`
57
+ - Set `AUTOPILOT_SCOPE` = remainder of `$ARGUMENTS` after `FIRST_TOKEN` (trimmed)
58
+ - Else:
59
+ - Set `SPEC_ARG=""` (resolver uses Active Specifications table)
60
+ - Set `AUTOPILOT_SCOPE="$ARGUMENTS"`
61
+
62
+ Call:
63
+
64
+ ```bash
65
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state resolve $SPEC_ARG
66
+ ```
67
+
68
+ Use `AUTOPILOT_SCOPE` in the subsequent mode-determination step (e.g. `--all` flag).
54
69
 
55
70
  Parse the JSON response:
56
71
  - `{"action":"use","id":"SPEC-XXX"}` → proceed with SPEC-XXX
@@ -274,7 +289,7 @@ mv .specflow/specs/SPEC-XXX.md .specflow/archive/
274
289
  5. **Update STATE.md:**
275
290
  Remove SPEC-XXX from Active Specifications table:
276
291
  ```bash
277
- node bin/sf-tools.cjs state remove-active SPEC-XXX
292
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state remove-active SPEC-XXX
278
293
  ```
279
294
  Remove SPEC-XXX row from Queue table (using Read+Write).
280
295
 
@@ -62,7 +62,7 @@ Determine discussion mode from arguments:
62
62
  - Mode: `requirements-gathering`
63
63
 
64
64
  **Case E: No arguments**
65
- - Call `node bin/sf-tools.cjs state resolve` to resolve active spec
65
+ - Call `node ~/.claude/specflow-cc/bin/sf-tools.cjs state resolve` to resolve active spec
66
66
  - `{"action":"use","id":"SPEC-XXX"}` → discuss that spec
67
67
  - `{"action":"error","code":"NO_ACTIVE_SPEC"}` → ask what to discuss
68
68
  - `{"action":"ask","options":[...]}` → use AskUserQuestion to pick which spec to discuss
@@ -39,7 +39,22 @@ Exit.
39
39
 
40
40
  ## Step 2: Resolve Active Specification
41
41
 
42
- Call `node bin/sf-tools.cjs state resolve $ARGUMENTS` (pass the optional SPEC-XXX arg if provided).
42
+ Parse `$ARGUMENTS`:
43
+ - Let `FIRST_TOKEN` = first whitespace-separated token of `$ARGUMENTS`.
44
+ - If `FIRST_TOKEN` matches `^SPEC-\d{3,}$`:
45
+ - Set `SPEC_ARG="$FIRST_TOKEN"`
46
+ - Set `DONE_SCOPE` = remainder of `$ARGUMENTS` after `FIRST_TOKEN` (trimmed)
47
+ - Else:
48
+ - Set `SPEC_ARG=""` (resolver uses Active Specifications table)
49
+ - Set `DONE_SCOPE="$ARGUMENTS"`
50
+
51
+ Call:
52
+
53
+ ```bash
54
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state resolve $SPEC_ARG
55
+ ```
56
+
57
+ Use `DONE_SCOPE` in the subsequent argument-parsing step (Step 2.5).
43
58
 
44
59
  Parse the JSON response:
45
60
  - `{"action":"use","id":"SPEC-XXX"}` → proceed with SPEC-XXX
@@ -61,7 +76,7 @@ Parse the JSON response:
61
76
 
62
77
  ## Step 2.5: Handle `--apply=minor` Flag
63
78
 
64
- **Check if `--apply=minor` was passed in the invocation arguments.**
79
+ **Check if `DONE_SCOPE` contains `--apply=minor`.**
65
80
 
66
81
  **If `--apply=minor` is NOT present:** Continue to Step 3 (existing behavior unchanged).
67
82
 
@@ -85,7 +100,7 @@ Extract Critical, Major, and Minor counts from that entry.
85
100
 
86
101
  Run:
87
102
  ```bash
88
- node bin/sf-tools.cjs recommend --source review --critical N --major M --minor K
103
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs recommend --source review --critical N --major M --minor K
89
104
  ```
90
105
 
91
106
  Parse the JSON response.
@@ -414,7 +429,7 @@ If the command fails (parser cannot extract required fields), log a warning to t
414
429
  ### Remove from Active Specifications Table
415
430
 
416
431
  ```bash
417
- node bin/sf-tools.cjs state remove-active SPEC-XXX
432
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state remove-active SPEC-XXX
418
433
  ```
419
434
 
420
435
  ### Remove from Queue
@@ -43,7 +43,22 @@ Exit.
43
43
 
44
44
  ## Step 2: Resolve Active Specification
45
45
 
46
- Call `node bin/sf-tools.cjs state resolve $ARGUMENTS` (pass the optional SPEC-XXX arg if provided).
46
+ Parse `$ARGUMENTS`:
47
+ - Let `FIRST_TOKEN` = first whitespace-separated token of `$ARGUMENTS`.
48
+ - If `FIRST_TOKEN` matches `^SPEC-\d{3,}$`:
49
+ - Set `SPEC_ARG="$FIRST_TOKEN"`
50
+ - Set `FIX_SCOPE` = remainder of `$ARGUMENTS` after `FIRST_TOKEN` (trimmed)
51
+ - Else:
52
+ - Set `SPEC_ARG=""` (resolver uses Active Specifications table)
53
+ - Set `FIX_SCOPE="$ARGUMENTS"`
54
+
55
+ Call:
56
+
57
+ ```bash
58
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state resolve $SPEC_ARG
59
+ ```
60
+
61
+ Use `FIX_SCOPE` in the subsequent argument-parsing step (Step 5).
47
62
 
48
63
  Parse the JSON response:
49
64
  - `{"action":"use","id":"SPEC-XXX"}` → proceed with SPEC-XXX
@@ -93,14 +108,16 @@ Exit.
93
108
 
94
109
  ## Step 5: Parse Arguments
95
110
 
96
- | Argument | Action |
97
- |----------|--------|
98
- | (none) | Interactive mode show issues, ask what to fix |
111
+ Parse `FIX_SCOPE` (set in Step 2):
112
+
113
+ | Value of `FIX_SCOPE` | Action |
114
+ |----------------------|--------|
115
+ | (empty) | Interactive mode — show issues, ask what to fix |
99
116
  | "all" | Apply all critical AND major AND minor fixes |
100
117
  | "1,2,3" | Apply only numbered items |
101
118
  | "..." | Treat as custom fix instructions |
102
119
 
103
- ### If Interactive Mode (no arguments):
120
+ ### If Interactive Mode (FIX_SCOPE is empty):
104
121
 
105
122
  Display review findings:
106
123
 
@@ -182,7 +199,7 @@ Append to Review History:
182
199
  **If `--internal` is NOT set (normal invocation):**
183
200
 
184
201
  ```bash
185
- node bin/sf-tools.cjs state add-active SPEC-XXX review /sf:review
202
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state add-active SPEC-XXX review /sf:review
186
203
  ```
187
204
 
188
205
  ## Step 9: Display Result
@@ -38,7 +38,7 @@ Exit.
38
38
  Run migration on entry — idempotent, no-op when already migrated:
39
39
 
40
40
  ```bash
41
- node bin/sf-tools.cjs state migrate
41
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state migrate
42
42
  ```
43
43
 
44
44
  Parse the response:
@@ -84,7 +84,7 @@ For each check:
84
84
  Read STATE.md and validate:
85
85
 
86
86
  **E003: Active spec references non-existent file**
87
- - List all active specs via `node bin/sf-tools.cjs state list-active`
87
+ - List all active specs via `node ~/.claude/specflow-cc/bin/sf-tools.cjs state list-active`
88
88
  - For each SPEC-ID, check `.specflow/specs/{ID}.md` exists
89
89
  - If missing: error (repairable — remove that row via `state remove-active`)
90
90
 
@@ -206,7 +206,7 @@ Exit.
206
206
 
207
207
  Show active specs count (uses list-active for multi-spec awareness):
208
208
  ```bash
209
- node bin/sf-tools.cjs state list-active --raw
209
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state list-active --raw
210
210
  ```
211
211
 
212
212
  Display full command reference:
@@ -36,7 +36,22 @@ Exit.
36
36
 
37
37
  ## Step 2: Resolve Active Specification
38
38
 
39
- Call `node bin/sf-tools.cjs state resolve $ARGUMENTS` (pass the optional SPEC-XXX arg if provided).
39
+ Parse `$ARGUMENTS`:
40
+ - Let `FIRST_TOKEN` = first whitespace-separated token of `$ARGUMENTS`.
41
+ - If `FIRST_TOKEN` matches `^SPEC-\d{3,}$`:
42
+ - Set `SPEC_ARG="$FIRST_TOKEN"`
43
+ - Set `PAUSE_NOTE` = remainder of `$ARGUMENTS` after `FIRST_TOKEN` (trimmed)
44
+ - Else:
45
+ - Set `SPEC_ARG=""` (resolver uses Active Specifications table)
46
+ - Set `PAUSE_NOTE="$ARGUMENTS"`
47
+
48
+ Call:
49
+
50
+ ```bash
51
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state resolve $SPEC_ARG
52
+ ```
53
+
54
+ Use `PAUSE_NOTE` in Step 6.5 (notes prompt — pre-populate if non-empty).
40
55
 
41
56
  Parse the JSON response:
42
57
  - `{"action":"use","id":"SPEC-XXX"}` → proceed with SPEC-XXX
@@ -53,7 +68,7 @@ Parse the JSON response:
53
68
  Options: {id — title (status)} for each entry
54
69
  ```
55
70
 
56
- Also call `node bin/sf-tools.cjs state list-active` to capture all active specs in the pause file.
71
+ Also call `node ~/.claude/specflow-cc/bin/sf-tools.cjs state list-active` to capture all active specs in the pause file.
57
72
 
58
73
  ## Step 3: Load Active Specification Details
59
74
 
@@ -39,7 +39,22 @@ Exit.
39
39
 
40
40
  ## Step 2: Resolve Active Specification
41
41
 
42
- Call `node bin/sf-tools.cjs state resolve $ARGUMENTS` (pass the optional SPEC-XXX arg if provided).
42
+ Parse `$ARGUMENTS`:
43
+ - Let `FIRST_TOKEN` = first whitespace-separated token of `$ARGUMENTS`.
44
+ - If `FIRST_TOKEN` matches `^SPEC-\d{3,}$`:
45
+ - Set `SPEC_ARG="$FIRST_TOKEN"`
46
+ - Set `REVIEW_SCOPE` = remainder of `$ARGUMENTS` after `FIRST_TOKEN` (trimmed)
47
+ - Else:
48
+ - Set `SPEC_ARG=""` (resolver uses Active Specifications table)
49
+ - Set `REVIEW_SCOPE="$ARGUMENTS"`
50
+
51
+ Call:
52
+
53
+ ```bash
54
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state resolve $SPEC_ARG
55
+ ```
56
+
57
+ Use `REVIEW_SCOPE` in subsequent steps for any review flags.
43
58
 
44
59
  Parse the JSON response:
45
60
  - `{"action":"use","id":"SPEC-XXX"}` → proceed with SPEC-XXX
@@ -158,7 +173,7 @@ After the agent updates STATE.md, check if rotation is needed:
158
173
 
159
174
  ### If APPROVED (no minor issues):
160
175
 
161
- The `Recommendation:` line is emitted by the reviewer agent (Step 7.5 in `agents/impl-reviewer.md`) using `node bin/sf-tools.cjs recommend --source review --critical 0 --major 0 --minor 0`. The STATE.md Next Step remains `/sf:done` (canonical).
176
+ The `Recommendation:` line is emitted by the reviewer agent (Step 7.5 in `agents/impl-reviewer.md`) using `node ~/.claude/specflow-cc/bin/sf-tools.cjs recommend --source review --critical 0 --major 0 --minor 0`. The STATE.md Next Step remains `/sf:done` (canonical).
162
177
 
163
178
  ```
164
179
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@@ -345,9 +360,9 @@ Append Review History to spec.
345
360
 
346
361
  ```bash
347
362
  # If APPROVED:
348
- node bin/sf-tools.cjs state add-active SPEC-XXX done /sf:done
363
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state add-active SPEC-XXX done /sf:done
349
364
  # If CHANGES_REQUESTED:
350
- node bin/sf-tools.cjs state add-active SPEC-XXX review /sf:fix
365
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state add-active SPEC-XXX review /sf:fix
351
366
  ```
352
367
 
353
368
  </fallback>
@@ -42,7 +42,22 @@ Exit.
42
42
 
43
43
  ## Step 2: Resolve Active Specification
44
44
 
45
- Call `node bin/sf-tools.cjs state resolve $ARGUMENTS` (pass the optional SPEC-XXX arg if provided; strip non-SPEC-ID args first).
45
+ Parse `$ARGUMENTS`:
46
+ - Let `FIRST_TOKEN` = first whitespace-separated token of `$ARGUMENTS`.
47
+ - If `FIRST_TOKEN` matches `^SPEC-\d{3,}$`:
48
+ - Set `SPEC_ARG="$FIRST_TOKEN"`
49
+ - Set `REVISE_SCOPE` = remainder of `$ARGUMENTS` after `FIRST_TOKEN` (trimmed)
50
+ - Else:
51
+ - Set `SPEC_ARG=""` (resolver uses Active Specifications table)
52
+ - Set `REVISE_SCOPE="$ARGUMENTS"`
53
+
54
+ Call:
55
+
56
+ ```bash
57
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state resolve $SPEC_ARG
58
+ ```
59
+
60
+ Use `REVISE_SCOPE` in the subsequent argument-parsing step (Step 5).
46
61
 
47
62
  Parse the JSON response:
48
63
  - `{"action":"use","id":"SPEC-XXX"}` → proceed with SPEC-XXX
@@ -160,9 +175,11 @@ Continue to Step 5 with analysis context available.
160
175
 
161
176
  ## Step 5: Parse Arguments
162
177
 
163
- | Argument | Action |
164
- |----------|--------|
165
- | (none) | Interactive mode show comments, ask what to fix |
178
+ Parse `REVISE_SCOPE` (set in Step 2):
179
+
180
+ | Value of `REVISE_SCOPE` | Action |
181
+ |-------------------------|--------|
182
+ | (empty) | Interactive mode — show comments, ask what to fix |
166
183
  | "all" | Apply all critical issues AND recommendations |
167
184
  | "1,2,3" | Apply only numbered items |
168
185
  | "--no-analysis" | Skip pre-analysis, go directly to review mode |
@@ -170,9 +187,9 @@ Continue to Step 5 with analysis context available.
170
187
 
171
188
  **Check for `--no-analysis` flag:**
172
189
 
173
- If the arguments string contains `--no-analysis`:
190
+ If `REVISE_SCOPE` contains `--no-analysis`:
174
191
  - Set SKIP_ANALYSIS to true
175
- - Remove the `--no-analysis` flag from the arguments string for further processing
192
+ - Remove the `--no-analysis` flag from `REVISE_SCOPE` for further processing
176
193
 
177
194
  ### If Interactive Mode (no arguments):
178
195
 
@@ -532,7 +549,7 @@ In spec frontmatter: `status: auditing`
532
549
 
533
550
  In STATE.md:
534
551
  ```bash
535
- node bin/sf-tools.cjs state add-active SPEC-XXX auditing /sf:audit
552
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state add-active SPEC-XXX auditing /sf:audit
536
553
  ```
537
554
 
538
555
  </fallback>
@@ -42,7 +42,22 @@ Exit.
42
42
 
43
43
  ## Step 2: Resolve Active Specification
44
44
 
45
- Call `node bin/sf-tools.cjs state resolve $ARGUMENTS` (pass the optional SPEC-XXX arg if provided).
45
+ Parse `$ARGUMENTS`:
46
+ - Let `FIRST_TOKEN` = first whitespace-separated token of `$ARGUMENTS`.
47
+ - If `FIRST_TOKEN` matches `^SPEC-\d{3,}$`:
48
+ - Set `SPEC_ARG="$FIRST_TOKEN"`
49
+ - Set `RUN_SCOPE` = remainder of `$ARGUMENTS` after `FIRST_TOKEN` (trimmed)
50
+ - Else:
51
+ - Set `SPEC_ARG=""` (resolver uses Active Specifications table)
52
+ - Set `RUN_SCOPE="$ARGUMENTS"`
53
+
54
+ Call:
55
+
56
+ ```bash
57
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state resolve $SPEC_ARG
58
+ ```
59
+
60
+ Use `RUN_SCOPE` in the subsequent argument-parsing step (Step 3.5).
46
61
 
47
62
  Parse the JSON response:
48
63
  - `{"action":"use","id":"SPEC-XXX"}` → proceed with SPEC-XXX
@@ -68,7 +83,7 @@ Read the active spec file: `.specflow/specs/SPEC-XXX.md`
68
83
 
69
84
  ## Step 3.5: Handle `--apply=minor` Flag
70
85
 
71
- **Check if `--apply=minor` was passed in the invocation arguments.**
86
+ **Check if `RUN_SCOPE` contains `--apply=minor`.**
72
87
 
73
88
  **If `--apply=minor` is NOT present:** Continue to Step 4 (existing behavior unchanged).
74
89
 
@@ -92,7 +107,7 @@ Extract Critical count and Recommendations count from that entry. Map Recommenda
92
107
 
93
108
  Run:
94
109
  ```bash
95
- node bin/sf-tools.cjs recommend --source audit --critical N --minor M
110
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs recommend --source audit --critical N --minor M
96
111
  ```
97
112
 
98
113
  Parse the JSON response.
@@ -118,7 +133,7 @@ This reuses `/sf:revise`'s existing per-item commit behavior. Do NOT duplicate r
118
133
 
119
134
  Run spec structural validation:
120
135
  ```bash
121
- node bin/sf-tools.cjs spec validate SPEC-XXX
136
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs spec validate SPEC-XXX
122
137
  ```
123
138
 
124
139
  This is the exact gate specified in R2.5: verifies frontmatter parses, required fields present (`id`, `type`, `status`, `priority`), and `## Requirements` heading present. No fallback path.
@@ -265,7 +280,7 @@ Use model for `spec-executor` or `spec-executor-orchestrator` from selected prof
265
280
  ## Step 7: Update Status
266
281
 
267
282
  ```bash
268
- node bin/sf-tools.cjs state add-active SPEC-XXX running "(in progress)"
283
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state add-active SPEC-XXX running "(in progress)"
269
284
  ```
270
285
 
271
286
  Update spec frontmatter:
@@ -42,7 +42,7 @@ Exit.
42
42
  Use provided ID (e.g., SPEC-003).
43
43
 
44
44
  **If no argument:**
45
- Call `node bin/sf-tools.cjs state resolve` to get active spec.
45
+ Call `node ~/.claude/specflow-cc/bin/sf-tools.cjs state resolve` to get active spec.
46
46
 
47
47
  Parse the JSON response:
48
48
  - `{"action":"use","id":"SPEC-XXX"}` → use SPEC-XXX
@@ -58,7 +58,7 @@ Use `/sf:list` to see available specifications.
58
58
  Exit.
59
59
 
60
60
  **If no ID provided:**
61
- Call `node bin/sf-tools.cjs state resolve` to get active spec.
61
+ Call `node ~/.claude/specflow-cc/bin/sf-tools.cjs state resolve` to get active spec.
62
62
 
63
63
  Parse the JSON response:
64
64
  - `{"action":"use","id":"SPEC-XXX"}` → use SPEC-XXX
@@ -365,8 +365,8 @@ Add split reference to archived parent.
365
365
  - Add children to Queue (using Read+Write)
366
366
  - Register first child in Active Specifications table:
367
367
  ```bash
368
- node bin/sf-tools.cjs state remove-active SPEC-PARENT
369
- node bin/sf-tools.cjs state add-active SPEC-XXXa draft /sf:audit
368
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state remove-active SPEC-PARENT
369
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state add-active SPEC-XXXa draft /sf:audit
370
370
  ```
371
371
 
372
372
  </fallback>
@@ -39,12 +39,12 @@ Read `.specflow/STATE.md` and extract Queue, Recent Decisions, Warnings.
39
39
 
40
40
  Get active specs:
41
41
  ```bash
42
- node bin/sf-tools.cjs state list-active
42
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state list-active
43
43
  ```
44
44
 
45
45
  For single-spec display, also call:
46
46
  ```bash
47
- node bin/sf-tools.cjs state resolve
47
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state resolve
48
48
  ```
49
49
 
50
50
  Parse the resolve response:
@@ -108,13 +108,13 @@ Fix: Rename the spec in specs/ to next available ID.
108
108
  Compare the set of TODO files on disk to the IDs listed in `.specflow/todos/INDEX.md`:
109
109
 
110
110
  ```bash
111
- node bin/sf-tools.cjs todo check-stale
111
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs todo check-stale
112
112
  ```
113
113
 
114
114
  Parse the JSON response. If `stale: true`, add a warning to the Warnings section:
115
115
 
116
116
  ```
117
- INDEX.md stale — run /sf:todos (or `node bin/sf-tools.cjs todo reindex`).
117
+ INDEX.md stale — run /sf:todos (or `node ~/.claude/specflow-cc/bin/sf-tools.cjs todo reindex`).
118
118
  {If missing_from_index is non-empty:}
119
119
  Missing from INDEX.md (TODO file exists on disk but not listed):
120
120
  {comma-separated list}
@@ -232,7 +232,7 @@ Based on state, provide additional guidance:
232
232
  - [ ] STATE.md loaded
233
233
  - [ ] PROJECT.md info extracted
234
234
  - [ ] Statistics calculated
235
- - [ ] TODO index freshness checked via `node bin/sf-tools.cjs todo check-stale` (warning surfaced if stale)
235
+ - [ ] TODO index freshness checked via `node ~/.claude/specflow-cc/bin/sf-tools.cjs todo check-stale` (warning surfaced if stale)
236
236
  - [ ] Current position displayed
237
237
  - [ ] Queue shown
238
238
  - [ ] Recommended next step clear
@@ -36,7 +36,22 @@ Exit.
36
36
 
37
37
  ## Step 2: Resolve Active Specification
38
38
 
39
- Call `node bin/sf-tools.cjs state resolve $ARGUMENTS` (pass the optional SPEC-XXX arg if provided).
39
+ Parse `$ARGUMENTS`:
40
+ - Let `FIRST_TOKEN` = first whitespace-separated token of `$ARGUMENTS`.
41
+ - If `FIRST_TOKEN` matches `^SPEC-\d{3,}$`:
42
+ - Set `SPEC_ARG="$FIRST_TOKEN"`
43
+ - Set `VERIFY_SCOPE` = remainder of `$ARGUMENTS` after `FIRST_TOKEN` (trimmed)
44
+ - Else:
45
+ - Set `SPEC_ARG=""` (resolver uses Active Specifications table)
46
+ - Set `VERIFY_SCOPE="$ARGUMENTS"`
47
+
48
+ Call:
49
+
50
+ ```bash
51
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs state resolve $SPEC_ARG
52
+ ```
53
+
54
+ Use `VERIFY_SCOPE` in subsequent steps for any verify flags.
40
55
 
41
56
  Parse the JSON response:
42
57
  - `{"action":"use","id":"SPEC-XXX"}` → proceed with SPEC-XXX
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specflow-cc",
3
- "version": "1.22.0",
3
+ "version": "1.22.2",
4
4
  "description": "Spec-driven development system for Claude Code — quality-first workflow with explicit audit cycles",
5
5
  "bin": {
6
6
  "specflow-cc": "bin/install.js"