@gobing-ai/spur 0.3.99 → 0.4.1

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 (172) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/config.global.yaml +17 -0
  3. package/config/decisions/gates.yaml +36 -0
  4. package/config/decisions/history-anatomy.yaml +35 -0
  5. package/config/decisions/idea-pipeline.yaml +38 -0
  6. package/config/decisions/task-pipeline.yaml +55 -0
  7. package/config/plugin-scripts.json +25 -0
  8. package/config/rules/boundary/sp-runtime-path.yaml +2 -0
  9. package/config/rules/docs/sourced-api-claims.yaml +60 -0
  10. package/config/rules/quality/coverage-gate.yaml +5 -3
  11. package/config/rules/recommended-pre-check.yaml +8 -3
  12. package/config/rules/strict/runtime-boundaries.yaml +11 -0
  13. package/config/rules/structure/protected-files.yaml +3 -0
  14. package/config/rules/structure/scratch-evidence-pointer.yaml +35 -0
  15. package/config/script-placement-baseline.json +2 -2
  16. package/config/workflows/feature-lifecycle.yaml +9 -2
  17. package/config/workflows/history-anatomy.yaml +22 -0
  18. package/config/workflows/idea-pipeline.yaml +75 -0
  19. package/config/workflows/task-pipeline.yaml +368 -49
  20. package/config/workflows/wrapup-pipeline.yaml +106 -13
  21. package/package.json +9 -9
  22. package/plugins/sp/README.md +25 -2
  23. package/plugins/sp/agents/super-planner.md +11 -0
  24. package/plugins/sp/agents/super-reviewer.md +39 -11
  25. package/plugins/sp/bunfig.toml +8 -0
  26. package/plugins/sp/commands/dev-brainstorm.md +29 -16
  27. package/plugins/sp/commands/dev-changelog.md +5 -4
  28. package/plugins/sp/commands/dev-find-way.md +80 -0
  29. package/plugins/sp/commands/dev-idea.md +6 -0
  30. package/plugins/sp/commands/dev-parallel.md +8 -2
  31. package/plugins/sp/commands/dev-plan.md +6 -0
  32. package/plugins/sp/commands/dev-review-session.md +14 -7
  33. package/plugins/sp/commands/dev-run.md +17 -4
  34. package/plugins/sp/commands/dev-runall.md +21 -10
  35. package/plugins/sp/hooks/agent-lifecycle.ts +155 -0
  36. package/plugins/sp/hooks/context-session-start.ts +1 -1
  37. package/plugins/sp/hooks/fleet-guest-stop.ts +180 -0
  38. package/plugins/sp/hooks/hooks.json +45 -1
  39. package/plugins/sp/hooks/pi/guard-extension.ts +21 -0
  40. package/plugins/sp/lib/history-anatomy.generated.mjs +5 -0
  41. package/plugins/sp/lib/idea-handoff.generated.mjs +72 -11
  42. package/plugins/sp/lib/inline-run-app.ts +28 -0
  43. package/plugins/sp/lib/inline-run.generated.d.mts +6 -0
  44. package/plugins/sp/lib/inline-run.generated.mjs +364 -46
  45. package/plugins/sp/lib/plan-projection.generated.d.mts +28 -0
  46. package/plugins/sp/lib/plan-projection.generated.mjs +255 -0
  47. package/plugins/sp/lib/quality-gate.generated.d.mts +47 -1
  48. package/plugins/sp/lib/quality-gate.generated.mjs +30489 -82
  49. package/plugins/sp/lib/residual-scan.generated.d.mts +19 -0
  50. package/plugins/sp/lib/residual-scan.generated.mjs +66 -0
  51. package/plugins/sp/lib/run-summary-core.ts +561 -0
  52. package/plugins/sp/lib/transcript.ts +275 -0
  53. package/plugins/sp/plugin.json +1 -1
  54. package/plugins/sp/references/roles.md +1 -1
  55. package/plugins/sp/scripts/batch-plan.mjs +335 -0
  56. package/plugins/sp/scripts/batch-plan.ts +100 -0
  57. package/plugins/sp/scripts/batch-preflight.mjs +51 -3
  58. package/plugins/sp/scripts/batch-preflight.ts +72 -1
  59. package/plugins/sp/scripts/commit-guard.mjs +216 -0
  60. package/plugins/sp/scripts/commit-guard.ts +249 -0
  61. package/plugins/sp/scripts/history-anatomy-cache.mjs +5 -0
  62. package/plugins/sp/scripts/inline-run-dispatch.mjs +130 -0
  63. package/plugins/sp/scripts/inline-run-dispatch.ts +135 -0
  64. package/plugins/sp/scripts/inline-run-setup.mjs +563 -91
  65. package/plugins/sp/scripts/inline-run-setup.ts +65 -97
  66. package/plugins/sp/scripts/persist-out-check.mjs +90 -41
  67. package/plugins/sp/scripts/persist-out-check.ts +112 -57
  68. package/plugins/sp/scripts/quality-gate.mjs +30407 -73
  69. package/plugins/sp/scripts/quality-gate.ts +21 -5
  70. package/plugins/sp/scripts/residual-scan.mjs +88 -38
  71. package/plugins/sp/scripts/residual-scan.ts +35 -38
  72. package/plugins/sp/scripts/run-summary.mjs +693 -0
  73. package/plugins/sp/scripts/run-summary.ts +105 -0
  74. package/plugins/sp/scripts/session-timeline.mjs +331 -0
  75. package/plugins/sp/scripts/session-timeline.ts +204 -0
  76. package/plugins/sp/scripts/wrapup-steps.mjs +150 -2
  77. package/plugins/sp/scripts/wrapup-steps.ts +203 -1
  78. package/plugins/sp/skills/brainstorm/SKILL.md +9 -47
  79. package/plugins/sp/skills/branch-workflow/SKILL.md +1 -0
  80. package/plugins/sp/skills/branch-workflow/references/worktree-patterns.md +1 -0
  81. package/plugins/sp/skills/code-implementation/SKILL.md +48 -1
  82. package/plugins/sp/skills/code-verification/SKILL.md +8 -4
  83. package/plugins/sp/skills/code-verification/references/secu-review.md +3 -0
  84. package/plugins/sp/skills/code-verification/references/verdict-schema.md +68 -0
  85. package/plugins/sp/skills/fleet-join/SKILL.md +63 -0
  86. package/plugins/sp/skills/session-review/SKILL.md +77 -24
  87. package/plugins/sp/skills/source-driven-development/SKILL.md +5 -0
  88. package/plugins/sp/skills/spec-decomposition/references/decomposition.md +5 -3
  89. package/plugins/sp/skills/spur-cli/SKILL.md +6 -2
  90. package/plugins/sp/skills/spur-cli/references/agent.md +124 -17
  91. package/plugins/sp/skills/spur-cli/references/decision.md +98 -0
  92. package/plugins/sp/skills/spur-cli/references/message.md +7 -7
  93. package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +41 -3
  94. package/plugins/sp/skills/spur-cli/references/tasks.md +10 -7
  95. package/plugins/sp/skills/spur-cli/references/workflows/authoring-workflows.md +7 -0
  96. package/plugins/sp/skills/spur-cli/references/workflows.md +7 -2
  97. package/plugins/sp/skills/spur-composer/SKILL.md +28 -2
  98. package/plugins/sp/skills/spur-dev/SKILL.md +18 -14
  99. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +6 -3
  100. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +49 -14
  101. package/plugins/sp/skills/spur-dev/references/dev-operations.md +51 -18
  102. package/plugins/sp/skills/spur-dev/references/execution-batch-continuation.md +68 -0
  103. package/plugins/sp/skills/spur-dev/references/execution-batch-report.md +194 -0
  104. package/plugins/sp/skills/spur-dev/references/execution-batch.md +113 -963
  105. package/plugins/sp/skills/spur-dev/references/execution-parallel-isolation.md +130 -0
  106. package/plugins/sp/skills/spur-dev/references/execution-workflow.md +20 -0
  107. package/plugins/sp/skills/spur-dev/references/execution-worktree-landing.md +471 -0
  108. package/plugins/sp/skills/spur-dev/references/execution-worktree-setup.md +379 -0
  109. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +51 -9
  110. package/plugins/sp/skills/spur-dev/references/glossary.md +2 -2
  111. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +361 -156
  112. package/plugins/sp/skills/spur-dev/references/planning-workflow.md +6 -0
  113. package/plugins/sp/skills/spur-dev/references/structured-trace-emission.md +178 -0
  114. package/plugins/sp/skills/wayfinder/SKILL.md +10 -14
  115. package/schemas/decision-catalog.schema.json +226 -0
  116. package/schemas/spur-config.schema.json +25 -0
  117. package/schemas/state-machine-workflow.schema.json +23 -0
  118. package/spur.js +28165 -19051
  119. package/web/_astro/{BoardApp.i4eh_fHA.js → BoardApp.D66k_s_T.js} +1 -1
  120. package/web/_astro/BoardApp.D6sjAJr_.js +324 -0
  121. package/web/_astro/{TaskDetail.C5Cu8LdB.js → TaskDetail.BynLnMNc.js} +1 -1
  122. package/web/_astro/{arc.Bu5XpBEz.js → arc._BUadrdH.js} +1 -1
  123. package/web/_astro/{architectureDiagram-3BPJPVTR.9vHQTvhF.js → architectureDiagram-3BPJPVTR.Dh7xS1Pp.js} +1 -1
  124. package/web/_astro/{blockDiagram-GPEHLZMM.Cn2Xl7D6.js → blockDiagram-GPEHLZMM.DFDVpfXm.js} +1 -1
  125. package/web/_astro/{c4Diagram-AAUBKEIU.7o0P_QDo.js → c4Diagram-AAUBKEIU.V7_3_glh.js} +1 -1
  126. package/web/_astro/channel.DZVfto-r.js +1 -0
  127. package/web/_astro/{chunk-2J33WTMH.C3zZFsNt.js → chunk-2J33WTMH.De1yx7Jz.js} +1 -1
  128. package/web/_astro/{chunk-4BX2VUAB.CNy_M7fO.js → chunk-4BX2VUAB.BDhHFuxx.js} +1 -1
  129. package/web/_astro/{chunk-55IACEB6.2TiPnLBL.js → chunk-55IACEB6.DDLkWnmC.js} +1 -1
  130. package/web/_astro/{chunk-727SXJPM.5CGSyKAp.js → chunk-727SXJPM.CwfiLnA7.js} +1 -1
  131. package/web/_astro/{chunk-AQP2D5EJ.w-ZIgfsK.js → chunk-AQP2D5EJ.CtGDmUnM.js} +1 -1
  132. package/web/_astro/{chunk-FMBD7UC4.BkcEyhKa.js → chunk-FMBD7UC4.BOLjpw73.js} +1 -1
  133. package/web/_astro/{chunk-ND2GUHAM.mxKKbBG4.js → chunk-ND2GUHAM.BDhQls6O.js} +1 -1
  134. package/web/_astro/{chunk-QZHKN3VN.cyA0z9aT.js → chunk-QZHKN3VN.76qBynDF.js} +1 -1
  135. package/web/_astro/{classDiagram-4FO5ZUOK.CqtUzwhX.js → classDiagram-4FO5ZUOK.N0mpPHT0.js} +1 -1
  136. package/web/_astro/{classDiagram-v2-Q7XG4LA2.CqtUzwhX.js → classDiagram-v2-Q7XG4LA2.N0mpPHT0.js} +1 -1
  137. package/web/_astro/{cose-bilkent-S5V4N54A.BExPTopI.js → cose-bilkent-S5V4N54A.CKknFfjB.js} +1 -1
  138. package/web/_astro/{cynefin-OW5HDTMX.Bq2i10Cn.js → cynefin-OW5HDTMX.Cw3ZWBAh.js} +1 -1
  139. package/web/_astro/{dagre-BM42HDAG.By_HsOuv.js → dagre-BM42HDAG.D3yIKCRD.js} +1 -1
  140. package/web/_astro/{diagram-2AECGRRQ.BtU0b7hz.js → diagram-2AECGRRQ.D51dO83Z.js} +1 -1
  141. package/web/_astro/{diagram-5GNKFQAL.D00ztMdT.js → diagram-5GNKFQAL.Bb-FViDj.js} +1 -1
  142. package/web/_astro/{diagram-KO2AKTUF.DMVJWaUN.js → diagram-KO2AKTUF.D3mN8S6x.js} +1 -1
  143. package/web/_astro/{diagram-LMA3HP47.Cxqrjg5-.js → diagram-LMA3HP47.dMMyPcbJ.js} +1 -1
  144. package/web/_astro/{diagram-OG6HWLK6.2lz_1B5h.js → diagram-OG6HWLK6.AzbvzY4C.js} +1 -1
  145. package/web/_astro/{erDiagram-TEJ5UH35.BVQEuJ3T.js → erDiagram-TEJ5UH35.BR5I4OZb.js} +1 -1
  146. package/web/_astro/{flowDiagram-I6XJVG4X.Qlyo90ky.js → flowDiagram-I6XJVG4X.DFqvhGkn.js} +1 -1
  147. package/web/_astro/{ganttDiagram-6RSMTGT7.DRwb8HHZ.js → ganttDiagram-6RSMTGT7.ByJbhH6J.js} +1 -1
  148. package/web/_astro/{gitGraphDiagram-PVQCEYII.YfoPthfS.js → gitGraphDiagram-PVQCEYII.CInHjQR3.js} +1 -1
  149. package/web/_astro/index.COh_kBxN.css +1 -0
  150. package/web/_astro/{infoDiagram-5YYISTIA.DvFREck1.js → infoDiagram-5YYISTIA.Cm0dGVjJ.js} +1 -1
  151. package/web/_astro/{ishikawaDiagram-YF4QCWOH.BzCj9Q0-.js → ishikawaDiagram-YF4QCWOH.C3nOP6Sj.js} +1 -1
  152. package/web/_astro/{journeyDiagram-JHISSGLW.BDMT_AFb.js → journeyDiagram-JHISSGLW.4IvLa2MW.js} +1 -1
  153. package/web/_astro/{kanban-definition-UN3LZRKU.D6Fh3gj9.js → kanban-definition-UN3LZRKU.DS87Cl-k.js} +1 -1
  154. package/web/_astro/{linear.Dxw00fGQ.js → linear.MzmRrNER.js} +1 -1
  155. package/web/_astro/{mermaid.core.CsoxUWa0.js → mermaid.core.fK-WNswS.js} +4 -4
  156. package/web/_astro/{mindmap-definition-RKZ34NQL.CN8oeHLu.js → mindmap-definition-RKZ34NQL.BqipOHhY.js} +1 -1
  157. package/web/_astro/{pieDiagram-4H26LBE5.C7ADqQ_7.js → pieDiagram-4H26LBE5.0nBiPqFG.js} +1 -1
  158. package/web/_astro/{quadrantDiagram-W4KKPZXB.Cw9lKyHP.js → quadrantDiagram-W4KKPZXB.Szj7Zpx5.js} +1 -1
  159. package/web/_astro/{requirementDiagram-4Y6WPE33.B1ni-z4q.js → requirementDiagram-4Y6WPE33.D4UR6TWo.js} +1 -1
  160. package/web/_astro/{sankeyDiagram-5OEKKPKP.BhexdjVr.js → sankeyDiagram-5OEKKPKP.DAE7BdOs.js} +1 -1
  161. package/web/_astro/{sequenceDiagram-3UESZ5HK.C3Rm7dpQ.js → sequenceDiagram-3UESZ5HK.BP9ZVq25.js} +1 -1
  162. package/web/_astro/{stateDiagram-AJRCARHV.CkuMt27u.js → stateDiagram-AJRCARHV.BQW7mIxk.js} +1 -1
  163. package/web/_astro/{stateDiagram-v2-BHNVJYJU.Dc_aazUA.js → stateDiagram-v2-BHNVJYJU.PbK4nDih.js} +1 -1
  164. package/web/_astro/{timeline-definition-PNZ67QCA.ja7sUFhH.js → timeline-definition-PNZ67QCA.Ci_GvUpo.js} +1 -1
  165. package/web/_astro/{vennDiagram-CIIHVFJN.BxIshX_K.js → vennDiagram-CIIHVFJN.DNw1Y5qx.js} +1 -1
  166. package/web/_astro/{wardleyDiagram-YWT4CUSO.DfHlC0sh.js → wardleyDiagram-YWT4CUSO.CwlkaaNe.js} +1 -1
  167. package/web/_astro/{xychartDiagram-2RQKCTM6.DSnhHwCh.js → xychartDiagram-2RQKCTM6.MI6ZuiH_.js} +1 -1
  168. package/web/board-runtime.json +1 -1
  169. package/web/index.html +2 -2
  170. package/web/_astro/BoardApp.BVp-LYi6.js +0 -322
  171. package/web/_astro/channel.6IFIKBhu.js +0 -1
  172. package/web/_astro/index.CbNz17Sx.css +0 -1
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: spur-cli-decision
3
+ description: "spur-cli noun reference: operate `spur decision` as the read/serve surface over the decision catalog - list registered decisions, show one served contract (parameters, criteria vocabulary, effective maker), run a decision to a served outcome (never writes a workflow resultFile), and status the catalog layers. Backed by @gobing-ai/ts-ai-decision 0.5.16 hub; offline by default via the built-in `typesafe` maker. Introduced by task 1093."
4
+ see_also:
5
+ - spur-cli
6
+ ---
7
+
8
+ # spur decision - decision catalog surface
9
+
10
+ `spur decision` exposes the **decision catalog** (ADR-117 trace discipline, task 1092) to agents
11
+ and scripts: discover which decisions exist, inspect one's contract, serve one outcome, and audit
12
+ catalog health. It is a thin transport over `DecisionService` (`packages/app`); the decision hub
13
+ lives in `@gobing-ai/ts-ai-decision`.
14
+
15
+ **Frozen at exactly four verbs** (`list`, `show`, `run`, `status`) by task 1093's design
16
+ (`docs/design/decision-catalog.md` §3.4) — do not invent additional subcommands.
17
+
18
+ ## Catalog layers
19
+
20
+ Decisions resolve first-wins across three layers:
21
+
22
+ | Layer | Root | Notes |
23
+ | ----- | ---- | ----- |
24
+ | `project` | `<cwd>/.spur/decisions/*.yaml` | Highest precedence |
25
+ | `registered` | folders listed in config `decisions.paths` | Operator-added catalogs |
26
+ | `shared` | `decisions/` under the bundled config root | Shipped catalogs (`config/decisions/` in-repo) |
27
+
28
+ The bundled shared catalog ships `task-triage`, `failure-class`, and `review-failure-class` (all
29
+ `choice` type, param `wbs`). Duplicate ids across layers keep the higher layer; duplicates inside
30
+ one file are a load error.
31
+
32
+ **Config keys** (under `decisions:` in the global `~/.config/spur/config.yaml` or project `.spur/config.yaml`):
33
+ `paths` (extra catalog folders forming the `registered` layer), `maker` (default DecisionMaker
34
+ for every decision point), `makers` (per-decision-id overrides). An unregistered maker name is a
35
+ config error, never a silent fallback (design §3.6).
36
+
37
+ ## Verb map
38
+
39
+ | Verb | Purpose | Key flags |
40
+ | ---- | ------- | --------- |
41
+ | `list` | Every visible decision: id, type, layer, catalog file, description | `--layer <layer>`, `--json` |
42
+ | `show <id>` | One served contract: type, parameters, criteria, fallback, minConfidence, effective maker + source | `--json` |
43
+ | `run <id>` | Serve one outcome (closed vocabulary; **never writes a resultFile**) | `--param <pairs...>`, `--evidence <files...>`, `--maker <name>`, `--json` |
44
+ | `status` | Layer counts, registered makers, per-decision maker resolution, load errors | `--json` |
45
+
46
+ All verbs support `--json` (bare payload) and `--json-envelope` (`{ok, data|error}` envelope,
47
+ ADR-091). Failure output for `--json` commands uses the canonical error envelope only under
48
+ `--json-envelope`; plain `--json` keeps the human message on stderr.
49
+
50
+ **Exit codes:** `status` exits 1 on any catalog load error or maker-config error; `show` exits 1 on unknown id; `list` exits 0
51
+ (design §3.4 — load errors surface via `status`) except for an invalid `--layer` value (exit 1).
52
+ Error envelopes use `NOT_FOUND` for an unknown id and `VALIDATION_FAILED` for every other caller mistake.
53
+
54
+ **Exit contract for `run` (design §3.4):** any backend-observed outcome — low confidence, model
55
+ error surfaced as fallback, declined — is still a **successful serve** (exit 0, envelope carries
56
+ `source`/`confidence` so callers can see why). Exit 1 is reserved for caller mistakes caught
57
+ **before** the backend: unknown id, unknown parameter, missing required parameter, type-invalid
58
+ parameter, unregistered `--maker`, unreadable evidence file.
59
+
60
+ ## Parameters and evidence
61
+
62
+ `--param k=v` is repeatable and validated against the decision's declared parameters: values for
63
+ `number`/`boolean`/`json` params are parsed accordingly (`json` accepts inline JSON objects);
64
+ string/enum params pass through verbatim. A parameter with no `default` is **required** (hub
65
+ loader derives `required: !hasDefault`). Undeclared keys exit 1.
66
+
67
+ `--evidence <file>` is repeatable; each file is read, **redacted and bounded to
68
+ `DECIDE_EVIDENCE_MAX_CHARS` (2000 chars)** via the same `redactAndBound` used by workflow
69
+ agent execution. Evidence rides the hub's implicit `instructions` input parameter — it reaches the
70
+ maker through the rendered question, never as a raw input key (the hub rejects undeclared input
71
+ keys). An unreadable evidence file exits 1 before any backend call.
72
+
73
+ ## Effective maker resolution
74
+
75
+ Makers resolve `flag → config-decision → config-default → catalog-decision → catalog-default`;
76
+ `decision show` reports the effective maker as `{name, source}` with that source precedence
77
+ (operator config outranks the shipped catalog because only the machine owner knows which backends
78
+ exist there). The final `catalog-default` maker is the hub built-in `typesafe` — decisions served
79
+ without a configured backend still produce deterministic closed-vocabulary outcomes, which is why
80
+ `run` is usable in tests and scripts with no model access.
81
+
82
+ ## Examples
83
+
84
+ ```bash
85
+ spur decision list --json | jq -r '.[].id'
86
+ spur decision show task-triage # inspect contract before serving
87
+ spur decision run task-triage --param wbs=1093 --json
88
+ spur decision run failure-class --param wbs=1093 \
89
+ --evidence .spur/run/<runId>-test-output.txt # redacted evidence -> instructions
90
+ spur decision status --json | jq '.loadErrors' # audit catalog health
91
+ ```
92
+
93
+ ## References
94
+
95
+ - Design: `docs/design/decision-catalog.md` (§2 catalog authoring, §3.4 CLI surface)
96
+ - Hub: `@gobing-ai/ts-ai-decision` 0.5.16 (`DecisionService`, catalog schema, maker registry)
97
+ - App service: `packages/app/src/decision/decision-service.ts`
98
+ - Shipped catalogs: `config/decisions/*.yaml`
@@ -31,10 +31,10 @@ All verbs accept `--json` and `--json-envelope`. `watch` applies the envelope pe
31
31
 
