@gobing-ai/spur 0.3.85 → 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 (139) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/pipeline-budgets.json +0 -25
  3. package/config/plugin-scripts.json +4 -5
  4. package/config/rules/boundary/env-var-hygiene.yaml +41 -0
  5. package/config/templates/feature/default.md +2 -0
  6. package/config/templates/task/brainstorm.md +2 -2
  7. package/config/templates/task/feature-impl.md +2 -2
  8. package/config/templates/task/issue.md +2 -2
  9. package/config/templates/task/meta.md +2 -2
  10. package/config/templates/task/review.md +2 -2
  11. package/config/templates/task/standard.md +2 -2
  12. package/config/transition-shims.json +1 -1
  13. package/config/workflow-candidates.json +19 -0
  14. package/config/workflows/feature-lifecycle.yaml +10 -2
  15. package/config/workflows/feature-verification.yaml +71 -0
  16. package/config/workflows/idea-pipeline.yaml +87 -39
  17. package/config/workflows/task-pipeline.yaml +43 -12
  18. package/config/workflows/wrapup-pipeline.yaml +70 -7
  19. package/package.json +9 -9
  20. package/plugins/sp/README.md +7 -7
  21. package/plugins/sp/commands/dev-idea.md +9 -2
  22. package/plugins/sp/commands/dev-refactor.md +33 -0
  23. package/plugins/sp/hooks/agent-hint.ts +5 -4
  24. package/plugins/sp/hooks/careful-guard.ts +3 -1
  25. package/plugins/sp/hooks/context-post-tool.ts +2 -1
  26. package/plugins/sp/hooks/context-session-start.ts +4 -3
  27. package/plugins/sp/hooks/context-session-stop.ts +2 -1
  28. package/plugins/sp/hooks/pi/guard-extension.ts +4 -3
  29. package/plugins/sp/hooks/task-write-guard.ts +4 -3
  30. package/plugins/sp/lib/idea-handoff.generated.mjs +260 -260
  31. package/plugins/sp/plugin.json +1 -1
  32. package/plugins/sp/references/roles.md +1 -1
  33. package/plugins/sp/scripts/daily-summary/daily-summary.mjs +13 -4
  34. package/plugins/sp/scripts/daily-summary/daily-summary.ts +6 -4
  35. package/plugins/sp/scripts/feature-sync-bounded.mjs +10 -2
  36. package/plugins/sp/scripts/feature-sync-bounded.ts +2 -1
  37. package/plugins/sp/scripts/idea-coverage-check.ts +168 -0
  38. package/plugins/sp/scripts/idea-handoff.mjs +6 -1
  39. package/plugins/sp/scripts/idea-handoff.ts +4 -1
  40. package/plugins/sp/scripts/inline-pipeline-parity-check.ts +115 -4
  41. package/plugins/sp/scripts/inline-run-setup.ts +195 -2
  42. package/plugins/sp/scripts/pr-reviewing.mjs +8 -1
  43. package/plugins/sp/scripts/pr-reviewing.ts +2 -1
  44. package/plugins/sp/scripts/quality-gate.mjs +8 -1
  45. package/plugins/sp/scripts/quality-gate.ts +2 -1
  46. package/plugins/sp/scripts/surface-drift-inventory.ts +1 -4
  47. package/plugins/sp/scripts/task-evidence-precheck.ts +2 -1
  48. package/plugins/sp/scripts/task-size-precheck.ts +6 -4
  49. package/plugins/sp/scripts/verify-answer-lint.ts +2 -1
  50. package/plugins/sp/scripts/workflow-step-profile.mjs +10 -2
  51. package/plugins/sp/scripts/workflow-step-profile.ts +2 -1
  52. package/plugins/sp/scripts/wrapup-steps.mjs +8 -1
  53. package/plugins/sp/scripts/wrapup-steps.ts +2 -1
  54. package/plugins/sp/skills/brainstorm/SKILL.md +4 -0
  55. package/plugins/sp/skills/code-refactoring/SKILL.md +155 -0
  56. package/plugins/sp/skills/code-refactoring/references/finding-schema.md +74 -0
  57. package/plugins/sp/skills/code-refactoring/references/fix-ladder.md +52 -0
  58. package/plugins/sp/skills/code-refactoring/references/focus-detection.md +44 -0
  59. package/plugins/sp/skills/code-refactoring/references/refactor-finding.schema.json +95 -0
  60. package/plugins/sp/skills/spec-decomposition/references/decomposition.md +23 -16
  61. package/plugins/sp/skills/spur-cli/references/features/acceptance-criteria.md +4 -2
  62. package/plugins/sp/skills/spur-cli/references/features.md +6 -1
  63. package/plugins/sp/skills/spur-cli/references/workflows/authoring-workflows.md +2 -2
  64. package/plugins/sp/skills/spur-cli/references/workflows/operations.md +3 -3
  65. package/plugins/sp/skills/spur-cli/references/workflows/workflow-fit-and-tuning.md +1 -1
  66. package/plugins/sp/skills/spur-cli/references/workflows.md +8 -7
  67. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +24 -0
  68. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +4 -5
  69. package/plugins/sp/skills/spur-dev/references/dev-operations.md +18 -2
  70. package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +1 -1
  71. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +22 -3
  72. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +2 -2
  73. package/plugins/sp/skills/spur-dev/references/idea-evaluation.md +11 -1
  74. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +91 -1
  75. package/plugins/sp/skills/taste-refactoring-api/SKILL.md +44 -1
  76. package/plugins/sp/skills/taste-refactoring-api/references/protocol-modes.md +31 -0
  77. package/plugins/sp/skills/taste-refactoring-architect/SKILL.md +43 -0
  78. package/plugins/sp/skills/taste-refactoring-tests/SKILL.md +42 -0
  79. package/plugins/sp/skills/taste-refactoring-ui/SKILL.md +43 -0
  80. package/schemas/state-machine-workflow.schema.json +5 -0
  81. package/schemas/task-batch.schema.json +2 -2
  82. package/schemas/transition-flow-workflow.schema.json +5 -0
  83. package/spur.js +21106 -20669
  84. package/web/_astro/BoardApp.CJiqp5pS.js +1 -0
  85. package/web/_astro/{BoardApp.yW425dRZ.js → BoardApp.yBBcFXWP.js} +4 -4
  86. package/web/_astro/{TaskDetail.CGwJAinW.js → TaskDetail.DqFJbRFc.js} +1 -1
  87. package/web/_astro/{arc.B-qNXzSO.js → arc.DL-BpHoi.js} +1 -1
  88. package/web/_astro/{architectureDiagram-3BPJPVTR.Bdg-xiji.js → architectureDiagram-3BPJPVTR.9IdQYyDq.js} +1 -1
  89. package/web/_astro/{blockDiagram-GPEHLZMM.DFArg3Kp.js → blockDiagram-GPEHLZMM.BKsFCqTl.js} +1 -1
  90. package/web/_astro/{c4Diagram-AAUBKEIU.BkOLcjyx.js → c4Diagram-AAUBKEIU.DhwI0dh1.js} +1 -1
  91. package/web/_astro/channel.CX5453qQ.js +1 -0
  92. package/web/_astro/{chunk-2J33WTMH.DN3c20V4.js → chunk-2J33WTMH.B3QVmQ9S.js} +1 -1
  93. package/web/_astro/{chunk-4BX2VUAB.B64K0Ttd.js → chunk-4BX2VUAB.DBSuqs9F.js} +1 -1
  94. package/web/_astro/{chunk-55IACEB6.C-AJvNwa.js → chunk-55IACEB6.BSYTWAYD.js} +1 -1
  95. package/web/_astro/{chunk-727SXJPM.DMkr46uS.js → chunk-727SXJPM.cWVuxXfS.js} +1 -1
  96. package/web/_astro/{chunk-AQP2D5EJ.4_WGbI64.js → chunk-AQP2D5EJ.DpU_Ob3d.js} +1 -1
  97. package/web/_astro/{chunk-FMBD7UC4.cbFW_lVE.js → chunk-FMBD7UC4.BykFkyji.js} +1 -1
  98. package/web/_astro/{chunk-ND2GUHAM.CDW_-2O1.js → chunk-ND2GUHAM.DwgHlMdY.js} +1 -1
  99. package/web/_astro/{chunk-QZHKN3VN.BoYOt_yg.js → chunk-QZHKN3VN.CusXUGWM.js} +1 -1
  100. package/web/_astro/{classDiagram-4FO5ZUOK.BNT6XpHQ.js → classDiagram-4FO5ZUOK.fx0ObzkN.js} +1 -1
  101. package/web/_astro/{classDiagram-v2-Q7XG4LA2.BNT6XpHQ.js → classDiagram-v2-Q7XG4LA2.fx0ObzkN.js} +1 -1
  102. package/web/_astro/{cose-bilkent-S5V4N54A.CI1DQxR3.js → cose-bilkent-S5V4N54A.Z4HgOlsd.js} +1 -1
  103. package/web/_astro/{cynefin-OW5HDTMX.A8ARH61p.js → cynefin-OW5HDTMX.B5dIZHJu.js} +1 -1
  104. package/web/_astro/{dagre-BM42HDAG.u28ZmqwR.js → dagre-BM42HDAG.DT70Q_Yw.js} +1 -1
  105. package/web/_astro/{diagram-2AECGRRQ.Dx8JcrGc.js → diagram-2AECGRRQ.DqHA3XBF.js} +1 -1
  106. package/web/_astro/{diagram-5GNKFQAL.BXJUG9GY.js → diagram-5GNKFQAL.BmCem957.js} +1 -1
  107. package/web/_astro/{diagram-KO2AKTUF.BtlMuWqW.js → diagram-KO2AKTUF.sn0-hrE0.js} +1 -1
  108. package/web/_astro/{diagram-LMA3HP47.C4T7qaAy.js → diagram-LMA3HP47.BSHe9tVc.js} +1 -1
  109. package/web/_astro/{diagram-OG6HWLK6.D5HECE10.js → diagram-OG6HWLK6.DHIc-86k.js} +1 -1
  110. package/web/_astro/{erDiagram-TEJ5UH35.B_hMR3yw.js → erDiagram-TEJ5UH35.Bxayrs7v.js} +1 -1
  111. package/web/_astro/{flowDiagram-I6XJVG4X.BAmpcYl3.js → flowDiagram-I6XJVG4X.BkzoE_5I.js} +1 -1
  112. package/web/_astro/{ganttDiagram-6RSMTGT7.DV1bSWK-.js → ganttDiagram-6RSMTGT7.okT6CvTo.js} +1 -1
  113. package/web/_astro/{gitGraphDiagram-PVQCEYII.DxYKkKrJ.js → gitGraphDiagram-PVQCEYII.CJuYbhC7.js} +1 -1
  114. package/web/_astro/{infoDiagram-5YYISTIA.BAWY2xMb.js → infoDiagram-5YYISTIA.RqLy7nBo.js} +1 -1
  115. package/web/_astro/{ishikawaDiagram-YF4QCWOH.CZssRn6V.js → ishikawaDiagram-YF4QCWOH.BwIcoagw.js} +1 -1
  116. package/web/_astro/{journeyDiagram-JHISSGLW.C--muARd.js → journeyDiagram-JHISSGLW.UB1VbWtH.js} +1 -1
  117. package/web/_astro/{kanban-definition-UN3LZRKU.D_QCK4et.js → kanban-definition-UN3LZRKU.AaxMKpTk.js} +1 -1
  118. package/web/_astro/{linear.DzrmTtZ0.js → linear.Nv_xOUjP.js} +1 -1
  119. package/web/_astro/{mermaid.core.Da03W3iu.js → mermaid.core.Bc4LqQgX.js} +4 -4
  120. package/web/_astro/{mindmap-definition-RKZ34NQL.6cy-8hR_.js → mindmap-definition-RKZ34NQL.oKUvU_qi.js} +1 -1
  121. package/web/_astro/{pieDiagram-4H26LBE5.C5rS1pdU.js → pieDiagram-4H26LBE5.DQk0oo03.js} +1 -1
  122. package/web/_astro/{quadrantDiagram-W4KKPZXB.w56GZZ6Q.js → quadrantDiagram-W4KKPZXB.BdDjESDa.js} +1 -1
  123. package/web/_astro/{requirementDiagram-4Y6WPE33.CipX3Pwu.js → requirementDiagram-4Y6WPE33.C2u9hUeH.js} +1 -1
  124. package/web/_astro/{sankeyDiagram-5OEKKPKP.C0VVzgJm.js → sankeyDiagram-5OEKKPKP.CDEoiJST.js} +1 -1
  125. package/web/_astro/{sequenceDiagram-3UESZ5HK.BX2dUUbF.js → sequenceDiagram-3UESZ5HK.D_hT_GAT.js} +1 -1
  126. package/web/_astro/{stateDiagram-AJRCARHV.ypCdgODQ.js → stateDiagram-AJRCARHV.DI8RYG0b.js} +1 -1
  127. package/web/_astro/{stateDiagram-v2-BHNVJYJU.In0baEtg.js → stateDiagram-v2-BHNVJYJU.Bkxz4DnP.js} +1 -1
  128. package/web/_astro/{timeline-definition-PNZ67QCA.CJN4Vkvl.js → timeline-definition-PNZ67QCA.DSY-kH3-.js} +1 -1
  129. package/web/_astro/{vennDiagram-CIIHVFJN.Cf8KkIPY.js → vennDiagram-CIIHVFJN.CpaDtuGr.js} +1 -1
  130. package/web/_astro/{wardleyDiagram-YWT4CUSO.DCZBo9xw.js → wardleyDiagram-YWT4CUSO.DujQWvo8.js} +1 -1
  131. package/web/_astro/{xychartDiagram-2RQKCTM6.Cm4v_MiJ.js → xychartDiagram-2RQKCTM6.DcM5Y4b9.js} +1 -1
  132. package/web/index.html +1 -1
  133. package/config/workflows/basic.yaml +0 -146
  134. package/config/workflows/docs-pipeline.yaml +0 -350
  135. package/config/workflows/feature-dev.yaml +0 -288
  136. package/plugins/sp/scripts/feature-dev-precheck.mjs +0 -146
  137. package/plugins/sp/scripts/feature-dev-precheck.ts +0 -238
  138. package/web/_astro/BoardApp.CHenHFia.js +0 -1
  139. package/web/_astro/channel.CbDHK5UQ.js +0 -1
