Skip to content

test(suite): declare the interp oracle's platform scope - #65

Merged
LoganAMorrison merged 2 commits into
masterfrom
claude/interp-oracle-unsound-probe-57f202
Aug 13, 2026
Merged

test(suite): declare the interp oracle's platform scope#65
LoganAMorrison merged 2 commits into
masterfrom
claude/interp-oracle-unsound-probe-57f202

Conversation

@LoganAMorrison

@LoganAMorrison LoganAMorrison commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Summary

  • test/test_core_interp.py scoped its NumPy oracle with a probe, and that probe was resolving the wrong way. Built for linux/amd64 it returned False, so all nine of the module's cross-implementation claims skipped and hazma._core.interp was checked against nothing but its own clamping contract, quirks and error paths on every CI entry but macOS. Same mechanism Task 4.1 retired in test_core_positron_muon.py and the 2026-08-12 rewrite retired in test_core_boost.py. The module now runs 42 passed, 0 skipped on both platforms (was 24 passed, 9 skipped off macOS). Resolves interp-oracle-scoped-by-an-unsound-probe.md.
  • The mode is declared, and the budget was measured. ON_THE_CAPTURING_PLATFORM is read from test/parity/data/manifest.json so this module's scope cannot drift from the corpus's. Off it, the tree was built for linux/amd64 (Debian bookworm, glibc 2.36, CPython 3.12.13, NumPy 2.5.1) and compared directly over 1,154,010 abscissae: the port and that build's np.interp differ at 311,501 points by up to 4.0e-02 pointwise relative but only 2.2e-16 of the peak, with no non-finite value on either side (0 of 2,308,020) and no disagreement anywhere about which abscissae return exactly zero. Hence OFF_PLATFORM_BUDGET = 1e-12 scaled to the peak — two orders tighter than the boost module's 1e-10, not looser as the follow-up guessed, because peak scaling collapses the very cancellation population the pointwise reading blows up.
  • TestFusedArithmetic no longer discriminates against NumPy. Its reference is interp_reference, a full Python transcription of rust/src/interp.rs (bisection, clamps, exact-node short circuit, NumPy's two-step NaN rescue) parameterised by its multiply-add, asserted bit-for-bit on every platform. That makes it the stronger of the two off-platform gates, since peak scaling is blind to a defect confined to a value far below the peak. The discrimination is direct, not assumed: np.interp is bit-equal to mul_add=fma on all seven live tables on macOS/arm64 and bit-equal to mul_add=unfused on all seven on linux/amd64. TestOffPlatformBudget guards both the tolerance and the mode dispatch.
  • Two supporting fixes the measurement forced. rng.uniform(lo, hi, n) is not platform-independent — NumPy computes lo + (hi - lo) * u in C and macOS/arm64 contracts that, so 6,532 of 20,000 draws over the eta grid landed on different doubles than the same seed gives on Linux; the new spread() helper writes it as separate ufunc calls. And the per-table seed moved from hash(name) (randomised per process unless PYTHONHASHSEED is set) to zlib.crc32. Without both, every count recorded here would have been a per-platform anecdote rather than a reproducible measurement.
  • rust/src/interp.rs is comment-only (verified: git diff origin/master -- rust/src/interp.rs filtered to non-//! lines is empty). Its module docs carried the now-measurably-wrong claim that an unfused NumPy "would differ from this function by ≤1.1e-13 — an order inside the 1e-12 budget test/parity/tolerances.py sets"; the pointwise figure is 5.9e-05 on the live tables, and the corpus is skipped off-platform anyway.

No public value moves. The diff is one test module, comment-only Rust edits, and four docs; no public function changed.

Project

projects/cython-to-rust/not a PLAN task. This resolves the
cross-cutting follow-up
interp-oracle-scoped-by-an-unsound-probe.md,
which was carved out of the test_core_boost.py probe removal
(1ed4eda), so the branch is ad-hoc (claude/<short-description>) rather
than claude/<project-slug>/<task-slug> and there is no
task-notes/task-N-<slug>.md for it. The follow-up file carries the
Resolution, Verification and stale-state sweep that a task note would.

The module under change was built by Task 3.4 (projects/cython-to-rust/task-notes/phase-03/task-3.4-interp-boost.md,
shipped as #61); this PR supersedes that task's platform-scoping remedy
and patches the two inbound links plus a sweep-size slip in its records.
It does not reopen Task 3.4, whose status stays Complete.

Test plan

  • scripts/agents/preflight.sh --paths "test/test_core_interp.py" --md "…"RESULT: PASS, all eleven rows:
PASS   black --check           test/test_core_interp.py
PASS   isort --check-only      test/test_core_interp.py
PASS   ruff check              test/test_core_interp.py
PASS   cargo fmt --check       rust/
PASS   cargo clippy            rust/
PASS   cargo test              rust/
PASS   pytest                  1444 passed, 14 skipped, 5 warnings in 594.22s (0:09:54)
PASS   import hazma            version 2.1.0
PASS   markdownlint            docs/followups/README.md docs/followups/done/… projects/…
SKIP   version bump            not a closing PR (pass --closing)
PASS   forbidden tokens        none added
RESULT: PASS
  • pytest test/test_core_interp.py -q on macOS/arm64 → 42 passed in 0.94s

  • the same command inside the linux/amd64 container built from this tree → 42 passed in 2.61s

  • cargo test --manifest-path rust/Cargo.toml --no-default-features80 passed

  • Test validity, stash-proof. slope.mul_add(x - xp[j], fp[j]) in rust/src/interp.rs replaced with slope * (x - xp[j]) + fp[j], rebuilt with pip install -e ., module re-run on both platforms:

    • macOS/arm64 → 15 failed, 27 passed (all seven TestAgainstNumpy table cases, the random grid, all seven TestFusedArithmetic cases)
    • linux/amd64 → 7 failed, 35 passed (the seven TestFusedArithmetic cases only)

    That second line is the point in both directions: off-platform TestAgainstNumpy passes the mutant, because there np.interp is the unfused form — the budget genuinely cannot see this defect, and the fused reference is what catches it. Under the old module the off-platform count would have been 0 failed. Mutation reverted and the tree rebuilt before the gate was run.

The 14th skip is test/parity/test_parity.py in budget rather than bit-equality mode (hazma._core serves 1 kernel(s)) — Task 4.1's positron-muon swap, present on master before this change and untouched by it.

  • Confirmed on CI, which is where the skips lived. Linux py3.12, pytest --ignore=test/parity:

    run result
    master 707b07c (run 31646076820) 797 passed, 22 skipped
    this PR (run 31651543376) 815 passed, 13 skipped

    −9 skipped, +18 passed — the 9 are exactly the module's previously-voided cross-implementation claims, and the +18 is those 9 plus the 9 net-new tests (33 → 42). All eight checks green, including all five Ubuntu entries py3.10py3.14 and macOS py3.14.

LoganAMorrison and others added 2 commits August 12, 2026 16:36
`test/test_core_interp.py` decided whether to compare `hazma._core.interp`
against `np.interp` bit-for-bit by *measuring* whether the installed NumPy
fused its interpolation step. That is the mechanism Task 4.1 retired in
`test_core_positron_muon.py` and the 2026-08-12 rewrite retired in
`test_core_boost.py`: a probe tests one contraction mechanism and is blind
to every other, so it fails in both directions. This module was resolving
the second way -- built for linux/amd64 the probe returned False and all
nine cross-implementation claims skipped, leaving the port checked against
nothing but its own clamping contract, quirks and error paths on every CI
entry but macOS. The module now runs 42 passed / 0 skipped on both.

The mode is declared from the platform (`ON_THE_CAPTURING_PLATFORM`, read
from the parity corpus manifest so the two scopes cannot drift), and the
divergence off it was measured rather than assumed -- built for
linux/amd64 (Debian bookworm, glibc 2.36, CPython 3.12.13, NumPy 2.5.1)
and compared directly over 1,154,010 abscissae. The port and that build's
`np.interp` differ at 311,501 points by up to 4.0e-02 pointwise relative
but only 2.2e-16 of the peak, with no non-finite value and no
disagreement about which abscissae return exactly zero. Hence
`OFF_PLATFORM_BUDGET = 1e-12` scaled to the peak -- two orders *tighter*
than the boost module's, because peak scaling collapses the very
cancellation population the pointwise reading blows up.

`TestFusedArithmetic` no longer discriminates against NumPy. Its
reference is `interp_reference`, a full Python transcription of
`rust/src/interp.rs` parameterised by its multiply-add, asserted
bit-for-bit on every platform -- which makes it the stronger of the two
off-platform gates, since peak scaling is blind to a defect confined to a
small value. Unfusing the Rust and rebuilding fails 15 tests on macOS and
7 on linux/amd64, where `TestAgainstNumpy` passes the mutant because
there `np.interp` *is* the unfused form; under the old module the
off-platform count was 0.

Two supporting fixes the measurement forced: `rng.uniform(lo, hi, n)` is
not platform-independent (NumPy computes `lo + (hi - lo) * u` in C and
macOS/arm64 contracts it -- 6,532 of 20,000 draws landed on different
doubles), so `spread()` writes it as separate ufunc calls; and the
per-table seed moved off `hash(name)`, which is randomised per process.
Without both, every count recorded here would be a per-platform anecdote.

`rust/src/interp.rs` is comment-only: it carried the now-measurably-wrong
claim that an unfused NumPy would differ by <=1.1e-13, "an order inside
the 1e-12 budget test/parity/tolerances.py sets".

No public value moves.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Review round 1 on PR #65.

The resolved follow-up's §Why and §Entry points cite five line numbers in
`test/test_core_interp.py` for symbols the resolution deletes, so they
were stale the instant the PR landed rather than "later" -- and
`check_doc_citations.py` passes them, because it bounds-checks lines
rather than resolving symbols. Pinned to `707b07c`, verified with
`git show 707b07c:test/test_core_interp.py`.

The Task 3.4 records gave the `np.interp` sweep as 20,204 abscissae per
table. The sweep is `20,000 + 3n + 4`, so it is 20,304 for the 100-row
eta table and 21,504 for the six 500-row tables; the note's own
enumeration of the sweep contradicted its number, so this was wrong when
written rather than changed since. Corrected at all three sites, each
marked with the date and the old value, per the precedent of c316afc. The
companion `1,549` is annotated rather than replaced: it was drawn with a
`hash()`-seeded sweep and so was never reproducible, and the
deterministic seed gives 1,571.

Task 3.4's §Numerical impact, §Files Changed and §Stale-state sweep
describe that task's own diff in the present tense, which a reviewer read
as a claim about this branch -- "one file, `hazma/_core.pyi`,
comment-only" against a branch touching no `hazma/` file. Headed with the
task's PR number and date.

Both classes were already in the lessons ledger; PR #65 is added to
[touched-doc-inherits-its-citations] and [partial-historical-labeling]
with the sharper trigger each one missed.

Docs only -- no code, no public value moves.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@LoganAMorrison
LoganAMorrison merged commit 665aed5 into master Aug 13, 2026
8 checks passed
@LoganAMorrison
LoganAMorrison deleted the claude/interp-oracle-unsound-probe-57f202 branch August 13, 2026 00:40
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