@gobing-ai/spur 0.3.30 → 0.3.32

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.
Files changed (68) hide show
  1. package/config/rules/strict/runtime-boundaries.yaml +2 -1
  2. package/config/workflows/basic.yaml +92 -14
  3. package/config/workflows/docs-pipeline.yaml +71 -25
  4. package/config/workflows/feature-dev.yaml +104 -35
  5. package/config/workflows/feature-lifecycle.yaml +10 -2
  6. package/config/workflows/idea-pipeline.yaml +118 -54
  7. package/config/workflows/planning-pipeline.yaml +78 -30
  8. package/config/workflows/task-lifecycle.yaml +10 -2
  9. package/config/workflows/task-pipeline.yaml +219 -56
  10. package/config/workflows/wayfinder-resolution.yaml +64 -27
  11. package/config/workflows/wrapup-pipeline.yaml +79 -39
  12. package/package.json +9 -9
  13. package/schemas/state-machine-workflow.schema.json +5 -0
  14. package/spur.js +1302 -707
  15. package/web/_astro/BoardApp.CBVEjvSW.js +1 -0
  16. package/web/_astro/{BoardApp.BwAdAgK9.js → BoardApp.CyyIiK76.js} +74 -74
  17. package/web/_astro/TaskDetail.BfUuRsfM.js +1 -0
  18. package/web/_astro/{arc.CO-I_PZe.js → arc.C7fql4LL.js} +1 -1
  19. package/web/_astro/{architectureDiagram-3BPJPVTR.Si-A1Ncl.js → architectureDiagram-3BPJPVTR.IJPsRX-V.js} +1 -1
  20. package/web/_astro/{blockDiagram-GPEHLZMM.CeNy_ta6.js → blockDiagram-GPEHLZMM.B1AUwBxq.js} +1 -1
  21. package/web/_astro/{c4Diagram-AAUBKEIU.BgN_scEU.js → c4Diagram-AAUBKEIU.BuSJPR3z.js} +1 -1
  22. package/web/_astro/channel.D3uZSASb.js +1 -0
  23. package/web/_astro/{chunk-2J33WTMH.C3oDtmdi.js → chunk-2J33WTMH.CaOPTr9l.js} +1 -1
  24. package/web/_astro/{chunk-4BX2VUAB.Bv8Fxh4H.js → chunk-4BX2VUAB.DQzxExn8.js} +1 -1
  25. package/web/_astro/{chunk-55IACEB6.BT-TqtV6.js → chunk-55IACEB6.IIb103c7.js} +1 -1
  26. package/web/_astro/{chunk-727SXJPM.DkGMsI0B.js → chunk-727SXJPM.DOYz1K1b.js} +1 -1
  27. package/web/_astro/{chunk-AQP2D5EJ.B_-SqGnF.js → chunk-AQP2D5EJ.CFcfW-wt.js} +1 -1
  28. package/web/_astro/{chunk-FMBD7UC4.DwR3skMv.js → chunk-FMBD7UC4.C7Hn0jo3.js} +1 -1
  29. package/web/_astro/{chunk-ND2GUHAM.BaTQutFl.js → chunk-ND2GUHAM.Ba83VQ1m.js} +1 -1
  30. package/web/_astro/{chunk-QZHKN3VN.BJMSqqJp.js → chunk-QZHKN3VN.CizNbIIP.js} +1 -1
  31. package/web/_astro/{classDiagram-4FO5ZUOK.SaqCNUPF.js → classDiagram-4FO5ZUOK.2NYYPXHq.js} +1 -1
  32. package/web/_astro/{classDiagram-v2-Q7XG4LA2.SaqCNUPF.js → classDiagram-v2-Q7XG4LA2.2NYYPXHq.js} +1 -1
  33. package/web/_astro/{cose-bilkent-S5V4N54A.BkmjA_E2.js → cose-bilkent-S5V4N54A.DwBqVzml.js} +1 -1
  34. package/web/_astro/{dagre-BM42HDAG.CNUvWhrX.js → dagre-BM42HDAG.DqnYsHWG.js} +1 -1
  35. package/web/_astro/{diagram-2AECGRRQ.C68Cg9uE.js → diagram-2AECGRRQ.D8TKhgy-.js} +1 -1
  36. package/web/_astro/{diagram-5GNKFQAL.DbHkPLEn.js → diagram-5GNKFQAL.BUD6Prj5.js} +1 -1
  37. package/web/_astro/{diagram-KO2AKTUF.Dt0EdErs.js → diagram-KO2AKTUF.Cvg7hmND.js} +1 -1
  38. package/web/_astro/{diagram-LMA3HP47.Bixs6mnm.js → diagram-LMA3HP47.FUG_B9eS.js} +1 -1
  39. package/web/_astro/{diagram-OG6HWLK6.B4KBI6KT.js → diagram-OG6HWLK6.XsBZQ0hQ.js} +1 -1
  40. package/web/_astro/{erDiagram-TEJ5UH35.C_4i9Xvx.js → erDiagram-TEJ5UH35.M_LSGgLQ.js} +1 -1
  41. package/web/_astro/{flowDiagram-I6XJVG4X.CfGFczAY.js → flowDiagram-I6XJVG4X.DZikZBRa.js} +1 -1
  42. package/web/_astro/{ganttDiagram-6RSMTGT7.C2AIvtmg.js → ganttDiagram-6RSMTGT7.DTKuEmXY.js} +1 -1
  43. package/web/_astro/{gitGraphDiagram-PVQCEYII.HlXuGqQg.js → gitGraphDiagram-PVQCEYII.Dt-E9XmY.js} +1 -1
  44. package/web/_astro/index.yAse9IaO.css +1 -0
  45. package/web/_astro/{infoDiagram-5YYISTIA.BWQJsJ4Z.js → infoDiagram-5YYISTIA.D5snevU1.js} +1 -1
  46. package/web/_astro/{ishikawaDiagram-YF4QCWOH.CCHgIHik.js → ishikawaDiagram-YF4QCWOH.DmXdBf9W.js} +1 -1
  47. package/web/_astro/{journeyDiagram-JHISSGLW.D9M6YwOJ.js → journeyDiagram-JHISSGLW.HPJSRkkU.js} +1 -1
  48. package/web/_astro/{kanban-definition-UN3LZRKU.K20D-a1_.js → kanban-definition-UN3LZRKU.BxCqCnL1.js} +1 -1
  49. package/web/_astro/{linear.DeP5Qsol.js → linear.BnXQUpS-.js} +1 -1
  50. package/web/_astro/{mermaid.core.ClzxNMPU.js → mermaid.core.D-ZeOmpg.js} +4 -4
  51. package/web/_astro/{mindmap-definition-RKZ34NQL.CGn9RUNj.js → mindmap-definition-RKZ34NQL.DxrftiFR.js} +1 -1
  52. package/web/_astro/{pieDiagram-4H26LBE5.CoA92Csb.js → pieDiagram-4H26LBE5.D-ZcWxwg.js} +1 -1
  53. package/web/_astro/{quadrantDiagram-W4KKPZXB.CJ_UPjM1.js → quadrantDiagram-W4KKPZXB.C-dVJ7GW.js} +1 -1
  54. package/web/_astro/{requirementDiagram-4Y6WPE33.KkEPNNUU.js → requirementDiagram-4Y6WPE33.lalE_R8X.js} +1 -1
  55. package/web/_astro/{sankeyDiagram-5OEKKPKP.CoCWbQgh.js → sankeyDiagram-5OEKKPKP.C4uPynAF.js} +1 -1
  56. package/web/_astro/{sequenceDiagram-3UESZ5HK.DUFpV3EP.js → sequenceDiagram-3UESZ5HK.uBOenkqh.js} +1 -1
  57. package/web/_astro/{stateDiagram-AJRCARHV.CgWX0_9m.js → stateDiagram-AJRCARHV.CQOusSP2.js} +1 -1
  58. package/web/_astro/{stateDiagram-v2-BHNVJYJU.BKUXeGSf.js → stateDiagram-v2-BHNVJYJU.Bw0ZdjYb.js} +1 -1
  59. package/web/_astro/{timeline-definition-PNZ67QCA.CXayAguY.js → timeline-definition-PNZ67QCA.DbkPA5ce.js} +1 -1
  60. package/web/_astro/{vennDiagram-CIIHVFJN.DPak_Elh.js → vennDiagram-CIIHVFJN.CIKhzwoA.js} +1 -1
  61. package/web/_astro/{wardley-L42UT6IY.t3ZlDKd0.js → wardley-L42UT6IY.0P-tqaFs.js} +1 -1
  62. package/web/_astro/{wardleyDiagram-YWT4CUSO.CwPSVASQ.js → wardleyDiagram-YWT4CUSO.DrwTvM_M.js} +1 -1
  63. package/web/_astro/{xychartDiagram-2RQKCTM6.CJfrQgpF.js → xychartDiagram-2RQKCTM6.BgJsQVms.js} +1 -1
  64. package/web/index.html +2 -2
  65. package/web/_astro/BoardApp.Bk3T0o6s.js +0 -1
  66. package/web/_astro/TaskDetail.L36slEqE.js +0 -1
  67. package/web/_astro/channel.CYdGnFHM.js +0 -1
  68. package/web/_astro/index.D5Wqk2Tw.css +0 -1
