@gobing-ai/spur 0.3.92 → 0.3.94

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 (119) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/pipeline-budgets.json +0 -7
  3. package/config/plugin-scripts.json +10 -0
  4. package/config/rules/boundary/test-subpath-boundary.yaml +48 -0
  5. package/config/rules/strict/runtime-boundaries.yaml +2 -1
  6. package/config/rules/structure/protected-files.yaml +4 -0
  7. package/config/templates/AGENTS.md +4 -0
  8. package/config/templates/docs/02_ROADMAP.md +2 -0
  9. package/config/templates/docs/03_ARCHITECTURE.md +3 -1
  10. package/config/templates/docs/04_DESIGN.md +2 -0
  11. package/config/templates/docs/99_PROJECT_CONSTITUTION.md +10 -2
  12. package/config/workflow-candidates.json +72 -1
  13. package/config/workflows/feature-verification.yaml +1 -0
  14. package/config/workflows/history-anatomy.yaml +2 -0
  15. package/config/workflows/idea-pipeline.yaml +67 -18
  16. package/config/workflows/pr-review.yaml +8 -0
  17. package/config/workflows/task-pipeline.yaml +171 -39
  18. package/config/workflows/wayfinder-resolution.yaml +5 -0
  19. package/config/workflows/wrapup-pipeline.yaml +55 -14
  20. package/package.json +9 -9
  21. package/plugins/sp/README.md +8 -3
  22. package/plugins/sp/commands/dev-review-session.md +4 -4
  23. package/plugins/sp/commands/dev-review.md +16 -5
  24. package/plugins/sp/commands/dev-run.md +2 -2
  25. package/plugins/sp/commands/dev-runall.md +2 -2
  26. package/plugins/sp/hooks/pi/guard-extension.ts +17 -36
  27. package/plugins/sp/lib/idea-handoff.generated.mjs +8 -4
  28. package/plugins/sp/lib/inline-run.generated.d.mts +3 -0
  29. package/plugins/sp/lib/inline-run.generated.mjs +48 -19
  30. package/plugins/sp/plugin.json +1 -1
  31. package/plugins/sp/scripts/inline-pipeline-parity-check.ts +1 -1
  32. package/plugins/sp/scripts/inline-run-setup.mjs +117 -7
  33. package/plugins/sp/scripts/inline-run-setup.ts +211 -7
  34. package/plugins/sp/scripts/quality-gate.mjs +255 -6
  35. package/plugins/sp/scripts/quality-gate.ts +425 -9
  36. package/plugins/sp/scripts/residual-scan.mjs +13 -5
  37. package/plugins/sp/scripts/residual-scan.ts +34 -7
  38. package/plugins/sp/scripts/task-diffstat.mjs +156 -0
  39. package/plugins/sp/scripts/task-diffstat.ts +229 -0
  40. package/plugins/sp/scripts/wrapup-drift-probe.mjs +181 -0
  41. package/plugins/sp/scripts/wrapup-drift-probe.ts +258 -0
  42. package/plugins/sp/scripts/wrapup-steps.mjs +60 -1
  43. package/plugins/sp/scripts/wrapup-steps.ts +89 -4
  44. package/plugins/sp/skills/brainstorm/SKILL.md +2 -0
  45. package/plugins/sp/skills/brainstorm/references/workflows.md +17 -2
  46. package/plugins/sp/skills/code-verification/SKILL.md +2 -2
  47. package/plugins/sp/skills/code-verification/references/secu-review.md +3 -2
  48. package/plugins/sp/skills/session-review/SKILL.md +11 -9
  49. package/plugins/sp/skills/spur-check/SKILL.md +112 -0
  50. package/plugins/sp/skills/spur-dev/SKILL.md +2 -1
  51. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +14 -2
  52. package/plugins/sp/skills/spur-dev/references/dev-operations.md +8 -2
  53. package/plugins/sp/skills/spur-dev/references/document-authoring.md +85 -0
  54. package/plugins/sp/skills/spur-dev/references/execution-batch.md +46 -18
  55. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +24 -3
  56. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +3 -2
  57. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +34 -2
  58. package/plugins/sp/skills/spur-dev/references/planning-workflow.md +5 -5
  59. package/plugins/sp/skills/spur-dev/templates/design.md +31 -0
  60. package/plugins/sp/skills/spur-dev/templates/plan.md +32 -0
  61. package/plugins/sp/skills/spur-doctor/SKILL.md +60 -14
  62. package/schemas/state-machine-workflow.schema.json +4 -0
  63. package/spur.js +19577 -19822
  64. package/web/_astro/BoardApp.C02hAHPO.js +1 -0
  65. package/web/_astro/{BoardApp.CerSBgis.js → BoardApp.FTEs3-N8.js} +107 -105
  66. package/web/_astro/{TaskDetail.DCqiC-OZ.js → TaskDetail.C-GdsS-t.js} +1 -1
  67. package/web/_astro/arc.uuAf51IT.js +1 -0
  68. package/web/_astro/{architectureDiagram-3BPJPVTR.DM_vp_hO.js → architectureDiagram-3BPJPVTR.CGe629A1.js} +1 -1
  69. package/web/_astro/{blockDiagram-GPEHLZMM.DXVIiv0p.js → blockDiagram-GPEHLZMM.D1mGCq3p.js} +1 -1
  70. package/web/_astro/{c4Diagram-AAUBKEIU.BbF_zCxW.js → c4Diagram-AAUBKEIU.CMsolcde.js} +1 -1
  71. package/web/_astro/channel.fsgl7o5j.js +1 -0
  72. package/web/_astro/{chunk-2J33WTMH.CAgQHpPC.js → chunk-2J33WTMH.CrGA3fik.js} +1 -1
  73. package/web/_astro/{chunk-4BX2VUAB.BN-5tpw4.js → chunk-4BX2VUAB.DsLVVla0.js} +1 -1
  74. package/web/_astro/{chunk-55IACEB6.CnPkEEr0.js → chunk-55IACEB6.Dxc59Tfi.js} +1 -1
  75. package/web/_astro/{chunk-727SXJPM.BQzQeMVm.js → chunk-727SXJPM.CaEVE2Wy.js} +4 -4
  76. package/web/_astro/{chunk-AQP2D5EJ.B6xNyDnL.js → chunk-AQP2D5EJ.BiJ4HXeI.js} +1 -1
  77. package/web/_astro/{chunk-FMBD7UC4.C7f9Ih78.js → chunk-FMBD7UC4.Mxf1fru5.js} +1 -1
  78. package/web/_astro/{chunk-ND2GUHAM.CNV1dFXT.js → chunk-ND2GUHAM.pyOWQixH.js} +1 -1
  79. package/web/_astro/{chunk-QZHKN3VN.Cudn2TkJ.js → chunk-QZHKN3VN.BmEsg4vr.js} +1 -1
  80. package/web/_astro/{classDiagram-4FO5ZUOK.D1NwP50q.js → classDiagram-4FO5ZUOK.BHhhMFTO.js} +1 -1
  81. package/web/_astro/{classDiagram-v2-Q7XG4LA2.D1NwP50q.js → classDiagram-v2-Q7XG4LA2.BHhhMFTO.js} +1 -1
  82. package/web/_astro/{cose-bilkent-S5V4N54A.B1wSL-Xb.js → cose-bilkent-S5V4N54A.2fH4YOlp.js} +1 -1
  83. package/web/_astro/{cynefin-OW5HDTMX.BmK52w8G.js → cynefin-OW5HDTMX.C2j1_lKL.js} +1 -1
  84. package/web/_astro/{dagre-BM42HDAG.Bfy5CTDT.js → dagre-BM42HDAG.hZ2NCTdT.js} +2 -2
  85. package/web/_astro/diagram-2AECGRRQ.Bfw5_EzK.js +43 -0
  86. package/web/_astro/diagram-5GNKFQAL.Bt1V_Tmk.js +10 -0
  87. package/web/_astro/{diagram-KO2AKTUF.CW_vMJ4z.js → diagram-KO2AKTUF.DEk-YFwp.js} +3 -3
  88. package/web/_astro/{diagram-LMA3HP47.B_8ZGF67.js → diagram-LMA3HP47.CDjndtQm.js} +1 -1
  89. package/web/_astro/{diagram-OG6HWLK6.BppnHsdS.js → diagram-OG6HWLK6.cFnUHScG.js} +1 -1
  90. package/web/_astro/{erDiagram-TEJ5UH35.BEuHXcjJ.js → erDiagram-TEJ5UH35.DlhYp7NV.js} +5 -5
  91. package/web/_astro/{flowDiagram-I6XJVG4X.CH-UlnGr.js → flowDiagram-I6XJVG4X.DNTpsxfx.js} +4 -4
  92. package/web/_astro/{ganttDiagram-6RSMTGT7.BO81S85v.js → ganttDiagram-6RSMTGT7.DC_p36PI.js} +1 -1
  93. package/web/_astro/{gitGraphDiagram-PVQCEYII.XnPxPPZN.js → gitGraphDiagram-PVQCEYII.DkEqNI0P.js} +1 -1
  94. package/web/_astro/{infoDiagram-5YYISTIA.JyjYRu_T.js → infoDiagram-5YYISTIA.CrjioCTG.js} +1 -1
  95. package/web/_astro/{ishikawaDiagram-YF4QCWOH.BBRBF-Fo.js → ishikawaDiagram-YF4QCWOH.BcK0CN8n.js} +5 -5
  96. package/web/_astro/{journeyDiagram-JHISSGLW.C_iymSyp.js → journeyDiagram-JHISSGLW.p0CbBDX1.js} +1 -1
  97. package/web/_astro/{kanban-definition-UN3LZRKU.DdfW-Oqt.js → kanban-definition-UN3LZRKU.puHIFt6J.js} +7 -7
  98. package/web/_astro/{linear.C2_IkbZT.js → linear.Bb-3a1d7.js} +1 -1
  99. package/web/_astro/mermaid.core.CJDgXOJs.js +301 -0
  100. package/web/_astro/{mindmap-definition-RKZ34NQL.DAZIxQSK.js → mindmap-definition-RKZ34NQL.BoAZEI9t.js} +2 -2
  101. package/web/_astro/{pieDiagram-4H26LBE5.CN8sIhKM.js → pieDiagram-4H26LBE5.CJNSdqY7.js} +3 -3
  102. package/web/_astro/{quadrantDiagram-W4KKPZXB.3dGcX5GP.js → quadrantDiagram-W4KKPZXB.DtTy7_0Z.js} +1 -1
  103. package/web/_astro/{requirementDiagram-4Y6WPE33.BV2y4dd6.js → requirementDiagram-4Y6WPE33.BNYV98Xg.js} +3 -3
  104. package/web/_astro/{sankeyDiagram-5OEKKPKP.Cqo15Tvo.js → sankeyDiagram-5OEKKPKP.DRq9DGHp.js} +4 -4
  105. package/web/_astro/{sequenceDiagram-3UESZ5HK.CROCPMJB.js → sequenceDiagram-3UESZ5HK.B7KdBFCm.js} +1 -1
  106. package/web/_astro/{stateDiagram-AJRCARHV.RfXZrkFE.js → stateDiagram-AJRCARHV.CD62ZJ2H.js} +1 -1
  107. package/web/_astro/{stateDiagram-v2-BHNVJYJU.CPXmbBs9.js → stateDiagram-v2-BHNVJYJU.CeVk1TAj.js} +1 -1
  108. package/web/_astro/{timeline-definition-PNZ67QCA.DdgKTiO8.js → timeline-definition-PNZ67QCA.C_ZPA5tT.js} +3 -3
  109. package/web/_astro/{vennDiagram-CIIHVFJN.CPNVSHF1.js → vennDiagram-CIIHVFJN.CrThO_FQ.js} +5 -5
  110. package/web/_astro/{wardleyDiagram-YWT4CUSO.CQhA0Jyr.js → wardleyDiagram-YWT4CUSO.DSZCA5nl.js} +3 -3
  111. package/web/_astro/{xychartDiagram-2RQKCTM6.n61BWyy4.js → xychartDiagram-2RQKCTM6.KI7baTuk.js} +1 -1
  112. package/web/index.html +1 -1
  113. package/config/workflows/decision-routing-example.yaml +0 -134
  114. package/web/_astro/BoardApp.eoTz0pZs.js +0 -1
  115. package/web/_astro/arc.CPwg6Rw0.js +0 -1
  116. package/web/_astro/channel.MYZLKNwy.js +0 -1
  117. package/web/_astro/diagram-2AECGRRQ.DhNnvUvX.js +0 -43
  118. package/web/_astro/diagram-5GNKFQAL.lTX5KwnS.js +0 -10
  119. package/web/_astro/mermaid.core.GAOYeSR0.js +0 -303
