# The declared floors, pinned exactly. Installable, and installed by the
# `dependency-floor` CI job.
#
# Why this file has to exist: pip has no "resolve to the lowest permitted
# version" mode. A floor of `transformers>=4.56` is satisfied by whatever is
# newest, so a job that only reads pyproject tests the ceiling and calls it the
# floor. Every direct dependency therefore gets an `==` here, and this file is
# what makes the floor claim measurable.
#
# torch is deliberately absent: its CPU wheels live outside PyPI, so the job
# installs it by hand from the torch index before applying these. Its floor is
# version-dependent (see pyproject) and cannot be expressed as one pin.
#
# When a floor in pyproject changes, change it here in the same commit. A
# mismatch means the job is testing a version nothing declares.

transformers==5.10.1
# 0.32.0 and not 0.26: `peft` imports `accelerate.utils.memory.clear_device_cache`, which
# first exists at 0.32.0, while declaring only `accelerate>=0.21`. Raised in pyproject in
# the same commit, as the header above requires.
accelerate==0.32.0
# NOT 14, AND THE DECLARED FLOOR IS STILL 14. This is the one pin in this file that is
# deliberately ABOVE the floor it tests, and the reason is a collision between two declared
# floors rather than a preference.
#
# `datasets` 5.0.1, the security floor raised under Q-72, requires `pyarrow>=21.0.0` (read from
# the published metadata on 2026-10-01, not guessed). The `dev` extra pulls `[hub]`, so this
# environment always contains `datasets`, so it can never contain pyarrow 14 again. The base
# floor of `pyarrow>=14` remains correct and remains the thing that keeps `trackio` installable
# from a distribution package; it is simply no longer installed by this job.
#
# WHAT THAT COSTS, stated rather than left to be discovered: the `pyarrow>=14` claim now has no
# job that installs it. Restoring it needs a second, hub-free floor environment, which is a
# ledger item rather than something to pretend away here.
#
# 23.0.1 since 2026-10-06, raised from 21.0.0 for PYSEC-2026-113, which was live at 21.0.0. It
# still satisfies the `pyarrow>=21.0.0` that `datasets` 5.0.1 names as its minimum, and it ships
# a cp310 wheel, which is what this job's Python 3.10 needs. The pin stays exact for the original
# reason: an unpinned pyarrow resolves to whatever is newest and builds from source the day that
# stops shipping one, which is the cp314 failure this file already carries a scar from.
pyarrow==23.0.1
huggingface_hub==1.5.0
# numpy is not a declared dependency of this project and is pinned here anyway.
#
# THE ORIGINAL REASON NO LONGER APPLIES, and saying so is cheaper than letting the next reader
# trust it: pyarrow 14's extension modules are compiled against numpy 1 while its metadata said
# only `numpy>=1.16.6`, so the resolver paired it with numpy 2 and the job failed with
# "ImportError: numpy.core.multiarray failed to import" from `pyarrow.lib`. pyarrow is pinned at
# 23.0.1 here now, built for numpy 2, so that collision is gone.
#
# WHAT IS NOT PROVEN, said rather than left for the job to discover: pyarrow 23.0.1 declares no
# numpy bound at all, so nothing in the metadata forces numpy 2 and nothing proves its compiled
# extension imports against numpy 1.26.4. The resolve is satisfiable; the import is what the
# floors job actually tests. If it fails at `import pyarrow.lib`, this pairing is the cause.
#
# THE PIN STAYS ANYWAY, as a deliberate hold rather than a forced one. This environment has
# never been exercised on numpy 2, and `accelerate==0.32.0` runs against numpy 1.26.4, verified
# directly on Python 3.10 rather than inferred from its metadata. Moving the
# datasets floor and the numpy major in one commit would make a failure unattributable, which is
# the opposite of what a floors job is for. 1.26.4 is the last numpy 1 and supports Python 3.10.
# Lifting it is a separate, deliberate step with its own measurement.
numpy==1.26.4
# 4.0, not 3.1. `head-to-head/best_of_n_heretic.py` imports
# `optuna.storages.journal.JournalFileBackend`, which arrived in Optuna 4.0; at 3.1 the floors job
# died at collection with "No module named 'optuna.storages.journal'". A floor the project's own
# suite cannot pass is not a floor, it is a number.
optuna==4.0.0
# Both of these were declared with a floor and pinned nowhere, so the floors job resolved them
# to whatever was newest and called it the floor. `gguf` is precisely the dependency where an
# untested floor has already bitten this project: PyPI gguf 0.19.0 and llama.cpp's own gguf-py
# 0.19.0 are different code sharing a version number. Checked against PyPI on 2026-09-08: 0.19.0
# ships a py3 wheel, and sentencepiece ships cp310 wheels, so both install on the Python this job
# runs. sentencepiece is 0.2.1 since 2026-10-06, raised from 0.1.98 for PYSEC-2026-1909; 0.2.1
# ships cp310 wheels too, checked against PyPI rather than assumed.
gguf==0.19.0
sentencepiece==0.2.1
# The live display's dependency. Pure Python, so it installs on every runner this job uses.
#
# VERIFIED AT THIS EXACT VERSION on 2026-09-27, not assumed: 13.0.0 in a clean virtualenv, driving
# every API `livedisplay.py` touches (`Console(file=...)`, `Live` with `refresh_per_second` and
# `transient`, `Panel(title=, border_style=)`, `Table.grid` with `padding`, `add_column(justify=,
# style=)`, and `[dim]` markup). The panel rendered with its box and title.
#
# Worth knowing if anything here ever reads it: rich 13.0.0 has no `rich.__version__` attribute, so
# a version check has to go through `importlib.metadata`. Nothing in this project does one.
rich==13.0.0

# The card's temperature and power on the live dashboard, and nothing else in the tree reads it.
# The floor is from August 2023, far below what any recent driver ships against, so the cooldown
# is not a question and this is the oldest that has been exercised rather than the oldest that
# might work.
#
# `nvidia-ml-py` and NOT `pynvml`: the distribution name is not the module name. NVIDIA publishes
# the bindings under this name and installing it gives you the `pynvml` module the panel imports.
nvidia-ml-py==12.535.108

# The dev extra, because `pip install -e '.[dev]'` at the floors is a real
# thing a contributor does, and the suite has to pass there too.
#
# `datasets` moved out of the runtime dependencies and into the `hub` extra when
# `trackio.py` took over reading and writing tracks, but its floor still has to be
# tested: `[dev]` installs it so the suite can assert that both backends read and
# write the same bytes.
#
# 5.0.1 since 2026-10-01 (Q-72), and it is a SECURITY floor: PYSEC-2026-3716 is live at 2.15.0,
# 2.21.0, 3.0.0 and 4.0.0 and clean only at 5.0.1, so every version the old floor admitted
# carried a path traversal in the folder-based builders. This job is the only place that floor
# is ever installed, so it is the only place the exposure was ever visible, and it is why the
# pyarrow pin above had to move with it.
datasets==5.0.1
# A SECURITY FLOOR ON A TRANSITIVE DEPENDENCY, pinned 2026-10-10 the same day the floor was
# declared in pyproject.toml, because a floor with no pin here is a floor no job ever installs.
#
# `multidict` arrives through datasets -> aiohttp -> multidict, so nothing named it and a free
# resolve picked a vulnerable version: GHSA-54p9-h82j-f925 / CVE-2026-104874, a reference leak in
# the MultiDict and CIMultiDict items-view union and subtraction, introduced in 6.7.0 and fixed in
# 6.9.1. pyproject.toml carries the full reasoning for why the floor is 6.9.1 rather than a range.
#
# THE PIN AND THE FLOOR ARE ONE DECISION IN TWO FILES, which is what `test_declared_floors.py`
# exists to keep true: without it, the dependency-floor job resolves `multidict` freely, installs
# the newest release, and reports a pass for a version the floor does not describe. So the one job
# that would have caught a bad floor would have been testing the ceiling under the floor's name.
multidict==6.9.1
# 9.0.3 since 2026-10-06, raised from 7.0.0 for PYSEC-2026-1845, which was live at 7.0.0. The two
# pins below are deliberately NOT raised with it: neither carries an advisory, and both declare
# bounds that 9.0.3 satisfies (pytest-cov wants pytest>=4.6, xdist wants >=6.2.0). Raising a floor
# nothing asked to move would be testing a version nothing declares.
#
# WHAT THAT LEAVES UNPROVEN: pytest-cov 4.0.0 is from 2022 and pytest 9 changed internals that a
# plugin can reach into. The metadata is satisfied; whether the plugin works is what this job runs
# the suite to find out. If collection dies in pytest-cov, this pairing is the cause and the fix is
# to raise pytest-cov here rather than to lower pytest.
pytest==9.0.3
pytest-cov==4.0.0
# The floor for the parallel runner. `-n 4` is what every suite job uses, so the
# oldest xdist the project permits has to be one that still understands it.
pytest-xdist==3.2.0
build==1.0.0
shtab==1.6.0
# Test-only, and only where `tomllib` is not in the standard library.
tomli==2.0.0
# The adapter backend for `tamper --method lora`, declared on 2026-10-06 after being
# advertised in `--help` with nothing declaring it. 0.20.0 is the oldest release this
# project has actually run `tamper` against, so it is the oldest it claims.
peft==0.20.0
# ruff is already pinned exactly in pyproject, so it has no floor to test.

# bitsandbytes (the `quant` extra) is absent: it is not installed by `[dev]`,
# needs CUDA to do anything, and the CI runners have no GPU.
