@gobing-ai/spur 0.3.80 → 0.3.81

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 (158) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/config.example.yaml +29 -18
  3. package/config/config.global.yaml +10 -11
  4. package/config/pipeline-budgets.json +34 -2
  5. package/config/plugin-scripts.json +25 -0
  6. package/config/rules/boundary/config-loading-ownership.yaml +0 -3
  7. package/config/rules/boundary/dao-boundary.yaml +4 -17
  8. package/config/rules/boundary/planning-folder-hardcode.yaml +0 -1
  9. package/config/rules/boundary/sp-no-vendor-refs.yaml +3 -2
  10. package/config/rules/boundary/sp-runtime-path.yaml +3 -14
  11. package/config/rules/quality/coverage-gate.yaml +3 -14
  12. package/config/rules/quality/tsdoc-exports.yaml +4 -7
  13. package/config/rules/strict/http-boundaries.yaml +5 -8
  14. package/config/rules/strict/runtime-boundaries.yaml +1 -5
  15. package/config/rules/structure/protected-files.yaml +9 -3
  16. package/config/rules/structure/test-focus-skip.yaml +0 -2
  17. package/config/rules/structure/test-location.yaml +0 -5
  18. package/config/rules/surface/check-cli-surface.yaml +3 -2
  19. package/config/rules/typescript/bun-tooling.yaml +5 -7
  20. package/config/rules/typescript/guarded-happy-dom-register.yaml +0 -2
  21. package/config/rules/typescript/happy-dom-teardown.yaml +0 -2
  22. package/config/rules/typescript/no-biome-suppressions.yaml +0 -2
  23. package/config/rules/typescript/no-debugger.yaml +0 -2
  24. package/config/rules/typescript/no-eslint-suppressions.yaml +0 -4
  25. package/config/rules/typescript/no-leaky-module-mocks.yaml +6 -13
  26. package/config/rules/typescript/no-module-scope-import-calls.yaml +0 -2
  27. package/config/rules/typescript/no-syscall-emulation-in-boundary-mock.yaml +0 -3
  28. package/config/rules/typescript/no-unmocked-module-eval-side-effects.yaml +0 -3
  29. package/config/rules/typescript/output-boundaries.yaml +0 -3
  30. package/config/rules/typescript/prefer-accessible-role-for-button-queries.yaml +0 -3
  31. package/config/rules/ui/ui-import-boundary.yaml +1 -5
  32. package/config/transition-shims.json +7 -7
  33. package/config/workflows/basic.yaml +4 -0
  34. package/config/workflows/docs-pipeline.yaml +13 -14
  35. package/config/workflows/feature-dev.yaml +20 -65
  36. package/config/workflows/history-anatomy.yaml +22 -1
  37. package/config/workflows/idea-pipeline.yaml +53 -97
  38. package/config/workflows/pr-review.yaml +21 -33
  39. package/config/workflows/task-pipeline.yaml +87 -330
  40. package/config/workflows/wayfinder-resolution.yaml +12 -26
  41. package/config/workflows/wrapup-pipeline.yaml +48 -189
  42. package/package.json +9 -9
  43. package/plugins/sp/README.md +10 -1
  44. package/plugins/sp/agents/expert-spur.md +41 -19
  45. package/plugins/sp/lib/idea-handoff.generated.d.mts +17 -0
  46. package/plugins/sp/lib/idea-handoff.generated.mjs +1301 -0
  47. package/plugins/sp/plugin.json +1 -1
  48. package/plugins/sp/scripts/feature-dev-precheck.mjs +146 -0
  49. package/plugins/sp/scripts/feature-dev-precheck.ts +238 -0
  50. package/plugins/sp/scripts/idea-handoff.mjs +27 -0
  51. package/plugins/sp/scripts/idea-handoff.ts +44 -0
  52. package/plugins/sp/scripts/quality-gate.mjs +165 -0
  53. package/plugins/sp/scripts/quality-gate.ts +217 -0
  54. package/plugins/sp/scripts/workflow-step-profile.mjs +319 -0
  55. package/plugins/sp/scripts/workflow-step-profile.ts +456 -0
  56. package/plugins/sp/scripts/wrapup-steps.mjs +350 -0
  57. package/plugins/sp/scripts/wrapup-steps.ts +466 -0
  58. package/plugins/sp/skills/parallel-execution/references/dispatch-surface.md +1 -1
  59. package/plugins/sp/skills/spec-decomposition/references/decomposition.md +29 -0
  60. package/plugins/sp/skills/spur-cli/references/agent.md +56 -14
  61. package/plugins/sp/skills/spur-cli/references/message.md +30 -3
  62. package/plugins/sp/skills/spur-cli/references/projects.md +45 -1
  63. package/plugins/sp/skills/spur-cli/references/self.md +5 -4
  64. package/plugins/sp/skills/spur-cli/references/serve.md +5 -4
  65. package/plugins/sp/skills/spur-cli/references/tasks.md +1 -1
  66. package/plugins/sp/skills/spur-cli/references/team.md +21 -1
  67. package/plugins/sp/skills/spur-cli/references/workflows/operations.md +6 -3
  68. package/plugins/sp/skills/spur-cli/references/workflows/workflow-fit-and-tuning.md +57 -18
  69. package/plugins/sp/skills/spur-composer/SKILL.md +145 -0
  70. package/plugins/sp/skills/spur-dev/references/planning-workflow.md +24 -0
  71. package/plugins/sp/skills/spur-doctor/SKILL.md +138 -0
  72. package/plugins/sp/skills/taste-refactoring-api/README.md +43 -0
  73. package/plugins/sp/skills/taste-refactoring-api/SKILL.md +334 -0
  74. package/plugins/sp/skills/taste-refactoring-api/checklists/daily-api-review.md +71 -0
  75. package/plugins/sp/skills/taste-refactoring-api/examples/refactor-example.md +72 -0
  76. package/plugins/sp/skills/taste-refactoring-api/examples/review-template.md +93 -0
  77. package/plugins/sp/skills/taste-refactoring-api/references/api-refactoring-playbook.md +253 -0
  78. package/plugins/sp/skills/taste-refactoring-api/references/protocol-modes.md +79 -0
  79. package/plugins/sp/skills/taste-refactoring-api/references/research-basis.md +58 -0
  80. package/plugins/sp/skills/taste-refactoring-architect/README.md +26 -0
  81. package/plugins/sp/skills/taste-refactoring-architect/SKILL.md +471 -0
  82. package/plugins/sp/skills/taste-refactoring-architect/checklists/daily-architecture-review.md +48 -0
  83. package/plugins/sp/skills/taste-refactoring-architect/examples/refactor-example.md +55 -0
  84. package/plugins/sp/skills/taste-refactoring-architect/examples/review-template.md +51 -0
  85. package/plugins/sp/skills/taste-refactoring-architect/references/architecture-refactoring-playbook.md +173 -0
  86. package/plugins/sp/skills/taste-refactoring-architect/references/research-basis.md +28 -0
  87. package/plugins/sp/skills/taste-refactoring-tests/README.md +28 -0
  88. package/plugins/sp/skills/taste-refactoring-tests/SKILL.md +482 -0
  89. package/plugins/sp/skills/taste-refactoring-tests/checklists/daily-test-review.md +39 -0
  90. package/plugins/sp/skills/taste-refactoring-tests/examples/refactor-example.md +85 -0
  91. package/plugins/sp/skills/taste-refactoring-tests/examples/review-template.md +59 -0
  92. package/plugins/sp/skills/taste-refactoring-tests/references/research-basis.md +47 -0
  93. package/plugins/sp/skills/taste-refactoring-tests/references/test-refactoring-playbook.md +222 -0
  94. package/plugins/sp/skills/taste-refactoring-ui/README.md +12 -0
  95. package/plugins/sp/skills/taste-refactoring-ui/SKILL.md +290 -0
  96. package/plugins/sp/skills/taste-refactoring-ui/checklists/daily-ui-review.md +72 -0
  97. package/plugins/sp/skills/taste-refactoring-ui/examples/review-template.md +51 -0
  98. package/plugins/sp/skills/taste-refactoring-ui/references/refactoring-ui-playbook.md +170 -0
  99. package/plugins/sp/skills/wayfinder/SKILL.md +2 -2
  100. package/plugins/sp/skills/wayfinder/references/pipeline-resolution.md +30 -0
  101. package/schemas/spur-config.schema.json +49 -0
  102. package/spur.js +46754 -44121
  103. package/web/_astro/{BoardApp.CHQ1lycZ.js → BoardApp.B1U26g3I.js} +97 -95
  104. package/web/_astro/BoardApp.Csgyg-lS.js +1 -0
  105. package/web/_astro/{TaskDetail.GKfQJ60c.js → TaskDetail.DwPqpq7v.js} +1 -1
  106. package/web/_astro/{arc.DWEtA3Tx.js → arc.CweZEjN2.js} +1 -1
  107. package/web/_astro/{architectureDiagram-3BPJPVTR.DB42oWmP.js → architectureDiagram-3BPJPVTR.D89pbDuv.js} +1 -1
  108. package/web/_astro/{blockDiagram-GPEHLZMM.rhv-zNQV.js → blockDiagram-GPEHLZMM.BOuTeEpX.js} +1 -1
  109. package/web/_astro/{c4Diagram-AAUBKEIU.Ci4-4VvY.js → c4Diagram-AAUBKEIU.CASbkWZF.js} +1 -1
  110. package/web/_astro/channel.Cx6sXxhq.js +1 -0
  111. package/web/_astro/{chunk-2J33WTMH.Cc9veUgf.js → chunk-2J33WTMH.BKQYtOvY.js} +1 -1
  112. package/web/_astro/{chunk-4BX2VUAB.Bec9c4eI.js → chunk-4BX2VUAB.9sHLdMtG.js} +1 -1
  113. package/web/_astro/{chunk-55IACEB6.DoV8S1iB.js → chunk-55IACEB6.wOLXWlPs.js} +1 -1
  114. package/web/_astro/{chunk-727SXJPM.DwR-Qlyj.js → chunk-727SXJPM.DovFbwg3.js} +1 -1
  115. package/web/_astro/{chunk-AQP2D5EJ.ND_a81WY.js → chunk-AQP2D5EJ.B1Weod1X.js} +1 -1
  116. package/web/_astro/{chunk-FMBD7UC4.Wv_jwG48.js → chunk-FMBD7UC4.TEMS04st.js} +1 -1
  117. package/web/_astro/{chunk-ND2GUHAM.CXKXCMmp.js → chunk-ND2GUHAM.Cp8VT1wQ.js} +1 -1
  118. package/web/_astro/{chunk-QZHKN3VN.nkaoNYQq.js → chunk-QZHKN3VN.BzATdEcP.js} +1 -1
  119. package/web/_astro/{classDiagram-4FO5ZUOK.cMQcVlQu.js → classDiagram-4FO5ZUOK.C9BOCfAO.js} +1 -1
  120. package/web/_astro/{classDiagram-v2-Q7XG4LA2.cMQcVlQu.js → classDiagram-v2-Q7XG4LA2.C9BOCfAO.js} +1 -1
  121. package/web/_astro/{cose-bilkent-S5V4N54A.OaDJ7Mr2.js → cose-bilkent-S5V4N54A.DUnr4UAw.js} +1 -1
  122. package/web/_astro/{cynefin-OW5HDTMX.Chi8IphF.js → cynefin-OW5HDTMX.rYq5uM3D.js} +1 -1
  123. package/web/_astro/{cytoscape.esm.DzSz-X2X.js → cytoscape.esm.BB4DxJjf.js} +1 -1
  124. package/web/_astro/{dagre-BM42HDAG.CzK2t_Fp.js → dagre-BM42HDAG.CWeNKe3I.js} +1 -1
  125. package/web/_astro/{diagram-2AECGRRQ.DRvxlVS7.js → diagram-2AECGRRQ.DCkfls10.js} +1 -1
  126. package/web/_astro/{diagram-5GNKFQAL.CnYvNdwA.js → diagram-5GNKFQAL.D5U4JCka.js} +1 -1
  127. package/web/_astro/{diagram-KO2AKTUF.CpLpMw5R.js → diagram-KO2AKTUF.BZJgqaqG.js} +1 -1
  128. package/web/_astro/{diagram-LMA3HP47.JTb78qUA.js → diagram-LMA3HP47.DoMeHvPR.js} +1 -1
  129. package/web/_astro/{diagram-OG6HWLK6.Bk-1jDIb.js → diagram-OG6HWLK6.B50qwwWX.js} +1 -1
  130. package/web/_astro/{erDiagram-TEJ5UH35.D8hN9GZq.js → erDiagram-TEJ5UH35.DdGPG6LK.js} +1 -1
  131. package/web/_astro/{flowDiagram-I6XJVG4X.-6zQr6m5.js → flowDiagram-I6XJVG4X.QP2MJ12u.js} +1 -1
  132. package/web/_astro/{ganttDiagram-6RSMTGT7.DboLQ9ca.js → ganttDiagram-6RSMTGT7.BI6LgKSy.js} +1 -1
  133. package/web/_astro/{gitGraphDiagram-PVQCEYII.4tYvJKGR.js → gitGraphDiagram-PVQCEYII.npPZiC2G.js} +1 -1
  134. package/web/_astro/index.DayyIngm.css +1 -0
  135. package/web/_astro/{infoDiagram-5YYISTIA.Bd9rXpsB.js → infoDiagram-5YYISTIA.DCJCBVbp.js} +1 -1
  136. package/web/_astro/{ishikawaDiagram-YF4QCWOH.CvMoaf67.js → ishikawaDiagram-YF4QCWOH.BMLV-3I1.js} +1 -1
  137. package/web/_astro/{journeyDiagram-JHISSGLW.Ccy1CA7y.js → journeyDiagram-JHISSGLW.LE58crde.js} +1 -1
  138. package/web/_astro/{kanban-definition-UN3LZRKU.0MaMqHNS.js → kanban-definition-UN3LZRKU.BPbz8rH9.js} +1 -1
  139. package/web/_astro/{linear.CHXgcIbN.js → linear.DhZaBtYh.js} +1 -1
  140. package/web/_astro/{mermaid.core.Ca-kcelG.js → mermaid.core.BD5-jXum.js} +6 -6
  141. package/web/_astro/{mindmap-definition-RKZ34NQL.BUIDlHa0.js → mindmap-definition-RKZ34NQL.MTJyrQ65.js} +1 -1
  142. package/web/_astro/ordinal.BYWQX77i.js +1 -0
  143. package/web/_astro/{pieDiagram-4H26LBE5.2dX3CU1s.js → pieDiagram-4H26LBE5.BrDhDvIS.js} +1 -1
  144. package/web/_astro/{quadrantDiagram-W4KKPZXB.B3LBlRiv.js → quadrantDiagram-W4KKPZXB.71d73_5N.js} +1 -1
  145. package/web/_astro/{requirementDiagram-4Y6WPE33.X12I2uNx.js → requirementDiagram-4Y6WPE33.Bga6UF-z.js} +1 -1
  146. package/web/_astro/{sankeyDiagram-5OEKKPKP.BXohIHqx.js → sankeyDiagram-5OEKKPKP.BnHs4K82.js} +1 -1
  147. package/web/_astro/{sequenceDiagram-3UESZ5HK.C37ZIUzg.js → sequenceDiagram-3UESZ5HK.DsfY2gnj.js} +1 -1
  148. package/web/_astro/{stateDiagram-AJRCARHV.BRgz317z.js → stateDiagram-AJRCARHV.DvsTSc9a.js} +1 -1
  149. package/web/_astro/{stateDiagram-v2-BHNVJYJU.7VYSXN9-.js → stateDiagram-v2-BHNVJYJU.DxzzmHUR.js} +1 -1
  150. package/web/_astro/{timeline-definition-PNZ67QCA.BVNz_HiN.js → timeline-definition-PNZ67QCA.4ZuQmOTt.js} +1 -1
  151. package/web/_astro/{vennDiagram-CIIHVFJN.CHVDkPX4.js → vennDiagram-CIIHVFJN.Ck5Q86SG.js} +1 -1
  152. package/web/_astro/{wardleyDiagram-YWT4CUSO.EQQ_qT9v.js → wardleyDiagram-YWT4CUSO.BK7k2hXr.js} +1 -1
  153. package/web/_astro/{xychartDiagram-2RQKCTM6.DrAT9WoP.js → xychartDiagram-2RQKCTM6.DfCrgauK.js} +1 -1
  154. package/web/index.html +2 -2
  155. package/web/_astro/BoardApp.DV9kx0wo.js +0 -1
  156. package/web/_astro/channel.BAI6xLeV.js +0 -1
  157. package/web/_astro/index.Dcr_8fiK.css +0 -1
  158. package/web/_astro/ordinal.DBvzRdQf.js +0 -1
