@gobing-ai/spur 0.3.90 → 0.3.92
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/pipeline-budgets.json +9 -2
- package/config/plugin-scripts.json +17 -1
- package/config/workflows/decision-routing-example.yaml +134 -0
- package/config/workflows/feature-lifecycle.yaml +14 -5
- package/config/workflows/feature-verification.yaml +35 -27
- package/config/workflows/history-anatomy.yaml +14 -25
- package/config/workflows/idea-pipeline.yaml +17 -5
- package/config/workflows/task-pipeline.yaml +187 -4
- package/config/workflows/wayfinder-resolution.yaml +2 -0
- package/config/workflows/wrapup-pipeline.yaml +49 -5
- package/package.json +9 -9
- package/plugins/sp/README.md +1 -0
- package/plugins/sp/agents/expert-spur.md +2 -2
- package/plugins/sp/agents/super-planner.md +14 -5
- package/plugins/sp/commands/dev-dogfood.md +4 -4
- package/plugins/sp/commands/dev-fixall.md +8 -5
- package/plugins/sp/commands/dev-run.md +6 -0
- package/plugins/sp/commands/dev-runall.md +12 -6
- package/plugins/sp/commands/dev-verify.md +9 -0
- package/plugins/sp/commands/dev-verifyall.md +5 -0
- package/plugins/sp/lib/idea-handoff.generated.mjs +301 -300
- package/plugins/sp/lib/inline-run.generated.d.mts +17 -0
- package/plugins/sp/lib/inline-run.generated.mjs +1460 -0
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/references/environment-lens.md +1 -1
- package/plugins/sp/scripts/dogfood-testing/validate-report.mjs +136 -0
- package/plugins/sp/scripts/dogfood-testing/validate-report.ts +196 -2
- package/plugins/sp/scripts/feature-verification-steps.mjs +174 -0
- package/plugins/sp/scripts/feature-verification-steps.ts +275 -0
- package/plugins/sp/scripts/history-anatomy-cache.mjs +104 -4
- package/plugins/sp/scripts/history-anatomy-cache.ts +137 -13
- package/plugins/sp/scripts/inline-pipeline-parity-check.ts +2 -0
- package/plugins/sp/scripts/inline-run-setup.mjs +349 -0
- package/plugins/sp/scripts/inline-run-setup.ts +192 -75
- package/plugins/sp/scripts/record-feature-sync.mjs +63 -0
- package/plugins/sp/scripts/record-feature-sync.ts +84 -0
- package/plugins/sp/scripts/residual-scan.mjs +476 -0
- package/plugins/sp/scripts/residual-scan.ts +614 -0
- package/plugins/sp/scripts/surface-drift-inventory.ts +71 -6
- package/plugins/sp/scripts/task-evidence-precheck.ts +8 -3
- package/plugins/sp/scripts/task-size-precheck.ts +8 -3
- package/plugins/sp/scripts/validate-flag-contracts.ts +3 -3
- package/plugins/sp/skills/branch-workflow/SKILL.md +1 -0
- package/plugins/sp/skills/branch-workflow/references/worktree-patterns.md +2 -0
- package/plugins/sp/skills/code-implementation/SKILL.md +17 -0
- package/plugins/sp/skills/code-verification/SKILL.md +21 -0
- package/plugins/sp/skills/code-verification/references/verdict-schema.md +1 -0
- package/plugins/sp/skills/dogfood-testing/SKILL.md +5 -3
- package/plugins/sp/skills/dogfood-testing/references/monitor-ledger.md +63 -26
- package/plugins/sp/skills/dogfood-testing/references/report-template.md +33 -10
- package/plugins/sp/skills/history-anatomy/references/modes.md +5 -3
- package/plugins/sp/skills/next-feature/references/ranking-rubric.md +1 -1
- package/plugins/sp/skills/next-router/references/routing-table.md +7 -0
- package/plugins/sp/skills/parallel-execution/references/dispatch-surface.md +1 -1
- package/plugins/sp/skills/session-review/SKILL.md +12 -2
- package/plugins/sp/skills/spur-cli/references/agent.md +11 -2
- package/plugins/sp/skills/spur-cli/references/features.md +1 -1
- package/plugins/sp/skills/spur-cli/references/projects.md +3 -1
- package/plugins/sp/skills/spur-cli/references/self.md +5 -1
- package/plugins/sp/skills/spur-cli/references/workflows.md +42 -20
- package/plugins/sp/skills/spur-dev/SKILL.md +11 -4
- package/plugins/sp/skills/spur-dev/references/cross-cutting.md +25 -3
- package/plugins/sp/skills/spur-dev/references/dev-operations.md +2 -2
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +285 -57
- package/plugins/sp/skills/spur-dev/references/execution-workflow.md +14 -5
- package/plugins/sp/skills/spur-dev/references/flag-glossary.md +19 -4
- package/plugins/sp/skills/spur-dev/references/glossary.md +9 -1
- package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +51 -16
- package/plugins/sp/skills/spur-dev/references/planning-workflow.md +5 -0
- package/plugins/sp/skills/wayfinder/SKILL.md +1 -1
- package/spur.js +23422 -19364
- package/web/_astro/BoardApp.CerSBgis.js +192 -0
- package/web/_astro/BoardApp.eoTz0pZs.js +1 -0
- package/web/_astro/{TaskDetail.DwTmbQp5.js → TaskDetail.DCqiC-OZ.js} +1 -1
- package/web/_astro/arc.CPwg6Rw0.js +1 -0
- package/web/_astro/{architectureDiagram-3BPJPVTR.jvdDahWM.js → architectureDiagram-3BPJPVTR.DM_vp_hO.js} +1 -1
- package/web/_astro/{blockDiagram-GPEHLZMM.zSg4AmFD.js → blockDiagram-GPEHLZMM.DXVIiv0p.js} +1 -1
- package/web/_astro/{c4Diagram-AAUBKEIU.BkUIUQWH.js → c4Diagram-AAUBKEIU.BbF_zCxW.js} +1 -1
- package/web/_astro/channel.MYZLKNwy.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.DvfQ_f50.js → chunk-2J33WTMH.CAgQHpPC.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.DuI4gQqX.js → chunk-4BX2VUAB.BN-5tpw4.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.D3BWBOpF.js → chunk-55IACEB6.CnPkEEr0.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.3QSi0a9M.js → chunk-727SXJPM.BQzQeMVm.js} +4 -4
- package/web/_astro/{chunk-AQP2D5EJ.xazCQrAF.js → chunk-AQP2D5EJ.B6xNyDnL.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.B2g6u4rA.js → chunk-FMBD7UC4.C7f9Ih78.js} +1 -1
- package/web/_astro/{chunk-ND2GUHAM.wWwWs99t.js → chunk-ND2GUHAM.CNV1dFXT.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.BD5g3qa9.js → chunk-QZHKN3VN.Cudn2TkJ.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.C7CzCdsX.js → classDiagram-4FO5ZUOK.D1NwP50q.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.C7CzCdsX.js → classDiagram-v2-Q7XG4LA2.D1NwP50q.js} +1 -1
- package/web/_astro/{cose-bilkent-S5V4N54A.Xyiau0gw.js → cose-bilkent-S5V4N54A.B1wSL-Xb.js} +1 -1
- package/web/_astro/{cynefin-OW5HDTMX.BeC5MWas.js → cynefin-OW5HDTMX.BmK52w8G.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.yZbMN9vc.js → dagre-BM42HDAG.Bfy5CTDT.js} +2 -2
- package/web/_astro/diagram-2AECGRRQ.DhNnvUvX.js +43 -0
- package/web/_astro/diagram-5GNKFQAL.lTX5KwnS.js +10 -0
- package/web/_astro/{diagram-KO2AKTUF.CR6k3Y3G.js → diagram-KO2AKTUF.CW_vMJ4z.js} +3 -3
- package/web/_astro/{diagram-LMA3HP47.x7mwu8jz.js → diagram-LMA3HP47.B_8ZGF67.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.D8aTTvUr.js → diagram-OG6HWLK6.BppnHsdS.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.BoBqcKXQ.js → erDiagram-TEJ5UH35.BEuHXcjJ.js} +5 -5
- package/web/_astro/{flowDiagram-I6XJVG4X.D3mTQdrU.js → flowDiagram-I6XJVG4X.CH-UlnGr.js} +4 -4
- package/web/_astro/{ganttDiagram-6RSMTGT7.H-cqgIh-.js → ganttDiagram-6RSMTGT7.BO81S85v.js} +1 -1
- package/web/_astro/{gitGraphDiagram-PVQCEYII.B6s9zbfC.js → gitGraphDiagram-PVQCEYII.XnPxPPZN.js} +1 -1
- package/web/_astro/index.Hjbr15fG.css +1 -0
- package/web/_astro/{infoDiagram-5YYISTIA.BzgCoV6P.js → infoDiagram-5YYISTIA.JyjYRu_T.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.BZzVhy1-.js → ishikawaDiagram-YF4QCWOH.BBRBF-Fo.js} +5 -5
- package/web/_astro/{journeyDiagram-JHISSGLW.BV3195Py.js → journeyDiagram-JHISSGLW.C_iymSyp.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.BjRd2DWz.js → kanban-definition-UN3LZRKU.DdfW-Oqt.js} +7 -7
- package/web/_astro/{linear.BILTgS5N.js → linear.C2_IkbZT.js} +1 -1
- package/web/_astro/mermaid.core.GAOYeSR0.js +303 -0
- package/web/_astro/{mindmap-definition-RKZ34NQL.BiEjaI4-.js → mindmap-definition-RKZ34NQL.DAZIxQSK.js} +2 -2
- package/web/_astro/{pieDiagram-4H26LBE5.i_8V5pIn.js → pieDiagram-4H26LBE5.CN8sIhKM.js} +3 -3
- package/web/_astro/{quadrantDiagram-W4KKPZXB.BWaW3MHn.js → quadrantDiagram-W4KKPZXB.3dGcX5GP.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.CzddBbtg.js → requirementDiagram-4Y6WPE33.BV2y4dd6.js} +3 -3
- package/web/_astro/{sankeyDiagram-5OEKKPKP.X2ww0e-D.js → sankeyDiagram-5OEKKPKP.Cqo15Tvo.js} +4 -4
- package/web/_astro/{sequenceDiagram-3UESZ5HK.DSA4kTcc.js → sequenceDiagram-3UESZ5HK.CROCPMJB.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.D0DtFSpR.js → stateDiagram-AJRCARHV.RfXZrkFE.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.BfQq0zQv.js → stateDiagram-v2-BHNVJYJU.CPXmbBs9.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.Dmlrgi1m.js → timeline-definition-PNZ67QCA.DdgKTiO8.js} +3 -3
- package/web/_astro/{vennDiagram-CIIHVFJN.D5mpl00Z.js → vennDiagram-CIIHVFJN.CPNVSHF1.js} +5 -5
- package/web/_astro/{wardleyDiagram-YWT4CUSO.Df4BdzO4.js → wardleyDiagram-YWT4CUSO.CQhA0Jyr.js} +3 -3
- package/web/_astro/{xychartDiagram-2RQKCTM6.DiTRreKN.js → xychartDiagram-2RQKCTM6.n61BWyy4.js} +1 -1
- package/web/index.html +2 -2
- package/web/_astro/BoardApp.CDUcHlTJ.js +0 -188
- package/web/_astro/BoardApp.CaCGU_uX.js +0 -1
- package/web/_astro/arc.BzF71EFI.js +0 -1
- package/web/_astro/channel.SSVY0JPQ.js +0 -1
- package/web/_astro/diagram-2AECGRRQ.Cmo2zQM-.js +0 -43
- package/web/_astro/diagram-5GNKFQAL.D033eSVi.js +0 -10
- package/web/_astro/index.CcU5weKX.css +0 -1
- package/web/_astro/mermaid.core.DBy_WKeW.js +0 -301
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"decision": null
|
|
37
37
|
},
|
|
38
38
|
"history-anatomy": {
|
|
39
|
-
"modelQueries":
|
|
39
|
+
"modelQueries": 3,
|
|
40
40
|
"wallClockMs": null,
|
|
41
41
|
"tokenCostUsd": null,
|
|
42
|
-
"source": "Coverage entry (0826 R2): the live definition's model-query count (extractResolvedWorkflowFacts, 2026-09-11). No real-run measurement yet: wall-clock and cost are unenforced until measured, never 0.",
|
|
42
|
+
"source": "Coverage entry (0826 R2): the live definition's model-query count (extractResolvedWorkflowFacts, 2026-09-11). No real-run measurement yet: wall-clock and cost are unenforced until measured, never 0. 0920 recount 2026-09-23: 4 -> 3 — the resolve-scope model hop was removed; scope/window validation is deterministic in the history-anatomy-cache paths command.",
|
|
43
43
|
"decision": null
|
|
44
44
|
},
|
|
45
45
|
"wayfinder-resolution": {
|
|
@@ -48,6 +48,13 @@
|
|
|
48
48
|
"tokenCostUsd": null,
|
|
49
49
|
"source": "Coverage entry (0826 R2): the live definition's model-query count (extractResolvedWorkflowFacts, 2026-09-11). No real-run measurement yet: wall-clock and cost are unenforced until measured, never 0.",
|
|
50
50
|
"decision": null
|
|
51
|
+
},
|
|
52
|
+
"decision-routing-example": {
|
|
53
|
+
"modelQueries": 0,
|
|
54
|
+
"wallClockMs": null,
|
|
55
|
+
"tokenCostUsd": null,
|
|
56
|
+
"source": "Coverage entry (0911): authoring example (config/workflows/decision-routing-example.yaml) enumerating `decision:` modes. Measured 0 model queries — the producer is a shell action, so the example runs with no provider (live count via loadQueryCounts, 2026-09-20). Not a pipeline humans run; wall-clock and cost unenforced, never 0.",
|
|
57
|
+
"decision": null
|
|
51
58
|
}
|
|
52
59
|
}
|
|
53
60
|
}
|
|
@@ -48,7 +48,13 @@
|
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
"rel": "inline-run-setup.ts",
|
|
51
|
-
"contract": "
|
|
51
|
+
"contract": "standard",
|
|
52
|
+
"twin": "inline-run-setup.mjs"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"rel": "feature-verification-steps.ts",
|
|
56
|
+
"contract": "standard",
|
|
57
|
+
"twin": "feature-verification-steps.mjs"
|
|
52
58
|
},
|
|
53
59
|
{
|
|
54
60
|
"rel": "idea-coverage-check.ts",
|
|
@@ -63,11 +69,21 @@
|
|
|
63
69
|
"contract": "standard",
|
|
64
70
|
"twin": "pr-reviewing.mjs"
|
|
65
71
|
},
|
|
72
|
+
{
|
|
73
|
+
"rel": "record-feature-sync.ts",
|
|
74
|
+
"contract": "standard",
|
|
75
|
+
"twin": "record-feature-sync.mjs"
|
|
76
|
+
},
|
|
66
77
|
{
|
|
67
78
|
"rel": "quality-gate.ts",
|
|
68
79
|
"contract": "standard",
|
|
69
80
|
"twin": "quality-gate.mjs"
|
|
70
81
|
},
|
|
82
|
+
{
|
|
83
|
+
"rel": "residual-scan.ts",
|
|
84
|
+
"contract": "standard",
|
|
85
|
+
"twin": "residual-scan.mjs"
|
|
86
|
+
},
|
|
71
87
|
{
|
|
72
88
|
"rel": "script-contract-check.ts",
|
|
73
89
|
"contract": "repo-only"
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# DecisionMaker routing example (task 0911, D7). Demonstrates the three `decision:` modes
|
|
2
|
+
# on hitl.* actions; copy the pattern into your own workflow instead of running this file.
|
|
3
|
+
#
|
|
4
|
+
# never — the action always asks the human (DecisionMaker is bypassed even when
|
|
5
|
+
# `workflow.hitlDecisionMaker: true`). Used for gates that must stay human-only.
|
|
6
|
+
# evidence — the DecisionMaker answers from recorded action evidence of the listed producer
|
|
7
|
+
# states: it picks one of the offered choices when confidence >= 0.9, or defers
|
|
8
|
+
# (answer var is cleared, status var records `deferred`) when evidence is missing,
|
|
9
|
+
# stale, or inconclusive. Requires a non-paused state, a statusVar distinct from
|
|
10
|
+
# the answer var, and producer states that exist in this workflow.
|
|
11
|
+
# (omitted) — legacy 0910 semantics: DecisionMaker may confirm/select without evidence and
|
|
12
|
+
# without provenance. Kept for compatibility; prefer an explicit mode.
|
|
13
|
+
#
|
|
14
|
+
# The run is safe and local: one shell producer emits a fixed failure summary, the choose step
|
|
15
|
+
# reads it as evidence, and the operator gate has no side effects. No provider is required —
|
|
16
|
+
# without `workflow.hitlDecisionMaker: true` (or without a key) the evidence step defers and
|
|
17
|
+
# `never` behaves exactly like an unconfigured gate. See `spur self status` -> `decisionMaker`
|
|
18
|
+
# for offline readiness. Optional registered-summary evidence (`summaryArtifact`) is documented
|
|
19
|
+
# in docs/help/how_to_enable_jev_in_spur.md; this example deliberately creates no artifact.
|
|
20
|
+
"$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
|
|
21
|
+
kind: state-machine
|
|
22
|
+
name: decision-routing-example
|
|
23
|
+
version: "1"
|
|
24
|
+
initialState: assess
|
|
25
|
+
description: >
|
|
26
|
+
Worked example of DecisionMaker decision routing (0911 D7): a shell producer records a fixed
|
|
27
|
+
recovery summary as action evidence, a non-pausing hitl.select lets the DecisionMaker choose
|
|
28
|
+
retry or stop from that evidence (deferring with provenance when it is inconclusive), an
|
|
29
|
+
accepted retry runs exactly one attempt and then escalates, and the never-mode pause=true
|
|
30
|
+
hitl.confirm gate always waits for the operator with explicit yes/no/cancel branches.
|
|
31
|
+
Illustrative only — copy the patterns rather than running this file.
|
|
32
|
+
vars:
|
|
33
|
+
recoveryChoice: ""
|
|
34
|
+
decisionStatus: ""
|
|
35
|
+
# Default answer var the never-mode gate's yes/no/cancel branches read (matches the stock gates).
|
|
36
|
+
__hitlAnswer: ""
|
|
37
|
+
states:
|
|
38
|
+
- id: assess
|
|
39
|
+
description: >
|
|
40
|
+
Producer state: one shell action whose redacted output becomes the evidence the decide
|
|
41
|
+
state's DecisionMaker reads. One producer state carries one evidence-bearing action.
|
|
42
|
+
onEnter:
|
|
43
|
+
- kind: shell
|
|
44
|
+
options:
|
|
45
|
+
command: >-
|
|
46
|
+
printf 'Failure summary: verification failed twice on the flaky fixture; no data loss;
|
|
47
|
+
retry is safe, or stop and hand the decision to the operator.'
|
|
48
|
+
- id: decide
|
|
49
|
+
description: >
|
|
50
|
+
Evidence-mode select (non-paused): DecisionMaker picks a recovery step from the assess
|
|
51
|
+
state's recorded evidence. Low confidence, missing or stale evidence defers and writes the
|
|
52
|
+
status variable instead of answering, so no implicit approval is ever produced.
|
|
53
|
+
onEnter:
|
|
54
|
+
- kind: hitl.select
|
|
55
|
+
options:
|
|
56
|
+
prompt: "Choose the next safe recovery step using the recorded failure summary."
|
|
57
|
+
options: [retry, stop]
|
|
58
|
+
var: recoveryChoice
|
|
59
|
+
decision:
|
|
60
|
+
mode: evidence
|
|
61
|
+
statusVar: decisionStatus
|
|
62
|
+
evidenceNodes: [assess]
|
|
63
|
+
- id: retry
|
|
64
|
+
description: >
|
|
65
|
+
The single bounded retry an accepted `retry` choice buys: this state runs once and routes
|
|
66
|
+
to the operator gate, so an accepted answer can never loop back into the decision.
|
|
67
|
+
onEnter:
|
|
68
|
+
- kind: shell
|
|
69
|
+
options:
|
|
70
|
+
command: "printf 'retry attempt: re-running the failed verification step once'"
|
|
71
|
+
- id: humanGate
|
|
72
|
+
description: >
|
|
73
|
+
Never-mode confirm (paused): always waits for the operator, whichever branch reached it.
|
|
74
|
+
`spur workflow continue --answer yes|no|cancel` records the explicit operator answer.
|
|
75
|
+
pause: true
|
|
76
|
+
onEnter:
|
|
77
|
+
- kind: hitl.confirm
|
|
78
|
+
options:
|
|
79
|
+
prompt: "Publish the recovered result, stop, or cancel the run?"
|
|
80
|
+
decision:
|
|
81
|
+
mode: never
|
|
82
|
+
- id: published
|
|
83
|
+
description: Operator approved the recovered result; terminal marker state.
|
|
84
|
+
- id: stop
|
|
85
|
+
description: Recovery stopped deliberately — requested by the decision or rejected by the operator.
|
|
86
|
+
- id: cancelled
|
|
87
|
+
description: Operator cancelled the run at the gate; terminal marker state.
|
|
88
|
+
transitions:
|
|
89
|
+
# Accepted decision branches first: the state machine takes the first passing edge.
|
|
90
|
+
- from: assess
|
|
91
|
+
to: decide
|
|
92
|
+
guard: { kind: always }
|
|
93
|
+
- from: decide
|
|
94
|
+
to: retry
|
|
95
|
+
guard:
|
|
96
|
+
kind: shell
|
|
97
|
+
options:
|
|
98
|
+
command: 'test "$recoveryChoice" = "retry"'
|
|
99
|
+
- from: decide
|
|
100
|
+
to: stop
|
|
101
|
+
guard:
|
|
102
|
+
kind: shell
|
|
103
|
+
options:
|
|
104
|
+
command: 'test "$recoveryChoice" = "stop"'
|
|
105
|
+
# Declared defer edge: evidence mode wrote `deferred` and cleared the answer var.
|
|
106
|
+
- from: decide
|
|
107
|
+
to: humanGate
|
|
108
|
+
guard:
|
|
109
|
+
kind: shell
|
|
110
|
+
options:
|
|
111
|
+
command: 'test "$decisionStatus" = "deferred"'
|
|
112
|
+
- from: retry
|
|
113
|
+
to: humanGate
|
|
114
|
+
guard: { kind: always }
|
|
115
|
+
# Explicit yes / no / cancel branches on the default answer var, matching the stock gates.
|
|
116
|
+
- from: humanGate
|
|
117
|
+
to: published
|
|
118
|
+
guard:
|
|
119
|
+
kind: shell
|
|
120
|
+
options:
|
|
121
|
+
command: 'test "$__hitlAnswer" = "yes"'
|
|
122
|
+
- from: humanGate
|
|
123
|
+
to: stop
|
|
124
|
+
guard:
|
|
125
|
+
kind: shell
|
|
126
|
+
options:
|
|
127
|
+
command: 'test "$__hitlAnswer" = "no"'
|
|
128
|
+
- from: humanGate
|
|
129
|
+
to: cancelled
|
|
130
|
+
guard:
|
|
131
|
+
kind: shell
|
|
132
|
+
options:
|
|
133
|
+
command: 'test "$__hitlAnswer" = "cancel"'
|
|
134
|
+
terminalStates: [published, stop, cancelled]
|
|
@@ -40,9 +40,17 @@ states:
|
|
|
40
40
|
onEnter:
|
|
41
41
|
# Caller wiring (task 0880, ADR-119): entering verification RUNS the
|
|
42
42
|
# feature-scoped pass instead of only passively reading its status file.
|
|
43
|
+
# 0948 R1: pass BOTH vars the inner workflow needs. `--vars` was documented as
|
|
44
|
+
# replace-not-merge and a partial override silently blanked `spurBin`; the engine
|
|
45
|
+
# merges declared defaults today (0948 R2), but the caller stays explicit so the
|
|
46
|
+
# nested run is self-sufficient under either semantic.
|
|
43
47
|
- kind: shell
|
|
44
48
|
options:
|
|
45
|
-
|
|
49
|
+
# Pass featureId and spurBin together. A partial --vars map used to be
|
|
50
|
+
# applied as a replacement, so the inner run lost spurBin and loadModule
|
|
51
|
+
# fell into source mode (0948 R1). The nested JSON is shell-expanded:
|
|
52
|
+
# $spurBin inside the double quotes keeps a multi-word invocation intact.
|
|
53
|
+
command: '$spurBin workflow run feature-verification.yaml --vars "{\"featureId\":\"$featureId\",\"spurBin\":\"$spurBin\"}"'
|
|
46
54
|
- id: blocked
|
|
47
55
|
description: Impediment; work suspended.
|
|
48
56
|
- id: done
|
|
@@ -68,13 +76,14 @@ transitions:
|
|
|
68
76
|
- from: verifying
|
|
69
77
|
to: done
|
|
70
78
|
description: >
|
|
71
|
-
Feature verified — complete.
|
|
72
|
-
|
|
73
|
-
|
|
79
|
+
Feature verified — complete. The strict check at the done boundary also
|
|
80
|
+
validates the bound verification receipt (D63 task 0915): current, PASS,
|
|
81
|
+
matching feature identity and verifier contract, digest-chained to the
|
|
82
|
+
checked inputs. Stale/missing/failed evidence denies the hop.
|
|
74
83
|
guard:
|
|
75
84
|
kind: shell
|
|
76
85
|
options:
|
|
77
|
-
command: '
|
|
86
|
+
command: '$spurBin feature check $featureId --strict --as done'
|
|
78
87
|
|
|
79
88
|
# Rework: verifying → active (mandatory History entry)
|
|
80
89
|
- from: verifying
|
|
@@ -1,29 +1,34 @@
|
|
|
1
|
-
# Feature-scoped verification pass (ADR-119, feature D62, task 0872
|
|
1
|
+
# Feature-scoped verification pass (ADR-119, feature D62, task 0872; D63 task
|
|
2
|
+
# 0915 remediation folds the evidence contract into a workflow-owned script).
|
|
2
3
|
#
|
|
3
4
|
# Owns a lifecycle boundary no per-task graph owns: the repo-wide checks whose
|
|
4
|
-
# invariant spans the repository rather than a single task's diff
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
# feature until this pass records PASS (ADR-119 consequence: a feature is not
|
|
10
|
-
# done until it passes).
|
|
5
|
+
# invariant spans the repository rather than a single task's diff. They run
|
|
6
|
+
# once per feature, deliberately the slow pass; `feature-lifecycle`'s verifying
|
|
7
|
+
# entry invokes this workflow (task 0880 caller wiring), and its verifying→done
|
|
8
|
+
# guard refuses to complete the feature until this pass records PASS (ADR-119
|
|
9
|
+
# consequence: a feature is not done until it passes).
|
|
11
10
|
#
|
|
12
|
-
# Run: spur workflow run feature-verification.yaml --vars '{"featureId":"
|
|
11
|
+
# Run: spur workflow run feature-verification.yaml --vars '{"featureId":"D63"}'
|
|
13
12
|
#
|
|
14
|
-
# Shape: verify -> done | failed. The
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
13
|
+
# Shape: verify -> done | failed. The onEnter step runs the standard script
|
|
14
|
+
# `feature-verification-steps.ts` (no public CLI verb, D63 task 0915): it
|
|
15
|
+
# resolves this very definition for the verifier identity (name, source path,
|
|
16
|
+
# layer, definition digest), records the RUNNING receipt (run-scoped +
|
|
17
|
+
# feature-latest copies), registers the run-scoped receipt as a run artifact,
|
|
18
|
+
# runs the configured verification command via the safe launch splitter, and
|
|
19
|
+
# completes the receipt PASS/FAIL with the after-pass proof-input digest. A
|
|
20
|
+
# changed tree during the pass records FAIL.
|
|
18
21
|
#
|
|
19
22
|
# Reliability (aligned with task-pipeline / ADR-043): no agent.run nodes; the
|
|
20
|
-
# verification command
|
|
21
|
-
#
|
|
23
|
+
# verification command comes from `vars.verificationCmd` below and is never
|
|
24
|
+
# interpolated through a shell. The always-exit-0 onEnter means missing,
|
|
25
|
+
# corrupt or FAIL evidence routes to `failed` via the guard (fail-closed),
|
|
26
|
+
# never a silent PASS; infrastructure errors exit nonzero and surface.
|
|
22
27
|
"$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
|
|
23
28
|
kind: state-machine
|
|
24
29
|
name: feature-verification
|
|
25
30
|
version: "1"
|
|
26
|
-
description: "Feature-scoped verification pass (ADR-119): runs the repo-wide check set once per feature and records PASS/FAIL. Invoked by feature-lifecycle's verifying entry."
|
|
31
|
+
description: "Feature-scoped verification pass (ADR-119): runs the repo-wide check set once per feature and records a bound PASS/FAIL evidence receipt. Invoked by feature-lifecycle's verifying entry."
|
|
27
32
|
iterationBound: 2
|
|
28
33
|
initialState: verify
|
|
29
34
|
terminalStates:
|
|
@@ -35,37 +40,40 @@ vars:
|
|
|
35
40
|
featureId: "X"
|
|
36
41
|
spurBin: "spur"
|
|
37
42
|
verificationCmd: "bun run spur-check-feature"
|
|
43
|
+
__runId: ""
|
|
38
44
|
|
|
39
45
|
states:
|
|
40
46
|
- id: verify
|
|
41
47
|
description: >
|
|
42
|
-
Run the repo-wide check set
|
|
48
|
+
Run the repo-wide check set via the standard verification script, which
|
|
49
|
+
records the bound evidence receipt (verifier identity, checked-input
|
|
50
|
+
digest, run identity) and the coarse status file, always exit 0 so the
|
|
51
|
+
transition guard routes missing/corrupt/FAIL to `failed`.
|
|
43
52
|
onEnter:
|
|
44
53
|
- kind: shell
|
|
45
54
|
options:
|
|
46
55
|
command: >-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
exit 0
|
|
56
|
+
bun plugins/sp/scripts/feature-verification-steps.ts verify
|
|
57
|
+
--feature-id "$featureId"
|
|
58
|
+
--run-id "$__runId"
|
|
59
|
+
--spur-bin "$spurBin"
|
|
52
60
|
|
|
53
61
|
- id: done
|
|
54
|
-
description: Terminal — repo-wide checks passed.
|
|
62
|
+
description: Terminal — repo-wide checks passed and the receipt is bound.
|
|
55
63
|
|
|
56
64
|
- id: failed
|
|
57
|
-
description: Terminal — repo-wide checks failed or the
|
|
65
|
+
description: Terminal — repo-wide checks failed or the evidence is missing/corrupt.
|
|
58
66
|
|
|
59
67
|
transitions:
|
|
60
68
|
- from: verify
|
|
61
69
|
to: done
|
|
62
|
-
description: Repo-wide checks passed — the
|
|
70
|
+
description: Repo-wide checks passed — the script completed the receipt with PASS.
|
|
63
71
|
guard:
|
|
64
72
|
kind: shell
|
|
65
73
|
options:
|
|
66
|
-
command: 'test "$(cat .spur/run/$
|
|
74
|
+
command: 'test "$(cat .spur/run/$__runId-feature-verification.status 2>/dev/null)" = PASS'
|
|
67
75
|
- from: verify
|
|
68
76
|
to: failed
|
|
69
|
-
description: Repo-wide checks failed (or the
|
|
77
|
+
description: Repo-wide checks failed (or the evidence is missing/corrupt) — stop at failed.
|
|
70
78
|
guard:
|
|
71
79
|
kind: always
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
# would exceed the shell composition threshold and be flagged as an owned-capability candidate.
|
|
12
12
|
#
|
|
13
13
|
# Shape:
|
|
14
|
-
# start -> resolve-
|
|
14
|
+
# start -> resolve-paths -> analyze -> cache-probe
|
|
15
15
|
# (hit -> refresh-provenance -> publish -> published)
|
|
16
16
|
# (miss -> render -> enrich -> structure-gate -> validate -> stamp -> publish)
|
|
17
17
|
# (structure-gate FAIL -> correct (max 2 total) -> structure-gate; exhausted -> failed)
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
#
|
|
29
29
|
# Vars (all must be declared here — the vars: block is the only safe shape; `spur workflow
|
|
30
30
|
# validate` and the skill-structure test enforce it):
|
|
31
|
-
# mode — "daily" (default) | "ad-hoc" (validated
|
|
31
|
+
# mode — "daily" (default) | "ad-hoc" (validated deterministically by the helper `paths` command)
|
|
32
32
|
# date — YYYY-MM-DD for --date (daily); empty for ad-hoc
|
|
33
33
|
# since — inclusive ISO lower bound (ad-hoc; also normalizes daily via the DST-aware rule)
|
|
34
34
|
# until — inclusive ISO upper bound (ad-hoc)
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
# focus — ad-hoc focus string (required in ad-hoc mode, rejected in daily)
|
|
40
40
|
# recompute — "true" forces the full analyze/render/enrich/validate path (cache disposition
|
|
41
41
|
# forced-recompute)
|
|
42
|
-
# output — explicit report output path; default
|
|
42
|
+
# output — explicit report output path; default docs/report/<date>-history-anatomy.md
|
|
43
43
|
# agent — executor for the agent.run stages (enrich/validate)
|
|
44
44
|
# spurBin — PATH-independent spur invocation (overridden by CLI at run start)
|
|
45
45
|
# __runId — run-scoped id for explicit artifact paths (allocated in start)
|
|
@@ -85,28 +85,22 @@ states:
|
|
|
85
85
|
description: >
|
|
86
86
|
Allocate the run-scoped id and root. Every analyze/render path in this workflow writes to
|
|
87
87
|
an explicit unique path under this run id — no stage reads the mutable latest.json pointer.
|
|
88
|
+
The retained identity is `.spur/run/<runId>-history-anatomy-run.id` (0948 R8). The fixed
|
|
89
|
+
`history-anatomy-run.id` name is only a latest pointer and is overwritten by the next run.
|
|
88
90
|
onEnter:
|
|
89
91
|
- kind: shell
|
|
90
92
|
options:
|
|
91
93
|
command: >-
|
|
92
94
|
mkdir -p .spur/run;
|
|
93
95
|
if [ -z "$__runId" ]; then __runId=$(uuidgen | tr 'A-Z' 'a-z' | cut -c1-8); fi;
|
|
94
|
-
echo "$__runId" > .spur/run
|
|
96
|
+
echo "$__runId" > ".spur/run/$__runId-history-anatomy-run.id";
|
|
97
|
+
cp ".spur/run/$__runId-history-anatomy-run.id" .spur/run/history-anatomy-run.id
|
|
98
|
+
# 0948 R8 retention disposition: `history-anatomy-run.id` is a SINGLE fixed-name
|
|
99
|
+
# pointer that is overwritten every run — it does not accumulate, so it needs no
|
|
100
|
+
# reclamation path (unlike the run-record pair and legacy `.log` files, which
|
|
101
|
+
# `spur workflow clean --logs` owns). It is deliberately NOT a run record and is
|
|
102
|
+
# exempt from the catalog record-name sweep (see run-record-catalog.test.ts).
|
|
95
103
|
|
|
96
|
-
- id: resolve-scope
|
|
97
|
-
description: >
|
|
98
|
-
Dispatch the skill's mode validation (0658 references/modes.md): daily is the default and
|
|
99
|
-
rejects focus/since/until/output; ad-hoc requires a non-empty focus plus two ordered
|
|
100
|
-
inclusive bounds and rejects --date/--recompute. Writes the normalized selector artifact.
|
|
101
|
-
onEnter:
|
|
102
|
-
- kind: agent.run
|
|
103
|
-
options:
|
|
104
|
-
agent: ${vars.agent}
|
|
105
|
-
input: "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."
|
|
106
|
-
# Declared Layer-1 role (0538 R2): mode validation is a reviewer-standard judgment.
|
|
107
|
-
role: reviewer
|
|
108
|
-
expectFile: .spur/run/${vars.__runId}-selector.json
|
|
109
|
-
timeoutMs: ${vars.stepTimeoutMs}
|
|
110
104
|
|
|
111
105
|
- id: resolve-paths
|
|
112
106
|
description: >
|
|
@@ -122,6 +116,7 @@ states:
|
|
|
122
116
|
h=$(superskill script path sp history-anatomy-cache.mjs);
|
|
123
117
|
node "$h" paths --helper "$h" --report-dir "$reportDir" --date "$date"
|
|
124
118
|
--output "$output" --mode "$mode" --since "$since" --until "$until"
|
|
119
|
+
--focus "$focus" --recompute "$recompute" --run-id "$__runId"
|
|
125
120
|
--out .spur/run/$__runId-paths.txt
|
|
126
121
|
|
|
127
122
|
- id: analyze
|
|
@@ -338,14 +333,8 @@ states:
|
|
|
338
333
|
|
|
339
334
|
transitions:
|
|
340
335
|
- from: start
|
|
341
|
-
to: resolve-scope
|
|
342
|
-
description: Scope resolved.
|
|
343
|
-
guard:
|
|
344
|
-
kind: always
|
|
345
|
-
|
|
346
|
-
- from: resolve-scope
|
|
347
336
|
to: resolve-paths
|
|
348
|
-
description: Mode
|
|
337
|
+
description: Mode/window grammar validated and paths resolved once (deterministic).
|
|
349
338
|
guard:
|
|
350
339
|
kind: always
|
|
351
340
|
|
|
@@ -145,6 +145,8 @@ states:
|
|
|
145
145
|
- kind: hitl.confirm
|
|
146
146
|
options:
|
|
147
147
|
prompt: "Review the idea evaluation report (.spur/run/${vars.__runId}-idea-eval-report.md). Approve to create a feature, or reject to cancel? (Reject creates no feature.)"
|
|
148
|
+
decision:
|
|
149
|
+
mode: never
|
|
148
150
|
|
|
149
151
|
- id: feature-create
|
|
150
152
|
description: >
|
|
@@ -282,6 +284,8 @@ states:
|
|
|
282
284
|
- kind: hitl.confirm
|
|
283
285
|
options:
|
|
284
286
|
prompt: "Feature check for ${vars.featureId}. Review the AC and confirm to proceed? Requirement coverage status: $(cat .spur/run/${vars.__runId}-idea-coverage.status 2>/dev/null || echo unknown) — reason: $(cat .spur/run/${vars.__runId}-idea-coverage.reason 2>/dev/null || echo n/a) (.spur/run/${vars.__runId}-idea-coverage.status[.reason]). (Failures route back to ac-generate for revision, capped at 3 retries.)"
|
|
287
|
+
decision:
|
|
288
|
+
mode: never
|
|
285
289
|
|
|
286
290
|
- id: system-design
|
|
287
291
|
description: >
|
|
@@ -358,6 +362,8 @@ states:
|
|
|
358
362
|
- kind: hitl.confirm
|
|
359
363
|
options:
|
|
360
364
|
prompt: "Review the system design for feature ${vars.featureId}. Approve to proceed to decomposition? To reject, first record your feedback in .spur/run/${vars.__runId}-idea-design-review.md under the `## Operator feedback` heading, then answer no."
|
|
365
|
+
decision:
|
|
366
|
+
mode: never
|
|
361
367
|
|
|
362
368
|
- id: decompose
|
|
363
369
|
description: >
|
|
@@ -416,6 +422,8 @@ states:
|
|
|
416
422
|
- kind: hitl.confirm
|
|
417
423
|
options:
|
|
418
424
|
prompt: "Batch-create for feature ${vars.featureId}. Review the task batch and confirm to proceed? (Failures route back to decompose for revision, capped at 3 retries.)"
|
|
425
|
+
decision:
|
|
426
|
+
mode: never
|
|
419
427
|
|
|
420
428
|
- id: batch-create-run
|
|
421
429
|
description: >
|
|
@@ -453,10 +461,12 @@ states:
|
|
|
453
461
|
plan, ac, decisions, dependencies, premises) so the deterministic task
|
|
454
462
|
check passes, then writes the run-scoped ready evidence sidecar
|
|
455
463
|
(.spur/run/${vars.__runId}-idea-ready.json) with one row per task: wbs,
|
|
456
|
-
status (ready|failed|skipped), planningDigest, and seven check rows
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
464
|
+
status (ready|failed|skipped), planningDigest, and seven check rows,
|
|
465
|
+
with the premises row carrying tree-verified path:line citations
|
|
466
|
+
(0947). Handoff-finalize verifies presence, digest, feature binding and
|
|
467
|
+
checklist evidence before recommending auto runall; missing or failing
|
|
468
|
+
evidence never fails the run — it degrades the recommendation to
|
|
469
|
+
ready-depth refineall.
|
|
460
470
|
onEnter:
|
|
461
471
|
- kind: agent.run
|
|
462
472
|
options:
|
|
@@ -475,7 +485,9 @@ states:
|
|
|
475
485
|
for feature ${vars.featureId} per sp:spur-dev
|
|
476
486
|
references/planning-workflow.md § Step 5.6 (Ready preparation): read
|
|
477
487
|
.spur/run/${vars.__runId}-idea-batch-create-result.json and write
|
|
478
|
-
.spur/run/${vars.__runId}-idea-ready.json.
|
|
488
|
+
.spur/run/${vars.__runId}-idea-ready.json. The premises check row passes only
|
|
489
|
+
when each material premise was verified against the current tree and its evidence
|
|
490
|
+
cites at least one verified path:line (handoff-finalize lints it; task 0947).
|
|
479
491
|
answerFile: .spur/run/${vars.__runId}-ready-prepare-answer.txt
|
|
480
492
|
expectFile: .spur/run/${vars.__runId}-ready-prepare-answer.txt
|
|
481
493
|
# Fail-closed shape validation (mirrors the order-sidecar guard). Absence is
|