Skip to content

Close the id-keying audit: make the corpus-identity gate a tested unit - #214

Merged
joslat merged 2 commits into
mainfrom
feat/sha-keying-audit-sweep
Sep 2, 2026
Merged

Close the id-keying audit: make the corpus-identity gate a tested unit#214
joslat merged 2 commits into
mainfrom
feat/sha-keying-audit-sweep

Conversation

@joslat

@joslat joslat commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Discharges the family-wide audit of anything that could key on question_id / corpus_id /
revision across corpus versions.

Why it was needed: AgentEval redraws corpora keeping the question_id set 100% identical with
zero byte-identical items
, and neither corpus_id nor revision moves — corpus_sha256 is the
only distinguishing field. For bitemporal, 27 of 60 items keep the same question text with a
different gold
. Anything joining across corpus versions on an id is silently wrong, in the
direction that yields a confident number rather than an error.

Result: one gap, one surface, already closed in #213

surface keys on verdict
--regrade cross-artifact join position + question text ❌ gap — closed in #213
prepared-corpus reuse datasetSha256 + 11 identity fields ✅ already correct
perf ledger scenario names ✅ not corpus-versioned
TypedMemEval runs fresh container per run ✅ no cross-version cache
evidence index question id, within one load ✅ single-corpus scope
any other two-artifact verb ✅ none exist

Two results worth more than a tick: prepared-corpus reuse already compares datasetSha256 and its
own header states the principle this audit is about — "treating unknown as equal is how a check stops
being able to fail"
— reporting unrecorded fields on older manifests as drift, not agreement.
That is the standard the re-grade has now been raised to. And no other verb reads two artifacts,
so --regrade was the only place the hazard could live.

What this PR adds

The gate's decision was a code path only exercisable by running the tool against a hand-mutated
artifact. It is now CorpusIdentity.Verify with three verdicts and unit tests for each — including
hex casing, since artifacts and manifests disagree about it and that is not a redraw.

Unverifiable stays its own verdict deliberately. Folded into Match it passes silently — the
constant-column failure this project has hit three times. Folded into Mismatch it blocks every
artifact older than provenance capture, making the gate obstructive enough to get bypassed. So it
warns at the call site and refuses to be read as agreement.

Release 0-warn; LongMemEval 742/742.

…audit

Discharges the family-wide audit: every cache, baseline, join and tool of ours that could key on
question_id/corpus_id/revision across corpus versions.

RESULT: one gap, in one surface, already closed in #213 -- the --regrade cross-artifact join, whose
position-and-text keying catches a reworded redraw and catches nothing when the text is stable and
only the gold moves. Everything else is clean, and two of those are worth recording rather than
merely ticking:

  - PREPARED-CORPUS REUSE already compares datasetSha256 alongside eleven identity fields, and its
    own header states the principle this audit is about -- "treating unknown as equal is how a check
    stops being able to fail". It reports unrecorded fields on older manifests as DRIFT rather than
    agreement. That is the standard the re-grade has now been brought up to.
  - No other verb reads two artifacts at all, so --regrade was the only place the hazard could live.

WHAT THIS COMMIT ADDS: the gate's decision was a code path only exercisable by running the tool
against a hand-mutated artifact. It is now CorpusIdentity.Verify with three verdicts and unit tests
for each, including hex-casing (artifacts and manifests disagree about it, and that is not a redraw).

Unverifiable stays its own verdict deliberately. Folded into Match it passes silently -- the
constant-column failure this project has been bitten by three times. Folded into Mismatch it blocks
every artifact older than provenance capture, making the gate obstructive enough to get bypassed. So
it warns and refuses to be read as agreement.

Release 0-warn; LongMemEval 742/742.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RM9gMsvo3SpYqEBENbaefo
Copilot AI lite review requested due to automatic review settings September 2, 2026 21:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The mismatch abort message can throw at runtime when slicing short/corrupt SHA strings ([..16]), which undermines the “fail safely” goal of the gate.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR extracts the corpus-identity gate used by typedmemeval --regrade into a testable unit (CorpusIdentity.Verify) so re-grading can reliably detect corpus redraws (where question_id and even question text may remain stable while gold changes), preventing meaningless agreement results.

Changes:

  • Replaces the inline corpus SHA gate in TypedMemEvalRegradeProgram with a CorpusIdentity.Verify helper that returns a 3-way verdict (Match / Mismatch / Unverifiable).
  • Updates re-grade flow to switch on the verdict, aborting on mismatch and warning (without failing) when identity cannot be verified.
  • Adds unit tests covering all three verdicts, including case-insensitive SHA comparisons.
File summaries
File Description
tools/AgentMemory.LongMemEval/TypedMemEvalRegradeProgram.cs Extracts corpus-identity comparison into CorpusIdentity.Verify and switches re-grade gating logic to use a 3-way verdict.
tests/AgentMemory.Tests.Unit.LongMemEval/CorpusIdentityTests.cs Adds unit tests verifying Match/Mismatch/Unverifiable behavior, including hex-casing tolerance.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread tools/AgentMemory.LongMemEval/TypedMemEvalRegradeProgram.cs Outdated
Copilot's review of #214: the mismatch message sliced both shas at a fixed [..16], which throws
ArgumentOutOfRangeException on a truncated or corrupt value -- in the one branch whose entire purpose
is to fail SAFELY with an exit code rather than an exception.

Second time on this same gate. #213 hardened the sha's TYPE (a non-string CorpusSha256 would have
thrown out of GetString()) and left its LENGTH assumed. Same defensive question, same guard, asked
about one property and not the next. A guard that can throw is not a guard.

Verified end to end with a truncated sha: it now aborts cleanly and prints the short value as-is
rather than crashing.

Release 0-warn; LongMemEval 744/744.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RM9gMsvo3SpYqEBENbaefo
@joslat
joslat merged commit d85d39a into main Sep 2, 2026
7 checks passed
@joslat
joslat deleted the feat/sha-keying-audit-sweep branch September 2, 2026 21:50
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.

2 participants