Expand description
Segment index (SPEC_DURABLE_CONVERSATION_MEMORY_2026_09_23.md §4.1, P1): one record per provider session an agent has run, so “this agent’s conversation” is a chain AgentMux owns rather than whatever session id a pane happens to hold.
Stored as an append-only event log, segments.jsonl in the global
transcript store’s agent-uid:<uid>:segments zone, not as a SQL table
(§4.1.1): that store is shared by every srv on the machine and takes
additions without a schema version bump, where a new table in
identity-store.db would bump its version and lock older builds out of
it (check_schema_compat). Events: start at spawn, session when a
fresh process reports its provider session id, end when the process
goes away. segments folds them back into one row per segment.
The zone is keyed by the agent’s UID (AGENTMUX_AGENT_UID), not its
definition id: a template launch shares the template’s transcript zone
but is a different agent. It is deliberately not the transcript zone, so
“New conversation” (which clears agent:<defId>:current) never erases the
chain; a new conversation is just a segment whose rung is fresh.
Structs§
- Gate
Input 🔒 - What the gate weighs about the spawn.
- Head 🔒
- Where the agent’s conversation was last: the newest segment that has a provider session, and what that segment recorded about it.
- Segment 🔒
- One segment, folded from its events.
- Start 🔒
- What is known about a segment when its process starts.
Enums§
- EndReason 🔒
- Why a segment’s process went away.
- Event 🔒
- Resume
Gate 🔒 - What the resume gate decided for a session a spawn is about to
--resume(SPEC_RESUME_GATE_AND_SAME_IDENTITY_CONTINUATION_2026_09_25.md §4.2). - Rung 🔒
- How a segment began (§4.2’s rungs;
relocatedarrives with P4).
Constants§
- SEGMENTS_
FILE 🔒 - TAIL_
WINDOW_ 🔒BYTES - Enough of the log’s end to find the newest segment for a predecessor link without reading an agent’s whole history.
Functions§
- append 🔒
- chain_
head 🔒 - Where the agent’s conversation was last, read from its chain in
fs.Nonewhen the UID has no chain. - events_
in 🔒 - exit_
reason 🔒 - fold 🔒
- fork_
from 🔒 ResumeGate::ForkFromwhen this agent has no chain and the agent it was forked from is at the candidate: a Claude session, under the spawn’s own identity (both known, I2), whose file holds a complete record where it was recorded.- fork_
source_ 🔒head - The chain head of the agent
agent_uidwas forked from (its definition has abranch_labeland aparent_id): what a fork with no conversation of its own starts from (ResumeGate::ForkFrom). Shared by the spawn’s gate and the pane’s resume preflight. - head_
session 🔒 - The provider session the agent’s conversation was last in: the session
of the newest segment, other than
current(the spawn now running or just failed), that has one.Nonewhen the agent has no such segment. - kill_
reason 🔒 - Why a killed process went away, from the controller’s state at the kill.
- newest_
segment_ 🔒id - The id of the agent’s newest segment, from the end of its log.
- record_
end_ 🔒with_ provider_ bytes - [
record_end], also recording the provider session file’s size then (spec §4.4), so a later spawn can tell whether something outside AgentMux wrote to it since. - record_
session 🔒 - record_
start 🔒 - Records a segment’s start and returns its id.
start.segment_idandstart.predecessor_segment_idare filled in here. - recovery_
allowed 🔒 - Whether a resume-failure recovery may continue
candidate(§4.2: only the head of the chain is this conversation). With a chain, any other session is older or unrelated history. It’s typically the same agent’s session from the last time it ran under this account, and resuming it would show “Resumed” on the wrong conversation, so the caller falls through to a fresh session carrying the continuation packet. With no known head (an agent from before the segment index, whose only segment is the current one), nothing better is known and recovery works as before. - relocation_
source 🔒 - The head’s config dir when §4.3’s metadata preconditions hold: a Claude session, under another config dir than the spawn’s, recorded under the spawn’s own identity (both known, I2), for the same project dir.
- resume_
gate 🔒 - Only the chain head is resumed natively (spec §3 I1), and never across
identities (I2).
input.headis the agent’schain_head;None(an agent from before the segment index, or no readable chain) allows the candidate, as before the gate existed. A head equal to the poisoned id allows too: that head is known dead, so the chain has nothing better to offer than the candidate. The identity check refuses only when both sides are known and differ. A head recorded under the spawn’s own config dir whose file isn’t there is refused too: the provider never wrote it. - rung_
for_ 🔒spawn - The rung a spawn started on, from what the spawn knows: whether it passed
--resume, and whether it carries a continuation packet. - same_
dir 🔒 - segments 🔒
- Every segment the agent has run, oldest first. A segment with no
endis running, or its srv died before it could record one. - with_
legacy_ 🔒identity - A head whose segment predates
identity_key(recorded by a build before #3839) takes the identity from its own config dir’s.claude.json, so an agent’s first upgrade from such a build can still relocate (spec §4.1). That file names whoever is signed in there now, which for an account’s own dir is the login the session ran under unless the dir was since re-logged-into as someone else; a recorded key always wins. Unreadable (the dir is gone) stays unknown, which never relocates. - zone_
for 🔒 agent-uid:<uid>:segments, orNonefor a UID outside the safe zone-name character set.