@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
@@ -0,0 +1,112 @@
1
+ ---
2
+ name: spur-check
3
+ description: 'Two-tier check primitive for the sp pipeline: light (changed-scope biome, per-workspace typecheck, related tests) during development; full (bun run spur-check) once at the quality boundary. Reads/writes fingerprint-bound check receipts (.spur/run/<wbs>-check-receipt.json) and reuses a PASS full receipt only at the same proof digest.'
4
+ license: Apache-2.0
5
+ version: 1.0.0
6
+ metadata:
7
+ author: spur
8
+ platforms: "claude-code,codex,openclaw,opencode,antigravity,pi"
9
+ category: check-execution
10
+ interactions:
11
+ - pipeline
12
+ operations:
13
+ - check
14
+ - accumulate
15
+ - reuse
16
+ openclaw:
17
+ emoji: "🧾"
18
+ see_also:
19
+ - sp:spur-dev
20
+ - sp:spur-cli
21
+ - sp:code-verification
22
+ ---
23
+
24
+ # sp:spur-check — the two-tier check primitive (ADR-124)
25
+
26
+ One check primitive with two tiers behind the shipped `quality-gate` script
27
+ ([task 0939](../../../../docs/tasks5/0939_add-the-two-tier-spur-check-primitive-with-fingerprint-bound.md),
28
+ [workflow catalogue refactor §4](../../../../docs/design/workflow-catalogue-refactor.md)): light
29
+ checks accumulate during development, the full chain runs once at the quality boundary, and every
30
+ gate writes a fingerprint-bound receipt that downstream stages read instead of re-running checks.
31
+
32
+ ## Tiers
33
+
34
+ | Tier | Mode | When | Scope |
35
+ | --- | --- | --- | --- |
36
+ | `light` | `quality-gate.ts light` | after each implement/fix edit | `bunx biome check` on the changed files (`git diff --name-only HEAD` + untracked), `bun run typecheck` per touched workspace, and related tests (`<ws>/src/**/x.ts` → `<ws>/tests/**/x.test.ts` filename mapping) run via `cd <ws> && bun test …` — never from the repo root, whose bunfig preload does not apply inside the workspace |
37
+ | `full` | `quality-gate.ts run` | once at the task quality boundary (`test`) | today's chain: `bun run lint` + `bun run test-pre-check` + `bun run test` + `bun run test-post-check` (=`bun run spur-check`), with bounded findings, SQLite-busy retry, and the `recheck` probe |
38
+
39
+ Soft-fail contract: both tiers always exit 0; the verdict lives in files (`*-test-gate.status`,
40
+ receipt `status`), never in the exit code.
41
+
42
+ ## Receipt
43
+
44
+ `.spur/run/<wbs>-check-receipt.json`, schema `check-receipt/v1`:
45
+
46
+ ```json
47
+ {
48
+ "schemaVersion": "check-receipt/v1",
49
+ "wbs": "0939",
50
+ "runId": "pipeline-0939",
51
+ "tier": "full",
52
+ "inputDigest": "<proof-input digest>",
53
+ "checks": [{ "id": "test", "cmd": "…", "status": "PASS", "durationMs": 0, "logPath": "…" }],
54
+ "status": "PASS",
55
+ "completedAt": "2026-09-25T00:00:00.000Z"
56
+ }
57
+ ```
58
+
59
+ - `inputDigest` is the shared `ProofInputFingerprint` (task markdown + git tree of tracked
60
+ sources). The plugin never computes it — the pipeline captures it with the `proof.fingerprint`
61
+ action into `env.proofDigest` (ADR-124: no second fingerprint, no `@gobing-ai/*` import);
62
+ standalone callers use `inline-run-setup.ts --fingerprint`.
63
+ - Only `run`/`full` writes a reusable receipt. Without a digest, `run` writes no receipt and says
64
+ so in the gate log. The gate executes `qualityGateCmd` as one unit, so the full receipt carries a
65
+ single `test` row for the whole chain; `lint`, `typecheck`, `test-pre-check`,
66
+ `test-post-check` name the chain steps the full tier covers.
67
+ - `light` merges its rows under `tier: light` and skips any sub-check already `PASS` in a light
68
+ receipt at the same `{id, inputDigest}` (accumulation). Light rows never make a receipt
69
+ reusable for review.
70
+
71
+ ## Reuse rule
72
+
73
+ Check `status` mode before re-running a gate. Resolve the shipped script through the superskill
74
+ runtime (shipped surfaces never hard-code repo paths):
75
+
76
+ ```bash
77
+ QG="$(superskill script path sp quality-gate.mjs)"
78
+ bun "$QG" status # env: wbs, proofDigest → prints {"reuse":…,"reason":…}
79
+ ```
80
+
81
+ `reuse: true` only when the receipt is `status: PASS`, `tier: full`, and `inputDigest` equals the
82
+ current digest. Otherwise the reason is one of `missing | failed | stale | light-only`:
83
+
84
+ - `missing` — no readable receipt (or foreign schema version)
85
+ - `failed` — last full run failed
86
+ - `stale` — digest mismatch (or no current digest supplied)
87
+ - `light-only` — a valid PASS receipt that came from the light tier
88
+
89
+ Only `full` may satisfy a review/verify/record boundary: "review only after a green full gate" is
90
+ preserved by construction. `recheck` stays the no-progress probe path for fix loops.
91
+
92
+ ## Composition
93
+
94
+ - **Pipeline:** `sp:spur-dev` runs `run` at `test` and `recheck` at `test-recheck`; light mode
95
+ belongs to implement/fix edits, not to the gate state.
96
+ - **Fix loops:** `/sp:dev-fixall --gate-log` consumes `<wbs>-test-gate.log` (and the bounded
97
+ `<wbs>-test-gate.findings` anchors) after a red gate; it never writes receipts. A green fixall
98
+ output still requires a fresh `run` receipt before review.
99
+ - **Verification:** `sp:code-verification` and the review checklists read the receipt (status
100
+ mode) instead of re-running `bun run test`.
101
+ - **Feature scope:** `spur-check-feature` remains the ADR-119 repo-wide pass; this primitive is
102
+ task-local. A public `spur check` verb is out of scope without separate consent.
103
+
104
+ ## Gotchas
105
+
106
+ 1. **Never value-import `@gobing-ai/*` into the script** — the plugin standalone contract fails
107
+ the install; the digest arrives via `env.proofDigest`.
108
+ 2. **Never run light tests from the repo root** — the workspace `bunfig.toml` preload (coverage,
109
+ thresholds) only applies inside the workspace; `cd <ws> && bun test …` is the contract.
110
+ 3. **Light is a filter, not a boundary** — unmapped files (root-level scripts, non-src layouts)
111
+ are simply not covered by light; the full tier is the safety net. Do not widen the mapping
112
+ without an ADR.
@@ -116,7 +116,7 @@ reference for the half you're operating; do not duplicate its content here.
116
116
  | Feature check gate | planning | `spur feature check` | [planning-workflow.md](references/planning-workflow.md) |