@@ -23,17 +23,25 @@
23
23
  # design_approved — "true" only when the operator explicitly approved the design in-session;
24
24
  # lets profile=auto route around the design-approval taste gate (default "false")
25
25
  #
26
- # Seeded by `spur init`; adapt the agent.run inputs to your project's command set.
26
+ # Reliability (aligned with task-pipeline / ADR-043):
27
+ # - Soft start precheck (slug non-empty + agent doctor) → failed via transitions
28
+ # - feature-id + design-gen use expectFile so silent no-ops cannot proceed
29
+ # - HITL routing is exhaustive (yes/no/cancel) on phasing and design-approval
30
+ # - Free-form skill pointers remain only where no pure slash surface exists yet
27
31
 
28
32
  "$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
29
33
  kind: state-machine
30
34
  name: planning-pipeline
31
- description: "Front-half planning pipeline (phasing → feature-ID → design-gen → design-approval → handoff)"
35
+ description: "Front-half planning pipeline (start → phasing → feature-ID → design-gen → design-approval → handoff)"
32
36
  iterationBound: 20
33
37
  initialState: start
34
38
  terminalStates:
35
39
  - handoff
36
40
  - cancelled
41
+ - failed
42
+ failureStates:
43
+ - failed
44
+ - cancelled
37
45
  vars:
38
46
  slug: "draft"
39
47
  profile: "interactive"
@@ -42,14 +50,34 @@ vars:
42
50
  __hitlAnswer: ""
43
51
  spurBin: "spur"
44
52
  agent: "omp"
45
- stepTimeoutMs: "600000"
53
+ stepTimeoutMs: "1800000"
54
+ # Injected by WorkflowAppService.run(); scopes .spur/run artifacts per run (0425 R4).
55
+ __runId: ""
46
56
 
47
57
  states:
48
58
  - id: start
49
59
  description: >
50
- Entry pass-through. Routes to the phasing HITL gate (interactive) or straight to
51
- feature-id (profile=auto), so the phasing onEnter hitl.confirm only fires when a
52
- human is in the loop. No actions a pure routing node.
60
+ Soft precheck + routing node. Validates slug and agent doctor (status file,
61
+ always exit 0), then routes to the phasing HITL gate (interactive) or straight
62
+ to feature-id (profile=auto) so hitl.confirm only fires when a human is in loop.
63
+ onEnter:
64
+ - kind: shell
65
+ options:
66
+ command: >-
67
+ mkdir -p .spur/run &&
68
+ set +e &&
69
+ test -n "$slug"; slug_rc=$?;
70
+ $spurBin agent doctor $agent; doctor_rc=$?;
71
+ set -e &&
72
+ if [ "$slug_rc" -eq 0 ] && [ "$doctor_rc" -eq 0 ]; then
73
+ printf 'PASS\n' > .spur/run/$__runId-plan-precheck.status;
74
+ else
75
+ printf 'FAIL\n' > .spur/run/$__runId-plan-precheck.status;
76
+ fi &&
77
+ exit 0
78
+ - kind: note
79
+ options:
80
+ message: "Planning pipeline start for slug=${vars.slug}."
53
81
 
54
82
  - id: phasing
55
83
  description: >
@@ -64,30 +92,38 @@ states:
64
92
 
65
93
  - id: feature-id
66
94
  description: >
67
- Allocate the feature id via the canonical `spur feature create` verb (it owns the
68
- hierarchical ID rule per DD-14). The agent derives a feature name from ${vars.slug}
69
- and invokes the verb; the new id is captured for the design-doc generation step.
95
+ Allocate the feature id via the canonical `spur feature create` verb (DD-14).
96
+ expectFile fails a silent no-op so design-gen never runs without an id.
70
97
  onEnter:
98
+ - kind: shell
99
+ options:
100
+ command: 'mkdir -p .spur/run && rm -f .spur/run/$__runId-plan-feature-id.txt'
71
101
  - kind: agent.run
72
102
  options:
73
103
  agent: ${vars.agent}
74
- input: "Allocate a feature id for slug ${vars.slug} via the canonical verb. Run `${vars.spurBin} feature create \"<human title derived from ${vars.slug}>\" --parent ${vars.feature} --json` and capture the new feature id from the JSON output into .spur/run/plan-feature-id.txt for the design-gen step. If an existing feature for ${vars.slug} is appropriate, use its id instead and write it to the same file. Do not re-implement id-allocation rules in prose; the verb owns them."
75
- expectFile: .spur/run/plan-feature-id.txt
104
+ # `vars.feature` is optional and defaults to "" the parent flag must be
105
+ # described conditionally, never interpolated bare. `--parent <empty> --json`
106
+ # makes commander swallow `--json` as the parent value.
107
+ input: "Skill(skill=\"sp:spur-cli\", args=\"feature create for slug ${vars.slug}\"). Run `${vars.spurBin} feature create \"${vars.slug}\" --json` (or reuse an existing id); append `--parent \"${vars.feature}\"` ONLY if the parent id between those quotes is non-empty — if it is empty, omit the --parent flag entirely. Write the feature id alone to .spur/run/${vars.__runId}-plan-feature-id.txt."
108
+ expectFile: .spur/run/${vars.__runId}-plan-feature-id.txt
76
109
  timeoutMs: ${vars.stepTimeoutMs}
77
110
 
78
111
  - id: design-gen
79
112
  description: >
80
- Author the design doc at docs/design/${vars.slug}.md from the brainstormed feature
81
- draft (docs/plans/${vars.slug}-drafted.md). ADVISORY: use the highest-quality coding
82
- agent available (Q8 tier rule is guidance, not enforced). Invokes sp:doc-evolve to
83
- stage the 04_DESIGN index edit (never auto-write the authoritative index — Q3).
113
+ Author docs/design/${vars.slug}.md from docs/plans/${vars.slug}-drafted.md and
114
+ stage 04_DESIGN index via sp:doc-evolve (Q3 never auto-write the index).
115
+ expectFile fails a silent no-op design gen.
84
116
  onEnter:
85
117
  - kind: agent.run
86
118
  options:
87
119
  agent: ${vars.agent}
88
- input: "Author the design doc at docs/design/${vars.slug}.md from docs/plans/${vars.slug}-drafted.md. Invoke sp:doc-evolve to stage the 04_DESIGN index edit."
120
+ input: "Skill(skill=\"sp:doc-evolve\", args=\"design-gen slug=${vars.slug}\"). Author docs/design/${vars.slug}.md from docs/plans/${vars.slug}-drafted.md; stage 04_DESIGN index edit only."
121
+ expectFile: docs/design/${vars.slug}.md
89
122
  timeoutMs: ${vars.stepTimeoutMs}
90
123
 
124
+ - id: failed
125
+ description: Terminal — planning failed a hard gate (feature-id / design-gen / check).
126
+
91
127
  - id: design-approval
92
128
  description: >
93
129
  HITL gate — the highest-leverage gate in the pipeline. Loop until the operator
@@ -110,26 +146,38 @@ states:
110
146
  onEnter:
111
147
  - kind: shell
112
148
  options:
113
- command: 'mkdir -p .spur/memory/sessions && echo "checkpoint: planning-pipeline handoff slug=${vars.slug} ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)" > .spur/memory/sessions/${vars.slug}-checkpoint.md'
149
+ command: 'mkdir -p .spur/memory/sessions && echo "checkpoint: planning-pipeline handoff slug=$slug ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)" > .spur/memory/sessions/$slug-checkpoint.md'
114
150
 
115
151
  - id: cancelled
116
152
  description: Terminal — planning abandoned by the operator.
117
153
 
118
154
  transitions:
119
- # ── start: route AROUND the phasing HITL gate when profile=auto ──
120
- # Auto-skip guard tried FIRST: under profile=auto the run goes straight to
121
- # feature-id and never ENTERS phasing (whose onEnter hitl.confirm would block).
122
- # Otherwise fall through to phasing for the human gate.
155
+ # ── start: precheck FAIL failed; else route around phasing when profile=auto ──
156
+ # Declaration order: FAIL first, then auto-skip, then interactive phasing.
157
+ - from: start
158
+ to: failed
159
+ description: Precheck FAIL (empty slug and/or doctor red) — stop.
160
+ guard:
161
+ kind: shell
162
+ options:
163
+ command: 'test "$(cat .spur/run/$__runId-plan-precheck.status 2>/dev/null)" = FAIL'
123
164
  - from: start
124
165
  to: feature-id
125
- description: profile=auto — skip the phasing HITL gate.
166
+ description: profile=auto and precheck PASS — skip the phasing HITL gate.
126
167
  guard:
127
168
  kind: shell
128
169
  options:
129
- command: 'test "${vars.profile}" = auto'
170
+ command: 'test "$profile" = auto && test "$(cat .spur/run/$__runId-plan-precheck.status 2>/dev/null)" = PASS'
130
171
  - from: start
131
172
  to: phasing
132
- description: Interactive — enter the phasing HITL gate.
173
+ description: Interactive and precheck PASS — enter the phasing HITL gate.
174
+ guard:
175
+ kind: shell
176
+ options:
177
+ command: 'test "$(cat .spur/run/$__runId-plan-precheck.status 2>/dev/null)" = PASS'
178
+ - from: start
179
+ to: failed
180
+ description: Defense — corrupt/missing precheck status — failed.
133
181
  guard:
134
182
  kind: always
135
183
 
@@ -140,14 +188,14 @@ transitions:
140
188
  guard:
141
189
  kind: shell
142
190
  options:
143
- command: 'test "${vars.__hitlAnswer}" = yes || test "${vars.__hitlAnswer}" = no'
191
+ command: 'test "$__hitlAnswer" = yes || test "$__hitlAnswer" = no'
144
192
  - from: phasing
145
193
  to: cancelled
146
194
  description: Operator cancelled planning.
147
195
  guard:
148
196
  kind: shell
149
197
  options:
150
- command: 'test "${vars.__hitlAnswer}" = cancel'
198
+ command: 'test "$__hitlAnswer" = cancel'
151
199
 
152
200
  # ── linear body ──
153
201
  - from: feature-id
@@ -166,7 +214,7 @@ transitions:
166
214
  guard:
167
215
  kind: shell
168
216
  options:
169
- command: 'test "${vars.profile}" = auto && test "${vars.design_approved}" = true'
217
+ command: 'test "$profile" = auto && test "$design_approved" = true'
170
218
  - from: design-gen
171
219
  to: design-approval
172
220
  description: Design doc drafted — gate on human approval.
@@ -180,18 +228,18 @@ transitions:
180
228
  guard:
181
229
  kind: shell
182
230
  options:
183
- command: 'test "${vars.__hitlAnswer}" = yes'
231
+ command: 'test "$__hitlAnswer" = yes'
184
232
  - from: design-approval
185
233
  to: design-gen
186
234
  description: Rework — operator requested design revisions.
187
235
  guard:
188
236
  kind: shell
189
237
  options:
190
- command: 'test "${vars.__hitlAnswer}" = no'
238
+ command: 'test "$__hitlAnswer" = no'
191
239
  - from: design-approval
192
240
  to: cancelled
193
241
  description: Operator cancelled planning.
194
242
  guard:
195
243
  kind: shell
196
244
  options:
197
- command: 'test "${vars.__hitlAnswer}" = cancel'
245
+ command: 'test "$__hitlAnswer" = cancel'
@@ -1,3 +1,11 @@
1
+ # Externally driven FSM (requestTransition) — not an auto-running pipeline.
2
+ #
3
+ # Reliability (aligned with task-pipeline / ADR-043 — lifecycle-only contract):
4
+ # - Hard shell guards only at wip→testing and testing→done (no soft probe needed:
5
+ # requestTransition fails closed when the guard shell is non-zero)
6
+ # - CLI done verdict guard is a second layer (0292) covering --no-lifecycle paths
7
+ # - No agent.run nodes (by design — pure status graph)
8
+ # - cancelled is the sole terminal; done is re-enterable (reopen → wip)
1
9
  "$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
2
10
  kind: state-machine
3
11
  name: task-lifecycle
@@ -61,14 +69,14 @@ transitions:
61
69
  guard:
62
70
  kind: shell
63
71
  options:
64
- command: '${vars.spurBin} task check ${vars.wbs}'
72
+ command: '$spurBin task check $wbs'
65
73
  - from: testing
66
74
  to: done
67
75
  description: Testing passed — task complete
68
76
  guard:
69
77
  kind: shell
70
78
  options:
71
- command: '${vars.spurBin} task check ${vars.wbs} --strict-core'
79
+ command: '$spurBin task check $wbs --strict-core'
72
80
 
73
81
  # Reopen: done → wip (warned, mandatory History entry)
74
82
  - from: done