@gobing-ai/spur 0.3.72 → 0.3.74
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 +48 -27
- package/config/pipeline-budgets.json +9 -5
- package/config/plugin-scripts.json +4 -0
- package/config/proportional-route-table.ts +155 -0
- package/config/rules/strict/runtime-boundaries.yaml +1 -1
- package/config/rules/structure/protected-files.yaml +3 -0
- package/config/task-pipeline-proportional-migration-plan.md +79 -0
- package/config/templates/AGENTS.md +5 -0
- package/config/templates/docs/99_PROJECT_CONSTITUTION.md +2 -0
- package/config/workflows/basic.yaml +5 -2
- package/config/workflows/docs-pipeline.yaml +101 -54
- package/config/workflows/feature-dev.yaml +57 -27
- package/config/workflows/feature-lifecycle.yaml +1 -0
- package/config/workflows/history-anatomy.yaml +8 -4
- package/config/workflows/idea-pipeline.yaml +66 -33
- package/config/workflows/pr-review.yaml +31 -8
- package/config/workflows/task-lifecycle.yaml +28 -15
- package/config/workflows/task-pipeline.yaml +929 -844
- package/config/workflows/wayfinder-resolution.yaml +124 -90
- package/config/workflows/wrapup-pipeline.yaml +290 -107
- package/package.json +9 -9
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/scripts/daily-summary/daily-summary.mjs +2 -4
- package/plugins/sp/scripts/daily-summary/daily-summary.ts +2 -4
- package/plugins/sp/scripts/history-anatomy-cache.mjs +7 -1
- package/plugins/sp/scripts/history-anatomy-cache.ts +11 -2
- package/plugins/sp/scripts/inline-pipeline-parity-check.ts +185 -0
- package/plugins/sp/scripts/pr-reviewing.mjs +5 -1
- package/plugins/sp/scripts/pr-reviewing.ts +7 -1
- package/plugins/sp/scripts/task-evidence-precheck.ts +1 -1
- package/plugins/sp/scripts/transition-shim-check.ts +6 -6
- package/plugins/sp/scripts/verify-answer-lint.ts +4 -0
- package/plugins/sp/skills/pr-reviewing/SKILL.md +4 -1
- package/plugins/sp/skills/spur-cli/references/self.md +17 -3
- package/plugins/sp/skills/spur-cli/references/tasks.md +1 -1
- package/plugins/sp/skills/spur-cli/references/workflows/authoring-workflows.md +23 -0
- package/plugins/sp/skills/spur-cli/references/workflows/workflow-fit-and-tuning.md +5 -5
- package/plugins/sp/skills/spur-cli/references/workflows.md +4 -4
- package/plugins/sp/skills/spur-dev/SKILL.md +17 -0
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +3 -3
- package/plugins/sp/skills/spur-dev/references/gate-checklists.md +1 -2
- package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +20 -0
- package/plugins/sp/skills/wayfinder/SKILL.md +1 -1
- package/schemas/state-machine-workflow.schema.json +3 -1
- package/schemas/transition-flow-workflow.schema.json +3 -1
- package/spur.js +12639 -10106
- package/web/_astro/{BoardApp.BYCNkMOn.js → BoardApp.C60RJZRj.js} +78 -77
- package/web/_astro/BoardApp.ymfj1EHA.js +1 -0
- package/web/_astro/{TaskDetail.CgUreSP2.js → TaskDetail.Guk8VuNu.js} +1 -1
- package/web/_astro/{arc.BySSh34M.js → arc.CAZtlWJM.js} +1 -1
- package/web/_astro/{architectureDiagram-3BPJPVTR.DM46TS_h.js → architectureDiagram-3BPJPVTR.9-XbF_Tz.js} +1 -1
- package/web/_astro/{blockDiagram-GPEHLZMM.tZhvNUHA.js → blockDiagram-GPEHLZMM.DC4WLx3L.js} +1 -1
- package/web/_astro/{c4Diagram-AAUBKEIU.PT4Or4Nf.js → c4Diagram-AAUBKEIU.JgjUQMgG.js} +1 -1
- package/web/_astro/channel.Bxxe2Byc.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.J9r0_Bbe.js → chunk-2J33WTMH.D_JFiXa-.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.hzyeIvhR.js → chunk-4BX2VUAB.Bk_RxoeT.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.B0rO7qVh.js → chunk-55IACEB6.a_Rj2VxL.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.wE_Uk5D4.js → chunk-727SXJPM.C2NoS1U6.js} +1 -1
- package/web/_astro/{chunk-AQP2D5EJ.DqEEjQw7.js → chunk-AQP2D5EJ.D1Xn6CNa.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.CDoD9sBX.js → chunk-FMBD7UC4.BhJrSBsX.js} +1 -1
- package/web/_astro/{chunk-ND2GUHAM.CtX5nF9P.js → chunk-ND2GUHAM.ByVGduYQ.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.CK_EwfaT.js → chunk-QZHKN3VN.B47Paunq.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.DLt5a8Lh.js → classDiagram-4FO5ZUOK.BERMSD5C.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.DLt5a8Lh.js → classDiagram-v2-Q7XG4LA2.BERMSD5C.js} +1 -1
- package/web/_astro/{cose-bilkent-S5V4N54A.CMCWP49h.js → cose-bilkent-S5V4N54A.O_rHGlhU.js} +1 -1
- package/web/_astro/{cynefin-OW5HDTMX.HyXw_vdS.js → cynefin-OW5HDTMX.qCW2GdNp.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.BTuAzh01.js → dagre-BM42HDAG.C5Y4lH_u.js} +1 -1
- package/web/_astro/{diagram-2AECGRRQ.D9dr9wfT.js → diagram-2AECGRRQ.DxZmRXxF.js} +1 -1
- package/web/_astro/{diagram-5GNKFQAL.C4Rot0hj.js → diagram-5GNKFQAL.qSxZeYSK.js} +1 -1
- package/web/_astro/{diagram-KO2AKTUF.B_TK5uWC.js → diagram-KO2AKTUF.-7vl3bXs.js} +1 -1
- package/web/_astro/{diagram-LMA3HP47.JkXKK7CO.js → diagram-LMA3HP47.BHVV-UH3.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.BzMN8Bd6.js → diagram-OG6HWLK6.DHAuW9sK.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.DVZaWGUd.js → erDiagram-TEJ5UH35.DMRLQwPN.js} +1 -1
- package/web/_astro/{flowDiagram-I6XJVG4X.rjEiWUfR.js → flowDiagram-I6XJVG4X.B3EpPp_8.js} +1 -1
- package/web/_astro/{ganttDiagram-6RSMTGT7.C_EgAarK.js → ganttDiagram-6RSMTGT7.BgUrExXM.js} +1 -1
- package/web/_astro/{gitGraphDiagram-PVQCEYII.B-QQSDsK.js → gitGraphDiagram-PVQCEYII.CU-9yVN4.js} +1 -1
- package/web/_astro/{index.B5MTfe7k.css → index.BhvM3djt.css} +1 -1
- package/web/_astro/{infoDiagram-5YYISTIA.DlWesz7T.js → infoDiagram-5YYISTIA.CvVTCRLe.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.BUMZOawi.js → ishikawaDiagram-YF4QCWOH.BUzOfKPf.js} +1 -1
- package/web/_astro/{journeyDiagram-JHISSGLW.CWfkxfjY.js → journeyDiagram-JHISSGLW.BBTb7ziz.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.B-YpMwXf.js → kanban-definition-UN3LZRKU.CTQQr70i.js} +1 -1
- package/web/_astro/{linear.D7uqzENp.js → linear.CLKlJPiS.js} +1 -1
- package/web/_astro/{mermaid.core.CxrNppBD.js → mermaid.core.BA4wFhLP.js} +4 -4
- package/web/_astro/{mindmap-definition-RKZ34NQL.B4Qe7cM2.js → mindmap-definition-RKZ34NQL.t1vG2l5e.js} +1 -1
- package/web/_astro/{pieDiagram-4H26LBE5.Ds-5j2ro.js → pieDiagram-4H26LBE5.C8zJhyTu.js} +1 -1
- package/web/_astro/{quadrantDiagram-W4KKPZXB.tBd38uNC.js → quadrantDiagram-W4KKPZXB.DqYYvb7T.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.sFENkWl3.js → requirementDiagram-4Y6WPE33.lzfDZ9nI.js} +1 -1
- package/web/_astro/{sankeyDiagram-5OEKKPKP.BeB-Hk7C.js → sankeyDiagram-5OEKKPKP.lm6N5ORM.js} +1 -1
- package/web/_astro/{sequenceDiagram-3UESZ5HK.DnTeaSpx.js → sequenceDiagram-3UESZ5HK.E6_IV4Dj.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.B-8Jt5EJ.js → stateDiagram-AJRCARHV.Bnv6Ok2p.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.Br7xoqMW.js → stateDiagram-v2-BHNVJYJU.mJHH_Ng_.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.C-3WdOyi.js → timeline-definition-PNZ67QCA.BhRgqSLa.js} +1 -1
- package/web/_astro/{vennDiagram-CIIHVFJN.DCIs7Lc6.js → vennDiagram-CIIHVFJN.pjb5DMC9.js} +1 -1
- package/web/_astro/{wardleyDiagram-YWT4CUSO.rGAL-bbz.js → wardleyDiagram-YWT4CUSO.CW20KUng.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6.hkfQKiRl.js → xychartDiagram-2RQKCTM6.vX9_yuMl.js} +1 -1
- package/web/index.html +2 -2
- package/config/corpus-baseline.json +0 -1637
- package/config/workflow-composition-baseline.json +0 -576
- package/web/_astro/BoardApp.E12MFjOS.js +0 -1
- package/web/_astro/channel.5cYKr5cs.js +0 -1
|
@@ -11,12 +11,15 @@
|
|
|
11
11
|
# - requireDiff fails silent no-op drafts
|
|
12
12
|
# - HITL answer routing is exhaustive (yes/no/cancel)
|
|
13
13
|
# - verify measures the deliverable read-only (answer file + `spur task verdict` + proof
|
|
14
|
-
# digest bracket)
|
|
14
|
+
# digest bracket); recording happens only AFTER measured PASS (0769 ordering:
|
|
15
|
+
# precheck → draft → docs-review → verify → record → done) and `record → done` is
|
|
16
|
+
# fail-closed on the captured record result + re-asserted verdict — never on a stub
|
|
15
17
|
|
|
16
18
|
"$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
|
|
19
|
+
version: "1"
|
|
17
20
|
kind: state-machine
|
|
18
21
|
name: docs-pipeline
|
|
19
|
-
description: "Docs-only execution pipeline (precheck -> draft -> docs-review ->
|
|
22
|
+
description: "Docs-only execution pipeline (precheck -> draft -> docs-review -> verify -> record -> done)"
|
|
20
23
|
iterationBound: 12
|
|
21
24
|
initialState: precheck
|
|
22
25
|
terminalStates:
|
|
@@ -34,13 +37,15 @@ vars:
|
|
|
34
37
|
stepTimeoutMs: "1800000"
|
|
35
38
|
# Proof-state bracket (task 0704, mirroring task-pipeline 0612/0703). `proofDigest` is the
|
|
36
39
|
# canonical capture at verify entry; `proofDigestNow` is the live re-capture compared against
|
|
37
|
-
# it by the `verify →
|
|
40
|
+
# it by the `verify → record` guard so verifier-time mutation fails closed (R4/R5).
|
|
38
41
|
proofDigest: ""
|
|
39
42
|
proofDigestNow: ""
|
|
40
43
|
# `taskSpecPath` carries the task file path because `docs/tasks*` is excluded from the digest's
|
|
41
44
|
# git-tree half (task 0704 R4); resolved per-run by the verify state's taskpath shell step.
|
|
42
45
|
taskSpecPath: ""
|
|
43
46
|
__hitlAnswer: ""
|
|
47
|
+
# R8 (0366): injected by WorkflowAppService.run(); run-scopes every temporary capture.
|
|
48
|
+
__runId: ""
|
|
44
49
|
|
|
45
50
|
states:
|
|
46
51
|
- id: precheck
|
|
@@ -49,14 +54,16 @@ states:
|
|
|
49
54
|
(D5-J, ADR-069). Both gates run `softFail: true`, so a red probe records FAIL and lets
|
|
50
55
|
the transitions route to `failed` instead of aborting the run — the shipped action
|
|
51
56
|
schema exposes no `onError`, so soft mode is what preserves that routing.
|
|
52
|
-
The canonical `.spur/run/$
|
|
57
|
+
The canonical `.spur/run/$__runId-docs-precheck.status` is the AND of the two gate files.
|
|
58
|
+
(0769: temporary captures are run-scoped — `.spur/run/<runId>-docs-*` — so concurrent
|
|
59
|
+
runs on one task never share or clobber a capture.)
|
|
53
60
|
onEnter:
|
|
54
61
|
- kind: command.gate
|
|
55
62
|
options:
|
|
56
63
|
id: docs-precheck-task
|
|
57
64
|
executable: "${vars.spurBin}"
|
|
58
65
|
args: ["task", "check", "${vars.wbs}"]
|
|
59
|
-
resultFile: .spur/run/${vars.
|
|
66
|
+
resultFile: .spur/run/${vars.__runId}-docs-precheck-task.status
|
|
60
67
|
softFail: true
|
|
61
68
|
timeoutMs: 120000
|
|
62
69
|
- kind: command.gate
|
|
@@ -64,16 +71,16 @@ states:
|
|
|
64
71
|
id: docs-precheck-agent
|
|
65
72
|
executable: "${vars.spurBin}"
|
|
66
73
|
args: ["agent", "doctor", "${vars.agent}"]
|
|
67
|
-
resultFile: .spur/run/${vars.
|
|
74
|
+
resultFile: .spur/run/${vars.__runId}-docs-precheck-agent.status
|
|
68
75
|
softFail: true
|
|
69
76
|
timeoutMs: 120000
|
|
70
77
|
- kind: shell
|
|
71
78
|
options:
|
|
72
79
|
command: >-
|
|
73
|
-
if test "$(cat .spur/run/$
|
|
74
|
-
test "$(cat .spur/run/$
|
|
75
|
-
then printf 'PASS\n' > ".spur/run/$
|
|
76
|
-
else printf 'FAIL\n' > ".spur/run/$
|
|
80
|
+
if test "$(cat .spur/run/$__runId-docs-precheck-task.status 2>/dev/null)" = PASS &&
|
|
81
|
+
test "$(cat .spur/run/$__runId-docs-precheck-agent.status 2>/dev/null)" = PASS;
|
|
82
|
+
then printf 'PASS\n' > ".spur/run/$__runId-docs-precheck.status";
|
|
83
|
+
else printf 'FAIL\n' > ".spur/run/$__runId-docs-precheck.status"; fi
|
|
77
84
|
- kind: note
|
|
78
85
|
options:
|
|
79
86
|
message: "Docs pipeline start for task ${vars.wbs}."
|
|
@@ -108,44 +115,39 @@ states:
|
|
|
108
115
|
options:
|
|
109
116
|
prompt: "Approve docs-only deliverable for task ${vars.wbs}?"
|
|
110
117
|
|
|
111
|
-
- id: record
|
|
112
|
-
description: >
|
|
113
|
-
Record the docs-only outcome into the task file. The task record verb backfills
|
|
114
|
-
Solution from the diff and moves the task to testing; the done gate still runs
|
|
115
|
-
the normal task matrix check before completion.
|
|
116
|
-
onEnter:
|
|
117
|
-
- kind: shell
|
|
118
|
-
options:
|
|
119
|
-
command: "$spurBin task record $wbs --solution-from-diff --transition testing"
|
|
120
|
-
|
|
121
|
-
- id: done
|
|
122
|
-
description: Terminal — docs deliverable measured, reviewed, and recorded.
|
|
123
|
-
onEnter:
|
|
124
|
-
# R1 (0704): no synthetic verdict writer. The verdict artifact is produced by measured
|
|
125
|
-
# verification in `verify` and registered there; done only performs the guarded
|
|
126
|
-
# transition. Override path remains: --force-done --reason.
|
|
127
|
-
- kind: shell
|
|
128
|
-
options:
|
|
129
|
-
command: "$spurBin task update $wbs done --no-lifecycle"
|
|
130
|
-
- kind: note
|
|
131
|
-
options:
|
|
132
|
-
message: "Docs pipeline complete for task ${vars.wbs}."
|
|
133
118
|
- id: verify
|
|
134
119
|
description: >
|
|
135
120
|
Read-only measured verification (task 0704, R2/R4/R7): dispatch /sp:dev-verify --fix none
|
|
136
121
|
with an answer file, derive the ONE standard verdict via `spur task verdict`, register the
|
|
137
122
|
standard verify-verdict artifact, and bracket the verifier with proof-input digest capture/compare so any
|
|
138
123
|
task-spec or document mutation during certification fails closed (R4). No docs assurance
|
|
139
|
-
subclass — PASS semantics are identical to task-pipeline (R7).
|
|
124
|
+
subclass — PASS semantics are identical to task-pipeline (R7). 0769: verification now
|
|
125
|
+
PRECEDES recording; the `verify → record` guard compares the proof bracket, and the
|
|
126
|
+
verdict artifact keeps its `.spur/run/<wbs>-verdict.json` compatibility path with
|
|
127
|
+
runId + definitionDigest stamped through the existing proof/run-artifact contract.
|
|
140
128
|
onEnter:
|
|
129
|
+
# 0769: clear any stale current-run answer before the fresh-session verifier writes it.
|
|
130
|
+
- kind: shell
|
|
131
|
+
options:
|
|
132
|
+
command: "mkdir -p .spur/run && rm -f .spur/run/$__runId-docs-verify-answer.txt"
|
|
141
133
|
# R4 (0703 R6 precedent): resolve the task-spec path BEFORE capture. `docs/tasks*` is
|
|
142
134
|
# excluded from the digest's git-tree half, so the spec is folded in via `taskFile`.
|
|
143
135
|
- kind: shell
|
|
144
136
|
options:
|
|
145
|
-
|
|
137
|
+
# 0760 R1 (sibling of 0751 R2): task-path lookup fails closed. Drop
|
|
138
|
+
# `2>/dev/null`, `|| true`, and the forced `exit 0` so an unresolved
|
|
139
|
+
# wbs exits non-zero with a named message. The resolved path folds
|
|
140
|
+
# into the proof digest via `taskFile:` below; a silent miss would
|
|
141
|
+
# degrade the docs-pipeline proof to tree-only (same hazard 0751 R2
|
|
142
|
+
# removed from task-pipeline). (0769: run-scoped capture path.)
|
|
143
|
+
command: >-
|
|
144
|
+
set -e;
|
|
145
|
+
task_path="$($spurBin task path $wbs --json | jq -r '.path // .filePath // empty')";
|
|
146
|
+
if [ -z "$task_path" ]; then echo "docs-pipeline: task path did not resolve for wbs $wbs" >&2; exit 1; fi;
|
|
147
|
+
printf '%s' "$task_path" > ".spur/run/$__runId-docs-taskpath.txt"
|
|
146
148
|
- kind: file.read.into-var
|
|
147
149
|
options:
|
|
148
|
-
path: .spur/run/${vars.
|
|
150
|
+
path: .spur/run/${vars.__runId}-docs-taskpath.txt
|
|
149
151
|
var: taskSpecPath
|
|
150
152
|
# R4: canonical capture BEFORE the verifier runs. Same fingerprint input as the
|
|
151
153
|
# re-capture below so the bracket compares like for like.
|
|
@@ -164,19 +166,19 @@ states:
|
|
|
164
166
|
input: /sp:dev-verify ${vars.wbs} --auto --fix none --focus all
|
|
165
167
|
role: reviewer
|
|
166
168
|
timeoutMs: ${vars.stepTimeoutMs}
|
|
167
|
-
answerFile: .spur/run/${vars.
|
|
169
|
+
answerFile: .spur/run/${vars.__runId}-docs-verify-answer.txt
|
|
168
170
|
- kind: shell
|
|
169
171
|
options:
|
|
170
|
-
command: "$spurBin task verdict $wbs --from-answer .spur/run/$
|
|
171
|
-
# R7: stamp the proof block into the standard verdict artifact, then register
|
|
172
|
-
# Soft action + hard guard: a missing/malformed stamp fails the `verify ->
|
|
172
|
+
command: "$spurBin task verdict $wbs --from-answer .spur/run/$__runId-docs-verify-answer.txt"
|
|
173
|
+
# R7: stamp the proof block + run identity into the standard verdict artifact, then register
|
|
174
|
+
# it. Soft action + hard guard: a missing/malformed stamp fails the `verify -> record`
|
|
173
175
|
# guard below, not this step.
|
|
174
176
|
- kind: shell
|
|
175
177
|
options:
|
|
176
178
|
command: >-
|
|
177
179
|
V=".spur/run/$wbs-verdict.json";
|
|
178
180
|
if [ -f "$V" ] && [ -n "$proofDigest" ]; then
|
|
179
|
-
jq --arg d "$proofDigest" '. + {proof: {digest: $d, capturePoint: "docs-verify-entry"}}' "$V" > "$V.tmp" && mv "$V.tmp" "$V";
|
|
181
|
+
jq --arg d "$proofDigest" --arg r "$__runId" '. + {proof: {digest: $d, capturePoint: "docs-verify-entry", runId: $r}}' "$V" > "$V.tmp" && mv "$V.tmp" "$V";
|
|
180
182
|
fi;
|
|
181
183
|
exit 0
|
|
182
184
|
- kind: run.artifact
|
|
@@ -192,6 +194,37 @@ states:
|
|
|
192
194
|
input: /sp:dev-verify ${vars.wbs} --auto --fix none --focus all
|
|
193
195
|
timeoutMs: ${vars.stepTimeoutMs}
|
|
194
196
|
|
|
197
|
+
- id: record
|
|
198
|
+
description: >
|
|
199
|
+
Record the docs-only outcome AFTER measured verification (task 0769 ordering:
|
|
200
|
+
draft/approval → verify → record → done — the pre-verification record could write
|
|
201
|
+
UNKNOWN/old Testing evidence). The verdict is already derived and proof-bracketed in
|
|
202
|
+
`verify`; `verify → record` only opens on measured PASS with an intact bracket. The
|
|
203
|
+
task record verb backfills Solution from the diff and moves the task to testing; its
|
|
204
|
+
result is captured to a run-scoped status file so a record denial reaches `failed`
|
|
205
|
+
(record → failed) and is never converted to success by an exit 0.
|
|
206
|
+
onEnter:
|
|
207
|
+
- kind: shell
|
|
208
|
+
options:
|
|
209
|
+
command: >-
|
|
210
|
+
if $spurBin task record $wbs --solution-from-diff --transition testing; then
|
|
211
|
+
printf 'PASS\n' > ".spur/run/$__runId-docs-record.status";
|
|
212
|
+
else
|
|
213
|
+
printf 'FAIL\n' > ".spur/run/$__runId-docs-record.status";
|
|
214
|
+
fi
|
|
215
|
+
|
|
216
|
+
- id: done
|
|
217
|
+
description: Terminal — docs deliverable measured, reviewed, and recorded.
|
|
218
|
+
onEnter:
|
|
219
|
+
# R1 (0704): no synthetic verdict writer. The verdict artifact is produced by measured
|
|
220
|
+
# verification in `verify` and registered there; done only performs the guarded
|
|
221
|
+
# transition. Override path remains: --force-done --reason.
|
|
222
|
+
- kind: shell
|
|
223
|
+
options:
|
|
224
|
+
command: "$spurBin task update $wbs done --no-lifecycle"
|
|
225
|
+
- kind: note
|
|
226
|
+
options:
|
|
227
|
+
message: "Docs pipeline complete for task ${vars.wbs}."
|
|
195
228
|
- id: failed
|
|
196
229
|
description: Terminal — docs pipeline failed or was rejected.
|
|
197
230
|
|
|
@@ -213,8 +246,8 @@ transitions:
|
|
|
213
246
|
kind: always
|
|
214
247
|
|
|
215
248
|
- from: draft
|
|
216
|
-
to:
|
|
217
|
-
description: profile=auto — skip the docs-review HITL gate.
|
|
249
|
+
to: verify
|
|
250
|
+
description: "profile=auto — skip the docs-review HITL gate; verify measures BEFORE record (0769: a pre-verification record could write UNKNOWN/old Testing evidence)."
|
|
218
251
|
guard:
|
|
219
252
|
kind: shell
|
|
220
253
|
options:
|
|
@@ -226,8 +259,8 @@ transitions:
|
|
|
226
259
|
kind: always
|
|
227
260
|
|
|
228
261
|
- from: docs-review
|
|
229
|
-
to:
|
|
230
|
-
description: Docs approved —
|
|
262
|
+
to: verify
|
|
263
|
+
description: "Docs approved — measure the deliverable (0769: verification precedes recording)."
|
|
231
264
|
guard:
|
|
232
265
|
kind: shell
|
|
233
266
|
options:
|
|
@@ -247,16 +280,11 @@ transitions:
|
|
|
247
280
|
options:
|
|
248
281
|
command: 'test "$__hitlAnswer" = cancel'
|
|
249
282
|
|
|
250
|
-
- from: record
|
|
251
|
-
to: verify
|
|
252
|
-
description: Recorded — measure the deliverable (R2). Structural task-check gates remain
|
|
253
|
-
at precheck, record (wip→testing), and done (verdict-artifact guard, R3).
|
|
254
|
-
guard:
|
|
255
|
-
kind: always
|
|
256
|
-
|
|
257
283
|
- from: verify
|
|
258
|
-
to:
|
|
259
|
-
description: Measured PASS with the proof bracket intact (R4/R5)
|
|
284
|
+
to: record
|
|
285
|
+
description: Measured PASS with the proof bracket intact (R4/R5) — record only verified
|
|
286
|
+
outcomes (0769). Structural task-check gates remain at precheck, record (wip→testing),
|
|
287
|
+
and done (verdict-artifact guard, R3).
|
|
260
288
|
guard:
|
|
261
289
|
kind: shell
|
|
262
290
|
options:
|
|
@@ -274,6 +302,25 @@ transitions:
|
|
|
274
302
|
- from: verify
|
|
275
303
|
to: failed
|
|
276
304
|
description: Non-PASS verdict, missing/malformed answer, or digest mismatch (R5) — the run
|
|
277
|
-
reaches failed and
|
|
305
|
+
reaches failed and nothing is recorded.
|
|
306
|
+
guard:
|
|
307
|
+
kind: always
|
|
308
|
+
|
|
309
|
+
- from: record
|
|
310
|
+
to: done
|
|
311
|
+
description: Recorded from a verified outcome; the persisted verdict/bracket is re-asserted
|
|
312
|
+
so a failed `task record` (captured FAIL) never converts to done (0769).
|
|
313
|
+
guard:
|
|
314
|
+
kind: shell
|
|
315
|
+
options:
|
|
316
|
+
command: >-
|
|
317
|
+
test "$(cat .spur/run/$__runId-docs-record.status 2>/dev/null)" = PASS &&
|
|
318
|
+
test -f ".spur/run/$wbs-verdict.json" &&
|
|
319
|
+
test "$(jq -r '.verdict // empty' .spur/run/$wbs-verdict.json 2>/dev/null)" = PASS &&
|
|
320
|
+
test -n "$proofDigest" &&
|
|
321
|
+
test "$(jq -r '.proof.digest // empty' .spur/run/$wbs-verdict.json 2>/dev/null)" = "$proofDigest"
|
|
322
|
+
- from: record
|
|
323
|
+
to: failed
|
|
324
|
+
description: "Task record denied or errored (captured status not PASS) — the record denial reaches failed; the done guard above never converts it to success."
|
|
278
325
|
guard:
|
|
279
326
|
kind: always
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
|
|
10
10
|
kind: state-machine
|
|
11
11
|
name: feature-dev
|
|
12
|
+
version: "1"
|
|
12
13
|
description: >
|
|
13
14
|
End-to-end FEATURE development loop: precheck → brainstorm → plan (decompose) →
|
|
14
15
|
execute-tasks → feature-verify → done. Drives a whole feature (one description → a
|
|
@@ -143,32 +144,56 @@ states:
|
|
|
143
144
|
|
|
144
145
|
- id: integration-review
|
|
145
146
|
description: >
|
|
146
|
-
Advisory integration review (D5-P, feature R11)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
147
|
+
Advisory integration review (D5-P, feature R11), upgraded by 0770 to a
|
|
148
|
+
truthful collect: ONE Codex review request per HEAD, then exactly ONE
|
|
149
|
+
`pr-reviewing.ts collect --head <captured-head>` against that same HEAD —
|
|
150
|
+
no wait loop, no polling. The request verdict (`REQUESTED` /
|
|
151
|
+
`ALREADY_REQUESTED` / `ALREADY_REVIEWED`) describes request state only;
|
|
152
|
+
it is NEVER clean evidence. The ONLY clean evidence is the collected
|
|
153
|
+
status (CLEAN / FINDINGS / PENDING) persisted run-scoped at
|
|
154
|
+
.spur/run/<runId>-integration-review-collect.status. A missing head SHA,
|
|
155
|
+
an invalid collect result, or head drift records collect FAIL.
|
|
150
156
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
157
|
+
D8 decision D1 (0753 R3): invoking `pr-reviewing.ts request` directly —
|
|
158
|
+
the same per-HEAD dedupe-or-request logic `config/workflows/pr-review.yaml`
|
|
159
|
+
uses internally. Request FAIL records FAIL in
|
|
160
|
+
.spur/run/<runId>-integration-review.status, loudly (no softFail).
|
|
161
|
+
`requireCleanReview=true` turns a non-clean COLLECTED verdict (including
|
|
162
|
+
collect FAIL) into the blocking edge declared first below.
|
|
155
163
|
onEnter:
|
|
156
|
-
- kind:
|
|
164
|
+
- kind: shell
|
|
157
165
|
options:
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
-
|
|
162
|
-
-
|
|
163
|
-
|
|
164
|
-
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
166
|
+
command: >-
|
|
167
|
+
mkdir -p .spur/run &&
|
|
168
|
+
STATUS_FILE=".spur/run/$__runId-integration-review.status" &&
|
|
169
|
+
REQUEST_JSON=".spur/run/$__runId-integration-review.json" &&
|
|
170
|
+
COLLECT_JSON=".spur/run/$__runId-integration-review-collect.json" &&
|
|
171
|
+
COLLECT_STATUS=".spur/run/$__runId-integration-review-collect.status" &&
|
|
172
|
+
PR_REQUEST_STATUS=".spur/run/$__runId-integration-review-pr-request.status" &&
|
|
173
|
+
set +e &&
|
|
174
|
+
bun "$(superskill script path sp pr-reviewing.ts)" request --base "$baseBranch" --json
|
|
175
|
+
--status-file "$PR_REQUEST_STATUS" > "$REQUEST_JSON" 2>&1;
|
|
176
|
+
request_rc=$?; set -e &&
|
|
177
|
+
if [ "$request_rc" -eq 0 ]; then
|
|
178
|
+
printf 'PASS\n' > "$STATUS_FILE";
|
|
179
|
+
else
|
|
180
|
+
printf 'FAIL\n' > "$STATUS_FILE";
|
|
181
|
+
fi &&
|
|
182
|
+
HEAD_SHA=$(jq -r '.head // empty' "$REQUEST_JSON" 2>/dev/null || true) &&
|
|
183
|
+
if [ -z "$HEAD_SHA" ]; then
|
|
184
|
+
echo "integration-review: request result carried no head SHA — collect not run, recorded FAIL" >&2;
|
|
185
|
+
printf 'FAIL\n' > "$COLLECT_STATUS";
|
|
186
|
+
else
|
|
187
|
+
set +e &&
|
|
188
|
+
bun "$(superskill script path sp pr-reviewing.ts)" collect --head "$HEAD_SHA" --json
|
|
189
|
+
--status-file "$COLLECT_STATUS" > "$COLLECT_JSON" 2>&1;
|
|
190
|
+
collect_rc=$?; set -e &&
|
|
191
|
+
echo "integration-review: collect rc=$collect_rc status=$(cat "$COLLECT_STATUS" 2>/dev/null || echo missing) — verdict captured to $COLLECT_JSON" >&2;
|
|
192
|
+
fi;
|
|
193
|
+
exit 0
|
|
169
194
|
- kind: note
|
|
170
195
|
options:
|
|
171
|
-
message: "Integration review for feature ${vars.featureId}
|
|
196
|
+
message: "Integration review for feature ${vars.featureId}: request verdict at .spur/run/${vars.__runId}-integration-review.status (request state only — REQUESTED/ALREADY_* are NEVER clean evidence); collected verdict at .spur/run/${vars.__runId}-integration-review-collect.status (CLEAN/FINDINGS/PENDING — the only clean evidence). Advisory unless requireCleanReview=true."
|
|
172
197
|
|
|
173
198
|
- id: done
|
|
174
199
|
description: Terminal — feature planned, all tasks executed, and the feature verified.
|
|
@@ -239,18 +264,23 @@ transitions:
|
|
|
239
264
|
- from: integration-review
|
|
240
265
|
to: failed
|
|
241
266
|
description: >
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
267
|
+
Collected verdict is not CLEAN (FINDINGS / PENDING / collect FAIL or
|
|
268
|
+
missing) and this branch opted into a hard gate (requireCleanReview=true).
|
|
269
|
+
Exactly one collect ran against the captured request HEAD — no wait loop —
|
|
270
|
+
so pending or findings stop the feature here with the actual reason.
|
|
271
|
+
Ordered before the advisory edge so the strict policy wins when both
|
|
272
|
+
would match.
|
|
245
273
|
guard:
|
|
246
274
|
kind: shell
|
|
247
275
|
options:
|
|
248
|
-
command: 'test "$requireCleanReview" = true && test "$(cat .spur/run/$__runId-integration-review.status 2>/dev/null)"
|
|
276
|
+
command: 'test "$requireCleanReview" = true && test "$(cat .spur/run/$__runId-integration-review-collect.status 2>/dev/null)" != CLEAN'
|
|
249
277
|
- from: integration-review
|
|
250
278
|
to: done
|
|
251
279
|
description: >
|
|
252
|
-
|
|
253
|
-
non-clean advisory
|
|
280
|
+
Collected CLEAN, or advisory mode (requireCleanReview != true) — the
|
|
281
|
+
feature is complete. A non-clean advisory collect never blocks a
|
|
282
|
+
locally-verified feature (feature R11); the note above preserves the
|
|
283
|
+
collected non-clean state in the run record instead of hiding it.
|
|
254
284
|
guard:
|
|
255
285
|
kind: always
|
|
256
286
|
- from: feature-verify
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
|
|
10
10
|
kind: state-machine
|
|
11
11
|
name: feature-lifecycle
|
|
12
|
+
version: "1"
|
|
12
13
|
description: >
|
|
13
14
|
Feature lifecycle FSM (design §2.3, §5.1, DD-13). States are the canonical
|
|
14
15
|
FeatureStatus vocabulary; transitions encode the §2.3 graph including the
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
|
|
49
49
|
kind: state-machine
|
|
50
50
|
name: history-anatomy
|
|
51
|
+
version: "1"
|
|
51
52
|
description: "Daily/ad-hoc history-anatomy report: cache branch, deterministic analyze/render, skill enrichment, deterministic structure gate, independent evidence validation, bounded correction, atomic publication"
|
|
52
53
|
iterationBound: 20
|
|
53
54
|
initialState: start
|
|
@@ -153,7 +154,7 @@ states:
|
|
|
153
154
|
--baseline .spur/run/$__runId-history-anatomy-baseline.json --target "$HA_TARGET"
|
|
154
155
|
--mode "$mode" --date "$HA_DATE" --recompute "$recompute" --executor "$agent"
|
|
155
156
|
--skill-dir "$HA_SKILL" --contract "$HA_SKILL/references/report-contract.md"
|
|
156
|
-
--workflow "$workflowFile" --contract-version "$contractVersion" --run-id "$__runId"
|
|
157
|
+
--workflow "$workflowFile" --helper "$HA_HELPER" --contract-version "$contractVersion" --run-id "$__runId"
|
|
157
158
|
--out .spur/run/$__runId-provenance.json
|
|
158
159
|
> .spur/run/$__runId-cache-disposition.txt
|
|
159
160
|
|
|
@@ -208,6 +209,9 @@ states:
|
|
|
208
209
|
description: >
|
|
209
210
|
Independent evidence validation via the skill operation sp:history-anatomy validate.
|
|
210
211
|
Publication is reachable only from a PASS here. Same undeclared-write assertion as enrich (0676 R3).
|
|
212
|
+
The publish guard reads the ANCHORED FINAL LINE (0771): only a validation artifact whose last
|
|
213
|
+
line is exactly `Verdict: PASS` publishes — a leading PASS under a later FAIL or a
|
|
214
|
+
`not Verdict: PASS` line can never satisfy it.
|
|
211
215
|
onEnter:
|
|
212
216
|
- kind: shell
|
|
213
217
|
options:
|
|
@@ -390,18 +394,18 @@ transitions:
|
|
|
390
394
|
|
|
391
395
|
- from: validate
|
|
392
396
|
to: stamp
|
|
393
|
-
description: Independent validation PASS — stamp provenance, then publish atomically.
|
|
397
|
+
description: Independent validation PASS (anchored final line, 0771) — stamp provenance, then publish atomically.
|
|
394
398
|
guard:
|
|
395
399
|
kind: shell
|
|
396
400
|
options:
|
|
397
|
-
command: '
|
|
401
|
+
command: 'tail -n 1 .spur/run/$__runId-validation.txt 2>/dev/null | grep -qx "Verdict: PASS"'
|
|
398
402
|
- from: validate
|
|
399
403
|
to: correct
|
|
400
404
|
description: Validation FAIL under the shared two-pass correction cap.
|
|
401
405
|
guard:
|
|
402
406
|
kind: shell
|
|
403
407
|
options:
|
|
404
|
-
command: '!
|
|
408
|
+
command: '! tail -n 1 .spur/run/$__runId-validation.txt 2>/dev/null | grep -qx "Verdict: PASS" && test "$(cat .spur/run/$__runId-correction-count 2>/dev/null || echo 0)" -lt 2'
|
|
405
409
|
- from: validate
|
|
406
410
|
to: failed
|
|
407
411
|
description: Validation FAIL with the correction cap exhausted — terminate without publishing.
|