feat: add marketplace-ops plugin for pruning stale content#445
Conversation
Adds a new plugin with two commands: - /marketplace-ops:prune [--dry-run]: analyzes the marketplace for stale plugins, commands, and skills using git history and LLM judgment, then opens a PR to remove them - /marketplace-ops:prune-update: processes /save comments on pruning PRs, restores items, and adds them to .pruneprotect permanently Also adds .pruneprotect file for protecting paths from automated pruning. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extracts the plugin-level scoring heuristics into a standalone Python script that outputs structured JSON. The prune command now calls the script first and uses its output as the starting point, reserving LLM judgment for command/skill-level analysis. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New plugins naturally have few commits, low version numbers, and small footprints. These aren't signs of staleness — they're signs of being new. The script now tracks plugin age (first commit date) and only applies commit-count, version, footprint, and README signals to plugins older than 90 days. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove version-at-0.0.x penalty (most plugins stay at 0.0.x regardless of maturity). Add OWNERS file as a -2 bonus — active ownership is a strong positive signal that should protect a plugin from pruning. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace flat +2 for >90 days inactive with a graduated scale: >90d: +1, >120d: +2, >150d: +3, >180d: +4. Older dormant plugins now rank higher than borderline ones. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Companion to score-plugins.py — analyzes individual commands and skills within plugins that survived the plugin-level cut. Commands are scored per markdown file, skills per directory. Supports --plugins filter to scope analysis to specific plugins. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Plugin-level pruning is mechanical: if the script flags it, it goes. No LLM override. LLM judgment only applies at the item level within surviving plugins. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds a new Marketplace Ops plugin (v0.1.2): registration and catalog entries, a .pruneprotect allowlist, docs and command specs for prune and prune-update, and two CLI scoring scripts (score-plugins.py, score-items.py) for identifying and operating on stale marketplace plugins, commands, and skills. ChangesMarketplace Ops Plugin
Sequence DiagramsequenceDiagram
participant Operator
participant CLI as marketplace-ops CLI
participant Repo as Git Repo
participant LLM
participant GitHub
Operator->>CLI: run score-plugins / score-items (--dry-run?)
CLI->>Repo: read .pruneprotect, plugin files, git history
Repo-->>CLI: file & git metadata (commits, dates, sizes)
CLI->>CLI: compute scores, detect batch dates
CLI->>LLM: (optional) produce item review payload / prompt
LLM-->>CLI: review output / decisions
CLI->>GitHub: (full run) create branch, commit removals, push fork
GitHub-->>Operator: opens PR with removal manifest
Operator->>GitHub: comment with /save or /drop directives
GitHub-->>CLI: (prune-update) PR comments fetched
CLI->>Repo: restore saved paths, update .pruneprotect, commit & push
CLI->>GitHub: update PR body and post result comment
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (2 errors, 1 warning)
✅ Passed checks (7 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
The CI version-check workflow requires a version bump for any plugin with code changes. The prune command now bumps patch versions for surviving plugins that had commands or skills removed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (3)
plugins/marketplace-ops/README.md (1)
21-27: ⚡ Quick winAdd a language tag to the fenced example block to satisfy markdownlint.
Line 21 starts an unlabeled fence; use
text(orbash) to clear MD040.Suggested patch
-``` +```text # Canonical example plugin plugins/hello-world/ # Saved by `@username` on 2026-05-05 plugins/foo/</details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@plugins/marketplace-ops/README.mdaround lines 21 - 27, Add a language tag
to the fenced code block in the README example to satisfy markdownlint MD040:
update the opening triple-backtick that precedes the block containing "Canonical
example plugin" / "plugins/hello-world/" to include a language (e.g., changetotext or ```bash) so the fenced block is labeled; ensure the closing
triple-backtick remains unchanged.</details> </blockquote></details> <details> <summary>plugins/marketplace-ops/commands/prune-update.md (1)</summary><blockquote> `10-12`: _⚡ Quick win_ **Add language identifiers to unlabeled fenced code blocks.** These fences trigger MD040; labeling them (`text`/`bash`) keeps docs lint-clean. Also applies to: 82-85, 127-129, 133-135, 167-169, 172-174 <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@plugins/marketplace-ops/commands/prune-update.mdaround lines 10 - 12,
Several fenced code blocks in the prune-update docs are unlabeled (e.g., the
block containing "/marketplace-ops:prune-update [PR number or URL]") which
triggers MD040; update each unlabeled triple-backtick fence to include an
appropriate language identifier (bash for shell/CLI examples, text for plain
output/snippets). Locate the command/example fences (including the other similar
examples in the file) and changetobash or ```text as appropriate so
lint no longer flags MD040.</details> </blockquote></details> <details> <summary>plugins/marketplace-ops/commands/prune.md (1)</summary><blockquote> `10-12`: _⚡ Quick win_ **Add language tags to unlabeled code fences for markdownlint compliance.** These blocks should be tagged (`text`/`bash`) to satisfy MD040 consistently. Also applies to: 200-203, 228-230, 233-235 <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@plugins/marketplace-ops/commands/prune.mdaround lines 10 - 12, The
unlabeled fenced code blocks (for example the snippet containing
"/marketplace-ops:prune [--dry-run]") must include a language tag (e.g.,bash ortext) to satisfy markdownlint MD040; update each openingtobash
(or ```text for plain output blocks) for the affected fences and apply the same
change to the other unlabeled blocks mentioned (around the sections containing
the command examples at the later ranges) so all code fences are consistently
labeled.</details> </blockquote></details> </blockquote></details> <details> <summary>🤖 Prompt for all review comments with AI agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.Inline comments:
In@plugins/marketplace-ops/commands/prune-update.md:
- Around line 38-52: When collecting
/save <path>directives from issue and
review comments, only accept and persist paths into .pruneprotect if the
commenter is a trusted repository participant: for each matched commenter call
the GitHub collaborators/permission API (e.g., GET
/repos/{owner}/{repo}/collaborators/{username}/permission via gh api) and verify
their permission/association is one of OWNER, MEMBER or COLLABORATOR (or matches
an explicit allowlist); ignore and log any/savefrom other associations and
do not write those paths to .pruneprotect. Ensure deduplication still runs only
on the filtered list and add a clear message when untrusted directives are
skipped.In
@plugins/marketplace-ops/commands/prune.md:
- Around line 136-138: The current branch naming in prune.md uses a date-only
suffix (prune/$(date +%Y%m%d)) which can collide on multiple runs the same day;
change the branch name generation to include a high-resolution timestamp or
unique token (for example append hours/minutes/seconds or epoch seconds) so each
run produces a unique branch name — update the git checkout -b branch creation
example in prune.md to use date with time (e.g., include %H%M%S or %s) or a
random suffix to avoid collisions.In
@plugins/marketplace-ops/scripts/score-items.py:
- Around line 56-61: The git(...) helper currently swallows failures by
returning empty stdout even when git returns a non-zero exit code; update the
subprocess.run call in git to fail fast: use check=True (or inspect
result.returncode) and raise an exception that includes result.stderr (and
stdout) so callers won't continue with empty data; also catch and re-raise a
clearer error for subprocess.TimeoutExpired with context. Ensure the error
message references the repo_root and the git args for easier debugging.- Around line 49-53: The is_protected function overmatches because it uses raw
startswith; change it to perform segment-safe matching: for each prefix in the
protected list, normalize both path and prefix (remove trailing slashes), split
each into segments and consider the prefix a match only if the path segments
start with the exact sequence of prefix segments (or the normalized path equals
the normalized prefix). Update the is_protected function to use these normalized
segment comparisons (referencing is_protected, path, and protected) so sibling
paths like plugins/foo do not match plugins/foobar.- Around line 130-141: The scoring logic for inactivity (variable days_inactive)
currently uses strict greater-than comparisons and thus misses exact boundary
days (90,120,150,180); update the comparisons in the block that adjusts score
and appends to reasons so each condition uses >= instead of > (preserve the
existing ordering and increments to score and messages that reference
days_inactive and the thresholds) to ensure boundary-day commits receive the
intended score.In
@plugins/marketplace-ops/scripts/score-plugins.py:
- Around line 55-60: The git() helper currently swallows failures by returning
empty stdout on errors/timeouts; update git(repo_root, *args) to surface
failures by using subprocess.run with check=True (or call
result.check_returncode()) and include stderr in any raised exception, and add a
try/except to catch TimeoutExpired and re-raise or raise a descriptive error
including the command, repo_root, timeout, and stderr so callers of git() cannot
proceed on silent failures.- Around line 177-188: The inactivity-tier comparisons currently use strict
greater-than, so plugins with days_inactive equal to 90,120,150,180 are not
scored into the higher tier; update the conditions in the scoring block that
adjusts score and appends to reasons to use greater-than-or-equal (>=) for 90,
120, 150, and 180 (i.e., change each ">" to ">=" for the comparisons against
those thresholds for the days_inactive variable where score is incremented and
reasons appended).- Around line 48-52: The current is_protected(path, protected) uses
path.startswith(prefix) which incorrectly treats sibling prefixes (e.g., "foo"
vs "foobar") as matches; change the logic to compare normalized,
trailing-slash-stripped values and only accept exact matches or prefix + '/'
directory boundaries. Specifically, inside is_protected normalize both values (p
= path.rstrip('/') and pref = prefix.rstrip('/')) and return True only if p ==
pref or p.startswith(pref + '/'); keep the same function name is_protected and
parameters path, protected.
Nitpick comments:
In@plugins/marketplace-ops/commands/prune-update.md:
- Around line 10-12: Several fenced code blocks in the prune-update docs are
unlabeled (e.g., the block containing "/marketplace-ops:prune-update [PR number
or URL]") which triggers MD040; update each unlabeled triple-backtick fence to
include an appropriate language identifier (bash for shell/CLI examples, text
for plain output/snippets). Locate the command/example fences (including the
other similar examples in the file) and changetobash or ```text as
appropriate so lint no longer flags MD040.In
@plugins/marketplace-ops/commands/prune.md:
- Around line 10-12: The unlabeled fenced code blocks (for example the snippet
containing "/marketplace-ops:prune [--dry-run]") must include a language tag
(e.g.,bash ortext) to satisfy markdownlint MD040; update each opening
tobash (or ```text for plain output blocks) for the affected fences and
apply the same change to the other unlabeled blocks mentioned (around the
sections containing the command examples at the later ranges) so all code fences
are consistently labeled.In
@plugins/marketplace-ops/README.md:
- Around line 21-27: Add a language tag to the fenced code block in the README
example to satisfy markdownlint MD040: update the opening triple-backtick that
precedes the block containing "Canonical example plugin" /
"plugins/hello-world/" to include a language (e.g., changetotext orremains unchanged.🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID:
b40fb766-2d36-4a5e-bc50-69da31c0759a📒 Files selected for processing (10)
.claude-plugin/marketplace.json.pruneprotectPLUGINS.mddocs/data.jsonplugins/marketplace-ops/.claude-plugin/plugin.jsonplugins/marketplace-ops/README.mdplugins/marketplace-ops/commands/prune-update.mdplugins/marketplace-ops/commands/prune.mdplugins/marketplace-ops/scripts/score-items.pyplugins/marketplace-ops/scripts/score-plugins.py
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
plugins/marketplace-ops/commands/prune.md (1)
136-138:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUse a unique prune branch name to avoid same-day collisions.
Line 137 uses a date-only branch suffix, so a second run on the same day can fail on branch creation.
Suggested patch
-git checkout -b prune/$(date +%Y%m%d) main +git checkout -b "prune/$(date +%Y%m%d-%H%M%S)" main🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@plugins/marketplace-ops/commands/prune.md` around lines 136 - 138, The branch creation snippet using the git command "git checkout -b prune/$(date +%Y%m%d) main" can collide when run more than once per day; update that command to append a unique suffix (e.g., a high-resolution timestamp like hours/minutes/seconds or a random/PID-based token) so the branch name is unique on repeat runs and avoid same-day collisions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@plugins/marketplace-ops/commands/prune.md`:
- Around line 10-12: In plugins/marketplace-ops/commands/prune.md update the
unlabeled fenced code blocks to include a language label (e.g., text or bash)
and avoid nested triple-backtick clashes: change the top snippet containing
"/marketplace-ops:prune [--dry-run]" to use ```text, change the saved paths
snippet containing "/save plugins/foo/" and "/save plugins/bar/commands/baz.md"
to use ~~~text (or otherwise use tildes for the inner block) and update the
PR-body inner fenced snippets that contain "/marketplace-ops:prune --dry-run"
and "/marketplace-ops:prune" to ```text so markdownlint MD040 is satisfied and
the outer bash block rendering is preserved.
- Around line 202-220: Update the PR body placeholders that incorrectly
reference "Step 7": replace the literal placeholder "{paste the table from Step
7}" with "{paste the table from Step 5}", replace "{paste protected list from
Step 7}" with "{paste protected list from Step 5}", and ensure any other
occurrences that point to Step 7 (e.g., the two placeholders at the top and
bottom of the snippet) are changed to reference Step 5 so the artifacts match
the actual production step.
---
Duplicate comments:
In `@plugins/marketplace-ops/commands/prune.md`:
- Around line 136-138: The branch creation snippet using the git command "git
checkout -b prune/$(date +%Y%m%d) main" can collide when run more than once per
day; update that command to append a unique suffix (e.g., a high-resolution
timestamp like hours/minutes/seconds or a random/PID-based token) so the branch
name is unique on repeat runs and avoid same-day collisions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 0bb4cdb0-1338-424e-b6e2-acc6e6f4907e
📒 Files selected for processing (4)
.claude-plugin/marketplace.jsondocs/data.jsonplugins/marketplace-ops/.claude-plugin/plugin.jsonplugins/marketplace-ops/commands/prune.md
✅ Files skipped from review due to trivial changes (1)
- plugins/marketplace-ops/.claude-plugin/plugin.json
🚧 Files skipped from review as they are similar to previous changes (1)
- .claude-plugin/marketplace.json
- Use segment-safe path matching in is_protected() to prevent plugins/foo/ from matching plugins/foobar/ - Fail fast on git command errors instead of silently continuing - Use >= instead of > for inactivity tier thresholds - Add timestamp to prune branch name to avoid same-day collisions - Fix step references in PR body template - Add language labels to fenced code blocks - Only accept /save from trusted PR participants (OWNER/MEMBER/COLLABORATOR) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
this is nice! curious if you thought about how would we handle adding /save but then want it to drop it in the same PR? |
Adds /drop as the inverse of /save on pruning PRs. Supports two modes: undoing a previous /save (re-removes files, cleans .pruneprotect) and manually adding new removals not in the original manifest. Includes --force flag to override .pruneprotect and last-writer-wins conflict resolution when both /save and /drop target the same path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@plugins/marketplace-ops/commands/prune-update.md`:
- Around line 59-60: The parser currently only recognizes `/save <path>` and
`/drop <path>` and must be extended to accept an optional `--force` flag (i.e.,
`/drop --force <path>`); update the directive parsing routine (the function that
matches comment bodies for `/save` and `/drop`) to allow an optional `--force`
token, ensure the extracted directive object includes a boolean `force` field,
and make sure the trusted-author check (author_association in
OWNER/MEMBER/COLLABORATOR) and the warning message logic also handle forced
drops so `--force` directives are actionable; apply the same change to the other
parser occurrences referenced in the spec (the other directive matching sites
mentioned at lines 74-75 and 239-243).
- Around line 120-123: The Markdown file contains unlabeled fenced code blocks
that trigger markdownlint MD040; update each triple-backtick fence in
plugins/marketplace-ops/commands/prune-update.md to include the language tag
"text" (e.g., change ``` to ```text) for the blocks that include the snippet
beginning "# Saved by `@username` on 2026-05-05" and the subsequent table rows
(the blocks showing "| plugin | `plugins/foo/` ..." and the other table lines),
and also apply the same change to the other occurrences called out (around the
blocks at the other ranges noted such as 169-171, 175-177, 181-183, 187-189) so
all unlabeled fences become ```text.
- Around line 49-57: Update the gh api fetches for issue and PR review comments
to include created_at and id in the jq output so comments can be
deterministically ordered; modify the two jq expressions (currently '.[] |
{author: .user.login, association: .author_association, body: .body}') to also
emit .created_at and .id. Then update the explanatory text at the "latest
comment wins" line (referenced near line 66) to state that deduplication uses
created_at (and id as a tiebreaker) to sort comments so the newest comment for a
given path wins.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 693b6ff1-8776-48a4-b363-ddbca45dc429
📒 Files selected for processing (6)
.claude-plugin/marketplace.jsonPLUGINS.mddocs/data.jsonplugins/marketplace-ops/.claude-plugin/plugin.jsonplugins/marketplace-ops/commands/prune-update.mdplugins/marketplace-ops/commands/prune.md
🚧 Files skipped from review as they are similar to previous changes (1)
- docs/data.json
| ``` | ||
| # Saved by @username on 2026-05-05 | ||
| plugins/foo/ | ||
| ``` |
There was a problem hiding this comment.
Add language tags to fenced blocks to satisfy markdownlint (MD040).
Several fenced snippets are unlabeled; adding text preserves rendering and removes lint noise.
Proposed doc patch
-```
+```text
# Saved by `@username` on 2026-05-05
plugins/foo/- +text
| plugin | plugins/foo/ | No commits in 7 months, v0.0.1 |
-```
+```text
| ~~plugin~~ | ~~`plugins/foo/`~~ | ~~SAVED by `@username`~~ |
- +text
| plugin | plugins/foo/ | Dropped by @username |
-```
+```text
| command | `plugins/bar/commands/baz.md` | Manually dropped by `@username` |
</details>
Also applies to: 169-171, 175-177, 181-183, 187-189
<details>
<summary>🧰 Tools</summary>
<details>
<summary>🪛 markdownlint-cli2 (0.22.1)</summary>
[warning] 120-120: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
</details>
</details>
<details>
<summary>🤖 Prompt for AI Agents</summary>
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @plugins/marketplace-ops/commands/prune-update.md around lines 120 - 123, The
Markdown file contains unlabeled fenced code blocks that trigger markdownlint
MD040; update each triple-backtick fence in
plugins/marketplace-ops/commands/prune-update.md to include the language tag
"text" (e.g., change totext) for the blocks that include the snippet
beginning "# Saved by @username on 2026-05-05" and the subsequent table rows
(the blocks showing "| plugin | plugins/foo/ ..." and the other table lines),
and also apply the same change to the other occurrences called out (around the
blocks at the other ranges noted such as 169-171, 175-177, 181-183, 187-189) so
all unlabeled fences become ```text.
</details>
<!-- fingerprinting:phantom:poseidon:hawk -->
<!-- d98c2f50 -->
<!-- This is an auto-generated comment by CodeRabbit -->
That makes sense to add: #446 (comment) |
Add id and created_at to comment API queries for deterministic ordering, parse optional --force flag on /drop directives, and clarify last-writer-wins deduplication logic. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
plugins/marketplace-ops/commands/prune-update.md (2)
117-128:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd language tag to .pruneprotect example (MD040).
The fenced code block at line 121 also lacks a language specifier.
🔧 Proposed fix
For `/save` items: append each saved path to `.pruneprotect` with a comment indicating who requested the save: -``` +```text # Saved by `@username` on 2026-05-05 plugins/foo/</details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@plugins/marketplace-ops/commands/prune-update.mdaround lines 117 - 128, The
fenced code block in "Step 7: Update .pruneprotect" is missing a language tag
(MD040); update the example fenced block that shows the .pruneprotect entry by
adding a language identifier (e.g., use ```text) to the opening fence so the
snippet becomes a labeled text block; locate the block under the Step 7 heading
where the example shows "# Saved by@usernameon 2026-05-05" and "plugins/foo/"
and add the language tag to that fenced code block.</details> --- `161-195`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Add language tags to fenced code blocks (MD040).** The fenced code blocks at lines 170, 176, 182, and 188 lack language specifiers, triggering markdownlint MD040 warnings. This is the same issue raised in previous reviews but not yet addressed. <details> <summary>🔧 Proposed fix</summary> ```diff **For `/save` paths:** In the removal manifest table, find the rows for saved paths and apply strikethrough with a `[SAVED]` tag. For example, change: -``` +```text | plugin | `plugins/foo/` | No commits in 7 months, v0.0.1 | ``` To: -``` +```text | ~~plugin~~ | ~~`plugins/foo/`~~ | ~~SAVED by `@username`~~ | ``` **For `/drop` paths that undo a save:** Remove the strikethrough and `[SAVED]` tag, restoring the row to its original state with the original reason (if available from git history of the PR body), or use a new reason: -``` +```text | plugin | `plugins/foo/` | Dropped by `@username` | ``` **For new `/drop` paths:** Add a new row to the manifest table: -``` +```text | command | `plugins/bar/commands/baz.md` | Manually dropped by `@username` | ``` ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@plugins/marketplace-ops/commands/prune-update.mdaround lines 161 - 195, The
markdown examples in Step 10 contain fenced code blocks missing language tags
(MD040); update each example fence (the three table examples and the final code
fence around the gh pr edit snippet) to use a language tag such as "text" (i.e.,
changetotext) so lint stops flagging MD040—look for the fenced blocks
showing the table rows (the examples with | plugin ... and |plugin... and
| command ...) and the final ``` block around gh pr edit and add the language
specifier.</details> </blockquote></details> </blockquote></details> <details> <summary>🤖 Prompt for all review comments with AI agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.Inline comments:
In@plugins/marketplace-ops/commands/prune-update.md:
- Around line 85-98: Replace the ambiguous {upstream_remote} placeholder in Step
5 with a concrete instruction: explain that implementers should set an
upstream_remote variable (e.g., name it upstream_remote) and show how to
determine it for their workflow (common values: "upstream" when working from a
fork, "origin" when working directly in the main repo), then update the git
checkout example to use that variable (references: upstream_remote and
base_branch) and add a short note telling users to confirm their remotes with
git remote -v before running the restore step.
Duplicate comments:
In@plugins/marketplace-ops/commands/prune-update.md:
- Around line 117-128: The fenced code block in "Step 7: Update .pruneprotect"
is missing a language tag (MD040); update the example fenced block that shows
the .pruneprotect entry by adding a language identifier (e.g., use ```text) to
the opening fence so the snippet becomes a labeled text block; locate the block
under the Step 7 heading where the example shows "# Saved by@usernameon
2026-05-05" and "plugins/foo/" and add the language tag to that fenced code
block.- Around line 161-195: The markdown examples in Step 10 contain fenced code
blocks missing language tags (MD040); update each example fence (the three table
examples and the final code fence around the gh pr edit snippet) to use a
language tag such as "text" (i.e., changetotext) so lint stops flagging
MD040—look for the fenced blocks showing the table rows (the examples with |
plugin ... and |plugin... and | command ...) and the final ``` block
around gh pr edit and add the language specifier.</details> <details> <summary>🪄 Autofix (Beta)</summary> Fix all unresolved CodeRabbit comments on this PR: - [ ] <!-- {"checkboxId": "4b0d0e0a-96d7-4f10-b296-3a18ea78f0b9"} --> Push a commit to this branch (recommended) - [ ] <!-- {"checkboxId": "ff5b1114-7d8c-49e6-8ac1-43f82af23a33"} --> Create a new PR with the fixes </details> --- <details> <summary>ℹ️ Review info</summary> <details> <summary>⚙️ Run configuration</summary> **Configuration used**: Path: .coderabbit.yaml **Review profile**: CHILL **Plan**: Enterprise **Run ID**: `27a88e00-56c4-443a-beae-50e2a5d8574f` </details> <details> <summary>📥 Commits</summary> Reviewing files that changed from the base of the PR and between 0e59ccddcadce5cc57ebe601afee7f0131b399f7 and 7e047a675e219fb750db39b030fee7504dc9bc67. </details> <details> <summary>📒 Files selected for processing (1)</summary> * `plugins/marketplace-ops/commands/prune-update.md` </details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: bryan-cox, stbenjam The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Summary
marketplace-opsplugin with two commands:/marketplace-ops:prune(analyze and open a PR removing stale plugins/commands/skills) and/marketplace-ops:prune-update(process/savecomments on pruning PRs)score-plugins.pyfor plugin-level andscore-items.pyfor command/skill-level analysis) that use git metadata to identify inactive content.pruneprotectfile for permanently protecting plugins from automated removalDesign
Plugin-level scoring signals:
Plugins younger than 90 days skip all maturity signals. Batch-update commits are detected and excluded from "last commit" calculations.
Item-level scoring runs on surviving plugins, flagging individual commands/skills by inactivity and size. The LLM then applies judgment (e.g., does this command require AI reasoning?).
/saveworkflow: Comment/save <path>on a pruning PR, then run/marketplace-ops:prune-updateto restore the item and add it to.pruneprotectpermanently.Test plan
python3 plugins/marketplace-ops/scripts/score-plugins.pyand verify outputpython3 plugins/marketplace-ops/scripts/score-items.pyand verify output/marketplace-ops:prune --dry-runand verify reportmake lintto validate plugin structure🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
Chores