@gobing-ai/spur 0.4.20 → 0.4.21

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 (64) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/workflows/task-pipeline.yaml +28 -10
  3. package/package.json +9 -9
  4. package/plugins/sp/plugin.json +1 -1
  5. package/plugins/sp/skills/fleet-join/SKILL.md +70 -4
  6. package/plugins/sp/skills/spur-cli/references/agent.md +9 -1
  7. package/spur.js +2945 -874
  8. package/web/_astro/{BoardApp.BDo7Cplz.js → BoardApp.DFBNysRC.js} +179 -179
  9. package/web/_astro/{BoardApp.uR1DxOv6.js → BoardApp.DspUVt5b.js} +1 -1
  10. package/web/_astro/{TaskDetail.BiGHeRcp.js → TaskDetail.DEzLL6Fe.js} +1 -1
  11. package/web/_astro/{arc.BLw5ykEN.js → arc.TAQDSOGC.js} +1 -1
  12. package/web/_astro/{architectureDiagram-3BPJPVTR.C2BEgSVb.js → architectureDiagram-3BPJPVTR.D2Zyc6nm.js} +1 -1
  13. package/web/_astro/{blockDiagram-GPEHLZMM.D8G9DLH3.js → blockDiagram-GPEHLZMM.BnA_rJl6.js} +6 -6
  14. package/web/_astro/{board-facade-react-router-dom.Dy5pjzOw.js → board-facade-react-router-dom.CHNMUrya.js} +1 -1
  15. package/web/_astro/{board-facade-react-router.DjjqU27_.js → board-facade-react-router.Dob6MDgf.js} +1 -1
  16. package/web/_astro/{c4Diagram-AAUBKEIU.dU7HR9k5.js → c4Diagram-AAUBKEIU.DVUo9pxo.js} +1 -1
  17. package/web/_astro/channel.DpBpvy1k.js +1 -0
  18. package/web/_astro/{chunk-2J33WTMH.5BIk-HVp.js → chunk-2J33WTMH.BJ-VkV91.js} +1 -1
  19. package/web/_astro/{chunk-4BX2VUAB.BVIKX24s.js → chunk-4BX2VUAB.xpN1rBQK.js} +1 -1
  20. package/web/_astro/{chunk-55IACEB6.Bz2tdkGM.js → chunk-55IACEB6.Dtu4VTmK.js} +1 -1
  21. package/web/_astro/{chunk-727SXJPM.R0d_FlTN.js → chunk-727SXJPM.CjXhM1c1.js} +1 -1
  22. package/web/_astro/{chunk-AQP2D5EJ.C2kK8Ok-.js → chunk-AQP2D5EJ.DSCad_Gd.js} +1 -1
  23. package/web/_astro/{chunk-FMBD7UC4.COAncjFn.js → chunk-FMBD7UC4.DxwDIiuY.js} +1 -1
  24. package/web/_astro/{chunk-ND2GUHAM.CeNg5VSN.js → chunk-ND2GUHAM.D5LgSWYE.js} +1 -1
  25. package/web/_astro/{chunk-QZHKN3VN.DRGDDzrj.js → chunk-QZHKN3VN.CwXZoKZI.js} +1 -1
  26. package/web/_astro/chunk-YNUBSHFH.B6ndyWdA.js +7 -0
  27. package/web/_astro/{classDiagram-4FO5ZUOK.DmM59Lgb.js → classDiagram-4FO5ZUOK.DZ-I2QOo.js} +1 -1
  28. package/web/_astro/{classDiagram-v2-Q7XG4LA2.DmM59Lgb.js → classDiagram-v2-Q7XG4LA2.DZ-I2QOo.js} +1 -1
  29. package/web/_astro/{cose-bilkent-S5V4N54A.BjKuSb1i.js → cose-bilkent-S5V4N54A.DszE5dpz.js} +1 -1
  30. package/web/_astro/{cynefin-OW5HDTMX.DQevIJEc.js → cynefin-OW5HDTMX.c-ctyPLt.js} +1 -1
  31. package/web/_astro/cytoscape.esm.BDkkwuE4.js +321 -0
  32. package/web/_astro/{dagre-BM42HDAG.CqOK1C5k.js → dagre-BM42HDAG.Boq07Shn.js} +2 -2
  33. package/web/_astro/{diagram-2AECGRRQ.B7i8Xbcc.js → diagram-2AECGRRQ.Csap4wVu.js} +1 -1
  34. package/web/_astro/{diagram-5GNKFQAL.DXGFk2rU.js → diagram-5GNKFQAL.Cy4jXe_F.js} +1 -1
  35. package/web/_astro/{diagram-KO2AKTUF.BDC9f2pC.js → diagram-KO2AKTUF.BXEZQbTM.js} +1 -1
  36. package/web/_astro/{diagram-LMA3HP47.D-Mrwnmt.js → diagram-LMA3HP47.CFcDobF6.js} +1 -1
  37. package/web/_astro/{diagram-OG6HWLK6.XXGX1BQ_.js → diagram-OG6HWLK6.CJ8Q1cQd.js} +1 -1
  38. package/web/_astro/{erDiagram-TEJ5UH35.DahWkk7M.js → erDiagram-TEJ5UH35.B409nFLg.js} +1 -1
  39. package/web/_astro/{flowDiagram-I6XJVG4X.DaG5HfPs.js → flowDiagram-I6XJVG4X.BtF5dGDY.js} +4 -4
  40. package/web/_astro/{ganttDiagram-6RSMTGT7.DZe_CQWm.js → ganttDiagram-6RSMTGT7.BbflTg4R.js} +1 -1
  41. package/web/_astro/{gitGraphDiagram-PVQCEYII.C4zSw3kS.js → gitGraphDiagram-PVQCEYII.BLPcOhGS.js} +1 -1
  42. package/web/_astro/{infoDiagram-5YYISTIA.CmaEULgT.js → infoDiagram-5YYISTIA.DsaY8QU3.js} +1 -1
  43. package/web/_astro/{ishikawaDiagram-YF4QCWOH.DKKhZJ98.js → ishikawaDiagram-YF4QCWOH.D9PaTLtO.js} +1 -1
  44. package/web/_astro/{journeyDiagram-JHISSGLW.B6d7TuYQ.js → journeyDiagram-JHISSGLW.4_zPJ9m2.js} +1 -1
  45. package/web/_astro/{kanban-definition-UN3LZRKU.xiG_jH03.js → kanban-definition-UN3LZRKU.IqD1vq7W.js} +3 -3
  46. package/web/_astro/{linear.DsbUmqlh.js → linear.JJiEkviR.js} +1 -1
  47. package/web/_astro/{mermaid.core.CihlV6Wy.js → mermaid.core.Brxzivhz.js} +55 -55
  48. package/web/_astro/{mindmap-definition-RKZ34NQL.Cm2UvqJQ.js → mindmap-definition-RKZ34NQL.B6pZnBGO.js} +1 -1
  49. package/web/_astro/{pieDiagram-4H26LBE5.COyvnb_Q.js → pieDiagram-4H26LBE5.MM6Of7YP.js} +1 -1
  50. package/web/_astro/{quadrantDiagram-W4KKPZXB.BdaJr8EI.js → quadrantDiagram-W4KKPZXB.7eWQnH9R.js} +1 -1
  51. package/web/_astro/{requirementDiagram-4Y6WPE33.aS-qeofA.js → requirementDiagram-4Y6WPE33.C3T9mbHc.js} +1 -1
  52. package/web/_astro/{sankeyDiagram-5OEKKPKP.BxaOWF5N.js → sankeyDiagram-5OEKKPKP.CqlwDe_m.js} +1 -1
  53. package/web/_astro/{sequenceDiagram-3UESZ5HK.CfZPPWA1.js → sequenceDiagram-3UESZ5HK.BNVlPChR.js} +4 -4
  54. package/web/_astro/{stateDiagram-AJRCARHV.D6VXy0-M.js → stateDiagram-AJRCARHV.DSExW-ER.js} +1 -1
  55. package/web/_astro/{stateDiagram-v2-BHNVJYJU.DatbDxXn.js → stateDiagram-v2-BHNVJYJU.CxE4k_fB.js} +1 -1
  56. package/web/_astro/{timeline-definition-PNZ67QCA.BxQ7-VRY.js → timeline-definition-PNZ67QCA.uFqjG7Z5.js} +1 -1
  57. package/web/_astro/{vennDiagram-CIIHVFJN.BJny6MAy.js → vennDiagram-CIIHVFJN.DpTrAXYs.js} +5 -5
  58. package/web/_astro/{wardleyDiagram-YWT4CUSO.gzTiYN-4.js → wardleyDiagram-YWT4CUSO.Dl0KBFZe.js} +1 -1
  59. package/web/_astro/{xychartDiagram-2RQKCTM6.DTR_zwDh.js → xychartDiagram-2RQKCTM6.CE0syl0o.js} +1 -1
  60. package/web/board-runtime.json +2 -2
  61. package/web/index.html +2 -2
  62. package/web/_astro/channel.DSbvfOEf.js +0 -1
  63. package/web/_astro/chunk-YNUBSHFH.CxeAygfi.js +0 -7
  64. package/web/_astro/cytoscape.esm.BB4DxJjf.js +0 -321
