feat(session): add anti-drift session notes#7
Open
vicary wants to merge 8 commits into
Open
Conversation
ff69c1e to
cfac4be
Compare
There was a problem hiding this comment.
Pull request overview
This PR advances the “search-first unified memory” architecture by introducing normalized memory result contracts, durable session notes (no TTL) with freshness-aware ranking, and a new <memory version="2"> injection envelope that avoids injecting exact <entry> records. It also adds dream summary storage/job scaffolding and extends shutdown/teardown coverage to prove graceful waiting behavior.
Changes:
- Introduces normalized memory result models and a unified
session_search()orchestration path that can merge entries/notes/summaries. - Adds durable session notes (no TTL), note read metadata (
last_read_at), freshness-based ranking, and MCP note read/write tools. - Updates continuity injection to
<memory version="2">(nested<persistent_memory>and optional compaction-only<session_notes>), plus adds shutdown warning/proof scaffolding.
Reviewed changes
Copilot reviewed 47 out of 48 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/types/index.ts | Adds NormalizedMemoryResult contract for unified memory search/injection. |
| src/testing/detached-dream-proof.ts | Adds proof-only plugin to validate graceful shutdown waiting behavior. |
| src/testing/detached-dream-proof.test.ts | Tests detached dream proof plugin behavior/artifact writing. |
| src/session.ts | Updates injection envelope to <memory version="2">, strips <entry> blocks, adds compaction-only note injection. |
| src/session.test.ts | Adds tests for compaction notes injection and v2 envelope invariants. |
| src/services/session-snapshot.test.ts | Updates expectations to <memory version="2">. |
| src/services/session-notes.ts | Introduces durable session notes service with freshness-aware search and same-project delete-by-id semantics. |
| src/services/session-mcp-types.ts | Extends MCP schemas: normalized search results (ref/refs) and note tool request/response types. |
| src/services/session-mcp-runtime.ts | Wires session_search through unified memory search, adds note tools + descriptions, increases response budget. |
| src/services/runtime-teardown.ts | Adds createRuntimeTeardownTask helper and refines Deno vs Node signal listener wiring. |
| src/services/runtime-teardown.test.ts | Adds “live runtime” shutdown-wait proofs for SIGINT and beforeExit flows. |
| src/services/redis-snapshot.ts | Adds helper to emit snapshot summaries as NormalizedMemoryResult. |
| src/services/redis-client.test.ts | Makes waitFor async-friendly to reduce flakiness. |
| src/services/opencode-warning.ts | Adds notifyDreamShutdownDelay() warning helper. |
| src/services/memory-search.ts | Adds unified memory search service (entries + notes + summaries) with query vs reflection mode behavior. |
| src/services/memory-search.test.ts | Tests ordering and query/reflection mode behavior for unified memory search. |
| src/services/memory-results.ts | Adds ordering utilities for normalized memory results. |
| src/services/hot-tier-slice.test.ts | Updates continuity assertions for <memory version="2"> envelope. |
| src/services/exact-history.ts | Adds adapter interface/scaffold for exact-history searching. |
| src/services/dream-store.ts | Adds Redis-backed dream summary storage + retrieval around a reference time. |
| src/services/dream-runner.ts | Adds dream runner that buckets inputs and advances watermark. |
| src/services/dream-runner.test.ts | Tests dream store + runner watermark/summary behavior. |
| src/services/dream-jobs.ts | Adds pending dream job storage/preparation. |
| src/services/dream-jobs.test.ts | Tests dream job write/read/clear and prepare semantics. |
| src/services/detached-dream-worker.ts | Adds detached worker spawn scaffold (currently returns false). |
| src/index.ts | Wires notes service into runtime/session manager; adds session_search biasing and dream shutdown warning teardown task. |
| src/index.test.ts | Extends entrypoint tests for notes service wiring, biasing, dream shutdown warning behavior, and tool arg exposure. |
| src/handlers/tool-before.ts | Uses deny guidance as the thrown error message when present. |
| src/handlers/tool-before.test.ts | Updates tests to assert new thrown-denial guidance behavior. |
| src/handlers/messages.ts | Updates scrubbing logic for the new <memory> envelope and logging text. |
| src/handlers/messages.test.ts | Updates tests for <memory version="2"> injection and scrubbing behavior. |
| src/handlers/compacting.ts | Passes { forCompaction: true } to inject compaction-only session notes and updates log messages. |
| src/handlers/compacting.test.ts | Updates compaction tests for v2 envelope and compaction options. |
| src/handlers/chat.ts | Updates log messages to “memory” naming. |
| src/handlers/chat.test.ts | Updates chat handler tests for new prepareInjection signature. |
| opencode.json | Removes local dev plugin config from repo root. |
| docs/superpowers/specs/2026-05-10-session-notes-freshness-without-ttl-design.md | Adds design doc for durable notes and freshness ranking. |
| docs/superpowers/specs/2026-04-21-search-first-unified-memory-design.md | Adds design doc for search-first unified memory architecture. |
| docs/superpowers/specs/2026-04-11-session-notes-anti-drift-design.md | Adds spec doc for cross-session notes recall model. |
| docs/superpowers/plans/2026-05-10-session-notes-freshness-without-ttl.md | Adds implementation plan for durable notes + freshness ranking. |
| docs/superpowers/plans/2026-03-20-context-mode-mcp-first-implementation.md | Updates bounded-response budget documentation to 32 KB. |
| docs/SmokeTests.md | Updates smoke-test coverage and procedures for notes/tools and dream shutdown proof. |
| deno.lock | Adds @std/async dependency lock entry. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+243
to
+245
| session_notes_read: { | ||
| id: pluginSchema.string().min(1).optional(), | ||
| }, |
Comment on lines
+153
to
+157
| "- To check whether pinned session notes already contain the context you need.", | ||
| "", | ||
| 'Results may include indexed memory content (type: "memory") and, when pinned', | ||
| 'session notes exist, matching notes (type: "note"). Note results include', | ||
| '`id`, `root_session_id`, `scope: "local" | "project"`, `created_at`, and', |
|
|
||
| - `session:{rootSessionId}:notes` stores current-session note bodies and is used | ||
| for compaction note injection | ||
| - `project:{groupId}:notes` stores same-project notes for cross-session search |
| - `created_at` | ||
| - `updated_at` | ||
|
|
||
| 2. `project:{groupId}:notes` |
Comment on lines
844
to
+857
| - pre-compaction delegated work appears in the compaction-preserved memory | ||
| envelope; | ||
| - the compaction-time `<session_memory>` evidence includes a | ||
| `<session_notes source="note_tools">` section with the complete pinned note | ||
| body as input material; | ||
| - the root resumes correctly after compaction without the operator replaying | ||
| the history; | ||
| - the resumed children continue from the preserved state rather than starting | ||
| a fresh branch. | ||
| a fresh branch, and the reopened note text still matches the pinned | ||
| pre-compaction note. | ||
| - **Evidence to collect:** pre-compaction prompt/evidence; compaction occurrence | ||
| note or log; post-compaction root answer; post-compaction child tool results; | ||
| post-compaction `<session_memory>` envelope. | ||
| note or log; `session_notes_write` and `session_notes_read` responses; | ||
| post-compaction root answer; post-compaction child tool results; post- | ||
| compaction `<session_memory>` envelope. |
Comment on lines
490
to
513
| ### 5.9 Suite I — Continuity assembly and compaction survival | ||
|
|
||
| - **Objective:** Prove that `session_*` activity folds into local continuity, | ||
| `<session_memory>` assembly stays deterministic, and continuity survives | ||
| compaction. | ||
| - **Prerequisites:** Same as Suite A. | ||
| - **Exact commands:** | ||
|
|
||
| ```bash | ||
| deno test src/handlers/chat.test.ts src/handlers/messages.test.ts src/handlers/compacting.test.ts src/handlers/event.test.ts src/services/session-snapshot.test.ts src/services/hot-tier-slice.test.ts | ||
| deno test src/session.test.ts src/handlers/chat.test.ts src/handlers/messages.test.ts src/handlers/compacting.test.ts src/handlers/event.test.ts src/services/session-snapshot.test.ts src/services/hot-tier-slice.test.ts | ||
| deno task check | ||
| ``` | ||
|
|
||
| - **Expected result:** PASS. Local continuity sections and snapshots are | ||
| assembled from hot-tier state, optional cached `<persistent_memory>` is | ||
| additive only, stale envelopes are scrubbed, and compaction preserves | ||
| continuity for both direct and delegated work. | ||
| additive only, stale envelopes are scrubbed, normal chat-turn injection omits | ||
| `<session_notes>`, compaction-only injection includes complete pinned note | ||
| bodies inside `<session_notes source="note_tools">` from the current root | ||
| session only (same-project foreign-session note bodies are excluded), and | ||
| compaction preserves continuity for both direct and delegated work. | ||
| - **Artifacts/evidence to save:** Full test output; representative emitted | ||
| `<session_memory>` blocks; compaction-hook assertions; snapshot-related | ||
| assertions. | ||
| `<session_memory>` blocks with and without `<session_notes>` as applicable; | ||
| compaction-hook assertions; snapshot-related assertions. | ||
| - **Common failure signatures:** Missing or duplicated `<session_memory>` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
session_search()is the canonical recall API and injected XML is only a bounded hint surface.Design
Authority Model
opencode db/ SQLite is the exact chronological source of truth for user turns, assistant turns, and tool calls.Canonical Recall Path
session_search()becomes the default memory read API.queryplus optionalwhen, searches normalized exact/history, notes, and summaries, and returns exact-style results before summaries.when.type: "entry" | "note" | "summary",ref,snippet,score,created_at, and optional metadata.Injection Contract
<memory version="2">wrapper.<persistent_memory>is nested inside<memory>instead of being a separate top-level block.session_search().<session_memory>expectations were updated in tests to the normalized<memory>envelope.Durable Session Notes
last_read_aton successfulsession_notes_read(id)calls.session_searchnote hits exposecreated_atandupdated_at, but notlast_read_at.Dream Summary Layer
Graphiti Role
session_search().Retention Model
Implementation Notes
session_searchschemas and runtime wiring for normalizedref/refsresponses and optionalwhen.<memory version="2">wrapper.Test Plan
deno test -Adeno task checkdeno task lintdeno task fmt --checkLatest full-suite verification before commit:
66 passed (692 steps), 0 failed.