Overview
autonerves.setup_colab installs the PyAuto stack on Colab with --no-deps, so every dependency Colab does not preinstall must be hand-listed in _SHARED_EXTRAS. On 2026-09-15 corner — a base autofit dependency imported lazily inside corner_cornerpy — was missing, and HowToFit tutorial 5 died mid-workshop after its emcee run. Nothing caught it: workspace smoke runs at PYAUTO_TEST_MODE=2 (samplers never constructed), and Heart check F emulates Colab by pip install autolens jax with dependencies, so its venv already contains everything the --no-deps path would miss. This task makes check F a faithful Colab gate: seed the venv from Google's published Colab manifest, run the real --no-deps bootstrap, then prove every module the libraries import is importable. Check F FAIL already maps to readiness RED, so the gate blocks release.
Scoping decision (time vs robustness): rung 2 — import probe after a faithful bootstrap, ~5 min, inside the existing release-only verify_install_release lane. Rung 1 (static scan) is an input, not a gate; rung 3/4 (notebooks end to end at real settings, tens of minutes to hours) test a different bug class and are declined for this gate (HowTo repos have no release profile; tutorial 5 cannot complete at real sampling today, PyAutoFit#1454).
Plan
- Ground the Colab emulation on Google's live manifest (
googlecolab/backend-info pip-freeze.txt), with cache + vendored snapshot fallback, and say which source was used.
- Seed the sim venv with only the manifest packages the stack needs (dry-run resolve ∩ manifest), never with the stack's own dependencies.
- Run the injected setup cell verbatim (real
--no-deps install + workspace clone), as today.
- Walk declared requirements against what is installed / what Colab ships; AST-scan the installed libraries for every third-party import (module- and function-level, guarded or not) and import each one; construct the tutorial searches.
- Verdict: unguarded import that fails on Colab → FAIL (RED); guarded misses, version conflicts, never-imported declared deps → WARN. No allowlist shipped; an empty
accepted_missing config exists for the human.
- Rewrite the stale check-F docs; unit-test the gate offline; run the witness locally (PyPI as-is → FAIL naming
corner; Nerves#167 branch → PASS).
Detailed implementation plan
Affected Repositories
- PyAutoHeart (primary, only)
PyAutoNerves and the HowTo repos are listed in the prompt but need no edit: the gate reads released wheels and Google's manifest. All four are claimed by in-flight tasks (colab-bootstrap-lazy-deps, colab-workshop-dep-stopgap, howtofit-mode).
Branch Survey
| Repository |
Current Branch |
Dirty? |
| ./PyAutoHeart |
main |
clean (1 behind origin) |
Suggested branch: feature/colab-notebook-release-gate
Worktree: ~/Code/PyAutoLabs-wt/colab-notebook-release-gate/
Implementation Steps
-
New heart/checks/colab_gate.py (stdlib + packaging; run with the sim venv's interpreter so importlib.metadata sees the venv). JSON report via --report-json; exit 0 pass / 1 fail / 2 tool error.
seed: load manifest (fetch https://raw.githubusercontent.com/googlecolab/backend-info/main/pip-freeze.txt → fallback $HEART_STATE_DIR/colab_pip_freeze.txt → vendored heart/checks/colab_pip_freeze.snapshot.txt, dated; record source; cache live copy). pip install --dry-run --report - <f_targets> jax (same targets + PIP_INDEX_ARGS check F uses) for the with-deps closure; intersect PEP 503-normalised names with the manifest, drop PyAuto packages, pip install --no-deps name==<colab version> for the intersection.
verify (after the setup cell): (a) requirement walk from the installed PyAuto dists over requires_dist (markers evaluated, extras empty): unmet + in manifest → install Colab's version --no-deps, continue; unmet + not in manifest → missing_declared; installed but outside specifier → version_conflict. (b) AST-scan every .py of installed autonerves/autofit/autoarray/autogalaxy/autolens for all imports, keep third-party top-level names (not sys.stdlib_module_names, not PyAuto), flag whether the site is inside a try: catching ImportError/ModuleNotFoundError/Exception; import each name in a subprocess. Unguarded failure → FAIL with file:line; guarded-only → WARN. (c) instantiate af.Emcee, af.DynestyStatic, af.Nautilus, af.LBFGS with defaults; exception → FAIL. (d) Verdict: FAIL on any unguarded import failure, constructor failure, or missing_declared that is imported anywhere; everything else WARN. Optional heart/config/colab_gate.yaml accepted_missing: (name + reason) downgrades a named FAIL to WARN — ships empty.
-
Rework check_f() in heart/checks/verify_install.sh (lines 685-812): venv on python3.12 (Colab's interpreter; missing interpreter is FAIL like B/E); replace pip install ${f_targets[*]} jax with pip install packaging + colab_gate.py seed; keep the fake google.colab stub, the verbatim setup-cell driver and the al.Imaging.from_fits cell; insert colab_gate.py verify between the setup cell and the notebook cell; result line F|FAIL|colab gate: unguarded imports missing on Colab: corner (autofit/non_linear/plot/samples_plotters.py:95), … / F|PASS|Colab manifest <date/source>; N Colab-provided, M extras, K probed imports; fold the gate JSON into the --report-json sidecar under checks.F.colab_gate. Dev flag COLAB_GATE_AUTONERVES_SRC=<path>: after the cell's pip install autonerves --no-deps, pip install --no-deps <path> so the gate can run against an unreleased setup_colab.
-
Tests — new tests/test_colab_gate.py (manifest parsing + fallback order; requirement walk on fabricated requires_dist; AST scanner guarded/unguarded/stdlib/PyAuto exclusion; verdict rules incl. accepted_missing); extend tests/test_verify_install_script.py (check_f calls seed and verify, uses python3.12, no with-deps stack install). No network, no venv in unit CI.
-
Docs — skills/verify_install/verify_install.md row F (still says autoconf, dataset/imaging/simple); health_agent/capabilities.yaml verify_install.measures; docs/release_validation.md F description. State what the simulation does (Colab's package set, Python 3.12) and does not (GPU, OS, 1–2 day manifest lag) cover.
-
Ship via ship_workspace. PR body must flag: the first release-integrate run after merge will be RED until the autonerves that ships PyAutoNerves#167 is on PyPI (today's PyPI autonerves lacks corner/optax/xxhash/blackjax). That is the gate working.
Verification (the witness)
heart/checks/verify_install.sh check F against PyPI as-is → F|FAIL naming corner — the 2026-09-15 failure that 18/18 smoke missed.
- Same with
COLAB_GATE_AUTONERVES_SRC=~/Code/PyAutoLabs-wt/colab-bootstrap-lazy-deps/PyAutoNerves → F|PASS (or WARNs only).
python3 -m pytest -q -n auto PyAutoHeart/tests green; pyauto-heart readiness reads the new sidecar.
Paste both F result lines and wall time into the PR.
Key Files
heart/checks/verify_install.sh — check F (check_f(), lines 685-812), dispatch at 830, verdict roll-up 843-871, sidecar 868-919
heart/checks/colab_gate.py — new
heart/checks/colab_pip_freeze.snapshot.txt — new, dated vendored fallback
heart/config/colab_gate.yaml — new, empty accepted_missing:
heart/readiness.py:511-542 — consumes verify_install.json (ready:false → RED)
.github/workflows/workspace-validation.yml:649-686 — verify_install_release job (release mode only)
tests/test_verify_install_script.py, tests/test_colab_gate.py
skills/verify_install/verify_install.md, health_agent/capabilities.yaml, docs/release_validation.md
Cadence / follow-ups (not this task)
- Runs every nightly release (release-integrate → verify_install_release) and on demand via
pyauto-heart verify_install.
- Follow-up prompts to offer: PR-time trigger in PyAutoNerves when
setup_colab.py changes; a HowTo real-settings nightly (rung 3) once PyAutoFit#1454 is fixed.
Original Prompt
Click to expand starting prompt
Release-time gate that proves the Colab notebooks actually run
Type: feature
Target: PyAutoHeart
Repos:
- PyAutoHeart
- PyAutoNerves
- HowToFit
- HowToGalaxy
- HowToLens
Difficulty: medium
Autonomy: safe
Priority: high
Status: formalised
Consequence: glance
Witness: with corner deleted from _SHARED_EXTRAS, the new gate reports RED, where today's workspace smoke reports 18/18 green — i.e. the gate catches the 2026-09-15 tutorial-5 failure that every existing gate missed.
Review-minutes: 3
Unattended: ready
Filed: 2026-09-15
Raw request from the user, verbatim:
can we /intake something that checks colab notebooks run during release? IU guess
that could be slow but the intake can scope out the best way to do that and balance
time versus robustness
Why now
autonerves/setup_colab.py bootstraps Colab with pip install *packages --no-deps,
so every dependency Colab does not itself preinstall must be named by hand in
_SHARED_EXTRAS or it never lands. On 2026-09-15 HowToFit chapter 1 tutorial 5 died
on Colab with ModuleNotFoundError: No module named 'corner' — after a 2000-step
emcee search had already completed, in the results update that follows it. A workshop
was running that day.
The reason nothing caught it is the part that should shape the scoping:
corner is imported INSIDE corner_cornerpy
(autofit/non_linear/plot/samples_plotters.py:95), not at module scope. So
import autofit succeeds, the model builds, the search runs to completion, and
only the post-fit plot raises.
- Workspace smoke runs at
PYAUTO_TEST_MODE=2 (config/build/profile_smoke.yaml),
which bypasses the sampler entirely — the searches are never constructed and the
lazy imports never execute. Scripts pass green while being unrunnable by a reader.
config/build/no_run.yaml already documents this same blind spot for
tutorial_5_expectation_propagation.
Third instance of the class: 8336939 (PyAutoNerves#166) closed it for emcee and
dynesty; a HowToFit prompt had it open for blackjax; PyAutoNerves#167 closes corner,
optax, xxhash and blackjax at once. Each fix needs its own PyPI release to reach a
single user, and the list is being patched one user report at a time.
What already exists (build on, do not duplicate)
- PyAutoHeart
verify_install check F already simulates the Colab bootstrap. That is
the right place; the open question is what it should execute once bootstrapped.
- PyAutoNerves#167 adds a test deriving
_SHARED_EXTRAS specifiers from PyAutoFit's
pyproject.toml. That closes the DRIFT class statically. It does not prove a
notebook runs.
- 100 notebooks carry the Colab setup cell: HowToFit 18, HowToGalaxy 32, HowToLens 50,
plus the three workspace repos.
The tradeoff to scope — time versus robustness
This is explicitly what the task is for. Weigh these rungs and recommend one; do not
merely list them.
- STATIC — AST-scan the libraries for function-level third-party imports, cross-check
against _SHARED_EXTRAS and what Colab preinstalls. Seconds. Catches exactly this
class; proves nothing about runtime.
- IMPORT PROBE — after a real Colab bootstrap, import every lazily-imported module and
construct every af.<Search> class the scripts instantiate. Minutes. Catches missing
deps and bad pins without running a fit.
- ONE REPRESENTATIVE NOTEBOOK per chapter, end to end at REAL settings — not
PYAUTO_TEST_MODE=2, since that mode is the blindness. Tens of minutes.
- EVERY notebook end to end. Hours; probably too slow for a release gate, but worth
pricing so the decision is informed.
Also in scope for the scoping
- Where it runs. A real Colab runtime is not reachable from CI, so check F's simulation
is an approximation — and Colab's exact preinstalled package set is precisely the
thing being approximated. Getting that wrong IS the bug. Say what the approximation
does and does not cover.
- Whether the gate blocks a release or merely reports. A missing dependency makes
notebooks unrunnable for every user, so blocking is arguable.
- Cadence: per-release, nightly, or only when
_SHARED_EXTRAS or a pyproject.toml
changes.
Overview
autonerves.setup_colabinstalls the PyAuto stack on Colab with--no-deps, so every dependency Colab does not preinstall must be hand-listed in_SHARED_EXTRAS. On 2026-09-15corner— a base autofit dependency imported lazily insidecorner_cornerpy— was missing, and HowToFit tutorial 5 died mid-workshop after its emcee run. Nothing caught it: workspace smoke runs atPYAUTO_TEST_MODE=2(samplers never constructed), and Heart check F emulates Colab bypip install autolens jaxwith dependencies, so its venv already contains everything the--no-depspath would miss. This task makes check F a faithful Colab gate: seed the venv from Google's published Colab manifest, run the real--no-depsbootstrap, then prove every module the libraries import is importable. Check F FAIL already maps to readiness RED, so the gate blocks release.Scoping decision (time vs robustness): rung 2 — import probe after a faithful bootstrap, ~5 min, inside the existing release-only
verify_install_releaselane. Rung 1 (static scan) is an input, not a gate; rung 3/4 (notebooks end to end at real settings, tens of minutes to hours) test a different bug class and are declined for this gate (HowTo repos have no release profile; tutorial 5 cannot complete at real sampling today, PyAutoFit#1454).Plan
googlecolab/backend-infopip-freeze.txt), with cache + vendored snapshot fallback, and say which source was used.--no-depsinstall + workspace clone), as today.accepted_missingconfig exists for the human.corner; Nerves#167 branch → PASS).Detailed implementation plan
Affected Repositories
PyAutoNerves and the HowTo repos are listed in the prompt but need no edit: the gate reads released wheels and Google's manifest. All four are claimed by in-flight tasks (
colab-bootstrap-lazy-deps,colab-workshop-dep-stopgap,howtofit-mode).Branch Survey
Suggested branch:
feature/colab-notebook-release-gateWorktree:
~/Code/PyAutoLabs-wt/colab-notebook-release-gate/Implementation Steps
New
heart/checks/colab_gate.py(stdlib +packaging; run with the sim venv's interpreter soimportlib.metadatasees the venv). JSON report via--report-json; exit 0 pass / 1 fail / 2 tool error.seed: load manifest (fetchhttps://raw.githubusercontent.com/googlecolab/backend-info/main/pip-freeze.txt→ fallback$HEART_STATE_DIR/colab_pip_freeze.txt→ vendoredheart/checks/colab_pip_freeze.snapshot.txt, dated; record source; cache live copy).pip install --dry-run --report - <f_targets> jax(same targets +PIP_INDEX_ARGScheck F uses) for the with-deps closure; intersect PEP 503-normalised names with the manifest, drop PyAuto packages,pip install --no-deps name==<colab version>for the intersection.verify(after the setup cell): (a) requirement walk from the installed PyAuto dists overrequires_dist(markers evaluated, extras empty): unmet + in manifest → install Colab's version--no-deps, continue; unmet + not in manifest →missing_declared; installed but outside specifier →version_conflict. (b) AST-scan every.pyof installedautonerves/autofit/autoarray/autogalaxy/autolensfor all imports, keep third-party top-level names (notsys.stdlib_module_names, not PyAuto), flag whether the site is inside atry:catchingImportError/ModuleNotFoundError/Exception; import each name in a subprocess. Unguarded failure → FAIL withfile:line; guarded-only → WARN. (c) instantiateaf.Emcee,af.DynestyStatic,af.Nautilus,af.LBFGSwith defaults; exception → FAIL. (d) Verdict: FAIL on any unguarded import failure, constructor failure, ormissing_declaredthat is imported anywhere; everything else WARN. Optionalheart/config/colab_gate.yamlaccepted_missing:(name + reason) downgrades a named FAIL to WARN — ships empty.Rework
check_f()inheart/checks/verify_install.sh(lines 685-812): venv onpython3.12(Colab's interpreter; missing interpreter is FAIL like B/E); replacepip install ${f_targets[*]} jaxwithpip install packaging+colab_gate.py seed; keep the fakegoogle.colabstub, the verbatim setup-cell driver and theal.Imaging.from_fitscell; insertcolab_gate.py verifybetween the setup cell and the notebook cell; result lineF|FAIL|colab gate: unguarded imports missing on Colab: corner (autofit/non_linear/plot/samples_plotters.py:95), …/F|PASS|Colab manifest <date/source>; N Colab-provided, M extras, K probed imports; fold the gate JSON into the--report-jsonsidecar underchecks.F.colab_gate. Dev flagCOLAB_GATE_AUTONERVES_SRC=<path>: after the cell'spip install autonerves --no-deps,pip install --no-deps <path>so the gate can run against an unreleasedsetup_colab.Tests — new
tests/test_colab_gate.py(manifest parsing + fallback order; requirement walk on fabricatedrequires_dist; AST scanner guarded/unguarded/stdlib/PyAuto exclusion; verdict rules incl.accepted_missing); extendtests/test_verify_install_script.py(check_f callsseedandverify, usespython3.12, no with-deps stack install). No network, no venv in unit CI.Docs —
skills/verify_install/verify_install.mdrow F (still saysautoconf,dataset/imaging/simple);health_agent/capabilities.yamlverify_install.measures;docs/release_validation.mdF description. State what the simulation does (Colab's package set, Python 3.12) and does not (GPU, OS, 1–2 day manifest lag) cover.Ship via
ship_workspace. PR body must flag: the first release-integrate run after merge will be RED until the autonerves that ships PyAutoNerves#167 is on PyPI (today's PyPI autonerves lacks corner/optax/xxhash/blackjax). That is the gate working.Verification (the witness)
heart/checks/verify_install.shcheck F against PyPI as-is → F|FAIL namingcorner— the 2026-09-15 failure that 18/18 smoke missed.COLAB_GATE_AUTONERVES_SRC=~/Code/PyAutoLabs-wt/colab-bootstrap-lazy-deps/PyAutoNerves→ F|PASS (or WARNs only).python3 -m pytest -q -n auto PyAutoHeart/testsgreen;pyauto-heart readinessreads the new sidecar.Paste both F result lines and wall time into the PR.
Key Files
heart/checks/verify_install.sh— check F (check_f(), lines 685-812), dispatch at 830, verdict roll-up 843-871, sidecar 868-919heart/checks/colab_gate.py— newheart/checks/colab_pip_freeze.snapshot.txt— new, dated vendored fallbackheart/config/colab_gate.yaml— new, emptyaccepted_missing:heart/readiness.py:511-542— consumesverify_install.json(ready:false→ RED).github/workflows/workspace-validation.yml:649-686—verify_install_releasejob (release mode only)tests/test_verify_install_script.py,tests/test_colab_gate.pyskills/verify_install/verify_install.md,health_agent/capabilities.yaml,docs/release_validation.mdCadence / follow-ups (not this task)
pyauto-heart verify_install.setup_colab.pychanges; a HowTo real-settings nightly (rung 3) once PyAutoFit#1454 is fixed.Original Prompt
Click to expand starting prompt
Release-time gate that proves the Colab notebooks actually run
Type: feature
Target: PyAutoHeart
Repos:
Difficulty: medium
Autonomy: safe
Priority: high
Status: formalised
Consequence: glance
Witness: with
cornerdeleted from_SHARED_EXTRAS, the new gate reports RED, where today's workspace smoke reports 18/18 green — i.e. the gate catches the 2026-09-15 tutorial-5 failure that every existing gate missed.Review-minutes: 3
Unattended: ready
Filed: 2026-09-15
Raw request from the user, verbatim:
Why now
autonerves/setup_colab.pybootstraps Colab withpip install *packages --no-deps,so every dependency Colab does not itself preinstall must be named by hand in
_SHARED_EXTRASor it never lands. On 2026-09-15 HowToFit chapter 1 tutorial 5 diedon Colab with
ModuleNotFoundError: No module named 'corner'— after a 2000-stepemcee search had already completed, in the results update that follows it. A workshop
was running that day.
The reason nothing caught it is the part that should shape the scoping:
corneris imported INSIDEcorner_cornerpy(
autofit/non_linear/plot/samples_plotters.py:95), not at module scope. Soimport autofitsucceeds, the model builds, the search runs to completion, andonly the post-fit plot raises.
PYAUTO_TEST_MODE=2(config/build/profile_smoke.yaml),which bypasses the sampler entirely — the searches are never constructed and the
lazy imports never execute. Scripts pass green while being unrunnable by a reader.
config/build/no_run.yamlalready documents this same blind spot fortutorial_5_expectation_propagation.Third instance of the class:
8336939(PyAutoNerves#166) closed it for emcee anddynesty; a HowToFit prompt had it open for blackjax; PyAutoNerves#167 closes corner,
optax, xxhash and blackjax at once. Each fix needs its own PyPI release to reach a
single user, and the list is being patched one user report at a time.
What already exists (build on, do not duplicate)
verify_installcheck F already simulates the Colab bootstrap. That isthe right place; the open question is what it should execute once bootstrapped.
_SHARED_EXTRASspecifiers from PyAutoFit'spyproject.toml. That closes the DRIFT class statically. It does not prove anotebook runs.
plus the three workspace repos.
The tradeoff to scope — time versus robustness
This is explicitly what the task is for. Weigh these rungs and recommend one; do not
merely list them.
against
_SHARED_EXTRASand what Colab preinstalls. Seconds. Catches exactly thisclass; proves nothing about runtime.
construct every
af.<Search>class the scripts instantiate. Minutes. Catches missingdeps and bad pins without running a fit.
PYAUTO_TEST_MODE=2, since that mode is the blindness. Tens of minutes.pricing so the decision is informed.
Also in scope for the scoping
is an approximation — and Colab's exact preinstalled package set is precisely the
thing being approximated. Getting that wrong IS the bug. Say what the approximation
does and does not cover.
notebooks unrunnable for every user, so blocking is arguable.
_SHARED_EXTRASor apyproject.tomlchanges.