@gobing-ai/spur 0.3.86 → 0.3.87

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.
Files changed (46) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/plugin-scripts.json +4 -0
  3. package/config/templates/feature/default.md +2 -0
  4. package/config/templates/task/brainstorm.md +2 -2
  5. package/config/templates/task/feature-impl.md +2 -2
  6. package/config/templates/task/issue.md +2 -2
  7. package/config/templates/task/meta.md +2 -2
  8. package/config/templates/task/review.md +2 -2
  9. package/config/templates/task/standard.md +2 -2
  10. package/config/workflow-candidates.json +13 -35
  11. package/config/workflows/feature-lifecycle.yaml +6 -0
  12. package/config/workflows/feature-verification.yaml +6 -5
  13. package/config/workflows/idea-pipeline.yaml +72 -36
  14. package/package.json +1 -1
  15. package/plugins/sp/README.md +7 -4
  16. package/plugins/sp/commands/dev-idea.md +9 -2
  17. package/plugins/sp/commands/dev-refactor.md +33 -0
  18. package/plugins/sp/plugin.json +1 -1
  19. package/plugins/sp/references/roles.md +1 -1
  20. package/plugins/sp/scripts/idea-coverage-check.ts +168 -0
  21. package/plugins/sp/scripts/inline-pipeline-parity-check.ts +114 -3
  22. package/plugins/sp/scripts/inline-run-setup.ts +28 -18
  23. package/plugins/sp/skills/brainstorm/SKILL.md +4 -0
  24. package/plugins/sp/skills/code-refactoring/SKILL.md +155 -0
  25. package/plugins/sp/skills/code-refactoring/references/finding-schema.md +74 -0
  26. package/plugins/sp/skills/code-refactoring/references/fix-ladder.md +52 -0
  27. package/plugins/sp/skills/code-refactoring/references/focus-detection.md +44 -0
  28. package/plugins/sp/skills/code-refactoring/references/refactor-finding.schema.json +95 -0
  29. package/plugins/sp/skills/spec-decomposition/references/decomposition.md +23 -16
  30. package/plugins/sp/skills/spur-cli/references/features/acceptance-criteria.md +4 -2
  31. package/plugins/sp/skills/spur-cli/references/features.md +6 -1
  32. package/plugins/sp/skills/spur-cli/references/workflows/authoring-workflows.md +2 -2
  33. package/plugins/sp/skills/spur-cli/references/workflows/operations.md +3 -3
  34. package/plugins/sp/skills/spur-cli/references/workflows/workflow-fit-and-tuning.md +1 -1
  35. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +24 -0
  36. package/plugins/sp/skills/spur-dev/references/dev-operations.md +18 -2
  37. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +22 -3
  38. package/plugins/sp/skills/spur-dev/references/idea-evaluation.md +11 -1
  39. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +33 -1
  40. package/plugins/sp/skills/taste-refactoring-api/SKILL.md +44 -1
  41. package/plugins/sp/skills/taste-refactoring-api/references/protocol-modes.md +31 -0
  42. package/plugins/sp/skills/taste-refactoring-architect/SKILL.md +43 -0
  43. package/plugins/sp/skills/taste-refactoring-tests/SKILL.md +42 -0
  44. package/plugins/sp/skills/taste-refactoring-ui/SKILL.md +43 -0
  45. package/schemas/task-batch.schema.json +2 -2
  46. package/spur.js +124 -23
@@ -7,7 +7,7 @@
7
7
  "plugins": [
8
8
  {
9
9
  "name": "sp",
10
- "version": "0.3.86",
10
+ "version": "0.3.87",
11
11
  "source": "./plugins/sp"
12
12
  }
13
13
  ]
@@ -50,6 +50,10 @@
50
50
  "rel": "inline-run-setup.ts",
51
51
  "contract": "repo-only"
52
52
  },
