pub struct CoderSessionEntry {Show 17 fields
pub session: Arc<Mutex<CoderSession>>,
pub events: Arc<Mutex<CoderEventBuffer>>,
pub cancel: CancelFlag,
pub preparation: RwLock<()>,
pub session_wall_secs: AtomicU64,
pub sink: Arc<EventSink>,
pub infra: SharedInfra,
pub generator: Arc<dyn TurnGenerator>,
pub routing_exclusions: Vec<String>,
pub memory: RepairMemory,
pub mcp_endpoint: Option<String>,
pub mcp_config_dir: Option<PathBuf>,
pub user_input: Arc<UserInputGate>,
pub attention: Arc<AttentionState>,
pub next_seq: Arc<AtomicU64>,
pub task: Mutex<Option<JoinHandle<()>>>,
pub fleet: Mutex<Option<Arc<FleetPool>>>,
}Expand description
One live session in the daemon’s registry.
Fields§
§session: Arc<Mutex<CoderSession>>§events: Arc<Mutex<CoderEventBuffer>>Replay buffer for coder.subscribe { from_seq } after reconnects.
cancel: CancelFlag§preparation: RwLock<()>Planning/baseline operations hold read guards. Cancellation drains them before declaring a pre-execution workspace safe to recover.
session_wall_secs: AtomicU64Effective wall ceiling for this live session. Zero means unbounded.
Set once when the confirmed run creates its shared SessionDeadline;
the liveness watchdog reads it without restarting or duplicating that
clock.
sink: Arc<EventSink>§infra: SharedInfraState, audit log, and runtime policies inherited from the client session that started this coder run. Foreman’s delivery gate consumes these exact handles; replacing them with fresh infra would silently discard policy.register rules and write verdicts outside the session journal.
generator: Arc<dyn TurnGenerator>The model seam the loops run on (production: the shared
InferenceEngine; tests: a script).
routing_exclusions: Vec<String>Models the adaptive native loop must not use. Empty for ordinary coder sessions; self-heal fills it with canonical review-panel model names.
memory: RepairMemoryDurable repair learning for the native loop. Cloned from the embedder’s
shared_memgine; a no-op store when the daemon runs standalone.
mcp_endpoint: Option<String>The daemon’s MCP URL (e.g. "http://127.0.0.1:9102/mcp"), captured at
session start from ServerState::mcp_url. Threaded into the external
and foreman delegation engines so the CLI’s CAR-namespace tool calls
(memory_*, verify, skill_*) route back through the daemon’s policy
- memgine — gated and audited.
Nonewhen the daemon has no MCP listener (--mcp-bind disabled); delegation degrades to ungoverned CAR-namespace calls (the CLI’s own built-in tools are ungoverned either way — the residual upstream stage-4b limitation).
mcp_config_dir: Option<PathBuf>Where the claude-code adapter writes its short-lived MCP config file
(car#1534). None keeps the adapter’s original behaviour, a bare
tempfile() under $TMPDIR.
The daemon sets it to <coder state dir>/mcp so the one file every
normal external session writes stops depending on an environment
variable the daemon inherited and never checked: a daemon launched with
an installer-sandbox TMPDIR could not create it, and the session
silently ran the native engine instead (the drill trigger behind
car#1534; car#1518 fixed only the CarHost launch path).
user_input: Arc<UserInputGate>Mid-session user-input rendezvous: the native loop parks a oneshot here
when it asks a question (via the ask_user tool); coder.respond
fulfills it. Cancellation clears it so a waiting question unblocks.
attention: Arc<AttentionState>Operator-attention signals folded from the event stream (outstanding sign-in, budget cut). Shared with the drain task, which is the single funnel every event passes through.
next_seq: Arc<AtomicU64>The sequence after the newest event the drain has appended — the
coder.subscribe resume cursor, readable WITHOUT taking the buffer lock.
That matters: the drain holds the buffer lock across an untimed WS send,
so one SIGSTOPped subscriber parks it indefinitely. A summary that read
events.lock().await.len() would block behind that subscriber, and
(before this was split out) it did so while coder.list held the global
coder_sessions registry — wedging every other coder.* call
daemon-wide. Bumped by the drain immediately AFTER the push, so it is
never AHEAD of the buffer: a cursor that lags replays an event, a cursor
that leads drops one.
task: Mutex<Option<JoinHandle<()>>>The running loop task, present from confirm until terminal.
fleet: Mutex<Option<Arc<FleetPool>>>The distributed run’s worker pool, present from the moment
run_session_loop builds one until whoever drains it takes it.
Here rather than only on the loop’s stack because coder.cancel aborts
the task at its next await — so the loop never reaches the block that
folds pool.placements() onto the session, the Arc drops, and the
answer to “which machines was this farmed to?” is gone. That is exactly
the run an operator wants a receipt for: they cancelled it because it
looked wrong (car#1346).
Option and taken, not held, so the ordinary paths return the pool at
the moment they always did — the loop’s fold and coder.cancel each
take it. Not every path: the two early returns above the foreman rung
and a panic inside the loop task leave the slot populated, and the entry
carries it until prune_finished_sessions collects the session. That
is bounded for the early returns (both reach a terminal state, so the
prune does collect) and unbounded on panic — where the entry and its
replay buffer already leaked. A RemoteWorktreeAgent is names, a repo
fingerprint and an Arc<PeerIdentity>; it holds no socket and no task,
which is what makes that acceptable rather than merely tolerated.
Auto Trait Implementations§
impl !Freeze for CoderSessionEntry
impl !RefUnwindSafe for CoderSessionEntry
impl !UnwindSafe for CoderSessionEntry
impl Send for CoderSessionEntry
impl Sync for CoderSessionEntry
impl Unpin for CoderSessionEntry
impl UnsafeUnpin for CoderSessionEntry
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
impl<S, T> Duplex<S> for Twhere
T: FromSample<S> + ToSample<S>,
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more