specflow-cc 1.22.0 → 1.22.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 +6 -0
- package/bin/lib/todo.cjs +27 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,12 @@ All notable changes to SpecFlow will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.22.1] - 2026-05-20
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- `todo next-id` now scans `.specflow/specs/` and `.specflow/archive/` for `source: TODO-XXX` frontmatter entries, preventing reissue of retired IDs. Previously, a TODO file deleted during promotion to a spec could have its ID reassigned to an unrelated new TODO, leaving downstream `/sf:plan` unable to operate on the new TODO (it rejects the ID as "already promoted").
|
|
13
|
+
|
|
8
14
|
## [1.22.0] - 2026-05-19
|
|
9
15
|
|
|
10
16
|
### Added
|
package/bin/lib/todo.cjs
CHANGED
|
@@ -183,6 +183,8 @@ function cmdTodoList(cwd, raw, { showAll } = {}) {
|
|
|
183
183
|
* Scans:
|
|
184
184
|
* 1. .specflow/todos/TODO-*.md filenames using fs.readdirSync() + JS regex
|
|
185
185
|
* 2. .specflow/todos/TODO.md for legacy IDs using fs.readFileSync() + /TODO-(\d+)/g
|
|
186
|
+
* 3. .specflow/specs/*.md and .specflow/archive/*.md for `source: TODO-XXX`
|
|
187
|
+
* frontmatter entries (retired IDs from promoted TODOs).
|
|
186
188
|
*
|
|
187
189
|
* NOTE: Does NOT use grep -oP (GNU-only, unavailable on macOS).
|
|
188
190
|
*
|
|
@@ -222,6 +224,31 @@ function cmdTodoNextId(cwd, raw) {
|
|
|
222
224
|
// file may not exist — skip
|
|
223
225
|
}
|
|
224
226
|
|
|
227
|
+
// Scan promoted-spec frontmatter for retired TODO IDs.
|
|
228
|
+
// On promotion, the source TODO file is deleted; the only surviving
|
|
229
|
+
// record is `source: TODO-XXX` in the spec's frontmatter. Without this
|
|
230
|
+
// scan, next-id can reissue a retired ID and downstream `/sf:plan` will
|
|
231
|
+
// reject the new TODO because the archive still records the old promotion.
|
|
232
|
+
for (const sub of ['specs', 'archive']) {
|
|
233
|
+
const dir = path.join(cwd, '.specflow', sub);
|
|
234
|
+
let files;
|
|
235
|
+
try {
|
|
236
|
+
files = fs.readdirSync(dir).filter(f => f.endsWith('.md'));
|
|
237
|
+
} catch (e) { continue; }
|
|
238
|
+
for (const file of files) {
|
|
239
|
+
let content;
|
|
240
|
+
try {
|
|
241
|
+
content = fs.readFileSync(path.join(dir, file), 'utf8');
|
|
242
|
+
} catch (e) { continue; }
|
|
243
|
+
const regex = /(?:^|\n)source:\s*TODO-(\d+)/g;
|
|
244
|
+
let match;
|
|
245
|
+
while ((match = regex.exec(content)) !== null) {
|
|
246
|
+
const num = parseInt(match[1], 10);
|
|
247
|
+
if (num > maxNum) maxNum = num;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
225
252
|
const nextNumber = maxNum + 1;
|
|
226
253
|
const nextId = 'TODO-' + String(nextNumber).padStart(3, '0');
|
|
227
254
|
|