@gobing-ai/spur 0.3.91 → 0.3.93

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 (148) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/pipeline-budgets.json +2 -9
  3. package/config/plugin-scripts.json +27 -1
  4. package/config/templates/AGENTS.md +4 -0
  5. package/config/templates/docs/02_ROADMAP.md +2 -0
  6. package/config/templates/docs/03_ARCHITECTURE.md +3 -1
  7. package/config/templates/docs/04_DESIGN.md +2 -0
  8. package/config/templates/docs/99_PROJECT_CONSTITUTION.md +10 -2
  9. package/config/workflow-candidates.json +72 -1
  10. package/config/workflows/feature-lifecycle.yaml +14 -5
  11. package/config/workflows/feature-verification.yaml +36 -27
  12. package/config/workflows/history-anatomy.yaml +16 -25
  13. package/config/workflows/idea-pipeline.yaml +76 -23
  14. package/config/workflows/pr-review.yaml +8 -0
  15. package/config/workflows/task-pipeline.yaml +362 -40
  16. package/config/workflows/wayfinder-resolution.yaml +5 -0
  17. package/config/workflows/wrapup-pipeline.yaml +102 -19
  18. package/package.json +9 -9
  19. package/plugins/sp/README.md +7 -2
  20. package/plugins/sp/agents/super-planner.md +14 -5
  21. package/plugins/sp/commands/dev-dogfood.md +4 -4
  22. package/plugins/sp/commands/dev-fixall.md +8 -5
  23. package/plugins/sp/commands/dev-run.md +8 -2
  24. package/plugins/sp/commands/dev-runall.md +14 -8
  25. package/plugins/sp/commands/dev-verify.md +9 -0
  26. package/plugins/sp/commands/dev-verifyall.md +5 -0
  27. package/plugins/sp/lib/idea-handoff.generated.mjs +306 -301
  28. package/plugins/sp/lib/inline-run.generated.d.mts +18 -0
  29. package/plugins/sp/lib/inline-run.generated.mjs +1468 -0
  30. package/plugins/sp/plugin.json +1 -1
  31. package/plugins/sp/references/environment-lens.md +1 -1
  32. package/plugins/sp/scripts/dogfood-testing/validate-report.mjs +136 -0
  33. package/plugins/sp/scripts/dogfood-testing/validate-report.ts +196 -2
  34. package/plugins/sp/scripts/feature-verification-steps.mjs +174 -0
  35. package/plugins/sp/scripts/feature-verification-steps.ts +275 -0
  36. package/plugins/sp/scripts/history-anatomy-cache.mjs +104 -4
  37. package/plugins/sp/scripts/history-anatomy-cache.ts +137 -13
  38. package/plugins/sp/scripts/inline-pipeline-parity-check.ts +2 -1
  39. package/plugins/sp/scripts/inline-run-setup.mjs +421 -0
  40. package/plugins/sp/scripts/inline-run-setup.ts +325 -78
  41. package/plugins/sp/scripts/quality-gate.mjs +248 -6
  42. package/plugins/sp/scripts/quality-gate.ts +410 -9
  43. package/plugins/sp/scripts/record-feature-sync.mjs +63 -0
  44. package/plugins/sp/scripts/record-feature-sync.ts +84 -0
  45. package/plugins/sp/scripts/residual-scan.mjs +484 -0
  46. package/plugins/sp/scripts/residual-scan.ts +640 -0
  47. package/plugins/sp/scripts/task-diffstat.mjs +156 -0
  48. package/plugins/sp/scripts/task-diffstat.ts +229 -0
  49. package/plugins/sp/scripts/task-evidence-precheck.ts +8 -3
  50. package/plugins/sp/scripts/task-size-precheck.ts +8 -3
  51. package/plugins/sp/scripts/wrapup-drift-probe.mjs +181 -0
  52. package/plugins/sp/scripts/wrapup-drift-probe.ts +258 -0
  53. package/plugins/sp/scripts/wrapup-steps.mjs +60 -1
  54. package/plugins/sp/scripts/wrapup-steps.ts +89 -4
  55. package/plugins/sp/skills/brainstorm/SKILL.md +2 -0
  56. package/plugins/sp/skills/brainstorm/references/workflows.md +17 -2
  57. package/plugins/sp/skills/branch-workflow/SKILL.md +1 -0
  58. package/plugins/sp/skills/branch-workflow/references/worktree-patterns.md +2 -0
  59. package/plugins/sp/skills/code-implementation/SKILL.md +17 -0
  60. package/plugins/sp/skills/code-verification/SKILL.md +21 -0
  61. package/plugins/sp/skills/code-verification/references/secu-review.md +3 -2
  62. package/plugins/sp/skills/code-verification/references/verdict-schema.md +1 -0
  63. package/plugins/sp/skills/dogfood-testing/SKILL.md +5 -3
  64. package/plugins/sp/skills/dogfood-testing/references/monitor-ledger.md +63 -26
  65. package/plugins/sp/skills/dogfood-testing/references/report-template.md +33 -10
  66. package/plugins/sp/skills/history-anatomy/references/modes.md +5 -3
  67. package/plugins/sp/skills/next-feature/references/ranking-rubric.md +1 -1
  68. package/plugins/sp/skills/next-router/references/routing-table.md +7 -0
  69. package/plugins/sp/skills/parallel-execution/references/dispatch-surface.md +1 -1
  70. package/plugins/sp/skills/session-review/SKILL.md +12 -2
  71. package/plugins/sp/skills/spur-check/SKILL.md +112 -0
  72. package/plugins/sp/skills/spur-cli/references/features.md +1 -1
  73. package/plugins/sp/skills/spur-cli/references/projects.md +3 -1
  74. package/plugins/sp/skills/spur-cli/references/workflows.md +39 -19
  75. package/plugins/sp/skills/spur-dev/SKILL.md +13 -5
  76. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +18 -3
  77. package/plugins/sp/skills/spur-dev/references/dev-operations.md +2 -2
  78. package/plugins/sp/skills/spur-dev/references/document-authoring.md +85 -0
  79. package/plugins/sp/skills/spur-dev/references/execution-batch.md +286 -58
  80. package/plugins/sp/skills/spur-dev/references/execution-workflow.md +1 -1
  81. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +27 -4
  82. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +3 -2
  83. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +61 -16
  84. package/plugins/sp/skills/spur-dev/references/planning-workflow.md +10 -5
  85. package/plugins/sp/skills/spur-dev/templates/design.md +31 -0
  86. package/plugins/sp/skills/spur-dev/templates/plan.md +32 -0
  87. package/plugins/sp/skills/spur-doctor/SKILL.md +60 -14
  88. package/schemas/state-machine-workflow.schema.json +4 -0
  89. package/spur.js +22501 -19644
  90. package/web/_astro/BoardApp.CerSBgis.js +192 -0
  91. package/web/_astro/BoardApp.eoTz0pZs.js +1 -0
  92. package/web/_astro/{TaskDetail.CXGltuT_.js → TaskDetail.DCqiC-OZ.js} +1 -1
  93. package/web/_astro/arc.CPwg6Rw0.js +1 -0
  94. package/web/_astro/{architectureDiagram-3BPJPVTR.DJ8DHkWE.js → architectureDiagram-3BPJPVTR.DM_vp_hO.js} +1 -1
  95. package/web/_astro/{blockDiagram-GPEHLZMM.D8DHK3Jl.js → blockDiagram-GPEHLZMM.DXVIiv0p.js} +1 -1
  96. package/web/_astro/{c4Diagram-AAUBKEIU.BugQbX9u.js → c4Diagram-AAUBKEIU.BbF_zCxW.js} +1 -1
  97. package/web/_astro/channel.MYZLKNwy.js +1 -0
  98. package/web/_astro/{chunk-2J33WTMH.Mv26KlVn.js → chunk-2J33WTMH.CAgQHpPC.js} +1 -1
  99. package/web/_astro/{chunk-4BX2VUAB.CD51JoT_.js → chunk-4BX2VUAB.BN-5tpw4.js} +1 -1
  100. package/web/_astro/{chunk-55IACEB6.D_PFaIEe.js → chunk-55IACEB6.CnPkEEr0.js} +1 -1
  101. package/web/_astro/{chunk-727SXJPM.DemMW1ao.js → chunk-727SXJPM.BQzQeMVm.js} +4 -4
  102. package/web/_astro/{chunk-AQP2D5EJ.Iu2V5-ex.js → chunk-AQP2D5EJ.B6xNyDnL.js} +1 -1
  103. package/web/_astro/{chunk-FMBD7UC4.MsNgSP-E.js → chunk-FMBD7UC4.C7f9Ih78.js} +1 -1
  104. package/web/_astro/{chunk-ND2GUHAM.DfbRaAlm.js → chunk-ND2GUHAM.CNV1dFXT.js} +1 -1
  105. package/web/_astro/{chunk-QZHKN3VN.BbJAQ4h-.js → chunk-QZHKN3VN.Cudn2TkJ.js} +1 -1
  106. package/web/_astro/{classDiagram-4FO5ZUOK.CPurtiC2.js → classDiagram-4FO5ZUOK.D1NwP50q.js} +1 -1
  107. package/web/_astro/{classDiagram-v2-Q7XG4LA2.CPurtiC2.js → classDiagram-v2-Q7XG4LA2.D1NwP50q.js} +1 -1
  108. package/web/_astro/{cose-bilkent-S5V4N54A.CKKdx1bM.js → cose-bilkent-S5V4N54A.B1wSL-Xb.js} +1 -1
  109. package/web/_astro/{cynefin-OW5HDTMX.CoKMTg-R.js → cynefin-OW5HDTMX.BmK52w8G.js} +1 -1
  110. package/web/_astro/{dagre-BM42HDAG.D4h4_k56.js → dagre-BM42HDAG.Bfy5CTDT.js} +2 -2
  111. package/web/_astro/diagram-2AECGRRQ.DhNnvUvX.js +43 -0
  112. package/web/_astro/diagram-5GNKFQAL.lTX5KwnS.js +10 -0
  113. package/web/_astro/{diagram-KO2AKTUF.BFoCkiCr.js → diagram-KO2AKTUF.CW_vMJ4z.js} +3 -3
  114. package/web/_astro/{diagram-LMA3HP47.exHn9OVx.js → diagram-LMA3HP47.B_8ZGF67.js} +1 -1
  115. package/web/_astro/{diagram-OG6HWLK6.CeqO34nN.js → diagram-OG6HWLK6.BppnHsdS.js} +1 -1
  116. package/web/_astro/{erDiagram-TEJ5UH35.D_v7HqxR.js → erDiagram-TEJ5UH35.BEuHXcjJ.js} +5 -5
  117. package/web/_astro/{flowDiagram-I6XJVG4X.EUmrpbwh.js → flowDiagram-I6XJVG4X.CH-UlnGr.js} +4 -4
  118. package/web/_astro/{ganttDiagram-6RSMTGT7.BOCF5lII.js → ganttDiagram-6RSMTGT7.BO81S85v.js} +1 -1
  119. package/web/_astro/{gitGraphDiagram-PVQCEYII.Di7otYZD.js → gitGraphDiagram-PVQCEYII.XnPxPPZN.js} +1 -1
  120. package/web/_astro/index.Hjbr15fG.css +1 -0
  121. package/web/_astro/{infoDiagram-5YYISTIA.TcBkCAJk.js → infoDiagram-5YYISTIA.JyjYRu_T.js} +1 -1
  122. package/web/_astro/{ishikawaDiagram-YF4QCWOH.D-2y4M0c.js → ishikawaDiagram-YF4QCWOH.BBRBF-Fo.js} +5 -5
  123. package/web/_astro/{journeyDiagram-JHISSGLW.DPbJI_n2.js → journeyDiagram-JHISSGLW.C_iymSyp.js} +1 -1
  124. package/web/_astro/{kanban-definition-UN3LZRKU.EFxhQ9Fj.js → kanban-definition-UN3LZRKU.DdfW-Oqt.js} +7 -7
  125. package/web/_astro/{linear.DSAsQLzs.js → linear.C2_IkbZT.js} +1 -1
  126. package/web/_astro/mermaid.core.GAOYeSR0.js +303 -0
  127. package/web/_astro/{mindmap-definition-RKZ34NQL.CJY1N_7V.js → mindmap-definition-RKZ34NQL.DAZIxQSK.js} +2 -2
  128. package/web/_astro/{pieDiagram-4H26LBE5.567ZNoL2.js → pieDiagram-4H26LBE5.CN8sIhKM.js} +3 -3
  129. package/web/_astro/{quadrantDiagram-W4KKPZXB.mqfz9-MY.js → quadrantDiagram-W4KKPZXB.3dGcX5GP.js} +1 -1
  130. package/web/_astro/{requirementDiagram-4Y6WPE33.Bv1Gv9In.js → requirementDiagram-4Y6WPE33.BV2y4dd6.js} +3 -3
  131. package/web/_astro/{sankeyDiagram-5OEKKPKP.B6Gs4X4r.js → sankeyDiagram-5OEKKPKP.Cqo15Tvo.js} +4 -4
  132. package/web/_astro/{sequenceDiagram-3UESZ5HK.BhYj4v-m.js → sequenceDiagram-3UESZ5HK.CROCPMJB.js} +1 -1
  133. package/web/_astro/{stateDiagram-AJRCARHV.BPbBnkpw.js → stateDiagram-AJRCARHV.RfXZrkFE.js} +1 -1
  134. package/web/_astro/{stateDiagram-v2-BHNVJYJU.C4squMNK.js → stateDiagram-v2-BHNVJYJU.CPXmbBs9.js} +1 -1
  135. package/web/_astro/{timeline-definition-PNZ67QCA.C_SwIHgl.js → timeline-definition-PNZ67QCA.DdgKTiO8.js} +3 -3
  136. package/web/_astro/{vennDiagram-CIIHVFJN.Bz4NZGpQ.js → vennDiagram-CIIHVFJN.CPNVSHF1.js} +5 -5
  137. package/web/_astro/{wardleyDiagram-YWT4CUSO.CozMVZ3i.js → wardleyDiagram-YWT4CUSO.CQhA0Jyr.js} +3 -3
  138. package/web/_astro/{xychartDiagram-2RQKCTM6.BwMGBwjB.js → xychartDiagram-2RQKCTM6.n61BWyy4.js} +1 -1
  139. package/web/index.html +2 -2
  140. package/config/workflows/decision-routing-example.yaml +0 -134
  141. package/web/_astro/BoardApp.BEDWpzsr.js +0 -188
  142. package/web/_astro/BoardApp.DQG2xfEz.js +0 -1
  143. package/web/_astro/arc.C0rrflm_.js +0 -1
  144. package/web/_astro/channel.SRrg1P-w.js +0 -1
  145. package/web/_astro/diagram-2AECGRRQ.DJ0h9zgw.js +0 -43
  146. package/web/_astro/diagram-5GNKFQAL.DvPk1jYd.js +0 -10
  147. package/web/_astro/index.Bx6GY4RH.css +0 -1
  148. package/web/_astro/mermaid.core.kAZjgJHG.js +0 -301
@@ -262,6 +262,23 @@ states:
262
262
  printf 'FAIL run=%s checker not found — run superskill install sp\n' "$__runId" | tee ".spur/run/$__runId-idea-coverage.reason" >&2;
263
263
  printf 'FAIL\n' > ".spur/run/$__runId-idea-coverage.status";
264
264
  fi
265
+ # 0945 R2: derive the route facts ONCE at this boundary (0769 pattern) — guards read these
266
+ # named files instead of re-deriving design×needs_design inline. The same command is
267
+ # duplicated in feature-check's onEnter (YAML has no include); byte-equality is
268
+ # test-pinned (idea-pipeline-routing.test.ts). Missing/corrupt needs-design JSON fails
269
+ # safe to `design`; readiness is PASS only when both recorded checks are PASS.
270
+ # (warn) 7 commands: two three-way `test && printf || printf` derivations over captured
271
+ # signal files (ADR-115); no model hop, no CLI re-run.
272
+ - kind: shell
273
+ options:
274
+ command: >-
275
+ mkdir -p .spur/run &&
276
+ { test "$design" = skip -o "$design" = auto -a "$(jq -r .needs_design .spur/run/$__runId-idea-needs-design.json 2>/dev/null)" = false &&
277
+ printf 'skip\n' > .spur/run/$__runId-idea-design-route.txt ||
278
+ printf 'design\n' > .spur/run/$__runId-idea-design-route.txt; } &&
279
+ { test "$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" = PASS -a "$(cat .spur/run/$__runId-idea-coverage.status 2>/dev/null)" = PASS &&
280
+ printf 'PASS\n' > .spur/run/$__runId-idea-ac-ready.status ||
281
+ printf 'FAIL\n' > .spur/run/$__runId-idea-ac-ready.status; }
265
282
 
266
283
  - id: feature-check
267
284
  description: >
@@ -286,6 +303,19 @@ states:
286
303
  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
304
  decision:
288
305
  mode: never
306
+ # 0945 R2: same writer as ac-generate's onEnter (byte-equal, test-pinned) — refreshes the
307
+ # derived route facts after the interactive gate so both entries into this boundary read
308
+ # consistent files; hitl.confirm only sets $__hitlAnswer.
309
+ - kind: shell
310
+ options:
311
+ command: >-
312
+ mkdir -p .spur/run &&
313
+ { test "$design" = skip -o "$design" = auto -a "$(jq -r .needs_design .spur/run/$__runId-idea-needs-design.json 2>/dev/null)" = false &&
314
+ printf 'skip\n' > .spur/run/$__runId-idea-design-route.txt ||
315
+ printf 'design\n' > .spur/run/$__runId-idea-design-route.txt; } &&
316
+ { test "$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" = PASS -a "$(cat .spur/run/$__runId-idea-coverage.status 2>/dev/null)" = PASS &&
317
+ printf 'PASS\n' > .spur/run/$__runId-idea-ac-ready.status ||
318
+ printf 'FAIL\n' > .spur/run/$__runId-idea-ac-ready.status; }
289
319
 
290
320
  - id: system-design
