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 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
@@ -176,7 +176,13 @@ For each deferred item:
176
176
  - TODO-{XXX} — {item description}
177
177
  ```
178
178
 
179
- **Important:** This step is mandatory. Every deferred item MUST produce a TODO. If TODO creation fails, report the failure do not silently skip.
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
- '> Auto-generated from individual TODO files. Do not edit manually.',
299
- '> Regenerate with `/sf:todos`.',
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 generated from the new files
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
- Write `.specflow/todos/INDEX.md` with all migrated TODOs, sorted by priority then date:
176
+ Invoke the shared regen helper to build `.specflow/todos/INDEX.md` from the migrated files:
177
177
 
178
- ```markdown
179
- # To-Do Index
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 generated from migrated files
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
@@ -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>
@@ -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
@@ -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
@@ -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>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specflow-cc",
3
- "version": "1.20.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"
@@ -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
  |---|-----|-------|----------|--------|---------|