Repository navigation
Description
Overview
import autocti hard-requires arcticpy, which is not a pip dependency: its sdist is source-only C++ (needs libgsl-dev + a toolchain + Cython) and its own requirements downgrade numpy below 2.0. Every CTI repo that runs CI therefore carries its own copy of the install recipe, there is no single owner, and the documented recipe is incomplete for a clean environment. This task makes one canonical arcticpy install step owned by PyAutoHeart (the organ that owns the reusable CI workflows), repoints every consumer at it, and fixes the human/agent docs so they match CI.
Audit result (this supersedes the prompt's site list)
The prompt flagged PyAutoCTI's own lib-tests CI as UNREAD. Audited:
PyAutoCTI/.github/workflows/main.ymlis a thin caller ofPyAutoHeart/.github/workflows/lib-tests.yml@main. It contains no arcticpy recipe of its own.- That reusable workflow carries two further copies, one per job:
unittest(L81–90) andunittest-nojax(L180–186).
So there are four shell copies, not two:
| # | Site | setuptools wheel? |
|---|---|---|
| 1 | PyAutoHeart/.github/workflows/lib-tests.yml — job unittest |
yes |
| 2 | PyAutoHeart/.github/workflows/lib-tests.yml — job unittest-nojax |
yes |
| 3 | autocti_workspace_test/.github/scripts/smoke_install.sh |
no |
| 4 | autocti_assistant/.github/workflows/wiki-currency.yml |
yes |
autocti_workspace has no .github/ directory at all — it is a docs-only consumer.
Correction to the "latent failure" framing
The prompt says smoke_install.sh "relies on the runner image's ambient setuptools" and is one runner-image change from breaking. That is not accurate as written. PyAutoHeart's smoke-tests.yml runs
- name: Install (base + the workspace's own epilogue)
run: |
pip install --upgrade pip setuptools wheel
pip install pyyaml
bash workspace/.github/scripts/smoke_install.shso setuptools is present when the epilogue runs. The real defect is weaker but still worth fixing: the epilogue's correctness depends implicitly on a preceding step in a different repository's workflow, with nothing stating the dependency. Reordering or trimming that Heart step would silently break CTI smoke. Making the canonical step self-contained removes the coupling.
Docs are worse than CI
PyAutoCTI/AGENTS.md§arcticpy — the note both other repos cite as canonical. Says "install it after numpy is in place" and then the barepip install arcticpyline. Omits bothCythonandsetuptools.autocti_workspace/AGENTS.md§arcticpy — "install it after numpy". Omits Cython and setuptools.autocti_workspace_test/AGENTS.md— "after numpy+cython". Omits setuptools.autocti_assistant/skills/ac_setup_environment.md— numpy + cython, no setuptools.
Plan
- Add a canonical composite action
install-arcticpyto PyAutoHeart, version-pinned in one place, ending in an import assertion. - Give it a self-test workflow in PyAutoHeart so a change to the recipe is proven to build before it can break four repos.
- Repoint all four shell copies at it and delete the local recipes.
- Fix the four documented recipes so humans and agents get the same working commands CI uses.
- Leave the build-cache idea unimplemented; record it as a measured follow-up rather than guessing.
Detailed implementation plan
Affected Repositories
- PyAutoHeart (primary)
- autocti_workspace_test
- autocti_assistant
- PyAutoCTI
- autocti_workspace
Branch Survey
| Repository | Current Branch | Dirty? |
|---|---|---|
| ./PyAutoHeart | main | clean |
| ./autocti_workspace_test | main | clean |
| ./autocti_assistant | main | clean |
| ./PyAutoCTI | main | clean |
| ./autocti_workspace | main | clean |
Suggested branch: feature/arcticpy-install-standardisation
Shape: composite action, not a shell script
PyAutoHeart has no .github/actions/ today, so this is a new convention for the repo. It is the right one:
- PyAutoHeart is public, so
uses: PyAutoLabs/PyAutoHeart/.github/actions/install-arcticpy@mainresolves from any consumer repo with no checkout of Heart required — the same reach the reusable workflows already have, and the same@mainreference style every caller already uses. - A shell script in Heart would need each consumer to fetch it first (curl or a checkout), which is more machinery and a worse pin.
smoke_install.sh is a bash script and cannot uses: an action. Rather than leave copy #3 in place, the arcticpy install moves out of the workspace epilogue and into Heart's smoke-tests.yml as a gated step. This matches the existing precedent inside Heart: lib-tests.yml already gates its arcticpy step on if: inputs.package == 'autocti'.
Implementation Steps
-
PyAutoHeart/.github/actions/install-arcticpy/action.yml(new) — composite action:- input
version, default2.6(the single pin). - input
sudo, defaulttrue, so a container without sudo can opt out of the apt leg. sudo apt-get update && sudo apt-get install -y libgsl-devpython -m pip install --upgrade pip setuptools wheel— self-contained, no reliance on a caller's preceding step.python -m pip install numpy cythonpython -m pip install "arcticpy==${version}" --no-build-isolation --no-depspython -c "import arcticpy; print(arcticpy.__version__)"— the assertion. Today a broken arcticpy surfaces much later as a confusingimport autoctifailure in an unrelated job.
- input
-
PyAutoHeart/.github/workflows/arcticpy-action.yml(new) — self-test. Runs on PRs touching the action or the workflow, plusworkflow_dispatch. Uses the local path./.github/actions/install-arcticpyso it exercises the branch's version, then assertsadd_ctiproduces a trail on a single bright pixel. Without this, a@mainreference means a recipe change cannot be validated before merge. -
PyAutoHeart/.github/workflows/lib-tests.yml— replace both inline blocks (jobsunittest,unittest-nojax) with the action, keeping theif: inputs.package == 'autocti'gate. -
PyAutoHeart/.github/workflows/smoke-tests.yml— add anarcticpyboolean input (defaultfalse); when true, run the action after Python setup and before the workspace epilogue. Default-false keeps every non-CTI workspace caller byte-identical. -
autocti_workspace_test— caller.github/workflows/smoke_tests.ymlpassesarcticpy: true; delete the recipe from.github/scripts/smoke_install.sh, leaving it to do only what is genuinely workspace-specific (the chain install and the autonerves re-pin). -
autocti_assistant/.github/workflows/wiki-currency.yml— replace the inline recipe in "Install the stack" with the action, and delete the "Recipe mirrors …smoke_install.sh" comment that acknowledged the copy-paste. -
Docs — fix all four, each to the verified-complete recipe, and point them at the canonical action so the CI/doc link is explicit:
PyAutoCTI/AGENTS.md§arcticpy (the cited canonical note; keep the no-root header workaround)autocti_workspace/AGENTS.md§arcticpyautocti_workspace_test/AGENTS.mdautocti_assistant/skills/ac_setup_environment.md(note: the assistant's.claude/skills/*.mdare symlinks intoskills/, git mode 120000 — one edit covers both surfaces)
Verified recipe (measured 2026-08-24, clean Ubuntu container, Python 3.12 venv)
apt-get install -y libgsl-dev # g++/gcc/make already present on the image
pip install numpy scipy setuptools wheel Cython matplotlib
pip install arcticpy==2.6 --no-build-isolation --no-depsEach missing build dep failed the build naming the next one: setuptools → Cython → builds. matplotlib is a runtime import (arcticpy/read_noise.py) needed only because --no-deps suppresses it; the CTI stack installs it anyway, so it is not a build dep and does not belong in the canonical step.
Deliberately not done
Caching the built wheel (actions/cache keyed on arcticpy version + Python version + runner image). arcticpy compiles from source on every CI run in every CTI repo, so there is real time to reclaim — but the prompt asks for a measured proposal with before/after timings rather than an assumed win, and cache-invalidation complexity is a genuine cost. Filed as a follow-up, not guessed at here.
Key Files
PyAutoHeart/.github/actions/install-arcticpy/action.yml— new canonical stepPyAutoHeart/.github/workflows/arcticpy-action.yml— new self-testPyAutoHeart/.github/workflows/lib-tests.yml— copies 1 and 2PyAutoHeart/.github/workflows/smoke-tests.yml— new gated step for copy 3autocti_workspace_test/.github/scripts/smoke_install.sh— copy 3autocti_assistant/.github/workflows/wiki-currency.yml— copy 4
Original Prompt
Click to expand starting prompt
PyAutoMind/draft/maintenance/ci/arcticpy_install_standardisation.md, filed 2026-08-24 — reproduced verbatim:
Standardise the arcticpy CI install across every CTI repo
Type: maintenance / Target: pyautoheart / Difficulty: medium / Autonomy: supervised / Priority: normal
import autoctihard-requires arcticpy, which is not a pip dependency: its sdist is source-only (needslibgsl-dev+ a C++ toolchain + Cython) and its own requirements downgrade numpy below 2.0. Every CTI repo that runs CI therefore carries its own copy of the install recipe. There is no single owner, the copies have already diverged in a way that matters, and the recipe as documented is incomplete for a clean environment.Make one canonical arcticpy install step, owned by the organ that owns the reusable CI workflows, and have every CTI repo consume it.
Work: (1) put the canonical step in PyAutoHeart alongside the reusable workflows the CTI repos already call — check PyAutoHeart's actual layout and conventions before choosing the shape; (2) add the missing
setuptools wheel; (3) assert the install worked withpython -c "import arcticpy; print(arcticpy.__version__)"; (4) repoint every consumer and delete the local copies; (5) fix the documented recipe inautocti_workspace/AGENTS.md,autocti_assistant/skills/ac_setup_environment.mdandPyAutoCTI/AGENTS.md; (6) single pin — bumpingarcticpy==2.6should become a one-line change.Optional, decide deliberately: caching the built wheel. Raise it as a measured proposal with before/after timings rather than assuming it is worth the cache-invalidation complexity.
Why now: two tasks in the preceding sequence were deferred on the belief that arcticpy could not be built outside a prepared machine — a belief that turned out to be false, and cost real work. A canonical, documented, CI-owned install is what stops that assumption forming again.
Unblocks
draft/test/autocti/phase5_smoke_reenable_ordered_trap_scripts.md(CTI epic Phase 5) and helpsdraft/bug/autocti/wiki_currency_baseline_drift.md, whose baseline regeneration needs the same stack.
Activity
Jammy2211 commentedon Aug 24, 2026
Shipped
All five PRs merged, every branch proven an ancestor of its repo's
main.3f77e2fb15c013b929e994c2c8ed2ca093ac60c7Result: one canonical arcticpy install —
PyAutoHeart/.github/actions/install-arcticpy— holding the singlearcticpy==2.6pin. Four divergent shell copies removed; four documented recipes corrected.Proven working, not just merged
1000.0 → 997.2389438265325, trail[1.18249389, 0.77773508, 0.50869121, …], charge conserved to 5.8e-4 — byte-identical to the local run.unittest(3.12, 3.13) andunittest-nojaxgreen through the action.smoke(3.12, 3.13) green through it.wiki-currencygreen through it.Two spec corrections worth remembering
Both found by building arcticpy rather than reading about it, and both would have shipped broken:
--no-depssuppresses runtime deps too.arcticpy/read_noise.pyimports scipy as well as matplotlib, and__init__.pyimports it — so build-deps-only leavesimport arcticpyraisingModuleNotFoundError. The issue's prose named only matplotlib.__version__. The assertion this issue specified raisesAttributeErroron a healthy install. The same broken command was already live inautocti_assistant/skills/ac_setup_environment.md— the assistant would have diagnosed a working arcticpy as broken. Nowimportlib.metadata.Writing the self-test is what caught both. It is now a permanent guard: the action is consumed cross-repo at
@main, so without it a recipe change reaches four repos unexercised.Caching: measured, and declined
Per-step timings from run 32769526194 — the compile is ~14 s of a ~52 s step.
actions/cacherestore+save plus stale-key risk costs more than it saves; the larger costs areapt-get(15.9 s) and pip downloads (18.9 s), neither addressed by caching the wheel. Full breakdown in the PR comment.Mind record:
complete/2026/08/arcticpy-install-standardisation.md.Outstanding
Remote branch deletion returns HTTP 403 from this session's git proxy (and misreports it as "Everything up-to-date", exit 0), so
feature/arcticpy-install-standardisationstill exists on all five repos and needs deleting from a normal checkout or/repo_cleanup.Generated by Claude Code