Skip to content

fix(deps): pin vulture, the last unpinned lint tool — and it never ran - #496

Open
ProtocolWarden wants to merge 1 commit into
mainfrom
fix/pin-vulture-and-backlog
Open

fix(deps): pin vulture, the last unpinned lint tool — and it never ran#496
ProtocolWarden wants to merge 1 commit into
mainfrom
fix/pin-vulture-and-backlog

Conversation

@ProtocolWarden

Copy link
Copy Markdown
Owner

Closes the drift class from #492, and turns up something bigger on the way.

The pin

.custodian/config.yaml sets vulture: true, so the audit gate runs it — but pyproject.toml pinned only ruff==0.15.13, ty==0.0.40 and custodian@SHA, while custodian-audit.yml installed vulture separately and unpinned. That is the same setup that let ruff float to 0.16.1 and red-fail main for a week.

vulture==2.16 now lives in [project.optional-dependencies].dev, and the separate install is gone so it arrives via pip install -e ".[dev]" alongside ruff and ty. One source of truth, no version literal left in the workflow.

What verifying it turned up

The audit has never actually run vulture. It reports VULTURE: status=pass count=0. The tool itself disagrees:

vulture src tests --min-confidence=60   ->  exit 3, 621 findings
vulture src --min-confidence=60 tests   ->  exit 2, 0 lines
                                            "unrecognized arguments: tests"

The second is what OC's gate runs. The SHA-pinned Custodian (d6ba8ab) builds [vulture, src_root, --min-confidence=N, tests_root] — the tests positional lands after the flag, vulture's argparse rejects it, and it exits 2 with empty stdout. That adapter version has no returncode guard, so empty stdout is indistinguishable from a clean repo and the pattern is recorded status: pass.

The gate has been green for a tool that never analysed a line. It is the same vacuous-green shape #492 removed || true to prevent — one layer down, and already present.

Why this PR does not fix that

Current Custodian main fixes both halves (every path before the options, plus TOOL_ERROR when the returncode is not 0/3 with empty stdout). So bumping the SHA — worth doing anyway, since main now carries the find_tool fix from ProtocolWarden/Custodian#72 — makes those 621 findings real and reds the audit.

They are LOW/advisory and read as heavily false-positive: test side_effect attributes, pydantic model_config, public-API methods vulture cannot see called. The resolution is a .vulture_whitelist.py, a higher vulture_min_confidence, or vulture: false. That is a decision about what the gate should assert, not one to make inside a pinning change. It is recorded in .console/backlog.md under Up Next.

Pinning does not make vulture run. It makes it deterministic — so when the SHA is bumped, the 621 are a stable number to triage rather than a moving one.

Also

Backfills .console/backlog.md, which CLAUDE.md requires updating after meaningful progress and which had not been touched since #474. Entries added for #491 and #492 alongside this work.

Verification

  • vulture 2.16 / ruff 0.15.13 / ty 0.0.40 all resolve from the dev extras.
  • ruff check . — All checks passed, under the pinned ruff.
  • Audit: 0 findings, exit 0.
  • custodian-audit.yml parses; pre-push gate passed clean on push.

🤖 Generated with Claude Code

Closes the drift class from #492. `.custodian/config.yaml` sets `vulture: true`
so the audit gate runs it, but pyproject pinned only ruff, ty and custodian@SHA,
and custodian-audit.yml installed vulture separately and unpinned — the same
setup that let ruff float to 0.16.1 and red-fail main for a week.

`vulture==2.16` now lives in [project.optional-dependencies].dev, and the
separate install is gone so it arrives via `pip install -e ".[dev]"` with ruff
and ty. One source of truth, no version literal in the workflow.

DISCOVERED WHILE VERIFYING: the audit has never actually run vulture.

  vulture src tests --min-confidence=60   ->  exit 3, 621 findings
  vulture src --min-confidence=60 tests   ->  exit 2, 0 lines
                                              "unrecognized arguments: tests"

The second is what OC's gate runs. The SHA-pinned Custodian (d6ba8ab) builds
[vulture, src_root, --min-confidence=N, tests_root] — the tests positional lands
after the flag, vulture's argparse rejects it, and it exits 2 with empty stdout.
That adapter version has no returncode guard, so empty stdout is
indistinguishable from a clean repo and the pattern is recorded `status: pass`.
The gate has been green for a tool that never analysed a line — the same
vacuous-green shape #492 removed `|| true` to prevent, one layer down.

NOT fixed here, deliberately. Current Custodian main fixes both halves (paths
before options; TOOL_ERROR when returncode is not 0/3 with empty stdout), so
bumping the SHA — worth doing anyway, since main now carries the find_tool fix
from Custodian#72 — makes those 621 findings real and reds the audit. They are
LOW/advisory and read as heavily false-positive (test `side_effect` attributes,
pydantic `model_config`, public-API methods vulture cannot see called), so the
resolution is a .vulture_whitelist.py, a higher vulture_min_confidence, or
vulture: false. That is a decision about what the gate should assert, not one to
make inside a pinning change. Recorded in .console/backlog.md under Up Next.

Pinning does not make vulture run. It makes it deterministic, so when the SHA is
bumped the 621 are a stable number to triage rather than a moving one.

Also backfills .console/backlog.md — CLAUDE.md requires updating it after
meaningful progress and it had not been touched since #474. Entries added for
#491 and #492 alongside this work.

Verified: vulture 2.16 / ruff 0.15.13 / ty 0.0.40 all resolve from the dev
extras; `ruff check .` passes under the pinned ruff; audit 0 findings, exit 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant