Draft preview
Correcting or forgetting a memory when a decision changes
Testing correction, stale revisions, and logical forgetting in Cairn's local MCP preview, with fresh-session read-back and clear limits.
A project decision changes, but an older Memory can still be present. We wanted to know what an engineer can verify before trusting the new version. We tested a pinned local MCP preview with synthetic, project-scoped decisions. Cairn (cairn.ink) keeps private Memory separate from a Knowledge Card; correcting one did not publish anything to a shared collection.
The database was local, but the native Claude client used an existing subscription, so this was not an offline run. We made no hosted Cairn write.
Two different kinds of evidence
First, an official MCP SDK 2.0.0 harness exercised the adapter at source commit ad274b6; the MCP server ran on Node 24.22.1. It ran 14 protocol cases, with 19 tool calls and eight fresh MCP server processes. All 14 cases passed and the harness exited 0. A correct_memory call advanced one record from revision 1 to revision 2 and created a new Source Receipt. Reusing revision 1 for either correction or forget returned revision_conflict. The protocol's later forget call used expectedRevision 2 on that same record. Inspection immediately after forget returned memory_not_found; a new process then found an empty memory list and source list.
That was an adapter protocol result, not a native-client test. The keyless semantic-recall probe returned model_not_configured, as expected without a configured model. read_memory_sources is a source listing, not semantic retrieval. The pinned MCP guide documents the tool boundary.
We then ran a separate Claude-only native test on the same local source preview. It covered 12 synthetic cases in 12 distinct sessions, with 20 explicit tool calls. The MCP server ran on Node 24.22.1; Claude Code 2.1.319 reported claude-opus-5-5. Every CLI process exited 0, the wrapper exited 0, and the evidence audit exited 0. A second read-only audit of the existing event log passed without new native calls, and a separate SDK check in two fresh server processes (four calls total) confirmed the postconditions.
In that test, correction kept the same Memory ID and advanced revision 1 to 2. A new session read the corrected record and current source. The new Source Receipt appeared in the current-admitted view; the old receipt did not. A stale correction and a stale forget both conflicted, leaving revision 2 unchanged. For a separate disposable record, forget returned true; in a new process, inspection returned memory_not_found and the current source list was empty. The wrong-project controls were also empty.
What “forgotten” means here
The read-back proves the record is absent from the adapter's current admitted view after a logical forget. It does not establish physical erasure from SQLite pages, journals, snapshots or backups. The pinned local store contract describes the local state and revision behavior. A Source Receipt helps trace a Memory's origin; it is not proof that a decision is still current or correct.
To repeat the native-client check, use a fresh synthetic database and two different project-scoped fixtures. Save an old decision and inspect its scope and receipt. Correct it with the exact memoryId and expectedRevision, then inspect the same record from a new session. Retry with the old revision to confirm the stale request conflicts. Use the second fixture for forget, then verify both exact-ID inspection and the current source list from a new process. Keep expected values outside the receiver prompt and repo. These are reproduction steps, not a claim that every client offers the same controls.
What we have not tested
The successful native mutation test described here covered Claude Code. Earlier source-continuity tests used Codex 0.166.0. That earlier native batch planned 14 sessions: eight were attempted (seven passed, one was blocked), and six were left unattempted. All eight CLI invocations exited 0, while the batch wrapper exited 1. In that batch, a Codex correction request reached an approval gate and was blocked because the approval policy was set to never; it did not produce a successful mutation, and a read-only check found the old revision unchanged. Native forget was not attempted in that batch. A subsequent CLI capability check used Codex 0.167.0. Its interactive TUI lacked the per-invocation isolation controls used by our exec setup, so we did not attempt another mutation in that setup. We left global configuration and approval policy alone, and kept the blocked attempt separate from the later Claude result.
Hosted same-account behavior, semantic recall quality, automatic capture and automatic retrieval remain untested. The local owner and project settings are not hosted account authentication. These results describe synthetic data in a source-run development preview.
For steps to inspect and manage a private Memory, read the Learn guide to Memory source control.