Skip to content

Audit: the fidelity gate's soundness argument covers the resolution layer only - #586

Merged
WilfordGrimley merged 1 commit into
masterfrom
audit/fidelity-gate-recheck
Jul 29, 2026
Merged

Audit: the fidelity gate's soundness argument covers the resolution layer only#586
WilfordGrimley merged 1 commit into
masterfrom
audit/fidelity-gate-recheck

Conversation

@WilfordGrimley

Copy link
Copy Markdown

Read-only audit. One new file, no code changed: docs/reports/2026-07-29-fidelity-gate-recheck.md.

Commissioned because pipeline-fidelity-gate.md's Artifact 2 (knowledge-inventory sweep) certified "every empirically-derived constant/threshold/override/skip-reason mapped to its home" at a time when the skip-reason roster was not enumerable — only ~11 of ~30+ values were named constants. PR #567 made it enumerable (51 constants, 37 distinct values), so the claim could finally be tested.

Verdict: keep FIRED, but qualify it to the resolution layer

The property the fire turned on — no machine-only resolution — is intact and re-verified against the worst population available. All 1,261 artist-contradiction cards read printing_tag_status=unresolved; catalog-wide it is 230,744 unresolved / 22 no_match / 4 resolved. theory.md §7b's "resolution-level false accept = 0, structurally" survives every finding below.

Every defect found is suggestion-level, not resolution-level. Re-firing would re-run a sequence whose backlogs are drained (join-key considered 28, fallback 0, slow-path 0) and would not measure any of it — the gate's instrument is blind to these findings by construction.

The crux: Artifact 1's 83.2% is a self-comparison

§4 calls the replay a "cross-method verdict diff." That holds for the full 41,586-card cohort, but the 83.2% headline is computed on the 28,456-card subset where it is precisely not true — both sides are the same decoder. stage-d-join-key-v1 reads the collector line through local_ocr's own DEFAULT_CROP_BOX, _SET_CODE_RE, _COLLECTOR_NUMBER_RE and _normalize_collector_number, resolves against the same CandidateNameIndex, and carries JOIN_KEY_CONFIDENCE_* as literal copies of the OCR engine's tiers.

Measured: the two identities agree 33,622 / 33,622 with zero conflicts. A pair that cannot disagree cannot corroborate.

Direct proof the agreement population contains wrong votes: of the 1,261 cards where the artist recovered from the card's own printed text contradicts the printing the vote names, 1,072 also carry a local-ocr-v1 vote, and on all 1,072 both channels name the same contradicted printing. Zero name a different one. Those 1,072 sit inside the 83.2%.

So theory.md §7c's "zero of the full 17,793 was a case where this chain committed to a wrong printing that the pilot's own recorded vote contradicts" is true and vacuous — wrongness was operationalised as "contradicts the pilot's vote", and the pilot's vote is the same decoder's output.

Artifact 1 stands as a port-fidelity check, which it passes decisively. What does not survive is the "cross-method" label and the inference to "zero false-accept risk."

Largest open exposure: stage-d-fallback-v1

30,311 positive printing votes — 18% of the printing pool — and it has never been compared to anything. Artifact 1 excluded the fallback channel by construction; §12 records that at gate time it had never cast a vote, and its first production execution was the gate's own fire.

Against local-ocr-v1: overlap 1,203, agree 15, conflict 1,188 (98.8%). All 1,188 are two different printings of the same card name — the sibling-printing question the pipeline exists to answer.

Adjudicated using the catalog card's own uploader-supplied name (not CanonicalCard, which is imported reference data, not truth): 402 conflicts are decisive, and stage-d-fallback-v1 is wrong on 362 of them — 90.0%. Stated honestly: 402 of 1,188 is a biased subsample, selecting cards whose uploader named the artist. It is not an estimate of the channel's catalog-wide error rate; it is proof that a large, never-audited disagreement population exists and that its error direction is one-sided.

