fix(vector): address PR review round 14 — accurate offset-skip comment + news_item doc_id guard
Round-14 review surfaced one blocking and one important issue. context.py: the comment justifying `skip_offset_lookup` claimed chunk_start/end_offset weren't in _PAYLOAD_INDEX_FIELDS — round 13 indexed both as INTEGER, so the comment now actively misleads. Replace with the real reason: an indexed chunk_index miss is canonical (both paths hit the same Qdrant collection), and skipping the offset filter avoids a redundant round-trip. verification.py: hoist an is_valid_nextcloud_doc_id guard before the `int(d)` cast in _verify_news_items, mirroring the boundary-validation pattern already in _fetch_document_text. Coerce via `str(d)` because SearchResult.id is `int | str` (D1 forward-compat widening). Malformed ids now surface as a logger.warning rather than a generic debug line; fail-open semantics are preserved. 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
ae23bbe8b8
commit
c5020d9629
@@ -374,14 +374,13 @@ async def get_chunk_with_context(
|
|||||||
chunk_text = await _get_chunk_by_index_from_qdrant(
|
chunk_text = await _get_chunk_by_index_from_qdrant(
|
||||||
user_id, doc_id, doc_type, chunk_index
|
user_id, doc_id, doc_type, chunk_index
|
||||||
)
|
)
|
||||||
# When chunk_index is available, treat the indexed lookup as canonical
|
# When chunk_index is supplied, the indexed lookup is canonical: both the
|
||||||
# for every doc_type. A miss means the chunk is genuinely absent, not
|
# index path and the offset path query the same Qdrant collection, so an
|
||||||
# "fall back to the unindexed slow path". chunk_start/end_offset aren't
|
# indexed miss means the chunk is genuinely absent. Skipping the offset
|
||||||
# in _PAYLOAD_INDEX_FIELDS, so the offset filter 400s in Qdrant Cloud
|
# filter avoids a redundant Qdrant round-trip. Legacy data without
|
||||||
# strict mode and surfaces a misleading logger.error. Legacy data
|
# chunk_index (pre-cbcoutinho/astrolabe#75) still hits the offset path
|
||||||
# without chunk_index (pre-cbcoutinho/astrolabe#75) still hits the
|
# and degrades to a None chunk with a WARNING; that's the same behavior
|
||||||
# offset path and degrades to a None chunk with a WARNING; that's the
|
# get_chunk_bbox_and_page_from_qdrant already documents.
|
||||||
# same behavior get_chunk_bbox_and_page_from_qdrant already documents.
|
|
||||||
skip_offset_lookup = chunk_index is not None
|
skip_offset_lookup = chunk_index is not None
|
||||||
if chunk_text is None and not skip_offset_lookup:
|
if chunk_text is None and not skip_offset_lookup:
|
||||||
chunk_text = await _get_chunk_from_qdrant(
|
chunk_text = await _get_chunk_from_qdrant(
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ from nextcloud_mcp_server.search.algorithms import (
|
|||||||
NextcloudClientProtocol,
|
NextcloudClientProtocol,
|
||||||
SearchResult,
|
SearchResult,
|
||||||
)
|
)
|
||||||
|
from nextcloud_mcp_server.utils.validation import is_valid_nextcloud_doc_id
|
||||||
from nextcloud_mcp_server.vector.eviction import delete_document_points
|
from nextcloud_mcp_server.vector.eviction import delete_document_points
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -388,6 +389,15 @@ async def _verify_news_items(
|
|||||||
# above for why this is narrower than the API-response failure path.
|
# above for why this is narrower than the API-response failure path.
|
||||||
accessible: set[str] = set()
|
accessible: set[str] = set()
|
||||||
for d in doc_ids:
|
for d in doc_ids:
|
||||||
|
# SearchResult.id is `int | str` (D1: forward-compat widening). Coerce
|
||||||
|
# to str so the validator's regex applies consistently to both shapes.
|
||||||
|
if not is_valid_nextcloud_doc_id(str(d)):
|
||||||
|
logger.warning(
|
||||||
|
"Malformed news_item doc_id %r in verifier; keeping (cannot verify)",
|
||||||
|
d,
|
||||||
|
)
|
||||||
|
accessible.add(d)
|
||||||
|
continue
|
||||||
try:
|
try:
|
||||||
if int(d) in present_ids:
|
if int(d) in present_ids:
|
||||||
accessible.add(d)
|
accessible.add(d)
|
||||||
|
|||||||
Reference in New Issue
Block a user