specflow-cc 1.19.0 → 1.20.1

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.
@@ -171,6 +171,14 @@ rm .specflow/todos/TODO-{XXX}.md
171
171
 
172
172
  **Important:** Only remove after confirmed spec creation. No "Last updated" lines to update.
173
173
 
174
+ 3. **Refresh INDEX.md** via the shared regen helper so the cache no longer references the removed file:
175
+
176
+ ```bash
177
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs todo reindex
178
+ ```
179
+
180
+ This is mandatory — skipping it leaves INDEX.md listing a TODO that no longer exists on disk, which trips the `/sf:status` freshness check and breaks downstream consumers.
181
+
174
182
  ## Step 8: Display Result
175
183
 
176
184
  **IMPORTANT:** Output the following directly as formatted text, NOT wrapped in a markdown code block:
@@ -232,7 +240,12 @@ Use `/sf:new "{todo description}"` logic:
232
240
 
233
241
  ### Remove Todo
234
242
 
235
- Delete the file `.specflow/todos/TODO-{XXX}.md`.
243
+ Delete the file `.specflow/todos/TODO-{XXX}.md`, then refresh INDEX.md:
244
+
245
+ ```bash
246
+ rm .specflow/todos/TODO-{XXX}.md
247
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs todo reindex
248
+ ```
236
249
 
237
250
  </fallback>
238
251
 
@@ -246,5 +259,6 @@ Delete the file `.specflow/todos/TODO-{XXX}.md`.
246
259
  - [ ] Priority inherited from todo
247
260
  - [ ] TODO-XXX.md file deleted (not edited — whole file removed)
248
261
  - [ ] Deletion verified (file no longer exists)
262
+ - [ ] INDEX.md refreshed via `node ~/.claude/specflow-cc/bin/sf-tools.cjs todo reindex`
249
263
  - [ ] Clear result with next step
250
264
  </success_criteria>
@@ -123,7 +123,12 @@ If input matches pattern `{ID}={priority}`:
123
123
 
124
124
  1. Validate priority (high | medium | low)
125
125
  2. **If ID is a spec (SPEC-XXX):** Update `priority:` in frontmatter of `.specflow/specs/SPEC-XXX.md` using the Edit tool
126
- 3. **If ID is a TODO (TODO-XXX):** Read `.specflow/todos/TODO-XXX.md`, update `priority:` line in frontmatter using the Edit tool
126
+ 3. **If ID is a TODO (TODO-XXX):**
127
+ a. Read `.specflow/todos/TODO-XXX.md`, update `priority:` line in frontmatter using the Edit tool
128
+ b. Refresh INDEX.md so the cached priority column matches:
129
+ ```bash
130
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs todo reindex
131
+ ```
127
132
  4. Display confirmation
128
133
  5. Return to Step 3
129
134
 
@@ -203,6 +208,7 @@ Use `/sf:next` to work on highest priority task.
203
208
  - [ ] Reorder command works
204
209
  - [ ] Technical order suggestion available
205
210
  - [ ] TODO priority updated in individual file frontmatter (not TODO.md)
211
+ - [ ] INDEX.md refreshed via `node ~/.claude/specflow-cc/bin/sf-tools.cjs todo reindex` after any TODO priority change
206
212
  - [ ] STATE.md Queue updated after spec reorder
207
213
  - [ ] Clear feedback on changes
208
214
  </success_criteria>
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: sf:review
3
3
  description: Review the implementation against specification
4
+ # SPEC-011: Accepts optional SPEC-XXX as first positional arg; resolves via state resolve
4
5
  allowed-tools:
5
6
  - Read
6
7
  - Write
