@gobing-ai/spur 0.3.94 → 0.3.96

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 (198) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/README.md +42 -0
  3. package/board/index.d.ts +38 -0
  4. package/config/plugin-scripts.json +3 -52
  5. package/config/rules/boundary/sp-script-placement.yaml +19 -0
  6. package/config/rules/strict/runtime-boundaries.yaml +5 -0
  7. package/config/rules/structure/test-location.yaml +2 -0
  8. package/config/rules/typescript/no-syscall-emulation-in-boundary-mock.yaml +1 -1
  9. package/config/rules/typescript/output-boundaries.yaml +15 -2
  10. package/config/script-placement-baseline.json +51 -0
  11. package/config/workflows/feature-verification.yaml +7 -4
  12. package/config/workflows/history-anatomy.yaml +23 -11
  13. package/config/workflows/idea-pipeline.yaml +87 -86
  14. package/config/workflows/pr-review.yaml +18 -9
  15. package/config/workflows/task-pipeline.yaml +84 -109
  16. package/config/workflows/wrapup-pipeline.yaml +173 -46
  17. package/package.json +15 -11
  18. package/plugins/sp/README.md +8 -10
  19. package/plugins/sp/agents/super-reviewer.md +43 -18
  20. package/plugins/sp/commands/dev-fixgha.md +83 -0
  21. package/plugins/sp/commands/dev-gitmsg.md +8 -6
  22. package/plugins/sp/commands/dev-gtd.md +2 -2
  23. package/plugins/sp/commands/dev-idea.md +22 -12
  24. package/plugins/sp/commands/dev-plan.md +8 -9
  25. package/plugins/sp/commands/dev-review.md +22 -13
  26. package/plugins/sp/commands/dev-verify.md +7 -4
  27. package/plugins/sp/commands/dev-verifyall.md +5 -4
  28. package/plugins/sp/commands/dev-wrap.md +1 -1
  29. package/plugins/sp/commands/spur-init.md +2 -2
  30. package/plugins/sp/hooks/context-post-tool.ts +2 -2
  31. package/plugins/sp/hooks/context-session-start.ts +2 -1
  32. package/plugins/sp/hooks/context-session-stop.ts +22 -14
  33. package/plugins/sp/hooks/pi/guard-extension.ts +109 -150
  34. package/plugins/sp/lib/history-anatomy.generated.d.mts +112 -0
  35. package/plugins/sp/lib/history-anatomy.generated.mjs +686 -0
  36. package/plugins/sp/lib/idea-handoff.generated.mjs +6 -5
  37. package/plugins/sp/lib/inline-run.generated.d.mts +13 -2
  38. package/plugins/sp/lib/inline-run.generated.mjs +33 -16
  39. package/plugins/sp/lib/quality-gate.generated.d.mts +104 -0
  40. package/plugins/sp/lib/quality-gate.generated.mjs +438 -0
  41. package/plugins/sp/lib/residual-scan.generated.d.mts +62 -0
  42. package/plugins/sp/lib/residual-scan.generated.mjs +210 -0
  43. package/plugins/sp/lib/spur-bin.ts +36 -0
  44. package/plugins/sp/lib/step-profile.generated.d.mts +71 -0
  45. package/plugins/sp/lib/step-profile.generated.mjs +174 -0
  46. package/plugins/sp/plugin.json +1 -1
  47. package/plugins/sp/references/roles.md +1 -1
  48. package/plugins/sp/scripts/daily-summary/daily-summary.mjs +3 -3
  49. package/plugins/sp/scripts/daily-summary/daily-summary.ts +3 -3
  50. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.mjs +2 -0
  51. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts +1 -0
  52. package/plugins/sp/scripts/dogfood-testing/validate-report.mjs +9 -7
  53. package/plugins/sp/scripts/dogfood-testing/validate-report.ts +8 -7
  54. package/plugins/sp/scripts/feature-verification-steps.ts +6 -6
  55. package/plugins/sp/scripts/history-anatomy-cache.mjs +23 -22
  56. package/plugins/sp/scripts/history-anatomy-cache.ts +23 -928
  57. package/plugins/sp/scripts/inline-run-setup.mjs +90 -315
  58. package/plugins/sp/scripts/inline-run-setup.ts +109 -639
  59. package/plugins/sp/scripts/pr-reviewing.mjs +2 -0
  60. package/plugins/sp/scripts/pr-reviewing.ts +1 -0
  61. package/plugins/sp/scripts/quality-gate.mjs +38 -21
  62. package/plugins/sp/scripts/quality-gate.ts +20 -660
  63. package/plugins/sp/scripts/residual-scan.mjs +138 -159
  64. package/plugins/sp/scripts/residual-scan.ts +102 -499
  65. package/plugins/sp/scripts/script-root.mjs +129 -0
  66. package/plugins/sp/scripts/script-root.ts +199 -0
  67. package/plugins/sp/scripts/workflow-step-profile.mjs +27 -16
  68. package/plugins/sp/scripts/workflow-step-profile.ts +22 -314
  69. package/plugins/sp/scripts/wrapup-drift-probe.mjs +12 -3
  70. package/plugins/sp/scripts/wrapup-drift-probe.ts +6 -3
  71. package/plugins/sp/scripts/wrapup-steps.mjs +42 -40
  72. package/plugins/sp/scripts/wrapup-steps.ts +64 -46
  73. package/plugins/sp/skills/code-improvement/SKILL.md +5 -4
  74. package/plugins/sp/skills/code-verification/SKILL.md +46 -16
  75. package/plugins/sp/skills/code-verification/references/verdict-schema.md +13 -2
  76. package/plugins/sp/skills/functional-review/SKILL.md +8 -5
  77. package/plugins/sp/skills/functional-review/references/verdict-schema.md +1 -1
  78. package/plugins/sp/skills/history-anatomy/references/modes.md +2 -1
  79. package/plugins/sp/skills/next-feature/references/handoff-routing.md +1 -1
  80. package/plugins/sp/skills/next-router/references/routing-table.md +2 -2
  81. package/plugins/sp/skills/spur-cli/SKILL.md +3 -3
  82. package/plugins/sp/skills/spur-cli/references/agent.md +10 -10
  83. package/plugins/sp/skills/spur-cli/references/features.md +17 -6
  84. package/plugins/sp/skills/spur-cli/references/init.md +17 -16
  85. package/plugins/sp/skills/spur-cli/references/self.md +3 -2
  86. package/plugins/sp/skills/spur-cli/references/serve.md +10 -10
  87. package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +28 -5
  88. package/plugins/sp/skills/spur-cli/references/tasks.md +14 -8
  89. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +4 -3
  90. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +11 -9
  91. package/plugins/sp/skills/spur-dev/references/decision-brief.md +1 -1
  92. package/plugins/sp/skills/spur-dev/references/dev-operations.md +86 -70
  93. package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +3 -3
  94. package/plugins/sp/skills/spur-dev/references/execution-batch.md +107 -44
  95. package/plugins/sp/skills/spur-dev/references/execution-workflow.md +5 -9
  96. package/plugins/sp/skills/spur-dev/references/feature-link-helper.md +3 -3
  97. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +31 -21
  98. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +19 -19
  99. package/plugins/sp/skills/spur-dev/references/idea-evaluation.md +4 -3
  100. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +35 -6
  101. package/plugins/sp/skills/spur-doctor/SKILL.md +1 -1
  102. package/plugins/sp/skills/sys-architecture/SKILL.md +3 -2
  103. package/plugins/sp/tsconfig.json +8 -0
  104. package/spur.js +6638 -4775
  105. package/web/_astro/BoardApp.BIjMatT1.js +1 -0
  106. package/web/_astro/{BoardApp.FTEs3-N8.js → BoardApp.GvjIe9Z6.js} +150 -153
  107. package/web/_astro/TaskDetail.BZM3EAFx.js +1 -0
  108. package/web/_astro/_commonjsHelpers.CqkleIqs.js +1 -0
  109. package/web/_astro/{arc.uuAf51IT.js → arc.HkRiZnoI.js} +1 -1
  110. package/web/_astro/architectureDiagram-3BPJPVTR.BDdK-tgZ.js +36 -0
  111. package/web/_astro/{blockDiagram-GPEHLZMM.D1mGCq3p.js → blockDiagram-GPEHLZMM.CZ9kOBxx.js} +1 -1
  112. package/web/_astro/board-facade-react-dom-client.B2U5wMvk.js +1 -0
  113. package/web/_astro/board-facade-react-dom.Cd2MuMhF.js +1 -0
  114. package/web/_astro/board-facade-react-jsx-dev-runtime.B_L3JzfC.js +1 -0
  115. package/web/_astro/board-facade-react-jsx-runtime.BY2yfHRi.js +1 -0
  116. package/web/_astro/board-facade-react-router-dom.Dy5pjzOw.js +1 -0
  117. package/web/_astro/board-facade-react-router.DjjqU27_.js +1 -0
  118. package/web/_astro/board-facade-react.Dgf4GRyj.js +1 -0
  119. package/web/_astro/{c4Diagram-AAUBKEIU.CMsolcde.js → c4Diagram-AAUBKEIU.DXK9qeRD.js} +1 -1
  120. package/web/_astro/channel.DlhX2MEt.js +1 -0
  121. package/web/_astro/{chunk-2J33WTMH.CrGA3fik.js → chunk-2J33WTMH.BTD2WeX5.js} +1 -1
  122. package/web/_astro/{chunk-4BX2VUAB.DsLVVla0.js → chunk-4BX2VUAB.Ci6Qbcvk.js} +1 -1
  123. package/web/_astro/{chunk-55IACEB6.Dxc59Tfi.js → chunk-55IACEB6.yl3zsj7p.js} +1 -1
  124. package/web/_astro/{chunk-727SXJPM.CaEVE2Wy.js → chunk-727SXJPM.ClXZsfyR.js} +1 -1
  125. package/web/_astro/{chunk-AQP2D5EJ.BiJ4HXeI.js → chunk-AQP2D5EJ.BmKWZBcP.js} +1 -1
  126. package/web/_astro/{chunk-FMBD7UC4.Mxf1fru5.js → chunk-FMBD7UC4.By30fcb7.js} +1 -1
  127. package/web/_astro/chunk-JMJ3UQ3L.BQJEJHu4.js +34 -0
  128. package/web/_astro/{chunk-ND2GUHAM.pyOWQixH.js → chunk-ND2GUHAM.24NmrD-k.js} +1 -1
  129. package/web/_astro/{chunk-QZHKN3VN.BmEsg4vr.js → chunk-QZHKN3VN.BN4sKdcS.js} +1 -1
  130. package/web/_astro/chunk-YNUBSHFH.CxeAygfi.js +7 -0
  131. package/web/_astro/{classDiagram-4FO5ZUOK.BHhhMFTO.js → classDiagram-4FO5ZUOK.CJpoMPb5.js} +1 -1
  132. package/web/_astro/{classDiagram-v2-Q7XG4LA2.BHhhMFTO.js → classDiagram-v2-Q7XG4LA2.CJpoMPb5.js} +1 -1
  133. package/web/_astro/client.BhluLQqe.js +1 -0
  134. package/web/_astro/client.DBpSRLnx.js +9 -0
  135. package/web/_astro/cose-bilkent-S5V4N54A.BraxQ2Nt.js +1 -0
  136. package/web/_astro/{cynefin-OW5HDTMX.C2j1_lKL.js → cynefin-OW5HDTMX.gzoU73oL.js} +1 -1
  137. package/web/_astro/{dagre-BM42HDAG.hZ2NCTdT.js → dagre-BM42HDAG.wyDfWySU.js} +1 -1
  138. package/web/_astro/{diagram-2AECGRRQ.Bfw5_EzK.js → diagram-2AECGRRQ.h2_EbMxV.js} +1 -1
  139. package/web/_astro/{diagram-5GNKFQAL.Bt1V_Tmk.js → diagram-5GNKFQAL.Db6dcs89.js} +1 -1
  140. package/web/_astro/{diagram-KO2AKTUF.DEk-YFwp.js → diagram-KO2AKTUF.NVwzxu_U.js} +1 -1
  141. package/web/_astro/{diagram-LMA3HP47.CDjndtQm.js → diagram-LMA3HP47.B-eNgDQk.js} +1 -1
  142. package/web/_astro/{diagram-OG6HWLK6.cFnUHScG.js → diagram-OG6HWLK6.Bsa8ZRbJ.js} +1 -1
  143. package/web/_astro/{erDiagram-TEJ5UH35.DlhYp7NV.js → erDiagram-TEJ5UH35.BospRE5Q.js} +1 -1
  144. package/web/_astro/{flowDiagram-I6XJVG4X.DNTpsxfx.js → flowDiagram-I6XJVG4X.DMzvHwAA.js} +1 -1
  145. package/web/_astro/ganttDiagram-6RSMTGT7.Dmdxgd-M.js +292 -0
  146. package/web/_astro/{gitGraphDiagram-PVQCEYII.DkEqNI0P.js → gitGraphDiagram-PVQCEYII.CaqdO0rL.js} +1 -1
  147. package/web/_astro/index.5dn-Zm-2.js +1 -0
  148. package/web/_astro/index.C-IqPpW2.js +1 -0
  149. package/web/_astro/index.Cyc_GA4f.js +1 -0
  150. package/web/_astro/index.EoZlzLK-.css +1 -0
  151. package/web/_astro/index.tZfqwSut.js +1 -0
  152. package/web/_astro/{infoDiagram-5YYISTIA.CrjioCTG.js → infoDiagram-5YYISTIA.DDVD9Wn7.js} +1 -1
  153. package/web/_astro/{ishikawaDiagram-YF4QCWOH.BcK0CN8n.js → ishikawaDiagram-YF4QCWOH.EKyCUFsL.js} +1 -1
  154. package/web/_astro/{journeyDiagram-JHISSGLW.p0CbBDX1.js → journeyDiagram-JHISSGLW.By2-RkYB.js} +1 -1
  155. package/web/_astro/jsx-runtime.DWOiEOII.js +1 -0
  156. package/web/_astro/{kanban-definition-UN3LZRKU.puHIFt6J.js → kanban-definition-UN3LZRKU.ar-WmlyR.js} +1 -1
  157. package/web/_astro/{linear.Bb-3a1d7.js → linear.BnzMBgo_.js} +1 -1
  158. package/web/_astro/{mermaid.core.CJDgXOJs.js → mermaid.core.DSqeFu2Y.js} +4 -4
  159. package/web/_astro/{mindmap-definition-RKZ34NQL.BoAZEI9t.js → mindmap-definition-RKZ34NQL.1XcF8Wh2.js} +1 -1
  160. package/web/_astro/{pieDiagram-4H26LBE5.CJNSdqY7.js → pieDiagram-4H26LBE5.DnItHOdK.js} +1 -1
  161. package/web/_astro/{quadrantDiagram-W4KKPZXB.DtTy7_0Z.js → quadrantDiagram-W4KKPZXB.BQQyrnBt.js} +1 -1
  162. package/web/_astro/{requirementDiagram-4Y6WPE33.BNYV98Xg.js → requirementDiagram-4Y6WPE33.Dmzxun82.js} +1 -1
  163. package/web/_astro/{sankeyDiagram-5OEKKPKP.DRq9DGHp.js → sankeyDiagram-5OEKKPKP.BBIeRKYB.js} +1 -1
  164. package/web/_astro/{sequenceDiagram-3UESZ5HK.B7KdBFCm.js → sequenceDiagram-3UESZ5HK.CUNVdBBf.js} +1 -1
  165. package/web/_astro/{stateDiagram-AJRCARHV.CD62ZJ2H.js → stateDiagram-AJRCARHV.DlFf2sJm.js} +1 -1
  166. package/web/_astro/{stateDiagram-v2-BHNVJYJU.CeVk1TAj.js → stateDiagram-v2-BHNVJYJU.DXR7I1H5.js} +1 -1
  167. package/web/_astro/{timeline-definition-PNZ67QCA.C_ZPA5tT.js → timeline-definition-PNZ67QCA.BcO-GyX2.js} +1 -1
  168. package/web/_astro/{vennDiagram-CIIHVFJN.CrThO_FQ.js → vennDiagram-CIIHVFJN.ChCECmmW.js} +1 -1
  169. package/web/_astro/{wardleyDiagram-YWT4CUSO.DSZCA5nl.js → wardleyDiagram-YWT4CUSO.CRaT12mD.js} +1 -1
  170. package/web/_astro/{xychartDiagram-2RQKCTM6.KI7baTuk.js → xychartDiagram-2RQKCTM6.B3lsHVpj.js} +1 -1
  171. package/web/board-runtime.json +69 -0
  172. package/web/index.html +2 -2
  173. package/plugins/sp/lib/artifact-digest.generated.d.mts +0 -7
  174. package/plugins/sp/lib/artifact-digest.generated.mjs +0 -48
  175. package/plugins/sp/scripts/feature-sync-bounded.mjs +0 -298
  176. package/plugins/sp/scripts/feature-sync-bounded.ts +0 -479
  177. package/plugins/sp/scripts/idea-coverage-check.ts +0 -168
  178. package/plugins/sp/scripts/inline-pipeline-parity-check.ts +0 -298
  179. package/plugins/sp/scripts/record-feature-sync.mjs +0 -63
  180. package/plugins/sp/scripts/record-feature-sync.ts +0 -84
  181. package/plugins/sp/scripts/script-contract-check.ts +0 -377
  182. package/plugins/sp/scripts/stage-registry-adapter.ts +0 -1533
  183. package/plugins/sp/scripts/surface-drift-inventory.ts +0 -989
  184. package/plugins/sp/scripts/task-evidence-precheck.ts +0 -187
  185. package/plugins/sp/scripts/task-size-precheck.ts +0 -210
  186. package/plugins/sp/scripts/transition-shim-check.ts +0 -238
  187. package/plugins/sp/scripts/validate-commands.ts +0 -689
  188. package/plugins/sp/scripts/validate-flag-contracts.ts +0 -878
  189. package/plugins/sp/scripts/verify-answer-lint.ts +0 -547
  190. package/web/_astro/BoardApp.C02hAHPO.js +0 -1
  191. package/web/_astro/TaskDetail.C-GdsS-t.js +0 -1
  192. package/web/_astro/architectureDiagram-3BPJPVTR.CGe629A1.js +0 -36
  193. package/web/_astro/channel.fsgl7o5j.js +0 -1
  194. package/web/_astro/client.yhYJvxCU.js +0 -9
  195. package/web/_astro/cose-bilkent-S5V4N54A.2fH4YOlp.js +0 -1
  196. package/web/_astro/ganttDiagram-6RSMTGT7.DC_p36PI.js +0 -292
  197. package/web/_astro/index.De90oHcH.js +0 -1
  198. package/web/_astro/index.Hjbr15fG.css +0 -1
@@ -0,0 +1,83 @@
1
+ ---
2
+ description: Find and fix failing GitHub Actions runs — gh fetch → diagnose → root-cause fix → commit → push → re-verify until green
3
+ role: coder
4
+ argument-hint: "[<context>] [--max-retry <n>] [--no-push]"
5
+ allowed-tools: ["Bash", "Read", "Write", "Edit", "Grep", "Glob"]
6
+ ---
7
+
8
+ # Dev Fixgha
9
+
10
+ Self-contained all-in-one GitHub Actions repair loop (no backing skill): fetch failing runs with
11
+ `gh`, diagnose each from its failed-step log, fix the root cause locally, commit, push, and watch the
12
+ new runs — repeating until every in-scope workflow is green. Invoking this command is the operator's
13
+ explicit request to edit `.github/workflows/` when the root cause lives there.
14
+
15
+ ## Argument Flags
16
+
17
+ | Flag | Description | Default |
18
+ | --- | --- | --- |
19
+ | `<context>` | Free-text context and/or search filter: a workflow name or file, run ID/URL, PR number, branch, job/step name, or a hint about the failure. Narrows which runs are in scope and seeds the diagnosis. | latest failing run per workflow on the current branch |
20
+ | `--max-retry <n>` | Max fix → push → verify iterations before stopping with the remaining failures. | 3 |
21
+ | `--no-push` | Fix and commit locally but do not push or re-verify on GitHub. | off |
22
+
23
+ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag-glossary.md).
24
+
25
+ ## Usage
26
+
27
+ /sp:dev-fixgha [<context>] [--max-retry <n>] [--no-push]
28
+
29
+ ## Implementation
30
+
31
+ Execute the stages below in order. Parse `gh` output with `--json` / `--jq`; never scrape tables.
32
+ A stage that cannot succeed after `--max-retry` iterations stops the run with the specific failing
33
+ output — do not silently skip a real failure.
34
+
35
+ **1 — Preflight.** `gh auth status` must pass (otherwise stop and tell the operator to run
36
+ `! gh auth login`). Resolve the repo (`gh repo view --json nameWithOwner`), the current branch, and
37
+ `HEAD`. The working tree must be clean of unrelated changes (one writer per tree) — if it is not,
38
+ stop and report instead of mixing them into CI-fix commits.
39
+
40
+ **2 — Collect failing runs.** Build the in-scope set from `<context>`:
41
+
42
+ - run ID / URL → that run (`gh run view <id> --json databaseId,workflowName,headBranch,headSha,conclusion,jobs,url`);
43
+ - PR number → `gh pr checks <n> --json name,state,link,workflow` (failed checks only);
44
+ - workflow name/file → `gh run list --workflow <wf> --branch <branch> --limit 10 --json databaseId,workflowName,headSha,status,conclusion,event,url`;
45
+ - otherwise → `gh run list --branch <branch> --limit 30 --json …` and keep the **latest** run per
46
+ workflow whose `conclusion` is `failure`, `startup_failure`, or `timed_out`. An older failure
47
+ already superseded by a green run of the same workflow is out of scope.
48
+
49
+ Free text that is not an identifier narrows by workflow/job/step name and is carried into diagnosis.
50
+ If `actionlint` is on `PATH`, also run it over `.github/workflows/` and add its findings as
51
+ static issues. Nothing failing and no static findings → report "all GitHub Actions green" and stop.
52
+
53
+ **3 — Diagnose each failure.** Pull only the failing output: `gh run view <id> --log-failed`
54
+ (bounded — keep the tail around the first error per failed step, not the whole log). Classify:
55
+
56
+ | Class | Signal | Action |
57
+ | --- | --- | --- |
58
+ | Code | test / lint / typecheck / build error | Reproduce locally with the failing step's command, then fix the source. |
59
+ | Workflow | YAML / expression error, bad action ref or deprecated version, missing `permissions`, wrong runner/tool version, cache/path mismatch | Fix the workflow file minimally. |
60
+ | Environment | CI-only behavior (OS, root vs non-root, missing binary, timezone, case-sensitive FS) | Fix the code or workflow so both environments are correct — never weaken a correct test. |
61
+ | Transient | network/registry timeout, runner outage, rate limit, no code/workflow cause | `gh run rerun <id> --failed` once; if it fails again, reclassify. |
62
+ | External | missing/expired secret, repo setting, billing, third-party outage | Cannot be fixed from the tree — record and report for the operator. |
63
+
64
+ **4 — Fix.** Root cause only, surgical diff. Forbidden shortcuts: `continue-on-error`, `if: false`,
65
+ deleting or skipping jobs/steps/tests, loosening thresholds, `--no-verify`, force-push, and any edit
66
+ to secrets. After fixing, run the local quality gate (`bun run check`, or the project's equivalent);
67
+ if red, run `/sp:dev-fixall "<gate-command>"` before continuing.
68
+
69
+ **5 — Commit.** Follow the gitmsg procedure in
70
+ [dev-operations.md](../skills/spur-dev/references/dev-operations.md#9-gitmsg) to produce one
71
+ conventional commit per iteration (typically `fix(ci): …` for workflow changes, or the owning
72
+ `fix(<scope>): …` for code), whose body names the run IDs it addresses. Commit with the
73
+ repository's hooks enabled.
74
+
75
+ **6 — Push and re-verify.** Skip when `--no-push` (report the commits and stop). Otherwise
76
+ `git push` (set upstream if missing; on rejection, pull `--rebase` then retry — never force). Find
77
+ the runs for the pushed SHA (`gh run list --commit <sha> --json databaseId,workflowName,status,conclusion`;
78
+ poll briefly — runs can take a few seconds to appear), then `gh run watch <id> --exit-status` for
79
+ each in-scope workflow. Any new failure feeds back into stage 3. Stop when all in-scope workflows
80
+ are green or `--max-retry` iterations are spent.
81
+
82
+ **7 — Report.** One table: workflow · run ID · class · root cause · fix (`path:line`) · commit ·
83
+ final status. List External/unfixed items separately with the exact operator action required.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Generate conventional commit message(s) from the current change set via one bounded diff capture, optionally commit
2
+ description: Generate conventional commit message(s) from the current change set via one bounded gather call, optionally commit
3
3
  role: scribe
4
4
  argument-hint: "[--commit] [--squash] [--all] [--scope <path>]"
5
5
  allowed-tools: ["Bash", "Read"]
@@ -28,8 +28,10 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
28
28
 
29
29
  Follow the inline procedure in [dev-operations.md](../skills/spur-dev/references/dev-operations.md#9-gitmsg) (gitmsg).
30
30
 
31
- One diff capture per run — `-U0`, lockfiles excluded, 60 KB cap — is the token contract; never re-read
32
- the diff wider. Neither `--commit` nor `--squash` → messages only. `--commit` → one commit per concern, split automatically,
33
- so the operator is never asked to re-stage and re-run. `--squash` → one commit for everything.
34
- An empty index widens to the whole tree only on a message-only run, and says so; a committing run
35
- stops there and prints the exact `--all` re-run line instead of guessing.
31
+ One gather call per run (per-file-capped `-U0` diff including untracked content, recent subjects for
32
+ scope vocabulary, secret and partial-staging guards — git + shell only), then at most one commit call.
33
+ Never re-read the diff wider. Neither `--commit` nor `--squash` → messages only. `--commit` → one
34
+ commit per concern, split automatically, so the operator is never asked to re-stage and re-run.
35
+ `--squash` → one commit for everything. An empty index widens to the whole tree only on a
36
+ message-only run, and says so; a committing run stops there and prints the exact `--all` re-run line
37
+ instead of guessing.
@@ -63,8 +63,8 @@ Then stop the run (this stage failed). The operator can proceed by re-running wi
63
63
 
64
64
  **3 — Generate a conventional commit message.** Follow the gitmsg procedure (the same one
65
65
  `/sp:dev-gitmsg` runs) — see
66
- [dev-operations.md](../skills/spur-dev/references/dev-operations.md#9-gitmsg): one bounded diff
67
- capture, concern grouping, conventional `<type>(<scope>): <summary>` formatting. Two deviations
66
+ [dev-operations.md](../skills/spur-dev/references/dev-operations.md#9-gitmsg): one bounded gather
67
+ call, concern grouping, conventional `<type>(<scope>): <summary>` formatting. Two deviations
68
68
  belong to this flow: read the change set with `--all` semantics (this stage commits everything the
69
69
  gate just proved green, not only what happens to be staged), and resolve multiple concerns to a
70
70
  **single combined message** (dominant type/scope, one body bullet per concern) so the push is
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Turn a vague idea into a feature with AC and a decomposed task batch — discovery, idea-eval, feature-create, AC, feature-check, system-design, decompose, batch-create (Design by default), handoff
3
3
  role: planner
4
- argument-hint: "\"<idea>\" [--from-file <path>] [--auto] [--skip-design] [--approve-taste] [--agent <inline|auto|name>]"
4
+ argument-hint: "\"<idea>\" | --from-file <path> [--skip-design] [--agent <inline|auto|name>] [--auto]"
5
5
  allowed-tools: ["Bash", "Read", "Skill", "AskUserQuestion"]
6
6
  ---
7
7
 
@@ -16,29 +16,39 @@ contract below maps to that workflow's transitions.
16
16
  | --- | --- | --- |
17
17
  | `"<idea>"` | Vague idea to turn into a feature with AC and tasks. | required (or `--from-file`) |
18
18
  | `--from-file` `<path>` | Read the idea from a file instead of the positional argument. Mutually exclusive with `"<idea>"` — exactly one must be present. The file's contents become the verbatim idea text (trimmed of surrounding whitespace only). Useful for long or multiline asks that are awkward to quote. | off |
19
- | `--auto` | Skip objective HITL gates only (taste gates still pause). | off |
20
- | `--skip-design` | Omit system-design and per-task Design. | off |
21
- | `--approve-taste` | With `--auto`: set idea_approved + design_approved so idea-eval / design-approval do not pause. | off |
22
- | `--idea-approved` | Compatibility alias for idea_approved=true (subset of --approve-taste). | off |
23
- | `--design-approved` | Compatibility alias for design_approved=true (subset of --approve-taste). | off |
19
+ | `--skip-design` | Omit system-design (and its approval gate) and per-task Design. | off |
24
20
  | `--agent` `<inline\|auto\|name>` | Who runs the model-bearing ideation. Omission and `inline` drive `idea-pipeline.yaml` in this session with zero external agent/workflow processes; `auto` tier-resolves an executor and a name pins one, both through the async workflow worker. | inline |
21
+ | `--auto` | Accept the pipeline's recommendation at every operator gate (see below). | off |
25
22
 
26
23
  For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag-glossary.md).
27
24
 
28
25
  ## Usage
29
26
 
30
27
  ```
31
- /sp:dev-idea "<idea>"
32
- [--auto] # skip objective HITL only (feature-check, batch-create)
33
- [--skip-design] # design package off (system-design + task Design)
34
- [--approve-taste] # with --auto: skip idea-eval + design-approval pauses
28
+ /sp:dev-idea "<idea>" | --from-file <path>
29
+ [--skip-design] # design package off (system-design + task Design)
35
30
  [--agent <inline|auto|name>] # inline is the current session; auto/name are async workers
31
+ [--auto] # no operator pauses; follow each gate's recommendation
36
32
  ```
37
33
 
38
34
  There is **no** `--design` force flag. Design is default-on; only `--skip-design` opts out.
39
35
 
40
- **Aliases (one-release / scripts):** `--idea-approved` and `--design-approved` still map into the same
41
- vars as subsets of `--approve-taste` (`idea_approved` / `design_approved`). Prefer `--approve-taste`.
36
+ **Removed flags:** `--approve-taste`, `--idea-approved`, and `--design-approved` are folded into
37
+ `--auto`. If passed, ignore them with a one-line notice; do not treat them as `--auto`.
38
+
39
+ **Operator gates.** Every gate is asked as one `AskUserQuestion` [decision brief](../skills/spur-dev/references/decision-brief.md):
40
+ the recommended option first, then options with their reasoning. The operator picks; they never
41
+ type a yes/no. `--auto` takes the recommended option at each gate without asking.
42
+
43
+ | Gate | Pauses when | Recommendation comes from | `--auto` takes |
44
+ | --- | --- | --- | --- |
45
+ | idea-eval | after discovery | eval report `## Recommendation` (`proceed` / `reshape` / `drop`) | `proceed`/`reshape` → continue; `drop` → cancel; missing → still asks |
46
+ | feature-check | after AC | recorded AC check + requirement coverage | PASS → continue; FAIL → revise AC (cap 3) |
47
+ | design-approval | after system-design (skipped by `--skip-design`) | recorded design check | PASS → approve; FAIL → still asks |
48
+ | batch-create | after decompose | batch schema + task-order sidecar validation | create the batch |
49
+
50
+ Flag → vars: `--auto` sets `profile=auto`, `idea_approved=true`, `design_approved=true`;
51
+ `--skip-design` sets `design=skip`.
42
52
 
43
53
  ## Implementation
44
54
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Plan a feature from a description — intake → feature create → AC generation → feature check gate → decomposition → batch-create (Design by default)
3
3
  role: planner
4
- argument-hint: "\"<description>\" [--feature <id>] [--parent <feature-id>] [--agent <inline|auto|name>] [--skip-design] [--auto] [--approve-taste]"
4
+ argument-hint: "\"<description>\" [--feature <id>] [--parent <feature-id>] [--skip-design] [--agent <inline|auto|name>] [--auto]"
5
5
  allowed-tools: ["Bash", "Read", "Skill", "AskUserQuestion"]
6
6
  ---
7
7
 
@@ -18,8 +18,7 @@ Wraps the **sp:spur-dev** skill.
18
18
  | `--parent` `<feature-id>` | Create under a parent feature. | omitted |
19
19
  | `--agent` `<inline\|auto\|name>` | Who runs the model-bearing planning. Omission and `inline` drive `idea-pipeline.yaml` in this session with zero external agent/workflow processes; `auto` tier-resolves an executor and a name pins one, both through the async workflow worker. | inline |
20
20
  | `--skip-design` | Omit the system-design hop. | off |
21
- | `--auto` | Skip objective HITL gates. | off |
22
- | `--approve-taste` | With --auto: skip design-approval pause. | off |
21
+ | `--auto` | Accept the pipeline's recommendation at every operator gate (same gate table as `/sp:dev-idea`). | off |
23
22
 
24
23
  For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag-glossary.md).
25
24
 
@@ -27,18 +26,18 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
27
26
 
28
27
  ```
29
28
  /sp:dev-plan "<description>"
30
- [--feature <id>] [--parent <feature-id>] [--agent <inline|auto|name>]
31
- [--auto] # skip objective HITL where the plan path supports it
32
- [--skip-design] # design package off (satellite + task Design)
33
- [--approve-taste] # with --auto: skip design-approval taste pause when applicable
29
+ [--feature <id>] [--parent <feature-id>]
30
+ [--skip-design] # design package off (satellite + task Design)
31
+ [--agent <inline|auto|name>]
32
+ [--auto] # no operator pauses; follow each gate's recommendation
34
33
  ```
35
34
 
36
35
  **Design package (unified with `/sp:dev-idea`):** Design is **on by default**. Default fills
37
36
  per-task `### Design` in the batch and the feature satellite when the seam heuristic fires
38
37
  (ties lean **design**). There is **no** `--design` force flag — only **`--skip-design`** opts out.
39
38
 
40
- **Taste re-entry:** `--approve-taste` is the same flag as on `dev-idea` (sets prior design approval
41
- for taste gates). Alias: `--design-approved` (prefer `--approve-taste`).
39
+ **Removed flags:** `--approve-taste` and `--design-approved` are folded into `--auto` (same
40
+ contract as `/sp:dev-idea`). If passed, ignore them with a one-line notice.
42
41
 
43
42
  ## Implementation
44
43
 
@@ -1,8 +1,8 @@
1
1
  ---
2
- description: "Review code for a task or path — multi-dimensional review across functional traceability, SECUA quality, and architectural depth. With --triage: fix small findings directly, then file the rest as implement-ready tasks. Triggers: \"review this\", \"check the code\", \"SECUA review\", \"dev review\", \"audit this\", \"triage review findings\"."
2
+ description: "Review code for a task set or paths — multi-dimensional review across functional traceability, SECUA quality, and architectural depth. With --triage: fix small findings directly, then file the rest as implement-ready tasks. Triggers: \"review this\", \"check the code\", \"SECUA review\", \"dev review\", \"audit this\", \"triage review findings\"."
3
3
  role: reviewer
4
- argument-hint: "[<wbs|path>] [--agent <inline|auto|name>] [--focus <dims>] [--triage] [--worktree [<name>]]"
5
- allowed-tools: ["Bash", "Read", "Skill"]
4
+ argument-hint: "[--tasks <selector> | --feature <id>[,<id>] | --scope <path>[,<path>]] [--agent <inline|auto|name>] [--focus <dims>] [--triage] [--worktree [<name>]] [--auto]"
5
+ allowed-tools: ["Bash", "Read", "Skill", "Edit", "Write"]
6
6
  ---
7
7
 
8
8
  # Dev Review
@@ -13,19 +13,24 @@ Wraps the **sp:functional-review**, **sp:code-verification**, and **sp:code-impr
13
13
 
14
14
  | Flag | Description | Default |
15
15
  | --- | --- | --- |
16
- | `[<wbs\|path>]` | Task WBS or source path to review. | cwd |
16
+ | `--tasks <selector>` | Review a task set — batch selector grammar ([execution-batch.md § Step 1](../skills/spur-dev/references/execution-batch.md#step-1--selector-resolution-r1)): comma WBS list or `feature:<id>`; status pseudo-lists and `ready` are rejected for review (they select work to do, not work to review). Resolved once, frozen; one WBS-mode review per task, each writing its own merged `## Review`; the run ends with a combined summary table (WBS, verdict, P1/P2 counts). | — |
17
+ | `--feature <id>[,<id>]` | Sugar for the union of the `feature:<id>` sets — resolved once, frozen, then reviewed as `--tasks`. | — |
18
+ | `--scope <path>[,<path>]` | Advisory review of the tracked files under one or more paths: paths must exist (exit 2 otherwise), are normalized, duplicates dropped and nested paths collapse to the ancestor (`--scope apps,apps/cli` → `apps`); one sub-review per path, one merged report with a cross-path architecture pass; no task mutation. | — |
19
+ | `[<wbs\|path>]` | **Deprecated positional alias** (one release): a `^\d{4}$` token with a resolvable task → `--tasks <wbs>`; an existing path → `--scope <path>`; otherwise exit 2. Prints a deprecation warning naming the replacement. | — |
17
20
  | `--agent` `<inline\|auto\|name>` | Who runs the model-bearing review. | omit |
18
- | `--focus` `<dims>` | Review dimensions (functional / SECUA / architecture). | all |
19
- | `--triage` | After the review: fix small findings directly, file the rest as one or more implement-ready tasks. | off (report-only) |
20
- | `--worktree` `[<name>]` | Run the triage in an isolated git worktree; FF-merge on success, retain on failure. Bare `--worktree` creates a fresh tree; `--worktree <name>` adopts an existing worktree by name/path/branch. Requires `--triage`. | off |
21
+ | `--focus` `<dims>` | Review dimensions — vocabulary and skill routing: [code-verification/SKILL.md](../skills/code-verification/SKILL.md) review mode (SSOT). | all |
22
+ | `--triage` | After the review: bucket findings across all targets once (identical `file:line` findings deduped), fix small findings directly, file the rest as one or more implement-ready tasks. | off (report-only) |
23
+ | `--worktree` `[<name>]` | Run the triage in an isolated git worktree; FF-merge on success, retain on failure. Bare `--worktree` creates a fresh tree; `--worktree <name>` adopts an existing worktree by name/path/branch. Multi-target aware (below). Requires `--triage`. | off |
24
+ | `--auto` | Skip objective HITL confirmations. | off |
21
25
 
22
26
  For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag-glossary.md).
23
27
 
24
28
  ## Usage
25
29
 
26
30
  ```
27
- /sp:dev-review [<wbs|path>] [--agent <inline|auto|name>] [--focus <dims>] [--triage] [--worktree [<name>]]
28
- /sp:dev-review scripts --triage
31
+ /sp:dev-review [--tasks <selector> | --feature <id>[,<id>] | --scope <path>[,<path>]] [--agent <inline|auto|name>] [--focus <dims>] [--triage] [--worktree [<name>]] [--auto]
32
+ /sp:dev-review --tasks 0962,0963 --triage
33
+ /sp:dev-review --scope apps,packages,plugins,scripts
29
34
  /sp:dev-review 0962 --triage --worktree
30
35
  ```
31
36
 
@@ -34,10 +39,14 @@ Put the target first: a bare token after `--worktree` is read as the worktree na
34
39
  ## Implementation
35
40
 
36
41
  - Apply the [inline-default execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface).
37
- - WBS mode (`<wbs>`): `Skill(skill="sp:functional-review", args="<wbs> $ARGUMENTS")` + `Skill(skill="sp:code-verification", args="review $ARGUMENTS")` + `Skill(skill="sp:code-improvement", args="<wbs> $ARGUMENTS")` (functional traceability + SECUA framework + architectural depth; the three skills return review fragments and the coordinator (`sp:super-reviewer`) writes the combined `## Review` — F92 0593 R1)
38
- - Path mode (`<path>`): `Skill(skill="sp:code-verification", args="review $ARGUMENTS")` + `Skill(skill="sp:code-improvement", args="<path> $ARGUMENTS")` (advisory SECUA quality + architectural depth; performs no task mutation)
39
- - `--triage`: after the review returns, run the triage protocol in [dev-operations.md § 2. review](../skills/spur-dev/references/dev-operations.md#2-review) **inline in this session** — the review skills and `sp:super-reviewer` stay report-only.
42
+ - **Selector validation (before any review runs).** Exactly one target kind per invocation: `--tasks`, `--feature`, or `--scope`. More than one → exit 2 naming the conflicting selectors (a positional beside an explicit selector is a second target kind → exit 2); none (and no positional) → exit 2 with usage — there is no implicit `cwd` target. The set is resolved once and frozen through the [execution-batch.md § Step 1](../skills/spur-dev/references/execution-batch.md#step-1--selector-resolution-r1) batch resolver — no review-specific parser; `--feature <id>[,<id>]` is sugar for the union of the `feature:<id>` sets.
43
+ - **WBS mode (per task target):** `Skill(skill="sp:functional-review", args="<wbs> $FLAGS")` + `Skill(skill="sp:code-verification", args="review <wbs> $FLAGS")` + `Skill(skill="sp:code-improvement", args="<wbs> $FLAGS")` (functional traceability + SECUA framework + architectural depth — each skill receives its one resolved WBS exactly once plus `$FLAGS` = `$ARGUMENTS` minus the selector (`--tasks`/`--feature`/`--scope` or positional) and its value, never the raw selector, and returns a review fragment only — F92 0593 R1)
44
+ - **Task fan-out (`--tasks` / `--feature`).** One WBS-mode review per task in the frozen set. Tasks in `backlog`/`todo`/`blocked` are reported NOT-STARTED and skipped (§ 3a outcome vocabulary); a per-task failure does not stop the remaining tasks. Each implemented task gets its own merged `## Review`; the run ends with a combined summary table (WBS, verdict, P1/P2 counts).
45
+ - Coordinator = this session. No `sp:super-reviewer` subagent is dispatched: act as the review coordinator defined in [agents/super-reviewer.md](../agents/super-reviewer.md) — merge the fragments per its Output Format (native `P1`–`P4` priority cells, section-relative headings) and, for every task target (standalone or pipeline), write that task's combined `## Review` via `spur task update <wbs> --section Review --from-file`. Path mode emits advisory output only.
46
+ - **Path mode (per path target):** `Skill(skill="sp:code-verification", args="review <path> $FLAGS")` + `Skill(skill="sp:code-improvement", args="<path> $FLAGS")` (advisory SECUA quality + architectural depth — one normalized path forwarded once plus `$FLAGS`; performs no task mutation). Under `--scope <path>[,<path>]`: paths must exist (exit 2 otherwise), are normalized, duplicates dropped and nested paths collapse to the ancestor (`--scope apps,apps/cli` → `apps`); each surviving path gets a sub-review (Step 3p path scope), eligible for native-subagent dispatch per [dispatch-surface.md](../skills/parallel-execution/references/dispatch-surface.md); the coordinator merges the sub-reviews, runs **one** cross-path architecture pass (`sp:code-improvement` over the inter-path imports), and emits **one** advisory report. No task mutation.
47
+ - **Positional alias (deprecated).** A positional `<wbs|path>` is accepted for one release: a `^\d{4}$` token with a resolvable task behaves as `--tasks <wbs>`; an existing path as `--scope <path>`; otherwise exit 2. Print a deprecation warning naming the replacement selector; removal is a follow-up.
48
+ - `--triage`: after the review returns, run the triage protocol in [dev-operations.md § 2. review](../skills/spur-dev/references/dev-operations.md#2-review) **inline in this session** — the review skills and `sp:super-reviewer` stay report-only. With multiple targets, bucket the findings across all targets once (identical `file:line` findings deduped before bucketing). `Edit`/`Write` in `allowed-tools` exist only for these direct fixes.
40
49
  - Without `--worktree`, every write lands in the current working tree on the current branch: no branch creation, no checkout, no commit.
41
- - `--worktree [<name>]`: the [execution-batch.md § Worktree isolation](../skills/spur-dev/references/execution-batch.md#worktree-isolation---worktree-name) lifecycle as a run of one (marker `command` = `dev-review`, `selector` = the target). Rejected without `--triage`.
50
+ - `--worktree [<name>]`: the [execution-batch.md § Worktree isolation](../skills/spur-dev/references/execution-batch.md#worktree-isolation---worktree-name) lifecycle as a run of one (marker `command` = `dev-review`, `selector` = the full normalized target list). Admission requires every target to resolve before the tree is cut. Branch slug: `sp/review-<first>-and-<N>-<short-id>` for a multi-target run (N = target count), `sp/review-<slug>-<short-id>` for a single target (the WBS or the path's basename). Rejected without `--triage`.
42
51
  While it runs, fixes and filed tasks land in the worktree copy; the main tree shows them only after the FF-merge.
43
52
  - `--fix`: Deprecated (still accepted: no-op + warning; route remediation to `--triage` or `/sp:dev-verify --fix`). **`--next` removed** (feature H8, 2026-07-31) — it was a deprecated no-op; route progression to `/sp:dev-next`. **was: `--next` deprecated no-op.**
@@ -40,10 +40,13 @@ See `sp:code-verification` § Shippable readiness gate.
40
40
 
41
41
  - Apply the [inline-default execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface).
42
42
  - `Skill(skill="sp:code-verification", args="verify $ARGUMENTS")`
43
- - **Residual sweep (F96 R1):** after the verify answer is written and `task verdict` derives
44
- `.spur/run/<wbs>-verdict.json`, run `residual-scan scan` + `fold` (observe-only; folds the
45
- verdict's `residual-sweep` check, PASS → PARTIAL when a blocking residual exists) — under every
46
- `--fix` mode — before `spur task record`. Resolve the script via `superskill script path sp
43
+ - **Residual sweep (F96 R1, post-record since 0987):** after `task verdict` derives
44
+ `.spur/run/<wbs>-verdict.json` and `spur task record` has flipped the verdict-proven R/AC boxes,
45
+ run `residual-scan scan` + `fold` (observe-only; folds the verdict's `residual-sweep` check,
46
+ PASS → PARTIAL when a blocking residual exists) — under every `--fix` mode — then, only on a
47
+ downgrade, re-run `spur task record <wbs> --verdict-file .spur/run/<wbs>-verdict.json` so Testing
48
+ carries the final verdict. Same order as the pipeline `record` state (0983): scanning before
49
+ record reads unticked-but-proven boxes and folds a clean PASS to PARTIAL. Resolve the script via `superskill script path sp
47
50
  residual-scan.mjs`; never reference `plugins/sp/scripts/` in shipped surfaces
48
51
  (script-contract-check rule 4). When the task reaches `done` through `--next`, run
49
52
  `residual-scan settle` (best-effort). On a folded PARTIAL: the bounded remediation loop has
@@ -49,7 +49,7 @@ the FF-merge on success. Expected, not a bug.
49
49
 
50
50
  **`--next` (per-task lifecycle chaining):** `--next`
51
51
  is chain-to-completion with propagation. For each task whose verdict is **PASS**, the chain's first
52
- hop transitions `testing → done` through the FSM with the `--strict-core` Review L3 guard honored;
52
+ hop transitions `testing → done` through the FSM with the `--as done` Review L3 guard honored;
53
53
  a task whose verdict is **PARTIAL** or **FAIL** does **not** transition (it stays `testing` as
54
54
  review-pending) — that task's chain halts, reporting the verdict. One task's non-PASS never blocks
55
55
  another task's transition — each task's verdict is its own, and each task's chain is independent.
@@ -72,8 +72,9 @@ Without `--fix all`, shippable is not evaluated (optional note: use `--fix all`
72
72
  - Batch orchestration: `Skill(skill="sp:spur-dev", args="verifyall $ARGUMENTS")`
73
73
  - Per-task verification (inner): `Skill(skill="sp:code-verification", args="verify <wbs> $SHARED_FLAGS")`
74
74
  - Shippable gate: once after the batch (same skill § Shippable readiness gate)
75
- - **Residual sweep (F96 R1, per task):** same contract as `/sp:dev-verify` — after each task's
76
- verdict artifact is derived, run `residual-scan scan` + `fold` (under every `--fix` mode) before
77
- `spur task record`; on reaching `done` via `--next`, run `settle`. Script resolution:
75
+ - **Residual sweep (F96 R1, per task, post-record since 0987):** same contract as
76
+ `/sp:dev-verify` — after each task's verdict artifact is derived and `spur task record` has
77
+ flipped its verdict-proven boxes, run `residual-scan scan` + `fold` (under every `--fix` mode),
78
+ and re-record only on a downgrade; on reaching `done` via `--next`, run `settle`. Script resolution:
78
79
  `superskill script path sp residual-scan.mjs` (never `plugins/sp/scripts/` —
79
80
  script-contract-check rule 4).
@@ -17,7 +17,7 @@ Wraps the **wrapup-pipeline.yaml** workflow.
17
17
  | `--agent` `<inline\|auto\|name>` | Who runs the wrap's model-bearing steps. Wrap is workflow-backed (headless): `omit` and `--agent inline` resolve identically per task 0687 — tier substitution under objective trigger 3 (durable auditable run record required) with a warning naming the substituted executor; `auto` tier-resolves an executor; a name pins that executor into `vars.agent`. | inline |
18
18
  | `--auto` | Skip objective HITL gates. | off |
19
19
  | `--merge` | Merge the wrap branch. | off |
20
- | `--dry-run` | Render the wrap without writing. | off |
20
+ | `--dry-run` | Validate and walk transitions without executing actions. Conditional states therefore resolve to their declared failure edges (their guard files are never written), so a render ending in `failed` is **not** a run failure — it reports "this state's route cannot be decided without running it". Use a real run to preview a route. | off |
21
21
 
22
22
  For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag-glossary.md).
23
23
 
@@ -7,7 +7,7 @@ allowed-tools: ["Bash", "Read", "Write", "Skill"]
7
7
 
8
8
  # Spur Init
9
9
 
10
- Wraps **spur init** (deterministic scaffold) + **sp:doc-evolve** (project customization).
10
+ Wraps **spur self init** (deterministic scaffold) + **sp:doc-evolve** (project customization).
11
11
 
12
12
  ## Usage
13
13
 
@@ -16,7 +16,7 @@ Wraps **spur init** (deterministic scaffold) + **sp:doc-evolve** (project custom
16
16
  ## Implementation
17
17
 
18
18
  ```bash
19
- spur init --json $ARGUMENTS
19
+ spur self init --json $ARGUMENTS
20
20
  ```
21
21
  - Parse the JSON envelope once and retain it as `scaffoldResult`; summarize its created/skipped files in one block.
22
22
  - Customize (Phase 2): `Skill(skill="sp:doc-evolve", args="customize --project <scaffoldResult.project>")`.
@@ -34,7 +34,7 @@ export const REDACTION_CAP_BYTES = 4096;
34
34
  /** Max command/pattern summary length before ellipsis (chars). */
35
35
  export const SUMMARY_MAX_CHARS = 200;
36
36
 
37
- interface ToolPayload {
37
+ export interface ToolPayload {
38
38
  session_id?: string;
39
39
  tool_name?: string;
40
40
  tool_input?: {
@@ -115,7 +115,7 @@ export function redactText(text: string, capBytes: number = REDACTION_CAP_BYTES)
115
115
  if (bytes.length <= capBytes) return s;
116
116
  // Truncate on byte boundary then append marker
117
117
  let end = capBytes;
118
- while (end > 0 && (bytes[end] & 0xc0) === 0x80) end--;
118
+ while (end > 0 && ((bytes[end] ?? 0) & 0xc0) === 0x80) end--;
119
119
  return `${new TextDecoder().decode(bytes.subarray(0, end))}…[truncated]`;
120
120
  }
121
121
 
@@ -126,6 +126,7 @@ export function recordSessionStart(
126
126
  dir: string,
127
127
  env: NodeJS.ProcessEnv = getEnvVars(),
128
128
  now: () => Date = () => new Date(),
129
+ agentFallback?: string,
129
130
  ): string | null {
130
131
  try {
131
132
  mkdirSync(dir, { recursive: true });
@@ -140,7 +141,7 @@ export function recordSessionStart(
140
141
  const pad = (n: number) => String(n).padStart(2, '0');
141
142
  const sessionId = `session-${at.toISOString().slice(0, 10)}-${pad(at.getHours())}${pad(at.getMinutes())}`;
142
143
  const ts = at.toISOString();
143
- const agent = resolveAgentHint(env);
144
+ const agent = resolveAgentHint(env, agentFallback);
144
145
  const model = resolveModelHint(env);
145
146
 
146
147
  const sessionBody: Record<string, unknown> = {
@@ -49,30 +49,30 @@ function computeSessionTotals(
49
49
  return { reads, writes, tokens };
50
50
  }
51
51
 
52
- function exitOk(): never {
53
- process.exit(0);
54
- }
55
-
56
- async function main(): Promise<void> {
57
- const dir = join(getEnvVar('CLAUDE_PROJECT_DIR') ?? process.cwd(), '.spur', 'context');
58
-
52
+ /**
53
+ * Finalize one session (task 0969 R3): read the `.session.json` pointer, compute the session's
54
+ * rollup totals, append the `session_end` row, remove the pointer (best-effort) and return the
55
+ * event. Shared by this hook's entrypoint and Pi's `session_shutdown` so both hosts roll up
56
+ * identically. Returns null on every fail-open path.
57
+ */
58
+ export function recordSessionEnd(dir: string, now: () => Date = () => new Date()): Record<string, unknown> | null {
59
59
  const sessionFile = join(dir, '.session.json');
60
- if (!existsSync(sessionFile)) exitOk();
60
+ if (!existsSync(sessionFile)) return null;
61
61
 
62
62
  let sessionId = '';
63
63
  try {
64
64
  const session = JSON.parse(readFileSync(sessionFile, 'utf-8')) as { session?: string };
65
65
  sessionId = session.session ?? '';
66
66
  } catch {
67
- exitOk();
67
+ return null;
68
68
  }
69
69
 
70
- if (!sessionId) exitOk();
70
+ if (!sessionId) return null;
71
71
 
72
72
  const totals = computeSessionTotals(join(dir, 'token-ledger.jsonl'), sessionId);
73
73
 
74
74
  const event = {
75
- ts: new Date().toISOString(),
75
+ ts: now().toISOString(),
76
76
  session: sessionId,
77
77
  type: 'session_end' as const,
78
78
  totals,
@@ -81,7 +81,7 @@ async function main(): Promise<void> {
81
81
  try {
82
82
  appendFileSync(join(dir, 'token-ledger.jsonl'), `${JSON.stringify(event)}\n`);
83
83
  } catch {
84
- exitOk();
84
+ return null;
85
85
  }
86
86
 
87
87
  try {
@@ -90,7 +90,15 @@ async function main(): Promise<void> {
90
90
  // cleanup is best-effort
91
91
  }
92
92
 
93
- exitOk();
93
+ return event;
94
94
  }
95
95
 
96
- void main().catch(exitOk);
96
+ // Entrypoint: run the shared core, then exit 0 (fail-open) as this hook always has.
97
+ if (import.meta.main) {
98
+ try {
99
+ recordSessionEnd(join(getEnvVar('CLAUDE_PROJECT_DIR') ?? process.cwd(), '.spur', 'context'));
100
+ } catch {
101
+ /* fail-open: every error path exits 0 */
102
+ }
103
+ process.exit(0);
104
+ }