Commit Graph
11 Commits
Author SHA1 Message Date
bastien cc2f246e65 fix(impeccable): global-scope install with agents, pin fallback, output-read failure check
make plugin never installed impeccable. The 3.2.0 pin had rotted upstream
(the CLI fetches its skill dist at install time; that release's zip is
gone), the --scope=project staging moved the skill dir alone and dropped
the 4 impeccable-* subagents, and /impeccable init was never announced.

Step 8d now installs at --scope=global straight through the
~/.claude/{skills,agents} symlinks into the repo (both paths gitignored),
guards on those symlinks existing, keeps a profile-parked copy parked,
falls back to @latest on a pin failure with a bump-the-lock warning, and
prints the per-project init hint. update-all.sh mirrors the shape.

Found while probing: with a copy already installed a rotted pin exits 0
("Could not check for skill updates ... left unchanged"), byte-identical
on disk to an up-to-date rerun, so imp_install reads the installer output
instead of trusting the exit code. Harness 4/4 in a sandbox HOME with the
real installer.

plugins.lock.json: impeccable 3.2.0 -> 4.1.0 (CLI only). link.sh drops
impeccable from EXTERNAL_SKILLS. lib/design-gate.md section 5: suggest-only
/impeccable init check when a frontend project has no PRODUCT.md.
2026-09-22 03:20:25 +00:00
bastien 7c05f75eab feat(21st): replace the magic MCP with the @21st-dev CLI + skill pack
Upstream supersedes `@21st-dev/magic` with `@21st-dev/cli` (bin `21st`):
same endpoint, `21st login` in place of an API key, no MCP process loaded
into every session.

- install-plugins.sh Step 8.7: `npm i -g @21st-dev/cli` (pinned in
  plugins.lock.json), staged `21st skills install`, TTY-only login offer,
  pack disabled by default. update-all.sh 7.4 refreshes both.
- The documented `21st install-skill` cannot be used: the installer refuses
  to follow a symlink on the target path and `~/.claude/skills` is one. The
  install runs under a throwaway HOME and the result moves into
  skills-external/21st-* (gitignored), symlinked on demand.
- toggle-external.sh manages `21st` as a pack (names globbed from
  skills-external/21st-*, parked under plain names). `magic` is gone.
- The 5 design skills join design/web/web-full/full and MANAGED_EXTERNALS;
  21st-registry and 21st-design-sync stay parked. MANAGED_MCPS is now empty
  and profile.sh's dead magic branches are removed.
- Design gate: GATE-BLOCK gains `21st` (required-manual, magic's old slot)
  and `21st-ui-build`; PATH repair extended to the npm global bin.
- settings.json: the 4 mcp__magic__* ask entries go; the outward-facing
  21st verbs land in autoMode.soft_deny, the tier that holds under auto
  mode (LRN-153).
- Docs: README, CLAUDE.global.md, design-gate.md, profile SKILL.md,
  .env.example, .gitleaks.toml, link.sh. BDR-093, LRN-158.

Tests: profile-set-managed 17/17, make test green except 2 pre-existing
gitflow FAILs (gitleaks binary absent on this host), shellcheck clean.
2026-09-22 02:53:31 +00:00
Bastien Chanot 73c765aa08 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
2026-07-05 14:42:42 +02:00
Bastien ChanotandClaude Opus 4.8 11792ccb33 feat(design-gate): §4 anim-lib suggestion — suggest-only, non-blocking, stateless 1-line
Add §4 to lib/design-gate.md: when a non-trivial design task hits a motion
signal (animation/transition/hover/motion/animate, now in §DETECTION) and the
stack is motion-eligible with no anim lib installed, surface a single-line
suggestion for the recommended `motion` package. Suggest-only (install on
explicit consent), non-blocking, stateless (always one line, no marker; calls
the helper, no 3rd copy of the lib list).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W9sqAwZxBMZSynZoVrEJhd
2026-06-26 00:11:01 +02:00
Bastien ChanotandClaude Opus 4.8 4d191354c6 fix(design-gate): fail-visible on unverified tools (no silent READY)
When `claude` is unreachable, the plugin/MCP checks (magic, ui-ux-pro-max —
the most important design tools) return `unknown`. The old verdict folded that
into a silent `READY` exit 0 — a fail-OPEN: the gate granted "proceed" exactly
when it had verified nothing. Contradicts the fail-closed-on-uncertainty rule.

Now fail-VISIBLE (not strict fail-closed — claude can be merely slow, false
blocks would get the gate ignored): a third outcome READY BUT UNVERIFIED with a
distinct exit 11. It proceeds, but says so loudly and names the unchecked tools,
telling the user to confirm with `claude mcp list` / `claude plugin list`. The
distinct non-zero code also stops a naive `if gate; then proceed` shell caller
from silently passing. Also covers the non-reproducible "transient claude absent
after apply" flake seen in live testing.

design-gate.md §DECISION updated: exit-code line + a real branch-3 state for 11.

Verified: shellcheck clean; reachable+active -> READY exit 0; claude off PATH ->
READY BUT UNVERIFIED exit 11 naming magic+ui-ux-pro-max; magic off -> INCOMPLETE
exit 10 (trip branch intact after the restructure).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 11:57:48 +02:00
Bastien ChanotandClaude Opus 4.8 131d0bcb5d feat(secrets): .env source-of-truth in ~/.claude + repo symlink
Move the real secret out of the git tree: the key lives in ~/.claude/.env
(outside the repo), and link.sh symlinks repo/.env -> ~/.claude/.env so
`source "$REPO/.env"` resolves transparently. The secret never enters git —
not as content (it's a link) and not by accident (gitignored).

link.sh: add link_env() — verify ~/.claude/.env exists + has MAGIC_API_KEY
(warn, never create/copy the secret), then create repo/.env -> ~/.claude/.env.
Defensive + idempotent: links only when repo/.env is absent or already the
right symlink; a residual REAL repo/.env is left untouched with a migrate hint
(never clobbered, so the secret can't be destroyed).

.gitignore: harden .env -> .env + .env.* + !.env.example (covers .env.local,
.env.bak, .env.save; keeps the template tracked).

Messages point at ~/.claude/.env (the canonical edit location) instead of the
ambiguous $REPO/.env: design-tool-gate.sh gate output, design-gate.md
(branch 3 + IMPORTANT), toggle-external.sh, install-plugins.sh.

Verified: shellcheck clean (link.sh, toggle-external.sh, design-tool-gate.sh);
link.sh created the symlink (1 change, idempotent re-run); repo/.env absent
from git status; magic-off path still exits 10 with the ~/.claude/.env hint.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 11:44:47 +02:00
Bastien ChanotandClaude Opus 4.8 3eefb8ad7c feat(design-gate): profile-based toolchain gate + design-tool-gate.sh
design-tool-gate.sh: deterministic design-toolchain state check. Reads the
design-core tools from design.profile's `# GATE-BLOCK:` allowlist + their
types via `profile.sh show design --plain` (claude-free parse contract),
checks each on its own channel (skill symlink / claude plugin list / claude
mcp list / command -v). Never reads disabledMcpServers. Exit 0 ready · 10
incomplete · 2 error.

Remedy is always a profile (/profile design), never an atomic tool toggle —
the profile system stays the single source of truth for activation. magic is
required-but-manual: it TRIPS the gate (not advisory) and the output names
the MAGIC_API_KEY step. Non-design tools bundled in the profile (browse,
plan-*, design-shotgun, graphify) are excluded from the trip via GATE-BLOCK,
so the gate fires only on real design tools.

design-gate.md: §DECISION rewritten profile-based (tier → run script → branch
on 3 groups), replacing the old atomic "ask user to activate ui-ux-pro-max".
§DETECTION unchanged. design.profile: add the `# GATE-BLOCK:` allowlist
(8 design-core tools); it is a comment, so read_profile/--plain are unaffected.

Verified: shellcheck clean; magic-off (real design profile) → exit 10 +
API-key line; all active → exit 0; browse-off (non-GATE-BLOCK) → exit 0,
no trip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 11:21:48 +02:00
Bastien ChanotandClaude Opus 4.6 469c807c10 feat(skills): add design-motion-principles from kylezantos
Motion/animation design skill with 3-designer lens (Emil Kowalski,
Jakub Krehel, Jhey Tompkins). Two modes: Create and Audit.
Complements frontend-design (broad) with deep motion expertise.

Integration points:
- skills-external/design-motion-principles/ — skill files + references
- link.sh EXTERNAL_SKILLS — symlink to ~/.claude/skills/
- install-plugins.sh step 8c — presence check
- update-all.sh step 7.2 — sync from GitHub
- profiles: design, full, web, web-full — listed as external
- plugin-advisor — decision table, recommended sets, conditional rules
- design-gate — symlink check + non-blocking warning if missing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-25 22:40:23 +02:00
Bastien ChanotandClaude Opus 4.6 237810396c chore(plugins): add frontend-design to plugin-advisor and design-gate
frontend-design (Anthropic's anti-AI-slop skill) was installed but not
referenced in the plugin-advisor decision table, recommended sets, or
conditional rules — nor in the design-gate detection logic.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-25 20:59:19 +02:00
bastienandClaude Opus 4.7 f80f83ee77 feat(animation): auto-install motion lib + detection across init/onboard/advisor
Add lib/animation-lib-check.sh with detect_anim_eligibility,
is_anim_lib_installed and recommend_anim_install_cmd helpers.
Wire it into the framework:
- init-project STEP 5e: silent auto-install after scaffold validated
- onboard STEP 2.5: propose + wait for user confirmation (opt-in on
  existing projects)
- plugin-advisor PHASE 1/2/3: read-only detection only, never installs
- scaffolder PHASE 4: clarifies boundary (orchestrator owns motion install)
- design-gate filesystem signals: motion / motion-v / framer-motion /
  gsap / lottie-react / react-spring / popmotion / auto-animate

Recommends `motion` (rebranded from framer-motion in Nov 2024) for
React-family and Svelte stacks, `motion-v` for Vue 3 / Nuxt. Excludes
React Native (use react-native-reanimated), backend, embedded, Flutter.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 15:32:46 +02:00
bastienandClaude 57309b80f8 feat(agents): add design gate for automatic ui-ux-pro-max detection
Lightweight skills (feat, hotfix, bugfix) had zero plugin awareness —
design tasks ran without ui-ux-pro-max even when relevant. Add a
design gate (lib/design-gate.md) that auto-detects UI/style signals
in task description and filesystem, then asks the user to activate
ui-ux-pro-max if inactive. Orchestrators already handle this via
their STEP 0 plugin-check.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-16 01:50:56 +02:00