Repository navigation
Pre-release audit fixes (R1–R10 + S/J/A/T/D): Beta → RC - #6
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, alpha=2.1 valley diagnostic Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Engine B prescribed-density halo+core demo: Plummer halo (Osipkov-Merritt anisotropic) + EFF(gamma=5) core, sampled in shared-potential equilibrium, recovering (t, r_a, r_h) by joint MLE + Gauss-Newton Fisher from two binned observables: per-component sigma_1d(r) (binned EXPECTATION, amendment 4) and the halo OM beta(r)=r^2/(r^2+r_a^2) closed form (amendment 3). Velocity scale is the engine's own kappa=G M_sampled/(4 pi mu) convention. Run (N=3e4, exit 0, ALL PASS): t=0.602+/-0.008 (pull 0.22), r_a=3.05+/-0.05 (0.96), r_h=2.02+/-0.03 (0.51); all 3 dispersed inits -> identical loss 19.1479 (robust optimum); realizability min(f_min_j)=1.16e-4; self-consistency max|dev/se|=2.34; Fisher PD cond 13.4, near-zero param correlations. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The occupancy gate printed "STOP: ... a component is starved" but fell through to make_figure() before the deferred nonzero exit -- unlike the self-consistency (exit 1) and budget (exit 2) early gates. A "STOP" that doesn't stop would save a misleading figure on a genuine occupancy failure. Add sys.exit(4) so a starved fit stops before the figure. (Untaken in the passing run -- 16/16 bins both components -- so the headline result stands.) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New 60-science-demos/ section, four pages + six embedded figures, after the
Validation group. Pedagogical prose with governing equations and honest
clean-mock caveats; every number traces to a freshly-run printed table.
- index.md -- the shared physics-direct differentiable inference method
(binned kinematic summaries -> Gaussian likelihood vs
analytic predictions; gradients through the analytic side;
MLE + Gauss-Newton Fisher + NUTS) and honest-scope warning.
- cross-engine.md -- B1: King built by Engine A (lowered-isothermal DF + ODE)
vs Engine B (density-defined Eddington); KS 1.5e-4,
sigma-dev 3.5e-4, Q_j 0.50019/0.50000 (re-run, ALL PASS).
DF eq verified vs GZ15 eq 2 (index g; g=1 -> e^x-1 King).
- imf-equipartition.md -- B2: one alpha drives masses AND equipartition groups;
joint (alpha,delta,W0) recovery 2.293/0.397/4.990 (all 3s);
mass channel pins alpha 4.7x (Fisher rho -0.265->-0.059);
NUTS 0-div post-mean ~MLE; wrong-IMF bias + robustness grid.
- halo-core.md -- B3: Plummer halo (OM) + EFF core; (t,r_a,r_h) recovery
0.602/3.051/2.015 (all <1s); realizability + OM beta.
myst build: exit 0, 0 warnings, 151 pages (the plan's 148 assumed a 144
baseline; the merged LIMEPY arc grew it to 147, + these 4 = 151).
50-validation/index.md gains a one-line cross-link to the new section.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
FULL released-core gate 1192 passed (9:07), exit 0. Demos B1/B3/B2d exit 0 ALL PASS fresh; B2 recovery + all gates PASS fresh (bit-identical to the gold reference; clean exit 0 in ccf6ed1). myst build 151 pages, 0 warnings. Batch B science demos (Tasks 1-9) complete on feat/batch-b-demos; merge/push awaits Anna's go. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tation plan Source-of-truth references for the prerelease-audit-fixes arc. STATUS.md test-count tweak carried along. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…CI red since 2026-06-10 (audit R1/D2)
CI died at `uv lock --check`/`uv sync --locked` with 'Distribution not found
at ../jaxstroviz': the lock pinned an editable path to the PRIVATE jaxstroviz
repo (dragging private fluxax + gravax transitively), which the default
GITHUB_TOKEN cannot check out cross-repo.
Rather than introduce a cross-repo PAT on the PR gate, drop jaxstroviz from the
declared deps entirely (Anna's call). It is only used by the experimental SBC
figure gallery + integer-aware chi^2 helpers (AC18), which already
pytest.importorskip('jaxstroviz') and are xfail. The lock now resolves with
only the PUBLIC jaxstro path source (99 pkgs, no private repos).
Verified in a throwaway venv synced from the new lock with NO jaxstroviz:
- uv sync --locked --extra dev --extra experimental: exit 0
- tests/experimental -m 'not slow': 13 passed, 0 errors
- test_ac18_sbc_rank_uniformity: SKIPPED ('could not import jaxstroviz')
Local figure work: `uv pip install -e ../jaxstroviz`.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ures (audit T4) Adds a directory-level strict guard (test_strict_refs.py) and converts the silent pytest.skip in the LIMEPY parity loader to pytest.fail under strict mode, so a checkout/packaging mistake can no longer silently disable the strongest external-reference gate. Verified: strict+absent -> FAIL, non-strict+absent -> SKIP, present -> PASS, no-env -> SKIP. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ations (audit R8) The trust anchors (LIMEPY reference parity, multimass equilibrium, Engine A-vs-B, Engine B AD-vs-FD) are @pytest.mark.slow and the PR gate runs -m 'not slow', so they ran nowhere but Anna's laptop. New lane runs pytest tests -m slow nightly + on v* tags, with PROGENAX_STRICT_REFS=1 so a missing reference cache fails (T4). Only the public jaxstro sibling is checked out (lock decoupled from private jaxstroviz/fluxax). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…onvention (audit R3) Twin excess was mixed against the full q in [0.1,1] population; MD17 p.5/Fig.2 define F_twin relative to q>0.3. Realized F_twin at (M1=1, logP=1) was 0.367 for a Table-13 value of 0.300 (+22% twin overweight). Mixture rebuilt as PL + ft/(1-ft)*I_B twin block, jointly normalized; the q>0.3 excess is now ft exactly. Pinned at four Table-13 nodes; sample P(q>0.95) re-derived from pdf quadrature (was a stale magic constant encoding the overweight). RED->GREEN: realized 0.3672 != 0.3000 (buggy) -> all 21 pass; downstream MoeJointOrbit/MoeCompanions/gradients 405 passed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…optax (audit R1 follow-up) CI (finally running after the lock decouple) exposed a latent bug red CI had hidden: this released-core UNIT test imports scripts/_demo_inference.py, which imports optax/blackjax (the [experimental] extra). The released-core unit shard syncs --extra dev only -> ModuleNotFoundError: optax fails the whole shard. Local gates passed only because the dev venv also had experimental installed. Moved tests/unit -> tests/experimental/unit (runs in the experimental CI lane where optax is synced); fixed the repo-root parents[2]->[3] path depth. Verified: 17 passed from new location; tests/unit collects 907 clean in an optax-free venv. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… King+Michie (audit R4) Linear 1000-pt grids left <10 points in the core at W0>=9: measured core-mass errors +18% (W0=9) and +270% (W0=12) vs a dense ODE reference. r = r_t*u^2 grid + non-uniform trapezoid (per-interval diff(r_grid) weights). King + Michie fixed and verified: RED W0=12 @ 0.3 r_c: +270.3% (matches audit +264%) GREEN all R4 tests pass; W0=7 quadrature gates unchanged; 251 profile tests pass AD-vs-FD W0 gradient ratio 0.999805 (pre-fix 0.999869) — differentiability preserved EFF DELIBERATELY left on the linear grid: it has NO measured core-resolution bug at typical r_t/a, and compute_profile_potential (profiles/api.py) reads the same _r_grid with a uniform-dr enclosed-mass integral, so a non-uniform EFF grid would silently break the EFF potential. Making EFF non-uniform-consistent (eff.py CDF + api.py potential + its mirror test) is a clean follow-up flagged for CHECKPOINT 1 — Anna's call, since EFF has no measured bug. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ently undershooting (audit R5) Measured: target 500 Msun, n=1000 returned 349 Msun with no warning (the one-sided quantile stretch q*<=1 caps the total at sum(ppf(u_base)), and the clipped Newton solver converged to the boundary silently). Adds the stratified-ceiling guard (eager inputs raise ValueError; traced m_total skips the check so jit/grad still work — verified grad ~0.9999), an honest docstring, and the first-ever tests for the mass-target sampling-mode family (sample_m_total prefix-cut overshoot, _packed fractional-boundary exactness, fixed_n reachable). RED: test_unreachable_target_raises DID NOT RAISE -> GREEN 6 pass; imf 272 pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…where to PowerLawIMF (audit R10) Four sites (segment_integral, _cdf_unnorm, ppf incl. **(1/e), mean_mass first_moment) used the bare where(|e|<eps, log, pow/e) pattern; the untaken branch computed 0/0 and the where-VJP backprops 0*NaN -> grad(mean_mass)(1.0) and grad(ppf)(1.0) were nan. Ported the exp_safe double-where (e_safe in EVERY power/division of the regular branch) from imf/differentiable.py. Per Anna's call (keep exp_safe; honest test): the fix gives FINITE grads everywhere + FD-exact grads in a neighborhood of a=1; AT exactly a=1 the double-where selects the alpha-independent log branch (grad branch-limited at a measure-zero point — same property as the reference differentiable.py). Tests pin the achievable guarantee, asserting MORE than the prior convention: finite AT a=1, FD-exact at a=1+/-1e-3, kink-free forward value through a=1. RED: grad nan at a=1 -> GREEN 25 pass; imf physics 46 pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…audit R4)
Per Anna's call: make EFF non-uniform-consistent so it resolves the core at
large r_t/a like King/Michie. Three coupled changes kept in lockstep:
- eff.py: sqrt-stretched _r_grid (r = r_t*u^2) + non-uniform trapezoid CDF
- profiles/api.py: compute_profile_potential's EFF enclosed-mass/outer-shell
integrals (I2, J_outer) now weight each trapezoid by diff(rgrid) — required
because they read the same _r_grid; a uniform dr would silently mis-integrate
the core and break M_enc_frac == profile CDF.
- test_profile_potential.py mirror: recompute with diff(rgrid) (invariant
unchanged: potential enclosed mass == profile CDF).
Measured (r_t/a=100, dense-quadrature reference, n=4e6):
0.3a core mass error +4.2% (linear) -> +0.02% (stretched), within shot.
Pinned by a new slow TestEFFHighRtOverACoreResolution. EFF AD-vs-FD r_t
gradient ratio 1.000097. Regression: eff physics + profile potential 31 pass;
eddington + profiles 192 pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…1991) (audit R6) Previous exponents were inverted vs MS homology (uncited): 10 Msun -> 6.3 Rsun instead of ~4.8, 0.2 Msun -> 0.40 instead of ~0.23, and a factor-2.4 jump at the hydrogen-burning limit (audit F7). Now D&K91 Eqs. 5-6: R = 1.06 M^0.945 (0.08<=M<1.66), R = 1.33 M^0.555 (M>=1.66), BD plateau <0.08. Low-mass branch meets the BD plateau near-continuously (0.0975 vs 0.1). Tests anchored to the published fit + observed radii (Anna's call: D&K91 over Tout+1996). RED 4 fail -> GREEN 11 pass; downstream ICResult consistency 36 pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t T8/R1 follow-up) CI (running after the lock decouple) exposed test_eff_table_bit_identical_after_refactor failing on Linux by ~1 ulp: it pinned full-precision float literals captured on macOS-ARM and compared with ==. Cross-platform FP makes bit-exact == non-portable. Relaxed to pytest.approx(rel=1e-9) (Anna's call) — ~6 orders above the ulp noise floor, still catches real refactoring drift; renamed *_bit_identical_* -> *_stable_*. Local: 2 pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…efused (eager) (audit J4) _auto_ode_domain falls back to the fixed (300, 2000) domain under tracing; for W0 >~ 10 the ODE never crosses psi=0 there and _find_tidal_radius silently pinned xi_t to the boundary -- a wrong r_t exactly where the user can't see it. Adds r_t_is_pinned (Bool, = no psi crossing in the solved domain). from_W0_rc now REFUSES eagerly for concrete W0 when pinned (ValueError naming xi_max), and under tracing stores the flag (a traced bool can't gate a raise) -- the Engine-B concrete/traced pattern. Concrete high-W0 auto-sizes fine (no raise). RED 4 (no r_t_is_pinned attr) -> GREEN 4; King regression 53 pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…locities_to_virial (audit J5)
virial_scale divided by Q_current with no guard -> cold input (v=0) yielded
all-NaN velocities silently. Rescaling from T=0 is mathematically impossible
(0/0). Now ONE implementation in dynamics.virial.rescale_velocities_to_virial
(virial_scale delegates): concrete T=0 raises ValueError('zero kinetic'),
traced T=0 yields NaN via a double-where (honest sentinel; the old +1e-10 hack
silently mapped cold input to ~0). RED 2 -> GREEN; builders+dynamics 42 pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s compiling both branches (audit J6) Two sites used jax.lax.cond on a STATIC Python int (q_approx auto-dispatch on N, and _compute_s_bar_subsampled on n_pairs<=max_pairs), so XLA compiled BOTH branches every shape (~0.4 s wasted) and traced the O(N^2) exact() path even when subsampling. Replaced with Python if — identical semantics, half the compile, and no (N,N) allocation for large N. Equivalence pinned: auto==naive (small N), auto==fast (large N). substructure+diagnostics 60 pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ocityDF.r_t field (audit S1/A3/M4) S1: KingProfile's direct constructor accepted an arbitrary r_t inconsistent with c(W0) (the README's own KingProfile(W0=7,r_c=1,r_t=10) builds a non-self-consistent, non-equilibrium model). For concrete, non-pinned inputs it now warns (>5% deviation from r_c*xi_t); from_W0_rc derives r_t so never trips. A3: KingVelocityDF.r_t was stored but never used (sigma^2 = GM/(9 r_c mu); truncation comes from psi(xi)). Removed the field + param (no compat shim) and updated every callsite (~18). end_to_end King IC made self-consistent. Design (flagged for CHECKPOINT 2): WARN (not raise) on inconsistent r_t. NOTE: ~6 tests deliberately construct inconsistent King ICs (e.g. the r_t- truncation test) and now emit the warning (non-failing) -- follow-up to suppress/assert. RED -> GREEN; affected suites 170 pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
protocols.py:54 and kinematics/api.py:53 were two structurally identical runtime_checkable VelocityDF Protocols — a drift hazard. kinematics.api now imports + re-exports the canonical progenax.protocols.VelocityDF (no importer referenced the api.py copy). Pinned: api.VelocityDF IS protocols.VelocityDF. protocols + api + rotation 34 pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-level caveat (audit S2) The default EFF DF (gamma=3, sharp truncation) is knowingly ~8% sub-virial (Eddington inversion of a truncated rho with rho(r_t)>0 — disclosed in the module docstring, but the DEFAULT config is the broken case and nothing pinned it, so a regression to -15% would have passed). Measured-first: Q=0.458+/-0.0004 (N=20000, seeds 0/1/2). Frozen band 0.45<Q<0.47 pins the ~8% offset and catches both a -15% regression (Q<=0.425) and a vanished offset (Q>=0.49). Also surfaced the caveat at the EFFVelocityDF constructor docstring (was module-level only). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The unit tier (~900 tests) ran in ONE process and OOM-killed the 2-core/7 GB runner (exit 143, tests passing then SIGTERM at ~52%). Split into unit-a (imf), unit-b (profiles+binaries), unit-c (catch-all: tests/unit minus those) -- ~300 each in a fresh process, so cumulative JAX memory resets. unit-c uses --ignore so a new tests/unit subdir is still covered without editing the matrix. Partition verified locally: 281+318+305 = 904 = whole unit (not-slow). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…IMF/EnvironmentIMF claims (audit R7) 15 documented symbols (PowerLawIMF..MassDependentBinaryFraction + UniformSphereProfile) were promised by the docs but not exported from progenax.__init__. Added them + __all__ entries. IGIMF/EnvironmentIMF NEVER existed as classes (the environment-dependent IMF is the functional BirthEnvironment + env_to_imf_params API, Marks+2012/Jerabkova+2018 alpha3 relations, NOT galaxy-wide IGIMF integration). Purged the phantom CLASS mentions from CLAUDE.md (module table, test desc, exports list) and cluster/__init__.py; legitimate Jerabkova-2018 IGIMF-relation citations in science pages kept. RED 15 -> GREEN; documented-api + public-api + protocols pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…amples smoke test (audit R7/D3/D4/H2) README taught a DELETED API (TwoComponentConfig/generate_two_component_cluster), advertised phantom IGIMF/EnvironmentIMF classes + apply_osipkov_merritt(), had wrong kwargs (two_body_kepler m1/m2, KeplerElements.to_state['position']), reused PRNG keys, conda install, and stale LOC/test counts. Rewritten against reality: MultiComponentCluster + Michie + LIMEPY in the feature tables, anisotropy_radius constructor arg, KingVelocityDF without r_t, uv-first side-by-side-checkout install, not-on-PyPI banner, counts dropped (point to CI), '9 protocols'. New tests/integration/test_readme_examples.py executes EVERY python block (RED: TwoComponentConfig ImportError -> GREEN: 9 blocks pass). installation.md: split-repo clone, real extras (dev/experimental/diagnostics), split-key smoke test (was the reused-key anti-pattern). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t D5/H4) ic-redesign-history.md claimed 'pip install progenax-legacy still works' — it does not exist (no PyPI package, no git tag/branch, no ../legacy/progenax-legacy; ../legacy has only gravax-legacy + stellax-legacy). Replaced with the honest path: check out the pre-redesign commit from git history (redesign documented in the development log). Zero progenax-legacy hits remain in live docs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…cation, segregation, energy-budget, subgroup virial (audit S3/S4/S6/S10/S16/S15) - rotation.py (S3): module + both transforms now state they are KINEMATIC OVERLAYS that inject KE + L_z -> NOT stationary (Q>0.5); an isotropic rescale can't restore stationarity. (S15) concrete zero axis now RAISES (was a silent no-op under a stale 'result will be NaN' comment) via _normalized_rotation_axis + 2 tests. - kinematics/api.py (S3): Stage-3 target_Q note — isotropic rescale does not remove the rotation-injected L_z, so rescaling-to-0.5 is not a fix. - tidal.py (S4): survivors are super-virial w.r.t. the truncated potential (some formally unbound near r_t); re-virialize or use King/LIMEPY. - cluster/mass_segregation.py (S6): segregated mass-weighted density != parent -> self-consistent potential differs; finalize with a global virial rescale. - binaries/diagnostics.py (S10): Q_resolved is DEFLATED (~0.31), not inflated; softening does NOT soften E_internal (S18). - dynamics/virial.py (S16): per-group W_j is origin-DEPENDENT for subgroups; positions must be pre-centered on the cluster COM. 180 affected tests pass (incl. 2 new S15 zero-axis tests). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ng (audit T5/L3/D6) tests/README.md said 874, CLAUDE.md said 1163 — three documents, three numbers. Updated both to the current released-core count (~1243: unit 956, integration 43, validation 244; FAST/not-slow ~1192) and added 'see CI for the live count' so the numbers stop rotting. STATUS.md count refreshed at the final checkpoint. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eel metadata (audit D1/C3) No LICENSE file existed and the wheel METADATA had no license/author/classifier/ URL — the README's bare 'MIT' was an unenforceable claim. Per Anna's call the license is APACHE-2.0 (not MIT): added the full Apache 2.0 LICENSE (Copyright 2026 Anna Rosen), license='Apache-2.0' + license-files + authors + keywords + classifiers + [project.urls] in pyproject, and fixed the MIT->Apache claims in README + docs/website/myst.yml. Verified the built wheel METADATA carries License-Expression: Apache-2.0, License-File, Author-email, Classifiers, and the Repository URL, with no experimental/gravoturb leakage. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ctionable errors (audit R9) progenax.diagnostics imported numpy+scipy eagerly (substructure.py, mass_ segregation.py, pulled in by diagnostics/__init__.py), but neither was a declared dependency -> 'from progenax.diagnostics import compute_q_parameter' (and even 'import progenax.diagnostics') exploded in a clean install. Moved numpy/scipy behind a lazy _diagnostics_deps() helper (from __future__ import annotations so the np.ndarray annotations don't need np at def time); 'import progenax.diagnostics' + the JAX-native q_approx now work without scipy, and the scipy-backed estimators raise an ImportError naming 'progenax[diagnostics]'. Added the [diagnostics] extra (numpy>=1.24, scipy>=1.11). RED (import crash) -> GREEN; diagnostics+substructure 62 pass; subprocess test masks scipy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…oot (audit M6/T3/R1) - wheel-smoke job: build the wheel, install in a CLEAN venv with only public jaxstro, import progenax + progenax.diagnostics (no scipy present -> exercises the R9 lazy import). Wired into the 'tests' aggregator's needs. - physics-validation.yml: nightly version-matrix (3.10 + 3.13) running a memory- safe core slice (imf + profiles) -> covers requires-python>=3.10 (T3). - OOM root cause: the unit-b shard kept getting SIGTERM (exit 143) on the 7 GB runner because JAX caches every compiled executable and the diffrax-ODE profile/DF families accumulate unboundedly. conftest now clears the JAX cache between test MODULES in CI (gated on $CI; PROGENAX_CLEAR_JAX_CACHES=1 locally) so memory is bounded. Also isolated the two heaviest modules (imf, profiles) into their own shards; unit-c is the catch-all. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per-finding summary (R1-R10 + S/J/A/T/D handled) with commit refs, plus the known-limitations/deferred section (R2 pip-installability strategy, A2 units policy, R5 two-sided stretch). The R2 jaxstro-publish-vs-vendor decision is flagged for Anna, not implemented unilaterally. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…x arc Per-finding before/after evidence table (R1-R10 + S/J/A/T/D), lessons learned, and the open Anna-decision list (R2 jaxstro strategy, merge/PR, deferred A2/ two-sided-stretch). STATUS next: line updated to reflect the completed arc + the two blocking Anna decisions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…r startrax The D&K91 main-sequence relation is a static ZAMS approximation; flag that it will be replaced by the startrax package (first Tout+1996 ZAMS radii, then MIST and Hurley+2000 SSE tracks with real mass- and age-dependent stellar evolution). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bc98083997
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| ## Figure | ||
|
|
||
| :::{figure} figures/cross_engine.png |
There was a problem hiding this comment.
Commit the referenced science-demo figures
The new Science demos pages now render {figure} directives for figures/cross_engine.png, halo_core.png, and the IMF/equipartition PNGs, but I checked rg --files docs/website/60-science-demos and only the three Markdown files are present—there is no figures/ directory. In a docs build or published site this leaves every demo page with missing/broken images despite the text claiming the figures are embedded, so please add the generated PNGs under docs/website/60-science-demos/figures/ or remove the directives.
Useful? React with 👍 / 👎.
Pre-release audit fixes — Beta → Release Candidate
Resolves every release blocker from the 2026-06-11 pre-release adversarial audit
(
docs/reviews/2026-06-11-prerelease-adversarial-audit.md) via strict RED→GREEN TDD.Plan:
docs/plans/2026-06-12-prerelease-audit-fixes.md. Completion evidence:.claude-work/PRERELEASE_AUDIT_FIXES_COMPLETE.md.Highlights (audit findings R1–R10 + S/J/A/T/D)
CI un-broken and hardened (R1/D2/R8/T4/M6/T3)
jaxstrovizsibling (CI had been red since 2026-06-10).jax.clear_caches()between modules + unit sharding.Science fixes
F_twin→ paper's q>0.3 convention (0.367 → 0.300).sample_fixed_nraises on unreachable target (was a silent 30% shortfall).compute_stellar_radii→ Demircan & Kahraman (1991).JAX/API: J4 King r_t pinning flagged/refused; J5
virial_scaleT=0 guard + dedupe; J6 q_approx dispatch; S1/A3 King r_t warn + dead-field removal; A1 protocol dedupe.Docs/packaging: R7 exported 15 documented symbols + killed phantom
IGIMF/EnvironmentIMF; README rewrite with an executable-examples smoke test; D5 removed the fabricatedprogenax-legacy; Apache-2.0 LICENSE + wheel metadata; R9[diagnostics]extra + lazy numpy/scipy; CHANGELOG.Verification
PROGENAX_STRICT_REFS=1):1244 passed, exit 0.1191 passed, exit 0. myst build: 151 pages, 0 warnings.Deferred (separate decisions/arcs)
jaxstroto PyPI (chosen; follow-up, mostly in the jaxstro repo).sample_fixed_ntwo-sided stretch; suppress/assert the new S1 warning in ~6 deliberately-inconsistent King-IC tests.🤖 Generated with Claude Code