diff --git a/.github/workflows/nss_install_smoke.yml b/.github/workflows/nss_install_smoke.yml new file mode 100644 index 000000000..25653c869 --- /dev/null +++ b/.github/workflows/nss_install_smoke.yml @@ -0,0 +1,62 @@ +name: NSS install smoke + +# Phase 4 of nss_first_class_sampler — verifies that `pip install autofit[nss]` +# remains a single safe command. Runs on every PR (so we catch local regressions +# in pyproject.toml before merging) and on a weekly cron (so we catch upstream +# regressions in handley-lab/blackjax or yallup/nss that drift past the pinned +# SHAs). + +on: + pull_request: + schedule: + # Sundays at 03:00 UTC — quiet hours, catches upstream drift weekly. + - cron: '0 3 * * 0' + +jobs: + fresh_venv_install: + name: Fresh-venv install of autofit[nss] + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - name: Checkout PyAutoConf + uses: actions/checkout@v4 + with: + repository: PyAutoLabs/PyAutoConf + path: PyAutoConf + - name: Checkout PyAutoFit + uses: actions/checkout@v4 + with: + path: PyAutoFit + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Upgrade pip + run: python -m pip install --upgrade pip + - name: Install PyAutoConf + run: python -m pip install -e PyAutoConf + - name: Install PyAutoFit with [nss] extra + run: python -m pip install -e PyAutoFit[nss] + - name: Import smoke + run: | + python -c " + import autofit as af + import nss.ns + import blackjax + + # Confirm the right blackjax fork landed (mainline does not have + # blackjax.ns.adaptive — this attribute access is the canonical + # check for the handley-lab fork). + import blackjax.ns.adaptive + assert hasattr(blackjax.ns.adaptive, 'init'), ( + 'blackjax.ns.adaptive.init missing — wrong blackjax installed?' + ) + + # Confirm af.NSS instantiates without ImportError. + search = af.NSS(n_live=10, num_mcmc_steps=2, num_delete=5, termination=-1.0) + assert search.checkpoint_interval == 100 + + print('NSS install smoke: OK') + print(f' blackjax version: {blackjax.__version__}') + print(f' nss installed at: {nss.__file__}') + " diff --git a/autofit/non_linear/search/nest/nss/search.py b/autofit/non_linear/search/nest/nss/search.py index 21a668439..c91919ef5 100644 --- a/autofit/non_linear/search/nest/nss/search.py +++ b/autofit/non_linear/search/nest/nss/search.py @@ -240,11 +240,11 @@ def __init__( if not _HAS_NSS: raise ImportError( - "af.NSS requires the optional `nss` package. Install via\n" - " pip install git+https://github.com/yallup/nss.git\n" - "(Phase 4 of the nss_first_class_sampler roadmap will ship a\n" - "`pip install autofit[nss]` extra — track the progress in\n" - "PyAutoPrompt/autofit/nss_install_simplification.md.)" + "af.NSS requires the optional `nss` package and the matching " + "`handley-lab/blackjax` fork. Install via:\n" + " pip install autofit[nss]\n" + "The extra pins specific upstream commits — see PyAutoFit's " + "pyproject.toml `[project.optional-dependencies] nss` entry." ) super().__init__( diff --git a/pyproject.toml b/pyproject.toml index 01a60e96b..94e70813d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,6 +76,24 @@ optional = [ "nautilus-sampler==1.0.5", "zeus-mcmc==2.5.4", ] +# Phase 4 of nss_first_class_sampler — single safe install for `af.NSS`. +# Pins the `handley-lab/blackjax` fork (BSD-3-Clause) which carries the +# `blackjax.ns.adaptive.init` entrypoint that mainline blackjax lacks, +# plus `yallup/nss` (BSD-3-Clause) on top. Both pinned to specific SHAs +# so installs are reproducible. `fastprogress<1.1` keeps `fastprogress` +# from pulling `python-fasthtml` (1.1.5 transitively requires it). +# Re-pin SHAs periodically — see `autofit/install_nss.py` for the manual +# fallback when pip's resolver cannot sequence the URL deps cleanly. +nss = [ + "fastprogress<1.1", + # blackjax pinned to ef45acd2 (May 2026 "Merge pull request #60 — double_compile"). + # Locally-validated against the entire Phase 1-3 nss_first_class_sampler work. + # HEAD as of pin time (5dbf89a9) introduced `numpy>=1.25` which conflicts with + # autofit's `anesthetic==2.8.14` (numpy<2.0). Bump only after both pins move + # together — see PyAutoPrompt/issued/nss_install_simplification.md notes #3-4. + "blackjax @ git+https://github.com/handley-lab/blackjax.git@ef45acd2f2fa0cca15adbdcd3ff7cb3a98987cb5", + "nss @ git+https://github.com/yallup/nss.git@69159b0f4a3a53123b9eec7df91e4ed3885e4dc4", +] docs=[ "sphinx", "furo",