Repository navigation
tech-debt(deps): torch is pinned in 8 places with 5 different specs and none is the constraints SSOT — it blocks every dependabot bump #18127
Description
torch is declared in eight places with five different specs, and none of them is constraints/shared.txt — the file whose own header says "Change a version HERE, once. NEVER re-declare a constrained library's version in a component requirements file." The immediate consequence is that dependabot cannot bump torch without going red.
Measured
| file:line | spec |
|---|---|
autobot-backend/requirements.txt:80 |
torch==2.14.1 |
requirements-ci/ai-ml.txt:34 |
torch==2.14.1 |
autobot-npu-worker/requirements.txt:11 |
torch>=2.14.1 |
autobot-infrastructure/shared/docker/ai-stack/requirements-ai.txt:45 |
torch>=2.14.1 |
autobot-tts-worker/requirements.txt:4 |
torch>=2.14.0 |
autobot-slm-backend/ansible/roles/tts-worker/tasks/main.yml:234 |
- "torch>=2.14.0" |
requirements-gpu-torch.txt:22 |
torch==2.14.0 |
autobot-npu-worker/resources/windows-npu-worker/requirements.txt:68 |
torch>=2.6.0 |
constraints/shared.txt currently carries two entries. torch is not one.
How this is biting right now
PR #18105 (dependabot, autobot-tts-worker) bumps autobot-tts-worker/requirements.txt from >=2.14.0 to >=2.14.1. python-suite shard 5/12 then fails:
FAILED repo_tests/ansible_requirements_parity_test.py::test_every_cross_manifest_divergence_is_in_the_baseline
E AssertionError: New ansible/requirements version divergence:
E assert not ['autobot-slm-backend/ansible/roles/tts-worker/tasks/main.yml::{{ tts_install_dir }}/venv::torch']
The test is correct — the ansible role that provisions that very worker still pins >=2.14.0. And baselining is explicitly not the fix: the test's message says "Fix the declaration. ansible_pip_parity_baseline.txt only shrinks", and its docstring records that the baseline carries no entries.
So every torch bump needs a matching hand-edit in an ansible task file in a different service tree. The role's comments show that is the current process — main.yml:276 reads "Raised 3.1.0 -> 3.3.0 with autobot-tts-worker/requirements.txt (#17707)" — i.e. the duplication is known and manually kept in sync, which is exactly the failure mode a dependabot PR cannot perform.
This blocks #18105 and will block the next torch bump identically. The two declarations must move in one commit, which means the fix cannot land on main separately: bumping only the ansible role would make main itself divergent and fail the same test.
Not all eight should converge
Two are deliberately different and must not be flattened:
autobot-npu-worker/resources/windows-npu-worker/requirements.txt:68—>=2.6.0, annotated "GH#8324: CVE-2025-32434 — torch.load RCE via weights_only=True". A floor for an off-box Windows worker that has no path to the shared constraints file.requirements-gpu-torch.txt:22—==2.14.0, the GPU wheel build, referenced fromautobot-backend/requirements.txt:80as the GPU alternative (fix(deploy): CUDA torch is gated behind the vLLM flag, so GPU hosts without vLLM silently run CPU torch #15162). Whether GPU and CPU builds must share a version is a real question, not an obvious yes.
So the target is roughly five converging declarations plus one ansible pin, with two documented exceptions.
Proposed
- Add
torchtoconstraints/shared.txtand have the five convergeable requirements files reference it via-c, so a bump is one edit. Record the two exceptions inline with their reasons. - Stop the ansible role from carrying its own version. It cannot simply
pip install -r requirements.txtbecause the role deliberately splits packages across three pip tasks by index (torch comes from the CPU wheel index,main.yml:231-239), so this needs either a lookup of the pin from the requirements file or a role variable fed from one place. Either removes the hand-edit that dependabot cannot do. - Until (2) lands, chore(deps): bump the all-dependencies group in /autobot-tts-worker with 2 updates #18105 needs a one-line bump of
main.yml:234to>=2.14.1on its own branch, since both declarations have to move together.
Acceptance criteria
-
torch's version is declared once for the converging set, inconstraints/shared.txt, with the referencing files using-c - the ansible tts-worker role no longer hardcodes a torch version, or derives it from the single declaration
- the two deliberate exceptions carry an inline reason naming why they differ
- a dependabot torch bump passes
ansible_requirements_parity_testwith no hand-edit in an ansible file -
ansible_pip_parity_baseline.txtgains no entries (it only shrinks)
Related: the owner rule that one package version is declared once and reused; constraints/shared.txt covering 2 entries today is the measure of how far that is from true.
Activity
mrveiss commentedon Oct 9, 2026
The fix-shape already exists in this very role — but adding torch to constraints is all-or-nothing
Two findings that make this mechanical once one decision is made.
1. The role already does exactly this for numpy
autobot-slm-backend/ansible/roles/tts-worker/tasks/main.yml:285-296, verbatim:and it records that #15601 brought five pip constraint sites onto that shape. So the sanctioned pattern is: list the package bare in the role, let
-csupply the version. torch is the one package in this role that never got that treatment —main.yml:234still says- "torch>=2.14.0".2. Every relevant requirements file already references the SSOT
Measured — all six already carry a
-cline:autobot-backend/requirements.txtautobot-tts-worker/requirements.txtautobot-npu-worker/requirements.txtautobot-npu-worker/resources/windows-npu-worker/requirements.txtautobot-infrastructure/shared/docker/ai-stack/requirements-ai.txtrequirements-ci/ai-ml.txtSo the mechanism needs no plumbing. Adding
torchtoconstraints/shared.txtreaches all six immediately, and the constraint-drift workflow then fails any PR that re-declares it — which is precisely what would have caught #18105 at review instead of on a shard.The decision that blocks it
Because the drift guard forbids re-declaring a constrained version, adding torch is all-or-nothing across those six files: each must then list
torchbare. That pulls in two cases I am not willing to guess at:windows-npu-worker/requirements.txt:68—torch>=2.6.0, annotatedGH#8324: CVE-2025-32434 — torch.load RCE via weights_only=True. It does reference constraints (line 73), so it would be narrowed to whatever the SSOT says. A floor ≥2.14.1 subsumes the CVE fix, so the security intent survives — but I cannot verify a Windows wheel exists for that version on that worker's interpreter, and that worker installs from--extra-index-url https://download.pytorch.org/whl/cpu. Getting this wrong breaks an off-box worker's install.autobot-backend/requirements.txt:80istorch==2.14.1;requirements-gpu-torch.txt:22istorch==2.14.0, and the backend comment names it as the GPU alternative (fix(deploy): CUDA torch is gated behind the vLLM flag, so GPU hosts without vLLM silently run CPU torch #15162).requirements-gpu-torch.txtdoes not reference constraints, so it is naturally outside this change — but whether the GPU build may run an older torch than the CPU build is a real question, not an oversight to flatten.Also worth settling: house style here is a floor (
openvino>=2026.4.1) or a range (numpy>=2.5.3,<3.0.0), never an exact pin — while backend and CI both pin torch exactly (==2.14.1). A floor would leave the Windows worker free to take its newest available wheel; an exact pin would not.Recommendation
torch>=2.14.1as the constraint (floor, matching house style and the highest floor already stated), all six files bare, and the role'smain.yml:234bare with the-cextra-arg it already passes for numpy. That preserves the Windows CVE intent, keeps the GPU file out of scope, and removes the hand-edit dependabot cannot perform.I have not applied it — the Windows wheel-availability question needs an answer from someone who can check that worker, and a wrong call there breaks a deploy rather than a guard.
review(18130): answer all eleven CodeRabbit threads — one KB store, d…
refactor(forks): retire fifteen forks across eight issues, each onto …
refactor(forks): retire fifteen forks across eight issues, each onto …