@gobing-ai/spur 0.3.80 → 0.3.82

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 (177) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/config.example.yaml +31 -18
  3. package/config/config.global.yaml +13 -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/templates/docs/99_PROJECT_CONSTITUTION.md +75 -13
  33. package/config/transition-shims.json +0 -7
  34. package/config/workflows/basic.yaml +4 -0
  35. package/config/workflows/docs-pipeline.yaml +13 -14
  36. package/config/workflows/feature-dev.yaml +20 -65
  37. package/config/workflows/history-anatomy.yaml +22 -1
  38. package/config/workflows/idea-pipeline.yaml +53 -97
  39. package/config/workflows/pr-review.yaml +21 -33
  40. package/config/workflows/task-pipeline.yaml +87 -330
  41. package/config/workflows/wayfinder-resolution.yaml +12 -26
  42. package/config/workflows/wrapup-pipeline.yaml +48 -189
  43. package/package.json +9 -9
  44. package/plugins/sp/README.md +12 -3
  45. package/plugins/sp/agents/expert-spur.md +41 -19
  46. package/plugins/sp/lib/idea-handoff.generated.d.mts +17 -0
  47. package/plugins/sp/lib/idea-handoff.generated.mjs +1301 -0
  48. package/plugins/sp/plugin.json +1 -1
  49. package/plugins/sp/scripts/feature-dev-precheck.mjs +146 -0
  50. package/plugins/sp/scripts/feature-dev-precheck.ts +238 -0
  51. package/plugins/sp/scripts/idea-handoff.mjs +27 -0
  52. package/plugins/sp/scripts/idea-handoff.ts +44 -0
  53. package/plugins/sp/scripts/inline-run-setup.ts +69 -1
  54. package/plugins/sp/scripts/quality-gate.mjs +216 -0
  55. package/plugins/sp/scripts/quality-gate.ts +287 -0
  56. package/plugins/sp/scripts/surface-drift-inventory.ts +0 -2
  57. package/plugins/sp/scripts/task-size-precheck.ts +44 -16
  58. package/plugins/sp/scripts/verify-answer-lint.ts +17 -1
  59. package/plugins/sp/scripts/workflow-step-profile.mjs +319 -0
  60. package/plugins/sp/scripts/workflow-step-profile.ts +456 -0
  61. package/plugins/sp/scripts/wrapup-steps.mjs +350 -0
  62. package/plugins/sp/scripts/wrapup-steps.ts +466 -0
  63. package/plugins/sp/skills/code-review/references/review-lenses.md +3 -0
  64. package/plugins/sp/skills/parallel-execution/references/dispatch-surface.md +1 -1
  65. package/plugins/sp/skills/spec-decomposition/references/decomposition.md +29 -0
  66. package/plugins/sp/skills/spur-cli/SKILL.md +4 -8
  67. package/plugins/sp/skills/spur-cli/references/agent.md +44 -69
  68. package/plugins/sp/skills/spur-cli/references/message.md +30 -3
  69. package/plugins/sp/skills/spur-cli/references/projects.md +25 -1
  70. package/plugins/sp/skills/spur-cli/references/self.md +6 -5
  71. package/plugins/sp/skills/spur-cli/references/serve.md +8 -7
  72. package/plugins/sp/skills/spur-cli/references/tasks.md +1 -1
  73. package/plugins/sp/skills/spur-cli/references/workflows/operations.md +6 -3
  74. package/plugins/sp/skills/spur-cli/references/workflows/workflow-fit-and-tuning.md +57 -18
  75. package/plugins/sp/skills/spur-composer/SKILL.md +145 -0
  76. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +10 -0
  77. package/plugins/sp/skills/spur-dev/references/execution-batch.md +1 -1
  78. package/plugins/sp/skills/spur-dev/references/execution-workflow.md +4 -6
  79. package/plugins/sp/skills/spur-dev/references/glossary.md +1 -1
  80. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +11 -1
  81. package/plugins/sp/skills/spur-dev/references/planning-workflow.md +24 -0
  82. package/plugins/sp/skills/spur-doctor/SKILL.md +138 -0
  83. package/plugins/sp/skills/taste-refactoring-api/README.md +43 -0
  84. package/plugins/sp/skills/taste-refactoring-api/SKILL.md +334 -0
  85. package/plugins/sp/skills/taste-refactoring-api/checklists/daily-api-review.md +71 -0
  86. package/plugins/sp/skills/taste-refactoring-api/examples/refactor-example.md +72 -0
  87. package/plugins/sp/skills/taste-refactoring-api/examples/review-template.md +93 -0
  88. package/plugins/sp/skills/taste-refactoring-api/references/api-refactoring-playbook.md +253 -0
  89. package/plugins/sp/skills/taste-refactoring-api/references/protocol-modes.md +79 -0
  90. package/plugins/sp/skills/taste-refactoring-api/references/research-basis.md +58 -0
  91. package/plugins/sp/skills/taste-refactoring-architect/README.md +26 -0
  92. package/plugins/sp/skills/taste-refactoring-architect/SKILL.md +471 -0
  93. package/plugins/sp/skills/taste-refactoring-architect/checklists/daily-architecture-review.md +48 -0
  94. package/plugins/sp/skills/taste-refactoring-architect/examples/refactor-example.md +55 -0
  95. package/plugins/sp/skills/taste-refactoring-architect/examples/review-template.md +51 -0
  96. package/plugins/sp/skills/taste-refactoring-architect/references/architecture-refactoring-playbook.md +173 -0
  97. package/plugins/sp/skills/taste-refactoring-architect/references/research-basis.md +28 -0
  98. package/plugins/sp/skills/taste-refactoring-tests/README.md +28 -0
  99. package/plugins/sp/skills/taste-refactoring-tests/SKILL.md +482 -0
  100. package/plugins/sp/skills/taste-refactoring-tests/checklists/daily-test-review.md +39 -0
  101. package/plugins/sp/skills/taste-refactoring-tests/examples/refactor-example.md +85 -0
  102. package/plugins/sp/skills/taste-refactoring-tests/examples/review-template.md +59 -0
  103. package/plugins/sp/skills/taste-refactoring-tests/references/research-basis.md +47 -0
  104. package/plugins/sp/skills/taste-refactoring-tests/references/test-refactoring-playbook.md +222 -0
  105. package/plugins/sp/skills/taste-refactoring-ui/README.md +12 -0
  106. package/plugins/sp/skills/taste-refactoring-ui/SKILL.md +290 -0
  107. package/plugins/sp/skills/taste-refactoring-ui/checklists/daily-ui-review.md +72 -0
  108. package/plugins/sp/skills/taste-refactoring-ui/examples/review-template.md +51 -0
  109. package/plugins/sp/skills/taste-refactoring-ui/references/refactoring-ui-playbook.md +170 -0
  110. package/plugins/sp/skills/wayfinder/SKILL.md +2 -2
  111. package/plugins/sp/skills/wayfinder/references/pipeline-resolution.md +30 -0
  112. package/schemas/spur-config.schema.json +105 -85
  113. package/spur.js +44616 -43320
  114. package/web/_astro/BoardApp.D-WlxiN2.js +1 -0
  115. package/web/_astro/{BoardApp.CHQ1lycZ.js → BoardApp.D8bM9pKL.js} +97 -95
  116. package/web/_astro/{TaskDetail.GKfQJ60c.js → TaskDetail.BPRqgVUE.js} +1 -1
  117. package/web/_astro/{arc.DWEtA3Tx.js → arc.BPrPES3z.js} +1 -1
  118. package/web/_astro/{architectureDiagram-3BPJPVTR.DB42oWmP.js → architectureDiagram-3BPJPVTR.qX_7q02P.js} +1 -1
  119. package/web/_astro/{blockDiagram-GPEHLZMM.rhv-zNQV.js → blockDiagram-GPEHLZMM.CUZfj5V7.js} +1 -1
  120. package/web/_astro/{c4Diagram-AAUBKEIU.Ci4-4VvY.js → c4Diagram-AAUBKEIU.CTaOr8hH.js} +1 -1
  121. package/web/_astro/channel.DGZaFHZx.js +1 -0
  122. package/web/_astro/{chunk-2J33WTMH.Cc9veUgf.js → chunk-2J33WTMH.Dt-9wf3h.js} +1 -1
  123. package/web/_astro/{chunk-4BX2VUAB.Bec9c4eI.js → chunk-4BX2VUAB.CTC2sdoN.js} +1 -1
  124. package/web/_astro/{chunk-55IACEB6.DoV8S1iB.js → chunk-55IACEB6.DQcxt2_g.js} +1 -1
  125. package/web/_astro/{chunk-727SXJPM.DwR-Qlyj.js → chunk-727SXJPM.DXFPSn-a.js} +1 -1
  126. package/web/_astro/{chunk-AQP2D5EJ.ND_a81WY.js → chunk-AQP2D5EJ.BCx3U4bT.js} +1 -1
  127. package/web/_astro/{chunk-FMBD7UC4.Wv_jwG48.js → chunk-FMBD7UC4.DL2tJkdO.js} +1 -1
  128. package/web/_astro/{chunk-ND2GUHAM.CXKXCMmp.js → chunk-ND2GUHAM.DZyflMro.js} +1 -1
  129. package/web/_astro/{chunk-QZHKN3VN.nkaoNYQq.js → chunk-QZHKN3VN.CUI2mT09.js} +1 -1
  130. package/web/_astro/{classDiagram-4FO5ZUOK.cMQcVlQu.js → classDiagram-4FO5ZUOK.g4rX4Fr1.js} +1 -1
  131. package/web/_astro/{classDiagram-v2-Q7XG4LA2.cMQcVlQu.js → classDiagram-v2-Q7XG4LA2.g4rX4Fr1.js} +1 -1
  132. package/web/_astro/{cose-bilkent-S5V4N54A.OaDJ7Mr2.js → cose-bilkent-S5V4N54A.CzWJLqp0.js} +1 -1
  133. package/web/_astro/{cynefin-OW5HDTMX.Chi8IphF.js → cynefin-OW5HDTMX.WgsvQeCR.js} +1 -1
  134. package/web/_astro/{cytoscape.esm.DzSz-X2X.js → cytoscape.esm.BB4DxJjf.js} +1 -1
  135. package/web/_astro/{dagre-BM42HDAG.CzK2t_Fp.js → dagre-BM42HDAG.Dzv6ngql.js} +1 -1
  136. package/web/_astro/{diagram-2AECGRRQ.DRvxlVS7.js → diagram-2AECGRRQ.CpJ4a9rU.js} +1 -1
  137. package/web/_astro/{diagram-5GNKFQAL.CnYvNdwA.js → diagram-5GNKFQAL.CzPlF_dq.js} +1 -1
  138. package/web/_astro/{diagram-KO2AKTUF.CpLpMw5R.js → diagram-KO2AKTUF.TAkZNTcQ.js} +1 -1
  139. package/web/_astro/{diagram-LMA3HP47.JTb78qUA.js → diagram-LMA3HP47.uCjoKSag.js} +1 -1
  140. package/web/_astro/{diagram-OG6HWLK6.Bk-1jDIb.js → diagram-OG6HWLK6.eMplIjoK.js} +1 -1
  141. package/web/_astro/{erDiagram-TEJ5UH35.D8hN9GZq.js → erDiagram-TEJ5UH35.Bf7zoXGz.js} +1 -1
  142. package/web/_astro/{flowDiagram-I6XJVG4X.-6zQr6m5.js → flowDiagram-I6XJVG4X.B_bHj3gN.js} +1 -1
  143. package/web/_astro/{ganttDiagram-6RSMTGT7.DboLQ9ca.js → ganttDiagram-6RSMTGT7.BasrHRMj.js} +1 -1
  144. package/web/_astro/{gitGraphDiagram-PVQCEYII.4tYvJKGR.js → gitGraphDiagram-PVQCEYII.C6iphq1x.js} +1 -1
  145. package/web/_astro/index.DayyIngm.css +1 -0
  146. package/web/_astro/{infoDiagram-5YYISTIA.Bd9rXpsB.js → infoDiagram-5YYISTIA.HXmDMhW4.js} +1 -1
  147. package/web/_astro/{ishikawaDiagram-YF4QCWOH.CvMoaf67.js → ishikawaDiagram-YF4QCWOH.BSmW8NiU.js} +1 -1
  148. package/web/_astro/{journeyDiagram-JHISSGLW.Ccy1CA7y.js → journeyDiagram-JHISSGLW.DEQow5fo.js} +1 -1
  149. package/web/_astro/{kanban-definition-UN3LZRKU.0MaMqHNS.js → kanban-definition-UN3LZRKU.IVm9cTdc.js} +1 -1
  150. package/web/_astro/{linear.CHXgcIbN.js → linear.CrsM73_9.js} +1 -1
  151. package/web/_astro/{mermaid.core.Ca-kcelG.js → mermaid.core.CfBeDJls.js} +6 -6
  152. package/web/_astro/{mindmap-definition-RKZ34NQL.BUIDlHa0.js → mindmap-definition-RKZ34NQL.C3j60Y-0.js} +1 -1
  153. package/web/_astro/ordinal.BYWQX77i.js +1 -0
  154. package/web/_astro/{pieDiagram-4H26LBE5.2dX3CU1s.js → pieDiagram-4H26LBE5.B-aCMeEA.js} +1 -1
  155. package/web/_astro/{quadrantDiagram-W4KKPZXB.B3LBlRiv.js → quadrantDiagram-W4KKPZXB.Cib965yq.js} +1 -1
  156. package/web/_astro/{requirementDiagram-4Y6WPE33.X12I2uNx.js → requirementDiagram-4Y6WPE33.D61cS4O-.js} +1 -1
  157. package/web/_astro/{sankeyDiagram-5OEKKPKP.BXohIHqx.js → sankeyDiagram-5OEKKPKP.GKF2qVPy.js} +1 -1
  158. package/web/_astro/{sequenceDiagram-3UESZ5HK.C37ZIUzg.js → sequenceDiagram-3UESZ5HK.DZnq8F2h.js} +1 -1
  159. package/web/_astro/{stateDiagram-AJRCARHV.BRgz317z.js → stateDiagram-AJRCARHV.DXUFmdgM.js} +1 -1
  160. package/web/_astro/{stateDiagram-v2-BHNVJYJU.7VYSXN9-.js → stateDiagram-v2-BHNVJYJU.BtHmhLEz.js} +1 -1
  161. package/web/_astro/{timeline-definition-PNZ67QCA.BVNz_HiN.js → timeline-definition-PNZ67QCA.Cy-WW2ln.js} +1 -1
  162. package/web/_astro/{vennDiagram-CIIHVFJN.CHVDkPX4.js → vennDiagram-CIIHVFJN.SLp5b9KI.js} +1 -1
  163. package/web/_astro/{wardleyDiagram-YWT4CUSO.EQQ_qT9v.js → wardleyDiagram-YWT4CUSO.Bww45mWV.js} +1 -1
  164. package/web/_astro/{xychartDiagram-2RQKCTM6.DrAT9WoP.js → xychartDiagram-2RQKCTM6.DR4swI6a.js} +1 -1
  165. package/web/apple-touch-icon.png +0 -0
  166. package/web/favicon.ico +0 -0
  167. package/web/favicon.svg +17 -4
  168. package/web/icon-192.png +0 -0
  169. package/web/icon-512.png +0 -0
  170. package/web/index.html +2 -2
  171. package/web/site.webmanifest +31 -0
  172. package/web/spur_logo.svg +1 -0
  173. package/plugins/sp/skills/spur-cli/references/team.md +0 -145
  174. package/web/_astro/BoardApp.DV9kx0wo.js +0 -1
  175. package/web/_astro/channel.BAI6xLeV.js +0 -1
  176. package/web/_astro/index.Dcr_8fiK.css +0 -1
  177. package/web/_astro/ordinal.DBvzRdQf.js +0 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: spur-cli-agent