@@ -36,17 +37,27 @@ Run `/sf:init` first.
36
37
  ```
37
38
  Exit.
38
39
 
39
- ## Step 2: Get Active Specification
40
+ ## Step 2: Resolve Active Specification
40
41
 
41
- Read `.specflow/STATE.md` and extract Active Specification.
42
+ Call `node bin/sf-tools.cjs state resolve $ARGUMENTS` (pass the optional SPEC-XXX arg if provided).
42
43
 
43
- **If no active specification:**
44
- ```
45
- No active specification to review.
44
+ Parse the JSON response:
45
+ - `{"action":"use","id":"SPEC-XXX"}` → proceed with SPEC-XXX
46
+ - `{"action":"error","code":"NO_ACTIVE_SPEC"}` display error and exit:
47
+ ```
48
+ No active specification to review.
46
49
 
47
- Run `/sf:new "task description"` to create one.
48
- ```
49
- Exit.
50
+ Run `/sf:new "task description"` to create one.
51
+ ```
52
+ - `{"action":"error","code":"SPEC_NOT_ACTIVE","id":"SPEC-XXX"}` → display error and exit:
53
+ ```
54
+ SPEC-XXX is not in the Active Specifications table.
55
+ ```
56
+ - `{"action":"ask","options":[...]}` → use AskUserQuestion to show picker:
57
+ ```
58
+ Multiple active specifications. Which one to review?
59
+ Options: {id — title (status)} for each entry
60
+ ```
50
61
 
51
62
  ## Step 3: Load Specification
52
63
 
@@ -319,8 +330,12 @@ Append Review History to spec.
319
330
 
320
331
  ### Update STATE.md
321
332
 
322
- - If APPROVED: Status → "done", Next Step → "/sf:done"
323
- - If CHANGES_REQUESTED: Status → "review", Next Step → "/sf:fix"
333
+ ```bash
334
+ # If APPROVED:
335
+ node bin/sf-tools.cjs state add-active SPEC-XXX done /sf:done
336
+ # If CHANGES_REQUESTED:
337
+ node bin/sf-tools.cjs state add-active SPEC-XXX review /sf:fix
338
+ ```
324
339
 
325
340
  </fallback>
326
341
 
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: sf:revise
3
3
  description: Revise specification based on audit feedback
4
+ # SPEC-011: Accepts optional SPEC-XXX as first positional arg; resolves via state resolve
4
5
  allowed-tools:
5
6
  - Read
6
7
  - Write
@@ -37,17 +38,27 @@ Run `/sf:init` first.
37
38
  ```
38
39
  Exit.
39
40
 
40
- ## Step 2: Get Active Specification
41
+ ## Step 2: Resolve Active Specification
41
42
 
42
- Read `.specflow/STATE.md` and extract Active Specification.
43
+ Call `node bin/sf-tools.cjs state resolve $ARGUMENTS` (pass the optional SPEC-XXX arg if provided; strip non-SPEC-ID args first).
43
44
 
44
- **If no active specification:**
45
- ```
46
- No active specification to revise.
45
+ Parse the JSON response:
46
+ - `{"action":"use","id":"SPEC-XXX"}` → proceed with SPEC-XXX
47
+ - `{"action":"error","code":"NO_ACTIVE_SPEC"}` display error and exit:
48
+ ```
49
+ No active specification to revise.
47
50
 
48
- Run `/sf:new "task description"` to create one.
49
- ```
50
- Exit.
51
+ Run `/sf:new "task description"` to create one.
52
+ ```
53
+ - `{"action":"error","code":"SPEC_NOT_ACTIVE","id":"SPEC-XXX"}` → display error and exit:
54
+ ```
55
+ SPEC-XXX is not in the Active Specifications table.
56
+ ```
57
+ - `{"action":"ask","options":[...]}` → use AskUserQuestion to show picker:
58
+ ```
59
+ Multiple active specifications. Which one to revise?
60
+ Options: {id — title (status)} for each entry
61
+ ```
51
62
 
52
63
  ## Step 3: Load Specification
53
64
 
@@ -500,16 +511,21 @@ After recording the Response, if any items were marked "Deferred":
500
511
  Origin: {SPEC-XXX} Response v{N}. {reason for deferral}
