mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 22:26:38 +03:00
cli-v2.2.0
671
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9ffd3211d5 |
Neo Kinpaku design system + Live Mode v3 (#169)
* Add neo kinpaku design system page * skill: rip out baked-in category recipes and saturated-default motion tropes Programmatic bias mining (impeccable-evals) traced four major defects back to specific lines in this skill that contradicted SKILL.md's own first-order-reflex warning: - brand.md "Pairing and voice" prescribed four category→aesthetic recipes (editorial → serif+sans, tech/dev/fintech → tight tracking, consumer/food/travel → script/display serif, creative → rule-break). These directly drove OpenAI's 76% extreme-negative letter-spacing on tech briefs and Anthropic/Google's 28-34% italic-serif-display slop on editorial/food briefs. Replaced with one sentence: the shape depends on the brand, not on the brand's category. - brand.md "Brand permissions" had "Typographic risk. Enormous display type, unexpected italic cuts, mixed cases, hand-drawn headlines, a single oversize word as a hero." — a four-for-one slop driver behind 97% OpenAI comically-large H1, 42% bad-SVG illustration, and the editorial-italic slop. Deleted outright. - typeset.md and teach.md repeated the same category recipes; trimmed to the principle without the recipe. - SKILL.md Typography: added a hard hero-H1 ceiling (clamp() max ≤ 6rem ≈ 96px), with a <codex> block to make it explicit since OpenAI over-indexes here (97% ≥128px vs 24% for Anthropic). - animate.md, bolder.md, brand.md: removed "staggered reveals" and "scroll-triggered transitions" as the prescribed default ambitious motion. By 2026 that's the saturated AI tell, not a choreography. Reserved stagger for legitimate list-sibling rhythm. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * skill: anti-cream + codex-specific defect bans + universal slop bans Second pass after measuring more biases against the eval corpus. - SKILL.md Color: explicit "cream/sand/beige body bg is the saturated AI default of 2026" rule. Tone down the "tint every neutral" line so it doesn't read as "default to warm-tinted near-white" (which OpenAI hits at 74% and Anthropic at 31%-47%). - SKILL.md Absolute bans: add universal bans for two slop patterns detected at 55-95% across providers — tiny uppercase tracked eyebrow above every section (the 2023-era kicker that's now AI grammar) and numbered section markers (01/02/03). Also explicit "text that overflows its container is the universal defect on tablet/mobile." - SKILL.md Absolute bans → <codex> block: ban the GPT-specific defects Paul annotated repeatedly — `border:1px solid` + soft-wide-shadow (≥16px blur) "ghost cards", `border-radius:32px+` over-rounding, hand-drawn/sketchy SVG illustrations (loose-sketch / *-sketch classes, feTurbulence paper-grain filters), repeating-linear-gradient stripes, "X theater" AI-slop copy phrases. - SKILL.md Motion → <gemini> block: the image :hover transform tell (38% Google skill-on rate). Hover effects on images add no info; the image isn't an action target. Animate card chrome, not the image. - SKILL.md Typography: hard display letter-spacing floor ≥-0.04em (OpenAI defaults to -0.075em → cramped). Existing hero ceiling <codex> block extended with the letter-spacing rule. - codex.md Step A example: stop seeding "warm-grounded (deep oxblood + cream)" as the warm-palette template, which primes the cream default. - colorize.md Tinted backgrounds: stop printing the literal cream recipe `oklch(97% 0.01 60)`; replace with brand-anchored guidance. - document.md examples: warm-ash-cream → cool-paper so the example doesn't seed cream as the canonical neutral example. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * skill: universal anti-slop bans + contrast/font-count/all-caps-body rules Third pass after measuring the rest of the cross-provider matrix: - Color: explicit "Verify contrast" rule. Low-contrast text fires at 68% across all providers skill-on (90+% off). The most common failure is muted gray body on a tinted near-white; light-gray-for- elegance is named as the single biggest cause of unreadable AI pages. - Typography: max-3-font-families rule. Overused-fonts (>4 families) fires at 28% Anthropic / 36% Google / 0% OpenAI skill-on; >50% off. Also: universal "no all-caps body copy" (moved from brand-only ban to Shared design laws since product-register also overuses caps). - Copy: anti-aphoristic-cadence ban targets Anthropic's signature "X. No Y." / "X. Just Y." voice (63% skill-on copy-slop rate, 77% off — the worst rate in the matrix). Once-is-voice / three-or-more- is-tell framing per the runner's copy-slop detector. - Copy: anti-SaaS-buzzword-string ban with the literal phrase list the detector watches for (streamline/empower/supercharge, trusted- by-leading, best-in-class/enterprise-grade/cutting-edge, etc). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * skill: strengthen anti-cream rule across full warm-neutral band Smoke validation showed the cream fix worked for Google + OpenAI but Anthropic Sonnet italian-restaurant still shipped `--paper: oklch(90% .018 88)` — cream just outside the L≥95% band the rule cited. Broaden the rule: - Band: OKLCH L 0.84-0.97, C < 0.06, hue 40-100 (was 95-97% / 60-95). - Name the token-name tells explicitly (paper / cream / sand / bone / flour / linen / parchment / wheat / biscuit / ivory) — the model defaults to one of these regardless of what hex it lands on. - Call out the specific brief patterns ("warm, traditional, family- coastal-Italian" / "editorial-restraint") that the model translates into cream by reflex. Then provide three explicit non-cream options: saturated brand color, true off-white at C=0, or darker mid-tone. Warmth in the brand is carried by accent + typography + imagery, not by body bg. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * v3.2.0: skill bias-fix release Bumps version from 3.1.1 to mark the four-commit skill cleanup that rips out baked-in category recipes (brand.md), saturated-default motion tropes (staggered reveals everywhere), the cream/sand body-bg AI tell, codex-specific defects (1px+wide-shadow, over-rounding, hand-drawn SVGs, stripes, X-theater copy), the extreme-letter-spacing default, and universal slop bans (all-caps eyebrow on every section, numbered-section markers, all-caps body, font-family-count > 3, aphoristic copy cadence, SaaS buzzword strings). Plus a hard hero-H1 ceiling (clamp() ≤6rem) and a Gemini-specific image:hover transform block. Validated against ~190 post-fix samples — see impeccable-evals biases tab for per-provider deltas. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * drop "no pure black/white" rule entirely The rule was contested in the design world and causing more damage than good — pushing every page into the tinted-near-white default which is the cream/sand AI tell we already explicitly ban elsewhere. Vercel, SVKMS, Brutalist sites, et al. use pure black/white successfully; the skill shouldn't second-guess that. Skill markdown deletions: - SKILL.md Color: drop the "Never use #000 or #fff" bullet. - color-and-contrast.md: drop the "Never Use Pure Gray or Pure Black" subsection, the "Never pure black" table-row prescription, and the "Avoid: Using pure black for large areas" bullet. - colorize.md: drop the "NEVER use pure black or pure white for large areas" bullet. - polish.md: drop the "Tinted neutrals: No pure gray or pure black" half of the bullet (the gray-on-color bullet survives). Detector code (cli/engine): - registry/antipatterns.mjs: remove the `pure-black-white` entry. - rules/checks.mjs: remove the three `findings.push({ id: 'pure-black-white', ... })` emit points (inline #000 bg, Tailwind bg-black class, plain-HTML scan path). - engines/regex/detect-text.mjs: remove the two pure-black-white regex rules (CSS `background: #000…` + Tailwind `bg-black`). - detect-antipatterns-browser.js: regenerated via scripts/build-browser-detector.js. Tests: - detect-antipatterns-fixtures.test.mjs: invert the assertion that pure-black-white fires; expect it to NOT fire post-v3.2. Drop the Tailwind bg-black-opacity edge-case test (no longer relevant). - detect-antipatterns.test.js: drop the standalone "detects pure- black-white in styled-components" test and remove pure-black-white from the multi-detector assertions in PricingCard, globals.css, and GlobalStyle.tsx tests. 166 bun tests pass; 24 node fixture tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * skill: strip example patterns from copy rules, strengthen gemini block v3.2 rerun validation surfaced two issues: 1. Copy-slop detector fires more on Gemini under v3.2 (48% → 84%) than under no-skill baseline. Root cause: the anti-aphoristic-cadence rule printed the literal "X. No Y." / "X. Just Y." patterns as examples, and Gemini imitated them as the recommended voice. Same recipe-becomes- bias trap we hit with brand.md:116's "Enormous display type, unexpected italic cuts, mixed cases, hand-drawn headlines" enumeration. Fix: describe the cadence as a rhythm ("serious statement, then punchy short negation") without printing literal patterns. Buzzword list trimmed to a single inline phrase family rather than quoted strings. 2. Gemini image:hover transform Gemini-tell hadn't dropped (31% off → 32% v3.2). Strengthen the <gemini> block: explicit "Never animate <img> elements on hover", call out the Tailwind group-hover:scale / group-hover:rotate / group-hover:translate parent-hover patterns by name (Gemini was reaching for these via Tailwind even though the prior text talked about :hover on the image directly). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * skill: simplify context loading and inline register directive Replaces load-context.mjs's JSON output with a tight markdown block from the renamed context.mjs. The script now extracts PRODUCT.md's `## Register` field and appends a `NEXT STEP:` directive naming the matching reference (brand.md / product.md), which moved Gemini from skipping the register load entirely to honoring it. Drops the `.impeccable.md` auto-migration; makes IMPECCABLE_CONTEXT_DIR a lazy escape hatch consulted only when the default paths come up empty. Setup is now four bullets in one list. The DESIGN.md nudge is gone; in its place, a "familiarize with the existing design system" step that calls out CSS / tokens / running app as authoritative sources alongside DESIGN.md. The standalone `### Register` H3 stays for the cascade rules (task cue → surface → register field). New LLM-backed test suite at tests/skill-behavior/ runs five scenarios against claude-haiku-4-5, gpt-5.4-mini, and gemini-3.1-flash-lite via Vercel AI SDK. Captures real tool traces, asserts on context.mjs calls, brand.md loads, and teach.md fallback. Skips cleanly when API keys are unset. 13-14/15 pass; only stable failure is the v3.2.0-era gpt-mini S4 "don't re-run" regression. Adds @ai-sdk/google as devDep and the test:skill-behavior npm script. Touches em-dashes in skill/SKILL.md and four reference files so `bun run build:skills` passes its skill-prose validator. teach.md and document.md drop their "re-run the loader to refresh session cache" steps since the agent's own write is now the freshest source. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * skill: merge orphan reference files into command sub-skills + inline S-tier invariants Two related restructurings: 1. SKILL.md now carries the cross-domain invariants that catch defects in any project (contrast/placeholder/gray-on-color, similar-font pairing, text-wrap, tabular-nums, centered-stack default, Flex/Grid choice, auto-fit grids, semantic z-index, reduced motion, stagger vs section-fade, premium motion materials, focus-visible, placeholders-aren't-labels, dropdown overflow trap, button/link copy). Greenfield-only rules (theme picking, color strategy, tinted neutrals) live under "New projects only". 2. Reference files merged into their command counterparts: - spatial-design.md -> layout.md - motion-design.md -> animate.md - color-and-contrast.md -> colorize.md - responsive-design.md -> adapt.md - ux-writing.md -> clarify.md - typography.md -> typeset.md (bolder.md redirected) - cognitive-load.md + heuristics-scoring.md + personas.md -> critique.md craft.md and shape.md "load references" lists updated to new file homes. interaction-design.md stays standalone (no 1:1 command verb). Net: 36 -> 27 reference files. Same content, fewer files, no orphaned reference loaded only from craft.md. Also extends the routing rules: if the user's first word doesn't match a command but the intent clearly maps to one, load that command's reference and proceed as if invoked. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * skill: add sub-command + existing-project scenarios; move sub-command load to step 2 Adds three new LLM-backed scenarios to tests/skill-behavior: - S6: `/impeccable polish` → loads polish.md - S7: `/impeccable audit` → loads audit.md - S8: existing SvelteKit project (PRODUCT.md + DESIGN.md + src/app.css + src/lib/components/*.svelte + src/routes/+page.svelte) → agent reads at least one project code file to understand the existing design system S6/S7 surface a real model-floor: gpt-5.4-mini reads brand.md, reads the target index.html, and just does the polish/audit without ever loading the sub-command reference. Stronger SKILL.md wording didn't move it. Captured in the README baseline as a known weakness. Claude and Gemini honor the load reliably. To fix Gemini on S6/S7, sub-command reference loading is now Setup step 2 (right after context.mjs), not step 4 — placing it before the model gets focused on "doing the work". Step 3 (design-system familiarization) is tightened to require at least one project code read even when a sub-command reference loads in step 2, so Claude doesn't laser-focus on the sub-command flow and skip the broader exploration. Two new fixtures: MINIMAL_LANDING_HTML (a tiny static landing page for S6/S7) and SVELTE_PROJECT_FILES (a minimal SvelteKit scaffold with tokens, components, and a routes/+page.svelte for S8). Both designed to look real enough that agents treat them as production code. Suite is now 24 tests across three providers; baseline is 21-22/24, with the stable failures being gpt-5.4-mini scenarios 6 and 7. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * skill: add reveal-animation safety rule (must enhance, not gate visibility) Class-triggered visibility transitions pause on hidden tabs and headless renderers. The italian-restaurant smoke produced a build where 2 sections shipped opacity:0 because the CSS transition never advanced past currentTime=0 (timeline paused). Added one-liner under Motion to prevent the antipattern: reveals must enhance an already-visible default, never gate content visibility on a class-triggered transition. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * skill: restore prescriptive cream/sand/beige paragraph Bisection across 5 historical skill commits on Gemini 3.5 flash fast lane n=3 found thatext-v1.1.0 cli-v2.2.0 |
||
|
|
84135db0e6 |
Add DeepSeek live E2E adapter (#163)
* Add DeepSeek live E2E adapter * Fix DeepSeek live E2E review issues * Harden live-e2e helpers against silent failures - htmlToJsx: match multi-line inline style attributes ([\s\S]*?) - readCliOption: throw when --flag value is missing or another --flag - llm-agent: echo parsed payload (first 500 chars) in schema-error throws * Bind hoisted inline styles to their owning tag normalizeVariantOutput previously hoisted every stripped style attribute onto a selector derived from the variant's first tag, so a style on a nested <span> landed on <h1>. Now walks each opening tag and emits one rule per styled element with a descendant combinator so nested-element styles target the correct node. Also fixes the duplicated multi-line style regex bug (.*?) -> ([\s\S]*?) that survived the previous round. Extracts parseVariantResponse from llm-agent for direct schema-throw testing, and lifts readCliOption into its own module so its new missing-value throws can be unit-tested. Adds tests for: - multi-line style hoisting - nested-element tag binding and per-tag rule emission - astro-global-prefixed selector shape - no-op identity-return path - opts.config short-circuit in createLlmAgent - all four parseVariantResponse schema previews + JSON-parse failure - readCliOption value/throw matrix * Hoist inline styles via data attribute, not tag name Two bugs in normalizeVariantOutput that Bugbot flagged: 1. Hoisted rules like `:scope span` matched every same-tag descendant of the variant wrap, so a style on one of several <span>s leaked onto its siblings. 2. The opening-tag scan used `[^>]*` for attributes, so a literal `>` inside a quoted attribute value (e.g. `aria-label="x > y"`) terminated the match early and the trailing `style="..."` was never seen. stripInlineStylesPerElement now walks each opening tag character by character respecting quoted attribute values, and tags every styled element with `data-impeccable-hoist-id="N"`. Rules select on the attribute so they bind to exactly the one element they came from. The attribute is stripped during carbonize cleanup so it does not survive into the final source. * Harden live E2E variant CSS normalization * Fix Radix tests * Harden live E2E pick clicks |
||
|
|
642f03d5a1 |
fix(live-server-test): isolate shared server cwd so tests cannot pollute repo
Previously the main `live-server integration` describe block spawned its shared server against REPO_ROOT, so its session journals/snapshots (a1b2c3d4-dc, aa11bb22, sse-test, test-e2e-1) were written into the real repo's `.impeccable/live/sessions/`. On the next `npx impeccable live` run, restorePendingEventsFromStore replayed those into the poll queue, surfacing as synthetic test events to the agent. Run the shared server against a mkdtempSync tmpdir, seed a minimal package.json so the /source endpoint test still passes, and route the inline journal/snapshot reads (and the live-complete.mjs call) through server.cwd. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
bc1894889e |
Improve critique skill reliability
- add provider-specific block compilation and tests - bundle detector scripts for skill critique runs - harden critique orchestration, browser handling, and storage |
||
|
|
e1d3ea0b6f |
Detector architecture v2: static engine, benchmarks, lab, and visual contrast (#156)
* Add detector benchmark lab and visual contrast fallback * Expand visual contrast fixture coverage * Add browser visual contrast fallback * Show visual contrast overlays in detector lab * Fix detector lab short viewport layout * Fix detector lab visual overlays * Add visual contrast to browser scan overlays * Avoid browser scroll jumps during visual contrast scans * Resolve visual contrast lazily on scroll * Refresh detector lab visual counts lazily * Update pnpm lockfile for static parser deps * Address Bugbot detector API comments * Report extension visual contrast errors * Refactor detector into engine modules * Address Bugbot detector comments * Fix latest Bugbot detector notes * Fix visual contrast fixture labels * Refine detector lab fixtures * Fix stale detector overlay references * Fix detector lab fixture URLs * Fix typography lab fixture highlights * Fix typography lab page-level signal * Fix visual overlay lifecycle cleanup * Remove dead spotlight timer cleanup * Make browser async APIs reject consistently |
||
|
|
4af581e23f |
chore(skill): bump to v3.1.1 + changelog
Windows fix for /impeccable critique CLI guard (#155). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>skill-v3.1.1 |
||
|
|
5f15163c2b |
fix(critique-storage): make CLI entry-point check Windows-safe (#155)
The `import.meta.url === \`file://\${process.argv[1]}\`` guard at the
bottom of critique-storage.mjs silently failed on Windows: Node sets
import.meta.url to file:///D:/... (forward slashes) but process.argv[1]
is D:\... (backslashes), so the string compare returns false, main()
never runs, and the script exits 0 with no output. The OpenCode reporter
saw "/impeccable critique" skip the snapshot save with no error.
Switch to pathToFileURL(process.argv[1]).href, the standard cross-
platform pattern already used everywhere else in the repo.
Adds three CLI subprocess tests so future regressions of this guard
are caught even on macOS/Linux CI.
Fixes #155.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
e493504496 |
chore: sync bun.lock to jsdom 29.1.1 from #154
PR #154 bumped jsdom in package.json and pnpm-lock.yaml but left bun.lock at 29.0.0, so the next bun install regenerates this diff. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
de9aa13a53 | ignore talks | ||
|
|
1e8356fa25 |
fix(cli): pass --copy to npx skills add to avoid symlinking provider dirs (#148)
By default, `npx skills add` installs to .agents/skills/ and symlinks .claude/skills/ to it. That symlink fails to be created on fresh projects with no .claude/ directory, and on Windows without elevated privileges, leading to `Cannot find module .../.claude/skills/impeccable/scripts/ load-context.mjs` (issue #140). It also collapses meaningful per-provider differences between the two directories (Claude-specific frontmatter, command prefix, paths) into a single shared file. The skills CLI's `--copy` flag installs each provider's variant separately without any symlinks, fixing both problems at once. Fixes #140. Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
4027e17f4c |
chore: bump jsdom to 29.1.1, drop border-radius shorthand workaround (#154)
jsdom 29.1.1 ships two fixes that unblock this: - 5f66329: Fix background-origin/background-clip in background shorthand - ad8af77: Fix border shorthand handling The `resolveBorderRadiusPx` fallback chain (inline-style scan, stylesheet walk) was only needed because jsdom 29.0.x returned "" for `style.borderRadius` when the value came from a CSS shorthand rule. With 29.1.1 the computed shorthand value resolves correctly, so the plain `parseRadiusToPx(style.borderRadius)` path succeeds and the fallbacks are dead code. Test suite confirms 173/173 unit tests and 23/23 jsdom fixture tests pass with the simplified function. Closes jsdom/jsdom#4153 (from our side). Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
dc715c7359 |
craft + codex: explicit user gates before code (Codex test fix)
A live Codex test against v3.1.0 caught the model skipping both shape questions (when PRODUCT.md was present) and image generation entirely, going straight to implementation after the compact shape brief. The loophole: "confirm or override" at the end of compact shape reads as the final gate, even though codex.md adds four more gates before code. Three tightenings: - craft.md: new "Gates: do not compress" section at the top that names the four gates explicitly (shape brief, direction questions, palette, mock approval). Compact shape's closing line now says it advances to Step 3 and codex.md, not Step 4. New precondition at the top of Step 4 forbids mentioning implementation, file paths, or patch plans until codex.md Steps A-D are complete. - codex.md: new "Four stop points before code" intro listing the user-facing gates as a numbered checklist. Step A now says it's required even when shape just produced a confirmed brief; the shape and Step-A questions cover different ground. Explicit STOP markers added to Steps A, B, and D. - Changelog: v3.1.0 "Shape gates restored" bullet rewritten as "Shape and craft gates strengthened" to cover the additional craft.md sequencing. Retagging v3.1.0 to include this fix rather than cutting a 3.1.1 since the original tag is minutes old, no marketing went out, and the gate work is what the asset-producer story needs to actually work in Codex. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>skill-v3.1.0 |
||
|
|
23b6b9cc0e |
chore(cli): bump to v2.1.9 + changelog
Patch bump. Detector adds the body-text-viewport-edge rule (29 total) and fixes a class of false positives in modern token-based codebases (OKLCH and var() resolution, anchor inheritance). Live screenshot overlay no longer flashes solid black during loading. The "live mode survives disconnects" CLI work and the italic-serif / hero-eyebrow-chip rules from PR #129 already shipped in the v3.0.7 skill release notes, so they're not re-announced here. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>cli-v2.1.9 |
||
|
|
735a0f4e4f |
chore(skill): bump to v3.1.0 + changelog
Minor bump because the changes since v3.0.7 are genuinely additive: - Native subagent cross-compile pipeline and the Codex impeccable_asset_producer agent (Codex-only by design). - Critique persistence: per-target snapshots, ignore.md, polish reads matching snapshot as additional signal. - Codex-specific image flow extracted to reference/codex.md with the palette-first gate; craft.md is leaner for non-Codex. - Detector: body-text-viewport-edge rule (29 total), OKLCH/var-resolution and anchor-inherit FP fixes. - Brand register: inverse test and cultural-symbol palette guardrail. - Shape gates restored where weakening had crossed the line (image-gen announcement, explicit brief confirmation). Hero version link and full-history block updated. Manifests and harness SKILL.md frontmatter all on 3.1.0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
8cef296996 |
craft + codex: extract Codex-specific image flow into codex.md
Codex is the only harness today with native image generation (image_gen) and the shipped impeccable_asset_producer subagent. The detailed mock/palette/asset workflow only applies there. Inlining it in craft.md made every non-Codex harness read past 49 lines of instructions it can't act on, and weakened the Codex-specific guidance by averaging it down to a cross-provider lowest common denominator. Split: - New skill/reference/codex.md: Steps A-F covering direction exploration, palette-first generation, mock generation against confirmed palette, approval loop, mock-fidelity inventory, and asset slicing via the impeccable_asset_producer subagent. Adds the "palette first" forcing function that wasn't in craft.md before; locking the palette before any mocks is what stops generated comps from drifting. - craft.md Step 3 is now a one-line conditional: if the harness has native image generation, load codex.md and follow Steps A-F. If not, state in one line that the step is being skipped because the harness lacks native image generation, then proceed using the brief as the visual reference. Same announcement-required pattern as shape.md. - craft.md Step 4 (asset extraction) is absorbed into codex.md Step F. Steps renumber: 5 (build), 6 (iterate), 7 (present) become 4, 5, 6. Net: craft.md goes from 155 lines to 106 lines for non-Codex providers. Codex gets a sharper 92-line image flow with the palette-first gate that wasn't there before. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
afc974d630 |
shape: restore image-gen announcement + explicit brief confirmation
Two specific gates that
|
||
|
|
93a13f9882 |
Critique persistence: per-run snapshots, ignore list, polish reads as signal (#153)
* critique-storage: new helper for per-run snapshot persistence Adds skill/scripts/critique-storage.mjs with: - slugFromTarget(): mechanically derive a stable slug from a resolved file path or URL (NOT from the user's natural-language phrasing), so the same target lands in the same stream across runs even when dev-server ports drift or the user phrases it differently. - writeSnapshot(): writes .impeccable/critique/<timestamp>__<slug>.md with a small YAML frontmatter (timestamp, slug, target, total_score, p0_count, p1_count) plus the report body. - readLatestSnapshot(): newest snapshot for a slug, used by polish. - readTrend(): last N frontmatter entries for a slug, used by critique to print the score trend line. - readIgnoreList(): non-empty non-comment lines from ignore.md, the ONLY input critique consumes from prior runs. No separate index.json. The snapshot files are the single source of truth; trend reader globs them and parses frontmatter. Deleting a snapshot removes it from the trend cleanly with no orphan rows. CRITIQUE_DIR constant + getCritiqueDir / getCritiqueIgnorePath added to impeccable-paths.mjs alongside the existing live-dir helpers. 19 unit tests in tests/critique-storage.test.mjs cover slug stability, URL and file inputs, round-trip read/write, trend filtering by slug, and ignore-list parsing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * critique: persist snapshot per run, respect ignore.md Two new steps wired into the critique flow: - Setup: Resolve Target and Load Ignore List. Before gathering assessments, resolve the user's natural-language target ("the homepage") to a concrete artifact, compute the slug via critique-storage.mjs, and read ignore.md. Matching findings drop silently from the report. This is the only prior-run input critique consumes; anchoring on prior findings would defeat independent assessment. - Persist the Snapshot. After the report is finalized (before Ask the User), write it to .impeccable/critique/<ts>__<slug>.md with structured frontmatter, then surface a one-line trend ("Trend for index-astro: 24 → 28 → 32") and the written path. First run says "no trend yet". Persistence is fire-and-forget; failures print and move on rather than blocking the rest of the flow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * polish: read latest matching critique as fix backlog When polish is invoked after critique on the same target, the critique's P0/P1 findings are the right backlog; don't re-derive them. Adds a Setup step that resolves the target, computes the slug via critique-storage.mjs slug, and reads the latest matching snapshot via critique-storage.mjs latest. Found → use those P0/P1 items as the polish backlog and mention the snapshot path. Not found → proceed independently from a clean slate. Explicitly does NOT read snapshots for other targets (cross-target context is pollution). Explicitly does NOT cascade to atomic moves (bolder, quieter, clarify, animate, etc.); those act on a specific selection where the page-level critique would be noise. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * gitignore: .impeccable/critique/, opt ignore.md back in Per-run critique snapshots are local artifacts (same precedent as .impeccable/live/sessions/), but ignore.md carries user-curated deferrals that may be worth sharing across a team. Negate-pattern keeps it trackable while the snapshot files stay local. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * polish: reframe prior critique as additional signal, not backlog Three corrections to the previous polish.md addition: - "Polish is usually invoked after critique" is wrong; people polish without ever running critique. Dropped the presumption. - "This is the only command that auto-reads prior critique" leaks cross-command scope into polish's reference file. Dropped. - Treating critique findings as THE polish backlog biased polish to only fix what critique flagged, skipping its own checklist. The critique is one input among many; fold its P0/P1 items into the polish list, then do the normal pass. Now lives as a short item 4 in Pre-Polish Assessment ("Pull in any prior critique — optional signal") instead of a top-level Setup section. Less prominent, doesn't presume invocation order. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * critique-storage: drop the ignore subcommand, read ignore.md directly The ignore-list helper did nothing the model can't do inline: read a markdown file, skip blank and #-prefix lines. It added a tool roundtrip for no real value. Other helpers earn their keep by doing work the model can't trivially do (path normalization, filename generation, glob + frontmatter parsing); ignore-list did not. Removed: - `ignore` CLI subcommand - readIgnoreList() module export + its tests - getCritiqueIgnorePath() from impeccable-paths.mjs (now dead code) Critique.md step 3 now just says "read .impeccable/critique/ignore.md if it exists" and explains the format inline. Simpler. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * critique-storage: caller meta cannot override timestamp or slug Spotted by Cursor Bugbot on the PR. writeSnapshot built frontmatter as { timestamp, slug, ...meta } so a caller-supplied meta blob (parsed from the IMPECCABLE_CRITIQUE_META env var) could silently clobber the computed timestamp and slug. The filename keeps the computed values, so the frontmatter would drift from the filename and readTrend would attribute scores to wrong timestamps with no visible error. Swap to { ...meta, timestamp, slug } so internal values always win. Add a regression test that passes corrupt meta and asserts the frontmatter still matches the filename. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
c32daaf3b0 |
fix(site): update GitHub star count to 27k
Live count via GH API is 27,337. Bumps the shared Header component's visible label and aria-label from 24k → 27k. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
e7e923c4ef |
Skill + craft cleanup, detector hardening, native subagent pipeline (#152)
* skill: drop quality tiers, keep the real brand-craft guardrails Codex's craft/brand pass introduced fast/ship/showpiece "quality bars" plus brand-specific build gates, asset ledgers, sub-agent review, and self-graded fallback labels. In practice those tiers became escape hatches rather than craft pressure: the final output should always be 10/10, and the real decision points are splashiness and maximalism, not quality. Removed: - All quality-bar / showpiece / fast / ship framing in shape.md and craft.md - Standalone Brand Direction (#4) and Asset Requirements (#10) sections in shape's brief; renumbered back to 1-10 - The Brand hard rules section in brand.md (folded its real prohibitions into the existing Imagery and Brand bans sections) - Brand-specific build-gate item, mock-fidelity bullet, production-bar bullet, present-step bullet in craft.md - Asset ledger ceremony in craft Step 4 - Review-only sub-agents and "self-reviewed fallback, not independently validated" machinery in craft.md and polish.md - The For brand surfaces, assess hard failures subsection in polish.md and the brand checklist row - tests/brand-showpiece-reference.test.mjs (and its package.json wiring) Kept (the real nuggets): - Asset-substitution prohibition: image-led briefs ship real/generated assets or canvas/SVG/WebGL, not generic CSS panels, cards, bullets, or copy - Repeated tiny uppercase tracked kicker labels as a brand ban - Detector/QA output is defect evidence only, never proof of quality - "What visual assets are real content here?" discovery question - Inspect each major section individually for brand and long-form work - repeated-section-kickers detection rule + fixture - CLI improvements (JSON to stdout, -json/-fast aliases, severity field) - critique.md: npx impeccable detect --json fix Harness output dirs refreshed via bun run build. Full test suite (186) passes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * skill: strip gate ceremony; require shape pause; allow compact briefs The setup gate table and IMPECCABLE_PREFLIGHT banner pushed every craft run through ritual restatement (PRODUCT.md → original prompt → round 1 → round 2 → 70-line "confirmed brief" → critique → summary, all saying the same thing). Replaced with imperative prose that still demands the same work but skips the user-facing telemetry. Specifically: SKILL.md - Drop the Setup gate table and IMPECCABLE_PREFLIGHT banner. - Keep the imperative steps explicitly: load context, identify register and load brand.md or product.md, AND load the matching command reference (craft.md / shape.md / etc.) when a sub-command is invoked. The command-reference step is non-negotiable; without craft.md loaded the agent skips the shape-and-confirm pause. craft.md - Drop the Build Gate / Craft Contract formal sections; replace with one paragraph stating prerequisites. - Step 1 explicitly requires ending the response after presenting the shape output; the user must confirm before any code lands. Allows a compact 3-5 bullet brief when the prompt + PRODUCT.md already pin direction (full 10-section structure reserved for genuinely ambiguous tasks). - Step 3 image gate skips silently when image generation isn't natively available; no user-facing announcement. - Step 6 explicitly legitimizes "first pass clean, shipping" as a valid endpoint and bans inventing fake defects to demonstrate iteration. shape.md - Cap discovery at 1 round by default; second round only when first leaves material gaps. - Adds an "assert-then-confirm, not menu-with-escape" rule: when PRODUCT.md and the prompt make one option obvious, name it and ask for confirm or override instead of enumerating "Restrained / Committed / Or something else?" as a real choice. - Phase 2 brief has two forms now: compact (default for clear briefs) and full structured (genuinely ambiguous). Open Questions can't double as leading-with-Recommend; if you'd write "Recommend: X", decide X. - Image gate same as craft.md. Validated end-to-end with a Haiku skill-on observability run: agent loads craft.md plus the brief's recommended implementation refs, pauses for one productive question (accent color, trace fidelity, CTA), and ships an artifact with zero side-tab violations vs. the original v1 baseline. Cost trades up modestly for that quality. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * craft.md Step 6: Reading the screenshot is the inspection, not taking it A v4 eval run took 4 targeted screenshots (hero, mobile, tablet, query-section) and then never Read any of them back. The agent treated browser_screenshot itself as "I inspected" and shipped without the multimodal feedback loop ever closing. Detector caught the resulting slop (5+ side-tab violations) on adjacent runs that did the same thing. Step 6 now spells out the pattern explicitly: take the screenshot, then Read the resulting PNG so its image content enters the conversation as multimodal input, then critique what you actually see in the image. With a check: "if your critique could have been written without looking at the image, you didn't look at the image." Validated with v5b: agent took 6 screenshots, Read all 6 back, and shipped with zero detector findings (vs the previous greenfield runs that hit 1-12 findings each). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * craft + brand: framework foundation, build-pipeline respect, image verification Three closely-linked additions surfaced by an eval-harness session investigating why the agent always shipped flat single-file HTML and zero imagery on greenfield brand briefs. 1. craft.md gains a new Step 0 "Project Foundation" before Shape. Detects existing framework / component library / icon set and uses what's there. Greenfield: ask the user via AskUserQuestion with sensible defaults framed by the brief (Astro for content/ brand sites, SvelteKit/Next/Nuxt for app surfaces, single index.html only for one-shot demos). Skipping the framework decision and writing flat HTML "to satisfy the spec" produces work that reads as a 2018 prototype regardless of visual quality. 2. craft.md Step 5 production bar gains two bullets: - Respect the build pipeline. Edit source files and run the project's `npm run build`; do not write to build/ / dist/ / .next/ directly with cat/heredoc/Bash redirects. Bypassing the pipeline skips asset hashing, image optimization, code splitting, and CSS extraction. - Verify external image URLs before referencing them. Use an image-search MCP, web-fetch tool, or browser if available; guessed photo IDs ship as broken-image placeholders. 3. brand.md "Imagery" section: - Generalizes the Unsplash URL guidance to "verify URLs before referencing them" with a hierarchy: image-search MCP > web-fetch > confidence-restricted manual selection > fewer photos. - Tightens the tech/dev-tool exception. Old line "zero imagery can be correct" gave models a permission slip. New framing keeps the underlying truth (typography + code + diagrams primarily carry voice) but raises the floor: imagery still earns its place when it serves the brief, and skipping it requires naming the typographic/diagrammatic move that's carrying the visual weight instead. "Zero imagery is the failure mode of laziness, not restraint." Eval-harness corpus that prompted this: 19/19 brand landing tasks shipped 0 images each, including ones where Opus had taste enough to break the dev-tool color default lane. The skill needs to teach both halves of the decision; the harness shouldn't have to nudge. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * detector: body-text-viewport-edge rule + OKLCH/var-resolution + anchor-inherit FP fixes New rule: body-text-viewport-edge flags body paragraphs that render flush against the left/right viewport edges (no container padding). Tested via the new tests/fixtures/antipatterns/body-text-viewport-edge.html fixture (3 flag cases, 5 pass cases) and the test in detect-antipatterns-browser. False-positive class fixes — all jsdom-mode only (real browsers resolve the cascade correctly so these gates stay inert there). Five related gaps that compounded into ~14× spurious contrast findings on Tailwind v4 pages with OKLCH color tokens: • OKLCH parser. jsdom returns the literal "oklch(...)" string from getComputedStyle; the detector now converts to sRGB via Björn Ottosson's matrices. Handles Tailwind v4's compact minified form "oklch(21.5%.02 50)" (no space after %). • var() resolution. resolveBackground + checkElementColors now accept the existing customPropMap and parse `var(--color-paper)` etc. as proper RGB via the new parseColorResolved helper. • bg-color before bg-image. The old order bailed on any gradient ancestor before checking for a solid background-color underneath, causing the body's decorative paper-grain gradient to be measured against instead of the page's actual `bg-paper` cream. • body/html-level gradient → white fallback. When the only opaque ancestor we can read is body/html with a gradient overlay (and jsdom can't decompose `background: var(--paper) gradient` to extract the solid color), return white instead of falling through to resolveGradientStops — which was picking up paper-grain noise colors and using them as the bg. • Anchor-inherit workaround for jsdom :link UA specificity. Tailwind v4's preflight declares `a { color: inherit }` (0,0,1). jsdom's UA stylesheet has `:link { color: blue }` at (0,1,1) and wins the cascade. Real Chrome wraps :link in :where() (0,0,0) so the page rule wins. When the page declares the inherit rule AND we see jsdom's default `rgb(0,0,238)` on an anchor, walk to the nearest non-anchor ancestor and use its color. • Alpha-fallback safety gate. When text has alpha<1 AND we couldn't find an opaque ancestor (effectiveBg null), skip the contrast finding. Covers any remaining FP class the deeper fixes miss. Verified end-to-end against an Opus iter-1 artifact on Tailwind v4 with 14 cream/cream FPs + 2 blue-link UA FPs before; 0 findings after, while the color.html fixture's 12 real low-contrast cases continue to flag (verified via direct detectHtml calls). cli/engine/detect-antipatterns-browser.js is the generated browser distribution — regenerated from .mjs via scripts/build-browser-detector.js (no manual edits to the generated file). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * craft.md: tighten verbose passages, de-codex Step 6, cut redundancies Cumulative reduction: 218 → 155 lines (-29%). Step 0: drop the "Why this matters" paragraph at the end. The body of Step 0 already makes the framework-pick point; the paragraph just re-explains it with extra rhetoric. Step 1: replace the 4-sentence "you must end your response" block with a single line. The original said the same thing three different ways. Step 3: trim the conditional / defensive scaffolding (Purpose subsection, "do not skip because the eventual UI is semantic..." paragraph, duplicated approval-loop guidance). Mock fidelity inventory preserved. Step 4: drop the "keep UI text semantic" sentence; it duplicates Step 5's "Semantic first" rule. The rasterized-vs-semantic decision rule stays. Step 5: tighten each production-bar bullet to bold-lead + specifics format. All 15 rules preserved (real content, mock ingredients, semantic first, spacing/alignment, typography, state coverage, interaction quality, icon set, build pipeline, image URL verification, optimized imagery, premium motion, maintainability, technical cleanliness, ask-when-uncertain). Step 6: rewrite around "look at what you built like a designer would — your eyes are whatever the harness gives you." Drops Codex-specific "In Codex, use browser-use" bias. Drops the verbose 3-step Read pattern (condensed to one sentence). Drops the 1-8 numbered checklist (replaced by a tight paragraph). Keeps the load-bearing rules: read the PNG, don't fabricate iteration, mock fidelity reference, exit bar = studio defensibility. Step 7: drop the closing "Iterate based on feedback. Good design is rarely right on the first pass" preachy filler. All em-dashes converted to semicolons / colons / periods to satisfy the skill prose validator. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * build: native subagent pipeline + Codex-only asset producer Adds an agent cross-compile pipeline alongside the existing skill pipeline. Sources live at skill/agents/*.md; providers that declare agentFormat (codex-toml, claude-md) emit native subagent files. An optional providers: <list> field on an agent gates which harnesses get a copy; default (no field) ships everywhere. The impeccable-asset-producer agent is opt-in to Codex only. It's useful for Codex's native image generation path and is untested elsewhere; Claude has no native image gen anyway. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * brand: inverse-test + cultural-symbol palette guardrail Two additions to the brand register reference: - Inverse slop test: describe the page the way a competitor would describe theirs. If that sentence fits the modal landing page in the category, restart. - Palette guardrail: when a cultural-symbol palette is the obvious pull, reach past it. Let cultural reading come from typography, imagery, and copy. Harness mirrors regenerated; some also catch up to the image- verification paragraph from |
||
|
|
e587004ee4 |
Refactor: cleaner top-level directory structure (#138)
* refactor(content): merge content/site/ into site/content/ Phase 1 step 1 of the directory restructure. The dual content tree was called out in CLAUDE.md as cleanup; both trees were already in sync except for anti-patterns-catalog.js, which moves to site/data/. - Delete content/site/skills/ and content/site/tutorials/ (duplicates of site/content/, which is what Astro's content collection actually reads). - Move content/site/anti-patterns-catalog.js -> site/data/. - Update scripts/lib/sub-pages-data.js and scripts/build.js to read from site/content/ and site/data/. - Drop content/site/ from validateProse target list (site/content was already there). - Rewrite the "Two content trees" section in CLAUDE.md as a single-tree pointer; update stale dev-server text mentioning the deleted server/index.js. Tests: 186/186 pass. Skills build: clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(skill): rename source/skills/impeccable/ -> skill/ Phase 1 step 2 of the directory restructure. The path was redundantly nested ("source/" wrapper plus "skills/impeccable/" — singular content hidden behind the plural). Collapses to flat skill/SKILL.md + skill/reference/ + skill/scripts/. - Move source/skills/impeccable/ -> skill/. - Rewrite scripts/lib/utils.js readSourceFiles(): drop the multi-skill iteration (CLAUDE.md commits to a single user-invocable skill); read skill/SKILL.md directly. - Update scripts/build.js, scripts/generate-og-image.js, and the sub-pages data layer to point at skill/. - Update tests/lib/utils.test.js: drop the "multi-skill" and "dir-name fallback" cases, update single-skill paths to skill/. - Update tests/build.test.js similarly: drop "multiple skills" integration test, update paths. - Update non-glob path joins in tests/framework-fixtures.test.mjs, tests/live-e2e/session.mjs, tests/live-e2e/agents/llm-agent.mjs, tools/live-loop.mjs. - Update prose/text references in CLAUDE.md, AGENTS.md, DEVELOP.md, README.md, scripts/lib/sub-pages-data.js, bin/commands/skills.mjs, site/data/anti-patterns-catalog.js, site/pages/docs/[...slug].astro, docs/adr-live-variant-mode.md, docs/plans/. Eval framework note: the separate impeccable-evals repo reads ../impeccable/source/skills/impeccable/ and needs a coordinated rename to ../impeccable/skill/. Tests: 186/186 pass. Skills build: clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor: rename docs/ -> notes/ Phase 1 step 3 of the directory restructure. The internal docs/ dir (ADRs and plans) clashed with the site's /docs route. Renaming it "notes/" makes the difference unambiguous: notes/ is project-internal process, /docs is the user-facing route under site/pages/docs/. No code references the dir; the rename is a clean git mv. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(site): move public/ under site/public/ Phase 2 step 4 of the directory restructure. Public assets and the Astro publicDir now live alongside the rest of the site, so site/ is fully self-contained for static content. - git mv public site/public. - astro.config.mjs: add publicDir: './site/public'. Astro defaults to ./public at the project root, so the override is required. - scripts/build.js: write generated _data, _headers, _redirects, _routes.json, and js/detect-antipatterns-browser.js into site/public/. Also delete the dead _REMOVED() Bun static-site builder (replaced by Astro at #130; the placeholder no longer earns its keep). - scripts/build.js validateProse: replace the stale public/index.html reference (deleted at the Astro migration) with site/pages/index.astro in the count-validation file list, restoring homepage drift detection. - scripts/generate-og-image.js: write OG image into site/public/. - scripts/screenshot-antipatterns.js: read examples from + write screenshots to site/public/antipattern-{examples,images}/. - scripts/lib/sub-pages-data.js: load command demos from site/public/js/demos/commands. - .gitignore: rename the public/* generator-output entries to site/public/*. - CLAUDE.md: refresh CSS/data-file paths (still pointing at the old pre-Astro public/css/ + public/js/ tree), point the changelog and command-add checklists at site/pages/index.astro and site/scripts/data.js + site/scripts/components/framework-viz.js. Cloudflare Pages note: functions/ stays at the repo root because CF Pages auto-discovers it there with no configuration knob to relocate. Moving it under site/ would either break deployment or require a build-time copy step that adds more complexity than the cleanup is worth. Tests: 186/186 pass. Skills + site build clean. _headers, _redirects, _routes.json, _data/ all land in build/ correctly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(cli): consolidate bin/ + src/ + lib/ under cli/ Phase 2 step 5 of the directory restructure. The CLI surface was split across three top-level dirs whose names were easy to mistake for each other (especially src/ vs source/ pre-step-2). Consolidates under cli/. - git mv bin -> cli/bin (CLI entry + skills sub-command) - git mv src -> cli/engine (detect-antipatterns engine + browser variant) - git mv lib -> cli/lib (download-providers helper) Update package.json: - bin.impeccable: cli/bin/cli.js - main + exports: cli/engine/detect-antipatterns.mjs and the ./browser variant - files: ["cli/", "LICENSE"] Update internal references: - cli/bin/cli.js: dynamic import points at ../engine/, package.json read goes one level deeper (../../package.json). - functions/api/download/[type]/[provider]/[id].js + bundle/[provider].js: cli/lib/download-providers.js path. - scripts/build.js, scripts/build-browser-detector.js, scripts/build-extension.js: cli/engine path constants. - scripts/lib/sub-pages-data.js, scripts/lib/utils.js, skill/scripts/ live-server.mjs: comment refs. - tests/detect-antipatterns{,-browser,-fixtures}.test.{js,mjs}, tests/windows-path-fix.test.js: import + read paths. - AGENTS.md, CLAUDE.md: doc paths. Verified: - npx node cli/bin/cli.js --version, --help, detect --help all work. - bun run build, bun run build:browser, bun run build:extension all clean. Browser detector lands at cli/engine/detect-antipatterns-browser.js; extension/detector/detect.js still emits to the same location. - bun run test: 186/186 pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: update browser-detector paths missed in cli/ rename Bugbot caught two runtime path leaks where the comment got renamed to cli/engine/ but the actual code still used the old src/ segment. - skill/scripts/live-server.mjs: detectPaths array now joins cli, engine, detect-antipatterns-browser.js for both the repo-relative lookup (4 dirs up from .claude/skills/impeccable/scripts/ to repo root) and the npm node_modules fallback. Without this fix, the detection overlay would silently not load during live-server sessions. - scripts/build.js: the post-build copy of the browser detector into site/public/js/ was reading from src/. The if (fs.existsSync(...)) guard meant the copy was silently skipping, so antipattern-examples pages would 404 on /js/detect-antipatterns-browser.js once the site was deployed. Tests: 186/186 pass. Build clean. site/public/js/detect-antipatterns-browser.js re-emits as expected. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: cleanup-deprecated import path missed an extra .. in cli/ rename Bugbot caught three call sites in cli/bin/commands/skills.mjs that import '../../skill/scripts/cleanup-deprecated.mjs'. Pre-rename, that was correct from bin/commands/ (one parent to bin/, one to repo root). After moving the file from bin/commands/ to cli/bin/commands/, the path is one directory deeper, so it needs three .. segments to reach the repo root. Without the fix, every cleanup invocation throws on import and gets swallowed by the surrounding try/catch — silent skip. cli/bin/cli.js's package.json read already uses '../../package.json' (the same depth pattern), confirming three levels is correct. Verified: dynamic import resolves and exports the expected functions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: sweep stale path/file references missed in the restructure Same root cause as the two bugbot finds: some references in moved or related files weren't tracked because they didn't match a simple sed pattern. Caught the rest by walking each moved dir's depth and each Astro-migration deletion. Stale path references (post-Astro migration, missed earlier): - CLAUDE.md: legacy URL redirects "live in server/index.js" -> point at the actual sources (scripts/build.js generateCFConfig + site/public/_redirects). - AGENTS.md: counts.js path (public/ -> site/public/), changelog file (public/index.html -> site/pages/index.astro), screenshots note (public/ -> site/), source-of-truth dirs (source/, src/ -> skill/, cli/). - tests/detect-antipatterns-browser.test.mjs: comment about routes "in server/index.js". - skill/reference/live.md: workflow.css example for "this repo" was pre-Astro (public/css/) -> site/styles/. (User-project Vite/Next example unchanged.) Stale path that pointed at moved files: - tests/skills-cli.test.js: CLI path was '..', 'bin', 'cli.js'; now '..', 'cli', 'bin', 'cli.js'. Test isn't wired into bun run test but it would have failed if invoked. Dead files (orphaned by Astro migration, never cleaned up): - tests/server/download-validation.test.js: imported from ../../server/lib/{validation,api-handlers}.js which were deleted in |
||
|
|
2aeac48b19 |
chore: track .impeccable/live/config.json for this repo
Live mode injection config for the Astro site (Base.astro, before </body>, HTML comment syntax). The .gitignore already permits tracking generated sidecars; this commit makes the choice explicit so contributors get the same wiring on first run. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
f7ab774fe4 |
fix(release): read changelog from site/pages/index.astro after Astro migration
The release script still pointed at public/index.html, which the Astro migration deleted. The changelog lives in site/pages/index.astro now. The substring extraction logic works unchanged because the source contains the same markup that the build emits. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>skill-v3.0.7 |
||
|
|
8e3d4d2b04 |
chore(skill): bump to v3.0.7 + changelog
- Detector: italic-serif display heroes and hero eyebrow chips (#129, contributed by @vinaypokharkar). - Live mode: durable session journal, status/resume/complete commands (#125, contributed by @nqh-packages). - Reference files: stripped "Remember:" closer chants, brochure-style openers (12 files), and 419 em-dashes. Less context per command load, less repetition the model reads past. Refresh harness output dirs and plugin/ subtree. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
d874af046a |
feat(live): make live sessions recoverable (#125)
* feat(live): make live sessions recoverable tired of live mode losing the plot when the browser moved faster than the agent. now the state is boring: journal it, resume it, finish it. --- - add durable live-session journal, checkpoint events, and status/resume/complete commands - split browser session storage into a testable helper and harden accept/discard completion - fix Astro live CSS preview mode and add recovery/live E2E coverage - declare Bun as the package manager and add a Bun-native audit script * fix(live): acknowledge fallback recovery states * fix(live): flush recoverable handoffs promptly * fix(live): keep recovery handoffs accurate * fix(live): preserve poll reply metadata * fix(live): treat event HTTP failures as failed sends * fix(live): acknowledge manual completion through helper * Add .impeccable project state paths * Fix live disconnect recovery phase * Refine live CSS authoring contract * Test live CSS authoring guidance * Harden live LLM E2E recovery * Fix live recovery review issues --------- Co-authored-by: Paul Bakaus <paulbakaus@pauls-mbp-3.lan> |
||
|
|
88b82ae5f5 |
Remove Tessl skill review workflow (#136)
Co-authored-by: Paul Bakaus <paulbakaus@pauls-mbp-3.lan> |
||
|
|
ea930268a8 |
docs(skill): apply STYLE.md to source/skills/impeccable (#135)
Follow-up to #134, which scoped validateProse to user-facing copy and left the LLM-facing skill files alone. Bring those to the same bar, phased so hardening repetition stays intact. - Em dashes: 419 → 0 across SKILL.md and 35 reference files. Each replacement picks the right relationship (colon, semicolon, period, or parens) instead of letting the dash hide the choice. - Closer cleanup: deleted or rewrote the "Remember:" sermonettes that were pure adjective chants (bolder/quieter/clarify/delight/extract/ colorize/layout/typeset/audit/adapt). Survivors that load-bear an instruction now hand off to /impeccable polish instead of summarizing. - Opener taglines: rewrote the "[Verb] [object] to [outcome]" brochure openers in 12 older files to lead with the failure mode, the strongest claim, or a directive. Newer files (live, brand, product, audit, critique, harden) kept their existing openers. - data-driven: rephrased the two technical hits in live.md so the validator can stay strict on this term. - validateSkillProse: narrow validator scoped to source/skills/impeccable/. Em-dash check + the small denylist of phrases with no technical reading. Hardening repetition and structural-prose rules are deliberately not enforced — those need human judgment. Test failure on detectUrl is pre-existing (puppeteer needs --no-sandbox when running as root); unrelated to these changes. https://claude.ai/code/session_013zZY6rbB1bS8z3D63rX5hW Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
122a82f715 |
docs: strip AI prose, add STYLE.md and validateProse (#134)
Site copy was being called out as AI slop (specifically the word
"load-bearing"). Five-pass cleanup with a build validator to keep it
from creeping back.
Pass 1 — mechanical purge:
- Remove "load-bearing" from impeccable.md, brand.md, live.md,
iterate-live.md
- Remove "highest-leverage" from critique.md, typeset.md, designing
- Remove em dashes from all 9 slop-page rule cards
- Replace "leverage" verb in personas.md
Pass 2 — rewrite the worst offenders:
- Changelog v2.0 "Data-driven skill rewrite" entry: drop "data-driven",
"frontier models", "collapses into monoculture", "biggest unlock",
"reflex defaults"; name the actual mechanism
- README opener: drop "deeper expertise and more control"; replace with
three concrete differentiators (7 reference files, 23 commands, 27
detection rules)
- Neo Mirai case study opener: action-first, name the image model used
Pass 3 — editorials:
- Fix negation pivot in distill.md ("simplicity is not about ... It is
about ...")
Pass 4 — homepage why-panels:
- Foundation lead: name the 7 reference files specifically
- Language lead: show the discipline mapping with real command names
- Production-codebases panel: drop "Impeccable isn't a sketchpad"
negation pivot
- Ships-code panel: replace "is native to that world" with "runs there"
Pass 5 — STYLE.md and validator:
- New STYLE.md at root: editorial brief with 12 principles and the
enforced denylist (each rule with a rationale and a suggested
replacement)
- scripts/build.js: validateNoEmDashes becomes validateProse. Adds 21
phrase rules with rationales, catches the \`--\` em-dash substitute,
expands target list to site/pages, site/content, README.md,
README.npm.md
- CLAUDE.md: replace the em-dash section with a STYLE.md pointer and
document the two-content-tree footgun (content/site/ vs site/content/
must be edited in lockstep until they're unified)
Co-authored-by: Claude <noreply@anthropic.com>
|
||
|
|
eecdfa128e |
fix(site): style Astro-rendered <pre> blocks in prose bodies (#133)
The Astro migration switched fenced code blocks from the hand-written `<div class="code-block-wrap"><pre class="code-block">` wrapper to Astro+Shiki's auto-generated `<pre class="astro-code">`. The existing CSS only targeted the legacy class names, so docs and tutorial code blocks rendered with no padding, no border-radius, and no margin. On top of that, the inner `<code>` inherited `.prose code`'s cream pill styling and showed it through Shiki's dark theme. Extends `.prose .code-block` rules to cover `.prose pre`, adds the missing margin and max-width, and resets `.prose pre code` to drop the inline-code background and border. Shiki's inline background color still wins on `.astro-code`, so the box keeps its dark theme; hand-written `.code-block` blocks on the case-study page get the warmer oklch palette as before. Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
ccf3573579 |
fix(site): restore .prose class on docs and tutorial bodies (#132)
The Astro migration (
|
||
|
|
444e4acad3 |
Detector: add italic-serif display headline + hero eyebrow chip rules (#127) (#129)
* feat(detector): flag italic-serif display heroes and uppercase eyebrow chips (#127) Two new rules covering the structural tells of late-2025/early-2026 AI-generated marketing pages. - italic-serif-display: oversized italic serif (Fraunces, Recoleta, Newsreader, Playfair, Cormorant, Tiempos, ...) as the primary hero headline. Anchored on h1 (or h2 at >= 48px) with font-style: italic and a serif primary face. - hero-eyebrow-chip: uppercase letter-spaced label sitting as the previousElementSibling of a hero h1 (font-size >= 48px). Bounded text length 2-30 chars, letter-spacing >= 1.6px, font-size <= 14px. The pill-chip variant (background + border-radius: 999px) falls out of the same gates for free. Both follow the existing icon-tile-stack pattern: pure check function + browser DOM adapter + jsdom adapter, wired into both element loops. Two-column fixtures (4 flag / 6 pass each) drive the jsdom tests. Skill copy in source/skills/impeccable/reference/typography.md and critique.md calls out the patterns by name. The italic-serif rule's description acknowledges that editorial/magazine register may legitimately want the pattern -- judge by context. Closes #127 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Add sandbox gotchas for Codex * Trim verbose detector skill copy --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Paul Bakaus <paulbakaus@pauls-mbp-3.lan> |
||
|
|
b8f09c8142 |
Migrate site from Bun to Astro (#130)
* feat(site): scaffold Astro migration, convert 3 pages Phase 1+2 of the Astro migration: - Astro v6.2.1 installed, srcDir: 'site', static output to build/ - Shared layout: Base.astro (head, fonts, meta, slots), Header.astro (star count in one place: 23k), Footer.astro - CSS moved from public/css/ to site/styles/ (9 files, @import chains resolve via Vite) - Three pages converted: privacy, cases/neo-mirai, live-mode (all return 200 on astro dev) Remaining: designing, slop, homepage, content collections (docs), JS migration, server/index.js deletion, build.js cleanup. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(site): migrate all 6 main pages to Astro Converts the remaining pages: - designing/index.html → site/pages/designing/index.astro (551 lines) - slop/index.html → site/pages/slop/index.astro (909 lines) - index.html → site/pages/index.astro (1278 lines, the homepage) Base.astro gains OG meta tag props, before-header/after-header slots (for grain overlay and section nav), and configurable mainId. Homepage uses link tags to public/css/ instead of frontmatter CSS imports to avoid esbuild choking on :has() in main.css. Curly braces inside <code> elements (CSS snippets in changelog) escaped with HTML entities to prevent Astro JSX expression parsing. All 6 pages return 200 on astro dev. Branch: feat/astro-migration. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(site): content collections for docs and tutorials Replaces the 1532-line build-sub-pages.js generator with Astro v6 content collections: - 24 skill editorial files move to site/content/skills/ - 4 tutorial files move to site/content/tutorials/ - site/content.config.ts defines both collections with glob loaders - site/pages/docs/[...slug].astro reads skills collection + command metadata from source/skills/ at build time - site/pages/docs/index.astro renders the command grid grouped by category (create, evaluate, refine, simplify, harden, system) - site/pages/tutorials/ mirrors the pattern with ordered index - Doc.astro layout provides sidebar nav, breadcrumbs, and related- command chips from the COMMAND_RELATIONSHIPS data - Category/relationship data extracted to site/data/sub-pages-data.ts All 15 tested pages return 200: 6 main pages + 5 docs + 2 tutorials + 2 index pages. The old generator is not yet deleted (Task #6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(site): move JS source from public/js/ to site/scripts/ Moves all 49 JS files (app.js + 48 in js/) into site/scripts/. Vite now processes them through its module bundler instead of serving them raw from public/. app.js import paths updated from ./js/X to ./X (the js/ nesting is gone since app.js now lives alongside the subdirectories). Homepage and live-mode page switch from <script is:inline src="/app.js"> to Vite-processed <script> imports, so tree-shaking, bundling, and minification happen automatically at build time. public/js/ still exists for now (cleanup in Task #6) and the generated/counts.js build output path needs updating there too. @paper-design/shaders added to npm dependencies (was missing). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(site): delete old Bun server, generator, and duplicated files Cleanup after the Astro migration: Deleted: - server/index.js (233 lines, replaced by `astro dev`) - scripts/build-sub-pages.js (1532 lines, replaced by content collections) - scripts/lib/render-page.js (247 lines, replaced by Base.astro layout) - content/site/partials/header.html (replaced by Header.astro component) - public/index.html, privacy.html, designing/, live-mode/, cases/ (replaced by .astro pages in site/pages/) - public/css/ (moved to site/styles/) - public/js/ old source files (moved to site/scripts/) - public/app.js (moved to site/scripts/app.js) Kept in public/: - antipattern-examples/ (standalone HTML demos, not Astro pages) - antipattern-images/, assets/, neo-mirai/ (static assets) - js/detect-antipatterns-browser.js (referenced by antipattern examples) - js/generated/counts.js (build output from scripts/build.js) - _data/api/ (generated API data, now written to public/ so Astro passes it through to build/) Updated: - astro.config.mjs: added redirects (skills->docs, cheatsheet->docs, gallery->slop, neon-mirai->neo-mirai, etc.) - package.json: dev->astro dev, build->build:skills+build:site, preview->astro preview - scripts/build.js: removed buildStaticSite(), generateSubPages(), static-asset copying. API data writes to public/_data/ instead of build/_data/. Site-header validator is a no-op (shared component). Em-dash validator scans site/components + site/layouts, not pages (pages contain content from other sources like detector descriptions). - .gitignore: removed public/slop/ entry Tests: 186/186 pass. Skills build: clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(site): fix redirect config for Astro compatibility Move the dynamic /skills/:id -> /docs/:id redirect to public/_redirects (Cloudflare Pages native format) since Astro's redirect config can't handle dynamic routes that don't match existing page patterns. Remove duplicate trailing-slash redirect entries that caused warnings. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(site): switch remaining pages from /css/ link tags to frontmatter imports Doc.astro, docs/index, tutorials/index, and tutorials/[slug] were still using <link href="/css/sub-pages.css"> which pointed at the deleted public/css/ directory. Switched to frontmatter CSS imports (import '../../styles/sub-pages.css') which Vite resolves from site/styles/. Homepage also switches from link tags to frontmatter imports for main.css and sub-pages.css — the esbuild error that originally forced the link-tag workaround was caused by unescaped curly braces in the HTML content (since fixed), not by the CSS itself. All pages verified visually in Chrome: homepage hero, foundation grid, docs index (card grid with categories), docs detail (sidebar + editorial content + visual mockups), designing (core loop diagram), privacy, tutorials. Header renders with 23k stars on every page. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(site): fix edge-to-edge sections, broken API paths, CSS links Three fixes: 1. Homepage sections sat on the viewport edge because Base.astro's <main> lacked the site-content class (provides max-width + padding). Added mainClass prop to Base.astro; homepage sets mainClass="site-content". 2. "Failed to load commands" because app.js fetched /api/commands which only existed in the old Bun server's routing. Updated to fetch from /_data/api/commands.json (the static JSON files that build:skills writes to public/_data/). 3. CSS reference fix (previous commit was incomplete): Doc.astro, docs/index, tutorials pages all used <link href="/css/sub-pages.css"> pointing at deleted public/css/. Switched to frontmatter imports. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(site): add sidebar to docs index page The docs index was using Base.astro directly without the skills-layout grid, so it rendered without a sidebar. Added the same sidebar structure from Doc.astro (category-grouped command list) and wrapped the content in the skills-layout grid. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(site): extract footer CSS to shared file, import in Base.astro Footer was unstyled on sub-pages because footer CSS lived only in main.css (loaded by the homepage) not in sub-pages.css. Extracted the 95 lines of footer rules into site/styles/footer.css and imported it in Base.astro so every page gets footer styles regardless of which page-specific CSS it loads. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(demos): move landing-demo into repo, add as slop specimens Moves ~/code/landing-demo/ into demos/landing-demo/ (without node_modules or the redundant .claude/.agents skill copies — the repo root's skill is found by walking up). PRODUCT.md, DESIGN.md, DESIGN.json, PROMPT.md, and SCRIPT.md stay in place so running Claude from demos/landing-demo/ picks up the project context. Also copies both pages as slop specimens to public/antipattern-examples/ with the detector script baked in: - new-slop-2026.html (Fraunces + warm cream editorial monoculture) - old-slop-2022.html (purple gradient + glassmorphism + neon glow) These can be linked from the slop page gallery alongside the existing 11 synthetic specimens. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(slop): replace single demo iframe with Then vs Now comparison The "See it" section (01) on the slop page now shows two side-by-side browser frames: 2022 slop (purple gradients, glassmorphism, neon glow) and 2026 slop (Fraunces, warm cream, editorial restraint). Both run the detector overlay live — hover either to see which rules fire. Replaces the single visual-mode-demo.html iframe. Responsive: stacks vertically on viewports below 900px. Caption: "Same engine, different decade, both flagged." Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(slop): switch to single-frame era toggle, center the section Replaces the side-by-side dual-iframe layout with a single large frame and a segmented 2022/2026 toggle. Clicking the toggle swaps which iframe is visible (both pre-loaded, instant switch). Browser chrome title updates to match the active era. Centers the lede text and toggle above the frame for visual cohesion with the full-width iframe below. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(slop): left-align See It section, toggle inline with lede Moves the era toggle to the right of the lede paragraph using a flex row (align-items: flex-end). Left-aligned text + right-docked toggle matches the rest of the page's flow instead of standing out as a centered island. Stacks vertically on narrow viewports. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(slop): left-align iframe, remove max-width and auto margin The visual-mode-preview had max-width: 1040px + margin: 0 auto which centered it within the column. Override both in the .slop-then-now context so the frame fills the full content width flush with the text above. Caption left-aligned to match. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(site): update star count to 24k (24,062) One file, one edit. The Astro migration working as intended. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(build): regenerate pnpm-lock.yaml for astro + shaders deps Cloudflare Pages uses pnpm with frozen-lockfile. The lockfile was stale after adding astro, @astrojs/cloudflare, and @paper-design/shaders via npm. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(build): resolve 3 bugbot review issues 1. Restore public/slop/ to .gitignore — prevents accidental legacy generator output from conflicting with the Astro page. 2. Move astro and @paper-design/shaders to devDependencies — these are site-build tools, not CLI runtime deps. Removes @astrojs/cloudflare entirely (unused; static output mode needs no adapter). 3. Fix Astro wiping build:skills output — CF config (_headers, _redirects, _routes.json) and API data now write to public/ so Astro copies them through. Dist ZIPs copy to build/_data/dist/ as a post-build step (after Astro finishes). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(build): merge duplicate devDependencies, use npx for astro CLI The previous commit created a second devDependencies key in package.json. JSON doesn't support duplicate keys — pnpm ignored the first block (with astro), so `astro build` wasn't found. Merged astro and @paper-design/shaders into the existing devDependencies block. Changed `astro build/dev/preview` to `npx astro build/dev/preview` so pnpm finds the local binary on Cloudflare Pages (which doesn't add node_modules/.bin to PATH by default). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(demos): remove private demo script and prompt from public repo SCRIPT.md contained a detailed conference talk script with personal delivery strategies, rehearsed Q&A answers, and venue details. PROMPT.md contained the origin brief for the demo page. Neither belongs in a public repo. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(build): gitignore generated public/ artifacts, consolidate redirects 1. Generated files written to public/ by build:skills (API data, CF config, browser detector, counts.js) are now gitignored. Prevents noisy diffs and merge conflicts from committed build artifacts. 2. Removed duplicate redirects from astro.config.mjs. All redirects now live in one place: the _redirects file generated by scripts/build.js (which Cloudflare Pages processes natively). Eliminates the dual-maintenance risk where the two sources could drift apart. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
a312da5ec7 |
fix(site): update GitHub star count to 23k, add changelog highlight reel
Star count was 21k on sub-pages and the header partial, 22k on the homepage. Updated all seven source files to 23k (actual: 23,692). Changelog section gains a curated "Highlights since v3.0" block above the full version history, which now collapses behind a disclosure toggle. Fixes the vertical bloat from 9 entries in three weeks while keeping v3.0's anchor content visible. Also fixes a nesting bug where an orphan </div> from the old changelog-list wrapper prematurely closed the changelog-section, breaking the two-column changelog+FAQ grid layout. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
8c4ea9f0fd |
chore(build): refresh harness output dirs for v3.0.6
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>skill-v3.0.6 |
||
|
|
a08f808edb |
chore(skill): bump to v3.0.6 + changelog
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
f4b2b1b0ca |
fix(skill): remove lane catalog from live departure mode, reinforce params
The seven-lane list in Phase C departure mode was acting as a menu: the model ran "furthest from editorial" as its selection criterion and converged on Swiss-grid / Terminal / Industrial-signage every time. Replaced with a brand-voice derivation process (read personality words, imagine physical experiences, derive visual directions). Explicitly names the failure mode so the model can't fall into it. Phase D family-pass labels are now open-ended nouns, not a fixed vocabulary list that re-anchored the same categories. Reinforced parameter generation: Phase C (both modes) now requires naming 2-3 parameter knobs alongside each variant during planning, not as an afterthought. The freeform bias paragraph aligns with the budget table (2-3 for large compositions, not 1-2) and frames 0-param heroes as mistakes, not judgment calls. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
64c6df216b |
fix(detector): contrast checks run on styled <a> and <button> (v1.0.3)
SAFE_TAGS skipped <a> and <button> categorically to avoid noise on inline links and unstyled controls. The blanket skip overshot: a pill-style anchor or styled button with its own opaque background was silently exempted from the contrast check, so a "Get started" button with charcoal text on near-black background (~2:1) read as fine to both the CLI and the browser overlay. The bail in checkColors now permits <a> and <button> when they have their own opaque background AND direct text. Inline links and bare controls keep skipping. checkElementColorsDOM no longer short-circuits before reaching checkColors so the exception fires on the browser path. Adds readOwnBackgroundColor() helper to handle jsdom's missing shorthand decomposition; falls back to parsing the inline style attr when getComputedStyle returns empty (real browsers always decompose, so the fallback is a no-op there). Fixture gains four cases: pill-style <a> low-contrast (flag), <button> low-contrast (flag), inline <a> with no own bg (pass), pill-style <a> with high contrast (pass). Three new tests assert the right flags fire and the no-regression cases stay clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>ext-v1.0.3 |
||
|
|
d154a5feb3 |
fix(extension): popup scan stuck on Scanning after page reload (v1.0.2)
The service worker's webNavigation.onCompleted handler only cleared csInjected when DevTools was open. The popup-only flow never registered the tab in devtoolsTabs, so a page reload left a stale csInjected: true even though the content script had been destroyed. The next popup scan saw the stale flag, skipped re-injection, and silently sent its scan request to a tab with no listener — popup UI got stuck on "Scanning..." indefinitely. Reset is now unconditional (page reload always destroys the content script regardless of which UI is open). Auto-rescan stays gated to DevTools, since the popup is strictly user-driven. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>ext-v1.0.2 |
||
|
|
ac2237a7a9 |
feat(skill): identity-first variant planning in /impeccable live
Restructures live.md Step 4 into four phases: identity extraction (Phase A, non-skippable, falls back to CSS variables and computed styles when DESIGN.md is absent), default vs departure mode pick (Phase B), variant planning by primary axis or aesthetic lane (Phase C), and a family-level squint test before the sentence pass (Phase D). Default mode preserves identity and varies expression; departure mode only triggers on explicit signals (PRODUCT.md anti-references calling out the current surface, or the user prompt asking for departure). Adds reflex-reject aesthetic lanes to brand.md as a parallel to the existing font reflex-reject list. Editorial-typographic is the first entry. Expands SKILL.md's category-reflex check to two altitudes (theme + palette from category, then aesthetic family from category + anti-references). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
b5c203f38a |
feat(detector): flag Fraunces, Geist, and the new monoculture fonts
Adds Fraunces, Geist (Sans/Mono), Mona Sans, Plus Jakarta Sans, Space Grotesk, Recoleta, and Instrument Sans to OVERUSED_FONTS. Brand-domain exceptions for Geist on vercel.com / nextjs.org / v0.app and Mona Sans on github.com / githubnext.com. Updates four should-pass fixtures that used the now-flagged faces as "good examples"; switches to Newsreader + Karla. Adds positive assertions for Fraunces and Geist. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
856b90e52b |
chore(release): print a tweet-ready string after a successful release
Pulls the bold lead text from each <li><strong>...</strong> in the changelog entry as a tweet-grade summary, fits as many bullets as possible under the 280-char limit (first highlight always wins since it's already the most user-facing line), and prints inside a labeled box with a live char count so the user can copy-paste into @impeccable_ai. Adds tweetHeader and tweetCta to each component config (skill / cli / extension); skill uses the npx skills install line, CLI uses npm i -g, extension drops the CTA entirely (link to the release page is enough since the user has to upload to Chrome Web Store separately). Falls back to header + URL only if even the first highlight overflows. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
c332c7aa91 |
feat(load-context): resolve context dir outside repo root (#119) (#123)
Adds a configurable lookup path for PRODUCT.md / DESIGN.md / DESIGN.json so
they don't have to live at the project root. Resolution order (first match
wins):
1. process.env.IMPECCABLE_CONTEXT_DIR (absolute or relative to cwd)
2. cwd, when canonical or legacy files are at the root (back-compat)
3. Auto-fallback subdirs of cwd: .agents/context/ then docs/
4. cwd as a default "no context found" location
Existing layouts (PRODUCT.md / DESIGN.md at repo root) keep working unchanged
- step 2 preserves the current behaviour. The auto-fallback covers the two
most common conventions seen in the wild (.agents/context/ for AGENTS.md
auto-import setups, docs/ for the request in the issue) without needing any
configuration.
Changes:
- load-context.mjs: export resolveContextDir() and use it inside
loadContext(); add contextDir to the JSON output
- live-server.mjs: import resolveContextDir and read PRODUCT.md /
DESIGN.md / DESIGN.json from the resolved dir instead of process.cwd()
- SKILL.md: short note on the env var and fallback dirs in Setup -> Context
- tests/load-context.test.mjs: 19 cases covering env var, fallbacks,
legacy migration scope, and back-compat
Legacy .impeccable.md -> PRODUCT.md auto-migration stays scoped to cwd root;
fallback dirs are read-only as far as auto-rename is concerned.
Closes #119
|
||
|
|
9a5d0e71a9 |
fix(live): switch live-poll to execFileSync, validate ids strictly (#124)
* fix(live): switch live-poll to execFileSync, validate ids strictly
live-poll.mjs built the live-accept invocation with execSync and string
interpolation of event.id and event.variantId. Both fields originate in
the browser; validateEvent only checked truthiness, so shell metacharacters
in either field would land in the shell-parsed command.
Real exploitability is gated by the per-session token (loopback only,
unguessable UUID), so risk is low. The construction itself is structurally
unsafe though, and the fix is small.
- live-poll.mjs: execSync(string) → execFileSync('node', argv). Drops the
hand-rolled single-quote wrap for --param-values; execFileSync passes
each arg as a discrete argv slot, no shell parsing.
- live-server.mjs validateEvent: tighten id and variantId to match the
actual generator shapes (8 hex chars and 1-3 digit numeric strings).
Defense in depth so any value reaching downstream code is inert by
construction.
- live-server.test.mjs: add three regression tests covering accept/discard
rejection of shell-metachar ids and non-numeric variantIds. Update the
three existing fixture ids to match the new pattern.
Reported in #122.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore: refresh pnpm-lock.yaml to match package.json
Cloudflare Pages runs pnpm install --frozen-lockfile and was failing on
ERR_PNPM_OUTDATED_LOCKFILE: the lockfile was missing entries for
@ai-sdk/anthropic, @ai-sdk/openai, @anthropic-ai/claude-agent-sdk,
@anthropic-ai/sdk, @google/genai, ai, modern-screenshot, zod, and had
stale specifiers for jsdom, marked, playwright, wrangler, puppeteer.
Drift was introduced when package.json was last edited without a lockfile
regen. Running pnpm install --lockfile-only resolves it; verified with
pnpm install --frozen-lockfile (clean install succeeds).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Paul Bakaus <paulbakaus@pauls-mbp-3.lan>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
7e0ce5e6b1 |
ci: add Tessl skill review on SKILL.md changes (#74)
Use tesslio/skill-review to run tessl skill review on changed skills and post results on the PR. No Tessl account required; only GITHUB_TOKEN. Made-with: Cursor Co-authored-by: rohan-tessl <rohan-tessl@users.noreply.github.com> |
||
|
|
18fa503d44 |
fix: normalize quoted user-invocable frontmatter (#87)
* fix: normalize quoted user-invokable frontmatter Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: preserve quoted non-boolean frontmatter values Only normalize quoted booleans for the user-invocable frontmatter flag so other quoted fields like argument-hint and description continue to round-trip as plain strings. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> --------- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> |
||
|
|
04709eadf0 |
security: use JSON.stringify for selector escaping in devtools panel (#93)
The inspectElement function previously used manual replace() chains to escape backslashes and single quotes in CSS selectors before passing them to chrome.devtools.inspectedWindow.eval(). This escaping was incomplete: selectors containing crafted sequences of special characters (backticks, newlines, Unicode escapes) could break out of the string literal and inject arbitrary JS into the inspected page context. JSON.stringify produces a properly escaped JS string literal that handles all special characters, eliminating the injection surface entirely. |
||
|
|
efedf2d3d3 |
Merge pull request #97 from Gujiassh/fix/community-section
docs: add community & ecosystem section |
||
|
|
f67add25e5 |
Merge pull request #120 from vinaypokharkar/feature/qoder-support
feat: add Qoder harness support |
||
|
|
6b507e0c6a |
Release impeccable skill v3.0.5
Live-mode bug-fix release. Closes #114, with thanks again to @dergachoff. - Live mode lands valid TSX through the wrap → preview → accept → carbonize loop on Vite/Next React/TSX projects, including repeated sibling branches and JSX `asChild` parents (Radix `<Title>` etc.). - Wrap correctly disambiguates repeated identical-class siblings via the picked element's textContent (`--text` flag). - Carbonize CSS no longer double-wraps in nested template literals on TSX targets. - JSX accept/discard restores at the picked element's original indent; relative depth between lines preserved through the round trip. - Screenshot overlay during loading no longer flashes solid black on default-background pages. - live-inject's CSP-meta patch+revert byte-for-byte preserves self-closing tag whitespace. - live.md gained explicit guidance on `:scope` descendant combinators (authoring trap), the new `--text` flag, JSX `<style>` template- literal wrapping, and the agent-side abort path.skill-v3.0.5 |
||
|
|
c1e1104e31 |
Merge pull request #118 from pbakaus/feat/live-jsx-wrap-and-carbonize
fix(live): land valid TSX through wrap → preview → accept → carbonize |
||
|
|
1f760aff61 |
fix(live): expandReplaceRange handles multi-line self-closing JSX <div />
Cursor Bugbot review on
|