Skip to content

maintenance: CI flake guard, stale paths, two-tier acceptance tolerance (3.14.20, 3.14.21) - #251

Merged
jdeast merged 5 commits into
masterfrom
worktree-ci-upload-flake
Sep 11, 2026
Merged

maintenance: CI flake guard, stale paths, two-tier acceptance tolerance (3.14.20, 3.14.21)#251
jdeast merged 5 commits into
masterfrom
worktree-ci-upload-flake

Conversation

@jdeast

@jdeast jdeast commented Sep 11, 2026

Copy link
Copy Markdown
Owner

Three independent maintenance changes from the 8.6.17 follow-up list.

1. A failed diagnostic upload must not fail the job (3.14.21)

PR #246 went red on probe (3.13) with Failed to CreateArtifact: Unable to make request: ENOTFOUND after 13m48s of the probe's own work had passed. A DNS blip reaching GitHub's artifact endpoint turned a green run red.

That last part is the cost, and why it is worth fixing rather than re-running: it teaches people to re-run reds instead of reading them, in a repo whose CI discipline is "red means stop". A flake amplifier is worse than a flake — and if: always() means these steps run precisely when something else has already gone wrong, i.e. exactly when the real failure most needs to be the thing you see.

Both uploads are diagnostics, and each file says so itself. continue-on-error: true on the two of them, so a job's verdict comes from the work it did. The alternative considered and rejected — keep the failure but move the aggregate gate ahead of the upload — keeps a lost artifact visible but leaves the shard red, which is the misleading half.

2. Retire the last references to paths that no longer exist

All of these passed: they are arbitrary Parameter labels, docstring examples, or synthetic configs the generic config layer does not validate. Worth fixing for one reason — a reader who greps lens.t_E finds nothing in the source and then has to work out whether the test is stale or the code is.

test_param_specificity.py gets a docstring fix rather than a rewrite, and the reason is worth recording: its TWO_SOURCE_SYSTEM is a pre-split config that passes only because ConfigManager does not validate a lens block — the same property that had made four test_config_provenance tests inert until the 8.6.17 sweep. Here it is harmless, because the check under test is component-agnostic. So the scenario is labelled historical, with a note that the LIVE case for that check is now detrend_coeffs.

Left alone deliberately: anything already framed as history. Still open: test_latex_macro_xref.py:228 asserts _latex_varname("lens.12.t_E") == "ezlensonetwotE"; pointing it at a real path changes the expected mangled string, so it needs a run rather than a guess.

3. Two-tier acceptance tolerance keyed on a platform fingerprint (3.14.20)

ONE tolerance (rtol 1e-6 / atol 1e-3), sized to the worst cross-platform difference, applied everywhere — including on the machine that recorded the fixtures, where no regression smaller than that can be detected at all. A genuine 1e-4 nat change on the reference machine passed.

Each fixture now records the platform it was measured on. The recording machine is held tight; anything else gets the physics tolerance. No per-platform fixtures, no calibration through CI, and a new platform gets the loose tier automatically instead of no coverage.

Measured, not assumed. PR #246's macOS job dumped every term: 786 of 925 bit-identical, largest absolute difference 2.2e-06 nats, signs mixed 74/65 (scatter, not a directional offset), macOS on accelerate against Linux's scipy-openblas. For scale, 0.1 sigma on a 1-D Gaussian is ~5e-3 nats.

The strict tier is 1e-14, not zero, and that came out of running the generator's --check before touching a fixture. 12 of 13 reproduce exactly; OGLE_0383LD's RV:mulensinstrument.model comes back 26832.036090685935 -> 26832.03609068592 (5.4e-16 relative, the same delta every run). So that recorded value is about an ulp stale against current code, and rtol=0 would have failed the reference platform against its own fixtures. 1e-14 is a few ulp here — still eight orders tighter than the cross-platform tier.

The fixtures were not regenerated. Regeneration rewrites every recorded value from current code, and these are a pre-split recording that cannot be reproduced — it would have silently adopted that OGLE_0383LD ulp instead of leaving it visible. One key added per file, every other key verified byte-for-byte: 65 insertions, 0 deletions.

The fingerprint is coarse — system, machine, BLAS name, not version — so a point release that changes no result cannot silently demote the reference machine to the loose tier, and one that does change a result is caught by the loose tier anyway.

test_both_tolerance_tiers_are_reachable exists because every fixture here carries this machine's fingerprint, so the strict tier is the only one the suite exercises locally: a bug making is_reference_platform answer True unconditionally would be invisible while holding macOS eight orders too tight. It asserts all three directions (own / foreign / unstamped) with a fabricated fingerprint. Same shape as the vacuity failures in docs/testing.md — the guarded path passes and the unguarded one is never entered.

Verification

Pre-push hook green (ruff, ruff format, full suite). Acceptance 29 passed on the strict tier with the delta dump unchanged; 200 passed across the files touched in (2).

🤖 Generated with Claude Code

jdeast and others added 5 commits September 10, 2026 00:11
PR #246 went red on `probe (3.13)` with

    ##[error]Failed to CreateArtifact: Unable to make request: ENOTFOUND

AFTER 13m48s of the probe's own work had passed.  A DNS blip reaching
GitHub's artifact endpoint turned a green run red, and the remedy was a
human noticing that a red check was not a real failure.

That last part is the actual cost, and it is why this is worth fixing rather
than re-running: it teaches people to re-run reds instead of reading them,
in a repo whose CI discipline is "red means stop".  A flake amplifier is
worse than a flake.

Both uploads are DIAGNOSTICS, and each file says so itself: intel-mac's
comment is "when the install fails, the requirement file and whatever pip
managed to resolve are the diagnosis", and tests.yml's transcript feeds
gen_durations.py.  So losing one costs a diagnostic, while failing the job
on one costs a signal -- and `if: always()` means they run precisely when
something else has already gone wrong, i.e. exactly when the real failure
most needs to be the thing you see.

`continue-on-error: true` on the two upload steps, so a job's verdict comes
from the work it did.  The alternative considered and not taken -- keep the
failure but move the aggregate gate's decision ahead of the upload -- keeps
a lost artifact visible but leaves the shard itself red, which is the half
that misleads.

Verified: both workflows still parse, and both upload steps are the only
`upload-artifact` uses in either file.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
All of these PASSED -- the strings are arbitrary Parameter labels, docstring
examples, or synthetic configs the generic config layer does not validate.
They are worth fixing for one reason: a reader who greps `lens.t_E` to
understand what a test means finds nothing in the source, and then has to
work out whether the test is stale or the code is. That is the same cost the
multiseed and MMEXOFAST-converter ports paid down; this is the tail of it.

  test_bad_user_input.py        label="lens.t_E" x4 -> mulensevent.t_E
  test_microlensing_physics.py  same, x1
  test_mode_evidence.py         a docstring example, lens.t_0_raw
  test_element_parameterization.py  a selector error-message label
  test_mkparam.py               the writer's synthetic per-source config

test_param_specificity.py gets a DOCSTRING fix rather than a rewrite, and
the reason is worth recording: its `TWO_SOURCE_SYSTEM` is a PRE-SPLIT config
(`lens: [{lenses, sources}]`) and it passes only because ConfigManager does
not validate a lens block -- the same property that had made four
test_config_provenance tests inert until the 8.6.17 sweep. Here it is
harmless, because the check under test is component-agnostic and a
fictional lens exercises it as well as a real component would. So the
scenario is now labelled historical, with the note that this direction lost
its shipped instance in the split and the LIVE case is the shorter one
(`detrend_coeffs`).

