@gobing-ai/spur 0.4.8 → 0.4.10

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 (211) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/pipeline-budgets.json +2 -2
  3. package/config/rules/README.md +1 -1
  4. package/config/rules/boundary/config-loading-ownership.yaml +1 -0
  5. package/config/rules/boundary/env-var-hygiene.yaml +0 -1
  6. package/config/rules/boundary/sp-plugin-standalone.yaml +1 -1
  7. package/config/rules/boundary/sp-script-placement.yaml +3 -3
  8. package/config/rules/docs/sourced-api-claims.yaml +29 -64
  9. package/config/rules/strict/runtime-boundaries.yaml +40 -1
  10. package/config/rules/structure/protected-files.yaml +1 -1
  11. package/config/rules/surface/check-cli-surface.yaml +33 -0
  12. package/config/rules/typescript/no-debugger.yaml +3 -0
  13. package/config/workflow-candidates.json +2 -2
  14. package/config/workflows/feature-verification.yaml +6 -19
  15. package/config/workflows/history-anatomy.yaml +14 -28
  16. package/config/workflows/idea-pipeline.yaml +6 -19
  17. package/config/workflows/pr-review.yaml +9 -16
  18. package/config/workflows/task-pipeline.yaml +18 -25
  19. package/config/workflows/wrapup-pipeline.yaml +21 -63
  20. package/package.json +3 -3
  21. package/plugins/sp/README.md +70 -37
  22. package/plugins/sp/agents/expert-spur.md +0 -1
  23. package/plugins/sp/agents/super-planner.md +5 -5
  24. package/plugins/sp/agents/super-reviewer.md +2 -2
  25. package/plugins/sp/commands/dev-changelog.md +1 -1
  26. package/plugins/sp/commands/dev-daily.md +1 -1
  27. package/plugins/sp/commands/dev-pr-review.md +1 -1
  28. package/plugins/sp/commands/dev-review-session.md +1 -1
  29. package/plugins/sp/commands/dev-runall.md +4 -4
  30. package/plugins/sp/commands/dev-verify.md +4 -6
  31. package/plugins/sp/commands/dev-verifyall.md +4 -5
  32. package/plugins/sp/hooks/hooks.json +11 -1
  33. package/plugins/sp/lib/context-post-tool.ts +1 -1
  34. package/plugins/sp/lib/context-session-start.ts +1 -1
  35. package/plugins/sp/lib/context-session-stop.ts +1 -1
  36. package/plugins/sp/lib/destructive-policy.ts +65 -1
  37. package/plugins/sp/plugin.json +2 -5
  38. package/plugins/sp/{hooks → scripts/hooks}/agent-lifecycle.ts +1 -1
  39. package/plugins/sp/scripts/hooks/careful-guard.ts +94 -0
  40. package/plugins/sp/{hooks → scripts/hooks}/context-post-tool.ts +2 -2
  41. package/plugins/sp/{hooks → scripts/hooks}/context-session-start.ts +1 -1
  42. package/plugins/sp/{hooks → scripts/hooks}/context-session-stop.ts +1 -1
  43. package/plugins/sp/{hooks → scripts/hooks}/fleet-guest-stop.ts +6 -4
  44. package/plugins/sp/{hooks → scripts/hooks}/task-write-guard.ts +38 -21
  45. package/plugins/sp/skills/brainstorm/SKILL.md +12 -11
  46. package/plugins/sp/skills/brainstorm/agents/openai.yaml +1 -1
  47. package/plugins/sp/skills/brainstorm/examples/ideation-example.md +0 -4
  48. package/plugins/sp/skills/brainstorm/metadata.openclaw +1 -1
  49. package/plugins/sp/skills/brainstorm/references/workflows.md +4 -14
  50. package/plugins/sp/skills/code-implementation/SKILL.md +1 -1
  51. package/plugins/sp/skills/code-verification/SKILL.md +8 -8
  52. package/plugins/sp/skills/code-verification/references/secu-review.md +4 -4
  53. package/plugins/sp/skills/code-verification/references/verdict-schema.md +9 -1
  54. package/plugins/sp/skills/daily-summary/SKILL.md +4 -5
  55. package/plugins/sp/skills/dogfood-testing/SKILL.md +9 -9
  56. package/plugins/sp/skills/dogfood-testing/references/report-template.md +1 -1
  57. package/plugins/sp/skills/history-anatomy/references/modes.md +2 -2
  58. package/plugins/sp/skills/history-anatomy/references/operations.md +3 -4
  59. package/plugins/sp/skills/history-anatomy/references/report-contract.md +2 -3
  60. package/plugins/sp/skills/issue-finding/SKILL.md +1 -1
  61. package/plugins/sp/skills/next-router/references/routing-table.md +1 -1
  62. package/plugins/sp/skills/parallel-execution/SKILL.md +2 -2
  63. package/plugins/sp/skills/parallel-execution/references/result-synthesis.md +9 -10
  64. package/plugins/sp/skills/pr-reviewing/SKILL.md +14 -15
  65. package/plugins/sp/skills/reverse-engineering/SKILL.md +4 -6
  66. package/plugins/sp/skills/session-review/SKILL.md +13 -29
  67. package/plugins/sp/skills/source-driven-development/SKILL.md +26 -27
  68. package/plugins/sp/skills/spur-check/SKILL.md +14 -13
  69. package/plugins/sp/skills/spur-cli/SKILL.md +1 -1
  70. package/plugins/sp/skills/spur-cli/references/agent.md +17 -2
  71. package/plugins/sp/skills/spur-cli/references/builder.md +27 -6
  72. package/plugins/sp/skills/spur-cli/references/features.md +6 -1
  73. package/plugins/sp/skills/spur-cli/references/history.md +3 -0
  74. package/plugins/sp/skills/spur-cli/references/self.md +5 -3
  75. package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +3 -0
  76. package/plugins/sp/skills/spur-cli/references/tasks.md +13 -3
  77. package/plugins/sp/skills/spur-cli/references/workflows/authoring-workflows.md +1 -1
  78. package/plugins/sp/skills/spur-cli/references/workflows.md +36 -1
  79. package/plugins/sp/skills/spur-dev/SKILL.md +1 -1
  80. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +1 -1
  81. package/plugins/sp/skills/spur-dev/references/dev-operations.md +12 -13
  82. package/plugins/sp/skills/spur-dev/references/execution-batch-report.md +10 -11
  83. package/plugins/sp/skills/spur-dev/references/execution-batch.md +16 -17
  84. package/plugins/sp/skills/spur-dev/references/execution-parallel-isolation.md +1 -1
  85. package/plugins/sp/skills/spur-dev/references/execution-worktree-landing.md +9 -12
  86. package/plugins/sp/skills/spur-dev/references/execution-worktree-setup.md +6 -8
  87. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +1 -1
  88. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +33 -40
  89. package/plugins/sp/skills/spur-dev/references/structured-trace-emission.md +24 -24
  90. package/plugins/sp/skills/spur-doctor/SKILL.md +5 -4
  91. package/spur.js +12726 -1456
  92. package/web/_astro/{BoardApp.CaNvQBD_.js → BoardApp.B5rTVNd_.js} +1 -1
  93. package/web/_astro/{BoardApp.C5jnkkKP.js → BoardApp.BMprmPRc.js} +141 -141
  94. package/web/_astro/{TaskDetail.DGKndhI8.js → TaskDetail.Ddsur8qd.js} +1 -1
  95. package/web/_astro/{arc.DHrwdg3G.js → arc.DLqVVBxP.js} +1 -1
  96. package/web/_astro/{architectureDiagram-3BPJPVTR.pvKpK1s5.js → architectureDiagram-3BPJPVTR.C-Pk3uAi.js} +1 -1
  97. package/web/_astro/{blockDiagram-GPEHLZMM.BQmRcZsS.js → blockDiagram-GPEHLZMM.BRO1i_Nm.js} +1 -1
  98. package/web/_astro/{c4Diagram-AAUBKEIU.CCLjHeH1.js → c4Diagram-AAUBKEIU.BU_cWu6e.js} +1 -1
  99. package/web/_astro/channel.Bs3Illhy.js +1 -0
  100. package/web/_astro/{chunk-2J33WTMH.DL6Yuoma.js → chunk-2J33WTMH.D2VXiQ2t.js} +1 -1
  101. package/web/_astro/{chunk-4BX2VUAB.CzlyEI7l.js → chunk-4BX2VUAB.BcHT772J.js} +1 -1
  102. package/web/_astro/{chunk-55IACEB6.B60EWxp1.js → chunk-55IACEB6.DhDtICmo.js} +1 -1
  103. package/web/_astro/{chunk-727SXJPM.c7v_fRLo.js → chunk-727SXJPM.BoKHp7gV.js} +1 -1
  104. package/web/_astro/{chunk-AQP2D5EJ.8BxLWdDc.js → chunk-AQP2D5EJ.Chu4JRpE.js} +1 -1
  105. package/web/_astro/{chunk-FMBD7UC4.DmKuxGFT.js → chunk-FMBD7UC4.wHdwKPlq.js} +1 -1
  106. package/web/_astro/{chunk-ND2GUHAM.1Zwd4mqV.js → chunk-ND2GUHAM.ffN-M1JB.js} +1 -1
  107. package/web/_astro/{chunk-QZHKN3VN.BvYLu-A1.js → chunk-QZHKN3VN.FRubwg4S.js} +1 -1
  108. package/web/_astro/{classDiagram-4FO5ZUOK.CEqRt0WU.js → classDiagram-4FO5ZUOK.c22tQsc_.js} +1 -1
  109. package/web/_astro/{classDiagram-v2-Q7XG4LA2.CEqRt0WU.js → classDiagram-v2-Q7XG4LA2.c22tQsc_.js} +1 -1
  110. package/web/_astro/{cose-bilkent-S5V4N54A.C7JiUdj2.js → cose-bilkent-S5V4N54A.B9c6fiSj.js} +1 -1
  111. package/web/_astro/{cynefin-OW5HDTMX.B6mZ-1be.js → cynefin-OW5HDTMX.DrZsrUHl.js} +1 -1
  112. package/web/_astro/{dagre-BM42HDAG.BuryfDy6.js → dagre-BM42HDAG.DG1U4b3y.js} +1 -1
  113. package/web/_astro/{diagram-2AECGRRQ.dao39YQM.js → diagram-2AECGRRQ.CH15b-K3.js} +1 -1
  114. package/web/_astro/{diagram-5GNKFQAL.lnGZe4At.js → diagram-5GNKFQAL.BH1j7twR.js} +1 -1
  115. package/web/_astro/{diagram-KO2AKTUF.uWfhzEfT.js → diagram-KO2AKTUF.q2zCkbAj.js} +1 -1
  116. package/web/_astro/{diagram-LMA3HP47.ppq8-198.js → diagram-LMA3HP47.BLaaZnHV.js} +1 -1
  117. package/web/_astro/{diagram-OG6HWLK6.CKSCqDt5.js → diagram-OG6HWLK6.BcpRdQwI.js} +1 -1
  118. package/web/_astro/{erDiagram-TEJ5UH35.sFSf2yBN.js → erDiagram-TEJ5UH35.D7KBlqfM.js} +1 -1
  119. package/web/_astro/{flowDiagram-I6XJVG4X.BJQjKLbz.js → flowDiagram-I6XJVG4X.D_gmuRqg.js} +1 -1
  120. package/web/_astro/{ganttDiagram-6RSMTGT7.DAHKNj2N.js → ganttDiagram-6RSMTGT7.DzgWYniD.js} +1 -1
  121. package/web/_astro/{gitGraphDiagram-PVQCEYII.BlmzcW_O.js → gitGraphDiagram-PVQCEYII.576i3hm3.js} +1 -1
  122. package/web/_astro/index.DiC1a6lh.css +1 -0
  123. package/web/_astro/{infoDiagram-5YYISTIA.DGhjaqsi.js → infoDiagram-5YYISTIA.DMCclBiz.js} +1 -1
  124. package/web/_astro/{ishikawaDiagram-YF4QCWOH.gKIpgt6F.js → ishikawaDiagram-YF4QCWOH.9Kyca4SH.js} +1 -1
  125. package/web/_astro/{journeyDiagram-JHISSGLW.DG3tmP0R.js → journeyDiagram-JHISSGLW.chbdG-8q.js} +1 -1
  126. package/web/_astro/{kanban-definition-UN3LZRKU.CgHDSxkR.js → kanban-definition-UN3LZRKU.Bds54-e0.js} +1 -1
  127. package/web/_astro/{linear.BuGEpcuM.js → linear.D5ND9GN_.js} +1 -1
  128. package/web/_astro/{mermaid.core.DBVqkWBp.js → mermaid.core.D9N_PGbj.js} +4 -4
  129. package/web/_astro/{mindmap-definition-RKZ34NQL.D-kOcji9.js → mindmap-definition-RKZ34NQL.t0xop5vp.js} +1 -1
  130. package/web/_astro/{pieDiagram-4H26LBE5.BvGPwtZt.js → pieDiagram-4H26LBE5.DqgKh6hM.js} +1 -1
  131. package/web/_astro/{quadrantDiagram-W4KKPZXB.BKb_9FV6.js → quadrantDiagram-W4KKPZXB.DeuHVi2t.js} +1 -1
  132. package/web/_astro/{requirementDiagram-4Y6WPE33.Cx0fvD8v.js → requirementDiagram-4Y6WPE33.BdYFSG4W.js} +1 -1
  133. package/web/_astro/{sankeyDiagram-5OEKKPKP.fatULi0W.js → sankeyDiagram-5OEKKPKP.k1LPPETJ.js} +1 -1
  134. package/web/_astro/{sequenceDiagram-3UESZ5HK.ChHyKqco.js → sequenceDiagram-3UESZ5HK.DdyfpzoG.js} +1 -1
  135. package/web/_astro/{stateDiagram-AJRCARHV.BdUpKWyj.js → stateDiagram-AJRCARHV.DSEI8il0.js} +1 -1
  136. package/web/_astro/{stateDiagram-v2-BHNVJYJU.fmJxqIm5.js → stateDiagram-v2-BHNVJYJU.CoMnQRKo.js} +1 -1
  137. package/web/_astro/{timeline-definition-PNZ67QCA.BayDn5-V.js → timeline-definition-PNZ67QCA.DM1AHNm-.js} +1 -1
  138. package/web/_astro/{vennDiagram-CIIHVFJN.Bm2Aggwa.js → vennDiagram-CIIHVFJN.C-cJmVtl.js} +1 -1
  139. package/web/_astro/{wardleyDiagram-YWT4CUSO.DI75O-uG.js → wardleyDiagram-YWT4CUSO.D0xMzKPb.js} +1 -1
  140. package/web/_astro/{xychartDiagram-2RQKCTM6.DL90E7Q7.js → xychartDiagram-2RQKCTM6.BH5xJcEq.js} +1 -1
  141. package/web/index.html +2 -2
  142. package/config/plugin-scripts.json +0 -116
  143. package/config/script-placement-baseline.json +0 -33
  144. package/plugins/sp/hooks/careful-guard.ts +0 -74
  145. package/plugins/sp/hooks/pi/guard-extension.ts +0 -304
  146. package/plugins/sp/lib/dogfood-pipeline.ts +0 -265
  147. package/plugins/sp/lib/dogfood-report.ts +0 -278
  148. package/plugins/sp/lib/history-anatomy.generated.d.mts +0 -112
  149. package/plugins/sp/lib/history-anatomy.generated.mjs +0 -691
  150. package/plugins/sp/lib/idea-handoff.generated.d.mts +0 -17
  151. package/plugins/sp/lib/idea-handoff.generated.mjs +0 -1446
  152. package/plugins/sp/lib/inline-run-app.ts +0 -68
  153. package/plugins/sp/lib/inline-run.generated.d.mts +0 -37
  154. package/plugins/sp/lib/inline-run.generated.mjs +0 -3103
  155. package/plugins/sp/lib/plan-projection.generated.d.mts +0 -197
  156. package/plugins/sp/lib/plan-projection.generated.mjs +0 -982
  157. package/plugins/sp/lib/quality-gate.generated.d.mts +0 -139
  158. package/plugins/sp/lib/quality-gate.generated.mjs +0 -30510
  159. package/plugins/sp/lib/residual-scan.generated.d.mts +0 -93
  160. package/plugins/sp/lib/residual-scan.generated.mjs +0 -383
  161. package/plugins/sp/lib/run-summary-core.ts +0 -225
  162. package/plugins/sp/lib/spur-bin.ts +0 -36
  163. package/plugins/sp/lib/step-profile.generated.d.mts +0 -71
  164. package/plugins/sp/lib/step-profile.generated.mjs +0 -174
  165. package/plugins/sp/lib/transcript.ts +0 -112
  166. package/plugins/sp/scripts/batch-plan.mjs +0 -1096
  167. package/plugins/sp/scripts/batch-plan.ts +0 -145
  168. package/plugins/sp/scripts/batch-preflight.mjs +0 -423
  169. package/plugins/sp/scripts/batch-preflight.ts +0 -270
  170. package/plugins/sp/scripts/commit-guard.mjs +0 -226
  171. package/plugins/sp/scripts/commit-guard.ts +0 -248
  172. package/plugins/sp/scripts/daily-summary/daily-summary.mjs +0 -626
  173. package/plugins/sp/scripts/daily-summary/daily-summary.ts +0 -855
  174. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.mjs +0 -211
  175. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts +0 -110
  176. package/plugins/sp/scripts/dogfood-testing/validate-report.mjs +0 -282
  177. package/plugins/sp/scripts/dogfood-testing/validate-report.ts +0 -98
  178. package/plugins/sp/scripts/feature-verification-steps.mjs +0 -82
  179. package/plugins/sp/scripts/feature-verification-steps.ts +0 -164
  180. package/plugins/sp/scripts/history-anatomy-cache.mjs +0 -931
  181. package/plugins/sp/scripts/history-anatomy-cache.ts +0 -247
  182. package/plugins/sp/scripts/idea-handoff.mjs +0 -32
  183. package/plugins/sp/scripts/idea-handoff.ts +0 -47
  184. package/plugins/sp/scripts/inline-run-dispatch.mjs +0 -131
  185. package/plugins/sp/scripts/inline-run-dispatch.ts +0 -115
  186. package/plugins/sp/scripts/inline-run-setup.mjs +0 -746
  187. package/plugins/sp/scripts/inline-run-setup.ts +0 -198
  188. package/plugins/sp/scripts/persist-out-check.mjs +0 -217
  189. package/plugins/sp/scripts/persist-out-check.ts +0 -249
  190. package/plugins/sp/scripts/pr-reviewing.mjs +0 -712
  191. package/plugins/sp/scripts/pr-reviewing.ts +0 -952
  192. package/plugins/sp/scripts/quality-gate.mjs +0 -30491
  193. package/plugins/sp/scripts/quality-gate.ts +0 -80
  194. package/plugins/sp/scripts/residual-scan.mjs +0 -634
  195. package/plugins/sp/scripts/residual-scan.ts +0 -248
  196. package/plugins/sp/scripts/run-summary.mjs +0 -758
  197. package/plugins/sp/scripts/run-summary.ts +0 -107
  198. package/plugins/sp/scripts/script-root.mjs +0 -129
  199. package/plugins/sp/scripts/script-root.ts +0 -199
  200. package/plugins/sp/scripts/session-timeline.mjs +0 -359
  201. package/plugins/sp/scripts/session-timeline.ts +0 -190
  202. package/plugins/sp/scripts/task-diffstat.mjs +0 -181
  203. package/plugins/sp/scripts/task-diffstat.ts +0 -219
  204. package/plugins/sp/scripts/workflow-step-profile.mjs +0 -338
  205. package/plugins/sp/scripts/workflow-step-profile.ts +0 -165
  206. package/plugins/sp/scripts/wrapup-drift-probe.mjs +0 -190
  207. package/plugins/sp/scripts/wrapup-drift-probe.ts +0 -261
  208. package/plugins/sp/scripts/wrapup-steps.mjs +0 -627
  209. package/plugins/sp/scripts/wrapup-steps.ts +0 -891
  210. package/web/_astro/channel.C7wG9RxA.js +0 -1
  211. package/web/_astro/index.BCY1JJHd.css +0 -1
@@ -88,12 +88,6 @@ states:
88
88
  handoff — no task execution. Soft agent doctor (status file) so doctor red
89
89
  routes to `failed` via transitions instead of a raw lifecycle abort.
90
90
  onEnter:
91
- # 0960 R2: run-start script-resolution identity — record which tree this run
92
- # resolved (source-repo vs installed) before any step executes. Never aborts.
93
- - kind: shell
94
- options:
95
- command: >-
96
- S=plugins/sp/scripts/script-root.ts; [ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp script-root.mjs 2>/dev/null)"; RUNNER=bun; case "$S" in *.mjs) RUNNER=node ;; esac; [ -f "$S" ] && "$RUNNER" "$S" --run-id "$__runId" --spur-bin "$spurBin" || echo "script-root failed closed — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; exit 0
97
91
  - kind: note
98
92
  options:
99
93
  message: "Idea pipeline start for idea: ${vars.idea}"
@@ -606,21 +600,14 @@ states:
606
600
  A mapping or CLI error fails the run before terminal handoff; an unready
607
601
  task is a successful planning outcome recorded as a refineall recommendation.
608
602
  onEnter:
609
- # (d) idea-handoff owns finalization (0824): the bundled finalizeIdeaHandoff
610
- # capability runs from the monorepo checkout first; seeded projects (no
611
- # packages/, no plugins/) resolve the registered idea-handoff.mjs twin under
612
- # bare node; neither present fails closed (exit 1) instead of silently
613
- # skipping finalization. The zip/deps/refresh/check/report contract itself is
614
- # pinned by finalizeIdeaHandoff unit tests, not by this file.
603
+ # (d) `spur feature handoff` owns finalization (0824; script-absorption PR-5
604
+ # retired the idea-handoff plugin script and its bundle). A nonzero exit fails
605
+ # the run (fail closed) instead of silently skipping finalization. The
606
+ # zip/deps/refresh/check/report contract itself is pinned by
607
+ # finalizeIdeaHandoff unit tests, not by this file.
615
608
  - kind: shell
616
609
  options:
617
- command: >-
618
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/idea-handoff.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/idea-handoff.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then
619
- "$RUNNER" "$S";
620
- else
621
- echo "idea handoff failed closed — idea-handoff script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2;
622
- exit 1;
623
- fi
610
+ command: '$spurBin feature handoff "$featureId" --run-id "$__runId" --no-logo'
624
611
  - id: handoff
625
612
  description: >
626
613
  Terminal — idea pipeline complete. Ordering applied, roster refreshed, and
@@ -8,7 +8,7 @@
8
8
  # never a raw lifecycle abort — same reliability contract as basic.yaml)
9
9
  #
10
10
  # This YAML is the SSOT for the review spine's state order and guards. Every state shells
11
- # out to the staged pr-reviewing.ts entrypoint (the tested deterministic core); no gh/git
11
+ # out to `spur builder pr` (the tested deterministic core); no gh/git
12
12
  # logic lives in this file. All model-bearing work — finding triage, `fix` mode, `rules`
13
13
  # mode — stays in the sp:pr-reviewing skill and never enters this machine.
14
14
  #
@@ -66,14 +66,7 @@ states:
66
66
  before any push can publish it).
67
67
  Writes PASS|FAIL to .spur/run/${vars.__runId}-pr-preflight.status; always exit 0.
