Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/file-length-enforce.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Enforced the file-length rule now that no Python file is over its limit, deleted its empty baseline, and registered it in the metric tier, the tier for a number crossing a threshold.
14 changes: 5 additions & 9 deletions docs/engineering/skills/file-length.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,8 @@ where that is natural, and keep every one under the limit.
no longer reaches that call, and the test silently stops using its fake.
Patch the module whose code calls the name.

## The baseline

The rule is ratcheted: `rules/baselines/file-length.txt` lists the files that
were over their limit when the rule was added, and the guard tolerates only
those. It fails on an oversized file the baseline doesn't list, and on a listed
file that is now within its limit or no longer exists, so the list only
shrinks. When a split brings a file under its limit, remove its entry and lower
the rule's `baseline.count` in the same pull request. Never add an entry: split
the file instead.
## Enforcement

The rule is enforced, with no baseline of tolerated files: the guard fails on
any measured file over its limit. When a change would take a file over, split
the file by responsibility, as above, in the same pull request.
10 changes: 5 additions & 5 deletions docs/generated/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ Every rule that governs `policyengine-api` is listed here with how it is enforce

| Tier | enforced | ratcheted | advisory | doc-only | Total |
| --- | ---: | ---: | ---: | ---: | ---: |
| mechanical | 59 | 1 | 1 | 13 | 74 |
| metric | 0 | 0 | 0 | 0 | 0 |
| mechanical | 59 | 0 | 1 | 13 | 73 |
| metric | 1 | 0 | 0 | 0 | 1 |
| judgment | 0 | 0 | 0 | 1 | 1 |

**Blocking:** 60 of 75 rules.
Expand Down Expand Up @@ -66,7 +66,7 @@ Every rule that governs `policyengine-api` is listed here with how it is enforce

### Ratcheted (existing violations still tolerated)

- `api.quality.file-length`: 0 remaining in `rules/baselines/file-length.txt`
- None.

### Exceptions and review dates

Expand Down Expand Up @@ -333,7 +333,7 @@ flowchart LR
| `api.quality.command-line-modules-ruff-exemptions` | Application modules that also run as command-line programs (if __name__ == "__main__") may print their output (T201); every other ruff rule applies to them. | mechanical | enforced | yes | ruff per-file ignore of T201 for `policyengine_api/{data/v2/catalog/initialization,data/v2/household_migration_qualification,data/v2/policy_migration_qualification,data/v2/privilege_reconciliation,data/v2/user_association_migration_qualification,worker_spm_release}.py` | `pr.yml:lint` | — |
| `api.quality.command-line-scripts-ruff-exemptions` | Command-line scripts under scripts/ may print their output, run other programs, fetch fixed URLs, stamp today's date and pick random samples (T201, S603, S607, S310, DTZ011, S311); every other ruff rule applies to them. | mechanical | enforced | yes | ruff per-file ignore of DTZ011, S310, S311, S603, S607, T201 for `scripts/**` | `pr.yml:lint` | — |
| `api.quality.environment-variables-load` | Required environment variables and credentials load in a deployed-like environment. | mechanical | enforced | yes | CI job `test_env_vars` | `pr.yml:test_env_vars` | — |
| `api.quality.file-length` | A tracked Python file has at most 800 physical lines, or at most 1,500 if it is test code (a file under a tests or fixtures directory, or a conftest.py); a longer file is split by responsibility into modules, and keeps its public import path. | mechanical | ratcheted | yes | quality guard `file-length` | `pr.yml:quality-guards` | yes |
| `api.quality.file-length` | A tracked Python file has at most 800 physical lines, or at most 1,500 if it is test code (a file under a tests or fixtures directory, or a conftest.py); a longer file is split by responsibility into modules, and keeps its public import path. | metric | enforced | yes | quality guard `file-length` | `pr.yml:quality-guards` | yes |
| `api.quality.mypy-v2` | Shared query models, FastAPI dependencies, v2 routes and services, and the user sign-in and account-deletion libraries pass mypy with untyped definitions disallowed. | mechanical | enforced | yes | mypy | `pr.yml:typecheck-v2` | — |
| `api.quality.ruff-format` | All Python files are formatted with ruff format. | mechanical | enforced | yes | ruff format | `pr.yml:lint` | — |
| `api.quality.ruff-lint` | All Python code passes ruff check with every ruff rule selected (ALL), with no ratchet, except the ignores in pyproject.toml: COM812 and ISC001, which conflict with ruff format, and D203 and D213, which conflict with the kept D211 and D212. | mechanical | enforced | yes | ruff check (ALL) | `pr.yml:lint` | — |
Expand All @@ -356,7 +356,7 @@ flowchart LR
r_api_quality_environment_variables_load("api.quality.environment-variables-load (enforced)")
e_CI_job_test_env_vars["CI job test_env_vars"]
j_CI_pr_yml_test_env_vars["CI pr.yml:test_env_vars"]
r_api_quality_file_length("api.quality.file-length (ratcheted)")
r_api_quality_file_length("api.quality.file-length (enforced)")
e_quality_guard_file_length["quality guard file-length"]
j_CI_pr_yml_quality_guards["CI pr.yml:quality-guards"]
r_api_quality_mypy_v2("api.quality.mypy-v2 (enforced)")
Expand Down
6 changes: 0 additions & 6 deletions rules/baselines/file-length.txt

This file was deleted.

14 changes: 5 additions & 9 deletions rules/registry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1096,10 +1096,8 @@ category = "quality"
statement = "A tracked Python file has at most 800 physical lines, or at most 1,500 if it is test code (a file under a tests or fixtures directory, or a conftest.py); a longer file is split by responsibility into modules, and keeps its public import path."
rationale = "docs/engineering/skills/file-length.md"
scope = ["**/*.py"]
tier = "mechanical"
# Ratcheted with the files over their limit on 2026-10-27, as Anthony Volk
# decided that day; #4053 enforces the rule once the baseline is empty.
status = "ratcheted"
tier = "metric"
status = "enforced"
autofix = false
[rule.enforcer]
kind = "quality-guard"
Expand All @@ -1108,12 +1106,10 @@ name = "file-length"
workflow = ".github/workflows/pr.yml"
job = "quality-guards"
invocation = "run_quality_guards.py"
[rule.baseline]
file = "rules/baselines/file-length.txt"
count = 0
[rule.proof]
bad_fixture = "rules/fixtures/api.quality.file-length/bad_tree.toml"
good_fixture = "rules/fixtures/api.quality.file-length/good_tree.toml"
below_fixture = "rules/fixtures/api.quality.file-length/good_tree.toml"
above_fixture = "rules/fixtures/api.quality.file-length/bad_tree.toml"
threshold = 800
test = "scripts/rules/tests/test_file_length.py::TestFileLengthProof::test_rule_proof_file_length"
workflow = ".github/workflows/pr.yml"
job = "quality-guards"
Expand Down
Loading