Other findings

  • local-ocr-v1 × local-phash-v1's perfect 2,309/2,309 agreement is manufactured. When the two legacy engines disagree, disagreement-with-other-engine fires and neither vote is cast (1,914 live rows = 957 suppressed disagreements). The surviving population is agreement by construction.
  • The calculator tether has a one-directory hole. Both roster checks use src_dir.glob("*.py") — non-recursive — so management/commands/ is never scanned. scryfall-tagger-v1 lives there, writes real PrintingTagVote rows, and is absent from the derived set, the gate doc, and the allowlist.
  • PrintingTagVote is a vote family the gate has never named — zero mentions in pipeline-fidelity-gate.md and zero in theory.md.
  • Four vote-casting modules did not exist at certification, three of them landing after the fire; three more existed and were never inventoried.
  • The skip-reason roster is genuinely complete — 37 declared values, 23 live, exactly one live-but-undeclared (multi-faced-v1, documented as such). Both tethers clean. This is what PR Adopt a *_SKIP_REASON declaration convention; tether the roster to a doc #567 bought, and it works.

Decisions requested

  1. Accept "FIRED, qualified to the resolution layer", and correct §2/§4 accordingly?
  2. Re-mark Artifact 2 as "DONE (2026-07-22 snapshot; superseded)"?
  3. stage-d-fallback-v1: commission a human-audited sample, retract pending that, or accept as suggestion-level noise under the human gate? Recommendation is the first.
  4. Do the 1,261 existing artist-contradicted votes get retracted, or stay as suggestions until a human votes?

Full method, every query, and the honest limits are in the report.

…te roster

Read-only audit, no code changes. Redoes the 2026-07-22 knowledge-inventory
sweep's mapping against what code declares today (51 *_SKIP_REASON / 20
*_ANONYMOUS_ID constants, PR #567), and re-tests whether the gate's FIRED
verdict survives.

Headline findings:
- The skip-reason clause the sweep could not test is now testable and PASSES.
- Artifact 1's 83.2% "OCR-channel agreement" is a self-comparison, not a
  cross-method one: the two identities agree 33,622/33,622 with zero conflicts,
  and 1,072 of the 1,261 artist-contradiction cards sit INSIDE that agreement.
- stage-d-fallback-v1 (30,311 votes, 18% of the printing pool) first ran during
  the fire itself and was never compared to anything; it loses 362 of 402
  adjudicable disagreements against local-ocr-v1.
- scryfall-tagger-v1 falls through the calculator tether's non-recursive glob.
- The resolution-level soundness property holds, re-verified against the worst
  population available.

Recommendation: keep FIRED, QUALIFIED to the resolution layer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013NhYmT1PxCcyemA16dFDxN
@WilfordGrimley

Copy link
Copy Markdown
Author

Cross-link: PR #598 publishes the companion audit from the same day — a deliberate hunt for self-referential reasoning across the whole pipeline (20 instances beyond the 7 previously known, plus 5 checked-and-sound), as docs/reference/self-referential-reasoning.md.

Kept as a separate document rather than merged into this report, for a stated reason: this PR is a verdict on one named gate with a governing status page and a natural home in the dated record; that one is a cross-cutting catalogue of recurring shapes, which has to stay findable by someone who has never heard of issue #154. It lives in docs/reference/ specifically because docs/reports/ and docs/audits/ are both in docs_lint's ARCHIVE_PREFIXES — frozen buckets the orphan graph does not traverse.

They meet at exactly one substantive point, and it corroborates this PR's crux. Your finding that the 83.2% headline is computed on a 28,456-card subset where both sides are the same decoder is measured from the other direction there: of 33,749 cards both stage-d-join-key-v1 and local-ocr-v1 voted on, 33,622 had both name a printing and they never differed, and the 127 disagreements are strictly one-directional — join-key abstains where OCR commits, OCR never abstains where join-key commits. That is the signature of a strict subset, not of an independent method.

Worth noting it started as a false alarm and is recorded as one: a first pass counted those 127 as conflicts and appeared to refute the 33,622/33,622 figure. Re-run per card, separating abstention from contradiction, your figure is correct — and the corrected number is the stronger argument. One-directional containment is better evidence of non-independence than any agreement rate is of independence.

The register generalises this as one of its eight named shapes ("an agreement rate between two channels that share a decoder"), citing this PR as the worked example.

@WilfordGrimley
WilfordGrimley merged commit 48cccce into master Jul 29, 2026
9 checks passed
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