| 1 | # Ruff Baseline |
| 2 | |
| 3 | > Issue: jmservera/SquadScope#540 (Phase A baseline) · jmservera/SquadScope#543 (Phase B fixes) |
| 4 | > Epic: jmservera/SquadScope-Coordinator#33 |
| 5 | > Status: **Phase B complete** — `ruff check .` and `ruff format --check .` are clean. |
| 6 | |
| 7 | Ruff is the Python linter/formatter for SquadScope. In Phase A it runs in CI as a |
| 8 | **non-blocking** job (`continue-on-error: true`) that emits GitHub annotations only. |
| 9 | |
| 10 | ## Configuration |
| 11 | |
| 12 | See `[tool.ruff]` in `pyproject.toml`: |
| 13 | |
| 14 | - `line-length = 100` |
| 15 | - `target-version = "py312"` |
| 16 | - Lint rule subset: `E` (pycodestyle errors), `F` (Pyflakes), `I` (import sorting) |
| 17 | - `ignore = ["E501"]` — line length is owned by the **formatter** (`ruff format`), |
| 18 | enforced via `ruff format --check`. The lint-side E501 only fired on un-wrappable |
| 19 | content (long URLs, prose inside triple-quoted string templates and test |
| 20 | fixtures). This mirrors the standard Black/Ruff split. |
| 21 | - Vendored/generated/archived paths excluded (`.venv`, `node_modules`, `public`, |
| 22 | `resources`, `themes`, `scripts/archived`, `.worktrees`) |
| 23 | |
| 24 | ## Phase A snapshot (resolved in Phase B) |
| 25 | |
| 26 | - **Tool:** ruff 0.15.7 |
| 27 | - **Date:** 2026-06-26 |
| 28 | - **Total violations at baseline:** 1235 (129 auto-fixable) |
| 29 | |
| 30 | | Count | Rule | Description | Phase B resolution | |
| 31 | |------:|------|-------------|--------------------| |
| 32 | | 1080 | E501 | line-too-long | `ruff format` wrapped code; residual content lines covered by `ignore` (formatter owns line length) | |
| 33 | | 65 | F401 | unused-import | `ruff check --fix` | |
| 34 | | 62 | I001 | unsorted-imports | `ruff check --fix` | |
| 35 | | 14 | E402 | module-import-not-at-top-of-file | `# noqa: E402` on `sys.path` bootstrap imports | |
| 36 | | 8 | F841 | unused-variable | removed dead assignments | |
| 37 | | 2 | E741 | ambiguous-variable-name | renamed `l` → `ln` | |
| 38 | | 2 | F541 | f-string-missing-placeholders | `ruff check --fix` | |
| 39 | | 1 | F402 | import-shadowed-by-loop-var | renamed loop variable | |
| 40 | | 1 | F821 | undefined-name | defined missing `DEFAULT_SYNTHESIS_MODEL` constant (latent bug) | |
| 41 | |
| 42 | Current state: **`ruff check .` reports no violations.** Regenerate with |
| 43 | `ruff check . --statistics`. |
| 44 | |
| 45 | ## Running locally |
| 46 | |
| 47 | ```bash |
| 48 | # Install (pinned to match CI) |
| 49 | pip install ruff==0.15.7 |
| 50 | |
| 51 | # Lint the repository (report only) |
| 52 | ruff check . |
| 53 | |
| 54 | # Show counts by rule |
| 55 | ruff check . --statistics |
| 56 | |
| 57 | # Auto-fix the safe subset (Phase B work — do not bulk-apply in Phase A) |
| 58 | ruff check . --fix |
| 59 | |
| 60 | # Format check / apply (not enforced in Phase A) |
| 61 | ruff format --check . |
| 62 | ruff format . |
| 63 | ``` |
| 64 | |
| 65 | ## Phase plan |
| 66 | |
| 67 | - **Phase A:** baseline + non-blocking CI annotations. ✅ |
| 68 | - **Phase B:** fix violations — ✅ all categories resolved; `ruff check`/`ruff format --check` clean. |
| 69 | - **Phase C:** pre-push hooks (#544) + blocking CI gate (#545). ✅ `Lint / Ruff` |
| 70 | runs `ruff check` and `ruff format --check` in blocking mode; mark it required. |