501
512
  ```
502
513
  3. Append "**TODOs Created:**" subsection to the Response in Audit History listing created TODO IDs
514
+ 4. After the loop completes (at least one TODO created), refresh INDEX.md:
515
+ ```bash
516
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs todo reindex
517
+ ```
503
518
 
504
- **This step is mandatory.** Every "Deferred" decision MUST produce a corresponding TODO-XXX.md file.
519
+ **This step is mandatory.** Every "Deferred" decision MUST produce a corresponding TODO-XXX.md file AND the reindex helper MUST run if any TODO was created — otherwise INDEX.md silently drifts out of sync with `todos/`.
505
520
 
506
521
  ### Update Status
507
522
 
508
523
  In spec frontmatter: `status: auditing`
509
524
 
510
525
  In STATE.md:
511
- - Status → "auditing"
512
- - Next Step "/sf:audit"
526
+ ```bash
527
+ node bin/sf-tools.cjs state add-active SPEC-XXX auditing /sf:audit
528
+ ```
513
529
 
514
530
  </fallback>
515
531
 
@@ -520,6 +536,7 @@ In STATE.md:
520
536
  - [ ] Changes applied correctly
521
537
  - [ ] Response recorded in Audit History
522
538
  - [ ] Deferred items (if any) created as individual TODO-XXX.md files in `.specflow/todos/`
539
+ - [ ] INDEX.md refreshed via `node ~/.claude/specflow-cc/bin/sf-tools.cjs todo reindex` (if any TODO was created)
523
540
  - [ ] Spec frontmatter status updated
524
541
  - [ ] STATE.md updated
525
542
  - [ ] Clear summary of changes shown
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: sf:run
3
3
  description: Execute the specification (implement the code)
4
+ # SPEC-011: Accepts optional SPEC-XXX as first positional arg; resolves via state resolve
4
5
  allowed-tools:
5
6
  - Read
6
7
  - Write
@@ -39,17 +40,27 @@ Run `/sf:init` first.
39
40
  ```
40
41
  Exit.
41
42
 
42
- ## Step 2: Get Active Specification
43
+ ## Step 2: Resolve Active Specification
43
44
 
44
- Read `.specflow/STATE.md` and extract Active Specification.
45
+ Call `node bin/sf-tools.cjs state resolve $ARGUMENTS` (pass the optional SPEC-XXX arg if provided).
45
46
 
46
- **If no active specification:**
47
- ```
48
- No active specification to execute.
47
+ Parse the JSON response:
48
+ - `{"action":"use","id":"SPEC-XXX"}` → proceed with SPEC-XXX
49
+ - `{"action":"error","code":"NO_ACTIVE_SPEC"}` display error and exit:
50
+ ```
51
+ No active specification to execute.
49
52
 
50
- Run `/sf:new "task description"` to create one.
51
- ```
52
- Exit.
53
+ Run `/sf:new "task description"` to create one.
54
+ ```
55
+ - `{"action":"error","code":"SPEC_NOT_ACTIVE","id":"SPEC-XXX"}` → display error and exit:
56
+ ```
57
+ SPEC-XXX is not in the Active Specifications table.
58
+ ```
59
+ - `{"action":"ask","options":[...]}` → use AskUserQuestion to show picker:
60
+ ```
61
+ Multiple active specifications. Which one to run?
62
+ Options: {id — title (status)} for each entry
63
+ ```
53
64
 
54
65
  ## Step 3: Load Specification
55
66
 
@@ -182,9 +193,9 @@ Use model for `spec-executor` or `spec-executor-orchestrator` from selected prof
182
193
 
183
194
  ## Step 7: Update Status
184
195
 
185
- Update STATE.md:
186
- - Status "running"
187
- - Next Step → "(in progress)"
196
+ ```bash
197
+ node bin/sf-tools.cjs state add-active SPEC-XXX running "(in progress)"
198
+ ```
188
199
 
189
200
  Update spec frontmatter:
190
201
  - status → "running"
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: sf:show
3
3
  description: Display full specification details
4
+ # SPEC-011: Accepts optional SPEC-XXX as first positional arg; resolves via state resolve when no arg
4
5
  allowed-tools:
5
6
  - Read
6
7
  - Bash
@@ -41,16 +42,22 @@ Exit.
41
42
  Use provided ID (e.g., SPEC-003).
42
43
 
43
44
  **If no argument:**
44
- Read `.specflow/STATE.md` and get Active Specification.
45
-
46
- **If no active specification and no argument:**
47
- ```
48
- No specification specified and no active specification.
49
-
50
- Use `/sf:show SPEC-XXX` to view a specific spec
51
- or `/sf:list` to see all specifications.
52
- ```
53
- Exit.
45
+ Call `node bin/sf-tools.cjs state resolve` to get active spec.
46
+
47
+ Parse the JSON response:
48
+ - `{"action":"use","id":"SPEC-XXX"}` → use SPEC-XXX
49
+ - `{"action":"error","code":"NO_ACTIVE_SPEC"}` display error and exit:
50
+ ```
51
+ No specification specified and no active specification.
52
+
53
+ Use `/sf:show SPEC-XXX` to view a specific spec
54
+ or `/sf:list` to see all specifications.
55
+ ```
56
+ - `{"action":"ask","options":[...]}` → use AskUserQuestion to show picker:
57
+ ```
58
+ Multiple active specifications. Which one to show?
59
+ Options: {id — title (status)} for each entry
60
+ ```
54
61
 
55
62
  ## Step 3: Find Specification File
56
63
 
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: sf:split
3
3
  description: Split a large specification into smaller sub-specifications
4
+ # SPEC-011: Accepts optional SPEC-XXX as first positional arg; resolves via state resolve when no arg
4
5
  allowed-tools:
5
6
  - Read
6
7
  - Write
@@ -57,18 +58,22 @@ Use `/sf:list` to see available specifications.
57
58
  Exit.
58
59
 
59
60
  **If no ID provided:**
60
- Read active specification from `.specflow/STATE.md`:
61
- - Parse "Active Specification" field
62
- - Use that ID
63
-
64
- **If no active specification:**
65
- ```
66
- No specification specified and no active specification.
67
-
68
- Usage: `/sf:split SPEC-001`
69
- or: Set active spec with `/sf:show SPEC-001`
70
- ```
71
- Exit.
61
+ Call `node bin/sf-tools.cjs state resolve` to get active spec.
62
+
63
+ Parse the JSON response:
64
+ - `{"action":"use","id":"SPEC-XXX"}` → use SPEC-XXX
65
+ - `{"action":"error","code":"NO_ACTIVE_SPEC"}` display error and exit:
66
+ ```
67
+ No specification specified and no active specification.
68
+
69
+ Usage: `/sf:split SPEC-001`
70
+ or: Set active spec with `/sf:show SPEC-001`
71
+ ```
72
+ - `{"action":"ask","options":[...]}` → use AskUserQuestion to show picker:
73
+ ```
74
+ Multiple active specifications. Which one to split?
75
+ Options: {id — title (status)} for each entry
76
+ ```
72
77
 
73
78
  ## Step 3: Check Complexity
74
79
 
@@ -356,9 +361,13 @@ Add split reference to archived parent.
356
361
 
357
362
  ### Update STATE.md
358
363
 
359
- - Remove parent from Queue
360
- - Add children to Queue
361
- - Set first child as Active Specification
364
+ - Remove parent from Queue (using Read+Write)
365
+ - Add children to Queue (using Read+Write)
366
+ - Register first child in Active Specifications table:
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
370
+ ```
362
371
 
363
372
  </fallback>
364
373
 
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: sf:status
3
3
  description: Show current SpecFlow state and recommended next step
4
+ # SPEC-011: Uses state list-active and state resolve for multi-spec awareness
4
5
  allowed-tools:
5
6
  - Read
6
7
  - Bash
@@ -34,13 +35,22 @@ Exit.
34
35
 
35
36
  ## Step 2: Load State
36
37
 
37
- Read `.specflow/STATE.md` and extract:
38
- - Active Specification
39
- - Status
40
- - Next Step
41
- - Queue
42
- - Recent Decisions
43
- - Warnings
38
+ Read `.specflow/STATE.md` and extract Queue, Recent Decisions, Warnings.
39
+
40
+ Get active specs:
41
+ ```bash
42
+ node bin/sf-tools.cjs state list-active
43
+ ```
44
+
45
+ For single-spec display, also call:
46
+ ```bash
47
+ node bin/sf-tools.cjs state resolve
48
+ ```
49
+
50
+ Parse the resolve response:
51
+ - `{"action":"use","id":"SPEC-XXX"}` → show single active spec
52
+ - `{"action":"error","code":"NO_ACTIVE_SPEC"}` → show idle state
53
+ - `{"action":"ask","options":[...]}` → show all active specs in table format
44
54
 
45
55
  ## Step 3: Load Project Info
46
56
 
@@ -77,10 +87,10 @@ for f in .specflow/specs/SPEC-*.md; do
77
87
  done
78
88
  ```
79
89
 
80
- **If STATE.md shows "Active Specification: None" but specs exist in specs/:**
90
+ **If the Active Specifications table is empty (no rows) but specs exist in specs/:**
81
91
  Add warning:
82
92
  ```
83
- STATE MISMATCH: Found {N} spec(s) in specs/ but STATE.md shows no active spec.
93
+ STATE MISMATCH: Found {N} spec(s) in specs/ but the Active Specifications table is empty.
84
94
  Likely cause: STATE.md was not updated after spec creation.
85
95
  Run: Read the spec file and manually update STATE.md, or delete orphan spec if duplicate.
86
96
  ```
@@ -93,6 +103,30 @@ Likely cause: Spec numbering bug - archive was not checked when generating ID.
93
103
  Fix: Rename the spec in specs/ to next available ID.
94
104
  ```
95
105
 
106
+ ### TODO Index Freshness
107
+
108
+ Compare the set of TODO files on disk to the IDs listed in `.specflow/todos/INDEX.md`:
109
+
110
+ ```bash
111
+ node bin/sf-tools.cjs todo check-stale
112
+ ```
113
+
114
+ Parse the JSON response. If `stale: true`, add a warning to the Warnings section:
115
+
116
+ ```
117
+ INDEX.md stale — run /sf:todos (or `node bin/sf-tools.cjs todo reindex`).
118
+ {If missing_from_index is non-empty:}
119
+ Missing from INDEX.md (TODO file exists on disk but not listed):
120
+ {comma-separated list}
121
+ {If extra_in_index is non-empty:}
122
+ Stale entries in INDEX.md (listed but TODO file no longer exists):
123
+ {comma-separated list}
124
+ {If !index_exists and todo_count > 0:}
125
+ INDEX.md does not exist yet but {todo_count} TODO file(s) are on disk.
126
+ ```
127
+
128
+ This is a safety net — every command that mutates `todos/` is supposed to call the regen helper itself, but external edits, manual `rm`, or a missed call will surface here. Do NOT auto-fix from `/sf:status`; only report. The user runs `/sf:todos` (or the helper directly) to clear the warning.
129
+
96
130
  ## Step 5: Determine Next Action
97
131
 
98
132
  Based on current status:
@@ -198,6 +232,7 @@ Based on state, provide additional guidance:
198
232
  - [ ] STATE.md loaded
199
233
  - [ ] PROJECT.md info extracted
200
234
  - [ ] Statistics calculated
235
+ - [ ] TODO index freshness checked via `node bin/sf-tools.cjs todo check-stale` (warning surfaced if stale)
201
236
  - [ ] Current position displayed
202
237
  - [ ] Queue shown
203
238
  - [ ] Recommended next step clear
@@ -8,7 +8,7 @@ allowed-tools:
8
8
  ---
9
9
 
10
10
  <purpose>
11
- Display all to-do items from the backlog, sorted by priority. Reads individual TODO-XXX.md files (or legacy TODO.md for backward compatibility). Writes an auto-generated INDEX.md after display. Provides quick access to convert items to specifications.
11
+ Display all to-do items from the backlog, sorted by priority. Reads individual TODO-XXX.md files (or legacy TODO.md for backward compatibility). Refreshes the INDEX.md cache via the shared regen helper after display. Provides quick access to convert items to specifications.
12
12
  </purpose>
13
13
 
14
14
  <context>
@@ -109,27 +109,15 @@ From the list:
109
109
 
110
110
  ## Step 6: Regenerate INDEX.md
111
111
 
112
- After displaying the list, write `.specflow/todos/INDEX.md` using the Write tool.
112
+ After displaying the list, regenerate `.specflow/todos/INDEX.md` by invoking the shared helper:
113
113
 
114
- Use the format from `templates/todo-index.md`:
115
-
116
- ```markdown
117
- # To-Do Index
118
-
119
- > Auto-generated from individual TODO files. Do not edit manually.
120
- > Regenerate with `/sf:todos`.
121
-
122
- | # | ID | Title | Priority | Status | Created |
123
- |---|-----|-------|----------|--------|---------|
124
- {rows from sorted list — one row per TODO}
125
-
126
- **Total:** {N} items ({high} high, {medium} medium, {low} low, {unset} unset)
127
-
128
- ---
129
- *Last regenerated: {YYYY-MM-DD HH:MM}*
114
+ ```bash
115
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs todo reindex
130
116
  ```
131
117
 
132
- **Important:** INDEX.md is a display cache only. Never edit it manually it is regenerated here each time `/sf:todos` runs.
118
+ The helper scans `.specflow/todos/TODO-*.md`, sorts the rows the same way Step 2 does, and writes INDEX.md in the format defined by `templates/todo-index.md`. It is the single source of truth for INDEX layout do NOT write INDEX.md manually here.
119
+
120
+ **Important:** INDEX.md is a cache. Other commands that mutate `todos/` (`/sf:todo`, `/sf:plan`, `/sf:done`, `/sf:triage`, `/sf:revise`, `/sf:priority`, `/sf:migrate-todos`, and the `sf-spec-reviser` agent) must call the same helper after their mutation so the cache stays consistent between `/sf:todos` invocations. `/sf:status` runs `todo check-stale` and warns if drift is detected.
133
121
 
134
122
  </workflow>
135
123
 
@@ -142,6 +130,6 @@ Use the format from `templates/todo-index.md`:
142
130
  - [ ] `--all` flag shows eliminated items visually distinct
143
131
  - [ ] Statistics shown (total, by priority)
144
132
  - [ ] Clear actions provided
145
- - [ ] INDEX.md written to `.specflow/todos/INDEX.md` after display
146
- - [ ] INDEX.md contains "Do not edit manually" notice
133
+ - [ ] INDEX.md regenerated via `node ~/.claude/specflow-cc/bin/sf-tools.cjs todo reindex` after display
134
+ - [ ] INDEX.md header describes it as a cache refreshed by `/sf:todos` or the regen helper
147
135
  </success_criteria>
@@ -188,6 +188,16 @@ created: {YYYY-MM-DD}
188
188
 
189
189
  Do NOT append to TODO.md. Do NOT update any "Last updated" lines. Each finding gets its own separate TODO-XXX.md file.
190
190
 
191
+ ### 6.3 Refresh INDEX.md
192
+
193
+ After all selected TODO files have been written, regenerate the cache once:
194
+
195
+ ```bash
196
+ node ~/.claude/specflow-cc/bin/sf-tools.cjs todo reindex
197
+ ```
198
+
199
+ This is mandatory whenever the triage loop creates at least one TODO. Skipping it leaves INDEX.md missing the just-created entries until the next `/sf:todos` run.
200
+
191
201
  ## Step 7: Display Results
192
202
 
193
203
  **IMPORTANT:** Output the following directly as formatted text, NOT wrapped in a markdown code block:
@@ -255,5 +265,6 @@ Run /sf:triage again to review findings.
255
265
  - [ ] Each file has valid YAML frontmatter (id, title, priority, status, created)