@@ -286,6 +286,13 @@ states:
286
286
  # a silent no-op routes the run to `failed` here instead of drifting
287
287
  # into test/review and being caught a full pass later.
288
288
  requireDiff: true
289
+ # Verification-only re-run admission (task 0976): when requireDiff
290
+ # sees zero non-corpus changes because the implementation already
291
+ # landed through another path, `spur task check <wbs>` PASS admits
292
+ # the empty implement as a certification pass; a check failure
293
+ # keeps the 0424 R3 empty-implement violation. Static option —
294
+ # deliberately no run-var knob (ADR-115).
295
+ requireDiffAllowCleanCheck: true
289
296
  # 0933 R26: escalation contract — the agent.run option names the QUESTION
290
297
  # file (the pause signal, deleted pre-dispatch for freshness); a paused
291
298
  # attempt (agent wrote its question there and exited 0) succeeds with
@@ -486,8 +493,8 @@ states:
486
493
  - id: test-recheck
487
494
  description: >
488
495
  Soft recheck after fixall with bounded SQLite-lock retry. Writes PASS|FAIL (always exit 0). Transitions
489
- branch to review (PASS), another test-fix (FAIL and under max attempts),
490
- or the pipeline `failed` state (FAIL and attempts exhausted) — never a
496
+ branch to `triage` (PASS — the 0943 lane router), `test-fail-triage` (FAIL — the 0943
497
+ failure-class router), or the pipeline `failed` state (corrupt status) — never a
491
498
  raw lifecycle abort that skips the terminal `failed` state.
492
499
  onEnter:
493
500
  # R4 (0703, ADR-071): bounded remediation mutated the tree by design, so the fresh evidence
@@ -510,6 +517,92 @@ states:
510
517
  command: >-
511
518
  mkdir -p .spur/run; if [ -f plugins/sp/scripts/quality-gate.ts ]; then bun plugins/sp/scripts/quality-gate.ts recheck; elif Q="$(superskill script path sp quality-gate.mjs 2>/dev/null)" && [ -f "$Q" ]; then node "$Q" recheck; else echo "quality gate failed closed — quality-gate script not found — run 'superskill install sp'" >&2; printf 'FAIL\n' > ".spur/run/$wbs-test-gate.status"; fi; exit 0
512
519
 
520
+ - id: triage
521
+ description: >-
522
+ Deterministic lane router between a green gate and the review/verify fork (0943 R1).
523
+ Writes the diffstat evidence file, honors a caller-set `mode` (never overridden), pins
524
+ the safety lane on sensitive paths or >400 changed lines without a model call (R2c),
525
+ otherwise consults `decide task-triage` (low → fast lane; anything else stays empty →
526
+ standard review path), and appends the triage route reason to
527
+ .spur/memory/task-pipeline-routes.log (R5). The `decide` action itself runs
528
+ unconditionally (the engine has no onEnter conditionals); its result is consulted only
529
+ when neither a caller mode nor the deterministic guard resolved the lane. The resolved
530
+ lane lands in the `mode` var for the triage → verify/review guards.
531
+ onEnter:
532
+ # (a) diffstat producer: task-diffstat.ts owns git reading and sensitive-path
533
+ # classification; shell only resolves it and fails closed (writes sensitive:true,
534
+ # which the pre-guard below maps to the safety lane).
535
+ - kind: shell
536
+ options:
537
+ command: >-
538
+ mkdir -p .spur/run; if [ -f plugins/sp/scripts/task-diffstat.ts ]; then bun plugins/sp/scripts/task-diffstat.ts --spur-bin "$spurBin"; elif D="$(superskill script path sp task-diffstat.mjs 2>/dev/null)" && [ -f "$D" ]; then node "$D"; else echo "task-diffstat failed closed — task-diffstat script not found — run 'superskill install sp'" >&2; printf '{"files":0,"insertions":0,"deletions":0,"paths":[],"sensitive":true}\n' > ".spur/run/$wbs-diffstat.json"; fi; exit 0
539
+ # (b)+(c) lane pre-guard BEFORE decide: a caller-set mode is projected verbatim (R2b);
540
+ # a sensitive path or >400 changed lines pins safety (R2c) and the decide result below
541
+ # is never consulted. A missing/malformed diffstat row (producer crashed or never ran,
542
+ # disk error) pins safety HERE: an empty mode file would let the low decide row project
543
+ # the fast lane downstream, so the "never to fast" fail-safe is enforced at the guard,
544
+ # not by the projection (the full-suite gate run exposed this fail-open path).
545
+ - kind: shell
546
+ options:
547
+ command: >-
548
+ mkdir -p .spur/run; if [ -n "$mode" ]; then printf '%s\n' "$mode" > ".spur/run/$wbs-mode.txt"; exit 0; fi; DF=".spur/run/$wbs-diffstat.json"; if ! jq -e 'type == "object"' "$DF" >/dev/null 2>&1; then printf 'safety\n' > ".spur/run/$wbs-mode.txt"; exit 0; fi; jq -r 'if .sensitive == true or ((.insertions // 0) + (.deletions // 0)) > 400 then "safety" else empty end' "$DF" 2>/dev/null > ".spur/run/$wbs-mode.txt"; exit 0
549
+ # (d) lane decision — degrades to the standard default whenever workflow.decideDecisionMaker
550
+ # is off (R4), so with the flag off this state is pure shell: no model call is made.
551
+ - kind: decide
552
+ options:
553
+ id: task-triage
554
+ method: choice
555
+ question: >-
556
+ The quality gate is green. Which verification lane does this diff deserve —
557
+ low (small, contained diff — fast lane), standard, or high caution?
558
+ choices: [low, standard, high]
559
+ default: standard
560
+ evidence:
561
+ - .spur/run/${vars.wbs}-diffstat.json
562
+ - ${vars.taskSpecPath}
563
+ resultFile: .spur/run/${vars.wbs}-triage.decision
564
+ # (d) project the decision: low → fast lane; anything else (standard/high, degraded
565
+ # default, missing row) leaves the mode empty → standard review path. A non-empty mode
566
+ # file (caller-set or deterministic-high) is never overridden.
567
+ - kind: shell
568
+ options:
569
+ command: >-
570
+ MF=".spur/run/$wbs-mode.txt"; [ -s "$MF" ] && exit 0; jq -r 'if .value == "low" then "fast" else empty end' ".spur/run/$wbs-triage.decision" 2>/dev/null > "$MF"; exit 0
571
+ # R5: append the triage route reason in the shared routes-log format.
572
+ - kind: shell
573
+ options:
574
+ command: >-
575
+ m="$(cat ".spur/run/$wbs-mode.txt")"; RUN_ID="$__runId"; [ -n "$RUN_ID" ] || RUN_ID="pipeline-$wbs"; mkdir -p .spur/memory; printf '%s %s %s\n' "$RUN_ID" "$wbs" "$(jq -rn --arg m "$m" --arg c "$mode" 'if $c != "" then ($c + ":caller-set") else {"fast":"fast:triage low lane","safety":"safety:triage deterministic-high","":"safety:triage standard lane"}[$m] // "safety:triage unrecognized mode" end')" >> .spur/memory/task-pipeline-routes.log
576
+ # (d) the resolved lane becomes the `mode` var for the triage → verify/review guards.
577
+ - kind: file.read.into-var
578
+ options:
579
+ path: .spur/run/${vars.wbs}-mode.txt
580
+ var: mode
581
+
582
+ - id: test-fail-triage
583
+ description: >-
584
+ Deterministic failure-class router on a red gate (0943 R3). The engine has no onEnter
585
+ conditionals, so the FAIL branch from `test`/`test-recheck` lands here as its own
586
+ deterministic state (the sanctioned alternative), while the green branch goes to
587
+ `triage`. `decide failure-class` reads the bounded gate findings and routes: fix →
588
+ test-fix (the bounded repair hop; its default, recorded as `source: default` when no
589
+ backend decides — 0976 R2), stop → failed with terminalReason failed-check. A
590
+ missing/corrupt decision fails closed to failed-check. (0976 R2 collapsed the former
591
+ `retryable` lane: the declared default made it unreachable on the inline path.)
592
+ onEnter:
593
+ - kind: decide
594
+ options:
595
+ id: failure-class
596
+ method: choice
597
+ question: >-
598
+ The quality gate failed. Is the failure fixable by the repair agent, or should
599
+ the run stop here?
600
+ choices: [fix, stop]
601
+ default: fix
602
+ evidence:
603
+ - .spur/run/${vars.wbs}-test-gate.findings
604
+ resultFile: .spur/run/${vars.wbs}-failure-class.decision
605
+
513
606
  - id: review
