specflow-cc 1.19.0 → 1.20.0
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 +33 -0
- package/README.md +9 -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/sf-tools.cjs +54 -6
- 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/pause.md +18 -11
- package/commands/sf/review.md +25 -10
- package/commands/sf/revise.md +22 -10
- 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 +19 -9
- package/commands/sf/verify.md +22 -11
- package/package.json +1 -1
- package/templates/state.md +6 -4
package/bin/sf-tools.cjs
CHANGED
|
@@ -14,8 +14,13 @@
|
|
|
14
14
|
* todo next-id Next available TODO-XXX number
|
|
15
15
|
* todo reindex Regenerate INDEX.md from TODO files
|
|
16
16
|
* queue next First actionable spec from queue
|
|
17
|
-
* state get Current active spec, status, next step
|
|
18
|
-
* state set-active <id> <status> [next] Update active spec in STATE.md
|
|
17
|
+
* state get Current active spec, status, next step (legacy shim)
|
|
18
|
+
* state set-active <id> <status> [next] Update active spec in STATE.md (legacy shim)
|
|
19
|
+
* state list-active List all active specs from Active Specifications table
|
|
20
|
+
* state add-active <id> <status> <next> Append/update one row in Active Specifications table
|
|
21
|
+
* state remove-active <id> Remove one row from Active Specifications table
|
|
22
|
+
* state resolve [id] Resolve active spec; emit JSON contract
|
|
23
|
+
* state migrate One-shot idempotent migration to new schema
|
|
19
24
|
* resolve-model <agent-type> Model for agent by current profile
|
|
20
25
|
* verify-structure Check .specflow/ integrity
|
|
21
26
|
* generate-slug <text> Text to URL-safe slug
|
|
@@ -24,7 +29,16 @@
|
|
|
24
29
|
'use strict';
|
|
25
30
|
|
|
26
31
|
const { output, error, generateSlug } = require('./lib/core.cjs');
|
|
27
|
-
const {
|
|
32
|
+
const {
|
|
33
|
+
cmdStateGet,
|
|
34
|
+
cmdStateSetActive,
|
|
35
|
+
cmdStateListActive,
|
|
36
|
+
cmdStateAddActive,
|
|
37
|
+
cmdStateRemoveActive,
|
|
38
|
+
cmdStateResolve,
|
|
39
|
+
cmdStateMigrate,
|
|
40
|
+
cmdQueueNext,
|
|
41
|
+
} = require('./lib/state.cjs');
|
|
28
42
|
const { cmdSpecLoad, cmdSpecList, cmdSpecNextId } = require('./lib/spec.cjs');
|
|
29
43
|
const { cmdTodoLoad, cmdTodoList, cmdTodoNextId, cmdTodoReindex } = require('./lib/todo.cjs');
|
|
30
44
|
const { cmdResolveModel } = require('./lib/config.cjs');
|
|
@@ -62,13 +76,42 @@ const COMMANDS = {
|
|
|
62
76
|
'todo next-id': () => cmdTodoNextId(cwd, raw),
|
|
63
77
|
'todo reindex': () => cmdTodoReindex(cwd, raw),
|
|
64
78
|
'queue next': () => cmdQueueNext(cwd, raw),
|
|
79
|
+
|
|
80
|
+
// Legacy shims (backwards compatible)
|
|
65
81
|
'state get': () => cmdStateGet(cwd, raw),
|
|
66
82
|
'state set-active': () => {
|
|
67
83
|
if (!filteredArgs[2] || !filteredArgs[3]) {
|
|
68
84
|
error('Missing arguments. Usage: state set-active <id> <status> [next_step]');
|
|
69
85
|
}
|
|
70
|
-
cmdStateSetActive(cwd, filteredArgs[2], filteredArgs[3], filteredArgs[4], raw)
|
|
86
|
+
Promise.resolve(cmdStateSetActive(cwd, filteredArgs[2], filteredArgs[3], filteredArgs[4], raw))
|
|
87
|
+
.catch(e => error(e.message));
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
// New multi-spec state commands
|
|
91
|
+
'state list-active': () => cmdStateListActive(cwd, raw),
|
|
92
|
+
'state add-active': () => {
|
|
93
|
+
if (!filteredArgs[2] || !filteredArgs[3]) {
|
|
94
|
+
error('Missing arguments. Usage: state add-active <id> <status> <next_step>');
|
|
95
|
+
}
|
|
96
|
+
Promise.resolve(cmdStateAddActive(cwd, filteredArgs[2], filteredArgs[3], filteredArgs[4] || '', raw))
|
|
97
|
+
.catch(e => error(e.message));
|
|
71
98
|
},
|
|
99
|
+
'state remove-active': () => {
|
|
100
|
+
if (!filteredArgs[2]) {
|
|
101
|
+
error('Missing arguments. Usage: state remove-active <id>');
|
|
102
|
+
}
|
|
103
|
+
Promise.resolve(cmdStateRemoveActive(cwd, filteredArgs[2], raw))
|
|
104
|
+
.catch(e => error(e.message));
|
|
105
|
+
},
|
|
106
|
+
'state resolve': () => {
|
|
107
|
+
// Optional specId argument (filteredArgs[2])
|
|
108
|
+
cmdStateResolve(cwd, filteredArgs[2] || undefined, raw);
|
|
109
|
+
},
|
|
110
|
+
'state migrate': () => {
|
|
111
|
+
Promise.resolve(cmdStateMigrate(cwd, raw))
|
|
112
|
+
.catch(e => error(e.message));
|
|
113
|
+
},
|
|
114
|
+
|
|
72
115
|
'resolve-model': () => {
|
|
73
116
|
if (!filteredArgs[1]) error('Missing agent type. Usage: resolve-model <agent-type>');
|
|
74
117
|
cmdResolveModel(cwd, filteredArgs[1], raw);
|
|
@@ -94,8 +137,13 @@ Commands:
|
|
|
94
137
|
todo next-id Next available TODO-XXX number
|
|
95
138
|
todo reindex Regenerate INDEX.md from TODO files
|
|
96
139
|
queue next First actionable spec from queue table
|
|
97
|
-
state get Current active spec, status, next step
|
|
98
|
-
state set-active <id> <status> [next] Update active spec, status, next step
|
|
140
|
+
state get Current active spec, status, next step (legacy shim)
|
|
141
|
+
state set-active <id> <status> [next] Update active spec, status, next step (legacy shim)
|
|
142
|
+
state list-active List all rows in Active Specifications table
|
|
143
|
+
state add-active <id> <status> <next> Append/update one row (under advisory lock)
|
|
144
|
+
state remove-active <id> Remove one row (under advisory lock)
|
|
145
|
+
state resolve [SPEC-ID] Resolve active spec; emit JSON contract
|
|
146
|
+
state migrate One-shot idempotent migration to new schema
|
|
99
147
|
resolve-model <agent-type> Resolve model for agent by current profile
|
|
100
148
|
verify-structure Check .specflow/ directory integrity
|
|
101
149
|
generate-slug <text> Convert text to URL-safe slug
|
package/commands/sf/audit.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
name: sf:audit
|
|
3
3
|
description: Audit the active specification in a fresh context
|
|
4
4
|
argument-hint: "[SPEC-XXX] [--import \"feedback\"]"
|
|
5
|
+
# SPEC-011: Accepts optional SPEC-XXX as first positional arg; resolves via state resolve
|
|
5
6
|
allowed-tools:
|
|
6
7
|
- Read
|
|
7
8
|
- Write
|
|
@@ -40,17 +41,27 @@ Run `/sf:init` first.
|
|
|
40
41
|
```
|
|
41
42
|
Exit.
|
|
42
43
|
|
|
43
|
-
## Step 2:
|
|
44
|
+
## Step 2: Resolve Active Specification
|
|
44
45
|
|
|
45
|
-
|
|
46
|
+
Call `node bin/sf-tools.cjs state resolve $ARGUMENTS` (pass the optional SPEC-XXX arg if provided).
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
Parse the JSON response:
|
|
49
|
+
- `{"action":"use","id":"SPEC-XXX"}` → proceed with SPEC-XXX
|
|
50
|
+
- `{"action":"error","code":"NO_ACTIVE_SPEC"}` → display error and exit:
|
|
51
|
+
```
|
|
52
|
+
No active specification to audit.
|
|
50
53
|
|
|
51
|
-
Run `/sf:new "task description"` to create one.
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
+
Run `/sf:new "task description"` to create one.
|
|
55
|
+
```
|
|
56
|
+
- `{"action":"error","code":"SPEC_NOT_ACTIVE","id":"SPEC-XXX"}` → display error and exit:
|
|
57
|
+
```
|
|
58
|
+
SPEC-XXX is not in the Active Specifications table.
|
|
59
|
+
```
|
|
60
|
+
- `{"action":"ask","options":[...]}` → use AskUserQuestion to show picker:
|
|
61
|
+
```
|
|
62
|
+
Multiple active specifications. Which one to audit?
|
|
63
|
+
Options: {id — title (status)} for each entry
|
|
64
|
+
```
|
|
54
65
|
|
|
55
66
|
## Step 3: Load Specification
|
|
56
67
|
|
|
@@ -143,10 +154,11 @@ In spec frontmatter, set: `status: revision_requested`
|
|
|
143
154
|
|
|
144
155
|
### 4.6 Update STATE.md
|
|
145
156
|
|
|
146
|
-
Update STATE.md:
|
|
147
|
-
|
|
148
|
-
-
|
|
149
|
-
|
|
157
|
+
Update STATE.md via CLI:
|
|
158
|
+
```bash
|
|
159
|
+
node bin/sf-tools.cjs state add-active SPEC-XXX external_review /sf:revise
|
|
160
|
+
```
|
|
161
|
+
Add decision: "Imported external feedback for SPEC-XXX"
|
|
150
162
|
|
|
151
163
|
### 4.7 Display Import Result
|
|
152
164
|
|
package/commands/sf/autopilot.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
name: sf:autopilot
|
|
3
3
|
description: Run full spec lifecycle autonomously (audit -> run -> review -> done)
|
|
4
4
|
argument-hint: "[SPEC-XXX] [--all]"
|
|
5
|
+
# SPEC-011: Accepts optional SPEC-XXX; resolves via state resolve; FAILS when N>1 and no ID (no picker)
|
|
5
6
|
allowed-tools:
|
|
6
7
|
- Read
|
|
7
8
|
- Write
|
|
@@ -43,25 +44,42 @@ Parse the command argument to determine execution mode:
|
|
|
43
44
|
|
|
44
45
|
| Argument | Mode | Behavior |
|
|
45
46
|
|----------|------|----------|
|
|
46
|
-
| (none) | single |
|
|
47
|
-
| `SPEC-XXX` | single |
|
|
48
|
-
| `--all` | batch | Process all actionable specs in Queue order |
|
|
47
|
+
| (none) | single | Resolve active spec; fail fast if N>1 (no picker) |
|
|
48
|
+
| `SPEC-XXX` | single | Process this explicit spec ID |
|
|
49
|
+
| `--all` | batch | Process all actionable specs in Queue order; still requires explicit SPEC-ID if N>1 |
|
|
49
50
|
|
|
50
|
-
**
|
|
51
|
-
- If SPEC-XXX argument provided: update STATE.md to set it as active spec
|
|
52
|
-
- If no argument and no active spec exists: display error and exit
|
|
51
|
+
**CRITICAL — N>1 guard (autopilot must be unambiguous):**
|
|
53
52
|
|
|
54
|
-
|
|
55
|
-
- Identify all actionable specs from Queue (any spec with status: draft, auditing, revision_requested, audited, running, review)
|
|
53
|
+
Call `node bin/sf-tools.cjs state resolve $SPEC_ID_ARG` (pass SPEC-ID arg if provided; omit if not).
|
|
56
54
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
Parse the JSON response:
|
|
56
|
+
- `{"action":"use","id":"SPEC-XXX"}` → proceed with SPEC-XXX
|
|
57
|
+
- `{"action":"error","code":"NO_ACTIVE_SPEC"}` → display error and exit:
|
|
58
|
+
```
|
|
59
|
+
No active specification to process.
|
|
60
60
|
|
|
61
|
-
Provide a spec ID: `/sf:autopilot SPEC-XXX`
|
|
62
|
-
Or run on all specs: `/sf:autopilot --all`
|
|
63
|
-
```
|
|
64
|
-
|
|
61
|
+
Provide a spec ID: `/sf:autopilot SPEC-XXX`
|
|
62
|
+
Or run on all specs: `/sf:autopilot --all`
|
|
63
|
+
```
|
|
64
|
+
- `{"action":"error","code":"SPEC_NOT_ACTIVE","id":"SPEC-XXX"}` → display error and exit:
|
|
65
|
+
```
|
|
66
|
+
SPEC-XXX is not in the Active Specifications table.
|
|
67
|
+
```
|
|
68
|
+
- `{"action":"ask","options":[...]}` → **FAIL FAST** (do NOT show picker):
|
|
69
|
+
```
|
|
70
|
+
Autopilot requires explicit SPEC-ID when >1 active specs.
|
|
71
|
+
|
|
72
|
+
Active specs: {list SPEC-IDs from options}
|
|
73
|
+
|
|
74
|
+
Provide a spec ID: `/sf:autopilot SPEC-XXX`
|
|
75
|
+
```
|
|
76
|
+
Exit. (This applies to both plain `/sf:autopilot` AND `/sf:autopilot --all` without a SPEC-ID. `--all` controls within-spec behavior, not multi-spec iteration.)
|
|
77
|
+
|
|
78
|
+
**If single mode with explicit SPEC-ID:**
|
|
79
|
+
- SPEC-ID was resolved via state resolve above (action:use)
|
|
80
|
+
|
|
81
|
+
**If batch mode (--all):**
|
|
82
|
+
- Identify all actionable specs from Queue (any spec with status: draft, auditing, revision_requested, audited, running, review)
|
|
65
83
|
|
|
66
84
|
## Step 3: Set Configuration Constants
|
|
67
85
|
|
|
@@ -107,8 +125,7 @@ current_spec = null
|
|
|
107
125
|
|
|
108
126
|
### 5.1 Load Current Spec State
|
|
109
127
|
|
|
110
|
-
Read `.specflow/
|
|
111
|
-
Read `.specflow/specs/SPEC-XXX.md` to get frontmatter status.
|
|
128
|
+
Read `.specflow/specs/SPEC-XXX.md` to get frontmatter status (spec ID resolved in Step 2).
|
|
112
129
|
|
|
113
130
|
### 5.2 Determine Current Phase
|
|
114
131
|
|
|
@@ -255,10 +272,11 @@ mv .specflow/specs/SPEC-XXX.md .specflow/archive/
|
|
|
255
272
|
```
|
|
256
273
|
|
|
257
274
|
5. **Update STATE.md:**
|
|
258
|
-
- Active
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
275
|
+
Remove SPEC-XXX from Active Specifications table:
|
|
276
|
+
```bash
|
|
277
|
+
node bin/sf-tools.cjs state remove-active SPEC-XXX
|
|
278
|
+
```
|
|
279
|
+
Remove SPEC-XXX row from Queue table (using Read+Write).
|
|
262
280
|
|
|
263
281
|
6. **Check STATE.md size and rotate** (same logic as 5.5 step 2)
|
|
264
282
|
|
package/commands/sf/discuss.md
CHANGED
|
@@ -62,9 +62,10 @@ Determine discussion mode from arguments:
|
|
|
62
62
|
- Mode: `requirements-gathering`
|
|
63
63
|
|
|
64
64
|
**Case E: No arguments**
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
65
|
+
- Call `node bin/sf-tools.cjs state resolve` to resolve active spec
|
|
66
|
+
- `{"action":"use","id":"SPEC-XXX"}` → discuss that spec
|
|
67
|
+
- `{"action":"error","code":"NO_ACTIVE_SPEC"}` → ask what to discuss
|
|
68
|
+
- `{"action":"ask","options":[...]}` → use AskUserQuestion to pick which spec to discuss
|
|
68
69
|
|
|
69
70
|
## 3. Load Context
|
|
70
71
|
|
package/commands/sf/done.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sf:done
|
|
3
3
|
description: Finalize specification, archive, and update state
|
|
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 finalize.
|
|
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 finalize?
|
|
59
|
+
Options: {id — title (status)} for each entry
|
|
60
|
+
```
|
|
50
61
|
|
|
51
62
|
## Step 3: Load Specification
|
|
52
63
|
|
|
@@ -309,11 +320,11 @@ mv .specflow/specs/SPEC-XXX.md .specflow/archive/
|
|
|
309
320
|
|
|
310
321
|
## Step 9: Update STATE.md
|
|
311
322
|
|
|
312
|
-
###
|
|
323
|
+
### Remove from Active Specifications Table
|
|
313
324
|
|
|
314
|
-
|
|
315
|
-
-
|
|
316
|
-
|
|
325
|
+
```bash
|
|
326
|
+
node bin/sf-tools.cjs state remove-active SPEC-XXX
|
|
327
|
+
```
|
|
317
328
|
|
|
318
329
|
### Remove from Queue
|
|
319
330
|
|
package/commands/sf/fix.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sf:fix
|
|
3
3
|
description: Fix implementation based on review 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
|
|
@@ -38,17 +39,27 @@ Run `/sf:init` first.
|
|
|
38
39
|
```
|
|
39
40
|
Exit.
|
|
40
41
|
|
|
41
|
-
## Step 2:
|
|
42
|
+
## Step 2: Resolve Active Specification
|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
Call `node bin/sf-tools.cjs state resolve $ARGUMENTS` (pass the optional SPEC-XXX arg if provided).
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
Parse the JSON response:
|
|
47
|
+
- `{"action":"use","id":"SPEC-XXX"}` → proceed with SPEC-XXX
|
|
48
|
+
- `{"action":"error","code":"NO_ACTIVE_SPEC"}` → display error and exit:
|
|
49
|
+
```
|
|
50
|
+
No active specification to fix.
|
|
48
51
|
|
|
49
|
-
Run `/sf:new "task description"` to create one.
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
+
Run `/sf:new "task description"` to create one.
|
|
53
|
+
```
|
|
54
|
+
- `{"action":"error","code":"SPEC_NOT_ACTIVE","id":"SPEC-XXX"}` → display error and exit:
|
|
55
|
+
```
|
|
56
|
+
SPEC-XXX is not in the Active Specifications table.
|
|
57
|
+
```
|
|
58
|
+
- `{"action":"ask","options":[...]}` → use AskUserQuestion to show picker:
|
|
59
|
+
```
|
|
60
|
+
Multiple active specifications. Which one to fix?
|
|
61
|
+
Options: {id — title (status)} for each entry
|
|
62
|
+
```
|
|
52
63
|
|
|
53
64
|
## Step 3: Load Specification
|
|
54
65
|
|
|
@@ -164,8 +175,9 @@ Append to Review History:
|
|
|
164
175
|
|
|
165
176
|
## Step 8: Update STATE.md
|
|
166
177
|
|
|
167
|
-
|
|
168
|
-
-
|
|
178
|
+
```bash
|
|
179
|
+
node bin/sf-tools.cjs state add-active SPEC-XXX review /sf:review
|
|
180
|
+
```
|
|
169
181
|
|
|
170
182
|
## Step 9: Display Result
|
|
171
183
|
|
package/commands/sf/health.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
name: sf:health
|
|
3
3
|
description: Diagnose .specflow/ directory health and optionally repair issues
|
|
4
4
|
argument-hint: [--repair]
|
|
5
|
+
# SPEC-011: Invokes migrate-state on entry; re-stamps STATE.md header from template after migration (--repair path)
|
|
5
6
|
allowed-tools:
|
|
6
7
|
- Read
|
|
7
8
|
- Bash
|
|
@@ -32,7 +33,19 @@ SpecFlow not initialized. Run `/sf:init` first.
|
|
|
32
33
|
```
|
|
33
34
|
Exit.
|
|
34
35
|
|
|
35
|
-
## Step 2:
|
|
36
|
+
## Step 2: Invoke STATE.md Migration (entry point)
|
|
37
|
+
|
|
38
|
+
Run migration on entry — idempotent, no-op when already migrated:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
node bin/sf-tools.cjs state migrate
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Parse the response:
|
|
45
|
+
- `{"migrated":true,...}` → Migration completed. After migration, re-stamp the `## Active Specifications` header block in STATE.md from `templates/state.md` to reconcile any format drift (non-destructive: Queue, Decisions, Notes sections are preserved; only the Active Specifications block is normalized). This is the `--repair` path.
|
|
46
|
+
- `{"migrated":false,...}` → Already migrated, no action needed.
|
|
47
|
+
|
|
48
|
+
## Step 2.5: Parse Arguments
|
|
36
49
|
|
|
37
50
|
Check if `--repair` flag is present.
|
|
38
51
|
|
|
@@ -71,9 +84,9 @@ For each check:
|
|
|
71
84
|
Read STATE.md and validate:
|
|
72
85
|
|
|
73
86
|
**E003: Active spec references non-existent file**
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
- If missing: error (repairable —
|
|
87
|
+
- List all active specs via `node bin/sf-tools.cjs state list-active`
|
|
88
|
+
- For each SPEC-ID, check `.specflow/specs/{ID}.md` exists
|
|
89
|
+
- If missing: error (repairable — remove that row via `state remove-active`)
|
|
77
90
|
|
|
78
91
|
**W005: Queue references non-existent spec file**
|
|
79
92
|
- Parse queue table rows
|
package/commands/sf/help.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sf:help
|
|
3
3
|
description: Show SpecFlow help and command reference
|
|
4
|
+
# SPEC-011: Uses state list-active to show active specs in overview; no state resolve needed (no single-spec operations)
|
|
4
5
|
allowed-tools:
|
|
5
6
|
- Read
|
|
6
7
|
- Glob
|
|
@@ -203,6 +204,11 @@ Exit.
|
|
|
203
204
|
|
|
204
205
|
## Step 2b: Overview Help
|
|
205
206
|
|
|
207
|
+
Show active specs count (uses list-active for multi-spec awareness):
|
|
208
|
+
```bash
|
|
209
|
+
node bin/sf-tools.cjs state list-active --raw
|
|
210
|
+
```
|
|
211
|
+
|
|
206
212
|
Display full command reference:
|
|
207
213
|
|
|
208
214
|
```
|
package/commands/sf/pause.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sf:pause
|
|
3
3
|
description: Save current work context for later resumption
|
|
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,20 +34,26 @@ Run `/sf:init` to start.
|
|
|
33
34
|
```
|
|
34
35
|
Exit.
|
|
35
36
|
|
|
36
|
-
## Step 2:
|
|
37
|
+
## Step 2: Resolve Active Specification
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
- Active Specification
|
|
40
|
-
- Status
|
|
41
|
-
- Next Step
|
|
39
|
+
Call `node bin/sf-tools.cjs state resolve $ARGUMENTS` (pass the optional SPEC-XXX arg if provided).
|
|
42
40
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
Parse the JSON response:
|
|
42
|
+
- `{"action":"use","id":"SPEC-XXX"}` → proceed with SPEC-XXX
|
|
43
|
+
- `{"action":"error","code":"NO_ACTIVE_SPEC"}` → display info and allow general notes:
|
|
44
|
+
```
|
|
45
|
+
No active work to pause.
|
|
46
46
|
|
|
47
|
-
Current state: idle
|
|
48
|
-
```
|
|
49
|
-
|
|
47
|
+
Current state: idle
|
|
48
|
+
```
|
|
49
|
+
Still allow pausing to capture general notes.
|
|
50
|
+
- `{"action":"ask","options":[...]}` → use AskUserQuestion to show picker:
|
|
51
|
+
```
|
|
52
|
+
Multiple active specifications. Which session to pause?
|
|
53
|
+
Options: {id — title (status)} for each entry
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Also call `node bin/sf-tools.cjs state list-active` to capture all active specs in the pause file.
|
|
50
57
|
|
|
51
58
|
## Step 3: Load Active Specification Details
|
|
52
59
|
|
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
|
|
|
@@ -508,8 +519,9 @@ After recording the Response, if any items were marked "Deferred":
|
|
|
508
519
|
In spec frontmatter: `status: auditing`
|
|
509
520
|
|
|
510
521
|
In STATE.md:
|
|
511
|
-
|
|
512
|
-
-
|
|
522
|
+
```bash
|
|
523
|
+
node bin/sf-tools.cjs state add-active SPEC-XXX auditing /sf:audit
|
|
524
|
+
```
|
|
513
525
|
|
|
514
526
|
</fallback>
|
|
515
527
|
|
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"
|