') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); test(desktop): add rendered computed-style contract for the chat chrome by Astro-Han · Pull Request #1318 · apache/maka · GitHub
Skip to content

test(desktop): add rendered computed-style contract for the chat chrome - #1318

Merged
Astro-Han merged 1 commit into
mainfrom
fix/1312-chat-chrome-rendered-contract
Jul 22, 2026
Merged

test(desktop): add rendered computed-style contract for the chat chrome#1318
Astro-Han merged 1 commit into
mainfrom
fix/1312-chat-chrome-rendered-contract

Conversation

@Astro-Han

@Astro-HanAstro-Han commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes#1312.

#1308 deleted the chat-chrome pixel script; the surviving chat-chrome-no-gradient-contract.test.ts regex-matches the first source rule per selector, so it cannot see the rendered cascade — a real blind spot: the "three-color-band" incident documented in theme-glass.css was exactly a checked declaration losing to an unlayered higher-specificity rule in reference-shell.css.

This locks the rendered invariant with a Playwright e2e spec, apps/desktop/e2e/chat-chrome-style.spec.ts, measuring the REAL shell elements of the live app (fake backend, long-transcript fixture). The platform axis boots natively: the existing e2e-fixture override seam (which already carries theme/locale/timezone/reduced-motion) gains a MAKA_E2E_FIXTURE_PLATFORM override that app:info reports to the renderer, so a fixture window enters the darwin glass cascade — or the opaque win32 base cascade — through the production data-os path on any host. The theme axis drives page.emulateMedia({ colorScheme }) — the real prefers-color-scheme path the fixture's seeded theme: 'auto' production listener follows — because an in-page .dark class flip leaves the relative-color chains in --surface-canvas resolved against stale token values (measured: appFrame stuck at light [247,247,247] instead of dark [9,9,11]). Reads wait two animation frames after the class lands (the relative-color recalc settles only after a produced frame), and a per-window guard asserts the light and dark appFrame reads differ — equal reads mean a phantom stale cascade, so an insufficient settle fails loud instead of passing vacuously.

Per combo, in the expanded sidebar state, the spec asserts: the effective gutter (Porter-Duff composite of .appFrame.maka-shell-2col, the only two painters of the gutter pixel) is fully painted (alpha 255) and visibly distinct from the effective card; no background-image on any chrome surface (the thrice-rejected 172deg gradient is invisible to color reads); no seam on either boundary side including both resize-handle borders; transparent handle background and resting ::after grip; no adjacent box-shadows; exact-string '12px' corner radii (catches elliptical 12px / 0px; doubles as the vacuous-green self-check); exact-string '4px' card margins; a mode-split shadow lock — dark requires a layer with visible color alpha AND non-zero paint geometry, light requires exactly none per the reference-shell.css design comment; cumulative ancestor-chain opacity exactly 1 (an opacity: 0 anywhere hides the shell while every color read stays green); resting outlines invisible and filter: none on the seam trio (outline and drop-shadow() paint boundary lines the border/box-shadow checks cannot see).

Shape history, for reviewers: four external review rounds (Codex + Kimi K3, fresh sessions each) drove this from a standalone synthetic-DOM Electron script through an in-place-clone probe to the current form. The through-line: any probe state — hand-built mirror DOM, shallow clones, or a cascade reached by an in-page class flip — diverges from what a real user's window computes, in ways that hide regressions (missing painters, relational-selector blindness, stale relative-color chains). Round 4 proved the previous shape's dark combos asserted against a phantom shell (the historical dark transparent-backplate regression passed silently) and replaced the flip with the production media-query path; it also removed a guard that bound a visually-equivalent internal painter split (darwin's residual transparent shell) instead of final appearance. The source-string contract stays as the fast pre-check; its header points here.

Verification

  • Spec green: both forced-platform windows × both emulated themes in one run (2.9s); full e2e suite 33 passed; desktop unit tests 2764 pass (including the platform-override cases: closed enum, fail-closed to null, dev/test-only); typecheck clean.
  • Non-vacuity — five red proofs this round (source edit + rebuild + rerun + exact restore, never committed), each targeting a vector the prior shape provably missed:
    • html.dark .appFrame, html.dark .maka-shell-2col { background: transparent } → dark gutter alpha fails RED (this exact regression stayed GREEN against the in-page-flip shape — the decisive phantom proof);
    • deleting the settle → the per-window phantom guard fails RED (light=[247,247,247] dark=[247,247,247]);
    • .maka-shell-2col { opacity: 0 } → ancestor-opacity fact fails;
    • resting outline: 2px solid red on the handle → outline fact fails;
    • filter: drop-shadow(0 0 4px red) on the panel list → filter fact fails.
    • Earlier rounds' red proofs (172deg gradient, shell recolor, elliptical radius, margin: 0.01px, zero-geometry dark shadow, late 1px border, adjacent-sibling border, ::after grip color) remain covered by the carried-over assertions.
  • Production-code footprint: the platform override rides the existing e2e-fixture override seam — one fallback in the app:info handler (e2eFixture?.platform ?? process.platform), one parse function with the same closed-enum fail-closed discipline as theme/locale/timezone, active only in unpackaged fixture mode.

Review focus

The spec header documents the gutter painter model, why the platform axis must be booted (no mid-session data-os value flip on a long-lived resolved cascade) and the theme axis must ride the real media-query path (an in-page class flip reads a phantom shell — measured values in the header), and the settle + phantom-guard pair that keeps the dark reads honest on any host.

@Astro-Han
Astro-Hanforce-pushed the fix/1312-chat-chrome-rendered-contract branch from 001daa9 to 6d3a0dbCompareJuly 22, 2026 01:42
@Astro-Han
Astro-Hanforce-pushed the fix/1312-chat-chrome-rendered-contract branch 2 times, most recently from d88f2c4 to c2f34afCompareJuly 22, 2026 03:20
…e contract
Add apps/desktop/e2e/chat-chrome-style.spec.ts: it measures getComputedStyle
on the REAL live shell elements across darwin/win32 x light/dark and asserts
the rendered chat-chrome facts: fully painted composited gutter vs card
contrast, no boundary seam or gradient, transparent resize gutter and ::after
grip, exact 12px card radius and 4px inset, and a mode-split card shadow with
visible color and non-zero paint geometry. The platform axis boots natively
per window through a new e2e-fixture override (MAKA_E2E_FIXTURE_PLATFORM ->
app:info platform -> data-os), because a post-boot data-os flip makes
Chromium resolve relative-color backgrounds against stale values, and any
probe DOM (a synthetic mirror or in-place clones) diverges from the real
shell on relational and sibling selectors. The earlier standalone
synthetic-DOM script was abandoned after two review rounds of mirror-fidelity
defects plus its raw-electron CI step hitting the ubuntu sandbox failure
class; measuring the real shell in the existing e2e runner deletes the
mirror DOM, drift guard, CSS inlining, extra npm script, and CI step
wholesale. The source-string contract stays as the fast pre-check and now
points at the spec.
Fixes#1312
@Astro-Han
Astro-Hanforce-pushed the fix/1312-chat-chrome-rendered-contract branch from c2f34af to 4836711CompareJuly 22, 2026 10:09
@Astro-Han
Astro-Han merged commit 5328bc0 into mainJul 22, 2026
3 checks passed
@Astro-Han
Astro-Han deleted the fix/1312-chat-chrome-rendered-contract branch July 22, 2026 11:17
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(desktop): upgrade the chat-chrome invariant to a rendered computed-style contract

1 participant

@Astro-Han