@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
@@ -7,7 +7,7 @@
7
7
  "plugins": [
8
8
  {
9
9
  "name": "sp",
10
- "version": "0.3.94",
10
+ "version": "0.3.96",
11
11
  "source": "./plugins/sp"
12
12
  }
13
13
  ]
package/README.md CHANGED
@@ -59,6 +59,21 @@ If `~/.local/bin` isn't already on your `PATH`, add it (e.g. `export PATH="$HOME
59
59
  in your shell profile). Supported targets: `darwin-arm64`, `darwin-x64`, `linux-arm64`, `linux-x64`.
60
60
  Windows: use the Bun path under WSL.
61
61
 
62
+ **Verification.** The installer downloads to a temp file, checks it against the release's
63
+ `SHA256SUMS`, and only then atomically replaces `spur`. A failed download, a checksum mismatch, or a
64
+ missing `SHA256SUMS` leaves an existing install untouched and exits non-zero. `SPUR_RELEASE_URL`
65
+ overrides the download base URL (a mirror, or a `file://` directory in tests).
66
+
67
+ The checksum is a **code-execution** boundary, not just an integrity check: having verified the
68
+ download, the installer *runs* it (`spur init`), so a release whose `SHA256SUMS` cannot be verified
69
+ is a release you cannot safely install. `SPUR_SKIP_VERIFY=1` is the single explicit bypass and
70
+ prints a warning — keep it for local or air-gapped installs, and pipe the script into `sh` only from
71
+ a source you trust.
72
+
73
+ **Releasing standalone binaries.** Run `bun run build:binaries` in `apps/cli`, then upload **all**
74
+ of `dist/cli/spur-*` **and** `dist/cli/SHA256SUMS` to the GitHub Release for the tag. A release
75
+ without `SHA256SUMS` makes the installer fail by default.
76
+
62
77
  ### Package layout (what ships)
63
78
 
64
79
  The published tarball is a self-contained Bun bundle plus static assets:
@@ -98,6 +113,33 @@ spur status
98
113
 
99
114
  Every command supports `--json` for machine-readable output.
100
115
 
116
+ ### Extending the Spur Board
117
+
118
+ A project can add its own Board modules — a compiled React tool or an embedded URL app — without
119
+ editing this package. An installed Board reads them from a fresh project's `.spur/config.yaml`:
120
+
121
+ ```yaml
122
+ bootstrap:
123
+ modules:
124
+ - id: team-board
125
+ name: Team board
126
+ icon: "🧭"
127
+ type: react
128
+ directory: board/team-board/dist
129
+ entry: index.js
130
+ styles: [index.css]
131
+ - id: docs
132
+ name: Documentation
133
+ icon: "📚"
134
+ type: iframe
135
+ url: https://docs.example.test/
136
+ ```
137
+
138
+ `spur init` seeds `modules: []` (built-ins only); change selection with a config edit, then restart
139
+ `spur serve` and reload. The full authoring contract — the declaration union, the
140
+ `@gobing-ai/spur/board` type export, the Vite library setup and the frame/trust limits — is in the
141
+ [downstream Board modules design](https://github.com/gobing-ai/spur/blob/main/docs/design/downstream-board-modules.md).
142
+
101
143
  ## Documentation
102
144
 
103
145
  Full docs, architecture, and the complete command surface live in the
@@ -0,0 +1,38 @@
1
+ // Generated by scripts/commands/emit-board-types.ts from
2
+ // apps/web/src/modules/contribution.ts — edit the authoring source, then regenerate.
3
+ import type { ComponentType } from 'react';
4
+ /**
5
+ * Public authoring contract for a native (compiled React) Board module contribution
6
+ * (A8 / task 0988 R1).
7
+ *
8
+ * This file is the ONE authoring source for the declaration-only `@gobing-ai/spur/board`
9
+ * package export: `scripts/commands/emit-board-types.ts` emits `apps/cli/board/index.d.ts`
10
+ * from it, so the published ABI cannot drift from the Board's own types. Keep it
11
+ * type-only — no React *value* import may reach the CLI or plugin artifacts (the CLI
12
+ * ships no React; the contributor supplies compatible React types through its own
13
+ * devDependencies).
14
+ *
15
+ * Module metadata (id/name/icon/route) is deliberately absent: it is project
16
+ * configuration (one selection authority), while this shape carries only what the
17
+ * renderer needs to mount a contribution.
18
+ */
19
+ export interface BoardModuleContribution {
20
+ /** Contribution protocol version this Board accepts. */
21
+ readonly apiVersion: 1;
22
+ /**
23
+ * Workspace component. Rendered inside the Board's React tree with the Board's own
24
+ * React instance — it must not call `createRoot`, and no private Board context is
25
+ * exported to it.
26
+ */
27
+ readonly component: ComponentType;
28
+ /** Optional companion the Board's right panel renders while this module is active. */
29
+ readonly rightPanelComponent?: ComponentType;
30
+ }
31
+ /**
32
+ * The named export a native Board module entry must publish.
33
+ *
34
+ * Declared rather than implemented: `@gobing-ai/spur/board` is a declaration-only export,
35
+ * not a runtime SDK (consumers import its types; their compiled ESM entry exports this
36
+ * name for the renderer).
37
+ */
38
+ export declare const webModule: BoardModuleContribution;
@@ -26,11 +26,6 @@
26
26
  "contract": "standard",
27
27
  "twin": "dogfood-testing/validate-report.mjs"
28
28
  },
29
- {
30
- "rel": "feature-sync-bounded.ts",
31
- "contract": "standard",
32
- "twin": "feature-sync-bounded.mjs"
33
- },
34
29
  {
35
30
  "rel": "idea-handoff.ts",
36
31
  "contract": "standard",
@@ -61,24 +56,11 @@
61
56
  "contract": "standard",
62
57
  "twin": "feature-verification-steps.mjs"
63
58
  },
64
- {
65
- "rel": "idea-coverage-check.ts",
66
- "contract": "repo-only"
67
- },
68
- {
69
- "rel": "inline-pipeline-parity-check.ts",
70
- "contract": "repo-only"
71
- },
72
59
  {
73
60
  "rel": "pr-reviewing.ts",
74
61
  "contract": "standard",
75
62
  "twin": "pr-reviewing.mjs"
76
63
  },
77
- {
78
- "rel": "record-feature-sync.ts",
79
- "contract": "standard",
80
- "twin": "record-feature-sync.mjs"
81
- },
82
64
  {
83
65
  "rel": "quality-gate.ts",
84
66
  "contract": "standard",
@@ -90,46 +72,15 @@
90
72
  "twin": "residual-scan.mjs"
91
73
  },
92
74
  {
93
- "rel": "script-contract-check.ts",
94
- "contract": "repo-only"
95
- },
96
- {
97
- "rel": "stage-registry-adapter.ts",
98
- "contract": "repo-only"
99
- },
100
- {
101
- "rel": "surface-drift-inventory.ts",
102
- "contract": "repo-only"
75
+ "rel": "script-root.ts",
76
+ "contract": "standard",
77
+ "twin": "script-root.mjs"
103
78
  },
104
79
  {
105
80
  "rel": "task-diffstat.ts",
106
81
  "contract": "standard",
107
82
  "twin": "task-diffstat.mjs"
108
83
  },
