Skip to content

feat(receipts): mechanical byte-offset receipt verifier (phase a)#481

Merged
plind-junior merged 4 commits into
testfrom
feat/span-receipts
Jul 15, 2026
Merged

feat(receipts): mechanical byte-offset receipt verifier (phase a)#481
plind-junior merged 4 commits into
testfrom
feat/span-receipts

Conversation

@plind-junior

Copy link
Copy Markdown
Member

phase a of the fidelity pivot: the mechanical byte-offset receipt — the
primitive that lets the review gate become arithmetic instead of a person.

a claim's evidence can now carry a byte-offset span [byte_start, byte_end)
into its cited source's raw bytes, and receipts.verify_receipt checks the
quoted text against those bytes by string comparison alone — no llm, no judge.
the quoted span is in the source at those offsets or it is not. three states,
kept distinct because the gate treats them differently:

  • VERIFIED — the span decodes to exactly the quote
  • FORGED — a span is claimed but is out of range, inverted, undecodable,
    mismatched, or points at a source the kb does not hold
  • NO_RECEIPT — no offsets to verify against

byte offsets rather than char offsets because sources are stored as raw
content-addressed bytes, and under utf-8 a character index diverges from a byte
index at the first multibyte codepoint; the receipt indexes the artifact that
was actually hashed. locate_span / receipt_for_quote are the quote half of
the retrieve-then-quote loop — they find the verbatim span or drop the claim,
the mechanical form of "drops any claim it cannot quote", with a property test
tying them to the verifier (anything the locator emits verifies).

correcting the roadmap's own assumption: Evidence / cite() / DERIVED_FROM
existed, but there were no byte offsets and no verifier. that keystone is what
this adds.

scope: purely additive — two optional Evidence fields and one new module. no
existing path changes behaviour yet. draft because the rest of phase a (wiring
receipt_for_quote into propose_claim/approve, surfacing receipt status
through cite() and _meta) lands on this branch next; opening now so the
primitive is reviewable while it grows.

gate: pytest (full, minus embeddings), mypy src (96 files), ruff — all
green. 20 new tests in tests/test_receipts.py.

the atom the fidelity pivot rests on: a claim's evidence can now carry a
byte-offset span [byte_start, byte_end) into the cited source's raw bytes,
and receipts.verify_receipt checks the quoted text against the source bytes
by string comparison alone — no llm, no judge. the quoted span is in the
source at those offsets or it is not.

three receipt states, kept distinct because the review gate treats them
differently: VERIFIED (span decodes to exactly the quote), FORGED (span
claimed but out of range / inverted / undecodable / mismatched, or the
source is absent from the kb), NO_RECEIPT (no offsets to verify). byte
offsets rather than char offsets because sources are stored as raw
content-addressed bytes and utf-8 char indices diverge from byte indices at
the first multibyte codepoint.

verify_evidence loads the source from the store and delegates; a receipt
whose source is missing is reported forged, never verified, so an
unverifiable citation can never read as approved. purely additive — two
optional evidence fields and one new module, no existing path changes
behaviour yet. this is the primitive phase d's auto-approve will call.
the quote step of phase a's retrieve-then-quote loop. locate_span finds the
byte offsets of a quote's first exact occurrence in a source's raw bytes, or
None when the quote is not present verbatim. the match is deliberately exact
and case-sensitive — no normalization, no fuzzy match — because the receipt's
value is that it is checkable by string comparison, so a paraphrase must fail
to locate and be dropped.

receipt_for_quote composes the locator with the schema: it returns an
Evidence whose byte-offset receipt is guaranteed to verify against the same
bytes, or None to drop an unquotable claim — the mechanical form of "drops
any claim it cannot quote." a property test ties the two halves together:
anything the locator produces verifies VERIFIED.
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2ddeaf55-19c3-4fa9-a55c-424af4a1f0df

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/span-receipts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added storage kb storage, migrations, schemas, and proposals tests tests and fixtures size: M 200-499 changed non-doc lines labels Jul 15, 2026
propose_quoted_claim wires the span locator into the gated write path: given
a source and the quote that supports a claim, it locates the verbatim span,
stores a receipt-backed Evidence, and files a normal claim proposal citing
it. when the quote is not in the source it returns None and files nothing —
the mechanical form of "drops any claim it cannot quote."

the write still goes through propose_claim and the review gate; what is new
is that the filed claim now carries a byte-offset receipt the gate can verify
by string comparison. intake is idempotent: receipt_for_quote mints a
content-addressed evidence id from the span, so re-filing the same span reuses
the existing Evidence instead of duplicating it.

layering kept honest — proposals depends on the receipts primitive, not the
reverse. receipt_for_quote's evidence_id is now optional (content-addressed
default).
evaluate_claim_receipts is the function phase d's auto-approve will call: it
returns approve=True only when a claim cites at least one thing and every
citation is a receipt that verifies. a forged receipt, a bare source id (no
byte-offset span), an unknown id, or an empty citation list all reject, with
reasons naming each failure. the verdict is the conjunction of per-citation
string comparisons — no llm, no judge.

this completes the verification machinery for "human leaves the loop": schema
-> per-evidence verify -> receipt-backed intake -> per-claim verdict. what it
deliberately does NOT do yet is touch approve(); wiring the verdict into
automatic approval is the phase d step, gated behind the step 0 gate-integrity
and step 1 concurrency work so the auto-gate is not forgeable or
race-corruptible.
@github-actions github-actions Bot added size: L 500-999 changed non-doc lines and removed size: M 200-499 changed non-doc lines labels Jul 15, 2026
@plind-junior plind-junior merged commit 89b01fc into test Jul 15, 2026
9 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size: L 500-999 changed non-doc lines storage kb storage, migrations, schemas, and proposals tests tests and fixtures

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant