@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
@@ -1,107 +0,0 @@
1
- #!/usr/bin/env bun
2
- /**
3
- * run-summary — the measured execution summary `/sp:dev-run` and `/sp:dev-runall` print by default
4
- * (`--no-summary` skips it). Inputs: one or more `spur workflow progress <run-id> --json` files
5
- * (`--progress [<label>=]<file>`) and the host transcript (resolved like session-timeline, or
6
- * `--transcript`), OR the close-written per-run summary files (`--rollup [<label>=]<file>`, 1146 R3).
7
- * Measurement lives in `packages/app/src/workflow/run-summary.ts` (reached through the generated
8
- * pure bundle entry); presentation and host IO live in `../lib/run-summary-core` (ADR-130 glue
9
- * budget). This script is argv parsing and dispatch. Reporting only: no transcript or no timed
10
- * attempts → an `n/a` result, exit 0. Node builtins only.
11
- */
12
- import { readFileSync } from 'node:fs';
13
- import { getEnvVars } from '../lib/env';
14
- import {
15
- buildRunSummary,
16
- gateFromReceipt,
17
- type Progress,
18
- type RollupInput,
19
- renderRollupMarkdown,
20
- renderSummaryMarkdown,
21
- } from '../lib/run-summary-core';
22
- import { parseRows, resolveTranscript } from '../lib/transcript';
23
-
24
- // Re-exported so the suite and any consumer keep one import path for the whole surface.
25
- export * from '../lib/run-summary-core';
26
-
27
- export const RUN_SUMMARY_USAGE =
28
- 'usage: run-summary (--progress [<label>=]<file> [--progress ...] | --rollup [<label>=]<summary.json> [--rollup ...]) [--transcript <path>] [--since <iso>] [--markdown]';
29
-
30
- export function main(
31
- argv: string[],
32
- env: Record<string, string | undefined> = getEnvVars(),
33
- write: (s: string) => void = (s) => process.stdout.write(s),
34
- projectsRoot?: string,
35
- ): number {
36
- let transcript: string | undefined;
37
- let since: string | undefined;
38
- let markdown = false;
39
- const progressArgs: string[] = [];
40
- const rollupArgs: string[] = [];
41
- for (let i = 0; i < argv.length; i++) {
42
- const arg = argv[i];
43
- if (arg === '--transcript' && argv[i + 1]) transcript = argv[++i];
44
- else if (arg === '--progress' && argv[i + 1]) progressArgs.push(argv[++i] as string);
45
- else if (arg === '--rollup' && argv[i + 1]) rollupArgs.push(argv[++i] as string);
46
- else if (arg === '--since' && argv[i + 1]) since = argv[++i];
47
- else if (arg === '--markdown') markdown = true;
48
- else if (arg === '--spur-bin' && argv[i + 1])
49
- i++; // 0482 R2: accepted, unused (no spur calls)
50
- else {
51
- process.stderr.write(`${RUN_SUMMARY_USAGE}\n`);
52
- return 2;
53
- }
54
- }
55
- // 1146 AC5: --rollup is a different mode — it reads close-written summary files and never
56
- // re-measures, so combining it with a measurement source is a usage error.
57
- if (rollupArgs.length > 0 && (progressArgs.length > 0 || since !== undefined || transcript !== undefined)) {
58
- process.stderr.write(`${RUN_SUMMARY_USAGE}\n`);
59
- return 2;
60
- }
61
- if (rollupArgs.length > 0) {
62
- try {
63
- const inputs: RollupInput[] = rollupArgs.map((arg) => {
64
- const eq = arg.indexOf('=');
65
- const [label, file] = eq > 0 ? [arg.slice(0, eq), arg.slice(eq + 1)] : [undefined, arg];
66
- const summary = JSON.parse(readFileSync(file as string, 'utf8')) as RollupInput['summary'];
67
- return { label: label ?? summary.runId ?? (file as string), summary };
68
- });
69
- write(`${renderRollupMarkdown(inputs)}\n`);
70
- return 0;
71
- } catch (error) {
72
- process.stderr.write(`run-summary: ${(error as Error).message}\n`);
73
- return 2;
74
- }
75
- }
76
- if (!progressArgs.length) {
77
- process.stderr.write(`${RUN_SUMMARY_USAGE}\n`);
78
- return 2;
79
- }
80
- const resolved = resolveTranscript(env, projectsRoot, transcript);
81
- if (!resolved.ok) {
82
- const out = markdown
83
- ? `Execution summary: n/a (${resolved.reason})`
84
- : JSON.stringify({ available: false, reason: resolved.reason });
85
- write(`${out}\n`);
86
- return 0;
87
- }
88
- try {
89
- const inputs = progressArgs.map((arg) => {
90
- const eq = arg.indexOf('=');
91
- const [label, file] = eq > 0 ? [arg.slice(0, eq), arg.slice(eq + 1)] : [undefined, arg];
92
- return { label, progress: JSON.parse(readFileSync(file, 'utf8')) as Progress };
93
- });
94
- const { rows, skippedLines } = parseRows(readFileSync(resolved.path, 'utf8').split('\n'));
95
- const summary = buildRunSummary(rows, inputs, { since, skippedLines });
96
- summary.gate = gateFromReceipt(process.cwd(), inputs[0]?.progress.runId ?? '');
97
- write(
98
- `${markdown ? renderSummaryMarkdown(summary) : JSON.stringify({ ...summary, transcript: resolved.path })}\n`,
99
- );
100
- return 0;
101
- } catch (error) {
102
- process.stderr.write(`run-summary: ${(error as Error).message}\n`);
103
- return 2;
104
- }
105
- }
106
-
107
- if (import.meta.main) process.exit(main(process.argv.slice(2)));
@@ -1,129 +0,0 @@
1
- #!/usr/bin/env node
2
- // @bun
3
-
4
- // plugins/sp/scripts/script-root.ts
5
- import { spawnSync } from "child_process";
6
- import { createHash } from "crypto";
7
- import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "fs";
8
- import { dirname, join } from "path";
9
-
10
- // plugins/sp/lib/env.ts
11
- function getEnvVars() {
12
- return process.env;
13
- }
14
-
15
- // plugins/sp/scripts/script-root.ts
16
- var SOURCE_REPO_MARKER = join("config", "plugin-scripts.json");
17
- var PROJECT_SCRIPTS_DIR = join("plugins", "sp", "scripts");
18
- var SCRIPT_ROOT_TWIN_REL = "script-root.mjs";
19
- function defaultResolveScript(cwd) {
20
- return (rel) => {
21
- const run = spawnSync("superskill", ["script", "path", "sp", rel, "--json"], {
22
- cwd,
23
- encoding: "utf8",
24
- env: getEnvVars()
25
- });
26
- if (run.status !== 0 || !run.stdout)
27
- return null;
28
- const lastLine = run.stdout.trim().split(`
29
- `).pop() ?? "";
30
- try {
31
- const parsed = JSON.parse(lastLine);
32
- return typeof parsed.path === "string" && parsed.path.length > 0 ? parsed : null;
33
- } catch {
34
- return null;
35
- }
36
- };
37
- }
38
- function digestScriptSet(dir, cwd) {
39
- const abs = cwd ? join(cwd, dir) : dir;
40
- const names = readdirSync(abs).filter((name) => {
41
- try {
42
- return statSync(join(abs, name)).isFile();
43
- } catch {
44
- return false;
45
- }
46
- }).sort();
47
- const list = names.map((name) => `${name}:${createHash("sha256").update(readFileSync(join(abs, name))).digest("hex")}`);
48
- return `sha256:${createHash("sha256").update(list.join(`
49
- `)).digest("hex")}`;
50
- }
51
- function runScriptRoot(env, options = {}) {
52
- const cwd = options.cwd;
53
- const runId = env.__runId ?? env.runId ?? "";
54
- const relResult = join(".spur", "run", `${runId}-script-root.json`);
55
- const abs = (p) => cwd ? join(cwd, p) : p;
56
- const warn = options.warn ?? ((message) => void process.stderr.write(`${message}
57
- `));
58
- mkdirSync(abs(join(".spur", "run")), { recursive: true });
59
- const write = (row) => {
60
- writeFileSync(abs(relResult), `${JSON.stringify(row)}
61
- `);
62
- return { ...row, resultFile: relResult, exitCode: 0 };
63
- };
64
- if (existsSync(abs(SOURCE_REPO_MARKER))) {
65
- try {
66
- return write({
67
- mode: "source-repo",
68
- source: "project",
69
- dir: PROJECT_SCRIPTS_DIR,
70
- scriptSetDigest: digestScriptSet(PROJECT_SCRIPTS_DIR, cwd)
71
- });
72
- } catch (error) {
73
- return write({ mode: "unresolved", error: `source-repo digest failed: ${String(error)}` });
74
- }
75
- }
76
- if (existsSync(abs(PROJECT_SCRIPTS_DIR))) {
77
- warn(`script-root: ignoring vendored ${PROJECT_SCRIPTS_DIR}/ (no ${SOURCE_REPO_MARKER} marker) \u2014 ` + `steps resolve the installed twin via 'superskill script path sp <rel>'`);
78
- }
79
- const resolve = options.resolveScript ?? defaultResolveScript(cwd);
80
- const resolved = resolve(SCRIPT_ROOT_TWIN_REL);
81
- if (!resolved?.path) {
82
- return write({
83
- mode: "unresolved",
84
- error: `'superskill script path sp ${SCRIPT_ROOT_TWIN_REL}' resolved nothing`
85
- });
86
- }
87
- const dir = dirname(resolved.path);
88
- try {
89
- return write({
90
- mode: "installed",
91
- source: resolved.source ?? "unknown",
92
- dir,
93
- scriptSetDigest: digestScriptSet(dir)
94
- });
95
- } catch (error) {
96
- return write({ mode: "unresolved", error: `installed digest failed: ${String(error)}` });
97
- }
98
- }
99
- var SCRIPT_ROOT_USAGE = "usage: script-root --run-id <id> [--spur-bin <path>]";
100
- function main(argv, env = getEnvVars(), options = {}) {
101
- let runId = env.__runId ?? "";
102
- for (let i = 0;i < argv.length; i++) {
103
- if (argv[i] === "--run-id") {
104
- runId = argv[i + 1] ?? "";
105
- i++;
106
- continue;
107
- }
108
- if (argv[i] === "--spur-bin") {
109
- i++;
110
- continue;
111
- }
112
- process.stderr.write(`${SCRIPT_ROOT_USAGE}
113
- `);
114
- return 2;
115
- }
116
- return runScriptRoot({ ...env, __runId: runId }, options).exitCode;
117
- }
118
- {
119
- process.exit(main(process.argv.slice(2)));
120
- }
121
- export {
122
- PROJECT_SCRIPTS_DIR,
123
- SCRIPT_ROOT_TWIN_REL,
124
- SCRIPT_ROOT_USAGE,
125
- SOURCE_REPO_MARKER,
126
- digestScriptSet,
127
- main,
128
- runScriptRoot
129
- };
@@ -1,199 +0,0 @@
1
- #!/usr/bin/env bun
2
- /**
3
- * script-root — run-start script-resolution identity for the sp pipelines (task 0960 R2).
4
- *
5
- * WHY: the pipeline YAML ships to every consumer, but its script probes resolved
6
- * `plugins/sp/scripts/` **project-first**. A consumer that hand-vendored a stale copy then ran
7
- * a different revision than the installed twin, mixing revisions across steps that write and
8
- * read the same cross-step artifacts (status files, verdicts, proof digests). The probe is
9
- * dogfooding-only, so it is now gated on `config/plugin-scripts.json` — a marker that lives
10
- * outside `plugins/sp/`, so copying the plugin tree cannot reproduce it.
11
- *
12
- * This script records *which* tree a run resolved, once, before any step executes:
13
- * `.spur/run/<runId>-script-root.json` `{ mode, source, dir, scriptSetDigest }`
14
- *
15
- * - `source-repo` — the marker is present; the project's live `plugins/sp/scripts/` is the
16
- * resolved tree (the dogfood path).
17
- * - `installed` — no marker; the tree is `dirname(superskill script path sp script-root.mjs
18
- * --json .path)`, with `source` from the same probe. One stderr warning names a dead
19
- * vendored `plugins/sp/scripts/` dir that is no longer executed.
20
- * - `unresolved` — nothing resolved. Written with an `error` and **exit 0**: a missing
21
- * optional script must stay a per-step fail-closed outcome, never a run-wide abort (R3).
22
- *
23
- * `scriptSetDigest` is one sha256 over the sorted `name:sha256` list of the resolved dir's
24
- * regular files (non-recursive) — the installed staging has no version file, so this answers
25
- * "which revision produced this run?" without a Superskill change.
26
- *
27
- * Node/bun builtins and the vendored `../lib/env` gateway only — bundled standalone by
28
- * `superskill install`, so no `@gobing-ai/*` value imports (task 0669).
29
- */
30
-
31
- import { spawnSync } from 'node:child_process';
32
- import { createHash } from 'node:crypto';
33
- import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
34
- import { dirname, join } from 'node:path';
35
- import { getEnvVars } from '../lib/env';
36
-
37
- export type ScriptRootMode = 'source-repo' | 'installed' | 'unresolved';
38
-
39
- export interface ScriptRoot {
40
- mode: ScriptRootMode;
41
- source?: string;
42
- dir?: string;
43
- scriptSetDigest?: string;
44
- error?: string;
45
- }
46
-
47
- export interface ScriptRootResult extends ScriptRoot {
48
- resultFile: string;
49
- exitCode: number;
50
- }
51
-
52
- export interface ScriptRootEnv {
53
- __runId?: string;
54
- [key: string]: string | undefined;
55
- }
56
-
57
- /** Resolved script descriptor from `superskill script path sp <rel> --json`. */
58
- export interface ResolvedScript {
59
- path?: string;
60
- source?: string;
61
- }
62
-
63
- export interface ScriptRootOptions {
64
- /** Base directory for `.spur/run` and the project marker; defaults to process cwd. */
65
- cwd?: string;
66
- /** Test seam: run `superskill script path sp script-root.mjs --json`. */
67
- resolveScript?: (rel: string) => ResolvedScript | null;
68
- /** Test seam: the one-warning sink. */
69
- warn?: (message: string) => void;
70
- }
71
-
72
- /** Marker that identifies the Spur source repo (owned by script-contract-check, outside plugins/sp). */
73
- export const SOURCE_REPO_MARKER = join('config', 'plugin-scripts.json');
74
- /** The project-first tree the dogfood probes execute. */
75
- export const PROJECT_SCRIPTS_DIR = join('plugins', 'sp', 'scripts');
76
- /** The rel the installed twin resolves under (its own staging name). */
77
- export const SCRIPT_ROOT_TWIN_REL = 'script-root.mjs';
78
-
79
- function defaultResolveScript(cwd?: string): (rel: string) => ResolvedScript | null {
80
- return (rel: string): ResolvedScript | null => {
81
- const run = spawnSync('superskill', ['script', 'path', 'sp', rel, '--json'], {
82
- cwd,
83
- encoding: 'utf8',
84
- env: getEnvVars(),
85
- });
86
- if (run.status !== 0 || !run.stdout) return null;
87
- const lastLine = run.stdout.trim().split('\n').pop() ?? '';
88
- try {
89
- const parsed = JSON.parse(lastLine) as ResolvedScript;
90
- return typeof parsed.path === 'string' && parsed.path.length > 0 ? parsed : null;
91
- } catch {
92
- return null;
93
- }
94
- };
95
- }
96
-
97
- /** sha256 over the sorted `name:sha256` list of `dir`'s regular files (non-recursive). */
98
- export function digestScriptSet(dir: string, cwd?: string): string {
99
- const abs = cwd ? join(cwd, dir) : dir;
100
- const names = readdirSync(abs)
101
- .filter((name) => {
102
- try {
103
- return statSync(join(abs, name)).isFile();
104
- } catch {
105
- return false;
106
- }
107
- })
108
- .sort();
109
- const list = names.map(
110
- (name) =>
111
- `${name}:${createHash('sha256')
112
- .update(readFileSync(join(abs, name)))
113
- .digest('hex')}`,
114
- );
115
- return `sha256:${createHash('sha256').update(list.join('\n')).digest('hex')}`;
116
- }
117
-
118
- /**
119
- * Resolve the run's script root and write `.spur/run/<runId>-script-root.json`.
120
- * Never aborts: every failure is recorded as `mode: "unresolved"` with exit 0 (R3).
121
- */
122
- export function runScriptRoot(env: ScriptRootEnv, options: ScriptRootOptions = {}): ScriptRootResult {
123
- const cwd = options.cwd;
124
- const runId = env.__runId ?? env.runId ?? '';
125
- const relResult = join('.spur', 'run', `${runId}-script-root.json`);
126
- const abs = (p: string): string => (cwd ? join(cwd, p) : p);
127
- const warn = options.warn ?? ((message: string): void => void process.stderr.write(`${message}\n`));
128
- mkdirSync(abs(join('.spur', 'run')), { recursive: true });
129
-
130
- const write = (row: ScriptRoot): ScriptRootResult => {
131
- writeFileSync(abs(relResult), `${JSON.stringify(row)}\n`);
132
- return { ...row, resultFile: relResult, exitCode: 0 };
133
- };
134
-
135
- // Source repo: the project's live tree is the resolved tree (R6).
136
- if (existsSync(abs(SOURCE_REPO_MARKER))) {
137
- try {
138
- return write({
139
- mode: 'source-repo',
140
- source: 'project',
141
- dir: PROJECT_SCRIPTS_DIR,
142
- scriptSetDigest: digestScriptSet(PROJECT_SCRIPTS_DIR, cwd),
143
- });
144
- } catch (error) {
145
- return write({ mode: 'unresolved', error: `source-repo digest failed: ${String(error)}` });
146
- }
147
- }
148
-
149
- // Installed: resolve the twin, and name a dead vendored dir that is no longer executed.
150
- if (existsSync(abs(PROJECT_SCRIPTS_DIR))) {
151
- warn(
152
- `script-root: ignoring vendored ${PROJECT_SCRIPTS_DIR}/ (no ${SOURCE_REPO_MARKER} marker) — ` +
153
- `steps resolve the installed twin via 'superskill script path sp <rel>'`,
154
- );
155
- }
156
- const resolve = options.resolveScript ?? defaultResolveScript(cwd);
157
- const resolved = resolve(SCRIPT_ROOT_TWIN_REL);
158
- if (!resolved?.path) {
159
- return write({
160
- mode: 'unresolved',
161
- error: `'superskill script path sp ${SCRIPT_ROOT_TWIN_REL}' resolved nothing`,
162
- });
163
- }
164
- const dir = dirname(resolved.path);
165
- try {
166
- return write({
167
- mode: 'installed',
168
- source: resolved.source ?? 'unknown',
169
- dir,
170
- scriptSetDigest: digestScriptSet(dir),
171
- });
172
- } catch (error) {
173
- return write({ mode: 'unresolved', error: `installed digest failed: ${String(error)}` });
174
- }
175
- }
176
-
177
- export const SCRIPT_ROOT_USAGE = 'usage: script-root --run-id <id> [--spur-bin <path>]';
178
-
179
- export function main(argv: string[], env: ScriptRootEnv = getEnvVars(), options: ScriptRootOptions = {}): number {
180
- let runId = env.__runId ?? '';
181
- for (let i = 0; i < argv.length; i++) {
182
- if (argv[i] === '--run-id') {
183
- runId = argv[i + 1] ?? '';
184
- i++;
185
- continue;
186
- }
187
- if (argv[i] === '--spur-bin') {
188
- i++;
189
- continue;
190
- }
191
- process.stderr.write(`${SCRIPT_ROOT_USAGE}\n`);
192
- return 2;
193
- }
194
- return runScriptRoot({ ...env, __runId: runId }, options).exitCode;
195
- }
196
-
197
- if (import.meta.main) {
198
- process.exit(main(process.argv.slice(2)));
199
- }