32
32
  ```bash
33
33
  spur message send "Please review PR 42" --to reviewer
34
- spur message send "Task 0040 is blocked" --to worker-1 --from operator
34
+ spur message send "Task 0040 is blocked" --to myapp-coder-1 --from operator
35
35
  spur message send "Done" --to planner --json
36
36
  spur message send "Review 0042" --to reviewer --wait --until invoke-exit --timeout 30000
37
- spur message send "Done" --to manager --request-key 0695-report-42 # retry-safe: same key replays the original receipt
37
+ spur message send "Done" --to myapp-planner-1 --request-key 0695-report-42 # retry-safe: same key replays the original receipt
38
38
  spur message send "Start the pass" --role reviewer # resolves to exactly one instance
39
39
  ```
40
40
 
@@ -66,9 +66,9 @@ wait; enqueue is **not** rolled back if the wait later fails.
66
66
  ## `inbox` - list addressed messages
67
67
 
68
68
  ```bash
69
- spur message inbox --agent worker-1
70
- spur message inbox --agent worker-1 --json
71
- spur message inbox --agent worker-1 --unresolved --json
69
+ spur message inbox --agent myapp-coder-1
70
+ spur message inbox --agent myapp-coder-1 --json
71
+ spur message inbox --agent myapp-coder-1 --unresolved --json
72
72
  ```
