feat: add unified memory routing to consolidation service

- Add MemoryRouteClassification and MemoryRoutingResult models
- Implement unified classifier (_classify_web_results_unified) that routes
  web results to: wiki, volatile, file (Paperless), prefetch, or skip
- Add routing methods: _route_to_volatile, _route_to_files, _register_prefetch
- Update _process_search to use unified classifier instead of separate analysis
- Add get_volatile_cache_service factory to dependencies
- Wire volatile_service and settings_client into ConsolidationService
- Update ConsolidationResult/Response with new routing counters

Test fixes:
- Fix WikiJSClient fixtures to use api_token instead of username/password
- Fix entity linking test assertions to expect full user-namespaced paths
- Add sample_unified_classification fixture for new classifier format

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-28 17:19:20 +01:00
co-authored by Claude Opus 4.5
parent ab892745fa
commit 1f47b052d8
9 changed files with 533 additions and 104 deletions
+6 -7
View File
@@ -55,8 +55,7 @@ async def wiki_client(wikijs_test_config) -> AsyncGenerator[WikiJSClient, None]:
"""Get Wiki.js client."""
client = WikiJSClient(
base_url=wikijs_test_config["base_url"],
username=wikijs_test_config["username"],
password=wikijs_test_config["password"]
api_token=wikijs_test_config["api_token"]
)
yield client
@@ -212,7 +211,7 @@ class TestAddEntityLinksToContent:
updated, count = add_entity_links_to_content(content, entities)
assert count == 1
assert "[Docker](/docker)" in updated
assert "[Docker](/users/test/docker)" in updated
def test_add_multiple_instances(self):
"""Test linking all instances of an entity."""
@@ -224,7 +223,7 @@ class TestAddEntityLinksToContent:
updated, count = add_entity_links_to_content(content, entities)
assert count == 2 # Both instances linked
assert updated.count("[Docker](/docker)") == 2
assert updated.count("[Docker](/users/test/docker)") == 2
def test_skip_entities_without_path(self):
"""Test that entities without wiki pages are not linked."""
@@ -237,7 +236,7 @@ class TestAddEntityLinksToContent:
updated, count = add_entity_links_to_content(content, entities)
assert count == 1 # Only Docker
assert "[Docker](/docker)" in updated
assert "[Docker](/users/test/docker)" in updated
assert "[Kubernetes]" not in updated
def test_protect_existing_links(self):
@@ -252,7 +251,7 @@ class TestAddEntityLinksToContent:
# Should link the second "Docker" but not the one already linked
assert count == 1
assert "[Docker](https://docker.com)" in updated # Preserved
assert updated.count("[Docker](/docker)") == 1
assert updated.count("[Docker](/users/test/docker)") == 1
def test_no_nested_links(self):
"""Test that entity names in URLs are not linked."""
@@ -278,7 +277,7 @@ class TestAddEntityLinksToContent:
updated, count = add_entity_links_to_content(content, entities)
# Should link "Machine Learning" first, leaving "Machine" alone
assert "[Machine Learning](/ml)" in updated
assert "[Machine Learning](/users/test/ml)" in updated
assert count >= 1