fix(vector): address PR review round 11 — broaden offset-skip gate, clarify ordering

- search/context.py: drop the doc_type=='file' guard on skip_offset_lookup
  so notes / deck cards / news items also bypass the unindexed offset
  fallback when chunk_index is available. Legacy chunk_index=None data
  still uses the offset path.
- vector/qdrant_client.py: clarify the backfill/_ensure_payload_indexes
  ordering invariant (backfill rewrites payload values only, never schema
  or indexes). Acknowledge OSS-vs-Cloud uncertainty in the 400-branch
  comment and the new-collection call-site comment.
- vector/scanner.py: hoist qdrant_client to function scope so the
  file-scroll block doesn't depend on a name bound inside the
  notes-scroll block.
- tests/unit/test_chunk_context_offset_gate.py: flip the note-with-
  chunk_index test to assert the offset fallback is skipped.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2026-05-09 17:59:41 +02:00
co-authored by Claude Opus 4.7
parent 47c531969f
commit f3ce46da0f
4 changed files with 55 additions and 21 deletions
+9 -6
View File
@@ -373,12 +373,15 @@ async def get_chunk_with_context(
chunk_text = await _get_chunk_by_index_from_qdrant(
user_id, doc_id, doc_type, chunk_index
)
# Skip the offset fallback for files when the indexed chunk_index
# lookup already ran: chunk_start/end_offset aren't indexed in Qdrant
# Cloud strict mode, so the call returns 400 and surfaces a misleading
# logger.error. The file fast-fail below correctly handles the miss
# without it.
skip_offset_lookup = chunk_index is not None and doc_type == "file"
# When chunk_index is available, treat the indexed lookup as canonical
# for every doc_type. A miss means the chunk is genuinely absent, not
# "fall back to the unindexed slow path". chunk_start/end_offset aren't
# in _PAYLOAD_INDEX_FIELDS, so the offset filter 400s in Qdrant Cloud
# strict mode and surfaces a misleading logger.error. Legacy data
# without chunk_index (pre-cbcoutinho/astrolabe#75) still hits the
# offset path and degrades to a None chunk with a WARNING; that's the
# same behavior get_chunk_bbox_and_page_from_qdrant already documents.
skip_offset_lookup = chunk_index is not None
if chunk_text is None and not skip_offset_lookup:
chunk_text = await _get_chunk_from_qdrant(
user_id, doc_id, doc_type, chunk_start, chunk_end