Per the orchestrator checkpoint protocol + the saved-memory feedback
"trust harness over manual UAT", Task 4's dark-mode aesthetic
judgment uses Puppeteer-produced screenshots (NOT a manual Chrome
session). This script:
1. Loads dist/ via puppeteer.launch enableExtensions.
2. Resolves the runtime extension ID via the canonical
browser.extensions() Map (mirrors tests/uat/lib/launch.ts
resolveExtensionIdWithPolling).
3. Opens chrome-extension://<id>/src/welcome/welcome.html.
4. Captures the .welcome-hero bounding-box region in LIGHT surface
(default OS appearance — the regression-baseline shot, matching
the Plan 01-10 cycle-2 operator ack 2026-05-20).
5. Sets [data-theme="dark"] on <html> (Mokosh's tokens.css cascade
uses the explicit .dark / [data-theme="dark"] selector at line
234; emulateMediaFeatures alone does NOT trigger it because
tokens.css has no @media (prefers-color-scheme: dark) block — a
fact verified live this session). emulateMediaFeatures is also
set, forward-compatible with any future @media block.
6. Re-screenshot the hero region — the DARK-surface aesthetic shot.
Output paths (canonical per the 04-06-PLAN Task 4 contract):
- /tmp/04-06-welcome-hero-light.png
- /tmp/04-06-welcome-hero-dark.png
Run results (this session):
- LIGHT: computed stroke = rgb(250, 247, 241) — linen-50; the
--mks-fg-inverse value on the LIGHT cascade flowing through
.welcome-hero__mark to the inline <svg>'s currentColor.
- DARK: computed stroke = rgb(24, 27, 42) — ink-900; the
--mks-fg-inverse value AFTER the .dark cascade override
(tokens.css 244 sets --mks-fg-inverse: var(--mks-ink-900)) —
the strategy's contrast flip is empirically verified.
Implementation notes (deviation Rule 3 — observed environment
constraints fixed inline):
- Initial extension ID resolver used browser.targets() polling +
regex; rewritten to use the canonical Puppeteer 22.x
browser.extensions() Map approach.
- Initial screenshot used ElementHandle.screenshot(); Puppeteer
Runtime.callFunctionOn timed out on the second elementHandle
evaluate in headless extension page context. Rewritten to a
single page.evaluate() that returns getBoundingClientRect() +
computedStroke in one CDP round trip, then page.screenshot({clip})
against those coordinates — succeeds reliably.
- protocolTimeout set to 120s to match the UAT harness baseline.
References:
- .planning/phases/04-harden-clean-up-optional/04-06-PLAN.md Task 4.
- tests/uat/lib/launch.ts (the canonical extension-loading pattern).
- https://pptr.dev/api/puppeteer.browser.extensions
- https://pptr.dev/api/puppeteer.page.screenshot
7.5 KiB
7.5 KiB