53
+ {
54
+ "rel": "idea-coverage-check.ts",
55
+ "contract": "repo-only"
56
+ },
53
57
  {
54
58
  "rel": "inline-pipeline-parity-check.ts",
55
59
  "contract": "repo-only"
@@ -23,6 +23,8 @@ updated_at: "{{ CREATED_AT }}"
23
23
  ## Acceptance Criteria
24
24
 
25
25
  ```gherkin
26
+ # Keep the Feature: line (feature check L3.ac-bdd-error without it). Each Scenario: title is the
27
+ # identity key tasks reference verbatim ("- [ ] AC1 — <title>"); number R1, R2, …; never rename after tasks link.
26
28
  Feature: {{ NAME }}
27
29
 
28
30
  Scenario: Basic acceptance
@@ -23,11 +23,11 @@ updated_at: "{{ CREATED_AT }}"
23
23
 
24
24
  ### Requirements
25
25
 
26
- <!-- Constraints the eventual direction must satisfy, if known. -->
26
+ <!-- One R-item per line, exactly `- [ ] R1. <text>` (checkbox + `R<n>.`); `spur task check` flags any other form. Constraints the eventual direction must satisfy, if known. -->
27
27
 
28
28
  ### Acceptance Criteria
29
29
 
30
- <!-- Decision criteria or success checks for the brainstorm output. Keep empty if not applicable. -->
30
+ <!-- Number items AC1, AC2, … (never R<n> — that is the Requirements namespace): `- [ ] AC1 — <feature scenario title without its R-number>` bullets or `Scenario: AC1 — <title>` blocks; add `(req: R<n>)` to bind a task requirement; task-only checks go in prose below, or set `ac_altitude: task-local`. Keep empty if not applicable. -->
31
31
 
32
32
  ### Q&A
33
33
 
@@ -23,11 +23,11 @@ updated_at: "{{ CREATED_AT }}"
23
23
 
24
24
  ### Requirements
25
25
 
26
- <!-- R-numbered list derived from the linked feature or refined task scope. -->
26
+ <!-- One R-item per line, exactly `- [ ] R1. <text>` (checkbox + `R<n>.`); `spur task check` flags any other form. Derive from the linked feature or refined task scope. -->
27
27
 
28
28
  ### Acceptance Criteria
29
29
 
30
- <!-- Copy or derive real scenarios from the linked feature. Do not leave placeholder AC here. -->
30
+ <!-- Number items AC1, AC2, … (never R<n> — that is the Requirements namespace): `- [ ] AC1 — <feature scenario title without its R-number>` bullets or `Scenario: AC1 — <title>` blocks; add `(req: R<n>)` to bind a task requirement; task-only checks go in prose below, or set `ac_altitude: task-local`. Do not leave placeholder AC here. -->
31
31
 
32
32
  ### Q&A
33
33
 
@@ -23,11 +23,11 @@ updated_at: "{{ CREATED_AT }}"
23
23
 
24
24
  ### Requirements
25
25
 
26
- <!-- R-numbered expectations for the fix. Include repro/expected behavior if it helps traceability. -->
26
+ <!-- One R-item per line, exactly `- [ ] R1. <text>` (checkbox + `R<n>.`); `spur task check` flags any other form. Include repro/expected behavior if it helps traceability. -->
27
27
 
28
28
  ### Acceptance Criteria
29
29
 
30
- <!-- Given/When/Then regression scenario or checklist proving the bug is fixed. -->
30
+ <!-- Number items AC1, AC2, … (never R<n> — that is the Requirements namespace): `- [ ] AC1 — <feature scenario title without its R-number>` bullets or `Scenario: AC1 — <title>` blocks; add `(req: R<n>)` to bind a task requirement; task-only checks go in prose below, or set `ac_altitude: task-local`. Use a regression scenario proving the bug is fixed. -->
31
31
 
32
32
  ### Q&A
33
33
 
@@ -23,11 +23,11 @@ updated_at: "{{ CREATED_AT }}"
23
23
 
24
24
  ### Requirements
25
25
 
26
- <!-- R-numbered expectations for the process/docs/chore outcome. Keep empty if not applicable. -->
26
+ <!-- One R-item per line, exactly `- [ ] R1. <text>` (checkbox + `R<n>.`); `spur task check` flags any other form. Keep empty if not applicable. -->
27
27
 
28
28
  ### Acceptance Criteria
29
29
 
30
- <!-- Lightweight checklist or Given/When/Then if there is an observable completion condition. -->
30
+ <!-- Number items AC1, AC2, … (never R<n> — that is the Requirements namespace): `- [ ] AC1 — <feature scenario title without its R-number>` bullets or `Scenario: AC1 — <title>` blocks; add `(req: R<n>)` to bind a task requirement; task-only checks go in prose below, or set `ac_altitude: task-local`. Keep empty if not applicable. -->
31
31
 
32
32
  ### Q&A
33
33
 
@@ -33,11 +33,11 @@ in the reviewed PR/commit/diff). Fix in priority order (P1 → P2 → …); re-r
33
33
 
34
34
  ### Requirements
35
35
 
36
- <!-- R-numbered fix requirements derived from the findings. Fill after triage/refinement. -->
36
+ <!-- One R-item per line, exactly `- [ ] R1. <text>` (checkbox + `R<n>.`); `spur task check` flags any other form. Fill after triage/refinement from the findings. -->
37
37
 
38
38
  ### Acceptance Criteria
39
39
 
40
- <!-- Checks that prove the findings were addressed. Keep empty until the review task becomes executable work. -->
40
+ <!-- Number items AC1, AC2, … (never R<n> — that is the Requirements namespace): `- [ ] AC1 — <feature scenario title without its R-number>` bullets or `Scenario: AC1 — <title>` blocks; add `(req: R<n>)` to bind a task requirement; task-only checks go in prose below, or set `ac_altitude: task-local`. Keep empty until the review task becomes executable work. -->
41
41
 
42
42
  ### Q&A
43
43
 
@@ -23,11 +23,11 @@ updated_at: "{{ CREATED_AT }}"
23
23
 
24
24
  ### Requirements
25
25
 
26
- <!-- R-numbered list of what must be true when this task is complete. Keep empty until requirements are known. -->
26
+ <!-- One R-item per line, exactly `- [ ] R1. <text>` (checkbox + `R<n>.`); `spur task check` flags any other form. Keep empty until requirements are known. -->
27
27
 
28
28
  ### Acceptance Criteria
29
29
 
30
- <!-- Given/When/Then scenarios or a checklist derived from Requirements. Keep empty if this task has no objective AC yet. -->
30
+ <!-- Number items AC1, AC2, … (never R<n> — that is the Requirements namespace): `- [ ] AC1 — <feature scenario title without its R-number>` bullets or `Scenario: AC1 — <title>` blocks; add `(req: R<n>)` to bind a task requirement; task-only checks go in prose below, or set `ac_altitude: task-local`. Keep empty if this task has no objective AC yet. -->
31
31
 
32
32
  ### Q&A
33
33
 
@@ -1,41 +1,19 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "note": "Workflow graph-change promotion candidates (task 0873, feature D62; ADR-076 amendment). A candidate is shadow-run against recorded real-run inputs and is promoted into the canonical definition or deleted by its named deadline — never left as a standing parallel <name>2.yaml. `verdict` is null while pending and is filled by `bun scripts/spur-dev.ts promotion evaluate <id>`; `promotion check` (spur-check-feature) fails any candidate still present past its deadline and any unreferenced parallel definition in config/workflows/.",
4
- "candidates": [
3
+ "note": "Workflow graph-change promotion candidates (task 0873, feature D62; ADR-076 amendment). A candidate is shadow-run against recorded real-run inputs and is promoted into the canonical definition or deleted by its named deadline — never left as a standing parallel <name>2.yaml. `verdict` is null while pending and is filled by `bun scripts/spur-dev.ts promotion evaluate <id>`; `promotion check` (spur-check-feature) fails any candidate still present past its deadline, any unreferenced parallel definition in config/workflows/, and (0877 R8) any retired definition with real (non-dry) terminal runs lacking a recorded decision in `retirements[]`.",
4
+ "candidates": [],
5
+ "retirements": [
5
6
  {
6
- "id": "wrapup-contract-violation-pilot-routing",
7
- "canonical": "wrapup-pipeline",
8
- "deadline": "2026-10-17",
9
- "createdAt": "2026-09-17",
10
- "rationale": "ADR-118 pilot graph change shipped by task 0871 (doc-sync contract-violation routing to the shell-only repair state). Registered by task 0876 to take the promotion decision on its first real-run measurement (R4/R5): wrapup-pipeline run fadca099-25a7-4884-a4ae-923cd0239775 (done, state-machine, definition sha256:cad7ad8b..., v4, created 2026-09-17T15:14:46Z, 14h28m after 0871 landed at 00:46:46Z - the only post-landing terminal non-dry wrapup run) routed doc-sync->learnings-append on the default edge: the doc-sync agent.run exited clean (exitCode 0) and produced its declared expectFile capture (.spur/run/fadca099-...-wrapup-learnings.md), so data.outcome was success, ContractViolationGuardRunner passed:false (packages/app/src/workflow/guards/contract-violation.ts:26), zero workflow.agent.contract-violation system_events, zero failed actions (executor-failure path not taken), no repair status file. Measured absence on real traffic - never fabricated. The change projects delta.agentRunCount=1 (unchanged): the repair edge adds no model hop (repair is a shell that records the miss; ADR-118 forbids re-dispatch), so the ADR-076 cost bar cannot reward it; its justification is ADR-118 routing correctness, evidenced here by the measured absence on the first real run. Disposition (resolve delete, or hold as the pattern-spread precedent for 0873's gate) belongs to the D62 owner before the deadline.",
11
- "measurement": {
12
- "workflow": "wrapup-pipeline",
13
- "runIds": ["fadca099-25a7-4884-a4ae-923cd0239775"]
14
- },
15
- "delta": {
16
- "agentRunCount": 1
17
- },
18
- "verdict": {
19
- "decision": "delete",
20
- "evaluatedAt": "2026-09-17T15:33:27.274Z",
21
- "agentRunCount": {
22
- "runs": 1,
23
- "mean": 1,
24
- "median": 1,
25
- "min": 1,
26
- "max": 1
27
- },
28
- "agentRunDurationMs": {
29
- "runs": 1,
30
- "mean": 505937,
31
- "median": 505937,
32
- "min": 505937,
33
- "max": 505937
34
- },
35
- "candidateAgentRunCount": 1,
36
- "canonicalAgentRunCount": 1,
37
- "reason": "candidate projects 1 agent.run action(s), not fewer than the canonical wrapup-pipeline count of 1 (1 real run(s), median 1 agent.run action(s)/run, median 505937 ms/run) — ADR-076 rejected a graph adding a model hop"
38
- }
7
+ "name": "planning-pipeline",
8
+ "recordedBy": "0872 (ADR-072/075 composition-baseline pass 2dc86579a)",
9
+ "date": "2026-08-19",
10
+ "rationale": "Planning pipeline superseded by the task-pipeline planning stages; 3 real terminal runs retained in history."
11
+ },
12
+ {
13
+ "name": "task-pipeline2",
14
+ "recordedBy": "ADR-076 (commit 017ac7a30)",
15
+ "date": "2026-08-20",
16
+ "rationale": "Standing parallel definition deleted with the D5-N fixture promotion bar; 5 real terminal runs retained in history."
39
17
  }
40
18
  ]
41
19
  }
@@ -37,6 +37,12 @@ states:
37
37
  description: >
38
38
  Feature verification work (DD-13). Makes verification derivable —
39
39
  listable, event-triggerable, assignable.
40
+ onEnter:
41
+ # Caller wiring (task 0880, ADR-119): entering verification RUNS the
42
+ # feature-scoped pass instead of only passively reading its status file.
43
+ - kind: shell
44
+ options:
45
+ command: '$spurBin workflow run feature-verification.yaml --vars "{\"featureId\":\"$featureId\"}"'
40
46
  - id: blocked
41
47
  description: Impediment; work suspended.
42
48
  - id: done
@@ -3,10 +3,11 @@
3
3
  # Owns a lifecycle boundary no per-task graph owns: the repo-wide checks whose
4
4
  # invariant spans the repository rather than a single task's diff — corpus
5
5
  # consistency, contract baselines, dependency/schema drift, the frozen History
6
- # surface, and the repo-wide test set. They run once per feature against a
7
- # settled tree, deliberately the slow pass, and `feature-lifecycle`'s
8
- # verifying→done guard refuses to complete the feature until this pass records
9
- # PASS (ADR-119 consequence: a feature is not done until it passes).
6
+ # surface, and the repo-wide test set. They run once per feature, deliberately
7
+ # the slow pass; `feature-lifecycle`'s verifying entry invokes this workflow (task
8
+ # 0880 caller wiring), and its verifying→done guard refuses to complete the
9
+ # feature until this pass records PASS (ADR-119 consequence: a feature is not
10
+ # done until it passes).
10
11
  #
11
12
  # Run: spur workflow run feature-verification.yaml --vars '{"featureId":"D62"}'
12
13
  #
@@ -22,7 +23,7 @@
22
23
  kind: state-machine
23
24
  name: feature-verification
24
25
  version: "1"
25
- description: "Feature-scoped verification pass (ADR-119): runs the repo-wide check set once per feature against a settled tree and records PASS/FAIL."
26
+ description: "Feature-scoped verification pass (ADR-119): runs the repo-wide check set once per feature and records PASS/FAIL. Invoked by feature-lifecycle's verifying entry."
26
27
  iterationBound: 2
27
28
  initialState: verify
28
29
  terminalStates:
@@ -97,7 +97,10 @@ states:
97
97
  - kind: shell
98
98
  options:
99
99
  command: >-
100
- test -n "$idea" || printf 'FAIL\n' > ".spur/run/$__runId-idea-precheck-doctor.status"
100
+ mkdir -p .spur/run &&
101
+ printf '%s\n' "$idea" > ".spur/run/$__runId-idea-input.md" &&
102
+ awk 'NF' ".spur/run/$__runId-idea-input.md" | grep -q . ||
103
+ printf 'FAIL\n' > ".spur/run/$__runId-idea-precheck-doctor.status"
101
104
 
102
105
  - id: discovery
103
106
  description: >
@@ -109,12 +112,14 @@ states:
109
112
  brainstorm also emits the idea-evaluation report to .spur/run/${vars.__runId}-idea-eval-report.md
110
113
  (template: the `sp:spur-dev` skill's `idea-evaluation` reference — named by skill, not by
111
114
  repo path, because `spur init` never scaffolds `plugins/sp/` into a seeded project).
115
+ The operator's verbatim idea argument is persisted at .spur/run/${vars.__runId}-idea-input.md
116
+ (written by start; the authoritative ask every model-bearing stage reads).
112
117
  expectFile fails a silent no-op discovery (no eval report).
113
118
  onEnter:
114
119
  - kind: agent.run
115
120
  options:
116
121
  agent: ${vars.planningAgent}
117
- input: "Run sp:brainstorm for the idea: ${vars.idea}. The skill owns the approach-generation, design summary, and `needs_design` signal criteria; emit .spur/run/${vars.__runId}-idea-needs-design.json ({\"needs_design\": true|false}) and the design summary per the skill's `Design Approval Gate` and `The needs_design signal` sections. Also emit the idea-evaluation report to .spur/run/${vars.__runId}-idea-eval-report.md per the `sp:spur-dev` skill's `idea-evaluation` reference (urgency/necessity 0–5, premises, pros/cons, alternatives, enhanced idea, recommendation). At the END of the report, append a provenance footer block of the exact form: `---\\nrun_id: ${vars.__runId}\\ngenerated_at: <RFC3339 timestamp>\\n---` (omit the footer only if run_id is empty)."
122
+ input: "The operator's ask of record is .spur/run/${vars.__runId}-idea-input.md — idea persisted verbatim at start; authoritative, read it first (${vars.idea} is a convenience echo). Run sp:brainstorm. The skill owns the approach-generation, design summary, and `needs_design` signal criteria; emit .spur/run/${vars.__runId}-idea-needs-design.json ({\"needs_design\": true|false}) plus the design summary per its `Design Approval Gate` / `The needs_design signal` sections. Also emit the idea-evaluation report to .spur/run/${vars.__runId}-idea-eval-report.md per the `sp:spur-dev` skill's `idea-evaluation` reference (urgency/necessity 0–5, premises, pros/cons, alternatives, enhanced idea, recommendation, plus mandatory `## Requirement inventory`: numbered I<n> items quoting/paraphrasing idea-input lines; `[unclear: ...]` marks ambiguity, `[deferred: <reason>]` marks out-of-scope). End with this exact footer: `---\\nrun_id: ${vars.__runId}\\ngenerated_at: <RFC3339>\\n---` (omit if run_id is empty)."
118
123
  # Declared Layer-1 role (0538 R2): routing reason beside the agent: pin.
119
124
  role: planner
120
125
  expectFile: .spur/run/${vars.__runId}-idea-eval-report.md
@@ -143,12 +148,14 @@ states:
143
148
  checklists never enter Goal. Shell actions then persist both sections through
144
149
  `spur feature update --section Goal|Scope --from-file ...`; a missing/empty artifact
145
150
  stops the state. Prefer the enhanced idea from .spur/run/${vars.__runId}-idea-eval-report.md as
146
- context; do not overwrite vars.idea.
151
+ context; do not overwrite vars.idea. The operator's verbatim ask of record is
152
+ .spur/run/${vars.__runId}-idea-input.md (persisted at start; authoritative over any
153
+ paraphrase).
147
154
  onEnter:
148
155
  - kind: agent.run
149
156
  options:
150
157
  agent: ${vars.planningAgent}
151
- input: 'Create a feature for the idea: ${vars.idea}. Read .spur/run/${vars.__runId}-idea-eval-report.md if present for the enhanced idea and scores. Use ''spur feature create "<name>" --json'' to create it. Write the feature id to .spur/run/${vars.__runId}-idea-feature-id.txt. If an existing feature is appropriate, use its id instead. Also write two body-only intent artifacts: .spur/run/${vars.__runId}-idea-goal.md with concise Goal intent only (a short statement of what the feature achieves; never task breakdowns, checklists, or how-to steps), and .spur/run/${vars.__runId}-idea-scope.md with explicit in-scope and out-of-scope boundary bullets.'
158
+ input: 'Create a feature for the idea. The operator''s ask of record is .spur/run/${vars.__runId}-idea-input.md — the idea argument persisted verbatim at start; treat it as the authoritative ask. Read .spur/run/${vars.__runId}-idea-eval-report.md if present for the enhanced idea and scores. Use ''spur feature create "<name>" --json'' to create it; with --json the feature id is returned under the .ref.id envelope (n), not a top-level .id — read it from there. Write the feature id to .spur/run/${vars.__runId}-idea-feature-id.txt. If an existing feature is appropriate, use its id instead. Also write two body-only intent artifacts: .spur/run/${vars.__runId}-idea-goal.md with concise Goal intent only (a short statement of what the feature achieves; never task breakdowns, checklists, or how-to steps), and .spur/run/${vars.__runId}-idea-scope.md with explicit in-scope and out-of-scope boundary bullets.'
152
159
  # Declared Layer-1 role (0538 R2): routing reason beside the agent: pin.
153
160
  role: planner
154
161
  expectFile: .spur/run/${vars.__runId}-idea-feature-id.txt
@@ -182,6 +189,9 @@ states:
182
189
  check records FAIL and routes through the capped retry loop via guards that consume the
183
190
  recorded result — it never fails the run (the engine's default onError policy is `fail`,
184
191
  so an in-action check failure would kill the run before the retry edges are evaluated).
192
+ Requirement coverage is MEASURED alongside it by the soft idea-coverage-check shell
193
+ (0887 R4): the recorded coverage status conjuncts into the profile=auto ac-generate
194
+ guards below so uncovered inventory items route through the same capped retry loop.
185
195
  onEnter:
186
196
  - kind: shell
187
197
  options:
@@ -189,7 +199,7 @@ states:
189
199
  - kind: agent.run
190
200
  options:
191
201
  agent: ${vars.planningAgent}
192
- input: "Generate acceptance criteria for feature ${vars.featureId}. Read the feature file and author R-numbered BDD Gherkin scenarios per ac-style-guide.md. Output only the complete Acceptance Criteria section body, including the gherkin code fence, with no surrounding commentary and no section heading."
202
+ input: "Generate acceptance criteria for feature ${vars.featureId}. The operator's ask of record is .spur/run/${vars.__runId}-idea-input.md — idea persisted verbatim at start; authoritative. Read the feature file and author R-numbered BDD Gherkin scenarios per ac-style-guide.md. Tie every scenario to the `## Requirement inventory` of .spur/run/${vars.__runId}-idea-eval-report.md: under each `Scenario:` heading add a comment `# covers: I1, I3` listing covered ids — every non-`[deferred: ...]` item needs at least one covering scenario. Two `spur task check` rules bind AC text: (1) AC bullets copy scenario titles verbatim — the title is the byte-identical identity key of its bullet; (2) gate-language words (HITL, approval/approved, merged/merge event, content-gate, GATED, capstone standalone) are forbidden in titles, bodies, and enum values (L4.gate-language) — rephrase around them. Output only the Acceptance Criteria section body (gherkin fence included), no commentary, no heading."
193
203
  # Declared Layer-1 role (0538 R2): routing reason beside the agent: pin.
194
204
  role: planner
195
205
  answerFile: .spur/run/${vars.__runId}-idea-ac-content.md
@@ -221,6 +231,24 @@ states:
221
231
  resultFile: .spur/run/${vars.__runId}-idea-ac-check.status
222
232
  softFail: true
223
233
  timeoutMs: 120000
234
+ # 0887 R4: requirement-inventory ↔ AC coverage, measured once at the same author/revise
235
+ # boundary. Soft shell (exit 0 always): the checker writes the PASS/FAIL status itself and
236
+ # the guards below consume the recorded result — never re-run the checker (0769 pattern).
237
+ # Repo-checkout path first, then the superskill-staged twin (handoff-finalize resolution
238
+ # shape); neither present fails closed to FAIL so readiness degrades visibly instead of
239
+ # silently skipping coverage.
240
+ - kind: shell
241
+ options:
242
+ command: >-
243
+ mkdir -p .spur/run &&
244
+ S=plugins/sp/scripts/idea-coverage-check.ts &&
245
+ if [ ! -f "$S" ]; then S="$(superskill script path sp idea-coverage-check.ts 2>/dev/null)"; fi &&
246
+ if [ -n "$S" ] && [ -f "$S" ]; then
247
+ bun "$S" --run-id "$__runId" --report ".spur/run/$__runId-idea-eval-report.md" --ac ".spur/run/$__runId-idea-ac-content.md" || printf 'FAIL run=%s checker exited nonzero (bun missing or checker crash)\n' "$__runId" > ".spur/run/$__runId-idea-coverage.reason";
248
+ else
249
+ printf 'FAIL run=%s checker not found — run superskill install sp\n' "$__runId" | tee ".spur/run/$__runId-idea-coverage.reason" >&2;
250
+ printf 'FAIL\n' > ".spur/run/$__runId-idea-coverage.status";
251
+ fi
224
252
 
225
253
  - id: feature-check
226
254
  description: >
@@ -235,11 +263,14 @@ states:
235
263
  the transition guards route directly from ac-generate to the appropriate next
236
264
  state, so this state is only entered in interactive mode. On failure, the retry
237
265
  cap routes back to ac-generate (≤3 retries) or escalates to failed.
266
+ Requirement coverage (.spur/run/${vars.__runId}-idea-coverage.status, 0887 R4) is part of
267
+ the recorded results this gate surfaces: a FAIL there means some inventory items have no
268
+ covering scenario — answer no to route back to ac-generate for revision if needed.
238
269
  pause: true
239
270
  onEnter:
240
271
  - kind: hitl.confirm
241
272
  options:
242
- prompt: "Feature check for ${vars.featureId}. Review the AC and confirm to proceed? (Failures route back to ac-generate for revision, capped at 3 retries.)"
273
+ prompt: "Feature check for ${vars.featureId}. Review the AC and confirm to proceed? Requirement coverage status: $(cat .spur/run/${vars.__runId}-idea-coverage.status 2>/dev/null || echo unknown) — reason: $(cat .spur/run/${vars.__runId}-idea-coverage.reason 2>/dev/null || echo n/a) (.spur/run/${vars.__runId}-idea-coverage.status[.reason]). (Failures route back to ac-generate for revision, capped at 3 retries.)"
243
274
 
244
275
  - id: system-design
245
276
  description: >
@@ -264,7 +295,7 @@ states:
264
295
  - kind: agent.run
265
296
  options:
266
297
  agent: ${vars.planningAgent}
267
- input: 'Run sp:sys-architecture for feature ${vars.featureId}. Read the brainstorm artifact, feature AC, and .spur/run/${vars.__runId}-idea-design-review.md. Produce ADR entries, architecture updates, and design satellites (docs/design/<slug>.md) following the constitution edit rules. Do not write task or feature corpus files directly. Design-review contract (.spur/run/${vars.__runId}-idea-design-review.md, fixed headings `## Proposed design`, `## Operator feedback`, `## Reconciliation`): on the first pass write the proposed design summary under `## Proposed design` and leave `## Operator feedback` empty; on retry with operator feedback present, revise the design/ADR artifacts, document the changes under `## Reconciliation`, and when the feedback invalidates an Acceptance Criteria scenario write the revised AC section body to a file and persist it via `$spurBin feature update "$featureId" --section "Acceptance Criteria" --from-file <file>` — never edit feature corpus files directly.'
298
+ input: 'The operator''s ask of record is .spur/run/${vars.__runId}-idea-input.md (idea persisted verbatim at start; authoritative). Run sp:sys-architecture for feature ${vars.featureId}. Read the brainstorm artifact, feature AC, and .spur/run/${vars.__runId}-idea-design-review.md. Produce ADR entries, architecture updates, and design satellites (docs/design/<slug>.md) per the constitution edit rules; never write task or feature corpus files directly. Design-review contract (fixed headings `## Proposed design`, `## Operator feedback`, `## Reconciliation`): first pass — write the proposed summary under `## Proposed design`, leave `## Operator feedback` empty; retry after operator feedback — revise the design/ADR artifacts, document changes under `## Reconciliation`, and when feedback invalidates an Acceptance Criteria scenario write the revised AC section body to a file, persist via `$spurBin feature update "$featureId" --section "Acceptance Criteria" --from-file <file>`.'
268
299
  # Declared Layer-1 role (0538 R2): routing reason beside the agent: pin.
269
300
  role: planner
270
301
  expectFile: .spur/run/${vars.__runId}-idea-design-review.md
@@ -331,7 +362,7 @@ states:
331
362
  - kind: agent.run
332
363
  options:
333
364
  agent: ${vars.planningAgent}
334
- input: "Run sp:spec-decomposition for feature ${vars.featureId} per skill references/decomposition.md § Idea-pipeline emission: sizing first, then the batch JSON at .spur/run/${vars.__runId}-idea-task-batch.json and the private task-order sidecar at .spur/run/${vars.__runId}-idea-task-order.json."
365
+ input: "The operator's ask of record is .spur/run/${vars.__runId}-idea-input.md (the idea argument persisted verbatim at start; authoritative). Run sp:spec-decomposition for feature ${vars.featureId} per skill references/decomposition.md § Idea-pipeline emission: sizing first, then the batch JSON at .spur/run/${vars.__runId}-idea-task-batch.json and the private task-order sidecar at .spur/run/${vars.__runId}-idea-task-order.json."
335
366
  # Declared Layer-1 role (0538 R2): routing reason beside the agent: pin.
336
367
  role: planner
337
368
  expectFile: .spur/run/${vars.__runId}-idea-task-batch.json
@@ -422,7 +453,9 @@ states:
422
453
  # project's own computePlanningDigest), so the bounded prompt pins the skill
423
454
  # reference instead of a command; artifacts are gated by answerFile/expectFile.
424
455
  input: >-
425
- Run the ready-prepare stage for feature ${vars.featureId} per sp:spur-dev
456
+ The operator's ask of record is .spur/run/${vars.__runId}-idea-input.md (the idea
457
+ argument persisted verbatim at start; authoritative). Run the ready-prepare stage
458
+ for feature ${vars.featureId} per sp:spur-dev
426
459
  references/planning-workflow.md § Step 5.6 (Ready preparation): read
427
460
  .spur/run/${vars.__runId}-idea-batch-create-result.json and write
428
461
  .spur/run/${vars.__runId}-idea-ready.json.
@@ -559,57 +592,60 @@ transitions:
559
592
 
560
593
  # ── ac-generate: auto-skip (profile=auto) OR enter feature-check HITL gate (interactive) ──
561
594
  # Declaration order: auto-skip guards tried FIRST (same pattern as task-pipeline review→verify
562
- # and design-gen→handoff). Under profile=auto, the recorded `idea-ac-check` result routes
563
- # directly to the appropriate next state — guards never re-run the CLI (task 0769). Under
564
- # interactive, the always fallback enters the feature-check state whose onEnter hitl.confirm
565
- # pauses for operator confirmation.
595
+ # and design-gen→handoff). Under profile=auto, the recorded `idea-ac-check` result and the
596
+ # recorded requirement-coverage status (0887 R4) route directly to the appropriate next
597
+ # state — guards never re-run the CLI or the checker (task 0769). Under interactive, the
598
+ # always fallback enters the feature-check state whose onEnter hitl.confirm pauses for
599
+ # operator confirmation (coverage is surfaced in that prompt; the operator's answer governs).
566
600
  #
567
- # Auto-skip 1: pass + design route → system-design (design=auto + needs_design != false)
601
+ # Auto-skip 1: pass + coverage + design route → system-design (design=auto + needs_design != false)
568
602
  - from: ac-generate
