3 Commits

Author SHA1 Message Date
c02914df86 feat(03-01): Task 1 — probe HTML for A29 rrweb DOM verification (SPEC §10 #4)
- Append form (text + email + password + submit) + table (thead + 2 rows)
  + modal trigger + hidden modal div below existing `<pre id="status">`
  scaffold; preserves `<head>` block + tokens.css link untouched (A18/A21
  invariant).
- Modal trigger uses inline onclick to toggle style.display — rrweb
  records the attribute mutation, satisfying IncrementalSnapshot
  emission per RESEARCH Pitfall 1 (synthetic probe HTML emits Meta +
  FullSnapshot but NOT IncrementalSnapshot without a DOM mutation
  between page load and SAVE).
- Per RESEARCH Pitfall 4: the rrweb-alpha.4-leaky multi-line input
  element (rrweb-io/rrweb#1596) is excluded; only single-line inputs.
- Per UI-SPEC §"Test Fixture Conventions": data-test-* attributes
  only; no data-mokosh-* (production-welcome-page reserved); no
  tokens.css import on the probe sub-tree (head already imports the
  canonical tokens for A18/A21).
- npm run build exit 0; all 7 acceptance grep gates GREEN.
2026-05-20 19:11:41 +02:00
b909c374cc feat(01-12): wave-6 task-1 — harness A18-A22 (font reachability + icon-distinct + manifest-i18n + Lora-resolved + welcome-tokens)
UAT harness extended with 5 new page-side assertions following the
01-13 Approach B pattern (page-side assertA* + host-side driveA*
wrapper + harness.test.ts orchestrator entry):

A18 — Lora WOFF2 reachable from harness page (font self-host MV3 CSP
  invariant). Walks document.styleSheets for the first @font-face rule
  referencing Lora, resolves the rebased asset URL (handles Vite's
  content-hashing), fetches, asserts byteLength >= 40_000 (subset Lora
  is ~49 KB) + WOFF2 signature 'wOF2'. 4 checks.

A19 — icons rasterized from Loom mark (not Bug A placeholders). Fetches
  icon128.png, parses IHDR bytes 24-25 (bit-depth + color-type),
  asserts (8, 6) RGBA vs the placeholder (16, 2) RGB. 2 checks.

A20 — manifest:name resolves via chrome i18n. Reads
  chrome.runtime.getManifest().name; asserts it matches EN extName
  'Mokosh — Session Capture' OR RU 'Mokosh — Запись сессии' (robust
  to whatever locale Chrome uses); explicitly checks no __MSG_
  placeholder leaks. 2 checks.

A21 — --mks-font-display resolves to Lora stack. Creates transient
  .mks-display-1 probe div, reads getComputedStyle.fontFamily,
  asserts the stack starts with 'Lora' or '"Lora"' (accommodates
  both quoted + unquoted forms across Chrome versions); explicitly
  checks no Newsreader leak (R2 substitution complete). 2 checks.

A22 — welcome page tokens.css adoption (CONDITIONAL on Plan 01-10).
  Skip-gate on missing welcome.html: catches both HTTP 404 AND
  network-layer fetch failure (Chrome extensions throw TypeError
  'Failed to fetch' for non-web_accessible_resources paths). On
  reachable: extracts <link rel=stylesheet> hrefs, fetches each,
  asserts >= 3 var(--mks-*) usages OR tokens.css reference. 1 check.

Companion changes:

- tests/uat/extension-page-harness.html gains `<link rel="stylesheet"
  href="../../src/shared/tokens.css">` so A18 + A21 have the @font-face
  rules + .mks-display-1 class + CSS custom properties resolvable via
  document.styleSheets + getComputedStyle. Vite's crxjs plugin handles
  the asset path rebasing at build:test time.

- tests/uat/lib/harness-page-driver.ts: driveA18..driveA22 wrappers
  following the established driveA8 pattern (page.evaluate → window.
  __mokoshHarness.assertXX). No new host-side fs/ffprobe primitives;
  all A18-A22 work is page-side.

- tests/uat/harness.test.ts: orchestrator drivers list extended with
  A18-A22 between A14 and A23. FORBIDDEN_HOOK_STRINGS UNCHANGED at 12
  entries post-Plan-01-14 (A18-A22 use production chrome.* + fetch +
  getComputedStyle exclusively; no new test-mode symbols).

Verification (this commit):
- npm run test:uat: 21/21 GREEN (was 16/16 post-01-14)
- SKIP_BUILD=1 npm test: 147/147 GREEN
- Tier-1 grep gate: 13/13 GREEN (no FORBIDDEN_HOOK_STRINGS growth)
- npx tsc --noEmit: clean
- npm run build + npm run build:test: both succeed

The chain of A1..A14 + A18..A22 + A23 runs in ~95 seconds end-to-end
under Puppeteer headless mode against the bundled Chrome at
~/.cache/puppeteer/chrome/linux-148.0.7778.167.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 07:41:51 +02:00
eb2258a880 feat(01-13): wave-1 — promote c647f61 prototype to production paths; A6 GREEN
Move the three load-bearing prototype files from `tests/uat/prototype/`
to their production paths under `tests/uat/`, leaving the architectural
narrative (research findings, BLOCKER citations, falsification table
references) intact. No behavioral changes — A6 still PASSES 5/5 in ~7s
end-to-end from the new paths.

File moves (git mv preserves history):
  - tests/uat/prototype/extension-page-harness.html
      → tests/uat/extension-page-harness.html
  - tests/uat/prototype/extension-page-harness.ts
      → tests/uat/extension-page-harness.ts
  - tests/uat/prototype/a6.test.ts
      → tests/uat/a6.test.ts

The `tests/uat/prototype/` directory is now empty (git does not track
empty directories; will not appear in subsequent `git status`).

Path-reference updates inside the moved files:
  - tests/uat/extension-page-harness.html: `<p>` line referencing the
    chrome-extension:// URL updated to drop `/prototype/`.
  - tests/uat/extension-page-harness.ts: file-header docstring rewritten
    to cite Plan 01-13 / Approach B / inheritance from c647f61. The
    load-bearing architectural-finding comment block (MV3 SW dynamic-
    import block falsification, Approach-B chrome.* surface summary)
    is REWORDED but its semantic content + research citations are
    PRESERVED — every load-bearing fact survives the rename.
  - tests/uat/a6.test.ts:
      * File-header rewritten to position the file as Plan 01-13's
        standalone single-assertion entry point (preserves the future-
        proof rationale: this entry stays around forever for fast TDD
        iteration on A6 even after Wave 3 folds A6 into the orchestrator
        harness.test.ts).
      * REPO_ROOT resolvePath chain corrected from `..,..,..` to `..,..`
        — the file is now two directory levels above the repo root
        instead of three. Without this fix DIST_TEST_DIR would resolve
        to a path one level above the actual repo root and
        assertBundlePresent would throw. **VERIFIED by running the
        driver: build path resolves correctly.**
      * harnessUrl constant updated to drop `/prototype/` from the
        chrome-extension://<id>/tests/uat/extension-page-harness.html
        URL — must match the rollup emission path in dist-test/.
      * Stdout labels updated: 'PROTOTYPE A6 result' → 'A6 result',
        'Plan 01-11 PROTOTYPE — A6 ... feasibility test' → 'Plan 01-13
        — A6 (Bug B canonical) standalone driver'. Inside the docstrings
        the historical 'originally landed as 01-11 prototype' provenance
        is preserved per the plan's contract.

vite.test.config.ts:
  - `rollupOptions.input` renamed `prototype_harness` → `extension_page_harness`
    pointing at the new production path. crxjs emits the harness HTML
    to `dist-test/tests/uat/extension-page-harness.html` (verified by
    `ls dist-test/tests/uat/`).
  - The `modulePreload: { polyfill: false }` line is PRESERVED — this
    is the CRITICAL SW FIX per 01-11-SUMMARY (disabling the polyfill
    is what makes the test bundle's offscreen-side dynamic import work
    without crashing in non-DOM contexts that incorrectly try to call
    document.querySelector).
  - File-header comment §4 and the inline `define.__MOKOSH_UAT__` comment
    are PRESERVED — load-bearing rationale for the dedicated build-time
    token (vs `import.meta.env.MODE === 'test'` which collides with
    vitest).

Verification (all GREEN):
  - `npm run build:test` — exit 0; dist-test/ emits
    `tests/uat/extension-page-harness.html` and `assets/extension_page_harness-*.js`.
  - `npx tsx tests/uat/a6.test.ts` — exits 0 with "A6 result: PASS";
    5/5 checks GREEN (SETUP: badge becomes REC; A6.1 badge==''; A6.2
    popup==''; A6.3 notif delta==0; A6.4 isRecording=false). End-to-end
    runtime ~7s headless on this workstation.
  - `npx tsc --noEmit` — exit 0 (root tsconfig + tests/uat/tsconfig.json).
  - `npx vitest run` — 92/92 GREEN; the moves do not touch any vitest-
    discovered files.
  - `npm run build` — exit 0; Tier-1 grep gate stays GREEN
    (the moves do not touch production code).

Wave 2 (next): build out `tests/uat/lib/{launch,assertions,harness-page-
driver}.ts` around the extension-page architecture; rewrite
`tests/uat/a6.test.ts` to use the shared lib (still PASSES 5/5).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 15:01:58 +02:00