@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
@@ -9,9 +9,9 @@
9
9
  #
10
10
  # Shape: start -> discovery -> idea-eval -> feature-create -> ac-generate -> feature-check
11
11
  # -> system-design (conditional: needs_design signal)
12
- # -> design-approval (taste HITL gate; not auto-clicked by --auto)
12
+ # -> design-approval (taste HITL gate; bypassed only when design_approved=true + design check PASS)
13
13
  # -> decompose -> batch-create -> handoff-finalize -> handoff
14
- # (idea-eval rejection -> cancelled)
14
+ # (idea-eval rejection, or auto + `drop` recommendation -> cancelled)
15
15
  # (feature-check failure routes back to ac-generate; batch-create failure to decompose).
16
16
  #
17
17
  # Evidence instead of ceremony (task 0769): the feature check is MEASURED exactly once at
@@ -27,11 +27,11 @@
27
27
  # design — "auto" (default, signal-driven) or "skip" (--skip-design). No force path.
28
28
  # Unified: skip also means omit per-task Design in batch-create (scaffold only;
29
29
  # refine fills later). Default: decompose must author batch item `design`.
30
- # design_approved — "true" when taste pre-cleared (CLI --approve-taste or alias --design-approved);
31
- # lets profile=auto route around the design-approval taste gate (default "false")
32
- # idea_approved — "true" when taste pre-cleared (CLI --approve-taste or alias --idea-approved);
33
- # lets profile=auto route around the idea-eval taste gate (default "false")
34
- # CLI --approve-taste sets both design_approved and idea_approved to true.
30
+ # design_approved — "true" lets profile=auto route around the design-approval taste gate when
31
+ # the recorded design check PASSes (default "false")
32
+ # idea_approved — "true" lets profile=auto accept the idea-eval report's recommendation
33
+ # (proceed/reshape → continue, drop → cancelled; missing → pause) (default "false")
34
+ # CLI --auto on dev-idea / dev-plan sets profile=auto AND both pre-clear vars to true.
35
35
  # spurBin — PATH-independent spur invocation (overridden by CLI at run start)
36
36
  # agent — agent for agent.run steps (default: auto → `agent.default` in config)
37
37
  #
@@ -84,6 +84,12 @@ states:
84
84
  handoff — no task execution. Soft agent doctor (status file) so doctor red
85
85
  routes to `failed` via transitions instead of a raw lifecycle abort.
86
86
  onEnter:
87
+ # 0960 R2: run-start script-resolution identity — record which tree this run
88
+ # resolved (source-repo vs installed) before any step executes. Never aborts.
89
+ - kind: shell
90
+ options:
91
+ command: >-
92
+ 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
87
93
  - kind: note
88
94
  options:
89
95
  message: "Idea pipeline start for idea: ${vars.idea}"
@@ -131,15 +137,24 @@ states:
131
137
  session: fresh
132
138
  expectFile: .spur/run/${vars.__runId}-idea-eval-report.md
133
139
  timeoutMs: ${vars.stepTimeoutMs}
140
+ # Derive the eval recommendation ONCE (0769 pattern): the first non-blank line under
141
+ # `## Recommendation` → proceed | reshape | drop | unknown. The --auto guards out of
142
+ # discovery / idea-eval read this file; `unknown` routes to the idea-eval pause.
143
+ - kind: shell
144
+ options:
145
+ command: >-
146
+ awk '/^## Recommendation/{f=1;next} f&&NF{r=tolower($0);exit}
147
+ END{print (match(r,/^[*_ ]*(proceed|reshape|drop)/) ? substr(r,RSTART,RLENGTH) : "unknown")}'
148
+ ".spur/run/$__runId-idea-eval-report.md" | tr -d '*_ ' > ".spur/run/$__runId-idea-recommendation.txt"
134
149
 
135
150
  - id: idea-eval
136
151
  description: >
137
152
  HITL taste gate. Discovery has produced the idea-evaluation report
