T-LQQL-lint-unused-module-level-names
Status: closed/obsoleted · Impact: low · Complexity: small
Auto-generated from a /sdlc:task-work post-mortem. Review and
promote to open/ready before picking up.
The refactor in T-ZU6V-new-scripts-derive-patterns-from-schema
discovered a dead TASK_BASENAME_RE constant in
plugin/scripts/new_milestone.py that was defined at module scope
but never referenced. A lint pass that catches this class of drift
prevents the same kind of dead-but-shaped-correct code from
accumulating across the script set.
ruff is not currently wired up for plugin/scripts/. Function-scope
unused names (F841) would be caught by default ruff configuration,
but module-level unused assignments (F401-adjacent — unused module-
level names that aren’t imports) need a heavier tool: vulture, or
ruff’s RUF set if it grows the rule. The motivating instance:
# plugin/scripts/new_milestone.py (pre-refactor)TASK_BASENAME_RE = re.compile(r"^\d{4}-\d{2}-\d{2}-[a-z0-9]+(?:-[a-z0-9]+)*$")# (compiled but never referenced anywhere in the file)Caught only because the post-mortem author grep’d for _RE constants
during refactor classification.
Proposed
Section titled “Proposed”A pre-commit or quality-check stage that runs vulture (or an
equivalent) against plugin/scripts/ and fails on any module-level
name not referenced anywhere in the file. Add it to
sdlc.yaml’s quality_checks: list so /sdlc:task-work Step 7
catches future occurrences before PR.
Approach
Section titled “Approach”- Pick a runner.
vulture --min-confidence 80 plugin/scripts/is the obvious first try; verify it does not false-positive on names exported via__all__or imported elsewhere. - Add it to
sdlc.yamlunderquality_checks:(or as a separate step if it’s noisy enough to need allowlist tuning). - Run it once across the existing tree, fix or whitelist any findings, lock the baseline.
Files to touch
Section titled “Files to touch”| Location | Kind | Change |
|---|---|---|
sdlc.yaml | new | add the new linter to quality_checks:. |
plugin/scripts/*.py | modify | possible fixups if vulture flags |
(new, optional) plugin/scripts/.vulture-whitelist.py“ | new | if |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1:
vulture plugin/scripts/(or chosen equivalent) runs as part of/sdlc:task-workStep 7 and exits 0 on a clean tree. - AC-2: Re-introducing a dead module-level name (e.g. add an
unreferenced
DEAD_RE = re.compile(...)to any script) causes the quality-check stage to fail.
Out of scope
Section titled “Out of scope”- Linting beyond
plugin/scripts/(entities, validators, skills/<*>) is a separate decision — start small. - Adopting ruff broadly. This task is about catching unused module-level names specifically.
Dependencies
Section titled “Dependencies”- none
Discovery context
Section titled “Discovery context”Spawned by /sdlc:task-work post-mortem of
T-ZU6V-new-scripts-derive-patterns-from-schema on 2026-05-21.
The originating refactor surfaced TASK_BASENAME_RE as defined-but-
never-used in plugin/scripts/new_milestone.py; this task closes
the gap that allowed the dead constant to ship.