@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
|
@@ -2,15 +2,22 @@
|
|
|
2
2
|
# implementation pipeline (no task-pipeline / /sp:dev-run recursion).
|
|
3
3
|
#
|
|
4
4
|
# Reliability (aligned with task-pipeline / ADR-043):
|
|
5
|
-
# - Soft precheck (task check + show) → failed via transitions (status file, always exit 0)
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
# - verify
|
|
5
|
+
# - Soft precheck (task check + show) → failed via transitions (status file, always exit 0);
|
|
6
|
+
# the show capture doubles as the investigate input bundle (0769: the separate collect
|
|
7
|
+
# state re-ran the same CLI reads with no write in between — deleted)
|
|
8
|
+
# - investigate→verify passes only on a non-empty answer capture (fail-closed both ways)
|
|
9
|
+
# - verify is an independent fresh-session observe-only reviewer over the standard verdict
|
|
10
|
+
# contract (`spur task verdict --from-answer` + proof digest bracket + verify-verdict
|
|
11
|
+
# artifact) — 0769 retires the ad-hoc PASS-word file and the >5-line/>60-word padding
|
|
12
|
+
# metrics; evidence citations must still be truthful (grep -n anchors)
|
|
9
13
|
# - HITL approve routing is exhaustive (yes/no/cancel)
|
|
10
|
-
# - record → done
|
|
14
|
+
# - record captures `task record` → `task update done --no-lifecycle` into a status file;
|
|
15
|
+
# record → done is fail-closed on the captured result + persisted status readback — an
|
|
16
|
+
# exit 0 never converts a denied record into success (0769)
|
|
11
17
|
# - Free-form agent inputs are intentional: no pure-slash research surface yet
|
|
12
18
|
|
|
13
19
|
"$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
|
|
20
|
+
version: "1"
|
|
14
21
|
kind: state-machine
|
|
15
22
|
name: wayfinder-resolution
|
|
16
23
|
description: "Reusable resolution pipeline for research/specification tasks without invoking the code implementation pipeline"
|
|
@@ -33,46 +40,42 @@ vars:
|
|
|
33
40
|
resolutionMode: "research"
|
|
34
41
|
evidencePolicy: "spur-cli-first"
|
|
35
42
|
__hitlAnswer: ""
|
|
43
|
+
# R8 (0366): injected by WorkflowAppService.run(); run-scopes every capture.
|
|
44
|
+
__runId: ""
|
|
45
|
+
# Resolved per-run by the verify state's taskpath shell step; folded into the proof
|
|
46
|
+
# digest via taskFile (docs/tasks* is excluded from the digest's git-tree half).
|
|
47
|
+
taskSpecPath: ""
|
|
48
|
+
# Proof-state bracket (docs-pipeline precedent): canonical capture at verify entry,
|
|
49
|
+
# live re-capture after the verifier; the verify → record guard compares them.
|
|
50
|
+
proofDigest: ""
|
|
51
|
+
proofDigestNow: ""
|
|
36
52
|
|
|
37
53
|
states:
|
|
38
54
|
- id: precheck
|
|
39
55
|
description: >
|
|
40
|
-
Soft precheck: task check + show, status
|
|
41
|
-
route to `failed` via transitions (not a raw lifecycle abort).
|
|
56
|
+
Soft precheck: task check + show, status file, always exit 0 so failures
|
|
57
|
+
route to `failed` via transitions (not a raw lifecycle abort). The `task show`
|
|
58
|
+
capture is reused as the investigate input bundle — no separate collect state
|
|
59
|
+
(0769: same reads, no intervening write, no re-run).
|
|
42
60
|
onEnter:
|
|
43
61
|
- kind: shell
|
|
44
62
|
options:
|
|
45
63
|
command: >-
|
|
46
|
-
mkdir -p .spur/run
|
|
64
|
+
mkdir -p .spur/run &&
|
|
47
65
|
set +e &&
|
|
48
66
|
$spurBin task check $wbs; check_rc=$?;
|
|
49
|
-
$spurBin task show $wbs --json > .spur/run
|
|
67
|
+
$spurBin task show $wbs --json > .spur/run/$__runId-wayfinder-input.json; show_rc=$?;
|
|
50
68
|
set -e &&
|
|
51
69
|
if [ "$check_rc" -eq 0 ] && [ "$show_rc" -eq 0 ]; then
|
|
52
|
-
printf 'PASS\n' > .spur/run
|
|
70
|
+
printf 'PASS\n' > .spur/run/$__runId-wayfinder-precheck.status;
|
|
53
71
|
else
|
|
54
|
-
printf 'FAIL\n' > .spur/run
|
|
72
|
+
printf 'FAIL\n' > .spur/run/$__runId-wayfinder-precheck.status;
|
|
55
73
|
fi &&
|
|
56
74
|
exit 0
|
|
57
75
|
- kind: note
|
|
58
76
|
options:
|
|
59
77
|
message: "Wayfinder resolution started for task ${vars.wbs} (mode=${vars.resolutionMode}, evidence=${vars.evidencePolicy}); no code implementation pipeline is permitted."
|
|
60
78
|
|
|
61
|
-
- id: collect
|
|
62
|
-
description: "Create a deterministic local input bundle before delegation."
|
|
63
|
-
onEnter:
|
|
64
|
-
- kind: shell
|
|
65
|
-
options:
|
|
66
|
-
command: "mkdir -p .spur/run/wayfinder && $spurBin task show $wbs --json > .spur/run/wayfinder/$wbs-input.json"
|
|
67
|
-
# `wayfinder-resolution.yaml` uses the project→bundled resolver (tasks 0648/0650):
|
|
68
|
-
# a bare name falls back to the bundled tree; an explicit project path wins.
|
|
69
|
-
- kind: shell
|
|
70
|
-
options:
|
|
71
|
-
command: "$spurBin workflow validate wayfinder-resolution.yaml > .spur/run/wayfinder/$wbs-workflow-check.txt"
|
|
72
|
-
- kind: shell
|
|
73
|
-
options:
|
|
74
|
-
command: "$spurBin task check $wbs > .spur/run/wayfinder/$wbs-precheck.txt"
|
|
75
|
-
|
|
76
79
|
- id: investigate
|
|
77
80
|
description: "Resolve the task's research/specification requirements and author evidence-backed sections through Spur CLI."
|
|
78
81
|
onEnter:
|
|
@@ -85,7 +88,7 @@ states:
|
|
|
85
88
|
mode: text
|
|
86
89
|
input: >-
|
|
87
90
|
Resolve task ${vars.wbs} in resolution mode ${vars.resolutionMode} using the prepared
|
|
88
|
-
local bundle `.spur/run
|
|
91
|
+
local bundle `.spur/run/${vars.__runId}-wayfinder-input.json` and only local shell/file
|
|
89
92
|
reads plus the `spur` CLI; do not use network search or MCP tools. Do not
|
|
90
93
|
invoke task-pipeline.yaml, /sp:dev-run, /sp:dev-runall, or code implementation.
|
|
91
94
|
Read the task file, map its existing Requirements and Acceptance Criteria to the
|
|
@@ -93,24 +96,46 @@ states:
|
|
|
93
96
|
sections through `spur task update --section --from-file`. Preserve the research
|
|
94
97
|
boundary. Finish with a short summary and stop. Evidence policy: ${vars.evidencePolicy}.
|
|
95
98
|
|
|
96
|
-
Evidence-anchor
|
|
97
|
-
lives in a shared evidence file
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
section. Before finishing, re-read each cited line and confirm it names the
|
|
105
|
-
requirement's subject (0299 R1 line-anchor rule).
|
|
99
|
+
Evidence-anchor contract (mandatory — 0299 R1 line-anchor rule): when the task's
|
|
100
|
+
evidence lives in a shared evidence file, anchor every Solution/Testing `file:line`
|
|
101
|
+
citation truthfully — resolve the section's real start line with
|
|
102
|
+
`grep -n "^## <wbs> " <evidence-file>` and cite that exact line. NEVER copy a line
|
|
103
|
+
number from another ticket's example; each WBS anchors to its own section. Before
|
|
104
|
+
finishing, re-read each cited line and confirm it names the requirement's subject.
|
|
105
|
+
answerFile: .spur/run/${vars.__runId}-wayfinder-answer.md
|
|
106
|
+
expectFile: .spur/run/${vars.__runId}-wayfinder-answer.md
|
|
106
107
|
timeoutMs: ${vars.stepTimeoutMs}
|
|
107
108
|
|
|
108
109
|
- id: verify
|
|
109
|
-
description:
|
|
110
|
+
description: >
|
|
111
|
+
Independent, observe-only measured verification (0769): a fresh-session reviewer runs
|
|
112
|
+
/sp:dev-verify --fix none, the standard `spur task verdict` contract derives ONE verdict,
|
|
113
|
+
and a proof-input digest bracket fails closed on verifier-time mutation. Retires the
|
|
114
|
+
ad-hoc resolution-verdict PASS-word file. The verifier never repairs and never edits
|
|
115
|
+
task sections.
|
|
110
116
|
onEnter:
|
|
111
117
|
- kind: shell
|
|
112
118
|
options:
|
|
113
|
-
command: "rm -f .spur/run/
|
|
119
|
+
command: "mkdir -p .spur/run && rm -f .spur/run/$__runId-wayfinder-verify-answer.txt .spur/run/$wbs-verdict.json"
|
|
120
|
+
# Fail-closed task-path lookup (0760 R1 pattern): the resolved path folds into the
|
|
121
|
+
# proof digest via taskFile; a silent miss would degrade the proof to tree-only.
|
|
122
|
+
- kind: shell
|
|
123
|
+
options:
|
|
124
|
+
command: >-
|
|
125
|
+
set -e;
|
|
126
|
+
task_path="$($spurBin task path $wbs --json | jq -r '.path // .filePath // empty')";
|
|
127
|
+
if [ -z "$task_path" ]; then echo "wayfinder-resolution: task path did not resolve for wbs $wbs" >&2; exit 1; fi;
|
|
128
|
+
printf '%s' "$task_path" > ".spur/run/$__runId-wayfinder-taskpath.txt"
|
|
129
|
+
- kind: file.read.into-var
|
|
130
|
+
options:
|
|
131
|
+
path: .spur/run/${vars.__runId}-wayfinder-taskpath.txt
|
|
132
|
+
var: taskSpecPath
|
|
133
|
+
- kind: proof.fingerprint
|
|
134
|
+
options:
|
|
135
|
+
var: proofDigest
|
|
136
|
+
taskFile: ${vars.taskSpecPath}
|
|
137
|
+
input: /sp:dev-verify ${vars.wbs} --auto --fix none --focus all
|
|
138
|
+
timeoutMs: ${vars.stepTimeoutMs}
|
|
114
139
|
- kind: agent.run
|
|
115
140
|
options:
|
|
116
141
|
agent: ${vars.agent}
|
|
@@ -118,15 +143,33 @@ states:
|
|
|
118
143
|
# Declared Layer-1 role (0538 R2): routing reason beside the agent: pin.
|
|
119
144
|
role: reviewer
|
|
120
145
|
mode: text
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
146
|
+
# Observe-only + fresh session (ADR-071 / 0710 R2 precedent): the verifier
|
|
147
|
+
# certifies, it never repairs and never inherits the investigate session.
|
|
148
|
+
freshSession: true
|
|
149
|
+
input: /sp:dev-verify ${vars.wbs} --auto --fix none --focus all
|
|
150
|
+
answerFile: .spur/run/${vars.__runId}-wayfinder-verify-answer.txt
|
|
151
|
+
expectFile: .spur/run/${vars.__runId}-wayfinder-verify-answer.txt
|
|
152
|
+
timeoutMs: ${vars.stepTimeoutMs}
|
|
153
|
+
- kind: shell
|
|
154
|
+
options:
|
|
155
|
+
command: "$spurBin task verdict $wbs --from-answer .spur/run/$__runId-wayfinder-verify-answer.txt"
|
|
156
|
+
- kind: shell
|
|
157
|
+
options:
|
|
158
|
+
command: >-
|
|
159
|
+
V=".spur/run/$wbs-verdict.json";
|
|
160
|
+
if [ -f "$V" ] && [ -n "$proofDigest" ]; then
|
|
161
|
+
jq --arg d "$proofDigest" --arg r "$__runId" '. + {proof: {digest: $d, capturePoint: "wayfinder-verify-entry", runId: $r}}' "$V" > "$V.tmp" && mv "$V.tmp" "$V";
|
|
162
|
+
fi;
|
|
163
|
+
exit 0
|
|
164
|
+
- kind: run.artifact
|
|
165
|
+
options:
|
|
166
|
+
path: .spur/run/${vars.wbs}-verdict.json
|
|
167
|
+
artifactKind: verify-verdict
|
|
168
|
+
- kind: proof.fingerprint
|
|
169
|
+
options:
|
|
170
|
+
var: proofDigestNow
|
|
171
|
+
taskFile: ${vars.taskSpecPath}
|
|
172
|
+
input: /sp:dev-verify ${vars.wbs} --auto --fix none --focus all
|
|
130
173
|
timeoutMs: ${vars.stepTimeoutMs}
|
|
131
174
|
|
|
132
175
|
- id: approve
|
|
@@ -138,22 +181,24 @@ states:
|
|
|
138
181
|
prompt: "Approve research resolution for task ${vars.wbs}?"
|
|
139
182
|
|
|
140
183
|
- id: record
|
|
141
|
-
description:
|
|
184
|
+
description: >
|
|
185
|
+
Record the resolution AFTER measured verification (0769). The `task record` verb
|
|
186
|
+
backfills Solution from the diff and moves the task to testing; `task update done
|
|
187
|
+
--no-lifecycle` then completes it (this pipeline's own verify already produced the
|
|
188
|
+
standard verdict evidence). Both results are captured to a run-scoped status file and
|
|
189
|
+
the persisted status is read back — a denied record or a task that never reached done
|
|
190
|
+
routes to `failed` via the guards below and is never converted to success by exit 0.
|
|
142
191
|
onEnter:
|
|
143
|
-
# Both steps are soft (`; exit 0`) BY DESIGN, not laxity: the real gate is the
|
|
144
|
-
# `record → done` guard below, which re-runs `spur task check` AND asserts the
|
|
145
|
-
# status actually reached done. Hard-failing here aborted the run inside the
|
|
146
|
-
# state, so the declared `record → failed` edge was unreachable and a blocked
|
|
147
|
-
# lifecycle transition surfaced as a bare "Command exited with 1" instead of
|
|
148
|
-
# the terminal `failed` this workflow documents.
|
|
149
192
|
- kind: shell
|
|
150
193
|
options:
|
|
151
|
-
command:
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
194
|
+
command: >-
|
|
195
|
+
if $spurBin task record $wbs --solution-from-diff --transition testing &&
|
|
196
|
+
$spurBin task update $wbs done --no-lifecycle; then
|
|
197
|
+
printf 'PASS\n' > ".spur/run/$__runId-wayfinder-final.status";
|
|
198
|
+
else
|
|
199
|
+
printf 'FAIL\n' > ".spur/run/$__runId-wayfinder-final.status";
|
|
200
|
+
fi;
|
|
201
|
+
$spurBin task show $wbs --json | jq -r '.status // empty' > ".spur/run/$__runId-wayfinder-status.txt"
|
|
157
202
|
|
|
158
203
|
- id: done
|
|
159
204
|
description: "Research task resolved and ready to feed the implementation backlog."
|
|
@@ -170,52 +215,43 @@ states:
|
|
|
170
215
|
|
|
171
216
|
transitions:
|
|
172
217
|
- from: precheck
|
|
173
|
-
to:
|
|
174
|
-
description: "Precheck PASS —
|
|
218
|
+
to: investigate
|
|
219
|
+
description: "Precheck PASS — resolve the research task (input bundle captured at precheck)."
|
|
175
220
|
guard:
|
|
176
221
|
kind: shell
|
|
177
222
|
options:
|
|
178
|
-
command: 'test "$(cat .spur/run
|
|
223
|
+
command: 'test "$(cat .spur/run/$__runId-wayfinder-precheck.status 2>/dev/null)" = PASS'
|
|
179
224
|
- from: precheck
|
|
180
225
|
to: failed
|
|
181
226
|
description: "Precheck FAIL — stop before delegation."
|
|
182
227
|
guard:
|
|
183
228
|
kind: always
|
|
184
|
-
- from: collect
|
|
185
|
-
to: investigate
|
|
186
|
-
description: "Input bundle collected — resolve the research task."
|
|
187
|
-
guard:
|
|
188
|
-
kind: shell
|
|
189
|
-
options:
|
|
190
|
-
command: "test -s .spur/run/wayfinder/$wbs-input.json && test -s .spur/run/wayfinder/$wbs-precheck.txt"
|
|
191
|
-
- from: collect
|
|
192
|
-
to: failed
|
|
193
|
-
description: "Input collection failed — stop before delegation."
|
|
194
|
-
guard:
|
|
195
|
-
kind: shell
|
|
196
|
-
options:
|
|
197
|
-
command: "! test -s .spur/run/wayfinder/$wbs-input.json || ! test -s .spur/run/wayfinder/$wbs-precheck.txt"
|
|
198
229
|
- from: investigate
|
|
199
230
|
to: verify
|
|
200
|
-
description: "Research resolution authored — verify evidence and traceability. Guard enforces
|
|
231
|
+
description: "Research resolution authored — verify evidence and traceability. Guard enforces a non-empty answer capture (fail-closed both ways)."
|
|
201
232
|
guard:
|
|
202
233
|
kind: shell
|
|
203
234
|
options:
|
|
204
|
-
command: 'test
|
|
235
|
+
command: 'test -s .spur/run/$__runId-wayfinder-answer.md'
|
|
205
236
|
- from: investigate
|
|
206
237
|
to: failed
|
|
207
|
-
description: "
|
|
238
|
+
description: "Empty answer capture — investigate produced nothing to verify; stop rather than certify hollow evidence."
|
|
208
239
|
guard:
|
|
209
240
|
kind: shell
|
|
210
241
|
options:
|
|
211
|
-
command: 'test
|
|
242
|
+
command: '! test -s .spur/run/$__runId-wayfinder-answer.md'
|
|
212
243
|
- from: verify
|
|
213
244
|
to: record
|
|
214
|
-
description: "Auto profile — record only on a
|
|
245
|
+
description: "Auto profile — record only on a measured PASS verdict with the proof bracket intact (fail-closed to the approve gate otherwise)."
|
|
215
246
|
guard:
|
|
216
247
|
kind: shell
|
|
217
248
|
options:
|
|
218
|
-
command:
|
|
249
|
+
command: >-
|
|
250
|
+
test "$approval" = auto &&
|
|
251
|
+
test -n "$proofDigest" &&
|
|
252
|
+
test "$proofDigestNow" = "$proofDigest" &&
|
|
253
|
+
test -f ".spur/run/$wbs-verdict.json" &&
|
|
254
|
+
test "$(jq -r '.verdict // empty' .spur/run/$wbs-verdict.json 2>/dev/null)" = PASS
|
|
219
255
|
- from: verify
|
|
220
256
|
to: approve
|
|
221
257
|
description: "Verification completed — require explicit review approval."
|
|
@@ -244,15 +280,13 @@ transitions:
|
|
|
244
280
|
command: 'test "$__hitlAnswer" = no'
|
|
245
281
|
- from: record
|
|
246
282
|
to: done
|
|
247
|
-
description: "
|
|
283
|
+
description: "Captured record result PASS and the persisted status readback is actually done."
|
|
248
284
|
guard:
|
|
249
285
|
kind: shell
|
|
250
286
|
options:
|
|
251
|
-
command: '$
|
|
287
|
+
command: 'test "$(cat .spur/run/$__runId-wayfinder-final.status 2>/dev/null)" = PASS && test "$(cat .spur/run/$__runId-wayfinder-status.txt 2>/dev/null)" = done'
|
|
252
288
|
- from: record
|
|
253
289
|
to: failed
|
|
254
|
-
description: "Recording
|
|
290
|
+
description: "Recording failed, was denied, or the task never reached done — stop without claiming completion."
|
|
255
291
|
guard:
|
|
256
|
-
kind:
|
|
257
|
-
options:
|
|
258
|
-
command: '! $spurBin task check $wbs || test "$($spurBin task show $wbs --json | jq -r .status)" != done'
|
|
292
|
+
kind: always
|