@gobing-ai/spur 0.4.11 → 0.4.13

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 (108) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/config.example.yaml +22 -0
  3. package/config/rules/boundary/config-loading-ownership.yaml +1 -1
  4. package/config/rules/quality/coverage-gate.yaml +2 -2
  5. package/config/rules/strict/runtime-boundaries.yaml +2 -2
  6. package/config/rules/surface/check-cli-surface.yaml +4 -0
  7. package/config/rules/typescript/output-boundaries.yaml +4 -10
  8. package/config/workflows/feature-verification.yaml +14 -5
  9. package/config/workflows/idea-pipeline.yaml +92 -12
  10. package/config/workflows/task-pipeline.yaml +456 -830
  11. package/config/workflows/wayfinder-resolution.yaml +20 -3
  12. package/config/workflows/wrapup-pipeline.yaml +22 -9
  13. package/package.json +1 -1
  14. package/plugins/sp/README.md +2 -2
  15. package/plugins/sp/agents/super-planner.md +2 -2
  16. package/plugins/sp/agents/super-reviewer.md +17 -8
  17. package/plugins/sp/bunfig.toml +3 -3
  18. package/plugins/sp/commands/dev-changelog.md +1 -1
  19. package/plugins/sp/commands/dev-gitmsg.md +2 -2
  20. package/plugins/sp/commands/dev-handover.md +1 -1
  21. package/plugins/sp/commands/dev-idea.md +23 -13
  22. package/plugins/sp/commands/dev-job-dump.md +1 -1
  23. package/plugins/sp/commands/dev-plan.md +17 -6
  24. package/plugins/sp/commands/dev-review.md +1 -1
  25. package/plugins/sp/commands/dev-run.md +8 -7
  26. package/plugins/sp/commands/dev-runall.md +1 -1
  27. package/plugins/sp/plugin.json +1 -1
  28. package/plugins/sp/skills/code-implementation/SKILL.md +7 -7
  29. package/plugins/sp/skills/code-refactoring/SKILL.md +1 -1
  30. package/plugins/sp/skills/code-verification/SKILL.md +1 -1
  31. package/plugins/sp/skills/code-verification/references/secu-review.md +1 -1
  32. package/plugins/sp/skills/code-verification/references/verdict-schema.md +23 -10
  33. package/plugins/sp/skills/doc-evolve/SKILL.md +1 -1
  34. package/plugins/sp/skills/next-router/references/routing-table.md +1 -1
  35. package/plugins/sp/skills/parallel-execution/references/dispatch-surface.md +7 -7
  36. package/plugins/sp/skills/spec-decomposition/references/decomposition.md +4 -4
  37. package/plugins/sp/skills/spur-check/SKILL.md +9 -8
  38. package/plugins/sp/skills/spur-cli/SKILL.md +2 -2
  39. package/plugins/sp/skills/spur-cli/references/self.md +37 -2
  40. package/plugins/sp/skills/spur-cli/references/tasks/l3-guard-cheatsheet.md +1 -1
  41. package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +3 -3
  42. package/plugins/sp/skills/spur-cli/references/tasks.md +1 -1
  43. package/plugins/sp/skills/spur-cli/references/workflows.md +5 -3
  44. package/plugins/sp/skills/spur-dev/SKILL.md +3 -3
  45. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +12 -11
  46. package/plugins/sp/skills/spur-dev/references/dev-operations.md +15 -15
  47. package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +4 -3
  48. package/plugins/sp/skills/spur-dev/references/execution-batch-report.md +4 -4
  49. package/plugins/sp/skills/spur-dev/references/execution-batch.md +13 -11
  50. package/plugins/sp/skills/spur-dev/references/execution-workflow.md +32 -23
  51. package/plugins/sp/skills/spur-dev/references/execution-worktree-landing.md +5 -5
  52. package/plugins/sp/skills/spur-dev/references/execution-worktree-setup.md +4 -4
  53. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +4 -4
  54. package/plugins/sp/skills/spur-dev/references/idea-evaluation.md +1 -1
  55. package/schemas/spur-config.schema.json +19 -1
  56. package/spur.js +31459 -31868
  57. package/web/_astro/{BoardApp.BMprmPRc.js → BoardApp.Bjdp3XWV.js} +36 -36
  58. package/web/_astro/{BoardApp.B5rTVNd_.js → BoardApp.DCDZxLlQ.js} +1 -1
  59. package/web/_astro/{TaskDetail.Ddsur8qd.js → TaskDetail.B3vBxynO.js} +1 -1
  60. package/web/_astro/{arc.DLqVVBxP.js → arc.DcuHTB_T.js} +1 -1
  61. package/web/_astro/{architectureDiagram-3BPJPVTR.C-Pk3uAi.js → architectureDiagram-3BPJPVTR.ClOFWBON.js} +1 -1
  62. package/web/_astro/{blockDiagram-GPEHLZMM.BRO1i_Nm.js → blockDiagram-GPEHLZMM.otYyr7Zb.js} +1 -1
  63. package/web/_astro/{c4Diagram-AAUBKEIU.BU_cWu6e.js → c4Diagram-AAUBKEIU.BCjpc9LP.js} +1 -1
  64. package/web/_astro/channel.qgOLXjI_.js +1 -0
  65. package/web/_astro/{chunk-2J33WTMH.D2VXiQ2t.js → chunk-2J33WTMH.D5Wpnpt_.js} +1 -1
  66. package/web/_astro/{chunk-4BX2VUAB.BcHT772J.js → chunk-4BX2VUAB.DkQGtWNz.js} +1 -1
  67. package/web/_astro/{chunk-55IACEB6.DhDtICmo.js → chunk-55IACEB6.B7dqjAip.js} +1 -1
  68. package/web/_astro/{chunk-727SXJPM.BoKHp7gV.js → chunk-727SXJPM.BDQvnKE2.js} +1 -1
  69. package/web/_astro/{chunk-AQP2D5EJ.Chu4JRpE.js → chunk-AQP2D5EJ.D92doBX5.js} +1 -1
  70. package/web/_astro/{chunk-FMBD7UC4.wHdwKPlq.js → chunk-FMBD7UC4.C968oI5G.js} +1 -1
  71. package/web/_astro/{chunk-ND2GUHAM.ffN-M1JB.js → chunk-ND2GUHAM.AkkYC1bY.js} +1 -1
  72. package/web/_astro/{chunk-QZHKN3VN.FRubwg4S.js → chunk-QZHKN3VN.sCc-rKKo.js} +1 -1
  73. package/web/_astro/{classDiagram-4FO5ZUOK.c22tQsc_.js → classDiagram-4FO5ZUOK.pOQ9u0mY.js} +1 -1
  74. package/web/_astro/{classDiagram-v2-Q7XG4LA2.c22tQsc_.js → classDiagram-v2-Q7XG4LA2.pOQ9u0mY.js} +1 -1
  75. package/web/_astro/{cose-bilkent-S5V4N54A.B9c6fiSj.js → cose-bilkent-S5V4N54A.CRaeD6FY.js} +1 -1
  76. package/web/_astro/{cynefin-OW5HDTMX.DrZsrUHl.js → cynefin-OW5HDTMX.BiCPBu54.js} +1 -1
  77. package/web/_astro/{dagre-BM42HDAG.DG1U4b3y.js → dagre-BM42HDAG.C1-q3vkT.js} +1 -1
  78. package/web/_astro/{diagram-2AECGRRQ.CH15b-K3.js → diagram-2AECGRRQ.BSVOv30O.js} +1 -1
  79. package/web/_astro/{diagram-5GNKFQAL.BH1j7twR.js → diagram-5GNKFQAL.CHMkjJ-V.js} +1 -1
  80. package/web/_astro/{diagram-KO2AKTUF.q2zCkbAj.js → diagram-KO2AKTUF.CKY9M564.js} +1 -1
  81. package/web/_astro/{diagram-LMA3HP47.BLaaZnHV.js → diagram-LMA3HP47.B9yNJiTP.js} +1 -1
  82. package/web/_astro/{diagram-OG6HWLK6.BcpRdQwI.js → diagram-OG6HWLK6.Dk8AUGsk.js} +1 -1
  83. package/web/_astro/{erDiagram-TEJ5UH35.D7KBlqfM.js → erDiagram-TEJ5UH35.BQHR89TZ.js} +1 -1
  84. package/web/_astro/{flowDiagram-I6XJVG4X.D_gmuRqg.js → flowDiagram-I6XJVG4X.oNkWVgoK.js} +1 -1
  85. package/web/_astro/{ganttDiagram-6RSMTGT7.DzgWYniD.js → ganttDiagram-6RSMTGT7.Kz2U2nu9.js} +1 -1
  86. package/web/_astro/{gitGraphDiagram-PVQCEYII.576i3hm3.js → gitGraphDiagram-PVQCEYII.DHIZ_wPq.js} +1 -1
  87. package/web/_astro/{infoDiagram-5YYISTIA.DMCclBiz.js → infoDiagram-5YYISTIA.D0NJLcv9.js} +1 -1
  88. package/web/_astro/{ishikawaDiagram-YF4QCWOH.9Kyca4SH.js → ishikawaDiagram-YF4QCWOH.CFEfTWRG.js} +1 -1
  89. package/web/_astro/{journeyDiagram-JHISSGLW.chbdG-8q.js → journeyDiagram-JHISSGLW.Dc7IE7I4.js} +1 -1
  90. package/web/_astro/{kanban-definition-UN3LZRKU.Bds54-e0.js → kanban-definition-UN3LZRKU.D5v0xO9k.js} +1 -1
  91. package/web/_astro/{linear.D5ND9GN_.js → linear.wR5KzXnE.js} +1 -1
  92. package/web/_astro/{mermaid.core.D9N_PGbj.js → mermaid.core.BDQ2FoPd.js} +4 -4
  93. package/web/_astro/{mindmap-definition-RKZ34NQL.t0xop5vp.js → mindmap-definition-RKZ34NQL.W6_INsia.js} +1 -1
  94. package/web/_astro/{pieDiagram-4H26LBE5.DqgKh6hM.js → pieDiagram-4H26LBE5.61ihbgkK.js} +1 -1
  95. package/web/_astro/{quadrantDiagram-W4KKPZXB.DeuHVi2t.js → quadrantDiagram-W4KKPZXB.B5lEpFLo.js} +1 -1
  96. package/web/_astro/{requirementDiagram-4Y6WPE33.BdYFSG4W.js → requirementDiagram-4Y6WPE33.CmhVBVX0.js} +1 -1
  97. package/web/_astro/{sankeyDiagram-5OEKKPKP.k1LPPETJ.js → sankeyDiagram-5OEKKPKP.D7Vvj9Wf.js} +1 -1
  98. package/web/_astro/{sequenceDiagram-3UESZ5HK.DdyfpzoG.js → sequenceDiagram-3UESZ5HK.B1vPLixM.js} +1 -1
  99. package/web/_astro/{stateDiagram-AJRCARHV.DSEI8il0.js → stateDiagram-AJRCARHV.BnACmrGi.js} +1 -1
  100. package/web/_astro/{stateDiagram-v2-BHNVJYJU.CoMnQRKo.js → stateDiagram-v2-BHNVJYJU.CW4pnmc3.js} +1 -1
  101. package/web/_astro/{timeline-definition-PNZ67QCA.DM1AHNm-.js → timeline-definition-PNZ67QCA.CkzMCPnC.js} +1 -1
  102. package/web/_astro/{vennDiagram-CIIHVFJN.C-cJmVtl.js → vennDiagram-CIIHVFJN.CY4aNdAR.js} +1 -1
  103. package/web/_astro/{wardleyDiagram-YWT4CUSO.D0xMzKPb.js → wardleyDiagram-YWT4CUSO.BtoU9UFk.js} +1 -1
  104. package/web/_astro/{xychartDiagram-2RQKCTM6.BH5xJcEq.js → xychartDiagram-2RQKCTM6._9ijUUAs.js} +1 -1
  105. package/web/index.html +1 -1
  106. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +0 -997
  107. package/plugins/sp/skills/spur-dev/references/structured-trace-emission.md +0 -178
  108. package/web/_astro/channel.Bs3Illhy.js +0 -1
@@ -7,7 +7,7 @@
7
7
  "plugins": [
8
8
  {
9
9
  "name": "sp",
10
- "version": "0.4.11",
10
+ "version": "0.4.13",
11
11
  "source": "./plugins/sp"
12
12
  }
13
13
  ]
@@ -230,6 +230,28 @@ redaction:
230
230
  # releaseCommitType: chore
231
231
  # releaseCommitScope: release
232
232
  # ghRunListLimit: 5
233
+ # # Stack preset for the SDLC action vocabulary (ADR-139): the commands Spur's gates run.
234
+ # # bun (default) — every reserved action resolves to the legacy bun scripts below, so a
235
+ # # bun project needs no binding at all.
236
+ # # none — only the stack-neutral `spur rule run` presets are bound; declare the
237
+ # # rest in `actions` (see below) or they stay unbound.
238
+ # preset: bun
239
+ # # action name -> one shell command, or a list of action names (composite, run in order,
240
+ # # fail-fast). A declared entry replaces the preset binding whole. Reserved names: build, dev,
241
+ # # clean, format, autofix, lint, typecheck, test, test-full, test-heavy, rules-pre, rules-post,
242
+ # # check, check-full, check-feature, lint-changed, typecheck-changed, test-changed. Any other
243
+ # # name is a custom action (exec-only). {files}/{paths}/{workspace} are allowed only in the
244
+ # # three *-changed actions; each substituted item is shell-quoted.
245
+ # actions:
246
+ # build: make build
247
+ # lint: ruff check .
248
+ # typecheck: mypy src
249
+ # test: pytest -q
250
+ # test-full: pytest --cov
251
+ # lint-changed: ruff check {files}
252
+ # test-changed: cd {workspace} && pytest {paths}
253
+ # check: [lint, test, rules-post]
254
+ # release: ./scripts/release.sh
233
255
 