109
- {
110
- "rel": "task-evidence-precheck.ts",
111
- "contract": "repo-only"
112
- },
113
- {
114
- "rel": "task-size-precheck.ts",
115
- "contract": "repo-only"
116
- },
117
- {
118
- "rel": "verify-answer-lint.ts",
119
- "contract": "repo-only"
120
- },
121
- {
122
- "rel": "transition-shim-check.ts",
123
- "contract": "repo-only"
124
- },
125
- {
126
- "rel": "validate-commands.ts",
127
- "contract": "repo-only"
128
- },
129
- {
130
- "rel": "validate-flag-contracts.ts",
131
- "contract": "repo-only"
132
- },
133
84
  {
134
85
  "rel": "workflow-step-profile.ts",
135
86
  "contract": "standard",
@@ -0,0 +1,19 @@
1
+ $schema: "@gobing-ai/spur/schemas/rule-file.schema.json"
2
+ # [boundary] ADR-130 script placement contract (task 1000). Runs the fast
3
+ # --placement-only mode of the relocated script-contract-check on every
4
+ # recommended-pre-check; SKIPs outside the Spur source repo (same pattern as
5
+ # strict/rule-files-structural.yaml SKIP on missing yq). The full twin check
6
+ # stays in spur-check-feature.
7
+ rules:
8
+ - id: sp-script-placement
9
+ description: "Plugins/sp scripts must honor the ADR-130 placement contract (glue budget, no db imports, no corpus parsing, no noun clash); baseline config/script-placement-baseline.json can only shrink."
10
+ severity: error
11
+ evaluator:
12
+ type: exit-code
13
+ config:
14
+ command: sh
15
+ args:
16
+ - -c
17
+ - >-
18
+ [ -f scripts/commands/script-contract-check.ts ] || { echo "SKIP: not the Spur source repo"; exit 0; };
19
+ bun scripts/commands/script-contract-check.ts --placement-only
@@ -32,6 +32,9 @@ rules:
32
32
  - "**/tests/**"
33
33
  - "**/*.test.ts"
34
34
 
35
+ # Low-level system primitives:
36
+ - "packages/app/src/services/quality-gate.ts" # gate runs `sh -c` with stdout+stderr merged onto ONE fd; ProcessExecutor captures streams separately and cannot reproduce the stream-order contract (task 1006 R1; mirrors the history-anatomy bundling exemptions)
37
+
35
38
  - id: no-direct-fs-io
36
39
  description: "Prefer ts-runtime's FileSystem seam for fs IO."
37
40
  severity: warning
@@ -60,9 +63,11 @@ rules:
60
63
  - "packages/app/src/services/slash-commands-service.ts" # synchronous ~/.config/spur/slash_commands.json persistence (mirrors project-registry.ts)
61
64
  - "packages/app/src/services/agent-usage-producer.ts" # atomic agent-usage snapshot write (tmp + rename, mirrors project-registry.ts; task 0892 R1)
62
65
  - "packages/app/src/services/history-service.ts" # versioned analyze artifact + bounded-errors sidecar + latest.json symlink pointer (task 0474); ts-runtime FileSystem seam has no symlink, so the pointer uses node:fs directly (mirrors project-registry.ts persistence exemption)
66
+ - "packages/app/src/services/history-anatomy.ts" # deterministic history-anatomy cache core (task 1005 R2): fsync'd tmp+rename atomic publish, readdir digest scans and sync report reads must stay byte-stable; bundled standalone for the bare-node plugin twin (mirrors agent-usage-producer.ts / history-service.ts exemptions)
63
67
  - "packages/app/src/observability/workflow-run-log-sink.ts" # sync FD append for mid-run tail-able all-in-one run log (task 0426 / feature D2); append() is sync from the observability bus
64
68
  - "apps/cli/src/commands/workflow.ts" # FD byte-window tail of the mid-run run log for `workflow trace --follow` streaming (task 0428 / feature D2); readSync at offset over the observability sink's FDs
65
69
  - "apps/web/src/modules/discover.ts" # Vite/Astro module scanner fallback under bun test
70
+ - "packages/app/src/services/quality-gate.ts" # gate artifacts (log/findings/receipt) written directly; merged-fd gate log and fsync-free atomic writes must stay byte-stable; bundled standalone for the bare-node plugin twin (task 1006 R1; mirrors history-anatomy.ts)
66
71
 
67
72
  # Synchronous bootstrap & path resolution:
68
73
  - "packages/config/src/bundled-config.ts" # sync bundledConfigRoot() directory walk
@@ -36,6 +36,8 @@ rules:
36
36
  - "apps/**/src/**/*.ts"
37
37
 
38
38
  exclude:
39
+ ## transient CLI test-fixture projects (apps/cli/tests/.tmp-*), same pattern as .gitignore
40
+ - "**/.tmp-*/**"
39
41
  - "**/index.ts"
40
42
  - "**/*.d.ts"
41
43
  - "**/types.ts"
@@ -12,7 +12,7 @@ $schema: "@gobing-ai/spur/schemas/rule-file.schema.json"
12
12
  # replaced the very portability the tests were supposed to verify.
13
13
  #
14
14
  # SCOPE / discriminator: mocking the subprocess boundary to control *subprocess
15
- # responses* (e.g. feature-sync-bounded.test.ts intercepting `show`/`list`/`sync`
15
+ # responses* (e.g. a boundary test intercepting `show`/`list`/`sync`
16
16
  # commands) is legitimate and NOT flagged — the boundary mock returns canned
17
17
  # responses, it does not re-implement the syscall the code under test calls. The
18
18
  # rule fires only when the mock handler itself references `stat`/`%m`/`birthtime`
@@ -2,8 +2,9 @@ $schema: "@gobing-ai/spur/schemas/rule-file.schema.json"
2
2
  # Output boundary rules — terminal writes go through the output seam
3
3
  # (apps/cli/src/output.ts → ts-utils echo/echoError), never raw console/stdout.
4
4
  # Absorbed from ts-libs/.spur/rules/typescript/no-raw-output.yaml, re-scoped to
5
- # the app-monorepo layout. Spur's only sanctioned sink is the ts-utils helper,
6
- # so no local exclusions are needed.
5
+ # the app-monorepo layout. Spur's only sanctioned sink is the ts-utils helper;
6
+ # narrow per-rule excludes exist only for moved driver code whose byte-stable
7
+ # stdout contract must survive lib bundling under bare node (task 1006).
7
8
  include:
8
9
  - "apps/**/src/**/*.ts"
9
10
  - "packages/**/src/**/*.ts"
@@ -16,6 +17,11 @@ rules:
16
17
  type: rg
17
18
  config:
18
19
  pattern: "console\\.(log|error|warn|info|debug|dir|time|trace)"
20
+ # Task 1006 R3: the inline-run driver's fail-closed stderr lines moved here from the
21
+ # plugin script (byte-stable driver contract, emitted through the bundled lib under
22
+ # bare node); the output seam is a CLI-layer dependency the app service cannot take.
23
+ exclude:
24
+ - "packages/app/src/services/inline-run-setup.ts"
19
25
 
20
26
  - id: no-raw-stdout-stderr
21
27
  description: "Use the output seam (ts-utils echo/echoError) instead of process.stdout/stderr.write directly."
@@ -24,3 +30,10 @@ rules:
24
30
  type: rg
25
31
  config:
26
32
  pattern: "process\\.(stdout|stderr)\\.write"
33
+ # Tasks 1006 R1/R3: gate receipts (`check-receipt/v1`, one JSON line — the runner's parsed
34
+ # stdout contract) and the inline driver's stdout lines moved here from the plugin scripts.
35
+ # Both must stay byte-stable through the bundled libs under bare node; the seam would
36
+ # rewrite framing the CLI/tests parse. Mirrors the history-anatomy bundling exemptions.
37
+ exclude:
38
+ - "packages/app/src/services/quality-gate.ts"
39
+ - "packages/app/src/services/inline-run-setup.ts"
@@ -0,0 +1,51 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "description": "ADR-130 placement baseline (task 1000, seeded from plan \u00a72 inventory). Entries suppress sp-script-placement findings; kinds[] rows are migration-ledger entries for plan \u00a72 rows with no current findings. Baseline can only shrink: a listed kind the file no longer produces is a stale-baseline finding. Tasks 1001-1007 delete their entries in the same commit as the move.",
4
+ "entries": {
5
+ "plugins/sp/scripts/pr-reviewing.ts": {
6
+ "kinds": ["budget"],
7
+ "reason": "Keep, sp-owned git/gh loop; cited exemption (plan \u00a72)"
8
+ },
9
+ "plugins/sp/scripts/wrapup-steps.ts": {
10
+ "kinds": ["budget"],
11
+ "reason": "Keep (budget exemption), W2 (plan \u00a72)",
12
+ "exempt": true
13
+ },
14
+ "plugins/sp/scripts/batch-preflight.ts": {
15
+ "kinds": ["budget"],
16
+ "reason": "Keep (budget exemption; reviewed W4) (plan \u00a72)",
17
+ "exempt": true
18
+ },
19
+ "plugins/sp/scripts/feature-verification-steps.ts": {
20
+ "kinds": ["budget"],
21
+ "reason": "Keep (ADR-119 receipt writer; budget exemption) (plan \u00a72)",
22
+ "exempt": true
23
+ },
24
+ "plugins/sp/scripts/wrapup-drift-probe.ts": {
25
+ "kinds": ["budget", "corpus-parse"],
26
+ "reason": "Keep (glue over capture file; budget exemption) (plan \u00a72)",
27
+ "exempt": true
28
+ },
29
+ "plugins/sp/scripts/daily-summary/daily-summary.ts": {
30
+ "kinds": ["budget", "db-import"],
31
+ "reason": "Keep (daily-summary/, plan \u00a72); read-only history-health query via dynamic bun:sqlite import (task 1018)"
32
+ },
33
+ "plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts": {
34
+ "kinds": ["budget"],
35
+ "reason": "Keep (dogfood-testing/, plan \u00a72)"
36
+ },
37
+ "plugins/sp/scripts/dogfood-testing/validate-report.ts": {
38
+ "kinds": ["budget"],
39
+ "reason": "Keep (dogfood-testing/, plan \u00a72)"
40
+ },
41
+ "plugins/sp/hooks/context-post-tool.ts": {
42
+ "kinds": ["budget"],
43
+ "reason": "Keep: ADR-129 core (budget exemption) (plan \u00a72)",
44
+ "exempt": true
45
+ },
46
+ "plugins/sp/hooks/pi/guard-extension.ts": {
47
+ "kinds": ["budget"],
48
+ "reason": "Keep (ADR-129 normalizer) (plan \u00a72)"
49
+ }
50
+ }
51
+ }
@@ -50,13 +50,16 @@ states:
50
50
  digest, run identity) and the coarse status file, always exit 0 so the
51
51
  transition guard routes missing/corrupt/FAIL to `failed`.
52
52
  onEnter:
53
+ # 0960 R2: run-start script-resolution identity — record which tree this run
54
+ # resolved (source-repo vs installed) before the verification step runs. Never aborts.
53
55
  - kind: shell
54
56
  options:
55
57
  command: >-
56
- bun plugins/sp/scripts/feature-verification-steps.ts verify
57
- --feature-id "$featureId"
58
- --run-id "$__runId"
59
- --spur-bin "$spurBin"
58
+ 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
59
+ - kind: shell
60
+ options:
61
+ command: >-
62
+ mkdir -p .spur/run; eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/feature-verification-steps.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/feature-verification-steps.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; [ -f "$S" ] && "$RUNNER" "$S" verify --feature-id "$featureId" --run-id "$__runId" --spur-bin "$spurBin" || printf 'FAIL feature-verification failed closed — script not found — run superskill install sp --marketplace gobing-ai/spur\n' > ".spur/run/$__runId-feature-verification.status"; exit 0
60
63
 
61
64
  - id: done
62
65
  description: Terminal — repo-wide checks passed and the receipt is bound.
@@ -102,6 +102,14 @@ states:
102
102
  # exempt from the catalog record-name sweep (see run-record-catalog.test.ts).
103
103
 
104
104
 
105
+ # 1007 R8: run-start script-resolution identity (same command as feature-verification
106
+ # verify's first action), placed AFTER the id allocation above — the snippet reads
107
+ # .spur/run/$__runId-script-root.json, so it needs the allocated id. Later
108
+ # plugin-script actions resolve through it (1007 R4 snippet). Never aborts.
109
+ - kind: shell
110
+ options:
111
+ command: >-
112
+ 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
105
113
  - id: resolve-paths
106
114
  description: >
107
115
  Resolve the helper, the skill/contract logic paths, and the publication target once, into a
@@ -113,8 +121,8 @@ states:
113
121
  # Path arithmetic lives in the helper (ADR-069 R1); the shell only locates it. Avoid
114
122
  # `${...}` here — that syntax collides with the engine's own template interpolation.
115
123
  command: >-
116
- h=$(superskill script path sp history-anatomy-cache.mjs);
117
- node "$h" paths --helper "$h" --report-dir "$reportDir" --date "$date"
124
+ eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/history-anatomy-cache.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/history-anatomy-cache.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)";
125
+ "$RUNNER" "$S" paths --helper "$S" --report-dir "$reportDir" --date "$date"
118
126
  --output "$output" --mode "$mode" --since "$since" --until "$until"
119
127
  --focus "$focus" --recompute "$recompute" --run-id "$__runId"
120
128
  --out .spur/run/$__runId-paths.txt
@@ -147,12 +155,13 @@ states:
147
155
  - kind: shell
148
156
  options:
149
157
  command: >-
158
+ eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/history-anatomy-cache.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/history-anatomy-cache.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)";
150
159
  . .spur/run/$__runId-paths.txt;
151
- node "$HA_HELPER" probe --artifact .spur/run/$__runId-history-anatomy-current.json
160
+ "$RUNNER" "$S" probe --artifact .spur/run/$__runId-history-anatomy-current.json
152
161
  --baseline .spur/run/$__runId-history-anatomy-baseline.json --target "$HA_TARGET"
153
162
  --mode "$mode" --date "$HA_DATE" --recompute "$recompute" --executor "$agent"
154
163
  --skill-dir "$HA_SKILL" --contract "$HA_SKILL/references/report-contract.md"
155
- --workflow "$workflowFile" --helper "$HA_HELPER" --contract-version "$contractVersion" --run-id "$__runId"
164
+ --workflow "$workflowFile" --helper "$S" --contract-version "$contractVersion" --run-id "$__runId"
156
165
  --out .spur/run/$__runId-provenance.json
157
166
  > .spur/run/$__runId-cache-disposition.txt
158
167
 
@@ -189,7 +198,7 @@ states:
189
198
  - kind: shell
190
199
  options:
191
200
  command: >-
192
- node "$(superskill script path sp history-anatomy-cache.mjs)" assert-clean --baseline .spur/run/$__runId-baseline-enrich.txt --expect .spur/run/$__runId-candidate.md
201
+ eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/history-anatomy-cache.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/history-anatomy-cache.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; "$RUNNER" "$S" assert-clean --baseline .spur/run/$__runId-baseline-enrich.txt --expect .spur/run/$__runId-candidate.md
193
202
 
194
203
  - id: structure-gate
195
204
  description: >
@@ -200,7 +209,7 @@ states:
200
209
  - kind: shell
201
210
  options:
202
211
  command: >-
203
- node "$(superskill script path sp history-anatomy-cache.mjs)" check \
212
+ eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/history-anatomy-cache.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/history-anatomy-cache.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; "$RUNNER" "$S" check \
204
213
  .spur/run/$__runId-candidate.md > .spur/run/$__runId-structure-gate.txt 2>&1 || true
205
214
 
206
215
  - id: validate
@@ -244,7 +253,7 @@ states:
244
253
  - kind: shell
245
254
  options:
246
255
  command: >-
247
- node "$(superskill script path sp history-anatomy-cache.mjs)" assert-clean --baseline .spur/run/$__runId-baseline-validate.txt --expect .spur/run/$__runId-validation.txt
256
+ eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/history-anatomy-cache.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/history-anatomy-cache.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; "$RUNNER" "$S" assert-clean --baseline .spur/run/$__runId-baseline-validate.txt --expect .spur/run/$__runId-validation.txt
248
257
 
249
258
  - id: correct
250
259
  description: >
@@ -281,7 +290,7 @@ states:
281
290
  - kind: shell
282
291
  options:
283
292
  command: >-
284
- node "$(superskill script path sp history-anatomy-cache.mjs)" assert-clean --baseline .spur/run/$__runId-baseline-correct.txt --expect .spur/run/$__runId-candidate.md
293
+ eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/history-anatomy-cache.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/history-anatomy-cache.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; "$RUNNER" "$S" assert-clean --baseline .spur/run/$__runId-baseline-correct.txt --expect .spur/run/$__runId-candidate.md
285
294
 
286
295
  - id: refresh-provenance
287
296
  description: >
@@ -293,8 +302,9 @@ states:
293
302
  - kind: shell
294
303
  options:
295
304
  command: >-
305
+ eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/history-anatomy-cache.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/history-anatomy-cache.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)";
296
306
  . .spur/run/$__runId-paths.txt;
297
- node "$HA_HELPER" refresh --report "$HA_TARGET"
307
+ "$RUNNER" "$S" refresh --report "$HA_TARGET"
298
308
  --out .spur/run/$__runId-publishable.md --disposition hit
299
309
 
300
310
  - id: stamp
@@ -307,8 +317,9 @@ states:
307
317
  - kind: shell
308
318
  options:
309
319
  command: >-
320
+ eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/history-anatomy-cache.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/history-anatomy-cache.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)";
310
321
  . .spur/run/$__runId-paths.txt;
311
- node "$HA_HELPER" stamp --candidate .spur/run/$__runId-candidate.md
322
+ "$RUNNER" "$S" stamp --candidate .spur/run/$__runId-candidate.md
312
323
  --provenance .spur/run/$__runId-provenance.json
313
324
  --out .spur/run/$__runId-publishable.md
314
325
 
@@ -321,9 +332,10 @@ states:
321
332
  - kind: shell
322
333
  options:
323
334
  command: >-
335
+ eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/history-anatomy-cache.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/history-anatomy-cache.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)";
324
336
  . .spur/run/$__runId-paths.txt;
325
337
  mkdir -p "$(dirname "$HA_TARGET")";
326
- node "$HA_HELPER" publish .spur/run/$__runId-publishable.md "$HA_TARGET"
338
+ "$RUNNER" "$S" publish .spur/run/$__runId-publishable.md "$HA_TARGET"
327
339
 
328
340
  - id: published
329
341
  description: Terminal — report published atomically after a passing validation.