specflow-cc 1.18.0 → 1.18.2
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 +19 -0
- package/bin/install.js +26 -4
- package/commands/sf/metrics.md +2 -2
- package/commands/sf/plan.md +3 -3
- package/commands/sf/priority.md +1 -1
- package/commands/sf/revise.md +1 -1
- package/commands/sf/todo.md +1 -1
- package/commands/sf/todos.md +3 -3
- package/commands/sf/triage.md +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,25 @@ 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.18.2] - 2026-04-11
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **Installer no longer corrupts `settings.json`** — the installer wrote the `context-monitor` PostToolUse hook as a flat `{ type, command }` object, but Claude Code expects every `PostToolUse` entry to be a matcher group of the shape `{ matcher?, hooks: [{ type, command }] }`. Claude Code failed to parse `settings.json` with `"Expected array, but received undefined"`, and permission rules in the affected file were silently disabled
|
|
13
|
+
- The hook is now written as a proper matcher group
|
|
14
|
+
- Broken duplicate-detection fixed: the installer previously checked `entry.command` on the top-level entry, but in the correct format the command lives inside `entry.hooks[i].command`. As a result, every repeat install pushed a new (broken) entry. Detection now walks `entry.hooks[]` and matches the existing hook correctly, so repeat installs are idempotent
|
|
15
|
+
- Smoke test extended with four new cases: format assertion, presence check, repeat-install idempotency, and preservation of a pre-existing correctly-formatted hook
|
|
16
|
+
- **Heads-up:** if you already ran `1.18.0` or `1.18.1` against a `settings.json` that had a pre-existing PostToolUse hook, you may have a duplicate flat entry. Remove any `PostToolUse` element that lacks a `hooks:` array (i.e. has `type`/`command` at the top level) and re-run the installer
|
|
17
|
+
|
|
18
|
+
## [1.18.1] - 2026-04-11
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **Installer now copies `bin/`** — the installer previously shipped `agents/`, `templates/`, `commands/`, and `hooks/` into `~/.claude/specflow-cc/` but never copied `bin/`, so any slash command invoking `node bin/sf-tools.cjs ...` failed with `MODULE_NOT_FOUND` in user projects. Affected commands: `/sf:todos`, `/sf:priority`, `/sf:metrics`, `/sf:plan`, `/sf:triage`, `/sf:revise`, `/sf:todo`
|
|
23
|
+
- Installer now copies `bin/` recursively (excluding `install.js` itself) via the existing `copyWithPathReplacement` helper
|
|
24
|
+
- All 12 affected command invocations rewritten to use the absolute path `node ~/.claude/specflow-cc/bin/sf-tools.cjs` (auto-rewritten to `./.claude/specflow-cc/` for local installs by the existing path-replacement pass)
|
|
25
|
+
- New smoke test `tests/install-bin-cli.test.cjs` runs the full installer in a temp project and invokes the installed CLI end-to-end, preventing regression
|
|
26
|
+
|
|
8
27
|
## [1.18.0] - 2026-04-08
|
|
9
28
|
|
|
10
29
|
### Added
|
package/bin/install.js
CHANGED
|
@@ -213,6 +213,20 @@ function install(isGlobal) {
|
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
+
// Copy bin (CLI tools) — exclude install.js, which is the installer itself
|
|
217
|
+
const binSrc = path.join(src, 'bin');
|
|
218
|
+
if (fs.existsSync(binSrc)) {
|
|
219
|
+
const binDest = path.join(specflowDir, 'bin');
|
|
220
|
+
copyWithPathReplacement(binSrc, binDest, pathPrefix);
|
|
221
|
+
const installerCopy = path.join(binDest, 'install.js');
|
|
222
|
+
if (fs.existsSync(installerCopy)) fs.unlinkSync(installerCopy);
|
|
223
|
+
if (verifyInstalled(binDest, 'bin')) {
|
|
224
|
+
console.log(` ${green}✓${reset} Installed bin (CLI tools)`);
|
|
225
|
+
} else {
|
|
226
|
+
failures.push('bin');
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
216
230
|
// Copy hooks
|
|
217
231
|
const hooksSrc = path.join(src, 'hooks');
|
|
218
232
|
if (fs.existsSync(hooksSrc)) {
|
|
@@ -275,13 +289,21 @@ function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallS
|
|
|
275
289
|
if (!settings.hooks) settings.hooks = {};
|
|
276
290
|
if (!settings.hooks.PostToolUse) settings.hooks.PostToolUse = [];
|
|
277
291
|
|
|
278
|
-
|
|
279
|
-
|
|
292
|
+
// Claude Code expects each PostToolUse entry to be a matcher group:
|
|
293
|
+
// { matcher?: string, hooks: [{ type, command }, ...] }
|
|
294
|
+
// Detect an existing context-monitor hook inside any matcher group.
|
|
295
|
+
const hasMonitor = settings.hooks.PostToolUse.some(entry =>
|
|
296
|
+
Array.isArray(entry && entry.hooks) &&
|
|
297
|
+
entry.hooks.some(h => h && h.command && h.command.includes('context-monitor'))
|
|
280
298
|
);
|
|
281
299
|
if (!hasMonitor) {
|
|
282
300
|
settings.hooks.PostToolUse.push({
|
|
283
|
-
|
|
284
|
-
|
|
301
|
+
hooks: [
|
|
302
|
+
{
|
|
303
|
+
type: 'command',
|
|
304
|
+
command: monitorCommand
|
|
305
|
+
}
|
|
306
|
+
]
|
|
285
307
|
});
|
|
286
308
|
console.log(` ${green}✓${reset} Configured context monitor hook`);
|
|
287
309
|
}
|
package/commands/sf/metrics.md
CHANGED
|
@@ -80,12 +80,12 @@ For each `.specflow/archive/SPEC-*.md`:
|
|
|
80
80
|
|
|
81
81
|
```bash
|
|
82
82
|
# Count todos via CLI tool (format-agnostic, excludes eliminated by default)
|
|
83
|
-
node bin/sf-tools.cjs todo list --raw
|
|
83
|
+
node ~/.claude/specflow-cc/bin/sf-tools.cjs todo list --raw
|
|
84
84
|
```
|
|
85
85
|
|
|
86
86
|
This returns the list of open TODO IDs. For `--all` (including eliminated):
|
|
87
87
|
```bash
|
|
88
|
-
node bin/sf-tools.cjs todo list --all --raw
|
|
88
|
+
node ~/.claude/specflow-cc/bin/sf-tools.cjs todo list --all --raw
|
|
89
89
|
```
|
|
90
90
|
|
|
91
91
|
Parse priority breakdown from the JSON output to count by priority level.
|
package/commands/sf/plan.md
CHANGED
|
@@ -46,7 +46,7 @@ Exit.
|
|
|
46
46
|
## Step 2: Check for Todos
|
|
47
47
|
|
|
48
48
|
```bash
|
|
49
|
-
node bin/sf-tools.cjs todo list --raw
|
|
49
|
+
node ~/.claude/specflow-cc/bin/sf-tools.cjs todo list --raw
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
**If empty output (no todos):**
|
|
@@ -62,13 +62,13 @@ Exit.
|
|
|
62
62
|
Format detection is handled automatically by the CLI tool.
|
|
63
63
|
|
|
64
64
|
**If argument is a number (e.g., "1", "2"):**
|
|
65
|
-
Run `node bin/sf-tools.cjs todo list` to get sorted array, pick the Nth item (1-indexed).
|
|
65
|
+
Run `node ~/.claude/specflow-cc/bin/sf-tools.cjs todo list` to get sorted array, pick the Nth item (1-indexed).
|
|
66
66
|
|
|
67
67
|
**If argument is TODO-XXX format:**
|
|
68
68
|
The target ID is known directly.
|
|
69
69
|
|
|
70
70
|
**If no argument:**
|
|
71
|
-
Run `node bin/sf-tools.cjs todo list` and display todos, then prompt:
|
|
71
|
+
Run `node ~/.claude/specflow-cc/bin/sf-tools.cjs todo list` and display todos, then prompt:
|
|
72
72
|
|
|
73
73
|
```
|
|
74
74
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
package/commands/sf/priority.md
CHANGED
package/commands/sf/revise.md
CHANGED
|
@@ -476,7 +476,7 @@ After recording the Response, if any items were marked "Deferred":
|
|
|
476
476
|
|
|
477
477
|
1. For each deferred item, generate next TODO ID:
|
|
478
478
|
```bash
|
|
479
|
-
node bin/sf-tools.cjs todo next-id --raw
|
|
479
|
+
node ~/.claude/specflow-cc/bin/sf-tools.cjs todo next-id --raw
|
|
480
480
|
```
|
|
481
481
|
2. Create `.specflow/todos/TODO-{XXX}.md` for each deferred item:
|
|
482
482
|
```markdown
|
package/commands/sf/todo.md
CHANGED
|
@@ -60,7 +60,7 @@ Use AskUserQuestion:
|
|
|
60
60
|
Run the CLI tool to get the next available ID:
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
|
-
node bin/sf-tools.cjs todo next-id --raw
|
|
63
|
+
node ~/.claude/specflow-cc/bin/sf-tools.cjs todo next-id --raw
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
This handles both per-file format (TODO-XXX.md) and legacy TODO.md automatically.
|
package/commands/sf/todos.md
CHANGED
|
@@ -41,12 +41,12 @@ Call the CLI tool, which handles format detection automatically:
|
|
|
41
41
|
|
|
42
42
|
**If `--all` flag was passed:**
|
|
43
43
|
```bash
|
|
44
|
-
node bin/sf-tools.cjs todo list --all
|
|
44
|
+
node ~/.claude/specflow-cc/bin/sf-tools.cjs todo list --all
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
**Otherwise:**
|
|
48
48
|
```bash
|
|
49
|
-
node bin/sf-tools.cjs todo list
|
|
49
|
+
node ~/.claude/specflow-cc/bin/sf-tools.cjs todo list
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
The tool returns a JSON array of `{ id, title, priority, status, complexity, created }` objects, sorted by priority (high > medium > low > unset), then by created date (oldest first).
|
|
@@ -135,7 +135,7 @@ Use the format from `templates/todo-index.md`:
|
|
|
135
135
|
|
|
136
136
|
<success_criteria>
|
|
137
137
|
- [ ] Initialization verified
|
|
138
|
-
- [ ] TODOs listed via `node bin/sf-tools.cjs todo list` (format-agnostic)
|
|
138
|
+
- [ ] TODOs listed via `node ~/.claude/specflow-cc/bin/sf-tools.cjs todo list` (format-agnostic)
|
|
139
139
|
- [ ] Empty state handled with helpful message
|
|
140
140
|
- [ ] Sorted by priority then date (oldest first within same priority)
|
|
141
141
|
- [ ] Numbered list displayed with Status column
|
package/commands/sf/triage.md
CHANGED
|
@@ -146,7 +146,7 @@ For each selected finding:
|
|
|
146
146
|
### 6.1 Generate TODO ID
|
|
147
147
|
|
|
148
148
|
```bash
|
|
149
|
-
node bin/sf-tools.cjs todo next-id --raw
|
|
149
|
+
node ~/.claude/specflow-cc/bin/sf-tools.cjs todo next-id --raw
|
|
150
150
|
```
|
|
151
151
|
|
|
152
152
|
This handles both per-file format and legacy TODO.md automatically (uses Node.js fs/regex — not grep -oP).
|