Skip to content

Commit 35edc84

Browse files
committed
docs(memory): §12 memory from you and Search Sessions — how it decides, how Claude's app does it, what differs
levelcode-sessions-memory.md §12: the remember/forget tools and the crediting rule, how notes live beside facts, MEMORY.md's "From you" section with ages and caps, Search Sessions as a quick pick and why, how Claude's desktop app and its Claude Code handle memory and history (read from the shipped bundles on 2026-10-19), the differences on purpose (and why per-request memory selection was left out: memory rides the cached system prompt), what was run and what was not. Settings table: sessions.memory.notes. levelcode-sessions-experience.md §4.4: a note that the in-panel search was removed (77d4f13) and came back as the Search Sessions quick pick.
1 parent e03f1da commit 35edc84

2 files changed

Lines changed: 95 additions & 1 deletion

File tree

‎docs/levelcode-sessions-experience.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,11 @@ It expands (`--mo-base`) into a third zone, so nothing is lost, only deferred to
183183

184184
### 4.4 Search & filter (in the panel)
185185

186+
> **As built:** the search field was taken out of the panel on 2026-08-02 (77d4f13), when History became a
187+
> list of the 30 most recent sessions. Search came back as **LevelCode: AI: Search Sessions…**, a quick pick
188+
> over every session's title and conversation — see `levelcode-sessions-memory.md` §12. The design below is
189+
> the original plan.
190+
186191
- **One field, three indexes:** title (weighted highest), files-edited, commands-run. Match highlights show *why* a session matched ("matched `refund.rb`").
187192
- **Scope switch:** `This project` (default) ↔ `All projects` — because sometimes you remember the work, not the repo.
188193
- **Filter chips** (toggle, combine): `★ pinned`, `⟳ has edits`, `⚠ interrupted`, `by model ▾`, `date ▾`. Chips animate in/out and the list reflows at `--mo-base`. Active filters are summarized in the empty-result state ("No interrupted sessions in the last 7 days — clear filters?").

‎docs/levelcode-sessions-memory.md‎

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# LevelCode Sessions — Project Memory & Continuity
22

3-
**Status:** **shipped** — M1–M4 complete (§10) · **Scope:** `extensions/levelcode-ai` + the sessions store · **Third of the triad:** [`levelcode-chat-sessions-design.md`](./levelcode-chat-sessions-design.md) stores a chat · [`levelcode-sessions-experience.md`](./levelcode-sessions-experience.md) lets you browse it · **this doc lets the project *remember itself*.**
3+
**Status:** **shipped** — M1–M4 complete (§10); M5, memory from you, in review (§12) · **Scope:** `extensions/levelcode-ai` + the sessions store · **Third of the triad:** [`levelcode-chat-sessions-design.md`](./levelcode-chat-sessions-design.md) stores a chat · [`levelcode-sessions-experience.md`](./levelcode-sessions-experience.md) lets you browse it · **this doc lets the project *remember itself*.**
44

55
> The wish, in the user's words: *"if in one session we tidy the CHANGELOG for v1.0.4, then a new session already knows something about what was achieved — the past experience keeps growing, and it feels like home."* That is the right ambition. It is also the feature most likely to become expensive, stale, creepy, or wrong. This document is mostly about **not** doing those four things while still delivering the magic.
66
@@ -156,6 +156,7 @@ The magic, delivered quietly (never a wall of text):
156156
| `sessions.memory.journalRecentDays` | `21` | recency window fed to the always-on digest |
157157
| `sessions.memory.confirmFacts` | `false` | require a click before an inferred Fact becomes confirmed |
158158
| `sessions.memory.recallTool` | `true` | expose `recall_sessions` to the agent |
159+
| `sessions.memory.notes` | `true` | expose `remember` / `forget` to the agent (§12) |
159160

160161
---
161162

@@ -189,4 +190,92 @@ The magic, delivered quietly (never a wall of text):
189190

190191
---
191192