@@ -27,6 +27,14 @@ Rules:
27
27
  - **One R-number = one scenario.** Never split a requirement across multiple scenarios
28
28
  under the same R-number; never merge two requirements into one scenario.
29
29
 
30
+ ## Task-side numbering (`AC<n>`)
31
+
32
+ `R<n>` is the **feature** scenario key and the **task Requirements** key. Task `### Acceptance
33
+ Criteria` items therefore use their own namespace: `- [ ] AC1 — <title>` or `Scenario: AC1 — <title>`,
34
+ numbered task-locally. Carry a feature scenario by copying its title after the prefix (`normalizeTitle`
35
+ strips both `AC<n>` and `R<n>`, so DD-09 matching is unaffected); bind a task requirement with
36
+ `(req: R<n>)`. Legacy tasks that wrote `- [ ] R<n> —` / `Scenario: R<n> —` keep working unchanged.
37
+
30
38
  ## Two AC tiers (authoring convention)
31
39
 
32
40
  A planning convention (DD-06 "permissive start"), not a `spur feature check` feature today —
@@ -73,6 +81,10 @@ scenario, it matches by title. Rules:
73
81
  Registered user can log in with email and password" is traceable.
74
82
  - **No synonyms in cross-references.** The title in the feature file and the title in the
75
83
  task's AC reference must be byte-identical.