234
256
  # ── Planning (design §2.1 / §9) ──
235
257
  tasks:
@@ -67,7 +67,7 @@ rules:
67
67
  exclude:
68
68
  - "packages/config/src/**"
69
69
  - "apps/cli/src/index.ts"
70
- - "apps/cli/src/workflow-transport.ts" # boot-free composition root of `spur workflow inline|commit-guard` (PR-4)
70
+ - "apps/cli/src/workflow-transport.ts" # boot-free composition root of `spur workflow commit-guard|persist-*` (PR-4)
71
71
  - "apps/server/src/serve.ts"
72
72
  - "apps/server/src/context.ts"
73
73
  - "**/tests/**"
@@ -1,8 +1,8 @@
1
1
  $schema: "@gobing-ai/spur/schemas/rule-file.schema.json"
2
2
  # Coverage gate — per-file line coverage meets threshold from Bun's lcov output.
3
3
  #
4
- # PROVENANCE (task 1203): since task 1203 the repository post-check scripts
5
- # (`test-post-check`, `test-post-check:full`) validate canonical coverage
4
+ # PROVENANCE (task 1203): since task 1203 the repository post-check script
5
+ # (`test-post-check`) validates canonical coverage
6
6
  # certification BEFORE this rule evaluates: only a completed successful canonical
7
7
  # full-suite run (`bun run test`, `test:coverage`, `test:full`) certifies
8
8
  # .coverage/lcov.info (marker: .coverage/coverage-certification.json, written by
@@ -101,8 +101,8 @@ rules:
101
101
  - "packages/app/src/services/history-anatomy.ts" # deterministic history-anatomy cache core (task 1005 R2): fsync'd tmp+rename atomic publish, readdir digest scans and sync report reads must stay byte-stable; bundled standalone for the bare-node plugin twin (mirrors agent-usage-producer.ts / history-service.ts exemptions)
102
102
  - "packages/app/src/observability/workflow-run-log-sink.ts" # sync FD append for mid-run tail-able all-in-one run log (task 0426 / feature D2); append() is sync from the observability bus
103
103
  - "packages/app/src/observability/agent-run-log.ts" # same primitive as the sink above for the per-run agent stream (task 1076 R1, ADR-132); append() is sync from the agent service's own onOutput hook, and the byte cap needs the FD position it tracks
104
- # Inline-driver transports (script-absorption PR-4, `spur workflow inline|commit-guard`): moved
105
- # verbatim from the plugin scripts with their golden output pinned; synchronous probes and
104
+ # Workflow transports (script-absorption PR-4, `spur workflow commit-guard`): moved
105
+ # verbatim from the plugin scripts; synchronous probes and
106
106
  # atomic tmp+rename snapshot writes inside one short-lived CLI process.
