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
scripts/
Dev-only utility scripts. These are NOT bundled by npm run build — the
production dist/ contains zero smoke artifacts (verified by
grep -rn smoke dist/ returning empty post-build).
Smoke-isolation invariant
smoke.sh and any future smoke-test harness live ENTIRELY in this
directory. Vite's rollupOptions.input (vite.config.ts) does NOT
reference any path under scripts/; the build pipeline cannot include
smoke artifacts in dist/. RESEARCH §12 verifies no-op condition via
grep -rn 'smoke\|SMOKE\|data:text/html' src/ returning empty.
A defensive __VITE_DEV__ define-token (see vite.config.ts:define)
is reserved for any future inline smoke-mode check; currently it
defaults to false so even a misplaced if (__VITE_DEV__) { ... }
branch is statically tree-shaken out of production by Rollup.
Override per-build via env var:
VITE_DEV=1 npm run dev # __VITE_DEV__ === true
npm run build # __VITE_DEV__ === false (production default)
Index
| Script | Purpose |
|---|---|
subset-fonts.sh |
One-off font subsetting (Lora + IBM Plex Sans/Mono → Latin+Cyrillic) |
rasterize-icons.sh |
One-off icon rasterization (mokosh-mark.svg → icons/icon{16,48,128}.png) |
smoke.sh (if present) |
Local smoke harness — not part of npm run build |
Re-run conditions:
subset-fonts.sh: when upstream Lora-Cyrillic or IBM/plex releases a major bump with bug fixes; or when the UNICODES range needs expansion. Seesrc/shared/fonts/README.mdfor the canonical recipe.rasterize-icons.sh: whensrc/shared/brand/mokosh-mark.svgchanges (the source-of-truth for the toolbar icon).
References
.planning/phases/01-stabilize-video-pipeline/01-12-PLAN.mdWave 5 Task 1 — the smoke-isolation contract this README documents.planning/phases/01-stabilize-video-pipeline/01-12-RESEARCH.md§12 — verification rationale.planning/intel/brand-decisions-v1.mdD-09 — dev-only smoke shipping decision