256
266
  - [ ] Priority preserved from scan
257
267
  - [ ] Source reference included in notes (scan date, files, problem)
268
+ - [ ] INDEX.md refreshed via `node ~/.claude/specflow-cc/bin/sf-tools.cjs todo reindex` (skip only if zero TODOs created)
258
269
  - [ ] Clear summary of created TODOs
259
270
  </success_criteria>
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: sf:verify
3
3
  description: Interactive human verification of acceptance criteria
4
+ # SPEC-011: Accepts optional SPEC-XXX as first positional arg; resolves via state resolve
4
5
  allowed-tools:
5
6
  - Read
6
7
  - Write
@@ -33,17 +34,27 @@ Run `/sf:init` first.
33
34
  ```
34
35
  Exit.
35
36
 
36
- ## Step 2: Get Active Specification
37
-
38
- Read `.specflow/STATE.md` and extract Active Specification.
39
-
40
- **If no active specification:**
41
- ```
42
- No active specification to verify.
43
-
44
- Run `/sf:new "task description"` to create one.
45
- ```
46
- Exit.
37
+ ## Step 2: Resolve Active Specification
38
+
39
+ Call `node bin/sf-tools.cjs state resolve $ARGUMENTS` (pass the optional SPEC-XXX arg if provided).
40
+
41
+ Parse the JSON response:
42
+ - `{"action":"use","id":"SPEC-XXX"}` → proceed with SPEC-XXX
43
+ - `{"action":"error","code":"NO_ACTIVE_SPEC"}` display error and exit:
44
+ ```
45
+ No active specification to verify.
46
+
47
+ Run `/sf:new "task description"` to create one.
48
+ ```
49
+ - `{"action":"error","code":"SPEC_NOT_ACTIVE","id":"SPEC-XXX"}` → display error and exit:
50
+ ```
51
+ SPEC-XXX is not in the Active Specifications table.
52
+ ```
53
+ - `{"action":"ask","options":[...]}` → use AskUserQuestion to show picker:
54
+ ```
55
+ Multiple active specifications. Which one to verify?
56
+ Options: {id — title (status)} for each entry
57
+ ```
47
58
 
48
59
  ## Step 3: Load Specification
49
60
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specflow-cc",
3
- "version": "1.19.0",
3
+ "version": "1.20.1",
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"
@@ -2,11 +2,13 @@
2
2
 
3
3
  <!-- This file is kept compact (<100 lines). Old decisions are automatically rotated to DECISIONS_ARCHIVE.md. -->
4
4
 
5
- ## Current Position
5
+ ## Active Specifications
6
6
 
7
- - **Active Specification:** [none | SPEC-XXX]
8
- - **Status:** [idle | drafting | auditing | revision_requested | external_review | running | reviewing]
9
- - **Next Step:** [/sf:new | /sf:audit | /sf:revise | /sf:run | /sf:review | /sf:done]
7
+ <!-- Multi-spec registry. Zero rows = no active specs. One row = single-spec ergonomics (no prompt). -->
8
+ <!-- Multiple rows = resolver emits AskUserQuestion picker when no SPEC-ID argument provided. -->
9
+
10
+ | SPEC-ID | Status | Next Step |
11
+ |---------|--------|-----------|
10
12
 
11
13
  ## Queue
12
14
 
@@ -1,7 +1,9 @@
1
1
  # To-Do Index
2
2
 
3
- > Auto-generated from individual TODO files. Do not edit manually.
4
- > Regenerate with `/sf:todos`.
3
+ > Cache of individual TODO files. Refreshed when `/sf:todos` runs OR when an
4
+ > INDEX-mutating command explicitly invokes the regen helper
5
+ > (`node bin/sf-tools.cjs todo reindex`). Do not edit manually — changes will
6
+ > be overwritten on the next regen.
5
7
 
6
8
  | # | ID | Title | Priority | Status | Created |
7
9
  |---|-----|-------|----------|--------|---------|