# impeccable interop — gstack's design skills and the impeccable engine, catalog, and open DESIGN.md format **Status:** Shipped on `tehran-v1` (one PR, 13 bisected commits). Promoted from the CEO plan at `~/.gstack/projects/garrytan-gstack/ceo-plans/2026-09-08-impeccable-design-interop.md`. **Last updated:** 2026-09-08 **Authors:** garrytan (with /plan-ceo-review, /plan-eng-review, and two Codex outside-voice passes) ## What shipped - **Detector pre-pass.** `bin/gstack-design-detect.ts` probes for an impeccable engine the user installed (never runs impeccable's installer or launcher; after the review a consent-gated download of the engine binary itself was added: one question asked once, checksum-pinned in `lib/design-detect-contract.ts`, receipted fail-closed, installing no skill and no hook) and scans local files with it. `/design-review` (source mode on a diff, DOM mode on a URL through a rendered-DOM dump), `/ship` review-lite, `/review`'s Design specialist, and `/design-html`'s one-pass slop gate run it when `IMPECCABLE_READY`. Sentinel vocabulary: `lib/design-detect-contract.ts`. Off switch: `gstack-config set design_detector off`. - **One typed catalog.** `lib/design-catalog.ts` replaced four drifting slop lists. Every one of impeccable's 61 rule ids is mapped with gstack prose, tier, impact, confidence, and `/impeccable` handoff; gstack-only judgment tells have no brackets. `review/design-checklist.md` and `lib/dom-dump.js` are generated from `lib/`. - **Doctrine.** Persuade / Operate / Read / Experience modes, the craft-floor reflexes, the three-looks calibration, a font procedure with role-scoped overused lists, Restrained / Committed / Full palette / Drenched color strategies. - **Open DESIGN.md format.** `lib/design-md.ts` + `bin/gstack-design-md.ts` read, convert, and write the google-labs-code/design.md format; the conversion answer is persisted in the file's marker line. gstack's own DESIGN.md is converted. - **Generation-time guard.** The design binary's image prompt carries a "Never:" line built from ten catalog ids. - **Attribution.** `NOTICE.md` + `licenses/Apache-2.0.txt`. ## Plugin discovery follow-up (2026-09-25) The detector recognizes Claude Code marketplace installs at `${CLAUDE_CONFIG_DIR:-~/.claude}/plugins/cache////skills/impeccable/` as well as traditional skill installs. A trusted absolute `CLAUDE_CONFIG_DIR` replaces the default Claude user profile for both layouts. Relative, missing, non-directory, or repository-resolving overrides are ignored; `probe --verbose` explains the fallback. No Claude settings, plugin registry, or hook configuration is changed. Within each marketplace/plugin, discovery selects the newest semver directory with a regular `SKILL.md`, including prerelease ordering. Equal versions use the directory name as a stable tie-breaker. Hash and `unknown` directories remain supported after semver candidates in stable name order; their names do not prove recency. An incomplete directory is skipped, but a valid newer skill without an engine does not borrow an older plugin's engine. Launcher, bundled engine and engine `VERSION` stay associated with the selected installation. Plugin version numbers never replace engine compatibility evidence. Traditional user skill installs precede plugin candidates; explicit `IMPECCABLE_BIN`, an accepted PATH binary and the standalone engine cache retain their existing higher priority. The standalone engine cache shares strict semver ordering so an rc directory cannot win over its stable release; unlike plugin discovery, it still rejects opaque names. Multiple marketplaces/plugins are ordered by name. A ready engine suppresses the install offer; a missing engine retains the existing consent and never-ask controls. `IMPECCABLE_SKILL: present` still means files were found on disk, not that a cached plugin is enabled in the current Claude session. `IMPECCABLE_ENGINE_UNTESTED` remains an honest warning for engines outside the captured test set. Discovery is a fixed-depth, read-only filesystem walk. It does not execute launchers, install plugins, prune caches, or recursively search arbitrary home directories. Resolved paths inside the reviewed project are not executable candidates, including symlinked installs. Cache traversal skips directory symlinks and rejects a cache that resolves outside its configuration directory; repository configuration links cannot redirect the walk outside the project. Canonical HOME comparisons preserve user installs when the home directory is accessed through an alias, without allowing arbitrary home files as scan targets. Verbose output records rejected paths and filesystem errors without breaking the sentinel protocol. Runnable launcher hints use POSIX-shell quoting; control-character or Markdown-breaking names and Windows receive non-command guidance instead. The raw path used for engine execution is separate from its sanitized display. Regressions live in `test/gstack-design-detect.test.ts`; the plugin handoff agent case in `test/skill-e2e-design.test.ts` exercises the actual discovery-to-report path without an explicit engine override. Native Windows executable behavior and macOS path alias behavior require their own platform results; Linux fixture passes are not evidence of those native runs. ## CEO plan (promoted) ### CEO Plan: impeccable.style interop for gstack's design skills Generated by /plan-ceo-review on 2026-09-08 Branch: tehran-v1 | Mode: SELECTIVE EXPANSION Repo: garrytan/gstack ## Vision ### 10x Check Every AI design skill on the market is a prose vocabulary, and two vocabularies loaded together cancel out (impeccable's own docs say so). The 10x version of "incorporate impeccable" is not a fifth vocabulary. It is gstack as the design orchestrator: it runs every deterministic check the ecosystem offers (today: impeccable's 61-rule engine, when the user installed it), speaks the shared rule ids in its own voice, reads and writes the open DESIGN.md interchange format that Google Stitch and impeccable both use, and keeps the three things nobody else has: a live-site design audit through the user's real browser (Aside), image mockups with a comparison board, and a plan-stage design review before a line of UI is written. What the user feels: `/design-review` opens with the machine's findings already on the table, each tagged `[side-tab]` or `[nested-cards]`, then spends its judgment on hierarchy, trust, and copy. `/design-consultation` writes a DESIGN.md that impeccable, Stitch, and any future tool read without translation. The mockup board stops showing purple gradients because the generator prompt was told not to reach for them. And when the user has impeccable installed, every deferred finding ends with the command that fixes it. ### Platonic Ideal Not run (SELECTIVE EXPANSION mode). ## Scope Decisions | # | Proposal | Effort | Decision | Reasoning | |---|----------|--------|----------|-----------| | 1 | "Never:" line in `design/src/brief.ts` `briefToPrompt()` built from a pinned `MOCKUP_NEVER_NAMES` export (ten catalog ids, plain-English names, deduped) | S (human ~2 h / CC ~10 min) | ACCEPTED | Cheapest win in the plan: slop stopped at mockup generation; prompt text only; `design/test/brief.test.ts` added (no brief test exists today) | | 2 | Detector on live URLs via a rendered-DOM dump (one shared dump script for both engines; Aside writes under `pwd`, browse engine writes under a temp dir via `$B eval --out --raw`; bash copies both into `$REPORT_DIR/dom/`), scanned by the static engine; wrapper allow-lists `${GSTACK_HOME:-$HOME/.gstack}/projects/*/designs/` as a scan root | M (human ~1.5 days / CC ~40 min) | ACCEPTED | Resolves the tension between Phase 0 scanning source and design-review Rule 4 ("never read source"); works on deployed sites; the wrapper root check, the dump script, and the `$REPORT_DIR` path fix are the real work | | 3 | `detector: {mode, engine, total, byRule}` in `design-baseline.json`; regression mode reports ids that appeared and disappeared when `mode` matches, with an `engine changed` caveat when the engine differs | S (human ~4 h / CC ~15 min) | ACCEPTED | The number is already computed; tracked per rule id across runs; the mode gate and the engine caveat keep source-vs-DOM and engine upgrades from reading as regressions | | 4 | Slop rubric in `$D check` (GPT-4o vision) | M (human ~2 days / CC ~40 min) | DEFERRED | Paid call per variant; vision misjudges cream palettes and nested cards; revisit once catalog LLM-tells are exercised | | 5 | Taste-profile interplay for `overused-font` hits | S (human ~4 h / CC ~15 min) | DEFERRED | `.impeccable/config.json` ignore-value already covers the case without coupling two schemas | | 6 | Catalog bullets in plan-ceo-review Section 11 | S | DEFERRED | plan-ceo-review skeleton has ~555 B of carve headroom; sequence after the doctrine-carve TODO | Implementation approach decision (D1): B, the reviewed 13-commit plan, over A (detector only, 5/10) and C (B plus generation-time enforcement, 10/10). C's free half (proposal 1) accepted as a cherry-pick; its paid half (proposal 4) deferred. Delivery: ONE PR (user decision 2026-09-08, overriding the review's two-PR suggestion). Commits stay bisected; goldens regenerated at commits 4, 7, and 9; commits 12 and 13 are whole. ## Accepted Scope (added to this plan) **1. Generation-time slop guard (commit 7b).** `lib/design-catalog.ts` sets `mockupNever: true` on exactly these ten ids: `kicker-above-heading`, `icon-tile-stack`, `gradient-text`, `ai-color-palette`, `cream-palette`, `nested-cards`, `dark-glow`, `pulsing-dot`, and the gstack-only `identical-cards` and `hero-metrics`. It exports `MOCKUP_NEVER_NAMES: string[]` (their `name` fields, deduped, plain English, no ids). `design/src/brief.ts` `briefToPrompt()` pushes `"Never: " + MOCKUP_NEVER_NAMES.join(", ") + "."` (shipped as `Never by default (unless the brief above asks for it): …`) before its fixed tail. Import path `../../lib/design-catalog` (precedent: `design/src/receipted-fetch.ts` imports `../../lib/egress-receipt`; `scripts/build.sh` bundles relative TS into the binary; `setup` already treats `lib/` mtime as a rebuild trigger). `lib/design-catalog.ts` imports nothing from `scripts/`. The catalog invariant test checks the ten ids; the new `design/test/brief.test.ts` asserts the "Never:" line is present, precedes the fixed tail, and lists `MOCKUP_NEVER_NAMES.length` names. Binary rebuilt by `./setup`; `design/dist/` is never committed. **2. Detector on live URLs via a rendered-DOM dump (commit 7).** - Mode rule: the target is a URL (including an explicit `http://localhost:3000` on a feature branch) → DOM mode, no source scan. Diff-aware mode with no URL → source mode over the changed frontend dirs. Stated in the Phase 0 prose so nobody scans source "helpfully". - Hook rule (superseded before shipping, eng review decision 35): `IMPECCABLE_HOOK: present` never skips a scan; the prose tells the agent to use gstack's rows and ignore the hook's vocabulary. DOM mode scans the dump regardless, because the hook cannot see a rendered page. - One dump script for both engines, rendered once by the resolver as a fenced JS block, written as an IIFE expression with no single-quote characters (superseded before shipping: the script is an arrow function called in the page, spliced into the single-quoted Aside script and into `$B js '('"$_DUMP"')()'` through a closed-quote segment, never a double-quoted block; see lib/dom-dump-script.ts) (every `aside repl '...'` script is a single-quoted bash string, and `$B eval` wraps an expression): serialize the stylesheets whose `ownerNode` is a `` (inline `