specflow-cc 1.20.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 +15 -0
- package/agents/spec-reviser.md +8 -1
- package/bin/lib/todo.cjs +74 -2
- package/bin/sf-tools.cjs +4 -1
- package/commands/sf/migrate-todos.md +7 -17
- package/commands/sf/plan.md +15 -1
- package/commands/sf/priority.md +7 -1
- package/commands/sf/revise.md +6 -1
- package/commands/sf/status.md +25 -0
- package/commands/sf/todos.md +9 -21
- package/commands/sf/triage.md +11 -0
- package/package.json +1 -1
- package/templates/todo-index.md +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,21 @@ 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.20.1] - 2026-05-14
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **INDEX.md staleness across all TODO-mutating paths** — `1.19.0` wired the `todo reindex` helper into `/sf:todo` and `/sf:done`, but every other command that mutates `.specflow/todos/` (`/sf:plan` `rm`, `/sf:triage` create, `/sf:revise` deferred-TODO creation, `/sf:priority` priority edits, `/sf:migrate-todos`, and the `sf-spec-reviser` agent) still left INDEX.md silently out of sync. All of these now invoke `node bin/sf-tools.cjs todo reindex` after the mutation. `/sf:todos` no longer writes INDEX.md inline — it delegates to the same helper, making the reindex routine the single source of truth for INDEX layout.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **`todo check-stale` CLI subcommand** in `bin/sf-tools.cjs` — compares the set of `TODO-*.md` files on disk to the set of IDs in `INDEX.md` and returns `{stale, index_exists, todo_count, index_count, missing_from_index, extra_in_index}`. Used by `/sf:status` as a safety-net freshness check: if any drift is detected (external edits, manual `rm`, a missed helper call), `/sf:status` surfaces an "INDEX.md stale" warning naming the specific divergences. No auto-fix — the user re-runs `/sf:todos` or the helper.
|
|
17
|
+
- 9 new tests in `tests/todo-index.test.cjs` covering reindex idempotency, header content, drop-after-delete, and all `check-stale` scenarios (fresh, extra-in-index, missing-from-index, no-INDEX-with-files, empty-both, raw output).
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- **INDEX.md header text** rewritten to describe actual behaviour. Old wording ("Auto-generated from individual TODO files. Do not edit manually. Regenerate with `/sf:todos`.") implied a self-maintaining file. New wording: "Cache of individual TODO files. Refreshed when `/sf:todos` runs OR when an INDEX-mutating command explicitly invokes the regen helper (`node bin/sf-tools.cjs todo reindex`). Do not edit manually — changes will be overwritten on the next regen." Applied in both `bin/lib/todo.cjs` (the source of truth) and `templates/todo-index.md`.
|
|
22
|
+
|
|
8
23
|
## [1.20.0] - 2026-05-02
|
|
9
24
|
|
|
10
25
|
### Added
|
package/agents/spec-reviser.md
CHANGED
|
@@ -176,7 +176,13 @@ For each deferred item:
|
|
|
176
176
|
- TODO-{XXX} — {item description}
|
|
177
177
|
```
|
|
178
178
|
|
|
179
|
-
|
|
179
|
+
4. After the loop completes (at least one TODO created), refresh the INDEX.md cache so it reflects the newly-created files:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
node bin/sf-tools.cjs todo reindex
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**Important:** Both substeps are mandatory. Every deferred item MUST produce a TODO, and if any TODO is created the reindex helper MUST run before reporting completion. Skipping the reindex leaves `.specflow/todos/INDEX.md` missing the just-created entries, which the `/sf:status` freshness check will then flag. If TODO creation fails, report the failure — do not silently skip.
|
|
180
186
|
|
|
181
187
|
## Step 6: Update Frontmatter
|
|
182
188
|
|
|
@@ -245,6 +251,7 @@ Tip: `/clear` recommended — auditor needs fresh context
|
|
|
245
251
|
- [ ] Revision Response recorded in Audit History
|
|
246
252
|
- [ ] Deferred items (if any) created as individual `.specflow/todos/TODO-XXX.md` files
|
|
247
253
|
- [ ] TODOs Created subsection appended to Response (if deferred items exist)
|
|
254
|
+
- [ ] INDEX.md refreshed via `node bin/sf-tools.cjs todo reindex` (if any TODO was created)
|
|
248
255
|
- [ ] Frontmatter status updated
|
|
249
256
|
- [ ] STATE.md updated
|
|
250
257
|
- [ ] Clear summary of changes provided
|
package/bin/lib/todo.cjs
CHANGED
|
@@ -295,8 +295,10 @@ function cmdTodoReindex(cwd, raw) {
|
|
|
295
295
|
const lines = [
|
|
296
296
|
'# To-Do Index',
|
|
297
297
|
'',
|
|
298
|
-
'>
|
|
299
|
-
'>
|
|
298
|
+
'> Cache of individual TODO files. Refreshed when `/sf:todos` runs OR when an',
|
|
299
|
+
'> INDEX-mutating command explicitly invokes the regen helper',
|
|
300
|
+
'> (`node bin/sf-tools.cjs todo reindex`). Do not edit manually — changes will',
|
|
301
|
+
'> be overwritten on the next regen.',
|
|
300
302
|
'',
|
|
301
303
|
'| # | ID | Title | Priority | Status | Created |',
|
|
302
304
|
'|---|-----|-------|----------|--------|---------|',
|
|
@@ -324,9 +326,79 @@ function cmdTodoReindex(cwd, raw) {
|
|
|
324
326
|
output({ reindexed: todos.length, path: indexPath }, raw, `Reindexed ${todos.length} TODOs → INDEX.md`);
|
|
325
327
|
}
|
|
326
328
|
|
|
329
|
+
/**
|
|
330
|
+
* Check whether INDEX.md is stale relative to TODO-*.md files.
|
|
331
|
+
*
|
|
332
|
+
* Stale = the set of TODO-XXX IDs on disk diverges from the set of TODO-XXX IDs
|
|
333
|
+
* listed in INDEX.md (file deleted but still in INDEX, or file present but missing).
|
|
334
|
+
*
|
|
335
|
+
* NOTE: Eliminated TODOs (`status: eliminated`) still appear in `/sf:todos --all`
|
|
336
|
+
* regenerated INDEX.md output, so they are NOT filtered here — both sides see them.
|
|
337
|
+
*
|
|
338
|
+
* Output JSON: { stale, missing_from_index, extra_in_index, index_exists }
|
|
339
|
+
* - missing_from_index: file exists on disk but not in INDEX.md
|
|
340
|
+
* - extra_in_index: ID listed in INDEX.md but no file on disk
|
|
341
|
+
*
|
|
342
|
+
* @param {string} cwd - Working directory
|
|
343
|
+
* @param {boolean} raw - Output mode
|
|
344
|
+
*/
|
|
345
|
+
function cmdTodoCheckStale(cwd, raw) {
|
|
346
|
+
const todosDir = path.join(cwd, '.specflow', 'todos');
|
|
347
|
+
const indexPath = path.join(todosDir, 'INDEX.md');
|
|
348
|
+
|
|
349
|
+
// Collect IDs from disk
|
|
350
|
+
const diskIds = new Set();
|
|
351
|
+
try {
|
|
352
|
+
for (const f of fs.readdirSync(todosDir)) {
|
|
353
|
+
const m = f.match(/^(TODO-\d+)\.md$/);
|
|
354
|
+
if (m) diskIds.add(m[1]);
|
|
355
|
+
}
|
|
356
|
+
} catch (e) {
|
|
357
|
+
// todos dir missing — treat as empty
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Collect IDs referenced in INDEX.md (parse only the table rows)
|
|
361
|
+
const indexIds = new Set();
|
|
362
|
+
const indexContent = safeReadFile(indexPath);
|
|
363
|
+
const indexExists = indexContent !== null;
|
|
364
|
+
|
|
365
|
+
if (indexContent) {
|
|
366
|
+
// Match TODO-XXX in pipe-table cells: "| N | TODO-001 | ..."
|
|
367
|
+
const regex = /\|\s*\d+\s*\|\s*(TODO-\d+)\s*\|/g;
|
|
368
|
+
let m;
|
|
369
|
+
while ((m = regex.exec(indexContent)) !== null) {
|
|
370
|
+
indexIds.add(m[1]);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const missingFromIndex = [...diskIds].filter(id => !indexIds.has(id)).sort();
|
|
375
|
+
const extraInIndex = [...indexIds].filter(id => !diskIds.has(id)).sort();
|
|
376
|
+
|
|
377
|
+
// If INDEX.md does not exist but there are TODO files, INDEX is stale.
|
|
378
|
+
// If INDEX.md does not exist and no TODO files, not stale (nothing to track).
|
|
379
|
+
const stale =
|
|
380
|
+
missingFromIndex.length > 0 ||
|
|
381
|
+
extraInIndex.length > 0 ||
|
|
382
|
+
(!indexExists && diskIds.size > 0);
|
|
383
|
+
|
|
384
|
+
output(
|
|
385
|
+
{
|
|
386
|
+
stale,
|
|
387
|
+
index_exists: indexExists,
|
|
388
|
+
todo_count: diskIds.size,
|
|
389
|
+
index_count: indexIds.size,
|
|
390
|
+
missing_from_index: missingFromIndex,
|
|
391
|
+
extra_in_index: extraInIndex,
|
|
392
|
+
},
|
|
393
|
+
raw,
|
|
394
|
+
stale ? 'STALE' : 'FRESH'
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
|
|
327
398
|
module.exports = {
|
|
328
399
|
cmdTodoLoad,
|
|
329
400
|
cmdTodoList,
|
|
330
401
|
cmdTodoNextId,
|
|
331
402
|
cmdTodoReindex,
|
|
403
|
+
cmdTodoCheckStale,
|
|
332
404
|
};
|
package/bin/sf-tools.cjs
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* todo list [--all] List all TODOs sorted by priority
|
|
14
14
|
* todo next-id Next available TODO-XXX number
|
|
15
15
|
* todo reindex Regenerate INDEX.md from TODO files
|
|
16
|
+
* todo check-stale Report drift between TODO-*.md and INDEX.md
|
|
16
17
|
* queue next First actionable spec from queue
|
|
17
18
|
* state get Current active spec, status, next step (legacy shim)
|
|
18
19
|
* state set-active <id> <status> [next] Update active spec in STATE.md (legacy shim)
|
|
@@ -40,7 +41,7 @@ const {
|
|
|
40
41
|
cmdQueueNext,
|
|
41
42
|
} = require('./lib/state.cjs');
|
|
42
43
|
const { cmdSpecLoad, cmdSpecList, cmdSpecNextId } = require('./lib/spec.cjs');
|
|
43
|
-
const { cmdTodoLoad, cmdTodoList, cmdTodoNextId, cmdTodoReindex } = require('./lib/todo.cjs');
|
|
44
|
+
const { cmdTodoLoad, cmdTodoList, cmdTodoNextId, cmdTodoReindex, cmdTodoCheckStale } = require('./lib/todo.cjs');
|
|
44
45
|
const { cmdResolveModel } = require('./lib/config.cjs');
|
|
45
46
|
const { cmdVerifyStructure } = require('./lib/verify.cjs');
|
|
46
47
|
|
|
@@ -75,6 +76,7 @@ const COMMANDS = {
|
|
|
75
76
|
'todo list': () => cmdTodoList(cwd, raw, { showAll: flags.all ?? false }),
|
|
76
77
|
'todo next-id': () => cmdTodoNextId(cwd, raw),
|
|
77
78
|
'todo reindex': () => cmdTodoReindex(cwd, raw),
|
|
79
|
+
'todo check-stale': () => cmdTodoCheckStale(cwd, raw),
|
|
78
80
|
'queue next': () => cmdQueueNext(cwd, raw),
|
|
79
81
|
|
|
80
82
|
// Legacy shims (backwards compatible)
|
|
@@ -136,6 +138,7 @@ Commands:
|
|
|
136
138
|
todo list [--all] List TODOs sorted by priority (--all includes eliminated)
|
|
137
139
|
todo next-id Next available TODO-XXX number
|
|
138
140
|
todo reindex Regenerate INDEX.md from TODO files
|
|
141
|
+
todo check-stale Report drift between TODO-*.md and INDEX.md
|
|
139
142
|
queue next First actionable spec from queue table
|
|
140
143
|
state get Current active spec, status, next step (legacy shim)
|
|
141
144
|
state set-active <id> <status> [next] Update active spec, status, next step (legacy shim)
|
|
@@ -13,7 +13,7 @@ Migrate an existing monolithic `.specflow/todos/TODO.md` to the new per-file for
|
|
|
13
13
|
This is a one-time migration command. After migration:
|
|
14
14
|
- `TODO.md` is renamed to `TODO.md.bak` (NOT deleted — safety net)
|
|
15
15
|
- Each TODO becomes its own `TODO-XXX.md` file
|
|
16
|
-
- `INDEX.md` is
|
|
16
|
+
- `INDEX.md` is regenerated from the new files via the shared `todo reindex` helper
|
|
17
17
|
- All other commands will use the new per-file format automatically
|
|
18
18
|
|
|
19
19
|
Use `--dry-run` to preview the migration without writing any files.
|
|
@@ -173,24 +173,14 @@ created: {YYYY-MM-DD}
|
|
|
173
173
|
|
|
174
174
|
## Step 7: Generate INDEX.md
|
|
175
175
|
|
|
176
|
-
|
|
176
|
+
Invoke the shared regen helper to build `.specflow/todos/INDEX.md` from the migrated files:
|
|
177
177
|
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
> Auto-generated from individual TODO files. Do not edit manually.
|
|
182
|
-
> Regenerate with `/sf:todos`.
|
|
183
|
-
|
|
184
|
-
| # | ID | Title | Priority | Status | Created |
|
|
185
|
-
|---|-----|-------|----------|--------|---------|
|
|
186
|
-
{one row per TODO, sorted by priority then created date}
|
|
187
|
-
|
|
188
|
-
**Total:** {N} items ({high} high, {medium} medium, {low} low, {unset} unset)
|
|
189
|
-
|
|
190
|
-
---
|
|
191
|
-
*Last regenerated: {YYYY-MM-DD HH:MM}*
|
|
178
|
+
```bash
|
|
179
|
+
node ~/.claude/specflow-cc/bin/sf-tools.cjs todo reindex
|
|
192
180
|
```
|
|
193
181
|
|
|
182
|
+
Do NOT write INDEX.md inline — the helper is the single source of truth for its layout (see `templates/todo-index.md`).
|
|
183
|
+
|
|
194
184
|
## Step 8: Rename Legacy TODO.md
|
|
195
185
|
|
|
196
186
|
```bash
|
|
@@ -245,7 +235,7 @@ Migrated {N} TODOs from TODO.md to per-file format.
|
|
|
245
235
|
- [ ] Individual TODO-XXX.md files created for each block
|
|
246
236
|
- [ ] Each file has valid YAML frontmatter (id, title, priority, status, created)
|
|
247
237
|
- [ ] Title derived from description (first sentence, ~80 chars)
|
|
248
|
-
- [ ] INDEX.md
|
|
238
|
+
- [ ] INDEX.md regenerated via `node ~/.claude/specflow-cc/bin/sf-tools.cjs todo reindex`
|
|
249
239
|
- [ ] TODO.md renamed to TODO.md.bak (NOT deleted)
|
|
250
240
|
- [ ] Clear migration summary shown
|
|
251
241
|
- [ ] Cleanup instructions provided
|
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/revise.md
CHANGED
|
@@ -511,8 +511,12 @@ After recording the Response, if any items were marked "Deferred":
|
|
|
511
511
|
Origin: {SPEC-XXX} Response v{N}. {reason for deferral}
|
|
512
512
|
```
|
|
513
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
|
+
```
|
|
514
518
|
|
|
515
|
-
**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/`.
|
|
516
520
|
|
|
517
521
|
### Update Status
|
|
518
522
|
|
|
@@ -532,6 +536,7 @@ node bin/sf-tools.cjs state add-active SPEC-XXX auditing /sf:audit
|
|
|
532
536
|
- [ ] Changes applied correctly
|
|
533
537
|
- [ ] Response recorded in Audit History
|
|
534
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)
|
|
535
540
|
- [ ] Spec frontmatter status updated
|
|
536
541
|
- [ ] STATE.md updated
|
|
537
542
|
- [ ] Clear summary of changes shown
|
package/commands/sf/status.md
CHANGED
|
@@ -103,6 +103,30 @@ Likely cause: Spec numbering bug - archive was not checked when generating ID.
|
|
|
103
103
|
Fix: Rename the spec in specs/ to next available ID.
|
|
104
104
|
```
|
|
105
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
|
+
|
|
106
130
|
## Step 5: Determine Next Action
|
|
107
131
|
|
|
108
132
|
Based on current status:
|
|
@@ -208,6 +232,7 @@ Based on state, provide additional guidance:
|
|
|
208
232
|
- [ ] STATE.md loaded
|
|
209
233
|
- [ ] PROJECT.md info extracted
|
|
210
234
|
- [ ] Statistics calculated
|
|
235
|
+
- [ ] TODO index freshness checked via `node bin/sf-tools.cjs todo check-stale` (warning surfaced if stale)
|
|
211
236
|
- [ ] Current position displayed
|
|
212
237
|
- [ ] Queue shown
|
|
213
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/package.json
CHANGED
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
|
|---|-----|-------|----------|--------|---------|
|