Dependency policy¶
HelioAI follows PHEP 3, the PyHC adoption of SPEC 0.
The rules¶
- Python minor versions are supported for 36 months after release.
- Upstream core Scientific Python packages —
numpy,scipy,matplotlib,pandas,scikit-image,networkx,scikit-learn,xarray,ipython,zarr— are supported for 24 months after release. - New versions of both are adopted within 6 months of release.
In practice that means about three Python minor versions at any time. Today: 3.12, 3.13 and 3.14.
Compliance is checked in CI by the official PyHC PHEP 3 action, so the policy is enforced rather than merely written down.
What this means when you add a dependency¶
Use >= floors. Upper bounds and exact pins are the exception, not the default:
"numpy>=2.1", # good
"numpy<2", # needs a very good reason and a tracking issue
"scipy==1.15.0", # almost never
PHEP 3 permits an upper bound "only when absolutely necessary", and requires an issue to be opened at the same time to remove it.
Note that the floor matters too
A floor older than 24 months is itself a warning: it means you claim to support a version the ecosystem has moved past. Bumping the floor is part of routine maintenance, not a breaking change.
Current exceptions¶
None currently.
torch>=2.6 is a direct dependency although HelioAI never imports torch: it is reached
only through sentence-transformers. The floor is ours because transformers 5 requires
torch>=2.5 and declares it in no core requirement. Installing the 0.3.0 wheel with
uv pip in a fresh environment resolved torch 2.4.1 — uv backtracked torch to escape an
unrelated conflict (mpmath 1.4 against sympy's <1.4 cap) where pip backtracked mpmath —
and transformers then disabled torch at import: the dense search failed and the tool fell
back to a text scan with no error at the boundary. The floor forces every resolver to the
same answer. 2.6 is also the first torch with cp313/cp314 wheels, which is what the former
uv-only constraint existed for.
Lifting a cap is not a local change¶
Removing an upper bound re-resolves the entire graph, not just the package you touched.
Dropping transformers<5.0 here also let mcp jump from 1.x to 2.0, which broke the web
server at startup.
So, when you lift a cap:
- Read the whole
uv lockdiff, not just the dependency you meant to change. - Run the application, not only the tests —
helioai serve --webcaught that one before CI did. - Expect the lint to move too. Pinning ruff's rule set explicitly (rather than inheriting its shifting defaults) exists for the same reason.
Keeping the environment sane¶
uv sync --extra X purges extras you did not list. Always combine:
Otherwise pytest quietly disappears from your environment, and the failure you get next is confusing rather than obvious.