mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 06:06:37 +03:00
Add codex-grid-background detector rule (#328)
* 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>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
5844c40177
commit
f5c1bd65ae
@@ -478,6 +478,17 @@ const ANTIPATTERNS = [
|
||||
skillSection: 'Visual Details',
|
||||
skillGuideline: 'repeating-gradient decorative stripes',
|
||||
},
|
||||
{
|
||||
id: 'codex-grid-background',
|
||||
category: 'slop',
|
||||
severity: 'advisory',
|
||||
gated: 'gpt',
|
||||
name: 'Decorative grid-line background',
|
||||
description:
|
||||
'A two-axis grid drawn with hairline linear-gradient layers ("1px, transparent 1px" on both axes) is a recurring generated-UI signature. Reserve grid overlays for actual canvas, map, blueprint, or measurement surfaces; elsewhere use product structure or a plain surface.',
|
||||
skillSection: 'Visual Details',
|
||||
skillGuideline: 'two-axis grid-line gradient background',
|
||||
},
|
||||
{
|
||||
id: 'theater-slop-phrase',
|
||||
category: 'slop',
|
||||
@@ -1172,6 +1183,42 @@ function checkHtmlPatterns(html) {
|
||||
findings.push({ id: 'repeating-stripes-gradient', snippet: 'repeating-gradient decorative stripes' });
|
||||
}
|
||||
|
||||
// --- Provider tells (gated): two-axis grid-line background (Codex/GPT) ---
|
||||
// The Codex grid tell is two hairline `linear-gradient(... <color> 1px,
|
||||
// transparent 1px)` layers (one per axis) tiled by a repeating
|
||||
// `background-size` cell. Both signals must co-occur in the SAME style block
|
||||
// (a CSS rule body or one inline `style="..."`): two hairline stops WITHOUT a
|
||||
// tiling background-size is a fixed crosshair, not a grid, and a single
|
||||
// hairline is a legitimate ruled line. Scoping to one block also stops
|
||||
// unrelated single-axis rules on separate elements from adding up across the
|
||||
// page. Count hairlines only inside `background`/`background-image` values so
|
||||
// a hairline in an unrelated property (mask-image, border-image) can't stand
|
||||
// in for the second axis. Colors like `oklch(96% 0.012 82 / 0.055)` carry
|
||||
// nested parens, so match the hairline stop directly rather than parsing
|
||||
// whole gradient layers.
|
||||
{
|
||||
const hairlineRe = /\b\d{1,3}px\s*,\s*transparent\s+\d{1,3}px/gi;
|
||||
const gridSizeRe = /background-size\s*:[^;{}"']*\b\d{1,3}px\b/i;
|
||||
const bgDeclRe = /\bbackground(?:-image)?\s*:\s*([^;{}"']*)/gi;
|
||||
const blockRe = /\{([^{}]*)\}|style\s*=\s*"([^"]*)"|style\s*=\s*'([^']*)'/gi;
|
||||
let blk;
|
||||
while ((blk = blockRe.exec(html)) !== null) {
|
||||
const block = blk[1] || blk[2] || blk[3] || '';
|
||||
if (!gridSizeRe.test(block)) continue;
|
||||
let hairlineCount = 0;
|
||||
let bm;
|
||||
bgDeclRe.lastIndex = 0;
|
||||
while ((bm = bgDeclRe.exec(block)) !== null) {
|
||||
const stops = bm[1].match(hairlineRe);
|
||||
if (stops) hairlineCount += stops.length;
|
||||
}
|
||||
if (hairlineCount >= 2) {
|
||||
findings.push({ id: 'codex-grid-background', snippet: 'two-axis grid-line gradient background' });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Provider tells (gated): "X theater" framing copy (GPT) ---
|
||||
// Lives here (regex-on-HTML) rather than in the text-content analyzers so it
|
||||
// runs in the bundled browser path too, not just the CLI/static path.
|
||||
|
||||
@@ -376,6 +376,17 @@ const ANTIPATTERNS = [
|
||||
skillSection: 'Visual Details',
|
||||
skillGuideline: 'repeating-gradient decorative stripes',
|
||||
},
|
||||
{
|
||||
id: 'codex-grid-background',
|
||||
category: 'slop',
|
||||
severity: 'advisory',
|
||||
gated: 'gpt',
|
||||
name: 'Decorative grid-line background',
|
||||
description:
|
||||
'A two-axis grid drawn with hairline linear-gradient layers ("1px, transparent 1px" on both axes) is a recurring generated-UI signature. Reserve grid overlays for actual canvas, map, blueprint, or measurement surfaces; elsewhere use product structure or a plain surface.',
|
||||
skillSection: 'Visual Details',
|
||||
skillGuideline: 'two-axis grid-line gradient background',
|
||||
},
|
||||
{
|
||||
id: 'theater-slop-phrase',
|
||||
category: 'slop',
|
||||
|
||||
@@ -573,6 +573,42 @@ function checkHtmlPatterns(html) {
|
||||
findings.push({ id: 'repeating-stripes-gradient', snippet: 'repeating-gradient decorative stripes' });
|
||||
}
|
||||
|
||||
// --- Provider tells (gated): two-axis grid-line background (Codex/GPT) ---
|
||||
// The Codex grid tell is two hairline `linear-gradient(... <color> 1px,
|
||||
// transparent 1px)` layers (one per axis) tiled by a repeating
|
||||
// `background-size` cell. Both signals must co-occur in the SAME style block
|
||||
// (a CSS rule body or one inline `style="..."`): two hairline stops WITHOUT a
|
||||
// tiling background-size is a fixed crosshair, not a grid, and a single
|
||||
// hairline is a legitimate ruled line. Scoping to one block also stops
|
||||
// unrelated single-axis rules on separate elements from adding up across the
|
||||
// page. Count hairlines only inside `background`/`background-image` values so
|
||||
// a hairline in an unrelated property (mask-image, border-image) can't stand
|
||||
// in for the second axis. Colors like `oklch(96% 0.012 82 / 0.055)` carry
|
||||
// nested parens, so match the hairline stop directly rather than parsing
|
||||
// whole gradient layers.
|
||||
{
|
||||
const hairlineRe = /\b\d{1,3}px\s*,\s*transparent\s+\d{1,3}px/gi;
|
||||
const gridSizeRe = /background-size\s*:[^;{}"']*\b\d{1,3}px\b/i;
|
||||
const bgDeclRe = /\bbackground(?:-image)?\s*:\s*([^;{}"']*)/gi;
|
||||
const blockRe = /\{([^{}]*)\}|style\s*=\s*"([^"]*)"|style\s*=\s*'([^']*)'/gi;
|
||||
let blk;
|
||||
while ((blk = blockRe.exec(html)) !== null) {
|
||||
const block = blk[1] || blk[2] || blk[3] || '';
|
||||
if (!gridSizeRe.test(block)) continue;
|
||||
let hairlineCount = 0;
|
||||
let bm;
|
||||
bgDeclRe.lastIndex = 0;
|
||||
while ((bm = bgDeclRe.exec(block)) !== null) {
|
||||
const stops = bm[1].match(hairlineRe);
|
||||
if (stops) hairlineCount += stops.length;
|
||||
}
|
||||
if (hairlineCount >= 2) {
|
||||
findings.push({ id: 'codex-grid-background', snippet: 'two-axis grid-line gradient background' });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Provider tells (gated): "X theater" framing copy (GPT) ---
|
||||
// Lives here (regex-on-HTML) rather than in the text-content analyzers so it
|
||||
// runs in the bundled browser path too, not just the CLI/static path.
|
||||
|
||||
Reference in New Issue
Block a user