138
153
  (.spur/run/${vars.__runId}-idea-eval-report.md) with urgency/necessity scores, premises,
139
154
  pros/cons, and a recommendation. The operator reviews and approves or
140
- rejects. This gate is NOT auto-clicked by --auto (taste gate, like
141
- design-approval). Only routes around when vars.idea_approved=true
142
- (explicit prior approval).
155
+ rejects. Routed around only when profile=auto AND vars.idea_approved=true
156
+ (CLI --auto) AND the report's recommendation is proceed/reshape; a drop
157
+ recommendation cancels, a missing one still pauses here.
143
158
  pause: true
144
159
  onEnter:
145
160
  - kind: hitl.confirm
@@ -175,16 +190,15 @@ states:
175
190
  options:
176
191
  path: .spur/run/${vars.__runId}-idea-feature-id.txt
177
192
  var: featureId
193
+ # 1007 R2: one shell persists both sections — the Goal and Scope updates share the
194
+ # artifact precondition, so the two update shells merged (original commands in order,
195
+ # same && fail-fast semantics).
178
196
  - kind: shell
179
197
  options:
180
198
  command: >-
181
199
  mkdir -p .spur/run &&
182
200
  test -s .spur/run/$__runId-idea-goal.md &&
183
- $spurBin feature update "$featureId" --section Goal --from-file .spur/run/$__runId-idea-goal.md
184
- - kind: shell
185
- options:
186
- command: >-
187
- mkdir -p .spur/run &&
201
+ $spurBin feature update "$featureId" --section Goal --from-file .spur/run/$__runId-idea-goal.md &&
188
202
  test -s .spur/run/$__runId-idea-scope.md &&
189
203
  $spurBin feature update "$featureId" --section Scope --from-file .spur/run/$__runId-idea-scope.md
190
204
 
@@ -200,9 +214,10 @@ states:
200
214
  check records FAIL and routes through the capped retry loop via guards that consume the
201
215
  recorded result — it never fails the run (the engine's default onError policy is `fail`,
202
216
  so an in-action check failure would kill the run before the retry edges are evaluated).
203
- Requirement coverage is MEASURED alongside it by the soft idea-coverage-check shell
204
- (0887 R4): the recorded coverage status conjuncts into the profile=auto ac-generate
205
- guards below so uncovered inventory items route through the same capped retry loop.
217
+ Requirement coverage is MEASURED by the same gate (1004 R2): the `idea-ac-check` args
218
+ carry `--inventory .spur/run/${vars.__runId}-idea-eval-report.md`, so uncovered
219
+ inventory items record FAIL on `idea-ac-check.status` and route through the same capped
220
+ retry loop via the guards below.
206
221
  onEnter:
207
222
  - kind: shell
208
223
  options:
@@ -240,33 +255,16 @@ states:
240
255
  options:
241
256
  id: idea-ac-check
242
257
  executable: "${vars.spurBin}"
243
- args: ["feature", "check", "${vars.featureId}"]
258
+ args: ["feature", "check", "${vars.featureId}", "--inventory", ".spur/run/${vars.__runId}-idea-eval-report.md"]
244
259
  resultFile: .spur/run/${vars.__runId}-idea-ac-check.status
245
260
  softFail: true
246
261
  timeoutMs: 120000