@@ -19,8 +19,8 @@ use it well*.
19
19
 
20
20
  | Verb | Purpose | Key flags |
21
21
  | ---- | ------- | --------- |
22
- | `send <body>` | Enqueue a message for an agent | `--to <id>` `--role <name>` `--from <id>` `--wait` `--until <state>` `--timeout <ms>` `--json` |
23
- | `inbox` | List messages addressed to an agent | `--agent <id>` `--json` |
22
+ | `send <body>` | Enqueue a message for an agent | `--to <id>` `--role <name>` `--from <id>` `--request-key <key>` `--wait` `--until <state>` `--timeout <ms>` `--json` |
23
+ | `inbox` | List messages addressed to an agent | `--agent <id>` `--unresolved` `--json` |
24
24
  | `reply <msg-id> <body>` | Thread a reply to a message | `--json` |
25
25
  | `watch` | Follow an agent inbox - surface new messages as they arrive | `--agent <id>` `--interval <ms>` `--json` |
26
26
 
@@ -34,6 +34,7 @@ spur message send "Please review PR 42" --to reviewer
34
34
  spur message send "Task 0040 is blocked" --to worker-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
38
  spur message send "Start the pass" --role reviewer # resolves to exactly one instance
38
39
  ```
39
40
 
@@ -51,6 +52,9 @@ wait; enqueue is **not** rolled back if the wait later fails.
51
52
  | `--to <id>` | Recipient agent id. Mutually exclusive with `--role`; exactly one of the two is required. |
52
53
  | `--role <name>` | Address by Layer-1 role or executor name. Must resolve to exactly one materialized instance; zero (`count=0`, candidates `none`) or multi (`count=N` + candidates) matches are hard errors (exit 1); unknown name exits 2 naming the accepted vocabulary (`AGENT_ROLE_NAMES` ∪ executor names). Resolution yields the same spec-id path as `--to`; `--wait` snapshots that occupant pin. (0685 R6 / ADR-075 amendment) |
53
54
  | `--from <id>` | Sender id (default: `operator`). |
55
+ | `--request-key <key>` | Caller-minted idempotency key. The same key with the same body + recipient replays the original receipt (`replayed: true`, no second row/delivery); the same key with a different payload fails with a request-key-conflict error (0832). |
56
+ | `replayed` receipt field | Present on keyed sends: `true` when this submission was a replay of an earlier accepted send. |
57
+ | `requestKey` receipt field | Present on keyed sends, including replays; echoes the accepted key. Blank keys are rejected. |
54
58
  | `--wait` | Block until the recipient reaches `--until` (snapshots occupant before send). |
55
59
  | `--until <state>` | Wait target: `injected` \| `invoke-exit` (repeatable OR). Default `invoke-exit`. |
56
60
  | `--timeout <ms>` | Caller deadline in milliseconds. |
@@ -64,11 +68,33 @@ wait; enqueue is **not** rolled back if the wait later fails.
64
68
  ```bash