193+
## 12. Memory from you (M5) — and Search Sessions
194+
195+
Everything in §3–§10 is memory LevelCode *infers*: the summarizer reads a finished session and writes an
196+
outcome and at most two facts. Nothing records what the person *says* they want kept, and the most valuable
197+
kind of memory, a correction ("no, use pnpm") or a confirmed approach, is usually phrased as an order, which
198+
§7's instruction guard rightly holds back when it comes from a transcript.
199+
200+
### What changes
201+
202+
- **Two agent tools, `remember` and `forget`.** The agent saves a note during the run when the person asks it
203+
to remember something, corrects how it works, confirms an approach that was not obvious, states a decision
204+
(with an absolute date), or says where something lives. Each note has a `kind` (`preference`, `project`,
205+
`reference`), the note `text`, and `said`: the person's own words, copied from their message.
206+
- **A note is credited to the person by code, not by the model** (`sessionMemory.groundNote`):
207+
1. `said` must appear in what the person typed *this run*: their goal (handed over by the host as typed)
208+
and their ask_user choices and notes. Nothing the agent read counts.
209+
2. The note must say no more than those words: at least two thirds of its content words must come from
210+
them (exact, a shared start of four letters or more, or a five-letter stem).
211+
212+
A credited note is active at once, even phrased as an order, because the person said it. Any other note is
213+
still kept and listed, as *unconfirmed*: one Confirm click in the Memory tab makes it active. That is the
214+
same asymmetry as §7: a false negative costs one click, a false positive would put a repository's order into
215+
every future session.
216+
- **Notes live in `facts.jsonl`** as observations with `origin: "person"`, `kind`, `said` (secret-scrubbed)
217+
and `verified`, so they get the existing fold, panel, recall and "not true". Two rules differ from facts:
218+
repetition never promotes an uncredited note, and the summarizer's supersede pass is never shown a note
219+
(`supersedableFacts`). Only the person changes it: `remember` again, `forget`, or the panel.
220+
- **`MEMORY.md`** gets a "From you" section, each line with the person's words beside it. Every line older
221+
than a day says how old it is ("9 days old"). The always-on file is capped at 25 notes and 15 facts; the
222+
rest are named as "…and N more; recall_sessions finds them".
223+
- **`forget`** removes the best match for a query, only when the request is in the person's own words, and
224+
tells the agent what it removed so it can say so.
225+
- **Search Sessions…** (Command Palette, and a search icon in the Sessions panel's title bar): every session
226+
not in the trash, archived ones included, matched on its title and its whole conversation (all words must
227+
match), newest first, each with the line it matched. A quick pick, not a field in History: History stays
228+
the short list of recent work it was cut down to on 2026-08-02 (77d4f13), and this reaches what that list no
229+
longer shows. Transcripts are read at most 150 at a time and cached by file size and modification time.
230+
231+
### Where the shape came from: Claude's desktop app
232+
233+
Read from `/Applications/Claude.app` (2.42304.2) and the Claude Code it downloads (2.1.299) on 2026-10-19:
234+
235+
- **Memory is files the agent writes itself**, one per memory, typed `user` / `feedback` / `project` /
236+
`reference`, with a one-line pointer in a `MEMORY.md` index that is always loaded and cut off after 200
237+
lines. The agent is told to save when the user corrects *or confirms* its approach, to record the why, and
238+
to convert relative dates. Claude Code keeps the folder beside the project's transcripts
239+
(`~/.claude/projects/<project>/memory/`); in its Cowork mode the app passes another folder and the
240+
guidelines through environment variables, and allows writes there.
241+
- **Recall is per request**: a side model call is shown each memory's type, file name, date and description
242+
and picks up to five that clearly help the current request, never one it already picked. Each memory it
243+
brings back carries "This memory is N days old… verify" once it is older than a day.
244+
- **A background "dream"** periodically rewrites the memory files from recent sessions: merges, updates,
245+
prunes.
246+
- **History** is a metadata record per session (title and where the title came from, archived, last activity,
247+
turns, model) beside an append-only transcript, and transcript search is a plain case-insensitive match
248+
across sessions, returning one snippet each.
249+
250+
What LevelCode does differently, on purpose:
251+
252+
| | Claude | LevelCode |
253+
|---|---|---|
254+
| who decides a memory is the user's | the agent writes the file | the host checks the quoted words against what the person typed |
255+
| a memory phrased as an order | saved like any other | saved; active only when credited to the person, else one click |
256+
| recall | a model picks up to 5 per request | the capped always-on digest plus `recall_sessions` on demand |
257+
| age warning | on recalled memories older than a day | on every digest line older than a day |
258+
| consolidation | a model "dream" pass over the files | the existing deterministic fold on every seal |
259+
| history search | substring match, one snippet per session | every word must match, title matches first, one snippet each |
260+
261+
Per-request selection was left out for a reason that is specific to LevelCode: memory reaches the agent in
262+
the system prompt, which providers cache together with the whole conversation after it. Changing it per
263+
request would make every new goal re-send the conversation at full price. Claude adds recalled memories to
264+
the conversation as attachments (its transcripts carry `attachment` records); doing that here touches how a
265+
goal is stored, titled, compacted and replayed, and is a separate change.
266+
267+
### What was run (2026-10-19, macOS 27.0.1, Node 24)
268+
269+
- `scripts/test-extensions.sh`, including `test/memoryNotes.test.js` (21: the crediting check, the fold, the
270+
digest, recall states, search over a real store), `test/memoryNotesHost.test.js` (8: the real runAgent with
271+
a stood-in provider, and the host halves lifted out of `extension.js`), and ten new hostile cases in
272+
`test/memoryPoisoning.test.js` (each order, quoted against a real goal, stays an inactive note).
273+
- Fifteen single-defect mutations, each turning a test red.
274+
- `scripts/memory-editor-check.js` in the dev build with a stand-in provider: 11 checks, from the remember
275+
call through the Memory tab, the next session's instructions and Search Sessions reopening the conversation.
276+
277+
Not run: a real model deciding when to call `remember` (only a scripted one has), the browser edition, Linux.
278+
279+
---
280+
192281
*Store it (spine) · browse it (experience) · **remember it (this doc).** Together: a sessions feature where the project accumulates its own experience — small in every prompt, deep on request, legible and yours, and safe against the repo that would lie to it.*

0 commit comments

Comments
 (0)