From c7d413e7c321eecd20c1f354b5e60745475b69c8 Mon Sep 17 00:00:00 2001 From: notbucki <103531753+notbucki@users.noreply.github.com> Date: Mon, 31 Aug 2026 19:21:02 +0200 Subject: [PATCH] fix(design): use skill-relative script paths + CI path contract (#474 finding 1) (#476) Replace all 22 hard-coded ~/.claude/skills/design/scripts/... invocations in the design skill with skill-relative paths (python3 scripts/...), the same convention the brand and design-system sub-skills already use. The user-level path only works in one install context: under a marketplace/ plugin install the skill lives in the plugin cache, and under project-level CLI installs there is no ~/.claude/skills/design/ either. Edited .claude/skills/design/SKILL.md (source of truth) and regenerated the CLI copy with cli/scripts/sync-assets.mjs; --check passes. Adds a path-contract step to check-asset-sync.yml that fails if any SKILL.md (either copy) reintroduces a ~/.claude/skills/ invocation, and widens the workflow's path filters to .claude/skills/** so the contract actually fires on sub-skill edits. Co-authored-by: Claude Fable 5 --- .claude/skills/design/SKILL.md | 44 +++++++++++++------------- .github/workflows/check-asset-sync.yml | 18 ++++++++--- cli/assets/skills/design/SKILL.md | 44 +++++++++++++------------- 3 files changed, 58 insertions(+), 48 deletions(-) diff --git a/.claude/skills/design/SKILL.md b/.claude/skills/design/SKILL.md index fadccf4..a0cdc2f 100644 --- a/.claude/skills/design/SKILL.md +++ b/.claude/skills/design/SKILL.md @@ -44,15 +44,15 @@ Unified design skill: brand, tokens, UI, logo, CIP, slides, banners, social phot ### Logo: Generate Design Brief ```bash -python3 ~/.claude/skills/design/scripts/logo/search.py "tech startup modern" --design-brief -p "BrandName" +python3 scripts/logo/search.py "tech startup modern" --design-brief -p "BrandName" ``` ### Logo: Search Styles/Colors/Industries ```bash -python3 ~/.claude/skills/design/scripts/logo/search.py "minimalist clean" --domain style -python3 ~/.claude/skills/design/scripts/logo/search.py "tech professional" --domain color -python3 ~/.claude/skills/design/scripts/logo/search.py "healthcare medical" --domain industry +python3 scripts/logo/search.py "minimalist clean" --domain style +python3 scripts/logo/search.py "tech professional" --domain color +python3 scripts/logo/search.py "healthcare medical" --domain industry ``` ### Logo: Generate with AI @@ -60,9 +60,9 @@ python3 ~/.claude/skills/design/scripts/logo/search.py "healthcare medical" --do **ALWAYS** generate output logo images with white background. ```bash -python3 ~/.claude/skills/design/scripts/logo/generate.py --brand "TechFlow" --style minimalist --industry tech -python3 ~/.claude/skills/design/scripts/logo/generate.py --prompt "coffee shop vintage badge" --style vintage -python3 ~/.claude/skills/design/scripts/logo/generate.py --brand "TechFlow" --provider atlas +python3 scripts/logo/generate.py --brand "TechFlow" --style minimalist --industry tech +python3 scripts/logo/generate.py --prompt "coffee shop vintage badge" --style vintage +python3 scripts/logo/generate.py --brand "TechFlow" --provider atlas ``` **IMPORTANT:** When scripts fail, try to fix them directly. @@ -76,32 +76,32 @@ After generation, **ALWAYS** ask user about HTML preview via `AskUserQuestion`. ### CIP: Generate Brief ```bash -python3 ~/.claude/skills/design/scripts/cip/search.py "tech startup" --cip-brief -b "BrandName" +python3 scripts/cip/search.py "tech startup" --cip-brief -b "BrandName" ``` ### CIP: Search Domains ```bash -python3 ~/.claude/skills/design/scripts/cip/search.py "business card letterhead" --domain deliverable -python3 ~/.claude/skills/design/scripts/cip/search.py "luxury premium elegant" --domain style -python3 ~/.claude/skills/design/scripts/cip/search.py "hospitality hotel" --domain industry -python3 ~/.claude/skills/design/scripts/cip/search.py "office reception" --domain mockup +python3 scripts/cip/search.py "business card letterhead" --domain deliverable +python3 scripts/cip/search.py "luxury premium elegant" --domain style +python3 scripts/cip/search.py "hospitality hotel" --domain industry +python3 scripts/cip/search.py "office reception" --domain mockup ``` ### CIP: Generate Mockups ```bash # With logo (RECOMMENDED) -python3 ~/.claude/skills/design/scripts/cip/generate.py --brand "TopGroup" --logo /path/to/logo.png --deliverable "business card" --industry "consulting" +python3 scripts/cip/generate.py --brand "TopGroup" --logo /path/to/logo.png --deliverable "business card" --industry "consulting" # Full CIP set -python3 ~/.claude/skills/design/scripts/cip/generate.py --brand "TopGroup" --logo /path/to/logo.png --industry "consulting" --set +python3 scripts/cip/generate.py --brand "TopGroup" --logo /path/to/logo.png --industry "consulting" --set # Pro model (4K text) -python3 ~/.claude/skills/design/scripts/cip/generate.py --brand "TopGroup" --logo logo.png --deliverable "business card" --model pro +python3 scripts/cip/generate.py --brand "TopGroup" --logo logo.png --deliverable "business card" --model pro # Without logo -python3 ~/.claude/skills/design/scripts/cip/generate.py --brand "TechFlow" --deliverable "business card" --no-logo-prompt +python3 scripts/cip/generate.py --brand "TechFlow" --deliverable "business card" --no-logo-prompt ``` Models: `flash` (default, `gemini-2.5-flash-image`), `pro` (`gemini-3-pro-image-preview`) @@ -109,7 +109,7 @@ Models: `flash` (default, `gemini-2.5-flash-image`), `pro` (`gemini-3-pro-image- ### CIP: Render HTML Presentation ```bash -python3 ~/.claude/skills/design/scripts/cip/render-html.py --brand "TopGroup" --industry "consulting" --images /path/to/cip-output +python3 scripts/cip/render-html.py --brand "TopGroup" --industry "consulting" --images /path/to/cip-output ``` **Tip:** If no logo exists, use Logo Design section above first. @@ -184,21 +184,21 @@ Load `references/banner-sizes-and-styles.md` for complete sizes and styles refer ### Icon: Generate Single Icon ```bash -python3 ~/.claude/skills/design/scripts/icon/generate.py --prompt "settings gear" --style outlined -python3 ~/.claude/skills/design/scripts/icon/generate.py --prompt "shopping cart" --style filled --color "#6366F1" -python3 ~/.claude/skills/design/scripts/icon/generate.py --name "dashboard" --category navigation --style duotone +python3 scripts/icon/generate.py --prompt "settings gear" --style outlined +python3 scripts/icon/generate.py --prompt "shopping cart" --style filled --color "#6366F1" +python3 scripts/icon/generate.py --name "dashboard" --category navigation --style duotone ``` ### Icon: Generate Batch Variations ```bash -python3 ~/.claude/skills/design/scripts/icon/generate.py --prompt "cloud upload" --batch 4 --output-dir ./icons +python3 scripts/icon/generate.py --prompt "cloud upload" --batch 4 --output-dir ./icons ``` ### Icon: Multi-size Export ```bash -python3 ~/.claude/skills/design/scripts/icon/generate.py --prompt "user profile" --sizes "16,24,32,48" --output-dir ./icons +python3 scripts/icon/generate.py --prompt "user profile" --sizes "16,24,32,48" --output-dir ./icons ``` ### Icon: Top Styles diff --git a/.github/workflows/check-asset-sync.yml b/.github/workflows/check-asset-sync.yml index 578f9cf..0823454 100644 --- a/.github/workflows/check-asset-sync.yml +++ b/.github/workflows/check-asset-sync.yml @@ -5,8 +5,7 @@ on: paths: - "src/ui-ux-pro-max/**" - "cli/assets/**" - - ".claude/skills/ui-ux-pro-max/data/**" - - ".claude/skills/ui-ux-pro-max/scripts/**" + - ".claude/skills/**" - "cli/scripts/sync-assets.mjs" - "cli/package.json" - "scripts/evaluate-relevance.py" @@ -18,8 +17,7 @@ on: - "src/ui-ux-pro-max/**" - "cli/assets/**" - "cli/package.json" - - ".claude/skills/ui-ux-pro-max/data/**" - - ".claude/skills/ui-ux-pro-max/scripts/**" + - ".claude/skills/**" jobs: check-assets: @@ -38,3 +36,15 @@ jobs: # installed as a plugin, and previously had no sync check at all. - name: Check assets are in sync with source of truth run: npm --prefix cli run check:assets + # Path contract (#474): skill instructions must invoke their scripts via + # skill-relative paths (like the brand/design-system sub-skills do). A + # user-level "~/.claude/skills/..." path only works in one install + # context: it breaks under a marketplace/plugin install (skills live in + # the plugin cache) and under project-level CLI installs. + - name: Path contract - no hard-coded user-level skill paths + run: | + if grep -rn '~/\.claude/skills/' .claude/skills/*/SKILL.md cli/assets/skills/*/SKILL.md; then + echo "::error::SKILL.md files must use skill-relative script paths, not ~/.claude/skills/... (see #474)" + exit 1 + fi + echo "OK: no hard-coded user-level skill paths" diff --git a/cli/assets/skills/design/SKILL.md b/cli/assets/skills/design/SKILL.md index fadccf4..a0cdc2f 100644 --- a/cli/assets/skills/design/SKILL.md +++ b/cli/assets/skills/design/SKILL.md @@ -44,15 +44,15 @@ Unified design skill: brand, tokens, UI, logo, CIP, slides, banners, social phot ### Logo: Generate Design Brief ```bash -python3 ~/.claude/skills/design/scripts/logo/search.py "tech startup modern" --design-brief -p "BrandName" +python3 scripts/logo/search.py "tech startup modern" --design-brief -p "BrandName" ``` ### Logo: Search Styles/Colors/Industries ```bash -python3 ~/.claude/skills/design/scripts/logo/search.py "minimalist clean" --domain style -python3 ~/.claude/skills/design/scripts/logo/search.py "tech professional" --domain color -python3 ~/.claude/skills/design/scripts/logo/search.py "healthcare medical" --domain industry +python3 scripts/logo/search.py "minimalist clean" --domain style +python3 scripts/logo/search.py "tech professional" --domain color +python3 scripts/logo/search.py "healthcare medical" --domain industry ``` ### Logo: Generate with AI @@ -60,9 +60,9 @@ python3 ~/.claude/skills/design/scripts/logo/search.py "healthcare medical" --do **ALWAYS** generate output logo images with white background. ```bash -python3 ~/.claude/skills/design/scripts/logo/generate.py --brand "TechFlow" --style minimalist --industry tech -python3 ~/.claude/skills/design/scripts/logo/generate.py --prompt "coffee shop vintage badge" --style vintage -python3 ~/.claude/skills/design/scripts/logo/generate.py --brand "TechFlow" --provider atlas +python3 scripts/logo/generate.py --brand "TechFlow" --style minimalist --industry tech +python3 scripts/logo/generate.py --prompt "coffee shop vintage badge" --style vintage +python3 scripts/logo/generate.py --brand "TechFlow" --provider atlas ``` **IMPORTANT:** When scripts fail, try to fix them directly. @@ -76,32 +76,32 @@ After generation, **ALWAYS** ask user about HTML preview via `AskUserQuestion`. ### CIP: Generate Brief ```bash -python3 ~/.claude/skills/design/scripts/cip/search.py "tech startup" --cip-brief -b "BrandName" +python3 scripts/cip/search.py "tech startup" --cip-brief -b "BrandName" ``` ### CIP: Search Domains ```bash -python3 ~/.claude/skills/design/scripts/cip/search.py "business card letterhead" --domain deliverable -python3 ~/.claude/skills/design/scripts/cip/search.py "luxury premium elegant" --domain style -python3 ~/.claude/skills/design/scripts/cip/search.py "hospitality hotel" --domain industry -python3 ~/.claude/skills/design/scripts/cip/search.py "office reception" --domain mockup +python3 scripts/cip/search.py "business card letterhead" --domain deliverable +python3 scripts/cip/search.py "luxury premium elegant" --domain style +python3 scripts/cip/search.py "hospitality hotel" --domain industry +python3 scripts/cip/search.py "office reception" --domain mockup ``` ### CIP: Generate Mockups ```bash # With logo (RECOMMENDED) -python3 ~/.claude/skills/design/scripts/cip/generate.py --brand "TopGroup" --logo /path/to/logo.png --deliverable "business card" --industry "consulting" +python3 scripts/cip/generate.py --brand "TopGroup" --logo /path/to/logo.png --deliverable "business card" --industry "consulting" # Full CIP set -python3 ~/.claude/skills/design/scripts/cip/generate.py --brand "TopGroup" --logo /path/to/logo.png --industry "consulting" --set +python3 scripts/cip/generate.py --brand "TopGroup" --logo /path/to/logo.png --industry "consulting" --set # Pro model (4K text) -python3 ~/.claude/skills/design/scripts/cip/generate.py --brand "TopGroup" --logo logo.png --deliverable "business card" --model pro +python3 scripts/cip/generate.py --brand "TopGroup" --logo logo.png --deliverable "business card" --model pro # Without logo -python3 ~/.claude/skills/design/scripts/cip/generate.py --brand "TechFlow" --deliverable "business card" --no-logo-prompt +python3 scripts/cip/generate.py --brand "TechFlow" --deliverable "business card" --no-logo-prompt ``` Models: `flash` (default, `gemini-2.5-flash-image`), `pro` (`gemini-3-pro-image-preview`) @@ -109,7 +109,7 @@ Models: `flash` (default, `gemini-2.5-flash-image`), `pro` (`gemini-3-pro-image- ### CIP: Render HTML Presentation ```bash -python3 ~/.claude/skills/design/scripts/cip/render-html.py --brand "TopGroup" --industry "consulting" --images /path/to/cip-output +python3 scripts/cip/render-html.py --brand "TopGroup" --industry "consulting" --images /path/to/cip-output ``` **Tip:** If no logo exists, use Logo Design section above first. @@ -184,21 +184,21 @@ Load `references/banner-sizes-and-styles.md` for complete sizes and styles refer ### Icon: Generate Single Icon ```bash -python3 ~/.claude/skills/design/scripts/icon/generate.py --prompt "settings gear" --style outlined -python3 ~/.claude/skills/design/scripts/icon/generate.py --prompt "shopping cart" --style filled --color "#6366F1" -python3 ~/.claude/skills/design/scripts/icon/generate.py --name "dashboard" --category navigation --style duotone +python3 scripts/icon/generate.py --prompt "settings gear" --style outlined +python3 scripts/icon/generate.py --prompt "shopping cart" --style filled --color "#6366F1" +python3 scripts/icon/generate.py --name "dashboard" --category navigation --style duotone ``` ### Icon: Generate Batch Variations ```bash -python3 ~/.claude/skills/design/scripts/icon/generate.py --prompt "cloud upload" --batch 4 --output-dir ./icons +python3 scripts/icon/generate.py --prompt "cloud upload" --batch 4 --output-dir ./icons ``` ### Icon: Multi-size Export ```bash -python3 ~/.claude/skills/design/scripts/icon/generate.py --prompt "user profile" --sizes "16,24,32,48" --output-dir ./icons +python3 scripts/icon/generate.py --prompt "user profile" --sizes "16,24,32,48" --output-dir ./icons ``` ### Icon: Top Styles