Merges the impeccable-detect CLI repo (pbakaus/impeccable-cli@831a6cc)
into this repo. The BSL-1.1 license that motivated the split is gone;
everything is now Apache 2.0.
- Add bin/, src/, detection tests and fixtures from CLI repo
- Merge package.json: name → "impeccable", add bin/exports/files fields
- Internal refs now read from local src/ instead of node_modules/
- Update SPDX headers, NOTICE.md, CLAUDE.md, FAQ, npm README
- Add prepack/postpack scripts for CLI-focused README on npm
- Remove terminal license labels (no longer needed)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tier 1: Add Vue/Svelte <style> block extraction and CSS-in-JS template literal
detection (styled-components, emotion) so anti-patterns inside framework-specific
syntax are caught. Enable multi-line context for CSS files so cross-line patterns
like gradient-text are detected.
Tier 2: Build a lightweight import graph when scanning directories. Findings are
annotated with importedBy context (e.g. "imported by App.tsx") in both human and
JSON output.
Tier 3: Detect framework config files (Next.js, Vite, SvelteKit, Nuxt, Astro,
Angular, Remix), probe the dev server port with HTTP fingerprinting to distinguish
the expected framework from unrelated services, and suggest URL-based scanning for
more accurate results.
Adds realistic Next.js project fixtures (Tailwind, CSS Modules, styled-components)
plus Vue, Svelte, JSX, and CSS-in-JS unit fixtures. 158 tests, 356 assertions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Detection improvements:
- Remove SAFE_TAGS from glow check (buttons/links with glows are valid)
- Add gradient color parsing (parseGradientColors) for AI palette
detection on gradient backgrounds including buttons
- Detect cyan neon text on dark backgrounds as AI palette
- Resolve gradient backgrounds as dark for glow detection
- Fix pure-black false positive on semi-transparent overlays (a >= 0.9)
- Skip low-contrast/gray-on-color when background is a gradient
- Fix "Only font:" double-colon in browser labels
Test performance:
- Split jsdom fixture tests to Node's test runner (bun + jsdom hangs
after ~13 instances due to resource leak)
- bun test for unit/regex/CLI tests (94 tests, 4s)
- node --test for jsdom fixtures (15 tests, 1.3s)
- Total: 109 tests in ~5s (was 280s+)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New detections:
- bounce-easing: flags bounce/elastic animation names, animate-bounce
(Tailwind), and cubic-bezier curves with overshoot (y values outside
[0, 1])
- layout-transition: flags explicit transition of width, height, padding,
margin, and max-height/min-width variants; skips transition: all
- dark-glow: flags colored box-shadow with blur > 4px on dark backgrounds
(luminance < 0.1); skips gray shadows, focus rings (no blur), and
non-dark backgrounds
Includes 48 new tests across unit, regex, and jsdom fixture tests with
dedicated should-flag and should-pass HTML fixtures for both categories.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three fixes:
- Only flag innermost nested cards: if L1>L2>L3, only L3 gets flagged
(not L2). Uses ancestor-filtering after collection pass.
- Lower text threshold from 20 to 10 chars to catch short card content
like "Inner card via CSS."
- isCardLike now also checks raw inline style attribute for box-shadow
and border-radius (jsdom doesn't resolve CSS shorthands). Tightened
heuristic: shadow or border is mandatory (not optional).
Fixes false positive on layout-should-pass where a tinted subsection
(rounded + bg, no shadow) inside a card was incorrectly flagged.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Nested cards: fixed dedup to use WeakSet on actual elements instead
of tag-name key, so all nested card instances are found (not just
the first div-in-div pair). Now catches all 4+ nesting examples.
- Dropped identical-card-grid: too many legitimate uses (data displays,
pricing cards, navigation tiles) make false positives unavoidable.
- Removed from CLI, browser script, tests, and ANTIPATTERNS registry.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Four new layout detections:
- nested-cards: jsdom DOM walk finds card-like elements (shadow + rounded + bg)
nested inside other card-like elements. Excludes dropdowns (absolute/fixed),
form inputs, code blocks, badges (<20 chars), and known component classes.
- identical-card-grid: detects grid/flex parents with 3+ children sharing the
same structural fingerprint (icon + heading + paragraph template pattern).
- monotonous-spacing: regex on raw HTML collects padding/margin/gap values
(px, rem, Tailwind classes), rounds to nearest 4px, flags when >60% use
the same value with <=3 distinct values.
- everything-centered: regex counts text-align:center and Tailwind text-center
on text elements, flags when >70% of 5+ text elements are centered.
Also narrowed pure-black-white to only flag #000 as background color —
text-black, text-white, bg-white, and #fff are no longer flagged (too
common, per user feedback).
Extensive should-pass fixture covers: shadcn card sub-components, cards
with form inputs/dropdowns/code blocks/badges/accordions/tabs/images,
pricing cards, varied spacing, mixed centered/left-aligned layouts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Five new detections:
- pure-black-white: flags #000/#fff in styles via regex (jsdom bg
resolution unreliable for this)
- gray-on-color: gray text (low chroma, mid luminance) on colored
backgrounds via getComputedStyle + ancestor bg walk
- low-contrast: WCAG AA violation (4.5:1 body, 3:1 large text) via
computed contrast ratio with resolved effective background
- gradient-text: background-clip:text + gradient combo via regex
(jsdom doesn't compute background-clip)
- ai-color-palette: conservative purple/violet accent detection via
regex on known hex values in prominent contexts
Background resolution handles jsdom limitation where background
shorthand isn't decomposed — falls back to parsing raw style attribute
for hex colors.
Color fixtures added for both should-flag (all 5 types) and
should-pass (tinted neutrals, good contrast, non-purple accents).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Page-level typography checks (flat hierarchy, single font, overused font)
now only run on files that look like full pages (have <!DOCTYPE, <html>,
or <head> tags). Partials and components still get element-level border
checks.
isFullPage() strips HTML comments before checking to avoid false matches
on prose that mentions tag names.
Added partial-component.html fixture that has Inter, flat sizes, and a
side-tab border — verifies only the border is flagged.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Architecture simplified to two paths:
- HTML files: jsdom with getComputedStyle (resolves linked CSS, cascade)
- Non-HTML files: regex fallback (CSS, JSX, TSX, etc.)
- URLs: Puppeteer (unchanged)
- --fast flag forces regex-only for all files
Removed --deep flag (jsdom is now the default). Removed static mode
from browser script (always uses getComputedStyle — it's in a real
browser). Anti-pattern definitions split into:
- checkElementBorders() — shared element-level computed style checker
- checkPageTypography() — shared page-level checker
- REGEX_MATCHERS/REGEX_ANALYZERS — regex fallback for non-HTML
Browser script simplified from 470 lines to 250. CLI script reduced
from 810 lines to 440. Detection logic is now single-source for
jsdom/puppeteer/browser.
Fixtures now served via /fixtures/* route in dev server for proper
CORS handling of linked stylesheets.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three new detections:
- overused-font: flags Inter, Roboto, Open Sans, Lato, Montserrat, Arial
as primary font-family or via Google Fonts imports
- single-font: file-level analyzer flags pages using only one non-generic
font family (needs pairing for typographic hierarchy)
- flat-type-hierarchy: file-level analyzer collects all font-size values
(px, rem, Tailwind text-* classes, clamp min/max) and flags when the
max/min ratio is below 2.0
Detection engine extended to support file-level analyzers alongside
line-level matchers. Typography fixtures added for both should-flag
and should-pass cases.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Anti-pattern detector script (source/skills/critique/scripts/detect-antipatterns.mjs):
CLI tool that scans files/dirs for UI anti-patterns via regex. Detects side-tab
accent borders and border-accent-on-rounded patterns across Tailwind, CSS, JSX.
Context-aware: skips safe elements (blockquotes, nav, inputs, code), neutral
colors, and adjusts thresholds based on border-radius co-occurrence.
- Browser visualizer (public/js/detect-antipatterns-browser.js):
Drop-in script that highlights anti-patterns directly in the browser with
labeled overlays. Two modes: "static" (regex, matches CLI) and "computed"
(getComputedStyle, catches CSS cascade). Scans both inline styles and
<style> blocks.
- Gallery of Shame (public/gallery.html):
Standalone page showcasing 11 AI anti-pattern examples with thumbnails
and links. Anti-pattern example pages updated from 1080x1080 Twitter
format to responsive layouts, labels removed, screenshots retaken at 16:10.
- Critique skill updated to run detector before manual review.
- Build system: skills now support scripts/ directories alongside reference/.
All 8 provider transformers refactored to use shared.js (DRY).
- 58 new tests covering detection logic, fixtures, CLI integration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>