291
321
  description: >
@@ -461,10 +491,12 @@ states:
461
491
  plan, ac, decisions, dependencies, premises) so the deterministic task
462
492
  check passes, then writes the run-scoped ready evidence sidecar
463
493
  (.spur/run/${vars.__runId}-idea-ready.json) with one row per task: wbs,
464
- status (ready|failed|skipped), planningDigest, and seven check rows.
465
- Handoff-finalize verifies presence, digest and checklist evidence before
466
- recommending auto runall; missing or failing evidence never fails the
467
- run — it degrades the recommendation to ready-depth refineall.
494
+ status (ready|failed|skipped), planningDigest, and seven check rows,
495
+ with the premises row carrying tree-verified path:line citations
496
+ (0947). Handoff-finalize verifies presence, digest, feature binding and
497
+ checklist evidence before recommending auto runall; missing or failing
498
+ evidence never fails the run — it degrades the recommendation to
499
+ ready-depth refineall.
468
500
  onEnter:
469
501
  - kind: agent.run
470
502
  options:
@@ -483,7 +515,9 @@ states:
483
515
  for feature ${vars.featureId} per sp:spur-dev
484
516
  references/planning-workflow.md § Step 5.6 (Ready preparation): read
485
517
  .spur/run/${vars.__runId}-idea-batch-create-result.json and write