117
117
  | Decomposition (dispatch) | planning | `task-batch.schema.json` | `sp:spec-decomposition` competency — the spine dispatches, does not inline |
118
118
  | Batch-create gate | planning | `spur task batch-create` | [planning-workflow.md](references/planning-workflow.md) |
119
- | Design doc | planning | — (prompt work; §4.5/T9) | [planning-workflow.md](references/planning-workflow.md) |
119
+ | Design doc | planning | — (§4.5/T9) | [document-authoring.md](references/document-authoring.md) |
120
120
  | Refine | planning | `spur task update --section` | [planning-workflow.md](references/planning-workflow.md) |
121
121
  | Batch refine | planning | `sp:dev-refineall` → per-task `refine` | [dev-operations.md](references/dev-operations.md) § refineall · [planning-workflow.md](references/planning-workflow.md) |
122
122
  | Task selection | execution | `spur task list` | [execution-workflow.md](references/execution-workflow.md) |
@@ -246,6 +246,7 @@ for "what's actually in file Y" or for resources that sit outside the step seque
246
246
  - `idea-pipeline.yaml` — the front-half state machine (absorbed the retired
247
247
  planning-pipeline in D5-K; `/sp:dev-plan` routes here, ADR-072).
248
248
  - `templates/bdd/gherkin.md` — the BDD scenario template.
249
+ - `templates/plan.md` and `templates/design.md` — plan and design starting points.
249
250
 
250
251
  ## Platform Notes
251
252
 
@@ -120,6 +120,14 @@ This is **the same rule, not an exception**: `--agent` names who does the thinki
120
120
  the thinking happens in the stages. Selecting an executor for a loop that runs no prompts would be
121
121
  meaningless.
122
122
 
123
+ **Fleet executor (0942, ADR-126, opt-in).** A workflow run may opt its `agent.run` stages into the
124
+ agent fleet control plane by mapping the pipeline selector to `executor: 'fleet'` (dev-run /
125
+ dev-runall `--agent fleet`). The stage dispatches to a fleet member through the fleet coordination
126
+ surface instead of spawning a subprocess; a subprocess fallback happens only when the run declares
127
+ `executorFallback: 'traditional'`, and an unavailable fleet otherwise fails the stage explicitly
128
+ (0937 `failed-agent`). This is an additional `agent.run` transport — it does not change the
129
+ `--agent` selector semantics documented above, and the interactive driver never resolves to it.
130
+
123
131
  **Interactive task pipelines invert control into the host session (ADR-047 amendment).**
124
132
  `dev-run --mode full` and sequential `dev-runall` with omitted `--agent` or explicit `--agent
125
133
  inline` interpret the existing `task-pipeline.yaml` in the host session; they do not launch `spur
@@ -785,8 +793,12 @@ The Design Approval Gate is the taste gate between system design and decompositi
785
793
  **The `needs_design` signal routing:**
786
794
 
787
795
  The signal is emitted by the `discovery` state's brainstorm dispatch and written to
788
- `.spur/run/idea-needs-design.json`. The `feature-check` state's transition guards read it to
789
- determine routing:
796
+ `.spur/run/idea-needs-design.json`. A deterministic shell action at the end of the `ac-generate`
797
+ and `feature-check` onEnter lists (0945 R2) folds `design` × `needs_design` once into
798
+ `.spur/run/<runId>-idea-design-route.txt` (`design` | `skip`; missing/corrupt JSON fails safe to
799
+ `design`) and the two recorded check statuses into `.spur/run/<runId>-idea-ac-ready.status`
800
+ (`PASS` only when both are PASS). The transition guards read those derived files to determine
801
+ routing — they never re-derive the signal inline (0769):
790
802
 
791
803
  | `design` var | `needs_design` signal | Route |
792
804
  | --- | --- | --- |
@@ -68,7 +68,7 @@ each would be scope creep for one-liner procedures.
68
68
  | # | Operation | Command | Backing | Skill / Verb | Arg-hint |
69
69
  | --- | ---------- | ------------------- | ----------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
70
70
  | 1 | unit | `dev-unit` | `Skill()` | `sp:code-testing` | `<target> [--coverage <pct>] [--agent <inline\|auto\|name>] [--auto]` |
71
- | 2 | review | `dev-review` | `Skill()` | `sp:code-verification` (`review`) + `sp:functional-review` + `sp:code-improvement` | `[<wbs\|path>] [--agent <inline\|auto\|name>] [--focus <dims>] [--fix (deprecated)]` |
71
+ | 2 | review | `dev-review` | `Skill()` | `sp:code-verification` (`review`) + `sp:functional-review` + `sp:code-improvement` | `[<wbs\|path>] [--agent <inline\|auto\|name>] [--focus <dims>] [--triage] [--worktree [<name>]]` |
72
72
  | 3 | verify | `dev-verify` | `Skill()` | `sp:code-verification` (`verify`) | `<wbs> [--agent <inline\|auto\|name>] [--fix <none\|blockers-first\|all>] [--focus <lens>] [--bdd] [--auto] [--force] [--next] [--skip-shippable]` |
73
73
  | 3a | verifyall | `dev-verifyall` | `Skill()` → agent | `sp:spur-dev` (`verifyall`) | `--tasks <selector> [--feature <id>] [--agent <inline\|auto\|name>] [--fix <none\|blockers-first\|all>] [--focus <lens>] [--bdd] [--auto] [--force] [--next] [--json] [--skip-shippable] [--worktree [<name>]]` |
74
74
  | 4 | run | `dev-run` | `Skill()` | `sp:spur-dev` (`run` / `implement`) | `<wbs> [--mode <full\|implement>] [--agent <inline\|auto\|name>] [--auto] [--next] [--wrap] [--continue] [--worktree [<name>]]` |
@@ -116,7 +116,13 @@ must not be changed without updating the backing skill.
116
116
  - **Modes:**
117
117
  - **WBS mode (`<wbs>`)**: Runs functional requirements traceability (`sp:functional-review`), SECUA framework (`sp:code-verification`), and architectural depth (`sp:code-improvement`). The three skills return review fragments; the coordinator writes the combined `## Review` (F92 0593 R1).
