From 50c699ade76f0e5723ee7a48d0d4d6dc12096bb1 Mon Sep 17 00:00:00 2001 From: mishablank Date: Sun, 28 Jun 2026 14:33:19 +0400 Subject: [PATCH] fix: import merge_duplicate_notes in bot.py (/rebuild crashed with NameError) on_rebuild referenced merge_duplicate_notes without importing it; the merge branch only runs when the semantic index is enabled, which no test exercised. Add the import and a regression test that runs /rebuild with the index enabled. Co-Authored-By: Claude Opus 4.8 --- src/engram/bot.py | 1 + tests/test_bot_rebuild.py | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/engram/bot.py b/src/engram/bot.py index b22947b..703ba32 100644 --- a/src/engram/bot.py +++ b/src/engram/bot.py @@ -41,6 +41,7 @@ ) from .pdf import extract_pdf_text from .relinker import relink_note +from .retro import merge_duplicate_notes from .vault import VaultIndex, load_note_body, scan_vault, search_vault from .vision import ocr_image from .whisper import transcribe diff --git a/tests/test_bot_rebuild.py b/tests/test_bot_rebuild.py index 6bdeb14..a12dccc 100644 --- a/tests/test_bot_rebuild.py +++ b/tests/test_bot_rebuild.py @@ -3,6 +3,7 @@ from types import SimpleNamespace from engram import bot as bot_module +from engram import retro as retro_module from engram.vault import VaultIndex from tests.test_bot import ( _fake_callback_update, @@ -79,3 +80,27 @@ async def test_rebuild_builds_entity_pages(tmp_path, monkeypatch): assert "works on AI ([[a]])" in page.read_text(encoding="utf-8") last = update.effective_chat.send_message.call_args.args[0] assert "Rebuild done" in last + + +async def test_rebuild_runs_merge_branch_when_index_enabled(tmp_path, monkeypatch): + # Regression: on_rebuild must reach merge_duplicate_notes without a NameError + # when the semantic index is enabled. (The other rebuild test disables the + # index, so it never exercised the merge import.) + state = _make_state(tmp_path, monkeypatch) + stub = SimpleNamespace(dim=8, embed=lambda texts: [[1.0] * 8 for _ in texts]) + state._semantic_index.embedder = stub # enable merge branch + monkeypatch.setattr(state._semantic_index, "refresh", lambda: None) + # No duplicates found → no merge rewrites, no anthropic merge calls. + monkeypatch.setattr(retro_module, "find_semantic_duplicate", lambda *a, **k: None) + ai = tmp_path / "AI" + ai.mkdir() + (ai / "a.md").write_text("---\nc: x\n---\n# a\nbody\n", encoding="utf-8") + _set_text(state, "not json") # entity extraction yields nothing + + on_rebuild = bot_module.make_handlers(state)[13] + update = _fake_update(_fake_message(text="/rebuild")) + await on_rebuild(update, SimpleNamespace()) + + last = update.effective_chat.send_message.call_args.args[0] + assert "Rebuild done" in last + assert "merged 0" in last.lower() # merge phase ran (not skipped)