feat(install): wire impeccable into the toolchain — deterministic design floor + /impeccable verbs

Complementary to frontend-design (kept: build-time aesthetic direction).
impeccable adds what the chain lacked: 45 deterministic anti-slop rules
(npx impeccable detect, exit 0/2, --json) — the design counterpart of the
semgrep gate — plus 23 design verbs under one /impeccable skill and
persistent per-project design context.

- plugins.lock.json: CLI pinned 3.2.0 (rules update = audit output change
  on unchanged code, LRN-077 class); skill dist = its own release track
- install-plugins.sh Step 8d: staged npx install (tmpdir) -> moved to
  skills-external/impeccable (machine-owned, gitignored, ctx7 pattern);
  never writes through the ~/.claude/skills symlink into the tracked tree
- update-all.sh: pin-honored refresh, Node<24 or failure -> dist kept
- Node >= 24 required (host at 22): steps skip gracefully, activation
  deferred to a deliberate Node bump
- link.sh EXTERNAL_SKILLS, profiles (design/web/web-full/full),
  plugin-advisor, CLAUDE.md design routing, design-gate, README, CHANGELOG
- NOT in design GATE-BLOCK yet: promotion after first dogfood
This commit is contained in:
Bastien Chanot
2026-07-05 14:42:42 +02:00
parent c47a902b78
commit 73c765aa08
14 changed files with 119 additions and 5 deletions
+7
View File
@@ -64,6 +64,7 @@ skills/ios-sync
skills/design-motion-principles skills/design-motion-principles
skills/emil-design-eng skills/emil-design-eng
skills/frontend-design skills/frontend-design
skills/impeccable
# External skills installed via `npx skills add` — auto-created by link.sh # External skills installed via `npx skills add` — auto-created by link.sh
skills/darwin-skill skills/darwin-skill
@@ -136,6 +137,12 @@ desktop.ini
# an update. The source is always re-synced, so no offline copy is needed. # an update. The source is always re-synced, so no offline copy is needed.
skills-external/frontend-design/ skills-external/frontend-design/
# Impeccable — machine-owned dist produced by `npx impeccable skills install`
# (install-plugins.sh Step 8d, update-all.sh), pinned in plugins.lock.json.
# Not vendored: the installer owns the layout and rewrites it on update
# (ctx7 pattern). Symlinked into skills/ by link.sh.
skills-external/impeccable/
# npx `skills add` project-scope artifacts — darwin-skill copies itself into # npx `skills add` project-scope artifacts — darwin-skill copies itself into
# the repo's .agents/ and writes skills-lock.json at root. Our own agents live # the repo's .agents/ and writes skills-lock.json at root. Our own agents live
# in agents/ (no dot) and stay tracked. Anchored to root so only the dotted # in agents/ (no dot) and stay tracked. Anchored to root so only the dotted
+1
View File
@@ -7,6 +7,7 @@ Format follows [Keep a Changelog](https://keepachangelog.com/).
## [Unreleased] ## [Unreleased]
### Added ### Added
- **impeccable** (pbakaus, Apache-2.0) wired into the toolchain as the design counterpart of semgrep: the `/impeccable` skill (23 verbs under one command: audit, polish, bolder, quieter…) plus the 45-rule deterministic anti-pattern detector (`npx impeccable detect`, exit 0/2, `--json`). Complementary to `frontend-design` (kept — aesthetic direction at build time); impeccable adds the deterministic audit floor and per-project design context (`/impeccable init`). CLI pinned in `plugins.lock.json` (3.2.0 — a silent rules update would change audit output on unchanged code); dist is machine-owned under `skills-external/impeccable/` (gitignored, ctx7 pattern), staged-installed by `install-plugins.sh` Step 8d, refreshed pin-honored by `update-all.sh`, symlinked by `link.sh`, listed in the design/web/web-full/full profiles and the design-work routing. Requires Node ≥ 24 — the install/update steps skip gracefully below that (this host runs 22: bump Node to activate). Not in the design gate's GATE-BLOCK list yet — promotion deliberate, after first dogfood.
- `/tour` skill — grouped all-axes sweep over one or several projects: security (pinned-semgrep `security-auditor` agent + `/cso` posture when gstack is ON) → cleanup → re-verify → reconcile (report-only, never edits the target TODO/registries) → doc sync, looping until a full pass applies zero fixes (bounded at 3 iterations). Fixes land on a `chore/tour-<date>` branch the skill never merges; each project gets an append-only `.claude/audits/TOUR.md` report with BREAKING tags on contract-changing security fixes. Built TDD (superpowers:writing-skills): baseline run showed silent TODO rewrites, autonomous registry writes, grep-as-security-pass, no persistent report, scope creep and an unbounded loop — each countered and verified on a seeded fixture. - `/tour` skill — grouped all-axes sweep over one or several projects: security (pinned-semgrep `security-auditor` agent + `/cso` posture when gstack is ON) → cleanup → re-verify → reconcile (report-only, never edits the target TODO/registries) → doc sync, looping until a full pass applies zero fixes (bounded at 3 iterations). Fixes land on a `chore/tour-<date>` branch the skill never merges; each project gets an append-only `.claude/audits/TOUR.md` report with BREAKING tags on contract-changing security fixes. Built TDD (superpowers:writing-skills): baseline run showed silent TODO rewrites, autonomous registry writes, grep-as-security-pass, no persistent report, scope creep and an unbounded loop — each countered and verified on a seeded fixture.
### Fixed ### Fixed
+4 -1
View File
@@ -292,8 +292,11 @@ source for design routing; the design-toolchain hook reinforces it.
- Build UI (component, page, redesign) → ui-ux-pro-max + frontend-design - Build UI (component, page, redesign) → ui-ux-pro-max + frontend-design
(anti-slop) + Magic MCP /ui + emil-design-eng (polish) + (anti-slop) + Magic MCP /ui + emil-design-eng (polish) +
design-motion-principles (if motion) + design-html (if static). design-motion-principles (if motion) + design-html (if static).
Post-build floor: `npx impeccable detect <files>` (45 deterministic
anti-slop rules, exit 2 = findings) when impeccable installed.
- Design system / brand → design-consultation first, then the build tools. - Design system / brand → design-consultation first, then the build tools.
- Review / audit → design-review + emil-design-eng + design-motion-principles. - Review / audit → design-review + emil-design-eng + design-motion-principles
+ /impeccable audit|critique (skill) + `impeccable detect` floor.
Scope doubt → don't silently skip: ask, or default to Build tier. Scope doubt → don't silently skip: ask, or default to Build tier.
Gate: lightweight skills run `~/.claude/lib/design-gate.md`; orchestrators via Gate: lightweight skills run `~/.claude/lib/design-gate.md`; orchestrators via
plugin-check. Magic MCP costs API calls — generation, not micro-tweaks. plugin-check. Magic MCP costs API calls — generation, not micro-tweaks.
+1
View File
@@ -100,6 +100,7 @@ Versions are pinned in `plugins.lock.json`. To update: edit the file, then re-ru
| `/code-clean` | Dead code removal, style/norm enforcement | | `/code-clean` | Dead code removal, style/norm enforcement |
| `/doc` | Documentation audit and sync — detect stale docs, patch | | `/doc` | Documentation audit and sync — detect stale docs, patch |
| `/seo` | Full SEO/GEO audit and optimization | | `/seo` | Full SEO/GEO audit and optimization |
| `/impeccable` | Design verbs (audit, polish, bolder…) + deterministic anti-slop detector (`npx impeccable detect`) |
| `/commit-change` | Smart commit grouping from staged/unstaged changes | | `/commit-change` | Smart commit grouping from staged/unstaged changes |
| `/gitflow` | Gitflow branch operations — bootstrap main+develop, start a typed branch, directed merge | | `/gitflow` | Gitflow branch operations — bootstrap main+develop, start a typed branch, directed merge |
| `/release-candidate` | Cut a versioned release — finalize version.txt + CHANGELOG, merge develop→main, tag, push | | `/release-candidate` | Cut a versioned release — finalize version.txt + CHANGELOG, merge develop→main, tag, push |
+2 -2
View File
@@ -217,10 +217,10 @@ findings before producing recommendations:
| Signal | Enable / Use | Disable / Skip | Notes | | Signal | Enable / Use | Disable / Skip | Notes |
|---|---|---|---| |---|---|---|---|
| `frontend` | ui-ux-pro-max, frontend-design, design-motion-principles | — | UI design + polish + motion. frontend-design = anti-AI-slop, design-motion-principles = motion/animation (both external, symlinked) | | `frontend` | ui-ux-pro-max, frontend-design, design-motion-principles, impeccable | — | UI design + polish + motion. frontend-design = anti-AI-slop, design-motion-principles = motion/animation, impeccable = /impeccable verbs + deterministic detector (`npx impeccable detect`, 45 rules) — all external, symlinked |
| `mobile` (React Native/Expo/Flutter) | — | gstack (no browser QA), Docker N/A | ui-ux-pro-max optional | | `mobile` (React Native/Expo/Flutter) | — | gstack (no browser QA), Docker N/A | ui-ux-pro-max optional |
| `monorepo` | per-package plugin recommendations | avoid recommending gstack for whole repo if only one package has browser QA | Specify which plugin applies to which package | | `monorepo` | per-package plugin recommendations | avoid recommending gstack for whole repo if only one package has browser QA | Specify which plugin applies to which package |
| `design-system` | ui-ux-pro-max, frontend-design, design-motion-principles | — | Design tokens, theme, Storybook, motion | | `design-system` | ui-ux-pro-max, frontend-design, design-motion-principles, impeccable | — | Design tokens, theme, Storybook, motion; impeccable init persists the design context (DESIGN.md/PRODUCT.md) |
| `deploy` + `browser-qa` | gstack | — | Full-product workflow | | `deploy` + `browser-qa` | gstack | — | Full-product workflow |
| `multi-session` | gsd v2 CLI | — | Run `gsd` in terminal, not CC plugin | | `multi-session` | gsd v2 CLI | — | Run `gsd` in terminal, not CC plugin |
| `fast-libs` | context7 | — | Doc freshness critical | | `fast-libs` | context7 | — | Doc freshness critical |
+52
View File
@@ -750,6 +750,57 @@ else
fi fi
echo "" echo ""
# ── Step 8d: Impeccable (design anti-pattern detector + skill) ──
# 45 deterministic detector rules (CLI `impeccable detect`, exit 0/2) +
# /impeccable skill (23 verbs). Machine-owned dist: the installer produces
# it, we stage it in a tmpdir then move it under skills-external/
# (gitignored, ctx7 pattern) — never let the installer write through the
# ~/.claude/skills symlink into the tracked repo dir.
echo "── Step 8d: Impeccable — design anti-pattern detector ────"
echo ""
IMP_DIR="$REPO/skills-external/impeccable"
IMP_VER=$(pinned_version "impeccable")
NODE_MAJOR=$(node -v 2>/dev/null | sed 's/^v//' | cut -d. -f1)
if [ -z "${NODE_MAJOR:-}" ] || [ "$NODE_MAJOR" -lt 24 ]; then
if [ -f "$IMP_DIR/SKILL.md" ]; then
ok "impeccable already present (update skipped — needs Node >= 24, found ${NODE_MAJOR:-none})"
else
warn "impeccable: needs Node >= 24 (found ${NODE_MAJOR:-none}) — skipped. Bump Node, then: make plugin"
fi
else
IMP_PKG="impeccable"
if [ "$IMP_VER" != "latest" ]; then
IMP_PKG="impeccable@${IMP_VER}"
info "Installing impeccable ${IMP_VER} (pinned in plugins.lock.json, staged)..."
else
info "Installing impeccable latest (consider pinning in plugins.lock.json)..."
fi
IMP_STAGE=$(mktemp -d)
if (cd "$IMP_STAGE" && npx -y "$IMP_PKG" skills install -y --providers=claude --scope=project --no-hooks >/dev/null 2>&1); then
IMP_SRC=$(find "$IMP_STAGE" -type d -name impeccable -path "*skills*" 2>/dev/null | head -1)
if [ -n "$IMP_SRC" ] && [ -f "$IMP_SRC/SKILL.md" ]; then
rm -rf "$IMP_DIR"
mv "$IMP_SRC" "$IMP_DIR"
ok "impeccable synced to skills-external/ (CLI ${IMP_VER})"
else
warn "impeccable: installer ran but produced no skills/impeccable/SKILL.md — layout changed? Inspect: npx impeccable skills install"
fi
else
if [ -f "$IMP_DIR/SKILL.md" ]; then
ok "impeccable already present (installer failed — existing dist kept)"
else
warn "impeccable install failed — run manually: npx impeccable skills install -y --providers=claude --scope=project --no-hooks"
fi
fi
rm -rf "$IMP_STAGE"
fi
if [ -L "$HOME/.claude/skills/impeccable" ]; then
ok "impeccable symlink OK"
else
info "Symlinking — will be created by link.sh"
fi
echo ""
# ============================================================ # ============================================================
# STEP 8.5 — EXTERNAL SKILLS (npx skills add …) # STEP 8.5 — EXTERNAL SKILLS (npx skills add …)
# ============================================================ # ============================================================
@@ -949,6 +1000,7 @@ echo " 🔄 context7 CLI — ctx7 (npm global, standalone or MCP setup
echo " 🔄 graphifyy (CLI: graphify) — codebase knowledge graph (pipx, PreToolUse hook)" echo " 🔄 graphifyy (CLI: graphify) — codebase knowledge graph (pipx, PreToolUse hook)"
echo " 🔄 emil-design-eng — UI polish, animations, component craft (curl → symlink)" echo " 🔄 emil-design-eng — UI polish, animations, component craft (curl → symlink)"
echo " 🔄 frontend-design — distinctive frontend interfaces, anti-AI-slop (anthropic-agent-skills)" echo " 🔄 frontend-design — distinctive frontend interfaces, anti-AI-slop (anthropic-agent-skills)"
echo " 🔄 impeccable — /impeccable design verbs + 45-rule deterministic detector (npx impeccable detect)"
echo " 🔄 design-motion-principles — motion/animation design, 3-designer lens (kylezantos)" echo " 🔄 design-motion-principles — motion/animation design, 3-designer lens (kylezantos)"
echo " 🔄 darwin-skill — autonomous skill optimizer (npx skills, ~/.agents/skills/)" echo " 🔄 darwin-skill — autonomous skill optimizer (npx skills, ~/.agents/skills/)"
echo " 🔄 find-skills — skill discovery helper (npx skills, ~/.agents/skills/)" echo " 🔄 find-skills — skill discovery helper (npx skills, ~/.agents/skills/)"
+1 -1
View File
@@ -40,7 +40,7 @@ and if not, point at ONE command — `/profile design`.
Tier does NOT change WHAT gets checked. Every non-trivial design tier draws from Tier does NOT change WHAT gets checked. Every non-trivial design tier draws from
the one `design` profile — so the gate checks that profile's **design-core the one `design` profile — so the gate checks that profile's **design-core
tools** (the `# GATE-BLOCK:` allowlist in `design.profile`: ui-ux-pro-max, tools** (the `# GATE-BLOCK:` allowlist in `design.profile`: ui-ux-pro-max,
frontend-design, emil-design-eng, design-motion-principles, design-html, frontend-design, emil-design-eng, design-motion-principles, impeccable, design-html,
design-review, design-consultation, magic). The profile also bundles design-review, design-consultation, magic). The profile also bundles
browser/plan/shotgun tooling and graphify for convenience; those never trip the browser/plan/shotgun tooling and graphify for convenience; those never trip the
gate. Motion (`design-motion-principles`) and static-HTML (`design-html`) are gate. Motion (`design-motion-principles`) and static-HTML (`design-html`) are
+1
View File
@@ -28,6 +28,7 @@ plan-ceo-review
emil-design-eng external emil-design-eng external
frontend-design external frontend-design external
design-motion-principles external design-motion-principles external
impeccable external
# Plugin (auto-toggle) # Plugin (auto-toggle)
ui-ux-pro-max plugin@ui-ux-pro-max-skill ui-ux-pro-max plugin@ui-ux-pro-max-skill
+1
View File
@@ -78,6 +78,7 @@ guard
emil-design-eng external emil-design-eng external
frontend-design external frontend-design external
design-motion-principles external design-motion-principles external
impeccable external
ui-ux-pro-max plugin@ui-ux-pro-max-skill ui-ux-pro-max plugin@ui-ux-pro-max-skill
# pr-review-toolkit REMOVED from full (audit 2026-07-02 #12): heaviest # pr-review-toolkit REMOVED from full (audit 2026-07-02 #12): heaviest
# single plugin cost (~2.2k tokens of agent descriptions/session), useful # single plugin cost (~2.2k tokens of agent descriptions/session), useful
+1
View File
@@ -48,6 +48,7 @@ qa-only
emil-design-eng external emil-design-eng external
frontend-design external frontend-design external
design-motion-principles external design-motion-principles external
impeccable external
ui-ux-pro-max plugin@ui-ux-pro-max-skill ui-ux-pro-max plugin@ui-ux-pro-max-skill
magic mcp magic mcp
+1
View File
@@ -36,6 +36,7 @@ web-validate personal
emil-design-eng external emil-design-eng external
frontend-design external frontend-design external
design-motion-principles external design-motion-principles external
impeccable external
# Plugin: UI/UX intelligence (auto-toggle) # Plugin: UI/UX intelligence (auto-toggle)
ui-ux-pro-max plugin@ui-ux-pro-max-skill ui-ux-pro-max plugin@ui-ux-pro-max-skill
+1 -1
View File
@@ -71,7 +71,7 @@ if [ -d "$GSTACK_SRC/browse/dist" ]; then
fi fi
fi fi
EXTERNAL_SKILLS=(emil-design-eng frontend-design design-motion-principles) EXTERNAL_SKILLS=(emil-design-eng frontend-design design-motion-principles impeccable)
for _ext_skill in "${EXTERNAL_SKILLS[@]}"; do for _ext_skill in "${EXTERNAL_SKILLS[@]}"; do
if [ -d "$REPO/skills-external/$_ext_skill" ]; then if [ -d "$REPO/skills-external/$_ext_skill" ]; then
if [ -L "$CLAUDE/skills/$_ext_skill" ] && [ "$(readlink "$CLAUDE/skills/$_ext_skill")" = "$REPO/skills-external/$_ext_skill" ]; then if [ -L "$CLAUDE/skills/$_ext_skill" ] && [ "$(readlink "$CLAUDE/skills/$_ext_skill")" = "$REPO/skills-external/$_ext_skill" ]; then
+5
View File
@@ -37,5 +37,10 @@
"path": "skills/emil-design-eng/SKILL.md", "path": "skills/emil-design-eng/SKILL.md",
"managed_by": "curl", "managed_by": "curl",
"note": "Emil Kowalski's design engineering skill — UI polish, animations, component craft. Downloaded to skills-external/emil-design-eng/, symlinked by link.sh." "note": "Emil Kowalski's design engineering skill — UI polish, animations, component craft. Downloaded to skills-external/emil-design-eng/, symlinked by link.sh."
},
"impeccable": {
"source": "npm:impeccable",
"version": "3.2.0",
"note": "Design anti-pattern detector (45 deterministic rules, CLI 'impeccable detect', exit 0/2) + /impeccable skill (23 verbs) by pbakaus. Pin = CLI version; the skill dist has its own release track fetched by 'skills install'. Pinned for audit reproducibility (LRN-077 class: a rules update silently changes audit output). Requires Node >= 24 — install step skips gracefully below that. Machine-owned: synced to skills-external/impeccable/ (gitignored), symlinked by link.sh."
} }
} }
+41
View File
@@ -341,6 +341,47 @@ else
info "design-motion-principles not installed — skipping" info "design-motion-principles not installed — skipping"
fi fi
# ── Impeccable (design anti-pattern detector + skill) ──
echo ""
echo "── Updating impeccable..."
IMP_DIR="$REPO/skills-external/impeccable"
if [ ! -f "$IMP_DIR/SKILL.md" ]; then
info "impeccable not installed — skipping (run: make plugin)"
else
IMP_VER=""
if [ -f "$REPO/plugins.lock.json" ] && command -v python3 &>/dev/null; then
IMP_VER=$(python3 -c "
import json
with open('$REPO/plugins.lock.json') as f:
d = json.load(f)
print(d.get('impeccable',{}).get('version','latest'))
" 2>/dev/null || true)
fi
IMP_NODE=$(node -v 2>/dev/null | sed 's/^v//' | cut -d. -f1)
if [ -z "${IMP_NODE:-}" ] || [ "$IMP_NODE" -lt 24 ]; then
info "impeccable update skipped — needs Node >= 24 (found ${IMP_NODE:-none}); existing dist kept"
else
IMP_PKG="impeccable"
# Pin honored (LRN-077 class: a silent rules update changes audit
# output on unchanged code) — bump the pin deliberately, then update.
[ -n "$IMP_VER" ] && [ "$IMP_VER" != "latest" ] && IMP_PKG="impeccable@${IMP_VER}"
IMP_STAGE=$(mktemp -d)
if (cd "$IMP_STAGE" && npx -y "$IMP_PKG" skills install -y --providers=claude --scope=project --no-hooks >/dev/null 2>&1); then
IMP_SRC=$(find "$IMP_STAGE" -type d -name impeccable -path "*skills*" 2>/dev/null | head -1)
if [ -n "$IMP_SRC" ] && [ -f "$IMP_SRC/SKILL.md" ]; then
rm -rf "$IMP_DIR"
mv "$IMP_SRC" "$IMP_DIR"
ok "impeccable refreshed (CLI ${IMP_VER:-latest})"
else
warn "impeccable: installer produced no dist — existing kept"
fi
else
warn "impeccable refresh failed — existing dist kept"
fi
rm -rf "$IMP_STAGE"
fi
fi
# ── 7.5. Update external skills (npx skills) ── # ── 7.5. Update external skills (npx skills) ──
echo "" echo ""
echo "── Updating external skills (npx skills)..." echo "── Updating external skills (npx skills)..."