@@ -7,7 +7,7 @@
7
7
  "plugins": [
8
8
  {
9
9
  "name": "sp",
10
- "version": "0.4.20",
10
+ "version": "0.4.21",
11
11
  "source": "./plugins/sp"
12
12
  }
13
13
  ]
@@ -660,19 +660,27 @@ states:
660
660
  # feature credit) is owned by `plugins/sp/agents/super-reviewer.md` Output Format,
661
661
  # which this pointer names.
662
662
  input: >-
663
- /sp:dev-review --tasks ${vars.wbs} --auto --focus ${vars.reviewFocus} Answer contract (full: super-reviewer Output
664
- Format). Two artifacts: the `## Review` section (deriveReviewConfidence) and your captured answer
665
- (`spur task verdict` input). The answer has one `Confidence: HIGH|MEDIUM|LOW` line, EVIDENCE-derived
666
- (deriveVerifyConfidence), never the section's disposition level. End with one `Verdict: PASS|PARTIAL|FAIL` line after `| Req | Status | Evidence |` (one row per requirement; MET | PARTIAL | UNMET) and `| AC | Status |
667
- Evidence Type | Evidence |` (one row per AC; MET | PARTIAL | UNMET | N/A). Evidence types (`+` ok): test
668
- | command | static-ref | manual-review | llm-judge | n/a. Evidence cells cite a repo-root-relative `path:line`
669
- (never `/tmp`: out-of-repo blocks done) or a named check. AC rows
670
- key on the task's identities or a declared `AC-N` alias; a linked scenario covers its task and a task-local criterion
671
- needs no feature credit. Open P1-P3 blocks completion.
663
+ /sp:dev-review --tasks ${vars.wbs} --auto --focus ${vars.reviewFocus}
664
+ Answer contract: super-reviewer Output Format. Emit the machine-linted artifact, not a prose summary.
665
+ `## Review`: deriveReviewConfidence. Captured answer (`spur task verdict`) has one `Confidence: HIGH|MEDIUM|LOW`
666
+ line (deriveVerifyConfidence), never the section's disposition level.
667
+ End with one `Verdict: PASS|PARTIAL|FAIL` line (plain, final) after
668
+ `| Req | Status | Evidence |` (one row per requirement; MET | PARTIAL | UNMET) and
669
+ `| AC | Status | Evidence Type | Evidence |` (one row per AC; MET | PARTIAL | UNMET | N/A).
670
+ Evidence types (`+` ok): test | command | static-ref | manual-review | llm-judge | n/a.
671
+ Cite repo-root-relative `path:line` (never `/tmp`) or named checks. AC rows use the task's identities or
672
+ a declared `AC-N` alias; a linked scenario covers its task; a task-local criterion needs no feature credit.
673
+ Open P1-P3 blocks completion.
674
+ Also write it to `.spur/run/${vars.__runId}-review-cert.md`.
672
675
  # The captured review answer is the run's certification input (and the