3
- description: "spur-cli noun reference: operate `spur agent` as the coding-agent execution surface - run prompts, wait on pinned occupants, manage team agent specs, run the persistent self-draining loop, and check readiness."
3
+ description: "spur-cli noun reference: operate `spur agent` as the coding-agent execution surface - run prompts, wait on pinned occupants, list agent specs, start/stop supervised processes, and check readiness."
4
4
  see_also:
5
5
  - spur-cli
6
6
  ---
@@ -9,7 +9,7 @@ see_also:
9
9
 
10
10
  `spur agent` is the CLI for **running and inspecting coding agents**. It wraps the agents the
11
11
  operator already has installed (Claude Code, Codex, omp, OpenCode, Antigravity, etc.) behind a
12
- uniform run, wait, loop, and spec-management surface, so the rest of the harness can dispatch work without
12
+ uniform run, wait, and supervision surface, so the rest of the harness can dispatch work without
13
13
  hard-coding a specific agent.
14
14
 
15
15
  This is a **companion reference**, not an orchestrator. It documents *what each verb is and how to
@@ -22,16 +22,14 @@ that before using `run` for fan-out dispatch.
22
22
  | Verb | Purpose | Key flags |
23
23
  | ---- | ------- | --------- |
24
24
  | `run <prompt>` | Execute a prompt or slash command via a coding agent | `--agent <name>` `--spec <id>` `--model <name>` `--mode <mode>` `--continue` `--cwd <path>` `--drain` `--json` |
25
- | `loop` | Persistent self-draining inbox loop for a team member (supervisor-managed) | `--spec <id>` `--agent <id>` `--poll <ms>` |
26
25
  | `wait [<specId>]` | Identity-pinned wait for an occupant run to reach a lifecycle state (G4 wave 2; `--role` selector per 0685) | `--role <name>` `--run <runId>` `--until <state>...` `--timeout <ms>` `--json` |
27
- | `list` | List detected coding agents, or team agent specs with `--specs` | `--specs` `--json` |
26
+ | `list` | List detected coding agents, or agent specs with `--specs` (live run status merged from `spur serve`) | `--specs` `--server <url>` `--json` |
28
27
  | `doctor [agent]` | Check agent readiness | `--json` `--probe-health` `--force-refresh` |
29
- | `create <id>` | Write a team agent spec to `.spur/agents/<id>.yaml` | `--type` `--tags` `--model` `--autonomy` `--system-prompt` `--name` `--workspace` `--purpose` `--auto-start` `--no-identity-preamble` `--json` |
30
- | `edit <id>` | Open an agent spec in `$EDITOR`, or print its path | - |
31
- | `delete <id>` | Remove an agent spec | `--force` |
28
+ | `start <spec-id>` | Start a supervised agent process (requires `spur serve`) | `--server <url>` `--json` |
29
+ | `stop <spec-id>` | Stop a supervised agent process (requires `spur serve`) | `--server <url>` `--json` |
32
30
 
33
- `list`, `doctor`, `run`, `wait`, and `create` accept `--json` plus `--json-envelope`. `loop`, `edit`,
34
- and `delete` are human/process-control surfaces. **Exit codes:** `0` success, `1` failure, and `2`
31
+ `list`, `doctor`, `run`, `wait`, `start`, and `stop` accept `--json` plus `--json-envelope`. The hidden
32
+ `loop` is a supervisor-internal process surface. **Exit codes:** `0` success, `1` failure, and `2`
35
33
  invalid usage; `run` can also propagate the invoked agent's non-zero result.
36
34
 
37
35
  ## `run` - execute a prompt via a coding agent
@@ -54,7 +52,7 @@ through a coding agent as an external process, producing a persisted run record
54
52
  | `--mode <mode>` | Agent output mode: `text` or `json`. |
55
53
  | `--continue` | Resume the previous agent session instead of starting fresh. |
56
54
  | `--cwd <path>` | Working directory for agent execution (default: current directory). |
57
- | `--spec <id>` | Team agent spec id (occupant addressing, 0542 R1). Pairs with `--drain`; with `--spec` alone the run is addressed to the occupant without touching the inbox. A legacy `--agent <spec-id>` still works during the transition with a one-time warning (shim `agent-flag-spec-id`). |
55
+ | `--spec <id>` | Agent spec id (occupant addressing, 0542 R1). Pairs with `--drain`; with `--spec` alone the run is addressed to the occupant without touching the inbox. A legacy `--agent <spec-id>` is still accepted as fallback addressing (task 0849 retired the `agent-flag-spec-id` deprecation warning). |
58
56
  | `--drain` | Prepend pending inbox messages addressed to `--spec <id>` before the prompt. |
59
57
  | `--json` | Output machine-readable JSON where supported. |
60
58
  | `--json-envelope` | Wrap JSON using the facade's standard output contract. |
@@ -83,26 +81,15 @@ can fail when the external agent writes its own storage outside the sandbox's al
83
81
  `AgentStorage` SQLite DB). This is not a reason to abandon `spur agent run` - triggers 1-4 still
84
82
  justify it - but ensure the run executes in a context that can write the target agent's storage.
85
83
 
86
- ## `loop` - persistent self-draining wrapper
84
+ ## `loop` - supervisor-internal self-draining wrapper (hidden)
87
85
 
88
- ```bash
89
- spur agent loop --agent worker-1 --poll 2000
90
- ```
91
-
92
- `loop` is the **persistent self-draining wrapper** used by the team supervisor. It polls the
93
- addressed agent's inbox, drains each pending message into an `agent run` invocation, and idles
94
- between drains. It is not typically invoked directly by the operator - `spur team start` launches it
95
- under supervision.
96
-
97
- ### Flags
98
-
99
- | Flag | Purpose |
100
- |------|---------|
101
- | `--spec <id>` | **Required.** Team agent spec id / message recipient (0542 R1; legacy `--agent <spec-id>` still read with a one-time warning). |
102
- | `--poll <ms>` | Idle poll interval in milliseconds (default: `2000`). |
103
-
104
- The loop runs until `SIGINT` / `SIGTERM`. Each iteration: check inbox -> if messages, drain each
105
- into `run` with `--drain` -> else sleep for `--poll` ms.
86
+ `spur agent loop --spec <id> [--poll <ms>]` is spawned by the `spur serve` supervisor for each
87
+ materialized agent spec; it is hidden from `--help` and not an operator verb (use `spur agent start`).
88
+ It waits for a wake on the `system_events` ledger — a human request (`message.sent`), a strategy
89
+ change (`strategy.changed`), a capacity change (`fleet.capacity.changed`), or a completion receipt
90
+ (`agent.invoke.exit`) — then drains the inbox into an `agent run` invocation. An idle wake records
91
+ the hold reason instead of dispatching; with no wake event it still drains every `--poll` ms
92
+ (default `2000`). It runs until `SIGINT` / `SIGTERM`.
106
93
 
107
94
  ## `wait` - identity-pinned occupant wait (G4 wave 2)
108
95
 
@@ -143,16 +130,26 @@ exits 2 naming the accepted vocabulary. Resolution collapses onto the same ident
143
130
  | `timeout` | 1 | Caller `--timeout` elapsed (or aborted via SIGINT). |
144
131
  | `usage` | 2 | Invalid flags, or `--until blocked` as the sole target (no first-class signal in wave 2). |
145
132
 
146
- ## `list` - detected agents and team specs
133
+ ## `list` - detected agents and agent specs
147
134
 
148
135
  ```bash
149
136
  spur agent list # detected coding agents on this machine
150
- spur agent list --specs # team agent specs under .spur/agents/
137
+ spur agent list --specs # agent specs under .spur/agents/
151
138
  spur agent list --json # machine-readable
152
139
  ```
153
140
 
154
141
  Without `--specs`, lists coding agents detected on the host (by binary on `PATH`). With `--specs`,
155
- lists team agent specs (`.spur/agents/*.yaml`).
142
+ lists agent specs (`.spur/agents/*.yaml`) **with live run status merged from the server's
143
+ supervisor**: each row carries a trailing status column
144
+ (`running` / `stopped` / `errored` / `unknown`) and `pid=<n>` where a process exists. When `spur serve`
145
+ is unreachable, the listing falls back to all `stopped` with a stderr warning. `--server <url>`
146
+ (default `http://localhost:3000/api`) targets the supervisor API.
147
+
148
+ ```bash
149
+ spur agent list --specs
150
+ # planner claude reviewer claude plans the work running pid=4132
151
+ # worker-1 pi worker pi implements stopped
152
+ ```
156
153
 
157
154
  ## `doctor` - readiness check
158
155
 
@@ -168,63 +165,41 @@ Checks whether each agent is installed and ready to run. Text mode renders a cap
168
165
  (`cheap|standard|capable-*`), MODEL the pinned config model (`—` when undeclared), and ROLES lists
169
166
  candidate pipeline roles with `*` on the elected one. Exit `1` if any checked agent is not ready.
170
167
 
171
- ## `create` - author a team agent spec
172
-
173
- ```bash
174
- spur agent create worker-1 --type claude --tags team:alpha --model sonnet
175
- spur agent create reviewer --type codex --autonomy review --auto-start
176
- ```
177
-
178
- Writes a team agent spec to `.spur/agents/<id>.yaml`. The spec captures the agent's identity
179
- (type, model, autonomy, system prompt, tags) so `spur team up` can materialize a roster and `spur
180
- agent loop` can self-drain its inbox.
181
-
182
- ### Flags
183
-
184
- | Flag | Purpose |
185
- | ------ | --------- |
186
- | `--type <agent-type>` | Agent spec type (e.g. `claude`, `codex`, `omp`). |
187
- | `--tags <a,b>` | Comma-separated team identity tags (e.g. `team:alpha,role:worker`). |
188
- | `--model <name>` | Agent model argument. |
189
- | `--autonomy <level>` | Autonomy level (e.g. `full`, `review`). |
190
- | `--system-prompt <text>` | Team identity system prompt. |
191
- | `--name <name>` | Agent display name. |
192
- | `--workspace <path>` | Workspace path for this agent. |
193
- | `--purpose <text>` | Team identity purpose. |
194
- | `--auto-start` | Auto-start flag (start on `team up` without manual `team start`). |
195
- | `--no-identity-preamble` | Disable the identity preamble prepended to prompts. |
196
- | `--json` | Output machine-readable JSON. |
197
-
198
- ## `edit` - open a spec in `$EDITOR`
168
+ ## `start` - start a supervised process
199
169
 
200
170
  ```bash
201
- spur agent edit worker-1
171
+ spur agent start worker-1
172
+ spur agent start worker-1 --json
202
173
  ```
203
174
 
204
- Opens `.spur/agents/<id>.yaml` in `$EDITOR`. If `$EDITOR` is unset, prints the spec path instead.
175
+ Posts to the `spur serve` supervisor API
176
+ (`POST /api/agents/:id/start`) and prints `started <id> (pid=<n>, status=<s>)`. Requires a
177
+ reachable `spur serve`; `--server <url>` (default `http://localhost:3000/api`) targets it. Exit `1`
178
+ when the server is unreachable or the start fails.
205
179
 
206
- ## `delete` - remove a spec
180
+ ## `stop` - stop a supervised process
207
181
 
208
182
  ```bash
209
- spur agent delete worker-1 --force
183
+ spur agent stop worker-1
184
+ spur agent stop worker-1 --json
210
185
  ```
211
186
 
212
- `--force` is required (guards against accidental deletion). Removes `.spur/agents/<id>.yaml`.
187
+ Posts to the supervisor API
188
+ (`POST /api/agents/:id/stop`) and prints `stopped <id>`. Same server requirement and flags as
189
+ `start`.
213
190
 
214
191
  ## What this skill is NOT
215
192
 
216
193
  - **Not the dispatch decision.** *When* to use `spur agent run` vs a native subagent is the
217
194
  **[dispatch-surface rule](../../parallel-execution/references/dispatch-surface.md)**, not this
218
195
  reference. This reference documents the verbs; that rule decides which surface carries a dispatch.
219
- - **Not the team orchestrator.** `spur team up` / `spur team start` drive the supervisor lifecycle;
220
- `spur agent` provides the execution primitives they compose.
196
+ - **Not the fleet orchestrator.** The `spur serve` supervisor drives the lifecycle: `spur agent
197
+ start` / `stop` manage supervised processes and `agent list --specs` reports live state.
221
198
 