569
603
  to: system-design
570
- description: "profile=auto, check passed, design route — run system design."
571
- # (warn) 5 commands (named status capture + 4 conditions): profile gate + captured status + route signal jointly own the
572
- # route; guards never re-run the CLI (0769), so there is nothing smaller to extract.
604
+ description: "profile=auto, check passed, requirements covered, design route — run system design."
605
+ # (warn) 4 commands: one persistent multi-assignment line captures both statuses; `test -a` folds the
606
+ # profile/ac and design/needs pairs (same operand semantics); guards never re-run the CLI (0769).
573
607
  guard:
574
608
  kind: shell
575
609
  options:
576
610
  command: >-
577
- ac_status="$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)";
578
- test "$profile" = auto && test "$ac_status" = PASS && test "$design" = auto && test "$(jq -r .needs_design .spur/run/$__runId-idea-needs-design.json 2>/dev/null)" != false
579
- # Auto-skip 2: pass + skip-design route → decompose
611
+ ac_status="$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" cov_status="$(cat .spur/run/$__runId-idea-coverage.status 2>/dev/null)";
612
+ test "$profile" = auto -a "$ac_status" = PASS && test "$cov_status" = PASS && test "$design" = auto -a "$(jq -r .needs_design .spur/run/$__runId-idea-needs-design.json 2>/dev/null)" != false
613
+ # Auto-skip 2: pass + coverage + skip-design route → decompose
580
614
  - from: ac-generate
