feat(tutor): receipt re-verification with typed CHAIN_BROKEN / VERDICT_MISMATCH failures#1
Merged
Merged
Conversation
…T_MISMATCH failures Recompute a tutor receipt's own evidence instead of trusting its stored booleans (verified / ledgerVerified are author-controlled and ignored): the hash chain over the witnessed practice entries must recompute, and the stored mastery verdict must re-derive from the recorded attempts under the recorded policy. A chainless receipt re-verifies as UNVERIFIED, never as verified. - src/tutor/reverify.mjs: reverifyReceipt / reverifyFiles / formatReverify / reverifySelfCheck - CLI: learn tutor reverify <id> [--file <receipt.json>], exit 0 only when every checked receipt re-verifies VERIFIED with a witnessed summary digest; any typed failure or UNVERIFIED exits 1 - MCP: learn_tutor_reverify (advisory, read-only) - doctor: tutor.reverify_rejects_known_bad, the re-verifier must pass a clean receipt and reject each known-bad fixture - 17 new tests incl. negative fixtures: tampered middle entry -> CHAIN_BROKEN with offending seq+hash, hand-edited verdict -> VERDICT_MISMATCH, hash-consistent truncation -> CHAIN_BROKEN via attempt accounting, chainless -> UNVERIFIED Co-Authored-By: Claude Opus 4.8 <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.
What
A tutor receipt currently carries author-controlled booleans (
verified,ledgerVerified) that a consumer has to take on faith. This PR addstutor/reverify.mjs: a re-verification entry point that recomputes the receipt's own evidence and ignores those booleans entirely.CHAIN_BROKENwith the offending entry's seq and stored hash; a hash-consistent truncation is caught by attempt accounting against the receipt's claimed total.VERDICT_MISMATCHwith both projections.entries) re-verify asUNVERIFIED, never as verified.Surfaces
learn tutor reverify <id> [--file <receipt.json>]. Exit 0 only when every checked receipt re-verifies VERIFIED, with a witnessed (content-addressed) summary digest; any typed failure or UNVERIFIED exits 1.learn_tutor_reverify(advisory, read-only), keeping the CLI/MCP surfaces aligned per AGENTS.md.tutor.reverify_rejects_known_bad. The re-verifier must pass a clean receipt and reject each known-bad fixture. A verifier that cannot fail on a known-bad input is not a verifier.Tests (TDD, red observed before green)
The 7 CLI/MCP tests were run and seen failing before the wiring existed (and the whole file fails at import against pre-change HEAD, which has no reverify module). 17 new tests, negative fixtures first:
CHAIN_BROKENat seq 1 with the stored hashverified: true/ledgerVerified: true-> still FAILS (author-controlled strings never gate)VERDICT_MISMATCHCHAIN_BROKENvia attempt accountingUNVERIFIEDsha256:witnessed summaryFull suite: 206/206 pass.
learn doctor: MATCH (8 checks). Docs updated: README, USAGE, CHANGELOG (Unreleased), docs/HOW-IT-WORKS, docs/ENTERPRISE-READINESS.🤖 Generated with Claude Code