Skip to content

fix(memory): harden memory prune guards#1889

Merged
zerob13 merged 2 commits into
devfrom
fix/memory-audit-prune-guards
Jul 6, 2026
Merged

fix(memory): harden memory prune guards#1889
zerob13 merged 2 commits into
devfrom
fix/memory-audit-prune-guards

Conversation

@yyhhyyyyyy

@yyhhyyyyyy yyhhyyyyyy commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator
  • make dead-vector sweep warm-store-only and dim-aware
  • guard inline prune against restore/re-embed races
  • keep management memory search read-only
  • narrow vector prune error handling
  • add stale-dim and inline-race regressions

Summary by CodeRabbit

  • New Features

    • Improved memory.search depth controls with a safer default (50) and tighter max cap (100).
    • Enhanced recall/search performance by reusing in-flight query embeddings and better managing vector-search concurrency.
  • Bug Fixes

    • Excludes internal persona/working entries from search and management results, including correct limit behavior.
    • Strengthened maintenance: consolidation scanning and neighbor lookups, plus more reliable pruning/repair of stale or dead vector references during lifecycle changes.
  • Documentation

    • Updated the Agent Memory System and hot-path keyword recall specifications with the latest behavior details.
  • Tests

    • Expanded coverage for search limits, concurrency, pruning, and internal archive/restore/forget correctness.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a1555959-0bb3-4eda-8fdc-41cf8c7332bd

📥 Commits

Reviewing files that changed from the base of the PR and between 276c0c5 and 36f1415.

📒 Files selected for processing (2)
  • src/main/presenter/memoryPresenter/services/managementService.ts
  • test/main/presenter/memoryPresenter.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/main/presenter/memoryPresenter.test.ts

📝 Walkthrough

Walkthrough

This PR updates the agent-memory system’s retrieval, consolidation, pruning, and lifecycle behavior. It adds stored-vector neighbor lookup, dead-vector cleanup, resumable consolidation scanning, tighter memory.search limits, and guards that keep persona/working rows out of generic management flows.

Changes

Memory pruning, consolidation, retrieval

Layer / File(s) Summary
Spec and documentation updates
docs/architecture/agent-memory-system/spec.md, docs/issues/memory-recall-hot-path-keyword-recall/spec.md
Updates describing search override limits, query dedupe/pruning, consolidation budgets and cursoring, lifecycle rules, test commands, and tuning constants.
Runtime constants and repository/vector-store contracts
src/main/presenter/memoryPresenter/runtimeConstants.ts, src/main/presenter/memoryPresenter/types.ts
Adds limits for neighbor scans, prune batches, recall concurrency, and search defaults; extends repository/vector-store ports with scan, repair, and prunable-ref operations.
Vector store infra and fakes
src/main/presenter/memoryPresenter/infra/memoryVectorStore.ts, src/main/presenter/memoryPresenter/infra/vectorStoreManager.ts, test/main/presenter/fakes/memoryFakes.ts, test/main/presenter/memoryVectorStore.test.ts, test/main/presenter/memoryExtraction.test.ts
Adds queryByMemoryId, warm-dimension lookup, prunable-vector deletion, and matching fake/test harness updates.
Presenter dependency wiring
src/main/presenter/memoryPresenter/index.ts
Wires the new vector-store callbacks into presenter and maintenance construction.
Retrieval service
src/main/presenter/memoryPresenter/services/retrievalService.ts, test/main/presenter/memorySearch.test.ts, test/main/presenter/memoryPresenter.test.ts
Adds per-query embedding coalescing, inline dead-vector pruning, and clamped search limits with coverage.
Maintenance service
src/main/presenter/memoryPresenter/services/maintenanceService.ts, test/main/presenter/memoryPresenter.test.ts
Reworks consolidation around stored-vector scans with a cursor and adds dead-vector pruning plus internal repair work.
Persona/working lifecycle guards
src/main/presenter/memoryPresenter/services/managementService.ts, src/main/presenter/sqlitePresenter/tables/agentMemory.ts, test/main/presenter/agentMemoryTable.test.ts, test/main/presenter/memoryPresenter.test.ts
Excludes persona/working rows from generic management/search paths and adds pruning/repair helpers with tests.
Route contract limit tightening
src/shared/contracts/routes/memory.routes.ts, test/main/routes/memoryDto.test.ts
Lowers memory.search limit max from 500 to 100.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant RetrievalService
  participant EmbeddingProvider
  participant VectorStoreManager
  Caller->>RetrievalService: retrieve(query, options)
  RetrievalService->>RetrievalService: startQueryEmbedding(query, fingerprint)
  alt identical query in-flight
    RetrievalService-->>Caller: reuse in-flight promise
  else distinct query, under concurrency limit
    RetrievalService->>EmbeddingProvider: embed(query)
    EmbeddingProvider-->>RetrievalService: embedding
  else third distinct concurrent query
    RetrievalService-->>Caller: degrade to FTS-only
  end
  RetrievalService->>VectorStoreManager: query vectors, collect dead matches
  RetrievalService->>VectorStoreManager: deletePrunableVectorsForMemoryIds(deadIds)
  RetrievalService-->>Caller: fused results
Loading
sequenceDiagram
  participant MaintenanceService
  participant VectorStoreManager
  participant MemoryVectorStore
  participant Repository
  MaintenanceService->>Repository: listConsolidationScanRows(cursor)
  MaintenanceService->>VectorStoreManager: queryNeighborsByMemoryId(memoryId, topK)
  VectorStoreManager->>MemoryVectorStore: queryByMemoryId(memoryId, options)
  MemoryVectorStore-->>VectorStoreManager: neighbor matches
  VectorStoreManager-->>MaintenanceService: matches
  MaintenanceService->>MaintenanceService: select/merge superseding pairs, advance cursor
  MaintenanceService->>VectorStoreManager: deletePrunableVectorsForMemoryIds(deadIds)
  MaintenanceService->>Repository: clearPrunableEmbeddingRefs(ids)
Loading

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately reflects the main change: safer memory pruning and guard hardening.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/memory-audit-prune-guards

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/main/presenter/memoryPresenter.test.ts (1)

4356-4360: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Loosened assertion may be masking non-determinism.

This assertion was widened to accept either pending_embedding or embedded for the challenger row post-consolidation, rather than a single deterministic status. Given this PR's broader changes to query-embedding concurrency and pruning, worth confirming whether this reflects a legitimate, understood race (e.g., embedding completion timing relative to consolidation) versus a symptom of a flaky/nondeterministic write ordering that should instead be fixed or awaited deterministically in the test setup.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/main/presenter/memoryPresenter.test.ts` around lines 4356 - 4360, The
`memoryPresenter.test.ts` expectation for `repo.getById('c1')?.status` is
masking a possible race between consolidation and embedding completion. Tighten
the test around the relevant `consolidate`/embedding flow so the challenger row
reaches one deterministic status before asserting, or explicitly await the async
embedding work in the test setup rather than accepting both `pending_embedding`
and `embedded`. Use the `buildMemoryProvenanceKey`, `repo.getById`, and
consolidation path in the test to locate and make the ordering deterministic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/presenter/memoryPresenter/services/managementService.ts`:
- Around line 114-120: `listMemories` in `managementService.ts` still exposes
internal `working` rows because it only filters out `persona`; update it to use
the shared `isInternalMemoryKind` guard, matching the hardened checks already
used by `restoreMemory`, `forgetMemory`, and `archiveUserMemory`. Locate the
change in `ManagementService.listMemories` and replace the ad hoc kind check
with the internal-memory predicate so the management UI only receives
non-internal memories.

---

Nitpick comments:
In `@test/main/presenter/memoryPresenter.test.ts`:
- Around line 4356-4360: The `memoryPresenter.test.ts` expectation for
`repo.getById('c1')?.status` is masking a possible race between consolidation
and embedding completion. Tighten the test around the relevant
`consolidate`/embedding flow so the challenger row reaches one deterministic
status before asserting, or explicitly await the async embedding work in the
test setup rather than accepting both `pending_embedding` and `embedded`. Use
the `buildMemoryProvenanceKey`, `repo.getById`, and consolidation path in the
test to locate and make the ordering deterministic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 475c06a5-192b-4a45-a800-b923e99039ce

📥 Commits

Reviewing files that changed from the base of the PR and between 2110c4b and 276c0c5.

📒 Files selected for processing (19)
  • docs/architecture/agent-memory-system/spec.md
  • docs/issues/memory-recall-hot-path-keyword-recall/spec.md
  • src/main/presenter/memoryPresenter/index.ts
  • src/main/presenter/memoryPresenter/infra/memoryVectorStore.ts
  • src/main/presenter/memoryPresenter/infra/vectorStoreManager.ts
  • src/main/presenter/memoryPresenter/runtimeConstants.ts
  • src/main/presenter/memoryPresenter/services/maintenanceService.ts
  • src/main/presenter/memoryPresenter/services/managementService.ts
  • src/main/presenter/memoryPresenter/services/retrievalService.ts
  • src/main/presenter/memoryPresenter/types.ts
  • src/main/presenter/sqlitePresenter/tables/agentMemory.ts
  • src/shared/contracts/routes/memory.routes.ts
  • test/main/presenter/agentMemoryTable.test.ts
  • test/main/presenter/fakes/memoryFakes.ts
  • test/main/presenter/memoryExtraction.test.ts
  • test/main/presenter/memoryPresenter.test.ts
  • test/main/presenter/memorySearch.test.ts
  • test/main/presenter/memoryVectorStore.test.ts
  • test/main/routes/memoryDto.test.ts

Comment thread src/main/presenter/memoryPresenter/services/managementService.ts
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.

2 participants