@gobing-ai/spur 0.3.71 → 0.3.73
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/config.example.yaml +33 -23
- package/config/corpus-baseline.json +168 -0
- package/config/pipeline-budgets.json +7 -3
- package/config/plugin-scripts.json +4 -0
- package/config/proportional-route-table.ts +155 -0
- package/config/rules/structure/protected-files.yaml +3 -0
- package/config/task-pipeline-proportional-migration-plan.md +79 -0
- package/config/workflow-composition-baseline.json +124 -85
- package/config/workflows/docs-pipeline.yaml +11 -1
- package/config/workflows/feature-dev.yaml +27 -20
- package/config/workflows/task-lifecycle.yaml +27 -15
- package/config/workflows/task-pipeline.yaml +72 -11
- package/config/workflows/wrapup-pipeline.yaml +100 -42
- package/package.json +9 -9
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/scripts/daily-summary/daily-summary.mjs +119 -0
- package/plugins/sp/scripts/daily-summary/daily-summary.ts +202 -0
- package/plugins/sp/scripts/inline-pipeline-parity-check.ts +185 -0
- package/plugins/sp/scripts/task-evidence-precheck.ts +1 -1
- package/plugins/sp/scripts/verify-answer-lint.ts +4 -0
- package/plugins/sp/skills/spur-cli/references/workflows/authoring-workflows.md +23 -0
- package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +20 -0
- package/schemas/spur-config.schema.json +35 -0
- package/schemas/state-machine-workflow.schema.json +3 -1
- package/schemas/transition-flow-workflow.schema.json +3 -1
- package/spur.js +12391 -8659
- package/web/_astro/BoardApp.BYCNkMOn.js +185 -0
- package/web/_astro/BoardApp.E12MFjOS.js +1 -0
- package/web/_astro/{TaskDetail.BvkKvo57.js → TaskDetail.CgUreSP2.js} +1 -1
- package/web/_astro/{arc.DuEIzPMi.js → arc.BySSh34M.js} +1 -1
- package/web/_astro/{architectureDiagram-3BPJPVTR.D0dUxCjA.js → architectureDiagram-3BPJPVTR.DM46TS_h.js} +1 -1
- package/web/_astro/{blockDiagram-GPEHLZMM.Cv60iOpM.js → blockDiagram-GPEHLZMM.tZhvNUHA.js} +1 -1
- package/web/_astro/{c4Diagram-AAUBKEIU.Ddx7WGhb.js → c4Diagram-AAUBKEIU.PT4Or4Nf.js} +1 -1
- package/web/_astro/channel.5cYKr5cs.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.BGKzU_1t.js → chunk-2J33WTMH.J9r0_Bbe.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.FlApjIIH.js → chunk-4BX2VUAB.hzyeIvhR.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.CDfmvDeW.js → chunk-55IACEB6.B0rO7qVh.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.T9bc-xir.js → chunk-727SXJPM.wE_Uk5D4.js} +1 -1
- package/web/_astro/{chunk-AQP2D5EJ.BiTc-MQo.js → chunk-AQP2D5EJ.DqEEjQw7.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.he4KrHni.js → chunk-FMBD7UC4.CDoD9sBX.js} +1 -1
- package/web/_astro/{chunk-ND2GUHAM.D05XuUuJ.js → chunk-ND2GUHAM.CtX5nF9P.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.CA2NThIE.js → chunk-QZHKN3VN.CK_EwfaT.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.Couj-zYZ.js → classDiagram-4FO5ZUOK.DLt5a8Lh.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.Couj-zYZ.js → classDiagram-v2-Q7XG4LA2.DLt5a8Lh.js} +1 -1
- package/web/_astro/{cose-bilkent-S5V4N54A.B8YYW7NG.js → cose-bilkent-S5V4N54A.CMCWP49h.js} +1 -1
- package/web/_astro/{cynefin-OW5HDTMX.BExFdiin.js → cynefin-OW5HDTMX.HyXw_vdS.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.BybKbz3q.js → dagre-BM42HDAG.BTuAzh01.js} +1 -1
- package/web/_astro/{diagram-2AECGRRQ.UyRTSl9n.js → diagram-2AECGRRQ.D9dr9wfT.js} +1 -1
- package/web/_astro/{diagram-5GNKFQAL.BrxCucBf.js → diagram-5GNKFQAL.C4Rot0hj.js} +1 -1
- package/web/_astro/{diagram-KO2AKTUF.CdE5oy5J.js → diagram-KO2AKTUF.B_TK5uWC.js} +1 -1
- package/web/_astro/{diagram-LMA3HP47.BJLgdosK.js → diagram-LMA3HP47.JkXKK7CO.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.CUynieTU.js → diagram-OG6HWLK6.BzMN8Bd6.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.C0vS6DJv.js → erDiagram-TEJ5UH35.DVZaWGUd.js} +1 -1
- package/web/_astro/{flowDiagram-I6XJVG4X.T3QLi_en.js → flowDiagram-I6XJVG4X.rjEiWUfR.js} +1 -1
- package/web/_astro/{ganttDiagram-6RSMTGT7.BNsk3w9Z.js → ganttDiagram-6RSMTGT7.C_EgAarK.js} +1 -1
- package/web/_astro/{gitGraphDiagram-PVQCEYII.Mwe2I4V6.js → gitGraphDiagram-PVQCEYII.B-QQSDsK.js} +1 -1
- package/web/_astro/index.B5MTfe7k.css +1 -0
- package/web/_astro/{infoDiagram-5YYISTIA.BlcjLmtc.js → infoDiagram-5YYISTIA.DlWesz7T.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.js8qeS0h.js → ishikawaDiagram-YF4QCWOH.BUMZOawi.js} +1 -1
- package/web/_astro/{journeyDiagram-JHISSGLW.CM6UK0a4.js → journeyDiagram-JHISSGLW.CWfkxfjY.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.a6ihOzMd.js → kanban-definition-UN3LZRKU.B-YpMwXf.js} +1 -1
- package/web/_astro/{linear.CsIB2jFu.js → linear.D7uqzENp.js} +1 -1
- package/web/_astro/{mermaid.core.Br2Fo22q.js → mermaid.core.CxrNppBD.js} +4 -4
- package/web/_astro/{mindmap-definition-RKZ34NQL.29inC1Mk.js → mindmap-definition-RKZ34NQL.B4Qe7cM2.js} +1 -1
- package/web/_astro/{pieDiagram-4H26LBE5.C9CxG_Kf.js → pieDiagram-4H26LBE5.Ds-5j2ro.js} +1 -1
- package/web/_astro/{quadrantDiagram-W4KKPZXB.6qo9MOJM.js → quadrantDiagram-W4KKPZXB.tBd38uNC.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.DN07zrP5.js → requirementDiagram-4Y6WPE33.sFENkWl3.js} +1 -1
- package/web/_astro/{sankeyDiagram-5OEKKPKP.BSw5o173.js → sankeyDiagram-5OEKKPKP.BeB-Hk7C.js} +1 -1
- package/web/_astro/{sequenceDiagram-3UESZ5HK.LJPzySKw.js → sequenceDiagram-3UESZ5HK.DnTeaSpx.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.ClNjEiKV.js → stateDiagram-AJRCARHV.B-8Jt5EJ.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.c6Z-_WfX.js → stateDiagram-v2-BHNVJYJU.Br7xoqMW.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.CIMR-87j.js → timeline-definition-PNZ67QCA.C-3WdOyi.js} +1 -1
- package/web/_astro/{vennDiagram-CIIHVFJN.BnRSRI9I.js → vennDiagram-CIIHVFJN.DCIs7Lc6.js} +1 -1
- package/web/_astro/{wardleyDiagram-YWT4CUSO.uN08C3gv.js → wardleyDiagram-YWT4CUSO.rGAL-bbz.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6.BjbEvfuq.js → xychartDiagram-2RQKCTM6.hkfQKiRl.js} +1 -1
- package/web/index.html +2 -2
- package/web/_astro/BoardApp.BnjsI80-.js +0 -178
- package/web/_astro/BoardApp.SJcrHBZp.js +0 -1
- package/web/_astro/channel.tWfETQvX.js +0 -1
- package/web/_astro/index.9npdrEIr.css +0 -1
|
@@ -1,22 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"proofInputs": {
|
|
4
|
-
"repository": {
|
|
5
|
-
"excludeConfiguredCorpusFolders": true
|
|
6
|
-
},
|
|
7
|
-
"taskFields": ["wbs", "name", "feature_id", "depends_on"],
|
|
8
|
-
"taskSections": ["Background", "Requirements", "Acceptance Criteria", "Design", "Plan"],
|
|
9
|
-
"featureFields": ["id", "name"],
|
|
10
|
-
"featureSections": ["Goal", "Scope", "Acceptance Criteria"]
|
|
11
|
-
},
|
|
12
3
|
"workflows": {
|
|
13
4
|
"docs-pipeline": {
|
|
14
5
|
"definition": "config/workflows/docs-pipeline.yaml",
|
|
15
|
-
"boundary": "docs-evolution",
|
|
16
|
-
"disposition": "keep",
|
|
17
|
-
"callers": ["sp:spur-dev", "/sp:dev-run"],
|
|
18
|
-
"artifacts": ["docs-precheck", "docs-verdict"],
|
|
19
|
-
"failurePolicy": "fail-closed",
|
|
20
6
|
"terminalStates": ["done", "failed", "cancelled"],
|
|
21
7
|
"modelQueries": ["draft", "verify"],
|
|
22
8
|
"actions": {
|
|
@@ -57,7 +43,7 @@
|
|
|
57
43
|
},
|
|
58
44
|
"verify:onEnter:0": {
|
|
59
45
|
"kind": "shell",
|
|
60
|
-
"invocation": "$spurBin task path $wbs --json
|
|
46
|
+
"invocation": "set -e; task_path=\"$($spurBin task path $wbs --json | jq -r '.path // .filePath // empty')\"; if [ -z \"$task_path\" ]; then echo \"docs-pipeline: task path did not resolve for wbs $wbs\" >&2; exit 1; fi; printf '%s' \"$task_path\" > \".spur/run/$wbs-docs-taskpath.txt\""
|
|
61
47
|
},
|
|
62
48
|
"verify:onEnter:1": {
|
|
63
49
|
"kind": "file.read.into-var"
|
|
@@ -85,23 +71,10 @@
|
|
|
85
71
|
"kind": "proof.fingerprint",
|
|
86
72
|
"invocation": "/sp:dev-verify ${vars.wbs} --auto --fix none --focus all"
|
|
87
73
|
}
|
|
88
|
-
}
|
|
89
|
-
"digest": "sha256:2794f4f926ecfcd69c0265214f9fcd69ab84cdd3ed53409a8af77a700fd635cc"
|
|
74
|
+
}
|
|
90
75
|
},
|
|
91
76
|
"idea-pipeline": {
|
|
92
77
|
"definition": "config/workflows/idea-pipeline.yaml",
|
|
93
|
-
"boundary": "idea-decomposition",
|
|
94
|
-
"disposition": "keep",
|
|
95
|
-
"callers": ["sp:spur-dev", "/sp:dev-idea"],
|
|
96
|
-
"artifacts": [
|
|
97
|
-
"idea-eval-report",
|
|
98
|
-
"idea-needs-design",
|
|
99
|
-
"idea-design-review",
|
|
100
|
-
"idea-task-batch",
|
|
101
|
-
"idea-task-order",
|
|
102
|
-
"idea-handoff"
|
|
103
|
-
],
|
|
104
|
-
"failurePolicy": "fail-closed",
|
|
105
78
|
"terminalStates": ["handoff", "cancelled", "failed"],
|
|
106
79
|
"modelQueries": ["discovery", "feature-create", "ac-generate", "system-design", "decompose"],
|
|
107
80
|
"actions": {
|
|
@@ -204,16 +177,10 @@
|
|
|
204
177
|
"kind": "shell",
|
|
205
178
|
"invocation": "mkdir -p .spur/memory/sessions && echo \"checkpoint: idea-pipeline handoff feature=$featureId ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)\" > .spur/memory/sessions/idea-checkpoint.md"
|
|
206
179
|
}
|
|
207
|
-
}
|
|
208
|
-
"digest": "sha256:acc878217ffc7e31d31600b59d5b240588a079638d2eb0caff8c7a78524220b9"
|
|
180
|
+
}
|
|
209
181
|
},
|
|
210
182
|
"task-pipeline": {
|
|
211
183
|
"definition": "config/workflows/task-pipeline.yaml",
|
|
212
|
-
"boundary": "task-execution",
|
|
213
|
-
"disposition": "canonical",
|
|
214
|
-
"callers": ["sp:spur-dev", "sp:super-planner"],
|
|
215
|
-
"artifacts": ["verify-answer", "verify-verdict", "testing-section", "review-section"],
|
|
216
|
-
"failurePolicy": "fail-closed",
|
|
217
184
|
"terminalStates": ["done", "failed", "cancelled"],
|
|
218
185
|
"modelQueries": ["implement", "test-fix", "review", "verify"],
|
|
219
186
|
"actions": {
|
|
@@ -236,6 +203,10 @@
|
|
|
236
203
|
"kind": "shell",
|
|
237
204
|
"invocation": "EVID_FILE=\".spur/run/$wbs-precheck-evidence.status\" && mkdir -p .spur/run && EVID_SCRIPT=\"plugins/sp/scripts/task-evidence-precheck.ts\"; [ -f \"$EVID_SCRIPT\" ] || EVID_SCRIPT=\"$(superskill script path sp task-evidence-precheck.ts 2>/dev/null)\"; if [ -n \"$EVID_SCRIPT\" ] && [ -f \"$EVID_SCRIPT\" ]; then bun \"$EVID_SCRIPT\" \"$wbs\" --spur-bin \"$spurBin\"; else\n echo \"task-evidence-precheck failed closed — checker not found\" >&2 &&\n echo \"in plugins/sp/scripts/ nor staged; run 'superskill install sp'.\" >&2 &&\n echo \"FAIL\" > \"$EVID_FILE\";\nfi && exit 0"
|
|
238
205
|
},
|
|
206
|
+
"precheck:onEnter:5": {
|
|
207
|
+
"kind": "shell",
|
|
208
|
+
"invocation": "mkdir -p .spur/run .spur/memory && RUN_ID=\"$__runId\" && if [ -z \"$RUN_ID\" ]; then RUN_ID=\"pipeline-$wbs\"; fi && REASON_FILE=\".spur/run/$RUN_ID-route-reason.txt\" && if [ \"$mode\" = \"fast\" ]; then\n echo \"fast:evidence complete+consistent\" > \"$REASON_FILE\";\nelif [ -z \"$mode\" ]; then\n echo \"safety:standard verification\" > \"$REASON_FILE\";\nelif [ \"$mode\" = \"unknown\" ]; then\n echo \"safety:unknown evidence quality\" > \"$REASON_FILE\";\nelif [ \"$mode\" = \"conflict\" ]; then\n echo \"safety:conflicting evidence\" > \"$REASON_FILE\";\nelse\n echo \"safety:unrecognized evidence (mode=$mode)\" > \"$REASON_FILE\";\nfi && printf '%s %s %s\\n' \"$RUN_ID\" \"$wbs\" \"$(cat \"$REASON_FILE\")\" >> .spur/memory/task-pipeline-routes.log && exit 0"
|
|
209
|
+
},
|
|
239
210
|
"implement:onEnter:0": {
|
|
240
211
|
"kind": "agent.run",
|
|
241
212
|
"invocation": "/sp:dev-run --mode implement ${vars.wbs} --auto"
|
|
@@ -250,7 +221,7 @@
|
|
|
250
221
|
},
|
|
251
222
|
"test:onEnter:0": {
|
|
252
223
|
"kind": "shell",
|
|
253
|
-
"invocation": "$spurBin task path $wbs --json
|
|
224
|
+
"invocation": "mkdir -p .spur/run; $spurBin task path $wbs --json | jq -r \".path // .filePath // empty\" > \".spur/run/$wbs-taskpath.txt\"; task_path=\"$(cat \".spur/run/$wbs-taskpath.txt\")\"; if [ -z \"$task_path\" ]; then echo \"fail-closed proof chain (0751 R2): task path for $wbs did not resolve - the task spec cannot be folded into the proof digest\" >&2; exit 1; fi; sed -n \"s/^priority:[[:space:]]*//p\" \"$task_path\" | head -1 | tr -d \"[:space:]\" | tr \"[:lower:]\" \"[:upper:]\" > \".spur/run/$wbs-priority.txt\""
|
|
254
225
|
},
|
|
255
226
|
"test:onEnter:1": {
|
|
256
227
|
"kind": "file.read.into-var"
|
|
@@ -307,7 +278,7 @@
|
|
|
307
278
|
},
|
|
308
279
|
"verify:onEnter:4": {
|
|
309
280
|
"kind": "shell",
|
|
310
|
-
"invocation": "V=\".spur/run/$wbs-verdict.json\"; if [ -f \"$V\" ] && [ -n \"$proofDigest\" ]; then\n jq --arg d \"$proofDigest\" --arg g \"$(cat .spur/run/$wbs-test-gate.status 2>/dev/null || echo UNKNOWN)\"\n '. + {proof: {digest: $d, capturePoint: \"quality-gate-entry\", stages: {\n qualityGate: {status: $g, digest: $d},\n review: {status: \"completed\", digest: $d},\n verification: {status: .verdict, digest: $d}}}}\n | .checks += [{name: \"proof-input-digest\", status: \"pass\", evidence: $d}]'\n \"$V\" > \"$V.tmp\" && mv \"$V.tmp\" \"$V\";\nfi; exit 0"
|
|
281
|
+
"invocation": "V=\".spur/run/$wbs-verdict.json\"; if [ -f \"$V\" ] && [ -n \"$proofDigest\" ]; then\n jq --arg d \"$proofDigest\" --arg r \"$__runId\" --arg dd \"$__definitionDigest\" --arg g \"$(cat .spur/run/$wbs-test-gate.status 2>/dev/null || echo UNKNOWN)\"\n '. + {proof: {digest: $d, runId: $r, definitionDigest: $dd, capturePoint: \"quality-gate-entry\", stages: {\n qualityGate: {status: $g, digest: $d},\n review: {status: \"completed\", digest: $d},\n verification: {status: .verdict, digest: $d}}}}\n | .checks += [{name: \"proof-input-digest\", status: \"pass\", evidence: $d}]'\n \"$V\" > \"$V.tmp\" && mv \"$V.tmp\" \"$V\";\nfi; exit 0"
|
|
311
282
|
},
|
|
312
283
|
"record:onEnter:0": {
|
|
313
284
|
"kind": "proof.fingerprint"
|
|
@@ -334,16 +305,10 @@
|
|
|
334
305
|
"kind": "shell",
|
|
335
306
|
"invocation": "mkdir -p .spur/memory/sessions; CP_TS=\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"; CP_COMMIT=\"$(git rev-parse HEAD 2>/dev/null || echo unknown)\"; CP_DIGEST=\"$(cut -d= -f2 .spur/run/$wbs-proofdigest.txt 2>/dev/null || echo '')\"; CP_RUN=\"$SPUR_RUN_ID\"; [ -z \"$CP_RUN\" ] && CP_RUN=\"$RUN_ID\"; printf '%s\\n' '---' 'schema_version: 1' \"session_id: $(date -u +%Y-%m-%d)-$wbs\" 'workflow: task-pipeline' \"run_id: $CP_RUN\" \"task_wbs: $wbs\" 'feature_id: \"\"' 'phase: done' 'status: done' 'last_gate: record' \"source_commit: $CP_COMMIT\" \"digest: $CP_DIGEST\" \"generated_at: $CP_TS\" \"updated_at: $CP_TS\" \"next_action: none - task $wbs complete (terminal; advisory only)\" 'artifacts:' ' - .spur/run/$wbs-verdict.json' ' - .spur/run/$wbs-test-gate.log' '---' '' '## Session Notes' '' \"Terminal checkpoint for task $wbs (task-pipeline done).\" 'Advisory only; the task file is authoritative.' > .spur/memory/sessions/$wbs-checkpoint.md; exit 0"
|
|
336
307
|
}
|
|
337
|
-
}
|
|
338
|
-
"digest": "sha256:455fcf48f685809780187b7345562f3d377c5aa66d2fa3130c078b168bebf436"
|
|
308
|
+
}
|
|
339
309
|
},
|
|
340
310
|
"wrapup-pipeline": {
|
|
341
311
|
"definition": "config/workflows/wrapup-pipeline.yaml",
|
|
342
|
-
"boundary": "task-wrapup",
|
|
343
|
-
"disposition": "keep",
|
|
344
|
-
"callers": ["sp:spur-dev", "/sp:dev-wrap", "/sp:dev-wrapall"],
|
|
345
|
-
"artifacts": ["wrapup-learnings", "wrapup-metrics"],
|
|
346
|
-
"failurePolicy": "fail-closed",
|
|
347
312
|
"terminalStates": ["done", "skipped"],
|
|
348
313
|
"modelQueries": ["doc-sync"],
|
|
349
314
|
"actions": {
|
|
@@ -353,6 +318,10 @@
|
|
|
353
318
|
"task-resolve:onEnter:0": {
|
|
354
319
|
"kind": "note"
|
|
355
320
|
},
|
|
321
|
+
"task-resolve:onEnter:1": {
|
|
322
|
+
"kind": "shell",
|
|
323
|
+
"invocation": "mkdir -p .spur/run .spur/memory && RUN_ID=\"$__runId\" && if [ -z \"$RUN_ID\" ]; then RUN_ID=\"wrapup\"; fi && REASON_FILE=\".spur/run/$RUN_ID-route-reason.txt\" && if [ \"$(echo \"$tasks\" | jq length 2>/dev/null || echo 0)\" -eq 0 ]; then\n echo \"skipped:empty task list\" > \"$REASON_FILE\";\nelif [ \"$mode\" = \"fast\" ]; then\n echo \"fast:evidence complete+consistent\" > \"$REASON_FILE\";\nelif [ -z \"$mode\" ]; then\n echo \"safety:missing evidence (mode empty)\" > \"$REASON_FILE\";\nelif [ \"$mode\" = \"unknown\" ]; then\n echo \"safety:unknown evidence quality\" > \"$REASON_FILE\";\nelif [ \"$mode\" = \"conflict\" ]; then\n echo \"safety:conflicting evidence\" > \"$REASON_FILE\";\nelse\n echo \"safety:unrecognized evidence (mode=$mode)\" > \"$REASON_FILE\";\nfi && printf '%s %s\\n' \"$RUN_ID\" \"$(cat \"$REASON_FILE\")\" >> .spur/memory/wrapup-routes.log && exit 0"
|
|
324
|
+
},
|
|
356
325
|
"doc-sync:onEnter:0": {
|
|
357
326
|
"kind": "agent.run",
|
|
358
327
|
"invocation": "First run Skill(skill=\"sp:doc-evolve\", args=\"wrapup tasks=${vars.tasks}\") to repair drift in docs/00_ADR.md, docs/03_ARCHITECTURE.md, docs/04_DESIGN.md, docs/design/* per constitution edit rules; do not write task/feature corpus. THEN extract working learnings from tasks ${vars.tasks} — conventions, errors fixed, patterns, gotchas, grouped by date and task WBS — as raw markdown (no fences) and END your final message with that markdown (it is captured to .spur/run/wrapup-learnings.md)."
|
|
@@ -379,25 +348,10 @@
|
|
|
379
348
|
"kind": "shell",
|
|
380
349
|
"invocation": "mkdir -p .spur/memory/sessions && echo \"checkpoint: wrapup-pipeline done tasks=$tasks ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)\" > .spur/memory/sessions/wrapup-checkpoint.md"
|
|
381
350
|
}
|
|
382
|
-
}
|
|
383
|
-
"digest": "sha256:390621dd339709682065e8954f2d1b49a195111c8372ec83e094fe7e2e35927f"
|
|
351
|
+
}
|
|
384
352
|
},
|
|
385
353
|
"pr-review": {
|
|
386
354
|
"definition": "config/workflows/pr-review.yaml",
|
|
387
|
-
"boundary": "pr-review",
|
|
388
|
-
"disposition": "keep",
|
|
389
|
-
"callers": ["sp:spur-dev", "/sp:dev-pr-review"],
|
|
390
|
-
"artifacts": [
|
|
391
|
-
"pr-context",
|
|
392
|
-
"pr-hygiene",
|
|
393
|
-
"pr-push",
|
|
394
|
-
"pr",
|
|
395
|
-
"pr-request",
|
|
396
|
-
"pr-wait",
|
|
397
|
-
"pr-findings",
|
|
398
|
-
"pr-status"
|
|
399
|
-
],
|
|
400
|
-
"failurePolicy": "fail-closed",
|
|
401
355
|
"terminalStates": ["done", "pending", "failed"],
|
|
402
356
|
"modelQueries": [],
|
|
403
357
|
"actions": {
|
|
@@ -433,16 +387,10 @@
|
|
|
433
387
|
"kind": "shell",
|
|
434
388
|
"invocation": "mkdir -p .spur/run && STATUS_FILE=\".spur/run/$__runId-pr-collect.status\" && set +e && SINCE=\"$(bun -e 'const fs=require(\"node:fs\");const value=JSON.parse(fs.readFileSync(process.argv[1],\"utf8\")).requestedAt;process.stdout.write(value ?? \"\")' \".spur/run/$__runId-pr-request.json\")\" && REQUEST_HEAD=\"$(bun -e 'const fs=require(\"node:fs\");const value=JSON.parse(fs.readFileSync(process.argv[1],\"utf8\")).head;process.stdout.write(value ?? \"\")' \".spur/run/$__runId-pr-request.json\")\" && bun \"$(superskill script path sp pr-reviewing.ts)\" collect --since \"$SINCE\" --head \"$REQUEST_HEAD\" --json --status-file \"$STATUS_FILE\" > \".spur/run/$__runId-pr-findings.json\"; collect_rc=$?; bun \"$(superskill script path sp pr-reviewing.ts)\" status --since \"$SINCE\" --head \"$REQUEST_HEAD\" --json > \".spur/run/$__runId-pr-status.json\"; status_rc=$?; set -e && if [ \"$collect_rc\" -ne 0 ] || [ \"$status_rc\" -ne 0 ]; then printf 'FAIL\\n' > \"$STATUS_FILE\"; fi && if [ ! -f \"$STATUS_FILE\" ]; then printf 'FAIL\\n' > \"$STATUS_FILE\"; fi && { cat \".spur/run/$__runId-pr-findings.json\" 2>/dev/null || true; } && exit 0"
|
|
435
389
|
}
|
|
436
|
-
}
|
|
437
|
-
"digest": "sha256:eb3f51877647f25907ed6b660b79e4d22b3c7462ceccacc4fc251eb31bac06f0"
|
|
390
|
+
}
|
|
438
391
|
},
|
|
439
392
|
"basic": {
|
|
440
393
|
"definition": "config/workflows/basic.yaml",
|
|
441
|
-
"boundary": "generic-execution",
|
|
442
|
-
"disposition": "keep",
|
|
443
|
-
"callers": ["spur workflow run"],
|
|
444
|
-
"artifacts": ["fix-attempt-counter", "gate-status"],
|
|
445
|
-
"failurePolicy": "fail-closed",
|
|
446
394
|
"terminalStates": ["done", "failed"],
|
|
447
395
|
"modelQueries": ["fix"],
|
|
448
396
|
"actions": {
|
|
@@ -465,16 +413,10 @@
|
|
|
465
413
|
"kind": "agent.run",
|
|
466
414
|
"invocation": "/sp:dev-fixall \"${vars.qualityGateCmd}\""
|
|
467
415
|
}
|
|
468
|
-
}
|
|
469
|
-
"digest": "sha256:fb8ab828b9527f225368d20b08e3fc7ca4b92e6e22642a57868da193d5ebef2c"
|
|
416
|
+
}
|
|
470
417
|
},
|
|
471
418
|
"feature-dev": {
|
|
472
419
|
"definition": "config/workflows/feature-dev.yaml",
|
|
473
|
-
"boundary": "feature-umbrella",
|
|
474
|
-
"disposition": "keep",
|
|
475
|
-
"callers": ["/sp:dev-runall --feature"],
|
|
476
|
-
"artifacts": ["feature-checkpoint"],
|
|
477
|
-
"failurePolicy": "fail-closed",
|
|
478
420
|
"terminalStates": ["done", "failed"],
|
|
479
421
|
"modelQueries": ["brainstorm", "plan", "execute-tasks-auto", "execute-tasks"],
|
|
480
422
|
"actions": {
|
|
@@ -502,7 +444,8 @@
|
|
|
502
444
|
"invocation": "/sp:dev-runall --feature ${vars.featureId}"
|
|
503
445
|
},
|
|
504
446
|
"integration-review:onEnter:0": {
|
|
505
|
-
"kind": "
|
|
447
|
+
"kind": "shell",
|
|
448
|
+
"invocation": "mkdir -p .spur/run && STATUS_FILE=\".spur/run/$__runId-integration-review.status\" && REQUEST_JSON=\".spur/run/$__runId-integration-review.json\" && PR_REQUEST_STATUS=\".spur/run/$__runId-integration-review-pr-request.status\" && set +e && bun \"$(superskill script path sp pr-reviewing.ts)\" request --base \"$baseBranch\" --json --status-file \"$PR_REQUEST_STATUS\" > \"$REQUEST_JSON\" 2>&1; rc=$?; set -e && if [ \"$rc\" -eq 0 ]; then\n printf 'PASS\\n' > \"$STATUS_FILE\";\nelse\n printf 'FAIL\\n' > \"$STATUS_FILE\";\nfi && exit 0"
|
|
506
449
|
},
|
|
507
450
|
"integration-review:onEnter:1": {
|
|
508
451
|
"kind": "note"
|
|
@@ -511,16 +454,10 @@
|
|
|
511
454
|
"kind": "shell",
|
|
512
455
|
"invocation": "mkdir -p .spur/memory/sessions && echo \"checkpoint: feature-dev done featureId=$featureId ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)\" > .spur/memory/sessions/$featureId-checkpoint.md"
|
|
513
456
|
}
|
|
514
|
-
}
|
|
515
|
-
"digest": "sha256:e1fa6b86cb7bcad0f927cf73336996ee8ce0088b6685cebba8c8849e26029529"
|
|
457
|
+
}
|
|
516
458
|
},
|
|
517
459
|
"wayfinder-resolution": {
|
|
518
460
|
"definition": "config/workflows/wayfinder-resolution.yaml",
|
|
519
|
-
"boundary": "wayfinder-resolution",
|
|
520
|
-
"disposition": "keep",
|
|
521
|
-
"callers": ["spur workflow run"],
|
|
522
|
-
"artifacts": ["wayfinder-report", "resolution-status"],
|
|
523
|
-
"failurePolicy": "fail-closed",
|
|
524
461
|
"terminalStates": ["done", "failed", "cancelled"],
|
|
525
462
|
"modelQueries": ["investigate", "verify"],
|
|
526
463
|
"actions": {
|
|
@@ -569,8 +506,110 @@
|
|
|
569
506
|
"done:onEnter:0": {
|
|
570
507
|
"kind": "note"
|
|
571
508
|
}
|
|
572
|
-
}
|
|
573
|
-
|
|
509
|
+
}
|
|
510
|
+
},
|
|
511
|
+
"feature-lifecycle": {
|
|
512
|
+
"definition": "config/workflows/feature-lifecycle.yaml",
|
|
513
|
+
"terminalStates": ["cancelled"],
|
|
514
|
+
"modelQueries": [],
|
|
515
|
+
"actions": {}
|
|
516
|
+
},
|
|
517
|
+
"history-anatomy": {
|
|
518
|
+
"definition": "config/workflows/history-anatomy.yaml",
|
|
519
|
+
"terminalStates": ["published", "failed"],
|
|
520
|
+
"modelQueries": ["resolve-scope", "enrich", "validate", "correct"],
|
|
521
|
+
"actions": {
|
|
522
|
+
"start:onEnter:0": {
|
|
523
|
+
"kind": "shell",
|
|
524
|
+
"invocation": "mkdir -p .spur/run; if [ -z \"$__runId\" ]; then __runId=$(uuidgen | tr 'A-Z' 'a-z' | cut -c1-8); fi; echo \"$__runId\" > .spur/run/history-anatomy-run.id"
|
|
525
|
+
},
|
|
526
|
+
"resolve-scope:onEnter:0": {
|
|
527
|
+
"kind": "agent.run",
|
|
528
|
+
"invocation": "Validate the mode arguments per sp:history-anatomy references/modes.md and write the normalized selector to .spur/run/${vars.__runId}-selector.json. mode=${vars.mode} date=${vars.date} since=${vars.since} until=${vars.until} focus=${vars.focus}. Reject conflicting arguments, naming the offending one; a rejection marks the run failed."
|
|
529
|
+
},
|
|
530
|
+
"resolve-paths:onEnter:0": {
|
|
531
|
+
"kind": "shell",
|
|
532
|
+
"invocation": "h=$(superskill script path sp history-anatomy-cache.mjs); node \"$h\" paths --helper \"$h\" --report-dir \"$reportDir\" --date \"$date\" --output \"$output\" --mode \"$mode\" --since \"$since\" --until \"$until\" --out .spur/run/$__runId-paths.txt"
|
|
533
|
+
},
|
|
534
|
+
"analyze:onEnter:0": {
|
|
535
|
+
"kind": "shell",
|
|
536
|
+
"invocation": "mkdir -p .spur/run; . .spur/run/$__runId-paths.txt; $spurBin history analyze --out .spur/run/$__runId-history-anatomy-current.json --since \"$HA_SINCE\" --until \"$HA_UNTIL\" --json"
|
|
537
|
+
},
|
|
538
|
+
"analyze:onEnter:1": {
|
|
539
|
+
"kind": "shell",
|
|
540
|
+
"invocation": ". .spur/run/$__runId-paths.txt; $spurBin history analyze --out .spur/run/$__runId-history-anatomy-baseline.json --since \"$HA_BASELINE_SINCE\" --until \"$HA_BASELINE_UNTIL\" --json 2>/dev/null || true"
|
|
541
|
+
},
|
|
542
|
+
"cache-probe:onEnter:0": {
|
|
543
|
+
"kind": "shell",
|
|
544
|
+
"invocation": ". .spur/run/$__runId-paths.txt; node \"$HA_HELPER\" probe --artifact .spur/run/$__runId-history-anatomy-current.json --baseline .spur/run/$__runId-history-anatomy-baseline.json --target \"$HA_TARGET\" --mode \"$mode\" --date \"$HA_DATE\" --recompute \"$recompute\" --executor \"$agent\" --skill-dir \"$HA_SKILL\" --contract \"$HA_SKILL/references/report-contract.md\" --workflow \"$workflowFile\" --contract-version \"$contractVersion\" --run-id \"$__runId\" --out .spur/run/$__runId-provenance.json > .spur/run/$__runId-cache-disposition.txt"
|
|
545
|
+
},
|
|
546
|
+
"render:onEnter:0": {
|
|
547
|
+
"kind": "shell",
|
|
548
|
+
"invocation": "mkdir -p .spur/run; $spurBin history report .spur/run/$__runId-history-anatomy-current.json --mode forensics > .spur/run/$__runId-history-anatomy-current.md; $spurBin history report .spur/run/$__runId-history-anatomy-baseline.json --mode forensics > .spur/run/$__runId-history-anatomy-baseline.md || true"
|
|
549
|
+
},
|
|
550
|
+
"enrich:onEnter:0": {
|
|
551
|
+
"kind": "shell",
|
|
552
|
+
"invocation": "git status --porcelain > .spur/run/$__runId-baseline-enrich.txt || true"
|
|
553
|
+
},
|
|
554
|
+
"enrich:onEnter:1": {
|
|
555
|
+
"kind": "agent.run",
|
|
556
|
+
"invocation": "Run sp:history-anatomy enrich: given .spur/run/${vars.__runId}-history-anatomy-current.json and -baseline.json, author the model half of the report (Baseline comparison, Findings, Recurrence ledger, Remediation options, Performance analysis, Workflow/process improvements, Positive patterns) to .spur/run/${vars.__runId}-candidate.md per references/report-contract.md. This operation never launches a workflow."
|
|
557
|
+
},
|
|
558
|
+
"enrich:onEnter:2": {
|
|
559
|
+
"kind": "shell",
|
|
560
|
+
"invocation": "node \"$(superskill script path sp history-anatomy-cache.mjs)\" assert-clean --baseline .spur/run/$__runId-baseline-enrich.txt --expect .spur/run/$__runId-candidate.md"
|
|
561
|
+
},
|
|
562
|
+
"structure-gate:onEnter:0": {
|
|
563
|
+
"kind": "shell",
|
|
564
|
+
"invocation": "node \"$(superskill script path sp history-anatomy-cache.mjs)\" check \\\n .spur/run/$__runId-candidate.md > .spur/run/$__runId-structure-gate.txt 2>&1 || true"
|
|
565
|
+
},
|
|
566
|
+
"validate:onEnter:0": {
|
|
567
|
+
"kind": "shell",
|
|
568
|
+
"invocation": "git status --porcelain > .spur/run/$__runId-baseline-validate.txt || true"
|
|
569
|
+
},
|
|
570
|
+
"validate:onEnter:1": {
|
|
571
|
+
"kind": "agent.run",
|
|
572
|
+
"invocation": "Run sp:history-anatomy validate: independently check .spur/run/${vars.__runId}-candidate.md against the two artifacts per references/operations.md; write Verdict: PASS or FAIL to .spur/run/${vars.__runId}-validation.txt. This operation never launches a workflow."
|
|
573
|
+
},
|
|
574
|
+
"validate:onEnter:2": {
|
|
575
|
+
"kind": "shell",
|
|
576
|
+
"invocation": "node \"$(superskill script path sp history-anatomy-cache.mjs)\" assert-clean --baseline .spur/run/$__runId-baseline-validate.txt --expect .spur/run/$__runId-validation.txt"
|
|
577
|
+
},
|
|
578
|
+
"correct:onEnter:0": {
|
|
579
|
+
"kind": "shell",
|
|
580
|
+
"invocation": "n=$(cat .spur/run/$__runId-correction-count 2>/dev/null || echo 0) && printf '%s\\n' \"$((n + 1))\" > .spur/run/$__runId-correction-count"
|
|
581
|
+
},
|
|
582
|
+
"correct:onEnter:1": {
|
|
583
|
+
"kind": "shell",
|
|
584
|
+
"invocation": "git status --porcelain > .spur/run/$__runId-baseline-correct.txt || true"
|
|
585
|
+
},
|
|
586
|
+
"correct:onEnter:2": {
|
|
587
|
+
"kind": "agent.run",
|
|
588
|
+
"invocation": "Repair .spur/run/${vars.__runId}-candidate.md in place. Read its structure-gate findings, optional validation notes, references/report-contract.md, and the references/operations.md validate rubric; fix every violation. Use a backticked `.md`/`.ts`/`.json` path or a `path:line` anchor, never `current #/...`; remove placeholders and empty rows; restore the twelve-section order; ensure every problem and positive finding carries the full field set; verify every quantitative claim (counts, durations, percentages, distributions) and every current/baseline full-digest match against .spur/run/${vars.__runId}-history-anatomy-current.json and -baseline.json. Overwrite only the candidate; never launch a workflow."
|
|
589
|
+
},
|
|
590
|
+
"correct:onEnter:3": {
|
|
591
|
+
"kind": "shell",
|
|
592
|
+
"invocation": "node \"$(superskill script path sp history-anatomy-cache.mjs)\" assert-clean --baseline .spur/run/$__runId-baseline-correct.txt --expect .spur/run/$__runId-candidate.md"
|
|
593
|
+
},
|
|
594
|
+
"refresh-provenance:onEnter:0": {
|
|
595
|
+
"kind": "shell",
|
|
596
|
+
"invocation": ". .spur/run/$__runId-paths.txt; node \"$HA_HELPER\" refresh --report \"$HA_TARGET\" --out .spur/run/$__runId-publishable.md --disposition hit"
|
|
597
|
+
},
|
|
598
|
+
"stamp:onEnter:0": {
|
|
599
|
+
"kind": "shell",
|
|
600
|
+
"invocation": ". .spur/run/$__runId-paths.txt; node \"$HA_HELPER\" stamp --candidate .spur/run/$__runId-candidate.md --provenance .spur/run/$__runId-provenance.json --out .spur/run/$__runId-publishable.md"
|
|
601
|
+
},
|
|
602
|
+
"publish:onEnter:0": {
|
|
603
|
+
"kind": "shell",
|
|
604
|
+
"invocation": ". .spur/run/$__runId-paths.txt; mkdir -p \"$(dirname \"$HA_TARGET\")\"; node \"$HA_HELPER\" publish .spur/run/$__runId-publishable.md \"$HA_TARGET\""
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
},
|
|
608
|
+
"task-lifecycle": {
|
|
609
|
+
"definition": "config/workflows/task-lifecycle.yaml",
|
|
610
|
+
"terminalStates": ["cancelled"],
|
|
611
|
+
"modelQueries": [],
|
|
612
|
+
"actions": {}
|
|
574
613
|
}
|
|
575
614
|
}
|
|
576
615
|
}
|
|
@@ -142,7 +142,17 @@ states:
|
|
|
142
142
|
# excluded from the digest's git-tree half, so the spec is folded in via `taskFile`.
|
|
143
143
|
- kind: shell
|
|
144
144
|
options:
|
|
145
|
-
|
|
145
|
+
# 0760 R1 (sibling of 0751 R2): task-path lookup fails closed. Drop
|
|
146
|
+
# `2>/dev/null`, `|| true`, and the forced `exit 0` so an unresolved
|
|
147
|
+
# wbs exits non-zero with a named message. The resolved path folds
|
|
148
|
+
# into the proof digest via `taskFile:` below; a silent miss would
|
|
149
|
+
# degrade the docs-pipeline proof to tree-only (same hazard 0751 R2
|
|
150
|
+
# removed from task-pipeline).
|
|
151
|
+
command: >-
|
|
152
|
+
set -e;
|
|
153
|
+
task_path="$($spurBin task path $wbs --json | jq -r '.path // .filePath // empty')";
|
|
154
|
+
if [ -z "$task_path" ]; then echo "docs-pipeline: task path did not resolve for wbs $wbs" >&2; exit 1; fi;
|
|
155
|
+
printf '%s' "$task_path" > ".spur/run/$wbs-docs-taskpath.txt"
|
|
146
156
|
- kind: file.read.into-var
|
|
147
157
|
options:
|
|
148
158
|
path: .spur/run/${vars.wbs}-docs-taskpath.txt
|
|
@@ -143,29 +143,36 @@ states:
|
|
|
143
143
|
|
|
144
144
|
- id: integration-review
|
|
145
145
|
description: >
|
|
146
|
-
Advisory integration review (D5-P, feature R11).
|
|
147
|
-
|
|
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.
|
|
146
|
+
Advisory integration review (D5-P, feature R11). Spends one Codex review
|
|
147
|
+
on the current HEAD after the local gates and before wrap merge/cleanup.
|
|
150
148
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
149
|
+
D8 decision D1 (0753 R3): the nested `spur workflow run pr-review.yaml`
|
|
150
|
+
was refused by the SPUR_WORKFLOW_RUN_ACTIVE child guard and the refusal
|
|
151
|
+
was masked by `softFail: true`. The non-spawning replacement invokes
|
|
152
|
+
`pr-reviewing.ts request` directly — the same per-HEAD dedupe-or-request
|
|
153
|
+
logic `config/workflows/pr-review.yaml` uses internally — and writes its
|
|
154
|
+
own PASS/FAIL status. `ALREADY_REVIEWED` / `ALREADY_REQUESTED` / `REQUESTED`
|
|
155
|
+
all count as PASS (review is initiated for this HEAD); only a request
|
|
156
|
+
error counts as FAIL. `softFail` is gone: a real failure now records FAIL
|
|
157
|
+
loudly. `requireCleanReview=true` still turns that FAIL into a blocking edge.
|
|
155
158
|
onEnter:
|
|
156
|
-
- kind:
|
|
159
|
+
- kind: shell
|
|
157
160
|
options:
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
-
|
|
162
|
-
-
|
|
163
|
-
|
|
164
|
-
- --
|
|
165
|
-
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
161
|
+
command: >-
|
|
162
|
+
mkdir -p .spur/run &&
|
|
163
|
+
STATUS_FILE=".spur/run/$__runId-integration-review.status" &&
|
|
164
|
+
REQUEST_JSON=".spur/run/$__runId-integration-review.json" &&
|
|
165
|
+
PR_REQUEST_STATUS=".spur/run/$__runId-integration-review-pr-request.status" &&
|
|
166
|
+
set +e &&
|
|
167
|
+
bun "$(superskill script path sp pr-reviewing.ts)" request --base "$baseBranch" --json
|
|
168
|
+
--status-file "$PR_REQUEST_STATUS" > "$REQUEST_JSON" 2>&1;
|
|
169
|
+
rc=$?; set -e &&
|
|
170
|
+
if [ "$rc" -eq 0 ]; then
|
|
171
|
+
printf 'PASS\n' > "$STATUS_FILE";
|
|
172
|
+
else
|
|
173
|
+
printf 'FAIL\n' > "$STATUS_FILE";
|
|
174
|
+
fi &&
|
|
175
|
+
exit 0
|
|
169
176
|
- kind: note
|
|
170
177
|
options:
|
|
171
178
|
message: "Integration review for feature ${vars.featureId} recorded at .spur/run/${vars.__runId}-integration-review.status (advisory unless requireCleanReview=true)."
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
# Externally driven FSM (requestTransition) — not an auto-running pipeline.
|
|
2
2
|
#
|
|
3
|
+
# [CRITICAL] One transition per (from, to) pair. `requestTransition` selects with
|
|
4
|
+
# `transitions.find(t => t.from === … && t.to === …)` and denies on that single
|
|
5
|
+
# transition's guard — it never falls through to a sibling with the same pair
|
|
6
|
+
# (dual-workflow-engine/src/service.ts requestTransition). Guard-paired siblings
|
|
7
|
+
# (e.g. a `mode = fast` fast path beside a `mode != fast` safety path) are only
|
|
8
|
+
# valid in auto-run pipelines, where `firstPassingTransition` evaluates every
|
|
9
|
+
# outbound edge. Adding a sibling here blocks the forward path outright: task 0758
|
|
10
|
+
# did exactly that and denied every wip→testing and testing→done write until it
|
|
11
|
+
# was reverted.
|
|
12
|
+
#
|
|
3
13
|
# Reliability (aligned with task-pipeline / ADR-043 — lifecycle-only contract):
|
|
4
|
-
# - Hard shell guards only at wip→testing and testing→done
|
|
5
|
-
# requestTransition fails closed when
|
|
6
|
-
# - CLI done verdict guard is a second layer (0292) covering --no-lifecycle
|
|
14
|
+
# - Hard shell guards only at wip→testing and testing→done
|
|
15
|
+
# (no soft probe needed: requestTransition fails closed when guard shell is non-zero)
|
|
16
|
+
# - CLI done verdict guard is a second layer (0292) covering --no-lifecycle
|
|
17
|
+
# paths
|
|
7
18
|
# - No agent.run nodes (by design — pure status graph)
|
|
8
19
|
# - cancelled is the sole terminal; done is re-enterable (reopen → wip)
|
|
9
20
|
"$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
|
|
@@ -21,20 +32,20 @@ description: >
|
|
|
21
32
|
auto-advance).
|
|
22
33
|
|
|
23
34
|
Two-layer done gate (task 0292): this workflow's testing→done guard
|
|
24
|
-
(`spur task check --as done`, F92 R3 — target-aware) is the FIRST gate.
|
|
25
|
-
(`packages/app/src/services/done-transition-guard.ts`)
|
|
26
|
-
invoked by `apps/cli/src/commands/task.ts` for every
|
|
27
|
-
done` call — it reads `.spur/run/<wbs>-verdict.json`
|
|
28
|
-
verdicts unless `--force-done --reason "<why>"` is
|
|
29
|
-
covers the `--no-lifecycle` and adapter-unavailable
|
|
30
|
-
workflow. Overrides are recorded via the `done_forced`
|
|
31
|
-
frontmatter fields.
|
|
35
|
+
(`spur task check --as done`, F92 R3 — target-aware) is the FIRST gate.
|
|
36
|
+
The CLI verdict guard (`packages/app/src/services/done-transition-guard.ts`)
|
|
37
|
+
is the SECOND gate, invoked by `apps/cli/src/commands/task.ts` for every
|
|
38
|
+
`spur task update <wbs> done` call — it reads `.spur/run/<wbs>-verdict.json`
|
|
39
|
+
and blocks non-PASS verdicts unless `--force-done --reason "<why>"` is
|
|
40
|
+
supplied. The CLI gate covers the `--no-lifecycle` and adapter-unavailable
|
|
41
|
+
paths that bypass this workflow. Overrides are recorded via the `done_forced`
|
|
42
|
+
/ `done_reason` frontmatter fields.
|
|
32
43
|
initialState: backlog
|
|
33
44
|
terminalStates:
|
|
34
45
|
- cancelled
|
|
35
46
|
vars:
|
|
36
|
-
spurBin:
|
|
37
|
-
wbs:
|
|
47
|
+
spurBin: "spur"
|
|
48
|
+
wbs: "0000"
|
|
38
49
|
|
|
39
50
|
states:
|
|
40
51
|
- id: backlog
|
|
@@ -48,7 +59,8 @@ states:
|
|
|
48
59
|
- id: blocked
|
|
49
60
|
description: Impediment; work suspended.
|
|
50
61
|
- id: done
|
|
51
|
-
description:
|
|
62
|
+
description: >
|
|
63
|
+
Completed. Re-enterable (reopen with warning + mandatory History entry).
|
|
52
64
|
- id: cancelled
|
|
53
65
|
description: Terminal — abandoned.
|
|
54
66
|
|
|
@@ -73,7 +85,7 @@ transitions:
|
|
|
73
85
|
command: '$spurBin task check $wbs --as testing'
|
|
74
86
|
- from: testing
|
|
75
87
|
to: done
|
|
76
|
-
description: Testing passed
|
|
88
|
+
description: Testing passed; mark done
|
|
77
89
|
guard:
|
|
78
90
|
kind: shell
|
|
79
91
|
options:
|