222
199
  ## See also
223
200
 
224
201
  - **[dispatch-surface.md](../../parallel-execution/references/dispatch-surface.md)** - native
225
202
  subagent vs `spur agent run` decision rule. `--model` and `--agent` are its escalation levers.
226
- - **`spur team` (see [team.md](team.md))** - team lifecycle that launches `agent loop` under
227
- supervision.
228
203
  - **`spur message` (see [message.md](message.md))** - the inbox `--drain` reads from.
229
204
  - **`sp:spur-cli`** SKILL.md - the facade that routes to this reference.
230
205
 
@@ -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.
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,7 +19,7 @@ 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
25
 
@@ -36,6 +36,30 @@ exit `0`; validation, registry, spawn, health, or lookup failure is exit `1`.
36
36
  defaults the display name to its basename. It upserts; it does not start a server. The current
37
37
  source does not enforce a `.spur/` marker or directory type.
38
38
  - `list` probes recorded ports and heals stale entries to `port: 0` before reporting `running`.
39
+ - `list --fleet` (0835/0858) additionally resolves each project's `agent.fleet` section from that
40
+ project's `.spur/config.yaml` under the existing verb (no new noun). Per project it prints one line
41
+ per member: instance id (the spec id / mailbox identity), `role`, resolved `executor`,
42
+ `fsWrite` capability state, and derived `write` flag. A project with no declaration reports
43
+ `no declaration (agent.fleet)`; a declared but switched-off fleet reports
44
+ `disabled (agent.fleet.enabled: false)` and still lists its roster; an all-disabled roster reports
45
+ `no enabled members`; a project whose config fails to load (a retired source, an invalid section)
46
+ reports the loader's message without failing the listing. Under `--json` each project gains `fleet`
47
+ (the resolved fleet, `null` on resolution failure) and, on failure, `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`.
39
63
 
40
64
  ## Server lifecycle
41
65
 
@@ -77,7 +77,7 @@ spur self serve --json # dry probe: print { port, url, pid, runni
77
77
  ```
78
78
 
79
79
  Starts the Hono/Cloudflare-Worker server that serves the web Task Kanban and exposes the team
80
- supervisor API (`/api/team/*`). It is the local fallback when no remote server is configured.
80
+ supervisor API (`/api/processes/*` + `/api/agents/*`). It is the local fallback when no remote server is configured.
81
81
  Flags: `--port <n>`, `--host <addr>`, `--no-open`, `--cwd <path>`, `--json` (a dry probe — reports
82
82
  the resolved port/url without starting the server). Full flag semantics: **[serve.md](serve.md)**.
83
83
 
@@ -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 agent 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
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: spur-cli-serve
3
- description: "spur-cli noun reference: operate `spur serve` as the local web-server fallback - start the Hono/Cloudflare-Worker server that backs the web Task Kanban and the team supervisor API. Single verb, five flags."
3
+ description: "spur-cli noun reference: operate `spur serve` as the local web-server fallback - start the Hono/Cloudflare-Worker server that backs the web Task Kanban and the supervisor API. Single verb, five flags."
4
4
  see_also:
5
5
  - spur-cli
6
6
  ---
@@ -8,7 +8,7 @@ see_also:
8
8
  # spur serve - local web server
9
9
 
10
10
  `spur serve` starts the **Spur web server** - a local Hono / Cloudflare-Worker server that serves
11
- the web Task Kanban and exposes the team supervisor API (`/api/team/*`). It is the local fallback
11
+ the web Task Kanban and exposes the supervisor API (`/api/processes/*` + `/api/agents/*`). It is the local fallback
12
12
  when no remote server is configured.
13
13
 
14
14
  ## Verb map
@@ -29,7 +29,7 @@ spur serve --json # dry probe: print { port, url, pid, running
29
29
  ```
30
30
 
31
31
  Starts the server with the Hono app backed by the local SQLite database. The web Task Kanban and
32
- the team supervisor API become available at `http://<host>:<port>`.
32
+ the supervisor API become available at `http://<host>:<port>`.
33
33
 
34
34
  ### Flags
35
35
 
@@ -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 agent 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>` (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` |
@@ -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