From d526b43c87fdea6c8b257e79917bcc4b8a49f582 Mon Sep 17 00:00:00 2001 From: Dai Ha Date: Sat, 22 Aug 2026 22:07:25 +0200 Subject: [PATCH] =?UTF-8?q?CB-622:=20sync=20the=20portable=20CLAUDE.md=20b?= =?UTF-8?q?lock=20=E2=80=94=20tools=20are=20now=20fleet=5F*?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keeps the template byte-identical with claude-bridge/CLAUDE.md. Also fixes the fallback ladder's charter quote, which said 'off-subscription worker' while REPLY_CHARTER has long said 'spawned member' — so that rung of the ladder could never fire. --- 7-Use-Cases.md | 66 +++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/7-Use-Cases.md b/7-Use-Cases.md index 1b4cb73..d172a0e 100644 --- a/7-Use-Cases.md +++ b/7-Use-Cases.md @@ -296,31 +296,31 @@ notes after the block). Improvements land *here* first, then propagate to each p > CLAUDE.md block*); improvements go to the template first, then out to each project. Anything > specific to *this* repo lives under §Project addendum below, never inline above it. -If no `bridge_*` MCP tools are mounted in this session, this section does not apply — skip it. +If no `fleet_*` MCP tools are mounted in this session, this section does not apply — skip it. `bridged` is the **sole communication gateway** between agents here. The orchestrating session (the **primary**) and every delegated peer (a **member**) mount the *same* MCP server and talk only -through its `bridge_*` tools. No session addresses a peer, a broker, or the network directly. +through its `fleet_*` tools. No session addresses a peer, a broker, or the network directly. ### Which role am I? — settle this before acting **Every role reads this file.** A member runs in a git worktree of this same repo, so it inherits this `CLAUDE.md` verbatim, and every rule below is role-conditional. -**Call `bridge_whoami`.** It returns `primary`, `worker`, or `architect`, resolved by the daemon from +**Call `fleet_whoami`.** It returns `primary`, `worker`, or `architect`, resolved by the daemon from your connection — unforgeable, and the same resolution its authorization gate uses. A worker also carries its `sessionId`, `profile`, `worktree` and `branch`; an architect carries the slot name it was bound to. Don't infer what you can ask. Only if that call is unavailable, fall back to these — each is one-way, so keep reading until one -fires: the reply charter in your system prompt (*"You are an off-subscription worker in the +fires: the reply charter in your system prompt (*"You are a spawned member in the claude-bridge fleet"*) ⇒ **spawned member**; bridge tools prefixed `mcp__bridge__*` ⇒ **spawned member** (the launcher fixes that mount name; a primary's mount is named by whoever wrote its `.mcp.json`, so it varies); `ANTHROPIC_BASE_URL` set ⇒ **spawned member** (Claude-model members run on a clean env, so its *absence* proves nothing). None of these separate a worker from an architect — -only `bridge_whoami` does. **Still unsure ⇒ act as a worker**, the most restricted member role. The +only `fleet_whoami` does. **Still unsure ⇒ act as a worker**, the most restricted member role. The two mistakes are not symmetric: a primary acting as a worker is refused by the authorization gate — -loud and self-correcting — while a member acting as the primary ends its turn with no `bridge_reply`, +loud and self-correcting — while a member acting as the primary ends its turn with no `fleet_reply`, and the sender silently receives nothing. Fail toward the recoverable error. ### Invariants — both roles, no exceptions @@ -329,7 +329,7 @@ and the sender silently receives nothing. Fail toward the recoverable error. stays on subscription; only the bridge puts a member off it, at spawn. Mounting the bridge must never move a session across that boundary. 2. **The bridge is the only channel.** Text you print in your terminal reaches nobody — the other - side cannot see your screen. An answer that isn't in a `bridge_*` call is silently discarded. + side cannot see your screen. An answer that isn't in a `fleet_*` call is silently discarded. 3. **Identity comes from the connection, never an argument.** Workers never pass a target; you cannot act as another session. Spawn/stop/drain are lead-only; **send is lead or architect**; reply/ask are only-as-itself — any peer may answer for its own pane, and for no other. A call @@ -345,10 +345,10 @@ and the sender silently receives nothing. Fail toward the recoverable error. **Delegate by default — that is the job.** With the bridge mounted you are an orchestrator on a metered subscription, and workers are cheap, parallel, and disposable. The default answer to "who -does this?" is **a worker**, not you. Reach for `bridge_send` before you reach for `Edit`. The steps +does this?" is **a worker**, not you. Reach for `fleet_send` before you reach for `Edit`. The steps below are the procedure — run them in order, every task, not only the big ones. -0. **Know your role** — `bridge_whoami`, once per session, before anything else. +0. **Know your role** — `fleet_whoami`, once per session, before anything else. 1. **Split.** Write the unit list. Every unit carries: scope · the files or PR in question · acceptance criteria · exactly what to report back. A unit with no acceptance criteria is not ready to delegate — refine it or keep it. @@ -358,17 +358,17 @@ below are the procedure — run them in order, every task, not only the big ones delegate. The keep-list is closed: the conversation with the user, decomposition and planning, the final judgment call, verification, merges, and anything that depends on context only you hold. Nothing else is yours by default. -3. **Spawn every delegated unit first** — `bridge_spawn{profile, worktree:true, ticket}`, one per +3. **Spawn every delegated unit first** — `fleet_spawn{profile, worktree:true, ticket}`, one per unit, *before* sending any. Pass `profile` explicitly: profiles differ in model and cost, not in tier, so the default is rarely what you want. -4. **Then send them all** — `bridge_send{sessionId, content, wait:false}`. Line 1 of every brief is +4. **Then send them all** — `fleet_send{sessionId, content, wait:false}`. Line 1 of every brief is `Load the skill.` naming the worker's playbook; those skills are opt-in and that line is what makes them reliable. Where the project ships no such skill, spell the procedure out in the brief instead. The brief is self-contained — the worker sees your message and the repo, nothing of your context, your plan, or your screen. -5. **Collect** — `bridge_poll{ticket}` → `bridge_ack{target, msgId}`. Answer a worker's `bridge_ask` - with `bridge_send{turnId, content}` — **not** `sessionId`. A worker gone quiet is diagnosed with - `bridge_status`, never by reading its terminal; it also reports an open question and the `turnId` +5. **Collect** — `fleet_poll{ticket}` → `fleet_ack{target, msgId}`. Answer a worker's `fleet_ask` + with `fleet_send{turnId, content}` — **not** `sessionId`. A worker gone quiet is diagnosed with + `fleet_status`, never by reading its terminal; it also reports an open question and the `turnId` that answers it. **A worker's ask waits ~55 seconds, and no nudge makes that longer** — so never brief a worker to "ask me". Decide before you delegate, or give it an explicit default. 6. **Verify yourself.** Re-run the build and the checks. A worker cannot run your IDE tooling, any @@ -381,11 +381,11 @@ below are the procedure — run them in order, every task, not only the big ones read it yourself. 8. **Adjudicate, merge, tear down — yours alone.** Read the diff yourself: fully if it is small, targeted at the reported findings and the risky paths if it is large. Reviewer findings direct - your attention; they never substitute for it. Then merge, then `bridge_stop{paneId}`. + your attention; they never substitute for it. Then merge, then `fleet_stop{paneId}`. **Steps 3 and 4 are separate on purpose** — spawning and sending in one loop is how parallel work silently becomes serial, and it is the most common way this layer is wasted. For the same reason, -prefer `wait:false` + `bridge_poll` for anything non-trivial: a blocking `bridge_send` is capped by +prefer `wait:false` + `fleet_poll` for anything non-trivial: a blocking `fleet_send` is capped by *your own* MCP client call timeout (~60s), well below the task's real runtime. **Delegating does not delegate responsibility.** Workers open PRs; you are the gate. Never delegate @@ -393,21 +393,21 @@ the merge — and merging on a reviewer's word is delegating it by proxy. | Intent | Tool | |---|---| -| Confirm your own role | `bridge_whoami` | -| See backends available | `bridge_profiles` | -| Start a member | `bridge_spawn{role?, profile?, cwd?, worktree?, ticket?, sessionName?, resumeSessionId?}` → `sessionId` + `paneId` | -| See the fleet | `bridge_list` → `leads` (your peers) + `members` (each carries `agentSessionId` when its backend knows one) · one peer's state: `bridge_status{sessionId}` | -| Delegate (blocking) | `bridge_send{sessionId, content}` | -| Delegate (long task) | `bridge_send{sessionId, content, wait:false}` → ticket → `bridge_poll{ticket}` | -| Answer a member's `bridge_ask` | `bridge_send{turnId, content}` — **not** `sessionId` | -| Message a **peer lead** | `bridge_send{sessionId: , content}` — `bridge_list` → `leads` reports it. Coordination only, **never** a task | -| Answer a peer lead that messaged you | `bridge_reply{content}` — the one case a lead replies | -| Collect a held reply | `bridge_poll{target}` · then `bridge_ack{target, msgId}` | -| Tear down a member | `bridge_stop{paneId}` | +| Confirm your own role | `fleet_whoami` | +| See backends available | `fleet_profiles` | +| Start a member | `fleet_spawn{role?, profile?, cwd?, worktree?, ticket?, sessionName?, resumeSessionId?}` → `sessionId` + `paneId` | +| See the fleet | `fleet_list` → `leads` (your peers) + `members` (each carries `agentSessionId` when its backend knows one) · one peer's state: `fleet_status{sessionId}` | +| Delegate (blocking) | `fleet_send{sessionId, content}` | +| Delegate (long task) | `fleet_send{sessionId, content, wait:false}` → ticket → `fleet_poll{ticket}` | +| Answer a member's `fleet_ask` | `fleet_send{turnId, content}` — **not** `sessionId` | +| Message a **peer lead** | `fleet_send{sessionId: , content}` — `fleet_list` → `leads` reports it. Coordination only, **never** a task | +| Answer a peer lead that messaged you | `fleet_reply{content}` — the one case a lead replies | +| Collect a held reply | `fleet_poll{target}` · then `fleet_ack{target, msgId}` | +| Tear down a member | `fleet_stop{paneId}` | ### Lead ↔ lead — coordinate, never delegate -`bridge_list` returns `leads` alongside `members`; your own row carries `self: true`. Every other row +`fleet_list` returns `leads` alongside `members`; your own row carries `self: true`. Every other row is a peer — an orchestrator with its own context, its own members, and its own judgment. An empty `members` array means no members are spawned; it says nothing about peers. @@ -428,7 +428,7 @@ The traffic between leads is coordination and nothing else: against the code, and re-run the build. A peer's correction gets the same treatment — right or wrong on the evidence, not on who said it. Neither of you merges the other's work unreviewed. -Being messaged by a peer does not make you its worker: answer with `bridge_reply`, and push back on +Being messaged by a peer does not make you its worker: answer with `fleet_reply`, and push back on the substance if it is wrong. A peer that simply complies has thrown away the reason there are two of you. @@ -436,11 +436,11 @@ you. 1. **Load the playbook skill the lead named** before doing anything else. 2. **Do the assigned scope only.** Note anything you spot outside it in one line; don't go hunt it. -3. **`bridge_ask{question}`** when a decision is genuinely the lead's (ambiguous requirement, two +3. **`fleet_ask{question}`** when a decision is genuinely the lead's (ambiguous requirement, two defensible fixes, "bug or intended?"). It blocks and you resume the *same* turn with the answer. Don't ask what you could decide yourself. -4. **End the turn with exactly one `bridge_reply{content}`**, carrying your complete answer. This is - the whole handoff. No `bridge_reply` ⇒ the sender gets nothing and the exchange stalls. +4. **End the turn with exactly one `fleet_reply{content}`**, carrying your complete answer. This is + the whole handoff. No `fleet_reply` ⇒ the sender gets nothing and the exchange stalls. Do **not** lean on the completion fallback to carry your answer for you: when you end a turn without replying, the bridge scrapes your pane, and it can return only the last 4000 characters. A clipped scrape is marked as partial, but the missing text is gone — your report reaches the @@ -459,7 +459,7 @@ you. | Layer | Scope | Reaches | |---|---|---| -| the launcher's reply charter | the one rule that must survive with no repo: *end every turn with `bridge_reply`* | every spawned member, at launch, every peer kind — never a lead | +| the launcher's reply charter | the one rule that must survive with no repo: *end every turn with `fleet_reply`* | every spawned member, at launch, every peer kind — never a lead | | **this section** | protocol + orchestration policy | primary **and** every member that reads the repo — tracked in git, so worktrees inherit it | | role agent definition files | role contract and per-job procedure | a member whose launcher binds its role to the matching file in its worktree | | role playbook skills | per-job procedure (commit/PR recipe, finding format) | a member told to load one |