DATA_HANDLING.md said there is no built-in retention expiry, but the daily
forget sweep tombstones cold episodic pages (below [decay] cold_threshold)
and hard-deletes them after hard_delete_after_days, and TTL (expires_at) pages
expire too — both on by default. Describe the actual [decay]/TTL behavior and
what stays (semantic/procedural/pinned, raw observations).
Closes#972
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MDbhmszrjG9s5MrPrTuNtm
OpenCode 2.0.10 replaced the lifecycle events the generated plugin listened
for (session.idle and friends) with session.execution.{succeeded,failed,
interrupted}, and it runs one long-lived service behind every CLI: closing a
terminal is not a session end, so sessions captured through the old binding
rarely produced a summary page or a baton. The plugin also re-ran two `git`
processes per event, lost startup context after the first model request,
dropped content-only tool results, and shared queue and spool state across
the per-location instances OpenCode 2 loads.
Plugin (install_hooks.rs, render_shared.rs, the node host fixture):
- binds session.execution.*, session.text.ended, session.moved,
session.deleted, session.compaction.started and the context/prompt/tool
hooks; every name was checked against the OpenCode 2.0.14 binary;
- claims startup context once per root session and re-injects it on every
model request; child sessions never claim it or publish a baton;
- keeps queue, spool and cleanup state per location instance; spool names
can no longer collide within a millisecond, and a torn-down host cancels
what is still in flight only after its final session-ends had the drain
budget (all generated TypeScript integrations share this runtime now);
- opt-in assistant capture (--capture-assistant) hands the last completed
text to the native hook, which sanitizes and caps it before the spool or
the wire, and falls back to the plain stop hook if that binary cannot run.
Server (router.rs, ops.rs, reader.rs, writer.rs):
- a completed root turn is a turn checkpoint: sessions/<id>.md and the
automatic baton are refreshed deterministically (no LLM) in the session
row's own scope, keeping one open baton per live session, refreshed in
place and audited; a checkpoint that lost the race with the session's end
touches nothing;
- an explicit, keyed session.moved rebinds the live session row to its new
directory on first delivery (compare-and-set on the cwd it left), so the
session's end and checkpoints follow it;
- a SessionEnd whose resolved scope drifted under the same cwd (a
.ai-memory.toml appeared mid-session) ends the session instead of
stranding it open; scope-drifted ordinary events are recorded as upstream
records any other drifted event;
- the latest captured assistant excerpt rides in the automatic baton; it is
not rendered into the git-tracked session page.
Docs: install.md, support-matrix.md, auto-scope.md, SECURITY.md and
DATA_HANDLING.md describe the checkpoint, routing and capture behavior.
Verified: cargo fmt --all -- --check; cargo clippy --workspace --all-targets
-- -D warnings; cargo test --workspace --all-targets (3569 passed, on release/2.5); the node
host fixture runs under cargo test (node >= 22.6) and fails if unload aborts
deliveries before its session-ends. Live on Windows 11 with OpenCode 2.0.14:
after a 64 -> 66 store migration, the running OpenCode service loaded the
regenerated plugin and one real turn through it (a Code Mode call to memory_status)
recorded its prompt, tool events and stop, logged "turn checkpoint written;
native session remains open", left the session open, wrote
sessions/<id>.md and exactly one open baton carrying the captured
assistant excerpt, which the session page does not contain.
Addresses review feedback on #744: the embedding-provider config was only
mentioned in a subordinate clause, which undersells it as the broadest
data-egress path (full text of every stored page, including a backfill of
the existing corpus when switching providers). Promote it to a numbered
item alongside assistant capture and reranking, matching the "LLM or
embedding provider" framing SECURITY.md/the processor-relationship section
already use.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Consolidates facts already documented in SECURITY.md, docs/install.md, and
docs/local-embeddings.md into the shape a security/legal reviewer typically
needs before approving a dev tool: a single data-flow page, an SSO/OIDC
summary, and an offline-install path. No behavior change. Adds a fallback
security-contact path for reporters who can't use GitHub's private-advisory
flow.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>