Repository navigation
fix: intra-family version floors — autolens[optional] import fails #687
Description
Overview
pyauto-heart verify_install Check D (pip install "autolens[optional]") is FAILING, and is one of the two legs holding release readiness RED (sidecar 2026-08-03T06:01:09Z, PyAutoHeart run 30788224561, job 91606144514). The install succeeds but import autolens raises AttributeError: module 'autofit' has no attribute 'Latent' — pip resolved autofit 2026.4.30.582, an April release, alongside a 2026.8.2.1 autoarray/autogalaxy/autonerves.
The cause is that every intra-family dependency across the five libraries is a bare package name with no version floor. When pip backtracks through the [optional] -> [jax] -> autofit[jax] -> autonerves[jax] extras chain it may walk the release history back to 2022, and it treats "version X does not provide the extra 'jax'" as a warning rather than an error — so an ancient autofit with no jax extra is a legal solution, and pip settles there. This is a real user-facing defect, not a CI artefact.
Plan
- Add
>=2026.7.29.2floors to the cross-package intra-family dependencies in PyAutoArray, PyAutoFit, PyAutoGalaxy, PyAutoLens and PyAutoCTI — in both the basedependenciesand the[jax]extras. - Leave self-referential extras (
autolens[jax]insideautolens[optional], and siblings) unfloored: a self-reference is already version-locked, and a floor there would make a local1.0.dev0wheel build unsatisfiable. - Make
verify_installCheck D name the interpreter it used in its sidecar detail, so a CI-vs-local Python divergence can never hide a resolution bug again. - Verify on both python3.12 and python3.13 before shipping — the bug is invisible on 3.12.
Detailed implementation plan
Affected Repositories
- PyAutoLens (primary)
- PyAutoArray
- PyAutoFit
- PyAutoGalaxy
- PyAutoCTI
- PyAutoHeart (Check D evidence detail)
- PyAutoNerves — inspected, no change needed (only self-references)
Branch Survey
| Repository | Current Branch | Dirty? |
|---|---|---|
| ./PyAutoNerves | main | clean |
| ./PyAutoArray | main | clean |
| ./PyAutoFit | main | clean |
| ./PyAutoGalaxy | main | clean |
| ./PyAutoLens | main | clean |
| ./PyAutoCTI | main | clean |
| ./PyAutoHeart | main | clean |
worktree_check_conflict reports formal claims on PyAutoFit (point-source-defaults-campaign, nautilus-1core-serial-pool, simulator-util-to-af-ex), PyAutoLens (point-source-defaults-campaign) and PyAutoHeart (interferometer-start-here-integrate-oom). Each claiming branch was diffed against origin/main: none touches pyproject.toml, and the PyAutoHeart branch has an empty diff (already merged). No genuine file-level overlap; proceeding rather than parking, since this is a release-RED leg.
Suggested branch: feature/intra-family-dep-floors
Implementation Steps
PyAutoArray/pyproject.toml—dependencies:"autonerves"->"autonerves>=2026.7.29.2";[project.optional-dependencies] jax:"autonerves[jax]"->"autonerves[jax]>=2026.7.29.2". Leave theautoarray[jax]self-reference inoptionalunchanged.PyAutoFit/pyproject.toml— same two edits (autonerves,autonerves[jax]). Leave theautofit[jax]self-reference unchanged.PyAutoGalaxy/pyproject.toml—dependencies:"autofit","autoarray"->>=2026.7.29.2;jaxextra:"autofit[jax]"->"autofit[jax]>=2026.7.29.2". Leave theautogalaxy[jax]self-reference unchanged.PyAutoLens/pyproject.toml—dependencies:"autogalaxy"->"autogalaxy>=2026.7.29.2";jaxextra:"autogalaxy[jax]"->"autogalaxy[jax]>=2026.7.29.2". Leave theautolens[jax]self-reference unchanged.PyAutoCTI/pyproject.toml—dependencies:"autofit","autoarray"->>=2026.7.29.2.PyAutoHeart/heart/checks/verify_install.sh— incheck_d, capture the venv interpreter version and include it in both the PASS and FAILRESULTS+=(...)detail strings, matching how Check B names its interpreter.
Why 2026.7.29.2 is the right floor
It is live on PyPI, is not yanked, and is the oldest release that still carries af.Latent. This is a floor, not an exact pin — consistent with the floors-not-pins release design (PyAutoBuild#118/#120). A floor must name an installable version.
Testing
- Control test, already run on both interpreters before this issue was filed:
- without floors, python3.13, TestPyPI+PyPI ->
autofit 2026.4.30.582,import autolensraises - with floors, same command/interpreter ->
autoarray/autofit/autogalaxy/autonerves 2026.8.2.1, import OK
- without floors, python3.13, TestPyPI+PyPI ->
- After the edits: rebuild the five wheels, re-run
pip install "autolens[optional]"on python3.12 and python3.13, confirm newest-family resolution and a clean import in both. pyauto-heart verify_install D.
Known trade-off
The verify_install skill doc's B --version 1.0.dev0 --find-links dist/ example will no longer resolve intra-family wheels out of dist/, since 1.0.dev0 < 2026.7.29.2. Release CI is unaffected: it builds dated dev versions (e.g. 2026.8.3.1.dev69801) that clear the floor.
Timing note
The floors only take effect once new wheels are published. The RED verify_install leg does not clear until a release rehearsal republishes to TestPyPI and Check D re-runs against those wheels.
Key Files
PyAutoArray/pyproject.toml,PyAutoFit/pyproject.toml,PyAutoGalaxy/pyproject.toml,PyAutoLens/pyproject.toml,PyAutoCTI/pyproject.toml— intra-family dependency floorsPyAutoHeart/heart/checks/verify_install.sh—check_dinterpreter in the evidence detail
Original Prompt
Click to expand starting prompt
autolens[optional] resolves an ancient autofit — intra-family deps have no version floors
Type: bug
Target: health_fixes
Repos:
- @PyAutoNerves
- @PyAutoArray
- @PyAutoFit
- @PyAutoGalaxy
- @PyAutoLens
- @PyAutoCTI
Difficulty: low
Autonomy: supervised
Priority: high
Status: draft
Finding (2026-08-03, PyAutoHeart readiness RED)
pyauto-heart verify_install Check D (pip install "autolens[optional]") FAILED
in the Release Integrate run (PyAutoHeart run 30788224561, job 91606144514),
sidecar ~/.pyauto-heart/verify_install.json 2026-08-03T06:01:09Z,
detail pip rc=0 import rc=1. It is one of the two legs holding the release RED.
The install succeeds; the import does not:
[05:58:53] -> import autolens
Traceback (most recent call last):
import autolens; print(autolens.__version__)
AttributeError: module 'autofit' has no attribute 'Latent'
Check D resolved autofit 2026.4.30.582 (an April release, pulling
autoconf 2026.7.15.1 with it) while autoarray / autogalaxy / autonerves came
in at 2026.8.2.1.
Root cause
autolens[optional] expands to
autolens[jax] -> autogalaxy[jax] -> autofit[jax] -> autonerves[jax].
Every intra-family dependency in the five pyproject.toml files is a bare
package name with no version floor ("autofit", "autoarray",
"autogalaxy", "autonerves"). When pip backtracks anywhere in that extras
chain it may walk the entire release history back to 2022 — and pip treats
"version X does not provide the extra 'jax'" as a warning, not an error,
so an ancient autofit carrying no jax extra is a legal solution. pip settles
there after ~22,600 lines of backtracking.
The metadata itself did not regress: requires_dist for autonerves / autofit /
autogalaxy is identical between 2026.7.29.2 (PyPI) and 2026.8.2.1
(TestPyPI). The whole 2026.8.2.1 family is TestPyPI-only; PyPI's newest is
still 2026.7.29.2.
Why it passed locally and failed in CI
Check D builds its venv with the default python3. The verify_install_release
job calls setup-python for 3.11, then 3.12, then 3.13 — the last wins, so CI's
python3 is 3.13. Locally it is 3.12. Reproduced on both, same command,
same index args:
| interpreter | resolved autofit | import autolens |
|---|---|---|
| 3.12 | 2026.7.29.2 | passes (still has Latent) |
| 3.13 | 2026.4.30.582 | AttributeError |
Both are backtracked; 3.12 merely stops at a version that still has Latent.
This is a real user-facing defect, not a CI artefact — pip install autolens[optional] from live PyPI today also silently walks the family back.
Control test — floors fix it
Same command, same python3.13, floors added:
pip install "autolens[optional]==2026.8.3.1.dev69801" \
autofit>=2026.7.29.2 autogalaxy>=2026.7.29.2 \
autoarray>=2026.7.29.2 autonerves>=2026.7.29.2
-> autoarray 2026.8.2.1 autofit 2026.8.2.1
autogalaxy 2026.8.2.1 autonerves 2026.8.2.1
-> import autolens: OK
Without the floors the identical command lands on autofit 2026.4.30.582 and
raises.
Task
- Add
>=2026.7.29.2floors to every intra-family dependency — base
dependenciesand the[jax]/[optional]extras — in
PyAutoNerves, PyAutoArray, PyAutoFit, PyAutoGalaxy, PyAutoLens, and
PyAutoCTI (autofit,autoarrayare bare there too).
This is a floor, not an exact pin — consistent with the floors-not-pins
release design (PyAutoBuild#118/Feature/phase #120). A floor must name an installable
version, so2026.7.29.2(live on PyPI, not yanked) is the right value. - Make Check D state which interpreter it used in its sidecar
detail
(PyAutoHeart/heart/checks/verify_install.sh,check_d). "Default
python3" silently differing between CI (3.13) and local (3.12) is what hid
this; the evidence should name the interpreter the way Check B's details do.
Acceptance
pip install "autolens[optional]"on python3.12 and python3.13 resolves
the whole PyAuto family at the newest available release, andimport autolens
succeeds.- Check D's sidecar detail names the interpreter version.
- Note: the floors only take effect once new wheels are published. The RED
verify_installleg does not clear until a release rehearsal republishes to
TestPyPI and Check D re-runs against those wheels.
Activity
Jammy2211 commentedon Aug 3, 2026
Library PRs created
All six carry
pending-release. Branchfeature/intra-family-dep-floorsin each.Shipped under the corrective-PR exception for Heart RED, human-authorized in
session, scoped to the RED reason
install verification FAILED (testpypi; checks D).Open-PR only — merge and release stay a separate human act. The other RED reasons
(
PyAutoFit: 1 commit(s) behind origin,release validation FAILED (stage integrate))are untouched by this work.
Verification
The first pass at verifying this was contaminated and is worth recording: the
dev shell exports
PYTHONPATHpointing at the five source checkouts, so ahand-rolled venv reports
Requirement already satisfiedfor every PyAuto packageand
import autolensloads the source tree rather than the installed wheel.(
verify_install.shitself is fine — itunset PYTHONPATHs at line 47.) Everynumber below is from a clean
env -u PYTHONPATHvenv.Discriminating test — the family built into wheels from this branch, autolens
pinned to the published (unfloored) dev wheel, siblings supplied via
--find-links,python3.13, TestPyPI + PyPI. Identical inputs; only the sibling metadata differs:
import autolensmain)2026.4.30.582AttributeError: module 'autofit' has no attribute 'Latent'2026.8.4.1This is the important one: it shows the floors bite transitively, from
sibling metadata, not merely as top-level pins.
Also confirmed:
tomllibparses every editedpyproject.toml; the built wheels'METADATAcarries exactly the intended
Requires-Distfloors, with the self-referencesstill bare.
pyauto-heart verify_install D --testpypi --version 2026.8.3.1.dev69801→D PASS ... (python 3.12.10).pytest tests/→ 338 passed.Correction to the plan
The issue body flagged a "known trade-off": that
verify_install B --version 1.0.dev0 --find-links dist/would stop resolvingintra-family wheels out of
dist/. That was wrong — pip already prefers thehigher released sibling (
2026.7.29.2>1.0.dev0) over a local1.0.dev0wheel, floors or no floors, because only
autolensis pinned by that invocation.The floors change nothing there. No regression; disregard that paragraph.
No workspace impact
Packaging metadata plus one Heart shell script — no Python symbol added, removed
or renamed, so there is nothing for a workspace script to migrate to.
/smoke_testwould also be structurally uninformative here: workspace scripts import the
libraries from the
PYTHONPATHsource checkouts, which never consultpyproject.tomldependency metadata.Still open
The floors only take effect once the libraries are republished carrying them.
The RED
verify_installleg does not clear until a release rehearsal republishesto TestPyPI and Check D re-runs against those wheels.
Jammy2211 commentedon Aug 3, 2026
Merged
All six PRs merged 2026-08-03 (all checks green on 3.12 and 3.13 before merge):
54ba44e8a26033fb4f4249384b8d582ecfdf55fd223ec2149156f1Worktree removed, feature branches deleted local + remote, all six main
checkouts synced. Completion record:
PyAutoMind/complete/2026/08/intra-family-dep-floors.md.Deliberately left open
The floors are inert until the libraries are republished carrying them —
the fix lives in packaging metadata, so the wheels currently on PyPI/TestPyPI
still have the bare dependencies that let pip reach
autofit 2026.4.30.582.This issue stays open until:
verify_installCheck D re-runs against those wheels and passes — its detailline will now name the interpreter, so a 3.13 pass is visibly a 3.13 pass.
Only then does the Heart RED leg
install verification FAILED (testpypi; checks D)clear.
Jammy2211 commentedon Aug 4, 2026
Closing — the condition this issue was deliberately held open for has been met.
The floors merged 2026-08-03, but as recorded at the time they only take effect
once the libraries are republished carrying them. That happened on
2026-08-04: release
2026.8.4.1published to PyPI at11:43:29Z(unyanked).1. The floors are in the published metadata (
requires_dist, PyPI JSON API):autolens2026.8.4.1autogalaxy>=2026.7.29.2,autogalaxy[jax]>=2026.7.29.2; extra=="jax"autogalaxy2026.8.4.1autofit>=2026.7.29.2,autoarray>=2026.7.29.2,autofit[jax]>=2026.7.29.2autofit2026.8.4.1autonerves>=2026.7.29.2,autonerves[jax]>=2026.7.29.2autoarray2026.8.4.1autonerves>=2026.7.29.2,autonerves[jax]>=2026.7.29.22. Check D passes in CI —
integrate / verify_install_releaseis SUCCESS inPyAutoHeart Release Integrate run
30901054267(2026-08-04T10:32), a run that isgreen end-to-end (51 success / 2 skipped / 0 failure).
3. Control test, re-run locally against the published wheels on the interpreter
that originally reproduced the bug. The write-up noted Check D only failed on
python3.13 (CI's last
setup-pythonwins) and passed on a 3.12 dev laptop, sothis was re-run on 3.13 specifically, in a fresh venv with
PYTHONPATHunset:Original failure was
pip rc=0 import rc=1withautofit 2026.4.30.582resolvedoff the backtracked extras chain. The resolver now lands on
autofit 2026.8.4.1and
af.Latentis present — theAttributeErroris gone.One residual, tracked separately, not a reason to hold this issue open:
autoction PyPI is still2024.11.13.2and its metadata carries the oldautofit==2024.11.13.2/autoarray==2024.11.13.2exact pins. PyAutoCTI#104landed the floors in source, but that package has not been republished on this
release cadence, so the fix is not yet live for
autoctiusers. Out of scope here— this issue is the
autolens[optional]chain, which is verified fixed.Record:
PyAutoMind/complete/2026/08/intra-family-dep-floors.md.