Repository navigation
Description
Split out of #1475, which settled the unit-test job's interpreter and said explicitly that "whether the lint job needs the same treatment is a separate call". #1484 took the first half and left this one filed rather than widened into it.
The finding
validate-task.yml's lint job pins its interpreter and exposes no input to change it. Read on the branch #1484 merges:
.github/workflows/validate-task.yml:202 python-version: "3.13"
The python-versions input #1484 adds reaches the unit-test job's matrix alone. Nothing a caller can pass moves the lint job.
Two separate costs, and only one is settleable downstream
A type-check target, which a repository can settle in its own configuration. The Type check Python step runs mypy or pyright under that pinned interpreter. Each defaults its target to the interpreter it runs under, so a repository declaring requires-python = ">=3.13" and testing 3.13 and 3.14 gets its type check performed at 3.13 alone. A 3.14-only typing error, a sys.version_info branch or a typeshed symbol version-gated on one, passes the hub gate with nothing failing and nothing warning. That is the same silent-narrowing shape #1475 was filed for, moved from the test leg to the type checker.
A repository closes this itself by naming a version in its own [tool.mypy] or [tool.pyright] section, and #1484's adopter docs say so. ruff needs nothing, taking its target from requires-python where a [project] table declares one. So this half is a documented workaround rather than a block.
A lockfile floor, which it cannot settle anywhere. The Sync Python dependencies step runs uv sync --all-groups --frozen under the same pinned interpreter, guarded on a committed uv.lock. A repository carrying a uv.lock whose requires-python floor is above the pin fails that step outright: UV_PYTHON resolves to 3.13, which cannot satisfy the lockfile's own requirement. No [tool.*] section reaches it and no value of python-versions reaches it. That repository cannot adopt the gate at all.
No current adopter is in that state. aiopurpleair declares >=3.13 and is unaffected, and a repository whose Python dependencies come from requirements*.txt skips the step entirely, its guard naming uv.lock. It is a constraint on the next adopter rather than a live break, which is why it is filed rather than fixed under #1484.
Suggested remedy, and what makes it not obvious
The shape #1484 used does not transfer unchanged. Its matrix is over interpreters that each run the same tests, where linting the same sources under two interpreters is mostly redundant work: ruff reports identically, and only the type check and the sync actually differ. So a lint-python-version scalar input, defaulting to today's pin, is likely the right size rather than a second matrix, and it would settle both costs at once. A matrix here would double every lint leg, the doc gates included, to re-derive findings the first leg already produced.
Whether the doc-lint block should move out of a job that gains an interpreter dimension is the question to answer first, since it is language-independent and pays for any fan-out it sits inside.
Not filed here
No registry or spec change. No audit report is being written back, and #1484's adopter docs already state both costs so a reader is not misled while this is open.
Activity
ptr727 commentedon Nov 1, 2026
Decision needed (decision triage, 2026-11-01)
Question: How should
validate-task.yml'slintjob choose its interpreter (setup-uvpython-version: "3.13", line 315) so a repository whoseuv.lockfloor is above 3.13 can adopt the gate: the firstpython-versionsentry, a newlint-python-versionscalar input, or a lint matrix with the doc-lint block moved out first?Options, recommended first:
test-matrixlegs default to it; the["3.13"]default keeps today's behavior, settles the lockfile floor, and needs no fan-out, so doc-lint stays put. Needs the same named-cause guard as :345-352. No work in flight.python-versionsand the pip path's rule. No work in flight.Evidence: validate-task.yml:147-165 (doc-lint in the lint job), :315 (the pin), :337 (
uv sync --frozenunder it), :345-352 (pip path readspython-versions[0]with a named-cause check). docs/reusable-workflows.md:479 documents the costs. No current adopter is affected.Blocks: none
ptr727 commentedon Nov 1, 2026
Maintainer answer (decision triage, 2026-11-01): Option 1: the lint job uses the first python-versions entry, with no new input, guarded by the same named-cause check as the pip path. This is now work for the next burndown round.
ptr727 commentedon Nov 1, 2026
Released (2026-11-02): worktree and branch removed, so this claim holds no files. Its fix merged to develop in PR #3796.
Backlog burndown claim (round 2, group R2G3). Branch:
feature/burn-3334. Issues: #3334, #1516, #3487, #1485, #1938.Predicted file set:
.github/workflows/test-pull-request.yml,.github/workflows/validate-task.yml,.github/workflows/build-release-task.ymlcatalog/snippets/workflows/test-pull-request.yml,catalog/snippets/workflows/test-pull-request-smoke.ymldocs/reusable-workflows.md,WORKFLOW.md,spec/audit.py,spec/files.json,scripts/repo_gate.pyspec/project-types.json,spec/fidelity-model.md(added in adjudication)tests/test_audit.py,tests/test_audit_helpers.py,tests/test_release_guards.py,tests/test_repo_gate.py.agents/skills/workflow-ci-contract/and its generated trees (.github/skills/workflow-ci-contract/,.claude-plugin/fleet-skills/skills/workflow-ci-contract/,.claude-plugin/fleet-skills/.source-digests/workflow-ci-contract)Gate the Required Check Name, Latest Flag, Lint Interpreter, and .NET…