pub struct SessionState {Show 25 fields
pub id: String,
pub version: u32,
pub started_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub project_root: Option<String>,
pub shell_cwd: Option<String>,
pub task: Option<TaskInfo>,
pub findings: Vec<Finding>,
pub decisions: Vec<Decision>,
pub files_touched: Vec<FileTouched>,
pub test_results: Option<TestSnapshot>,
pub progress: Vec<ProgressEntry>,
pub next_steps: Vec<String>,
pub evidence: Vec<EvidenceRecord>,
pub intents: Vec<IntentRecord>,
pub active_structured_intent: Option<StructuredIntent>,
pub stats: SessionStats,
pub terse_mode: bool,
pub compression_level: String,
pub last_consolidate_ts: Option<DateTime<Utc>>,
pub last_aaak_hash: Option<String>,
pub extra_roots: Vec<String>,
pub wakeup_manifest: Vec<ManifestEntry>,
pub playbook: Playbook,
pub last_semantic_query: Option<String>,
/* private fields */
}Expand description
Persistent session state tracking task, findings, files, decisions, and stats.
Fields§
§id: String§version: u32§started_at: DateTime<Utc>§updated_at: DateTime<Utc>§project_root: Option<String>§shell_cwd: Option<String>§task: Option<TaskInfo>§findings: Vec<Finding>§decisions: Vec<Decision>§files_touched: Vec<FileTouched>§test_results: Option<TestSnapshot>§progress: Vec<ProgressEntry>§next_steps: Vec<String>§evidence: Vec<EvidenceRecord>§intents: Vec<IntentRecord>§active_structured_intent: Option<StructuredIntent>§stats: SessionStats§terse_mode: boolWhen true, resume / compaction prompts encourage concise model replies.
compression_level: StringUnified compression level label (off/lite/standard/max).
last_consolidate_ts: Option<DateTime<Utc>>Watermark: timestamp of last auto-consolidation to prevent duplicate knowledge entries.
last_aaak_hash: Option<String>§extra_roots: Vec<String>Extra project roots for multi-root workspaces.
Populated from config extra_roots and/or MCP roots/list.
wakeup_manifest: Vec<ManifestEntry>LITM placement manifest (#539): what the last wakeup injection placed where, so explicit re-recalls can be scored as placement misses.
playbook: PlaybookACE delta playbook (#541): incremental, stable-ID checkpoint entries — grown by ctx_compress, never rewritten (anti context-collapse).
last_semantic_query: Option<String>Last ctx_semantic_search query (#542): fallback query source for query-conditioned IB compression when no explicit task is set.
Implementations§
Source§impl SessionState
impl SessionState
Sourcepub fn format_compact(&self) -> String
pub fn format_compact(&self) -> String
Formats the session state as a compact multi-line summary for agent context.
Sourcepub fn build_compaction_snapshot(&self) -> String
pub fn build_compaction_snapshot(&self) -> String
Builds a size-limited XML snapshot of session state for context compaction.
Sourcepub fn save_compaction_snapshot(&self) -> Result<String, String>
pub fn save_compaction_snapshot(&self) -> Result<String, String>
Writes the compaction snapshot to disk and returns the snapshot string.
Sourcepub fn load_compaction_snapshot(session_id: &str) -> Option<String>
pub fn load_compaction_snapshot(session_id: &str) -> Option<String>
Loads a previously saved compaction snapshot by session ID.
Sourcepub fn load_latest_snapshot() -> Option<String>
pub fn load_latest_snapshot() -> Option<String>
Loads the most recently modified compaction snapshot from disk.
When a project root can be derived from CWD, only snapshots whose embedded session data matches the project root are considered. This prevents cross-project snapshot leakage.
Sourcepub fn build_resume_block(&self) -> String
pub fn build_resume_block(&self) -> String
Build a compact resume block for post-compaction injection. Max ~500 tokens. Includes task, decisions, files, and archive references.
Source§impl SessionState
impl SessionState
Sourcepub fn save(&mut self) -> Result<(), String>
pub fn save(&mut self) -> Result<(), String>
Serializes and writes the session state to disk synchronously.
Sourcepub fn prepare_save(&mut self) -> Result<PreparedSave, String>
pub fn prepare_save(&mut self) -> Result<PreparedSave, String>
Serialize session state while holding the lock (CPU-only), reset the
unsaved counter, and return a PreparedSave whose I/O can be deferred
to a background thread via write_to_disk().
Sourcepub fn load_latest() -> Option<Self>
pub fn load_latest() -> Option<Self>
Loads the most recent session matching the current working directory’s project root.
Returns None (a fresh session) rather than falling back to the global
latest.json pointer: that unconditional fallback bypassed project-root
matching and was the root cause of cross-project session leakage — one
project’s findings/decisions/knowledge bleeding into another project’s
first session. The correct project session is loaded later from the MCP
roots handshake (load_latest_for_project_root).
Also refuses to scope to a broad/unsafe cwd (e.g. the MCP daemon’s HOME), which would otherwise resurrect the contaminated “HOME mega-session”.
Sourcepub fn load_global_latest_pointer() -> Option<Self>
pub fn load_global_latest_pointer() -> Option<Self>
Loads the session referenced by the global latest.json pointer,
regardless of project. Intended only for explicit, cross-project UX
(e.g. lean-ctx session status from an arbitrary directory) — never for
injecting knowledge into a new project’s context. Prefer load_latest.
Sourcepub fn load_latest_for_project_root(project_root: &str) -> Option<Self>
pub fn load_latest_for_project_root(project_root: &str) -> Option<Self>
Loads the most recent session matching a specific project root.
Sourcepub fn load_by_id(id: &str) -> Option<Self>
pub fn load_by_id(id: &str) -> Option<Self>
Loads a specific session from disk by its unique ID.
Sourcepub fn delete_session(id: &str) -> Result<bool, String>
pub fn delete_session(id: &str) -> Result<bool, String>
Deletes a saved session and its compaction snapshot.
If the deleted session is the global latest pointer, the pointer is moved to the newest remaining session or removed when none remain.
Sourcepub fn list_sessions() -> Vec<SessionSummary>
pub fn list_sessions() -> Vec<SessionSummary>
Lists all saved sessions as summaries, sorted by most recently updated.
Sourcepub fn doctor_quarantine_unsafe_roots(
apply: bool,
) -> (Vec<(String, String)>, usize)
pub fn doctor_quarantine_unsafe_roots( apply: bool, ) -> (Vec<(String, String)>, usize)
Scans all saved sessions for contaminated ones — those rooted at a broad/unsafe path (HOME, filesystem root, agent sandbox dir) without a real project marker, i.e. the historic “HOME mega-session” artifact.
Returns (found, quarantined) where found is (id, root) pairs. When
apply is true, each offending session file is moved to a
sessions/quarantine/ subdirectory (non-destructive) instead of being
loaded into any project’s context.
Sourcepub fn cleanup_old_sessions(max_age_days: i64) -> u32
pub fn cleanup_old_sessions(max_age_days: i64) -> u32
Deletes sessions older than max_age_days, preserving the latest. Returns count removed.
Source§impl SessionState
impl SessionState
Sourcepub fn should_save(&self) -> bool
pub fn should_save(&self) -> bool
Returns true if enough changes have accumulated to warrant a disk
save — or, since #717, if any change has waited longer than
SESSION_FLUSH_INTERVAL: the 5-change batch alone left slow
sessions invisible to the dashboard (stuck “idle”) for the whole
batch window. A fresh in-memory session flushes its first change
immediately so new activity surfaces at once.
Sourcepub fn set_task(&mut self, description: &str, intent: Option<&str>)
pub fn set_task(&mut self, description: &str, intent: Option<&str>)
Sets the active task and infers a structured intent from the description.
Sourcepub fn auto_infer_task(&mut self)
pub fn auto_infer_task(&mut self)
Auto-infers the task from available context (plans, git diff, file patterns). Only sets if no explicit task is already set or it’s stale.
Sourcepub fn add_finding(
&mut self,
file: Option<&str>,
line: Option<u32>,
summary: &str,
)
pub fn add_finding( &mut self, file: Option<&str>, line: Option<u32>, summary: &str, )
Records a finding (discovery or observation) in the session log.
Sourcepub fn add_decision(&mut self, summary: &str, rationale: Option<&str>)
pub fn add_decision(&mut self, summary: &str, rationale: Option<&str>)
Records a design or implementation decision with optional rationale.
Sourcepub fn touch_file(
&mut self,
path: &str,
file_ref: Option<&str>,
mode: &str,
tokens: usize,
)
pub fn touch_file( &mut self, path: &str, file_ref: Option<&str>, mode: &str, tokens: usize, )
Records a file read/access in the session, incrementing its read count.
Sourcepub fn mark_modified(&mut self, path: &str)
pub fn mark_modified(&mut self, path: &str)
Marks a previously touched file as modified (written to).
Sourcepub fn set_file_summary(&mut self, path: &str, summary: &str)
pub fn set_file_summary(&mut self, path: &str, summary: &str)
Sets a one-line content summary for a touched file (max 80 chars).
Sourcepub fn record_tool_call(&mut self, tokens_saved: u64, tokens_input: u64)
pub fn record_tool_call(&mut self, tokens_saved: u64, tokens_input: u64)
Increments the tool call counter and accumulates token savings.
Sourcepub fn record_intent(&mut self, intent: IntentRecord)
pub fn record_intent(&mut self, intent: IntentRecord)
Records an inferred or explicit intent, coalescing consecutive duplicates.
Sourcepub fn record_tool_receipt(
&mut self,
tool: &str,
action: Option<&str>,
input_md5: &str,
output_md5: &str,
agent_id: Option<&str>,
client_name: Option<&str>,
)
pub fn record_tool_receipt( &mut self, tool: &str, action: Option<&str>, input_md5: &str, output_md5: &str, agent_id: Option<&str>, client_name: Option<&str>, )
Appends an auditable evidence record for a tool invocation.
Sourcepub fn record_manual_evidence(&mut self, key: &str, value: Option<&str>)
pub fn record_manual_evidence(&mut self, key: &str, value: Option<&str>)
Appends a manual (non-tool) evidence record to the audit log.
Sourcepub fn has_evidence_key(&self, key: &str) -> bool
pub fn has_evidence_key(&self, key: &str) -> bool
Returns true if an evidence record with the given key exists.
Sourcepub fn record_cache_hit(&mut self)
pub fn record_cache_hit(&mut self)
Increments the session-level cache hit counter.
Sourcepub fn record_command(&mut self)
pub fn record_command(&mut self)
Increments the session-level command counter.
Sourcepub fn effective_cwd(&self, explicit_cwd: Option<&str>) -> String
pub fn effective_cwd(&self, explicit_cwd: Option<&str>) -> String
Returns the effective working directory for shell commands. Priority: explicit cwd arg > session shell_cwd > project_root > process cwd. Explicit CWD and stored shell_cwd are jail-checked against the project root to prevent MCP clients from escaping the workspace.
Sourcepub fn effective_cwd_checked(
&self,
explicit_cwd: Option<&str>,
) -> (String, Option<String>)
pub fn effective_cwd_checked( &self, explicit_cwd: Option<&str>, ) -> (String, Option<String>)
Like Self::effective_cwd, but also reports why an explicit cwd
request was rejected by the project-root jail and silently replaced with
the project root (#629).
The jail itself is deliberate sandboxing (it stops MCP clients escaping
the workspace) and must stay — the only gap was that the substitution was
silent, so a caller running pwd && ls in what they think is dir A
actually ran in the project root with no indication why. Callers that
surface output to a human/agent (e.g. ctx_shell) use the returned
Option<String> reason to append a one-line hint instead of letting the
swap pass unnoticed; effective_cwd keeps the original lossless behaviour.
Sourcepub fn note_explicit_cwd(&mut self, cwd: &str)
pub fn note_explicit_cwd(&mut self, cwd: &str)
Persist an explicit, jail-accepted cwd argument as the live shell
cwd (#707). update_shell_cwd only tracks cd inside the command
text, but clients that switch checkouts mid-session (Claude Code
after EnterWorktree) pass the new directory as the cwd param of
every subsequent call — without persisting it, the worktree-divergence
detection in path resolution never sees the switch. Callers must pass
a cwd that already passed the project-root jail.
Sourcepub fn update_shell_cwd(&mut self, command: &str)
pub fn update_shell_cwd(&mut self, command: &str)
Updates shell_cwd by detecting cd in the command.
Handles: cd /abs/path, cd rel/path (relative to current cwd),
cd .., and chained commands like cd foo && ....
The new CWD is jail-checked against the project root.
Trait Implementations§
Source§impl Clone for SessionState
impl Clone for SessionState
Source§fn clone(&self) -> SessionState
fn clone(&self) -> SessionState
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for SessionState
impl Debug for SessionState
Source§impl Default for SessionState
impl Default for SessionState
Source§impl<'de> Deserialize<'de> for SessionState
impl<'de> Deserialize<'de> for SessionState
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 SessionState
impl RefUnwindSafe for SessionState
impl Send for SessionState
impl Sync for SessionState
impl Unpin for SessionState
impl UnsafeUnpin for SessionState
impl UnwindSafe for SessionState
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
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
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