84
+ - **Avoid gate vocabulary in titles.** `spur task check` (L4.gate-language) rejects task sections
85
+ containing `HITL`, `approval`/`approved`, `merged`/`merge event`, `content-gate`, `GATED`, or
86
+ `capstone` as standalone words; task AC bullets copy scenario titles verbatim, so a title using
87
+ them fails every child task. Write "pause for an operator answer" instead of "HITL approval".
76
88
 
77
89
  ## Verdict AC ↔ feature scenario linkage
78
90
 
@@ -199,6 +211,18 @@ Use the canonical BDD template at `templates/bdd/gherkin.md`. Key rules:
199
211
  - **When** describes the single action under test.
200
212
  - **Then** asserts the observable outcome.
201
213
  - **And** chains additional preconditions, actions, or assertions.
214
+ - **Trace the scenario to its requirements (0887 R4).** Directly under each `Scenario:`
215
+ heading add a comment line listing the requirement-inventory ids the scenario covers;
216
+ the BDD parser skips `#` comment lines, so the form is checker-inert:
217
+
218
+ ```gherkin
219
+ Scenario: Registered user can log in with email and password
220
+ # covers: I1, I3
221
+ Given ...
222
+ ```
223
+
224
+ Every inventory item without a `[deferred: ...]` marker must be covered by at least one
225
+ scenario — `idea-coverage-check` measures this at the idea-pipeline's ac-generate boundary.
202
226
 
203
227
  Avoid:
204
228
 
@@ -573,8 +573,6 @@ invariants that keep the pipeline set coherent as new ones are added.
573
573
  | `idea-pipeline.yaml` | Ideation + planning (vague idea or known slug → feature + AC + task batch) | `/sp:dev-idea`, `/sp:dev-plan` | `handoff`, `cancelled` |
574
574
  | `task-pipeline.yaml` | Execution (one task → done) | `/sp:dev-run` | `done`, `failed` |
575
575
  | `wrapup-pipeline.yaml` | Wrap-up (completed tasks → learning + metrics + doc-sync) | `/sp:dev-wrap`, `/sp:dev-wrapall` | `done`, `skipped` |
576
- | `feature-dev.yaml` | Umbrella (brainstorm → plan → execute → feature-verify) | `/sp:dev-runall --feature <id>` (or `--tasks feature:<id>`) | `done`, `failed` |
577
- | `basic.yaml` | Simple (generic implement/check/fix loop) | direct `spur workflow run` | `done`, `failed` |
578
576
  | `feature-lifecycle.yaml` | Feature status FSM (entity lifecycle, not a phase pipeline) | `spur feature update` | `done`, `cancelled` |
579
577
  | `task-lifecycle.yaml` | Task status FSM (entity lifecycle, not a phase pipeline) | `spur task update` | `done`, `cancelled` |
580
578
 
@@ -587,8 +585,9 @@ not replace them.
587
585
  A pipeline may invoke another workflow through a command wrapper or `spur workflow run` **only at a
588
586
  phase boundary** — it must NOT inline another pipeline's state graph. Concretely:
589
587
 
590
- - `feature-dev.yaml`'s `execute-tasks` state may invoke `task-pipeline.yaml` per task via
591
- `spur workflow run` (phase boundary: design → execution).
588
+ - The feature-level batch entry (`/sp:dev-runall --feature <id>`) dispatches `task-pipeline.yaml`
589
+ per task through the CLI command wrapper, not by inlining the task graph (feature roster →
590
+ execution boundary).
592
591
  - `idea-pipeline.yaml`'s `handoff` state may output a command for the operator to run
593
592
  `task-pipeline.yaml` (phase boundary: ideation → execution).
594
593
  - `task-pipeline.yaml`'s `implement` state must NOT contain a nested state machine for
@@ -692,7 +691,7 @@ Field semantics (enforced by `parseCheckpointMetadata` / `checkpointStaleness`):
692
691
  **Writer cadence (0784 R4).** There is exactly one canonical writer: the `task-pipeline` done
693
692
  state's terminal checkpoint (`status: done`, real HEAD, run id from `$__runId`, and `$wbs`-expanded
694
693
  artifact paths). It is a plain `shell` step — checkpoints are working memory, not CLI-gated corpus.
695
- The `feature-dev`, `wrapup-pipeline`, and `idea-pipeline` pipelines used to echo pseudo-checkpoints
694
+ The `wrapup-pipeline`, and `idea-pipeline` pipelines (plus the since-retired `feature-dev`) used to echo pseudo-checkpoints
696
695
  ("checkpoint: <workflow> done ...") that violated the canonical schema; those writers were removed
697
696
  in 0784 — the persisted run row is the authoritative terminal record, and a non-canonical echo
698
697
  cannot be resumed, routed, or reclaimed safely.
@@ -85,7 +85,8 @@ each would be scope creep for one-liner procedures.
85
85
  | 13a | parallel | `dev-parallel` | `Skill()` | `sp:parallel-execution` | `--tasks <selector> [--feature <id>] [--mode <fan-out\|review-panel\|investigation>] [--agent <inline\|auto\|name>] [--json]` |
86
86
  | 14 | wrap | `dev-wrap` | `Skill()` | `spur workflow run` (wrapup-pipeline) | `<wbs> [--agent <inline\|auto\|name>] [--auto] [--merge] [--dry-run]` |
87
87
  | 15 | wrapall | `dev-wrapall` | `Skill()` | `spur workflow run` (wrapup-pipeline) | `[--since <iso>] [--feature <id>] [--status <s>] [--agent <inline\|auto\|name>] [--auto] [--merge] [--dry-run]` |
88
- | 16 | idea | `dev-idea` | `Skill()` | inline driver (`idea-pipeline`) or async workflow | `"<idea>" [--auto] [--skip-design] [--approve-taste] [--agent <inline\|auto\|name>]` |
88
+ | 16 | idea | `dev-idea` | `Skill()` | inline driver (`idea-pipeline`) or async workflow | `"<idea>" [--from-file <path>] [--auto] [--skip-design] [--approve-taste] [--agent <inline\|auto\|name>]` |
89
+ | 17 | refactor | `dev-refactor` | `Skill()` | `sp:code-refactoring` skill (thin wrapper, ADR-032) | `[<description>] [--scope <path>] [--focus <api\|architect\|tests\|ui\|auto>] [--fix <none\|blockers-first\|all>] [--check <cmd>] [--agent <inline\|auto\|name>] [--auto]` |
89
90
 
90
91
  ## Skill-backed operations
91
92
 
@@ -335,11 +336,18 @@ must not be changed without updating the backing skill.
335
336
  ### 16. idea
336
337
 
337
338
  - **Purpose:** Turn a vague idea into a feature with AC and a decomposed task batch — the unified entry point for the planning half.
338
- - **Inputs:** `"<idea>"` (required, positional, quoted). Three everyday axes:
339
+ - **Inputs:** `"<idea>"` (quoted) or `--from-file <path>` — exactly one; the two are mutually
340
+ exclusive (0887 R7). Three everyday axes:
339
341
  - `--auto` — skip **objective** HITL (feature-check, batch-create); taste gates still pause.
340
342
  - `--skip-design` — design package off (system-design + task Design).
341
343
  - `--approve-taste` — with `--auto`, skip **all** remaining taste pauses this run (idea-eval + design-approval). Sets `idea_approved=true` and `design_approved=true`.
342
344
  Aliases (prefer `--approve-taste`): `--idea-approved` → `idea_approved`; `--design-approved` → `design_approved`. There is **no** `--design` force flag.
345
+ - `--from-file <path>` — read the idea text from a file instead of the positional argument
346
+ (verbatim; long/multiline asks). Mutually exclusive with `"<idea>"`.
347
+ - **Verbatim idea artifact:** before `start` executes, the driver persists the idea argument (or
348
+ `--from-file` contents) unmodified to `.spur/run/<run-id>-idea-input.md` (0887 R1); the precheck
349
+ fails the run when that file is empty or missing, and every model-bearing stage prompt treats
350
+ it as the authoritative ask (R2).
343
351
  - **Backing:** `idea-pipeline.yaml` through the inline driver for omitted/`inline`, or `spur workflow run idea-pipeline.yaml --async` for `auto`/name.
344
352
  - **Behavior:** Builds vars from the table above and drives the idea pipeline. Flow: discovery → **idea-eval** (taste; reject → cancelled) → feature-create → ac-generate → feature-check → system-design (conditional) → design-approval (taste) → decompose → batch-create (`--skip-ready`) → ready-prepare (ready checklist per created task + ready-evidence sidecar, 0788) → handoff. STOPS at handoff — no task execution, no pipeline nesting. Headless runs use one `trace --follow`; cancellation is reported stopped only when `workflow cancel --json` returns `killed: true`.
345
353
  - **Delegation:** Host-session inline driver by default; explicit executor selection uses the async workflow worker.
@@ -356,6 +364,14 @@ must not be changed without updating the backing skill.
356
364
 
357
365
  - **Taste pre-clear (`--approve-taste`):** owned with design-approval var semantics in [cross-cutting.md](cross-cutting.md) § "Design Approval Gate"; idea-eval uses the parallel `idea_approved` var. One CLI flag sets both.
358
366
 
367
+ ### 17. refactor
368
+
369
+ - **Purpose:** Lens-routed refactoring with a preservation contract — route a scope through taste lenses (api / architect / tests / ui, auto-detected by path), classify findings on the shared `refactor-finding` schema, and apply via the fix ladder without breaking preserved behavior.
370
+ - **Inputs:** `[<description>]` free-text steering, `--scope <path>` (default: working tree), `--focus <lens>` (default: auto), `--fix <policy>` (default: none), `--check <cmd>` (default: project gate), `--agent <selector>` (default: inline), `--auto` (default: off).
371
+ - **Backing:** `sp:code-refactoring` skill — the command carries zero orchestration logic (ADR-032); the skill owns focus auto-detection, lens dispatch, the P1–P4 severity map, objective/taste gates, and the fix ladder with revert-on-regression.
372
+ - **Behavior:** Green `--check` baseline → focus detection → lens dispatch → findings to `.spur/run/<run-id>-refactor-findings.json` + human report `.spur/run/<run-id>-refactor-report.md` (lens set, P1–P4 table, preservation summary, applied/reverted/deferred). `--fix blockers-first` auto-applies P1/P2 `auto`-eligible findings; `--fix all` extends to `operator`-eligible P3/P4; every fix re-runs `--check` and reverts on regression. Tests are never removed or weakened by an `auto` fix.
373
+ - **Operator taste gates:** every `cutting` or `breaking` finding pauses for an explicit operator answer in every mode — even `--auto` skips only objective gates. `--fix none` (the default) writes both artifacts with no edits.
374
+
359
375
  ---
360
376
 
361
377
  ## Inline operations
@@ -105,7 +105,7 @@ gate will reject the task without it). Use the normal `--section --from-file` co
105
105
  **4. Force-done with an honest reason.**
106
106
 
107
107
  ```bash
108
- SPUR_PROVENANCE_OVERRIDE=1 spur task update <wbs> done --force-done \
108
+ spur task update <wbs> done --force-done --provenance-bypass \
109
109
  --reason "<step> agent.run timed out at <N>s; recovered manually: lint clean, <suite> pass, sections authored by hand"
110
110
  ```
111
111
 
@@ -160,13 +160,21 @@ Scope the operation to all tasks under a feature id (`^[A-Z][1-9]*$`). On featur
160
160
  commands (`dev-wrapall`) it also advances the feature through legal lifecycle edges with guards
161
161
  honored.
162
162
 
163
+ ### `--check <cmd>` — validation command for iterate-and-check loops
164
+
165
+ **Anchor:** `#flag-check`.
166
+
167
+ Verification command a command iterates against (`dev-simplify`, `dev-refactor`). The command
168
+ establishes a baseline with it before the first change and re-runs it after each change.
169
+
163
170
  ### `--focus <dims>` — constrain the operation to specific dimensions
164
171
 
165
172
  **Anchor:** `#flag-focus`.
166
173
 
167
174
  Constrain the operation to a named subset of dimensions — review dimensions on `dev-review`/
168
175
  `dev-verify`/`dev-verifyall` (`all|stack|dependencies|data|flows|api|security|quality|performance`),
169
- a refine focus mode on `dev-refine`/`dev-refineall`, or a reconstruction lens on `dev-reverse`.
176
+ a refactor lens set on `dev-refactor` (`api|architect|tests|ui|auto`), a refine focus mode on
177
+ `dev-refine`/`dev-refineall`, or a reconstruction lens on `dev-reverse`.
170
178
  Narrowing reduces token cost; omitting runs
171
179
  all dimensions.
172
180
 
@@ -175,7 +183,7 @@ all dimensions.
175
183
  **Anchor:** `#flag-scope`.
176
184
 
177
185
  Limit the operation to a file or directory path (`dev-arch`, `dev-debug`, `dev-fixall`,
178
- `dev-gitmsg`, `dev-gtd`, `dev-simplify`) to bound the working set.
186
+ `dev-gitmsg`, `dev-gtd`, `dev-refactor`, `dev-simplify`) to bound the working set.
179
187
 
180
188
  ### `--all` — widen the operation to everything in its domain
181
189
 
@@ -253,7 +261,8 @@ tasks by `updated_at >= date`).
253
261
 
254
262
  **Anchor:** `#flag-fix`.
255
263
 
256
- Remediation policy on verify-family commands (`dev-verify`, `dev-verifyall`):
264
+ Remediation policy on verify-family commands (`dev-verify`, `dev-verifyall`) and the refactor
265
+ coordinator (`dev-refactor`):
257
266
  `none|blockers-first|all`. `none` reports findings without fixing; `blockers-first` fixes only P1/P2;