73
73
 
74
74
  Lists messages addressed to `--agent <id>`, oldest first. The body is truncated in plain-text output;
@@ -107,8 +107,8 @@ Threads a reply to a specific message id. The reply is addressable to the origin
107
107
  ## `watch` - follow an inbox live
108
108
 
109
109
  ```bash
110
- spur message watch --agent worker-1
111
- spur message watch --agent worker-1 --interval 1000 --json
110
+ spur message watch --agent myapp-coder-1
111
+ spur message watch --agent myapp-coder-1 --interval 1000 --json
112
112
  ```
113
113
 
114
114
  Polls the inbox and surfaces each **new** message exactly once as it arrives. `Ctrl-C` to exit. With
@@ -258,14 +258,28 @@ the active tasks folder (or `--folder`).
258
258
 
259
259
  ## `migrate-anchors`
260
260
 
261
- Qualify ambiguous in-repo evidence anchors to repo-relative paths across the task corpus. Run
261
+ Qualify in-repo evidence anchors to repo-relative paths across the task corpus. Run
262
262
  `--dry-run` first: unambiguous matches are reported in `qualified`, multiple matches in `ambiguous`
263
263
  without rewriting, and schema-incompatible files in `skipped`. The write path uses the planning
264
264
  service rather than raw file edits.
