You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A notice cannot be addressed to one agent conversation. AgentRecipient has actor | host | session | workspace, and the notice principal is built from the same four axes — lineage is not part of it. So a plugin that wants to tell the other subagent something ("you and I are both editing src/shared.ts") can only target:
recipient.session — on Claude/Codex every subagent's hooks carry the rootsession_id, so this reaches every agent under the root, not one of them (on Cursor conversation_id doubles as the session id, so it happens to work there);
recipient.workspace — reaches every agent whose cwd is that directory, which is what examples/worktree-proximity does today (one actor per worktree is the assumption that makes it work);
The #99 scope note (2026-09-03) says directed notices "should target session, workspace, or the conversation tree via request.lineage" — but the kernel has no recipient axis for that yet.
packages/rsc-runtime/src/agent-request.ts:493-499 — openRequest({ principal: { actor, host, session, workspace } }); lineage is on the request (:489, :505) but not on the principal.
packages/rsc-runtime/src/notices/state.ts:185-202 — recipientMatchesPrincipal compares the four axes only.
packages/agent-bundle/src/mcp-server-runtime.ts:134-150 — actor is http.authInfo.clientId; :759-788 — event scopes mount host/session/workspace/lineage, no actor. Same for standalone hooks, packages/agent-bundle/src/adapters/hook-contract.ts:730-741.
examples/worktree-proximity/src/events/tool/before.tsx:67-82 — publishes with recipient: { workspace: { root: conflict.worktreeRoot } } while dedupeKey still names the target actor.
README.md:77-81: tool envelopes carry no agent_id, so peers in one directory collapse to the derived worktree:<root> identity — the workspace axis cannot separate two agents in one worktree.
Proposed shape (small)
interfaceAgentRecipient{// …existing…/** Matches when request.lineage.conversation === conversation (a specific agent thread). */readonlyconversation?: string;/** Matches when request.lineage.root === root (every agent under one root). */readonlyroot?: string;}interfaceAgentNoticePrincipal{// …existing…readonlylineage: Observed<AgentLineage>;}
recipientMatchesPrincipal treats an unavailable lineage like an unavailable axis today (no match). Ledger schema gains two optional recipient fields — no state-definition id bump needed if the schema is additive (state.ts notice schema). The next-event admission, inbox, resources/updated, and receipt discipline are unchanged; attempted stays the strongest state, exactly as #99 records.
Design question (from the same use-case): is a thin peer-messaging façade worth adding on top — notices.send({ to: { conversation }, content }) / notices.read() — or is the recipient axis enough and the façade stays app-level? The #99 survey already establishes that no pinned host offers a directed push channel, so the façade would only be sugar over publish + next-event admission.
In examples/worktree-proximity: tool/before.tsx publishes with recipient: { conversation: <other actor's lineage conversation> }; the route-unit test "attempts and surfaces a notice on the recipient next event" (tests/route-unit/routes.test.ts) passes with two actors bound to the same worktree (today impossible), and the cross-process journey suite (packages/agent-bundle/tests/worktree-proximity-journeys.test.ts) still proves workspace-directed delivery for the existing journeys. A new ledger test proves a conversation-addressed notice is not admitted on a sibling's event.
Problem
A notice cannot be addressed to one agent conversation.
AgentRecipienthasactor | host | session | workspace, and the notice principal is built from the same four axes —lineageis not part of it. So a plugin that wants to tell the other subagent something ("you and I are both editingsrc/shared.ts") can only target:recipient.session— on Claude/Codex every subagent's hooks carry the rootsession_id, so this reaches every agent under the root, not one of them (on Cursorconversation_iddoubles as the session id, so it happens to work there);recipient.workspace— reaches every agent whosecwdis that directory, which is whatexamples/worktree-proximitydoes today (one actor per worktree is the assumption that makes it work);recipient.actor— never matches in event scopes:actoris the HTTP-authenticated MCP client only (Actor principal for generated event scopes: typed unavailable reasons and the one derivable host field (parked from #233/#223) #391 closed as not planned, feat(lineage): request.lineage is the only identity-adjacent surface; scoped, self-correcting Cursor child binding #444).The #99 scope note (2026-09-03) says directed notices "should target session, workspace, or the conversation tree via
request.lineage" — but the kernel has no recipient axis for that yet.Evidence (
main@284141958)packages/rsc-runtime/src/notices/contract.ts:34-39(AgentRecipient),:41-46(AgentNoticePrincipal: actor/host/session/workspace).packages/rsc-runtime/src/agent-request.ts:493-499—openRequest({ principal: { actor, host, session, workspace } });lineageis on the request (:489,:505) but not on the principal.packages/rsc-runtime/src/notices/state.ts:185-202—recipientMatchesPrincipalcompares the four axes only.packages/agent-bundle/src/mcp-server-runtime.ts:134-150—actorishttp.authInfo.clientId;:759-788— event scopes mount host/session/workspace/lineage, no actor. Same for standalone hooks,packages/agent-bundle/src/adapters/hook-contract.ts:730-741.packages/rsc-runtime/src/lineage-native.ts:40-54— Claude/Codex:conversation = agent_id ?? session_id,root = session_id; Cursor:conversation = conversation_id.examples/worktree-proximity/src/events/tool/before.tsx:67-82— publishes withrecipient: { workspace: { root: conflict.worktreeRoot } }whilededupeKeystill names the target actor.examples/worktree-proximity/README.md:96-102: "Generated event principals in v1 mount host, session, and workspace identity, but not actor identity. Proximity notices therefore target the recipient worktree throughrecipient.workspace.root… Actor-directed delivery remains future work tied to actor-principal mounting in the Add recipient-aware notices and capability-gated delivery #99/Track remaining #98 state-kernel scope: warm-runtime process state, generated-runtime state mounting, budgets, lifetime visibility #233 lineage."README.md:77-81: tool envelopes carry noagent_id, so peers in one directory collapse to the derivedworktree:<root>identity — the workspace axis cannot separate two agents in one worktree.Proposed shape (small)
recipientMatchesPrincipaltreats an unavailablelineagelike an unavailable axis today (no match). Ledger schema gains two optional recipient fields — no state-definition id bump needed if the schema is additive (state.tsnotice schema). The next-event admission, inbox,resources/updated, and receipt discipline are unchanged;attemptedstays the strongest state, exactly as #99 records.Design question (from the same use-case): is a thin peer-messaging façade worth adding on top —
notices.send({ to: { conversation }, content })/notices.read()— or is the recipient axis enough and the façade stays app-level? The #99 survey already establishes that no pinned host offers a directed push channel, so the façade would only be sugar over publish + next-event admission.Out of scope / related
actorkeeps its current meaning.Acceptance
In
examples/worktree-proximity:tool/before.tsxpublishes withrecipient: { conversation: <other actor's lineage conversation> }; the route-unit test "attempts and surfaces a notice on the recipient next event" (tests/route-unit/routes.test.ts) passes with two actors bound to the same worktree (today impossible), and the cross-process journey suite (packages/agent-bundle/tests/worktree-proximity-journeys.test.ts) still proves workspace-directed delivery for the existing journeys. A new ledger test proves aconversation-addressed notice is not admitted on a sibling's event.