feat(plh): flag plugin namespace collisions (same declared name)
Two plugins that declare the same `name` in plugin.json collapse into one component namespace (/name:command, name:skill, agent "name"). Resolution between two installed same-name plugins is undocumented, so one plugin's commands/skills/agents are silently shadowed and unreachable. PLH now flags this at medium severity, keying on the declared `name` (not folder basename, via new declaredName on scanSinglePlugin) with a COL-shaped details.namespaces payload. Name-less plugins are excluded from the collision map. Search-first (code.claude.com/docs/en/plugins): plugin components are namespaced by the declared name, so a plugin component can never shadow a user/project one — only a same-name collision loses components. This refutes the original "plugin vs user vs project shadowing" framing in the backlog. Adds humanizer pattern, fixture (duplicate-plugin-name: 2 colliding + 2 name-less), and 3 tests. Suite 929->932. self-audit A 97 / A 100, scanners 13.
This commit is contained in:
parent
d678765fad
commit
c6c5f17752
11 changed files with 182 additions and 3 deletions
23
CLAUDE.md
23
CLAUDE.md
|
|
@ -109,7 +109,7 @@ Default: auto-detects scope from git context. Override with `/config-audit full|
|
|||
node --test 'tests/**/*.test.mjs'
|
||||
```
|
||||
|
||||
929 tests across 56 test files (17 lib + 29 scanner + 1 hook + 1 agent + 3 commands + 1 knowledge + 4 top-level). Test fixtures in `tests/fixtures/`. Top-level humanizer tests: `json-backcompat.test.mjs`, `raw-backcompat.test.mjs`, `scenario-read-test.test.mjs`, `snapshot-default-output.test.mjs`.
|
||||
932 tests across 56 test files (17 lib + 29 scanner + 1 hook + 1 agent + 3 commands + 1 knowledge + 4 top-level). Test fixtures in `tests/fixtures/`. Top-level humanizer tests: `json-backcompat.test.mjs`, `raw-backcompat.test.mjs`, `scenario-read-test.test.mjs`, `snapshot-default-output.test.mjs`.
|
||||
|
||||
### CML scanner — context-window-scaled char budget
|
||||
|
||||
|
|
@ -151,6 +151,27 @@ Beyond deny/allow overlap, the DIS scanner now also flags:
|
|||
These predicates live in `scanners/lib/permission-rules.mjs` (shared with the CNF
|
||||
conflict-detector). Behavior verified against `code.claude.com/docs/en/permissions`.
|
||||
|
||||
### PLH scanner — plugin namespace collision
|
||||
|
||||
The standalone PLH scanner (cross-plugin checks in `scan()`) flags **plugin namespace
|
||||
collisions**: two or more discovered plugins that declare the **same `name`** in
|
||||
`plugin.json`. The search-first finding that shaped this check: Claude Code namespaces
|
||||
every plugin component by the declared `name` — `/name:command`, `name:skill`, agent
|
||||
`name` (verified against `code.claude.com/docs/en/plugins`, and observable in any session's
|
||||
namespaced skill listing). A plugin component therefore can **never** shadow a user- or
|
||||
project-level one; the only shadow that loses components is a same-`name` collision, where
|
||||
the namespaces collapse into one and CC must pick a winner. Resolution between two installed
|
||||
same-name plugins is **undocumented**, so the loser's commands/skills/agents go silently
|
||||
unreachable — hence severity **MEDIUM** (dead config), `category: 'plugin-hygiene'`, with a
|
||||
COL-shaped `details.namespaces` payload (`{ source: 'plugin:<dir>', name, path }`).
|
||||
|
||||
Two design notes: (1) the check keys on the declared `name` field, **not** `basename(dir)` —
|
||||
the folder name is irrelevant to the namespace; `scanSinglePlugin` now returns `declaredName`
|
||||
for this. (2) Name-less plugins are excluded from the collision map (they are flagged by the
|
||||
missing-field check and must never group on an `undefined` key). The pre-existing cross-plugin
|
||||
**command**-name conflict check still uses the folder basename and over-reports given
|
||||
namespacing — left as a separate backlog candidate, intentionally out of scope here.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Session directories accumulate — use `/config-audit cleanup` to manage
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue