Preserve quoted attribute values and escaped identifiers while resolving real pseudo-elements to live hosts.
AI assistance disclosure: Codex helped implement and test this fix under maintainer direction.
Keep valid empty pseudo-class matches authoritative and omit selector-less linked at-rules that cannot be tied to rendered nodes.
AI assistance disclosure: Codex helped implement and test this fix under maintainer direction.
Use a temporary custom-property probe so the browser decides whether a nested style rule actually applies in the current container layout.
AI assistance disclosure: Codex helped implement and test this fix under maintainer direction.
Exclude linked container-query groups when their current applicability cannot be resolved, with a browser regression proving inactive styles do not leak.
AI assistance disclosure: This commit was prepared with Codex under maintainer direction.
Resolve pseudo-element selectors to live hosts, reject unresolvable linked CSS findings, and make the regression assertions independent. Also ignore comment delimiters when recovering CSS rule selectors.
AI assistance disclosure: This commit was prepared with Codex under maintainer direction.
Flatten linked stylesheet grouping rules and collect only selector rules that target the live DOM, preventing unused grouped and selector-less patterns from leaking into URL findings.
AI assistance disclosure: Implemented and verified with Codex under maintainer direction.
Recover joined URL arguments without splitting local paths, derive advisory behavior from registry severity across consumers, inspect readable linked CSS in URL scans, and report only the dominant primary font.
AI assistance disclosure: Implemented and verified with Codex under maintainer direction.
Ensure install, link, update, and check render static help before entering any operational path. Covers top-level and legacy routing for both -h and --help.
AI-assisted implementation under maintainer direction.
Move Codex and .agents skill versions under metadata while keeping all version readers compatible with legacy top-level frontmatter.\n\nAI assistance: prepared with Codex under maintainer direction.
Add a first-class OpenCode command bridge across builds, installs, updates, linked installs, and pinned shortcuts. Preserve current provider behavior while backfilling missing or drifted command files.\n\nAI assistance: contributor and maintainer work used AI tools as disclosed in the PR discussion and commits.
* Fix flat type hierarchy false positives
Use rendered semantic roles and dominant size frequency, align the adjacent-step guidance, and abstain in source-only scans.\n\nAI assistance: prepared with Codex under maintainer direction.
* Fix static hidden typography filtering
Honor the hidden attribute in the static wrapper and use raw browser findings in regression coverage.
AI assistance: prepared with Codex under maintainer direction.
* Align typography sampling with painted content
Count visibly painted aria-hidden text and exclude content-visibility hidden subtrees in both static and browser scans.
AI assistance: prepared with Codex under maintainer direction.
Treat the leading system face as primary so later Roboto fallbacks do not trigger overused-font, while named web-font primaries still flag.
AI-assisted merge: reviewed and executed by Codex under maintainer direction.
The generated browser bundle is rebuilt from the merged engine sources in the next commit's build step (both branches had regenerated it).
AI-assisted (Claude Code).
- keyChroma re-encodes with the PNG's tEXt chunks intact (the embedded prompt survived generation but not keying)
- organic-clip-path counts relative curve commands too (path data letters are only commands, so the match is case-insensitive)
- buried-raster normalizes percentage alphas (parseFloat('80%') read as 80) and reads 4- and 8-digit hex alpha instead of treating #rrggbbaa as opaque
- the extension-injected-node skip in checkQuality runs before any finding is pushed (a low-opacity injected raster was recorded, then returned by the skip)
- fake-mode plates carry impeccable:fake tEXt and the plates gate's crop-identity refusal skips them (fake mode IS the crop by design; the refusal is for models shipping the comp's pixels as artwork)
Findings by cursor[bot] and Copilot on PR #599; detector engines rebuilt (build:browser, build:extension).
AI-assisted (Claude Code).
Bugbot on PR #665: the skipScan guard emptied only the analytic
collectBrowserFindings pass, and scan()'s detached visual-contrast
stage then repopulated an ignoreFiles-waived page with contrast
markers and a second non-zero results post. Hoist the guard into
skipScanActive() and honor it in scan() and the async collector;
regenerate the browser bundle.
Adds a browser-backed regression test that reproduces the leak
(second results post carrying low-contrast findings) and pins the
zero contract; drops a tautological assert flagged in review.
AI-assisted change: implemented with Claude Code under maintainer
direction.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Read waiver config from every live root (appRoot, contextRoot, repoRoot),
so monorepo projects whose config lives at the repo root reach the
overlay; serialize served roots and page identities repo-relative there.
Resolve each page URL to its actual serving file via the inject config's
resolved page list before applying file-scoped waivers; ambiguous URLs
keep the conservative common-ancestor fallback (PR #645 review
discussion r3840011436).
Honour detector.ignoreFiles: a wholly waived page now scans to zero
findings in the overlay, matching the CLI and the edit hook.
Guard the resolver call so a throwing resolver degrades to an unfiltered
scan instead of breaking the detect toggle.
Match design-system-color waivers by color value across hex and rgb()
spellings, and stop extracting font values for bounce-easing findings,
mirroring extractFindingIgnoreValue. Regenerate the browser bundle.
AI-assisted change: reviewed, planned, and implemented with Claude Code
under maintainer direction.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The live overlay's detect scan ran unfiltered: requestDetectScan() posted
only { scanId }, so detector.ignoreRules and detector.ignoreValues in
.impeccable/config.json reached impeccable detect and the edit hook but
never the surface a designer actually watches.
The server now serializes the project's detector waivers into the /live.js
prelude (window.__IMPECCABLE_PROJECT_IGNORES__), read per request through
hook-lib's readConfig so config.local.json wins and edits land on the next
tab reload. A new script part, live-browser-ignores.js, resolves that
config against the page URL when a scan starts: ignoreRules suppress
outright, wildcard ignoreValues suppress their rule in the files their
globs name, and the remaining entries ride along as disabledValues for the
detector to match on each finding's own value. The detector bundle applies
those where the findings are assembled, since the overlay draws its own
markers from the collected findings.
Scope resolution mirrors cli/lib/impeccable-config.mjs deliberately: the
same glob dialect (globToRegex, including {a,b} alternation), the same
path-suffix matching as findingMatchesScopedIgnoreFile, and the same
refusal to apply an unscoped wildcard entry. The served-root prefixes that
bridge project-relative globs and site-relative URLs come from the inject
config's own files globs, never from the ignore globs; deriving them from
the ignore globs lets one entry scoped to prototype/library/** lend its
prefix to every page and suppress site-wide, which looks like success
because the numbers go down.
Known gaps, recorded in the detector comment: the motion value extractor
is not mirrored, so a value-scoped bounce-easing waiver only matches when
the finding carries ignoreValue directly, and design-system-color matches
on the normalized string without the CLI's color-equality fallback.
Tests: unit tests for the resolver part (stale globals, string ignoreRules,
malformed entries, directory URLs, percent-escapes, glob metacharacters,
the roots trap), an extension-mode puppeteer test that disabledValues
suppress exactly the waived findings, and the live-browser regression pin
now asserts the new scan config shape instead of { scanId }.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
generate-image.mjs --plate produces one raster region of the measured spec
from the comp crop, scores it against the crop, and refuses under --min.
The asset producer's job becomes producing the spec's plates. Detector
gains organic-clip-path (many-vertex polygon / curved path() clips) and
buried-raster (raster under a near-opaque wash or at near-zero opacity),
wired into both engines with fixtures.
AI-assisted (Claude).
Co-Authored-By: Claude <noreply@anthropic.com>
page.authenticate is page-wide, so a cross-origin redirect that then 401s would receive the original credentials. Attach Authorization only to requests for the scan origin.
Written with AI assistance (Cursor); reviewed by maintainer.
Co-authored-by: Cursor <cursoragent@cursor.com>
Strip basic-auth credentials from scan-target URLs before goto and finding output, and pass them to page.authenticate instead.
Written with AI assistance (Cursor); reviewed by maintainer.
Co-authored-by: Cursor <cursoragent@cursor.com>
ignore-value stored exact values for rules that cannot extract one, so the entries never matched. Refuse them and point at "*" --file.
AI assistance: implemented with Cursor Grok 4.6.
Co-authored-by: Cursor <cursoragent@cursor.com>
Dot-segment hrefs like /../outside.css could leave the project, and a process-wide warning set hid missing-sheet notices on later detectHtml calls.
AI assistance: implemented with Cursor Grok 4.6.
Co-authored-by: Cursor <cursoragent@cursor.com>
Root-relative hrefs like /static/app.css were treated as OS-absolute and silently dropped, hiding contrast findings.
AI assistance: implemented with Cursor Grok 4.6.
Co-authored-by: Cursor <cursoragent@cursor.com>
packages/* now includes nested package.json dirs under a matched
workspace package, and Impeccable projectRoots govern a path even when
package-manager workspaces exclude it.
Written with AI assistance (Cursor); reviewed by maintainer.
Co-authored-by: Cursor <cursoragent@cursor.com>
findDesignRoot continued past every workspace package.json to any
workspace-declaring ancestor. It now matches the boundary against that
ancestor's globs (including negations and globstars), so excluded and
stray packages do not inherit, while included workspaces still do.
Written with AI assistance (Cursor); reviewed by maintainer.
Co-authored-by: Cursor <cursoragent@cursor.com>
Grok was skipped by the hook-command rewrite, so a global skill install left .grok/hooks/impeccable.json pointing at a project-relative hook.mjs that does not exist.
AI assistance: Cursor Grok 4.6 implemented this change.
Co-authored-by: Cursor <cursoragent@cursor.com>
Quote-bearing regexes made the frontmatter closer miss the closing ---, and url(//…) plus interpolations were treated as SCSS line comments that hid live font-family. Prepared with AI assistance.
Co-authored-by: Cursor <cursoragent@cursor.com>
Standalone SCSS/Sass/Less files already ignored // comments, but <style lang="scss"> in Astro/Vue/Svelte still scanned them as live CSS. Prepared with AI assistance.
Co-authored-by: Cursor <cursoragent@cursor.com>
codex-grid-background treated any 2D px background-size as a grid, so a single hairline tiled as a dash or rail false-positived. A finding now requires two hairline gradients plus a px tile.
Prepared with AI assistance (Cursor agent), directed by @abdulwahabone.
Co-authored-by: Cursor <cursoragent@cursor.com>
Naive HTML/CSS comment regexes were swallowing live markup between script-string delimiters, SCSS/Sass/Less line comments still reached the matchers, and indexOf treated --- inside a frontmatter template literal as the closing fence. Prepared with AI assistance.
Co-authored-by: Cursor <cursoragent@cursor.com>
parseGradientColors treated #000 inside color-mix() as a stop, so low-contrast scored text against phantom black. Prepared with AI assistance.
Co-authored-by: Cursor <cursoragent@cursor.com>
detectText only blanked comments for JS extensions, so broken-image still fired on <img> inside Astro/Vue/Svelte comments, CSS comments, and extracted style blocks. Prepared with AI assistance.
Co-authored-by: Cursor <cursoragent@cursor.com>