65
69
  spur message inbox --agent worker-1
66
70
  spur message inbox --agent worker-1 --json
71
+ spur message inbox --agent worker-1 --unresolved --json
67
72
  ```
68
73
 
69
74
  Lists messages addressed to `--agent <id>`, oldest first. The body is truncated in plain-text output;
70
75
  `--json` returns the full body.
71
76
 
77
+ ### Delivery failure states (0834)
78
+
79
+ `--unresolved` filters the listing to messages the delivery reconciler holds, and every `--json` row
80
+ gains the operator-read fields: `injectAttempts`, `injectError`, `reason`, `runId`, `taskId`, `runStatus`,
81
+ `artifacts`. The hold reasons are distinct and durable — never one overloaded status column:
82
+
83
+ Delivered messages remain eligible for holds until their receipt is verified. Interrupted runs
84
+ carry their persisted origin and run status; exhausted attempts keep the same reason on repeated reads.
85
+
86
+ | `reason` | Meaning |
87
+ | -------- | --------- |
88
+ | `delivery-failed` | The drain marked the delivery failed (`injectError` carries why), or its run's receipt outcome is `errored`. |
89
+ | `attempts-exhausted` | The message burned its bounded redelivery budget (`MAX_INJECT_ATTEMPTS`, 0831); the reconciler marks it `failed` — the reconciler's only write. |
90
+ | `outcome-unknown` | The drain consumed it and no completion receipt ever arrived: the agent may have edited files. **Never requeued, never auto-released** — a human decides. |
91
+ | `run-exit-only` | Its run exited (receipt outcome `run-exit-only`) with no workflow verification result. |
92
+
93
+ `runId`, `taskId`, and `artifacts` (path-only refs) come only from the persisted run row that lists
94
+ the message in its receipt; nothing is inferred from terminal output or process lists. The same
95
+ reconciler runs once at `spur agent loop` startup and writes a `reconcile:` summary to the run log
96
+ before the first drain.
97
+
72
98
  ## `reply` - thread a reply
73
99
 
74
100
  ```bash
@@ -107,7 +133,8 @@ lines.
107
133
  ## See also
108
134
 
109
135
  - **`spur agent` (see [agent.md](agent.md))** - `run --drain` and `loop` consume the inbox.
110
- - **`spur team` (see [team.md](team.md))** - team lifecycle that assigns agents to tasks.
136
+ - **`spur task` (see [tasks.md](tasks.md))** - `task update --assignee` wires an agent spec to a
137
+ task (0848 moved home of `spur team assign`).
111
138
  - **`sp:spur-cli`** SKILL.md - the facade that routes to this reference.
112
139
 
113
140
  > **Shared option declarations (0618):** options shared across command modules resolve from
@@ -19,9 +19,10 @@ shapes live in `apps/cli/src/commands/projects.ts`.
19
19
  | ---- | ------- | --------- |
20
20
  | `add <path>` | Upsert an existing path in the registry | `--name <name>` `--json` |
21
21
  | `remove <target>` | Remove an entry by display name or path | `--json` |
22
- | `list` | List entries with live running status | `--json` |
22
+ | `list` | List entries with live running status | `--json` `--fleet` |
23
23
  | `start <target>` | Start or reuse a detached project server | `--port <n>` `--json` |
24
24
  | `stop <target>` | Best-effort stop the listener and clear its recorded port | `--json` |
25
+ | `migrate [path]` | Preview (default) or apply the legacy `agent.team` → `fleet.json` conversion (0847) | `--dry-run` `--apply` `--json` |
25
26
 
26
27
  Every verb also advertises `--json-envelope`; use the facade's machine-output contract. Success is
27
28
  exit `0`; validation, registry, spawn, health, or lookup failure is exit `1`.
@@ -36,6 +37,49 @@ exit `0`; validation, registry, spawn, health, or lookup failure is exit `1`.
36
37
  defaults the display name to its basename. It upserts; it does not start a server. The current
37
38
  source does not enforce a `.spur/` marker or directory type.
38
39
  - `list` probes recorded ports and heals stale entries to `port: 0` before reporting `running`.
40
+ - `list --fleet` (0835) additionally resolves each project's fleet declaration at
41
+ `<project>/.spur/fleet.json` under the existing verb (no new noun). Per project it prints one line
42
+ per member: instance id (the spec id / mailbox identity), `role`, resolved `executor`,
43
+ `fsWrite` capability state, and derived `write` flag. A project with no declaration reports
44
+ `no declaration (.spur/fleet.json)`; an all-disabled roster reports `no enabled members`; a project
45
+ whose executors fail resolution reports the error without failing the listing. Under `--json` each
46
+ project gains `fleet` (the resolved fleet, `null` on resolution failure) and, on failure,
47
+ `fleetError`.
48
+ - `list --fleet` (0836) also reports the project's orchestrator binding: one
49
+ `orchestrator:` line per project with state `bound-online <id> (holder <spec-id>)`,
50
+ `bound-offline <id> (no live claim)`, `missing (no-orchestrator-declared)`, or
51
+ `unresolvable (<reason>)` — missing (nothing bound) and bound-offline (bound, no live
52
+ claim) are distinct states with distinct next actions, and an unresolvable pointer is an
53
+ error, never inferred. Reading the live claim touches the project's own `.spur/spur.db`
54
+ (lazily; only when the pointer resolves). Under `--json` each project gains
55
+ `orchestrator` (the binding, `null` on resolution failure) and, on failure,
56
+ `orchestratorError`.
57
+ - `list --fleet` (0838) also reports the project's persisted strategy (0838): one
58
+ `strategy:` line — `rest (default)` when nothing is persisted (the read never
59
+ writes; only the runtime's `setStrategy`/`resume` persist), `<name> (v<n>)` for a
60
+ persisted row, or `unavailable (<error>)` on a db failure. Under `--json` each
61
+ project gains `strategy` (`{ strategy, strategyVersion }`, `null` when
62
+ unpersisted) and, on failure, `strategyError`.
63
+ - `migrate [path]` (0847) converts the single legacy `agent.team.<id>` roster whose
64
+ `work_dir` resolves to the project into `<project>/.spur/fleet.json`, preserving
65
+ every spec id verbatim (explicit member ids freeze the `<role>-<n>` derivation).
66
+ Dry-run is the default: it emits the 0846 plan (steps + conflicts + warnings) and
67
+ writes nothing — an existing project db is opened read-only without migrations;
68
+ an absent db or table contributes no addressed identities.
69
+ `--apply` validates first, deep-equals an existing declaration (`unchanged`, no
70
+ rewrite), backs up a differing prior file to `.bak`, then atomically writes the
71
+ declaration (`converted`). It is purely additive — specs, `config.yaml`, and the
72
+ database are never touched — and it refuses to write while any conflict exists
73
+ (`addressed-id-without-spec`, `two-teams-one-project`, …). A registry name that
74
+ differs from the legacy team ID is `project-name-mismatch`: align that name
75
+ explicitly before conversion so fleet resolution preserves the spec-id prefix.
76
+ Exit codes: `0` for a
77
+ clean preview or `converted`/`unchanged`/`nothing-to-convert`; `2` when blocked
78
+ (the JSON payload still carries the full plan/result); `1` on error. Under
79
+ `--json` the payload is the raw `MigrationPlan` (preview) or `ConversionResult`
80
+ (apply). `rollback` is a service-level API (no CLI verb): restore the `.bak` a
81
+ previous apply created, remove a file that apply created when no `.bak` exists,
82
+ or report `nothing-to-roll-back`.
39
83
 
40
84
  ## Server lifecycle
41
85
 
@@ -95,8 +95,9 @@ directory. Only flag is `--json`.
95
95
 
96
96
  ## What this skill is NOT
97
97
 
98
- - **Not the team supervisor.** `self serve` hosts the supervisor API; `spur team start` / `stop` /
99
- `status` are the verbs that drive it. See **[team.md](team.md)**.
98
+ - **Not the team supervisor.** `self serve` hosts the supervisor API; `spur agent start` / `stop` /
99
+ `agent list --specs` are the verbs that drive and inspect it (0848). See
100
+ **[agent.md](agent.md)**.
100
101
  - **Not a production server.** This is the local fallback. Production deployment uses the Cloudflare
101
102
  Worker build (`apps/server/`), not `self serve`.
102
103
 
@@ -105,8 +106,8 @@ directory. Only flag is `--json`.
105
106
  - **[init.md](init.md)** - `init` / `status` verbs: scaffold semantics and the Phase 1.5 / 1.6
106
107
  post-scaffold validation probes.
107
108
  - **[serve.md](serve.md)** - `serve` verb: server flags and the `--json` dry-probe contract.
108
- - **`spur team` (see [team.md](team.md))** - `start`/`stop`/`status` require `self serve` for the
109
- supervisor API.
109
+ - **`spur agent` (see [agent.md](agent.md))** - `start`/`stop`/`list --specs` require `self serve`
110
+ for the supervisor API.
110
111
  - **`sp:spur-cli`** SKILL.md - the facade that routes to this reference.
111
112
 
112
113
  > **Shared option declarations (0618):** options shared across command modules resolve from
@@ -46,13 +46,14 @@ the team supervisor API become available at `http://<host>:<port>`.
46
46
 
47
47
  ## What this skill is NOT
48
48
 
49
- - **Not the team supervisor.** `spur serve` hosts the supervisor API; `spur team start` / `stop` /
50
- `status` are the verbs that drive it. See **[team.md](team.md)**.
49
+ - **Not the team supervisor.** `spur serve` hosts the supervisor API; `spur agent start` / `stop` /
50
+ `agent list --specs` are the verbs that drive and inspect it (0848). See
51
+ **[agent.md](agent.md)**.
51
52
  - **Not a production server.** This is the local fallback. Production deployment uses the Cloudflare
52
53
  Worker build (`apps/server/`), not `spur serve`.
53
54
 
54
55
  ## See also
55
56
 
56
- - **`spur team` (see [team.md](team.md))** - `start`/`stop`/`status` require `spur serve` for the
57
- supervisor API.
57
+ - **`spur agent` (see [agent.md](agent.md))** - `start`/`stop`/`list --specs` require `spur serve`
58
+ for the supervisor API.
58
59
  - **`sp:spur-cli`** SKILL.md - the facade that routes to this reference.
@@ -40,7 +40,7 @@ re-reading or re-tokenizing the task.
40
40
  | ---- | ------- | --------- |
41
41
  | `create <title>` | Allocate a new task (race-safe WBS) | `--feature <id>` `--parent <wbs>` `--template <variant>` `--dedupe-within <s>` `--allow-duplicate-name` `--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>` `--feature <id>` `--priority <p>` `--no-lifecycle` `--force-done` `--reason <text>` `--verdict-dir <path>` `--folder` `--json` |
43
+ | `update <wbs> [status]` | Lifecycle transition, section replace, **or** frontmatter set | `--section <name> --from-file <path>` `--assignee <spec-id>` (moved home of `spur team assign`; exclusive with `--section`) `--feature <id>` `--priority <p>` `--no-lifecycle` `--force-done` `--reason <text>` `--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` |
@@ -5,7 +5,27 @@ see_also:
5
5
  - spur-cli
6
6
  ---
7
7
 
8
- # spur team - team coordination and supervision
8
+ # spur team - team coordination and supervision (DEPRECATED — 0848)
9
+
10
+ > **Deprecated (0848, feature G64):** every `spur team` capability has moved to its owning noun.
11
+ > The noun keeps working until the G64 cutover window is recorded, emitting a one-time stderr
12
+ > warning per process. Migrate invocations now:
13
+ >
14
+ > | Old verb | New home |
15
+ > | --- | --- |
16
+ > | `spur team assign <task-id> <agent-id>` | `spur task update <wbs> --assignee <spec-id>` |
17
+ > | `spur team status` | `spur agent list --specs` (same live-run merge) |
18
+ > | `spur team status --by-team` | dropped — one project has one fleet; `spur agent list --specs` is the single fleet listing |
19
+ > | `spur team up <team>` | fleet materialization at `spur serve` start (`.spur/fleet.json`); `up --check` diff → `spur projects list --fleet` |
20
+ > | `spur team down <team> [--purge]` | `spur agent stop <spec-id>` per member (`spur agent delete <id>` replaces `--purge`) |
21
+ > | `spur team start <agent-id>` | `spur agent start <spec-id>` |
22
+ > | `spur team stop <agent-id>` | `spur agent stop <spec-id>` |
23
+
24
+ > **Retiring:** `spur team` is a retiring surface for spur-* guidance. `sp:expert-spur`,
25
+ > `sp:spur-composer` and `sp:spur-doctor` forbid it, and coordination or recurring loops belong to
26
+ > `sp:super-planner` or a workflow. Reach agent specs through `spur agent ... --specs` and use
27
+ > `spur message` for coordination transport. This reference is retained for CLI parity while the
28
+ > noun still ships; do not build new guidance on it.
9
29
 
10
30
  `spur team` is the CLI for **coordinating team agent assignments and supervision**. It sits above
11
31
  `spur agent` specs: `up` / `down` materialize and tear down rosters, `start` / `stop` manage
@@ -65,9 +65,12 @@ Reconciliation core — run this **before authoring anything**. Authoring withou
65
65
  workflows breeds redundant, diverged definitions (two near-identical approval flows, an import flow
66
66
  re-implemented under a new name). Inputs: the clarified process intent. Steps:
67
67
 
68
- 1. **Enumerate existing workflows** — list `.spur/workflows/*.yaml` (and any `--file`-adjacent
69
- directory); read each one's `name`, `kind`, and the states/nodes it defines so matches are found by
70
- *substance*, not just by filename.
68
+ 1. **Enumerate existing workflows** — `spur workflow list --json` across **all layers**
69
+ (`project`, `registered`, `shared` — the listed `layers` are the folders a name can resolve
70
+ from). Never glob `.spur/workflows`: a folder scan misses the registered and shared layers.
71
+ Match from each entry's `name`, `kind`, `source` (the layer it came from) and `description`
72
+ (the intent), then read the strongest candidates' definitions — states/nodes — so matches are
73
+ found by *substance*, not just by filename.
71
74
  2. **Classify the strongest match** against the new intent:
72
75
 
73
76
  | Match | Meaning | Action |
@@ -130,24 +130,63 @@ The flags (`--detail`, `--verbose`, `--trace-file`, `--follow`, `--output`) are
130
130
  ## 3. Node simplicity budget
131
131
 
132
132
  Simplicity is the operating constraint, and it is already measurable — `spur workflow validate`
133
- reports it. Do not invent a second threshold; author to the one that is frozen (ADR-069, task 0614).
134
-
135
- | Element | Budget | What breaching it means |
136
- | --- | --- | --- |
137
- | `shell` action `command` | **<= 5** non-comment units (split on newline and `;`) | >= 6 flags the composition advisory: the program holds reusable behavior that wants an owner |
138
- | `agent.run` action `input` | A **slash command or skill invocation** | A raw prose prompt flags: the operation belongs behind a centralized command (ADR-043). Prompt length sets severity only |
139
- | Transition guard | **One** boolean predicate | Guards are exempt from the shell measure by design. A guard needing five lines is a probe node in disguise — make it one |
140
- | Node count | Every node earns its transition round-trip | A node that always runs immediately after another, with no guard between them, is one node |
141
-
142
- **When a node breaches the budget, do not reformat to dodge the measure.** Joining five lines with
143
- `&&` moves the complexity, not the ownership. Pick one of the four remaining owners from
144
- `docs/design/workflow-shell-ownership.md`: public `spur` verb (consent-gated), application service,
145
- least-privilege built-in action kind, or workflow-relative external extension. (0775 retired the
146
- recorded stays-shell exception along with the suppression snapshot.)
147
-
148
- **Advisory posture is binding.** Composition findings never block a run, never change a `validate`
149
- exit status, and are never a reason to hot-edit an executing pipeline. Surface them; fix on operator
150
- acceptance.
133
+ reports it with a `warn`/`error` level. Do not invent a second threshold; author to the ADR-115
134
+ tiers frozen in [surface governance §1.2](../../../../../../docs/design/harness-surface-governance.md).
135
+
136
+ | Element | Clean | Warn (advisory) | Error |
137
+ | --- | --- | --- | --- |
138
+ | `shell` action `command` | ≤5 logical commands (split on newline, `;`, `&&`, `||`; blank/`#`/structure tokens skipped) | **6–10** | **>10** commands or **>800** characters |
139
+ | Shell transition guard | ≤3 logical commands — one predicate over a result file | **4–5** | **>5** |
140
+ | `agent.run` `input` | A slash command or skill invocation (ADR-043), ≤1000 chars | non-slash prompt (severity by raw length: <200 low, ≤1000 medium) | **>1000** chars, slash-led or not |
141
+ | `agent.run` output check | `expectFile` or `requireDiff` declared | neither declared | — |
142
+ | Node count | Every node earns its transition round-trip | A node that always runs immediately after another, with no guard between them, is one node | — |
143
+
144
+ **When a program breaches a cap, do not reformat to dodge the measure.** Joining lines with `&&`
145
+ moves the complexity, not the ownership. Move the program to one of the five recorded owners from
146
+ `docs/design/workflow-shell-ownership.md`: (a) public `spur` verb (consent-gated), (b) application
147
+ service, (c) least-privilege built-in action kind, (d) workflow-relative external extension, or
148
+ (e) a deliberately-stays-shell exception. (e) is valid only inside the warn band — above an error
149
+ cap the program moves to (a)–(d).
150
+
151
+ **Every remaining warn-band shell program carries a one-line `#` reason**: a YAML comment directly
152
+ above the action or guard, e.g. `# (e) <why it stays shell>` or `# (d) <script> owns <what>`. Never
153
+ write it as a shell `#` line inside a folded `>-` scalar — folding joins the lines, so the `#`
154
+ comments out the rest of the program. YAML comments do not count toward the measure.
155
+
156
+ **Posture is binding (ADR-115).** Warn-level findings never change a `validate` exit status and
157
+ never block a run. An error-level finding makes `validate` exit 1 and gates the spur repository's
158
+ shipped shared workflow layer (layer id `shared` in `spur workflow list --json`) in `spur-check`
159
+ (task 0826). No composition finding ever blocks `run`, `run --dry-run` or `continue`, and a finding
160
+ is never a reason to hot-edit an executing pipeline.
161
+
162
+ ### Consolidation and cache windows (ADR-115)
163
+
164
+ Two composition rules sit next to this budget: the table above stays the measure surface, these
165
+ decide where steps are cut. The rules are owned by the
166
+ [workflow composition contract](../../../../../../docs/design/workflow-composition-contract.md#composition-budgets-adr-115);
167
+ the text below is the operating summary, not a second owner.
168
+
169
+ **Consolidation — one model step per judgment.** Merge adjacent `agent.run` steps only when they
170
+ share a role and an executor **and** nothing between them must stay separate: a deterministic gate,
171
+ a HITL state, or an independence boundary. Never merge an author step with the review or verify
172
+ step that certifies it — those keep `freshSession: true`. A new model step in a shared workflow
173
+ raises its `pipeline-budgets` `modelQueries`, which needs a recorded decision, and every shared
174
+ workflow with a model query carries a budget entry.
175
+
176
+ **Cache windows — step boundaries follow the cache window, not the clock.** Provider prompt caches
177
+ expire after an idle window and refresh on every hit (Anthropic: 5 minutes by default; OpenAI:
178
+ 5–10 minutes in memory). The window W defaults to 300 s, the shortest common default:
179
+
180
+ - A tool call inside `agent.run` that runs longer than W idles the model — its next request
181
+ re-reads a cold prefix. Run that work in a deterministic step instead.
182
+ - An `agent.run` that resumes the inherited session after a gap longer than W (a HITL wait, a slow
183
+ deterministic step) rewrites the whole session into the cache. When the prior step's artifact
184
+ carries what the step needs, prefer `freshSession: true` with that artifact as the handoff.
185
+ - A deterministic step should finish within W at p50. An `agent.run` with p50 above 2W is a split
186
+ candidate only at a real artifact seam — each split adds a model query and a cold prefix, so it
187
+ must pay for itself in retry granularity or observability.
188
+
189
+ These are runtime budgets, judged from run traces and step profiles — never `validate` findings.
151
190
 
152
191
  ---
153
192
 
@@ -0,0 +1,145 @@
1
+ ---
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."
4
+ license: Apache-2.0
5
+ version: 1.0.0
6
+ metadata:
7
+ author: spur
8
+ platforms: "claude-code,codex,openclaw,opencode,antigravity"
9
+ category: artifact-composition
10
+ interactions:
11
+ - inversion
12
+ - companion
13
+ operations:
14
+ - select
15
+ - compose
16
+ - tune
17
+ - apply
18
+ openclaw:
19
+ emoji: "🎼"
20
+ see_also:
21
+ - sp:spur-cli
22
+ - sp:spur-doctor
23
+ - sp:super-planner
24
+ ---
25
+
26
+ # sp:spur-composer — compose, select and tune spur artifacts
27
+
28
+ One cross-noun method (ADR-114, [spur artifact evolution](../../../../docs/design/spur-artifact-evolution.md)
29
+ §2): **select** an existing artifact, **compose** a new one up the ladder, **tune** it against
30
+ evidence, and **apply** the proposals the operator accepts from `sp:spur-doctor`. It never judges
31
+ its own output and never runs a recurring loop — evaluation is the doctor's job.
32
+
33
+ ## Boundary — read before composing
34
+
35
+ - **Verbs and flags live in `sp:spur-cli`.** This skill links references; it never restates a verb
36
+ or flag catalog: [../spur-cli/SKILL.md](../spur-cli/SKILL.md).
37
+ - **Recurring loops and coordination go to `sp:super-planner`** or a workflow — not here. This skill
38
+ runs one bounded composition or tuning pass per invocation.
39
+ - **Forbidden surfaces: `spur team` and `spur agent loop`.** Agent specs are reached only through
40
+ `spur agent create|edit|delete|list --specs`.
41
+ - **Writes land only through `spur` verbs** and the ladder's gated file steps (§ below). The shared
42
+ step additionally needs recorded operator consent plus `build:bundle` parity.
43
+
44
+ ## Covered nouns
45
+
46
+ | Noun | Composition / tuning method | Verb reference |
47
+ | --- | --- | --- |
48
+ | task | Apply accepted doctor rows via the CLI-gated corpus surface; author variants through the task reference's conventions | [../spur-cli/references/tasks.md](../spur-cli/references/tasks.md) |
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
+ | 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
+ | 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 | Compose and edit `.spur/agents/<id>.yaml` only through `spur agent create|edit|delete|list --specs` | [../spur-cli/references/agent.md](../spur-cli/references/agent.md) |
53
+
54
+ Do not drive the planning→execution lifecycle from here — that is `sp:spur-dev`.
55
+
56
+ ## Workflow catalog selection
57
+
58
+ Run this **before composing anything new**, exactly as the
59
+ [find-existing-workflow](../spur-cli/references/workflows/operations.md#sub-procedure-find-existing-workflow)
60
+ procedure: the catalog is `spur workflow list --json` across all layers, and each entry's
61
+ `description` is its intent.
62
+
63
+ | Catalog match | Action |
64
+ | --- | --- |
65
+ | Matches the intent | **Run it as is.** No new artifact. |
66
+ | Near match | **Same-name override in the project layer** (`.spur/workflows/<name>.yaml`) — the project layer wins name resolution — and tune from there. |
67
+ | No match | **Compose** up the ladder (§ Composition ladder). |
68
+
69
+ Never glob a folder to enumerate candidates: layers you skip that way are layers a bare name
70
+ cannot resolve from.
71
+
72
+ ## Composition ladder
73
+
74
+ | Step | Location | Gate before use |
75
+ | --- | --- | --- |
76
+ | ephemeral | A scratch file outside every layer (for example under `.spur/run/`), run by explicit path | `spur workflow validate`, `spur workflow run --dry-run`, a `spur workflow show` preview |
77
+ | project | `.spur/workflows/<name>.yaml` | The same gates |
78
+ | shared | the spur repository's shipped shared workflow layer (layer id `shared` in `spur workflow list --json`) as `<name>.yaml` | The same gates, **plus recorded operator consent and `build:bundle` parity** |
79
+
80
+ - `spur workflow validate --json` exits 1 on an error-level composition finding, so a definition
81
+ over a cap cannot climb. Warn-level findings do not block a step.
82
+ - Verify each step through the shared
83
+ [validate-and-dry-run](../spur-cli/references/workflows/operations.md#sub-procedure-validate-and-dry-run)
84
+ core. The shared step is a promotion, not a copy: record the operator consent that authorizes it,
85
+ then rebuild the bundle (`bun run --filter @gobing-ai/spur build:bundle`) so the shipped config
86
+ matches.
87
+ - In an adopting project the shared layer is the installed package and is read-only — the project
88
+ step is the tuning path there.
89
+
90
+ ## Composition budgets (ADR-115)
91
+
92
+ The consolidation and cache-window rules are taught once in
93
+ [workflow-fit-and-tuning.md](../spur-cli/references/workflows/workflow-fit-and-tuning.md#consolidation-and-cache-windows-adr-115)
94
+ and owned by the
95
+ [workflow composition contract](../../../../docs/design/workflow-composition-contract.md#composition-budgets-adr-115);
96
+ link them, never restate them. While composing or tuning a workflow, apply them with the ADR-115
97
+ budgets:
98
+
99
+ - **Merge adjacent model steps** only when they share a role and an executor **and** no gate, HITL
100
+ state or independence boundary sits between them.
101
+ - **Never merge an author step with the review or verify step that certifies it** — those keep
102
+ `freshSession: true`.
103
+ - **Run long deterministic work outside `agent.run`** — an in-step tool call that outlasts the
104
+ cache window idles the model and cold-rewrites the prefix.
105
+
106
+ A new model step in a shared workflow raises its `pipeline-budgets` `modelQueries`; that needs a
107
+ recorded decision before the shared step.
108
+
109
+ ## Rule tuning loop
110
+
111
+ Start from trace evidence, never from a guess:
112
+
113
+ 1. `spur rule trace <runId> --json` — read the per-rule `evaluations` findings and severities.
114
+ 2. Classify each hit: true positive, false positive, or noise.
115
+ 3. Tune with the [fine-tuning levers](../spur-cli/references/rules/fine-tuning.md) — severity,
116
+ glob scoping, exemptions, preset composition.
117
+ 4. `spur rule validate` on the tuned rule files.
118
+ 5. `spur rule run` on the affected inputs (constitution T11 — affected inputs, not a corpus sweep).
119
+ 6. Trace again and compare. A tuning with no trace pair behind it is a preference.
120
+
121
+ ## Applying doctor proposals
122
+
123
+ `sp:spur-doctor` ([../spur-doctor/SKILL.md](../spur-doctor/SKILL.md)) returns a proposal table;
124
+ the operator accepts rows; **this skill applies them**:
125
+
126
+ 1. For each accepted row, run its `apply` route — always the `spur` verb or ladder step named in
127
+ the row. Composer never invents a write route.
128
+ 2. Re-run that row's `verify` evidence and confirm it clears. An accepted row that cannot verify
129
+ is reported as not applied, never waved through.
130
+ 3. A `task` row carries the history-anatomy finding `key` in the task body — the existing handoff
131
+ route. Keep it.
132
+ 4. A row that changes a shared workflow goes through the ladder's shared step and its recorded
133
+ consent.
134
+
135
+ A caller that wants a record saves the accepted table under `docs/reports/`; this skill creates no
136
+ artifact store.
137
+
138
+ ## What this skill is not
139
+
140
+ - **Not the judge.** `sp:spur-doctor` evaluates artifacts and proposes; code review is
141
+ `sp:super-reviewer`.
142
+ - **Not a loop.** Recurring evolution loops and multi-agent coordination belong to
143
+ `sp:super-planner` or a workflow definition.
144
+ - **Not a catalog.** Verb, flag, output and exit semantics live in the `sp:spur-cli` references
145
+ linked above.
@@ -270,6 +270,30 @@ missing title match. After batch creation, `handoff-finalize`:
270
270
  (runall is then omitted), otherwise `/sp:dev-runall --feature <id> --auto`. The terminal
271
271
  handoff note points at this report.
272
272
 
273
+ **Ready preparation (ready-prepare, 0788).** The input is the `.wbs` array in
274
+ `.spur/run/<runId>-idea-batch-create-result.json`. For EACH wbs: resolve the task file with
275
+ `spur task path <wbs> --json` and apply the ready-refinement checklist — make requirements,
276
+ design, plan, acceptance criteria, decisions, dependencies and premises present and
277
+ non-placeholder so `spur task check <wbs> --json` exits 0. Write planning sections only, through
278
+ `spur task update <wbs> --section <Name> --from-file <file>` — never Solution, Testing, Review
279
+ or History. Record one checklist row per id, with concrete evidence of how you verified it.
280
+ Compute the planning digest with the project's own implementation when this is a monorepo
281
+ checkout — resolve the file with `spur task path <wbs> --json`, then run:
282
+
283
+ ```bash
284
+ bun -e 'const m = await import("./packages/app/src/services/task-readiness"); console.log(m.computePlanningDigest(await Bun.file(process.argv[1]).text()))' <task-file>
285
+ ```
286
+
287
+ When that is impossible in this checkout, set status `skipped` instead of guessing a digest.
288
+ Finally write `.spur/run/<runId>-idea-ready.json` with exactly this shape:
289
+
290
+ ```json
291
+ {"runId":"<runId>","depth":"ready","tasks":[{"wbs":"<wbs>","status":"ready" | "failed" | "skipped","planningDigest":"<sha256 hex>","checks":[{"id":"requirements" | "design" | "plan" | "ac" | "decisions" | "dependencies" | "premises","pass":true,"evidence":"<how verified>"}]}]}
292
+ ```
293
+
294
+ A task you cannot fully prepare gets status `failed` or `skipped` — never fabricate evidence;
295
+ the handoff degrades to refineall.
296
+
273
297
  ## Step 6: Refine before execute (the spec-completion gate)
274
298
 
275
299
  `batch-create` accepts optional `design` / `plan` / `acceptance_criteria` fields (plus