@gobing-ai/spur 0.3.99 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/config.global.yaml +17 -0
  3. package/config/decisions/gates.yaml +36 -0
  4. package/config/decisions/history-anatomy.yaml +35 -0
  5. package/config/decisions/idea-pipeline.yaml +38 -0
  6. package/config/decisions/task-pipeline.yaml +55 -0
  7. package/config/plugin-scripts.json +25 -0
  8. package/config/rules/boundary/sp-runtime-path.yaml +2 -0
  9. package/config/rules/docs/sourced-api-claims.yaml +60 -0
  10. package/config/rules/quality/coverage-gate.yaml +5 -3
  11. package/config/rules/recommended-pre-check.yaml +8 -3
  12. package/config/rules/strict/runtime-boundaries.yaml +11 -0
  13. package/config/rules/structure/protected-files.yaml +3 -0
  14. package/config/rules/structure/scratch-evidence-pointer.yaml +35 -0
  15. package/config/script-placement-baseline.json +2 -2
  16. package/config/workflows/feature-lifecycle.yaml +9 -2
  17. package/config/workflows/history-anatomy.yaml +22 -0
  18. package/config/workflows/idea-pipeline.yaml +75 -0
  19. package/config/workflows/task-pipeline.yaml +368 -49
  20. package/config/workflows/wrapup-pipeline.yaml +106 -13
  21. package/package.json +9 -9
  22. package/plugins/sp/README.md +25 -2
  23. package/plugins/sp/agents/super-planner.md +11 -0
  24. package/plugins/sp/agents/super-reviewer.md +39 -11
  25. package/plugins/sp/bunfig.toml +8 -0
  26. package/plugins/sp/commands/dev-brainstorm.md +29 -16
  27. package/plugins/sp/commands/dev-changelog.md +5 -4
  28. package/plugins/sp/commands/dev-find-way.md +80 -0
  29. package/plugins/sp/commands/dev-idea.md +6 -0
  30. package/plugins/sp/commands/dev-parallel.md +8 -2
  31. package/plugins/sp/commands/dev-plan.md +6 -0
  32. package/plugins/sp/commands/dev-review-session.md +14 -7
  33. package/plugins/sp/commands/dev-run.md +17 -4
  34. package/plugins/sp/commands/dev-runall.md +21 -10
  35. package/plugins/sp/hooks/agent-lifecycle.ts +155 -0
  36. package/plugins/sp/hooks/context-session-start.ts +1 -1
  37. package/plugins/sp/hooks/fleet-guest-stop.ts +180 -0
  38. package/plugins/sp/hooks/hooks.json +45 -1
  39. package/plugins/sp/hooks/pi/guard-extension.ts +21 -0
  40. package/plugins/sp/lib/history-anatomy.generated.mjs +5 -0
  41. package/plugins/sp/lib/idea-handoff.generated.mjs +72 -11
  42. package/plugins/sp/lib/inline-run-app.ts +28 -0
  43. package/plugins/sp/lib/inline-run.generated.d.mts +6 -0
  44. package/plugins/sp/lib/inline-run.generated.mjs +364 -46
  45. package/plugins/sp/lib/plan-projection.generated.d.mts +28 -0
  46. package/plugins/sp/lib/plan-projection.generated.mjs +255 -0
  47. package/plugins/sp/lib/quality-gate.generated.d.mts +47 -1
  48. package/plugins/sp/lib/quality-gate.generated.mjs +30489 -82
  49. package/plugins/sp/lib/residual-scan.generated.d.mts +19 -0
  50. package/plugins/sp/lib/residual-scan.generated.mjs +66 -0
  51. package/plugins/sp/lib/run-summary-core.ts +561 -0
  52. package/plugins/sp/lib/transcript.ts +275 -0
  53. package/plugins/sp/plugin.json +1 -1
  54. package/plugins/sp/references/roles.md +1 -1
  55. package/plugins/sp/scripts/batch-plan.mjs +335 -0
  56. package/plugins/sp/scripts/batch-plan.ts +100 -0
  57. package/plugins/sp/scripts/batch-preflight.mjs +51 -3
  58. package/plugins/sp/scripts/batch-preflight.ts +72 -1
  59. package/plugins/sp/scripts/commit-guard.mjs +216 -0
  60. package/plugins/sp/scripts/commit-guard.ts +249 -0
  61. package/plugins/sp/scripts/history-anatomy-cache.mjs +5 -0
  62. package/plugins/sp/scripts/inline-run-dispatch.mjs +130 -0
  63. package/plugins/sp/scripts/inline-run-dispatch.ts +135 -0
  64. package/plugins/sp/scripts/inline-run-setup.mjs +563 -91
  65. package/plugins/sp/scripts/inline-run-setup.ts +65 -97
  66. package/plugins/sp/scripts/persist-out-check.mjs +90 -41
  67. package/plugins/sp/scripts/persist-out-check.ts +112 -57
  68. package/plugins/sp/scripts/quality-gate.mjs +30407 -73
  69. package/plugins/sp/scripts/quality-gate.ts +21 -5
  70. package/plugins/sp/scripts/residual-scan.mjs +88 -38
  71. package/plugins/sp/scripts/residual-scan.ts +35 -38
  72. package/plugins/sp/scripts/run-summary.mjs +693 -0
  73. package/plugins/sp/scripts/run-summary.ts +105 -0
  74. package/plugins/sp/scripts/session-timeline.mjs +331 -0
  75. package/plugins/sp/scripts/session-timeline.ts +204 -0
  76. package/plugins/sp/scripts/wrapup-steps.mjs +150 -2
  77. package/plugins/sp/scripts/wrapup-steps.ts +203 -1
  78. package/plugins/sp/skills/brainstorm/SKILL.md +9 -47
  79. package/plugins/sp/skills/branch-workflow/SKILL.md +1 -0
  80. package/plugins/sp/skills/branch-workflow/references/worktree-patterns.md +1 -0
  81. package/plugins/sp/skills/code-implementation/SKILL.md +48 -1
  82. package/plugins/sp/skills/code-verification/SKILL.md +8 -4
  83. package/plugins/sp/skills/code-verification/references/secu-review.md +3 -0
  84. package/plugins/sp/skills/code-verification/references/verdict-schema.md +68 -0
  85. package/plugins/sp/skills/fleet-join/SKILL.md +63 -0
  86. package/plugins/sp/skills/session-review/SKILL.md +77 -24
  87. package/plugins/sp/skills/source-driven-development/SKILL.md +5 -0
  88. package/plugins/sp/skills/spec-decomposition/references/decomposition.md +5 -3
  89. package/plugins/sp/skills/spur-cli/SKILL.md +6 -2
  90. package/plugins/sp/skills/spur-cli/references/agent.md +124 -17
  91. package/plugins/sp/skills/spur-cli/references/decision.md +98 -0
  92. package/plugins/sp/skills/spur-cli/references/message.md +7 -7
  93. package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +41 -3
  94. package/plugins/sp/skills/spur-cli/references/tasks.md +10 -7
  95. package/plugins/sp/skills/spur-cli/references/workflows/authoring-workflows.md +7 -0
  96. package/plugins/sp/skills/spur-cli/references/workflows.md +7 -2
  97. package/plugins/sp/skills/spur-composer/SKILL.md +28 -2
  98. package/plugins/sp/skills/spur-dev/SKILL.md +18 -14
  99. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +6 -3
  100. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +49 -14
  101. package/plugins/sp/skills/spur-dev/references/dev-operations.md +51 -18
  102. package/plugins/sp/skills/spur-dev/references/execution-batch-continuation.md +68 -0
  103. package/plugins/sp/skills/spur-dev/references/execution-batch-report.md +194 -0
  104. package/plugins/sp/skills/spur-dev/references/execution-batch.md +113 -963
  105. package/plugins/sp/skills/spur-dev/references/execution-parallel-isolation.md +130 -0
  106. package/plugins/sp/skills/spur-dev/references/execution-workflow.md +20 -0
  107. package/plugins/sp/skills/spur-dev/references/execution-worktree-landing.md +471 -0
  108. package/plugins/sp/skills/spur-dev/references/execution-worktree-setup.md +379 -0
  109. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +51 -9
  110. package/plugins/sp/skills/spur-dev/references/glossary.md +2 -2
  111. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +361 -156
  112. package/plugins/sp/skills/spur-dev/references/planning-workflow.md +6 -0
  113. package/plugins/sp/skills/spur-dev/references/structured-trace-emission.md +178 -0
  114. package/plugins/sp/skills/wayfinder/SKILL.md +10 -14
  115. package/schemas/decision-catalog.schema.json +226 -0
  116. package/schemas/spur-config.schema.json +25 -0
  117. package/schemas/state-machine-workflow.schema.json +23 -0
  118. package/spur.js +28165 -19051
  119. package/web/_astro/{BoardApp.i4eh_fHA.js → BoardApp.D66k_s_T.js} +1 -1
  120. package/web/_astro/BoardApp.D6sjAJr_.js +324 -0
  121. package/web/_astro/{TaskDetail.C5Cu8LdB.js → TaskDetail.BynLnMNc.js} +1 -1
  122. package/web/_astro/{arc.Bu5XpBEz.js → arc._BUadrdH.js} +1 -1
  123. package/web/_astro/{architectureDiagram-3BPJPVTR.9vHQTvhF.js → architectureDiagram-3BPJPVTR.Dh7xS1Pp.js} +1 -1
  124. package/web/_astro/{blockDiagram-GPEHLZMM.Cn2Xl7D6.js → blockDiagram-GPEHLZMM.DFDVpfXm.js} +1 -1
  125. package/web/_astro/{c4Diagram-AAUBKEIU.7o0P_QDo.js → c4Diagram-AAUBKEIU.V7_3_glh.js} +1 -1
  126. package/web/_astro/channel.DZVfto-r.js +1 -0
  127. package/web/_astro/{chunk-2J33WTMH.C3zZFsNt.js → chunk-2J33WTMH.De1yx7Jz.js} +1 -1
  128. package/web/_astro/{chunk-4BX2VUAB.CNy_M7fO.js → chunk-4BX2VUAB.BDhHFuxx.js} +1 -1
  129. package/web/_astro/{chunk-55IACEB6.2TiPnLBL.js → chunk-55IACEB6.DDLkWnmC.js} +1 -1
  130. package/web/_astro/{chunk-727SXJPM.5CGSyKAp.js → chunk-727SXJPM.CwfiLnA7.js} +1 -1
  131. package/web/_astro/{chunk-AQP2D5EJ.w-ZIgfsK.js → chunk-AQP2D5EJ.CtGDmUnM.js} +1 -1
  132. package/web/_astro/{chunk-FMBD7UC4.BkcEyhKa.js → chunk-FMBD7UC4.BOLjpw73.js} +1 -1
  133. package/web/_astro/{chunk-ND2GUHAM.mxKKbBG4.js → chunk-ND2GUHAM.BDhQls6O.js} +1 -1
  134. package/web/_astro/{chunk-QZHKN3VN.cyA0z9aT.js → chunk-QZHKN3VN.76qBynDF.js} +1 -1
  135. package/web/_astro/{classDiagram-4FO5ZUOK.CqtUzwhX.js → classDiagram-4FO5ZUOK.N0mpPHT0.js} +1 -1
  136. package/web/_astro/{classDiagram-v2-Q7XG4LA2.CqtUzwhX.js → classDiagram-v2-Q7XG4LA2.N0mpPHT0.js} +1 -1
  137. package/web/_astro/{cose-bilkent-S5V4N54A.BExPTopI.js → cose-bilkent-S5V4N54A.CKknFfjB.js} +1 -1
  138. package/web/_astro/{cynefin-OW5HDTMX.Bq2i10Cn.js → cynefin-OW5HDTMX.Cw3ZWBAh.js} +1 -1
  139. package/web/_astro/{dagre-BM42HDAG.By_HsOuv.js → dagre-BM42HDAG.D3yIKCRD.js} +1 -1
  140. package/web/_astro/{diagram-2AECGRRQ.BtU0b7hz.js → diagram-2AECGRRQ.D51dO83Z.js} +1 -1
  141. package/web/_astro/{diagram-5GNKFQAL.D00ztMdT.js → diagram-5GNKFQAL.Bb-FViDj.js} +1 -1
  142. package/web/_astro/{diagram-KO2AKTUF.DMVJWaUN.js → diagram-KO2AKTUF.D3mN8S6x.js} +1 -1
  143. package/web/_astro/{diagram-LMA3HP47.Cxqrjg5-.js → diagram-LMA3HP47.dMMyPcbJ.js} +1 -1
  144. package/web/_astro/{diagram-OG6HWLK6.2lz_1B5h.js → diagram-OG6HWLK6.AzbvzY4C.js} +1 -1
  145. package/web/_astro/{erDiagram-TEJ5UH35.BVQEuJ3T.js → erDiagram-TEJ5UH35.BR5I4OZb.js} +1 -1
  146. package/web/_astro/{flowDiagram-I6XJVG4X.Qlyo90ky.js → flowDiagram-I6XJVG4X.DFqvhGkn.js} +1 -1
  147. package/web/_astro/{ganttDiagram-6RSMTGT7.DRwb8HHZ.js → ganttDiagram-6RSMTGT7.ByJbhH6J.js} +1 -1
  148. package/web/_astro/{gitGraphDiagram-PVQCEYII.YfoPthfS.js → gitGraphDiagram-PVQCEYII.CInHjQR3.js} +1 -1
  149. package/web/_astro/index.COh_kBxN.css +1 -0
  150. package/web/_astro/{infoDiagram-5YYISTIA.DvFREck1.js → infoDiagram-5YYISTIA.Cm0dGVjJ.js} +1 -1
  151. package/web/_astro/{ishikawaDiagram-YF4QCWOH.BzCj9Q0-.js → ishikawaDiagram-YF4QCWOH.C3nOP6Sj.js} +1 -1
  152. package/web/_astro/{journeyDiagram-JHISSGLW.BDMT_AFb.js → journeyDiagram-JHISSGLW.4IvLa2MW.js} +1 -1
  153. package/web/_astro/{kanban-definition-UN3LZRKU.D6Fh3gj9.js → kanban-definition-UN3LZRKU.DS87Cl-k.js} +1 -1
  154. package/web/_astro/{linear.Dxw00fGQ.js → linear.MzmRrNER.js} +1 -1
  155. package/web/_astro/{mermaid.core.CsoxUWa0.js → mermaid.core.fK-WNswS.js} +4 -4
  156. package/web/_astro/{mindmap-definition-RKZ34NQL.CN8oeHLu.js → mindmap-definition-RKZ34NQL.BqipOHhY.js} +1 -1
  157. package/web/_astro/{pieDiagram-4H26LBE5.C7ADqQ_7.js → pieDiagram-4H26LBE5.0nBiPqFG.js} +1 -1
  158. package/web/_astro/{quadrantDiagram-W4KKPZXB.Cw9lKyHP.js → quadrantDiagram-W4KKPZXB.Szj7Zpx5.js} +1 -1
  159. package/web/_astro/{requirementDiagram-4Y6WPE33.B1ni-z4q.js → requirementDiagram-4Y6WPE33.D4UR6TWo.js} +1 -1
  160. package/web/_astro/{sankeyDiagram-5OEKKPKP.BhexdjVr.js → sankeyDiagram-5OEKKPKP.DAE7BdOs.js} +1 -1
  161. package/web/_astro/{sequenceDiagram-3UESZ5HK.C3Rm7dpQ.js → sequenceDiagram-3UESZ5HK.BP9ZVq25.js} +1 -1
  162. package/web/_astro/{stateDiagram-AJRCARHV.CkuMt27u.js → stateDiagram-AJRCARHV.BQW7mIxk.js} +1 -1
  163. package/web/_astro/{stateDiagram-v2-BHNVJYJU.Dc_aazUA.js → stateDiagram-v2-BHNVJYJU.PbK4nDih.js} +1 -1
  164. package/web/_astro/{timeline-definition-PNZ67QCA.ja7sUFhH.js → timeline-definition-PNZ67QCA.Ci_GvUpo.js} +1 -1
  165. package/web/_astro/{vennDiagram-CIIHVFJN.BxIshX_K.js → vennDiagram-CIIHVFJN.DNw1Y5qx.js} +1 -1
  166. package/web/_astro/{wardleyDiagram-YWT4CUSO.DfHlC0sh.js → wardleyDiagram-YWT4CUSO.CwlkaaNe.js} +1 -1
  167. package/web/_astro/{xychartDiagram-2RQKCTM6.DSnhHwCh.js → xychartDiagram-2RQKCTM6.MI6ZuiH_.js} +1 -1
  168. package/web/board-runtime.json +1 -1
  169. package/web/index.html +2 -2
  170. package/web/_astro/BoardApp.BVp-LYi6.js +0 -322
  171. package/web/_astro/channel.6IFIKBhu.js +0 -1
  172. package/web/_astro/index.CbNz17Sx.css +0 -1
@@ -35,9 +35,43 @@ interface VerifyVerdict {
35
35
  status: 'pass' | 'fail' | 'warn';
36
36
  evidence: string;
37
37
  }>;
38
+ /** Verifier confidence (task 1068 R3). REQUIRED for PASS — the done gate denies
39
+ * a confidence-less PASS. Accepted case-insensitively, normalized to uppercase. */
40
+ confidence?: 'HIGH' | 'MEDIUM' | 'LOW';
38
41
  }
39
42
  ```
40
43
 
44
+ ## Confidence level (task 1068 R3)
45
+
46
+ A PASS verdict must state the verifier's confidence: `"confidence": "HIGH" | "MEDIUM" | "LOW"`.
47
+ The value is case-insensitive on read (normalized to uppercase), but a present value outside the
48
+ enum invalidates the artifact, and a PASS with the field absent is denied at the `* → done`
49
+ transition with a remediation naming the field (`--force-done` remains the documented escape).
50
+ The verify answer's `Confidence:` lint rule (producer side) already guarantees the field for
51
+ pipeline-produced artifacts; this closes the hand-authored / pre-1068 artifact hole.
52
+
53
+ ### Coherence: the level must be earned (task 1133)
54
+
55
+ Presence and vocabulary are not enough — the level has to match the rows in the same answer, so the
56
+ lint rejects a level that contradicts its own evidence. Two rejection classes, both addressed to the
57
+ `Confidence:` line and both capped by the shared `ANSWER_LINT_MAX_FINDINGS` budget:
58
+
59
+ - `confidence-unwarranted` — `HIGH` while any requirement row normalizes to `PARTIAL`/`UNMET`, any
60
+ acceptance-criteria row does not normalize to `MET`, or any `MET` row's evidence is hedged.
61
+ A `HIGH` claim says the evidence needs no re-check; a non-MET or hedged row says the opposite.
62
+ - `confidence-understated` — `LOW` while at least one requirement row exists and every requirement
63
+ and acceptance-criteria row normalizes to `MET`. The evidence already did the work, so `LOW`
64
+ misreports the state as unproven.
65
+
66
+ `MEDIUM` carries no coherence rule in either direction: it is the level a verifier uses for a caveat
67
+ with no row to point at, and closing it would force either an overclaimed `HIGH` or an unusable
68
+ `LOW`. The level is normalized to uppercase before the decision, so `high` is judged as `HIGH`.
69
+
70
+ Set the level from the rows, not the mood: all rows `MET` with fresh evidence is `HIGH`; a
71
+ `PARTIAL`/`UNMET` row or a hedge means `MEDIUM`, not `HIGH`. An unwarranted level does not merely
72
+ warn — the lint rejects the answer and no verdict artifact is written, so the level is worth
73
+ choosing deliberately before the verdict line is finalized.
74
+
41
75
  ## Compatibility alias: `scenario` row key
42
76
 
43
77
  Task 0410 hardened the verdict reader. Producers SHOULD use the canonical `id` field for every
@@ -138,6 +172,23 @@ the run actually verified. Since 0804 R9 the checker ignores complete parsed cit
138
172
  scanning for subjects, so a citation's filename (including snake_case paths) can never become a
139
173
  false subject — a real absent symbol, nonexistent file, or invalid range still reports.
140
174
 
175
+ ## Basename-only anchors are unresolved anchors (task 1110 R1)
176
+
177
+ `spur task verdict --from-answer` accepts the citation *shape*, but the `--as done` gate resolves
178
+ every Testing/Solution anchor against the repo root. A basename citation — `decision-events.ts:83`,
179
+ `task.test.ts:42` — reports `L4.anchor-unresolved` at **error** and blocks
180
+ `spur task update <wbs> done`, because the gate cannot tell which file the row meant. Write the
181
+ repo-root-relative form from the first pass:
182
+
183
+ - Right: `packages/app/src/decision/decision-events.ts:83`, `apps/cli/tests/commands/task.test.ts:42`
184
+ - Wrong: `decision-events.ts:83`, `../services/foo.ts:12`, `@gobing-ai/ts-x/src/persistence.ts:108`
185
+ (a scoped package is never repo-relative — use the external named-origin form below)
186
+
187
+ The pipeline's implement stage also runs a scoped `spur task migrate-anchors --wbs <wbs>` pass
188
+ before the proof capture (task 1109), but it qualifies **unique** basenames only: an ambiguous
189
+ basename (two tracked files share it) is reported and left untouched, and line drift and
190
+ `L4.anchor-subject-mismatch` are never repaired by that pass — those remain the author's rows.
191
+
141
192
  ## Source citations for external claims (task 1070)
142
193
 
143
194
  A Requirement/AC evidence cell that asserts an external API/library claim must carry a verifiable
@@ -152,6 +203,23 @@ citation in the SAME cell, or lint rejects the row with `evidence-citation` (blo
152
203
  satisfy it. Marker-free receipts (test counts, reviewed-log notes) need no citation. The check is
153
204
  presence-only — which citation proves which claim is not deterministically decidable.
154
205
 
206
+ ## Hedged evidence is rejected on MET rows
207
+
208
+ A MET row asserts the requirement is satisfied; evidence that hedges ("the guard likely prevents
209
+ the leak") contradicts the assertion the row is making. The lint rejects such rows with
210
+ `evidence-hedged`, naming the detected phrase, with two remedies: state the deterministic fact
211
+ with a concrete anchor, or downgrade the row to PARTIAL (which is what suspected-but-unproven
212
+ behavior actually is).
213
+
214
+ - Detected phrases (closed set, word-anchored, case-insensitive): `likely`, `unlikely`,
215
+ `probably`, `presumably`, `apparently`, `seems/seeming/seemingly to`, `appears to`. Modal verbs
216
+ (`might`/`may`/`could`/`should`) are deliberately out of set — they are constant in remediation
217
+ prose and would drown the signal.
218
+ - Only MET rows are scanned. Hedging a gap in an UNMET row ("the stale path likely still loads
219
+ the old bundle") is honest reporting and stays clean.
220
+ - Citation spans are stripped before scanning, so a filename or test name containing a hedge
221
+ word (`likely-match.test.ts`) cannot fire.
222
+
155
223
  ## Checks evidence
156
224
 
157
225
  Wave C verification can emit the following additive `checks[]` rows:
@@ -0,0 +1,63 @@
1
+ ---
2
+ name: fleet-join
3
+ description: >-
4
+ Join a project fleet as a guest occupant and pull its work. Use when the operator asks to
5
+ "join the fleet", "become a fleet guest", "pull fleet inbox work in this session", or when a
6
+ session should receive fleet messages without being supervised. Runs `spur agent join`, then
7
+ loops `spur agent wait --inbox`, and releases the lease with `spur agent leave`.
8
+ ---
9
+ # fleet-join — a live session as a fleet guest (G73, task 1081)
10
+
11
+ A guest is a session that **pulls** work: it is neither supervised nor restarted, it is addressed
12
+ by concrete id only, and it never receives a stage (`requiresCapabilities` stages can never route
13
+ to it — a guest carries no attestation). Joining registers an occupant row plus a heartbeat lease;
14
+ leaving (or an expired lease) releases it and returns any claimed messages to `queued`.
15
+
16
+ ## Join
17
+
18
+ ```bash
19
+ spur agent join --role reviewer --json # id defaults to <role>-g<n>
20
+ spur agent join --role coder --id my-session --json
21
+ ```
22
+
23
+ Pick the role whose work this session can actually do. `--session-id` defaults to
24
+ `CLAUDE_CODE_SESSION_ID`, which is what the Stop hook matches against — without it the hook cannot
25
+ find this session, though the `wait --inbox` loop still works.
26
+
27
+ ## Pull loop
28
+
29
+ `spur agent wait --inbox <id> --timeout 540000` returns **0** the moment queued work exists and
30
+ **1** on timeout. Each call heartbeats the lease, so a looping session stays joined. The Bash tool's
31
+ own ~10-minute limit is why the timeout stays under it: one bounded call per turn, re-armed after
32
+ the work is done.
33
+
34
+ 1. `spur agent wait --inbox <id> --timeout 540000 --json` → exit 0 means work is waiting.
35
+ 2. `spur message inbox --agent <id> --json` → read the messages.
36
+ 3. Do the work the message asks for.
37
+ 4. `spur message reply <msgId> "<result>"` → reply to each one.
38
+ 5. Re-arm: go back to step 1 while the operator wants this session in the fleet.
39
+
40
+ ## Leave
41
+
42
+ ```bash
43
+ spur agent leave --json # the guest joined by this session
44
+ spur agent leave my-session --json # an explicit id
45
+ ```
46
+
47
+ Leaving releases the lease immediately. If the session dies without leaving, the lease expires and
48
+ the reconciler pass retires the guest — pending work is never lost, it returns to `queued`.
49
+
50
+ ## Stop-hook delivery (opportunistic)
51
+
52
+ When the host fires a `Stop` hook and the host supports the block contract, the
53
+ `fleet-guest-stop` plugin hook delivers pending messages at turn end by replying
54
+ `{"decision":"block","reason":"Pending fleet messages: …"}` — only for a session whose id matches a
55
+ joined guest, never twice in one continued turn, and always fail-open. Claude Code supports this;
56
+ Codex `exec` on 0.160.0 does not deliver `Stop` at all (`docs/plans/2026-10-05-codex-guest-spike.md`),
57
+ so the pull loop above — not the hook — is what makes a guest work anywhere.
58
+
59
+ ## Boundaries
60
+
61
+ - Guests are **not** supervised: do not expect restart, pid ownership, or `--drain` injection.
62
+ - Never dispatch a stage to a guest id: `spur agent run --spec <guest-id>` is refused on purpose.
63
+ - Never hold the write slot through a guest: the guest lease is the only heartbeat (R5).
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  name: session-review
3
- description: "Review the active coding-agent session: separate resolved from open issues with evidence, propose bounded improvements. With --triage, apply pure-doc / 1–2-line fixes inline and file the rest as one or more tasks. Triggers: review this session, wrap-up, triage findings."
3
+ description: "Review the active coding-agent session: separate resolved from open issues with evidence, propose bounded improvements. With --fix auto (alias --triage), apply pure-doc / 1–2-line fixes inline and file the rest as tasks; with --fix all, fix every actionable finding inline and file none. Triggers: review this session, wrap-up, triage findings."
4
4
  license: Apache-2.0
5
- version: 1.1.0
5
+ version: 1.3.0
6
6
  metadata:
7
7
  author: spur
8
8
  platforms: "claude-code,codex,openclaw,opencode,antigravity,pi"
@@ -24,14 +24,17 @@ compact, evidence-backed report of outcomes, resolved issues, remaining risks, a
24
24
 
25
25
  Use this skill immediately after focused operations when the operator asks what happened, what was
26
26
  resolved, or how the session could improve. Use imported-history analysis for ended sessions,
27
- cross-agent windows, recurrence, trends, or quantitative performance forensics.
27
+ cross-agent windows, recurrence, trends, or quantitative performance forensics: on pi, run
28
+ `spur history analyze --source pi --session <file-stem>` where `<file-stem>` is the transcript
29
+ basename without `.jsonl` (e.g. `2026-10-07T22-44-33-625Z_01a1188a-…`), not the bare uuid.
28
30
 
29
31
  ## Arguments
30
32
 
31
33
  | Argument | Description | Default |
32
34
  | --- | --- | --- |
33
35
  | `[focus]` | Question or operation to emphasize. It changes ordering, not evidence collection. | full active session |
34
- | `--triage` | Opt into bounded remediation after the report: apply direct fixes (pure docs / one-to-two-line fixes) inline, then file all remaining actionable findings as one or more implement-ready tasks via the CLI-gated corpus surface. | off (report-only) |
36
+ | `--fix <none\|auto\|all>` | Remediation after the report. `none`: report-only. `auto`: apply direct fixes (pure docs / one-to-two-line fixes) inline, then file all remaining actionable findings as one or more implement-ready tasks via the CLI-gated corpus surface. `all`: fix every actionable finding inline and file no task. | `none` |
37
+ | `--triage` | `--triage` is an alias of `--fix auto`; an explicit `--fix` wins when both are passed. | off |
35
38
 
36
39
  ## Evidence boundary
37
40
 
@@ -46,14 +49,16 @@ cross-agent windows, recurrence, trends, or quantitative performance forensics.
46
49
  name the confirmation needed.
47
50
  - State `not available` when compaction or missing output removed evidence. Never reconstruct it from
48
51
  memory or claim a verification that did not run.
49
- - Derive timing only from timestamps and tool-call records visible in the active session. Use
50
- non-overlapping stages whose durations sum to elapsed time; render unavailable duration or call
51
- counts as `n/a` instead of estimating them.
52
+ - Derive timing and tokens only from the host transcript measurement (Protocol step 1): the visible
53
+ conversation carries no timestamps or usage, so never estimate them from it. Use non-overlapping
54
+ stages whose durations sum to elapsed time; render a value as `n/a` only when the measurement
55
+ reports `available: false` or omits it.
52
56
 
53
- ## Triage mode (`--triage`)
57
+ ## Fix modes (`--fix auto|all`)
54
58
 
55
- Report-only stays the default. With `--triage`, run the same evidence pass, then remediate in
56
- three buckets — never skip triage and start fixing from the raw findings list.
59
+ Report-only stays the default. With `--fix auto` or `--fix all`, run the same
60
+ evidence pass, then remediate in three buckets — never skip triage and start fixing from the raw
61
+ findings list. Steps 1–4 below are `--fix auto`; `--fix all` differs only as stated after them.
57
62
 
58
63
  1. **Triage every finding into exactly one bucket:**
59
64
  - **Direct fix** — pure documentation work, or a one-to-two-line fix with obvious, local,
@@ -74,10 +79,31 @@ three buckets — never skip triage and start fixing from the raw findings list.
74
79
  4. **Report** — add a Triage section: applied fixes (path + one-line what + verification) and
75
80
  each created task WBS. The Resolved/Open tables keep their evidence rules unchanged.
76
81
 
82
+ **`--fix all` (defer nothing).** Triage still runs, but the Task bucket is fixed inline instead of
83
+ filed, so the mode creates no task. Fix in dependency order with the same surgical-diff and
84
+ per-fix re-verification rule as direct fixes, then run the project gate once at the end. A finding
85
+ that needs a design or operator decision is asked through the host question tool, never deferred;
86
+ one that still cannot be fixed (failed re-verification, blocked by the environment) stays in Open
87
+ issues with its evidence. Notes stay report-only.
88
+
77
89
  ## Protocol
78
90
 
79
91
  1. **Resolve scope.** Review the active session from the operator's initiating request through the
80
- latest result. Use `[focus]` only to rank relevant material.
92
+ latest result. Use `[focus]` only to rank relevant material. Measure it with
93
+ `node "$(superskill script path sp session-timeline.mjs)" --group "<ranges>"`: one segment per
94
+ operator prompt, read-only from the host transcript. Run it once without `--group` to list the
95
+ segments, then map them to stages (`"1-3,4,5-6"`). It splits each segment into `work` and
96
+ operator `wait` (idle before the next prompt plus AskUserQuestion answer time) and counts tokens
97
+ once per message id. On pi the transcript is `$PI_SESSION_FILE` (pass it as `--transcript` when
98
+ the run reports no host session id). **A measurement that returns `segments: []` with zero totals
99
+ while the session had operator prompts is an unreadable or stale adapter, not an empty session:**
100
+ compare the installed copy against this tree's `plugins/sp/scripts/session-timeline.mjs` and
101
+ refresh it with `superskill install sp` before reporting numbers; report `n/a` until then.
102
+ The transcript resolves from `--transcript`, else `CLAUDE_CODE_SESSION_ID`, else `PI_SESSION_FILE`
103
+ (the pi host sets it and no Claude session id); with none of them the measurement reports
104
+ `available:false` with a reason and the table renders `n/a` instead of guessing. A
105
+ skill-injected body (`<skill name="…">`) is counted as activity in `injectedPrompts`, never as a
106
+ segment — only the operator's own prompts segment the session.
81
107
  2. **Inventory outcomes.** List requested outcomes and classify each as completed, partial, blocked,
82
108
  or not attempted. Collapse repeated attempts into one outcome.
83
109
  3. **Classify issues.** For every material issue, distinguish resolved, open, or attempted. Record
@@ -108,26 +134,52 @@ State the overall result in one to three sentences, including partial or blocked
108
134
  Summarize elapsed time and, when supported by evidence, productive work, avoidable setup/recovery,
109
135
  and operator wait time. Then render non-overlapping stages:
110
136
 
111
- | Stage | Time | Tool calls | Assessment |
112
- | --- | ---: | ---: | --- |
137
+ | Stage | Time | Wait | Tool calls | Token | Assessment |
138
+ | --- | ---: | ---: | ---: | ---: | --- |
113
139
 
114
140
  Format durations as `M:SS` below one hour and `H:MM:SS` at one hour or above (`1:44`, not `1m44s`;
115
141
  `0:33`, not `33s`). Include a `Total` row when elapsed time is available. Keep operator approval
116
- waits separate from execution bottlenecks. Use `n/a` for any value not supported by the active
117
- session evidence.
142
+ waits separate from execution bottlenecks. Time is the stage `work` and Wait its operator `wait`.
143
+ Token renders `<total> / <non-cached>` in compact units (`28.7M / 717k`) — the measurement's
144
+ `token` field: total = input + cache creation + cache read + output; non-cached = total minus cache
145
+ read (fresh input, cache writes and output). These are measured session counts, not the 0912 baseline token/USD claims that
146
+ step 4 excludes. Use `n/a` for any value not supported by the measurement.
118
147
 
119
148
  ### Resolved issues
120
149
 
121
- | Issue | Root cause | Resolution | Evidence |
122
- | --- | --- | --- | --- |
150
+ | Issue | Root cause | Resolution | Evidence | Confidence |
151
+ | --- | --- | --- | --- | --- |
123
152
 
124
153
  Evidence names the tool result, verification command, or concrete repository state visible in the
125
154
  session. Do not list ordinary implementation steps as issues.
126
155
 
127
- ### Open issues and risks
156
+ **Confidence** is `HIGH`, `MEDIUM`, or `LOW` for that row's claim. The level is **derived from the
157
+ check that produced the claim, never assessed from how the row reads**, and the cell carries that
158
+ verifier (e.g. `HIGH — gate exit 0, /tmp/g0.log re-run this session`). Add the row's **falsifier**
159
+ when the level is not `HIGH`: what would have made it fail, or what moves it up. The same ladder
160
+ grades this report's Open-issues table.
128
161
 
129
- | Issue or risk | State | Evidence or confirmation needed |
162
+ | Level | Verifies when | Not this |
130
163
  | --- | --- | --- |
164
+ | `HIGH` | An executed check in this session produced the result and its raw output is reachable (command + exit code, test counts, query row, gate log). Re-runnable now. | The code or change "looks correct"; a claim asserted only in prose. |
165
+ | `MEDIUM` | The claim is inferred from observed facts, rests on prior-session or delegated evidence, or names state that moved after the check (stale by construction). Name which of the three. | Presenting an inference as an observation. |
166
+ | `LOW` | No executable check was run. Name the missing evidence **and** the command that would ground it. | Dropping the row instead of marking it. |
167
+
168
+ Two guards against level inflation:
169
+
170
+ - Evidence that cannot be re-run, or that is only the agent's own summary, **caps the row at
171
+ `MEDIUM`** — a re-run is what promotes it.
172
+ - An all-`HIGH` multi-finding review is a signal the ladder was not applied, not a clean session.
173
+ Where every row genuinely is `HIGH`, the cells show distinct check results rather than repeated
174
+ phrasing.
175
+
176
+ Any API/library statement in a row cites the installed source as `path:line` or a URL, and a claim
177
+ the session could not ground is written `LOW` with the missing evidence named.
178
+
179
+ ### Open issues and risks
180
+
181
+ | Issue or risk | State | Evidence or confirmation needed | Confidence |
182
+ | --- | --- | --- | --- |
131
183
 
132
184
  ### Process and environment improvements
133
185
 
@@ -137,13 +189,13 @@ observation adopted from the 0912 workflow baseline cites its anchor
137
189
  (`docs/reports/i31/0912-workflow-baseline.md`) and owner handoff, and carries no unsupported
138
190
  performance claim.
139
191
 
140
- ### Triage (only when `--triage` was passed)
192
+ ### Triage (only with `--fix auto|all`)
141
193
 
142
194
  | Applied fix / created task | Bucket | What + verification |
143
195
  | --- | --- | --- |
144
196
 
145
- One row per applied fix and one per created task (with its WBS). Omit the section entirely when
146
- `--triage` was not passed.
197
+ One row per applied fix and one per created task (with its WBS; `--fix all` has none). Omit the
198
+ section entirely under `--fix none`.
147
199
 
148
200
  ### Next actions
149
201
 
@@ -157,8 +209,9 @@ improvement. Use `None` when the session is complete and no follow-up is justifi
157
209
  comparison or recurrence classification, or emit a twelve-section forensic report; those belong
158
210
  to imported-history analysis.
159
211
  - Report-only by default: do not create or update corpus items or edit files. The single exception
160
- is `--triage` mode, which permits exactly two mutation classes — direct fixes from the triage
161
- bucket, and the triage tasks. Anything beyond that stays a proposal.
212
+ is `--fix auto|all`: `auto` permits exactly two mutation classes — direct fixes from the triage
213
+ bucket, and the triage tasks; `all` permits one — inline fixes of actionable findings. Anything
214
+ beyond that stays a proposal.
162
215
  - Do not turn a single low-impact observation into a new policy. Report it as a candidate until it
163
216
  recurs or demonstrates a high-impact contract violation.
164
217
 
@@ -101,6 +101,11 @@ line: `Verification: HIGH|MEDIUM|LOW — <first failing check and deviation, or
101
101
  - **Honest confidence** — the stated HIGH/MEDIUM/LOW matches the evidence: HIGH requires a check against the pinned source this session; MEDIUM/LOW items are labeled, and LOW is never presented as fact.
102
102
  - **HIGH** — all three checks pass. **MEDIUM** — coverage intact but some citations are off-version (latest docs for a pinned dependency) or secondary-source only. **LOW** — an API/library claim lacks any citation, or a LOW-confidence claim was asserted as fact.
103
103
 
104
+ Deterministic backstop: the `cited-version-strings` / `cited-api-claims` rules
105
+ (`.spur/rules/docs/sourced-api-claims.yaml`, run in `recommended-pre-check`) flag markdown lines that
106
+ assert version strings or time-anchored API claims with no citation anchor on the same line. They
107
+ are an info-severity advisory backstop for this contract (they do not gate; the checks above and the SECUA checklist are the enforcement points).
108
+
104
109
  ## Common Rationalizations
105
110
 
106
111
  | Rationalization | Reality |
@@ -562,9 +562,11 @@ schema before emitting.
562
562
 
563
563
  **Pass the deterministic task check.** Each `acceptance_criteria` bullet must be an exact feature
564
564
  scenario title (L4.uncovered-task-scenario); add task-local checks as prose after the bullets, not
565
- as extra bullets. No section body may use `HITL`, `approval`/`approved`, `merged`/`merge event`,
566
- `content-gate`, `GATED`, or `capstone` as standalone words (L4.gate-language) — say "operator
567
- answer" / "accepted" instead, and keep enum values out of that list too.
565
+ as extra bullets. No section body may use `HITL`, `merge event`, `content-gate`, `GATED`, or
566
+ `capstone` as standalone words (L4.gate-language); ambiguous words (`approval`, `approved`,
567
+ `merged`) warn only with a gating cue (`until`, `after`, `once`, `before`, `pending`, `blocked`,
568
+ `wait for`, `requires`) in the same sentence, so plain composition prose stays silent — say
569
+ "operator answer" / "accepted" instead, and keep enum values out of that list too.
568
570
 
569
571
  **The order sidecar.** Also emit the private task-order sidecar at
570
572
  `.spur/run/<runId>-idea-task-order.json`: a JSON array (one entry per batch item) of
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: spur-cli
3
- description: "Reference and operate the complete `spur` CLI surface: task, feature, rule, workflow, builder, agent, message, self, history, and projects. Use for verb or flag lookup, machine-readable output and exit contracts, or CLI-gated corpus writes. Triggers: \"spur task\", \"spur history\", \"spur projects\", \"create a task\", \"task check\", and any Spur CLI convention. Not for planning or execution lifecycle orchestration (`sp:spur-dev`)."
3
+ description: "Reference and operate the complete `spur` CLI surface: task, feature, rule, workflow, builder, agent, message, decision, self, history, and projects. Use for verb or flag lookup, machine-readable output and exit contracts, or CLI-gated corpus writes. Triggers: \"spur task\", \"spur history\", \"spur projects\", \"spur decision\", \"spur agent join\", \"create a task\", \"task check\", and any Spur CLI convention. Not for planning or execution lifecycle orchestration (`sp:spur-dev`)."
4
4
  license: Apache-2.0
5
5
  metadata:
6
6
  author: spur
@@ -17,6 +17,7 @@ metadata:
17
17
  - builder
18
18
  - agent
19
19
  - message
20
+ - decision
20
21
  - self
21
22
  - history
22
23
  - projects
@@ -44,11 +45,12 @@ Pick the noun, read its reference. Each Tier A and Tier B reference owns that no
44
45
  | **Tier A** | **rule** | Constraint quality gate: run presets, author rules, fine-tune, validate rule files/presets, extend engine | [references/rules.md](references/rules.md) |
45
46
  | **Tier A** | **workflow** | Dual-mode workflow runtime: author state-machine / transition-flow workflows, validate, run, read traces | [references/workflows.md](references/workflows.md) |
46
47
  | **Tier A** | **builder** | Release plumbing: bump a package (or the `workspace:`-pinned set) with `bump-ver`, delete release tags with `drop-tags`, commit + tag + optional push | [references/builder.md](references/builder.md) |
47
- | **Tier B** | **agent** | Coding-agent execution surface: run prompts via detected/named agents, list agent specs, start/stop supervised processes, readiness check | [references/agent.md](references/agent.md) |
48
+ | **Tier B** | **agent** | Coding-agent execution surface: run prompts via detected/named agents, list agent specs (incl. `agent.fleet` members), start/stop supervised processes, fleet `report`/`join`/`leave`/`wait`/`trace`, readiness check | [references/agent.md](references/agent.md) |
48
49
  | **Tier B** | **message** | Durable inter-agent messaging: send, inbox, reply, watch | [references/message.md](references/message.md) |
49
50
  | **Tier B** | **self** | Self-management verbs: scaffold (`init`), database maintenance (`maintain`), schema migrations (`migrate`), local web server (`serve`), status overview (`status`); `self init` runs post-scaffold validation probes & layout classification | [references/self.md](references/self.md) |
50
51
  | **Tier B** | **history** | Import agent histories, aggregate forensic artifacts, render reports, and run the checkpoint-resumed daily pipeline | [references/history.md](references/history.md) |
51
52
  | **Tier B** | **projects** | Manage the local multi-project registry and start/stop project servers | [references/projects.md](references/projects.md) |
53
+ | **Tier B** | **decision** | Decision-catalog transport: list visible decisions, show a served contract, run a decision to a served outcome, audit catalog health | [references/decision.md](references/decision.md) |
52
54
  | **Tier C** | **help** | Commander-generated help command; not a Spur noun | Generated `--help` |
53
55
 
54
56
  **Execute-First Contract:** Load the noun reference first and execute Tier A or Tier B commands
@@ -141,6 +143,8 @@ and spreading it; full contract in `docs/04_DESIGN.md` §1.0.1.
141
143
  [dispatch-surface rule](../parallel-execution/references/dispatch-surface.md).
142
144
  - **[references/message.md](references/message.md)** - durable inter-agent messaging (`send`,
143
145
  `inbox`, `reply`, `watch`).
146
+ - **[references/decision.md](references/decision.md)** - decision catalog (`list`, `show`, `run`,
147
+ `status`); offline by default via the built-in `typesafe` maker.
144
148
  - **[references/self.md](references/self.md)** - `spur self init|maintain|migrate|serve|status` CLI verbs
145
149
  (the five legacy top-level nouns remain hidden aliases). `self init` runs post-scaffold init
146
150
  validation (Phase 1.5/1.6 probes).
@@ -22,15 +22,19 @@ 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
- | `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` |
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>` `--inbox <id>` `--json` |
26
+ | `trace <runId>` | Print one execution record's lineage — the run, its dispatch parents, agent session ids and streams (1076 R4, ADR-132) | `--follow` `--timeout <ms>` `--json` |
26
27
  | `list` | List detected coding agents, or agent specs with `--specs` (live run status + member session merged from `spur self serve`) | `--specs` `--server <url>` `--json` |
28
+ | `report` | Report a fleet member lifecycle state (`working`/`idle`/`blocked`) from a host hook (G73 R1/R2, task 1080) | `--state <state>` `--seq <ns>` `--spec <id>` `--json` |
29
+ | `join` | Join the fleet as a guest occupant — a live session that pulls its own work (G73 R2, task 1081) | `--role <name>` `--id <id>` `--session-id <sid>` `--pid <n>` `--executor <name>` `--json` |
30
+ | `leave` | Leave the fleet: release the guest lease, retire the occupant, return claimed messages to `queued` | `[id]` `--session-id <sid>` `--json` |
27
31
  | `status` | Agent specs with live process status and member session (requires `spur self serve`) | `--server <url>` `--json` |
28
32
  | `doctor [agent]` | Check agent readiness | `--json` `--probe-health` `--force-refresh` |
29
33
  | `usage` | Run-once provider usage capture (codexbar) → quota-owned availability refresh; scheduled externally | `--dry-run` `--source <name>` `--json` |
30
34
  | `start <spec-id>` | Start a supervised agent process (requires `spur self serve`) | `--server <url>` `--json` |
31
35
  | `stop <spec-id>` | Stop a supervised agent process (requires `spur self serve`) | `--server <url>` `--json` |
32
36
 
33
- `list`, `status`, `doctor`, `run`, `wait`, `start`, and `stop` accept `--json` plus `--json-envelope`. The hidden
37
+ Every verb except `trace` accepts `--json` plus `--json-envelope`; `trace` is `--json` only. The hidden
34
38
  `loop` is a supervisor-internal process surface. **Exit codes:** `0` success, `1` failure, and `2`
35
39
  invalid usage; `run` can also propagate the invoked agent's non-zero result.
36
40
 
@@ -91,7 +95,9 @@ It waits for a wake on the `system_events` ledger — a human request (`message.
91
95
  change (`strategy.changed`), a capacity change (`fleet.capacity.changed`), or a completion receipt
92
96
  (`agent.invoke.exit`) — then drains the inbox into an `agent run` invocation. An idle wake records
93
97
  the hold reason instead of dispatching; with no wake event it still drains every `--poll` ms
94
- (default `2000`). It runs until `SIGINT` / `SIGTERM`.
98
+ (default `2000`). It runs until `SIGINT` / `SIGTERM`, or until its parent `spur serve` disappears —
99
+ the parent is re-read each poll and a change aborts the loop, so a `SIGKILL`ed serve leaves no
100
+ orphan loop (1088 R2).
95
101
 
96
102
  ## `wait` - identity-pinned occupant wait (G4 wave 2)
97
103
 
@@ -136,23 +142,27 @@ exits 2 naming the accepted vocabulary. Resolution collapses onto the same ident
136
142
 
137
143
  ```bash
138
144
  spur agent list # detected coding agents on this machine
139
- spur agent list --specs # agent specs under .spur/agents/
145
+ spur agent list --specs # agent specs: .spur/agents/*.yaml + agent.fleet members
140
146
  spur agent list --json # machine-readable
141
147
  ```
142
148
 
143
149
  Without `--specs`, lists coding agents detected on the host (by binary on `PATH`). With `--specs`,
144
- lists agent specs (`.spur/agents/*.yaml`) **with live run status merged from the server's
150
+ lists agent specs — hand-authored `.spur/agents/*.yaml` merged with the members declared under
151
+ `agent.fleet.members` (derived in memory, never written to disk; the fleet declaration wins on an
152
+ id clash; stale `fleet:generated` files are ignored) — **with live run status merged from the server's
145
153
  supervisor**: each row carries a trailing status column
146
154
  (`running` / `stopped` / `errored` / `unknown`), `pid=<n>` where a process exists, and the member
147
155
  session (0897): the session mode plus a shortened resume id (`resume id=3f9c2a1d`), or `-` when the
148
- member has no recorded session. When `spur self serve` is unreachable, the listing falls back to all
149
- `stopped` with a stderr warning. `--server <url>`
150
- (default `http://localhost:3000/api`) targets the supervisor API.
156
+ member has no recorded session. `--json` rows carry `source: file` (plus `path`) or `source: fleet`
157
+ (no backing file, so no `path`). When `spur self serve` is unreachable, the listing falls back to all
158
+ `stopped` with a stderr warning. `--server <url>` targets the supervisor API; without it the URL is
159
+ this project's serve — the port in the cwd's project-registry entry (`http://localhost:<port>/api`),
160
+ falling back to `http://localhost:3000/api` only when the project has no live entry (1088 R1).
151
161
 
152
162
  ```bash
153
163
  spur agent list --specs
154
- # planner claude reviewer claude plans the work running pid=4132 resume id=3f9c2a1d
155
- # worker-1 pi worker pi implements stopped one-shot
164
+ # myapp-planner-1 claude planner claude orchestrator running pid=4132 resume id=3f9c2a1d
165
+ # myapp-coder-1 pi coder pi implements stopped one-shot
156
166
  ```
157
167
 
158
168
  ## `status` - live status + member session per spec
@@ -164,9 +174,77 @@ spur agent status --json # full objects, session carried whole ({ mode, id }
164
174
 
165
175
  Reads the same supervisor feed as `list --specs` (liveness **and** session come from
166
176
  `GET /api/processes`; the served project's ledger is the source of the session state). An
167
- unreachable server reports every spec `stopped` with no session. See
177
+ unreachable server reports every spec `stopped` with no session. `--server <url>`
178
+ (default: this project's registry serve port, `http://localhost:<port>/api`; else
179
+ `http://localhost:3000/api` — 1088 R1) targets it. See
168
180
  [Member sessions](#member-sessions-g66) for what the modes mean.
169
181
 
182
+ ## `report` - fleet lifecycle state from a host hook (G73, task 1080)
183
+
184
+ ```bash
185
+ spur agent report --state working --seq 1759665600000000000
186
+ spur agent report --state blocked --seq 1759665600000000000 --spec myapp-coder-1 --json
187
+ ```
188
+
189
+ | Flag | Description |
190
+ | --- | --- |
191
+ | `--state <state>` | Lifecycle state: `working` \| `idle` \| `blocked` (required) |
192
+ | `--seq <ns>` | Monotonic report sequence in nanoseconds (required); not greater than the last accepted one → ignored |
193
+ | `--spec <id>` | Member spec id; defaults to `SPUR_SPEC_ID` |
194
+ | `--json` | Machine-readable result (`accepted`, `observation`) |
195
+ | `--json-envelope` | Wrap the JSON in the standard output envelope |
196
+
197
+ An accepted report writes the cataloged `agent.lifecycle.changed` ledger row — the newest
198
+ accepted row for the member is its current state, so there is no separate state store. The
199
+ dispatch strategy treats `blocked` as unavailable (hold reason `member-blocked`), and the Board
200
+ shows `needs human` on that member.
201
+
202
+ Exit `2` when `--state`/`--seq` is missing or malformed, or when no member id resolves
203
+ (`SPUR_SPEC_ID` unset and no `--spec`). The `sp` plugin's `agent-lifecycle` host hook calls this
204
+ in the background on `SessionStart` (idle), `UserPromptSubmit` (working), `Notification`
205
+ (`permission_prompt` → blocked) and `Stop` (idle); outside a fleet it makes no call at all.
206
+
207
+ ## `join` / `leave` - guest occupancy (G73 R2/R5, task 1081)
208
+
209
+ ```bash
210
+ spur agent join --role reviewer --json # id defaults to <role>-g<n>
211
+ spur agent join --role coder --id my-session --json
212
+ spur agent leave --json # the guest joined by this session
213
+ ```
214
+
215
+ A guest is a live session that **pulls** work: never supervised, never restarted, addressable by
216
+ concrete id only (role/executor selectors count declared members, so a guest is invisible to them).
217
+ `join` writes an occupant row in `coordination_runs`, claims a `guest:<id>` lease on the shared
218
+ claim table (same TTL/heartbeat semantics as the write slot — R5) and writes
219
+ `.spur/run/guests/<id>.json` so a host Stop hook can recognize its own session without a CLI call.
220
+ `leave`, or lease expiry in the reconciler pass, releases the lease, marks the occupant exited,
221
+ returns its claimed messages to `queued` and removes the record.
222
+
223
+ | Flag | Description |
224
+ | --- | --- |
225
+ | `--role <name>` | Layer-1 role (`scribe` \| `coder` \| `reviewer` \| `planner`); required for `join` |
226
+ | `--id <id>` | Guest id (defaults to `<role>-g<n>`); colliding with a declared member or a joined guest exits 2 |
227
+ | `--session-id <sid>` | Host session id (defaults to `CLAUDE_CODE_SESSION_ID`) |
228
+ | `--pid <n>` | Process id to record |
229
+ | `--executor <name>` | Executor name to record (informational — a guest is never dispatched to) |
230
+ | `--json` | Machine-readable result |
231
+
232
+ A guest carrying no executor attestation is never a stage target: `spur agent run --spec <guest-id>`
233
+ is refused (R3), and `requiresCapabilities` stages therefore can never reach one.
234
+
235
+ ## `wait --inbox <id>` - the guest pull primitive (G73 R4)
236
+
237
+ ```bash
238
+ spur agent wait --inbox reviewer-g1 --timeout 540000 --json
239
+ ```
240
+
241
+ Returns `0` as soon as queued inbox work exists for the guest and `1` on timeout or when the id is
242
+ not a joined guest — never a silent hang. Every call heartbeats the guest's lease, so a session that
243
+ keeps looping stays joined; the timeout stays under the Bash tool's ~10-minute limit. The
244
+ `fleet-join` skill loops it (wait → `spur message inbox --agent <id>` → work → `spur message reply`),
245
+ and the `fleet-guest-stop` plugin hook delivers the same messages at a turn boundary on hosts that
246
+ support a blocking Stop hook.
247
+
170
248
  ## `doctor` - readiness check
171
249
 
172
250
  ```bash
@@ -193,23 +271,50 @@ stderr-clean and carries `capabilities`, `capabilityStale: {verifiedAgainst, det
193
271
  normalized `availability` object, and a top-level `usage` per agent row instead. Exit `1` if any
194
272
  checked agent is not ready.
195
273
 
274
+ ## `trace` - one execution record's lineage (1076 R4, ADR-132)
275
+
276
+ ```bash
277
+ spur agent trace <runId> # the run, its parents, its children
278
+ spur agent trace <rootId> --follow # poll until every run in the lineage is terminal
279
+ spur agent trace <runId> --json
280
+ ```
281
+
282
+ `trace` reports ADR-132's execution record as one lineage. A node is a run: a workflow run comes from
283
+ the `runs` table, an agent run from `coordination_runs`, and the dispatch edge is
284
+ `coordination_runs.parent_run_id` — set from a workflow dispatch key (`<runId>/<state>`) or the
285
+ inherited `SPUR_RUN_ID`. `trace <runId>` first walks that edge UP to the root and then DOWN to the
286
+ leaves, so any id in the chain yields the whole picture. Each node carries its status, the agent
287
+ session ids recorded for it (`history_run_session`, exact rows only) and its durable stream under
288
+ `.spur/memory/runs/<runId>.md` when one was written. The stream is the record; the supervisor's ring
289
+ buffer is only a live view.
290
+
291
+ ### Flags
292
+
293
+ | Flag | Purpose |
294
+ | ------ | --------- |
295
+ | `--follow` | Poll until every run in the lineage reaches a terminal status. |
296
+ | `--timeout <ms>` | `--follow` budget (default 600000). On expiry one checkpoint line is printed and the command exits 1; the runs continue. |
297
+ | `--json` | `{ rootRunId, nodes: [{ runId, kind, status, parentRunId, sessionIds, logPath }] }` — root first, depth-first. |
298
+
196
299
  ## `start` - start a supervised process
197
300
 
198
301
  ```bash
199
- spur agent start worker-1
200
- spur agent start worker-1 --json
302
+ spur agent start myapp-coder-1
303
+ spur agent start myapp-coder-1 --json
201
304
  ```
202
305
 
203
306
  Posts to the `spur self serve` supervisor API
204
307
  (`POST /api/agents/:id/start`) and prints `started <id> (pid=<n>, status=<s>)`. Requires a
205
- reachable `spur self serve`; `--server <url>` (default `http://localhost:3000/api`) targets it. Exit `1`
308
+ reachable `spur self serve`; `--server <url>` targets it, defaulting to this project's registry
309
+ serve port (`http://localhost:<port>/api`, else `http://localhost:3000/api` when the project has no
310
+ live entry — 1088 R1). Exit `1`
206
311
  when the server is unreachable or the start fails.
207
312
 
208
313
  ## `stop` - stop a supervised process
209
314
 
210
315
  ```bash
211
- spur agent stop worker-1
212
- spur agent stop worker-1 --json
316
+ spur agent stop myapp-coder-1
317
+ spur agent stop myapp-coder-1 --json
213
318
  ```
214
319
 
215
320
  Posts to the supervisor API
@@ -286,7 +391,9 @@ one never re-sends settled work; only never-started deliveries release and redel
286
391
  **[dispatch-surface rule](../../parallel-execution/references/dispatch-surface.md)**, not this
287
392
  reference. This reference documents the verbs; that rule decides which surface carries a dispatch.
288
393
  - **Not the fleet orchestrator.** The `spur self serve` supervisor drives the lifecycle: `spur agent
289
- start` / `stop` manage supervised processes and `agent list --specs` reports live state.
394
+ start` / `stop` manage supervised processes and `agent list --specs` reports live state. Dispatch
395
+ policy (`agent.fleet.strategy` `rest|gtd`, the `orchestrator` member, `--agent fleet` routing)
396
+ lives in project config and the workflow executor, not in these verbs.
290
397
 
291
398
  ## See also
292
399