#7429·hive

Lint Python job has been failing on main since 2026-08-18, so every PR inherits a red check

Author: woahwhattheheckCreated Sep 7, 2026Updated Sep 16, 2026

Summary

The Lint Python job has been failing on main continuously since at least 2026-08-18. Every other job in the CI workflow passes on the same runs. Because the job fails on main, every open pull request inherits a red Lint Python check that is unrelated to its own diff, so the gate currently gives no signal — a genuine new lint regression in a PR is indistinguishable from the standing failure.

Evidence

Six most recent CI runs on main, all failure:

run head conclusion
33998987269 0c38749 failure
fad7219 failure
54fd8db failure
f71da3f failure
e418363 failure
c3181d9 failure

Jobs on the newest of those (0c38749): Test Python Framework (ubuntu + windows) success, Test Tools (ubuntu + windows) success, Validate Agent Exports skipped, Lint Python failure.

The job log for run 33998987269 ends with Found 21 errors, in B023 and I001.

Reproduction

bash
git clone --depth 1 https://github.com/aden-hive/hive.git
cd hive
uv sync --project core --group dev
uv run --project core ruff check core/
uv run --project core ruff check tools/
uv run --project core ruff format --check core/
uv run --project core ruff format --check tools/

Measured on a clean checkout of 0c38749 with ruff 0.16.6:

step result
ruff check core/ 22 errors — 14 B023, 6 I001, 1 UP041, 1 F401
ruff check tools/ 138 errors — all I001
ruff format --check core/ 19 files would be reformatted
ruff format --check tools/ 50 files would be reformatted

The CI run reports 21 rather than 22 for core/. core/pyproject.toml declares ruff>=0.14.14 with no upper bound, so the version CI resolves at run time drifts and the count moves with it. Pinning a compatible range would make this job reproducible regardless of what the fix turns out to be.

ruff check tools/ never runs in CI today: the two ruff check commands share one run: block, so the shell exits after core/ fails and the 138 tools/ findings are not currently visible in the log.

The findings

I001 (144 across core/ and tools/) and UP041 and F401 — 146 total, all auto-fixable. ruff check --fix resolves every one. The F401 is framework.config.HIVE_HOME imported but unused in core/framework/server/routes_config.py; the UP041 is an aliased timeout error in core/framework/agent_loop/agent_loop.py that TimeoutError now covers.

B023 (14, all in core/framework/server/routes_execution.py) — worth stating precisely: these are not a live bug. All fourteen sit in four closures defined inside the for idx, img in enumerate(image_content) loop:

closure defined invoked
_inspect_pdf 359 await asyncio.to_thread(...) at 387
_parse_csv 473 506
_read_text_attachment 541 558
_probe_dims 632 636

Each is awaited inside the same iteration that defines it, so the late-binding hazard B023 describes never actually fires — no closure outlives the iteration whose values it reads. The rule is correctly identifying the pattern; the current code is safe. Binding the captured names as default arguments silences it without any behaviour change.

Suggested fix

Two parts, mechanically separable:

  1. ruff check --fix core/ tools/ for the 146 auto-fixable findings, plus ruff format core/ tools/ for the 69 files.
  2. Default-argument binding on the four closures above for the 14 B023.

I have this applied and verified locally against 0c38749: ruff check core/ and ruff format --check core/ both pass, with python -m py_compile clean on every touched file. The B023 change is 20 changed lines in routes_execution.py; the largest single file is routes_config.py at 89, nearly all of it ruff format reflow, since several files are wrapped near 88 columns while core/pyproject.toml sets line-length = 150.

Happy to open a PR for this. Following the contribution policy in #472 I am raising it as an issue first rather than opening one unprompted — if a maintainer wants it and assigns accordingly, I will send it. It is also easy to split: the auto-fixable half and the format half are independent of the B023 half, so this can land as one PR or three, whichever is easier to review.

One choice belongs to the maintainers rather than to me: whether tools/ should be linted at the same strictness as core/. If not, a per-file-ignores entry or dropping tools/ from the job would resolve 138 of the 160 findings without touching those files at all.