feat(api): accept granularity on /api/v1/vector-viz/search - #1359
feat(api): accept granularity on /api/v1/vector-viz/search#1359cbcoutinho wants to merge 1 commit into
granularity on /api/v1/vector-viz/search#1359Conversation
This endpoint is the only one the Astrolabe app's search page calls, and it did not accept `granularity` at all — it passed no value to the search algorithm and hardcoded `chunk` into its metrics. So `granularity="document"` (one row per document rather than per passage) was unreachable from the UI, even though `/api/v1/search` and `nc_semantic_search` both expose it. That mattered beyond a missing feature: ADR-034's relevance curves were fitted at document granularity, so the app page could not request the retrieval shape its own relevance numbers were calibrated on. Brings the endpoint into line with its sibling on all four points: the value is read, an unknown value is rejected rather than silently downgraded to chunk, the document+semantic combination is refused with the same 422 payload, and the value reaches both the single-search and doc_types branches of the algorithm call. Search metrics now report the granularity actually used. Found by auditing which search settings the Astrolabe UI can reach versus what the server supports, after a retrieval benchmark turned out to be sweeping parameters no deployment could request. Deck #1070. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Claude finished @cbcoutinho's task in 2m 26s —— View job Review
Overall this is a clean, well-motivated parity fix — the new validation/422/prefetch logic in One real bug found in the diff, plus a note on the test-coverage gap that would have caught it. 🔴 Bug:
|
|



POST /api/v1/vector-viz/searchis the only endpoint the Astrolabe app's search page calls, and it did not acceptgranularityat all — it passed no value to the search algorithm and hardcodedchunkinto its metrics.granularity="document"(one row per document rather than per passage) was therefore unreachable from the UI, even though/api/v1/searchandnc_semantic_searchboth expose it.That matters beyond a missing feature: ADR-034's relevance curves were fitted at document granularity, so the app page could not request the retrieval shape its own relevance numbers were calibrated on.
How it was found
A benchmark sweep over rerankers, chunk sizes and embedders produced clean results — and then an audit of which of those settings the Astrolabe UI can actually reach found the answer was one (
limit, and only to 50). The numbers described configurations no user could request.granularitywas the worst case, because the endpoint had no such parameter at all.What changed
Brings the endpoint into line with its sibling on all four points:
chunkdocument+semantic/api/v1/searchreturnsdoc_typesbranchesAlso threads through
effective_pool_size(grouped=…)— the grouped prefetch is bounded byMAX_DOCUMENT_PREFETCH, so asking for more groups than it can fill makes Qdrant widen its grouping search and reorder the head before the reranker sees it — and makes search metrics report the granularity actually used rather than a hardcodedchunk.Compatibility
Purely additive. Omitting the field behaves exactly as before, which is what every existing Astrolabe release does (
test_default_granularity_is_chunkpins this). A client sendinggranularityto an older server is ignored rather than erroring, so there is no deployment-ordering requirement in either direction.Test coverage
New
tests/unit/api/test_vector_viz_granularity_api.py, 6 tests: default ischunk; the value reaches the algorithm on both the plain anddoc_typesbranches (a parameter threaded on one branch only would be invisible to anyone filtering by type, which the UI does on every search); unknown value → 400 without touching the algorithm;document+semantic→ 422 with the full payload asserted;chunk+semanticstill allowed.Verified end to end against a live login-flow stack with 60 indexed Deck cards —
granularity=documentreturns 200 with results, anddocument+semanticreturns the 422, which is what proves the server reads the value rather than accepting and ignoring it.e2e + contract: this adds a request parameter to an existing
/api/v1/*route rather than a new route or MCP tool. The provider pact covers only the public endpoints (/api/v1/status,/api/v1/vector-sync/status) — the authenticated surface including this one remains unverified pending the ADR-029 phase-4 Bearer-token/provider-state hook, which is a pre-existing gap tracked on Deck board 11, not one this PR introduces. Full-stack behaviour is covered by the manual verification above; there is no dedicatede2emarker in this repo.3,609 unit tests pass;
ruff,ruff format,tyclean.Deck #1070. The Astrolabe side (sending
fusion/granularity/min_relevance, plus a 422 passthrough fix) is a separate PR in that repo.This PR was generated with the help of AI, and reviewed by a Human