581
615
  to: decompose
582
- description: "profile=auto, check passed, skip-design route — go directly to decompose."
583
- # (warn) 5 test segments: same as auto-skip 1 plus the OR'd design=auto/needs_design=false
584
- # pair that keeps one captured signal file authoritative for both routes (0769).
616
+ description: "profile=auto, check passed, requirements covered, skip-design route — go directly to decompose."
617
+ # (warn) 4 test segments: profile + inlined ac/coverage reads + the OR'd design=skip/(design=auto AND
618
+ # needs_design=false) pair folded into one `test` (`-a` binds tighter than `-o`), keeping one captured
619
+ # signal file authoritative for both routes (0769).
585
620
  guard:
586
621
  kind: shell
587
622
  options:
588
- command: 'test "$profile" = auto && test "$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" = PASS && (test "$design" = skip || (test "$design" = auto && test "$(jq -r .needs_design .spur/run/$__runId-idea-needs-design.json 2>/dev/null)" = false))'
589
- # Auto-skip 3: check failed, retry < 3 → loop back to ac-generate (self-loop)
623
+ command: 'test "$profile" = auto && test "$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" = PASS && test "$(cat .spur/run/$__runId-idea-coverage.status 2>/dev/null)" = PASS && test "$design" = skip -o "$design" = auto -a "$(jq -r .needs_design .spur/run/$__runId-idea-needs-design.json 2>/dev/null)" = false'
624
+ # Auto-skip 3: check or coverage failed, retry < 3 → loop back to ac-generate (self-loop)
590
625
  - from: ac-generate
591
626
  to: ac-generate
592
- description: "profile=auto, check failed, retry cap not reached — re-run ac-generate."
593
- # (warn) 5 commands (named status capture + 4 conditions): profile gate + captured status + captured retry count; the
594
- # retry loop is the smallest honest formulation of cap<3 routing (0769).
627
+ description: "profile=auto, check or coverage failed, retry cap not reached — re-run ac-generate."
628
+ # (warn) 5 commands: one persistent multi-assignment line captures both statuses and the retry count
629
+ # (with its 0 fallback); the failed-check pair stays verbatim and the profile gate folds into the retry
630
+ # test via `test -a`; the retry loop is the smallest honest formulation of cap<3 routing (0769).
595
631
  guard:
596
632
  kind: shell
597
633
  options:
598
634
  command: >-
599
- ac_status="$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)";
600
- test "$profile" = auto && test "$ac_status" != PASS && test "$(cat .spur/run/$__runId-idea-ac-retry-count 2>/dev/null || echo 0)" -lt 3
601
- # Auto-skip 4: check failed, retry cap reached → escalate to failed
635
+ ac_status="$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" cov_status="$(cat .spur/run/$__runId-idea-coverage.status 2>/dev/null)" retry="$(cat .spur/run/$__runId-idea-ac-retry-count 2>/dev/null || echo 0)";
636
+ { test "$ac_status" != PASS || test "$cov_status" != PASS; } && test "$profile" = auto -a "$retry" -lt 3
637
+ # Auto-skip 4: check or coverage failed, retry cap reached → escalate to failed
602
638
  - from: ac-generate
603
639
  to: failed
604
- description: "profile=auto, check failed after 3 retries — escalate to failed."
605
- # (warn) 5 commands (named status capture + 4 conditions): mirror of the retry guard with cap>=3; keeping escalation and
606
- # retry as one test-chain pair makes the cap boundary auditable in the diff (0769).
640
+ description: "profile=auto, check or coverage failed after 3 retries — escalate to failed."
641
+ # (warn) 5 commands: mirror of the retry guard with cap>=3; keeping escalation and retry as one
642
+ # test-chain pair makes the cap boundary auditable in the diff (0769).
607
643
  guard:
