Overview
Finish the env-profile migration (build-chain campaign Phase 3, umbrella #155, research + design on #161; design doc docs/env_profile_redesign.md, merged #162; steps 1–3 shipped: validator #163, single resolver, scrubbed baseline env #165). In the ag/al release profiles JAX is re-enabled by a hand-enumerated list of ~10 path patterns — a list that silently rots: 15 scripts literally named for JAX (jax_assertions/, hessian_jax.py, tracer_jax.py, …) run NumPy in every nightly while asserting JAX behaviour. Step 4 replaces enumeration with the design's derivation rule (JAX-on in release mode iff a path segment/stem matches jax_* / *_jax / *_jit); steps 5–8 make the validator binding, rename the profiles, fold the duplicate library env read, and (human-gated) decide the use_jax sentinel.
This issue covers steps 4–8, executed in phases. This session: step 4 only.
Plan
Step 4 — the derivation rule (this session, three PRs, PyAutoHands first):
- Phase A (PyAutoHands): move
is_jax_marked from the validator into autohands/env_config.py (one owner of the rule); resolver applies the derivation when a profile sets a new derive_jax_markers: true top-level key (explicit key, not a filename heuristic); validator accepts the key, resolves through the shared logic, and skips non-runnable __init__.py files; unit tests. Old profiles + new resolver = unchanged behaviour, so this merges first.
- Phase B (autolens_workspace_test): rename the two mid-stem files
imaging/modeling_visualization_jit_delaunay.py → modeling_visualization_delaunay_jit.py (and _rectangular) so the _jit suffix carries the marker (human decision 2026-07-23); triage database/scrape/ on the NumPy path first — only fall back to a scrape_jax/ folder rename if JAX is genuinely required (human decision 2026-07-23; no exception list, ever); delete all 10 PYAUTO_DISABLE_JAX overrides from env_vars_release.yaml and add the key; triage the 10 runnable turns-ON scripts individually under their exact new JAX-on env (none has ever run JAX in the nightly).
- Phase C (autogalaxy_workspace_test): same minus renames/scrape — delete 8 overrides, add the key, triage the 3 runnable
jax_assertions/ scripts.
- Verification (binding): resolved-env diff via
resolve_clean() over every script, old profile vs new profile+rule, read line by line — must be exactly the triaged set and nothing else. Never smoke (smoke cannot see config-only changes). Prove against the real CI env (workspace-validation.yml), not a synthetic clean shell. The release path is only exercised by the nightly mega-run — mega-run verification accepted and stated on each PR.
Later phases (same issue):
- Step 5 — flip
--strict-derivation / --strict-markers to errors; wire the validator into the three *_workspace_test PR gates.
- Step 6 — rename
env_vars.yaml → profile_smoke.yaml, env_vars_release.yaml → profile_release.yaml (last; re-sweep for old names after every merge from main).
- Step 7 — fold
al.AnalysisDataset's duplicate PYAUTO_DISABLE_JAX read into base af.Analysis (own plan; PyAutoFit + PyAutoLens, library-first; currently queued behind the testmode-env-drift PyAutoFit claim).
- Step 8 —
use_jax: Optional[bool] = None sentinel: human decision required before any code; may be declined.
Detailed implementation plan
Affected Repositories
Branch Survey (2026-07-23)
| Repository |
Current Branch |
Dirty? |
| ./PyAutoHands |
main |
clean |
| ./autolens_workspace_test |
main |
clean |
| ./autogalaxy_workspace_test |
main |
clean |
No worktree conflicts (worktree_check_conflict clean for all three).
Suggested branch: feature/env-profile-derivation
Worktree root: ~/Code/PyAutoLabs-wt/env-profile-derivation/
Work classification: Both (PyAutoHands source first, workspace_test follow-ups)
Measured baseline (validator, 2026-07-23 — live re-measurement, not the stale 07-17 counts)
| repo |
override-enumeration |
JAX-marked but resolves NumPy |
unmarked but resolves JAX |
| autolens_workspace_test |
10 |
11 |
9 |
| autogalaxy_workspace_test |
8 |
4 |
0 |
| autofit_workspace_test |
0 |
0 |
0 |
Nuances found in planning: imaging/modeling_visualization_jit_delaunay.py / _rectangular.py are already in no_run.yaml (SLOW, 2026-05-07) — no immediate nightly impact, but post-migration the strict validator would see them as consistent NumPy scripts while their content asserts jax.Array, hence the rename. 4 of 7 database/scrape/ files are also no_run'd; only general.py + scaling_relation.py actually run. The 15 turns-ON scripts are not no_run'd — they genuinely run tonight on NumPy, so flipping them is a real nightly change and each is triaged individually.
Implementation Steps (Phase A)
autohands/env_config.py — move in is_jax_marked (from validate_env_profiles.py:46); in build_env_for_script, when env_config.get("derive_jax_markers") is truthy, after defaults+overrides: if is_jax_marked(file): env["PYAUTO_DISABLE_JAX"] = "0".
autohands/validate_env_profiles.py — import is_jax_marked from env_config (delete local copy); add derive_jax_markers to ALLOWED_TOP_KEYS; resolve_clean applies the same derivation via shared logic; skip __init__.py when collecting scripts.
- Unit tests (rule, derivation on/off, validator key,
__init__.py skip).
Implementation Steps (Phase B — al)
git mv the two renames; update config/build/no_run.yaml:26-27; sweep for other references.
- Scrape triage: run
database/scrape/general.py + scaling_relation.py under the resolved NumPy release env. Pass → drop override, state on PR. Fail (JAX-rooted) → git mv scripts/database/scrape → scrape_jax + sweep ~8 refs (smoke profile ×2, no_run ×4, release profile, AGENTS.md, folder CLAUDE.md).
config/build/env_vars_release.yaml — delete all PYAUTO_DISABLE_JAX overrides; add derive_jax_markers: true; rewrite header comment.
- Turns-ON triage (each under its exact new resolved env):
jax_assertions/ ×7, hessian_jax.py, profiles_jit.py, tracer_jax.py. Fail → trivial fix-forward, else no_run.yaml with dated reason, surfaced on the PR.
Implementation Steps (Phase C — ag)
As B steps 3–4: delete 8 overrides, add key, triage jax_assertions/ ×3.
Key Files
PyAutoHands/autohands/env_config.py — the single resolver; gains the rule + derivation
PyAutoHands/autohands/validate_env_profiles.py — PR-time gate; resolve_clean() is the verification harness
autolens_workspace_test/config/build/env_vars_release.yaml — 10 overrides to delete
autogalaxy_workspace_test/config/build/env_vars_release.yaml — 8 overrides to delete
PyAutoHeart/.github/workflows/workspace-validation.yml:295,322 — how the nightly invokes the release profile (read-only; parity check)
PyAutoHands/docs/env_profile_redesign.md — the decided design (§2 policy, §3 rule)
Config traps (from prior sweeps)
overrides: order is load-bearing (later entries win); an empty overrides: block loads as None, not []; verify config-only changes by resolved-env diff, never smoke.
Planning notes
Brain Feature Agent scored this too-large (score 25, repo-count proxy) and proposed a generic 4-phase split — overridden with the prompt's own step phasing (step 4 alone; 5+6 pair; 7 independent; 8 decision-first), recorded here per standing guidance.
Original Prompt
Click to expand starting prompt
Finish the env-profile migration: steps 4-8 (derivation, strict gate, rename, one-reader, sentinel)
Type: feature
Target: workspaces
Repos:
- autolens_workspace_test
- autogalaxy_workspace_test
- autofit_workspace_test
- PyAutoHands
- PyAutoFit
- PyAutoLens
Difficulty: large
Autonomy: supervised
Priority: normal
Status: formalised
Build-chain campaign Phase 3, the last remaining work from the umbrella closed
2026-07-22 (epic PyAutoHands#155). Tracked on PyAutoHands#161. Design
merged: PyAutoHands/docs/env_profile_redesign.md (#162). Steps 1-3 done:
validator (#163), single resolver, scrubbed baseline env (#165 + profiles).
What this is about
Each *_workspace_test repo has two env profiles under config/build/:
env_vars.yaml (smoke — the per-PR gate) and env_vars_release.yaml
(release — the nightly mega-run). PyAutoHands/autohands/env_config.py
resolves them: a defaults: block applied to every script, then an ordered
overrides: list of path patterns that flip vars for specific scripts.
In the ag/al release profiles PYAUTO_DISABLE_JAX: "1" is the default and
JAX is re-enabled by a hand-enumerated list of ~10 folder patterns. That
enumeration is the failure mode the whole campaign exists to remove: a
hand-maintained list of paths silently rots as scripts are added or renamed,
and the failure is quiet — a jax_grad/ script that falls off the list runs
NumPy and asserts a gradient that is all zeros, or tests nothing at all.
The decided policy (design doc §2, human 2026-07-16) is NOT "release =
production defaults" — that was rejected on measured JIT compile cost
(autolens_profiling#71). mode=release validates every script on the NumPy
path plus a derived, loud, bounded JAX set. Step 4 is what makes that set
derived instead of enumerated.
Measure first — the 2026-07-17 numbers are stale
Re-run the validator before planning; do not carry old counts into the work.
Measured 2026-07-22 (after the autobuild→autohands rename and the
dead-entry purge, both of which moved these numbers):
python3 PyAutoHands/autohands/validate_env_profiles.py <workspace_test_root>
| repo |
override-enumeration |
JAX-marked but resolves NumPy |
unmarked but resolves JAX |
| autolens_workspace_test |
10 |
11 |
9 |
| autogalaxy_workspace_test |
8 |
4 |
0 |
| autofit_workspace_test |
0 |
0 |
0 (clean — DISABLE_JAX "0", no overrides, the #47 shape) |
The 3 dead patterns the old brief mentioned (ag quantity/) are gone —
purged by the no_run/env_vars dead-entry campaign. autofit_workspace_test
needs no work at all; this task is ag + al.
Step 4 — the derivation rule (do this first; RELEASE-SURFACE RISK)
Replace the enumerated PYAUTO_DISABLE_JAX overrides with one rule in
autohands/env_config.py: JAX-on in mode=release iff a path segment matches
jax_* / *_jax / *_jit.
This is not a config tidy — it changes which backend scripts run on. Every
script below either starts or stops using JAX, and none of the "starts" has
ever run under JAX. Triage each individually: does it pass under JAX, and is it
fast enough for the nightly? Three groups, from the measured lists:
- Turns ON (marked, currently NumPy — 15 scripts). al:
jax_assertions/
(8 files, incl. __init__.py), hessian_jax.py, profiles_jit.py,
tracer_jax.py. ag: jax_assertions/ (4 files). Highest value — files
literally named for JAX that have never been JAX-validated — and the
highest chance of a red nightly.
database/scrape/ (7 files, al). The one place the rule does not match:
these need JAX on but carry no marker. Decide rename vs one
documented parity entry. The design says no exception list, so a rename is
the honest option, but it touches paths that no_run.yaml,
copy_files.yaml and docs may reference — sweep for references first.
- Turns OFF — a regression risk the old brief missed.
imaging/modeling_visualization_jit_delaunay.py and
..._jit_rectangular.py resolve JAX-on today only because the override
pattern imaging/modeling_visualization_jit substring-matches them. Under
the derivation rule their stems end _delaunay / _rectangular, so they
would stop getting JAX and silently no-op (the very failure the rule
exists to prevent). Resolve this before writing the rule — it is
evidence the *_jit suffix match is the wrong shape, and a
segment-contains form may be what the design actually needs.
Also decide what the rule does with __init__.py (3 of the counted files are
package inits, not runnable scripts) — probably skip them in the validator
rather than special-case the rule.
Verification (binding). Verify by resolved-env diff, never by smoke:
run resolve_clean() (autohands/validate_env_profiles.py:56) over every
script, old profile vs new rule, and read the diff line by line — it must be
exactly the triaged set above and nothing else. Traps from prior config
sweeps: overrides: order is load-bearing (later entries win; defaults:
order is not), and an empty overrides: block loads as None, not []. And
per the step-3 near-miss: prove it against the real CI env, not a synthetic
clean one — a synthetic run passed 65/65 while the real env would have gone
red, because the smoke profiles relied on a PYAUTO_ var injected by the
workflow rather than by the profile.
The release path is exercised only by the mega-run, not the per-PR gate. Land
behind a rehearsal, or accept mega-run verification and say so on the PR.
Step 5 — make the validator binding
Flip --strict-derivation / --strict-markers from warnings to errors and
wire validate_env_profiles into the three *_workspace_test PR gates.
Depends on step 4 (today it would fail on 42 warnings across ag+al).
Acceptance: a PR adding a JAX-marked script outside the derived set fails its
own gate.
Step 6 — rename the profiles
env_vars.yaml → profile_smoke.yaml, env_vars_release.yaml →
profile_release.yaml. Update autohands/env_config.py discovery,
run_python.py, run_smoke.py, workspace-validation.yml, docs. Wide but
mechanical; do it last, and re-sweep for the old names after every merge
from main — git rename-detection is blind to new files using the old name,
which is how the autobuild→autohands rename leaked.
Step 7 — library one-reader fold
al.AnalysisDataset reads PYAUTO_DISABLE_JAX a second time, before
super().__init__() (design doc failure mode 8). Fold it into base
af.Analysis so there is exactly one reader. Own plan; PyAutoFit + PyAutoLens,
so library-first then workspace. Behaviour-preserving — prove it with a unit
test asserting both construction orders resolve identically.
Step 8 — use_jax: Optional[bool] = None sentinel (HUMAN-GATED)
Only if the human wants "explicitly requested" distinguishable from
"defaulted". Cross-repo API change; may be declined — ask before building.
Suggested phasing
Step 4 is a session on its own (the triage is the work). Steps 5+6 can pair.
Step 7 is independent of 4-6 and could go first if a session is short. Step 8
needs a decision before any code.
Overview
Finish the env-profile migration (build-chain campaign Phase 3, umbrella #155, research + design on #161; design doc
docs/env_profile_redesign.md, merged #162; steps 1–3 shipped: validator #163, single resolver, scrubbed baseline env #165). In the ag/al release profiles JAX is re-enabled by a hand-enumerated list of ~10 path patterns — a list that silently rots: 15 scripts literally named for JAX (jax_assertions/,hessian_jax.py,tracer_jax.py, …) run NumPy in every nightly while asserting JAX behaviour. Step 4 replaces enumeration with the design's derivation rule (JAX-on in release mode iff a path segment/stem matchesjax_*/*_jax/*_jit); steps 5–8 make the validator binding, rename the profiles, fold the duplicate library env read, and (human-gated) decide theuse_jaxsentinel.This issue covers steps 4–8, executed in phases. This session: step 4 only.
Plan
Step 4 — the derivation rule (this session, three PRs, PyAutoHands first):
is_jax_markedfrom the validator intoautohands/env_config.py(one owner of the rule); resolver applies the derivation when a profile sets a newderive_jax_markers: truetop-level key (explicit key, not a filename heuristic); validator accepts the key, resolves through the shared logic, and skips non-runnable__init__.pyfiles; unit tests. Old profiles + new resolver = unchanged behaviour, so this merges first.imaging/modeling_visualization_jit_delaunay.py→modeling_visualization_delaunay_jit.py(and_rectangular) so the_jitsuffix carries the marker (human decision 2026-07-23); triagedatabase/scrape/on the NumPy path first — only fall back to ascrape_jax/folder rename if JAX is genuinely required (human decision 2026-07-23; no exception list, ever); delete all 10PYAUTO_DISABLE_JAXoverrides fromenv_vars_release.yamland add the key; triage the 10 runnable turns-ON scripts individually under their exact new JAX-on env (none has ever run JAX in the nightly).jax_assertions/scripts.resolve_clean()over every script, old profile vs new profile+rule, read line by line — must be exactly the triaged set and nothing else. Never smoke (smoke cannot see config-only changes). Prove against the real CI env (workspace-validation.yml), not a synthetic clean shell. The release path is only exercised by the nightly mega-run — mega-run verification accepted and stated on each PR.Later phases (same issue):
--strict-derivation/--strict-markersto errors; wire the validator into the three*_workspace_testPR gates.env_vars.yaml→profile_smoke.yaml,env_vars_release.yaml→profile_release.yaml(last; re-sweep for old names after every merge from main).al.AnalysisDataset's duplicatePYAUTO_DISABLE_JAXread into baseaf.Analysis(own plan; PyAutoFit + PyAutoLens, library-first; currently queued behind thetestmode-env-driftPyAutoFit claim).use_jax: Optional[bool] = Nonesentinel: human decision required before any code; may be declined.Detailed implementation plan
Affected Repositories
Branch Survey (2026-07-23)
No worktree conflicts (
worktree_check_conflictclean for all three).Suggested branch:
feature/env-profile-derivationWorktree root:
~/Code/PyAutoLabs-wt/env-profile-derivation/Work classification: Both (PyAutoHands source first, workspace_test follow-ups)
Measured baseline (validator, 2026-07-23 — live re-measurement, not the stale 07-17 counts)
Nuances found in planning:
imaging/modeling_visualization_jit_delaunay.py/_rectangular.pyare already inno_run.yaml(SLOW, 2026-05-07) — no immediate nightly impact, but post-migration the strict validator would see them as consistent NumPy scripts while their content assertsjax.Array, hence the rename. 4 of 7database/scrape/files are also no_run'd; onlygeneral.py+scaling_relation.pyactually run. The 15 turns-ON scripts are not no_run'd — they genuinely run tonight on NumPy, so flipping them is a real nightly change and each is triaged individually.Implementation Steps (Phase A)
autohands/env_config.py— move inis_jax_marked(fromvalidate_env_profiles.py:46); inbuild_env_for_script, whenenv_config.get("derive_jax_markers")is truthy, after defaults+overrides:if is_jax_marked(file): env["PYAUTO_DISABLE_JAX"] = "0".autohands/validate_env_profiles.py— importis_jax_markedfromenv_config(delete local copy); addderive_jax_markerstoALLOWED_TOP_KEYS;resolve_cleanapplies the same derivation via shared logic; skip__init__.pywhen collecting scripts.__init__.pyskip).Implementation Steps (Phase B — al)
git mvthe two renames; updateconfig/build/no_run.yaml:26-27; sweep for other references.database/scrape/general.py+scaling_relation.pyunder the resolved NumPy release env. Pass → drop override, state on PR. Fail (JAX-rooted) →git mv scripts/database/scrape → scrape_jax+ sweep ~8 refs (smoke profile ×2, no_run ×4, release profile, AGENTS.md, folder CLAUDE.md).config/build/env_vars_release.yaml— delete allPYAUTO_DISABLE_JAXoverrides; addderive_jax_markers: true; rewrite header comment.jax_assertions/×7,hessian_jax.py,profiles_jit.py,tracer_jax.py. Fail → trivial fix-forward, elseno_run.yamlwith dated reason, surfaced on the PR.Implementation Steps (Phase C — ag)
As B steps 3–4: delete 8 overrides, add key, triage
jax_assertions/×3.Key Files
PyAutoHands/autohands/env_config.py— the single resolver; gains the rule + derivationPyAutoHands/autohands/validate_env_profiles.py— PR-time gate;resolve_clean()is the verification harnessautolens_workspace_test/config/build/env_vars_release.yaml— 10 overrides to deleteautogalaxy_workspace_test/config/build/env_vars_release.yaml— 8 overrides to deletePyAutoHeart/.github/workflows/workspace-validation.yml:295,322— how the nightly invokes the release profile (read-only; parity check)PyAutoHands/docs/env_profile_redesign.md— the decided design (§2 policy, §3 rule)Config traps (from prior sweeps)
overrides:order is load-bearing (later entries win); an emptyoverrides:block loads asNone, not[]; verify config-only changes by resolved-env diff, never smoke.Planning notes
Brain Feature Agent scored this too-large (score 25, repo-count proxy) and proposed a generic 4-phase split — overridden with the prompt's own step phasing (step 4 alone; 5+6 pair; 7 independent; 8 decision-first), recorded here per standing guidance.
Original Prompt
Click to expand starting prompt
Finish the env-profile migration: steps 4-8 (derivation, strict gate, rename, one-reader, sentinel)
Type: feature
Target: workspaces
Repos:
Difficulty: large
Autonomy: supervised
Priority: normal
Status: formalised
Build-chain campaign Phase 3, the last remaining work from the umbrella closed
2026-07-22 (epic PyAutoHands#155). Tracked on PyAutoHands#161. Design
merged:
PyAutoHands/docs/env_profile_redesign.md(#162). Steps 1-3 done:validator (#163), single resolver, scrubbed baseline env (#165 + profiles).
What this is about
Each
*_workspace_testrepo has two env profiles underconfig/build/:env_vars.yaml(smoke — the per-PR gate) andenv_vars_release.yaml(release — the nightly mega-run).
PyAutoHands/autohands/env_config.pyresolves them: a
defaults:block applied to every script, then an orderedoverrides:list of path patterns that flip vars for specific scripts.In the ag/al release profiles
PYAUTO_DISABLE_JAX: "1"is the default andJAX is re-enabled by a hand-enumerated list of ~10 folder patterns. That
enumeration is the failure mode the whole campaign exists to remove: a
hand-maintained list of paths silently rots as scripts are added or renamed,
and the failure is quiet — a
jax_grad/script that falls off the list runsNumPy and asserts a gradient that is all zeros, or tests nothing at all.
The decided policy (design doc §2, human 2026-07-16) is NOT "release =
production defaults" — that was rejected on measured JIT compile cost
(autolens_profiling#71).
mode=releasevalidates every script on the NumPypath plus a derived, loud, bounded JAX set. Step 4 is what makes that set
derived instead of enumerated.
Measure first — the 2026-07-17 numbers are stale
Re-run the validator before planning; do not carry old counts into the work.
Measured 2026-07-22 (after the
autobuild→autohandsrename and thedead-entry purge, both of which moved these numbers):
DISABLE_JAX "0", no overrides, the #47 shape)The 3 dead patterns the old brief mentioned (ag
quantity/) are gone —purged by the no_run/env_vars dead-entry campaign.
autofit_workspace_testneeds no work at all; this task is ag + al.
Step 4 — the derivation rule (do this first; RELEASE-SURFACE RISK)
Replace the enumerated
PYAUTO_DISABLE_JAXoverrides with one rule inautohands/env_config.py: JAX-on inmode=releaseiff a path segment matchesjax_*/*_jax/*_jit.This is not a config tidy — it changes which backend scripts run on. Every
script below either starts or stops using JAX, and none of the "starts" has
ever run under JAX. Triage each individually: does it pass under JAX, and is it
fast enough for the nightly? Three groups, from the measured lists:
jax_assertions/(8 files, incl.
__init__.py),hessian_jax.py,profiles_jit.py,tracer_jax.py. ag:jax_assertions/(4 files). Highest value — filesliterally named for JAX that have never been JAX-validated — and the
highest chance of a red nightly.
database/scrape/(7 files, al). The one place the rule does not match:these need JAX on but carry no marker. Decide rename vs one
documented parity entry. The design says no exception list, so a rename is
the honest option, but it touches paths that
no_run.yaml,copy_files.yamland docs may reference — sweep for references first.imaging/modeling_visualization_jit_delaunay.pyand..._jit_rectangular.pyresolve JAX-on today only because the overridepattern
imaging/modeling_visualization_jitsubstring-matches them. Underthe derivation rule their stems end
_delaunay/_rectangular, so theywould stop getting JAX and silently no-op (the very failure the rule
exists to prevent). Resolve this before writing the rule — it is
evidence the
*_jitsuffix match is the wrong shape, and asegment-contains form may be what the design actually needs.
Also decide what the rule does with
__init__.py(3 of the counted files arepackage inits, not runnable scripts) — probably skip them in the validator
rather than special-case the rule.
Verification (binding). Verify by resolved-env diff, never by smoke:
run
resolve_clean()(autohands/validate_env_profiles.py:56) over everyscript, old profile vs new rule, and read the diff line by line — it must be
exactly the triaged set above and nothing else. Traps from prior config
sweeps:
overrides:order is load-bearing (later entries win;defaults:order is not), and an empty
overrides:block loads asNone, not[]. Andper the step-3 near-miss: prove it against the real CI env, not a synthetic
clean one — a synthetic run passed 65/65 while the real env would have gone
red, because the smoke profiles relied on a
PYAUTO_var injected by theworkflow rather than by the profile.
The release path is exercised only by the mega-run, not the per-PR gate. Land
behind a rehearsal, or accept mega-run verification and say so on the PR.
Step 5 — make the validator binding
Flip
--strict-derivation/--strict-markersfrom warnings to errors andwire
validate_env_profilesinto the three*_workspace_testPR gates.Depends on step 4 (today it would fail on 42 warnings across ag+al).
Acceptance: a PR adding a JAX-marked script outside the derived set fails its
own gate.
Step 6 — rename the profiles
env_vars.yaml→profile_smoke.yaml,env_vars_release.yaml→profile_release.yaml. Updateautohands/env_config.pydiscovery,run_python.py,run_smoke.py,workspace-validation.yml, docs. Wide butmechanical; do it last, and re-sweep for the old names after every merge
from main — git rename-detection is blind to new files using the old name,
which is how the
autobuild→autohandsrename leaked.Step 7 — library one-reader fold
al.AnalysisDatasetreadsPYAUTO_DISABLE_JAXa second time, beforesuper().__init__()(design doc failure mode 8). Fold it into baseaf.Analysisso there is exactly one reader. Own plan; PyAutoFit + PyAutoLens,so library-first then workspace. Behaviour-preserving — prove it with a unit
test asserting both construction orders resolve identically.
Step 8 —
use_jax: Optional[bool] = Nonesentinel (HUMAN-GATED)Only if the human wants "explicitly requested" distinguishable from
"defaulted". Cross-repo API change; may be declined — ask before building.
Suggested phasing
Step 4 is a session on its own (the triage is the work). Steps 5+6 can pair.
Step 7 is independent of 4-6 and could go first if a session is short. Step 8
needs a decision before any code.