Skip to content

test: smoke should run every tutorial, not a 4-of-26 allowlist #58

Description

@Jammy2211

Overview

Shipping #57 revealed that a public teaching notebook was broken in three places and this repo's CI could never have caught any of them. smoke_tests.txt is an allowlist — a script is tested only if someone remembers to add it — so every new tutorial is uncovered from birth.

repo covered total
HowToGalaxy 4 26
HowToLens 6 40
HowToFit 10 15

The only backstop is PyAutoHeart's workspace-smoke, which is weekly (Mondays 03:00 UTC) — and the run that caught #57 was a manual workflow_dispatch, not the schedule. A broken public tutorial can sit on main for a week.

The allowlist also concealed a false claim: profile_smoke.yaml caps datasets and its comment asserts "the chapters run correctly at 16x16". That is untrue for chapter 4, and nobody knew because chapter 4 was never in the list.

Plan

  • Ship a one-line mesh-shape fix first and on its own — without it Heart's next weekly run stays red (it flips from TypeError to IndexError).
  • Delete the allowlist and delegate to PyAutoHands' canonical run_python.py, so PR-smoke and Heart's validation become one code path reading one exclusion list.
  • Clean up two stale/mis-stated no_run.yaml exclusions.
  • Correct the AGENTS.md claim that contradicts the smoke profile.
  • Verify by the executed-script count rising, plus a negative control — a green tick already passes today while testing 4 of 26 files.
Detailed implementation plan

Work Classification

Workspace (three tutorial repos; no library change).

Affected Repositories

  • HowToGalaxy (primary)
  • HowToLens
  • HowToFit

Branch Survey

Repository Current Branch Dirty?
./HowToGalaxy main clean
./HowToLens main clean
./HowToFit main clean

No worktree claims → no conflict.

Suggested branch: feature/howto-smoke-all-tutorials
Worktree root: ~/Code/PyAutoLabs-wt/howto-smoke-all-tutorials/

Measured (2026-08-04, every script under each repo's own smoke profile)

repo result wall time
HowToGalaxy 25/26 → 26/26 with the mesh fix 3.9 min
HowToLens 39/40 (the 1 is already excluded) 6.4 min
HowToFit 15/15 0.9 min

Cost is not the blocker — HowToGalaxy spends ~2m18s today on 4 scripts.

Phase 1 — mesh shape (urgent, ships first)

scripts/chapter_4_pixelizations/tutorial_3_inversions.py:82 uses shape=dataset.shape_native, coupling the pixelization mesh to image resolution: 10000 mesh pixels at full res, 256 under the cap. The tutorial's pix_indexes = [[445], …] (line 140) then goes out of range → IndexError.

The indices are not the bug — they match the 625-pixel mesh of HowToLens/.../tutorial_3_inversions.py:102 (shape=(25, 25)) they were copied from, and this file's own line 176 already uses shape=(25, 25). Line 82 is the anomaly.

- mesh = ag.mesh.RectangularAdaptDensity(shape=dataset.shape_native)
+ mesh = ag.mesh.RectangularAdaptDensity(shape=(25, 25))

Verified: passes under the smoke profile, 19× faster there (8.2s vs 156.7s).

Phase 2 — delete the allowlist, delegate to the canonical runner

Do not hand-roll discovery. PyAutoHands/autohands/run_python.py is already the canonical script runner Heart's run_scripts invokes (workspace-validation.yml:313,343), and already does all of it:

  • build_util.find_scripts_in_folder() (build_util.py:449) — recursive, orders simulator* first then start_here.py, exactly what dataset-dependent tutorials need
  • should_skip() against config/build/no_run.yaml — the denylist
  • find_profile() + build_env_for_script() — the same env resolution
  • skips __init__/README as infrastructure

Each repo's .github/scripts/run_smoke.py collapses to a thin shim invoking run_python.py <project> scripts/; smoke_tests.txt is deleted. smoke_tests.yml keeps calling run_smoke.py, so PyAutoHeart's reusable-workflow contract is untouched.

Trap. run_python.py exits non-zero only when --report-dir is passed (gated on if report is not None). Without it the runner executes everything and always exits 0 — a vacuously green CI, strictly worse than today. The shim must always pass --report-dir, and this is what the negative control below proves.

Exclusion hygiene

  • tutorial_searches — excluded in both HowToGalaxy and HowToLens with no stated reason, and passes in both (10.4s / 10.1s). Remove.
  • HowToLens tutorial_5_borders — recorded as "Cant get right masks". Controlled re-test on identical dataset files: fails with the cap, passes without it (IndexError: index 371 out of bounds for axis 0 with size 272). Cap-induced; keep the exclusion but correct the reason and tag NEEDS_FIX.
  • HowToFit no_run.yaml exists and parses to an empty list — nothing to do.

Docs contradiction

AGENTS.md:34 says PYAUTO_SMALL_DATASETS is "deliberately not used in HowToGalaxy", while profile_smoke.yaml:16 sets it for every script. The cap stays (human decision), so AGENTS.md is what is wrong — correct it and drop the disproven "16x16" assertion from the profile comment.

Key Files

  • */.github/scripts/run_smoke.py — the triplicated runner (byte-identical, md5 f105e0e8)
  • */smoke_tests.txt — deleted
  • */config/build/no_run.yaml — the surviving single exclusion list
  • HowToGalaxy/scripts/chapter_4_pixelizations/tutorial_3_inversions.py:82 — Phase 1
  • PyAutoHands/autohands/run_python.py, build_util.py:449 — reused, not modified

Verification

  1. Executed count per repo: 4 → 26, 6 → 39, 10 → 15, read off the runner's output and checked against discovered-minus-no_run.
  2. Negative control — break a tutorial, confirm CI goes red. Catches the --report-dir trap.
  3. Add a throwaway tutorial, confirm it runs with no list edit.
  4. Four scripts pass in ~0.0s; verified prose-only (0 non-docstring statements), legitimate not vacuous.

Follow-up, deliberately not here

run_smoke.py is triplicated. Centralising it into PyAutoHands would mean the next change lands once — scoped out by the human.

Original Prompt

Click to expand starting prompt

I think its CI should check all tutorials: That coverage gap is arguably the more interesting finding: a public teaching notebook was broken in three places and its own repo's CI could never have caught any of them.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions