pub struct CoderSession {Show 37 fields
pub id: String,
pub repo: PathBuf,
pub intent: String,
pub engine: EngineChoice,
pub state: CoderState,
pub contract: Option<OutcomeContract>,
pub workspace_path: Option<PathBuf>,
pub project: Option<String>,
pub project_kind: Option<ProjectKind>,
pub built_agent: Option<DeclarativeAgentSpec>,
pub agent_build_progress: Option<AgentBuildProgress>,
pub iterations: u32,
pub max_iterations: u32,
pub cost_usd: Option<f64>,
pub repair_invokes: Option<u32>,
pub transient_retries: Option<u32>,
pub keep_workspace_on_failure: bool,
pub model: Option<String>,
pub last_check_results: Vec<CheckResult>,
pub baseline: Vec<CheckResult>,
pub baseline_gates_nothing: bool,
pub result_branch: Option<String>,
pub failure_kind: Option<String>,
pub discussion_id: Option<String>,
pub browser: bool,
pub distributed: bool,
pub workers: Vec<String>,
pub pool_workers: Vec<String>,
pub placements: Vec<Placement>,
pub integrated_subtasks: Vec<IntegratedSubtask>,
pub repaired_locally: bool,
pub authored_by: Vec<String>,
pub created_at: u64,
pub updated_at: u64,
pub error: Option<String>,
pub workspace: Option<AgentWorkspace>,
pub state_dir: Option<PathBuf>,
}Expand description
A coding session. Serializes to the JSON snapshot persisted on every
transition; the live worktree handle is process-only (#[serde(skip)]).
Fields§
§id: String§repo: PathBufThe user’s repository root (never written to directly).
intent: String§engine: EngineChoice§state: CoderState§contract: Option<OutcomeContract>§workspace_path: Option<PathBuf>Where the throwaway worktree lives (kept in the snapshot so orphaned sessions after a daemon restart can still report it).
project: Option<String>When this session works on a CAR-managed project (vs. a raw repo path),
the project slug + kind. Drives delivery (commit straight to the
project’s main instead of publishing a car/coder/<id> branch) and,
for Agent projects, the scenario-based contract + agent registration
on approve. None = raw-repo session (the original behavior).
project_kind: Option<ProjectKind>§built_agent: Option<DeclarativeAgentSpec>For an Agent project: the declarative agent spec the build loop
produced, stashed so approve_merge can register it. Persisted so
coder.get can show what was built.
agent_build_progress: Option<AgentBuildProgress>Present only for Agent-project builds. Additive on coder.get; older
hosts ignore it and older snapshots deserialize with None.
iterations: u32§max_iterations: u32§cost_usd: Option<f64>Metered inference spend, when anything reported it. None is
unknown, not free — the native loop does not meter.
repair_invokes: Option<u32>Per-session external-engine hypothesis budget. None = engine default.
transient_retries: Option<u32>Per-session external-engine availability budget. None = engine default.
keep_workspace_on_failure: boolWhen a session ends Failed, keep the throwaway worktree on disk (and
its handle in-process) so the operator can inspect it for a postmortem
instead of having it reaped on the terminal transition. Sourced from
~/.car/coder.toml (keep_workspace_on_failure); default false.
model: Option<String>Pin the native loop’s inference model (e.g. "parslee/reasoning").
None = adaptive routing. Sourced from ~/.car/coder.toml (model).
last_check_results: Vec<CheckResult>§baseline: Vec<CheckResult>The contract’s red-green baseline — how each check fared against the
unmodified worktree (car#707). Stored rather than recomputed because
it is part of how the current draft READS: a board renders the contract
with its baseline beside it, so a coder.revise_contract that could not
be honored has to hand back both, or the contract it swore was unchanged
visibly changes anyway when the baseline blanks out.
baseline_gates_nothing: boolWhether every baseline check already passed — i.e. the contract gates
nothing for this task. Travels with baseline for the same reason.
result_branch: Option<String>§failure_kind: Option<String>Why a failed session failed, as a machine-readable kind:
"budget_exhausted" | "auth_required" | "configuration" |
"infrastructure" | "error". Persisted so a summary read from disk
after a daemon restart still distinguishes “ran out of clock” from
“nobody signed in” from “routing excludes every model” from “the
machinery broke” from “the work was judged and rejected” — a live-only
derivation would go blank exactly when the operator comes back to look.
"infrastructure" is the one a scorer must act on: nothing was judged,
so the session is not a task loss. See rpc::failure_kind_for for how it
is chosen and why it is not folded into "error".
discussion_id: Option<String>The coder.discuss conversation this run was distilled from, when the
operator went through a discussion. Provenance only — the run itself is
independent of the discussion’s lifetime.
browser: boolWhether this session explicitly opted into the assistant’s browser tool surface. False by default and persisted so contract review cannot change which tools the later confirmed run receives.
distributed: boolFarm subtasks across reachable CAR instances rather than this machine
alone. Only the foreman engine reads it.
Persisted, and reported on the coder.list row, so a finished run can
say which way it ran. That is the whole reason — a session does NOT
resume across a daemon restart (adopt_orphaned_sessions rewrites every
non-terminal orphan to Failed), so this is not protecting a resumed
run from silently becoming local.
workers: Vec<String>Instances a distributed run is restricted to. Empty = every instance that can serve the repository.
The operator’s FILTER, not the resolved pool — see Self::pool_workers
for what the run actually got.
pool_workers: Vec<String>The peers the pool actually resolved to, recorded when it is built.
workers above is what the operator asked to restrict to; this is what
answering that restriction against reachability, enrollment and repo
eligibility produced. It was emitted as a foreman: "pool" event and
then dropped, so a subscriber that was not attached saw nothing and the
snapshot carried no record at all.
Written BEFORE any subtask runs, which is what makes it the durable
answer to “which machines was this farmed to?”. Self::placements
cannot answer it on its own: a placement is recorded when a worker
RETURNS, and foreman runs a level under join_all rather than spawning,
so coder.cancel’s abort drops every in-flight future before it records
— the subtasks running at the moment an operator gives up are exactly
the ones the ledger omits (car#1346). Empty on a local run.
placements: Vec<Placement>Where each of a distributed run’s subtasks actually ran, including the workers that failed it first.
Empty for a local run, and for a distributed one that fell off the foreman rung before farming anything out.
Not a proxy for “a distributed run completed.” A cancelled run
carries this populated with Self::integrated_subtasks empty, and so
does a run whose foreman union the gate rejected — three different
states, separated by state and by nothing else. And it is a floor, not
a census: subtasks still in flight at a cancel never reach it, which is
what Self::pool_workers is for.
foreman.run has reported this all along; the pipeline that DELIVERS had
strictly less provenance than the one that only reports, because
fleet_pool_for erased FleetPool to Arc<dyn WorktreeAgent> and
placements() is on the concrete type (car#1322). CAR’s position is that
receipts decide completion, and a delivered commit whose hunks were
authored on unnamed machines is the wrong artifact for that claim — the
question arrives the first time a distributed run produces something
surprising.
integrated_subtasks: Vec<IntegratedSubtask>Which of those subtasks actually LANDED in the worktree, and what each wrote. The diagnostic record above says what happened; this says what is in the tree, and only this may back a claim in the delivered commit.
repaired_locally: boolForeman’s union was integrated and then the native loop repaired on top of it, so some delivered hunks were written locally by no listed worker.
Without this the commit body would credit the fleet for a diff it only partly wrote — the same false attribution as crediting it for one it did not write at all, in a milder form.
Every model that AUTHORED part of this session’s work, as opposed to
Self::model, which is the pin the caller asked for.
They differ exactly when it matters: unpinned, the router chooses, and on a machine with one reachable credential that choice can also be a review-panel seat — the self-review the gate refuses when a coder is pinned, permitted by default because nothing knew who wrote the change (car#1299).
A projection of the journal (EventSink::authoring_models), not a
second record of the same fact — two records can disagree and then the
question is which one the gate believes. Empty for a session with no
native turns (foreman/external), which is the DEFAULT engine: read it as
“CAR’s own loop did not write this”, not “nobody did”.
created_at: u64§updated_at: u64§error: Option<String>§workspace: Option<AgentWorkspace>RAII worktree handle. Dropping it removes the worktree, so terminal transitions release it explicitly.
state_dir: Option<PathBuf>Where snapshots/journals/worktrees go; None disables persistence.
Implementations§
Source§impl CoderSession
impl CoderSession
pub fn new( repo: impl Into<PathBuf>, intent: impl Into<String>, engine: EngineChoice, max_iterations: u32, state_dir: Option<PathBuf>, ) -> Self
Sourcepub fn with_project(self, slug: impl Into<String>, kind: ProjectKind) -> Self
pub fn with_project(self, slug: impl Into<String>, kind: ProjectKind) -> Self
Mark this session as working on a managed project (builder so existing call sites and tests stay green).
Sourcepub fn provision_workspace(&mut self) -> Result<PathBuf, String>
pub fn provision_workspace(&mut self) -> Result<PathBuf, String>
Provision the throwaway git worktree under the state dir (NOT inside
the user’s repo, so their git status stays clean).
Sourcepub fn transition(
&mut self,
to: CoderState,
sink: &EventSink,
) -> Result<(), String>
pub fn transition( &mut self, to: CoderState, sink: &EventSink, ) -> Result<(), String>
Validated state transition: updates timestamps, emits StateChanged,
persists the snapshot, and releases the worktree on terminal states.
Sourcepub fn persist(&self) -> Result<(), String>
pub fn persist(&self) -> Result<(), String>
Write the JSON snapshot to <state_dir>/<id>.json (no-op without a
state dir, e.g. in unit tests).
Sourcepub fn load(path: &Path) -> Result<Self, String>
pub fn load(path: &Path) -> Result<Self, String>
Load a snapshot from disk. The worktree handle is NOT restored — a loaded session is read-only history unless re-provisioned.
Sourcepub fn list(state_dir: &Path) -> Vec<CoderSession>
pub fn list(state_dir: &Path) -> Vec<CoderSession>
All persisted sessions under state_dir, newest first.
Trait Implementations§
Source§impl Debug for CoderSession
impl Debug for CoderSession
Source§impl<'de> Deserialize<'de> for CoderSession
impl<'de> Deserialize<'de> for CoderSession
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for CoderSession
impl RefUnwindSafe for CoderSession
impl Send for CoderSession
impl Sync for CoderSession
impl Unpin for CoderSession
impl UnsafeUnpin for CoderSession
impl UnwindSafe for CoderSession
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<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
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