Symptom
main is green at 4312bc1, but PR #35 — which changes only AGENTS.md and CONTRIBUTING.md, no Python — fails ci / test with 4 ruff errors in scripts/apply-settings.py, a file it never touches.
Root cause
Two things compound:
requirements-dev.txt has ruff>=0.6. Correct per the >= minimums policy, but it means each CI run may install a newer ruff than the last.
- There is no ruff config in this repo. No
pyproject.toml, ruff.toml, or .ruff.toml. CONTRIBUTING.md line 79 documents select = ["E","F","I","W"], but nothing enforces it, so ruff check . runs with whatever the installed version's default selection happens to be.
Together: the lint gate's rule set can change without any commit to this repo. main isn't green because it's clean — it's green because it hasn't re-run since a newer ruff landed. Its next push will fail too, and this will keep ambushing unrelated PRs.
Why it isn't a one-line fix
Neither candidate state is currently green, so this is a policy decision:
| Configuration |
Result |
| No config (today) |
4 errors — SIM102 ×2, PLW1510, in scripts/apply-settings.py |
select = ["E","F","I","W"] as documented |
8 errors — all E501 line-too-long, in scripts/apply-settings.py and tests/test_apply_settings.py |
Note the documented selection is stricter in a different direction: E501 is in E but outside ruff's default, while SIM102 (flake8-simplify) and PLW1510 (pylint) are outside the documented selection entirely. So the code has never been checked against the policy the docs claim.
Options
- Enforce the documented selection and fix the findings. Add
pyproject.toml with lint.select = ["E","F","I","W"], then wrap the 8 long lines. Docs and reality agree, gate becomes deterministic, and the >= minimums policy stays intact. Recommended — it's the smallest change that makes the documented rule true.
- Adopt the broader selection. Keep
SIM102/PLW1510 (both are reasonable), fix those 3-4 findings, and update CONTRIBUTING.md line 79 to match. More churn, and a deliberate widening of the org-wide standard, since every repo cites this policy.
- Pin ruff exactly. Deterministic, but contradicts the
>= minimums policy in CONTRIBUTING.md § Dependencies, and only defers the problem to the next bump.
Option 1 or 2 also wants a follow-up: this config lives only in .github, while the policy is org-wide. If the intent is that every Python repo enforces the same selection, that belongs in a shared config or at least a documented snippet — worth a separate issue.
Acceptance criteria
Note
PLW1510 (subprocess.run without check) is not a latent bug here — apply-settings.py:145 inspects result.returncode immediately afterwards. Worth stating so whoever fixes it doesn't add check=True and change the control flow.
Symptom
mainis green at4312bc1, but PR #35 — which changes onlyAGENTS.mdandCONTRIBUTING.md, no Python — failsci / testwith 4 ruff errors inscripts/apply-settings.py, a file it never touches.Root cause
Two things compound:
requirements-dev.txthasruff>=0.6. Correct per the>=minimums policy, but it means each CI run may install a newer ruff than the last.pyproject.toml,ruff.toml, or.ruff.toml.CONTRIBUTING.mdline 79 documentsselect = ["E","F","I","W"], but nothing enforces it, soruff check .runs with whatever the installed version's default selection happens to be.Together: the lint gate's rule set can change without any commit to this repo.
mainisn't green because it's clean — it's green because it hasn't re-run since a newer ruff landed. Its next push will fail too, and this will keep ambushing unrelated PRs.Why it isn't a one-line fix
Neither candidate state is currently green, so this is a policy decision:
SIM102×2,PLW1510, inscripts/apply-settings.pyselect = ["E","F","I","W"]as documentedE501line-too-long, inscripts/apply-settings.pyandtests/test_apply_settings.pyNote the documented selection is stricter in a different direction:
E501is inEbut outside ruff's default, whileSIM102(flake8-simplify) andPLW1510(pylint) are outside the documented selection entirely. So the code has never been checked against the policy the docs claim.Options
pyproject.tomlwithlint.select = ["E","F","I","W"], then wrap the 8 long lines. Docs and reality agree, gate becomes deterministic, and the>=minimums policy stays intact. Recommended — it's the smallest change that makes the documented rule true.SIM102/PLW1510(both are reasonable), fix those 3-4 findings, and updateCONTRIBUTING.mdline 79 to match. More churn, and a deliberate widening of the org-wide standard, since every repo cites this policy.>=minimums policy inCONTRIBUTING.md§ Dependencies, and only defers the problem to the next bump.Option 1 or 2 also wants a follow-up: this config lives only in
.github, while the policy is org-wide. If the intent is that every Python repo enforces the same selection, that belongs in a shared config or at least a documented snippet — worth a separate issue.Acceptance criteria
ruff check .is green locally and in CI.CONTRIBUTING.mdline 79 matches what is actually enforced.Note
PLW1510(subprocess.runwithoutcheck) is not a latent bug here —apply-settings.py:145inspectsresult.returncodeimmediately afterwards. Worth stating so whoever fixes it doesn't addcheck=Trueand change the control flow.