CB-595: catalogue the async-ticket nudge and the member token shadow
Two of the ~14 operator-facing tickets that shipped since v1.0.0 with no Features entry. Written from behaviour I verified directly this session, not from commit messages. CB-588 — a wait:false ticket now nudges the lead's pane when it goes terminal. The why line is the point: the charter tells leads to prefer wait:false, and until this landed that was the one mode with no notification at all. Its gotcha is one I hit myself today. The nudge goes to the lead's PANE, so a lead driving the REST surface gets nothing, and the 10-minute terminal-ticket TTL then prunes the report. A ticket 404'd while its member still sat in done. The work survived only because the implementer skill had opened a PR. The ticket is not the durable artefact; the PR is. CB-592 — the admin GITEA_ACCESS_TOKEN is shadowed in every member's environment, with the BRIDGED_MEMBER marker to win against the pane's login shell re-exporting it. Its gotcha names the limit honestly: this blocks ONE name out of about thirty the login shell sources, and a second forge token is among the unblocked ones. Filed as CB-596. Records why it went unnoticed — present-and-useless looks identical to absent.
+53
@@ -1133,6 +1133,59 @@ you rather than forcing it.
|
||||
|
||||
---
|
||||
|
||||
## Get told when an async delegation finishes
|
||||
|
||||
**What.** A `bridge_send{wait:false}` ticket that reaches a terminal phase — replied, failed, wedged,
|
||||
or abandoned — now injects a short nudge into the **lead's own pane** telling it to poll. Several
|
||||
tickets finishing at once coalesce into one nudge naming the count. Polling a ticket marks it
|
||||
collected, so a ticket you already read is never nudged about again.
|
||||
|
||||
**On.** Automatic when the lead is a herdr pane. Bounded by `fleet.leaders.<name>.push_reminders`
|
||||
(default 5) and `push_backoff_ms` (default 15000). A lead that is not a herdr pane leaves the
|
||||
registry empty, the loop becomes a no-op, and delivery degrades to pull — nothing is lost.
|
||||
|
||||
**Why.** The charter tells leads to prefer `wait:false` for anything non-trivial, because a blocking
|
||||
`bridge_send` is capped by the caller's own MCP client timeout of about 60 seconds. But until this
|
||||
landed, that preferred mode was the one mode with **no notification at all**: `MessageService.reply`
|
||||
returns on the rendezvous fast path before the push loop hears anything, so an async ticket finished
|
||||
in silence and the lead only found out by polling on a hunch.
|
||||
|
||||
**Gotcha.** The nudge goes to the lead's **pane**, not to its MCP session. A lead driving the REST
|
||||
surface directly — which is exactly what you fall back to when the MCP mount drops — receives nothing.
|
||||
Combine that with the 10-minute terminal-ticket TTL (`MessageService.TICKET_TTL_NANOS`) and a finished
|
||||
worker's report can be pruned before it is ever read. That happened during this feature's own
|
||||
close-out: a ticket returned 404 while its member still sat in `done`. The work survived only because
|
||||
the implementer skill had opened a PR, and the PR body carried the report. **The ticket is not the
|
||||
durable artefact; the PR is.** If you orchestrate over REST, poll on a timer.
|
||||
|
||||
---
|
||||
|
||||
## Members cannot use the operator's admin forge token
|
||||
|
||||
**What.** Every member launch overwrites `GITEA_ACCESS_TOKEN` with a non-blank blocked sentinel, and
|
||||
sets a `BRIDGED_MEMBER=1` marker. Applied in `HerdrPeerLauncher.baseEnv` *after* the profile's own
|
||||
`env:` map, so no profile — present or future — can name that key and restore the real value. CB-302's
|
||||
separate `GITEA_TOKEN` grant is untouched, so a member can still push and open its own PR with a
|
||||
repo-scoped token.
|
||||
|
||||
**On.** Automatic, both adapters, every profile.
|
||||
|
||||
**Why.** A member is an autonomous agent running arbitrary tool calls. It has no business holding the
|
||||
operator's admin credential, and the rule the operator set is explicit: leads and architects may use
|
||||
`GITEA_ACCESS_TOKEN`, members use `WORKER_GITEA_TOKEN`. A plain env overlay was not enough — the
|
||||
pane's login shell re-sources the secret store afterwards and would put the real value back — which is
|
||||
why the marker exists: the shell's export is guarded on `BRIDGED_MEMBER` being unset.
|
||||
|
||||
**Gotcha, and it is the important one.** This blocks **one name**. The pane's login shell sources a
|
||||
secret store exporting about **thirty**, and a second forge token is among the ones nothing blocks.
|
||||
Tracked as **CB-596**. The reason nobody noticed is worth internalising: a Claude Code member inherits
|
||||
the operator's user-scope `~/.claude.json` servers, so it mounts 45 `mcp__gitea__*` tools including
|
||||
`delete_branch` and `delete_file`. They all fail — but **only** because the credential they read is
|
||||
blocked. Remove the block and the same picture becomes 45 working destructive tools, with no visible
|
||||
difference beforehand. **Present-and-useless looks identical to absent.**
|
||||
|
||||
---
|
||||
|
||||
## Backfill status
|
||||
|
||||
This page was started after the fact, so it is **not yet complete**. Entries above are written from
|
||||
|
||||
Reference in New Issue
Block a user