Expand description
Where basis’s conversations are persisted, and how they are scoped.
mentra persists every agent to its runtime store — since basis 0.7 the
file-backed one, plain files under one root, no database (ADR-0023;
upstream mentra#28) — and tags each record with a runtime
identifier. basis uses that tag to answer one question: which
conversations belong to this workspace? — which is what ACP’s
session/list asks and the only reading of “my sessions” that is both
honest and useful, since ACP scopes a session to a cwd from the moment
session/new opens it.
§Why the workspace path, verbatim
mentra’s default identifier is the literal string "default", and its
default store is one shared root. Listing under "default" would
therefore enumerate the agents of every mentra program on the machine —
worse than returning nothing, because a client would offer a user
conversations that are not theirs.
The identifier is the canonicalized workspace path with a basis: prefix. No
hash: the identifier never becomes a filename — mentra keeps it as a field
of each agent’s agent.json and filters listings by comparing it — so
every character survives, and a readable value is one a person debugging
the store can understand by opening the file. The prefix keeps basis’s
records from ever colliding with another program’s "default".
Changing the identifier does not move the store — mentra’s default path is
independent of it — so nothing already written is lost. Records created
before this scheme carry "default" and do not appear in any workspace’s
list, which is the correct answer for a conversation whose workspace was
never recorded. They are not stranded either: mentra loads an agent by id
alone, so resuming one still works, and it re-tags itself the next time it
persists. WorkspaceBuilder::open is where
the tag is set, and where that ruling is written down.
One caveat since ADR-0018: mentra fixes the tag per runtime at build
time, so only a workspace on its own private runtime — every
Workspace::open(path), the CLI, the free functions — tags rows with its
path. A workspace on a shared Runtime mints rows
tagged "basis:runtime" until mentra grows a per-session override; those
rows stay out of every per-workspace list (the "default" ruling above,
applied again) and re-file themselves the first time they persist under a
runtime that knows their workspace. Runtime’s mint is
the one line that changes when the override lands.
§Where the files go
mentra’s default directory is keyed by the process’s current directory,
not by the workspace basis opened, so every program started from one place
shares one store root whatever workspace it went on to open — including
every test binary in one cargo test.
RuntimeBuilder::with_store_dir
is how a caller says otherwise, and list_in is how the same caller reads
back what it wrote. The directory the caller names is the store’s root
— mentra lays agents/, rules.json and runs.jsonl inside it — and the
root is bound to the store in exactly one place, store_in, because two
places would eventually disagree and a conversation written under one root
and looked for under another is simply missing.
§When the directory holds a database instead
basis 0.6 and earlier kept conversations in runtime.sqlite under the
same directory. This build links no SQLite and does not migrate
(ADR-0023’s E2 precedent): opening, listing or deleting against a
directory that holds one is refused with RunError::LegacyStore, which
names the two ways forward, rather than starting an empty file store
beside data it cannot see — the refusal is refuse_legacy_store, and
every path that opens a store the caller pointed somewhere runs it.
§When there is no file
RuntimeBuilder::with_ephemeral_history
answers where with nowhere, and opens mentra’s in-memory store instead.
Nothing in this module can see one of those conversations: there is no file
for list_in to read and no row for list to filter, whichever
directory either is pointed at. One file still gets written even then — a
compaction snapshot, which mentra persists without consulting the store —
and it goes to a per-runtime directory under the OS temp directory, which
is as close to nowhere as that file gets. Everything else below is about
the durable case.
Structs§
- Persisted
Session - A conversation mentra has on disk, as basis reports it.
Functions§
- default_
directory - The directory mentra keeps basis’s conversations in, for a caller that wants to say where the history lives.
- forget
- Removes a conversation from the default directory’s store for good.
- forget_
in - The same, for conversations kept somewhere of the caller’s choosing.
- list
- Every conversation persisted for
workspace, most recently used first. - list_in
- The same, for conversations kept somewhere of the caller’s choosing.
- runtime_
identifier - The runtime identifier for conversations in
workspace.