265
265
 
266
+ **`done_reason` scratch pointers are retargeted** (task 1140, ADR-131): a `.spur/run/<wbs>-verdict.json`
267
+ or `.spur/run/<wbs>/verdict.json` substring becomes `.spur/memory/evidence/<wbs>-verdict.json` when
268
+ that copy exists, else `tracked Testing section (scratch verdict not retained)` when Testing is
269
+ non-empty; otherwise the value is left unchanged and reported in `doneReasonUnresolved`. Each
270
+ `doneReasons` row carries `kind` (`absolute-path` | `durable-evidence` | `tracked-testing`). This is
271
+ the repair for the `no-scratch-verdict-pointer` rule.
272
+
273
+ **`--wbs <wbs>` scopes the pass to one task file** (task 1109 R1) — the wbs is resolved through the
274
+ task locator and exactly that file is scanned, so the pipeline's implement stage can auto-repair a
275
+ task's unique basename anchors without the corpus-wide pass rewriting unrelated files (the unscoped
276
+ apply rewrote 119 on 2026-10-07). An unknown wbs exits `1` with an actionable message and writes
277
+ nothing. Ambiguous basenames are still reported and left untouched in scoped mode.
278
+
266
279
  ```bash
267
280
  spur task migrate-anchors --dry-run --json
268
281
  spur task migrate-anchors --json
282
+ spur task migrate-anchors --wbs 1109 --json # one task file only
269
283
  ```
270
284
 
271
285
  ## `resolve <file-path>`
@@ -358,7 +372,9 @@ and `prefixId` normalizes `AC<n>` so the box flips. A bare `AC-<i>` also does bo
358
372
  resolves it through the feature's scenario order to the AC line aliasing scenario *i*
359
373
  (`AC<k> — [R<n> — ]<scenario title>`) and flips that box — never the same-numbered `AC<i>`; with no
360
374
  aliasing line it flips nothing. A bare `AC<n>` credits no scenario; a title carrying the scenario's
361
- `R<n>` label matches neither.
375
+ `R<n>` label matches neither. When the task's AC section is a Gherkin fence (`Scenario: AC1 — …`
376
+ rows), there is no checklist label: cite each row by its exact scenario title — a bare `AC<i>`
377
+ matches nothing and the verdict is rejected.
362
378
 
363
379
  **Evidence rule (behavior-bearing AC):** an AC row with `status: MET` on a behavior-bearing id
364
380
  (no `[advisory]`/`[non-core]`/`[non-behavior]`/`[docs-only]` marker) MUST carry `test` or
@@ -436,7 +452,7 @@ spur task sections <wbs> <init|add|list> [name] [--folder] [--json]
436
452
  spur task list [--status <s>] [--phase <p>] [--parent <wbs>] [--feature <id>] [--folder] [--json]
437
453
  spur task refresh [--folder] [--json]
438
454
  spur task migrate [--dry-run] [--folder] [--json]
439
- spur task migrate-anchors [--dry-run] [--json]
455
+ spur task migrate-anchors [--wbs <wbs>] [--dry-run] [--json]
440
456
  spur task refresh-roster <wbs> [--folder] [--json]
441
457
  spur task batch-create --file <path> [--skip-ready | --agent <selector>] [--folder] [--json]
442
458
  spur task record <wbs> [--verdict-file <p>] [--solution-from-diff] [--transition <s>] [--folder] [--json]
@@ -448,3 +464,25 @@ spur task path <wbs> [--folder] [--json]
448
464
  spur task run-link <wbs> [--source <src>] [--run-id <id>] [--json]
449
465
  spur task scaffold-tests <wbs> [--file <path>] [--folder] [--json]
