Skip to content

chore(distribution): record claude-code-plugins as a locally-owned ruff consumer - #336

Merged
kyle-sexton merged 1 commit into
mainfrom
chore/335-plugins-ruff-locally-owned
Aug 8, 2026
Merged

chore(distribution): record claude-code-plugins as a locally-owned ruff consumer#336
kyle-sexton merged 1 commit into
mainfrom
chore/335-plugins-ruff-locally-owned

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

Closes #335

Summary

Registers ruff for melodic-software/claude-code-plugins — as
locally-owned, not managed.

What changed relative to the issue

#335 proposed adopting the managed component. This lands the other branch of the
same decision, deliberately: that repo now owns a ruff.toml selecting E4,
E7, E9, and F, and the manifest records that ownership.

The issue's own measurement is the reason. The canonical policy reports 385
findings against that tree; upstream's bare 0.16.0 defaults report 166 (the
issue's 130 predates ~2.8k lines of merged work). Adoption is a migration —
mostly S, ERA, FIX, PTH, ARG, RET, and the TID relative-import ban
meeting a codebase never held to them — and blocking that repo's ruff pin bump
behind a 385-finding migration is what has kept the pin stale in the first
place.

What #335 actually argued for is preserved: the rule set stops being an implicit
default inherited from whatever upstream shipped that week. An explicit select
delivers that property at either size, which is why the sequencing note in the
issue ("adoption should land before, or together with, raising that repo's CI
ruff pin") is satisfied by this shape too.

The locally-owned entry is what keeps the repo-local file from being a second,
unregistered lint policy — the exact objection #335 raises against a repo-local
ruff.toml. The manifest comment records the migration cost and the removal
trigger, so moving to managed later restores the canonical payload with no
archaeology.

Verification

  • distribution/sync-manifest.sh validate --source-root . --manifest distribution/sync-manifest.ymlManifest valid: 34 components, 8 targets.
  • locally-owned is never read, changed, or deleted by the synchronizer
    (distribution/README.md, "Ownership model"), so this entry cannot cause the
    canonical ruff.toml to overwrite the repo's own.

Related

…ff consumer

The repo was absent from the ruff component entirely, which is how it ended up
with an implicit rule set nobody chose — ruff 0.16.0 moved the default from 59
rules to 413 and turned two of its contract suites red on an unmodified main.

It now owns a ruff.toml selecting E4, E7, E9, and F. Registering that as
locally-owned is what keeps it from being a second unregistered lint policy,
and records the trigger for re-adopting the canonical payload as managed.

Closes #335

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KMBm1Ae29KhZmjFxw2wdZ7
@cursor

cursor Bot commented Aug 8, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@claude

claude Bot commented Aug 8, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 30s —— View job


Reviewing PR #336

  • Gather context (diff, manifest schema, ownership model docs)
  • Understand the request (code review)
  • Review distribution/sync-manifest.yml changes for correctness and alignment with CLAUDE.md/REVIEW.md
  • Post findings

Summary

Single-file change: adds ruff to melodic-software/claude-code-plugins's locally-owned list, with a rationale comment. This is a data-only manifest edit — no code paths change.

  • Ownership model compliance: per distribution/README.md's "Ownership model" section, locally-owned is never read, changed, or deleted by the synchronizer, so this entry cannot cause the canonical ruff.toml to overwrite the target's own file, matching the PR's verification claim.
  • Convention consistency: the new - ruff entry keeps the list alphabetically ordered (claude-review-caller, claude-security-review-caller, ruff), matching every other managed/locally-owned list in this file, and the accompanying rationale comment matches the file's existing verbose-documentation style (e.g. the claude-review-caller block above it, medley's locally-owned rationale).
  • Referenced component key: ruff is already a defined top-level component (distribution/sync-manifest.yml line 241), so this is a reference to an existing component, not a new one — consistent with the PR's claimed validate output (34 components, 8 targets; I hand-counted both from the file and they match).
  • Governance: AGENTS.md's cross-doc reconciliation self-review step applies to changes to a normative doc (a file stating a rule another doc cites/assumes, e.g. under conventions/). This PR adds a manifest data entry consistent with the ownership model distribution/README.md already documents — it doesn't restate or narrow a rule — so that step doesn't appear to apply here.
  • I was not able to execute distribution/sync-manifest.sh validate or node directly in this sandbox (both required approval that wasn't available), so I could not independently re-run the validator the PR description cites. The manual checks above (component/target counts, schema shape) are consistent with its claimed output.

Finding (Suggestion / nit)

Confusing double use of "against" in the new rationale comment.

distribution/sync-manifest.yml#L331-L332:

# `ruff`: the canonical policy reports 385 findings against that tree
# against 166 under upstream's bare defaults, so adoption is a migration

"against" is used twice with two different meanings in the same clause — first as "run against [the tree]" (the scan target), then as "compared against 166" (the contrast). A reader has to parse it twice to disambiguate. Since this comment is the durable record of why ruff is locally-owned here (the thing future maintainers read before deciding whether to migrate to managed), a small rewrite would help, e.g.:

ruff: the canonical policy reports 385 findings against that tree, versus 166 under upstream's bare defaults, so adoption is a migration...

No other issues found. The change is small, internally consistent, matches established patterns elsewhere in this file, and is inert to the synchronizer per the documented ownership model.

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown

Claude has reviewed this PR 1 time. The lane skips further automatic reviews after 5; deleting this comment resets the count.

@kyle-sexton
kyle-sexton merged commit 59eb776 into main Aug 8, 2026
43 checks passed
@kyle-sexton
kyle-sexton deleted the chore/335-plugins-ruff-locally-owned branch August 8, 2026 07:14
kyle-sexton added a commit to melodic-software/claude-code-plugins that referenced this pull request Aug 8, 2026
…k the repo (#1991)

Closes #1972

## Summary

The repo had no ruff configuration, so every ruff invocation in it
linted
against whatever upstream's default selection happened to be that
release. Ruff
0.16.0 moved that default from 59 rules to 413 and removed eighteen
`E`/`F`
rules from it — *"E401, E402, E701, E702, E703, E711, E712, E713, E714,
E721,
E731, E741, E742, E743, F403, F405, F406, and F722"*
([0.16.0 release
notes](https://github.com/astral-sh/ruff/releases/tag/0.16.0)).
That single change is behind both failures in #1972: the expansion
brought the
`TRY` category into the default set, and the removals took `E712` out of
it.

## Fix

- **`ruff.toml`** selects `E4`, `E7`, `E9`, and `F` — the pre-0.16
default set.
The rule set is now a decision recorded in the repo rather than one
inherited
from upstream. It is deliberately a floor: raise it toward the managed
policy
  with `extend-select` as each category is cleared.
  Registered as `locally-owned` for this repo in
melodic-software/standards#336 (merged), which is what keeps it from
being a
  second unregistered lint policy.
- **Eval fixtures are excluded.** An audit skill's fixture holds the
defect its
eval asserts on, so linting it fails by construction. The comment
records that
exclusion governs *traversal*: Ruff's settings reference states
*"Typically,
Ruff will lint any paths passed in directly, even if they would
typically be
excluded"*, and that `force-exclude` *"will cause Ruff to respect these
exclusions unequivocally"*. Every invocation here passes directories;
the
ruff-format hook passes a file explicitly and already sets
`--force-exclude`.
  Verified both ways against the fixture path.
- **`ruff-format.test.sh` case 4e selects `E712` in its fixture**
instead of
relying on it being a default rule. A case asserting on one rule's fix
safety
  must name that rule; this is version-agnostic rather than re-pinned.
- **Drops an unused `import stat`** in `python3_alias_probe.py` — a real
`F401`
the pinned set surfaces (line 90 calls `path.stat()`, the method, not
the
  module).

## The TRY004 decision, recorded

#1972 asked for this on its merits rather than by config, so both
halves:

- **On merits: the rule does not fit these sites.** All six raise on a
decoded
  payload or a persisted state file failing an `isinstance` guard —
`babysit_gh.py:603,699,728` on a GraphQL response,
`babysit_lease.py:114`,
`manage_feedback_ledger.py:176`, and `refresh_pr_branch.py:112` on state
files
this code wrote itself. None is a caller passing the wrong type to a
function.

That distinction is the whole argument, so it is worth being explicit
that it
is a judgment rather than something upstream states. TRY004's own
rationale is
"the Python documentation states that `TypeError` should be raised upon
encountering an inappropriate type"; the Python docs' operative sentence
is
*"Passing arguments of the wrong type … should result in a
`TypeError`"*,
which is a caller-contract rule, and they define `RuntimeError` as "an
error
is detected that doesn't fall in any of the other categories." The
broader
  opening sentence ("an operation or function is applied to an object of
inappropriate type") could be read to cover these; the reading taken
here is
that data-integrity validation of a payload is not argument passing.
Anything
catching `RuntimeError` at these sites would change behavior if they
were
  retyped. No `noqa` is needed; the sites stand as written.
- **Separately: `TRY` is not in the selected set**, so they are not
findings
today regardless. Recorded so a future `extend-select = ["TRY"]` knows
the
category was examined and rejected on merits, not merely left
unselected.

## What the prefix selection does not buy

Review raised that `E4`/`E7`/`E9`/`F` are prefixes, so a later release
adding a
rule inside one of those categories enables it here automatically — the
original
wording of this PR overstated the invariant, and the file now says so at
the
selection.

That exposure is real and is closed by version parity rather than by
config. The
pin in `.github/requirements-ci.txt` is held equal to the fleet
inventory
(melodic-software/dotfiles `.chezmoidata/uv-tools.yaml`), so a
newly-added rule
cannot reach CI before a developer or the reverse;
melodic-software/dotfiles#416
adds the check that keeps those two equal, and #1953 is the bump that
makes them
equal today.

Enumerating the exact pre-0.16 codes was the alternative. It trades a
reviewable
statement of intent for a list no reader can evaluate, freezes the
policy against
genuinely useful new correctness rules inside `F`, and still needs the
version
pin to be trustworthy — so it buys the appearance of the invariant
rather than
the invariant.

## Verification

- `ruff check --no-cache --statistics plugins/ scripts/` → **0
findings**
  (166 under bare 0.16.0 defaults before this change).
- `bash plugins/ruff-format/hooks/ruff-format.test.sh` → `PASS=52
FAIL=0`
  (was `PASS=51 FAIL=1`).
- `bash
plugins/source-control/skills/babysit-prs/scripts/engine.test.sh` →
exit 0; `Ran 597 tests ... OK`, ruff section clean (83 findings under
bare
  0.16.0 defaults before this change).
- `bash scripts/run-plugin-tests.sh` → complete sweep of all 170 suites,
exit 0,
`All plugin tests passed or were skipped.` Those two are also the only
suites
that invoke ruff at all (`grep -rl 'ruff check\|ruff format'
--include=*.sh`
finds `plugins/ruff-format/hooks/ruff-format.sh` and `engine.test.sh`),
so no
  other suite could be affected by a lint config.
- The ruff-format fixtures build their own repos under `mktemp -d`,
which
resolves outside the worktree, so they do not inherit this config — case
4e's
pass is real evidence about the fixture's own `select`, not about this
file.
- Local ruff is 0.16.0, matching the fleet pin in `dotfiles`
`.chezmoidata/uv-tools.yaml`, so these runs reproduce what a developer
sees.
  CI still installs 0.15.22; #1953 is what closes that half.

## Related

- melodic-software/standards#336 — registers the `ruff` component as
  `locally-owned` for this repo; closes melodic-software/standards#335.
- Refs #1953 — the Dependabot bump to ruff 0.16.0. This makes it safe
against
the failure that happened: with `select` explicit, the bump cannot
change
  which CATEGORIES run.
- Refs #1871 — resolves ruff from the pin file rather than PATH; it
reads the
  pin dynamically, so it needs no value change once #1953 lands.

---------

Co-authored-by: Claude Opus 5 (1M context) <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.

Adopt the managed ruff component in claude-code-plugins so upstream default churn is not a repo-breaking event

1 participant