673
676
  # `task verdict` input below): expectFile fails the step when no answer landed.
674
677
  answerFile: .spur/run/${vars.__runId}-review-answer.txt
675
678
  expectFile: .spur/run/${vars.__runId}-review-answer.txt
679
+ # The reviewer WRITES this one itself (see (c2)); declared so the composition lint can
680
+ # see the run path the prompt names (1233 R2).
681
+ inputs:
682
+ - path: .spur/run/${vars.__runId}-review-cert.md
683
+ kind: artifact
676
684
  # Declared Layer-1 role (0538 R2/0710 R7): routing reason; no executor pin — role routing feeds the distinctness gate.
677
685
  role: reviewer
678
686
  # B7 R3/R6 (0894): declared fresh policy (reviewer default) — the action
@@ -683,6 +691,16 @@ states:
683
691
  priority: ${vars.taskPriority}
684
692
  compareExecutorWith: implement
685
693
  timeoutMs: ${vars.stepTimeoutMs}
694
+ # (c2) The reviewer is asked to WRITE its canonical artifact to `-review-cert.md`, because
695
+ # the captured answer above is the agent's stdout: a reviewer that writes the artifact and
696
+ # then narrates its summary has the artifact overwritten by the narration, and the verdict
697
+ # lint fails work that is actually complete (four such runs in the G74 batch, 2026-10-24).
698
+ # The agent-written cert wins; when it is absent or empty the captured answer is used, so
699
+ # this is a strict widening of accepted inputs, never a new failure mode.
700
+ - kind: shell
701
+ options:
702
+ command: >-
703
+ A=".spur/run/$__runId-review-answer.txt"; C=".spur/run/$__runId-review-cert.md"; [ -s "$C" ] || cp "$A" "$C" 2>/dev/null; exit 0
686
704
  # (d) `spur task verdict` owns the answer lint and the verdict derivation (task 1003
687
705
  # R2): one complete requirement row per declared requirement, AC identities resolved,
688
706
  # status/evidence vocabularies accepted, hedged or uncited evidence rejected. It
@@ -694,7 +712,7 @@ states:
694
712
  options:
695
713
  id: review-verdict
696
714
  executable: "${vars.spurBin}"
697
- args: ["task", "verdict", "${vars.wbs}", "--from-answer", ".spur/run/${vars.__runId}-review-answer.txt"]
715
+ args: ["task", "verdict", "${vars.wbs}", "--from-answer", ".spur/run/${vars.__runId}-review-cert.md"]
698
716
  resultFile: .spur/run/${vars.__runId}-review-verdict.status
699
717
  softFail: true
700
718
  # (e) one fold, one token: PASS requires the typed verdict PASS, the artifact's own
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/spur",
3
- "version": "0.4.20",
3
+ "version": "0.4.21",
4
4
  "description": "Spur CLI — local-first harness for mainstream coding agents: constraint checking, workflow orchestration, agent health, and history analytics. Bun-native; exposes the `spur` command.",
5
5
  "keywords": [
6
6
  "spur",
@@ -58,14 +58,14 @@
58
58
  },
59
59
  "devDependencies": {
60
60
  "@commander-js/extra-typings": "^14.0.0",
61
- "@gobing-ai/ts-db": "^0.5.33",
62
- "@gobing-ai/ts-ai-runner": "^0.5.33",
63
- "@gobing-ai/ts-dual-workflow-engine": "^0.5.33",
64
- "@gobing-ai/ts-infra": "^0.5.33",
65
- "@gobing-ai/ts-llm-jsonl-importer": "^0.5.33",
66
- "@gobing-ai/ts-rule-engine": "^0.5.33",
67
- "@gobing-ai/ts-runtime": "^0.5.33",
68
- "@gobing-ai/ts-utils": "^0.5.33",
61
+ "@gobing-ai/ts-db": "^0.7.1",
62
+ "@gobing-ai/ts-ai-runner": "^0.7.1",
63
+ "@gobing-ai/ts-dual-workflow-engine": "^0.7.1",
64
+ "@gobing-ai/ts-infra": "^0.7.1",
65
+ "@gobing-ai/ts-llm-jsonl-importer": "^0.7.1",
66
+ "@gobing-ai/ts-rule-engine": "^0.7.1",
67
+ "@gobing-ai/ts-runtime": "^0.7.1",
68
+ "@gobing-ai/ts-utils": "^0.7.1",
69
69
  "@types/bun": "1.4.3",
70
70
  "@types/figlet": "^1.7.0",
71
71
  "@types/node-notifier": "8.0.5",
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "sp",
3
- "version": "0.4.20",
3
+ "version": "0.4.21",
4
4
  "description": "Spur — a local-first harness engineering toolkit that wraps mainstream coding agents with constraint checking, workflow orchestration, and history analytics."
5
5
  }
@@ -26,7 +26,44 @@ Pick the role whose work this session can actually do. `--session-id` defaults t
26
26
  `CLAUDE_CODE_SESSION_ID`, which is what the Stop hook matches against — without it the hook cannot
27
27
  find this session, though the `wait --inbox` loop still works.
28
28
 