450
466
  ```
467
+
468
+ **No `delete` verb — and that is the surface's shape, not an oversight.** The corpus is
469
+ append-only history: a task that is no longer wanted is a *decision*, and the lifecycle already owns
470
+ it. Use
471
+
472
+ ```
473
+ spur task update <wbs> cancelled [--json] # the in-band terminal; the file stays as the record
474
+ ```
475
+
476
+ Removing the file entirely is reserved for a task that should never have existed (a duplicate WBS, a
477
+ mis-scaffolded capture) — a **corpus repair**, not a lifecycle move. Do it as a tracked deletion so
478
+ the removal itself is auditable:
479
+
480
+ ```
481
+ git rm docs/tasks<N>/<wbs>_<slug>.md
482
+ git commit -m "chore(corpus): drop <wbs> — <why it never existed>"
483
+ ```
484
+
485
+ Check for inbound references before deleting (`grep -rn "<wbs>" docs/ config/ plugins/`, plus any
486
+ `dependencies[]` edge via `spur task list --json`). The `deps remove` verb clears an edge. A deleted
487
+ WBS must not stay referenced: a dangling `dependencies[]` entry is a broken traceability edge, not a
488
+ harmless leftover.
@@ -23,7 +23,7 @@ does what*, this skill.
23
23
  Start from the WBS, not the corpus layout:
24
24
 
25
25
  ```bash
26
- spur task show <wbs> --json # metadata + full content + filePath
26
+ spur task show <wbs> --json # {wbs, name, status, frontmatter, content, filePath}; priority etc. under .frontmatter
27
27
  spur task get <wbs> --json # alias of `show` — same output, no separate code path
28
28
  spur task path <wbs> --json # absolute path only
29
29
  ```
@@ -38,15 +38,15 @@ re-reading or re-tokenizing the task.
38
38
 
39
39
  | Verb | Purpose | Key flags |
40
40
  | ---- | ------- | --------- |
41
- | `create <title>` | Allocate a new task (race-safe WBS) | `--feature <id>` `--parent <wbs>` `--template <variant>` `--dedupe-within <s>` `--allow-duplicate-name` `--skip-ready` `--agent <selector>` `--folder` `--json` |
41
+ | `create <title>` | Allocate a new task (race-safe WBS) | `--feature <id>` `--no-reopen` `--parent <wbs>` `--template <variant>` `--dedupe-within <s>` `--allow-duplicate-name` `--skip-ready` `--agent <selector>` `--folder` `--json` |
42
42
  | `show <wbs>` | Print one task's frontmatter + body | `--folder` `--json` |
43
- | `update <wbs> [status]` | Lifecycle transition, section replace, **or** frontmatter set | `--section <name> --from-file <path>` `--assignee <spec-id>` (exclusive with `--section`) `--feature <id>` `--priority <p>` `--ac-numbering task-local` `--ac-altitude <a>` `--estimate-hours <n>` `--no-lifecycle` `--force-done` `--reason <text>` `--provenance-bypass` `--verdict-dir <path>` `--folder` `--json` |
43
+ | `update <wbs> [status]` | Lifecycle transition, section replace, **or** frontmatter set | `--section <name> --from-file <path>` `--assignee <spec-id>` (exclusive with `--section`) `--feature <id>` `--no-reopen` `--priority <p>` `--ac-numbering task-local` `--ac-altitude <a>` `--estimate-hours <n>` `--no-lifecycle` `--force-done` `--reason <text>` `--provenance-bypass` `--verdict-dir <path>` `--folder` `--json` |
44
44
  | `deps <wbs> <op> [values...]` | Mutate `dependencies[]` frontmatter array (ops: `set`, `add`, `remove`, `clear`) | `--folder` `--json` |
45
45
  | `sections <wbs> <op> [name]` | Initialize, add, or list canonical task sections (ops: `init`, `add`, `list`) | `--folder` `--json` |
46
46
  | `list` | List tasks, filtered | `--status <s>` `--phase <p>` `--parent <wbs>` `--feature <id>` `--folder` `--json` |
47
47
  | `refresh` | Re-scan the corpus and report counts (**`kanban.md` retired** — web Task Kanban is SSOT) | `--folder` `--json` |
48
48
  | `migrate` | One-time A17 corpus normalization pass | `--dry-run` `--folder` `--json` |
49
- | `migrate-anchors` | Qualify in-repo evidence anchors to repo-relative paths (0583 R1–R3) | `--dry-run` `--json` |
49
+ | `migrate-anchors` | Qualify in-repo evidence anchors to repo-relative paths (0583 R1–R3); `--wbs` scopes to one task file (1109 R1); retargets scratch `done_reason` verdict pointers (1140) | `--wbs` `--dry-run` `--json` |
50
50
  | `refresh-roster <wbs>` | Regenerate a parent task's sub-task roster block in `## Plan` | `--folder` `--json` |
51
51
  | `batch-create` | Create many tasks from a validated JSON array | `--file <path>` `--skip-ready` `--agent <selector>` `--folder` `--json` |
52
52
  | `record <wbs>` | Write `Testing` from a verify verdict (deterministic); bare-`## Review` fallback only; optional Solution + transition | `--verdict-file <path>` `--solution-from-diff` `--transition <status>` `--folder` `--json` |
@@ -67,8 +67,11 @@ tasks folder. **Exit codes:** `0` success, `1` error, `2` invalid usage.
67
67
  spur task create "Add email validation" --feature H2 --parent 0040
68
68
  ```
69
69
 
70
- - **`--feature <id>`** wires traceability: it derives the task's `Background` from the feature's
71
- `Goal` and records `feature_id` in frontmatter (L4 traceability reads this edge).
70
+ - **`--feature <id>`** wires traceability: it derives the task's `Background` from the feature's `Goal`
71
+ and records `feature_id` in frontmatter (L4 traceability reads this edge). The parent feature's
72
+ status is checked before any write: `done`/`cancelled` is rejected with the status plus up to three
73
+ `active` sibling ids, and `verifying` is reopened to `active` through the guarded feature transition
74
+ (`featureReopened` in `--json`); `--no-reopen` suppresses only that reopen.
72
75
  - **`--parent <wbs>`** groups the new task under a parent WBS for sub-task decomposition.
73
76
  - **`--template <variant>`** selects the section-matrix variant that shapes the new file's sections:
74
77
  `standard·feature-impl·issue·review·meta·brainstorm`. The default is **`feature-impl` when
@@ -273,7 +276,7 @@ corpus, or with a WBS for one task:
273
276
 
274
277
  ```bash
275
278
  spur task check --json # whole corpus
276
- spur task check 0040 --json # one task
279
+ spur task check 0040 --json # one task; output is an array — read .[0].pass
277
280
  spur task check --strict --json # elevate ALL warnings to failures
278
281
  spur task check 0040 --as done # evaluate as the done row (lifecycle target, F92 R2)
279
282
  spur task check 0040 --strict-core # compatibility alias; not the done gate (use --as done)
@@ -134,6 +134,13 @@ runner (see [validation-and-extension.md](validation-and-extension.md)).
134
134
  | Guard | `always` | Unconditional pass — the default edge condition / fallback transition |
135
135
  | Guard | `action-ok` | Pass iff the prior action on this state/node succeeded — useful for a single hard shell check |
136
136
 
137
+ Spur's host additionally registers (`registerSpurBuiltins`, `packages/app/src/workflow/builtins.ts`):
138
+
139
+ | Kind | Capability |
140
+ | ---- | ---------- |
141
+ | Action | `agent.run` (model call via `spur agent run`; `executor: 'fleet'` dispatches into the agent fleet), `decide` (inline `id`/`method`/`question`/`choices`/`default`/`evidence` → outcome written to `resultFile`; catalog-id references are pending task 1094 — use `spur decision run` for catalog decisions), `command.gate`, `rule.check`, `doctor.probe`, `response.validate`, `proof.fingerprint`, `run.artifact`, `file.exists`, `file.read`, `file.read.into-var`, `http.request`, `hitl.confirm`, `hitl.select`, `hitl.input`, `shell` (streaming) |
142
+ | Guard | `shell` (env-aware), `contract-violation` |
143
+
137
144
  Order matters for both guards and conditions: **the first that passes wins.** Put the discriminating
138
145
  guard before the unconditional fallback (`always` / no-guard edge). For multi-condition gates (doctor
139
146
  + task check, quality gate + attempt cap), prefer a **soft probe** shell that writes PASS|FAIL and
@@ -112,7 +112,7 @@ The skill's logic divides by **whether the LLM adds value**:
112
112
  | `run` | `spur workflow run` (CLI) | `<file> [--run-id <id>] [--vars <json>] [--dry-run] [--async] [--no-plan] [--quiet/--silent/--verbose] [--detail <level>] [--trace-file] [--no-log] [--steer]` | Terminal state reached (sync) or run started (async); trace readable |
113
113
  | `continue` | `spur workflow continue` (CLI) | `[run-id] [--yes] [--answer <yes\|no\|cancel>] [--answer-text <text>] [--async] [--no-log]` | Resume a paused or interrupted run (omit id -> most recent resumable); `--answer` injects a confirm/select gate answer and `--answer-text` answers an input gate with free text (H1 R27), both before guard re-evaluation; one of them is required headless (0901 R3) and each is validated against the pending gate kind; `--async` detaches the resume (0901 R4) |
114
114
  | `cancel` | `spur workflow cancel` (CLI) | `<run-id>` | Single non-terminal run marked failed (SIGTERM async worker when live) |
115
- | `clean` | `spur workflow clean` (CLI) | `[--older-than <min>] [--force] [--logs] [--dry-run]` | Bulk-finalize stale `running`/`pending` runs as failed **and** reclaim retained run logs older than `workflow.logRetentionDays` (30d default) |
115
+ | `clean` | `spur workflow clean` (CLI) | `[--older-than <min>] [--force] [--logs] [--dry-run]` | Bulk-finalize stale `running`/`pending` runs as failed **and** reclaim retained run logs older than `workflows.logRetentionDays` (30d default) |
116
116
  | `list` | `spur workflow list` (CLI) | — | Available workflow **YAML definition files** (not run records) |
117
117
  | `trace` | `spur workflow trace` (CLI) | `[run-id] [--workflow <n>] [--status <s>] [--since <iso>] [--last <n>] [--follow] [--poll <ms>] [--output] [--timeout <ms>]` | Run history list or per-run timeline |
118
118
  | `progress` | `spur workflow progress` (CLI) | `<run-id>` | The `projectWorkflowProgress` projection for that run — current state, per-action attempts, candidate next transitions, diagnostics. Read-only; the verb renders, `packages/app` derives. Unknown run id exits 1 with `Run <id> not found.` |
@@ -273,6 +273,11 @@ spur workflow progress <run-id> [--json]
273
273
  `spur workflow show <file>` renders the declared graph as Mermaid. `--format todo` instead emits a
274
274
  declared-step checklist; `--json` serializes the selected projection. This verb intentionally does
275
275
  not advertise `--json-envelope` because its JSON projection is a kept-raw document surface.
276
+ Task 1104: for annotated definitions the todo `--json` payload also carries `plan` — the two-layer
277
+ A-Z/1-9 phased plan derived from each state's `display` (`phase`/`phaseTitle`/`title`/`show`);
278
+ `null` when no state declares `display`. `workflow validate` enforces the phase table on annotated
279
+ definitions (every non-terminal state phased, terminals bare, ≤25 phases, ≤9 states per phase,
280
+ consistent `phaseTitle`).
276
281
 
277
282
  | Flag (on `run`) | Effect |
278
283
  | --------------- | ------ |
@@ -361,7 +366,7 @@ redirecting `agent.run` stages (ADR-047).
361
366
  - **Stale-run finalization** (existing): bulk-finalizes orphaned `running`/`pending` runs as `failed`.
362
367
  `--older-than <minutes>` (default 30) and `--force` (all non-terminal regardless of age) apply here only.
363
368
  - **Run-log reclamation** (0429): removes expired `.log` files from `.spur/memory/runs/`
364
- and legacy `.spur/run/`, using `workflow.logRetentionDays` (default 30 days). Non-terminal
369
+ and legacy `.spur/run/`, using `workflows.logRetentionDays` (default 30 days). Non-terminal
365
370
  runs, including paused/interrupted runs, are protected; ownership lookup failures preserve logs.
366
371
  The two-file record (`.md` + `.state.json`) and partial handoffs are retained.
367
372
  - **Checkpoint reclamation**: removes expired terminal checkpoints only when confinement,
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: spur-composer
3
- description: "Select, compose and tune spur artifacts — tasks, features, rules, workflows and agent specs. Owns workflow catalog selection, the ephemeral→project→shared ladder, the ADR-115 budgets, trace-driven rule tuning, and applying accepted sp:spur-doctor proposals. Triggers: compose a workflow, tune a rule, apply doctor proposals."
3
+ description: "Select, compose and tune spur artifacts — tasks, features, rules, workflows, agent specs and project Board modules. Owns workflow catalog selection, the ephemeral→project→shared ladder, ADR-115 budgets, trace-driven rule tuning and applying accepted sp:spur-doctor proposals. Triggers: compose a workflow, tune a rule, add a Board module."
4
4
  license: Apache-2.0
5
5
  version: 1.0.0
6
6
  metadata:
@@ -49,7 +49,8 @@ its own output and never runs a recurring loop — evaluation is the doctor's jo
49
49
  | feature | Apply accepted rows through `spur feature update --section --from-file`; keep acceptance criteria in Gherkin | [../spur-cli/references/features.md](../spur-cli/references/features.md) |
50
50
  | rule | The trace-driven tuning loop (§ Rule tuning loop) | [../spur-cli/references/rules.md](../spur-cli/references/rules.md) · [fine-tuning](../spur-cli/references/rules/fine-tuning.md) |
51
51
  | workflow | Catalog selection, the composition ladder, and the ADR-115 budgets (§ below) | [../spur-cli/references/workflows.md](../spur-cli/references/workflows.md) · [operations](../spur-cli/references/workflows/operations.md) |
52
- | agent spec | Read through `spur agent list --specs`; specs are materialized from the fleet declaration at serve start | [../spur-cli/references/agent.md](../spur-cli/references/agent.md) |
52
+ | agent spec | Read through `spur agent list --specs`; fleet member specs are derived in memory from `agent.fleet` (never written to `.spur/agents/`) | [../spur-cli/references/agent.md](../spur-cli/references/agent.md) |
53
+ | board module | Declare under `bootstrap.modules`, gated by the serve preflight (§ Board module composition) | [../spur-cli/references/serve.md](../spur-cli/references/serve.md) |
53
54
 
54
55
  Do not drive the planning→execution lifecycle from here — that is `sp:spur-dev`.
55
56
 
@@ -106,6 +107,31 @@ budgets:
106
107
  A new model step in a shared workflow raises its `pipeline-budgets` `modelQueries`; that needs a
107
108
  recorded decision before the shared step.
108
109
 
110
+ ## Board module composition
111
+
112
+ A project adds its own Spur Board modules (ADR-128) by declaration, never by editing the installed
113
+ package. The contract — the `react`/`iframe` union, the `@gobing-ai/spur/board` type, the Vite
114
+ externals and the frame/trust limits — is owned by
115
+ [downstream Board modules §6](../../../../docs/design/downstream-board-modules.md#6-authoring-guide);
116
+ the user walkthrough is
117
+ [docs/help/how_to_customize_project_modules.md](../../../../docs/help/how_to_customize_project_modules.md).
118
+ Link them, never restate them.
119
+
120
+ | Step | Action |
121
+ | --- | --- |
122
+ | select | A built-in module or an existing declaration already covers the need → no new module. An app that already runs and permits framing → `type: iframe`. Otherwise → `type: react`. |
123
+ | compose | Add one declaration to the project `.spur/config.yaml` `bootstrap.modules` list. Stage it with `enabled: false` first: it is fully validated (id shape, duplicates, host/retired collisions) but loads no assets. |
124
+ | build | `react` only: the downstream project builds its own ESM entry plus CSS into the declared `directory`, externalizing exactly the `imports` keys of the installed `web/board-runtime.json`. Building the module is the project's code work, not composer's. |
125
+ | gate | Restart `spur self serve`; the preflight fails startup on any declaration, asset or runtime-version error. Confirm the module in `GET /api/board/modules` and open `/board/modules/<id>`. `spur self serve --json` is a dry port probe and does **not** run this preflight. |
126
+ | enable | Flip to `enabled: true`, restart and reload. There is no hot reload. |
127
+
128
+ - The module is project-owned: it never climbs a shared layer, and it needs no `build:bundle`.
129
+ - Declare only trusted code — importing a `react` entry evaluates it. Spur never starts or proxies an
130
+ `iframe` app, and a frame the child refuses stays blank by design.
131
+ - Changing a built-in module is internal Board work in the spur repository
132
+ ([docs/help/how_to_add_a_new_ui_module.md](../../../../docs/help/how_to_add_a_new_ui_module.md)),
133
+ not a downstream declaration.
134
+
109
135
  ## Rule tuning loop
110
136
 
111
137
  Start from trace evidence, never from a guess:
@@ -39,11 +39,7 @@ metadata:
39
39
  It converts vague intent into shipped work by _orchestrating_, not by doing the work itself: it runs
40
40
  the gates (feature-check, batch-create) and the execution pipeline with human-in-the-loop control,
41
41
  and **dispatches deep competency skills** for each unit of work — it never inlines them. Every write
42
- to the corpus goes through a CLI verb that validates before writing — the spine knows _how to drive
43
- the lifecycle_; the competency skills know _how to do each job_; the CLI knows _what is valid_.
44
-
45
- The skill was decomposed **by function** (ADR-028): design, decomposition, implementation, testing,
46
- and verification each became a standalone competency skill, leaving this spine to orchestrate them.
42
+ to the corpus goes through a CLI verb that validates before writing.
47
43
 
48
44
  **Ownership (ADR-054).** This spine owns multi-step lifecycle orchestration — intake, gates,
49
45
  decomposition, pipeline runs, HITL pauses. CLI noun/verb/flag semantics, including
@@ -104,6 +100,19 @@ run. Resume with `spur workflow continue --answer-text <answer>` — the guard a
104
100
  Full procedure: **[references/execution-workflow.md](references/execution-workflow.md)**.
105
101
  Host-session procedure: **[references/inline-pipeline-driver.md](references/inline-pipeline-driver.md)**.
106
102
 
103
+ ## Bootstrap reads
104
+
105
+ Read this `SKILL.md` plus your mode's files below before the first dispatch; everything else under
106
+ `references/` is on demand, and the per-task delegate `inline-pipeline-driver.md` is read at dispatch
107
+ (budgets: `plugins/sp/tests/bootstrap-budget.test.ts`, task 1128).
108
+
109
+ - sequential-inline: `references/execution-batch.md`
110
+ - --worktree: `references/execution-batch.md`, `references/execution-worktree-setup.md`
111
+ - --mode parallel: `references/execution-batch.md`, `references/execution-parallel-isolation.md`
112
+
113
+ Byte budgets for these sums live in `plugins/sp/tests/bootstrap-budget.test.ts`
114
+ (`BOOTSTRAP_BUDGETS_BYTES`, task 1128); the test fails the build when a mode's bootstrap grows.
115
+
107
116
  ## Step routing
108
117
 
109
118
  Each step delegates to a CLI verb and is documented in exactly one reference file. Read the
@@ -201,10 +210,8 @@ path <wbs> --json` only when another tool needs the absolute path. Never search
201
210
 
202
211
  ## Additional Resources
203
212
 
204
- **Every reference file and its step is listed once, in [Step routing](#step-routing) above — this
205
- section adds what that table has no room for: per-file content summaries and items with no single
206
- step (glossary, config companions).** Read Step routing to find "which file for step X"; read below
207
- for "what's actually in file Y" or for resources that sit outside the step sequence.
213
+ **Every reference file and its step is listed once, in [Step routing](#step-routing) above.** This
214
+ section adds per-file content summaries and items with no single step (glossary, config companions).
208
215
 
209
216
  - Job transfer: [dump/resume](references/dev-operations.md#11a-job-dump).
210
217
 
@@ -212,12 +219,9 @@ for "what's actually in file Y" or for resources that sit outside the step seque
212
219
  corpus, gate, verdict, noun/verb, half, HITL, WBS, section-write contract — canonical term +
213
220
  Avoid list. Owns term definitions only; `cross-cutting.md` owns the process rules that use them.
214
221
  - [references/flag-glossary.md](references/flag-glossary.md) — the shared-flag glossary (one
215
- canonical entry per flag used by two or more `/sp:dev-*` commands) and the `--next` chain
216
- contract. Moved verbatim from `dev-operations.md` (task 0408) so command files can deep-link
217
- flag entries while this spine reads the operation catalog linearly.
222
+ canonical entry per flag used by two or more `/sp:dev-*` commands) and the `--next` chain contract.
218
223
  - [references/gate-checklists.md](references/gate-checklists.md) — checkbox checklists for the
219
- five gates (feature-check, batch-create, precheck, review, verify). Each checklist is a
220
- `- [ ]` list of prerequisites an agent verifies before entering the gate.
224
+ five gates (feature-check, batch-create, precheck, review, verify).
221
225
  - [references/section-batching.md](references/section-batching.md) — the evidence-section
222
226
  **one-writer protocol** (F92 0593 R1/R2): implement owns `Solution`, the review coordinator owns
223
227
  `Review`, deterministic `record` owns `Testing`; skills query `spur task sections` /
@@ -100,9 +100,12 @@ scenario, it matches by title. Rules:
100
100
  - **No synonyms in cross-references.** The title in the feature file and the title in the
101
101
  task's AC reference must be byte-identical.
102
102
  - **Avoid gate vocabulary in titles.** `spur task check` (L4.gate-language) rejects task sections
103
- containing `HITL`, `approval`/`approved`, `merged`/`merge event`, `content-gate`, `GATED`, or
104
- `capstone` as standalone words; task AC bullets copy scenario titles verbatim, so a title using
105
- them fails every child task. Write "pause for an operator answer" instead of "HITL approval".
103
+ containing `HITL`, `merge event`, `content-gate`, `GATED`, or `capstone` as standalone words;
104
+ ambiguous words (`approval`, `approved`, `merged`) warn only when the same sentence also carries
105
+ a gating cue (`until`, `after`, `once`, `before`, `pending`, `blocked`, `wait for`, `requires`)
106
+ — plain composition prose like "the stages merged back into one step" stays silent. Task AC
107
+ bullets copy scenario titles verbatim, so a title using the unconditional tokens fails every
108
+ child task. Write "pause for an operator answer" instead of "HITL approval".
106
109
 
107
110
  ## Verdict AC ↔ feature scenario linkage
108
111
 
@@ -245,25 +245,36 @@ stage is required, select the subprocess path (`--agent auto` or `--agent <name>
245
245
 
246
246
  The workflow-backed dev commands (`dev-run`, `dev-runall`, `dev-refineall`, `dev-verifyall`) share one
247
247
  startup order. The order is load-bearing and applies on both the inline driver and the subprocess
248
- path; skill-only operations (refine/verify batches with no nested workflow) display their owned
248
+ path. Runs that resolve a workflow definition publish the generated plan as their first action
249
+ (1105 R1); skill-only operations (refine/verify batches with no nested workflow) display their owned
249
250
  procedure and do not fabricate a workflow YAML.
250
251
 
251
- 1. **Publish a compact bootstrap checklist immediately** (host-preparation rows, never copied
252
- workflow states): `A, Quick readiness` · `B, Prepare Git` · `C, Publish workflow plan` ·
253
- `D, Comprehensive checking`.
254
- 2. **Quick deterministic readiness (R2), before isolation.** Evaluate `quickReadiness`
252
+ 1. **Publish the generated plan first (1105 R1), before readiness and isolation.** Resolve the
253
+ selected workflow through the same resolver execution uses and run `spur workflow show
254
+ <resolved-file> --no-logo --format todo --json`; the projection reads the definition and executes
255
+ nothing, so publishing it first is safe. Publish every `.plan` row's `text` verbatim (`A Prepare`,
256
+ `B Implement`, `B1 … · precheck`) as the visible host list — never hand-write rows or copy state
257
+ tables into prose. `.plan` is `null` for unannotated workflows: those keep the flat `steps[]`
258
+ inventory with `columnLabel` labels; the skill-only refine/verify batches keep the bootstrap rows
259
+ below.
260
+ 2. **Quick deterministic readiness (R2) — plan row A1, before isolation.** Evaluate `quickReadiness`
255
261
  (`plugins/sp/scripts/batch-preflight.ts`) with the operation, status, filtered-set size, and the
256
262
  selected matrix required/present sections + content-policy findings. This is an admission decision
257
263
  (runnable / needs-refinement / blocked / skipped / invalid), never an implementation certificate.
258
- 3. **Isolation (R3), only when `--worktree` is valid.** After quick readiness and the required Git
259
- safety checks, create/adopt and switch to the execution tree; confirm absolute cwd, branch, base
260
- SHA, and ownership. An invalid/empty target, unsupported mode, ambiguous ownership, or stale target
261
- stops without creating a tree or discarding work. All subsequent tools, agents, corpus writes, and
262
- run artifacts use the confirmed execution tree.
263
- 4. **Publish the workflow inventory (R4), before reading the YAML.** `spur workflow show
264
- <resolved-file> --no-logo --format todo --json`; validate with `parseWorkflowInventory` and bind to
265
- the run's `__definitionDigest` with `assertInventoryIdentity`. Drift or projection failure stops the
266
- run before any comprehensive/model work — never execute with a misleading plan.
264
+ 3. **Isolation (R3) — plan row A2, only when `--worktree` is valid.** After quick readiness and the
265
+ required Git safety checks, create/adopt and switch to the execution tree; confirm absolute cwd,
266
+ branch, base SHA, and ownership. An invalid/empty target, unsupported mode, ambiguous ownership, or
267
+ stale target stops without creating a tree or discarding work. All subsequent tools, agents, corpus
268
+ writes, and run artifacts use the confirmed execution tree.
269
+ 4. **Bind the published plan to the run digest (R4) — plan row A3.** Validate the step-1 projection
270
+ with `parseWorkflowInventory` and bind it to the run's `__definitionDigest` with
271
+ `assertInventoryIdentity`. Drift or projection failure stops the run before any
272
+ comprehensive/model work — never execute with a misleading plan.
273
+
274
+ **Bootstrap rows without a generated plan (1105 R1).** `dev-refineall` and `dev-verifyall` have no
275
+ workflow plan (their phases are map I13 fog), so until phases exist they keep publishing a compact
276
+ host-preparation checklist immediately, never copied workflow states: A Quick readiness, B Prepare
277
+ Git, C Publish workflow plan, D Comprehensive checking.
267
278
  5. **Load execution detail and run comprehensive checks (R7).** Only after the plan is visible (and
268
279
  after isolation when requested) load the full YAML for the active stage and run the owning
269
280
  comprehensive gates at their boundaries. Prefer deterministic checks; invoke semantic model work
@@ -300,6 +311,12 @@ keeps a malformed task out of `testing`/`done`.
300
311
  lifecycle-*run* creation because it is already a run and a nested one would orphan. The structural
301
312
  gate still runs — `→ testing` and `→ done` invoke `spur task check` regardless of the flag.
302
313
 
314
+ **Worktree interaction (1149 R1/R3).** When an interactive `--next` chain runs inside an isolated
315
+ git worktree (`--worktree`), the un-suppressed transitions create a `task-lifecycle` row in the
316
+ worktree DB. When persist-out runs at landing, the terminal row is classified as non-fatal
317
+ bookkeeping (`external-key-conflict-bookkeeping`) so it does not block teardown, and the receiving
318
+ lifecycle row in the invoking tree is automatically reconciled to `done`.
319
+
303
320
  > **Behavior corrected 2026-08-07.** `--no-lifecycle` previously suppressed enforcement as a side
304
321
  > effect of suppressing the run record, because the FSM guards live inside the lifecycle workflow.
305
322
  > Combined with `--force-done` (which waives the verify **verdict** only) it left nothing: a task
@@ -542,6 +559,24 @@ Do not re-run the full suite per iteration, and do not `spur-check` before you h
542
559
  target. **Target:** full `spur-check` runs ≤2 per task (one during iteration, one final) instead of
543
560
  4 across a chain.
544
561
 
562
+ **Isolation rerun for load-flakes (task 1112 review).** Under concurrent fleet load, subprocess-heavy
563
+ tests can exceed bun's 5s default timeout. Five such timeouts were seen during 1112, and each one
564
+ passed when run alone. A full gate that fails *only* on timeouts in tests outside the change scope
565
+ does not earn another full-gate run:
566
+
567
+ 1. Rerun each timed-out test alone: `(cd <workspace> && bun test <file> --test-name-pattern <test>)`.
568
+ 2. **Green alone** → classify it as a load-flake. Cite the gate failure (test, elapsed ms) and the
569
+ isolated pass receipt in the verify evidence. The original full-gate run stands as the single
570
+ final gate.
571
+ 3. **Red alone**, or a failure that is not a timeout → it is a real failure. Fix it.
572
+ 4. Give the test an explicit per-test timeout and a WHY comment (see
573
+ `plugins/sp/tests/inline-run-close-reason.test.ts:100-102`) as soon as EITHER (a) the same test
574
+ load-flakes in two separate runs, OR (b) it times out once **outside the change scope** and then
575
+ passes green alone on three consecutive isolated reruns. Waiting for a second gate run to license
576
+ the fix cost 21 minutes on 2026-10-08 (task 1128, the 1058 two-tree canary: 5145 ms then 5967 ms
577
+ against bun's 5000 ms default, green 3/3 alone). Never raise the global timeout, skip the test,
578
+ or loop full-gate reruns.
579
+
545
580
  ## Auto-Decision Principles
546
581
 
547
582
  Seven principles governing `--auto` mode. `--auto` sets `profile=auto` in the workflow vars; the