107
107
  - "packages/app/src/workflow/commit-guard.ts" # .spur/run/<run>-tree-start.json atomic snapshot + target conflict-marker reads
108
108
  - "packages/app/src/workflow/persist-check.ts" # recursive evidence-tree listing + byte comparison of both trees
@@ -65,6 +65,10 @@ rules:
65
65
  # commit-guard declares no --json: its {staged, foreign} / {foreign} lines are rendered by
66
66
  # @gobing-ai/spur-app/commit-guard (byte-identical to the retired script, PR-4 golden).
67
67
  - "apps/cli/src/commands/workflow/commit-guard.ts"
68
+ # WT-4 worktree-landing transports (D65 1242, flat since the inline group was deleted): they
69
+ # print the app operation's already-serialized payload (runPersistOut/persist-check), and
70
+ # declare no --json of their own.
71
+ - "apps/cli/src/commands/workflow/persist.ts"
68
72
  # Pipeline-internal task verbs (script-absorption PR-3) declare no --json: their contract is
69
73
  # the .spur/run artifact they write (gate status/receipt, residuals.json, diffstat.json) and
70
74
  # the exit code; the gate's own status line is serialized by the app service.
@@ -17,11 +17,6 @@ rules:
17
17
  type: rg
18
18
  config:
19
19
  pattern: "console\\.(log|error|warn|info|debug|dir|time|trace)"
20
- # Task 1006 R3: the inline-run driver's fail-closed stderr lines moved here from the
21
- # plugin script (byte-stable driver contract, emitted through the bundled lib under
22
- # bare node); the output seam is a CLI-layer dependency the app service cannot take.
23
- exclude:
24
- - "packages/app/src/services/inline-run-setup.ts"
25
20
 
26
21
  - id: no-raw-stdout-stderr
27
22
  description: "Use the output seam (ts-utils echo/echoError) instead of process.stdout/stderr.write directly."
@@ -30,10 +25,9 @@ rules:
30
25
  type: rg
31
26
  config:
32
27
  pattern: "process\\.(stdout|stderr)\\.write"
33
- # Tasks 1006 R1/R3: gate receipts (`check-receipt/v1`, one JSON line — the runner's parsed
34
- # stdout contract) and the inline driver's stdout lines moved here from the plugin scripts.
35
- # Both must stay byte-stable through the bundled libs under bare node; the seam would
36
- # rewrite framing the CLI/tests parse. Mirrors the history-anatomy bundling exemptions.
28
+ # Task 1006 R1: gate receipts (`check-receipt/v1`, one JSON line — the runner's parsed
29
+ # stdout contract) moved here from the plugin script. It must stay byte-stable through the
30
+ # bundled lib under bare node; the seam would rewrite framing the CLI/tests parse. Mirrors
31
+ # the history-anatomy bundling exemptions.
37
32
  exclude:
38
33
  - "packages/app/src/services/quality-gate.ts"
39
- - "packages/app/src/services/inline-run-setup.ts"
@@ -39,7 +39,7 @@
39
39
  "$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
40
40
  kind: state-machine
41
41
  name: feature-verification
42
- version: "1"
42
+ version: "2"
43
43
  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."
44
44
  iterationBound: 2
45
45
  initialState: verify
@@ -51,7 +51,7 @@ failureStates:
51
51
  vars:
52
52
  featureId: "X"
53
53
  spurBin: "spur"
54
- verificationCmd: "bun run spur-check-feature"
54
+ verificationCmd: "spur self exec check-feature"
55
55
  __runId: ""
56
56
 
57
57
  states:
@@ -62,10 +62,19 @@ states:
62
62
  digest, run identity) and the coarse status file, always exit 0 so the
63
63
  transition guard routes missing/corrupt/FAIL to `failed`.
64
64
  onEnter:
65
- - kind: shell
65
+ # D65 1238 R1: the pass runs as a typed gate builtin (1234), not a shell action — the same
66
+ # `spur feature verify` argv, whose configured `spur self exec check-feature` action is the
67
+ # verification command. `softFail` keeps a non-running pass a RECORDED outcome that the guards
68
+ # below route to `failed`, exactly as the always-exit-0 shell did. The pass still writes its
69
+ # own `.spur/run/<runId>-feature-verification.status` and evidence receipt; the gate's typed
70
+ # token lands beside them, so the pass's PASS/FAIL evidence is never overwritten.
71
+ - kind: command.gate
66
72
  options:
67
- command: >-
68
- mkdir -p .spur/run; $spurBin feature verify "$featureId" --run-id "$__runId" --no-logo || printf 'FAIL feature-verification failed closed — spur feature verify exited nonzero\n' > ".spur/run/$__runId-feature-verification.status"; exit 0
73
+ id: feature-verification
74
+ executable: "${vars.spurBin}"
75
+ args: ["feature", "verify", "${vars.featureId}", "--run-id", "${vars.__runId}", "--no-logo"]
76
+ resultFile: .spur/run/${vars.__runId}-feature-verification.gate.status
77
+ softFail: true
69
78
 
70
79
  - id: done
71
80
  description: Terminal — repo-wide checks passed and the receipt is bound.
@@ -76,6 +76,15 @@ vars:
76
76
  agent: "auto"
77
77
  planningAgent: ""
78
78
  stepTimeoutMs: "1800000"
79
+ # Executor for every agent.run stage (D65 R1): "host" pauses the run with a work item
80
+ # (`spur workflow run|continue --json`), "fleet" dispatches through ADR-126, and empty
81
+ # resolves the subprocess surface through the existing tier ladder.
82
+ executor: ""
83
+ # Accepted/deferred status each operator gate's decision binding writes (1236 R2).
84
+ ideaEvalStatus: ""
85
+ featureCheckStatus: ""
86
+ designApprovalStatus: ""
87
+ batchCreateStatus: ""
79
88
 
80
89
  states:
81
90
  - id: start
@@ -138,6 +147,11 @@ states:
138
147
  # explicitly so the definition is self-documenting.
139
148
  session: fresh
140
149
  expectFile: .spur/run/${vars.__runId}-idea-eval-report.md
150
+ # The signal is this stage's own output; the plural form declares it to the
151
+ # work item (host/fleet) while the singular expectFile stays the subprocess
152
+ # post-exit guard, so a missing signal still falls back to the catalog decision.
153
+ expectFiles:
154
+ - .spur/run/${vars.__runId}-idea-needs-design.json
141
155
  timeoutMs: ${vars.stepTimeoutMs}
142
156
  # Derive the eval recommendation ONCE (0769 pattern): the first non-blank line under
143
157
  # `## Recommendation` → proceed | reshape | drop | unknown. The --auto guards out of
@@ -183,14 +197,30 @@ states:
183
197
  pros/cons, and a recommendation. The operator reviews and approves or
184
198
  rejects. Routed around only when profile=auto AND vars.idea_approved=true
185
199
  (CLI --auto) AND the report's recommendation is proceed/reshape; a drop
