build: upgrade ruff to 0.16.0 - #69
Merged
Merged
Conversation
Owner
Author
|
@codex review for deterministic/RagaliQ ownership, dependency reproducibility, Python 3.14 compatibility, public-clone portability, paid-call safety, golden-fixture integrity, marker correctness, public API compatibility, and unintended behaviour changes |
There was a problem hiding this comment.
馃挕 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 604d555425
鈩癸笍 About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 馃憤.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Upgrades
rufffrom 0.15.21 to 0.16.0. This is a major bump under Ruff's own versioning scheme, not a minor one, and it changes whatruff formatdiscovers.Version delta
ruff>=0.15.21,<0.16to>=0.16.0,<0.17(pyproject.toml:24)Intervening stable releases: 0.15.22 and 0.16.0.
Why "major" for a numerically-minor bump. Ruff's
docs/versioning.mdat tag0.16.0, verbatim:Under "Minor version increases will occur when:", three bullets fire for this exact upgrade: "Support for a new file type is promoted to stable", "Stable rules are added to the default set", and under Formatter, "The stable style changed". The contrast is decisive because the patch list contains "Support for a new file type is added in preview" - which is precisely where Markdown formatting sat at 0.15.x.
Lock regenerated with the second form of
.agents/skills/upgrade-dependencies/SKILL.mdstep 5, not--upgrade:No transitive churn -
ruffships as a self-contained binary wheel:Breaking changes, and which touch this repository
[tool.ruff.lint] selectreplaces the default set rather than extending it, so the expansion cannot reach here. Without that explicitselect,CPY001(missing-copyright-notice) alone would fire on every file.E,W,F,I,B,C4,UPsets.UP019now recognisestyping_extensions.TextUPset - the only stabilised behaviour that is - but the repository contains notyping.Textand does not importtyping_extensionsat all.PLW2901changed in 0.15.22W(pycodestyle warnings), which is a different linter fromPLW(pylint warnings). A substring reading would wrongly flag it.ruff: ignorecomments now honoured at end-of-linecheckandformat --checknow render the proposed fix as a diff--add-ignorepromoted out of previewdocs/configuration.mdCLI-help diff between the tags. Inert here: nothing invokes--add-ignoreor--add-noqa.On the Markdown change. The release note reads:
It is stable, not preview. The strongest evidence is not the release note but a documentation diff across the two tags: at
ref=0.15.21,docs/formatter.mdline 230 carries "This feature is currently only available in preview mode."; atref=0.16.0that single sentence is deleted and the rest of the section is byte-identical. That is the preview-to-stable transition captured directly, and it also explains the 0.15.21 baseline: this repository sets neitherpreview = truenor--preview, so the feature was simply unreachable.The file-count arithmetic closes exactly, with no residual:
10 + 7 = 17. Only
README.mdcontains Python fences, which is why the other six.mdfiles land in the "already formatted" bucket.Prediction recorded before running anything
Recorded from a dry-run through
uvxagainst the unmodified tree, before any file was edited:The prediction, in full:
<0.16ceiling blocks the upgrade first. Since CI runsuv lock --checkand the byte-exactcmp pylock.tomlbefore any hook, raising the ceiling without regenerating both locks fails at that gate and never reaches the formatter - masking the real finding.ruff format --check .fails, exit 1, on exactly one file:README.md. Theask(...)call split across lines 105-107 collapses to a single line, because it fits underline-length = 100.ruff check .passes, and expectedly rather than luckily, for the two independent reasons in the table above.pre-commit run --all-filespasses, locally and in CI, because both Ruff hooks pintypes_or: [python, pyi, jupyter]with nomarkdown. No.mdfile is ever handed to Ruff.What actually happened
Every point above, exactly. The complete formatter diff was one hunk:
The joined line is 95 characters, inside
line-length = 100.The divergence, demonstrated rather than argued
With the locks upgraded to Ruff 0.16.0 and
README.mdstill at itsorigin/maincontent:All twelve hooks pass on a tree the documented command rejects. That is the finding.
Resolution chosen, and the two alternatives rejected
Applied the remediation the README itself documents at lines 437-438:
The reformat is semantically inert, verified by AST comparison rather than by reading:
The golden question string is unchanged and still matches
corpus.py.Two alternatives were considered and not applied:
markdownto both Ruff hooks'types_orso the hooks cover what the README claims to check*.mdtoextend-excludeto opt out of Markdown formattingextend-excludeis the only documented control - Ruff ships no dedicated Markdown-formatting toggle, andextensionmerely maps additional file extensions to Markdown. That negative is part of the answer.Gate results
uv lock --checkpylock.tomluv pip checkpytest eval/ -qpre-commit validate-configpre-commit run --all-filesruff format --check .ruff check .agent-policy-symbolsThe 10-to-17 file count is the one number in this table that moved, and it is the whole upgrade.
Free validation command and result:
The mutation question
Which behaviours of this dependency does the suite exercise? None, in the pytest sense - Ruff is dev tooling with no import-time role, appears in no
[tool.coverage.run] sourceentry, and is imported by no test. Its behaviour is exercised by two surfaces with different scopes, which is the crux:ruff-check/ruff-formathookstypes_or: [python, pyi, jupyter]- 10 filespre-commit run --all-filesruff format --check ./ruff check .(README:423-424)For each breaking change that touches a real call site, which test would have failed?
ruff format --check ., which CI does not run. Demonstrated above: all twelve hooks green, documented command exit 1.ruff-formathook would have caught it, since.pyfiles are intypes_or. Positively confirmed absent: 16 of 17 files were already formatted, and 16 = the 6 Python-free.mdfiles + all 10.pyfiles.E/W/F/I/B/C4/UPruff-checkhook would have caught it. None occurred.--output-formatvalues, nullable JSON fields)The finding, stated plainly. Ruff is pinned once and invoked from one hash-locked venv, which eliminates the classic version-skew failure mode - that part of the design holds. But the hook and the documented CLI command disagree about scope, and CI validates only the narrower of the two. A Ruff release that changes anything outside
python/pyi/jupyteris invisible to every gate this repository runs automatically. This upgrade is exactly that release, and only the manual documented command surfaced it. Per the audit brief, no test was added and no hook scope was widened in this pass; the fix is named above as a maintainer decision.Lock byte-comparison
pylock.tomlinvariants re-checked after the export:Clean-clone transcript
Isolated temp directory, both provider key variables unset and confirmed absent by presence check only, no sibling
../RagaliQreachable, README install commands verbatim with bareuvas documented.The
17 files already formattedline in a clean clone is the durable proof that the new discovery scope is satisfied from a fresh checkout, not only in a developer working tree.The clone-to-green figure is a warm-cache number: the uv cache was already populated (17G), so 4s measures command execution, not first contact. A cold-cache clone would additionally download 54 wheels.
Hidden costs
ruff format .write toREADME.md. A contributor following the documented remediation path now produces an edit to the file that documents the path. That is new behaviour, not a one-off: any future Markdown-embedded Python that does not match Ruff's style will be rewritten by the documented command.line-length = 100. This is the first such case; it will not be the last.<0.17means 0.17.0 will again require a source edit. Given that Ruff's minor number is its breaking-change vehicle, that is the correct shape for the pin, not an inconvenience.