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:
Kjell Tore Guttormsen 2026-06-19 15:13:19 +02:00
commit c6c5f17752
11 changed files with 182 additions and 3 deletions

View file

@ -12,7 +12,7 @@
![Commands](https://img.shields.io/badge/commands-18-green)
![Agents](https://img.shields.io/badge/agents-6-orange)
![Hooks](https://img.shields.io/badge/hooks-4-red)
![Tests](https://img.shields.io/badge/tests-929+-brightgreen)
![Tests](https://img.shields.io/badge/tests-932+-brightgreen)
![License](https://img.shields.io/badge/license-MIT-lightgrey)
A Claude Code plugin that checks configuration health, suggests context-aware improvements, and auto-fixes issues — `CLAUDE.md`, `settings.json`, hooks, rules, MCP servers, `@imports`, and plugins. 13 deterministic scanners across 10 quality areas, context-aware feature recommendations, auto-fix with backup/rollback, a prompt-cache-aware Token Hotspots scanner with optional API-calibrated `--accurate-tokens` mode, plus cache-prefix stability, dead-tool, and cross-plugin collision detection. Zero external dependencies.
@ -341,6 +341,18 @@ By default, `/config-audit` auto-detects scope from your git context. Override w
> predicate lives in `scanners/lib/permission-rules.mjs`; valid forms like `Bash(npm:*)`,
> `WebFetch(domain:host)`, and `Agent(model:opus)` are never flagged.
> **Plugin namespace collisions — the one shadow that actually loses components.**
> Claude Code namespaces every plugin component by the plugin's declared `name`
> (`/name:command`, `name:skill`, agent `name`), so a plugin component can never shadow a
> user- or project-level one — they live in separate namespaces. The real hazard is two
> plugins that declare the **same** `name` in `plugin.json`: their namespaces collapse into
> one, and because the resolution between two installed same-name plugins is undocumented,
> one plugin's commands, skills, and agents are silently shadowed and become unreachable.
> The standalone plugin-health scanner (PLH) flags this at **medium** severity, keying on the
> declared `name` field rather than the folder name (the folder name is irrelevant to the
> namespace). Skill-name overlaps across *different* namespaces are a separate, lower-severity
> concern owned by the COL scanner.
### CLI Tools
All tools work standalone — no Claude Code session needed: