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
Part of #22 (Meridian reliability umbrella). P0 — the biggest single lever on prompt-cache churn.
Problem
Anthropic-protocol providers have exactly one session-identity channel: metadata.user_id, set only in packages/ai/src/providers/anthropic.ts (buildParams). The Meridian extension fills it from ctx.sessionManager.getSessionId() in before_provider_request. That identity is wrong or missing in four cases:
Inline RLM children stamp the parent's key._createInlineRlmSubagentRuntime (packages/coding-agent/src/core/agent-session.ts) constructs the child Agent with onPayload: this.agent.onPayload — the root closure from packages/coding-agent/src/core/sdk.ts bound to the rootextensionRunnerRef and therefore the root session manager. Every inline child request carries the parent's metadata.user_id. Parent + N children interleaving on one proxy session key means the incoming history never matches what the key last saw, forcing a full fresh-session replay (guaranteed prompt-cache miss, and Meridian's replay drops assistant tool_use blocks — Fresh replay drops every assistant tool_use block, so a thinking-plus-tool-call turn becomes an empty turn rynfar/meridian#888 — losing child task context). Daemon-mode children get their own runner and behave correctly; behavior diverging by mode is itself a bug.
Identity mutates mid-conversation.SessionManager.sessionId changes on fork/branch/load (session-manager.tsnewSession, createBranchedSession), so a continuing conversation shows up at the proxy under a new key with old history → lineage=new divergence mid-session (observed in telemetry: lineage=new session=new msgCount=48).
Side questions reuse the parent's key with a forked message array (packages/coding-agent/src/core/side-question.ts reuses parent.onPayload and parent.sessionId) → same key, divergent prefix → churn.
Compaction, branch summarization, and refinement are unkeyed.compaction/compaction.ts, compaction/branch-summarization.ts, and refinement/refinement.ts call completeSimple directly with no onPayload/metadata → they reach the proxy with no session identity at all.
Proposed shape
Add a first-class, immutable per-AgentSession identity (survives fork/branch/load; distinct per RLM child and per side question, e.g. <rootId>, <rootId>/child:<childId>, <rootId>/side:<n>), exposed on AgentOptions/AgentLoopConfig and to extension contexts, rather than deriving identity from the mutable SessionManager.sessionId.
Make inline RLM children run their payload hooks through the child's extension runner (pass a child-scoped extensionRunnerRef instead of copying the parent's onPayload/onResponse), converging inline and daemon behavior.
Thread identity/onPayload through the four unkeyed completeSimple call sites.
With the Meridian extension active: a parent with 3 concurrent inline RLM children produces 4 distinct stable metadata.user_id values, unchanged across a branch/fork operation, across every request each agent makes (including compaction and side questions carrying their owner's identity or a derived sub-identity — never a sibling's).
Focused tests at the seams: inline child runner scoping, identity stability across createBranchedSession, keyed completeSimple call sites.
Part of #22 (Meridian reliability umbrella). P0 — the biggest single lever on prompt-cache churn.
Problem
Anthropic-protocol providers have exactly one session-identity channel:
metadata.user_id, set only inpackages/ai/src/providers/anthropic.ts(buildParams). The Meridian extension fills it fromctx.sessionManager.getSessionId()inbefore_provider_request. That identity is wrong or missing in four cases:_createInlineRlmSubagentRuntime(packages/coding-agent/src/core/agent-session.ts) constructs the childAgentwithonPayload: this.agent.onPayload— the root closure frompackages/coding-agent/src/core/sdk.tsbound to the rootextensionRunnerRefand therefore the root session manager. Every inline child request carries the parent'smetadata.user_id. Parent + N children interleaving on one proxy session key means the incoming history never matches what the key last saw, forcing a full fresh-session replay (guaranteed prompt-cache miss, and Meridian's replay drops assistanttool_useblocks — Fresh replay drops every assistant tool_use block, so a thinking-plus-tool-call turn becomes an empty turn rynfar/meridian#888 — losing child task context). Daemon-mode children get their own runner and behave correctly; behavior diverging by mode is itself a bug.SessionManager.sessionIdchanges on fork/branch/load (session-manager.tsnewSession,createBranchedSession), so a continuing conversation shows up at the proxy under a new key with old history →lineage=newdivergence mid-session (observed in telemetry:lineage=new session=new msgCount=48).packages/coding-agent/src/core/side-question.tsreusesparent.onPayloadandparent.sessionId) → same key, divergent prefix → churn.compaction/compaction.ts,compaction/branch-summarization.ts, andrefinement/refinement.tscallcompleteSimpledirectly with noonPayload/metadata→ they reach the proxy with no session identity at all.Proposed shape
AgentSessionidentity (survives fork/branch/load; distinct per RLM child and per side question, e.g.<rootId>,<rootId>/child:<childId>,<rootId>/side:<n>), exposed onAgentOptions/AgentLoopConfigand to extension contexts, rather than deriving identity from the mutableSessionManager.sessionId.extensionRunnerRefinstead of copying the parent'sonPayload/onResponse), converging inline and daemon behavior.onPayloadthrough the four unkeyedcompleteSimplecall sites.metadata.user_idremains a JSON envelope; a parent linkage field (e.g.parent_session_id) enables proxy-side parent→child cancellation later (Meridian reliability: make concurrent RLM subagents production-safe over Claude Max #22 sequencing).Acceptance
metadata.user_idvalues, unchanged across a branch/fork operation, across every request each agent makes (including compaction and side questions carrying their owner's identity or a derived sub-identity — never a sibling's).createBranchedSession, keyedcompleteSimplecall sites.