fix(session): vectorize memory parent directories on SessionCommit - #3665
fix(session): vectorize memory parent directories on SessionCommit#3665huangruiteng wants to merge 3 commits into
Conversation
SessionCommit could write memory leaf files and their .overview.md without enqueuing the L1 directory vectors, leaving parent directories without vector records. Hierarchical retrieval then returned zero results until a vectors_only reindex rebuilt the subtree. Default memory files (identity.md, soul.md) written by initialize_memory_files were likewise never embedded. Two root causes: 1. generate_overview() wrote .overview.md after _vectorize_memories() ran, so the new overview file was never vectorized. 2. initialize_memory_files() wrote defaults directly through viking_fs.write_file() with no embedding enqueue. Fixes: - Reorder apply_operations so overview generation happens before _vectorize_memories; collect the written overview URIs and pass them as a new overview_uris parameter. - _vectorize_memories enqueues one L1 OVERVIEW record per overview URI via vectorize_directory_meta(include_abstract=False), reusing the shared owner/timestamp/telemetry path. No L0 abstract record is emitted because no .abstract.md was written; overview files are kept out of written_uris so the leaf flow is unchanged. - vectorize_directory_meta gains include_abstract (default True) so callers that only wrote .overview.md can skip the L0 record. - initialize_memory_files returns the list of URIs it newly created; pre-existing files are skipped and not returned. - Add MemoryUpdater.initialize_and_vectorize_default_files and use it from compressor v2/v3 so newly initialized defaults are embedded on first session. Pre-existing defaults are not re-embedded. Tests: - tests/unit/session/memory/test_issue_3640_parent_vectors.py covers initialize_memory_files return semantics, the shared v2/v3 helper (success / no-op / vikingdb-unavailable), and apply_operations emitting exactly one L1 OVERVIEW per parent while keeping the leaf at L2 DETAIL and .overview.md out of written_uris. - tests/unit/test_vectorize_file_strategy.py covers include_abstract=False producing exactly one OVERVIEW record and the default still producing L0+L1. Fixes #3640
|
Gentle review ping — this is ready for maintainer review.
Happy to address any feedback on the same branch. |
|
@chenjw this touches the memory engine ( |
Ruff lint fix + format over the changed test file; no behavior change.
|
Friendly second-round ping — this is ready for review and merge. Since the first ping I ran a Verification on the latest push:
Summary: overview generation is reordered before vectorization so each parent directory gets an L1 @t0saki you're the most recent committer to the session/memory files touched here — would you have time to approve? @chenjw (Memory Engine owner) / @qin-ctx also welcome. |
|
Updated the PR description to match the repository |
…g-parent-vectors # Conflicts: # openviking/session/memory/memory_updater.py # openviking/utils/embedding_utils.py # tests/unit/test_vectorize_file_strategy.py
Description
Fixes #3640:
SessionCommitcould write memory leaf files and their.overview.mdwithout enqueuing the L1 directory vectors, leaving parent directories without vector records. Hierarchical retrieval returned zero results until avectors_onlyreindex rebuilt the subtree. Default memory files (identity.md,soul.md) written byinitialize_memory_fileswere likewise never embedded.Root causes:
generate_overview()wrote.overview.mdafter_vectorize_memories()ran, so the newly written overview file was never vectorized.initialize_memory_files()wrote defaults directly throughviking_fs.write_file()with no embedding enqueue.Human Involvement
Related Issue
Closes #3640.
Type of Change
Changes Made
apply_operations: overview generation now happens before_vectorize_memories; written overview URIs are collected and passed as a newoverview_urisparameter._vectorize_memoriesenqueues one L1OVERVIEWrecord per overview URI viavectorize_directory_meta(include_abstract=False). No L0 abstract record is emitted (no.abstract.mdwritten);.overview.mdis kept out ofwritten_urisso the leaf flow is unchanged.vectorize_directory_metagainsinclude_abstract(defaultTrue) so callers that only wrote.overview.mdcan skip the L0 record.initialize_memory_filesreturns the list of URIs it newly created; pre-existing files are skipped and not returned.MemoryUpdater.initialize_and_vectorize_default_files(new shared classmethod) is used by compressor v2 and v3 so newly initialized defaults are embedded on first session; pre-existing defaults are not re-embedded. Removes duplicated v2/v3 initialization plumbing.Leaf/level invariants: leaf memory files continue through the standard
ContextLevel.DETAIL(L2) flow withis_leaf=True; each parent directory receives exactly oneContextLevel.OVERVIEW(L1) record withis_leaf=False,context_type="memory", and the directory URI (not the.overview.mdURI); no L0ABSTRACTrecord is emitted for session-commit overviews.Testing
tests/unit/session/memory/test_issue_3640_parent_vectors.py— 7 new tests:initialize_memory_filesreturns only newly created URIs (pre-existing skipped, schemas withoutinit_valueproduce nothing);initialize_and_vectorize_default_files(v2/v3) vectorizes each new URI and is a no-op when nothing is created or vikingdb lacks a queue manager;apply_operationsemits exactly one L1OVERVIEWper parent, keeps.overview.mdout ofwritten_uris, routes the leaf through L2DETAIL, and emits no overview when there are no upserts.tests/unit/test_vectorize_file_strategy.py— 2 new tests:include_abstract=Falseproduces exactly oneOVERVIEWrecord; default behavior still produces L0ABSTRACT+ L1OVERVIEW.test_issue_3640_parent_vectors.py+test_vectorize_file_strategy.py); full CI green on the latest push.ruff check/ruff formatclean on all changed files (a pre-existing import-sort warning onorigin/mainincompressor_v2.pyis outside this PR's scope).Risk
Classification/flow is localized to memory overview vectorization; leaf embedding and request paths are unchanged. New or unrecognized cases fall through to existing behavior.
Checklist
Screenshots (if applicable)
N/A — backend logic changes with no UI impact.
Additional Notes
This PR was generated entirely by AI agents. All tests pass locally and in CI.