186
- recommendation cancels, a missing one still pauses here.
187
- pause: true
200
+ recommendation cancels, a missing one asks the gate, whose evidence binding then
201
+ answers under profile=auto (1236/1241).
188
202
  onEnter:
189
203
  - kind: hitl.confirm
190
204
  options:
191
205
  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.)"
206
+ # Interactive always prompts the operator; profile=auto answers from the discovery
207
+ # stage's recorded evidence, deferring when it cannot decide (1236 R1/R2).
192
208
  decision:
193
- mode: never
209
+ mode: evidence
210
+ statusVar: ideaEvalStatus
211
+ evidenceNodes:
212
+ - discovery
213
+ # A deferred/absent answer is the denial today's headless responder gave, so the
214
+ # guards keep routing on yes | no | cancel with no new edge.
215
+ - kind: shell
216
+ options:
217
+ command: >-
218
+ mkdir -p .spur/run; a="$__hitlAnswer"; [ -n "$a" ] || a=no;
219
+ printf '%s\n' "$a" > ".spur/run/$__runId-idea-eval-answer.txt"
220
+ - kind: file.read.into-var
221
+ options:
222
+ path: .spur/run/${vars.__runId}-idea-eval-answer.txt
223
+ var: __hitlAnswer
194
224
 
195
225
  - id: feature-create
196
226
  display:
@@ -218,6 +248,11 @@ states:
218
248
  # B7 R6 (0894): declared fresh policy (planner default).
219
249
  session: fresh
220
250
  expectFile: .spur/run/${vars.__runId}-idea-feature-id.txt
251
+ # Intent artifacts this stage writes; the shell below fails closed when either is
252
+ # missing, so declaring them adds the work-item contract, not a new precondition.
253
+ expectFiles:
254
+ - .spur/run/${vars.__runId}-idea-goal.md
255
+ - .spur/run/${vars.__runId}-idea-scope.md
221
256
  timeoutMs: ${vars.stepTimeoutMs}
222
257
  - kind: file.read.into-var
223
258
  options:
@@ -335,13 +370,29 @@ states:
335
370
  Requirement coverage (1004 R2) folds into the recorded `idea-ac-check` result via the
336
371
  gate's `--inventory` flag: a FAIL there can mean some inventory items have no covering
337
372
  scenario — answer no to route back to ac-generate for revision if needed.
338
- pause: true
339
373
  onEnter:
340
374
  - kind: hitl.confirm
341
375
  options:
342
376
  prompt: "Feature check for ${vars.featureId}. Review the AC and confirm to proceed? Recorded check status: $(cat .spur/run/${vars.__runId}-idea-ac-check.status 2>/dev/null || echo unknown) (.spur/run/${vars.__runId}-idea-ac-check.status — includes inventory-coverage findings, 1004 R2). (Failures route back to ac-generate for revision, capped at 3 retries.)"
377
+ # Interactive always prompts the operator; profile=auto answers from the AC
378
+ # authoring stage's recorded evidence (1236 R1/R2). No `pause: true` — an
379
+ # evidence binding cannot live in a paused state (0911 D2), and the responder
380
+ # is what asks the operator now.
343
381
  decision:
344
- mode: never
382
+ mode: evidence
383
+ statusVar: featureCheckStatus
384
+ evidenceNodes:
385
+ - ac-generate
386
+ # A deferred/absent answer is the denial today's headless responder gave.
387
+ - kind: shell
388
+ options:
389
+ command: >-
390
+ mkdir -p .spur/run; a="$__hitlAnswer"; [ -n "$a" ] || a=no;
391
+ printf '%s\n' "$a" > ".spur/run/$__runId-idea-feature-check-answer.txt"
392
+ - kind: file.read.into-var
393
+ options:
394
+ path: .spur/run/${vars.__runId}-idea-feature-check-answer.txt
395
+ var: __hitlAnswer
345
396
  # 1007 R2: the former post-confirm route-writer duplicate is deleted — ac-generate's
346
397
  # writer is the single writer (0945 R2 pin updated); its inputs (design var, needs-design
347
398
  # JSON, recorded ac-check status) cannot change across hitl.confirm.
@@ -420,7 +471,6 @@ states:
420
471
  records the concrete issue(s) in the run-scoped design-review artifact
421
472
  (.spur/run/${vars.__runId}-idea-design-review.md) under `## Operator feedback` —
422
473
  the revision pass reads it to reconcile invalidated AC before re-approval.
423
- pause: true
424
474
  onEnter:
425
475
  - kind: shell
426
476
  options:
@@ -428,8 +478,23 @@ states:
428
478
  - kind: hitl.confirm
429
479
  options:
430
480
  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."
481
+ # Interactive always prompts the operator; profile=auto answers from the
482
+ # system-design stage's recorded evidence (1236 R1/R2).
431
483
  decision:
432
- mode: never
484
+ mode: evidence
485
+ statusVar: designApprovalStatus
486
+ evidenceNodes:
487
+ - system-design
488
+ # A deferred/absent answer is the denial today's headless responder gave.
489
+ - kind: shell
490
+ options:
491
+ command: >-
492
+ mkdir -p .spur/run; a="$__hitlAnswer"; [ -n "$a" ] || a=no;
493
+ printf '%s\n' "$a" > ".spur/run/$__runId-idea-design-approval-answer.txt"
494
+ - kind: file.read.into-var
495
+ options:
496
+ path: .spur/run/${vars.__runId}-idea-design-approval-answer.txt
497
+ var: __hitlAnswer
433
498
 
434
499
  - id: decompose
435
500
  display:
@@ -491,13 +556,27 @@ states:
491
556
  from decompose to the appropriate next state, so this state is only
492
557
  entered in interactive mode. On failure, the retry cap routes back to
493
558
  decompose (≤3 retries) or escalates to failed.
494
- pause: true
495
559
  onEnter:
496
560
  - kind: hitl.confirm
497
561
  options:
498
562
  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.)"
563
+ # Interactive always prompts the operator; profile=auto answers from the
564
+ # decompose stage's recorded evidence (1236 R1/R2).
499
565
  decision:
500
- mode: never
566
+ mode: evidence
567
+ statusVar: batchCreateStatus
568
+ evidenceNodes:
569
+ - decompose
570
+ # A deferred/absent answer is the denial today's headless responder gave.
571
+ - kind: shell
572
+ options:
573
+ command: >-
574
+ mkdir -p .spur/run; a="$__hitlAnswer"; [ -n "$a" ] || a=no;
575
+ printf '%s\n' "$a" > ".spur/run/$__runId-idea-batch-create-answer.txt"
576
+ - kind: file.read.into-var
577
+ options:
578
+ path: .spur/run/${vars.__runId}-idea-batch-create-answer.txt
579
+ var: __hitlAnswer
501
580
 
502
581
  - id: batch-create-run
503
582
  display:
@@ -650,11 +729,12 @@ transitions:
650
729
 
651
730
  # ── discovery: auto-accept the eval recommendation (profile=auto + idea_approved) OR enter idea-eval ──
652
731
  # Declaration order: auto edges FIRST (same pattern as system-design → design-approval).
653
- # Without them, discovery always enters idea-eval (pause: true), rendering the prompt
654
- # and persisting an avoidable pause before the in-state auto-skip guard can fire (0366 R4/R5).
732
+ # Without them, discovery always enters the idea-eval gate, rendering the prompt and
733
+ # persisting an avoidable operator question before the gate's own auto answer can fire (0366 R4/R5).
655
734
  # --auto accepts the recommendation derived at the end of discovery (-idea-recommendation.txt):
656
735
  # drop → cancelled, proceed/reshape → feature-create; unknown/missing falls through to the
657
- # idea-eval pause (fail-safe: never auto-create a feature without an explicit proceed).
736
+ # idea-eval gate, whose evidence binding then answers (fail-safe: never auto-create a feature
737
+ # without an explicit proceed).
658
738
  - from: discovery
659
739
  to: cancelled
660
740
  terminalReason: cancelled