@gobing-ai/spur 0.3.78 → 0.3.81

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 (177) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/config.example.yaml +29 -18
  3. package/config/config.global.yaml +10 -11
  4. package/config/pipeline-budgets.json +34 -2
  5. package/config/plugin-scripts.json +25 -0
  6. package/config/rules/boundary/config-loading-ownership.yaml +0 -3
  7. package/config/rules/boundary/dao-boundary.yaml +4 -17
  8. package/config/rules/boundary/planning-folder-hardcode.yaml +0 -1
  9. package/config/rules/boundary/sp-no-vendor-refs.yaml +3 -2
  10. package/config/rules/boundary/sp-runtime-path.yaml +3 -14
  11. package/config/rules/quality/coverage-gate.yaml +3 -14
  12. package/config/rules/quality/tsdoc-exports.yaml +4 -7
  13. package/config/rules/strict/http-boundaries.yaml +5 -8
  14. package/config/rules/strict/runtime-boundaries.yaml +1 -5
  15. package/config/rules/structure/protected-files.yaml +9 -3
  16. package/config/rules/structure/test-focus-skip.yaml +0 -2
  17. package/config/rules/structure/test-location.yaml +0 -5
  18. package/config/rules/surface/check-cli-surface.yaml +3 -2
  19. package/config/rules/typescript/bun-tooling.yaml +5 -7
  20. package/config/rules/typescript/guarded-happy-dom-register.yaml +0 -2
  21. package/config/rules/typescript/happy-dom-teardown.yaml +0 -2
  22. package/config/rules/typescript/no-biome-suppressions.yaml +0 -2
  23. package/config/rules/typescript/no-debugger.yaml +0 -2
  24. package/config/rules/typescript/no-eslint-suppressions.yaml +0 -4
  25. package/config/rules/typescript/no-leaky-module-mocks.yaml +6 -13
  26. package/config/rules/typescript/no-module-scope-import-calls.yaml +0 -2
  27. package/config/rules/typescript/no-syscall-emulation-in-boundary-mock.yaml +0 -3
  28. package/config/rules/typescript/no-unmocked-module-eval-side-effects.yaml +0 -3
  29. package/config/rules/typescript/output-boundaries.yaml +0 -3
  30. package/config/rules/typescript/prefer-accessible-role-for-button-queries.yaml +0 -3
  31. package/config/rules/ui/ui-import-boundary.yaml +1 -5
  32. package/config/templates/AGENTS.md +26 -23
  33. package/config/templates/docs/00_ADR.md +13 -23
  34. package/config/templates/docs/01_PRD.md +5 -2
  35. package/config/templates/docs/02_ROADMAP.md +9 -13
  36. package/config/templates/docs/03_ARCHITECTURE.md +2 -2
  37. package/config/templates/docs/04_DESIGN.md +12 -31
  38. package/config/templates/docs/05_FEATURES.md +6 -18
  39. package/config/templates/docs/99_PROJECT_CONSTITUTION.md +162 -394
  40. package/config/transition-shims.json +7 -7
  41. package/config/workflows/basic.yaml +4 -0
  42. package/config/workflows/docs-pipeline.yaml +13 -14
  43. package/config/workflows/feature-dev.yaml +20 -65
  44. package/config/workflows/history-anatomy.yaml +22 -1
  45. package/config/workflows/idea-pipeline.yaml +53 -97
  46. package/config/workflows/pr-review.yaml +21 -33
  47. package/config/workflows/task-pipeline.yaml +87 -330
  48. package/config/workflows/wayfinder-resolution.yaml +12 -26
  49. package/config/workflows/wrapup-pipeline.yaml +48 -189
  50. package/package.json +9 -9
  51. package/plugins/sp/README.md +22 -8
  52. package/plugins/sp/agents/expert-spur.md +41 -19
  53. package/plugins/sp/agents/super-reviewer.md +43 -8
  54. package/plugins/sp/lib/idea-handoff.generated.d.mts +17 -0
  55. package/plugins/sp/lib/idea-handoff.generated.mjs +1301 -0
  56. package/plugins/sp/plugin.json +1 -1
  57. package/plugins/sp/scripts/feature-dev-precheck.mjs +146 -0
  58. package/plugins/sp/scripts/feature-dev-precheck.ts +238 -0
  59. package/plugins/sp/scripts/idea-handoff.mjs +27 -0
  60. package/plugins/sp/scripts/idea-handoff.ts +44 -0
  61. package/plugins/sp/scripts/quality-gate.mjs +165 -0
  62. package/plugins/sp/scripts/quality-gate.ts +217 -0
  63. package/plugins/sp/scripts/verify-answer-lint.ts +21 -3
  64. package/plugins/sp/scripts/workflow-step-profile.mjs +319 -0
  65. package/plugins/sp/scripts/workflow-step-profile.ts +456 -0
  66. package/plugins/sp/scripts/wrapup-steps.mjs +350 -0
  67. package/plugins/sp/scripts/wrapup-steps.ts +466 -0
  68. package/plugins/sp/skills/conflict-finding/SKILL.md +6 -0
  69. package/plugins/sp/skills/daily-summary/SKILL.md +1 -1
  70. package/plugins/sp/skills/doc-evolve/SKILL.md +26 -40
  71. package/plugins/sp/skills/doc-evolve/references/operations.md +17 -30
  72. package/plugins/sp/skills/parallel-execution/references/dispatch-surface.md +1 -1
  73. package/plugins/sp/skills/spec-decomposition/references/decomposition.md +29 -0
  74. package/plugins/sp/skills/spur-cli/references/agent.md +56 -14
  75. package/plugins/sp/skills/spur-cli/references/message.md +30 -3
  76. package/plugins/sp/skills/spur-cli/references/projects.md +45 -1
  77. package/plugins/sp/skills/spur-cli/references/self.md +5 -4
  78. package/plugins/sp/skills/spur-cli/references/serve.md +5 -4
  79. package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +17 -1
  80. package/plugins/sp/skills/spur-cli/references/tasks.md +32 -2
  81. package/plugins/sp/skills/spur-cli/references/team.md +21 -1
  82. package/plugins/sp/skills/spur-cli/references/workflows/operations.md +6 -3
  83. package/plugins/sp/skills/spur-cli/references/workflows/workflow-fit-and-tuning.md +57 -18
  84. package/plugins/sp/skills/spur-composer/SKILL.md +145 -0
  85. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +14 -0
  86. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +3 -3
  87. package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +12 -0
  88. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +46 -4
  89. package/plugins/sp/skills/spur-dev/references/planning-workflow.md +24 -0
  90. package/plugins/sp/skills/spur-doctor/SKILL.md +138 -0
  91. package/plugins/sp/skills/taste-refactoring-api/README.md +43 -0
  92. package/plugins/sp/skills/taste-refactoring-api/SKILL.md +334 -0
  93. package/plugins/sp/skills/taste-refactoring-api/checklists/daily-api-review.md +71 -0
  94. package/plugins/sp/skills/taste-refactoring-api/examples/refactor-example.md +72 -0
  95. package/plugins/sp/skills/taste-refactoring-api/examples/review-template.md +93 -0
  96. package/plugins/sp/skills/taste-refactoring-api/references/api-refactoring-playbook.md +253 -0
  97. package/plugins/sp/skills/taste-refactoring-api/references/protocol-modes.md +79 -0
  98. package/plugins/sp/skills/taste-refactoring-api/references/research-basis.md +58 -0
  99. package/plugins/sp/skills/taste-refactoring-architect/README.md +26 -0
  100. package/plugins/sp/skills/taste-refactoring-architect/SKILL.md +471 -0
  101. package/plugins/sp/skills/taste-refactoring-architect/checklists/daily-architecture-review.md +48 -0
  102. package/plugins/sp/skills/taste-refactoring-architect/examples/refactor-example.md +55 -0
  103. package/plugins/sp/skills/taste-refactoring-architect/examples/review-template.md +51 -0
  104. package/plugins/sp/skills/taste-refactoring-architect/references/architecture-refactoring-playbook.md +173 -0
  105. package/plugins/sp/skills/taste-refactoring-architect/references/research-basis.md +28 -0
  106. package/plugins/sp/skills/taste-refactoring-tests/README.md +28 -0
  107. package/plugins/sp/skills/taste-refactoring-tests/SKILL.md +482 -0
  108. package/plugins/sp/skills/taste-refactoring-tests/checklists/daily-test-review.md +39 -0
  109. package/plugins/sp/skills/taste-refactoring-tests/examples/refactor-example.md +85 -0
  110. package/plugins/sp/skills/taste-refactoring-tests/examples/review-template.md +59 -0
  111. package/plugins/sp/skills/taste-refactoring-tests/references/research-basis.md +47 -0
  112. package/plugins/sp/skills/taste-refactoring-tests/references/test-refactoring-playbook.md +222 -0
  113. package/plugins/sp/skills/taste-refactoring-ui/README.md +12 -0
  114. package/plugins/sp/skills/taste-refactoring-ui/SKILL.md +290 -0
  115. package/plugins/sp/skills/taste-refactoring-ui/checklists/daily-ui-review.md +72 -0
  116. package/plugins/sp/skills/taste-refactoring-ui/examples/review-template.md +51 -0
  117. package/plugins/sp/skills/taste-refactoring-ui/references/refactoring-ui-playbook.md +170 -0
  118. package/plugins/sp/skills/wayfinder/SKILL.md +2 -2
  119. package/plugins/sp/skills/wayfinder/references/pipeline-resolution.md +30 -0
  120. package/schemas/spur-config.schema.json +49 -0
  121. package/spur.js +46936 -44198
  122. package/web/_astro/{BoardApp.CHQ1lycZ.js → BoardApp.B1U26g3I.js} +97 -95
  123. package/web/_astro/BoardApp.Csgyg-lS.js +1 -0
  124. package/web/_astro/{TaskDetail.GKfQJ60c.js → TaskDetail.DwPqpq7v.js} +1 -1
  125. package/web/_astro/{arc.DWEtA3Tx.js → arc.CweZEjN2.js} +1 -1
  126. package/web/_astro/{architectureDiagram-3BPJPVTR.DB42oWmP.js → architectureDiagram-3BPJPVTR.D89pbDuv.js} +1 -1
  127. package/web/_astro/{blockDiagram-GPEHLZMM.rhv-zNQV.js → blockDiagram-GPEHLZMM.BOuTeEpX.js} +1 -1
  128. package/web/_astro/{c4Diagram-AAUBKEIU.Ci4-4VvY.js → c4Diagram-AAUBKEIU.CASbkWZF.js} +1 -1
  129. package/web/_astro/channel.Cx6sXxhq.js +1 -0
  130. package/web/_astro/{chunk-2J33WTMH.Cc9veUgf.js → chunk-2J33WTMH.BKQYtOvY.js} +1 -1
  131. package/web/_astro/{chunk-4BX2VUAB.Bec9c4eI.js → chunk-4BX2VUAB.9sHLdMtG.js} +1 -1
  132. package/web/_astro/{chunk-55IACEB6.DoV8S1iB.js → chunk-55IACEB6.wOLXWlPs.js} +1 -1
  133. package/web/_astro/{chunk-727SXJPM.DwR-Qlyj.js → chunk-727SXJPM.DovFbwg3.js} +1 -1
  134. package/web/_astro/{chunk-AQP2D5EJ.ND_a81WY.js → chunk-AQP2D5EJ.B1Weod1X.js} +1 -1
  135. package/web/_astro/{chunk-FMBD7UC4.Wv_jwG48.js → chunk-FMBD7UC4.TEMS04st.js} +1 -1
  136. package/web/_astro/{chunk-ND2GUHAM.CXKXCMmp.js → chunk-ND2GUHAM.Cp8VT1wQ.js} +1 -1
  137. package/web/_astro/{chunk-QZHKN3VN.nkaoNYQq.js → chunk-QZHKN3VN.BzATdEcP.js} +1 -1
  138. package/web/_astro/{classDiagram-4FO5ZUOK.cMQcVlQu.js → classDiagram-4FO5ZUOK.C9BOCfAO.js} +1 -1
  139. package/web/_astro/{classDiagram-v2-Q7XG4LA2.cMQcVlQu.js → classDiagram-v2-Q7XG4LA2.C9BOCfAO.js} +1 -1
  140. package/web/_astro/{cose-bilkent-S5V4N54A.OaDJ7Mr2.js → cose-bilkent-S5V4N54A.DUnr4UAw.js} +1 -1
  141. package/web/_astro/{cynefin-OW5HDTMX.Chi8IphF.js → cynefin-OW5HDTMX.rYq5uM3D.js} +1 -1
  142. package/web/_astro/{cytoscape.esm.DzSz-X2X.js → cytoscape.esm.BB4DxJjf.js} +1 -1
  143. package/web/_astro/{dagre-BM42HDAG.CzK2t_Fp.js → dagre-BM42HDAG.CWeNKe3I.js} +1 -1
  144. package/web/_astro/{diagram-2AECGRRQ.DRvxlVS7.js → diagram-2AECGRRQ.DCkfls10.js} +1 -1
  145. package/web/_astro/{diagram-5GNKFQAL.CnYvNdwA.js → diagram-5GNKFQAL.D5U4JCka.js} +1 -1
  146. package/web/_astro/{diagram-KO2AKTUF.CpLpMw5R.js → diagram-KO2AKTUF.BZJgqaqG.js} +1 -1
  147. package/web/_astro/{diagram-LMA3HP47.JTb78qUA.js → diagram-LMA3HP47.DoMeHvPR.js} +1 -1
  148. package/web/_astro/{diagram-OG6HWLK6.Bk-1jDIb.js → diagram-OG6HWLK6.B50qwwWX.js} +1 -1
  149. package/web/_astro/{erDiagram-TEJ5UH35.D8hN9GZq.js → erDiagram-TEJ5UH35.DdGPG6LK.js} +1 -1
  150. package/web/_astro/{flowDiagram-I6XJVG4X.-6zQr6m5.js → flowDiagram-I6XJVG4X.QP2MJ12u.js} +1 -1
  151. package/web/_astro/{ganttDiagram-6RSMTGT7.DboLQ9ca.js → ganttDiagram-6RSMTGT7.BI6LgKSy.js} +1 -1
  152. package/web/_astro/{gitGraphDiagram-PVQCEYII.4tYvJKGR.js → gitGraphDiagram-PVQCEYII.npPZiC2G.js} +1 -1
  153. package/web/_astro/index.DayyIngm.css +1 -0
  154. package/web/_astro/{infoDiagram-5YYISTIA.Bd9rXpsB.js → infoDiagram-5YYISTIA.DCJCBVbp.js} +1 -1
  155. package/web/_astro/{ishikawaDiagram-YF4QCWOH.CvMoaf67.js → ishikawaDiagram-YF4QCWOH.BMLV-3I1.js} +1 -1
  156. package/web/_astro/{journeyDiagram-JHISSGLW.Ccy1CA7y.js → journeyDiagram-JHISSGLW.LE58crde.js} +1 -1
  157. package/web/_astro/{kanban-definition-UN3LZRKU.0MaMqHNS.js → kanban-definition-UN3LZRKU.BPbz8rH9.js} +1 -1
  158. package/web/_astro/{linear.CHXgcIbN.js → linear.DhZaBtYh.js} +1 -1
  159. package/web/_astro/{mermaid.core.Ca-kcelG.js → mermaid.core.BD5-jXum.js} +6 -6
  160. package/web/_astro/{mindmap-definition-RKZ34NQL.BUIDlHa0.js → mindmap-definition-RKZ34NQL.MTJyrQ65.js} +1 -1
  161. package/web/_astro/ordinal.BYWQX77i.js +1 -0
  162. package/web/_astro/{pieDiagram-4H26LBE5.2dX3CU1s.js → pieDiagram-4H26LBE5.BrDhDvIS.js} +1 -1
  163. package/web/_astro/{quadrantDiagram-W4KKPZXB.B3LBlRiv.js → quadrantDiagram-W4KKPZXB.71d73_5N.js} +1 -1
  164. package/web/_astro/{requirementDiagram-4Y6WPE33.X12I2uNx.js → requirementDiagram-4Y6WPE33.Bga6UF-z.js} +1 -1
  165. package/web/_astro/{sankeyDiagram-5OEKKPKP.BXohIHqx.js → sankeyDiagram-5OEKKPKP.BnHs4K82.js} +1 -1
  166. package/web/_astro/{sequenceDiagram-3UESZ5HK.C37ZIUzg.js → sequenceDiagram-3UESZ5HK.DsfY2gnj.js} +1 -1
  167. package/web/_astro/{stateDiagram-AJRCARHV.BRgz317z.js → stateDiagram-AJRCARHV.DvsTSc9a.js} +1 -1
  168. package/web/_astro/{stateDiagram-v2-BHNVJYJU.7VYSXN9-.js → stateDiagram-v2-BHNVJYJU.DxzzmHUR.js} +1 -1
  169. package/web/_astro/{timeline-definition-PNZ67QCA.BVNz_HiN.js → timeline-definition-PNZ67QCA.4ZuQmOTt.js} +1 -1
  170. package/web/_astro/{vennDiagram-CIIHVFJN.CHVDkPX4.js → vennDiagram-CIIHVFJN.Ck5Q86SG.js} +1 -1
  171. package/web/_astro/{wardleyDiagram-YWT4CUSO.EQQ_qT9v.js → wardleyDiagram-YWT4CUSO.BK7k2hXr.js} +1 -1
  172. package/web/_astro/{xychartDiagram-2RQKCTM6.DrAT9WoP.js → xychartDiagram-2RQKCTM6.DfCrgauK.js} +1 -1
  173. package/web/index.html +2 -2
  174. package/web/_astro/BoardApp.DV9kx0wo.js +0 -1
  175. package/web/_astro/channel.BAI6xLeV.js +0 -1
  176. package/web/_astro/index.Dcr_8fiK.css +0 -1
  177. package/web/_astro/ordinal.DBvzRdQf.js +0 -1
@@ -130,24 +130,63 @@ The flags (`--detail`, `--verbose`, `--trace-file`, `--follow`, `--output`) are
130
130
  ## 3. Node simplicity budget
131
131
 
132
132
  Simplicity is the operating constraint, and it is already measurable — `spur workflow validate`
133
- reports it. Do not invent a second threshold; author to the one that is frozen (ADR-069, task 0614).
134
-
135
- | Element | Budget | What breaching it means |
136
- | --- | --- | --- |
137
- | `shell` action `command` | **<= 5** non-comment units (split on newline and `;`) | >= 6 flags the composition advisory: the program holds reusable behavior that wants an owner |
138
- | `agent.run` action `input` | A **slash command or skill invocation** | A raw prose prompt flags: the operation belongs behind a centralized command (ADR-043). Prompt length sets severity only |
139
- | Transition guard | **One** boolean predicate | Guards are exempt from the shell measure by design. A guard needing five lines is a probe node in disguise — make it one |
140
- | Node count | Every node earns its transition round-trip | A node that always runs immediately after another, with no guard between them, is one node |
141
-
142
- **When a node breaches the budget, do not reformat to dodge the measure.** Joining five lines with
143
- `&&` moves the complexity, not the ownership. Pick one of the four remaining owners from
144
- `docs/design/workflow-shell-ownership.md`: public `spur` verb (consent-gated), application service,
145
- least-privilege built-in action kind, or workflow-relative external extension. (0775 retired the
146
- recorded stays-shell exception along with the suppression snapshot.)
147
-
148
- **Advisory posture is binding.** Composition findings never block a run, never change a `validate`
149
- exit status, and are never a reason to hot-edit an executing pipeline. Surface them; fix on operator
150
- acceptance.
133
+ reports it with a `warn`/`error` level. Do not invent a second threshold; author to the ADR-115
134
+ tiers frozen in [surface governance §1.2](../../../../../../docs/design/harness-surface-governance.md).
135
+
136
+ | Element | Clean | Warn (advisory) | Error |
137
+ | --- | --- | --- | --- |
138
+ | `shell` action `command` | ≤5 logical commands (split on newline, `;`, `&&`, `||`; blank/`#`/structure tokens skipped) | **6–10** | **>10** commands or **>800** characters |
139
+ | Shell transition guard | ≤3 logical commands — one predicate over a result file | **4–5** | **>5** |
140
+ | `agent.run` `input` | A slash command or skill invocation (ADR-043), ≤1000 chars | non-slash prompt (severity by raw length: <200 low, ≤1000 medium) | **>1000** chars, slash-led or not |
141
+ | `agent.run` output check | `expectFile` or `requireDiff` declared | neither declared | — |
142
+ | Node count | Every node earns its transition round-trip | A node that always runs immediately after another, with no guard between them, is one node | — |
143
+
144
+ **When a program breaches a cap, do not reformat to dodge the measure.** Joining lines with `&&`
145
+ moves the complexity, not the ownership. Move the program to one of the five recorded owners from
146
+ `docs/design/workflow-shell-ownership.md`: (a) public `spur` verb (consent-gated), (b) application
147
+ service, (c) least-privilege built-in action kind, (d) workflow-relative external extension, or
148
+ (e) a deliberately-stays-shell exception. (e) is valid only inside the warn band — above an error
149
+ cap the program moves to (a)–(d).
150
+
151
+ **Every remaining warn-band shell program carries a one-line `#` reason**: a YAML comment directly
152
+ above the action or guard, e.g. `# (e) <why it stays shell>` or `# (d) <script> owns <what>`. Never
153
+ write it as a shell `#` line inside a folded `>-` scalar — folding joins the lines, so the `#`
154
+ comments out the rest of the program. YAML comments do not count toward the measure.
155
+
156
+ **Posture is binding (ADR-115).** Warn-level findings never change a `validate` exit status and
157
+ never block a run. An error-level finding makes `validate` exit 1 and gates the spur repository's
158
+ shipped shared workflow layer (layer id `shared` in `spur workflow list --json`) in `spur-check`
159
+ (task 0826). No composition finding ever blocks `run`, `run --dry-run` or `continue`, and a finding
160
+ is never a reason to hot-edit an executing pipeline.
161
+
162
+ ### Consolidation and cache windows (ADR-115)
163
+
164
+ Two composition rules sit next to this budget: the table above stays the measure surface, these
165
+ decide where steps are cut. The rules are owned by the
166
+ [workflow composition contract](../../../../../../docs/design/workflow-composition-contract.md#composition-budgets-adr-115);
167
+ the text below is the operating summary, not a second owner.
168
+
169
+ **Consolidation — one model step per judgment.** Merge adjacent `agent.run` steps only when they
170
+ share a role and an executor **and** nothing between them must stay separate: a deterministic gate,
171
+ a HITL state, or an independence boundary. Never merge an author step with the review or verify
172
+ step that certifies it — those keep `freshSession: true`. A new model step in a shared workflow
173
+ raises its `pipeline-budgets` `modelQueries`, which needs a recorded decision, and every shared
174
+ workflow with a model query carries a budget entry.
175
+
176
+ **Cache windows — step boundaries follow the cache window, not the clock.** Provider prompt caches
177
+ expire after an idle window and refresh on every hit (Anthropic: 5 minutes by default; OpenAI:
178
+ 5–10 minutes in memory). The window W defaults to 300 s, the shortest common default:
179
+
180
+ - A tool call inside `agent.run` that runs longer than W idles the model — its next request
181
+ re-reads a cold prefix. Run that work in a deterministic step instead.
182
+ - An `agent.run` that resumes the inherited session after a gap longer than W (a HITL wait, a slow
183
+ deterministic step) rewrites the whole session into the cache. When the prior step's artifact
184
+ carries what the step needs, prefer `freshSession: true` with that artifact as the handoff.
185
+ - A deterministic step should finish within W at p50. An `agent.run` with p50 above 2W is a split
186
+ candidate only at a real artifact seam — each split adds a model query and a cold prefix, so it
187
+ must pay for itself in retry granularity or observability.
188
+
189
+ These are runtime budgets, judged from run traces and step profiles — never `validate` findings.
151
190
 
152
191
  ---
153
192
 
@@ -0,0 +1,145 @@
1
+ ---
2
+ name: spur-composer
3
+ description: "Select, compose and tune spur artifacts — tasks, features, rules, workflows and agent specs. Owns workflow catalog selection, the ephemeral→project→shared ladder, the ADR-115 budgets, trace-driven rule tuning, and applying accepted sp:spur-doctor proposals. Triggers: compose a workflow, tune a rule, apply doctor proposals."
4
+ license: Apache-2.0
5
+ version: 1.0.0
6
+ metadata:
7
+ author: spur
8
+ platforms: "claude-code,codex,openclaw,opencode,antigravity"
9
+ category: artifact-composition
10
+ interactions:
11
+ - inversion
12
+ - companion
13
+ operations:
14
+ - select
15
+ - compose
16
+ - tune
17
+ - apply
18
+ openclaw:
19
+ emoji: "🎼"
20
+ see_also:
21
+ - sp:spur-cli
22
+ - sp:spur-doctor
23
+ - sp:super-planner
24
+ ---
25
+
26
+ # sp:spur-composer — compose, select and tune spur artifacts
27
+
28
+ One cross-noun method (ADR-114, [spur artifact evolution](../../../../docs/design/spur-artifact-evolution.md)
29
+ §2): **select** an existing artifact, **compose** a new one up the ladder, **tune** it against
30
+ evidence, and **apply** the proposals the operator accepts from `sp:spur-doctor`. It never judges
31
+ its own output and never runs a recurring loop — evaluation is the doctor's job.
32
+
33
+ ## Boundary — read before composing
34
+
35
+ - **Verbs and flags live in `sp:spur-cli`.** This skill links references; it never restates a verb
36
+ or flag catalog: [../spur-cli/SKILL.md](../spur-cli/SKILL.md).
37
+ - **Recurring loops and coordination go to `sp:super-planner`** or a workflow — not here. This skill
38
+ runs one bounded composition or tuning pass per invocation.
39
+ - **Forbidden surfaces: `spur team` and `spur agent loop`.** Agent specs are reached only through
40
+ `spur agent create|edit|delete|list --specs`.
41
+ - **Writes land only through `spur` verbs** and the ladder's gated file steps (§ below). The shared
42
+ step additionally needs recorded operator consent plus `build:bundle` parity.
43
+
44
+ ## Covered nouns
45
+
46
+ | Noun | Composition / tuning method | Verb reference |
47
+ | --- | --- | --- |
48
+ | task | Apply accepted doctor rows via the CLI-gated corpus surface; author variants through the task reference's conventions | [../spur-cli/references/tasks.md](../spur-cli/references/tasks.md) |
49
+ | feature | Apply accepted rows through `spur feature update --section --from-file`; keep acceptance criteria in Gherkin | [../spur-cli/references/features.md](../spur-cli/references/features.md) |
50
+ | rule | The trace-driven tuning loop (§ Rule tuning loop) | [../spur-cli/references/rules.md](../spur-cli/references/rules.md) · [fine-tuning](../spur-cli/references/rules/fine-tuning.md) |
51
+ | workflow | Catalog selection, the composition ladder, and the ADR-115 budgets (§ below) | [../spur-cli/references/workflows.md](../spur-cli/references/workflows.md) · [operations](../spur-cli/references/workflows/operations.md) |
52
+ | agent spec | Compose and edit `.spur/agents/<id>.yaml` only through `spur agent create|edit|delete|list --specs` | [../spur-cli/references/agent.md](../spur-cli/references/agent.md) |
53
+
54
+ Do not drive the planning→execution lifecycle from here — that is `sp:spur-dev`.
55
+
56
+ ## Workflow catalog selection
57
+
58
+ Run this **before composing anything new**, exactly as the
59
+ [find-existing-workflow](../spur-cli/references/workflows/operations.md#sub-procedure-find-existing-workflow)
60
+ procedure: the catalog is `spur workflow list --json` across all layers, and each entry's
61
+ `description` is its intent.
62
+
63
+ | Catalog match | Action |
64
+ | --- | --- |
65
+ | Matches the intent | **Run it as is.** No new artifact. |
66
+ | Near match | **Same-name override in the project layer** (`.spur/workflows/<name>.yaml`) — the project layer wins name resolution — and tune from there. |
67
+ | No match | **Compose** up the ladder (§ Composition ladder). |
68
+
69
+ Never glob a folder to enumerate candidates: layers you skip that way are layers a bare name
70
+ cannot resolve from.
71
+
72
+ ## Composition ladder
73
+
74
+ | Step | Location | Gate before use |
75
+ | --- | --- | --- |
76
+ | ephemeral | A scratch file outside every layer (for example under `.spur/run/`), run by explicit path | `spur workflow validate`, `spur workflow run --dry-run`, a `spur workflow show` preview |
77
+ | project | `.spur/workflows/<name>.yaml` | The same gates |
78
+ | shared | the spur repository's shipped shared workflow layer (layer id `shared` in `spur workflow list --json`) as `<name>.yaml` | The same gates, **plus recorded operator consent and `build:bundle` parity** |
79
+
80
+ - `spur workflow validate --json` exits 1 on an error-level composition finding, so a definition
81
+ over a cap cannot climb. Warn-level findings do not block a step.
82
+ - Verify each step through the shared
83
+ [validate-and-dry-run](../spur-cli/references/workflows/operations.md#sub-procedure-validate-and-dry-run)
84
+ core. The shared step is a promotion, not a copy: record the operator consent that authorizes it,
85
+ then rebuild the bundle (`bun run --filter @gobing-ai/spur build:bundle`) so the shipped config
86
+ matches.
87
+ - In an adopting project the shared layer is the installed package and is read-only — the project
88
+ step is the tuning path there.
89
+
90
+ ## Composition budgets (ADR-115)
91
+
92
+ The consolidation and cache-window rules are taught once in
93
+ [workflow-fit-and-tuning.md](../spur-cli/references/workflows/workflow-fit-and-tuning.md#consolidation-and-cache-windows-adr-115)
94
+ and owned by the
95
+ [workflow composition contract](../../../../docs/design/workflow-composition-contract.md#composition-budgets-adr-115);
96
+ link them, never restate them. While composing or tuning a workflow, apply them with the ADR-115
97
+ budgets:
98
+
99
+ - **Merge adjacent model steps** only when they share a role and an executor **and** no gate, HITL
100
+ state or independence boundary sits between them.
101
+ - **Never merge an author step with the review or verify step that certifies it** — those keep
102
+ `freshSession: true`.
103
+ - **Run long deterministic work outside `agent.run`** — an in-step tool call that outlasts the
104
+ cache window idles the model and cold-rewrites the prefix.
105
+
106
+ A new model step in a shared workflow raises its `pipeline-budgets` `modelQueries`; that needs a
107
+ recorded decision before the shared step.
108
+
109
+ ## Rule tuning loop
110
+
111
+ Start from trace evidence, never from a guess:
112
+
113
+ 1. `spur rule trace <runId> --json` — read the per-rule `evaluations` findings and severities.
114
+ 2. Classify each hit: true positive, false positive, or noise.
115
+ 3. Tune with the [fine-tuning levers](../spur-cli/references/rules/fine-tuning.md) — severity,
116
+ glob scoping, exemptions, preset composition.
117
+ 4. `spur rule validate` on the tuned rule files.
118
+ 5. `spur rule run` on the affected inputs (constitution T11 — affected inputs, not a corpus sweep).
119
+ 6. Trace again and compare. A tuning with no trace pair behind it is a preference.
120
+
121
+ ## Applying doctor proposals
122
+
123
+ `sp:spur-doctor` ([../spur-doctor/SKILL.md](../spur-doctor/SKILL.md)) returns a proposal table;
124
+ the operator accepts rows; **this skill applies them**:
125
+
126
+ 1. For each accepted row, run its `apply` route — always the `spur` verb or ladder step named in
127
+ the row. Composer never invents a write route.
128
+ 2. Re-run that row's `verify` evidence and confirm it clears. An accepted row that cannot verify
129
+ is reported as not applied, never waved through.
130
+ 3. A `task` row carries the history-anatomy finding `key` in the task body — the existing handoff
131
+ route. Keep it.
132
+ 4. A row that changes a shared workflow goes through the ladder's shared step and its recorded
133
+ consent.
134
+
135
+ A caller that wants a record saves the accepted table under `docs/reports/`; this skill creates no
136
+ artifact store.
137
+
138
+ ## What this skill is not
139
+
140
+ - **Not the judge.** `sp:spur-doctor` evaluates artifacts and proposes; code review is
141
+ `sp:super-reviewer`.
142
+ - **Not a loop.** Recurring evolution loops and multi-agent coordination belong to
143
+ `sp:super-planner` or a workflow definition.
144
+ - **Not a catalog.** Verb, flag, output and exit semantics live in the `sp:spur-cli` references
145
+ linked above.
@@ -113,6 +113,20 @@ Any of the four may additionally carry a **bracket tag** in any position — `[d
113
113
  `Scenario: [advisory] Foo`. Tags are stripped before matching (0398 R7), so tagging never breaks
114
114
  the linkage.
115
115
 
116
+ Task-side, `verify-answer-lint` additionally accepts a fifth declared id source — a **bold-trajectory
117
+ paragraph**: a whole-line `**AC id…**` paragraph inside the task's `### Acceptance Criteria`
118
+ block (task 0817 R3). The id up to its first `:` and the paragraph's full spelling are both
119
+ declared; two bold spans on one line are not a declaration (an interpolated bold id stays
120
+ unmatchable):
121
+
122
+ ```markdown
123
+ ### Acceptance Criteria
124
+
125
+ **AC-0817-HERM-SKIP: unpinned project-config resolution is suppressed.**
126
+
127
+ | AC-0817-HERM-SKIP | MET | test | `tests/loader.test.ts:962` | ← declared
128
+ ```
129
+
116
130
  ### The id is exactly the scenario title — no Gherkin body appended
117
131
 
118
132
  An AC row id must be **exactly** the scenario title (plus any of the four forms above), with the
@@ -634,9 +634,9 @@ CLI-gated corpus artifact. The `wrapup-pipeline.yaml` `learning-capture` step wr
634
634
 
635
635
  - **Not CLI-gated.** The file is written directly by the wrap-up pipeline's `learning-capture`
636
636
  agent.run step. It does not go through `spur task update` or `spur feature update`.
637
- - **Not a validated corpus.** The file is a working scratchpad. High-value learnings are promoted
638
- to `docs/99_PROJECT_CONSTITUTION.md §8` (lessons) by the `doc-sync` step (via `sp:doc-evolve`),
639
- not by the learning-capture step itself.
637
+ - **Not a validated corpus.** The file is a working scratchpad. Deduplicate reusable lessons in
638
+ existing project learning/context storage. Constitution §8 routes lessons outside that file;
639
+ doc-sync does not promote lessons into governance without operator-authorized §6.8 scope.
640
640
  - **Append-only within a session.** New entries are appended; existing entries are not rewritten.
641
641
  - **Grouped by date and task.** Each entry has a date and task WBS header so the operator can
642
642
  trace a learning back to its source task.
@@ -128,6 +128,18 @@ silently incomplete (H6 shipped at 23/48 that way, with one verdict carrying an
128
128
  `acceptanceCriteria` array and still reading PASS). See `ac-style-guide.md` §
129
129
  "Verdict AC ↔ feature scenario linkage" for the id forms and evidence vocabulary.
130
130
 
131
+ **Parser contract (verify-answer-lint + `task verdict`, 0817 re-verify findings):**
132
+
133
+ 1. The requirement id cell must be the **bare** id — `| R1 | MET | … |`. Suffixes (`R1 (AC1)`) or
134
+ decoration (`**R1**`) fail the exact-match completeness check (`missing requirement row`).
135
+ 2. The AC table only opens when the header's **third** cell contains the word "evidence" — use
136
+ `| AC | Status | Evidence Type | Evidence |`. `| AC | Status | Type | Evidence |` silently
137
+ parses zero AC rows while lint still reports PASS.
138
+ 3. A behavioral AC marked `MET` with a non-executable evidence type (`static-ref`,
139
+ `manual-review`, `llm-judge`) is **downgraded to PARTIAL** by `task verdict`, making the whole
140
+ verdict PARTIAL. Use `test`/`command` (grep-based verification counts as `command`), or tag the
141
+ AC id `[non-behavior]`/`[advisory]` when executable evidence genuinely doesn't apply.
142
+
131
143
  **Invariant:** a force-done task has a non-empty `done_reason` naming the timeout, a verdict
132
144
  artifact whose AC rows cover every declared scenario, and a green lint/test run recorded in
133
145
  `## Testing`.
@@ -244,10 +244,52 @@ No token estimate, stage-size threshold, model heuristic, or configuration switc
244
244
  resolved absolute path, not the YAML's relative string, is what the dispatched agent is instructed
245
245
  to write and what post-join validation reads. Resolving once at the dispatch boundary fixes every
246
246
  surface at once; a relative path would resolve against whatever cwd the writer process happens to
247
- have. Send only: the stage id, the YAML's exact pure slash command, and
248
- `execution surface already resolved: native subagent; do not dispatch this stage again`. The WBS/path
249
- already carried by the slash command is the handoff — do not paste task/session transcripts or embed
250
- machine-specific session paths. Dispatch exactly one native subagent and wait for it; the inline FSM
247
+ have.
248
+
249
+ **Dispatch payload (task 0818 R2).** Send exactly these five fields. The earlier "send only the
250
+ stage id, the slash command, and the no-recursion notice" restriction is **deliberately replaced**:
251
+ the execution-tree cwd, the Spur invocation, and the output path are all already resolved at this
252
+ boundary, and a delegate left to re-derive them re-derives them against its own cwd and PATH.
253
+
254
+ 1. The stage id.
255
+ 2. The YAML's **exact** pure slash command — unchanged, never reformulated.
256
+ 3. `execution surface already resolved: native subagent; do not dispatch this stage again`.
257
+ 4. The **confirmed execution-tree cwd** (absolute) and the **resolved absolute Spur invocation** —
258
+ `vars.spurBin`, i.e. `resolveSpurBin()`'s `<runtime> <mainModule>` form
259
+ (`apps/cli/src/workflow/resolve-spur-bin.ts`). The delegate MUST run every Spur command through
260
+ that invocation and MUST NOT rely on a bare `spur`: a competing `spur` earlier on the delegate's
261
+ PATH otherwise wins. Setting `SPUR_BIN` alone does **not** change bare-command resolution — only
262
+ using the supplied invocation does. Spur-owned scripted calls take it through the existing
263
+ `--spur-bin` flag rather than a new mechanism.
264
+ 5. The **resolved absolute output path** (`answerFile`/`expectFile`, resolved as above) and the
265
+ **owning stage's artifact contract** — for a verify stage, the compact contract below.
266
+
267
+ Nothing else: no task/session transcripts, no machine-specific session paths. The WBS/path already
268
+ carried by the slash command remains the task handoff.
269
+
270
+ **Verify-stage artifact contract.** A verify handoff names
271
+ [`code-verification/references/verdict-schema.md`](../../code-verification/references/verdict-schema.md)
272
+ as the canonical answer schema and carries this compact form verbatim:
273
+
274
+ ```text
275
+ Verdict: PASS|PARTIAL|FAIL top-level, one line
276
+ | Req | Status | Evidence | Status = MET | PARTIAL | UNMET
277
+ (N/A and PASS are NOT valid requirement statuses)
278
+ | AC | Status | Evidence Type | Evidence | Status = MET | PARTIAL | UNMET | N/A (justified)
279
+ Evidence Type = test | command | static-ref | manual-review | llm-judge | n/a
280
+ AC rows use the task's exact AC identities (verbatim `Scenario:` titles / checklist text).
281
+ A behavioral AC marked MET requires executable evidence (test | command);
282
+ static-ref or llm-judge alone cannot carry it.
283
+ ```
284
+
285
+ **Review-stage artifact contract.** A review handoff carries the Review output contract owned by
286
+ `plugins/sp/agents/super-reviewer.md` — native `P1 (blocker)` / `P2 (major)` / `P3 (minor)` /
287
+ `P4 (advisory)` priority cells and section-relative headings — **not** the verify answer schema.
288
+
289
+ This is an invocation and handoff fix, not a runtime PATH-injection subsystem: it makes no guarantee
290
+ about arbitrary bare commands in host shells or agent-generated shells.
291
+
292
+ Dispatch exactly one native subagent and wait for it; the inline FSM
251
293
  must not advance actions or guards concurrently (one writer at a time). After join, validate
252
294
  `answerFile`, `expectFile`, `requireDiff`, task scope, and the action's error policy from the shared
253
295
  filesystem — a subagent success message is not evidence. On success append exactly:
@@ -270,6 +270,30 @@ missing title match. After batch creation, `handoff-finalize`:
270
270
  (runall is then omitted), otherwise `/sp:dev-runall --feature <id> --auto`. The terminal
271
271
  handoff note points at this report.
272
272
 
273
+ **Ready preparation (ready-prepare, 0788).** The input is the `.wbs` array in
274
+ `.spur/run/<runId>-idea-batch-create-result.json`. For EACH wbs: resolve the task file with
275
+ `spur task path <wbs> --json` and apply the ready-refinement checklist — make requirements,
276
+ design, plan, acceptance criteria, decisions, dependencies and premises present and
277
+ non-placeholder so `spur task check <wbs> --json` exits 0. Write planning sections only, through
278
+ `spur task update <wbs> --section <Name> --from-file <file>` — never Solution, Testing, Review
279
+ or History. Record one checklist row per id, with concrete evidence of how you verified it.
280
+ Compute the planning digest with the project's own implementation when this is a monorepo
281
+ checkout — resolve the file with `spur task path <wbs> --json`, then run:
282
+
283
+ ```bash
284
+ bun -e 'const m = await import("./packages/app/src/services/task-readiness"); console.log(m.computePlanningDigest(await Bun.file(process.argv[1]).text()))' <task-file>
285
+ ```
286
+
287
+ When that is impossible in this checkout, set status `skipped` instead of guessing a digest.
288
+ Finally write `.spur/run/<runId>-idea-ready.json` with exactly this shape:
289
+
290
+ ```json
291
+ {"runId":"<runId>","depth":"ready","tasks":[{"wbs":"<wbs>","status":"ready" | "failed" | "skipped","planningDigest":"<sha256 hex>","checks":[{"id":"requirements" | "design" | "plan" | "ac" | "decisions" | "dependencies" | "premises","pass":true,"evidence":"<how verified>"}]}]}
292
+ ```
293
+
294
+ A task you cannot fully prepare gets status `failed` or `skipped` — never fabricate evidence;
295
+ the handoff degrades to refineall.
296
+
273
297
  ## Step 6: Refine before execute (the spec-completion gate)
274
298
 
275
299
  `batch-create` accepts optional `design` / `plan` / `acceptance_criteria` fields (plus
@@ -0,0 +1,138 @@
1
+ ---
2
+ name: spur-doctor
3
+ description: "Evaluate spur artifacts from read-only CLI evidence — tasks, features, rules, workflows, agent specs — reflect over sp:history-anatomy findings, and return a proposal table. Diagnoses spur artifacts, not runtime environments (that is spur agent doctor). Triggers: check artifact health, propose evolution, reflect over history findings."
4
+ license: Apache-2.0
5
+ version: 1.0.0
6
+ metadata:
7
+ author: spur
8
+ platforms: "claude-code,codex,openclaw,opencode,antigravity,pi"
9
+ category: artifact-composition
10
+ interactions:
11
+ - reviewer
12
+ - inversion
13
+ operations:
14
+ - evaluate
15
+ - reflect
16
+ - propose
17
+ openclaw:
18
+ emoji: "🔬"
19
+ see_also:
20
+ - sp:spur-cli
21
+ - sp:spur-composer
22
+ - sp:history-anatomy
23
+ - sp:super-planner
24
+ ---
25
+
26
+ # sp:spur-doctor — evaluate spur artifacts and propose changes
27
+
28
+ One cross-noun method (ADR-114, [spur artifact evolution](../../../../docs/design/spur-artifact-evolution.md)
29
+ §2): gather **read-only CLI evidence** about tasks, features, rules, workflows and agent specs,
30
+ **reflect** over `sp:history-anatomy` findings, and return a **proposal table**. It diagnoses spur
31
+ **artifacts** — definitions, rules, corpus records — not runtime environments: whether an agent
32
+ binary, host session or tool install is healthy is `spur agent doctor`'s job, not this skill's.
33
+
34
+ ## Read-only invariant
35
+
36
+ The doctor **writes nothing and names no mutating verb**. It performs no task, feature, rule or
37
+ workflow write — the operator accepts rows and `sp:spur-composer`
38
+ ([../spur-composer/SKILL.md](../spur-composer/SKILL.md)) applies them. A caller that wants a
39
+ record saves the returned table under `docs/reports/`; the doctor creates no artifact store.
40
+
41
+ - **History enters only through `sp:history-anatomy` findings.** Raw history records stay out
42
+ of scope and are never re-interpreted here; history-anatomy is the only history interpreter.
43
+ - **Recurring reflection loops and coordination go to `sp:super-planner`** or a workflow — one
44
+ bounded evaluation pass per invocation.
45
+ - **Forbidden surfaces: `spur team` and `spur agent loop`.** Agent specs are read only through
46
+ `spur agent list --specs --json`.
47
+
48
+ ## Evidence per noun
49
+
50
+ | Noun | Evidence (read-only) |
51
+ | --- | --- |
52
+ | task | `spur task check <wbs> --json` |
53
+ | feature | `spur feature check <id> --json` |
54
+ | rule | `spur rule trace --json`, `spur rule validate` |
55
+ | workflow | `spur workflow validate --json` (findings by `level`), `node "$(superskill script path sp workflow-step-profile.mjs)" <workflow> --json` |
56
+ | agent spec | `spur agent list --specs --json`, read and written through `spur agent` with `--specs`, never `spur team` |
57
+ | history | A `sp:history-anatomy` report ([../history-anatomy/SKILL.md](../history-anatomy/SKILL.md)), never raw history records |
58
+
59
+ Every row of a proposal cites the evidence it rests on. No anchor, no proposal.
60
+
61
+ ## Workflow step profile and cache-window flags
62
+
63
+ The step profile (`plugins/sp/scripts/workflow-step-profile`, ADR-065 plugin entrypoint) reads
64
+ `spur workflow trace` for a workflow's last N completed, non-dry runs. Per node and action kind it
65
+ reports run count, executions, p50 and max `durationMs`, p50 idle gap before the step, session mode
66
+ (`fresh`, `resumed` or `mixed`) and `cacheHit` p50 with its coverage — satellite §10 step evidence.
67
+
68
+ ```bash
69
+ node "$(superskill script path sp workflow-step-profile.mjs)" <workflow> --json
70
+ ```
71
+
72
+ `W` is the cache window, **300** seconds by default (satellite §10). The script computes every flag
73
+ arithmetically; doctor maps the flag ids to proposals and never re-derives numbers from prose. Each
74
+ flag and each composition finding becomes one proposal row with action class **workflow
75
+ optimization**, and the change comes from the §10 table:
76
+
77
+ | Evidence | Flag | Proposed change |
78
+ | --- | --- | --- |
79
+ | Validate finding, `level: error` | always | Extract to an owner from the closed fix vocabulary |
80
+ | Validate finding, `level: warn` | always | Extract, or record a stays-shell reason inside the warn band |
81
+ | Deterministic step | `step-over-window` — p50 > W | Split it, or move the slow work out of the step |
82
+ | Resumed `agent.run` | `resume-after-idle` — p50 idle gap before it > W | `freshSession: true` with the prior artifact as handoff |
83
+ | Resumed `agent.run` | `resume-cold-cache` — `cacheHit` p50 < 0.5, with evidence | The same, or move a long in-step tool call to a deterministic step |
84
+ | `agent.run` | `agent-run-over-2w` — p50 > 2W | Split at an artifact seam, or no-op when none exists |
85
+
86
+ - The two validate finding rows classify by `level` alone and carry no flag id.
87
+ - A row with `cacheHit.known: 0` raises no cache flag. Its cache evidence is **unknown, never a zero
88
+ hit rate**, and doctor reports it as unknown rather than as a 0% hit.
89
+ - A proposal that changes a shared workflow goes through §7 of the composition ladder
90
+ ([spur-composer](../spur-composer/SKILL.md)), including its recorded operator consent.
91
+
92
+ ## Reflection map over history findings
93
+
94
+ For each history-anatomy finding (`key`, `category`, `trend`, `ownerSurface`), assign **exactly
95
+ one** action class. The first matching row wins:
96
+
97
+ | # | Finding | Action class |
98
+ | --- | --- | --- |
99
+ | 1 | `trend` is `resolved` or `improved` | no-op |
100
+ | 2 | `category` is `positive` | doc or learning |
101
+ | 3 | Automatable, per step 1 of the [placement rule](../../references/environment-lens.md#placement-rule) | rule candidate |
102
+ | 4 | `ownerSurface` is a workflow definition | workflow optimization |
103
+ | 5 | `ownerSurface` is a doc, skill, reference or steering file | doc or learning |
104
+ | 6 | Anything else | task |
105
+
106
+ The five action classes are closed: **task**, **rule candidate**, **workflow optimization**,
107
+ **doc or learning**, **no-op**. The doctor classifies the report's findings and never derives new
108
+ ones from raw records — that would make it a second history interpreter.
109
+
110
+ ## Proposal table
111
+
112
+ Return one row per actionable finding, with exactly these columns:
113
+
114
+ | Column | Content |
115
+ | --- | --- |
116
+ | `key` | The finding key, or `<noun>:<id>:<check>` for an artifact finding |
117
+ | `evidence` | The CLI output or report section the row rests on |
118
+ | `action` | One action class from the reflection map (or the per-noun evaluation) |
119
+ | `change` | The proposed change, in one line |
120
+ | `apply` | The `spur` verb or composer procedure that lands it |
121
+ | `verify` | The evidence to re-run after applying |
122
+
123
+ Rules:
124
+
125
+ - The `apply` route is always a `spur` verb or a gated composer step — never a raw file edit this
126
+ skill performs. Shared-workflow rows route through the composition ladder's shared step.
127
+ - A `task` row carries the finding `key` in the task body (the history-anatomy handoff route).
128
+ - Rows are proposals only. No applied change, diff, or command output claimed as run.
129
+
130
+ ## What this skill is not
131
+
132
+ - **Not the applier.** `sp:spur-composer` applies accepted rows; this skill performs no
133
+ task/feature/rule/workflow write.
134
+ - **Not a runtime doctor.** Environment, binary and session readiness belong to
135
+ `spur agent doctor`; this skill diagnoses spur artifacts from CLI evidence.
136
+ - **Not a history interpreter.** Findings come from `sp:history-anatomy` reports, never from raw
137
+ history records.
138
+ - **Not a loop.** Recurring evolution passes belong to `sp:super-planner` or a workflow.
@@ -0,0 +1,43 @@
1
+ # taste-refactoring-api
2
+
3
+ A reusable agent skill for designing, reviewing, and safely refactoring production APIs.
4
+
5
+ ## What it covers
6
+
7
+ - REST/HTTP
8
+ - RPC/gRPC
9
+ - GraphQL
10
+ - events/webhooks
11
+ - domain/resource modeling
12
+ - naming and schemas
13
+ - errors
14
+ - pagination/filtering/sorting
15
+ - idempotency and retries
16
+ - concurrency
17
+ - versioning/deprecation/migration
18
+ - API security
19
+ - observability
20
+ - reliability/performance
21
+ - contract testing and documentation
22
+
23
+ ## Suggested installation
24
+
25
+ Install/copy this directory as an agent skill named `taste-refactoring-api` and load `SKILL.md` as the skill instructions. Keep the `references`, `checklists`, and `examples` directories available for deeper reviews.
26
+
27
+ ## Daily usage examples
28
+
29
+ - “Use taste-refactoring-api to review this OpenAPI spec.”
30
+ - “Refactor these Express routes without breaking current clients.”
31
+ - “Review this GraphQL schema for compatibility and developer experience.”
32
+ - “Design a safe pagination and filtering contract for this endpoint.”
33
+ - “Create a migration plan from v1 to v2 with no abrupt client breakage.”
34
+ - “Run the daily API quality checklist on this PR.”
35
+
36
+ ## Files
37
+
38
+ - `SKILL.md` — main agent operating instructions
39
+ - `references/api-refactoring-playbook.md` — deeper operational guidance
40
+ - `references/research-basis.md` — standards and sources used to build the skill
41
+ - `checklists/daily-api-review.md` — fast daily checklist
42
+ - `examples/review-template.md` — reusable review format
43
+ - `examples/refactor-example.md` — worked refactoring example