diff --git a/CLAUDE.md b/CLAUDE.md index e53854307..59368668e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -45,15 +45,15 @@ Edit any of these directly and the dev server hot-reloads. No rebuild needed for - **`--color-ash`** (55%) is for secondary labels, captions, relationship meta lines. - **Never use pure black or pure white.** Use the tinted tokens. -## Prose: read STYLE.md before writing user-facing copy +## Prose: read docs/STYLE.md before writing user-facing copy -Editorial brief is at `STYLE.md` (root). Read it before editing the homepage, sub-pages, command editorials, tutorials, or READMEs. The site has been called out for AI prose; the rules there exist to keep that from creeping back. +Editorial brief is at `docs/STYLE.md`. Read it before editing the homepage, sub-pages, command editorials, tutorials, or READMEs. The site has been called out for AI prose; the rules there exist to keep that from creeping back. -The build's `validateProse` step (in `scripts/build.js`) enforces a denylist: em dashes (`—` and HTML entities), the `--` em-dash substitute, `load-bearing`, `highest-leverage`, `biggest unlock`, `seamless`, `robust`, `delve`, `elevate`, `empower`, `underscore`, `pivotal`, `tapestry`, `data-driven`, `reflex defaults`, `collapses into monoculture`, `in today's`, `gone are the days`, `whether you're`, `let's dive in`, `in summary`, `in conclusion`, `moreover`, `furthermore`. Each rule prints a rationale and a suggested replacement when it fires. **Do not silently work around the regex.** If a banned word has earned a real meaning here, raise it as a STYLE.md amendment. +The build's `validateProse` step (in `scripts/build.js`) enforces a denylist: em dashes (`—` and HTML entities), the `--` em-dash substitute, `load-bearing`, `highest-leverage`, `biggest unlock`, `seamless`, `robust`, `delve`, `elevate`, `empower`, `underscore`, `pivotal`, `tapestry`, `data-driven`, `reflex defaults`, `collapses into monoculture`, `in today's`, `gone are the days`, `whether you're`, `let's dive in`, `in summary`, `in conclusion`, `moreover`, `furthermore`. Each rule prints a rationale and a suggested replacement when it fires. **Do not silently work around the regex.** If a banned word has earned a real meaning here, raise it as a `docs/STYLE.md` amendment. The validator scans `site/pages/`, `site/content/`, `site/components/`, `site/layouts/`, `README.md`, `README.npm.md`. It deliberately skips `skill/` because LLM-facing reference instructions sometimes need technical phrasings the marketing copy can't. -The deeper structural issues (negation pivot, triadic auto-pilot, uniform paragraph rhythm, hollow confidence) require human judgment. STYLE.md lists them. Use them on every editorial pass. +The deeper structural issues (negation pivot, triadic auto-pilot, uniform paragraph rhythm, hollow confidence) require human judgment. `docs/STYLE.md` lists them. Use them on every editorial pass. ## Editorial content lives under `site/content/` @@ -275,7 +275,6 @@ The build system counts commands from the router table automatically. Update the - `site/pages/index.astro` — meta descriptions, hero box, section lead - `/cheatsheet` redirects to `/docs` (no standalone page) - `README.md` — intro, command count, commands table -- `NOTICE.md` — command count - `AGENTS.md` — intro command count - `.claude-plugin/plugin.json` — description - `.claude-plugin/marketplace.json` — metadata description + plugin description diff --git a/EMPIRICAL_VALIDATION.md b/EMPIRICAL_VALIDATION.md deleted file mode 100644 index e302b30bf..000000000 --- a/EMPIRICAL_VALIDATION.md +++ /dev/null @@ -1,44 +0,0 @@ -# EMPIRICAL_VALIDATION.md - -The rules in `skill/SKILL.src.md` and `skill/reference/` are hypotheses. This doc names the ones with empirical evidence. - -Source: a private eval harness at `~/code/impeccable-evals/` ablates each rule across three providers (Claude Haiku 4.5, Gemini 3.5 Flash, GPT-5.4 mini) on four brand niches (luxury hotel, italian restaurant, observability dashboard, vintage moto forum) at n=10 samples each. A rule "validates" when removing it shifts a deterministic detector ≥ 20pp in the predicted direction. v2.1 sweep completed 2026-06-09 anchored to commit `54c3a502` (skill-v3.5.0 + the five prose fixes that landed alongside this doc). 544 cells total. - -Treat any rule **not** named here as "intended but not yet measured" — many are correctly doing their job in territory the current detectors don't cover (DOM-render-dependent signals, niches we don't test, model-resistant patterns). The audit overlay in the eval dashboard categorizes every miss so a "failed-validation" verdict isn't read as "this rule is dead." - -## Cross-provider winners (validated on ≥ 2 providers) - -These are the trustworthy core. The ablation moved the signal in the predicted direction by a wide margin on at least two providers. - -| rule | providers | strongest delta | -|---|---|---| -| `skill-typo-text-wrap-balance` | anthropic, google, openai | Gemini +100pp, OpenAI +92pp on `text_wrap_balance` | -| `brand-typo-reflex-reject-fonts` | google, openai | OpenAI +60pp; Gemini ablate samples switched fully to Inter | -| `brand-imagery-required` | anthropic, google | Anthropic +70pp, Gemini +60pp on `image_present` | -| `brand-imagery-one-decisive-photo` | anthropic, google | Removing the rule drops `single_hero_image` substantially on both | -| `brand-permission-first-load-motion` | anthropic, google | `first_load_motion_present` moves on both | -| `skill-color-strategy-commitment` | anthropic, google | Removing the rule drops `mentions_color_strategy` on both | -| `skill-color-anti-cream` | anthropic, google | Removing it raises `cream_sand_palette` on both | - -Single-provider validations exist for ~20 more rules; see the eval dashboard at `localhost:8723/dashboard/biases/rules/` (filter "v2 any"). - -## What we learned about the rules themselves - -- **Literal bad examples in rule prose primed the model to reproduce them.** Confirmed against OpenAI samples that emitted "fake theater", "vendor theater", and "heatmap theater" as verbatim copies of an example phrase in the skill. The five prose fixes landed alongside this doc remove that pattern from `skill-ban-codex-x-theater`, `brand-imagery-required`, `skill-typo-no-all-caps-body`, `brand-color-no-converge`, and `skill-copy-no-aphoristic-cadence`. **Going forward: describe the failure shape, never enumerate examples of it.** -- **Many "failed-validation" rules are doing their job; the detector just can't see the effect.** `det_low_contrast` saturates at 80% baseline; render-dependent detectors under-fire on one-shot output. A failed verdict on a render-dependent rule is not evidence the rule is dead. -- **Detector vocabulary anchoring is a real bias.** Detectors that grep for the rule's own example words measure echo, not effect. The current `mentions_color_strategy` / `mentions_register` detectors should be treated with caution. - -## What got deleted in this pass - -- `skill-typo-no-all-caps-body` — duplicate of `brand-ban-all-caps-body` (same signal, brand version is more specific). -- `skill-typo-codex-hero-ceiling-repeat` — duplicate of `skill-typo-hero-ceiling` (the codex-block restatement didn't reinforce; the universal rule covers it). -- `skill-typo-scale-ratio` — duplicate of `brand-typo-modular-scale` (same signal, brand version carries the implementation detail). -- `skill-typo-font-count` — no measurable signal; models don't reach for ≥4 families in any niche we test. The rule remains a defensible safety rail but isn't earning its place in skill prose. - -## Cost discipline note - -The v2.0 → v2.1 cycle cost ~$1,800 across two providers' worth of API plus operational waste. Ablation is expensive; new measurement should be triggered by a specific decision the existing matrix can't yet inform — not by a desire for more data. - -## Methodology - -For the harness setup, the rule-by-rule audit reports, and the cost trail: `~/code/impeccable-evals/notes/ablation-v2-plan.md` and `~/code/impeccable-evals/output/ablations/_audit_consolidated.json`. diff --git a/NOTICE.md b/NOTICE.md deleted file mode 100644 index ac91432b6..000000000 --- a/NOTICE.md +++ /dev/null @@ -1,25 +0,0 @@ -# Notice - -Impeccable -Copyright 2025-2026 Paul Bakaus - -## Anthropic frontend-design Skill - -The `impeccable` skill in this project builds on Anthropic's original frontend-design skill. - -**Original work:** https://github.com/anthropics/skills/tree/main/skills/frontend-design -**Original license:** Apache License 2.0 -**Copyright:** 2025 Anthropic, PBC - -This project extends the original with: -- 7 domain-specific reference files (typography, color-and-contrast, spatial-design, motion-design, interaction-design, responsive-design, ux-writing) -- 23 commands -- Expanded patterns and anti-patterns - -## Typecraft Guide Skill - -The `typography.md` reference in this project incorporates a set of tactical additions merged in from ehmo's `typecraft-guide-skill` at the author's request: dark-mode weight/tracking compensation, `font-display: optional` vs `swap`, preload-critical-weight-only guidance, variable fonts for 3+ weights, `clamp()` max-to-min ratio bound, responsive measure/container coupling, `text-wrap: balance` / `pretty`, `font-optical-sizing: auto`, ALL-CAPS tracking quantification, and the paragraph-rhythm rule (space OR indent, never both). - -**Original work:** https://github.com/ehmo/typecraft-guide-skill -**Original license:** see upstream repo -**Author:** ehmo diff --git a/README.md b/README.md index daf06cf3e..2a3514481 100644 --- a/README.md +++ b/README.md @@ -286,14 +286,12 @@ Join the community and ecosystem conversations: ## Contributing -See [DEVELOP.md](DEVELOP.md) for contributor guidelines and build instructions. +See [DEVELOP.md](docs/DEVELOP.md) for contributor guidelines and build instructions. ## License Apache 2.0. See [LICENSE](LICENSE). -The impeccable skill builds on [Anthropic's original frontend-design skill](https://github.com/anthropics/skills/tree/main/skills/frontend-design). See [NOTICE.md](NOTICE.md) for attribution. - --- Created by [Paul Bakaus](https://www.paulbakaus.com) diff --git a/DEVELOP.md b/docs/DEVELOP.md similarity index 98% rename from DEVELOP.md rename to docs/DEVELOP.md index 4d53b18bd..bfaff4090 100644 --- a/DEVELOP.md +++ b/docs/DEVELOP.md @@ -189,8 +189,9 @@ impeccable/ providers.js # Provider config map index.js # Re-exports tests/ # Bun test suite - HARNESSES.md # Provider capabilities reference - DEVELOP.md # This file + docs/ + HARNESSES.md # Provider capabilities reference + DEVELOP.md # This file README.md # User documentation ``` diff --git a/HARNESSES.md b/docs/HARNESSES.md similarity index 100% rename from HARNESSES.md rename to docs/HARNESSES.md diff --git a/STYLE.md b/docs/STYLE.md similarity index 100% rename from STYLE.md rename to docs/STYLE.md diff --git a/docs/issue-150-live-preview-plan.md b/docs/issue-150-live-preview-plan.md deleted file mode 100644 index 462f328f1..000000000 --- a/docs/issue-150-live-preview-plan.md +++ /dev/null @@ -1,48 +0,0 @@ -# Issue 150 Live Preview Plan - -## Current Bug Summary - -Live preview can lose framework state when variants are written directly into watched component source. The Svelte reproduction is a stateful expense row: after adding an expense, generating variants for the row should not reset the component or render raw Svelte expressions such as `{expenses[0].name}`. - -The current branch uses **Svelte component injection** for `.svelte` targets: variants are real components under `src/lib/impeccable//`, mounted in the browser via Svelte 5 `mount()`, and inlined back into the route source on live exit. Accept keeps the mounted component visible immediately while deferring the route write until `live-server stop`. - -## Manual test apps (home directory) - -Stateful framework repros live outside this repo: - -- **Svelte:** `~/impeccable-live-svelte` (see its `README.md`) -- **React:** `~/impeccable-live-react` (see its `README.md`) - -Each app includes a copied `.cursor/skills/impeccable` build from the local impeccable branch for live-server / inject / poll. - -## Current Status - -- Svelte component-injection Accept fix is implemented. -- Svelte manual pass with the user is complete (`~/impeccable-live-svelte`). -- React manual user check and the DeepSeek-backed final run are still pending (`~/impeccable-live-react`). -- Focused live tests, build, and full test suite should pass after harness refresh. - -## Svelte Fix Plan - -- Keep component injection scoped to `.svelte` targets. -- Extract `propContract` from the picked route markup and author variants as real `.svelte` files with `{propName}` bindings. -- Mount compiled variants in the browser with the app's shared Svelte runtime. -- On Accept, keep the chosen mounted variant visible immediately. -- Defer the real route source inline until live shutdown to avoid accept-time remounts. -- On live shutdown, inline accepted markup + CSS into the route and remove temp component files. -- Keep the connected indicator stable while an event is leased or actively being handled. - -## React Parity Test Plan - -- Same shape as the Svelte case in `~/impeccable-live-react`. -- Run the same Go, cycle, Accept flow against the React row. -- React already uses direct source wrap + Fast Refresh; keep that path unchanged unless manual testing shows state loss. - -## Validation Checklist (impeccable repo) - -- [ ] `node --test tests/live-browser-regression.test.mjs tests/live-accept.test.mjs tests/live-poll.test.mjs tests/live-server.test.mjs tests/live-svelte-component.test.mjs` -- [ ] Manual Svelte run in `~/impeccable-live-svelte` -- [ ] `bun run build` -- [ ] `bun run test` - -The PR should remain draft until the React manual check in `~/impeccable-live-react` passes. diff --git a/docs/issue-150-svelte-stuck-bar-handoff.md b/docs/issue-150-svelte-stuck-bar-handoff.md deleted file mode 100644 index f2f30867c..000000000 --- a/docs/issue-150-svelte-stuck-bar-handoff.md +++ /dev/null @@ -1,132 +0,0 @@ -# Handoff: Svelte live mode bar stuck at `0/0` (CYCLING with no variants) - -Date: 2026-05-30 -Branch: `codex/issue-150-svelte-live` -Status: **Unresolved.** Two rounds of fixes landed and were synced to the manual test repo, but the symptom still reproduces. - ---- - -## Symptom - -In `~/impeccable-live-svelte`, after running a live action (Polish/Bolder) on the expense row, the floating live bar shows the **CYCLING** layout (prev/next arrows, two faint dots, `✓ Accept`, `✕`) but the counter reads `0/0` and every control is disabled (`opacity: 0.3`, `pointer-events: none`). No variant is mounted. The bar persists across reloads. - -Captured DOM (trimmed): `
` … `0/0` … `✓ Accept` (disabled) `✕`. Full markup is in the chat history if needed. - -`0/0` = `visibleVariant=0 / arrivedVariants=0`. The two dots = `expectedVariants=2` rendered as "pending" (see `buildDots`, both unfilled because `arrivedVariants=0`). - ---- - -## Context: what this feature is - -Issue 150 replaced the Svelte "source-shadow" live preview with **real component injection**. See `docs/issue-150-live-preview-plan.md` and `skill/reference/live.md` (the `svelte-component` paragraph). Key pieces: - -- `skill/scripts/live-svelte-component.mjs` — scaffolds `src/lib/impeccable//` with `manifest.json`, `v1.svelte`…`vN.svelte`, and a one-time `__runtime.js`. Inlines the accepted variant back into the route on exit. -- `skill/scripts/live-wrap.mjs` — `.svelte` targets return `previewMode: "svelte-component"`, `file` = manifest path. -- `skill/scripts/live-browser.js` — mounts compiled variants via Svelte 5 `mount()` into a `display:contents` slot that replaces the original element. Cycling = unmount + remount. -- `skill/scripts/live-accept.mjs` / `live-server.mjs` — defer the route source write to `live-server stop`. - -The Svelte wrapper in the live DOM is **runtime-injected** and holds a single mount target (`[data-impeccable-component-mount]`), **not** `[data-impeccable-variant]` children like the HTML/JSX path. This distinction is the source of most of the trouble. - ---- - -## What has already been fixed (and synced to the test repo) - -All in `skill/scripts/live-browser.js`, rebuilt via `bun run build:skills` and rsync'd to `~/impeccable-live-svelte/.cursor/skills/impeccable/`. - -1. **Params sidecar (the original compile error).** Svelte parses `{` inside an attribute value as an expression, so `data-impeccable-params='[{…}]'` broke compilation (`Expected token }`). Params now load from `componentDir/params.json` keyed by variant number: - - `loadSvelteComponentParams(manifest)` fetches `params.json`. - - `parseVariantParams()` reads from `svelteComponentSession.paramsByVariant` for the component path instead of the DOM attribute. - - Agent contract updated in `live-svelte-component.mjs` (`buildSvelteComponentCssAuthoring`) and `skill/reference/live.md`. - -2. **Resume guard.** `resumeSession()` now drops an orphaned `svelte-component` wrapper (no live in-memory mount) instead of resuming it into an empty bar. Without this, every reload resumed `arrivedVariants=0`. - -3. **Abort-on-failure.** New `abortSvelteComponentInjection(sessionId, message)` resets the bar to PICKING (restores the original element, clears session, toast) when the picked element can't be found OR the initial `mountSvelteComponentVariant` returns false (compile/mount throw). Called from `injectSvelteComponentsFromManifest`. - -Tests added in `tests/live-browser-regression.test.mjs` (all green): orphan reset, abort helper, sidecar params. Full focused suite passes: `node --test tests/live-browser-regression.test.mjs tests/live-svelte-component.test.mjs tests/live-accept.test.mjs`. - ---- - -## Why it probably STILL reproduces (hypotheses, in priority order) - -### H1. The served `live.js` is stale (verify FIRST) -The browser loads `live.js` from the running live-server, not from disk directly. If the server wasn't restarted, or the `