From d951f7dc68cff96fd077c9775b7346ef4c542d47 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sun, 1 Nov 2026 11:39:14 -0500 Subject: [PATCH 1/2] fix(user-interface): name the settings source so design never searches its plugin root When detect cannot run (no shell, as in an eval run, or no node), design now takes its settings from reference/defaults.yaml by path, and the animation catalog names both sources of its resolved animation: config. Eval runs had searched the plugin root for those values, and the sandbox denied them. Closes #11980 Co-Authored-By: Claude Opus 5.5 --- .../fix-11980-plugin-root-search-9b2d4e17.md | 13 +++++++++++++ .../user-interface/reference/animation/catalog.md | 2 ++ plugins/user-interface/skills/design/SKILL.md | 7 +++++-- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 .changes/user-interface/fix-11980-plugin-root-search-9b2d4e17.md diff --git a/.changes/user-interface/fix-11980-plugin-root-search-9b2d4e17.md b/.changes/user-interface/fix-11980-plugin-root-search-9b2d4e17.md new file mode 100644 index 00000000000..c5ce70e47f5 --- /dev/null +++ b/.changes/user-interface/fix-11980-plugin-root-search-9b2d4e17.md @@ -0,0 +1,13 @@ +--- +bump: patch +--- + +### Fixed + +- `/user-interface:design` says where its settings come from when detect cannot run (no shell, as + in an eval run, or no `node`): `reference/defaults.yaml`. It reaches plugin files only by the + paths it and `concerns.json` name and never searches the plugin's directory, which the eval + sandbox denies. The animation catalog names both sources of its + resolved `animation:` config, detect's `config.values.animation` and the defaults file. Eval + runs had searched the plugin root for those values, and the sandbox's denials made both sides + invalid ([#11980](https://github.com/melodic-software/claude-code-plugins/issues/11980)). diff --git a/plugins/user-interface/reference/animation/catalog.md b/plugins/user-interface/reference/animation/catalog.md index b811354f508..466895dcb18 100644 --- a/plugins/user-interface/reference/animation/catalog.md +++ b/plugins/user-interface/reference/animation/catalog.md @@ -3,6 +3,8 @@ The rules for whether a piece of interface should move and, if it should, with which ingredients. The project's design system, motion tokens and conventions override everything in this file, and the values in the resolved `animation:` config fill only what the project leaves undefined. +That config is `config.values.animation` in the output of `scripts/detect.mjs --config`; when +detect cannot run, it is the `animation:` block of `reference/defaults.yaml`. Animation in a product interface is feedback, not decoration. The best UI animations go unnoticed: they make the interface feel fast, connected, and physical, then get out of the way. Default to diff --git a/plugins/user-interface/skills/design/SKILL.md b/plugins/user-interface/skills/design/SKILL.md index 191c65c7496..cc57283e846 100644 --- a/plugins/user-interface/skills/design/SKILL.md +++ b/plugins/user-interface/skills/design/SKILL.md @@ -211,8 +211,11 @@ which skill to run, the order for a whole screen, or what comes after a pass. ## Gotchas -- When `node` is missing, detect cannot run: read the project's design files yourself and treat - `installed` as `null`. +- With no shell or no `node`, detect cannot run: read the project's design files yourself, treat + `installed` as `null`, and take every setting a spoke calls resolved from + `${CLAUDE_PLUGIN_ROOT}/reference/defaults.yaml`. +- Reach plugin files only by the paths this skill and `concerns.json` name: a spoke already holds + the technique the concern needs. Never Grep or Glob the plugin's directory; search the project. - `installed` lists only what detect can see. A plugin installed but disabled for this project does not count, so do not route to it; tell the user it is installed and off. - A `reason` beside a non-null `installed` list means detect could not resolve this plugin's own From c839eed57b41e482792f432beaa0035396537d77 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Sun, 1 Nov 2026 11:57:28 -0500 Subject: [PATCH 2/2] fix(user-interface): narrow design's search ban to the plugin root Step 3 lists reference/types/, which a Glob reaches; only the plugin root is denied in the eval sandbox. The gotcha now allows the directories the skill names and bans Grep and Glob on the root alone. Co-Authored-By: Claude Opus 5.5 --- .../user-interface/fix-11980-plugin-root-search-9b2d4e17.md | 2 +- plugins/user-interface/skills/design/SKILL.md | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.changes/user-interface/fix-11980-plugin-root-search-9b2d4e17.md b/.changes/user-interface/fix-11980-plugin-root-search-9b2d4e17.md index c5ce70e47f5..1f706a774f9 100644 --- a/.changes/user-interface/fix-11980-plugin-root-search-9b2d4e17.md +++ b/.changes/user-interface/fix-11980-plugin-root-search-9b2d4e17.md @@ -6,7 +6,7 @@ bump: patch - `/user-interface:design` says where its settings come from when detect cannot run (no shell, as in an eval run, or no `node`): `reference/defaults.yaml`. It reaches plugin files only by the - paths it and `concerns.json` name and never searches the plugin's directory, which the eval + paths it and `concerns.json` name and never searches the plugin's root, which the eval sandbox denies. The animation catalog names both sources of its resolved `animation:` config, detect's `config.values.animation` and the defaults file. Eval runs had searched the plugin root for those values, and the sandbox's denials made both sides diff --git a/plugins/user-interface/skills/design/SKILL.md b/plugins/user-interface/skills/design/SKILL.md index cc57283e846..c5eab1b5d46 100644 --- a/plugins/user-interface/skills/design/SKILL.md +++ b/plugins/user-interface/skills/design/SKILL.md @@ -214,8 +214,9 @@ which skill to run, the order for a whole screen, or what comes after a pass. - With no shell or no `node`, detect cannot run: read the project's design files yourself, treat `installed` as `null`, and take every setting a spoke calls resolved from `${CLAUDE_PLUGIN_ROOT}/reference/defaults.yaml`. -- Reach plugin files only by the paths this skill and `concerns.json` name: a spoke already holds - the technique the concern needs. Never Grep or Glob the plugin's directory; search the project. +- Reach plugin files only by the paths this skill and `concerns.json` name, listing only the + directories this skill names (`${CLAUDE_PLUGIN_ROOT}/reference/types/`): a spoke already holds the technique the + concern needs. Never Grep or Glob the plugin's root; search the project. - `installed` lists only what detect can see. A plugin installed but disabled for this project does not count, so do not route to it; tell the user it is installed and off. - A `reason` beside a non-null `installed` list means detect could not resolve this plugin's own