514
607
  description: Three-dimensional code review via /sp:dev-review (functional requirements traceability + SECUA framework (Security, Efficiency, Correctness, Usability, Architecture) + architecture depth), findings written to `## Review`.
515
608
  onEnter:
@@ -779,6 +872,7 @@ transitions:
779
872
  test "$size_status" = PASS && test "$evidence_status" = PASS && $spurBin task check $wbs
780
873
  - from: precheck
781
874
  to: failed
875
+ terminalReason: failed-check
782
876
  description: Size and/or task check failed — stop before implement.
783
877
  guard:
784
878
  kind: always
@@ -791,6 +885,7 @@ transitions:
791
885
  # fresh question file so a COMPLETED implement after max asks still routes to test.
792
886
  - from: implement
793
887
  to: failed
888
+ terminalReason: retry-exhausted
794
889
  description: Escalation bound exhausted — the agent paused again after maxEscalations operator answers.
795
890
  # 0933 R30 (guard-lines compression): thin predicate; the report note is written
796
891
  # by the failed state's onEnter when it observes a bound-exhausted pause.
@@ -826,38 +921,36 @@ transitions:
826
921
  command: 'test -n "$__hitlInput"'
827
922
  - from: escalate
828
923
  to: failed
924
+ terminalReason: cancelled
829
925
  description: Empty operator answer — give-up routes to failed (question + transcript preserved as evidence).
830
926
  guard:
831
927
  kind: shell
832
928
  options:
833
929
  command: 'test -z "$__hitlInput"'
834
- # Soft probe branching (declaration order: PASS first, then FAIL, then defense).
930
+ # Soft probe branching (declaration order: PASS → triage, FAIL → test-fail-triage, defense).
931
+ # 0943 R1/R3: the four former gate-PASS edges (test/test-recheck → verify/review, split on
932
+ # `$mode`) are replaced by the deterministic `triage` lane producer; a red gate lands in
933
+ # `test-fail-triage` where `decide failure-class` routes the failure instead of a static fixall.
835
934
  - from: test
836
- to: verify
837
- description: Quality gate already green and mode is fast — proportional fast path bypasses review.
838
- guard:
839
- kind: shell
840
- options:
841
- command: >-
842
- gate_status="$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)";
843
- test "$gate_status" = PASS && test "$mode" = fast
844
- - from: test
845
- to: review
846
- description: Quality gate already green and safety mode — proceed to review.
935
+ to: triage
936
+ description: Quality gate green — route the lane deterministically (triage, 0943 R1).
847
937
  guard:
848
938
  kind: shell
849
939
  options:
850
940
  command: >-
851
941
  gate_status="$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)";
852
- test "$gate_status" = PASS && test "$mode" != fast
942
+ test "$gate_status" = PASS
853
943
  - from: test
854
- to: test-fix
855
- description: Quality gate red — start bounded fixall loop.
944
+ to: test-fail-triage
945
+ description: Quality gate red — classify the failure before the repair hop (0943 R3).
856
946
  guard:
857
947
  kind: shell
858
948
  options:
859
949
  command: 'test "$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)" = FAIL'
860
- # Defense: missing/corrupt status — treat as FAIL path, not silent PASS.
950
+ # 0943 review P3#2: the former `test → test-fix` FAIL edge is removed — it was dead (the
951
+ # identical guard on test → test-fail-triage fires first) and a silent spec-bypass trap:
952
+ # restoring it would skip failure-class on every red gate. The always-defense below keeps
953
+ # pre-0943 corrupt-status behavior (fixall then recheck).
861
954
  - from: test
862
955
  to: test-fix
863
956
  description: Probe status missing/corrupt — attempt fixall then recheck.
@@ -868,51 +961,86 @@ transitions:
868
961
  description: Fixall finished — soft recheck the same quality gate.
869
962
  guard:
870
963
  kind: always
871
- # Recheck branching (PASS first; under-max FAIL → fixall again; exhausted → failed).
964
+ # Recheck branching (PASS → triage; red → test-fail-triage; defense). The two former
965
+ # static FAIL edges (under-max → test-fix, exhausted → failed retry-exhausted) moved into
966
+ # test-fail-triage's decision routing (0943 R3).
872
967
  - from: test-recheck
873
- to: verify
874
- description: Quality gate green after fixall and mode is fast — proportional fast path bypasses review.
968
+ to: triage
969
+ description: Quality gate green after fixall — route the lane deterministically (triage, 0943 R1).
875
970
  guard:
876
971
  kind: shell
877
972
  options:
878
973
  command: >-
879
974
  gate_status="$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)";
880
- test "$gate_status" = PASS && test "$mode" = fast
975
+ test "$gate_status" = PASS
881
976
  - from: test-recheck
882
- to: review
883
- description: Quality gate green after fixall and safety mode — proceed to review.
977
+ to: test-fail-triage
978
+ description: Still red after fixall — classify the failure (0943 R3).
884
979
  guard:
885
980
  kind: shell
886
981
  options:
887
982
  command: >-
888
983
  gate_status="$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)";
889
- test "$gate_status" = PASS && test "$mode" != fast
984
+ test "$gate_status" = FAIL
985
+ # Defense: corrupt recheck status — failed, not review.
890
986
  - from: test-recheck
891
- to: test-fix
892
- description: Still red and under qualityGateMaxFixAttempts — another fixall hop.
893
- # (warn) 5 commands: named gate status + fix attempts (legibility, 0874).
987
+ to: failed
988
+ terminalReason: failed-check
989
+ description: Recheck status missing/corrupt — stop at failed.
990
+ guard:
991
+ kind: always
992
+ # ── triage routing (0943 R1/R2): the lane producer replaced the four gate-PASS edges.
993
+ # mode=fast → verify; anything else (standard/high, deterministic-high, degraded default,
994
+ # caller-set non-fast) → review. Together the two guards are exhaustive, so triage never hangs.
995
+ - from: triage
996
+ to: verify
997
+ description: Triage resolved the fast lane (caller-set fast or task-triage low) — skip review.
998
+ guard:
999
+ kind: shell
1000
+ options:
1001
+ command: 'test "$mode" = fast'
1002
+ - from: triage
1003
+ to: review
1004
+ description: Triage resolved a review lane (standard/high, deterministic-high, or caller-set) — review.
1005
+ guard:
1006
+ kind: shell
1007
+ options:
1008
+ command: 'test "$mode" != fast'
1009
+ # ── failure-class routing (0943 R3): stop first (never mislabeled by the cap), then the
1010
+ # attempt cap, then the fix lane, then the fail-closed defense. Declaration order matters.
1011
+ - from: test-fail-triage
1012
+ to: failed
1013
+ terminalReason: failed-check
1014
+ description: Failure class stop — the run terminates at failed, never bypassed.
894
1015
  guard:
895
1016
  kind: shell
896
1017
  options:
897
1018
  command: >-
898
- gate_status="$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)";
899
- fix_attempts="$(cat .spur/run/$wbs-test-fix-attempt 2>/dev/null || echo 0)";
900
- test "$gate_status" = FAIL && test "$fix_attempts" -lt "$qualityGateMaxFixAttempts"
901
- - from: test-recheck
1019
+ jq -e '.value == "stop"' ".spur/run/$wbs-failure-class.decision" >/dev/null 2>&1
1020
+ - from: test-fail-triage
902
1021
  to: failed
903
- description: Still red after max fixall attempts — stop at failed (not silent abort).
904
- # (warn) 5 commands: named gate status + fix attempts (legibility, 0874).
1022
+ terminalReason: retry-exhausted
1023
+ description: Attempt cap reached — qualityGateMaxFixAttempts bounds the fix lane.
1024
+ # (warn) 5 commands: named fix attempts (legibility, 0874).
905
1025
  guard:
906
1026
  kind: shell
907
1027
  options:
908
1028
  command: >-
909
- gate_status="$(cat .spur/run/$wbs-test-gate.status 2>/dev/null)";
910
1029
  fix_attempts="$(cat .spur/run/$wbs-test-fix-attempt 2>/dev/null || echo 0)";
911
- test "$gate_status" = FAIL && test "$fix_attempts" -ge "$qualityGateMaxFixAttempts"
912
- # Defense: corrupt recheck status — failed, not review.
913
- - from: test-recheck
1030
+ test "$fix_attempts" -ge "$qualityGateMaxFixAttempts"
1031
+ - from: test-fail-triage
1032
+ to: test-fix
1033
+ description: Failure class fix and under the cap — the bounded repair hop, as before.
1034
+ guard:
1035
+ kind: shell
1036
+ options:
1037
+ command: >-
1038
+ jq -e '.value == "fix"' ".spur/run/$wbs-failure-class.decision" >/dev/null 2>&1
1039
+ # Defense: missing/corrupt failure-class decision — fail closed instead of silently repairing.
1040
+ - from: test-fail-triage
914
1041
  to: failed
915
- description: Recheck status missing/corrupt — stop at failed.
1042
+ terminalReason: failed-check
1043
+ description: Failure-class decision missing/corrupt — stop at failed.
916
1044
  guard:
917
1045
  kind: always
918
1046
  # ── review → approve, OR skip the HITL gate entirely when profile=auto (R4) ──
@@ -947,6 +1075,7 @@ transitions:
947
1075
  command: 'test "$__hitlAnswer" = yes'
948
1076
  - from: approve
949
1077
  to: failed
1078
+ terminalReason: cancelled
950
1079
  description: Operator rejected at the approval gate — report and stop.
951
1080
  guard:
952
1081
  kind: shell
@@ -954,6 +1083,7 @@ transitions:
954
1083
  command: 'test "$__hitlAnswer" = no'
955
1084
  - from: approve
956
1085
  to: cancelled
1086
+ terminalReason: cancelled
957
1087
  description: Operator cancelled at the approval gate.
958
1088
  guard:
959
1089
  kind: shell
@@ -1002,6 +1132,7 @@ transitions:
1002
1132
  test "$(cat .spur/run/$wbs-test-fix-attempt 2>/dev/null || echo 0)" -lt "$qualityGateMaxFixAttempts"
1003
1133
  - from: verify
1004
1134
  to: failed
1135
+ terminalReason: retry-exhausted
1005
1136
  description: >-
1006
1137
  Non-PASS with the fix budget exhausted, or a PASS/missing/malformed verdict whose proof
1007
1138
  block is absent or mismatched (task 0703 R5) — block before done; defense catch-all so the
@@ -1031,6 +1162,7 @@ transitions:
1031
1162
  test "$verdict" = PASS && test "$proof_digest" = "$proofDigest"
1032
1163
  - from: record
1033
1164
  to: failed
1165
+ terminalReason: failed-check
1034
1166
  description: Task check failed or proof evidence missing/malformed/mismatched — block before done.
1035
1167
  guard:
1036
1168
  kind: always
@@ -209,6 +209,7 @@ transitions:
209
209
  command: 'test "$(cat .spur/run/$__runId-wayfinder-precheck.status 2>/dev/null)" = PASS'
210
210
  - from: precheck
211
211
  to: failed
212
+ terminalReason: failed-check
212
213
  description: "Precheck FAIL — stop before delegation."
213
214
  guard:
214
215
  kind: always
@@ -221,6 +222,7 @@ transitions:
221
222
  command: 'test -s .spur/run/$__runId-wayfinder-answer.md'
222
223
  - from: investigate
223
224
  to: failed
225
+ terminalReason: failed-agent
224
226
  description: "Empty answer capture — investigate produced nothing to verify; stop rather than certify hollow evidence."
225
227
  guard:
226
228
  kind: shell
@@ -254,6 +256,7 @@ transitions:
254
256
  command: 'test "$__hitlAnswer" = yes'
255
257
  - from: approve
256
258
  to: cancelled
259
+ terminalReason: cancelled
257
260
  description: "Operator cancelled the research resolution."
258
261
  guard:
259
262
  kind: shell
@@ -261,6 +264,7 @@ transitions:
261
264
  command: 'test "$__hitlAnswer" = cancel'
262
265
  - from: approve
263
266
  to: failed
267
+ terminalReason: cancelled
264
268
  description: "Operator rejected the research resolution."
265
269
  guard:
266
270
  kind: shell
@@ -275,6 +279,7 @@ transitions:
275
279
  command: 'test "$(cat .spur/run/$__runId-wayfinder-final.status 2>/dev/null)" = PASS && test "$(cat .spur/run/$__runId-wayfinder-status.txt 2>/dev/null)" = done'
276
280
  - from: record
277
281
  to: failed
282
+ terminalReason: failed-check
278
283
  description: "Recording failed, was denied, or the task never reached done — stop without claiming completion."
279
284
  guard:
280
285
  kind: always
@@ -75,7 +75,7 @@
75
75
  "$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
76
76
  kind: state-machine
77
77
  name: wrapup-pipeline
78
- version: "4"
78
+ version: "5"
79
79
  description: "Post-execution wrap-up: doc-sync (doc drift + learning capture), metrics, feature-transition, branch-cleanup"
80
80
  iterationBound: 10
81
81
  initialState: start
@@ -128,7 +128,10 @@ states:
128
128
  missing or corrupted capture refuses progression. A validated empty list
129
129
  -> skipped; length > 0 && mode == fast -> fast-path (metrics-record,
130
130
  bypassing doc-sync); missing/unknown/conflict -> doc-sync (safety-path).
131
- Writes bounded machine-readable reason to reasonFile.
131
+ Writes bounded machine-readable reason to reasonFile. When the caller leaves
132
+ mode empty, a deterministic drift probe (0944) projects mode=fast only when
133
+ no changed path matches a doc-owned surface and every task's Solution
134
+ change map parsed — any doubt stays on the safety path.
132
135
  onEnter:
133
136
  - kind: note
134
137
  options:
@@ -148,21 +151,53 @@ states:
148
151
  echo "wrapup-steps failed closed — script not found — run 'superskill install sp'" >&2;
149
152
  printf 'FAIL\n' > ".spur/run/$__runId-wrapup-resolve.status";
150
153
  fi
151
- # (e) route-reason writer: one jq table lookup over the mode var over the
152
- # validated capture; workflow-local routing glue (0824). Runs AFTER validation
153
- # and reads ONLY .spur/run/<runId>-wrapup-tasks.json — never raw vars.tasks
154
- # (0783 R2/R5). A FAIL resolve exits without writing: the failed reason written
155
- # by validation stands, and the skip reason can never mask it. A missing or
156
- # corrupted capture fails the jq lookup (no skipped claim can be invented);
157
- # the failed defense edge owns the run.
154
+ # (0944 R1-R3) deterministic drift probe — runs ONLY when the caller left mode
155
+ # empty (a caller-set mode is projected verbatim and the probe never runs). It
156
+ # writes <runId>-drift-probe.json {clean,reasons,paths} and projects the wrapup
157
+ # mode by writing <runId>-mode.txt: caller mode verbatim, `fast` when the probe
158
+ # is clean, empty when dirty (the probe script fails safe on any lookup or parse
159
+ # problem; a missing script writes a dirty probe + empty mode here). The next
160
+ # action reads the mode file into vars.mode via file.read.into-var.
158
161
  - kind: shell
159
162
  options:
160
163
  command: >-
161
- mkdir -p .spur/run .spur/memory; RUN_ID="$__runId"; case "$RUN_ID" in '') echo "task-resolve: __runId is empty — refusing to write a route reason" >&2; exit 1 ;; esac;
162
- REASON_FILE=".spur/run/$RUN_ID-route-reason.txt"; case "$(cat ".spur/run/$RUN_ID-wrapup-resolve.status" 2>/dev/null)" in FAIL) exit 0 ;; esac;
163
- N=$(jq length ".spur/run/$RUN_ID-wrapup-tasks.json" 2>/dev/null);
164
- jq -rn --arg m "$mode" --arg n "$N" 'if $n == "0" then "skipped:empty task list" else {"fast":"fast:evidence complete+consistent","":"safety:missing evidence (mode empty)","unknown":"safety:unknown evidence quality","conflict":"safety:conflicting evidence"}[$m] // "safety:unrecognized evidence (mode=\($m))" end' > "$REASON_FILE";
165
- printf '%s %s\n' "$RUN_ID" "$(cat "$REASON_FILE")" >> .spur/memory/wrapup-routes.log
164
+ if [ -n "$mode" ]; then
165
+ printf '%s\n' "$mode" > ".spur/run/$__runId-mode.txt";
166
+ elif [ -f plugins/sp/scripts/wrapup-drift-probe.ts ]; then
167
+ bun plugins/sp/scripts/wrapup-drift-probe.ts;
168
+ elif W="$(superskill script path sp wrapup-drift-probe.mjs 2>/dev/null)" && [ -f "$W" ]; then
169
+ node "$W";
170
+ else
171
+ printf '{"clean":false,"reasons":["probe script not found"],"paths":[]}' > ".spur/run/$__runId-drift-probe.json";
172
+ printf '\n' > ".spur/run/$__runId-mode.txt";
173
+ fi
174
+ - kind: file.read.into-var
175
+ options:
176
+ path: .spur/run/${vars.__runId}-mode.txt
177
+ var: mode
178
+ # (e) route-reason writer: one table lookup over the projected mode var over
179
+ # the validated capture and the drift probe verdict; workflow-local routing
180
+ # glue (0824, moved behind the wrapup-steps locator in 0944 to stay inside the
181
+ # ADR-115 shell caps). Runs AFTER the probe/projection so the reason reflects
182
+ # the projected mode. Reads ONLY .spur/run/<runId>-wrapup-tasks.json and the
183
+ # probe verdict — never raw vars.tasks (0783 R2/R5). A FAIL resolve exits
184
+ # without writing: the failed reason written by validation stands, and the
185
+ # skip reason can never mask it. A clean probe yields `fast:drift-probe-clean`
186
+ # (0944); mode `safety` claims `safety:operator-forced doc-sync`; a missing or
187
+ # corrupted capture fails the lookup (no skipped or clean claim can be
188
+ # invented); the failed defense edge owns the run.
189
+ - kind: shell
190
+ options:
191
+ command: >-
192
+ mkdir -p .spur/run .spur/memory &&
193
+ if [ -f plugins/sp/scripts/wrapup-steps.ts ]; then
194
+ bun plugins/sp/scripts/wrapup-steps.ts route-reason;
195
+ elif W="$(superskill script path sp wrapup-steps.mjs 2>/dev/null)" && [ -f "$W" ]; then
196
+ node "$W" route-reason;
197
+ else
198
+ echo "wrapup-steps failed closed — script not found — run 'superskill install sp'" >&2;
199
+ printf 'FAIL\n' > ".spur/run/$__runId-wrapup-resolve.status";
200
+ fi
166
201
 
167
202
  - id: doc-sync
168
203
  description: >
@@ -367,6 +402,7 @@ transitions:
367
402
  # ── task-resolve: validation fail + proportional route table (0758 R1-R4, 0770) ──
368
403
  - from: task-resolve
369
404
  to: failed
405
+ terminalReason: failed-check
370
406
  description: >
371
407
  Validation FAIL (0770): malformed wrap input, a non-string/empty entry, an
372
408
  unresolved or non-completed task, or an empty __runId. Declared before the
@@ -402,6 +438,7 @@ transitions:
402
438
  command: 'test "$(jq length .spur/run/$__runId-wrapup-tasks.json 2>/dev/null || echo -1)" -gt 0 && test "$mode" != fast'
403
439
  - from: task-resolve
404
440
  to: failed
441
+ terminalReason: failed-check
405
442
  description: >
406
443
  Defense (0770) — no PASS/FAIL resolve status (shell crashed or never ran):
407
444
  route to `failed` rather than claiming a skip.
@@ -429,6 +466,7 @@ transitions:
429
466
  kind: action-ok
430
467
  - from: doc-sync
431
468
  to: failed
469
+ terminalReason: failed-check
432
470
  description: >
433
471
  Executor failure (non-zero exit, signal, or dispatch error) — keep the
434
472
  existing fail semantics; a contract violation never falls through here
@@ -458,6 +496,7 @@ transitions:
458
496
  # the metrics status PASS so a missing status can never claim success.
459
497
  - from: metrics-record
460
498
  to: failed
499
+ terminalReason: failed-check
461
500
  description: >
462
501
  Metrics capture failed for at least one task — a missing metrics row is
463
502
  recorded as failure, never silently omitted as success (0770).
@@ -490,6 +529,7 @@ transitions:
490
529
  # ── feature-transition: fail edge, then branch-cleanup (if merge) or done ──
491
530
  - from: feature-transition
492
531
  to: failed
532
+ terminalReason: failed-check
493
533
  description: >
494
534
  Required synchronization failed (0770): non-zero sync exit, an invalid
495
535
  sync result, or a failed feature gate. The failed status carries the
@@ -507,6 +547,7 @@ transitions:
507
547
  command: 'test "$(cat .spur/run/$__runId-wrapup-sync.status 2>/dev/null)" = PASS'
508
548
  - from: feature-verify
509
549
  to: failed
550
+ terminalReason: failed-check
510
551
  description: >
511
552
  Post-wrapup feature check failed (0915 F1): the bound receipt no longer
512
553
  validates against the current feature contract. Already-written
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/spur",
3
- "version": "0.3.92",
3
+ "version": "0.3.94",
4
4
  "description": "Spur CLI — local-first harness for mainstream coding agents: constraint checking, workflow orchestration, agent health, and history analytics. Bun-native; exposes the `spur` command.",
5
5
  "keywords": [
6
6
  "spur",
@@ -53,14 +53,14 @@
53
53
  },
54
54
  "devDependencies": {
55
55
  "@commander-js/extra-typings": "^14.0.0",
56
- "@gobing-ai/ts-db": "^0.5.5",
57
- "@gobing-ai/ts-ai-runner": "^0.5.5",
58
- "@gobing-ai/ts-dual-workflow-engine": "^0.5.5",
59
- "@gobing-ai/ts-infra": "^0.5.5",
60
- "@gobing-ai/ts-llm-jsonl-importer": "^0.5.5",
61
- "@gobing-ai/ts-rule-engine": "^0.5.5",
62
- "@gobing-ai/ts-runtime": "^0.5.5",
63
- "@gobing-ai/ts-utils": "^0.5.5",
56
+ "@gobing-ai/ts-db": "^0.5.9",
57
+ "@gobing-ai/ts-ai-runner": "^0.5.9",
58
+ "@gobing-ai/ts-dual-workflow-engine": "^0.5.9",
59
+ "@gobing-ai/ts-infra": "^0.5.9",
60
+ "@gobing-ai/ts-llm-jsonl-importer": "^0.5.9",
61
+ "@gobing-ai/ts-rule-engine": "^0.5.9",
62
+ "@gobing-ai/ts-runtime": "^0.5.9",
63
+ "@gobing-ai/ts-utils": "^0.5.9",
64
64
  "@types/bun": "1.3.14",
65
65
  "@types/figlet": "^1.7.0",
66
66
  "@types/node-notifier": "8.0.5",
@@ -102,7 +102,7 @@ list this README is checked against.
102
102
  | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
103
103
  | `dev-next` | Status-aware router — inspect a task (or next frontier under a feature), dispatch the best existing `/sp:dev-*` command, chain on clean success |
104
104
  | `dev-run` | Run a task — full pipeline (precheck→implement→test→review→approve→verify→record→done) or single-step (implement) |
105
- | `dev-review` | Multi-dimensional review for a task or path — functional requirements traceability, SECUA framework, and architectural depth |
105
+ | `dev-review` | Multi-dimensional review for a task or path (traceability, SECUA, architecture); `--triage` fixes small findings, files the rest as tasks |
106
106
  | `dev-pr-review` | GitHub Codex PR review — prepare/reuse a PR, request `@codex review`, collect findings, validate/fix/re-review (fix mode); workflow-backed spine |
107
107
  | `dev-verify` | Verify a task against its requirements and Acceptance Criteria — traceability check producing a PASS/PARTIAL/FAIL verdict with evidence |
108
108
  | `dev-unit` | Generate or extend tests until the unit target is met |
@@ -186,7 +186,7 @@ pipeline step.
186
186
 
187
187
  ```
188
188
  plugins/sp/
189
- ├── skills/ # Domain knowledge + workflow docs (38 skills)
189
+ ├── skills/ # Domain knowledge + workflow docs (39 skills)
190
190
  │ ├── brainstorm/ # Structured ideation workflow
191
191
  │ │ ├── agents/openai.yaml
192
192
  │ │ ├── examples/ideation-example.md
@@ -342,6 +342,7 @@ surface or run one workflow. All skills target the same five core platforms: `cl
342
342
  | `session-review` | 1.1 | Inline review of the active coding-agent session — compact outcomes, evidence-backed resolved/open issue classification, proposal-only improvements, and next actions; no workflow, import, delegation, or mutation |
343
343
  | `spur-composer` | 1.0 | Cross-noun composition — workflow catalog selection, the ephemeral→project→shared ladder, ADR-115 budgets, trace-driven rule tuning; applies accepted `spur-doctor` proposals through `spur` verbs; never judges its own output and never runs a recurring loop |
344
344
  | `spur-doctor` | 1.0 | Cross-noun evaluation — read-only CLI evidence per noun (task/feature/rule/workflow/agent spec), reflection over `history-anatomy` findings through a closed action-class map, and a proposal table; writes nothing; diagnoses artifacts, not runtime environments (`spur agent doctor`'s job) |
345
+ | `spur-check` | 1.0 | Two-tier check primitive (ADR-124) — light changed-scope checks during development, the full `bun run spur-check` chain at the quality boundary, and the fingerprint-bound `<wbs>-check-receipt.json` with the `status` reuse rule; composes with `/sp:dev-fixall --gate-log` |
345
346
  | `redesign-web-ui` | 1.0 | Existing-UI visual upgrade — audit generic AI fingerprints, apply in-stack polish against `DESIGN.md` / live tokens, verify behavior and viewports; does not migrate frameworks |
346
347
  | `taste-refactoring-api` | 1.0 | API design and refactoring for REST/HTTP, RPC/gRPC, GraphQL, event contracts, and CLI surfaces; compatibility, security, and migration review |
347
348
  | `taste-refactoring-ui` | 1.0 | UI design and refactoring with visual hierarchy, typography, spacing, color, and interaction review |
@@ -512,6 +513,7 @@ hold `SKILL.md` and prompt-side companions only.
512
513
  | `scripts/feature-sync-bounded.ts` | Bounded retry-suppression wrapper for `spur feature sync` during batch/wrap-up runs — suppresses identical L4-blocked repeats |
513
514
  | `scripts/stage-registry-adapter.ts` | dev-next golden-path adapter over the canonical stage registry — TABLE A/B/C resolution bridge for the status-aware facade |
514
515
  | `scripts/task-size-precheck.ts` | Pipeline size precheck guard (R2) — evaluates R-item/Plan-count limits to PASS/FAIL |
516
+ | `scripts/task-diffstat.ts` | 0943 triage-lane diffstat producer — numstat + untracked scan vs the run base; writes `<wbs>-diffstat.json` with the sensitive-path flag; fails safe (sensitive) |
515
517
  | `scripts/validate-flag-contracts.ts` | Mechanical consistency gate — compares flag claims across command files, flag-glossary, cross-cutting, dev-operations, and ADR; reports disagreements |
516
518
  | `*.test.ts` | Unit suites — in `hooks/` for guards, in `tests/<skill>/` per ADR-031 pairing |
517
519
 
@@ -629,7 +631,10 @@ pipeline owns one lifecycle phase:
629
631
  | `idea-pipeline.yaml` | Idea/planning → feature + tasks | `/sp:dev-idea`, `/sp:dev-plan` |
630
632
  | `wrapup-pipeline.yaml` | Post-execution wrap-up | `/sp:dev-wrap`, `/sp:dev-wrapall` |
631
633
  | `wayfinder-resolution.yaml` | Wayfinder ticket resolution loop | `spur workflow run` (free-form) |
632
- | `decision-routing-example.yaml` | DecisionMaker routing example (never / evidence / omitted modes, defer → operator pause) | `spur workflow run` (authoring sample) |
634
+
635
+ > 0946 (D64): the `decision-routing-example.yaml` authoring sample was retired from the catalogue
636
+ > (zero runs, example-only — `docs/design/workflow-catalogue-refactor.md` §10); the pattern lives on
637
+ > as a test fixture (`packages/app/tests/services/fixtures/decision-routing-example.yaml`).
633
638
 
634
639
  ### Lifecycle operations
635
640
 
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Review the active coding-agent session immediately: summarize outcomes, distinguish resolved and open issues with evidence, and propose bounded improvements. With --triage: apply pure-doc / one-to-two-line fixes inline, then file remaining findings as one new task. Triggers: review this session, session wrap-up, immediate retrospective, what happened, what was resolved, triage findings"
2
+ description: "Review the active coding-agent session immediately: summarize outcomes, distinguish resolved and open issues with evidence, and propose bounded improvements. With --triage: apply pure-doc / one-to-two-line fixes inline, then file remaining findings as one or more implement-ready tasks. Triggers: review this session, session wrap-up, immediate retrospective, what happened, what was resolved, triage findings"
3
3
  role: reviewer
4
4
  argument-hint: "[<focus>] [--triage]"
5
5
  allowed-tools: ["Bash", "Read", "Grep", "Glob", "Skill"]
@@ -11,8 +11,8 @@ Wraps the **sp:session-review** skill for a lightweight review of the active hos
11
11
  default it is report-only: current conversation plus read-only repository evidence, run inline so
12
12
  the session context is preserved — no workflow launch, history import, task creation, or
13
13
  remediation. With `--triage`, it first triages the findings, then applies direct fixes (pure
14
- documentation work and one-to-two-line fixes) inline and files everything remaining as exactly one
15
- new task for further fixing. The result includes a non-overlapping time breakdown with durations in
14
+ documentation work and one-to-two-line fixes) inline and files everything remaining as one or more
15
+ implement-ready tasks for further fixing. The result includes a non-overlapping time breakdown with durations in
16
16
  `M:SS` or `H:MM:SS` form and `n/a` for unavailable measurements.
17
17
 
18
18
  ## Argument Flags
@@ -20,7 +20,7 @@ new task for further fixing. The result includes a non-overlapping time breakdow
20
20
  | Flag | Description | Default |
21
21
  | --- | --- | --- |
22
22
  | `[<focus>]` | Optional question or operation to emphasize without excluding material session outcomes. | full active session |
23
- | `--triage` | After the report: bucket findings → apply pure-doc / 1–2-line fixes inline → create one task for the remainder. | off (report-only) |
23
+ | `--triage` | After the report: bucket findings → apply pure-doc / 1–2-line fixes inline → file the remainder as one or more implement-ready tasks. | off (report-only) |
24
24
 
25
25
  For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag-glossary.md).
26
26