Skip to content

Memory page, and showing what memory did in chat - #261

Open
farhat-is-coding wants to merge 12 commits into
devfrom
farhat/feat/memory-page-overhaul
Open

Memory page, and showing what memory did in chat#261
farhat-is-coding wants to merge 12 commits into
devfrom
farhat/feat/memory-page-overhaul

Conversation

@farhat-is-coding

Copy link
Copy Markdown
Collaborator

Summary

The interface for the layered memory backend (cmudco/dare-backend#338).

Memory page — four layer cards, semantic search with relevance meters, inline editing, and "What DARE used to think": retired memories paired with whatever replaced them, so a correction reads as a correction rather than as data loss.

In chat — the per-message activity panel now shows the write side, not just the read side. What was remembered, what was retired, and what the gate refused, each with the writer's own reason. A decision the gate overruled says what was asked for alongside what was done.

The memory toggle now means what its copy says: it gates retrieval, the writer, and transcript search. The duplicate search_sessions checkbox is gone from the tool drawer.

Notable

  • The write summary arrives seconds after the reply — the writer runs in a background job — so it is stored on the message as well as pushed over the socket. A reload still shows it.
  • All sample/preview-mode code is gone; every card comes from the backend.
  • Profile lines are now real records with real ids, so editing one goes through the same path as any other memory.

Test plan

  • npm run app:build clean, 0 lint errors
  • Browser: memory page with all four layers, archive disclosure, inline edit + refusal, semantic search
  • Browser: live chat turn — recalled memories, tool call, and the write strip updating in place without a refresh
  • Memory toggle persists across reload and gates the pipeline both ways

Editing is no longer a disabled pencil with a promise attached — the layered
backend is here, so cards and USER.md lines are rewritten in place through a
shared InlineEditor (Enter saves, Escape cancels). The field stays open while
the save is in flight and when the server refuses, so a rejected edit — a
rule whose new trigger collides, a line that would cross the token ceiling —
keeps the text there to fix rather than throwing the work away.

Sample mode is gone entirely: memorySamples.ts, previewMode, the seed
endpoint and thunk, the local-only delete path, the sample banner and empty
-state button, and the semanticDisabled prop that existed only to hobble
search while sample data was showing. Everything on the page is now the
user's real store.

Also drops the permanently-disabled whole-file pencil (per-line editing
replaces it) and corrects the explainer's claim that the writer and gate are
still coming — only consolidation is.
The switch had no explanation attached, but it is the one control in this
panel that both reads and writes: on means DARE brings what it knows into
the conversation AND reads each finished reply for anything worth keeping.
That is a consent decision, so the panel now states it in those terms and
flips the wording with the switch.

Adds the route the panel was missing — 'See what it remembers' opens the
Memory page, so the toggle and the store it fills are one click apart. Also
swaps the Brain icon for the Fingerprint the Memory page already uses, and
labels the switch for screen readers.
Two things the store knew and the interface never said.

A turn's memory activity now ends with what the writer decided, on the same
timeline as the tools and sources — including the decisions it refused, since
those are the ones that show the gate working.

Retired memories get their own disclosure below the feed, each paired with
what replaced it: Pittsburgh struck through, Boston beside it. They stay out
of the main feed on purpose — mixed in with current memories they read as
contradictions, with nothing on the card saying which one is live.

Also swaps the recalled-memories icon from Brain to Fingerprint, matching the
Memory page.
The toggle now switches transcript search too, so the panel says so.
docs/RULES.md: one component per file, helpers included. MemoryArchive held
RetiredRow and MemoryWriteStep held ChangeRow.
It sat on the same timeline rail as the tool calls, with the same icon
treatment, so it read as a step the turn had taken. It isn't one — the writer
reads the finished turn in a background job, seconds later, in another
process. It now sits below the rail under "After the reply".

And it led with process instead of outcome. One "call me Abbas" produced
three ledger entries as the gate worked through a patch and two supersedes,
each describing a state that no longer exists by the time you read it. The
headline is now the last applied decision per memory — what the store
actually holds — with every decision, refusals included, one disclosure away.
The sweep finds duplicates, facts repeated enough to belong in the profile,
slots named for what they used to hold, and a profile with more pinned to it
than fits. Each one is a card that leads with the memory rather than the verb,
because the question being asked is "is this right about you?" — answered by
reading the sentence, not by parsing what "merge" means.

Opt-in rather than always-on. A panel permanently reading "6 things need your
attention" is a chore; asked for, it either has something to say or says
plainly that it does not.

Both buttons are safe: approving retires rather than deletes, and passing
changes nothing. Approving refetches the store so the archive count and the
layer cards move with it.

Dismissal lives in the panel rather than in each card. Held per-card, the last
"Leave it" emptied the panel with no closing state — it looked broken instead
of finished.
…page

The Sessions card used to open the explainer — a dead end dressed as a
layer. It now selects like the other three, and switches the search
surface below into transcript mode: the same search the model reaches
through its search_sessions tool, so what the page can find and what
the model can find are one and the same. Words, a date range, or both
(dates alone answer "what did we talk about last week?"); each hit
shows the matched exchange with the turn either side and opens the
conversation it came from. State lives in the memory slice — one
search surface, two modes, entering either clears the other's results.

Also rewrites the How-it-works sheet against what shipped: the recall
step now says what actually happens (profile whole, best 3 facts by
meaning, up to 5 rules, a relevance bar), the separate cold-layer
funnel section is gone, consolidation is described as the live Tidy up
sweep rather than a thing rolling out next, editing is no longer 'on
the way', and the FTS5 label — SQLite's module, which this never was —
reads FTS.
Export downloads the dare-memory-v2 bundle — the layered contract
itself, not a flat list. Import takes a bundle by file or paste, shows
what is inside before anything happens (active / retired / held / rules,
document or not), and surfaces the backend's refusals verbatim — the
empty-store rule above all. Successor to the MemU-era export dialog,
whose portability idea survives here with a format that can actually
reinstate a store.
Second mode in the Import dialog. Step one hands the person a prompt
for their other assistant — plain bullet points in their own voice,
exact wording preserved for instructions, nothing session-specific.
Step two takes whatever comes back and queues it through DARE's own
memory pipeline; the toast says work has started rather than
pretending it finished, because the writer works through the queue.
Memory page: export, import, and import from another AI
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant