Skip to content

feat(tutor): receipt re-verification with typed CHAIN_BROKEN / VERDICT_MISMATCH failures#1

Merged
HarperZ9 merged 1 commit into
mainfrom
feat/tutor-receipt-reverify
Jul 2, 2026
Merged

feat(tutor): receipt re-verification with typed CHAIN_BROKEN / VERDICT_MISMATCH failures#1
HarperZ9 merged 1 commit into
mainfrom
feat/tutor-receipt-reverify

Conversation

@HarperZ9

@HarperZ9 HarperZ9 commented Jul 2, 2026

Copy link
Copy Markdown
Owner

What

A tutor receipt currently carries author-controlled booleans (verified, ledgerVerified) that a consumer has to take on faith. This PR adds tutor/reverify.mjs: a re-verification entry point that recomputes the receipt's own evidence and ignores those booleans entirely.

  • Chain integrity: the hash chain over the witnessed practice entries must recompute. Any break is typed CHAIN_BROKEN with the offending entry's seq and stored hash; a hash-consistent truncation is caught by attempt accounting against the receipt's claimed total.
  • Verdict re-derivation: the stored mastery verdict must re-derive from the receipt's own recorded practice entries under the receipt's own recorded policy (threshold / minAttempts). A divergence is typed VERDICT_MISMATCH with both projections.
  • Chainless receipts (no entries) re-verify as UNVERIFIED, never as verified.

Surfaces

  • CLI: 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.
  • MCP: learn_tutor_reverify (advisory, read-only), keeping the CLI/MCP surfaces aligned per AGENTS.md.
  • doctor: 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:

  • tampered middle entry -> CHAIN_BROKEN at seq 1 with the stored hash
  • tampered receipt that also claims verified: true / ledgerVerified: true -> still FAILS (author-controlled strings never gate)
  • hand-edited overall verdict and hand-edited per-objective stat -> VERDICT_MISMATCH
  • hash-consistent truncation (dropped tail entry) -> CHAIN_BROKEN via attempt accounting
  • chainless / verdict-less receipts -> UNVERIFIED
  • clean mastery and study receipts -> VERIFIED with a sha256: witnessed summary

Full 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

…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>
@HarperZ9 HarperZ9 merged commit ec18009 into main Jul 2, 2026
6 checks passed
@HarperZ9 HarperZ9 deleted the feat/tutor-receipt-reverify branch July 2, 2026 03:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant