From 2814997f07f7de9736ee9e2f62512f2bbe0b6317 Mon Sep 17 00:00:00 2001 From: efiten Date: Sun, 6 Sep 2026 13:45:15 +0200 Subject: [PATCH] fix(scope-audit): neutral grey for unobserved scopes, green only for observed On live data 78 of 197 rows have nothing observed at all, so colouring every unobserved region red painted most of the table as an alarm. Absence over a short window is weak evidence, which the page header already states in words; it should not also shout in colour. Colour now marks the finding rather than its absence. Removes the dead .sa-chip-missing rule, which had no remaining callers. Frontend suite green. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01PQS3XLoPD98yu9pxdRujqg --- public/scope-audit.css | 11 ++++++++--- public/scope-audit.js | 2 +- test-frontend-helpers.js | 8 ++++---- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/public/scope-audit.css b/public/scope-audit.css index 59e57057..f782b2c9 100644 --- a/public/scope-audit.css +++ b/public/scope-audit.css @@ -35,7 +35,6 @@ font-size: 11px; font-family: var(--mono); white-space: nowrap; } .sa-chip-declared { background: var(--section-bg, var(--card-bg)); color: var(--text); border: 1px solid var(--border); } -.sa-chip-missing { background: color-mix(in srgb, var(--status-red) 16%, transparent); color: var(--danger); } .sa-chip-undeclared { background: color-mix(in srgb, var(--status-yellow) 18%, transparent); color: var(--status-amber-text); } .sa-chip-wildcard { background: var(--section-bg, var(--card-bg)); color: var(--text-muted); font-weight: 700; } .sa-chip-ambiguous { background: var(--section-bg, var(--card-bg)); color: var(--text-muted); border: 1px dashed var(--border); font-family: inherit; font-style: italic; } @@ -54,6 +53,12 @@ } /* Observed forwarding, the green half of the merged Scopes column. Pairs with - .sa-chip-missing above, which keeps the red. Same colour-mix construction so - the two read as one scale rather than two unrelated styles. */ + .sa-chip-unobserved below, which stays neutral. Only the observed side is + coloured: red on every unobserved region would read as an alarm on rows that + are often just a quiet region over a short window. */ .sa-chip-observed { background: color-mix(in srgb, var(--status-green) 16%, transparent); color: var(--status-green-text); } + +/* Declared but not observed in this window. Deliberately NOT red: absence over + a short window is weak evidence, which the page header says in words, so it + should not shout in colour. */ +.sa-chip-unobserved { background: var(--section-bg, var(--card-bg)); color: var(--text-muted); border: 1px solid var(--border); } diff --git a/public/scope-audit.js b/public/scope-audit.js index 44e7ad6c..47fea207 100644 --- a/public/scope-audit.js +++ b/public/scope-audit.js @@ -76,7 +76,7 @@ row.notObserved.forEach(function (n) { missing[n] = true; }); var chips = row.declaredRegions.map(function (n) { var observed = !missing[n]; - return '' + escapeHtml(n) + ''; diff --git a/test-frontend-helpers.js b/test-frontend-helpers.js index bf688f56..469c0d33 100644 --- a/test-frontend-helpers.js +++ b/test-frontend-helpers.js @@ -6984,12 +6984,12 @@ console.log('\n=== scope-audit.js: mergedScopeChips ==='); test('a declared region absent from notObserved renders as observed', () => { const h = chips(row(['be'], [])); assert.ok(h.includes('sa-chip-observed'), 'should carry the observed class'); - assert.ok(!h.includes('sa-chip-missing'), 'and not the missing one'); + assert.ok(!h.includes('sa-chip-unobserved'), 'and not the unobserved one'); }); - test('a declared region present in notObserved renders as missing', () => { + test('a declared region present in notObserved renders as unobserved, not as an alarm', () => { const h = chips(row(['be'], ['be'])); - assert.ok(h.includes('sa-chip-missing')); + assert.ok(h.includes('sa-chip-unobserved')); assert.ok(!h.includes('sa-chip-observed')); }); @@ -6998,7 +6998,7 @@ console.log('\n=== scope-audit.js: mergedScopeChips ==='); // 8 regions of which 6 are unobserved, so the observed ones are the needle. const h = chips(row(['be', 'eu', 'nl'], ['eu', 'nl'])); assert.strictEqual((h.match(/sa-chip-observed/g) || []).length, 1); - assert.strictEqual((h.match(/sa-chip-missing/g) || []).length, 2); + assert.strictEqual((h.match(/sa-chip-unobserved/g) || []).length, 2); assert.strictEqual((h.match(/