@gobing-ai/spur 0.3.53 → 0.3.55
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.
- package/.claude-plugin/marketplace.json +1 -1
- package/config/corpus-baseline.json +2783 -2783
- package/config/pipeline-budgets.json +42 -0
- package/config/plugin-scripts.json +73 -0
- package/config/workflow-composition-baseline.json +561 -0
- package/config/workflows/docs-pipeline.yaml +29 -13
- package/config/workflows/feature-dev.yaml +54 -2
- package/config/workflows/idea-pipeline.yaml +15 -0
- package/config/workflows/task-pipeline.yaml +77 -65
- package/config/workflows/wrapup-pipeline.yaml +40 -45
- package/package.json +9 -9
- package/plugins/README.md +1 -1
- package/plugins/sp/README.md +3 -3
- package/plugins/sp/agents/super-planner.md +1 -1
- package/plugins/sp/commands/dev-daily.md +1 -1
- package/plugins/sp/commands/dev-history-load.md +1 -1
- package/plugins/sp/commands/dev-idea.md +10 -2
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/scripts/batch-preflight.mjs +160 -0
- package/plugins/sp/scripts/batch-preflight.ts +1 -1
- package/plugins/sp/scripts/daily-summary/daily-summary.mjs +479 -0
- package/plugins/sp/scripts/daily-summary/daily-summary.ts +75 -37
- package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.mjs +204 -0
- package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts +1 -1
- package/plugins/sp/scripts/dogfood-testing/validate-report.mjs +141 -0
- package/plugins/sp/scripts/dogfood-testing/validate-report.ts +1 -1
- package/plugins/sp/scripts/feature-sync-bounded.mjs +290 -0
- package/plugins/sp/scripts/feature-sync-bounded.ts +9 -8
- package/plugins/sp/scripts/history-load.mjs +268 -0
- package/plugins/sp/scripts/pr-reviewing.mjs +685 -0
- package/plugins/sp/scripts/pr-reviewing.ts +1 -1
- package/plugins/sp/scripts/script-contract-check.ts +319 -0
- package/plugins/sp/skills/daily-summary/SKILL.md +3 -3
- package/plugins/sp/skills/dogfood-testing/SKILL.md +5 -5
- package/plugins/sp/skills/dogfood-testing/references/report-template.md +1 -1
- package/plugins/sp/skills/pr-reviewing/SKILL.md +3 -3
- package/plugins/sp/skills/spur-dev/SKILL.md +2 -1
- package/plugins/sp/skills/spur-dev/references/cross-cutting.md +3 -4
- package/plugins/sp/skills/spur-dev/references/dev-operations.md +1 -1
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +3 -3
- package/plugins/sp/skills/spur-dev/references/gate-checklists.md +4 -4
- package/spur.js +4270 -1323
- package/web/_astro/{BoardApp.plVXYkKo.js → BoardApp.DCLSB3Zs.js} +63 -63
- package/web/_astro/BoardApp.Dx5gzAhb.js +1 -0
- package/web/_astro/{TaskDetail.5DIyVQ_N.js → TaskDetail.DN_RxS-2.js} +1 -1
- package/web/_astro/{arc.BnUgL7ho.js → arc.CldTHRg-.js} +1 -1
- package/web/_astro/{architectureDiagram-3BPJPVTR.B9YMJau-.js → architectureDiagram-3BPJPVTR.DQ4T9oeU.js} +1 -1
- package/web/_astro/{blockDiagram-GPEHLZMM.Dw2qgvWJ.js → blockDiagram-GPEHLZMM.CGDaXH8J.js} +1 -1
- package/web/_astro/{c4Diagram-AAUBKEIU.jTbU0-Nk.js → c4Diagram-AAUBKEIU.Cqsc2iub.js} +1 -1
- package/web/_astro/channel.CrBJYpxo.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.Di46EtkU.js → chunk-2J33WTMH.CQSKsRmq.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.DweHBwqQ.js → chunk-4BX2VUAB.Pv1HCtp8.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.rRjTKaa7.js → chunk-55IACEB6.-9MseOIk.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.BkEQIkSV.js → chunk-727SXJPM.M3OI1DF7.js} +1 -1
- package/web/_astro/{chunk-AQP2D5EJ.Cfe9IvAd.js → chunk-AQP2D5EJ.NfHka5Ca.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.fI6tLbeN.js → chunk-FMBD7UC4.B2suYe3s.js} +1 -1
- package/web/_astro/{chunk-ND2GUHAM.BIjgpq0O.js → chunk-ND2GUHAM.BfJ7aucP.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.ZwLnVxyz.js → chunk-QZHKN3VN._582hZVc.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.BJAGYidE.js → classDiagram-4FO5ZUOK._tttU_jk.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.BJAGYidE.js → classDiagram-v2-Q7XG4LA2._tttU_jk.js} +1 -1
- package/web/_astro/{cose-bilkent-S5V4N54A.B5y3nz26.js → cose-bilkent-S5V4N54A.C4rVATLQ.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.DHmw0ZBC.js → dagre-BM42HDAG.8BLRi7f9.js} +1 -1
- package/web/_astro/{diagram-2AECGRRQ.10gapJfY.js → diagram-2AECGRRQ.D6lwUZos.js} +1 -1
- package/web/_astro/{diagram-5GNKFQAL.Gh33_drM.js → diagram-5GNKFQAL.Cl_rMiVT.js} +1 -1
- package/web/_astro/{diagram-KO2AKTUF.8ROWlfcX.js → diagram-KO2AKTUF.DhMExHLp.js} +1 -1
- package/web/_astro/{diagram-LMA3HP47.BsP3tKmg.js → diagram-LMA3HP47.3OAxzH_o.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.DM2WFDhU.js → diagram-OG6HWLK6.Uh9RLucG.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.royaC_lH.js → erDiagram-TEJ5UH35.izzElG0c.js} +1 -1
- package/web/_astro/{flowDiagram-I6XJVG4X.C9GEvIie.js → flowDiagram-I6XJVG4X.BlGwp5qM.js} +1 -1
- package/web/_astro/{ganttDiagram-6RSMTGT7.CXO4T2U0.js → ganttDiagram-6RSMTGT7.je7Vf8dN.js} +1 -1
- package/web/_astro/{gitGraphDiagram-PVQCEYII.Q02KzYH7.js → gitGraphDiagram-PVQCEYII.DNk0Ycop.js} +1 -1
- package/web/_astro/{index.DAxu50UF.css → index.V6Q7nhed.css} +1 -1
- package/web/_astro/{infoDiagram-5YYISTIA.DNfSDKJt.js → infoDiagram-5YYISTIA.K2HhGyWH.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.BFttvtgJ.js → ishikawaDiagram-YF4QCWOH.BbbOW4IN.js} +1 -1
- package/web/_astro/{journeyDiagram-JHISSGLW.Cfm-2SbG.js → journeyDiagram-JHISSGLW.B1UaZKqN.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.BWGNW6fV.js → kanban-definition-UN3LZRKU.9tsw5QFd.js} +1 -1
- package/web/_astro/{linear.BprdUk2Y.js → linear.I9dvtu-j.js} +1 -1
- package/web/_astro/{mermaid.core.B2zRNxtX.js → mermaid.core.5bKJsMgf.js} +4 -4
- package/web/_astro/{mindmap-definition-RKZ34NQL.g9jij8sw.js → mindmap-definition-RKZ34NQL.BC5MqSn6.js} +1 -1
- package/web/_astro/{pieDiagram-4H26LBE5.CbzR4n5b.js → pieDiagram-4H26LBE5.B8GIMyxD.js} +1 -1
- package/web/_astro/{quadrantDiagram-W4KKPZXB.DxV3viWt.js → quadrantDiagram-W4KKPZXB.K_aZSM_u.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.DvAb90JS.js → requirementDiagram-4Y6WPE33.B_V5kzfT.js} +1 -1
- package/web/_astro/{sankeyDiagram-5OEKKPKP.CIFz5t4D.js → sankeyDiagram-5OEKKPKP.DyV2quLS.js} +1 -1
- package/web/_astro/{sequenceDiagram-3UESZ5HK.DzlEQynd.js → sequenceDiagram-3UESZ5HK.BlKvPnBv.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.Dph2V-ts.js → stateDiagram-AJRCARHV.C1lYUMdS.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.wJhfrLAy.js → stateDiagram-v2-BHNVJYJU.DJWjr3QV.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.BrSiyubX.js → timeline-definition-PNZ67QCA.CYYiXVlv.js} +1 -1
- package/web/_astro/{vennDiagram-CIIHVFJN.COobPrUX.js → vennDiagram-CIIHVFJN.zYjQKa_S.js} +1 -1
- package/web/_astro/{wardley-L42UT6IY.CrjeTx8A.js → wardley-L42UT6IY.BGrWTY3D.js} +1 -1
- package/web/_astro/{wardleyDiagram-YWT4CUSO.B8_fTQ8E.js → wardleyDiagram-YWT4CUSO.CkXxtcI1.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6.BPpokgVv.js → xychartDiagram-2RQKCTM6.BhKH3KG3.js} +1 -1
- package/web/index.html +2 -2
- package/config/workflows/planning-pipeline.yaml +0 -249
- package/config/workflows/task-pipeline2.yaml +0 -778
- package/web/_astro/BoardApp.pdtYu-yW.js +0 -1
- package/web/_astro/channel.DEqvaz-I.js +0 -1
|
@@ -36,23 +36,35 @@ vars:
|
|
|
36
36
|
states:
|
|
37
37
|
- id: precheck
|
|
38
38
|
description: >
|
|
39
|
-
Soft precheck: task check + agent doctor
|
|
40
|
-
|
|
39
|
+
Soft precheck: task check + agent doctor, each owned by a deterministic `command.gate`
|
|
40
|
+
(D5-J, ADR-069). Both gates run `softFail: true`, so a red probe records FAIL and lets
|
|
41
|
+
the transitions route to `failed` instead of aborting the run — the shipped action
|
|
42
|
+
schema exposes no `onError`, so soft mode is what preserves that routing.
|
|
43
|
+
The canonical `.spur/run/$wbs-docs-precheck.status` is the AND of the two gate files.
|
|
41
44
|
onEnter:
|
|
45
|
+
- kind: command.gate
|
|
46
|
+
options:
|
|
47
|
+
id: docs-precheck-task
|
|
48
|
+
executable: "${vars.spurBin}"
|
|
49
|
+
args: ["task", "check", "${vars.wbs}"]
|
|
50
|
+
resultFile: .spur/run/${vars.wbs}-docs-precheck-task.status
|
|
51
|
+
softFail: true
|
|
52
|
+
timeoutMs: 120000
|
|
53
|
+
- kind: command.gate
|
|
54
|
+
options:
|
|
55
|
+
id: docs-precheck-agent
|
|
56
|
+
executable: "${vars.spurBin}"
|
|
57
|
+
args: ["agent", "doctor", "${vars.agent}"]
|
|
58
|
+
resultFile: .spur/run/${vars.wbs}-docs-precheck-agent.status
|
|
59
|
+
softFail: true
|
|
60
|
+
timeoutMs: 120000
|
|
42
61
|
- kind: shell
|
|
43
62
|
options:
|
|
44
63
|
command: >-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
set -e &&
|
|
50
|
-
if [ "$check_rc" -eq 0 ] && [ "$doctor_rc" -eq 0 ]; then
|
|
51
|
-
printf 'PASS\n' > ".spur/run/$wbs-docs-precheck.status";
|
|
52
|
-
else
|
|
53
|
-
printf 'FAIL\n' > ".spur/run/$wbs-docs-precheck.status";
|
|
54
|
-
fi &&
|
|
55
|
-
exit 0
|
|
64
|
+
if test "$(cat .spur/run/$wbs-docs-precheck-task.status 2>/dev/null)" = PASS &&
|
|
65
|
+
test "$(cat .spur/run/$wbs-docs-precheck-agent.status 2>/dev/null)" = PASS;
|
|
66
|
+
then printf 'PASS\n' > ".spur/run/$wbs-docs-precheck.status";
|
|
67
|
+
else printf 'FAIL\n' > ".spur/run/$wbs-docs-precheck.status"; fi
|
|
56
68
|
- kind: note
|
|
57
69
|
options:
|
|
58
70
|
message: "Docs pipeline start for task ${vars.wbs}."
|
|
@@ -109,6 +121,10 @@ states:
|
|
|
109
121
|
mkdir -p .spur/run &&
|
|
110
122
|
printf '%s\n' "{\"wbs\":\"$wbs\",\"verdict\":\"PASS\",\"source\":\"docs-pipeline\",\"requirements\":[{\"id\":\"docs-deliverable\",\"status\":\"MET\",\"evidence\":\"docs-pipeline record step\"}],\"acceptanceCriteria\":[],\"checks\":[{\"name\":\"docs-only\",\"status\":\"pass\",\"evidence\":\"docs-pipeline\"}]}"
|
|
111
123
|
> ".spur/run/$wbs-verdict.json"
|
|
124
|
+
- kind: run.artifact
|
|
125
|
+
options:
|
|
126
|
+
path: .spur/run/${vars.wbs}-verdict.json
|
|
127
|
+
artifactKind: verify-verdict
|
|
112
128
|
- kind: shell
|
|
113
129
|
options:
|
|
114
130
|
command: "$spurBin task update $wbs done --no-lifecycle"
|
|
@@ -48,6 +48,11 @@ vars:
|
|
|
48
48
|
profile: "standard"
|
|
49
49
|
spurBin: "spur"
|
|
50
50
|
stepTimeoutMs: "1800000"
|
|
51
|
+
# Integration review (D5-P, feature R11). Advisory by default: a pending, timed-out, or
|
|
52
|
+
# quota-unavailable review must never block a locally-verified feature. Set
|
|
53
|
+
# requireCleanReview=true to opt into a hard gate for a branch that must ship clean.
|
|
54
|
+
baseBranch: ""
|
|
55
|
+
requireCleanReview: "false"
|
|
51
56
|
# Injected by WorkflowAppService.run(); scopes .spur/run artifacts per run (0425 R4).
|
|
52
57
|
__runId: ""
|
|
53
58
|
|
|
@@ -136,6 +141,35 @@ states:
|
|
|
136
141
|
AC, traceability, and that all linked tasks are done. A clean strict check is the only
|
|
137
142
|
proof the feature is shippable.
|
|
138
143
|
|
|
144
|
+
- id: integration-review
|
|
145
|
+
description: >
|
|
146
|
+
Advisory integration review (D5-P, feature R11). Runs `config/workflows/pr-review.yaml`
|
|
147
|
+
ONCE for this feature/branch HEAD, after the local gates and before wrap merge/cleanup.
|
|
148
|
+
Current-HEAD dedup stays inside pr-review (`mode: full`), so a re-entry on the same HEAD
|
|
149
|
+
is a no-op there rather than a second quota spend here.
|
|
150
|
+
|
|
151
|
+
The gate is `softFail: true`, so `pending`, a wait timeout, a missing pr-review
|
|
152
|
+
definition, or an unavailable review quota records FAIL and still reaches `done`.
|
|
153
|
+
Only `requireCleanReview=true` turns that FAIL into a blocking edge. Findings are
|
|
154
|
+
collected by pr-review itself and re-enter the affected local gates on the next run.
|
|
155
|
+
onEnter:
|
|
156
|
+
- kind: command.gate
|
|
157
|
+
options:
|
|
158
|
+
id: feature-integration-review
|
|
159
|
+
executable: "${vars.spurBin}"
|
|
160
|
+
args:
|
|
161
|
+
- workflow
|
|
162
|
+
- run
|
|
163
|
+
- .spur/workflows/pr-review.yaml
|
|
164
|
+
- --vars
|
|
165
|
+
- '{"mode":"full","baseBranch":"${vars.baseBranch}"}'
|
|
166
|
+
resultFile: .spur/run/${vars.__runId}-integration-review.status
|
|
167
|
+
softFail: true
|
|
168
|
+
timeoutMs: 1800000
|
|
169
|
+
- kind: note
|
|
170
|
+
options:
|
|
171
|
+
message: "Integration review for feature ${vars.featureId} recorded at .spur/run/${vars.__runId}-integration-review.status (advisory unless requireCleanReview=true)."
|
|
172
|
+
|
|
139
173
|
- id: done
|
|
140
174
|
description: Terminal — feature planned, all tasks executed, and the feature verified.
|
|
141
175
|
# Checkpoint write: record session state for resume (Phase 4, task 0171 R3)
|
|
@@ -195,12 +229,30 @@ transitions:
|
|
|
195
229
|
# ── feature-verify gate: strict check certifies done, else fail ──
|
|
196
230
|
# Declaration order: the pass guard is tried FIRST.
|
|
197
231
|
- from: feature-verify
|
|
198
|
-
to:
|
|
199
|
-
description: Strict feature check passed —
|
|
232
|
+
to: integration-review
|
|
233
|
+
description: Strict feature check passed — spend one integration review on this stable HEAD.
|
|
200
234
|
guard:
|
|
201
235
|
kind: shell
|
|
202
236
|
options:
|
|
203
237
|
command: "$spurBin feature check $featureId --strict"
|
|
238
|
+
|
|
239
|
+
- from: integration-review
|
|
240
|
+
to: failed
|
|
241
|
+
description: >
|
|
242
|
+
Review came back FAIL and this branch opted into a hard gate
|
|
243
|
+
(requireCleanReview=true). Ordered before the advisory edge so the strict
|
|
244
|
+
policy wins when both would match.
|
|
245
|
+
guard:
|
|
246
|
+
kind: shell
|
|
247
|
+
options:
|
|
248
|
+
command: 'test "$requireCleanReview" = true && test "$(cat .spur/run/$__runId-integration-review.status 2>/dev/null)" = FAIL'
|
|
249
|
+
- from: integration-review
|
|
250
|
+
to: done
|
|
251
|
+
description: >
|
|
252
|
+
Review clean, pending, unavailable, or advisory — the feature is complete. A
|
|
253
|
+
non-clean advisory review never blocks a locally-verified feature (feature R11).
|
|
254
|
+
guard:
|
|
255
|
+
kind: always
|
|
204
256
|
- from: feature-verify
|
|
205
257
|
to: failed
|
|
206
258
|
description: Strict feature check failed — block before done; investigate incomplete tasks or AC.
|
|
@@ -379,9 +379,20 @@ states:
|
|
|
379
379
|
# flipping the recommendation to runall — violating R3's any-fail=>refineall invariant.
|
|
380
380
|
# Each `jq -c … >> "$CHECKS"` appends under `|| exit 1`, and a row-count assertion
|
|
381
381
|
# (CHECKS lines == WBS count) gates the recommendation computation.
|
|
382
|
+
# D5-O (R4): the deterministic writer owns finalization wherever it exists.
|
|
383
|
+
# `idea-handoff-cli.ts` calls the tested `finalizeIdeaHandoff` capability and
|
|
384
|
+
# implements this exact contract (equal-length/unique-name zip, `spur task deps`,
|
|
385
|
+
# `spur feature refresh`, per-task check with a row-count assertion, and a single
|
|
386
|
+
# recommended next command). `spur init` never scaffolds `packages/`, so seeded
|
|
387
|
+
# projects fall through to the portable shell program below — the same
|
|
388
|
+
# monorepo-writer/shell-fallback split the wrap-up metrics hop uses (0604 Q&A).
|
|
382
389
|
- kind: shell
|
|
383
390
|
options:
|
|
384
391
|
command: >-
|
|
392
|
+
if [ -f packages/app/src/workflow/idea-handoff-cli.ts ]; then
|
|
393
|
+
bun packages/app/src/workflow/idea-handoff-cli.ts;
|
|
394
|
+
exit $?;
|
|
395
|
+
fi;
|
|
385
396
|
BATCH=".spur/run/$__runId-idea-task-batch.json" &&
|
|
386
397
|
RESULT=".spur/run/$__runId-idea-batch-create-result.json" &&
|
|
387
398
|
ORDER=".spur/run/$__runId-idea-task-order.json" &&
|
|
@@ -452,6 +463,10 @@ states:
|
|
|
452
463
|
- kind: note
|
|
453
464
|
options:
|
|
454
465
|
message: "Idea pipeline handoff. Feature: ${vars.featureId}. See .spur/run/${vars.__runId}-idea-handoff.md for the created task list and recommended next command."
|
|
466
|
+
- kind: run.artifact
|
|
467
|
+
options:
|
|
468
|
+
path: .spur/run/${vars.__runId}-idea-handoff.md
|
|
469
|
+
artifactKind: idea-handoff
|
|
455
470
|
# Checkpoint write: record session state for resume (Phase 4, task 0171 R3)
|
|
456
471
|
- kind: shell
|
|
457
472
|
options:
|
|
@@ -78,6 +78,15 @@ vars:
|
|
|
78
78
|
# Answer captured by the approve gate's hitl.confirm (R1): "yes" | "no" | "cancel".
|
|
79
79
|
# Empty by default; only meaningful once the approve state has been entered.
|
|
80
80
|
__hitlAnswer: ""
|
|
81
|
+
# Proof-state bracket (task 0612, ADR-071). `proofDigest` is captured at verify-exit, once the
|
|
82
|
+
# verdict artifact exists; `proofDigestNow` is the re-capture compared against it immediately
|
|
83
|
+
# before `record`. A mismatch means a proof input changed after the verdict was established, so
|
|
84
|
+
# the run routes to `failed` instead of crossing the completion boundary. `taskSpecPath` carries
|
|
85
|
+
# the task file path because `docs/tasks*` is excluded from the digest's git-tree half — spec
|
|
86
|
+
# content is folded in explicitly or a task-file edit would go undetected.
|
|
87
|
+
proofDigest: ""
|
|
88
|
+
proofDigestNow: ""
|
|
89
|
+
taskSpecPath: ""
|
|
81
90
|
# Project quality gate for the `test` hop (probe + fixall + recheck). Override per project
|
|
82
91
|
# with the same package-manager surface (this monorepo is Bun-only):
|
|
83
92
|
# `--vars '{"qualityGateCmd":"bun run lint && bun run test"}'`. Soft probe, hard recheck,
|
|
@@ -124,72 +133,33 @@ states:
|
|
|
124
133
|
`spur task check <wbs>`. Failures route to the `failed` terminal state
|
|
125
134
|
(not a raw lifecycle abort mid-enter).
|
|
126
135
|
onEnter:
|
|
127
|
-
#
|
|
128
|
-
#
|
|
136
|
+
# Pre-launch executor doctor probe (task 0608 / D6 R4–R5). The auth classifier —
|
|
137
|
+
# per-agent-family classification (omp/pi env-key misses soft, explicit auth
|
|
138
|
+
# failures hard) plus the executor-divergence line — now lives in the
|
|
139
|
+
# `doctor.probe` built-in action kind (`packages/app/src/workflow/actions/doctor-probe.ts`)
|
|
140
|
+
# instead of this shell program; that is the ownership-surface landing for the
|
|
141
|
+
# task-pipeline precheck doctor probe (option c, least-privilege built-in).
|
|
129
142
|
#
|
|
130
|
-
#
|
|
131
|
-
#
|
|
132
|
-
#
|
|
133
|
-
#
|
|
134
|
-
#
|
|
135
|
-
#
|
|
136
|
-
#
|
|
137
|
-
#
|
|
138
|
-
#
|
|
139
|
-
#
|
|
140
|
-
#
|
|
141
|
-
#
|
|
142
|
-
|
|
143
|
+
# Semantics preserved from the replaced shell (behavior parity is covered by
|
|
144
|
+
# `packages/app/tests/workflow/actions/doctor-probe.test.ts`):
|
|
145
|
+
# R2 (0487): probe BOTH resolved executors ($agent and $implementAgent) and
|
|
146
|
+
# FAIL on `authenticated: unauthenticated`. Previously only $agent was probed
|
|
147
|
+
# and auth was informational, so a run whose implement executor had no
|
|
148
|
+
# provider key sailed through precheck into a guaranteed implement failure
|
|
149
|
+
# (runs e8cb00e7 / b16bfbf4). `unknown` auth keeps the old soft behavior —
|
|
150
|
+
# some agents expose no auth-status verb. `spur agent doctor` CLI exit-code
|
|
151
|
+
# semantics are deliberately untouched; the gate lives here.
|
|
152
|
+
# R4 (0487): one divergence line when the two executors differ.
|
|
153
|
+
# R2 (0503): omp/pi env-key probe misses are soft because the CLI process
|
|
154
|
+
# cannot see relay-owned credentials; explicit non-omp auth failures remain hard.
|
|
155
|
+
# Soft probe: writes PASS/FAIL to the status file and always succeeds so the
|
|
156
|
+
# transition guards below route on the token (never a raw lifecycle abort).
|
|
157
|
+
- kind: doctor.probe
|
|
143
158
|
options:
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
PROBE_DETAIL="$1";
|
|
149
|
-
PROBE_AGENT="$2";
|
|
150
|
-
case "$PROBE_AGENT" in
|
|
151
|
-
omp|omp-*|pi|pi-*)
|
|
152
|
-
if printf '%s' "$PROBE_DETAIL" | grep -Eiq 'API key not found for provider|no probe registered'; then
|
|
153
|
-
printf 'env-miss\n';
|
|
154
|
-
return;
|
|
155
|
-
fi;;
|
|
156
|
-
esac;
|
|
157
|
-
if printf '%s' "$PROBE_DETAIL" | grep -Eiq 'invalid (API )?key|unauthori[sz]ed|forbidden|authentication failed|credential(s)? rejected'; then
|
|
158
|
-
printf 'auth-fail\n';
|
|
159
|
-
else
|
|
160
|
-
printf 'unknown\n';
|
|
161
|
-
fi;
|
|
162
|
-
} &&
|
|
163
|
-
STATUS=PASS;
|
|
164
|
-
if [ -n "$implementAgent" ] && [ "$implementAgent" != "$agent" ]; then
|
|
165
|
-
echo "precheck: agent=$agent implementAgent=$implementAgent (executors diverge)";
|
|
166
|
-
EXECS="$agent $implementAgent";
|
|
167
|
-
else
|
|
168
|
-
EXECS="$agent";
|
|
169
|
-
fi;
|
|
170
|
-
for EXE in $EXECS; do
|
|
171
|
-
OUT=$($spurBin agent doctor "$EXE" --json 2>&1) || {
|
|
172
|
-
echo "precheck: FAIL - doctor exited non-zero for $EXE";
|
|
173
|
-
echo "$OUT";
|
|
174
|
-
STATUS=FAIL;
|
|
175
|
-
continue;
|
|
176
|
-
};
|
|
177
|
-
AUTH=$(printf '%s' "$OUT" | jq -r '.agents[0].authenticated // "unknown"' 2>/dev/null || echo unknown);
|
|
178
|
-
DETAIL=$(printf '%s' "$OUT" | jq -r '.agents[0].modelStatus.detail // ""' 2>/dev/null || echo "");
|
|
179
|
-
PROBE=$(classifyDoctorProbe "$DETAIL" "$EXE");
|
|
180
|
-
echo "precheck: $EXE auth=$AUTH probe=$PROBE $DETAIL";
|
|
181
|
-
if [ "$AUTH" = unauthenticated ]; then
|
|
182
|
-
case "$EXE:$PROBE" in
|
|
183
|
-
omp*:env-miss|pi*:env-miss|omp*:unknown|pi*:unknown)
|
|
184
|
-
echo "precheck: SOFT - executor $EXE auth probe cannot see agent-owned credentials";;
|
|
185
|
-
*)
|
|
186
|
-
echo "precheck: FAIL - executor $EXE is unauthenticated; fix agent.default or pass --vars '{\"agent\":\"<authenticated-executor>\"}' ($spurBin agent doctor $EXE --json); $DETAIL";
|
|
187
|
-
STATUS=FAIL;;
|
|
188
|
-
esac;
|
|
189
|
-
fi;
|
|
190
|
-
done;
|
|
191
|
-
echo "$STATUS" > "$DOCTOR_FILE";
|
|
192
|
-
exit 0
|
|
159
|
+
resultFile: ".spur/run/${vars.wbs}-precheck-doctor.status"
|
|
160
|
+
spurBin: "${vars.spurBin}"
|
|
161
|
+
agent: "${vars.agent}"
|
|
162
|
+
implementAgent: "${vars.implementAgent}"
|
|
193
163
|
# R6 (0487): pre-launch hygiene WARNING (never a block) — starting a task on
|
|
194
164
|
# a tree already dirty with another task's implementation is how 0485's diff
|
|
195
165
|
# got swept into 0486's run. Corpus dirs are excluded: the pipeline writes
|
|
@@ -245,9 +215,14 @@ states:
|
|
|
245
215
|
command: >-
|
|
246
216
|
SIZE_FILE=".spur/run/$wbs-precheck-size.status" &&
|
|
247
217
|
mkdir -p .spur/run &&
|
|
218
|
+
if [ -f plugins/sp/scripts/task-size-precheck.ts ]; then
|
|
248
219
|
bun plugins/sp/scripts/task-size-precheck.ts "$wbs"
|
|
249
220
|
--spur-bin "$spurBin" --max-reqs "$maxImplementReqs" --max-plan-items "$maxImplementPlanItems"
|
|
250
|
-
--executor "$implementAgent"
|
|
221
|
+
--executor "$implementAgent";
|
|
222
|
+
else
|
|
223
|
+
echo "task-size-precheck skipped — plugins/sp/scripts/task-size-precheck.ts not present in project." >&2 &&
|
|
224
|
+
echo "PASS" > "$SIZE_FILE";
|
|
225
|
+
fi &&
|
|
251
226
|
exit 0
|
|
252
227
|
|
|
253
228
|
- id: implement
|
|
@@ -486,6 +461,27 @@ states:
|
|
|
486
461
|
- kind: shell
|
|
487
462
|
options:
|
|
488
463
|
command: "$spurBin task verdict $wbs --from-answer .spur/run/$wbs-verify-answer.txt"
|
|
464
|
+
# Proof-state capture (task 0612, ADR-071). Placement is load-bearing: AFTER the verdict
|
|
465
|
+
# artifact exists, never before `verify`. `/sp:dev-verify --fix all` writes to the tree by
|
|
466
|
+
# design when it repairs a row, so an earlier capture would fire on verify's own legitimate
|
|
467
|
+
# repairs instead of on a violation.
|
|
468
|
+
- kind: shell
|
|
469
|
+
options:
|
|
470
|
+
command: '$spurBin task path $wbs --json 2>/dev/null | jq -r ".path // empty" > ".spur/run/$wbs-taskpath.txt" || true; exit 0'
|
|
471
|
+
- kind: file.read.into-var
|
|
472
|
+
options:
|
|
473
|
+
path: .spur/run/${vars.wbs}-taskpath.txt
|
|
474
|
+
var: taskSpecPath
|
|
475
|
+
- kind: proof.fingerprint
|
|
476
|
+
options:
|
|
477
|
+
var: proofDigest
|
|
478
|
+
taskFile: ${vars.taskSpecPath}
|
|
479
|
+
# R3: the evidence must NAME the digest, not just assert proof validity in prose. Stamp it
|
|
480
|
+
# into the verdict artifact's checks[] so the document that aggregates quality, review, and
|
|
481
|
+
# verification results carries the value `record`'s compare then proves unchanged.
|
|
482
|
+
- kind: shell
|
|
483
|
+
options:
|
|
484
|
+
command: 'V=".spur/run/$wbs-verdict.json"; if [ -f "$V" ] && [ -n "$proofDigest" ]; then jq --arg d "$proofDigest" ".checks += [{\"name\":\"proof-input-digest\",\"status\":\"pass\",\"evidence\":\$d}]" "$V" > "$V.tmp" && mv "$V.tmp" "$V"; fi; exit 0'
|
|
489
485
|
|
|
490
486
|
- id: record
|
|
491
487
|
description: >
|
|
@@ -496,6 +492,15 @@ states:
|
|
|
496
492
|
retry-suppression) if `feature_id` is present, or appends an orphan link proposal
|
|
497
493
|
to the run report if absent (task 0328 / ADR-0322).
|
|
498
494
|
onEnter:
|
|
495
|
+
# Proof-state compare (task 0612, ADR-071) — FIRST action in the state, so it runs before any
|
|
496
|
+
# record write. Re-captures the digest and asserts it equals the value taken at verify-exit.
|
|
497
|
+
# A mismatch means a proof input changed after the verdict was established; the default `fail`
|
|
498
|
+
# policy halts the sequence and routes the run to `failed` rather than crossing into `record`.
|
|
499
|
+
- kind: proof.fingerprint
|
|
500
|
+
options:
|
|
501
|
+
var: proofDigestNow
|
|
502
|
+
taskFile: ${vars.taskSpecPath}
|
|
503
|
+
expect: ${vars.proofDigest}
|
|
499
504
|
- kind: shell
|
|
500
505
|
options:
|
|
501
506
|
command: >-
|
|
@@ -558,6 +563,13 @@ states:
|
|
|
558
563
|
return "$RETRY_RC";
|
|
559
564
|
};
|
|
560
565
|
retry_transient $spurBin task update "$wbs" done --no-lifecycle
|
|
566
|
+
# D5-L: the verify verdict is this pipeline's proof of completion, so its ownership
|
|
567
|
+
# belongs to a deterministic primitive rather than an untracked file on disk.
|
|
568
|
+
# `run.artifact` records path + kind + runId only — never the body (ADR-069).
|
|
569
|
+
- kind: run.artifact
|
|
570
|
+
options:
|
|
571
|
+
path: .spur/run/${vars.wbs}-verdict.json
|
|
572
|
+
artifactKind: verify-verdict
|
|
561
573
|
- kind: note
|
|
562
574
|
options:
|
|
563
575
|
message: "Pipeline complete for task ${vars.wbs} (done gate cleared)."
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
# apply identically. Branch cleanup is an irreversible HITL gate — it always pauses,
|
|
8
8
|
# even under --auto (Iron Law #6: irreversible action -> surface to human).
|
|
9
9
|
#
|
|
10
|
-
# Shape: start -> task-resolve -> doc-sync ->
|
|
10
|
+
# Shape: start -> task-resolve -> doc-sync -> metrics-record
|
|
11
11
|
# -> feature-transition (conditional: if vars.feature set)
|
|
12
12
|
# -> branch-cleanup (conditional: if vars.merge=true)
|
|
13
13
|
# -> done
|
|
@@ -25,8 +25,10 @@
|
|
|
25
25
|
# Reliability (aligned with task-pipeline / ADR-043):
|
|
26
26
|
# - Prefer pure slash commands when a command exists; free-form inputs remain only
|
|
27
27
|
# where capture artifacts (answerFile) have no dedicated slash surface yet.
|
|
28
|
-
# -
|
|
29
|
-
# does not abort wrap-up after prior steps already landed).
|
|
28
|
+
# - doc-sync / metrics-record use expectFile + soft append (empty capture
|
|
29
|
+
# does not abort wrap-up after prior steps already landed). The doc-sync hop is a
|
|
30
|
+
# single model query that both repairs doc drift (sp:doc-evolve) and captures
|
|
31
|
+
# working learnings (task 0607 R2 — one query answers both; count 2 -> 1).
|
|
30
32
|
# - feature-transition is a soft shell (always exit 0) so a blocked feature sync
|
|
31
33
|
# does not abort wrap-up after learnings/metrics already landed.
|
|
32
34
|
# - branch-cleanup HITL is exhaustive (yes/no/cancel → done; missing answer defense).
|
|
@@ -35,7 +37,7 @@
|
|
|
35
37
|
"$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
|
|
36
38
|
kind: state-machine
|
|
37
39
|
name: wrapup-pipeline
|
|
38
|
-
description: "Post-execution wrap-up: doc-sync
|
|
40
|
+
description: "Post-execution wrap-up: doc-sync (doc drift + learning capture), metrics, feature-transition, branch-cleanup"
|
|
39
41
|
iterationBound: 10
|
|
40
42
|
initialState: start
|
|
41
43
|
terminalStates:
|
|
@@ -73,28 +75,24 @@ states:
|
|
|
73
75
|
|
|
74
76
|
- id: doc-sync
|
|
75
77
|
description: >
|
|
76
|
-
|
|
77
|
-
00_ADR, docs/design/*)
|
|
78
|
-
|
|
78
|
+
ONE model query that both repairs project-level doc drift for the batch
|
|
79
|
+
(04_DESIGN, 03_ARCHITECTURE, 00_ADR, docs/design/*) and captures working
|
|
80
|
+
learnings (task 0607 R2: two adjacent agent.run hops merged, count 2 -> 1;
|
|
81
|
+
no operator-decision pause or verdict boundary sits between them). No dedicated
|
|
82
|
+
slash command yet — free-form skill pointer until a /sp:doc-evolve command
|
|
83
|
+
exists (ADR-043 residual). Capture+shell decoupling preserved: expectFile gates
|
|
84
|
+
a non-empty capture before the append; append is best-effort soft (empty capture
|
|
85
|
+
skips without aborting wrap-up).
|
|
79
86
|
onEnter:
|
|
80
87
|
- kind: agent.run
|
|
81
88
|
options:
|
|
82
89
|
agent: ${vars.agent}
|
|
83
|
-
input:
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
description: >
|
|
90
|
-
Append working learnings to .spur/memory/learnings.md. Capture+shell decoupling:
|
|
91
|
-
expectFile gates non-empty capture before append; append is best-effort soft
|
|
92
|
-
(empty capture skips without aborting wrap-up).
|
|
93
|
-
onEnter:
|
|
94
|
-
- kind: agent.run
|
|
95
|
-
options:
|
|
96
|
-
agent: ${vars.agent}
|
|
97
|
-
input: "Extract working learnings from tasks ${vars.tasks}. Output raw markdown (no fences) grouped by date and task WBS: conventions, errors fixed, patterns, gotchas. Captured to .spur/run/wrapup-learnings.md."
|
|
90
|
+
input: >-
|
|
91
|
+
First run Skill(skill="sp:doc-evolve", args="wrapup tasks=${vars.tasks}") to repair drift in
|
|
92
|
+
docs/00_ADR.md, docs/03_ARCHITECTURE.md, docs/04_DESIGN.md, docs/design/* per constitution edit
|
|
93
|
+
rules; do not write task/feature corpus. THEN extract working learnings from tasks ${vars.tasks} —
|
|
94
|
+
conventions, errors fixed, patterns, gotchas, grouped by date and task WBS — as raw markdown
|
|
95
|
+
(no fences) and END your final message with that markdown (it is captured to .spur/run/wrapup-learnings.md).
|
|
98
96
|
# Declared Layer-1 role (0538 R2): routing reason beside the agent: pin.
|
|
99
97
|
role: coder
|
|
100
98
|
answerFile: .spur/run/wrapup-learnings.md
|
|
@@ -114,27 +112,29 @@ states:
|
|
|
114
112
|
|
|
115
113
|
- id: metrics-record
|
|
116
114
|
description: >
|
|
117
|
-
Append one JSONL row per task to .spur/memory/wrapup-metrics.jsonl.
|
|
118
|
-
(empty capture does not abort wrap-up after learnings already landed).
|
|
115
|
+
Append one JSONL row per task to .spur/memory/wrapup-metrics.jsonl deterministically.
|
|
119
116
|
onEnter:
|
|
120
|
-
- kind: agent.run
|
|
121
|
-
options:
|
|
122
|
-
agent: ${vars.agent}
|
|
123
|
-
input: "For each task in ${vars.tasks}, output one JSONL line (no fences) with fields: wbs, feature_id, status, verdict, timestamp. Captured to .spur/run/wrapup-metrics.jsonl."
|
|
124
|
-
# Declared Layer-1 role (0538 R2): routing reason beside the agent: pin.
|
|
125
|
-
role: scribe
|
|
126
|
-
answerFile: .spur/run/wrapup-metrics.jsonl
|
|
127
|
-
expectFile: .spur/run/wrapup-metrics.jsonl
|
|
128
|
-
timeoutMs: ${vars.stepTimeoutMs}
|
|
129
117
|
- kind: shell
|
|
130
118
|
options:
|
|
131
119
|
command: >-
|
|
132
120
|
mkdir -p .spur/memory &&
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
121
|
+
printf '%s' "$tasks" | jq -r '(if type == "string" then (try fromjson catch .) else . end) | if type == "array" then .[] else empty end' |
|
|
122
|
+
while IFS= read -r wbs; do
|
|
123
|
+
if [ -n "$wbs" ]; then
|
|
124
|
+
task_json=$($spurBin task show "$wbs" --json 2>/dev/null || true);
|
|
125
|
+
if [ -n "$task_json" ]; then
|
|
126
|
+
feat=$(printf '%s' "$task_json" | jq -r '.frontmatter.feature_id // .feature_id // empty' 2>/dev/null || true);
|
|
127
|
+
stat=$(printf '%s' "$task_json" | jq -r '.frontmatter.status // .status // "unknown"' 2>/dev/null || true);
|
|
128
|
+
verdict="UNKNOWN";
|
|
129
|
+
if [ -f ".spur/run/$wbs-verdict.json" ]; then
|
|
130
|
+
v=$(jq -r '.verdict // "UNKNOWN"' ".spur/run/$wbs-verdict.json" 2>/dev/null || true);
|
|
131
|
+
if [ -n "$v" ]; then verdict="$v"; fi;
|
|
132
|
+
fi;
|
|
133
|
+
ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ");
|
|
134
|
+
printf '{"wbs":"%s","feature_id":"%s","status":"%s","verdict":"%s","timestamp":"%s"}\n' "$wbs" "$feat" "$stat" "$verdict" "$ts" >> .spur/memory/wrapup-metrics.jsonl;
|
|
135
|
+
fi;
|
|
136
|
+
fi;
|
|
137
|
+
done &&
|
|
138
138
|
exit 0
|
|
139
139
|
|
|
140
140
|
- id: feature-transition
|
|
@@ -226,15 +226,10 @@ transitions:
|
|
|
226
226
|
guard:
|
|
227
227
|
kind: always
|
|
228
228
|
|
|
229
|
-
# ── linear body: doc-sync ->
|
|
229
|
+
# ── linear body: doc-sync -> metrics-record ──
|
|
230
230
|
- from: doc-sync
|
|
231
|
-
to: learning-capture
|
|
232
|
-
description: Doc sync complete — capture learnings.
|
|
233
|
-
guard:
|
|
234
|
-
kind: always
|
|
235
|
-
- from: learning-capture
|
|
236
231
|
to: metrics-record
|
|
237
|
-
description:
|
|
232
|
+
description: Doc drift repair + learning capture complete — record metrics.
|
|
238
233
|
guard:
|
|
239
234
|
kind: always
|
|
240
235
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gobing-ai/spur",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.55",
|
|
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",
|
|
@@ -53,14 +53,14 @@
|
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@commander-js/extra-typings": "^14.0.0",
|
|
56
|
-
"@gobing-ai/ts-db": "^0.4.
|
|
57
|
-
"@gobing-ai/ts-ai-runner": "^0.4.
|
|
58
|
-
"@gobing-ai/ts-dual-workflow-engine": "^0.4.
|
|
59
|
-
"@gobing-ai/ts-infra": "^0.4.
|
|
60
|
-
"@gobing-ai/ts-llm-jsonl-importer": "^0.4.
|
|
61
|
-
"@gobing-ai/ts-rule-engine": "^0.4.
|
|
62
|
-
"@gobing-ai/ts-runtime": "^0.4.
|
|
63
|
-
"@gobing-ai/ts-utils": "^0.4.
|
|
56
|
+
"@gobing-ai/ts-db": "^0.4.39",
|
|
57
|
+
"@gobing-ai/ts-ai-runner": "^0.4.39",
|
|
58
|
+
"@gobing-ai/ts-dual-workflow-engine": "^0.4.39",
|
|
59
|
+
"@gobing-ai/ts-infra": "^0.4.39",
|
|
60
|
+
"@gobing-ai/ts-llm-jsonl-importer": "^0.4.39",
|
|
61
|
+
"@gobing-ai/ts-rule-engine": "^0.4.39",
|
|
62
|
+
"@gobing-ai/ts-runtime": "^0.4.39",
|
|
63
|
+
"@gobing-ai/ts-utils": "^0.4.39",
|
|
64
64
|
"@types/bun": "1.3.14",
|
|
65
65
|
"@types/figlet": "^1.7.0",
|
|
66
66
|
"@types/node-notifier": "8.0.5",
|
package/plugins/README.md
CHANGED
|
@@ -359,8 +359,8 @@ Each pipeline owns one lifecycle phase:
|
|
|
359
359
|
| `basic.yaml` | Generic implement/check/fix | direct `spur workflow run` | existing |
|
|
360
360
|
| `feature-lifecycle.yaml` | Feature status FSM | `spur feature update` | existing |
|
|
361
361
|
| `task-lifecycle.yaml` | Task status FSM | `spur task update` | existing |
|
|
362
|
-
| `planning-pipeline.yaml` | Planning/design from known slug | `/sp:dev-plan` | existing |
|
|
363
362
|
| `task-pipeline.yaml` | Single-task execution | `/sp:dev-run` | existing |
|
|
363
|
+
| `idea-pipeline.yaml` | Idea/planning → feature + tasks | `/sp:dev-idea`, `/sp:dev-plan` | existing |
|
|
364
364
|
| `feature-dev.yaml` | Feature umbrella execution | `/sp:dev-runall --feature <id>` | existing |
|
|
365
365
|
| `idea-pipeline.yaml` | Idea to feature + AC + task batch | `/sp:dev-idea` | new in 0.2.12 |
|
|
366
366
|
| `wrapup-pipeline.yaml` | Post-execution wrap-up | `/sp:dev-wrap`, `/sp:dev-wrapall` | new in 0.2.12 |
|
package/plugins/sp/README.md
CHANGED
|
@@ -360,8 +360,8 @@ no per-platform artifacts — only the platform-independent thin wrappers.
|
|
|
360
360
|
**Thin-wrapper contract** is enforced by `scripts/validate-commands.ts`:
|
|
361
361
|
|
|
362
362
|
```bash
|
|
363
|
-
bun
|
|
364
|
-
bun
|
|
363
|
+
bun run validate-commands # validate all 39 commands
|
|
364
|
+
bun run validate-commands --json # machine-readable output
|
|
365
365
|
```
|
|
366
366
|
|
|
367
367
|
The validator checks five gates. For **non-`dev-*`** commands: (a) heading whitelist — only
|
|
@@ -583,8 +583,8 @@ pipeline owns one lifecycle phase:
|
|
|
583
583
|
| `basic.yaml` | Generic implement/check/fix | direct `spur workflow run` |
|
|
584
584
|
| `feature-lifecycle.yaml` | Feature status FSM | `spur feature update` |
|
|
585
585
|
| `task-lifecycle.yaml` | Task status FSM | `spur task update` |
|
|
586
|
-
| `planning-pipeline.yaml` | Planning/design from known slug | `/sp:dev-plan` |
|
|
587
586
|
| `task-pipeline.yaml` | Single-task execution | `/sp:dev-run` |
|
|
587
|
+
| `idea-pipeline.yaml` | Idea/planning → feature + tasks | `/sp:dev-idea`, `/sp:dev-plan` |
|
|
588
588
|
| `feature-dev.yaml` | Feature umbrella execution | `/sp:dev-runall --feature` |
|
|
589
589
|
| `idea-pipeline.yaml` | Idea to feature + AC + task batch | `/sp:dev-idea` |
|
|
590
590
|
| `wrapup-pipeline.yaml` | Post-execution wrap-up | `/sp:dev-wrap`, `/sp:dev-wrapall` |
|
|
@@ -153,7 +153,7 @@ When you fan out or dispatch a subagent, apply the four disciplines the SSOT
|
|
|
153
153
|
- [ ] Drive the loop in execution-batch.md - resolve -> freeze -> order -> **preflight** -> run -> inspect
|
|
154
154
|
-> optional recovery -> decide -> report.
|
|
155
155
|
- [ ] **Preflight** each WBS before `workflow run` using
|
|
156
|
-
`
|
|
156
|
+
`node "$(superskill script path sp batch-preflight.mjs)"` (or the pure `preflightTask` helper) with
|
|
157
157
|
`spur task show --json` deps. On `action: skip` (A2/A7/A8/A9), do **not** start the pipeline;
|
|
158
158
|
record skip in the batch report with the reason string.
|
|
159
159
|
- [ ] Launch each **ready** per-task pipeline with `--async`. The command/script layer polls
|
|
@@ -27,4 +27,4 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
|
|
|
27
27
|
|
|
28
28
|
## Implementation
|
|
29
29
|
|
|
30
|
-
Run the generator per [daily-summary/SKILL.md](../skills/daily-summary/SKILL.md): `
|
|
30
|
+
Run the generator per [daily-summary/SKILL.md](../skills/daily-summary/SKILL.md): `node "$(superskill script path sp daily-summary/daily-summary.mjs)" $ARGUMENTS`.
|
|
@@ -59,5 +59,5 @@ Run the load-then-analyze sequence per `plugins/sp/scripts/history-load.ts` —
|
|
|
59
59
|
only after import exits 0, narrowing forwarded to `analyze` only:
|
|
60
60
|
|
|
61
61
|
```
|
|
62
|
-
|
|
62
|
+
node "$(superskill script path sp history-load.mjs)" $ARGUMENTS
|
|
63
63
|
```
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Turn a vague idea into a feature with AC and a decomposed task batch — discovery, idea-eval, feature-create, AC, feature-check, system-design, decompose, batch-create (Design by default), handoff
|
|
3
3
|
role: planner
|
|
4
|
-
argument-hint: "\"<idea>\" [--auto] [--skip-design] [--approve-taste]"
|
|
4
|
+
argument-hint: "\"<idea>\" [--auto] [--skip-design] [--approve-taste] [--agent <inline|auto|name>]"
|
|
5
5
|
allowed-tools: ["Bash", "Read", "AskUserQuestion"]
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -19,6 +19,7 @@ Wraps the **idea-pipeline.yaml** workflow.
|
|
|
19
19
|
| `--approve-taste` | With `--auto`: set idea_approved + design_approved so idea-eval / design-approval do not pause. | off |
|
|
20
20
|
| `--idea-approved` | Compatibility alias for idea_approved=true (subset of --approve-taste). | off |
|
|
21
21
|
| `--design-approved` | Compatibility alias for design_approved=true (subset of --approve-taste). | off |
|
|
22
|
+
| `--agent` `<inline\|auto\|name>` | Who runs the model-bearing ideation. The pipeline's `agent.run` stages are headless — they always dispatch a subprocess, so `--agent inline` is rejected there with the stable special error (exit 2). Use `omit` (resolves to `agent.default`), `auto` (tier-resolves an executor), or a name (pins that executor). | agent.default |
|
|
22
23
|
|
|
23
24
|
For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag-glossary.md).
|
|
24
25
|
|
|
@@ -29,6 +30,7 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
|
|
|
29
30
|
[--auto] # skip objective HITL only (feature-check, batch-create)
|
|
30
31
|
[--skip-design] # design package off (system-design + task Design)
|
|
31
32
|
[--approve-taste] # with --auto: skip idea-eval + design-approval pauses
|
|
33
|
+
[--agent <inline|auto|name>] # who runs the model-bearing ideation (default: agent.default)
|
|
32
34
|
```
|
|
33
35
|
|
|
34
36
|
There is **no** `--design` force flag. Design is default-on; only `--skip-design` opts out.
|
|
@@ -46,6 +48,12 @@ spur workflow run .spur/workflows/idea-pipeline.yaml --vars '{
|
|
|
46
48
|
"profile":"interactive|auto",
|
|
47
49
|
"design":"auto|skip",
|
|
48
50
|
"design_approved":"false|true",
|
|
49
|
-
"idea_approved":"false|true"
|
|
51
|
+
"idea_approved":"false|true",
|
|
52
|
+
"agent":"<executor-or-role>"
|
|
50
53
|
}'
|
|
51
54
|
```
|
|
55
|
+
|
|
56
|
+
Omit `agent` from `--vars` unless the operator passed `--agent`: an absent var lets `agent.default`
|
|
57
|
+
(a Layer-1 role, resolved to its tier's cheapest usable executor) govern, which is the intended
|
|
58
|
+
routing. Passing `--agent <name>` pins that executor for every `agent.run` stage — the escape hatch
|
|
59
|
+
when the resolved executor is unusable (quota exhaustion, auth failure).
|