new-work.md section 6 becomes the spec / plates / hero / sections / motion /
responsive phase list, each closed by build-phase.mjs advance; the
reproduction and hero-checkpoint prose that asked the model to compare
from memory is gone. visualize.md's inventory, medium gate, and produce
sections collapse into the spec and plate mechanism. The finish reviewer
takes the state file and comp-diff reports as inputs and starts its
fidelity matrix from the measured verdicts. docs/COMP-FIDELITY.md records
the design.
AI-assisted (Claude).
Co-Authored-By: Claude <noreply@anthropic.com>
Upgrade @babel/parser from 7.29.7 to 8.0.4 and raise the repository Node 22 minimum from 22.12.0 to 22.18.0 across package metadata, CI, and npm documentation.
No parser API migration was required. Validated with the full local suite and refreshed GitHub CI on Node 22.18.0 and Node 24.
Prepared and validated with AI assistance from OpenAI Codex under maintainer instructions.
single-font's retirement made the detector 59 rules; both READMEs still
said 60 in five places, and the count validator reported clean because
'deterministic detector rules' puts a word the regex never expected
between the qualifier and the noun, and README.npm.md was never in the
checked file list. The regex now tolerates the detector infix, counts
qualified 'issues' claims, and README.npm.md joins the list.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Flags the decorative low-opacity chromatic radial-gradient "spotlight"
washed behind a hero or section and fading to transparent, an AI-slop
reflex the saturated radial-halo gate lets slip (e.g. rgba(80,111,255,
0.26) -> transparent on a mobile hero).
Gates: a non-repeating radial-gradient whose last stop is transparent,
whose visible stops are all low-opacity (alpha < 0.45) with at most two
of them, at least one chromatic (channel spread >= 24 exempts neutral
vignettes), on a decorative-scale surface (width >= 240, height >= 160,
exempting badges/avatars/small lights). The alpha band is disjoint from
radial-halo (>= 0.7), so the two never double-report.
Wired into both element loops (static-html + injected browser) with the
pure checkRadialSpotlight shared by both adapters. TDD fixture with 5
flag / 9 pass shapes. Browser-path sweep over the eval corpus: 29 hits
on 11 pages, 0 false positives. Count 59 -> 60.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two browser-engine quality rules, both warning severity.
text-occlusion / element-overlap fires on three shapes: an opaque
decorated box painted over a text element (elementFromPoint confirms
real coverage, box >= 30%), one text run buried under another when at
least one side is a positioned layer (text >= 45%, so line-box leading
bleed between stacked flow blocks does not count), and an inline element
whose opaque fill leaks past its line onto a neighbour (the class-name
collision bug). A large headline whose edge overhangs a bounded content
card is caught as an element collision even when the text stays on top.
Gradient scrims, decorative SVG emblems, fixed/sticky overlays, floats,
and raw image backdrops (contrast territory, deduped against the pixel
low-contrast rule) are exempt.
first-viewport-column-overflow fires when a multi-column opening section
runs one column past 140% of the viewport while a sibling fits inside
one screen, the stretched-hero signature. Single-column pages and
full-page heroes with no fitting sibling are exempt.
Validated: fires on the diagnosed repros, clean across a 60-sample
sweep. Fixtures + browser tests added.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Item 1 (hero liveness theater):
- pulsing-dot now merges declarations per selector across rule blocks
(cascade-approximate), descends into media queries, and strips
prefers-reduced-motion: reduce overrides before the predicate runs.
Catches the shipped split-block constructions (size in the base rule,
animation added later or inside a no-preference media block).
- Dots whose element sits inside a header/nav landmark are promoted to
error severity (string-level landmark ranges in both engines); the
browser engine additionally promotes dots resting in the first ~900px.
- blinking-cursor findings in the first ~900px or inside header/nav are
promoted from advisory to warning.
- Per-finding severity overrides now flow through static-html,
browser-injected serialization, and detect-url.
Item 2 (nav-CTA contrast constructions):
- The a24-opus 01/002 header CTA already fires (specificity cascade +
oklch + var() all resolved); systematic sweep found two remaining
escapes and closes both:
- own gradient background on a SAFE_TAGS element (checkColors styled-
control exception now treats an own gradient as an own surface,
contrast measured against the worst stop)
- ::before/::after full-cover surface (static cascade marks pseudo
surfaces; browser adapter reads the pseudo computed style) so text is
measured against the surface the browser actually paints
- nav-cta-constructions fixture locks all eight computable construction
families; background-image: url() remains unflaggable by design.
Item 3 (shape-assembled-illustration, slop/advisory):
- New rule for large inline SVGs composing a pictorial scene from >= 8
primitive shapes at >= 200x200 intrinsic size with >= 3 distinct fills.
Charts (axis labels), stroke-only technical drawings, icons/logos
(small explicit size), and pattern-tiled backgrounds are exempt.
1.8 percent fire rate over the 3069-sample eval corpus, all verified
pictorial scenes; zero fires across val-a22/val-a24.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three new rules and three widenings, all from confirmed eval-corpus
escapes found by eye:
script-error (quality, error severity, URL engine): pageerror listener
attached before goto catches uncaught exceptions AND parse errors (a
syntax error fires during the initial parse, long before load). Deduped
by message, capped at 3. A JS typo was silently deleting whole pages.
content-hidden-at-rest (quality, error, URL engine): after the main
at-rest scan, an instant-scroll reveal sweep (bypasses scroll-behavior:
smooth, which silently defeated the first sweep design) gives every
IntersectionObserver reveal its chance to fire, returns to top, then
measures the share of text characters still at opacity 0 / visibility
hidden. display:none / [hidden] / aria-hidden subtrees stay out of the
denominator. Fires above 30% with a 200/150-char floor. Calibration on
30 corpus samples: broken repro holds 83% after the sweep, all clean
samples (including 0.75-0.93 at-rest reveal pages) drop to <= 7%.
edge-flush-cards (quality, warning, browser): cards with their own
opaque background or 2+ borders inside a horizontal scroller, flush
against one edge of the clip box at rest (< 8px, > -24px so deliberate
mid-card peeks stay exempt) while keeping a gutter on the other side.
Grouped per scroller. Repro: transit-mobile pager whose first snap
panel is 407px wide inside a 390px clip. New --viewport WxH CLI flag
makes mobile-width URL scans reachable (--viewport 390x844).
Chip/badge contrast widening: the SAFE_TAGS styled-button exception in
checkColors now covers any text-bearing element painting its own opaque
background at >= 9px font, not just a/button. The shipped miss: a span
SEV-2 chip whose white text lost a specificity fight and rendered
muted-on-red at 1.2:1. Static adapter also resolves var() own-bg via
the custom-property map so the gate engages on token backgrounds.
background:none cascade fix: the background shorthand now resets
background-color/-image when it names neither (and no var()). Exposed
by the chip widening: pre code { background: none } left an earlier
surface color standing and manufactured 1.1:1 phantom findings.
text-overflow inline-owner widening: inline elements have no client
geometry (clientWidth 0) so the scrollWidth path never saw them, and
their block parent owns no direct text. New branch measures the inline
rect against the nearest block container's padding box (16px floor,
transform-path exempt). Repro: nowrap span.v spilling 45px past its
grid cell.
The round-3 nav-CTA contrast escape (val-a22-opus obs 003 header CTA)
was verified already covered at HEAD by the earlier parseAnyColor
oklch fallback; both engines fire 3.6:1 on the repro, no change needed.
FP sweep across 36 val-a21/a22/a23 samples: new rules fire only on
their repros (script-error also catches a second genuinely broken
sample); static-engine delta is limited to the chip repro plus two
borderline-but-real chip findings on one sample.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
heading-rhythm (quality): a heading binds to the content it introduces,
so its rendered space above must exceed its space below. Browser-only:
measures real getBoundingClientRect gaps (margin collapsing, flex rows,
and section padding make authored margins untrustworthy), merges eyebrow
labels into the heading cluster, requires same-column edges, and exempts
first-in-container headings, bounded bands, and small cards. Fires only
when 2+ headings on a page invert the rhythm.
blinking-cursor (slop, advisory): a decorative blinking caret (solid
block, underscore bar, or block glyph) bound to an infinite blink
animation in the landing region of a page. Real editable surfaces
(contenteditable, role=textbox, inputs) are exempt; round pulsing dots
stay with the pulsing-dot rule.
Verified against eval corpus repros: heading-rhythm fires on the
val-a18 observability sample Paul flagged (6 headings, 0px above vs
40px below) and blinking-cursor on the val-a19 hero terminal cursor;
10 other samples across both runs stay clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Four gaps found shipping in Opus 4.8 eval samples during human review:
1. low-contrast (extended): the browser adapters parsed text/own-bg
colors with parseRgb only, so Chrome's oklch()-serialized computed
colors silently skipped every contrast check — a flat dark-on-dark
nav CTA (broader nav selector beating the button class) shipped at
1.5:1 undetected. checkElementColorsDOM and readOwnBackgroundColor
now fall back to parseAnyColor. Near-threshold ratios print two
decimals so a 4.497 finding no longer reads "4.5 needs 4.5".
2. NEW numbered-section-labels (slop, advisory): tiny (<=13px) styled
numeric index labels riding beside section headings, repeated across
2+ sections with distinct indices. Sibling of repeated-section-kickers
(which deliberately excludes bare numeric labels); handles both the
direct prev-sibling shape and label-before-heading-wrapper shape.
List/nav/table/card-item numbering is exempt.
3. side-tab (extended): the vertical pseudo-element stripe scan required
the stripe to touch both corners (top/bottom 0 or height 100%), so a
left accent bar inset a few px from each end evaded it; small end
insets (<=20px each) now count. Added a browser-side pseudo-element
check (getComputedStyle(el, '::before'/'::after')) since runtime-
assigned custom-property colors are invisible to the text scanner.
Selection-state exemptions stay as narrowed: only aria-selected=true /
aria-current / active-class markers exempt, plus button/link
affordances on the horizontal variant.
4. NEW repeated-container-text (quality): the same literal string (>=4
chars, contains letters) rendered 3+ times at 3+ structurally distinct
positions inside one bordered/elevated container. Parallel/templated
repetition (table cells, calendar grids, nav lists, identical sibling
rows) never counts — structural signatures, not word lists.
Verified: each rule fires on its repro sample via the file:// browser
scan; clean eval samples add no new findings (the new low-contrast hits
on other samples are genuine sub-AA oklch button pairs). Full test
suite green; browser bundle regenerated; README/homepage rule counts
bumped 49 -> 51 (docs-integrity test enforces them).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two gaps surfaced by human eval review of real artifacts:
1. side-tab missed the pseudo-element variant. The accent stripe drawn as
an absolutely-positioned ::before/::after (left/right: 0, top+bottom: 0
or height: 100%, narrow width, colored background) uses no border
property at all, so neither the element-level border checks (pseudo
elements never enter the static cascade or DOM walk) nor the
border-left/right regexes could see it. New scanCssTextForPseudoStripe
scans stylesheet text for that shape, mirroring the border rule's
gates: >= 3px thick (<= 12px), chromatic fill (var()-resolved, neutral
dividers skipped), full height against a side edge, with the
blockquote/prose exemptions preserved.
2. New pulsing-dot rule (slop): small circular "live" indicator dots
(<= 16px, border-radius >= 40% or pill values) bound to an infinite
animation whose keyframes vary opacity, scale, or box-shadow — or
pulse/blink/ping names when the keyframes aren't in the scanned text —
plus the Tailwind animate-ping/pulse + rounded-full + tiny-size utility
combo. Rotation-only keyframes (spinners) never flag, including when
they hide behind a pulse-like name.
Both scanners live in checkHtmlPatterns, so the static-html engine and
the browser bundle share the same detection path. Browser/extension
bundles regenerated; docs rule count bumped to 47.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Lower the CLI engine floor to Node 22.12 so npx no longer falls back to stale 2.x releases for Node 22/23 users.
Add Node 22.12 CI coverage while preserving the stable required test check, and document the 3.2.1 CLI release notes including the detector and installer fixes already waiting on main.
AI-assisted-by: Codex
* Add mechanical pre-scan for typeset and layout commands.
Introduce --scope filtering, layout/type rule scopes, DESIGN.md font-size validation, and pre-scan steps in the skill references so agents run detect before LLM judgment.
Fixes#149
Co-authored-by: Cursor <cursoragent@cursor.com>
* Add isolated sub-agent orchestration for typeset and layout pre-scans.
Run the mechanical detector and visual assessment in parallel sub-agents so deterministic findings cannot anchor LLM judgment, matching the critique pattern Paul requested on PR #345.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix: reject bare --scope so detect never scans unscoped by mistake.
When --scope had no value, the CLI dropped the flag and ran a full scan instead of failing, which could silently use the wrong rule set during typeset/layout pre-scans.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix: require both typeset and layout assessments in sub-agents.
Close a loophole where agents ran only the mechanical pre-scan inline by interpreting "running both" as permitting one inline assessment.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Abdul Wahab <abdulwahab@Abduls-MacBook-Pro-2.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
* Add codex-grid-background detector rule
Detects the Codex two-axis grid-line background tell: a single background
value carrying two or more hairline `linear-gradient(... 1px, transparent
1px)` layers (one per axis), usually paired with a repeating
`background-size` cell. Gated behind --gpt like the sibling codex tells,
off by default.
Counts hairline stops within a single background declaration (not across
the page) so unrelated single-axis ruled lines don't add up to a false
flag, and matches the stop directly rather than parsing whole gradient
layers, since colors like oklch(...) carry nested parens.
Extends the gpt-tells fixture with one flag case and two pass cases
(single-axis rule, two-color blend), regenerates the browser detector
bundle, and bumps the rule count 44 -> 45.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Require tiling background-size for codex-grid-background
Address review: two hairline gradients alone draw a fixed crosshair, not a
grid. Scope detection to a single style block (CSS rule body or inline
style attr) and require both >=2 hairline stops AND a tiling
`background-size` px cell in the same block, matching the skill rule's
"plus background-size" wording. Add a crosshair-without-tiling pass case.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Scope codex-grid-background hairline count to background values
Address review: count hairline stops only inside background/background-image
declaration values, not the whole style block, so a hairline in an unrelated
property (mask-image, border-image) can't stand in for the grid's second
axis. Add a bg+mask-image hairline pass case.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Audit of every user-facing surface that enumerates supported harnesses
found GitHub Copilot missing or buried in several. Bring it to parity with
Claude Code, Codex, Cursor, and Gemini.
Missing -> added:
- site/content/reference/hooks.md: the public /docs/hooks page (tagline,
the post-edit list, and the manifest table) now covers GitHub Copilot,
including the `.github/hooks/impeccable.json` surface and the
default-branch/trust note. (Only skill/reference/hooks.md was updated in
the feature PR; this is the website doc.)
- README.md Design hook section + the manifest surface list.
- site/content/tutorials/getting-started.md hook note.
- site/pages/faq.astro tool-specific setup list and the docs-links list.
- PRODUCT.md audience line and README.npm.md suite description.
Prominence + naming:
- README "Supported Tools" and the homepage hero logo row: move GitHub
Copilot up to third (after Claude Code) instead of trailing.
- site/pages/designing: list GitHub Copilot earlier, full name.
- README "Supported Tools": the harness link now points at GitHub Copilot
(github.com/features/copilot) instead of the unrelated VS Code entry.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs: add PRD for design detector hook integration
Plans a PostToolUse hook for Claude Code and Codex that runs the
existing design detector after every relevant file write and feeds
findings back to the agent as advisory system-reminder context. No
implementation in this commit; covers UX, technical design, build
pipeline changes, distribution, coverage tradeoffs, and rollout.
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs: revise hook PRD with best-practices review
Folds in the P0/P1/P2 findings from an online best-practices critique
against the official Claude Code and Codex hook references plus 10+
2026 community guides and similar prior-art tools (claw-hooks,
claude-code-hooks-mastery).
Key changes:
- Exec form everywhere (Codex snippet was shell form), with Windows
rationale.
- Default timeout dropped from 10s to 5s.
- Re-entrancy guard (CLAUDE_HOOK_DEPTH) and per-file edit counter.
- Session-scoped finding dedup promoted from open question to v1.
- Per-language inline-ignore syntax map (HTML/JSX/CSS/JS).
- Hard-skip rules for sensitive paths and generated/lock files.
- Honest framing about Claude Code lacking per-plugin hook disable.
- Honest framing about Bash-written files being invisible in v1.
- Codex Windows-not-supported call-out, feature flag note, trust ceremony detail.
- Optional NDJSON audit log via IMPECCABLE_HOOK_LOG.
- Findings cap lowered 8 → 5 with attention-budget rationale.
- Versioned envelope ([impeccable@1]) on rendered template.
- Expanded test plan, decision log, and stdin payload appendix.
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(hooks): ship the design detector hook for Claude Code and Codex
Implements docs/hooks-prd.md: a PostToolUse hook that runs the
impeccable design detector after every Edit/Write/MultiEdit on a UI
file and pushes findings into the agent's next-turn context as a
short system reminder. Silent on clean files. Never blocks an edit.
Why this matters: today, design slop (side-tab borders, gradient
text, purple/cyan palettes, bounce easing, etc.) only gets caught
when a human notices or someone explicitly runs /impeccable audit.
The hook closes the loop at the moment slop is written.
What ships in v1
- skill/scripts/hook.mjs: PostToolUse entry. Reads stdin, runs the
detector in-process (no `npx impeccable` cold start), emits
hookSpecificOutput.additionalContext when fresh findings exist.
- skill/scripts/hook-lib.mjs: extracted helpers (config, cache,
filter, render, audit log, runHook orchestrator). 100% unit-testable.
- skill/scripts/hook-session-start.mjs: SessionStart greeting,
gated by a project-scannable probe + 30-day throttle.
- skill/scripts/hook-admin.mjs: backs /impeccable hooks
on/off/status/ignore-rule/ignore-file/reset.
Hardening built in
- Re-entrancy guard (IMPECCABLE_HOOK_DEPTH) so the hook can never
recursively spawn itself.
- Hard-skip regexes for sensitive paths (.env, .pem, id_rsa,
secrets, credentials, .git) and generated/lock/build output. These
fire before the file is even read; cannot be turned off via config.
- Path-traversal check on the inbound file_path.
- Session-scoped dedup keyed by (session, file, rule, line) so the
same finding never lands in context twice. Prevents the ~12.5K
wasted tokens per chatty session called out in the PRD.
- Per-(session, file) edit counter with a one-shot suppression
notice on the 7th edit, silent after.
- Fail-open contract: every error path returns exit 0 with no
stdout. Optional NDJSON audit log via IMPECCABLE_HOOK_LOG.
Three kill switches (precedence high to low):
1. IMPECCABLE_HOOK_DISABLED env var (1/true/yes/on, case-insensitive)
2. .impeccable/hook.json `enabled: false`
3. /impeccable hooks off slash command (writes the JSON)
Inline ignores are language-aware. `// impeccable: ignore <rule>` for
JS/TS, `<!-- impeccable: ignore <rule> -->` for HTML/Vue/Svelte/Astro,
`{/* impeccable: ignore <rule> */}` for JSX/TSX, `/* impeccable:
ignore <rule> */` for CSS. `*` matches any rule. Directive applies
to the next non-blank line. Same shape as ESLint, Stylelint, Biome.
Build pipeline
- scripts/lib/transformers/hooks.js: per-provider hooks.json
builders, plus the slim .codex-plugin/plugin.json manifest.
- providers.js: emitHooks: 'claude' for claude-code, emitHooks:
'codex' for codex and agents. Codex also emits emitCodexPlugin.
- factory.js: emits hooks/hooks.json next to the skills tree.
- build.js: syncs hooks/ into harness roots and into the slim
plugin/ subtree; writes .codex-plugin/plugin.json. Build is
idempotent (verified: 98 staged files unchanged across two runs).
Claude Code wiring uses exec form (command + args) and the
${CLAUDE_PLUGIN_ROOT} placeholder. Matcher: Edit|Write|MultiEdit.
`if:` glob filters to UI extensions before spawning Node. PostToolUse
timeout 5s, SessionStart timeout 3s.
Codex wiring uses ${PLUGIN_ROOT} (Codex's native placeholder),
matcher Edit|Write|apply_patch, no `if:` analog (the script does the
extension filter). macOS and Linux only; hooks are disabled on
Windows in current Codex builds. The trust ceremony and feature flag
are documented in README.md.
Routing
- /impeccable hooks lives outside the 23-command router table on
purpose: it is plumbing, not a design skill. The hidden
routing slot is added to SKILL.md alongside pin/unpin so the LLM
knows to dispatch it. The 23-command count and all stale-count
validators remain happy.
Tests
- tests/hook.test.mjs: 38 unit tests covering env parsing, config
load + defaults + malformed, cache round-trip + GC,
ignoreRules/minSeverity/inline ignores (all four languages),
globbing with **/*/{a,b}, render template with cap + clamp + 0-line
prefix drop, audit log NDJSON, payload event-name parameterization,
re-entrancy, kill switches, sensitive-path + generated-path +
traversal skips, allowlist filter, config ignoreFiles, edit
counter cycle including the 7th-edit notice, MultiEdit and
apply_patch payload shapes, detector throw swallow, malformed
stdin, missing file race.
- tests/hook-build.test.mjs: 18 integration tests covering hook
manifest shape (matcher, timeouts, exec form, if: glob, placeholders),
Codex differences (${PLUGIN_ROOT}, no if:, no SessionStart),
Codex plugin manifest (no inline hooks field to avoid the
duplicate-file error), routing across the hooksJsonFor table, and
presence of all three committed artifacts plus the bundled detector
the runtime relative-import path depends on.
Full suite: 175 bun tests + 186 node tests, all green.
Docs
- README.md: new "Design hook" section explaining default behavior,
per-project / global / inline disable paths, the JSON schema knobs,
the audit log debug flag, and the slop / a11y coverage split.
- HARNESSES.md: flips the `hooks` row for Codex from No -> Yes
(Claude was already Yes), adds a per-harness hook-surface table
with the manifest location and matcher each provider uses.
Open questions from the PRD intentionally deferred to v2: Bash-write
blind spot, effort-aware suppression, Stop-hook session summary,
per-rule severity, async hook mode. None block v1.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix Codex hook scanning: apply_patch paths and co-located stylesheets
Parse file targets from Codex apply_patch command bodies, co-scan imported
and sibling CSS when UI components are edited, drop the git-sweep PostToolUse
group, and align Codex SessionStart manifest and trust docs with the official
hooks spec.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Gitignore hook session cache and drop local test HTML
Hook dedup/throttle state in .impeccable/hook.cache.json is per-project
runtime data like other .impeccable/ sidecars. Remove an untracked
bad-nested-flexbox scratch page from site/public/.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix Claude Code hook: drop Edit-only if filter so Write/MultiEdit fire
Claude's if permission rule binds to one tool name, so Edit(*.{…}) never
spawned the hook on Write or MultiEdit despite the matcher listing them.
Extension filtering now lives in hook-lib on both Claude and Codex.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Surface Cursor design findings via stop-hook followup
Replace dropped postToolUse additional_context with afterFileEdit recording
and a one-shot stop followup_message so anti-pattern nudges reach the agent.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix design hook packaging and scans
* Fix Cursor hook pending bucket fallback
* Fix Sass hook scan coverage
* Fix Cursor hook review findings
* Fix session start dead hook normalization
* Fix hook config and relative scan paths
* Remove SessionStart design hook
* Remove redundant afterFileEdit normalization
* Fix Cursor suppression and module style scans
* Fix sensitive path hook filter
* Fix disabled Cursor stop hook emission
* Refresh hook harness artifacts
* Fix Cursor hook manifest install
* Add hook ignore-value support
* Ignore hook runtime files locally
* Fix Codex plugin hook packaging
* fix: address PR review bot findings
Block numeric hook depth counters from re-entering.
Avoid following stylesheet imports from traversal-looking hook targets.
* fix: gate ignore-value suggestions by supported rules
Only render exact ignore-value commands when the same finding can be suppressed by ignoreValues.
* Package Codex plugin as hook-only
* Remove Codex plugin packaging
* Recover hook install probe plumbing
* Remove Codex hook packaging follow-up doc
* Remove extra hook docs and skill wording changes
* Install real design hooks via skills CLI
* Add provider hook smoke runner
* Fix Cursor hook delivery with preToolUse gate
* Simplify Cursor hook install to preToolUse
* Clarify confirmed hook exceptions
* Persist hook ignores in shared config
* Guard font hook exceptions
* Fix hook install after main rebase
* Fix hook scan target handling
* fix: address hook review findings
* Address hook review feedback
* Stabilize DeepSeek insert live fixture
* Fix Cursor hook Python shell write bypass
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
* 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>
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>
The CLI and detection engine now live in pbakaus/impeccable-detect
(published as 'impeccable' on npm, BSL-1.1). This repo is purely
Apache 2.0: skills, prompts, website, and build system.
- Remove bin/ (CLI moved to CLI repo)
- Remove README.npm.md (moved to CLI repo)
- Remove @impeccable/detect dependency, add impeccable dependency
- Set package.json to private (no longer published to npm)
- Update all references from @impeccable/detect to impeccable
- Update CLAUDE.md, NOTICE.md, FAQ, and changelog
- Rebuild all provider skill distributions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New `impeccable skills` CLI with three subcommands:
- `skills help`: fetches and displays all 20 commands from the API
- `skills install`: delegates to `npx skills add pbakaus/impeccable`
- `skills update`: tries `npx skills update` first; if skills aren't
managed by the skills CLI, downloads the universal bundle from
impeccable.style and overwrites provider folders directly, with
git-based modification detection and confirmation prompt
Also fixes npm metadata: homepage -> impeccable.style, license -> Apache-2.0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rename bin/impeccable.mjs to bin/impeccable (npm rejects .mjs in bin)
- Shebang: #!/usr/bin/env node (works without Bun)
- Add README.npm.md with CLI-focused docs, swapped in during publish
- Build browser script to source/ dir so URL scanning works in npm pkg
- Include browser script in files field
- Move website-only deps (archiver, motion, playwright) to devDependencies
- jsdom as dependency, puppeteer as optionalDependency
- Bump version to 2.0.1 across package.json, plugin.json, marketplace.json
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>