fix(hardening): EPS harmonization, mypy gate, Zhou+Prony guards, anchor tests - #28
Merged
Merged
Conversation
…or tests
Four hardening candidates plus a debug pass:
1. EPS harmonization (nonnormality.petermann_factors): replace hard-coded
1.0e-300 divide-by-zero floor with a named, shared _consts.EPS_DIV. Kept
the value (underflow floor, NOT a physics tolerance) so no anchor changes;
verified canonical fixtures have |<l,r>|^2 ~ O(1), far from any threshold.
2. mypy CI gate: removed continue-on-error in ci.yml; fixed all 18 prior
type-blind findings (annotated numpy return locals, is_dataclass instance
narrowing in io/export). No behaviour change. mypy now exits 0.
3. Zhou guard (_zhou): adopt the canonical EPS_DIV/EPS_GAP constants for the
Petermann-style division floor and zero-eigenvalue check. New closed-form
anchor test (single-qubit pure dephasing: gap=1, K=1 -> both bounds =
log(1/eps)) + a defective-mode guard test.
4. Prony fallback (fitting.prony): wrap lstsq/np.roots in try/except, emit a
RuntimeWarning and fall back to a safe default seed (positive amplitude)
on near-singular/non-finite Hankel data. fails-before: the pre-guard code
raised LinAlgError on all-NaN/inf input (proven by stashing prony.py).
Debug pass: property-probed fitting/ + diagnostics/ (empty/single/NaN/inf
inputs). Prony was the one clear, provable bug. choose_model({})->'M0' and
estimate_neff_geyer(NaN)->n are documented/defensible, left as observations.
Local gates: ruff 0, mypy 0, pytest 162 passed / 4 skipped, coverage 87.95%
(>=80). Anchor regressions 17 passed / 2 skipped, 0 anchor values changed.
Backup-First context: no destructive git ops (ref Working-agreements §2,
2026-05-16 data-loss incident) -- branch-create + commit + push only.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…jumps CI 3.10 numpy stubs are stricter on ndarray shape-tuples than the local numpy 2.4.6: 'target = target / norm' narrowed the 2D shape to a 1D-typed result. Wrap the reassignment in np.asarray(..., dtype=complex) to keep the generic ndarray annotation (same pattern as resolvent.py). Caught by the now-enforcing mypy gate -- exactly its purpose. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Targeted hardening of LiouScope (4 candidates from a verified deep-dive) plus a debug pass. No anchor values changed. No destructive git ops (ref AGENTS.md Working-agreements §2 / 2026-05-16 data-loss incident — branch-create + commit + push only).
1. EPS harmonization (S) —
diagnostics/nonnormality.pyThe hard-coded
1.0e-300divide-by-zero floor for the Petermann inner product|<l,r>|^2is now the named, shared_consts.EPS_DIV. The value is kept:1.0e-300is a floating-point underflow floor (≈ smallest normal double), not a physics tolerance — collapsing it ontoEPS_GAP=1e-10would wrongly flag near-defective-but-finite modes asinf. Verified empirically that the canonical fixtures havemin|<l,r>|^2 ≈ 0.91…0.99, far from any threshold ⇒ no anchor change.2. mypy CI gate (M) —
ci.ymlRemoved
continue-on-error: true. Fixed all 18 previously type-blind findings (mostlyno-any-returnfrom numpy ops → annotated return locals; oneis_dataclassinstance-narrowing inio/export.py). No behaviour change.mypy src/liouscopenow exits 0.3. Zhou guard (M) —
_zhou.pyAdopted canonical
EPS_DIV(division floor) +EPS_GAP(zero-eigenvalue check) instead of inline magic numbers, matchingnonnormality. New tests:{0,0,-1,-1}⇒ gap=1 (hand-derived, numerically confirmed); diagonal ⇒ K=1; predictor collapses tot_lower = t_upper = log(1/eps)/gap = log(1000) = 6.9077….K_max→inf), sot_upperstays finite.4. Prony fallback (S) —
fitting/prony.pynp.linalg.lstsq/np.rootson a near-singular Hankel matrix could raise or yield garbage. Now wrapped intry/except (LinAlgError, ValueError)→ emitsRuntimeWarning+ falls back to a safe_default_seed(strictly positive amplitude).fails-before proof (stashed
prony.py, ran new tests against pre-guard code):Debug pass
Property-probed
fitting/+diagnostics/with empty / single / NaN / inf inputs. Prony was the single clear, provable bug. Two observations left as-is (documented/defensible, not bugs):choose_model({})→"M0"(documented baseline fallback);estimate_neff_geyer(all-NaN)→n(NaN propagation).Anchor impact
pytest tests/test_anchors.py→ 17 passed / 2 skipped (QuTiP), 0 anchor values changed.Test plan
ruff check src tests→ exit 0mypy src/liouscope→ exit 0 (18 → 0)pytest -q→ 162 passed / 4 skipped (was 155; +7 new tests)pytest --cov=liouscope --cov-fail-under=80→ 87.95% coverage🤖 Generated with Claude Code