Skip to content

Commit bb873ee

Browse files
authored
docs(rules): fix stale 5-plugin claims and make plugin inventory drift-resistant (#557)
* docs: fix stale 5-plugin claims and make inventory drift-resistant .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. * docs: check marketplace source paths, not just names, in parity check 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.
1 parent 7aa69ca commit bb873ee

2 files changed

Lines changed: 43 additions & 10 deletions

File tree

.claude/rules/plugin-docs.md

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ After ANY changes to `packages/plugins/`, you MUST update the Notion Plugin Mark
1616

1717
1. **Plugin inventory changes**: When skills, agents, commands, or MCP servers are added, removed, or renamed
1818
2. **Component counts**: The overview section shows totals for Skills, Agents, and Commands - keep these accurate
19-
3. **Per-plugin sections**: Each of the 5 plugins has its own section listing components - update the relevant section(s)
19+
3. **Per-plugin sections**: Each plugin has its own section listing components - update the relevant section(s)
2020
4. **Descriptions**: Update component descriptions when functionality changes significantly
2121

2222
### 2. Update Plugin CLAUDE.md Files
@@ -36,15 +36,47 @@ Before completing plugin-related work, verify:
3636
- [ ] Plugin `CLAUDE.md` reflects current structure
3737
- [ ] Notion marketplace doc is updated (if inventory changed)
3838

39-
## The 5 Plugins
39+
## The Plugins
4040

41-
For reference, these are the plugin directories:
41+
**Source of truth**: the directories under `packages/plugins/` and the `plugins` array in
42+
`.claude-plugin/marketplace.json`. Never rely on a count written in prose - including the
43+
snapshot below. Enumerate before acting:
4244

43-
1. `packages/plugins/development-planning/`
44-
2. `packages/plugins/development-pr-workflow/`
45-
3. `packages/plugins/development-codebase-tools/`
46-
4. `packages/plugins/development-productivity/`
47-
5. `packages/plugins/uniswap-integrations/`
45+
```bash
46+
find packages/plugins -mindepth 1 -maxdepth 1 -type d -exec basename {} \; | sort
47+
```
48+
49+
The two must always agree: every plugin directory needs a matching `marketplace.json` entry, and
50+
vice versa. Check `source`, not just `name` - `.github/actions/validate-plugins/action.yml`
51+
resolves `.plugins[].source` to decide which directory to load and validate, so a copied or stale
52+
`source` points the marketplace at the wrong directory even when `name` looks right. Two checks:
53+
54+
```bash
55+
# 1. Every source resolves to a real plugin directory, and every directory is referenced once.
56+
diff <(find packages/plugins -mindepth 1 -maxdepth 1 -type d | sort) \
57+
<(jq -r '.plugins[].source | sub("^\\./"; "")' .claude-plugin/marketplace.json | sort)
58+
59+
# 2. Every entry's name agrees with its own source directory.
60+
jq -r '.plugins[] | select((.source | sub("^\\./packages/plugins/"; "")) != .name)
61+
| "MISMATCH: name=\(.name) source=\(.source)"' .claude-plugin/marketplace.json
62+
```
63+
64+
Both silent means the inventory is consistent. Any output means it is not - fix that before
65+
continuing.
66+
67+
**Snapshot** (accurate as of 2026-07-30, verify with the commands above):
68+
69+
1. `packages/plugins/claude-setup/`
70+
2. `packages/plugins/development-codebase-tools/`
71+
3. `packages/plugins/development-planning/`
72+
4. `packages/plugins/development-pr-workflow/`
73+
5. `packages/plugins/development-productivity/`
74+
6. `packages/plugins/skill-management/`
75+
7. `packages/plugins/spec-workflow/`
76+
8. `packages/plugins/uniswap-integrations/`
77+
78+
If the enumerated output above differs from this snapshot, the enumerated output wins - update
79+
this snapshot (and the plugin table in the root `CLAUDE.md`) as part of your change.
4880

4981
## When to Skip Notion Updates
5082

CLAUDE.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ The repository uses a plugin-based architecture where Claude Code capabilities a
163163
- Plugins are stored in `./packages/plugins/<plugin-name>/`
164164
- Each plugin is a self-contained Nx package with its own `package.json`, `project.json`, and `.claude-plugin/plugin.json`
165165
- The `.claude-plugin/marketplace.json` file references plugins via relative paths: `"./packages/plugins/<plugin-name>"`
166-
- There are 8 plugins: claude-setup, development-codebase-tools, development-planning, development-pr-workflow, development-productivity, skill-management, spec-workflow, uniswap-integrations
166+
- The authoritative plugin inventory is the set of directories under `packages/plugins/` and the `plugins` array in `.claude-plugin/marketplace.json` - the two must always agree. Enumerate rather than trusting a count written in prose: `find packages/plugins -mindepth 1 -maxdepth 1 -type d -exec basename {} \; | sort`. See `.claude/rules/plugin-docs.md` for the parity check.
167+
- As of 2026-07-30 there are 8 plugins: claude-setup, development-codebase-tools, development-planning, development-pr-workflow, development-productivity, skill-management, spec-workflow, uniswap-integrations. If the enumerated output differs, it wins - update this list and the table below.
167168

168169
**Plugin Validation:**
169170

@@ -364,7 +365,7 @@ After making any changes to files in this repository, Claude Code MUST:
364365

365366
3. **Keep stats accurate**: The overview section contains counts of total Skills, Agents, and Commands - ensure these numbers stay accurate
366367

367-
4. **Maintain per-plugin sections**: Each of the 5 plugins has its own section listing components - update the relevant section(s) when plugins change
368+
4. **Maintain per-plugin sections**: Each plugin has its own section listing components - update the relevant section(s) when plugins change
368369

369370
This ensures the external documentation stays synchronized with the actual plugin codebase.
370371

0 commit comments

Comments
 (0)