Skip to content

docs(rules): fix stale 5-plugin claims and make plugin inventory drift-resistant - #557

Merged
wkoutre merged 2 commits into
nextfrom
nickkoutrelakos/infallible-bohr-7d3cd2
Jul 30, 2026
Merged

docs(rules): fix stale 5-plugin claims and make plugin inventory drift-resistant#557
wkoutre merged 2 commits into
nextfrom
nickkoutrelakos/infallible-bohr-7d3cd2

Conversation

@wkoutre

@wkoutre wkoutre commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Problem

.claude/rules/plugin-docs.md is a project rules file, so it loads into every session's context. Its ## The 5 Plugins section listed only 5 of the repo's 8 plugin directories, omitting claude-setup, skill-management, and spec-workflow. Any agent following that rule would skip those three when doing plugin work.

It also contradicted the root CLAUDE.md, which already said 8.

Verified actual inventory (8, and directories match marketplace.json exactly):

claude-setup                development-productivity
development-codebase-tools  skill-management
development-planning        spec-workflow
development-pr-workflow     uniswap-integrations

Approach

Correcting 5 to 8 would drift again on the next plugin addition, so both files now derive the inventory instead of asserting it:

  • Source of truth named: packages/plugins/ directories + the plugins array in .claude-plugin/marketplace.json.
  • Enumeration command given inline (uses find/basename rather than ls -1, which emits . and .. under a common ls alias).
  • Parity check as a one-liner: diff of the directory list against marketplace.json names. Any output means the inventory is inconsistent.
  • Snapshot retained but demoted: the 8 plugins are still listed for at-a-glance context (a rules file should not force a shell-out), but it is dated and readers are told the enumerated output wins and to repair the snapshot on mismatch.

Same de-hardcoding applied to the CLAUDE.md inventory bullet.

Changes

File Change
.claude/rules/plugin-docs.md ## The 5 Plugins -> ## The Plugins with source-of-truth block, enumeration command, parity check, dated snapshot of all 8
.claude/rules/plugin-docs.md "Each of the 5 plugins has its own section" -> "Each plugin"
CLAUDE.md Inventory bullet now points at the source of truth; count is dated and marked subordinate to enumeration
CLAUDE.md Same "Each of the 5 plugins" phrasing fixed in the Notion sync section

Grep sweep

Swept the repo for other hardcoded plugin-count claims. One remaining hit, deliberately left:

  • .plan/DEV-218-implementation.md:17 — "the 27 commands ... are covered by the 5 plugins". This is a point-in-time justification inside a completed migration plan. Rewriting it to 8 would make it wrong about the state it describes.

(packages/plugins/claude-setup/skills/setup-repository/references/boris-best-practices.md:21 matches "The 5 Pillars" — unrelated false positive.)

Verification

  • bunx nx format:write --uncommitted — clean
  • bunx markdownlint-cli2 --fix "**/*.md" — 196 files, 0 errors
  • Pre-commit hooks all green: format, lint, lint-markdown, test, typecheck
  • Ran both documented commands verbatim; the parity check reports the directories and marketplace.json agree
  • Diff touches exactly 2 files, nothing under packages/plugins/, so no plugin version bump applies

.claude/rules/plugin-docs.md is loaded into every session's context, so its
"## The 5 Plugins" section was actively steering plugin work away from
claude-setup, skill-management, and spec-workflow. The repo has had 8 plugins
for some time; the root CLAUDE.md already said 8, so the two contradicted
each other.

Rather than just correcting 5 to 8 (which drifts again on the next addition),
both files now name packages/plugins/ and .claude-plugin/marketplace.json as
the source of truth, give an enumeration command, and state that the
enumerated output wins over the inline snapshot.

- plugin-docs.md: rewrite "The 5 Plugins" as "The Plugins" with a
  source-of-truth block, an enumeration command, a one-line parity check
  between the directories and marketplace.json, and a dated snapshot that
  readers are told to repair on mismatch
- plugin-docs.md: "Each of the 5 plugins has its own section" -> "Each plugin"
- CLAUDE.md: same de-hardcoding for the inventory bullet and the same
  "Each of the 5 plugins" phrasing in the Notion sync section

Left .plan/DEV-218-implementation.md alone: its "5 plugins" is a point-in-time
justification in a completed migration plan, and rewriting it would make it
wrong about the state it describes.

No files under packages/plugins/ changed, so no plugin version bump applies.
@wkoutre
wkoutre requested a review from a team as a code owner July 30, 2026 22:27
@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ai-toolkit-slack-oauth-backend Ready Ready Preview Jul 30, 2026 10:34pm

Request Review

@datadog-official

datadog-official Bot commented Jul 30, 2026

Copy link
Copy Markdown

Pipelines

⚠️ Warnings

🚦 1 Pipeline job failed

Check PR Title | 🔡 Check PR Title   View in Datadog   GitHub Actions

See error No scope found in pull request title: 'docs: fix stale 5-plugin claims and make plugin inventory drift-resistant'.

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: b16f43e | Docs | Datadog PR Page | Give us feedback!

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

🤖 Claude Code Review

Review complete

Review: Documentation parity check for plugin inventory

This is a docs-only PR that replaces hardcoded plugin-count prose ("the 5 plugins", "8 plugins") with a "source of truth = enumerate the directories + marketplace.json" convention, plus two concrete parity-check commands. I verified the substance against the live repo rather than just reading the diff.

Verification performed

Inventory matches (8 plugins). find packages/plugins -mindepth 1 -maxdepth 1 -type d and jq '.plugins[].source' both produce the same 8 entries (claude-setup, development-codebase-tools, development-planning, development-pr-workflow, development-productivity, skill-management, spec-workflow, uniswap-integrations). The dated snapshot in .claude/rules/plugin-docs.md and the list in CLAUDE.md:167 match exactly.

Both parity commands run and exit silently against the current tree:

  • Check 1 (diff of dirs vs normalized source paths) → exit 0, no output.
  • Check 2 (jq name-vs-source-basename mismatch) → exit 0, no output.

The source-not-name rationale is accurate. .github/actions/validate-plugins/action.yml resolves .plugins[i].source into PLUGIN_PATH (lines 64–71) and passes that to scripts/validate-plugin.cjs (line 83). PLUGIN_NAME is only used in echo/::notice:: log output. So source is genuinely the field that decides which directory loads — comparing names alone would check the label, not the pointer. This confirms both the doc's claim and the earlier codex-bot concern.

Assessment

  • The internally-consistent design choice (keep a dated snapshot but declare "enumerated output wins") resolves the tension between the "never trust prose counts" philosophy and having a human-readable list. Handled cleanly.
  • The sub("^\\./"; "") normalization correctly reconciles find output (packages/plugins/foo) with marketplace.json sources (./packages/plugins/foo).
  • No bugs, no security or correctness concerns. The two prior "5 plugins" prose references are both updated at HEAD (.claude/rules/plugin-docs.md:19, CLAUDE.md:368).

No blocking issues. Safe to merge.


💡 Want a fresh review? Add a comment containing @request-claude-review to trigger a new review at any time.

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

📚 Documentation Check ✅

Verdict: Passed

This PR only touches documentation files (.claude/rules/plugin-docs.md, CLAUDE.md) fixing stale "5 plugins" references — no files under packages/plugins/ were modified, so no plugin version bump is required. The content changes are accurate and verified against the live repository state.


Summary

This PR fixes stale "5 plugins" claims in two documentation files and replaces hardcoded plugin counts/lists with drift-resistant guidance (enumerate via find/jq rather than trusting prose counts).

Verification performed:

  • Ran the exact find packages/plugins ... and jq parity checks the PR adds to .claude/rules/plugin-docs.md — both come back silent, confirming the 8-plugin directory list matches .claude-plugin/marketplace.json exactly, and every entry's name agrees with its source.
  • Confirmed the "Snapshot (accurate as of 2026-07-30)" list of 8 plugins in .claude/rules/plugin-docs.md and the "As of 2026-07-30 there are 8 plugins" line in CLAUDE.md both match the actual current plugin directories.
  • Grepped the repo for any other stale "5 plugin(s)" mentions that might have been missed — found none outside the two files already fixed by this PR. The "Current plugins" version table further down in CLAUDE.md was already listing all 8 plugins correctly and didn't need changes.

Plugin version bump check: No files under packages/plugins/<plugin-name>/ were changed — only root-level .claude/rules/plugin-docs.md and CLAUDE.md. The mandatory version-bump rule doesn't apply here, so this is not a blocking issue.

Assessment: The changes are self-consistent, verified accurate against live repo state, and actually improve documentation maintainability by pointing at an enumeration command as source of truth instead of a hardcoded count that will drift again. No missing updates identified.

✨ No Documentation Updates Needed

All documentation appears to be up to date with the code changes.


🤖 Generated by Claude Documentation Validator | Mode: suggest

github-actions[bot]
github-actions Bot previously approved these changes Jul 30, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📋 Review verdict: APPROVE

👆 The main review comment above is the source of truth for this PR review. It is automatically updated on each review cycle, so always refer to it for the most current feedback.

This formal review submission is for the verdict only.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1ebf1cc538

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .claude/rules/plugin-docs.md Outdated

```bash
diff <(find packages/plugins -mindepth 1 -maxdepth 1 -type d -exec basename {} \; | sort) \
<(jq -r '.plugins[].name' .claude-plugin/marketplace.json | sort)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Compare marketplace sources in the parity check

When a plugin is added or renamed and its marketplace entry retains a copied or stale source, this command still succeeds as long as the entry's name matches the directory. The marketplace validator in .github/actions/validate-plugins/action.yml resolves and validates .plugins[].source, so this can falsely certify parity while the marketplace loads another plugin directory and the new plugin remains unreferenced. Compare the normalized source paths or their basenames against the directories, in addition to checking names.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, this is real. Fixed in b16f43e.

Verified the mechanism before changing anything: .github/actions/validate-plugins/action.yml lines 64-71 resolve .plugins[i].source into PLUGIN_PATH and hand that path to scripts/validate-plugin.cjs. name is only used for log output, so source is the field that actually decides which directory loads. Comparing names alone checks the label, not the pointer.

Reproduced the false pass against a scratch fixture (new plugin foo, entry copy-pasted so source still points at skill-management):

=== CURRENT check (names vs dirs) ===
>>> PASSES (falsely certifies parity)

=== PROPOSED check (sources vs dirs) ===
2c2
< packages/plugins/foo
---
> packages/plugins/skill-management
>>> CATCHES IT

Replaced the single check with two:

# 1. Every source resolves to a real plugin directory, and every directory is referenced once.
diff <(find packages/plugins -mindepth 1 -maxdepth 1 -type d | sort) \
     <(jq -r '.plugins[].source | sub("^\\./"; "")' .claude-plugin/marketplace.json | sort)

# 2. Every entry's name agrees with its own source directory.
jq -r '.plugins[] | select((.source | sub("^\\./packages/plugins/"; "")) != .name)
       | "MISMATCH: name=\(.name) source=\(.source)"' .claude-plugin/marketplace.json

Check 1 catches the duplicate-source and dangling-source cases; check 2 catches the name/source disagreement with a direct message. Both are silent against the current marketplace.json (all 8 entries agree), and I ran them verbatim as extracted from the rendered markdown to confirm the jq escapes survive prettier.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independently verified this is fully addressed in b16f43e. I traced the mechanism in .github/actions/validate-plugins/action.yml: PLUGIN_SOURCE is resolved into PLUGIN_PATH (lines 64-71) and that path is what's handed to scripts/validate-plugin.cjs (line 83); PLUGIN_NAME is only used for echo/::notice:: output. So source is indeed the field that decides which directory loads, and the original concern is correct.

Ran both replacement checks verbatim against the current tree — check 1 (sources vs dirs) and check 2 (name vs source basename) both exit 0 with no output, and all 8 entries agree. The duplicate/stale/dangling-source cases the original comment described would now be caught by check 1. Leaving unresolved since there's an active discussion on the thread.

The parity check compared .plugins[].name against the directory names. That
passes even when an entry's `source` is stale or copy-pasted, because `name`
is not the field that determines what loads.

.github/actions/validate-plugins/action.yml:64-71 resolves .plugins[i].source
into PLUGIN_PATH and validates that path; `name` is only used for log output.
So an entry named `foo` whose source still points at `./packages/plugins/
skill-management` makes the validator check skill-management twice while `foo`
goes unreferenced - and the old check certified that as parity.

Reproduced against a scratch fixture: names-vs-dirs passed, sources-vs-dirs
caught it.

Replaced with two checks: (1) resolved source paths against the directories on
disk, (2) each entry's name against its own source basename. Both verified
silent against the current marketplace.json, and executed verbatim as
extracted from the rendered file to confirm the jq escapes survive prettier.
@wkoutre wkoutre changed the title docs: fix stale 5-plugin claims and make plugin inventory drift-resistant docs(rules): fix stale 5-plugin claims and make plugin inventory drift-resistant Jul 30, 2026
@github-actions
github-actions Bot dismissed their stale review July 30, 2026 22:37

Superseded by new review after PR update

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📋 Review verdict: APPROVE

👆 The main review comment above is the source of truth for this PR review. It is automatically updated on each review cycle, so always refer to it for the most current feedback.

This formal review submission is for the verdict only.

@wkoutre
wkoutre merged commit bb873ee into next Jul 30, 2026
29 of 30 checks passed
@wkoutre
wkoutre deleted the nickkoutrelakos/infallible-bohr-7d3cd2 branch July 30, 2026 22:38
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