247
- # 0887 R4: requirement-inventory ↔ AC coverage, measured once at the same author/revise
248
- # boundary. Soft shell (exit 0 always): the checker writes the PASS/FAIL status itself and
249
- # the guards below consume the recorded result — never re-run the checker (0769 pattern).
250
- # Repo-checkout path first, then the superskill-staged twin (handoff-finalize resolution
251
- # shape); neither present fails closed to FAIL so readiness degrades visibly instead of
252
- # silently skipping coverage.
253
- - kind: shell
254
- options:
255
- command: >-
256
- mkdir -p .spur/run &&
257
- S=plugins/sp/scripts/idea-coverage-check.ts &&
258
- if [ ! -f "$S" ]; then S="$(superskill script path sp idea-coverage-check.ts 2>/dev/null)"; fi &&
259
- if [ -n "$S" ] && [ -f "$S" ]; then
260
- bun "$S" --run-id "$__runId" --report ".spur/run/$__runId-idea-eval-report.md" --ac ".spur/run/$__runId-idea-ac-content.md" || printf 'FAIL run=%s checker exited nonzero (bun missing or checker crash)\n' "$__runId" > ".spur/run/$__runId-idea-coverage.reason";
261
- else
262
- printf 'FAIL run=%s checker not found — run superskill install sp\n' "$__runId" | tee ".spur/run/$__runId-idea-coverage.reason" >&2;
263
- printf 'FAIL\n' > ".spur/run/$__runId-idea-coverage.status";
264
- fi
265
262
  # 0945 R2: derive the route facts ONCE at this boundary (0769 pattern) — guards read these
266
263
  # named files instead of re-deriving design×needs_design inline. The same command is
267
264
  # duplicated in feature-check's onEnter (YAML has no include); byte-equality is
268
265
  # test-pinned (idea-pipeline-routing.test.ts). Missing/corrupt needs-design JSON fails
269
- # safe to `design`; readiness is PASS only when both recorded checks are PASS.
266
+ # safe to `design`; readiness is PASS only when the recorded check is PASS (1004 R2:
267
+ # coverage folds into idea-ac-check via --inventory).
270
268
  # (warn) 7 commands: two three-way `test && printf || printf` derivations over captured
271
269
  # signal files (ADR-115); no model hop, no CLI re-run.
272
270
  - kind: shell
@@ -276,7 +274,7 @@ states:
276
274
  { test "$design" = skip -o "$design" = auto -a "$(jq -r .needs_design .spur/run/$__runId-idea-needs-design.json 2>/dev/null)" = false &&
277
275
  printf 'skip\n' > .spur/run/$__runId-idea-design-route.txt ||
278
276
  printf 'design\n' > .spur/run/$__runId-idea-design-route.txt; } &&
279
- { test "$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" = PASS -a "$(cat .spur/run/$__runId-idea-coverage.status 2>/dev/null)" = PASS &&
277
+ { test "$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" = PASS &&
280
278
  printf 'PASS\n' > .spur/run/$__runId-idea-ac-ready.status ||
281
279
  printf 'FAIL\n' > .spur/run/$__runId-idea-ac-ready.status; }
282
280
 
@@ -293,29 +291,19 @@ states:
293
291
  the transition guards route directly from ac-generate to the appropriate next
294
292
  state, so this state is only entered in interactive mode. On failure, the retry
295
293
  cap routes back to ac-generate (≤3 retries) or escalates to failed.
296
- Requirement coverage (.spur/run/${vars.__runId}-idea-coverage.status, 0887 R4) is part of
297
- the recorded results this gate surfaces: a FAIL there means some inventory items have no
298
- covering scenario — answer no to route back to ac-generate for revision if needed.
294
+ Requirement coverage (1004 R2) folds into the recorded `idea-ac-check` result via the
295
+ gate's `--inventory` flag: a FAIL there can mean some inventory items have no covering
296
+ scenario — answer no to route back to ac-generate for revision if needed.
299
297
  pause: true
300
298
  onEnter:
301
299
  - kind: hitl.confirm
302
300
  options:
303
- prompt: "Feature check for ${vars.featureId}. Review the AC and confirm to proceed? Requirement coverage status: $(cat .spur/run/${vars.__runId}-idea-coverage.status 2>/dev/null || echo unknown) — reason: $(cat .spur/run/${vars.__runId}-idea-coverage.reason 2>/dev/null || echo n/a) (.spur/run/${vars.__runId}-idea-coverage.status[.reason]). (Failures route back to ac-generate for revision, capped at 3 retries.)"
301
+ prompt: "Feature check for ${vars.featureId}. Review the AC and confirm to proceed? Recorded check status: $(cat .spur/run/${vars.__runId}-idea-ac-check.status 2>/dev/null || echo unknown) (.spur/run/${vars.__runId}-idea-ac-check.status — includes inventory-coverage findings, 1004 R2). (Failures route back to ac-generate for revision, capped at 3 retries.)"
304
302
  decision:
305
303
  mode: never
306
- # 0945 R2: same writer as ac-generate's onEnter (byte-equal, test-pinned) — refreshes the
307
- # derived route facts after the interactive gate so both entries into this boundary read
308
- # consistent files; hitl.confirm only sets $__hitlAnswer.
309
- - kind: shell
310
- options:
311
- command: >-
312
- mkdir -p .spur/run &&
313
- { test "$design" = skip -o "$design" = auto -a "$(jq -r .needs_design .spur/run/$__runId-idea-needs-design.json 2>/dev/null)" = false &&
314
- printf 'skip\n' > .spur/run/$__runId-idea-design-route.txt ||
315
- printf 'design\n' > .spur/run/$__runId-idea-design-route.txt; } &&
316
- { test "$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" = PASS -a "$(cat .spur/run/$__runId-idea-coverage.status 2>/dev/null)" = PASS &&
317
- printf 'PASS\n' > .spur/run/$__runId-idea-ac-ready.status ||
318
- printf 'FAIL\n' > .spur/run/$__runId-idea-ac-ready.status; }
304
+ # 1007 R2: the former post-confirm route-writer duplicate is deleted — ac-generate's
305
+ # writer is the single writer (0945 R2 pin updated); its inputs (design var, needs-design
306
+ # JSON, recorded ac-check status) cannot change across hitl.confirm.
319
307
 
320
308
  - id: system-design
321
309
  description: >
@@ -370,9 +358,8 @@ states:
370
358
  - id: design-approval
371
359
  description: >
372
360
  HITL taste gate. The operator reviews the system design and approves or
373
- rejects it. This gate is NOT auto-clicked by --auto (Auto-Decision Principle
374
- #5: taste-decision -> surface to human). Only routes around when
375
- vars.design_approved=true (explicit prior approval).
361
+ rejects it. Routed around only when profile=auto AND vars.design_approved=true
362
+ (CLI --auto) AND the recorded design check PASSes; a FAIL still pauses here.
376
363
 
377
364
  R7 (0433): a headless `no` persisted by DefaultHitlResponder would loop
378
365
  design-approval -> system-design -> design-approval, burning unbounded
@@ -553,12 +540,10 @@ states:
553
540
  - kind: shell
554
541
  options:
555
542
  command: >-
556
- if [ -f packages/app/src/workflow/idea-handoff-cli.ts ]; then
557
- bun packages/app/src/workflow/idea-handoff-cli.ts;
558
- elif H="$(superskill script path sp idea-handoff.mjs 2>/dev/null)" && [ -f "$H" ]; then
559
- node "$H";
543
+ eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/idea-handoff.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/idea-handoff.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then
544
+ "$RUNNER" "$S";
560
545
  else
561
- echo "idea handoff failed closed — idea-handoff script not found — run 'superskill install sp'" >&2;
546
+ echo "idea handoff failed closed — idea-handoff script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2;
562
547
  exit 1;
563
548
  fi
564
549
  - id: handoff
@@ -569,9 +554,8 @@ states:
569
554
  next command (ready-depth refineall when any task is unready, else auto
570
555
  runall). No task execution — the pipeline stops here.
571
556
  onEnter:
572
- - kind: note
573
- options:
574
- message: "Idea pipeline handoff. Feature: ${vars.featureId}. See .spur/run/${vars.__runId}-idea-handoff.md for the created task list and recommended next command."
557
+ # 1007 R2: the handoff note is deleted — the run.artifact below carries the handoff
558
+ # (same path, the recommended-next-command report).
575
559
  - kind: run.artifact
576
560
  options:
577
561
  path: .spur/run/${vars.__runId}-idea-handoff.md
@@ -602,17 +586,32 @@ transitions:
602
586
  guard:
603
587
  kind: always
604
588
 
605
- # ── discovery: auto-skip (profile=auto + idea_approved) OR enter idea-eval taste gate ──
606
- # Declaration order: auto-skip FIRST (same pattern as system-design → design-approval).
607
- # Without this edge, discovery always enters idea-eval (pause: true), rendering the prompt
589
+ # ── discovery: auto-accept the eval recommendation (profile=auto + idea_approved) OR enter idea-eval ──
590
+ # Declaration order: auto edges FIRST (same pattern as system-design → design-approval).
591
+ # Without them, discovery always enters idea-eval (pause: true), rendering the prompt
608
592
  # and persisting an avoidable pause before the in-state auto-skip guard can fire (0366 R4/R5).
593
+ # --auto accepts the recommendation derived at the end of discovery (-idea-recommendation.txt):
594
+ # drop → cancelled, proceed/reshape → feature-create; unknown/missing falls through to the
595
+ # idea-eval pause (fail-safe: never auto-create a feature without an explicit proceed).
596
+ - from: discovery
597
+ to: cancelled
598
+ terminalReason: cancelled
599
+ description: profile=auto AND idea_approved=true AND eval recommends drop — accept it, no feature.
600
+ guard:
601
+ kind: shell
602
+ options:
603
+ command: >-
604
+ test "$profile" = auto && test "$idea_approved" = true &&
605
+ grep -qx drop .spur/run/$__runId-idea-recommendation.txt
609
606
  - from: discovery
610
607
  to: feature-create
611
- description: profile=auto AND idea_approved=true — skip idea-eval taste gate entirely.
608
+ description: profile=auto AND idea_approved=true AND eval recommends proceed/reshape — skip idea-eval taste gate.
612
609
  guard:
613
610
  kind: shell
614
611
  options:
615
- command: 'test "$profile" = auto && test "$idea_approved" = true'
612
+ command: >-
613
+ test "$profile" = auto && test "$idea_approved" = true &&
614
+ grep -qxE 'proceed|reshape' .spur/run/$__runId-idea-recommendation.txt
616
615
  - from: discovery
617
616
  to: idea-eval
618
617
  description: Discovery complete — gate on idea evaluation taste decision.
@@ -623,11 +622,13 @@ transitions:
623
622
  # Declaration order: auto-skip FIRST (same pattern as system-design → design-approval).
624
623
  - from: idea-eval
625
624
  to: feature-create
626
- description: profile=auto AND idea_approved=true — skip idea-eval taste gate.
625
+ description: profile=auto AND idea_approved=true AND eval recommends proceed/reshape — skip idea-eval taste gate.
627
626
  guard:
628
627
  kind: shell
629
628
  options:
630
- command: 'test "$profile" = auto && test "$idea_approved" = true'
629
+ command: >-
630
+ test "$profile" = auto && test "$idea_approved" = true &&
631
+ grep -qxE 'proceed|reshape' .spur/run/$__runId-idea-recommendation.txt
631
632
  - from: idea-eval
632
633
  to: feature-create
633
634
  description: Idea evaluation approved — create or select a feature.
@@ -688,32 +689,32 @@ transitions:
688
689
  test "$profile" = auto &&
689
690
  test "$(cat .spur/run/$__runId-idea-ac-ready.status 2>/dev/null)" = PASS &&
690
691
  test "$(cat .spur/run/$__runId-idea-design-route.txt 2>/dev/null)" = skip
691
- # Auto-skip 3: check or coverage failed, retry < 3 → loop back to ac-generate (self-loop)
692
+ # Auto-skip 3: check failed (incl. inventory coverage), retry < 3 → loop back to ac-generate (self-loop)
692
693
  - from: ac-generate
693
694
  to: ac-generate
694
- description: "profile=auto, check or coverage failed, retry cap not reached — re-run ac-generate."
695
- # (warn) 5 commands: one persistent multi-assignment line captures both statuses and the retry count
696
- # (with its 0 fallback); the failed-check pair stays verbatim and the profile gate folds into the retry
697
- # test via `test -a`; the retry loop is the smallest honest formulation of cap<3 routing (0769).
695
+ description: "profile=auto, check failed (incl. inventory coverage), retry cap not reached — re-run ac-generate."
696
+ # (warn) 4 commands: one persistent multi-assignment line captures the check status and the retry
697
+ # count (with its 0 fallback); the profile gate folds into the retry test via `test -a`; the retry
698
+ # loop is the smallest honest formulation of cap<3 routing (0769).
698
699
  guard:
699
700
  kind: shell
700
701
  options:
701
702
  command: >-
702
- ac_status="$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" cov_status="$(cat .spur/run/$__runId-idea-coverage.status 2>/dev/null)" retry="$(cat .spur/run/$__runId-idea-ac-retry-count 2>/dev/null || echo 0)";
703
- { test "$ac_status" != PASS || test "$cov_status" != PASS; } && test "$profile" = auto -a "$retry" -lt 3
704
- # Auto-skip 4: check or coverage failed, retry cap reached → escalate to failed
703
+ ac_status="$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" retry="$(cat .spur/run/$__runId-idea-ac-retry-count 2>/dev/null || echo 0)";
704
+ test "$ac_status" != PASS && test "$profile" = auto -a "$retry" -lt 3
705
+ # Auto-skip 4: check failed (incl. inventory coverage), retry cap reached → escalate to failed
705
706
  - from: ac-generate
706
707
  to: failed
707
708
  terminalReason: retry-exhausted
708
- description: "profile=auto, check or coverage failed after 3 retries — escalate to failed."
709
- # (warn) 5 commands: mirror of the retry guard with cap>=3; keeping escalation and retry as one
709
+ description: "profile=auto, check failed (incl. inventory coverage) after 3 retries — escalate to failed."
710
+ # (warn) 4 commands: mirror of the retry guard with cap>=3; keeping escalation and retry as one
710
711
  # test-chain pair makes the cap boundary auditable in the diff (0769).
711
712
  guard:
712
713
  kind: shell
713
714
  options:
714
715
  command: >-
715
- ac_status="$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" cov_status="$(cat .spur/run/$__runId-idea-coverage.status 2>/dev/null)" retry="$(cat .spur/run/$__runId-idea-ac-retry-count 2>/dev/null || echo 0)";
716
- { test "$ac_status" != PASS || test "$cov_status" != PASS; } && test "$profile" = auto -a "$retry" -ge 3
716
+ ac_status="$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" retry="$(cat .spur/run/$__runId-idea-ac-retry-count 2>/dev/null || echo 0)";
717
+ test "$ac_status" != PASS && test "$profile" = auto -a "$retry" -ge 3
717
718
  # Interactive fallback: enter feature-check HITL gate
718
719
  - from: ac-generate
719
720
  to: feature-check
@@ -50,6 +50,7 @@ vars:
50
50
  noWait: "false"
51
51
  waitTimeoutSec: "600"
52
52
  waitIntervalSec: "30"
53
+ spurBin: "spur"
53
54
  preReviewCmd: ""
54
55
  __runId: ""
55
56
  # Runtime-set by file.read.into-var (0771): the request record's requestedAt|head,
@@ -65,15 +66,23 @@ states:
65
66
  before any push can publish it).
66
67
  Writes PASS|FAIL to .spur/run/${vars.__runId}-pr-preflight.status; always exit 0.
67
68
  onEnter:
69
+ # 1007 R8: run-start script-resolution identity (same command as feature-verification
70
+ # verify's first action) — records which tree this run resolved (source-repo vs
71
+ # installed) into .spur/run/$__runId-script-root.json; later plugin-script actions
72
+ # resolve through it (1007 R4 snippet). Never aborts.
73
+ - kind: shell
74
+ options:
75
+ command: >-
76
+ S=plugins/sp/scripts/script-root.ts; [ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp script-root.mjs 2>/dev/null)"; RUNNER=bun; case "$S" in *.mjs) RUNNER=node ;; esac; [ -f "$S" ] && "$RUNNER" "$S" --run-id "$__runId" --spur-bin "$spurBin" || echo "script-root failed closed — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; exit 0
68
77
  - kind: shell
69
78
  options:
70
79
  # (e) 0825: 10 lines — detached-HEAD/dirty/gh-auth/base-refusal probes must record
71
80
  # before any push can publish; split would let a half-probed run continue.
72
81
  command: >-
73
- mkdir -p .spur/run &&
82
+
74
83
  STATUS_FILE=".spur/run/$__runId-pr-preflight.status" &&
75
84
  set +e &&
76
- bun "$(superskill script path sp pr-reviewing.ts)" preflight --base "$baseBranch" --json > ".spur/run/$__runId-pr-context.json";
85
+ eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/pr-reviewing.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/pr-reviewing.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; "$RUNNER" "$S" preflight --base "$baseBranch" --json > ".spur/run/$__runId-pr-context.json";
77
86
  rc=$?; set -e &&
78
87
  if [ "$rc" -eq 0 ]; then printf 'PASS\n' > "$STATUS_FILE"; else printf 'FAIL\n' > "$STATUS_FILE"; fi &&
79
88
  exit 0
@@ -88,10 +97,10 @@ states:
88
97
  # (e) 0825: 9 lines — hygiene verdict + json capture land together; the status-file
89
98
  # fallback keeps a silent driver from passing the gate.
90
99
  command: >-
91
- mkdir -p .spur/run &&
100
+
92
101
  STATUS_FILE=".spur/run/$__runId-pr-hygiene.status" &&
93
102
  set +e &&
94
- bun "$(superskill script path sp pr-reviewing.ts)" hygiene --base "$baseBranch" --json
103
+ eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/pr-reviewing.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/pr-reviewing.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; "$RUNNER" "$S" hygiene --base "$baseBranch" --json
95
104
  --status-file "$STATUS_FILE" > ".spur/run/$__runId-pr-hygiene.json";
96
105
  rc=$?; set -e &&
97
106
  if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
@@ -122,7 +131,7 @@ states:
122
131
  mkdir -p .spur/run &&
123
132
  STATUS_FILE=".spur/run/$__runId-pr-push.status" &&
124
133
  set +e &&
125
- bun "$(superskill script path sp pr-reviewing.ts)" push --json --status-file "$STATUS_FILE"
134
+ eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/pr-reviewing.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/pr-reviewing.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; "$RUNNER" "$S" push --json --status-file "$STATUS_FILE"
126
135
  > ".spur/run/$__runId-pr-push.json";
127
136
  rc=$?; set -e &&
128
137
  if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
@@ -139,7 +148,7 @@ states:
139
148
  mkdir -p .spur/run &&
140
149
  STATUS_FILE=".spur/run/$__runId-pr-ensure.status" &&
141
150
  set +e &&
142
- bun "$(superskill script path sp pr-reviewing.ts)" ensure-pr --base "$baseBranch" --json
151
+ eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/pr-reviewing.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/pr-reviewing.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; "$RUNNER" "$S" ensure-pr --base "$baseBranch" --json
143
152
  --status-file "$STATUS_FILE" > ".spur/run/$__runId-pr.json";
144
153
  rc=$?; set -e &&
145
154
  if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
@@ -155,7 +164,7 @@ states:
155
164
  # (e) 0825: 10 lines — the write-then-read split is the file-var transport feeding
156
165
  # wait/collect and must stay one action (same record, same run scope).
157
166
  command: >-
158
- mkdir -p .spur/run; case "$mode" in rerun) F=--force ;; *) F= ;; esac; bun "$(superskill script path sp pr-reviewing.ts)" request --focus "$focus" $F --json --status-file ".spur/run/$__runId-pr-request.status" > ".spur/run/$__runId-pr-request.json"; [ -f ".spur/run/$__runId-pr-request.status" ] || printf 'FAIL\n' > ".spur/run/$__runId-pr-request.status"; jq -e . ".spur/run/$__runId-pr-request.json" > /dev/null 2>&1 && jq -r '.requestedAt // ""' ".spur/run/$__runId-pr-request.json" > ".spur/run/$__runId-pr-since.txt" && jq -r '.head // ""' ".spur/run/$__runId-pr-request.json" > ".spur/run/$__runId-pr-head.txt"; exit 0
167
+ F="$([ "$mode" = rerun ] && echo --force)"; eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/pr-reviewing.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/pr-reviewing.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; "$RUNNER" "$S" request --focus "$focus" $F --json --status-file ".spur/run/$__runId-pr-request.status" > ".spur/run/$__runId-pr-request.json"; [ -f ".spur/run/$__runId-pr-request.status" ] || echo FAIL > ".spur/run/$__runId-pr-request.status"; jq -e . ".spur/run/$__runId-pr-request.json" >/dev/null 2>&1 && jq -r '.requestedAt // ""' ".spur/run/$__runId-pr-request.json" > ".spur/run/$__runId-pr-since.txt" && jq -r '.head // ""' ".spur/run/$__runId-pr-request.json" > ".spur/run/$__runId-pr-head.txt"; exit 0
159
168
 
160
169
  - id: wait
161
170
  description: >
@@ -180,7 +189,7 @@ states:
180
189
  mkdir -p .spur/run &&
181
190
  STATUS_FILE=".spur/run/$__runId-pr-wait.status" &&
182
191
  set +e &&
183
- bun "$(superskill script path sp pr-reviewing.ts)" wait --since "$prSince" --head "$prHead" --timeout "$waitTimeoutSec" --interval "$waitIntervalSec"
192
+ eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/pr-reviewing.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/pr-reviewing.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; "$RUNNER" "$S" wait --since "$prSince" --head "$prHead" --timeout "$waitTimeoutSec" --interval "$waitIntervalSec"
184
193
  --json --status-file "$STATUS_FILE" > ".spur/run/$__runId-pr-wait.json";
185
194
  rc=$?; set -e &&
186
195
  if [ ! -f "$STATUS_FILE" ]; then printf 'FAIL\n' > "$STATUS_FILE"; fi &&
@@ -204,7 +213,7 @@ states:
204
213
  # (e) 0825: 9 lines — collect + status must run against the same since/head pair
205
214
  # before the composite status is decided (same 0771 record contract).
206
215
  command: >-
207
- mkdir -p .spur/run; bun "$(superskill script path sp pr-reviewing.ts)" collect --since "$prSince" --head "$prHead" --json --status-file ".spur/run/$__runId-pr-collect.status" > ".spur/run/$__runId-pr-findings.json"; c=$?; bun "$(superskill script path sp pr-reviewing.ts)" status --since "$prSince" --head "$prHead" --json > ".spur/run/$__runId-pr-status.json" && [ "$c" -eq 0 ] && [ -f ".spur/run/$__runId-pr-collect.status" ] || printf 'FAIL\n' > ".spur/run/$__runId-pr-collect.status"; cat ".spur/run/$__runId-pr-findings.json" 2>/dev/null; exit 0
216
+ mkdir -p .spur/run; eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/pr-reviewing.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/pr-reviewing.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; "$RUNNER" "$S" collect --since "$prSince" --head "$prHead" --json --status-file ".spur/run/$__runId-pr-collect.status" > ".spur/run/$__runId-pr-findings.json"; c=$?; "$RUNNER" "$S" status --since "$prSince" --head "$prHead" --json > ".spur/run/$__runId-pr-status.json" && [ "$c" -eq 0 ] && [ -f ".spur/run/$__runId-pr-collect.status" ] || printf 'FAIL\n' > ".spur/run/$__runId-pr-collect.status"; cat ".spur/run/$__runId-pr-findings.json" 2>/dev/null; exit 0
208
217
 
209
218
  - id: done
210
219
  description: Terminal — review collected; findings artifact at .spur/run/${vars.__runId}-pr-findings.json