fix(core): carry corpus_id on Embedding for vector corpus scoping (ADR-0004 §3) - #175
Merged
Merged
Conversation
…R-0004 §3)
Close the ADR-0004 §3 gap: Embedding carried no corpus, so the vector arm
could not honour the corpus_ids filter on retrieve_ids — the noop store
ignored corpus_ids entirely and QdrantVectorStore stamped an empty corpus
("corpus_id not in Embedding"). A corpus-scoped vector retrieval could
therefore surface chunks from sibling corpora.
Add an optional corpus_id to Embedding (core type + proto field 6 + the
regenerated dist schema). The embedder SPI has no corpus, so the ingest
pipeline stamps each embedding from its source Chunk; the noop store and the
five backends now filter on corpus_ids and surface corpus_id on the ChunkRef.
A None corpus never matches a non-empty corpus_ids filter — the safe,
no-leak direction (query-side / HyDE embeddings carry no corpus). ragctl's
noop demos pass corpus_id through. Adds contract tests (isolation / surfacing
/ empty-filter / none-never-matches) + an ingest corpus-scoping test; ADR-0004
§3 and the backends reference updated.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
officialCodeWork
pushed a commit
that referenced
this pull request
Jun 9, 2026
… doc tests (Step 7.5) Publish the docs as a Docusaurus 3 site that sources the repo docs/ tree in place (single source of truth, no copy step; markdown.format 'detect' so the hand-written .md renders as CommonMark). - website/: Docusaurus scaffold (config, sidebars, theme, tsconfig). - scripts/gen_api_reference.py: renders dist/openapi.json -> docs/reference/ rest-api.md (43 paths). Drift-gated like dist/schemas + the proto stubs. - tests/docs/: asserts every ragctl subcommand and /v1 path in a quickstart is real (registered CLI command / OpenAPI path). No services needed. - .github/workflows/docs.yml: api-ref drift, doc tests, codespell, lychee offline link-check, npm run build. - task docs:api / docs:dev / docs:build. Deferred: Algolia search, versioned docs, the deploy workflow. Also records the backlog PR-history rows for #175-#177. ADR-0047. Verified locally: ruff, ruff format, tests/docs (3), gen_api_reference run, 208-link relative check. (npm site build is a CI step.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix(core): carry
corpus_idonEmbeddingfor vector corpus scoping (ADR-0004 §3)The bug
Embeddingcarried no corpus, so the vector arm could not honour thecorpus_idsfilter onretrieve_ids: the noop store ignoredcorpus_idsentirely and
QdrantVectorStorestamped an empty corpus. A corpus-scoped vectorretrieval could therefore surface chunks from sibling corpora — a tenant/corpus
isolation gap (ADR-0004 §3).
The fix
corpus_idtoEmbedding(core type +proto/core.protofield 6 + regenerated
dist/schemas/Embedding.json).from its source
Chunk; the noop store and all five vector backends nowfilter on
corpus_idsand surfacecorpus_idon theChunkRef.Nonecorpus never matches a non-emptycorpus_idsfilter — the safe,no-leak direction (query-side / HyDE embeddings carry no corpus).
Verification (local — see note)
mypy --strict(329 files) ✅ ·ruff✅pytestcontract + ingest + core + backends + ingest + ragctl ✅🤖 Generated with Claude Code