@gobing-ai/spur 0.4.7 → 0.4.9

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