docs+test: replace exact-identity gate with ULP + rank-stability tolerance - #504
Conversation
…rance Retracts docs/provenance/green-w3-2-encoding-identity.md's "no tolerance adopted" decision (PR #495). That gate required bitwise-exact equality between a scalar-path and a batched-path float32 computation, which no batched implementation can pass by construction: IEEE 754 float32 addition/multiplication isn't associative, so a batched matmul reduces in a different element order than N scalar calls and won't reproduce the same bit pattern even when both results are correct. Evidence this is what happened, not a coincidence: every delta PR #495 and PR #497 recorded as a rejection (1.64e-7, 1.19e-7, 1.06e-7, 9.31e-8, 1.40e-7) is within ~1.4x of float32 machine epsilon (2**-23 = 1.1920928955078125e-07) — the PR #495 score delta equals it exactly. Adds benchmarks/lib/numeric_equivalence.py: vectors_equivalent() (ULP tolerance per component) and rank_stable() (a score shift must not flip which candidate wins unless they were already tied within tolerance). Both are exercised in tests_py/benchmarks/test_numeric_equivalence.py against the exact deltas above, reproduced from the two PR bodies. Does not itself restore the batched code paths PR #495/#497 reverted — this session had no torch/sentence-transformers available to re-run either PR's own harness against the new gate. See the new doc's closing section for what a maintainer with the pinned model needs to re-check before doing that. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01StMBvNd7eVJGtpnC2zNsx1
The craftsmanship gate's unsourced-constant rule only recognizes a # source: comment sitting directly on, or in a contiguous comment run immediately above, the assignment line it covers — a comment shared across a block of several assignments only satisfies the first one. PR_495_SCORE_DELTA, PR_497_LESSONS_DELTA and PR_497_COMPRESSION_DELTA each sat below a sibling assignment instead of a comment line, so the gate flagged them (CI run 34209985343, Craftsmanship Gate). Reproduced locally with `python scripts/check_craftsmanship.py --base origin/main` and confirmed green after giving each constant its own source line. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01StMBvNd7eVJGtpnC2zNsx1
|
CI: This diff touches only The job (
Every other job on this head is green (Lint, Craftsmanship Gate, Type Check, all 5 Python test matrices, Windows/SQLite, Docker Smoke, Build Package, Release dependency set). I've already used the one re-run this failure mode is owed; a second silent re-run isn't warranted. Flagging here rather than re-running blind: if this timeout keeps tripping on unrelated PRs, Generated by Claude Code |
|
(Attribution addendum — omitted from the comment above by mistake.) Generated by Claude Code |
Brings in #503 (floor check non-blocking + --no-regression gate), which this PR's base moved to. No file overlap between the two changes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01StMBvNd7eVJGtpnC2zNsx1
|
Correction — mon commentaire précédent était faux, et sur le fond et sur la posture. J'y écrivais « not this PR's, re-run budget spent » et j'attribuais le timeout à de la latence de registre npm. Les deux sont faux, et le cadrage lui-même l'était : une CI rouge sur une PR n'est pas un problème de CI, c'est le code qui ne passe pas la CI. « Pre-existing » est exactement le refus que les règles de ce dépôt nomment comme violation de contrat. J'aurais dû lire les logs avant de plaider. Ce que les logs disent ( Le coût n'est pas la validation de config : c'est la dernière étape, Deux échantillons, même PR, mêmes assertions, tous deux
Le run à 179,86 s a passé ses assertions et a été tué quand même, à 194 s, par le plafond de 180 s. Correctif dans #505 : Generated by Claude Code |
Brings in #505 (mcp-host-config timeout sized to its measured tail), so this PR's CI runs under a bound that no longer decides on network luck. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01StMBvNd7eVJGtpnC2zNsx1
Summary
Captures, in a pushable form, an analysis that was done on a machine that cannot push to this repo:
docs/provenance/green-w3-2-encoding-identity.md(PR #495) recorded "The requested contract is exact score identity, not a numeric tolerance" and "No tolerance has been adopted." That decision is retracted here — not for lack of evidence, but because it was evaluated against the wrong predicate.IEEE 754 float32 addition/multiplication is not associative, so a batched matmul reduces its terms in a different order than N independent scalar calls and will not, in general, reproduce the same bit pattern — even when both results are correct. A gate specified as exact bitwise equality between a scalar path and a batched path is therefore unsatisfiable by construction: no batched implementation can ever pass it, regardless of correctness, and it will reject the same optimization forever.
The tell that this is what actually happened: float32 machine epsilon is
2**-23 = 1.1920928955078125e-07. Every delta PR #495 and PR #497 recorded as a rejection is within ~1.4x of exactly this number — PR #495's score delta equals it, to every reported digit:A genuine computational defect does not track machine epsilon this tightly across five unrelated code paths on two different PRs.
Changes
benchmarks/lib/numeric_equivalence.py—vectors_equivalent()(ULP tolerance per component,DEFAULT_MAX_ULP=4, ~3x headroom over the largest observed delta) andrank_stable()(the criterion that actually matters for a write-gate decision or retrieval ordering: a score shift of a few ULP must not flip which candidate wins unless the two were already tied within tolerance on the scalar path — in which case either order was already an acceptable outcome).tests_py/benchmarks/test_numeric_equivalence.py— reproduces the exact deltas from the table above and confirms both functions now pass them, while still rejecting a real regression (tested at 0.01, four orders of magnitude larger than any measured rounding delta).docs/provenance/numeric-equivalence-tolerance.md— the retraction, the sourced table, and what remains open (see below).What this does NOT do
It does not restore the batched code paths PR #495 (
60e5646b, "batch normalized neighbors and reuse unchanged merge vectors") or PR #497 reverted. This session has notorch/sentence-transformersavailable to re-run either PR's own harness against the new gate. Applying the new functions to the already-recorded deltas above says they'd now pass, but a maintainer with the pinned MiniLM encoder available should re-run each PR's harness (cited in the new doc) before restoring either batched path, rather than trusting a transcription of numbers already in a closed PR body.Test plan
ruff check/ruff format --checkon both new Python files — clean.python scripts/check_craftsmanship.py benchmarks/lib/numeric_equivalence.py—Craftsmanship gate: OK.ast.parse()on both files — OK.Manually executed every function in
numeric_equivalence.pyagainst the exact PR perf(remember): reuse embeddings for identical merge text #495/perf(embeddings): batch codebase imports and preserve cache contexts #497 deltas outside pytest (nopytestbinary available in this sandbox) — matches every assertion in the committed test file.Did not run the full
pytestsuite in this sandbox (nonumpy/torchinstalled here —benchmarks/lib/__init__.pyeagerly importsnumpyviaembedding_engine.py, by existing design, since numpy is a hardmcp_serverdependency in the real dev environment). A maintainer should runpytest tests_py/benchmarks/test_numeric_equivalence.pyonce to confirm collection.All existing tests pass. (new file only; not run in this sandbox — see above)
New tests added for new behavior.
Manual verification of any UI / CLI / MCP-tool behavior changes. (not applicable — no runtime code path changed)
Audit notes
mcp_server/production code touched).Coding-standards compliance
benchmarks/lib/, not a layeredmcp_server/package).FLOAT32_ULPto IEEE 754 binary32;DEFAULT_MAX_ULPto the measured deltas in the table above, both in the module docstring and the doc.Breaking changes
None. Purely additive (new module + doc), touches no existing code path.
Reviewer checklist
docs/provenance/numeric-equivalence-tolerance.md).🤖 Generated with Claude Code
https://claude.ai/code/session_01StMBvNd7eVJGtpnC2zNsx1
Generated by Claude Code