68
68
  onEnter:
69
- # 1007 R8: run-start script-resolution identity (same command as feature-verification
70
- # verify's first action) — records which tree this run resolved (source-repo vs
71
- # installed) into .spur/run/$__runId-script-root.json; later plugin-script actions
72
- # resolve through it (1007 R4 snippet). Never aborts.
73
- - kind: shell
74
- options:
75
- command: >-
76
- S=plugins/sp/scripts/script-root.ts; [ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp script-root.mjs 2>/dev/null)"; RUNNER=bun; case "$S" in *.mjs) RUNNER=node ;; esac; [ -f "$S" ] && "$RUNNER" "$S" --run-id "$__runId" --spur-bin "$spurBin" || echo "script-root failed closed — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; exit 0
69
+ # script-root retired for this workflow: actions call `$spurBin builder pr` directly (PR-7).
77
70
  - kind: shell
78
71
  options:
79
72
  # (e) 0825: 10 lines — detached-HEAD/dirty/gh-auth/base-refusal probes must record
@@ -82,7 +75,7 @@ states:
82
75
 
83
76
  STATUS_FILE=".spur/run/$__runId-pr-preflight.status" &&
84
77
  set +e &&
85
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/pr-reviewing.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/pr-reviewing.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; "$RUNNER" "$S" preflight --base "$baseBranch" --json > ".spur/run/$__runId-pr-context.json";
78
+ $spurBin builder pr preflight --base "$baseBranch" --json > ".spur/run/$__runId-pr-context.json";
86
79
  rc=$?; set -e &&
87
80
  if [ "$rc" -eq 0 ]; then printf 'PASS\n' > "$STATUS_FILE"; else printf 'FAIL\n' > "$STATUS_FILE"; fi &&
88
81
  exit 0
@@ -100,7 +93,7 @@ states:
100
93
 
101
94
  STATUS_FILE=".spur/run/$__runId-pr-hygiene.status" &&
102
95
  set +e &&
103
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/pr-reviewing.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/pr-reviewing.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; "$RUNNER" "$S" hygiene --base "$baseBranch" --json
96
+ $spurBin builder pr hygiene --base "$baseBranch" --json
104
97
  --status-file "$STATUS_FILE" > ".spur/run/$__runId-pr-hygiene.json";
105
98
  rc=$?; set -e &&
106
99
  if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
@@ -131,7 +124,7 @@ states:
131
124
  mkdir -p .spur/run &&
132
125
  STATUS_FILE=".spur/run/$__runId-pr-push.status" &&
133
126
  set +e &&
134
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/pr-reviewing.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/pr-reviewing.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; "$RUNNER" "$S" push --json --status-file "$STATUS_FILE"
127
+ $spurBin builder pr push --json --status-file "$STATUS_FILE"
135
128
  > ".spur/run/$__runId-pr-push.json";
136
129
  rc=$?; set -e &&
137
130
  if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
@@ -148,7 +141,7 @@ states:
148
141
  mkdir -p .spur/run &&
149
142
  STATUS_FILE=".spur/run/$__runId-pr-ensure.status" &&
150
143
  set +e &&
151
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/pr-reviewing.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/pr-reviewing.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; "$RUNNER" "$S" ensure-pr --base "$baseBranch" --json
144
+ $spurBin builder pr ensure-pr --base "$baseBranch" --json
152
145
  --status-file "$STATUS_FILE" > ".spur/run/$__runId-pr.json";
153
146
  rc=$?; set -e &&
154
147
  if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
@@ -164,7 +157,7 @@ states:
164
157
  # (e) 0825: 10 lines — the write-then-read split is the file-var transport feeding
165
158
  # wait/collect and must stay one action (same record, same run scope).
166
159
  command: >-
167
- F="$([ "$mode" = rerun ] && echo --force)"; eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/pr-reviewing.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/pr-reviewing.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; "$RUNNER" "$S" request --focus "$focus" $F --json --status-file ".spur/run/$__runId-pr-request.status" > ".spur/run/$__runId-pr-request.json"; [ -f ".spur/run/$__runId-pr-request.status" ] || echo FAIL > ".spur/run/$__runId-pr-request.status"; jq -e . ".spur/run/$__runId-pr-request.json" >/dev/null 2>&1 && jq -r '.requestedAt // ""' ".spur/run/$__runId-pr-request.json" > ".spur/run/$__runId-pr-since.txt" && jq -r '.head // ""' ".spur/run/$__runId-pr-request.json" > ".spur/run/$__runId-pr-head.txt"; exit 0
160
+ F="$([ "$mode" = rerun ] && echo --force)"; $spurBin builder pr request --focus "$focus" $F --json --status-file ".spur/run/$__runId-pr-request.status" > ".spur/run/$__runId-pr-request.json"; [ -f ".spur/run/$__runId-pr-request.status" ] || echo FAIL > ".spur/run/$__runId-pr-request.status"; jq -e . ".spur/run/$__runId-pr-request.json" >/dev/null 2>&1 && jq -r '.requestedAt // ""' ".spur/run/$__runId-pr-request.json" > ".spur/run/$__runId-pr-since.txt" && jq -r '.head // ""' ".spur/run/$__runId-pr-request.json" > ".spur/run/$__runId-pr-head.txt"; exit 0
168
161
 
169
162
  - id: wait
170
163
  description: >
@@ -189,7 +182,7 @@ states:
189
182
  mkdir -p .spur/run &&
190
183
  STATUS_FILE=".spur/run/$__runId-pr-wait.status" &&
191
184
  set +e &&
192
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/pr-reviewing.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/pr-reviewing.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; "$RUNNER" "$S" wait --since "$prSince" --head "$prHead" --timeout "$waitTimeoutSec" --interval "$waitIntervalSec"
185
+ $spurBin builder pr wait --since "$prSince" --head "$prHead" --timeout "$waitTimeoutSec" --interval "$waitIntervalSec"
193
186
  --json --status-file "$STATUS_FILE" > ".spur/run/$__runId-pr-wait.json";
194
187
  rc=$?; set -e &&
195
188
  if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
@@ -213,7 +206,7 @@ states:
213
206
  # (e) 0825: 9 lines — collect + status must run against the same since/head pair
214
207
  # before the composite status is decided (same 0771 record contract).
215
208
  command: >-
216
- mkdir -p .spur/run; eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/pr-reviewing.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/pr-reviewing.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; "$RUNNER" "$S" collect --since "$prSince" --head "$prHead" --json --status-file ".spur/run/$__runId-pr-collect.status" > ".spur/run/$__runId-pr-findings.json"; c=$?; "$RUNNER" "$S" status --since "$prSince" --head "$prHead" --json > ".spur/run/$__runId-pr-status.json" && [ "$c" -eq 0 ] && [ -f ".spur/run/$__runId-pr-collect.status" ] || printf 'FAIL\n' > ".spur/run/$__runId-pr-collect.status"; cat ".spur/run/$__runId-pr-findings.json" 2>/dev/null; exit 0
209
+ mkdir -p .spur/run; $spurBin builder pr collect --since "$prSince" --head "$prHead" --json --status-file ".spur/run/$__runId-pr-collect.status" > ".spur/run/$__runId-pr-findings.json"; c=$?; $spurBin builder pr status --since "$prSince" --head "$prHead" --json > ".spur/run/$__runId-pr-status.json" && [ "$c" -eq 0 ] && [ -f ".spur/run/$__runId-pr-collect.status" ] || printf 'FAIL\n' > ".spur/run/$__runId-pr-collect.status"; cat ".spur/run/$__runId-pr-findings.json" 2>/dev/null; exit 0
217
210
 
218
211
  - id: done
219
212
  description: Terminal — review collected; findings artifact at .spur/run/${vars.__runId}-pr-findings.json
@@ -58,8 +58,8 @@ name: task-pipeline
58
58
  # verifier's and reviewer's self-graded levels (re-imported from the cc anti-hallucination skill
59
59
  # by task 1068) are no longer written, checked, or gated on; spur certifies on deterministic
60
60
  # evidence (rows MET, proof digests, findings dispositioned). The `confidence` check row, the
61
- # `ackLowConfidence` var, and the guards' LOW/absent clauses are gone; the derived
62
- # feature-receipt confidence (ADR-131/1196) is a different family and stays.
61
+ # `ackLowConfidence` var, and the guards' LOW/absent clauses are gone. The derived
62
+ # feature-receipt confidence (1196) followed in task 1221 (ADR-138 amendment).
63
63
  version: "7"
64
64
  description: "Standard task pipeline: precheck → implement → quality-gate (test/fix/recheck) → review → approve → verify → record → done"
65
65
  # Task entity lifecycle (owned by task-lifecycle.yaml):
@@ -230,12 +230,6 @@ states:
230
230
  Fast deterministic task readiness and size checks. Failures route to the
231
231
  `failed` terminal state (not a raw lifecycle abort mid-enter).
232
232
  onEnter:
233
- # 0960 R2: run-start script-resolution identity — record which tree this run
234
- # resolved (source-repo vs installed) before any step executes. Never aborts.
235
- - kind: shell
236
- options:
237
- command: >-
238
- S=plugins/sp/scripts/script-root.ts; [ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp script-root.mjs 2>/dev/null)"; RUNNER=bun; case "$S" in *.mjs) RUNNER=node ;; esac; [ -f "$S" ] && "$RUNNER" "$S" --run-id "$__runId" --spur-bin "$spurBin" || echo "script-root failed closed — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; exit 0
239
233
  # (e) git-status hygiene advisory; never fails the run (0487 R6 / 0511 R1). 1007 R3:
240
234
  # the F96 base-sha capture (0950) merged into this shell — original commands in order,
241
235
  # then the one-time base commit capture; a resumed run keeps its original base so
@@ -492,11 +486,12 @@ states:
492
486
  var: proofDigest
493
487
  taskFile: ${vars.taskSpecPath}
494
488
  featureFile: ${vars.featureSpecPath}
495
- # (d) quality-gate.ts owns the gate; shell only resolves it and fails closed.
489
+ # (d) `spur task gate` owns the gate; shell only picks the mode and fails closed
490
+ # (a non-0/1 exit — spur missing, usage error, crash — writes FAIL).
496
491
  - kind: shell
497
492
  options:
498
493
  command: >-
499
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/quality-gate.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/quality-gate.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; M=run; [ "$deferQualityGate" = "true" ] && M=deferred; if [ -f "$S" ]; then "$RUNNER" "$S" "$M"; else echo "quality gate failed closed — quality-gate script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; printf 'FAIL\n' > ".spur/run/$wbs-test-gate.status"; fi; exit 0
494
+ M=run; [ "$deferQualityGate" = "true" ] && M=deferred; $spurBin task gate "$wbs" "$M" --no-logo; rc=$?; if [ "$rc" -gt 1 ]; then echo "quality gate failed closed — spur task gate exited $rc" >&2; printf 'FAIL\n' > ".spur/run/$wbs-test-gate.status"; fi; exit 0
500
495
 
501
496
  - id: test-fix
502
497
  display:
@@ -597,12 +592,12 @@ states:
597
592
  # a green probe (or empty gateProbeCmd) falls through to the full-gate loop unchanged.
598
593
  # Only the full gate writes PASS, so the `test-recheck → review` guard (reads PASS)
599
594
  # still means a full green qualityGateCmd ran — invariant preserved by construction.
600
- # (d) quality-gate.ts owns the recheck; shell only resolves it and fails closed
595
+ # (d) `spur task gate` owns the recheck; shell only picks the mode and fails closed
601
596
  # (0587 R3 probe-then-full: a red gateProbeCmd is the recheck verdict, the full gate is skipped).
602
597
  - kind: shell
603
598
  options:
604
599
  command: >-
605
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/quality-gate.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/quality-gate.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; M=recheck; [ "$deferQualityGate" = "true" ] && M=deferred; if [ -f "$S" ]; then "$RUNNER" "$S" "$M"; else echo "quality gate failed closed — quality-gate script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; printf 'FAIL\n' > ".spur/run/$wbs-test-gate.status"; fi; exit 0
600
+ M=recheck; [ "$deferQualityGate" = "true" ] && M=deferred; $spurBin task gate "$wbs" "$M" --no-logo; rc=$?; if [ "$rc" -gt 1 ]; then echo "quality gate failed closed — spur task gate exited $rc" >&2; printf 'FAIL\n' > ".spur/run/$wbs-test-gate.status"; fi; exit 0
606
601
 
607
602
  - id: triage
608
603
  display:
@@ -620,13 +615,13 @@ states:
620
615
  when neither a caller mode nor the deterministic guard resolved the lane. The resolved
621
616
  lane lands in the `mode` var for the triage → verify/review guards.
622
617
  onEnter:
623
- # (a) diffstat producer: task-diffstat.ts owns git reading and sensitive-path
624
- # classification; shell only resolves it and fails closed (writes sensitive:true,
618
+ # (a) diffstat producer: `spur task diffstat` owns git reading and sensitive-path
619
+ # classification; shell only fails closed on a non-zero exit (writes sensitive:true,
625
620
  # which the pre-guard below maps to the safety lane).
626
621
  - kind: shell
627
622
  options:
628
623
  command: >-
629
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/task-diffstat.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/task-diffstat.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then "$RUNNER" "$S" --spur-bin "$spurBin"; else echo "task-diffstat failed closed — task-diffstat script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; printf '{"files":0,"insertions":0,"deletions":0,"paths":[],"sensitive":true}\n' > ".spur/run/$wbs-diffstat.json"; fi; exit 0
624
+ $spurBin task diffstat "$wbs" --no-logo || { echo "task-diffstat failed closed — spur task diffstat exited $?" >&2; printf '{"files":0,"insertions":0,"deletions":0,"paths":[],"sensitive":true}\n' > ".spur/run/$wbs-diffstat.json"; }; exit 0
630
625
  # (b)+(c) lane pre-guard BEFORE decide: a caller-set mode is projected verbatim (R2b);
631
626
  # a sensitive path or >400 changed lines pins safety (R2c) and the decide result below
632
627
  # is never consulted. A missing/malformed diffstat row (producer crashed or never ran,
@@ -953,7 +948,7 @@ states:
953
948
  options:
954
949
  command: >-
955
950
  if [ "$deferFeatureSync" = "true" ]; then echo "feature sync deferred to batch integration" >> ".spur/run/$wbs-report.txt"; else FID="$($spurBin task show $wbs --json 2>/dev/null | jq -r '(.feature_id // .frontmatter.feature_id) // empty' 2>/dev/null)"; if [ -n "$FID" ]; then $spurBin feature sync "$FID" --json || echo "feature sync failed — re-run: $spurBin feature sync $FID" >> ".spur/run/$wbs-report.txt"; else echo "Orphan task $wbs — no feature_id linked — proposal: consider linking to a parent feature." >> ".spur/run/$wbs-report.txt"; fi; fi; exit 0
956
- # (d) F96 (0983): residual-scan.ts owns the sweep; shell only resolves it. The
951
+ # (d) F96 (0983): `spur task residual` owns the sweep; shell only sequences it. The
957
952
  # scan moved here from verify: it must read the task file AFTER `task record`
958
953
  # flipped the verdict-proven Requirement/AC boxes (0692), or a proven-but-unticked
959
954
  # box folds every good run to PARTIAL and the done guard is unreachable (0967).
@@ -963,7 +958,7 @@ states:
963
958
  - kind: shell
964
959
  options:
965
960
  command: >-
966
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/residual-scan.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/residual-scan.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ ! -f "$S" ]; then echo "residual-scan failed closed — scanner not found in plugins/sp/scripts/ nor staged — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; exit 1; fi; "$RUNNER" "$S" scan "$wbs" --spur-bin "$spurBin" && "$RUNNER" "$S" fold "$wbs" --spur-bin "$spurBin"
961
+ $spurBin task residual "$wbs" scan --no-logo && $spurBin task residual "$wbs" fold --no-logo
967
962
  # (e) F96 R5 (0983): a sweep downgrade must reach the task record — re-record from
968
963
  # the FINAL (post-fold) artifact so Testing carries the downgraded verdict; a failed
969
964
  # task must not retain a stale PASS Testing narrative. Soft (exit 0): the downgrade
@@ -983,13 +978,13 @@ states:
983
978
  guard runs `spur task check` before certifying; a genuinely non-compliant
984
979
  task routes to `failed` instead of a silent bad `done`.
985
980
  onEnter:
986
- # (d) F96 R4 (0950): residual-scan.ts owns the settle; shell only resolves it.
981
+ # (d) F96 R4 (0950): `spur task residual` owns the settle.
987
982
  # Soft best-effort (exit 0) — runs after certification and must never change
988
983
  # the outcome; failure prints the re-run command.
989
984
  - kind: shell
990
985
  options:
991
986
  command: >-
992
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/residual-scan.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/residual-scan.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then "$RUNNER" "$S" settle "$wbs" --spur-bin "$spurBin" || echo "residual-settle failed — re-run: residual-scan settle $wbs" >&2; else echo "residual-scan not staged — settle skipped — re-run: residual-scan settle $wbs" >&2; fi; exit 0
987
+ $spurBin task residual "$wbs" settle --no-logo || echo "residual-settle failed — re-run: spur task residual $wbs settle" >&2; exit 0
993
988
  # (c) command.gate owns the done transition with classified transient retry.
994
989
  - kind: command.gate
995
990
  options:
@@ -1029,13 +1024,13 @@ states:
1029
1024
  printf '\n## Escalation bound reached\n\nThe implement step asked an operator question %s times (bound %s) and ended without a resumable answer. Unanswered question:\n\n' "$n" "$maxEscalations" >> .spur/run/$wbs-report.txt;
1030
1025
  cat .spur/run/$wbs-question.md >> .spur/run/$wbs-report.txt;
1031
1026
  exit 0
1032
- # (d) F96 R5 (0950): residual-scan.ts owns the report; shell only resolves it.
1027
+ # (d) F96 R5 (0950): `spur task residual` owns the report.
1033
1028
  # Soft (exit 0): a run that exhausts its fix budget on residuals leaves the
1034
1029
  # report + recovery line while the task stays `wip`.
1035
1030
  - kind: shell
1036
1031
  options:
1037
1032
  command: >-
1038
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/residual-scan.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/residual-scan.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then "$RUNNER" "$S" report "$wbs" --spur-bin "$spurBin" || echo "residual-report failed — re-run: residual-scan report $wbs" >&2; else echo "residual-scan not staged — report skipped — re-run: residual-scan report $wbs" >&2; fi; exit 0
1033
+ $spurBin task residual "$wbs" report --no-logo || echo "residual-report failed — re-run: spur task residual $wbs report" >&2; exit 0
1039
1034
 
1040
1035
  - id: cancelled
1041
1036
  description: Terminal — pipeline cancelled by operator at the approval gate (R1).
@@ -1295,8 +1290,7 @@ transitions:
1295
1290
  command: >-
1296
1291
  test "$profile" = auto &&
1297
1292
  grep -qiE '^[[:space:]]*\**Verdict:\** *PASS' ".spur/run/$__runId-review-answer.txt" &&
1298
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/residual-scan.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/residual-scan.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)" &&
1299
- [ -f "$S" ] && "$RUNNER" "$S" review-gate "$wbs" --spur-bin "$spurBin" >&2
1293
+ $spurBin task residual "$wbs" review-gate --no-logo >&2
1300
1294
  - from: review
1301
1295
  to: approve
1302
1296
  description: Review certified a PASS with no open P1-P3 finding — gate on human approval before verification.
@@ -1305,8 +1299,7 @@ transitions:
1305
1299
  options:
1306
1300
  command: >-
1307
1301
  grep -qiE '^[[:space:]]*\**Verdict:\** *PASS' ".spur/run/$__runId-review-answer.txt" &&
1308
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/residual-scan.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/residual-scan.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)" &&
1309
- [ -f "$S" ] && "$RUNNER" "$S" review-gate "$wbs" --spur-bin "$spurBin" >&2
1302
+ $spurBin task residual "$wbs" review-gate --no-logo >&2
1310
1303
  - from: review
1311
1304
  to: review-fail-triage
1312
1305
  description: >-
@@ -138,12 +138,6 @@ states:
138
138
  Pipeline start. Task statuses are NOT mutated by wrap-up — wrap-up consumes
139
139
  completed tasks and produces learning/metrics/doc artifacts only.
140
140
  onEnter:
141
- # 0960 R2: run-start script-resolution identity — record which tree this run
142
- # resolved (source-repo vs installed) before any step executes. Never aborts.
143
- - kind: shell
144
- options:
145
- command: >-
146
- S=plugins/sp/scripts/script-root.ts; [ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp script-root.mjs 2>/dev/null)"; RUNNER=bun; case "$S" in *.mjs) RUNNER=node ;; esac; [ -f "$S" ] && "$RUNNER" "$S" --run-id "$__runId" --spur-bin "$spurBin" || echo "script-root failed closed — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; exit 0
147
141
  - kind: note
148
142
  options:
149
143
  message: "Wrap-up pipeline start for tasks: ${vars.tasks}. Task statuses are NOT mutated."
@@ -173,25 +167,20 @@ states:
173
167
  - kind: note
174
168
  options:
175
169
  message: "Resolving task list: ${vars.tasks} (proportional mode: ${vars.mode})"
176
- # (d) wrapup-steps.ts resolve owns task capture and status resolution (0824);
177
- # the wrapper only locates it (monorepo first, registered twin under node) and
170
+ # (d) `spur task wrapup resolve` owns task capture and status resolution (0824;
171
+ # script-absorption PR-5 retired the wrapup-steps plugin script). A nonzero exit
178
172
  # fails closed, writing FAIL for the failed defense edge — never PASS.
179
173
  - kind: shell
180
174
  options:
181
175
  command: >-
182
176
  mkdir -p .spur/run &&
183
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/wrapup-steps.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/wrapup-steps.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then
184
- "$RUNNER" "$S" resolve;
185
- else
186
- echo "wrapup-steps failed closed — script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2;
187
- printf 'FAIL\n' > ".spur/run/$__runId-wrapup-resolve.status";
188
- fi
177
+ $spurBin task wrapup resolve --no-logo || { rc=$?; echo "task wrapup resolve failed closed (rc=$rc)" >&2; printf 'FAIL\n' > ".spur/run/$__runId-wrapup-resolve.status"; }
189
178
  # (0944 R1-R3) deterministic drift probe — runs ONLY when the caller left mode
190
179
  # empty (a caller-set mode is projected verbatim and the probe never runs). It
191
180
  # writes <runId>-drift-probe.json {clean,reasons,paths} and projects the wrapup
192
181
  # mode by writing <runId>-mode.txt: caller mode verbatim, `fast` when the probe
193
- # is clean, empty when dirty (the probe script fails safe on any lookup or parse
194
- # problem; a missing script writes a dirty probe + empty mode here). The next
182
+ # is clean, empty when dirty (`spur task wrapup drift-probe` fails safe on any lookup
183
+ # or parse problem; a nonzero exit writes a dirty probe + empty mode here). The next
195
184
  # action reads the mode file into vars.mode via file.read.into-var.
196
185
  - kind: shell
197
186
  options:
@@ -199,13 +188,11 @@ states:
199
188
  if [ -n "$mode" ]; then
200
189
  printf '%s\n' "$mode" > ".spur/run/$__runId-mode.txt";
201
190
  else
202
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/wrapup-drift-probe.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/wrapup-drift-probe.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)";
203
- if [ -f "$S" ]; then
204
- "$RUNNER" "$S";
205
- else
206
- printf '{"clean":false,"reasons":["probe script not found"],"paths":[]}' > ".spur/run/$__runId-drift-probe.json";
191
+ $spurBin task wrapup drift-probe --no-logo || {
192
+ rc=$?;
193
+ printf '{"clean":false,"reasons":["drift probe failed (rc=%s)"],"paths":[]}' "$rc" > ".spur/run/$__runId-drift-probe.json";
207
194
  printf '\n' > ".spur/run/$__runId-mode.txt";
208
- fi;
195
+ };
209
196
  fi
210
197
  - kind: file.read.into-var
211
198
  options:
@@ -213,7 +200,7 @@ states:
213
200
  var: mode
214
201
  # (e) route-reason writer: one table lookup over the projected mode var over
215
202
  # the validated capture and the drift probe verdict; workflow-local routing
216
- # glue (0824, moved behind the wrapup-steps locator in 0944 to stay inside the
203
+ # glue (0824, moved behind `spur task wrapup` in 0944/PR-5 to stay inside the
217
204
  # ADR-115 shell caps). Runs AFTER the probe/projection so the reason reflects
218
205
  # the projected mode. Reads ONLY .spur/run/<runId>-wrapup-tasks.json and the
219
206
  # probe verdict — never raw vars.tasks (0783 R2/R5). A FAIL resolve exits
@@ -226,12 +213,7 @@ states:
226
213
  options:
227
214
  command: >-
228
215
  mkdir -p .spur/run .spur/memory &&
229
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/wrapup-steps.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/wrapup-steps.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then
230
- "$RUNNER" "$S" route-reason;
231
- else
232
- echo "wrapup-steps failed closed — script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2;
233
- printf 'FAIL\n' > ".spur/run/$__runId-wrapup-resolve.status";
234
- fi
216
+ $spurBin task wrapup route-reason --no-logo || { rc=$?; echo "task wrapup route-reason failed closed (rc=$rc)" >&2; printf 'FAIL\n' > ".spur/run/$__runId-wrapup-resolve.status"; }
235
217
 
236
218
  - id: doc-sync
237
219
  description: >
@@ -259,11 +241,7 @@ states:
259
241
  options:
260
242
  command: >-
261
243
  mkdir -p .spur/run &&
262
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/wrapup-steps.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/wrapup-steps.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then
263
- "$RUNNER" "$S" doc-sync-snapshot;
264
- else
265
- echo "wrapup-steps failed closed — script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2;
266
- fi
244
+ $spurBin task wrapup doc-sync-snapshot --no-logo || echo "task wrapup doc-sync-snapshot failed (rc=$?) — the scope check fails closed on the missing snapshot" >&2
267
245
  # (warn) free-form prompt: no /sp:doc-evolve command surface yet (ADR-043
268
246
  # residual, 0607 R2 one-query merge); capture is bounded by expectFile.
269
247
  - kind: agent.run
@@ -296,12 +274,7 @@ states:
296
274
  options:
297
275
  command: >-
298
276
  mkdir -p .spur/run &&
299
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/wrapup-steps.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/wrapup-steps.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then
300
- "$RUNNER" "$S" doc-sync-scope;
301
- else
302
- echo "wrapup-steps failed closed — script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2;
303
- printf 'scope-violation: wrapup-steps script not found\n' > ".spur/run/$__runId-wrapup-doc-sync-scope.status";
304
- fi
277
+ $spurBin task wrapup doc-sync-scope --no-logo || { rc=$?; echo "task wrapup doc-sync-scope failed closed (rc=$rc)" >&2; printf 'scope-violation: task wrapup doc-sync-scope failed\n' > ".spur/run/$__runId-wrapup-doc-sync-scope.status"; }
305
278
  # (1147 R2) supersession pins re-run: a doc-sync that resurrects a deliberately
306
279
  # delinked index row (`repo-wide-tests/adr-supersession.test.ts`, g2) fails HERE,
307
280
  # named with the pin, instead of being attributed to the later doc-tripwire
@@ -310,12 +283,7 @@ states:
310
283
  options:
311
284
  command: >-
312
285
  mkdir -p .spur/run &&
313
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/wrapup-steps.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/wrapup-steps.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then
314
- "$RUNNER" "$S" doc-supersession;
315
- else
316
- echo "wrapup-steps failed closed — script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2;
317
- printf 'supersession-pin-failed: wrapup-steps script not found\n' > ".spur/run/$__runId-wrapup-doc-supersession.status";
318
- fi
286
+ $spurBin task wrapup doc-supersession --no-logo || { rc=$?; echo "task wrapup doc-supersession failed closed (rc=$rc)" >&2; printf 'supersession-pin-failed: task wrapup doc-supersession failed\n' > ".spur/run/$__runId-wrapup-doc-supersession.status"; }
319
287
 
320
288
  - id: learnings-validate
321
289
  description: >
@@ -421,18 +389,13 @@ states:
421
389
  is UNKNOWN telemetry, never proof of completion; previously written valid rows
422
390
  survive a failure.
423
391
  onEnter:
424
- # (d) wrapup-steps.ts metrics owns the JSONL row append (0824); the wrapper
425
- # only locates it and fails closed — FAIL, never a silent skip.
392
+ # (d) `spur task wrapup metrics` owns the JSONL row append (0824); a nonzero
393
+ # exit fails closed — FAIL, never a silent skip.
426
394
  - kind: shell
427
395
  options:
428
396
  command: >-
429
397
  mkdir -p .spur/run &&
430
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/wrapup-steps.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/wrapup-steps.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then
431
- "$RUNNER" "$S" metrics;
432
- else
433
- echo "wrapup-steps failed closed — script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2;
434
- printf 'FAIL\n' > ".spur/run/$__runId-wrapup-metrics.status";
435
- fi
398
+ $spurBin task wrapup metrics --no-logo || { rc=$?; echo "task wrapup metrics failed closed (rc=$rc)" >&2; printf 'FAIL\n' > ".spur/run/$__runId-wrapup-metrics.status"; }
436
399
 
437
400
  - id: feature-transition
438
401
  description: >
@@ -450,9 +413,9 @@ states:
450
413
  (the engine only enters this state when vars.feature is set) and fails
451
414
  loud (dogfood 2026-08-15, feature I3).
452
415
  onEnter:
453
- # (d) wrapup-steps.ts feature-transition owns the bounded sync, observation
454
- # and the gate (0824); the wrapper only locates it and fails closed. The
455
- # script terminates exit 0 on every path so artifacts that already landed
416
+ # (d) `spur task wrapup feature-transition` owns the bounded sync, observation
417
+ # and the gate (0824); a nonzero exit fails closed. The
418
+ # step terminates exit 0 on every path so artifacts that already landed
456
419
  # are never discarded; soft TERMINATION is not soft TRUTH — only a verified
457
420
  # sync writes PASS (0783 R4). A gate PASS can never convert a failed sync
458
421
  # into success, and a gate FAIL fails the step (0770 failure routing).
@@ -460,12 +423,7 @@ states:
460
423
  options:
461
424
  command: >-
462
425
  mkdir -p .spur/run &&
463
- eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/wrapup-steps.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/wrapup-steps.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then
464
- "$RUNNER" "$S" feature-transition;
465
- else
466
- echo "wrapup-steps failed closed — script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2;
467
- printf 'FAIL\n' > ".spur/run/$__runId-wrapup-sync.status";
468
- fi
426
+ $spurBin task wrapup feature-transition --no-logo || { rc=$?; echo "task wrapup feature-transition failed closed (rc=$rc)" >&2; printf 'FAIL\n' > ".spur/run/$__runId-wrapup-sync.status"; }
469
427
 
470
428
  - id: feature-verify
471
429
  description: >
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/spur",
3
- "version": "0.4.8",
3
+ "version": "0.4.10",
4
4
  "description": "Spur CLI — local-first harness for mainstream coding agents: constraint checking, workflow orchestration, agent health, and history analytics. Bun-native; exposes the `spur` command.",
5
5
  "keywords": [
6
6
  "spur",
@@ -49,11 +49,11 @@
49
49
  "dev": "bun run src/index.ts",
50
50
  "build": "bun run ../../scripts/spur-dev.ts build-cli",
51
51
  "build:binaries": "bun run ../../scripts/spur-dev.ts build-binaries",
52
- "build:bundle": "bun run ../../scripts/commands/bundle-plugin-lib.ts && bun run ../../scripts/spur-dev.ts bundle-web && bun run ../../scripts/spur-dev.ts emit-board-types && bun build src/index.ts --target=bun --outfile spur.js --external @johnhenry/backend-webgpu && bun run ../../scripts/spur-dev.ts bundle-config config && bun run ../../scripts/spur-dev.ts bundle-plugins",
52
+ "build:bundle": "bun run ../../scripts/spur-dev.ts bundle-web && bun run ../../scripts/spur-dev.ts emit-board-types && bun build src/index.ts --target=bun --outfile spur.js --external @johnhenry/backend-webgpu && bun run ../../scripts/spur-dev.ts bundle-config config && bun run ../../scripts/spur-dev.ts bundle-plugins",
53
53
  "test": "bun test tests --coverage --coverage-dir=../../.coverage --pass-with-no-tests",
54
54
  "typecheck": "tsc --noEmit",
55
55
  "prepack": "bun run build:bundle",
56
- "prepublishOnly": "bun run ../../scripts/spur-dev.ts check-marketplace-version"
56
+ "prepublishOnly": "cd ../.. && bun run apps/cli/src/index.ts builder bump-ver --check spur --no-logo"
57
57
  },
58
58
  "devDependencies": {
59
59
  "@commander-js/extra-typings": "^14.0.0",