486
- .spur/run/${vars.__runId}-idea-ready.json.
518
+ .spur/run/${vars.__runId}-idea-ready.json. The premises check row passes only
519
+ when each material premise was verified against the current tree and its evidence
520
+ cites at least one verified path:line (handoff-finalize lints it; task 0947).
487
521
  answerFile: .spur/run/${vars.__runId}-ready-prepare-answer.txt
488
522
  expectFile: .spur/run/${vars.__runId}-ready-prepare-answer.txt
489
523
  # Fail-closed shape validation (mirrors the order-sidecar guard). Absence is
@@ -563,6 +597,7 @@ transitions:
563
597
  command: 'test "$(cat .spur/run/$__runId-idea-precheck-doctor.status 2>/dev/null)" = PASS'
564
598
  - from: start
565
599
  to: failed
600
+ terminalReason: failed-check
566
601
  description: Agent doctor FAIL — stop before discovery.
567
602
  guard:
568
603
  kind: always
@@ -602,6 +637,7 @@ transitions:
602
637
  command: 'test "$__hitlAnswer" = yes'
603
638
  - from: idea-eval
604
639
  to: cancelled
640
+ terminalReason: cancelled
605
641
  description: Idea evaluation rejected or cancelled — no feature created.
606
642
  guard:
607
643
  kind: shell
@@ -617,9 +653,11 @@ transitions:
617
653
 
618
654
  # ── ac-generate: auto-skip (profile=auto) OR enter feature-check HITL gate (interactive) ──
619
655
  # Declaration order: auto-skip guards tried FIRST (same pattern as task-pipeline review→verify
620
- # and design-gen→handoff). Under profile=auto, the recorded `idea-ac-check` result and the
621
- # recorded requirement-coverage status (0887 R4) route directly to the appropriate next
622
- # state — guards never re-run the CLI or the checker (task 0769). Under interactive, the
656
+ # and design-gen→handoff). Under profile=auto, the derived route facts — the ready file (both
657
+ # recorded checks PASS, 0887 R4) and the design route file (0945 R2 writer at the end of both
658
+ # ac-generate and feature-check onEnter) — route directly to the appropriate next state:
659
+ # guards never re-run the CLI or the checker and never re-derive the signals (task 0769).
660
+ # Under interactive, the
623
661
  # always fallback enters the feature-check state whose onEnter hitl.confirm pauses for
624
662
  # operator confirmation (coverage is surfaced in that prompt; the operator's answer governs).
625
663
  #
@@ -627,25 +665,29 @@ transitions:
627
665
  - from: ac-generate
628
666
  to: system-design
629
667
  description: "profile=auto, check passed, requirements covered, design route — run system design."
630
- # (warn) 4 commands: one persistent multi-assignment line captures both statuses; `test -a` folds the
631
- # profile/ac and design/needs pairs (same operand semantics); guards never re-run the CLI (0769).
668
+ # 0945 R3: three predicates over derived facts — the ready file folds both recorded check
669
+ # statuses (PASS only when ac-check AND coverage are PASS), the route file folds
670
+ # design×needs_design (fail-safe design); nothing re-runs, nothing re-derives (0769).
632
671
  guard:
633
672
  kind: shell
634
673
  options:
635
674
  command: >-
636
- ac_status="$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" cov_status="$(cat .spur/run/$__runId-idea-coverage.status 2>/dev/null)";
637
- test "$profile" = auto -a "$ac_status" = PASS && test "$cov_status" = PASS && test "$design" = auto -a "$(jq -r .needs_design .spur/run/$__runId-idea-needs-design.json 2>/dev/null)" != false
675
+ test "$profile" = auto &&
676
+ test "$(cat .spur/run/$__runId-idea-ac-ready.status 2>/dev/null)" = PASS &&
677
+ test "$(cat .spur/run/$__runId-idea-design-route.txt 2>/dev/null)" = design
638
678
  # Auto-skip 2: pass + coverage + skip-design route → decompose
639
679
  - from: ac-generate
640
680
  to: decompose
641
681
  description: "profile=auto, check passed, requirements covered, skip-design route — go directly to decompose."
642
- # (warn) 4 test segments: profile + inlined ac/coverage reads + the OR'd design=skip/(design=auto AND
643
- # needs_design=false) pair folded into one `test` (`-a` binds tighter than `-o`), keeping one captured
644
- # signal file authoritative for both routes (0769).
682
+ # 0945 R3: mirror of the design-route guard over the same derived facts with route=skip;
683
+ # one captured signal file per fact keeps both routes symmetric (0769).
645
684
  guard:
646
685
  kind: shell
647
686
  options:
648
- command: 'test "$profile" = auto && test "$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" = PASS && test "$(cat .spur/run/$__runId-idea-coverage.status 2>/dev/null)" = PASS && test "$design" = skip -o "$design" = auto -a "$(jq -r .needs_design .spur/run/$__runId-idea-needs-design.json 2>/dev/null)" = false'
687
+ command: >-
688
+ test "$profile" = auto &&
689
+ test "$(cat .spur/run/$__runId-idea-ac-ready.status 2>/dev/null)" = PASS &&
690
+ test "$(cat .spur/run/$__runId-idea-design-route.txt 2>/dev/null)" = skip
649
691
  # Auto-skip 3: check or coverage failed, retry < 3 → loop back to ac-generate (self-loop)
650
692
  - from: ac-generate
651
693
  to: ac-generate
@@ -662,6 +704,7 @@ transitions:
662
704
  # Auto-skip 4: check or coverage failed, retry cap reached → escalate to failed
663
705
  - from: ac-generate
664
706
  to: failed
707
+ terminalReason: retry-exhausted
665
708
  description: "profile=auto, check or coverage failed after 3 retries — escalate to failed."
666
709
  # (warn) 5 commands: mirror of the retry guard with cap>=3; keeping escalation and retry as one
667
710
  # test-chain pair makes the cap boundary auditable in the diff (0769).
@@ -683,23 +726,27 @@ transitions:
683
726
  - from: feature-check
684
727
  to: system-design
685
728
  description: Feature check passed, design route — run system design.
686
- # (warn) 5 commands (named status capture + 4 conditions): HITL answer + captured status + design route; same shape as the
687
- # ac-generate auto-skips, reading the same captured signal files (0769).
729
+ # 0945 R3: three predicates over derived facts — the recorded ac-check status stays the
730
+ # conjunct here (parity: the operator's answer governs the interactive gate, 0887), the
731
+ # route file folds design×needs_design (fail-safe design); nothing re-runs (0769).
688
732
  guard:
689
733
  kind: shell
690
734
  options:
691
735
  command: >-
692
- ac_status="$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)";
693
- test "$__hitlAnswer" = yes && test "$ac_status" = PASS && test "$design" = auto && test "$(jq -r .needs_design .spur/run/$__runId-idea-needs-design.json 2>/dev/null)" != false
736
+ test "$__hitlAnswer" = yes &&
737
+ test "$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" = PASS &&
738
+ test "$(cat .spur/run/$__runId-idea-design-route.txt 2>/dev/null)" = design
694
739
  - from: feature-check
695
740
  to: decompose
696
741
  description: Feature check passed, skip-design route — go directly to decompose.
697
- # (warn) 5 test segments: same as the feature-check design route plus the OR'd
698
- # design=auto/needs_design=false pair (0769).
742
+ # 0945 R3: mirror of the design-route guard over the same derived facts with route=skip.
699
743
  guard:
700
744
  kind: shell
701
745
  options:
702
- command: 'test "$__hitlAnswer" = yes && test "$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" = PASS && (test "$design" = skip || (test "$design" = auto && test "$(jq -r .needs_design .spur/run/$__runId-idea-needs-design.json 2>/dev/null)" = false))'
746
+ command: >-
747
+ test "$__hitlAnswer" = yes &&
748
+ test "$(cat .spur/run/$__runId-idea-ac-check.status 2>/dev/null)" = PASS &&
749
+ test "$(cat .spur/run/$__runId-idea-design-route.txt 2>/dev/null)" = skip
703
750
  - from: feature-check
704
751
  to: ac-generate
705
752
  description: "Feature check failed — revise AC (retry cap: 3)."
@@ -713,6 +760,7 @@ transitions:
713
760
  (test "$__hitlAnswer" = no || test "$ac_status" != PASS) && test "$(cat .spur/run/$__runId-idea-ac-retry-count 2>/dev/null || echo 0)" -lt 3
714
761
  - from: feature-check
715
762
  to: failed
763
+ terminalReason: retry-exhausted
716
764
  description: Feature check failed after 3 retries — escalate to failed.
717
765
  # (warn) 5 commands (named status capture + 4 conditions): mirror of the revise guard with cap>=3 (0769).
718
766
  guard:
@@ -723,6 +771,7 @@ transitions:
723
771
  (test "$__hitlAnswer" = no || test "$ac_status" != PASS) && test "$(cat .spur/run/$__runId-idea-ac-retry-count 2>/dev/null || echo 0)" -ge 3
724
772
  - from: feature-check
725
773
  to: cancelled
774
+ terminalReason: cancelled
726
775
  description: Operator cancelled the feature-check gate.
727
776
  guard:
728
777
  kind: shell
@@ -768,6 +817,7 @@ transitions:
768
817
  command: 'test "$__hitlAnswer" = no && test "$(cat .spur/run/$__runId-idea-design-reject-count 2>/dev/null || echo 0)" -le 1'
769
818
  - from: design-approval
770
819
  to: failed
820
+ terminalReason: retry-exhausted
771
821
  description: "Design rejected after 1 revise - design-approval gate exhausted (R7 0433)."
772
822
  guard:
773
823
  kind: shell
@@ -775,6 +825,7 @@ transitions:
775
825
  command: 'test "$__hitlAnswer" = no && test "$(cat .spur/run/$__runId-idea-design-reject-count 2>/dev/null || echo 0)" -gt 1'
776
826
  - from: design-approval
