Skip to content

Session Store

Z-M-Huang edited this page Apr 27, 2026 · 3 revisions

Session Store

Session Store extensions are persistence backends. Each store writes session snapshots and reads them back on resume. Exactly one store is active per session; the store owns both write and read.

contractVersion: 1.0.0


Intent

A session contains the whole observable state — message history, tool calls, the manifest, every extension's state slot. Persisting it must survive crashes, power loss, and process restarts. The filesystem store ships bundled as the default; other stores plug in through this contract.

Session Stores are extensions because the right backend varies by environment: a laptop uses the filesystem; a team tool might use a database; a Claude-compatible mode might write into Claude's session format.


Contract shape

classDiagram
    class SessionStoreContract {
        kind : "SessionStore"
        contractVersion : SemVer
        requiredCoreVersion : SemVerRange
        configSchema : JSONSchema
        loadedCardinality : unlimited
        activeCardinality : one
        stateSlot : optional
        validationSeverity : critical-when-active
        discoveryRules : DiscoveryRules
        reloadBehavior : never
        capabilities : StoreCapabilities
    }
    class StoreCapabilities {
        journaling : bool
        snapshotBytesLimit : int
        largeSlotStreaming : bool
        concurrentReaders : bool
    }
    SessionStoreContract --> StoreCapabilities
Loading

Write and read in one contract

A Session Store owns both persistence directions:

  • Write — snapshot at turn boundaries, journal between turns if journaling: true, persist state slots.
  • Read — resume by session ID, reconstitute the manifest, deliver state slots to their owners with drift handling.

Splitting read and write across separate extensions is not supported. The store that wrote the session is the only store that can read it. See the Persistence and Recovery page.


Configuration schema

Every Session Store's configSchema must accept:

Field Meaning
enabled Whether this store is loadable.
active Whether this is the active store this session. Exactly one loaded store must have active: true.

Plus store-specific options (filesystem path, database URL, credentials reference).


Lifecycle

Phase Store responsibilities
init Validate config; open handles; verify the backend is reachable and writable.
activate If active: true, announce as the session's store and take over the persistence path.
deactivate Drain pending writes; close handles.
dispose Release resources. Idempotent.

A store that cannot complete init as the active store fails the session with a clear diagnostic. See Validation Pipeline.


Cardinality

Loaded: unlimited. Multiple stores may be loaded (e.g., filesystem + remote backup), but only one writes the session's canonical snapshots.

Active: one. Cross-store resume is not supported. If the session was written by store A, the session must resume against store A.

See Cardinality and Activation.


State slot

Optional. A store's own slot typically holds:

  • Bookkeeping index (per-slot revisions, summary of what has been written).
  • Last successful snapshot offset/pointer.

The store's slot is self-referential — the store reads and writes its own slot like any extension, but it is also the backend that persists every other extension's slot. The store writes its own slot first in a snapshot, then the rest.

See Extension State.


Validation severity

Critical when active. A failed active store fails the session at init; there is no fallback. A loaded-but-inactive store that fails is a warning.

Config cannot relax an active store to optional.


Discovery path

Session Stores live in a session-stores/ folder under each configuration scope layer:

Layer Location
Bundled Ships with the package (filesystem store is bundled).
Global ~/.stud/session-stores/…
Project <cwd>/.stud/session-stores/…

Ordering

Session Stores are unordered. Only one is active; there is no concept of order across stores.


Reload behavior

reloadBehavior: never. Switching the active Session Store mid-session would require migrating the session across backends, which is out of scope for v1.

Changing the active store requires a session end and a new session. This is documented and explicit.


Persistence guarantees

A conforming store provides:

  • Atomicity. A snapshot write is all-or-nothing. An interrupted write leaves the previous snapshot intact.
  • Consistency. A resume sees a consistent view of the session at the last successfully-acknowledged snapshot.
  • Isolation. Concurrent writes (if the backend allows them) do not interleave.
  • Durability. After acknowledgement, the snapshot survives crashes.

Different stores implement these differently. The filesystem store uses a journal-plus-snapshot pattern. Remote stores may rely on their backend's guarantees. The contract is durability; the mechanism is not.

See Persistence and Recovery.


Interaction with core

A Session Store reads and writes only through the Host API, plus the session persistence surface core exposes to the active store:

  • host.session.persistenceSurface — the interface core uses to hand over serialized snapshots, slot payloads, and to request reads on resume.
  • host.env.get(name) — credentials for remote stores (by reference).
  • host.audit — every write and resume is audited.

A store never:

  • Reads another extension's state slot directly; slots are handed to it as opaque payloads during snapshot.
  • Drives the Interaction Protocol outside of trusted-store-setup scenarios.

Security notes

  • Stores must never persist resolved secrets. Session manifests and state slots pass through the store as opaque blobs, but they never contain resolved secrets in the first place — the session manifest and Extension State forbid it. The store's duty is to not introduce secrets of its own (e.g., an access token) into what it persists.
  • Stores may be network-attached. A remote store reaches the network at every snapshot. Network failure classes are part of Error Model.
  • Resume is a trust event. Resuming a session trusts that the stored manifest matches what core expects. Drift handling (see Session Resume flow) is the safeguard.
  • Durability has a cost. A store with synchronous fsync per snapshot is safer but slower. Configuration exposes the tradeoff; defaults favor durability.

Related pages


Changelog

1.0.0 — initial

  • Session Store contract as documented above. Read + write in one contract; exactly one active; reloadBehavior: never.
  • Slim manifest shape: stores only message history, attached-SM state reference, security mode, and project root. No extension set, config hashes, or capability probes.
  • Resume launched via stud --continue. On resume, missing or failing extensions are silently absent; core resume (messages + conversation continuation) must never fail due to extension drift. SM backward compatibility is the SM author's responsibility.
  • storeId is stamped on each manifest so resume can verify the originating store before hydration begins. Cross-store resume yields Session/ResumeMismatch.
  • No validationSeverity field. A failed Session Store is disabled and surfaced at startup; resume with no available store ends with Session/StoreUnavailable.

Introduction

Reading

Core runtime

Contracts

Category contracts

Context

Security

Runtime behavior

Operations

Providers (bundled)

Integrations

Reference extensions

Tools

UI

Session Stores

Loggers

Providers

Hooks

Context Providers

Commands

Case studies

Flows

Maintainers

Clone this wiki locally