refactor(search): address PR #750 round 6 review feedback
Closes out the remaining nits flagged in the round-6 review. Critical: - _verify_files contract comment now enumerates all None-return cases (404 + malformed PROPFIND XML) and documents the false-eviction trade-off; self-healing via re-indexing recovers - int(r.id) cast at the SemanticSearchResult boundary now raises a TypeError with explicit doc_type/value context instead of bubbling up as an opaque "Search failed: ..." McpError Design observations: - nc_semantic_search_answer docstring documents the per-note round-trip cost from the post-verification race guard - News verification latency hint added to configuration.md - SemanticSearchResponse exposes verified_count + dropped_count so short result pages on high-ghost-density indexes are distinguishable from genuine scarcity. verify_search_results now returns (kept, dropped_count); production caller and tests updated Minor: - Comment clarifies the .get() fallback in verify_search_results is defensive only (run_verifier always populates the entry) - Eviction task-group guard narrowed from except Exception to except RuntimeError (the only documented failure mode of TaskGroup.start_soon on a closed group) - Indexer logs a warning when a deck_card task is missing board_id/stack_id, surfacing data-quality issues at index time rather than at verification time - New unit test covers the news verifier's non-numeric-id fail-open path (one bad doc_id keeps the entire batch) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
ffcca23a7b
commit
e8df6003c5
@@ -58,9 +58,10 @@ async def test_verify_keeps_accessible_note(
|
||||
note_id = temporary_note["id"]
|
||||
results = [_result_for_note(note_id)]
|
||||
|
||||
kept = await verify_search_results(nc_client, results)
|
||||
kept, dropped_count = await verify_search_results(nc_client, results)
|
||||
|
||||
assert [r.id for r in kept] == [note_id]
|
||||
assert dropped_count == 0
|
||||
spy_evict.assert_not_awaited()
|
||||
|
||||
|
||||
@@ -96,9 +97,12 @@ async def test_verify_drops_deleted_note_and_schedules_eviction(
|
||||
await nc_client.notes.get_note(note_id)
|
||||
assert exc_info.value.response.status_code == 404
|
||||
|
||||
kept = await verify_search_results(nc_client, [_result_for_note(note_id)])
|
||||
kept, dropped_count = await verify_search_results(
|
||||
nc_client, [_result_for_note(note_id)]
|
||||
)
|
||||
|
||||
assert kept == [], "deleted note must not pass verification"
|
||||
assert dropped_count == 1
|
||||
spy_evict.assert_awaited_once_with(note_id, "note", nc_client.username)
|
||||
|
||||
|
||||
@@ -126,9 +130,10 @@ async def test_verify_mixed_accessible_and_deleted(
|
||||
_result_for_note(accessible_id),
|
||||
_result_for_note(ghost_id),
|
||||
]
|
||||
kept = await verify_search_results(nc_client, results)
|
||||
kept, dropped_count = await verify_search_results(nc_client, results)
|
||||
|
||||
assert [r.id for r in kept] == [accessible_id]
|
||||
assert dropped_count == 1
|
||||
spy_evict.assert_awaited_once_with(ghost_id, "note", nc_client.username)
|
||||
|
||||
|
||||
@@ -158,9 +163,10 @@ async def test_verify_dedupes_chunks_of_same_document(
|
||||
for i in range(3)
|
||||
]
|
||||
|
||||
kept = await verify_search_results(nc_client, results)
|
||||
kept, dropped_count = await verify_search_results(nc_client, results)
|
||||
|
||||
# All three chunks kept (they're all from the same accessible note)
|
||||
assert len(kept) == 3
|
||||
assert dropped_count == 0
|
||||
# ...but verification only fetched the note ONCE
|
||||
assert spy_get_note.await_count == 1
|
||||
|
||||
Reference in New Issue
Block a user