Convention: Python Ruff Standard

convention-python-ruff-standard Convention

active convention python

Convention: Python Ruff Standard

Every active Python repo uses Ruff with identical settings: line-length=88, select=["E","F","I","W"]. Parent issue: pal-e-platform#29.

Rule

All active Python repos must configure Ruff with line-length = 88, target-version = "py312", and select = ["E", "F", "I", "W"] in pyproject.toml. No repo-specific line-length overrides or additional rule categories without a convention amendment.

Rationale

Without a single enforced standard, repos drift. Today basketball-api uses line-length=100 with an extra N rule, minio-sdk/minio-api/pal-e-mcp use line-length=120, and pal-e-docs/pal-e-docs-sdk use the correct 88. Agents switching between repos produce inconsistent formatting. CI fails on style in some repos and not others. The 88-character default matches Ruff/Black upstream, the ["E","F","I","W"] set is minimal and high-signal, and the Claude Code hooks enforce mechanically so no review nit is ever about formatting again.

Examples

Correct Incorrect Why
<code>line-length = 88</code> in pyproject.toml <code>line-length = 120</code> in pyproject.toml 88 is the platform standard. No per-repo overrides.
<code>select = ["E", "F", "I", "W"]</code> <code>select = ["E", "F", "I", "N", "W"]</code> N (pep8-naming) is not in the standard set. Adding rules requires a convention amendment.
<code>extend-exclude = ["alembic/versions"]</code> for repos with Alembic <code>extend-exclude = ["tests"]</code> to skip test linting Only Alembic auto-generated migrations are excluded. Tests must pass lint.
Both <code>ruff-format</code> and <code>ruff</code> hooks in <code>.pre-commit-config.yaml</code> Only <code>ruff-format</code> without <code>ruff</code> lint hook Format and lint are both required. Format without lint misses logical errors.
Excluded repo (<code>mcd-tracker-api</code>) left as-is Updating excluded repo to match the standard Archive candidates get no new work. Do not waste tickets on deprecated repos.

Enforcement

Hook-enforced. Two Claude Code hooks in claude-custom fire on every git commit:
Hook File Trigger Behavior
Auto-format <code>hooks/auto-ruff-format.sh</code> PreToolUse on <code>git commit</code> Finds staged <code>.py</code> files, runs <code>ruff format</code>, re-stages. Always exits 0 (never blocks).
Lint gate <code>hooks/check-ruff-before-commit.sh</code> PreToolUse on <code>git commit</code> Runs <code>ruff check .</code> from repo root. Blocks commit with <code>permissionDecision: deny</code> if violations found. Fails open if ruff unavailable or repo is not Python.
Additionally, Woodpecker CI pipelines run ruff check . as a lint step (failure blocks merge), and repos with .pre-commit-config.yaml run ruff on human commits.

pyproject.toml Template

Add this section to every in-scope repo's pyproject.toml:
Optional per-repo addition: extend-exclude = ["alembic/versions"] for repos with Alembic migrations. No other overrides.

pre-commit-config.yaml Template

Pin rev to the latest stable release at adoption time. Bump as a batch across all repos.

Repos In Scope

Repo Current line-length Current select Conformant
<code>pal-e-docs</code> (API) 88 E, F, I, W Yes
<code>pal-e-docs-sdk</code> 88 E, F, I, W Yes
<code>basketball-api</code> 100 E, F, I, N, W No — line-length 100, extra N rule
<code>minio-sdk</code> 120 E, F, W, I No — line-length 120
<code>minio-api</code> 120 E, F, W, I No — line-length 120
<code>pal-e-mcp</code> 120 E, F, W, I No — line-length 120
Four repos require alignment tickets: update pyproject.toml, run ruff format ., fix lint violations, commit.

Repos Excluded

Repo Reason
<code>mcd-tracker-api</code> Archive candidate. No new work.
<code>mcd-tracker-app</code> Archive candidate. No new work.
<code>pal-e-mail</code> Deprecated. No new work.
  • ci-rules — CI conventions including lint steps
  • branch-protection — merge gates that CI lint feeds into
  • agent-spawn-conventions — agent dispatch patterns (hooks fire on every agent commit)
  • convention-validation-pipeline — validation tiers where lint is the first gate