docs/adr/0003-platform-support-policy.md
labelme drops Python minors on the SPEC 0
schedule (the successor to NEP 29),
anchored to what its core scientific dependencies (numpy, scipy, scikit-image)
actually ship. For v7.0.0 that makes the floor Python 3.12
(requires-python = ">=3.12"). The strict SPEC 0 calendar reaches 3.12 once 3.11
passes its three-year mark (around October 2025), and the dependency stack has now
caught up: numpy (2.5) and scipy (1.18) both require >=3.12 at HEAD, so 3.12 is
the real ecosystem floor as well. v6.3.x is the maintenance line for the Qt5 and
Python 3.10 / 3.11 stragglers left behind by v7.0.0, receiving critical fixes only.
This is an application policy, not a library one: labelme has effectively no downstream packages, so the value of SPEC 0 here is not coordination but honesty. The dependency stack decides what can be shipped, and SPEC 0 describes how that stack moves. When numpy/scipy/scikit-image drop 3.12, labelme raises its floor to match in the next release that crosses the boundary.
>=3.11 (rejected): numpy and scipy have both dropped 3.11 at HEAD
(numpy 2.5 / scipy 1.18 require >=3.12). A 3.11 install silently resolves to
stale science (the last numpy 2.4.x / scipy 1.17.x releases), the same trap that
retired 3.10 in the previous revision of this policy. Advertising 3.11 is a
promise the dependency stack no longer keeps.>=3.11 until scikit-image also drops it (rejected): the earlier
floor policy moved "when the first of numpy/scipy/scikit-image drops 3.11", and
that trigger has now fired twice (numpy and scipy). Waiting for the slowest
dependency would keep advertising a version two of three core deps no longer
build against, and would hold an extra minor in the CI matrix (each supported
Python is a full os x version cell across Windows, macOS, and Linux) for users
the stack can no longer serve.>=3.12)
now agree, so 3.12 is both the principled schedule and the version labelme can
actually install today. It also keeps the test matrix to the three minors the
ecosystem still builds against, rather than paying CI for a fourth it does not.requires-python, so raising the
floor to 3.12 raises the lowest tested Python (and the .python-version dev pin)
in lockstep and drops the 3.11 row from the test matrix.