LEFT ALONE, deliberately: anything already framed as history ("Before the
split this was ...", "HISTORICAL:") is correct as written.

STILL OPEN: test_latex_macro_xref.py:228 asserts
`_latex_varname("lens.12.t_E") == "ezlensonetwotE"`. Pointing it at a real
path changes the expected mangled string, so it needs a run to confirm
rather than a guess.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…(3.14.20)

ONE tolerance (rtol 1e-6 / atol 1e-3) was sized to the worst cross-platform
difference, so it applied everywhere -- including on the machine that
RECORDED the fixtures, where no regression smaller than that can be detected
at all.  A genuine 1e-4 nat change on the reference machine passed.

Now each fixture records the platform it was measured on, and the test picks
its tier: the recording machine is held tight, anything else to the physics
tolerance.  No per-platform fixtures, no calibration, and a new platform
gets the loose tier automatically rather than no coverage.

MEASURED, not assumed.  PR #246's macOS job dumped every term: 786 of 925
bit-identical, largest ABSOLUTE difference 2.2e-06 nats, signs mixed 74/65
(scatter, not a directional offset), macOS on accelerate against Linux's
scipy-openblas.  For scale, 0.1 sigma on a 1-D Gaussian is ~5e-3 nats.

THE STRICT TIER IS 1e-14, NOT ZERO, and that came out of running the
generator's --check BEFORE touching a fixture.  12 of 13 reproduce exactly;
OGLE_0383LD's RV:mulensinstrument.model comes back
26832.036090685935 -> 26832.03609068592 (5.4e-16 relative, the same delta on
every run), so that recorded value is about an ulp stale against current
code and rtol=0 would have failed the reference platform against its OWN
fixtures.  1e-14 is a few ulp here: still eight orders tighter than the
cross-platform tier.

THE FIXTURES WERE NOT REGENERATED.  Regeneration rewrites every recorded
value from current code, and these are a PRE-SPLIT recording that cannot be
reproduced -- it would have silently adopted that OGLE_0383LD ulp instead of
leaving it visible.  One key added per file, every other key verified
byte-for-byte: 65 insertions, 0 deletions.

The fingerprint is COARSE -- system, machine, BLAS NAME, not version -- so
an OpenBLAS point release that changes no result cannot silently demote the
reference machine to the loose tier, and one that DOES change a result is
caught by the loose tier anyway.

test_both_tolerance_tiers_are_reachable exists because every fixture in the
tree carries this machine's fingerprint, so the strict tier is the only one
the suite exercises here: a bug making is_reference_platform answer True
unconditionally would be invisible while holding macOS eight orders too
tight.  It asserts all three directions (own / foreign / unstamped) with a
fabricated fingerprint.  Same shape as the vacuity failures in
docs/testing.md -- the guarded path passes and the unguarded one is never
entered.

Verified: 29 passed on the strict tier, delta dump unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
PR #251 went red on ubuntu 3.12/3.13/3.14 and macOS 3.12 with
OGLE_0383LD's RV:mulensinstrument.model moving
26832.036090685935 -> 26832.036090686284: relative 1.3e-14, against a
REFERENCE_RTOL of 1e-14, and in the OPPOSITE direction from this box's
5.4e-16.

The fingerprint {system, machine, blas} names a platform CLASS, not a
machine.  CI's Linux runner matched it, therefore claimed to be the
machine that recorded the fixtures, and was held to a bit-identity
tolerance it had no reason to meet -- OpenBLAS dispatches kernels by CPU
capability at runtime, so one class rounds two ways.

Making the fingerprint finer (CPU model, OpenBLAS core) is a guess about
which attributes matter and would demote the reference machine on any
hardware change.  Requiring the claim to be STATED is honest instead:
EXOZIPPY_ACCEPTANCE_STRICT plus a fingerprint match.  The default -- CI
included -- is the physics tolerance, which is always safe.

Also REFERENCE_ATOL = 1e-30 for the denormal term CI flagged alongside it
(POT:low_bound.mulensevent.mu_rel_mag at -2.0e-220), where a relative
test is meaningless.  Same trap as the delta dump's 266% outlier, whose
absolute delta was 3.5e-22.

test_both_tolerance_tiers_are_reachable now asserts the new direction as
well: WITHOUT the opt-in nothing claims the strict tier.  That is the
assertion #251 lacked.

Verified: acceptance 24 passed on the default tier (what CI runs) and 24
passed with EXOZIPPY_ACCEPTANCE_STRICT=1.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
test_both_tolerance_tiers_are_reachable asserted is_reference_platform()
on a SHIPPED fixture.  Those carry the recording box's fingerprint
(Linux), so the assertion holds only there -- macos-latest 3.12 shard 2
went red with "this machine does not match the fingerprint in its own
fixtures".

The subject of the test is the SELECTOR, not where the suite runs.  So
stamp the own-machine case with platform_fingerprint() and it matches on
any runner, and make the foreign case an obviously fabricated platform
rather than macOS -- naming a real platform made the test read as though
it cared which one.

Verified: passes locally; the assertions no longer reference the recorded
fingerprint at all, so they are platform-independent by construction.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jdeast
jdeast merged commit 78a1141 into master Sep 11, 2026
21 checks passed
@jdeast
jdeast deleted the worktree-ci-upload-flake branch September 11, 2026 04:38
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