Skip to content

fix(polyphonic): hydrate content before diversity ranking#471

Merged
AxDSan merged 3 commits into
mnemosyne-oss:mainfrom
dplush:fix/polyphonic-content-similarity
Jul 16, 2026
Merged

fix(polyphonic): hydrate content before diversity ranking#471
AxDSan merged 3 commits into
mnemosyne-oss:mainfrom
dplush:fix/polyphonic-content-similarity

Conversation

@dplush

@dplush dplush commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes the regression introduced by #389: PolyphonicResult did not carry a content attribute, so the new content-Jaccard diversity scorer crashed and polyphonic recall returned no results.

The engine now hydrates source content in two bounded queries (working + episodic) after RRF fusion and before diversity ranking. Synthetic/unmapped results retain empty content and are handled safely.

Verification

  • Reproduced the current-main PolyphonicResult has no attribute content CI failure.
  • Added direct regression coverage for content hydration and content-Jaccard diversity.
  • Focused polyphonic/vector suite: 40 passed, 4 skipped.
  • py_compile and git diff --check pass.

Summary

Fixes a polyphonic recall regression where PolyphonicResult lacked a content attribute, breaking the content-Jaccard diversity re-ranking and potentially yielding empty polyphonic recall output. The polyphonic recall pipeline now hydrates PolyphonicResult.content from Mnemosyne’s local tiered memories immediately after RRF fusion and before diversity re-ranking; synthetic/unmapped IDs remain safe via empty content.

Architecture impact

  • Tiered memory (working/episodic/BEAM):

    • Adds content: str = "" to PolyphonicResult.
    • Introduces _hydrate_result_content() which populates result.content by performing local SQLite reads from working_memory and episodic_memory (does not change BEAM storage/schema).
    • Hydration only fills content when it’s currently empty (if result is not None and not result.content).
  • Retrieval strategies / ranking:

    • Preserves the multi-voice (vector/graph/fact/temporal) recall flow and RRF fusion, but inserts self._hydrate_result_content(combined) right after combining voices and before _diversity_rerank(), so content-Jaccard operates on real source text rather than missing attributes.
    • Hydration is bounded to two known tables and targets only the fused result IDs via an IN (...) placeholder query.
  • Local-first / privacy posture:

    • Reads content exclusively from the local SQLite tiered stores (working_memory, episodic_memory); no external network calls or external I/O are introduced.
    • Safely tolerates schema drift/absent tables by skipping sqlite3.OperationalError and leaving content as "" for unmapped/synthetic IDs.
  • Agent integration surfaces (Hermes, MCP, CLI):

    • No direct contract changes to Hermes/MCP/CLI; this is an internal fix within the polyphonic recall engine that runs under the existing retrieval feature path.
    • The model shape gains internal provenance (PolyphonicResult.content) used for ranking, without altering request/response semantics at the integration layer.
  • Veracity / sync layer / consolidation pipeline:

    • No changes to consolidation, veracity scoring, or sync behavior. The change is localized to the polyphonic recall re-ranking stage.
  • Maintainability / resilience:

    • Connection reuse aligns with Mnemosyne’s thread-local SQLite pattern: _hydrate_result_content() uses the engine’s shared conn when available, otherwise creates a short-lived connection and closes it.
    • Explicit test coverage prevents future regressions in content hydration and diversity similarity behavior.

Verification

  • Adds regression tests ensuring:
    • Hydration pulls exact DB-stored content and drives content-Jaccard similarity to the expected value (pytest.approx(1/9)).
    • Unmapped/synthetic IDs remain harmless: hydrated content == "" and similarity for identical empty content inputs returns 0.0.
  • The focused polyphonic/vector suite passes with the reported skips; py_compile and git diff --check also pass.

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 13f52f5d-bc81-4e03-8b9e-c5f845f8fbce

📥 Commits

Reviewing files that changed from the base of the PR and between 70f2267 and 278b228.

📒 Files selected for processing (1)
  • tests/test_beam_e5_polyphonic_recall.py

📝 Walkthrough

Walkthrough

Polyphonic recall results now store source content hydrated from memory tables before diversity re-ranking. The recall flow and regression tests cover database-backed content, unmapped IDs, and similarity estimation.

Changes

Polyphonic content hydration

Layer / File(s) Summary
Content field and database hydration
mnemosyne/core/polyphonic_recall.py
PolyphonicResult stores hydrated source text, and _hydrate_result_content() retrieves it from available memory tables using shared or temporary SQLite connections.
Hydated ranking flow and regression coverage
mnemosyne/core/polyphonic_recall.py, tests/test_beam_e5_polyphonic_recall.py
recall() hydrates fused results before diversity ranking, while tests verify database content, unmapped IDs, and similarity estimation.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: kohai-ut

Sequence Diagram(s)

sequenceDiagram
  participant RecallEngine
  participant SQLiteMemory
  participant DiversityRerank
  RecallEngine->>RecallEngine: Fuse voice results
  RecallEngine->>SQLiteMemory: Fetch source content by result IDs
  SQLiteMemory-->>RecallEngine: Return matching content
  RecallEngine->>DiversityRerank: Rank hydrated results
Loading
🚥 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 clearly summarizes the main fix: hydrating polyphonic content before diversity ranking.
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 unit tests (beta)
  • Create PR with unit tests

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@tests/test_beam_e5_polyphonic_recall.py`:
- Around line 178-199: Expand the related polyphonic recall tests around
PolyphonicRecallEngine.recall and _hydrate_result_content to cover grouped
integration cases: verify recall hydrates content before diversity reranking,
hydration works when conn=None via a temporary connection, unmapped synthetic
IDs retain empty content and produce zero similarity, and candidate sets larger
than the hydration batch size are fully hydrated. Preserve the existing fixture
style and assert retrieval behavior rather than only testing the helper
directly.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: efaa45f4-f697-49b7-9c92-e2c3eae621e8

📥 Commits

Reviewing files that changed from the base of the PR and between 0a64d2e and 2bb176b.

📒 Files selected for processing (2)
  • mnemosyne/core/polyphonic_recall.py
  • tests/test_beam_e5_polyphonic_recall.py

Comment thread tests/test_beam_e5_polyphonic_recall.py Outdated
Comment on lines +178 to +199
def test_diversity_hydrates_source_content(self, temp_db):
"""Content Jaccard must use DB content, not a missing result attribute."""
from mnemosyne.core.polyphonic_recall import (
PolyphonicRecallEngine,
RecallResult,
)

beam = BeamMemory(session_id="e5-content", db_path=temp_db)
first_id = beam.remember("Alice deployed the auth service")
second_id = beam.remember("Bob fixed the billing dashboard")
engine = PolyphonicRecallEngine(db_path=temp_db, conn=beam.conn)
combined = engine._combine_voices([
RecallResult(first_id, 0.8, "vector", {}),
RecallResult(second_id, 0.7, "vector", {}),
])

engine._hydrate_result_content(combined)
assert combined[first_id].content == "Alice deployed the auth service"
assert combined[second_id].content == "Bob fixed the billing dashboard"
assert engine._estimate_similarity(
combined[first_id], combined[second_id]
) < 0.8

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Cover the recall integration and hydration edge cases.

This meaningfully tests the helper, but not the regression path through recall(). Add grouped cases for: (1) recall() hydrating before diversity reranking, (2) conn=None temporary-connection hydration, (3) unmapped synthetic IDs retaining empty content with zero similarity, and (4) a candidate set above the hydration batch size.

As per path instructions, "tests/**: Group ALL suggestions for related fixtures/test files together" and verify meaningful coverage of retrieval behavior.

🤖 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 `@tests/test_beam_e5_polyphonic_recall.py` around lines 178 - 199, Expand the
related polyphonic recall tests around PolyphonicRecallEngine.recall and
_hydrate_result_content to cover grouped integration cases: verify recall
hydrates content before diversity reranking, hydration works when conn=None via
a temporary connection, unmapped synthetic IDs retain empty content and produce
zero similarity, and candidate sets larger than the hydration batch size are
fully hydrated. Preserve the existing fixture style and assert retrieval
behavior rather than only testing the helper directly.

Source: Path instructions

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/test_beam_e5_polyphonic_recall.py (1)

197-199: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert the exact Jaccard result.

The two seeded contents have no shared words, so the expected similarity is 0.0; < 0.8 would also accept incorrect results such as 0.79.

Proposed assertion
-        ) < 0.8
+        ) == 0.0
🤖 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 `@tests/test_beam_e5_polyphonic_recall.py` around lines 197 - 199, Update the
assertion for engine._estimate_similarity(combined[first_id],
combined[second_id]) to require the exact expected Jaccard similarity of 0.0
instead of merely checking that it is below 0.8.

Source: Path instructions

🤖 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.

Outside diff comments:
In `@tests/test_beam_e5_polyphonic_recall.py`:
- Around line 197-199: Update the assertion for
engine._estimate_similarity(combined[first_id], combined[second_id]) to require
the exact expected Jaccard similarity of 0.0 instead of merely checking that it
is below 0.8.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a6cfda31-b011-420b-a720-3043bd966d87

📥 Commits

Reviewing files that changed from the base of the PR and between 2bb176b and 70f2267.

📒 Files selected for processing (1)
  • tests/test_beam_e5_polyphonic_recall.py

@AxDSan
AxDSan merged commit 75c694a into mnemosyne-oss:main Jul 16, 2026
4 of 8 checks passed
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