Problem
import goldilocks_core eagerly loads goldilocks_core.ml.kindex, ml.qrf, ml.models, and scipy. The chain: goldilocks_core/__init__.py imports jobs; jobs.py imports the advisors at module top (from goldilocks_core.advisors import default_kmesh_advisor, ml_kmesh_advisor); resolving those names loads the advisor submodules, which import the ML backends.
The #132 tidy removed advisors/__init__.py's __getattr__ lazy facade (direct re-exports) — free, because the facade was already defeated by jobs.py's module-level import. The truly heavy import (torch) is still deferred inside the ML modules' own functions, but the ML submodules and scipy load on every import goldilocks_core, which matters for the long-lived server (#131) and any tool that imports the package without running a recommendation.
Proposed approach
Defer the advisor imports in jobs.py into the functions that use them (run_scf, recommend, generate, write_bundle) so import goldilocks_core stays cheap. Trade-off: each recommend() call pays an import-cache check (negligible — Python caches modules after first import). Verify with python -c "import sys; import goldilocks_core; assert 'scipy' not in sys.modules and not any(m.startswith('goldilocks_core.ml') for m in sys.modules)".
Acceptance criteria
Written by an agent on behalf of Willow.
Problem
import goldilocks_coreeagerly loadsgoldilocks_core.ml.kindex,ml.qrf,ml.models, andscipy. The chain:goldilocks_core/__init__.pyimportsjobs;jobs.pyimports the advisors at module top (from goldilocks_core.advisors import default_kmesh_advisor, ml_kmesh_advisor); resolving those names loads the advisor submodules, which import the ML backends.The #132 tidy removed
advisors/__init__.py's__getattr__lazy facade (direct re-exports) — free, because the facade was already defeated byjobs.py's module-level import. The truly heavy import (torch) is still deferred inside the ML modules' own functions, but the ML submodules andscipyload on everyimport goldilocks_core, which matters for the long-lived server (#131) and any tool that imports the package without running a recommendation.Proposed approach
Defer the advisor imports in
jobs.pyinto the functions that use them (run_scf,recommend,generate,write_bundle) soimport goldilocks_corestays cheap. Trade-off: eachrecommend()call pays an import-cache check (negligible — Python caches modules after first import). Verify withpython -c "import sys; import goldilocks_core; assert 'scipy' not in sys.modules and not any(m.startswith('goldilocks_core.ml') for m in sys.modules)".Acceptance criteria
import goldilocks_coreloads neitherscipynor anygoldilocks_core.ml.*submodule.recommend()/run_core_job()still work (advisors load on first use).uv run pytest,uv run ruff check src tests,uv run pre-commit run --all-filesgreen.Written by an agent on behalf of Willow.