ADR-008 — GenerationResult + VerificationReport bumped to schema_version=2¶
Status: Accepted and implemented (2026-04-23).
Context¶
P6 landed NLI-based verify(). Two shape changes followed from it:
GenerationResult.sources—verify()needs access to the source list to score entailment, pair cites to sources, and run the coverage check. Options were:Pass
sourcesas an argument toverify(). Awkward — callers would have to keep the source list alongside the result.Carry
sourcesonGenerationResult. Self-contained; serialised results round-trip cleanly.
VerificationReport.uncited_but_entailed— P1’s schema usedlist[int](sentence indices). P6 needs richer information per flagged sentence: span, candidate source, and entailment score. Introduced the newUncitedClaimpydantic model.
Both are breaking changes to the §10.3 contract (adding / reshaping fields on the pinned pydantic models).
Decision¶
Bump GenerationResult.schema_version and VerificationReport.schema_version
from 1 → 2. Update both snapshot tests in
tests/integration/test_schemas.py; update the §10.3-related tests in
tests/unit/test_core.py.
Consequences¶
Citeformer.generate()now setsresult.sources = list(sources)so default callers don’t think about it.Users hand-constructing
GenerationResult(tests, demo scripts, custom pipelines) must passsources=[...]; if they don’t,verify()raisesValueErrorwith a clear hint rather than downstream NLI crashes.VerificationReport.uncited_but_entailednow carriesUncitedClaim(span, candidate_source_id, entailment_score)— richer debug output for users writing their own presentation layer over the report.Snapshot tests regenerated; CHANGELOG documents the bump in the
Contracts (§10)block.Pre-P6 serialised results (schema_version=1) are not forward-compatible — the
sourcesfield would be missing, plusuncited_but_entaileditems would be ints, not objects. We considered writing a migration shim; since citeformer is pre-1.0 and hasn’t shipped real releases, we skipped it. Post-1.0 we’d addmodel_validatoraliases to accept the v1 shape.