258
267
  `all` fixes everything found. Deprecated on `dev-review` (routes to `dev-verify --fix`).
259
268
 
@@ -294,6 +303,16 @@ verifying a task whose artifact is intentionally not yet shippable (e.g. a doc-o
294
303
  Omit the design package (system-design satellite + task `### Design`) on planning commands
295
304
  (`dev-plan`, `dev-idea`). The task is created without the design section; refine supplies it later.
296
305
 
306
+ ### `--from-file <path>` — read the idea from a file (dev-idea)
307
+
308
+ **Anchor:** `#flag-from-file`.
309
+
310
+ `dev-idea` reads the idea text from `<path>` instead of the positional argument. Mutually
311
+ exclusive with `"<idea>"` — exactly one must be present. The file's contents become the verbatim
312
+ idea text, persisted unmodified to `.spur/run/<run-id>-idea-input.md` (0887 R1) and treated as
313
+ the authoritative ask by every model-bearing stage prompt. Useful for long or multiline asks
314
+ that are awkward to quote (0887 R7).
315
+
297
316
  ### `--output <path>` — write the result to a path
298
317
 
299
318
  **Anchor:** `#flag-output`.
@@ -149,11 +149,11 @@ passed, so provenance denied first and Review L3 denied on the retry.
149
149
 
150
150
  | # | Gate layer | Triggers denial when | Remediation |
151
151
  |---|------------|----------------------|-------------|
152
- | 1 | **Strict-core + verdict artifact** (`spur task check <wbs> --strict-core` + `done-transition-guard.ts`) | The strict-core check fails, or `.spur/run/<wbs>-verdict.json` is **missing** or has a non-PASS aggregate. **Missing artifact is a deny** (not a silent allow — closes the 0349 "done without verdict" class). The aggregate is recomputed from requirement/AC rows; the harsher of stored and computed wins. | Re-run `/sp:dev-verify <wbs>` until PASS (writes the artifact), or explicitly override with `spur task update <wbs> done --force-done --reason "<why>"`. Docs-only pipelines (`docs-pipeline.yaml`) meet the same layer: read-only measured verification
152
+ | 1 | **Strict-core + verdict artifact** (`spur task check <wbs> --strict-core` + `done-transition-guard.ts`) | The strict-core check fails, or `.spur/run/<wbs>-verdict.json` is **missing** or has a non-PASS aggregate. **Missing artifact is a deny** (not a silent allow — closes the 0349 "done without verdict" class). The aggregate is recomputed from requirement/AC rows; the harsher of stored and computed wins. | Re-run `/sp:dev-verify <wbs>` until PASS (writes the artifact), or explicitly override with `spur task update <wbs> done --force-done --reason "<why>"`. Docs-only procedures meet the same layer: read-only measured verification
153
153
  (answer file + `spur task verdict`) writes the standard `.spur/run/<wbs>-verdict.json` artifact
154
154
  under proof-input digest bracketing; missing or non-PASS evidence is a refusal, never a synthetic
155
155
  PASS stub. |
156
- | 2 | **Provenance guard** (`lifecycle-adapter.ts`) | No pipeline-kind run link exists for `<wbs>`. | Run `/sp:dev-run <wbs>` through the full pipeline, use `/sp:dev-run <wbs> --mode implement --auto --next` for the explicit step chain, or record the audited bypass with `SPUR_PROVENANCE_OVERRIDE=1`. |
156
+ | 2 | **Provenance guard** (`lifecycle-adapter.ts`) | No pipeline-kind run link exists for `<wbs>`. | Run `/sp:dev-run <wbs>` through the full pipeline, use `/sp:dev-run <wbs> --mode implement --auto --next` for the explicit step chain, or record the audited bypass with `--provenance-bypass` on `spur task update`. |
157
157
  | 3 | **Review L3** (`task-check.ts`) | `### Review` is empty, placeholder-only, or lacks a populated P1–P4 findings table. | Run `/sp:dev-review <wbs>`; verify cannot write Review because of the Step 10 prohibition above. |
158
158
 
159
159
  When the verdict is **PARTIAL/FAIL**, or any gate layer fails: stop as review-pending — surface
@@ -20,7 +20,9 @@ recommendation is mandatory, stakes in plain English, and approve/reject is the
20
20
  re-author the report.
21
21
 
22
22
  **Sidecar rule:** The enhanced idea does **not** overwrite `vars.idea`. Feature-create reads both
23
- the original idea and this report.
23
+ the original idea and this report. The operator's verbatim ask of record is the run's
24
+ `.spur/run/<run-id>-idea-input.md` (persisted by the pipeline `start` state / the inline driver
25
+ before any processing); the `## Requirement inventory` items trace back to it.
24
26
 
25
27
  ## Template
26
28
 
@@ -30,6 +32,13 @@ the original idea and this report.
30
32
  ## Enhanced Idea
31
33
  <one-paragraph refined statement of what the idea actually requires — the "real requirement" after discovery sharpens the vague input>
32
34
 
35
+ ## Requirement inventory
36
+ <mandatory — the coverage gate (idea-coverage-check) parses this section, so keep the exact `- I<n> — ` item form>
37
+ - I1 — <requirement stated as an ask, quoting or paraphrasing the source line from the run's idea-input artifact> (source: "<quoted fragment from the operator's idea>")
38
+ - I2 — <next requirement>
39
+ - I<n> — <optional: a requirement explicitly out of scope> [deferred: <reason>]
40
+ - I<n> — <optional: an ambiguous ask> [unclear: <why it is ambiguous>] — an unclear marker does not exempt the item; it still needs coverage or an explicit deferral
41
+
33
42
  ## Scores
34
43
 
35
44
  | Dimension | Score (0–5) | Rationale |
@@ -74,6 +83,7 @@ Stakes: <plain-English cost of proceeding vs not; reversibility; blast radius>
74
83
  |------|--------|
75
84
  | Filled instance path | `.spur/run/idea-eval-report.md` |
76
85
  | Template home | this file |
86
+ | Requirement inventory | mandatory `## Requirement inventory` section (0887 R3); consumed by `idea-coverage-check` (R4) |
77
87
  | HITL state | `idea-eval` in `idea-pipeline.yaml` |
78
88
  | Approve | continue → `feature-create` |
79
89
  | Reject / cancel | → `cancelled` (no feature) |
@@ -25,7 +25,11 @@ implements it; remove the entry when the corresponding kind is dropped from the
25
25
 
26
26
  **Actions:** `shell` · `note` · `doctor.probe` · `file.read.into-var` · `hitl.confirm` · `agent.run` · `proof.fingerprint` · `run.artifact` · `command.gate`
27
27
 
28
- **Guards (transitions):** `always` · `shell`
28
+ **Guards (transitions):** `always` · `shell` · `action-ok` · `contract-violation`
29
+
30
+ - `action-ok` — pass iff the prior action on this state/node succeeded (engine builtin).
31
+ - `contract-violation` — pass iff the prior `agent.run` result is a named contract violation
32
+ (`data.outcome === 'contract-violation'`, ADR-118); the report carries `contract` and `observed`.
29
33
 
30
34
  ## What this driver is
31
35
 
@@ -156,6 +160,35 @@ the human/native presentation layer — labels are display addresses only, never
156
160
  This is required for the normal `testing → done` provenance guard. Planning pipelines have no
157
161
  task lifecycle link and skip this task-specific action.
158
162
 
163
+ ### Idea-pipeline quick start (0887 R1/R2)
164
+
165
+ Minimum files to read for `/sp:dev-idea` inline runs — then drive `idea-pipeline.yaml`:
166
+
167
+ - `.spur/workflows/idea-pipeline.yaml` (the machine) and this driver.
168
+ - `plugins/sp/skills/spur-dev/references/idea-evaluation.md` (report template incl. the mandatory
169
+ `## Requirement inventory`) and `references/ac-style-guide.md` (scenario `# covers:` form).
170
+ - `references/dev-operations.md` § idea for the stage-by-stage surface.
171
+
172
+ **Persist the verbatim idea FIRST.** Before executing the `start` state, write the operator's
173
+ idea argument (or `--from-file` contents) **unmodified** to
174
+ `.spur/run/<run-id>-idea-input.md`; the run precheck fails when that file is empty or missing,
175
+ and every model-bearing stage prompt treats it as the authoritative ask. `--from-file` and the
176
+ positional idea are mutually exclusive — exactly one must be present.
177
+
178
+ Expected artifacts per stage (all run-scoped under `.spur/run/<run-id>-*`):
179
+
180
+ | Stage | Artifacts |
181
+ | ----- | --------- |
182
+ | start | `-idea-input.md` (verbatim idea), `-idea-precheck-doctor.status` |
183
+ | discovery | `-idea-eval-report.md` (with `## Requirement inventory`), `-idea-needs-design.json` |
184
+ | feature-create | `-idea-feature-id.txt`, `-idea-goal.md`, `-idea-scope.md` |
185
+ | ac-generate | `-idea-ac-content.md`, `-idea-ac-check.status`, `-idea-coverage.status` |
186
+ | system-design | `-idea-design-review.md`, `-idea-design-check.status` |
187
+ | decompose | `-idea-task-batch.json`, `-idea-task-order.json` |
188
+ | batch-create-run | `-idea-batch-create-result.json`, `-idea-batch-create.done`/`.failed` |
189
+ | ready-prepare | `-idea-ready.json` |
190
+ | handoff-finalize | `-idea-handoff.md` |
191
+
159
192
  ## Comprehensive-check retention and evidence (R7/R8)
160
193
 
161
194
  **R7 — comprehensive checks stay at their owning boundaries.** Quick readiness and plan projection are
@@ -398,6 +431,63 @@ keep their exact content after the stamp prefix. This normalization is contractu
398
431
  **bare local-clock stamps are prohibited** — a hand-appended `[stage 12:31]` form mixes timezones
399
432
  in one file and makes the run unauditable (task 0726 mixed both forms).
400
433
 
434
+ ## Structured trace emission (ADR-117, task 0868)
435
+
436
+ `.spur/run/<run-id>.log` is a human convenience, **not the record of truth**. A run's
437
+ observability is a property of the run, so the inline driver owes the same structured trace the
438
+ engine subprocess writes — and it owes it through the **same writer**, never a parallel
439
+ implementation. The shared writer is `WorkflowActionTraceWriter`
440
+ (`packages/app/src/workflow/action-trace.ts`): the same decorator the engine composition installs
441
+ around `DbWorkflowPersistenceAdapter`, so the two surfaces call one emission path and one run-row
442
+ closure path and cannot drift.
443
+
444
+ The driver reaches it through the existing run delegate (`$SETUP_SCRIPT`,
445
+ `plugins/sp/scripts/inline-run-setup.ts`) — no new entry point, no second resolution chain:
446
+
447
+ - **Every executed action** — after the action settles, whether it ran host-inline or via a native
448
+ subagent — append its provenance line as before, then record the boundary:
449
+
450
+ ```bash
451
+ bun "$SETUP_SCRIPT" --action --run-id "$RUN_ID" --node <state-id> --kind <action-kind> \
452
+ --status <done|failed> --ok <true|false> --duration-ms <measured-ms>
453
+ ```
454
+
455
+ `<state-id>` is the current YAML state id (the `node`), `<action-kind>` the YAML action kind
456
+ (`agent.run`, `shell`, `note`, `doctor.probe`, …). `--status` is `done` when the action settled
457
+ under its declared error policy and `failed` otherwise; `--duration-ms` is the wall clock the
458
+ driver measured around the action. This writes the `action_runs` row (node, kind, status, `ok`,
459
+ `duration_ms`, `run_id`) the engine would have written, so the run's rows are queryable by run id
460
+ (`spur workflow progress <run-id>`, `ActionRunDao`) without reading the text log. The writer
461
+ back-dates the row's `started_at` from its own `completed_at` minus the measured duration
462
+ (0887 R8), so `completed_at − started_at == duration_ms` exactly; a back-date failure is
463
+ recorded (`action.backdate`) and never affects the run.
464
+
465
+ - **At the run's declared terminal state** — before the driver reports the run complete, close the
466
+ row so a successful inline run is never left non-terminal for `spur workflow clean` to reap as
467
+ stale:
468
+
469
+ ```bash
470
+ bun "$SETUP_SCRIPT" --close --run-id "$RUN_ID" --status <done|failed|paused>
471
+ ```
472
+
473
+ `--status` is the declared terminal state's verdict, not a guess: a run that reached a terminal
474
+ state is `done`; a run halted by a failing action under its error policy is `failed`.
475
+
476
+ **Best-effort at the action boundary only (ADR-117).** An `--action` persistence failure is
477
+ recorded — the delegate appends a `trace-emission-failed` line to `.spur/run/<run-id>.log` and
478
+ prints `{"ok":false}` on stdout — and the run continues to its declared terminal state; the
479
+ delegate exits `0` for that outcome and the driver must never treat an emission failure as a run
480
+ failure, retry it in a loop, or substitute a hand-written row. The run-row closure (`--close`) is
481
+ bookkeeping, not trace emission, and is **not** best-effort: a missing run row or a persistence
482
+ failure exits `1` with `{"ok":false}` and a named error (a missing row also carries
483
+ `code:"RUN_NOT_FOUND"`), because a silently `running` row is exactly the stale state
484
+ `spur workflow clean` reaps as `failed`. Exit `2` means the invocation itself was malformed
485
+ (missing `--node`/`--kind`/`--status`/`--ok`, a miscased `--ok`, a missing or malformed
486
+ `--duration-ms`, or an unsafe run id) and must be corrected, not ignored.
487
+
488
+ Emission is not optional and not deferred: an inline run that skips it reintroduces the
489
+ 1,011-untraced-runs gap ADR-117 exists to close.
490
+
401
491
  Transition guards are not advisory. Execute the declared guard exactly, in order, with the same
402
492
  resolved variables and artifacts. `--no-lifecycle` remains bookkeeping only; the YAML's task checks,
403
493
  verdict gate, record step, and done guard all remain authoritative.
@@ -1,6 +1,18 @@
1
1
  ---
2
2
  name: taste-refactoring-api
3
3
  description: Design, review, and refactor REST/HTTP, RPC/gRPC, GraphQL, and event API contracts safely.
4
+ license: Apache-2.0
5
+ metadata:
6
+ author: spur
7
+ version: "1.0"
8
+ platforms: "claude-code,codex,openclaw,opencode,antigravity"
9
+ category: execution
10
+ interactions:
11
+ - technique
12
+ operations:
13
+ - refactor-apis
14
+ openclaw:
15
+ emoji: "🔌"
4
16
  ---
5
17
 
6
18
  # taste-refactoring-api
@@ -174,7 +186,7 @@ The goal is to eliminate repeated low-level API decisions, not to create bureauc
174
186
 
175
187
  ## Protocol-specific review
176
188
 
177
- After classifying the API, read the matching REST/HTTP, RPC/gRPC, GraphQL, or event/webhook section in [references/protocol-modes.md](references/protocol-modes.md). Apply that checklist before continuing with the refactoring strategy.
189
+ After classifying the API, read the matching REST/HTTP, RPC/gRPC, GraphQL, or event/webhook section in [references/protocol-modes.md](references/protocol-modes.md). Apply that checklist before continuing with the refactoring strategy. For command-line surface work (designing or reviewing a CLI), read the [CLI mode](references/protocol-modes.md) section instead — a CLI is a contract surface with the same compatibility duties as any wire protocol.
178
190
 
179
191
  ## Refactoring strategy
180
192
 
@@ -332,3 +344,34 @@ Specify the tests/checks needed: contract tests, schema validation, compatibilit
332
344
  ## Decision rule
333
345
 
334
346
  A “better” API is not the one with the prettiest route names. It is the one that makes common client code obvious, predictable, safe under failure, compatible over time, secure by default, and operable in production.
347
+
348
+ ## Spur contract
349
+
350
+ Machine-facing adapter for `sp:code-refactoring` dispatch (feature H13). Everything above is the
351
+ lens's native output and is unchanged; this section only maps it to the shared finding schema.
352
+
353
+ **Inputs received:** a scope path, an optional change description, and the `api` focus. Read
354
+ first: the classification and protocol section above (plus [references/protocol-modes.md](references/protocol-modes.md)),
355
+ then `../code-refactoring/references/finding-schema.md` for shared field semantics.
356
+
357
+ **Native finding → schema mapping:** each “Highest-impact refactor” item → `id` as
358
+ `RF-api-<nnn>`; the item's compatibility label → `rung` verbatim (`additive` | `risky` |
359
+ `breaking`); consumer impact → `title` and `proposal` (imperative); cited routes/lines →
360
+ `evidence` as `{file, line}` entries inside scope; `Verification` items → `verify`; the
361
+ “Proposed contract” snippets stay in `proposal`; new findings start at `status: open`.
362
+
363
+ **Severity mapping (design §5):** a `breaking` change already shipped, or contract ambiguity that
364
+ corrupts data → `P1`; a `risky` inconsistency across ≥2 endpoints → `P2`; `additive` cleanups →
365
+ `P3`; naming/docs → `P4`.
366
+
367
+ **Preserved-behavior inventory (required before proposals):** emit the consumer contract —
368
+ audience (public/partner/internal/service-to-service), endpoints/operations in scope, existing
369
+ clients that must remain compatible, and the compatibility promise — before the first finding.
370
+
371
+ **Preservation class (reuses the native classification):** `additive` → `preserving`; `risky`
372
+ and `breaking` → `breaking`; removal of an endpoint, field, or code path with callers →
373
+ `cutting` even when the change reads additive to remaining consumers.
374
+
375
+ **Stop rules:** an established style guide or public compatibility promise is a constraint, not
376
+ suggestion; `cutting`/`breaking` is never below `P2` and never `fix_eligibility: auto`; risky and
377
+ breaking changes carry a migration strategy; anything outside the scope path is not a finding.
@@ -77,3 +77,34 @@ For mutation races, prefer explicit optimistic concurrency such as ETags / `If-M
77
77
  - Make consumers tolerant of additive fields.
78
78
  - Do not use events as disguised synchronous RPC responses when the caller needs an immediate result.
79
79
 
80
+ ## CLI mode
81
+
82
+ A command-line interface is a contract surface with consumers (scripts, other agents, CI), not a
83
+ collection of convenience shortcuts. Review it with the same compatibility discipline as REST or
84
+ gRPC. Spur's own `apps/cli` is the first target.
85
+
86
+ **Noun/verb grammar:** keep one noun per domain and verbs per action (`spur task show`, not
87
+ `spur showTaskForTask`). Do not introduce a second grammar for the same concept — one spelling per
88
+ noun, one verb per operation, consistent object order.
89
+
90
+ **Flag vocabulary consistency:** shared flags (`--json`, `--scope`, `--agent`, `--fix`) keep the
91
+ same name, arity, and semantics everywhere they appear. A flag that means something new per
92
+ command is a defect; declare a new flag instead.
93
+
94
+ **Exit codes:** `0` = success, nonzero = failure, deterministic and machine-checkable. Never
95
+ swallow failures into `0`; never return nonzero for advisory output. Validation errors and
96
+ runtime failures should be distinguishable from output where practical.
97
+
98
+ **`--json` envelope stability:** `--json` output is a public schema. Add fields additively; never
99
+ remove or rename existing fields, never change a field's type, and emit no human decoration
100
+ (banners, progress text) on the JSON stream. Machine consumers parse the documented envelope only.
101
+
102
+ **Help-text parity:** every accepted flag appears in `--help` with its real arity and default;
103
+ every documented example runs as printed. A flag that works but is not documented, or documented
104
+ but rejected, is a parity break.
105
+
106
+ **Additive vs breaking:** adding a noun, verb, flag, or output field is additive. Renaming or
107
+ removing any of them, re-purposing a flag, changing a default, or altering existing output shape
108
+ is breaking — it requires a migration path and a deprecation window, and it never rides in a
109
+ patch release.
110
+
@@ -1,6 +1,18 @@
1
1
  ---
2
2
  name: taste-refactoring-architect
3
3
  description: Review, simplify, and refactor system architecture toward minimum sufficient architecture while preserving required capabilities, quality attributes, delivery safety, and data invariants. Backs architectural refactoring and boundary reviews.
4
+ license: Apache-2.0
5
+ metadata:
6
+ author: spur
7
+ version: "1.0"
8
+ platforms: "claude-code,codex,openclaw,opencode,antigravity"
9
+ category: execution
10
+ interactions:
11
+ - technique
12
+ operations:
13
+ - refactor-architecture
14
+ openclaw:
15
+ emoji: "🏛️"
4
16
  ---
5
17
 
6
18
  # taste-refactoring-architect
@@ -469,3 +481,34 @@ Do not block on perfect documentation. Produce:
469
481
  - decisions that can safely proceed now.
470
482
 
471
483
  Use A7 DEFER/OBSERVE when evidence is too weak for a structural change.
484
+
485
+ ## Spur contract
486
+
487
+ Machine-facing adapter for `sp:code-refactoring` dispatch (feature H13). Everything above is the
488
+ lens's native output and is unchanged; this section only maps it to the shared finding schema.
489
+
490
+ **Inputs received:** a scope path, an optional change description, and the `architect` focus.
491
+ Read first: the intervention ladder and workflow above, then
492
+ `../code-refactoring/references/finding-schema.md` for shared field semantics.
493
+
494
+ **Native finding → schema mapping:** `ID` → `id` as `RF-architect-<nnn>`; `Action` (A0–A7) →
495
+ `rung` verbatim; `Observation`/`Why it matters` → `title` plus `proposal` (imperative); `Evidence`
496
+ → `evidence` as `{file, line}` entries inside scope; `Fitness functions` → `verify`; new findings
497
+ start at `status: open`. ADR candidates and migration plans stay prose findings with
498
+ `fix_eligibility: suggest`.
499
+
500
+ **Severity mapping (design §5):** any axis ≤1 with a correctness/safety consequence → `P1`; axis
501
+ ≤2 or A5–A7 seam problems → `P2`; A3–A4 → `P3`; A0–A2, ADR candidates, deferred questions → `P4`.
502
+
503
+ **Preserved-behavior inventory (required before proposals):** emit the Preservation Contract
504
+ table — capabilities, quality attributes, data invariants, and their thresholds — for everything
505
+ in scope before the first finding.
506
+
507
+ **Preservation class:** A0/A3/A4 mechanical consolidations with identical behavior →
508
+ `preserving`; A1/A2 removal of a live service, endpoint, queue, or code path with callers →
509
+ `cutting`; A5–A7 seam or behavior changes → `breaking`; migration plans and ADR candidates →
510
+ `preserving` prose with `fix_eligibility: suggest`.
511
+
512
+ **Stop rules:** no removal without dependency/traffic/contract evidence; `cutting`/`breaking` is
513
+ never below `P2` and never `fix_eligibility: auto`; multi-task migrations are `suggest`, applied
514
+ only after an explicit operator answer; anything outside the scope path is not a finding.
@@ -1,6 +1,18 @@
1
1
  ---
2
2
  name: taste-refactoring-tests
3
3
  description: Refactor unit tests for failure sensitivity, deterministic confidence, and regression protection without mock-heavy brittle tests or vanity coverage. Backs test suite quality audits.
4
+ license: Apache-2.0
5
+ metadata:
6
+ author: spur
7
+ version: "1.0"
8
+ platforms: "claude-code,codex,openclaw,opencode,antigravity"
9
+ category: execution
10
+ interactions:
11
+ - technique
12
+ operations:
13
+ - refactor-tests
14
+ openclaw:
15
+ emoji: "🧪"
4
16
  ---
5
17
 
6
18
  # taste-refactoring-tests
@@ -480,3 +492,33 @@ A test refactor is complete only when:
480
492
  - delivery speed is not degraded without a justified risk trade-off.
481
493
 
482
494
  The goal is **earned confidence**: green means something because the suite has demonstrated that it can turn red when the product is wrong.
495
+
496
+ ## Spur contract
497
+
498
+ Machine-facing adapter for `sp:code-refactoring` dispatch (feature H13). Everything above is the
499
+ lens's native output and is unchanged; this section only maps it to the shared finding schema.
500
+
501
+ **Inputs received:** a scope path, an optional change description, and the `tests` focus. Read
502
+ first: the intervention ladder, Confidence Contract, and review severity above, then
503
+ `../code-refactoring/references/finding-schema.md` for shared field semantics.
504
+
505
+ **Native finding → schema mapping:** `ID` → `id` as `RF-tests-<nnn>`; `Action` (T0–T7) → `rung`
506
+ verbatim; `Severity` → `severity` via the map below; `Evidence` → `evidence` as `{file, line}`
507
+ entries inside scope; `Why it matters` → `title`; `Proposed change` → `proposal` (imperative);
508
+ `Expected regression-detection improvement` → folded into `proposal`; new findings start at
509
+ `status: open`.
510
+
511
+ **Severity mapping (design §5):** native P0 → `P1`; P1 → `P2`; P2 → `P3`; P3 → `P4`.
512
+
513
+ **Preserved-behavior inventory (required before proposals):** emit the Confidence Contract —
514
+ critical business rules, compatibility contracts, authorization/security decisions, data
515
+ integrity invariants, error semantics, and incident regressions the suite must keep protecting —
516
+ before the first finding.
517
+
518
+ **Preservation class:** T0 and rungs that keep or add protection (fixture cleanup, adding a
519
+ missing test) → `preserving`; removing a test or test file (T1) → `cutting`; weakening or
520
+ semantically changing existing assertions → `breaking`.
521
+
522
+ **Stop rules:** unknown protection is a risk, never permission to delete; a `cutting`/`breaking`
523
+ finding is never `fix_eligibility: auto` and never below `P2`; tests are never removed or
524
+ weakened by an `auto` fix; anything outside the scope path is not a finding.
@@ -1,6 +1,18 @@
1
1
  ---
2
2
  name: taste-refactoring-ui
3
3
  description: Design, review, and refactor UI hierarchy, layout, typography, spacing, color, and interactions.
4
+ license: Apache-2.0
5
+ metadata:
6
+ author: spur
7
+ version: "1.0"
8
+ platforms: "claude-code,codex,openclaw,opencode,antigravity"
9
+ category: execution
10
+ interactions:
11
+ - technique
12
+ operations:
13
+ - refactor-ui
14
+ openclaw:
15
+ emoji: "🎨"
4
16
  ---
5
17
 
6
18
  # taste-refactoring-ui
@@ -288,3 +300,34 @@ For deeper reasoning and daily use, read:
288
300
  - `references/refactoring-ui-playbook.md` — chapter-by-chapter distilled guidance.
289
301
  - `checklists/daily-ui-review.md` — fast audit and ship checklist.
290
302
  - `examples/review-template.md` — reusable UI critique response structure.
303
+
304
+ ## Spur contract
305
+
306
+ Machine-facing adapter for `sp:code-refactoring` dispatch (feature H13). Everything above is the
307
+ lens's native output and is unchanged; this section only maps it to the shared finding schema.
308
+
309
+ **Inputs received:** a scope path, an optional change description, and the `ui` focus. Read
310
+ first: the refactoring protocol and output contract above, then
311
+ `../code-refactoring/references/finding-schema.md` for shared field semantics.
312
+
313
+ **Native finding → schema mapping:** each issue → `id` as `RF-ui-<nnn>`; the pass that owns it
314
+ (hierarchy, spacing, typography, color, states) → `rung`; `Observation` + `Refactor` → `title`
315
+ and `proposal` (imperative); the cited component/file and line → `evidence` as `{file, line}`
316
+ entries inside scope; the `System rule` → folded into `proposal`; new findings start at
317
+ `status: open`.
318
+
319
+ **Severity mapping (design §5):** native P0 (task failure) → `P1`; P1 (hierarchy/structure) →
320
+ `P2`; P2 (system inconsistency) → `P3`; P3 (polish) → `P4`.
321
+
322
+ **Preserved-behavior inventory (required before proposals):** emit the controls and interactions
323
+ in scope — primary/secondary actions, navigation, form semantics, accessible names, states —
324
+ before the first finding.
325
+
326
+ **Preservation class:** token normalization and layout/typography consolidation with identical
327
+ function → `preserving`; adding a missing state or a11y attribute → `preserving`; removing or
328
+ merging a control or interaction → `cutting`; changes to user-visible flows or behavior →
329
+ `breaking`.
330
+
331
+ **Stop rules:** meaning is never carried by color alone; preserve component semantics and
332
+ accessibility; a `cutting`/`breaking` finding is never `fix_eligibility: auto` and never below
333
+ `P2`; anything outside the scope path is not a finding.
@@ -161,6 +161,11 @@
161
161
  "options": {
162
162
  "type": "object",
163
163
  "additionalProperties": true
164
+ },
165
+ "onError": {
166
+ "type": "string",
167
+ "enum": ["fail", "continue"],
168
+ "description": "Per-action error handling policy: 'fail' halts the run; 'continue' logs the failure and proceeds so transition guards can route the outcome."
164
169
  }
165
170
  }
166
171
  },