118
118
  - **Path mode (`<path>`)**: Runs advisory SECUA framework (`sp:code-verification`) and architectural depth (`sp:code-improvement`). Performs no task mutation.
119
- - **Inputs:** `<wbs|path>` (required). Review executes inline (in-session) by default. `--agent <inline|auto|name>` selector accepted (see [SSOT](cross-cutting.md#inline-default-execution-surface)). `--focus <lens>` narrows to one SECUA dimension. Note: `--fix` and `--next` are **deprecated** (no-op with warning; route remediation to `/sp:dev-verify --fix` and progression to `/sp:dev-next`).
119
+ - **Inputs:** `<wbs|path>` (required). Review executes inline (in-session) by default. `--agent <inline|auto|name>` selector accepted (see [SSOT](cross-cutting.md#inline-default-execution-surface)). `--focus <lens>` narrows to one SECUA dimension. `--triage` opts into bounded remediation after the report (below). `--worktree [<name>]` isolates the triage writes (below; requires `--triage`). Note: `--fix` and `--next` are **deprecated** (no-op with warning; route remediation to `--triage` or `/sp:dev-verify --fix` and progression to `/sp:dev-next`). The task pipeline's review stage never passes `--triage` or `--worktree`.
120
+ - **Triage (`--triage`):** runs inline in the invoking session after the merged report — never inside `sp:super-reviewer` or the review skills, which stay report-only. With `--agent <name>`, only the review is delegated; triage still runs inline on the returned findings. Never fix straight from the raw findings list:
121
+ 1. **Bucket every finding exactly once.** **Direct fix** — local, low-risk, obvious root cause: no design choice, no public-surface / schema / dependency change, not a shared write path, verifiable by a targeted check (docs, a guard, a missing throw, a wrong path helper, a stale comment). **Task** — real and actionable but needs design, crosses modules, touches a public surface, or is not verifiable locally; skip it when an existing task already owns it (cite that WBS). **Note** — pre-existing, environmental, or ownerless; report only.
122
+ 2. **Apply direct fixes** — smallest surgical diff in project style, then re-verify each with its targeted check (focused test, lint, or the exact command that exhibited the defect). A fix that grows beyond the bar or fails its check moves to the Task bucket with what was learned; do not leave it half-applied.
123
+ 3. **File the Task bucket as one or more tasks**, one per cohesive unit of work that one agent can implement and verify in one run — split unrelated fixes, merge findings that share a root cause or file set. File under the existing feature that owns the affected surface; if none fits, create a child feature under the closest existing parent — never a new root feature. Write through the CLI-gated corpus surface only (`spur task create --feature <id> --skip-ready`, then `spur task update <wbs> --section <s> --from-file`). Each task must meet the implement-ready bar ([§ 5. refine](#5-refine), `--depth ready`) so it cannot drift: per finding the evidence (`file:line`), the defect, the chosen fix direction with rejected alternatives, file targets, AC, and out-of-scope; promote `backlog → todo` only when `spur task check <wbs> --json` is clean. Name what the direct fixes already resolved in each task's Background.
124
+ 4. **Gate and report.** Run the project gate once after the direct fixes. Report a Triage section: each applied fix (path + one-line what + verification), each filed task (WBS + feature + scope), and the Notes. Never commit or create a branch outside `--worktree`.
125
+ - **Worktree (`--worktree [<name>]`):** omitted → all writes land in the current working tree on the current branch; no branch creation, checkout, or commit (the operator commits). Given → the [execution-batch.md § Worktree isolation](execution-batch.md#worktree-isolation---worktree-name) lifecycle as a run of one: marker `command` = `dev-review`, `selector` = the review target, derived branch/directory slug = the WBS or the path's basename (`sp/review-<slug>-<short-id>`). Admission is "the target resolves" (a known WBS or an existing path) — no `quickReadiness` task-set check. Review and triage both run in the tree; WT-3b commits the fixes and filed tasks. The WT-4 success condition reads as "every direct fix passed its check and the project gate is green"; a failed check or gate takes the WT-5 retention path. Rejected without `--triage` (WT-7) — to review another worktree read-only, pass a path inside it.
120
126
  - **Backing:** `sp:functional-review`, `sp:code-verification` (review mode), `sp:code-improvement`.
121
127
  - **Behavior:** WBS mode runs functional traceability + SECUA + architecture depth, ranking findings P1–P4, and hands the merged report to the review coordinator, which writes `## Review`. Component skills never write `## Review` in coordinated mode. Path mode runs advisory SECUA + architecture depth with no task mutation.
122
128
  - **Delegation:** WBS mode: `sp:functional-review` + `sp:code-verification` (review) + `sp:code-improvement`; Path mode: `sp:code-verification` (review) + `sp:code-improvement`.
@@ -0,0 +1,85 @@
1
+ ---
2
+ name: document-authoring
3
+ description: Light Markdown contracts for plan records and non-UI design satellites.
4
+ see_also:
5
+ - spur-dev
6
+ - planning-workflow
7
+ - doc-evolve
8
+ ---
9
+
10
+ # Plan and design document authoring
11
+
12
+ Use [plan.md](../templates/plan.md) for a new `docs/plans/*.md` working record and
13
+ [design.md](../templates/design.md) for a new `docs/design/*.md` non-UI contract satellite.
14
+ The project constitution owns their authority and maintenance; these templates are writing aids,
15
+ not parser schemas. Keep Markdown readable even when frontmatter is absent in a legacy file.
16
+
17
+ | Document | Job | Authority |
18
+ | --- | --- | --- |
19
+ | `docs/plans/` | Ordered work: intended outcome, premises, dependencies, execution sequence, verification, and follow-up. Older proposals and investigations remain working records. | Working record. Accepted conclusions take effect in their owner, such as an ADR, feature, roadmap, or design satellite. |
20
+ | `docs/design/` | Issue, context, solution, and its observable non-UI contract | Governed satellite of `docs/04_DESIGN.md`; label proposals and current behavior separately. |
21
+
22
+ ## Compose a new file
23
+
24
+ 1. Choose the owner before writing. Reuse an existing satellite when it already owns the surface.
25
+ Keep root `DESIGN.md` for UI rules and `03_ARCHITECTURE.md` for current system topology.
26
+ 2. Copy the relevant template. Replace placeholders. Keep `kind`, a descriptive `title`, a
27
+ truthful `status`, `created_at`, `updated_at`, `related` links, and `tags` for categorization.
28
+ Use ISO dates; leave `related` or `tags` empty when none apply. Keep one H1 matching the title.
29
+ 3. Use headings for the reader's question. The template's prompts are a starting shape: remove
30
+ inapplicable sections and keep specialized sections required by the producing workflow, such as
31
+ a brainstorm's `## Design Summary`. Number new sections in reading order. Plans make the
32
+ execution sequence and its premises usable; designs explain the issue, context, solution, and
33
+ observable contract. Never fill empty boilerplate.
34
+ 4. For a design satellite, write detail first, then add its pointer to `04_DESIGN.md` if missing.
35
+ Update an existing index row only when its indexed facts change. Do not put task receipts there.
36
+
37
+ ## Frontmatter vocabulary
38
+
39
+ Soft conventions for consistency and tag filtering, not a validator. Unknown values stay readable.
40
+
41
+ | Field | Values |
42
+ | --- | --- |
43
+ | `kind` | `plan` for any `docs/plans/` record, `design` for any `docs/design/` satellite. Nothing else. |
44
+ | `status` (plan) | `draft`, `proposed`, `approved`, `in-progress`, `done`, `superseded` |
45
+ | `status` (design) | `proposed`, `accepted`, `implemented`, `superseded` |
46
+ | `tags` | Ordered: one record-type tag, then owning feature ids (for example `H14`), then at most two area tags. |
47
+ | `related` | Repo-relative paths or feature/task ids; no prose. |
48
+
49
+ Record-type tags — plan: `brainstorm`, `proposal`, `investigation`, `audit`, `map`, `execution`,
50
+ `evidence`; design: `contract` (observable surface) or `system` (internal mechanism). Area tags:
51
+ `cli`, `server`, `web`, `workflow`, `planning`, `history`, `observability`, `agent`, `plugin`,
52
+ `docs`, `config`. A project may extend the area list; reuse a tag already in the corpus
53
+ (`rg -n '^tags:' docs/plans docs/design`) before adding one.
54
+
55
+ A producing workflow may keep its own keys beside these, such as a brainstorm's `needs_design` and
56
+ `run_id`, and its own section shape. The shared fields still apply.
57
+
58
+ ## Revise an existing file
59
+
60
+ Read the whole file and its inbound links first. Preserve the filename, meaningful headings,
61
+ anchors, dates, decisions, and historical status. Add missing metadata from evidence; label
62
+ unknowns instead of guessing. Restructure only where clarity improves, and keep a forwarding
63
+ heading when an anchor cannot be migrated safely. Update `updated_at` only for a substantive edit.
64
+ Do not turn an old proposal into a claim about current behavior without checking the owning source.
65
+
66
+ Legacy metadata upgrade:
67
+
68
+ - **Map** `date` → `created_at` and `feature`/`feature_id`/`task_wbs`/`parent_task` → `related`.
69
+ `title` is the H1 text; `topic` maps to `title` only when the file has no H1, otherwise drop it.
70
+ - **Owners:** when no owner key exists, a feature or task record that links the file
71
+ (`rg -l <filename> docs/features <task dir>`) is evidence for `related`. Ids found only in body
72
+ prose are not; requirement and priority labels look like feature ids.
73
+ - **Keep** workflow and provenance keys unchanged (`needs_design`, `run_id`, `doc`, `authority`,
74
+ `owns`, `read_before`, `edit_rules`, `version`, `derived_from`).
75
+ - **Dates:** `created_at` comes from a legacy `date`, else the filename date prefix, else the first commit
76
+ (`git log --follow --diff-filter=A --format=%as -- <file> | tail -1`), else leave it out and flag it.
77
+ `updated_at` is the existing value or the last commit date; do not bump it for a metadata-only edit.
78
+ - **Status:** use the vocabulary value only when the legacy value or body states it unambiguously
79
+ (`shipped`/`implemented`/`built …` → `implemented`; `approved-with-feedback` → `approved`).
80
+ Otherwise keep the legacy value and flag it for the operator. No status is better than a guessed one.
81
+ - **Headings:** never renumber or rename legacy headings; numbering applies to new files only.
82
+
83
+ For a bounded, read-only review of legacy files, use `sp:spur-doctor`. Apply accepted document
84
+ proposals in place using this guide, then use `sp:doc-evolve` to check affected key-document sync.
85
+ No bulk conversion or strict format check is required to read or maintain existing documents.
@@ -270,7 +270,7 @@ Only two flags cross the orchestrator→pipeline boundary; both are merged into
270
270
  | Flag | Effect on per-task `--vars` |
271
271
  | --- | --- |
272
272
  | `--auto` | sets `"profile":"auto"` (skips the HITL approve gate). Omitting it forwards nothing, so the pipeline uses its default profile (standard — HITL pause surfaces to the operator). (R4.2) |
273
- | `--agent <value>` | omit/`inline` in interactive sequential mode selects the host driver and is not forwarded. `auto` or a name sets **both** `"agent":"<value>"` and `"implementAgent":"<value>"` so every workflow `agent.run` step — including implement — spawns that executor. Headless omit/inline falls through the executor precedence chain. To pin ONLY implement, pass `--vars '{"implementAgent":"..."}'` separately; that explicit var selects the subprocess path. (R4.3, tasks 0483/0503) |
273
+ | `--agent <value>` | omit/`inline` in interactive sequential mode selects the host driver and is not forwarded. `auto` or a name sets **both** `"agent":"<value>"` and `"implementAgent":"<value>"` so every workflow `agent.run` step — including implement — spawns that executor. Headless omit/inline falls through the executor precedence chain. To pin ONLY implement, pass `--vars '{"implementAgent":"..."}'` separately; that explicit var selects the subprocess path. (R4.3, tasks 0483/0503) The opt-in `fleet` value instead maps the run to `"executor":"fleet"`: every `agent.run` stage dispatches through the agent fleet control plane (0942/ADR-126) and neither `agent` nor `implementAgent` is pinned. |
274
274
 
275
275
  The host session remains the orchestrator for interactive sequential omit/inline. `sp:super-planner`
276
276
  owns explicit-executor and parallel paths; there the flag pins the per-task step executor, not the
@@ -490,16 +490,25 @@ Evidence persistence precedes destructive cleanup: a persistence failure (unread
490
490
  disk-full, missing directory) routes to **WT-5** — the worktree and branch are retained so a green
491
491
  batch can never destroy its own evidence. Reuse mode retains its operator-owned tree but still
492
492
  persists the Step 5 report under the invoking tree; the reused tree's `.spur/run/` remains the live
493
- copy while that tree lives on.
494
-
495
- **Stage records are worktree-local too (0948 R9, E7 Finding 5).** The persisted report and verdict
496
- JSONs above are the batch's *summary* evidence. Each task's own per-stage run record
497
- (`.spur/run/<runId>.md` + `.state.json`, plus gate/answer artifacts) is written inside the
498
- worktree's `.spur/run/` and **is removed with the worktree** in create mode. A merged batch
499
- therefore leaves no per-stage run record in the invoking tree unless it is copied out. Anything
500
- auditing "what did this batch actually run?" must copy those records out **before** WT-4 removal —
501
- the E7 batch lost exactly this evidence this way. The rule is the same one above: copy out first,
502
- then remove; a copy failure retains the worktree.
493
+ copy while that tree lives on. The per-run provenance — the worktree DB's run/action rows and the
494
+ `.spur/run/<runId>.md` + `.state.json` records — is persisted mechanically by WT-4a's
495
+ `inline-run-setup.ts --persist-out --from <worktree>` call, not by hand.
496
+
497
+ **Stage records are worktree-local too (0948 R9, E7 Finding 5; persisted by 0975 R1).** Each task's
498
+ own per-stage run record (`.spur/run/<runId>.md` + `.state.json`) and the worktree DB's run rows are
499
+ written inside the worktree and **are removed with it** in create mode — the E7 batch lost exactly
500
+ this evidence. Copying them out is no longer a manual audit-time duty: WT-4a (create-mode block
501
+ below) runs `inline-run-setup.ts --persist-out --from "$WT_PATH"` **before** WT-4b holder cleanup,
502
+ which copies the run/action/phase/transition/workflow-state rows and both record files into the
503
+ invoking tree. The shapes are pinned (task 0975 R1): idempotent on re-persist; success exits 0
504
+ printing `{"ok":true,"persisted":<n>,"skipped":[{"id":<run-id>,"reason":"id-exists"|"external-key-conflict"|"record-conflict:<file>"}]}`
505
+ — an `id-exists` / `external-key-conflict` skip never modifies the pre-existing target rows, a
506
+ `record-conflict:<file>` skip never overwrites a divergent invoking-tree record — and any failure
507
+ exits 1 printing `{"ok":false,"error":<message>}` (a worktree DB run id that is not a single safe
508
+ filename component is rejected before any target write). Any persist-out failure
509
+ routes to **WT-5** — worktree and branch retained — the same copy-out-first contract as the
510
+ verdict persistence above. After a green persist-out, `spur workflow progress --json` in the
511
+ invoking tree shows the merged run `done` with its per-action rows.
503
512
 
504
513
  ## Step 6 — Batch wrap (`--wrap` / `--next`) (F96 task 0952 R1)
505
514
 
@@ -538,7 +547,7 @@ all subsequent tools, agents, task/feature writes, and run artifacts use the con
538
547
  tree's cwd. A stale or empty selector, an unsupported mode, or an invalid target creates no tree and
539
548
  no marker (WT-2/WT-7), and the required Git safety checks (WT-1) still precede creation.
540
549
 
541
- > **Command wiring (task 0814 R3).** The four worktree-capable commands (`dev-run`, `dev-runall`,
550
+ > **Command wiring (task 0814 R3).** The four task-set worktree commands (`dev-run`, `dev-runall`,
542
551
  > `dev-refineall`, `dev-verifyall`) each call `quickReadiness` with their operation (`run`/`refine`/
543
552
  > `verify`), the resolved selector/status, and the filtered-set size **before** WT-1/WT-2. The
544
553
  > admission outcome gates the tree: an invalid/empty selector, unsupported mode, or a target that
@@ -557,6 +566,13 @@ non-PASS verify verdict, or a HITL pause that ends the run take the WT-5 retenti
557
566
  full pipeline is eligible — `--worktree --mode implement` is rejected (WT-7), because that mode is
558
567
  the pipeline's implement stage and already runs in the driver's tree.
559
568
 
569
+ **Review triage `dev-review` (run of one).** `/sp:dev-review <target> --triage --worktree [<name>]`
570
+ runs this lifecycle around one review-plus-triage pass: WT-1…WT-6 apply unchanged, the marker's
571
+ `command` is `dev-review` and its `selector` is the review target, and the slug is the WBS or the
572
+ path's basename (`sp/review-<slug>-<short-id>`). It skips `quickReadiness` (there is no task set;
573
+ admission is "the target resolves"). WT-4 success reads as "every direct fix passed its check and the
574
+ project gate is green"; anything else takes WT-5. Contract: [dev-operations.md § 2. review](dev-operations.md#2-review).
575
+
560
576
  One flag, two modes (see the glossary entry for the ownership rule). Bare `--worktree` is **create
561
577
  mode** (cut a fresh branch + sibling tree). `--worktree <name>` is **reuse mode** (attach to a tree
562
578
  that already exists); name resolution (§ WT-2 below) runs before WT-1. The deltas each mode applies
@@ -805,13 +821,23 @@ git checkout "$BASE_REF"
805
821
  [ "$(git rev-list --count "$BASE_SHA..$BRANCH")" -gt 0 ] \
806
822
  || { echo "halt: branch carries no commits - nothing to merge" >&2; false; } # -> WT-5
807
823
  git merge --ff-only "$BRANCH" # FF-only: never rebase, merge-commit, or resolve conflicts
808
- # if FF succeeded — WT-4a evidence persistence (Step 5, task 0720 R3) runs FIRST:
809
- # persist the batch report + verdict artifacts into the invoking tree's .spur/run/
810
- # before anything below touches the worktree. Persistence failure routes to WT-5.
824
+ # if FF succeeded — WT-4a evidence persistence runs FIRST (Step 5, task 0720 R3):
825
+ # persist the batch report + verdict artifacts AND the per-run provenance (task
826
+ # 0975 R1) into the invoking tree before anything below touches the worktree.
827
+ # Any persistence failure routes to WT-5 — the worktree and branch are retained.
828
+ WT_PATH="$(cd "../<worktree-dir>" && pwd)" # hoisted: needed by WT-4a AND WT-4b below
829
+ # WT-4a provenance persist-out (task 0975 R1): copy the worktree DB's run rows plus
830
+ # the .spur/run/<runId>.md + .state.json records into THIS tree. Run from the main
831
+ # tree (cwd = the invoking tree). Idempotent; conflicts are reported, never
832
+ # overwritten. A non-zero exit — including a half-readable worktree — must NOT
833
+ # proceed to WT-4b removal:
834
+ SETUP_SCRIPT="plugins/sp/scripts/inline-run-setup.ts"
835
+ [ -f "$SETUP_SCRIPT" ] || SETUP_SCRIPT="$(superskill script path sp inline-run-setup.mjs 2>/dev/null)"
836
+ bun "$SETUP_SCRIPT" --persist-out --from "$WT_PATH" \
837
+ || { echo "halt: worktree run-record persist-out failed - worktree retained (WT-5)" >&2; exit 1; }
811
838
  #
812
- # WT-4b — bounded CWD-holder cleanup (task 0720 R1). Resolve the EXACT absolute
813
- # worktree path; a relative path or a stale entry matches the wrong processes.
814
- WT_PATH="$(cd "../<worktree-dir>" && pwd)"
839
+ # WT-4b — bounded CWD-holder cleanup (task 0720 R1). $WT_PATH above is the EXACT
840
+ # absolute worktree path; a relative path or a stale entry matches the wrong processes.
815
841
  # Holders = processes with any open fd under the worktree tree (lsof +D walks the
816
842
  # tree; CWD holders are the common case but +D also catches open-file holders —
817
843
  # over-match errs toward removal success; a plain -t <dir> matches only the
@@ -976,6 +1002,8 @@ fallback, because `<name>` was explicit and unambiguous intent.
976
1002
  - **`--mode implement`** is rejected when combined with `--worktree` on `dev-run` — that mode *is*
977
1003
  the pipeline's implement stage (bug-742) and runs in whatever tree the driver set up; a second
978
1004
  worktree would split one task's evidence across two trees.
1005
+ - **`dev-review` without `--triage`** is rejected when combined with `--worktree` — a read-only
1006
+ review writes nothing worth isolating; review another worktree by passing a path inside it.
979
1007
  - **No** create-with-name (`--worktree <name>` never creates; an unresolvable name is an error),
980
1008
  no `--worktree-keep` variant, no auto-cleanup of stale worktrees or markers from prior runs.
981
1009
 
@@ -69,6 +69,14 @@ inline is the default selector and omitted/explicit `inline` resolve identically
69
69
  the concrete coding-agent tool; `executor` remains the domain-layer role and is not a command flag.
70
70
  `inline` and `auto` are reserved values — config validation rejects an executor claiming either.
71
71
 
72
+ **Fleet executor (0942, ADR-126, opt-in).** On the pipeline selectors (`dev-run`, `dev-runall`),
73
+ `--agent fleet` maps the workflow run to the executor var `executor: 'fleet'`: every `agent.run`
74
+ stage dispatches through the agent fleet control plane instead of spawning a subprocess, with a
75
+ subprocess fallback only when the run declares `executorFallback: 'traditional'`; otherwise an
76
+ unavailable fleet fails the stage loudly (0937 `failed-agent`). `fleet` is deliberately not part of
77
+ the `<inline|auto|name>` selector grammar above — the value table and the executor precedence chain
78
+ are unchanged. Contract: [fleet-config-declaration.md](../../../../../docs/design/fleet-config-declaration.md).
79
+
72
80
  #### `--inline` (removed — collapsed into `--agent`)
73
81
 
74
82
  **Anchor:** `#flag-inline` (stub retained to avoid dangling external links).
@@ -402,6 +410,17 @@ Full checklist: [dev-operations.md](dev-operations.md) § refine (depth ready).
402
410
  Use the task's Gherkin scenarios as the verification lens on verify-family commands (`dev-verify`,
403
411
  `dev-verifyall`).
404
412
 
413
+ ### `--triage` — fix small findings, file the rest as tasks
414
+
415
+ **Anchor:** `#flag-triage`.
416
+
417
+ Review commands (`dev-review`, `dev-review-session`): after the report, bucket every finding once
418
+ (direct fix / task / note), apply the direct fixes inline with a targeted check each, and file the
419
+ remainder through `spur task` — never fix straight from the raw findings list. Off by default
420
+ (report-only). Both file one or more implement-ready tasks sized per cohesive unit, under existing
421
+ features ([dev-operations.md § 2. review](dev-operations.md#2-review)); `dev-review-session` keeps
422
+ the stricter direct-fix bar (pure docs / one-to-two-line fixes).
423
+
405
424
  ### `--approve-taste` — pre-clear all taste gates this run
406
425
 
407
426
  **Anchor:** `#flag-approve-taste`.
@@ -414,9 +433,11 @@ flag sets both.
414
433
 
415
434
  **Anchor:** `#flag-worktree`.
416
435
 
417
- Batch commands plus single-task `dev-run` (`dev-refineall`, `dev-runall`, `dev-verifyall`,
418
- `dev-run`): run the entire driver loop inside an isolated git worktree instead of the operator's
419
- working directory. One flag, two modes:
436
+ Batch commands plus single-task `dev-run` and review triage (`dev-refineall`, `dev-runall`,
437
+ `dev-verifyall`, `dev-run`, `dev-review`): run the entire driver loop inside an isolated git
438
+ worktree instead of the operator's working directory. On `dev-review` the flag requires `--triage`
439
+ and wraps the review-plus-triage pass
440
+ ([dev-operations.md § 2. review](dev-operations.md#2-review)). One flag, two modes:
420
441
 
421
442
  - **Create mode** — bare `--worktree` (no value). Cut a fresh branch from the current HEAD's ref,
422
443
  create a sibling worktree with a derived name, run the batch there. On a fully successful batch
@@ -89,8 +89,9 @@ Entered before `task-pipeline.yaml` `review` state dispatches `sp:code-verificat
89
89
 
90
90
  - [ ] The implementation matches the task's `## Plan` checklist (every checked item maps to a code/test/doc change).
91
91
  - [ ] `git status` shows only changes traceable to this task's Plan (no drive-by edits).
92
- - [ ] Lint and typecheck pass (`bun run lint`).
93
- - [ ] Tests pass (`bun run test`) — no `.skip`, `xfail`, or commented-out tests.
92
+ - [ ] Check receipt current: `quality-gate.ts status` reports `reuse: true` for
93
+ `.spur/run/<wbs>-check-receipt.json` at the current digest; run `bun run spur-check` only
94
+ when it reports stale or missing (0940 — never re-run the full chain on a reusable receipt).
94
95
  - [ ] New `biome-ignore` / `eslint-disable` suppressions: none, or each is justified inline.
95
96
  - [ ] No new `console.*` in scripts (use a project logger if one exists).
96
97
  - [ ] The `## Solution` section records the file:line change map and rationale.
@@ -23,7 +23,7 @@ the resolved actions and guards of every `.spur/workflows/*.yaml`; any element p
23
23
  in one and absent in the other fails the check. Add a new kind here when the driver
24
24
  implements it; remove the entry when the corresponding kind is dropped from the YAML.
25
25
 
26
- **Actions:** `shell` · `note` · `doctor.probe` · `file.read.into-var` · `hitl.confirm` · `hitl.input` · `hitl.select` · `agent.run` · `proof.fingerprint` · `run.artifact` · `command.gate`
26
+ **Actions:** `shell` · `note` · `doctor.probe` · `file.read.into-var` · `hitl.confirm` · `hitl.input` · `agent.run` · `proof.fingerprint` · `run.artifact` · `command.gate` · `decide`
27
27
 
28
28
  **Guards (transitions):** `always` · `shell` · `action-ok` · `contract-violation`
29
29
 
@@ -497,6 +497,27 @@ The driver reaches it through the existing run delegate (`$SETUP_SCRIPT`,
497
497
  (0887 R8), so `completed_at − started_at == duration_ms` exactly; a back-date failure is
498
498
  recorded (`action.backdate`) and never affects the run.
499
499
 
500
+ - **A `decide` action (0941)** — the driver never executes the DecisionMaker itself; it delegates
501
+ to the same app runner the engine registers, which writes the resultFile row (schemaVersion 1)
502
+ and returns the decision, then the delegate records the `action_runs` row (`kind=decide`)
503
+ through the same writer as every other action:
504
+
505
+ ```bash
506
+ bun "$SETUP_SCRIPT" --decide --run-id "$RUN_ID" --node <state-id> --options-json <options-file>
507
+ ```
508
+
509
+ The options JSON mirrors the YAML `decide` options (`id`, `method: choice|noul`, `question`,
510
+ `choices`/`default`, optional `evidence`, optional `minConfidence`, `resultFile`); paths resolve
511
+ against the project workdir. The decision never pauses and never fails the run for model
512
+ problems: a degraded outcome (feature switch off, no backend, error, timeout, low confidence)
513
+ prints `ok:true` with `degraded:true`, the declared `reason`, and `value = default`, and exits
514
+ `0` — route on the resultFile's `.value` with the declared file guards. Every row carries
515
+ `source: model|default` (0976 R2), and the delegate appends
516
+ `decide node=<id> value=<v> source=<s> reason=<r>` to the run log, so a declared-default
517
+ fallback is never read as a model decision. Only an invalid options
518
+ schema exits `1` (fail closed), and usage errors exit `2`. The `action_runs` trace row is
519
+ best-effort exactly like `--action`.
520
+
500
521
  - **At the run's declared terminal state** — before the driver reports the run complete, close the
501
522
  row so a successful inline run is never left non-terminal for `spur workflow clean` to reap as
502
523
  stale:
@@ -506,7 +527,18 @@ The driver reaches it through the existing run delegate (`$SETUP_SCRIPT`,
506
527
  ```
507
528
 
508
529
  `--status` is the declared terminal state's verdict, not a guess: a run that reached a terminal
509
- state is `done`; a run halted by a failing action under its error policy is `failed`.
530
+ state is `done`; a run halted by a failing action under its error policy is `failed`. On success
531
+ the close reports the recorded evidence: `{"ok":true,"runId":…,"actionRows":<n>}`.
532
+
533
+ **Zero-row done closes are a named failure (task 0975 R2).** A run closed `done` with **zero**
534
+ `action_runs` rows (`actionRows:0`) finalizes the row but exits `1` with
535
+ `{"ok":false,"code":"NO_ACTION_ROWS","actionRows":0}` — a run that claims success without a
536
+ single recorded action is exactly the untraced-runs gap ADR-117 closes, so the driver must
537
+ surface the code in its final report instead of reporting a clean close. The failure must NOT
538
+ be repaired by backfilling rows: the run row is already terminal, and hand-written rows are
539
+ forbidden (ADR-117) — record the finding and let the task's evidence show the gap. A `failed`
540
+ close with zero rows stays a clean `0` (a halt before the first boundary legitimately records
541
+ nothing), and any `done` close with `actionRows ≥ 1` exits `0`.
510
542
 
511
543
  **Best-effort at the action boundary only (ADR-117).** An `--action` persistence failure is
512
544
  recorded — the delegate appends a `trace-emission-failed` line to `.spur/run/<run-id>.md` and
@@ -198,11 +198,11 @@ task Design.
198
198
  order (§4.5 rule 5 / sync trigger **T9**):
199
199
 
200
200
  1. **Satellite first.** Write/update `docs/design/<slug>.md`. `<slug>` is the stable grep anchor —
201
- derive it from the feature name (kebab-case), and **reuse the existing slug** on re-runs. Capture
202
- the chosen approach + one-line reason, rejected alternatives, key interface/type **signatures**
203
- (not bodies), invariants, and the surface it touches. Do **not** restate the satellite file format
204
- here — follow the shape of existing satellites (`docs/design/server-side-adjustment-design.md`,
205
- `workflow-observability.md`).
201
+ derive it from the feature name (kebab-case), and **reuse the existing slug** on re-runs. For a
202
+ new file use [document-authoring.md](document-authoring.md) and its design template; for an
203
+ existing file preserve its headings and anchors. Capture the chosen approach + one-line reason,
204
+ rejected alternatives, key interface/type **signatures** (not bodies), invariants, and the
205
+ surface it touches.
206
206
  2. **Index second.** Add or update the satellite's row in `docs/04_DESIGN.md §0` (the `| Satellite |
207
207
  Area | Status |` table) — pointer + one-line area + status only, never a restatement of the body.
208
208
 
@@ -0,0 +1,31 @@
1
+ ---
2
+ kind: design
3
+ title: <specific non-UI contract or system design>
4
+ status: proposed
5
+ created_at: YYYY-MM-DD
6
+ updated_at: YYYY-MM-DD
7
+ related: []
8
+ tags: []
9
+ ---
10
+
11
+ # <Specific non-UI contract or system design>
12
+
13
+ ## 1. Issue and scope
14
+
15
+ <Specific issue or tasks this design addresses, observed impact, boundaries, and whether the solution is proposed or current. Link the owning records.>
16
+
17
+ ## 2. Context and constraints
18
+
19
+ <Relevant current behavior, evidence for the issue, and constraints the solution must respect. Link to 03 for wider architecture.>
20
+
21
+ ## 3. Solution
22
+
23
+ <Chosen approach and how it resolves the issue. Show ownership, boundaries, and flow; distinguish proposed behavior from implemented behavior.>
24
+
25
+ ## 4. Contract and compatibility
26
+
27
+ <Observable inputs, outputs, defaults, errors, invariants, edge cases, and migration behavior needed to implement or use the solution. Omit inapplicable parts.>
28
+
29
+ ## 5. Tradeoffs and open questions
30
+
31
+ <Why this solution was chosen, material costs or alternatives, and unresolved questions or follow-up. Link ADR decisions instead of restating them.>
@@ -0,0 +1,32 @@
1
+ ---
2
+ kind: plan
3
+ title: <specific title>
4
+ status: draft
5
+ created_at: YYYY-MM-DD
6
+ updated_at: YYYY-MM-DD
7
+ related: []
8
+ tags: []
9
+ ---
10
+
11
+ # <Specific title>
12
+
13
+ ## 1. Objective and outcome
14
+
15
+ <Issue or tasks this plan addresses, intended result, scope, and how completion will be recognized. Link the owning feature or tasks.>
16
+
17
+ ## 2. Premises and dependencies
18
+
19
+ <Facts, assumptions, prerequisites, decisions, and blockers that affect the sequence. Link evidence; mark unverified premises.>
20
+
21
+ ## 3. Execution sequence
22
+
23
+ 1. <Action, prerequisite, and tangible output or checkpoint. Name an owner when coordination matters.>
24
+ 2. <Next action. Show dependencies and safe parallel work explicitly.>
25
+
26
+ ## 4. Risks and verification
27
+
28
+ <What could change the sequence, the fallback or decision point, and how the intended result will be verified.>
29
+
30
+ ## 5. Follow-up
31
+
32
+ <Handoff, remaining actions, and deferred work with owners or links when known. Omit if none.>