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.
- package/CHANGELOG.md +48 -0
- package/README.md +9 -1
- package/agents/spec-reviser.md +8 -1
- package/bin/lib/core.cjs +26 -0
- package/bin/lib/lock.cjs +213 -0
- package/bin/lib/migrate-state.cjs +242 -0
- package/bin/lib/resolve.cjs +171 -0
- package/bin/lib/state.cjs +350 -52
- package/bin/lib/todo.cjs +74 -2
- package/bin/sf-tools.cjs +58 -7
- package/commands/sf/audit.md +24 -12
- package/commands/sf/autopilot.md +39 -21
- package/commands/sf/discuss.md +4 -3
- package/commands/sf/done.md +23 -12
- package/commands/sf/fix.md +22 -10
- package/commands/sf/health.md +17 -4
- package/commands/sf/help.md +6 -0
- package/commands/sf/migrate-todos.md +7 -17
- package/commands/sf/pause.md +18 -11
- package/commands/sf/plan.md +15 -1
- package/commands/sf/priority.md +7 -1
- package/commands/sf/review.md +25 -10
- package/commands/sf/revise.md +28 -11
- package/commands/sf/run.md +22 -11
- package/commands/sf/show.md +17 -10
- package/commands/sf/split.md +24 -15
- package/commands/sf/status.md +44 -9
- package/commands/sf/todos.md +9 -21
- package/commands/sf/triage.md +11 -0
- package/commands/sf/verify.md +22 -11
- package/package.json +1 -1
- package/templates/state.md +6 -4
- package/templates/todo-index.md +4 -2
package/commands/sf/plan.md
CHANGED
|
@@ -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>
|
package/commands/sf/priority.md
CHANGED
|
@@ -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):**
|
|
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>
|
package/commands/sf/review.md
CHANGED
|
@@ -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:
|
|
40
|
+
## Step 2: Resolve Active Specification
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
Call `node bin/sf-tools.cjs state resolve $ARGUMENTS` (pass the optional SPEC-XXX arg if provided).
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
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
|
-
|
|
323
|
-
|
|
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
|
|
package/commands/sf/revise.md
CHANGED
|
@@ -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:
|
|
41
|
+
## Step 2: Resolve Active Specification
|
|
41
42
|
|
|
42
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
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
|
-
|
|
512
|
-
-
|
|
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
|
package/commands/sf/run.md
CHANGED
|
@@ -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:
|
|
43
|
+
## Step 2: Resolve Active Specification
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
Call `node bin/sf-tools.cjs state resolve $ARGUMENTS` (pass the optional SPEC-XXX arg if provided).
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
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
|
-
|
|
186
|
-
-
|
|
187
|
-
|
|
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"
|
package/commands/sf/show.md
CHANGED
|
@@ -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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
|
package/commands/sf/split.md
CHANGED
|
@@ -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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
```
|
|
66
|
-
No specification specified and no active specification.
|
|
67
|
-
|
|
68
|
-
Usage: `/sf:split SPEC-001`
|
|
69
|
-
|
|
70
|
-
```
|
|
71
|
-
|
|
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
|
-
-
|
|
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
|
|
package/commands/sf/status.md
CHANGED
|
@@ -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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
|
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
|
|
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
|
package/commands/sf/todos.md
CHANGED
|
@@ -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).
|
|
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,
|
|
112
|
+
After displaying the list, regenerate `.specflow/todos/INDEX.md` by invoking the shared helper:
|
|
113
113
|
|
|
114
|
-
|
|
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
|
-
|
|
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
|
|
146
|
-
- [ ] INDEX.md
|
|
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>
|
package/commands/sf/triage.md
CHANGED
|
@@ -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>
|
package/commands/sf/verify.md
CHANGED
|
@@ -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:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
package/templates/state.md
CHANGED
|
@@ -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
|
-
##
|
|
5
|
+
## Active Specifications
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
|
package/templates/todo-index.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# To-Do Index
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
>
|
|
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
|
|---|-----|-------|----------|--------|---------|
|