Skip to content

Contracts

The data model. Every model here is a frozen Pydantic v2 model with extra="forbid" — an unknown key is a construction-time error, not a field that gets quietly dropped (SPEC.md §2, fail closed).

Chunk carries character offsets into its source document, and Citation carries document ID + chunk ID + offsets. Together they are what makes "citations are verifiable" a checkable property rather than a claim: verify_citation re-reads the source file and confirms the span still says what the citation says it says.

RetrievalResult carries source_class and extractor (ADR-0016), which route citation verification to the right re-derivation path. Their defaults — "text" and None — exist for backward compatibility with a published contract, not as a value any construction site should take implicitly: an AST-level test asserts that every RetrievalResult(...) in src/groundkit/ passes both fields explicitly. evals/ is exempt, and deliberately — the two sites there build synthetic fixtures whose provenance is invented for the harness rather than carried through from a store record, so there is nothing upstream of them for a default to silently replace.

groundkit.contracts

Core data model: Document, Chunk, RetrievalResult, Citation, SearchResponse, EmbeddingIdentity, CollectionManifest.

Ported from ARP's agentic_v2/rag/contracts.py per ADR-0001, with two deliberate changes: chunks carry character offsets into their source document (the substrate citation resolution depends on — SPEC.md §5.2), and the high-confidence threshold is a named constant instead of an inline literal.

All models are frozen and reject unknown fields. Functions that transform these models return new objects; nothing here is mutated.

Chunk

Bases: BaseModel

A chunk of text extracted from a document, addressable by offsets.

content must be the exact substring document.content[start_offset:end_offset] of its parent document — chunker tests enforce the substring property; this model enforces the length arithmetic so a drifting chunker cannot construct a valid Chunk.

Attributes:

Name Type Description
chunk_id str

Unique identifier for this chunk.

document_id str

ID of the parent document.

chunk_index int

Position of this chunk within the document.

content str

The chunk text.

start_offset int

Character offset of content in the parent document.

end_offset int

One past the last character of content in the parent.

metadata dict[str, Any]

Inherited + chunk-specific metadata.

content_hash property
content_hash: str

SHA-256 hash of the chunk content for deduplication.

Recomputed on every access, and deliberately not a functools.cached_property (GK-028). Staleness is not the objection -- the model is frozen and the hash is a pure function of content, so a cache could never disagree with its input. Unfreezing is: pydantic's __setattr__ special-cases cached_property before it consults the frozen config (pydantic/main.py::BaseModel._setattr_handler, checked against the pinned 2.13 in this tree), so chunk.content_hash = "..." would stop raising and start writing straight into __dict__. Every later reader -- BM25's and dense's tie-breaks, the value index/metadata.py persists -- would then use a string that is not the hash of content, on a model whose entire contract is that it cannot be changed after validation. Trading that for an unmeasured saving on a bounded string is the wrong way round; a caller that wants the hash once caches it itself at build time (index/bm25.py). tests/test_contracts.py pins the assignment refusal so the trade-off is enforced rather than remembered.

Citation

Bases: BaseModel

A verifiable pointer from a retrieved passage back to its source.

Attributes:

Name Type Description
document_id str

ID of the source document.

chunk_id str

ID of the cited chunk.

source str

The document's source identifier (path/URL).

source_class SourceClass

How to resolve source back to text (ADR-0016). Carried on the citation rather than looked up at resolution time so a resolver cannot verify a document under a different class's assumptions than the one it was ingested under.

extractor str | None

Extractor identity for an extracted source; a resolver must refuse rather than slice when its own differs.

start_offset int

Character offset where the cited span starts.

end_offset int

One past the last character of the cited span.

CollectionManifest

Bases: BaseModel

The persisted embedding identity a collection was built with (ADR-0004).

Identity is the triple (provider, model_name, dimensions), checked as a triple — never dimensions alone. Distinct embedding models can share a vector width (nomic-embed-text and all-mpnet-base-v2 are both 768-dimensional), so a width-only check would admit exactly the model swap this manifest exists to reject. Written once, by SQLiteMetadataStore.write_manifest on a collection's first dense write, and immutable for the collection's lifetime thereafter.

Attributes:

Name Type Description
provider str

Embedding provider the collection was built with.

model_name str

Model identifier the collection was built with.

dimensions int

Embedding vector width the collection was built with.

created_at str

ISO-8601 UTC timestamp of the manifest's creation.

Document

Bases: BaseModel

A source document before chunking.

Attributes:

Name Type Description
document_id str

Unique identifier (auto-generated UUID if omitted).

source str

File path, URL, or other source identifier.

content str

Raw text content of the document.

source_class SourceClass

How content relates to source, and therefore how a citation into this document is verified (ADR-0016). Defaults to "text", which is the only class a loader produced before PDF/HTML/URL support and the one the plain re-read-and-compare check assumes.

extractor str | None

Identity of the extractor that produced content, for extracted documents only. Recorded because two extractor versions produce two incompatible offset spaces under one name — the same argument ADR-0004 makes about two embedding models and one semantic space. None for every other class.

metadata dict[str, Any]

Arbitrary key-value metadata (author, date, etc.).

EmbeddingIdentity

Bases: BaseModel

The embedding identity triple a collection is bound to (ADR-0004 decision 2).

The input to a manifest write or verify, and the exact set of fields ADR-0004 defines identity as — no more. Distinct from :class:CollectionManifest, which is what comes back out of the store and additionally carries the created_at stamp the store assigns.

Deliberately not an EmbeddingConfig: that model also carries operational settings (base_url, batch_size, timeout_seconds) that have nothing to do with which semantic space a collection lives in, and its provider is a closed Literal over the providers this repo ships, which a third-party :class:~groundkit.providers.protocols.EmbeddingProtocol implementation could not satisfy. Taking the narrow triple lets the identity be read straight off the embedder that actually produces the vectors.

Attributes:

Name Type Description
provider str

Embedding provider identity (e.g. "ollama").

model_name str

Model identifier used to embed.

dimensions int

Embedding vector width.

RetrievalResult

Bases: BaseModel

A single retrieval result, always citation-bearing.

Producers must normalize scores into >= 0.0 before construction — feeding raw model logits into this contract is the ARP defect ADR-0001 hazard 2 records; it is a producer bug, not a contract relaxation.

Attributes:

Name Type Description
content str

The matched chunk text.

score float

Relevance score (>= 0.0, higher is better).

document_id str

ID of the source document.

chunk_id str

ID of the matched chunk.

source str

The document's source identifier (path/URL).

start_offset int

Character offset of the match in its document.

end_offset int

One past the last character of the match.

metadata dict[str, Any]

Chunk metadata.

citation property
citation: Citation

The verifiable source pointer for this result.

is_high_confidence property
is_high_confidence: bool

True if score meets :data:HIGH_CONFIDENCE_SCORE.

SearchResponse

Bases: BaseModel

Response from a search query.

Attributes:

Name Type Description
query str

The original query text.

results list[RetrievalResult]

Ordered list of retrieval results.

total_results int

Total number of results found.

metadata dict[str, Any]

Pipeline metadata (latency, stages, etc.).