29
- ## Pull loop
29
+ **Renewal is automatic (G75 R1, task 1279).** `join` records the *agent* process that launched this
30
+ session — never the short-lived CLI pid — and starts one detached renewer that heartbeats the lease
31
+ every third of the TTL. Long work with no `wait --inbox` in between no longer lets the lease expire.
32
+ The record says which happened: `identity: 'verified'` with a `pid`/`processStartedAt` means renewal
33
+ is running; `identity: 'unverified'` with `pid: null` means no agent ancestor could be proved, so
34
+ nothing renews and the session must keep looping `wait --inbox` to stay joined. A rejoin from the
35
+ same session reuses the running renewer instead of starting a second one.
36
+
37
+ ## Binding a declared member (opt-in, fenced)
38
+
39
+ ```bash
40
+ spur agent join --role coder --member <declared-member-id> --json
41
+ ```
42
+
43
+ `--member` binds this session to one **declared** member instead of joining as a plain guest: the
44
+ record id becomes the member id, so `wait --inbox <member-id>` addresses the declared member's inbox,
45
+ and a supervised spawn or fleet dispatch sees the member busy through its own occupant row. It exits 2
46
+ with a named reason for an unknown/disabled member, a role mismatch, an executor that cannot attest
47
+ the stage capabilities, a live occupant, or a concurrent binder that lost the race. Guests without
48
+ `--member` are unchanged — and still excluded from role selection.
49
+
50
+ ### Attached lifecycle reports carry the binding pin (task 1282)
51
+
52
+ A bound occupant's lifecycle reports must present the host binding pin or they are refused (exit 2):
53
+
54
+ ```bash
55
+ spur agent report --state working --seq <ns> --pin <ownerEpoch>:<occupancyGeneration> --json
56
+ ```
57
+
58
+ The first pin-matched report completes the handshake (the host's strategy then treats this member as
59
+ stage-visible); later reports never move it. A pin mismatch means the occupant generation moved —
60
+ re-read `spur agent list --specs --json` instead of retrying. Plain guests keep reporting without a pin.
61
+
62
+ ## Pull loop (the default path — hooks are acceleration only)
63
+
64
+ The durable inbox loop below is what makes a guest work on **every** host, hooks installed or not.
65
+ Never substitute it with repeated model turns or terminal polling while the session is busy: each
66
+ `wait --inbox` call is one bounded pull, and the session does the work between pulls.
30
67
 
31
68
  `spur agent wait --inbox <id> --timeout 540000 --json` returns **0** with up to five claimed messages
32
69
  in `{ id, pending, messages }`, settling their delivery after the output handoff. It returns **1**
@@ -39,7 +76,13 @@ the work is done.
39
76
  2. Read the returned messages, including their IDs. `spur message show <id> --json` can reread one;
40
77
  `spur message inbox --agent <id> --json` is a non-consuming historical view.
41
78
  3. Do the work the message asks for.
42
- 4. `spur message reply <msgId> "<result>"` → reply to each one.
79
+ 4. `spur message reply <msgId> "<result>"` → reply to each one. A bound occupant answering a **stage
80
+ request** (a `fleet:task:<requestId>:<attempt>` keyed message) MUST make the reply body the JSON
81
+ correlation payload — `{ "requestId": …, "attempt": …, "ownerEpoch": …, "occupancyGeneration": …,
82
+ "artifact": "<path or summary>" }` — with the values from the request and its own binding. The
83
+ host certifies the turn on that payload alone; a plain-text reply never completes a stage and the
84
+ request is retried to someone else. Do not answer stage requests for a binding you no longer hold:
85
+ a stale epoch/generation in the payload is fenced off, not promoted.
43
86
  5. Re-arm: go back to step 1 while the operator wants this session in the fleet.
44
87
 
45
88
  ## Leave
@@ -49,8 +92,29 @@ spur agent leave --json # the guest joined by this session
49
92
  spur agent leave my-session --json # an explicit id
50
93
  ```
51
94
 
52
- Leaving releases the lease immediately. If the session dies without leaving, the lease expires and
53
- the reconciler pass retires the guest — pending work is never lost, it returns to `queued`.
95
+ Leaving releases the lease immediately. A **bound** occupant's leave drains first: it stops new
96
+ assignment, waits up to the drain grace (default 30s, `--drain-timeout <ms>` to bound it) for the
97
+ in-flight turn to settle, then retires the record. A turn that does not settle in time is never
98
+ failed by the leave — it stays outcome-unknown and resumable; nothing is killed. If the session dies
99
+ without leaving, the lease expires and the reconciler pass retires the guest — pending work is never
100
+ lost, it returns to `queued`.
101
+
102
+ ## Host capabilities (probed, not assumed)
103
+
104
+ `bun run fleet-e2e --host-probe` writes `docs/reports/fleet-host-capabilities.json`: one row per
105
+ host×mode with the installed binary path/version, the wake channel and the exact `--help` line that
106
+ proves it. Anything unproven is `pull-only` with a reason.
107
+
108
+ | Host | Interactive wake | Headless |
109
+ | --- | --- | --- |
110
+ | Codex | `app-server` (a reachable App Server connection) | `pull-only` |
111
+ | Claude Code | `hook` (the Stop callback below) | `pull-only` |
112
+ | Pi | `rpc` | `pull-only` |
113
+
114
+ These values are **installed-host evidence**, so re-read the report instead of trusting this table
115
+ after an upgrade. A `pull-only` row is not a defect: the loop above is the portable contract, and the
116
+ hook/RPC/App Server channels only shorten the wait. `--real-hosts --agents <csv>` is the opt-in lane
117
+ that drives a real host end to end; the default lane never launches one.
54
118
 
55
119
  ## Stop-hook delivery (opportunistic)
56
120
 
@@ -66,3 +130,5 @@ so the pull loop above — not the hook — is what makes a guest work anywhere.
66
130
  - Guests are **not** supervised: do not expect restart, pid ownership, or `--drain` injection.
67
131
  - Never dispatch a stage to a guest id: `spur agent run --spec <guest-id>` is refused on purpose.
68
132
  - Never hold the write slot through a guest: the guest lease is the only heartbeat (R5).
133
+ - Renewal stops itself on agent-process death, a reused pid, a lost fence or `leave`. There is no
134
+ command to stop it and no daemon behind it: it lives no longer than the agent that joined.
@@ -26,7 +26,7 @@ that before using `run` for fan-out dispatch.
26
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` |
27
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
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` |
29
+ | `join` | Join the fleet as a guest occupant — a live session that pulls its own work (G73 R2, task 1081); `--member` binds a declared member instead (G75 R3, task 1281) | `--role <name>` `--id <id>` `--member <id>` `--session-id <sid>` `--pid <n>` `--executor <name>` `--json` |
30
30
  | `leave` | Leave the fleet: release the guest lease, retire the occupant, return claimed messages to `queued` | `[id]` `--session-id <sid>` `--json` |
31
31
  | `status` | Agent specs with live process status and member session (requires `spur self serve`) | `--server <url>` `--json` |
32
32
  | `doctor [agent]` | Check agent readiness | `--json` `--probe-health` `--force-refresh` |
@@ -228,11 +228,19 @@ returns its claimed messages to `queued` and removes the record.
228
228
  | `--session-id <sid>` | Host session id (defaults to `CLAUDE_CODE_SESSION_ID`) |
229
229
  | `--pid <n>` | Process id to record |
230
230
  | `--executor <name>` | Executor name to record (informational — a guest is never dispatched to) |
231
+ | `--member <id>` | Bind a **declared member** instead of joining as a guest (G75 R3, task 1281): resolves the enabled member, checks role/executor, requires a capability proof, and takes the fenced occupant of `guest:<member-id>`. The record id becomes the member id, so `wait --inbox <member-id>` addresses the declared member's inbox. Exits 2 with `unknown-member`, `disabled-member`, `role-mismatch`, `capability-unattested`, `live-occupant` or `collision`. Without it, `join` is unchanged |
231
232
  | `--json` | Machine-readable result |
232
233
 
233
234
  A guest carrying no executor attestation is never a stage target: `spur agent run --spec <guest-id>`
234
235
  is refused (R3), and `requiresCapabilities` stages therefore can never reach one.
235
236
 
237
+ `--member <id>` inverts that for exactly one declared id: the binding takes the member's occupant row
238
+ at generation `max+1` and the `guest:<member-id>` claim, so a supervised spawn or strategy dispatch
239
+ sees the member busy through the same `hasRunning` check it already uses — no dual writers. Every
240
+ renew re-checks both the claim epoch and that generation, so a taken-over member refuses the stale
241
+ binder's claim/accept. `memberBinding.stageEligible` is `false` when the binder's host has only the
242
+ `pull-only` wake channel (`bun run fleet-e2e --host-probe`), i.e. it may receive messages but no stage.
243
+
236
244
  ## `wait --inbox <id>` - the guest pull primitive (G73 R4)
237
245
 
238
246
  ```bash