608
644
  kind: shell
609
645
  options:
610
646
  command: >-
611
- ac_status="$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)";
612
- test "$profile" = auto && test "$ac_status" != PASS && test "$(cat .spur/run/$__runId-idea-ac-retry-count 2>/dev/null || echo 0)" -ge 3
647
+ ac_status="$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" cov_status="$(cat .spur/run/$__runId-idea-coverage.status 2>/dev/null)" retry="$(cat .spur/run/$__runId-idea-ac-retry-count 2>/dev/null || echo 0)";
648
+ { test "$ac_status" != PASS || test "$cov_status" != PASS; } && test "$profile" = auto -a "$retry" -ge 3
613
649
  # Interactive fallback: enter feature-check HITL gate
614
650
  - from: ac-generate
615
651
  to: feature-check
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/spur",
3
- "version": "0.3.86",
3
+ "version": "0.3.87",
4
4
  "description": "Spur CLI — local-first harness for mainstream coding agents: constraint checking, workflow orchestration, agent health, and history analytics. Bun-native; exposes the `spur` command.",
5
5
  "keywords": [
6
6
  "spur",
@@ -134,6 +134,7 @@ list this README is checked against.
134
134
  | `dev-find-next` | Prompt-first feature frontier prioritizer — ranks the open feature frontier by derived importance/urgency with per-candidate evidence; gates unactionable features; emits tree defects as proposals only |
135
135
  | `dev-fixall` | Fix all lint, type, and test errors systematically across the working tree |
136
136
  | `dev-simplify` | Simplify recently-changed code for clarity without changing behavior — incremental, test-after-each, revert on regression |
137
+ | `dev-refactor` | Lens-routed refactoring with a preservation contract — taste lenses (api/architect/tests/ui) classify findings on the shared schema; cutting/breaking changes pause for operator approval; forwards to sp:code-refactoring |
137
138
  | `dev-arch` | Survey a codebase (or module tree) for shallow modules and deepening opportunities — emit a ranked MARKDOWN candidate report that feeds the planning half; never auto-refactors |
138
139
  | `dev-reverse` | Reverse-engineer a codebase — analyze unfamiliar repos, generate HLD/architecture docs, audit quality/security, and produce onboarding documentation |
139
140
  | `dev-gitmsg` | Generate conventional commit message(s) from the current change set via one bounded diff capture, optionally commit |
@@ -199,6 +200,7 @@ plugins/sp/
199
200
  │ ├── code-review/ # Pre-commit self-review + SECUA review lenses
200
201
  │ │ └── references/{review-lenses, self-review-checklist}.md
201
202
  │ ├── code-simplification/ # Behavior-preserving simplification
203
+ │ ├── code-refactoring/ # Lens-routed refactoring coordinator (shared finding schema, P1–P4 severity map, fix ladder, focus detection)
202
204
  │ ├── code-testing/ # Testing / coverage competency
203
205
  │ │ └── references/{unit-testing.md, stacks/{bun-ts, go, python}.md}
204
206
  │ ├── code-verification/ # Verify + SECUA review
@@ -316,6 +318,7 @@ surface or run one workflow. All skills target the same five core platforms: `cl
316
318
  | `code-review` | 1.0 | Pre-commit self-review checklist (6 categories, catches 60-80% of issues) + SECUA review lenses + findings processing |
317
319
  | `code-simplification` | 1.0 | Behavior-preserving simplification — Chesterton's Fence, signal tables, incremental change + test-after-each, scope-to-changed |
318
320
  | `code-improvement` | 1.0 | Architectural deepening — surface shallow/tightly-coupled modules and propose refactors that make them deep, testable, AI-navigable; backs `/sp:dev-arch` |
321
+ | `code-refactoring` | 1.0 | Lens-routed refactoring coordinator with a preservation contract — focus auto-detection, taste-lens dispatch, shared finding schema, P1–P4 severity map, objective/taste gates, fix ladder with revert-on-regression; backs `/sp:dev-refactor` |
319
322
  | `functional-review` | 1.0 | Requirements-traceability assessment — per-requirement verdicts with file:line evidence that the implementation satisfies ALL task requirements; pipeline Phase 8b gate |
320
323
  | `doubt-driven-development` | 1.0 | In-flight adversarial review of a non-trivial decision before committing it — hand artifact + contract to a fresh-context skeptic, reconcile, stop at 3 cycles |
321
324
  | `source-driven-development` | 1.0 | Source-first verification — verify framework/API/library facts against primary sources before generating code; separates "the API exists" from "used correctly under its contract" |
@@ -340,10 +343,10 @@ surface or run one workflow. All skills target the same five core platforms: `cl
340
343
  | `spur-composer` | 1.0 | Cross-noun composition — workflow catalog selection, the ephemeral→project→shared ladder, ADR-115 budgets, trace-driven rule tuning; applies accepted `spur-doctor` proposals through `spur` verbs; never judges its own output and never runs a recurring loop |
341
344
  | `spur-doctor` | 1.0 | Cross-noun evaluation — read-only CLI evidence per noun (task/feature/rule/workflow/agent spec), reflection over `history-anatomy` findings through a closed action-class map, and a proposal table; writes nothing; diagnoses artifacts, not runtime environments (`spur agent doctor`'s job) |
342
345
  | `redesign-web-ui` | 1.0 | Existing-UI visual upgrade — audit generic AI fingerprints, apply in-stack polish against `DESIGN.md` / live tokens, verify behavior and viewports; does not migrate frameworks |
343
- | `taste-refactoring-api` | — | API design and refactoring for REST/HTTP, RPC/gRPC, GraphQL, and event contracts; compatibility, security, and migration review |
344
- | `taste-refactoring-ui` | — | UI design and refactoring with visual hierarchy, typography, spacing, color, and interaction review |
345
- | `taste-refactoring-architect` | — | Architecture review, simplification, and refactoring; boundary modeling, dependency reduction, and migration planning |
346
- | `taste-refactoring-tests` | — | Test suite refactoring for failure sensitivity, regression detection, and assertion strength; eliminates brittle mocks |
346
+ | `taste-refactoring-api` | 1.0 | API design and refactoring for REST/HTTP, RPC/gRPC, GraphQL, event contracts, and CLI surfaces; compatibility, security, and migration review |
347
+ | `taste-refactoring-ui` | 1.0 | UI design and refactoring with visual hierarchy, typography, spacing, color, and interaction review |
348
+ | `taste-refactoring-architect` | 1.0 | Architecture review, simplification, and refactoring; boundary modeling, dependency reduction, and migration planning |
349
+ | `taste-refactoring-tests` | 1.0 | Test suite refactoring for failure sensitivity, regression detection, and assertion strength; eliminates brittle mocks |
347
350
 
348
351
  #### Bounded coexistence and retirement gate — `sp:issue-finding` (HA-S1 0661)
349
352
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Turn a vague idea into a feature with AC and a decomposed task batch — discovery, idea-eval, feature-create, AC, feature-check, system-design, decompose, batch-create (Design by default), handoff
3
3
  role: planner
4
- argument-hint: "\"<idea>\" [--auto] [--skip-design] [--approve-taste] [--agent <inline|auto|name>]"
4
+ argument-hint: "\"<idea>\" [--from-file <path>] [--auto] [--skip-design] [--approve-taste] [--agent <inline|auto|name>]"
5
5
  allowed-tools: ["Bash", "Read", "Skill", "AskUserQuestion"]
6
6
  ---
7
7
 
@@ -14,7 +14,8 @@ contract below maps to that workflow's transitions.
14
14
 
15
15
  | Flag | Description | Default |
16
16
  | --- | --- | --- |
17
- | `"<idea>"` | Vague idea to turn into a feature with AC and tasks. | required |
17
+ | `"<idea>"` | Vague idea to turn into a feature with AC and tasks. | required (or `--from-file`) |
18
+ | `--from-file` `<path>` | Read the idea from a file instead of the positional argument. Mutually exclusive with `"<idea>"` — exactly one must be present. The file's contents become the verbatim idea text (trimmed of surrounding whitespace only). Useful for long or multiline asks that are awkward to quote. | off |
18
19
  | `--auto` | Skip objective HITL gates only (taste gates still pause). | off |
19
20
  | `--skip-design` | Omit system-design and per-task Design. | off |
20
21
  | `--approve-taste` | With `--auto`: set idea_approved + design_approved so idea-eval / design-approval do not pause. | off |
@@ -45,5 +46,11 @@ vars as subsets of `--approve-taste` (`idea_approved` / `design_approved`). Pref
45
46
  - Omitted/`inline`: drive `idea-pipeline.yaml` through the [inline pipeline driver](../skills/spur-dev/references/inline-pipeline-driver.md). Do not launch `spur workflow run`, `spur agent run`, or a native subagent unless the operator explicitly requests delegation.
46
47
  - `auto`/name: launch `spur workflow run idea-pipeline.yaml --async`, observe with one `workflow trace --follow`, and only report cancellation as stopped when `workflow cancel --json` returns `killed: true`.
47
48
  - `Skill(skill="sp:spur-dev", args="idea $ARGUMENTS")`
49
+ - Pass the idea text through every hop **verbatim** — never paraphrase or shorten it in the nested
50
+ `Skill` call or stage prompts; long ideas lose their trailing asks when summarized at the hop.
51
+ - Before executing the pipeline's `start` state, persist the operator's idea argument (or the
52
+ `--from-file` contents) **unmodified** to `.spur/run/<run-id>-idea-input.md` (0887 R1); every
53
+ model-bearing stage prompt treats that file as the authoritative ask, and the precheck fails
54
+ the run when it is empty or missing.
48
55
  - Stage contract (discovery → idea-eval → feature-create → AC → feature-check → system-design →
49
56
  decompose → batch-create → ready-prepare → handoff): `plugins/sp/skills/spur-dev/references/dev-operations.md` § idea.
@@ -0,0 +1,33 @@
1
+ ---
2
+ description: Lens-routed refactoring with a preservation contract — taste lenses classify findings against the shared schema; cutting/breaking changes pause for operator approval
3
+ role: reviewer
4
+ argument-hint: "[<description>] [--scope <path>] [--focus <api|architect|tests|ui|auto>] [--fix <none|blockers-first|all>] [--check <cmd>] [--agent <inline|auto|name>] [--auto]"
5
+ allowed-tools: ["Bash", "Read", "Edit", "Skill"]
6
+ ---
7
+
8
+ # Dev Refactor
9
+
10
+ Wraps the **sp:code-refactoring** skill.
11
+
12
+ ## Argument Flags
13
+
14
+ | Flag | Description | Default |
15
+ | --- | --- | --- |
16
+ | `[<description>]` | Free-text steering for the lenses (e.g. "pagination consistency"). | — |
17
+ | `--scope` `<path>` | Path bound; no edit may land outside it. | working tree |
18
+ | `--focus` `<api\|architect\|tests\|ui\|auto>` | Lens set; comma list allowed (`api,tests`). | auto |
19
+ | `--fix` `<none\|blockers-first\|all>` | Apply policy; `blockers-first` = P1/P2. | none |
20
+ | `--check` `<cmd>` | Verification command for baseline and per-fix checks. | project gate |
21
+ | `--agent` `<inline\|auto\|name>` | Who runs the model-bearing analysis. | inline |
22
+ | `--auto` | Skip objective gates only; cutting/breaking taste gates still pause. | off |
23
+
24
+ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag-glossary.md).
25
+
26
+ ## Usage
27
+
28
+ /sp:dev-refactor [<description>] [--scope <path>] [--focus <api|architect|tests|ui|auto>] [--fix <none|blockers-first|all>] [--check <cmd>] [--agent <inline|auto|name>] [--auto]
29
+
30
+ ## Implementation
31
+
32
+ - Apply the [inline-default execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface).
33
+ - `Skill(skill="sp:code-refactoring", args="$ARGUMENTS")`
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sp",
3
- "version": "0.3.86",
3
+ "version": "0.3.87",
4
4
  "description": "Spur — a local-first harness engineering toolkit that wraps mainstream coding agents with constraint checking, workflow orchestration, and history analytics.",
5
5
  "extensions": {
6
6
  "pi": ["./hooks/pi/guard-extension.ts"]
@@ -58,7 +58,7 @@ roles:
58
58
  stages: [implement, test, wrap]
59
59
  - id: reviewer
60
60
  tier: capable-1
61
- commands: [dev-verify, dev-verifyall, dev-review, dev-review-session, dev-pr-review, dev-dogfood, rule-scan, dev-find-conflict, dev-find-issue]
61
+ commands: [dev-verify, dev-verifyall, dev-review, dev-review-session, dev-pr-review, dev-dogfood, dev-refactor, rule-scan, dev-find-conflict, dev-find-issue]
62
62
  stages: [verify, review, dogfood]
63
63
  - id: planner
64
64
  tier: capable-2