chore: pin ruff to 0.16.0 across CI, pre-commit, and pyproject - #103
Conversation
`lint.yml` installed ruff unpinned (`pip install ruff`), so CI floated onto ruff 0.16.0 the moment it released and `ruff format --check .` began failing every PR — while the pre-commit hook and local dev stayed on the pinned v0.15.17. The pre-commit config's own comment promised "local runs, the pre-commit hook, and CI all use the same" ruff, but only mypy was actually pinned everywhere; ruff had an exact pin in pre-commit and a floor (`>=0.4.0`) in pyproject with nothing pinning CI at all. Adopt 0.16.0 deliberately and pin it in all three places, matching how mypy is already handled: - `.github/workflows/lint.yml`: `pip install ruff==0.16.0` - `.pre-commit-config.yaml`: ruff-pre-commit rev `v0.16.0` - `pyproject.toml` dev deps: `ruff==0.16.0` (was `ruff>=0.4.0`) 0.16.0 formats Python code blocks inside Markdown by default, so `ruff format .` restyled the examples in 19 docs (quote normalisation, comment spacing, blank lines). No source files changed — all `.py` was already clean under 0.16.0. Verified: `ruff check .` and `ruff format --check .` both pass, and code-fence counts are unchanged in every doc (no block merged or dropped). Future ruff bumps are now a deliberate `pre-commit autoupdate` plus the two matching pins, not a silent CI drift. Claude-Session: https://claude.ai/code/session_01XMWRh8uasxiH9jKiDxYtrZ
subindevs
left a comment
There was a problem hiding this comment.
Verified the pins locally with ruff 0.16.0 against this branch — ruff check . passes and ruff format --check . reports 497 files already formatted, no .py touched, and code-fence counts unchanged in every doc. The diagnosis and the fix both look right.
One thing the reformat did break, flagged inline: two snippets in the superpowers/plans docs are insertion fragments (a single line meant to be pasted into an existing _NO_HISTORY_TYPES set), and ruff parsed them as standalone one-tuple expressions. Following either doc literally now produces wrong code. Both are already correctly implemented in gently/core/event_bus.py:205,207, so nothing is broken today — the risk is the pattern recurring in future plan docs.
Retagging those two fences from ```python to a bare ``` fixes it; I confirmed 0.16.0 leaves bare fences alone (and silently skips unparseable python blocks, so genuine pseudo-code was never at risk).
Separately, worth a look before merge: the ruff-format hook in ruff-pre-commit v0.16.0 declares types_or: [python, pyi, jupyter] — no markdown. CI runs ruff format --check ., which does cover .md. So the pins align the ruff version across the three places but not the file scope: someone editing only a doc with a Python block passes pre-commit locally and gets a red CI — the same "invisible until CI ran" failure this PR is closing, just moved from version drift to scope drift. Either extend-exclude = ["*.md"] under [tool.ruff] (verified working, and would moot the fragment issue entirely) or adding markdown to the hook's types_or would close it.
| Add to `_NO_HISTORY_TYPES` (next to `BOTTOM_CAMERA_FRAME`): | ||
| ```python | ||
| EventType.LIGHTSHEET_FRAME, # high-volume live frames — keep out of history | ||
| (EventType.LIGHTSHEET_FRAME,) # high-volume live frames — keep out of history |
There was a problem hiding this comment.
This snippet is a fragment — a single line to paste into the existing _NO_HISTORY_TYPES set, as the line above says ("Add to _NO_HISTORY_TYPES (next to BOTTOM_CAMERA_FRAME)"). ruff read the bare EventType.LIGHTSHEET_FRAME, as a complete one-tuple expression and normalised it to (EventType.LIGHTSHEET_FRAME,).
The real target at gently/core/event_bus.py:202 is a frozenset({...}), so pasting the new form as instructed gives you a set containing a tuple rather than the enum member. The membership test at event_bus.py:418 (if event_type not in _NO_HISTORY_TYPES) would then miss, and the high-volume frames get retained in history — exactly what this step exists to prevent.
Already implemented correctly at event_bus.py:207, so no live impact. Suggest a bare fence so ruff skips it:
| (EventType.LIGHTSHEET_FRAME,) # high-volume live frames — keep out of history | |
| EventType.LIGHTSHEET_FRAME, # high-volume live frames — keep out of history |
(paired with changing the opening ```python on the previous line to a plain ```)
|
|
||
| ```python | ||
| EventType.TEMPERATURE_UPDATE, | ||
| (EventType.TEMPERATURE_UPDATE,) |
There was a problem hiding this comment.
Same fragment issue as in 2026-06-28-manual-mode-live-view.md. The prose above reads "add it to the high-volume set ... next to DEVICE_STATE_UPDATE in _NO_HISTORY_TYPES", so this is one line destined for a set literal — but ruff formatted the standalone EventType.TEMPERATURE_UPDATE, into the one-tuple (EventType.TEMPERATURE_UPDATE,).
Pasted as written, that puts a tuple in the set instead of the enum member, and TEMPERATURE_UPDATE would no longer be excluded from history. Already correct in the source at event_bus.py:205, so this is about the doc misleading a future reader.
| (EventType.TEMPERATURE_UPDATE,) | |
| EventType.TEMPERATURE_UPDATE, |
(with the opening ```python on the previous line changed to a plain ```)
Why
lint.ymlinstalled ruff unpinned (pip install ruff), so CI floated ontoruff 0.16.0 the moment it released — and
ruff format --check .startedfailing every open PR, including a docs-only one that touches no Python.
Meanwhile the pre-commit hook and local dev stayed on the pinned v0.15.17, so
the failure was invisible until CI ran.
The pre-commit config's own comment promises "local runs, the pre-commit hook,
and CI all use the same" ruff — but only mypy was actually pinned in all three
places. ruff had an exact pin in pre-commit, a floor (
>=0.4.0) in pyproject,and nothing pinning CI.
What
Adopt 0.16.0 deliberately and pin it everywhere, matching how mypy is already
handled:
.github/workflows/lint.yml→pip install ruff==0.16.0.pre-commit-config.yaml→ ruff-pre-commitrev: v0.16.0pyproject.tomldev deps →ruff==0.16.0(wasruff>=0.4.0)0.16.0 formats Python code blocks inside Markdown by default, so
ruff format .restyled the examples in 19 docs (quote normalisation, comment spacing,
blank lines). No source files changed — all
.pywas already clean under0.16.0. Verified
ruff check .andruff format --check .both pass, andcode-fence counts are unchanged in every doc (no block merged or dropped).
Future ruff bumps are now a deliberate
pre-commit autoupdateplus the twomatching pins, not a silent CI drift.
Unblocks
Every open PR is currently red on
ruff format --check .for the same reason(#102 among them). This should go in first; the others go green on re-run once
it lands on
development.