# Operator-scoped durable memory for the Eve drawer (EVE_EVERYWHERE 4.1–4.4)

The admin Operations Copilot pins `Memory: Session only` (gap G3 of
`EVE_EVERYWHERE_TODOS_2026-08-19.md`): an operator's standing context — what
initiative they are driving, how they like queues summarized, which workspaces
they watch — evaporates with every session. This proposal is the SMALL design:
one durable slice, reusing the member plane's scope/disclosure vocabulary. This
document began with explicit enablement required on 2026-08-20; the operator
default was explicitly flipped ON on 2026-08-23. The current default-on serving
contract is recorded under **Production default ON** below.

## What persists (three categories, nothing else)

1. **preferences** — presentation choices ("lead with sev0", "skip the
   copilot-health preamble"), each a short labeled sentence.
2. **standing-initiative** — the one line naming what the operator is driving
   right now ("EVE_EVERYWHERE Phase 5, content round-trip"), replaced, never
   appended.
3. **pinned-contexts** — up to 8 refs the operator pinned (a work item id, an
   incident id, a workspace id) with a label; refs are IDs into stores the
   drawer can already read, so recall can always be re-grounded live.

**Deliberately NOT stored:** member data of any kind (no member ids, no member
content — the store validator REFUSES values matching member-id shapes);
transcripts; tool results; anything the repo already records. Operator memory is
ABOUT the operator's working posture, never about members.

## Where and how

- A Postgres table `assistant_operator_memory` (composite primary key: operator
  sub, category, slot) holds the current revision, immutable memory id, source
  reference, confirmation and reauthorization provenance, salience, expiry,
  update time, and last prompt-use time. `assistant_operator_memory_history`
  holds superseded revisions and their successor pointer. It is never a recall
  source. Exact forget, forget-all, and operator-subject erasure delete both the
  current bytes and matching lineage.
- The BFF lazily bootstraps both tables and additive columns, validates writes
  and loaded rows, and fails loud on persistence errors. A transient bootstrap
  failure is retryable, and the Fastify shutdown hook closes/resets the lazy
  pool. Inspection never advances `last_used_at`; only active rows selected at
  the prompt-recall boundary do, so visible last use remains semantically
  honest. The privacy snapshot obtains the same per-category advisory locks as
  writers before reading current and historical rows, preventing a split view
  during correction.
- **Scope vocabulary is REUSED, not invented**: the session store already
  carries `MEMORY_SCOPES = {off, session, profile}` with `consentGranted` and
  `enabledCategories`. An admin-scoped session with the slice served reports
  scope `profile`; everything else reports `session`. The operator slice does
  not repurpose the member-plane Iris consent state.
- Historical launch posture (2026-08-20): `OSHUN_ASSISTANT_OPERATOR_MEMORY=1`
  was initially required. Superseded by the recorded 2026-08-23 decision below:
  absent now means ON when a database URL is bound, and `0`/`off` is the
  rollback switch.
- Prompt placement: a `memory` part in the DYNAMIC prompt section (never the
  stable prefix — cache order, SMX P1.1), rendered only when non-empty. Recall
  selects at most 8 active rows by salience then recency, and rendering is also
  capped at 4,096 characters.

## Transparency (the member plane's own patterns, mirrored)

- The drawer chip reads the honest scope: `Memory: Session only` ↔
  `Memory: Operator profile` (never a euphemism).
- A successful recalled reply carries `Recalled: N operator notes` directly
  under that reply. If the agent fails after reading memory, a system line still
  names the read and states that it did not ground the deterministic fallback.
- Writes ride the confirm bridge: "remember that I lead with sev0" parks a card
  like any other mutation — nothing is remembered silently. The outcome is
  rendered from the server result (including zero-row forgets), not inferred
  from the proposed card summary.
- Confirmed remembers and forgets are recorded in the canonical admin audit feed
  without duplicating the note text into its payload.
- Opt-out deletes rows (`DELETE`, not a hidden flag), reports the exact deleted
  count, and rejects ambiguous shapes such as a slot without a category. The
  direct privacy route additionally rejects category-only deletion: one-row
  deletion requires both category and slot, while forget-all requires neither.
- A collapsed `Memory` disclosure in the admin drawer lists the operator's own
  exact current rows, original source reference, confirmation time, current
  revision and predecessor pointer, update/use times, latest reauthorization,
  salience, expiry, and active/expired state. A nested collapsed section exposes
  the exact superseded values and successor pointers retained for correction
  lineage. It names profile scope, category retention, category and prompt
  ceilings, and the erasure location.
- From that surface the operator can correct a value, explicitly reauthorize a
  time-bound source without fabricating a content revision, confirm deletion of
  one exact row and its lineage, or separately confirm deletion of every current
  and superseded row. The BFF derives the subject from verified auth; no
  client-supplied subject is accepted, and route-level database coverage proves
  an adjacent operator's current and historical rows are neither exposed nor
  deleted.

## Provenance, supersession, dedupe, and recall policy (Task 9.4)

- Every new note receives a stable `memory_id`, revision 1, an original source
  reference, and a matching reauthorization record. A correction archives the
  complete prior row, keeps the stable memory id, increments the revision, and
  points both sides of the transition at the predecessor/successor revision.
  Superseded rows never participate in recall.
- Canonically identical content (Unicode whitespace collapsed, trimmed, and
  case-folded) cannot occupy two slots in the same category. Confirming the same
  content in the same lineage is a reauthorization, not a new revision.
- Fixed category policy is server-owned: standing initiative has salience 100
  and expires after 30 days; pinned context has salience 80 and expires after 14
  days; preferences have salience 50 and remain until forgotten. Expired rows
  stay visible for inspection but are excluded before prompt assembly. Explicit
  source reauthorization renews expiry, clears last use, records a new
  reauthorization reference, and does not alter content provenance or revision.
- The rendered block labels every note fallible and establishes strict
  precedence: security/system policy, authoritative state from authorized live
  tools, and the operator's live instruction override memory. Preferences are
  presentation guidance only. Pinned references must be re-grounded through
  authorized live tools before making current-state claims; stale, conflicting,
  or inapplicable notes are ignored.

## Non-goals

Cross-operator sharing; memory-derived automation; any model-authored
summarization of memory (slots hold what the OPERATOR confirmed, verbatim);
member-plane changes of any kind.

## Production default ON (user decision 2026-08-23, EVE_EVERYWHERE 4.5)

The code default flipped from off to ON for operators; the flag is now the kill
switch. Written down before the flip, per the decision:

- **What is stored.** Three categories only — `preferences` (≤12 slots),
  `standing-initiative` (1 slot), `pinned-contexts` (≤8 slots); values ≤280
  characters, slots ≤64. Every value is what the operator CONFIRMED on a card,
  verbatim; nothing is summarised or inferred. Member-data shapes (member ids,
  email addresses) are refused at write time — the slice is about the operator,
  never about members.
- **Where.** Table `assistant_operator_memory` in the admin database
  (`OSHUN_ADMIN_DATABASE_URL ?? OSHUN_V1_DATABASE_URL`), keyed by the operator's
  subject. No database URL ⇒ the slice is simply not served (the drawer chip
  shows "Session only"); it never throws on an operator turn.
- **Who sees it.** Only sessions of the SAME operator subject read it back, as a
  dynamic prompt part with an on-screen "Recalled: N operator notes" disclosure
  (4.3) — never another operator, never a member, never the stable prefix. Every
  read is turn-visible; every write and forget is card-gated and lands in the
  admin audit feed.
- **Retention.** Preferences remain until forgotten. Standing initiatives expire
  from recall after 30 days and pinned contexts after 14 days unless the
  operator explicitly reauthorizes their source. Expired values remain visible
  for correction, renewal, or deletion. Per-slot forget, forget-all, and
  operator-subject erasure delete both current and superseded revisions.
- **Concurrency.** Writers serialize per operator/category inside a Postgres
  transaction. Ceiling checks and inserts are one critical section, and the
  standing-initiative replacement is atomic; concurrent requests cannot exceed
  12/8 slots or leave multiple standing initiatives. Privacy inspection takes
  the same locks before reading current and historical rows.
- **Rollback.** `OSHUN_ASSISTANT_OPERATOR_MEMORY=0` on the deployable turns it
  off for every operator at once without a deploy.