777
827
  to: cancelled
828
+ terminalReason: cancelled
778
829
  description: Operator cancelled design approval.
779
830
  guard:
780
831
  kind: shell
@@ -812,6 +863,7 @@ transitions:
812
863
  command: 'test "$__hitlAnswer" = no'
813
864
  - from: batch-create
814
865
  to: cancelled
866
+ terminalReason: cancelled
815
867
  description: Operator cancelled batch creation.
816
868
  guard:
817
869
  kind: shell
@@ -841,6 +893,7 @@ transitions:
841
893
  command: 'test -f .spur/run/$__runId-idea-batch-create.failed && test "$(cat .spur/run/$__runId-idea-decompose-retry-count 2>/dev/null || echo 0)" -lt 3'
842
894
  - from: batch-create-run
843
895
  to: failed
896
+ terminalReason: retry-exhausted
844
897
  description: Batch-create failed after 3 retries — escalate to failed.
845
898
  guard:
846
899
  kind: shell
@@ -223,6 +223,7 @@ transitions:
223
223
  command: 'test "$(cat .spur/run/$__runId-pr-preflight.status 2>/dev/null)" = PASS'
224
224
  - from: preflight
225
225
  to: failed
226
+ terminalReason: failed-check
226
227
  description: Preflight red (detached HEAD, dirty tree, gh auth, no GitHub remote, or the current branch being the base branch) — stop before any publishing
227
228
  guard:
228
229
  kind: always
@@ -236,6 +237,7 @@ transitions:
236
237
  command: 'grep -qE "^(PASS|WARN)$" .spur/run/$__runId-pr-hygiene.status 2>/dev/null'
237
238
  - from: hygiene
238
239
  to: failed
240
+ terminalReason: failed-check
239
241
  description: BLOCK (secrets/.env/conflict markers) or probe failure — never submit a tainted diff
240
242
  guard:
241
243
  kind: always
@@ -249,6 +251,7 @@ transitions:
249
251
  command: 'grep -qE "^(PASS|SKIP)$" .spur/run/$__runId-pr-precheck.status 2>/dev/null'
250
252
  - from: precheck
251
253
  to: failed
254
+ terminalReason: failed-check
252
255
  description: Project checks red — do not spend a review request on code that fails its own gate
253
256
  guard:
254
257
  kind: always
@@ -262,6 +265,7 @@ transitions:
262
265
  command: 'grep -qE "^(PUSHED|UP_TO_DATE)$" .spur/run/$__runId-pr-push.status 2>/dev/null'
263
266
  - from: push
264
267
  to: failed
268
+ terminalReason: failed-check
265
269
  description: Push rejected (e.g. non-fast-forward) — report; never force-push as a workaround
266
270
  guard:
267
271
  kind: always
@@ -275,6 +279,7 @@ transitions:
275
279
  command: 'grep -qE "^(FOUND|CREATED)$" .spur/run/$__runId-pr-ensure.status 2>/dev/null'
276
280
  - from: ensure-pr
277
281
  to: failed
282
+ terminalReason: failed-check
278
283
  description: No reviewable delta or PR creation failed — report the actual git/GitHub state
279
284
  guard:
280
285
  kind: always
@@ -306,6 +311,7 @@ transitions:
306
311
  command: 'test "$(cat .spur/run/$__runId-pr-request.status 2>/dev/null)" = REQUESTED'
307
312
  - from: request
308
313
  to: failed
314
+ terminalReason: failed-check
309
315
  description: Request failed (no PR, gh error) — report the preserved error
310
316
  guard:
311
317
  kind: always
@@ -326,6 +332,7 @@ transitions:
326
332
  command: 'test "$(cat .spur/run/$__runId-pr-wait.status 2>/dev/null)" = TIMEOUT'
327
333
  - from: wait
328
334
  to: failed
335
+ terminalReason: failed-check
329
336
  description: Poll probe itself failed
330
337
  guard:
331
338
  kind: always
@@ -346,6 +353,7 @@ transitions:
346
353
  command: 'test "$(cat .spur/run/$__runId-pr-collect.status 2>/dev/null)" = PENDING'
347
354
  - from: collect
348
355
  to: failed
356
+ terminalReason: failed-check
349
357
  description: Collect probe failed
350
358
  guard:
351
359
  kind: always