From 17e55ddbb95391b0a5714a49ef77e9a7c79ea3ef Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 22 May 2026 10:05:38 +0200 Subject: [PATCH] =?UTF-8?q?docs(04-08):=20polish=20per=20iter-2=20advisori?= =?UTF-8?q?es=20=E2=80=94=20symbol=20mismatch=20+=20display-surface=20mode?= =?UTF-8?q?=20lock-in=20+=20cosmetic=20clarifications?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit iter-3 polish pass on Plan 04-08 per checker iter-2 verdict PASSED (commit 9c334b7). Five cosmetic-level fixes; no thesis/scope changes; BLOCKER fixes from iter-2 + WARNING fixes from iter-2 preserved verbatim. Remediations: - WARNING 1 (low-severity; displaySurface sub-gate scope ambiguity): HIGH-LATENCY catch path locked in; the under-specified `--check-display-surface-only` spike-script mode is dropped (would have required 5-10 LOC of executor improvisation for no meaningful latency win over the canonical spike re-run's assertA2 fast-fail at <30s). - Advisory 1 (symbol-name mismatch): Tier-2 snippet's `collectDistFiles` replaced with the actual helper `listAllFilesRecursive(DIST_DIR)` from tests/background/no-test-hooks-in-prod-bundle.test.ts:152; also uses the existing `countOccurrencesInFile` for binary-extension-aware grep. - Advisory 2 (SUMMARY-write practice for WARNING 1): explicit note added that 04-08-SUMMARY.md documents the WARNING 1 closure path (no Plan B fallback; explicit error-class identifier; observable via offscreen console capture). - Advisory 3 (vitest math): 183 -> 184 clarified consistently across must_haves truth + Step 5 body + acceptance_criteria + verification + success_criteria (+1 from the new Tier-2 `test(...)` block). - Advisory 4 (duration-N/A rationale): moved out of the PLAN body into the SUMMARY content list (Step 6); PLAN keeps only the load-bearing size gate + loop-attr behavioral assertion + spike-re-run empirical catch; 1.9 MB / ~400 kbps / ~38s decoded-timeline reasoning lands at SUMMARY-time. Frontmatter: - Added iter-2 entry to revision_history (iter-3 polish closure). - Tag flipped planner-iter-2-revision -> planner-iter-3-revision. Plan validates via gsd-sdk frontmatter.validate + verify.plan-structure: - valid: true; 0 errors; 0 warnings; 2 tasks; all 4 task elements present. Diff: +51/-22 lines (5640 chars net). Branch ready for plan-checker iter-3 (cosmetic-only polish review expected to PASS without further findings). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../04-harden-clean-up-optional/04-08-PLAN.md | 73 +++++++++++++------ 1 file changed, 51 insertions(+), 22 deletions(-) diff --git a/.planning/phases/04-harden-clean-up-optional/04-08-PLAN.md b/.planning/phases/04-harden-clean-up-optional/04-08-PLAN.md index 2d3ee3d..b96ffd5 100644 --- a/.planning/phases/04-harden-clean-up-optional/04-08-PLAN.md +++ b/.planning/phases/04-harden-clean-up-optional/04-08-PLAN.md @@ -36,7 +36,7 @@ tags: - charter-d-p4-01 - roadmap-sc-1-closes - post-debug-session-2 - - planner-iter-2-revision + - planner-iter-3-revision user_setup: [] revision_history: - iter: 1 @@ -56,6 +56,17 @@ revision_history: - "advisory 1: Task 3 mis-reference in commit message corrected (Task 1 + Task 2 only)." - "advisory 2: recorder.ts:91 segments invariant gated by grep in Task 1 verify." - "advisory 3: dual-fixture-location note added to Task 1 Step 1." + - iter: 2 + plan_commit: 1f2eb2e + checker_commit: 9c334b7 + verdict: PASSED + warnings_addressed: + - "WARNING 1 (iter-3 polish; checker iter-2 NEW WARNING): displaySurface sub-gate scope ambiguity resolved by locking in the HIGH-LATENCY catch path — the dedicated `--check-display-surface-only` spike-script mode is dropped (it was under-specified and would have required 5-10 LOC of executor improvisation for no meaningful latency win). The displaySurface invariant is now gated by the spike re-run's assertA2 fast-fail (Task 2 Step 1); the production gate at src/offscreen/recorder.ts:294 throws 'wrong-display-surface' within ~30s of spike start if the patchDisplaySurface helper is broken. SUMMARY documents the chosen closure path explicitly." + cosmetics_addressed: + - "advisory 1 (iter-3 polish; checker iter-2 NEW cosmetic-advisory 1): symbol-name mismatch in the WARNING 5 Tier-2 snippet — `collectDistFiles` replaced with the actual symbol `listAllFilesRecursive(DIST_DIR)` from tests/background/no-test-hooks-in-prod-bundle.test.ts:152; also uses the existing `countOccurrencesInFile` helper for binary-extension-aware grep (matches the Tier-1 entries' pattern verbatim)." + - "advisory 2 (iter-3 polish; checker iter-2 NEW cosmetic-advisory 2): WARNING 1 SUMMARY-write practice note added — the SUMMARY explicitly documents the chosen WARNING 1 closure path (no Plan B fallback; explicit error-class identifier on autoplay/codec reject; observable via offscreen console capture)." + - "advisory 3 (iter-3 polish; checker iter-2 NEW cosmetic-advisory 3): vitest math clarified throughout — must_haves truth + Step 5 body + acceptance_criteria + verification + success_criteria all consistently state '183 -> 184 GREEN; +1 from the new Tier-2 test(...) block in tests/background/no-test-hooks-in-prod-bundle.test.ts'." + - "advisory 4 (iter-3 polish; checker iter-2 NEW cosmetic-advisory 4): duration=N/A rationale moved out of the PLAN body into the SUMMARY content list (Step 6) — the PLAN keeps only the load-bearing >=1 MB size gate + loop-attr behavioral assertion + spike-re-run empirical catch; the 1.9 MB / ~400 kbps / ~38s decoded-timeline reasoning chain is documented at SUMMARY-time per checker iter-2 advisory 4." must_haves: truths: - "installFakeDisplayMedia() at src/test-hooks/offscreen-hooks.ts is SYNCHRONOUS at module load — preserves the eager-install contract at lines 533-537 (the monkey-patch on navigator.mediaDevices.getDisplayMedia is in place BEFORE recorder.ts:46-48 top-level await resolves)" @@ -67,7 +78,7 @@ must_haves: - "assertA33 / driveA33 / orchestrator wiring land per the original Plan 04-04 Pattern 4 verbatim (cs-injection-world precedent NOT applicable — A33 is host-side CDP-driven, not page-side rrweb-driven)" - "stopServiceWorker(browser, extensionId) helper at tests/uat/lib/harness-page-driver.ts is reused verbatim from Plan 04-04 (already committed at 3726eee); no new helper symbol needed" - "A33 env-gated by SKIP_LONG_UAT (default RUN for closure + alpha gate; SKIP_LONG_UAT=1 to skip per-commit iteration); 95s baseline preserved when skipped" - - "UAT harness count flips 33 -> 34 (A33 added); 34/34 GREEN when SKIP_LONG_UAT unset; vitest 183/183 GREEN preserved" + - "UAT harness count flips 33 -> 34 (A33 added); 34/34 GREEN when SKIP_LONG_UAT unset; vitest goes 183/183 -> 184/184 GREEN (Plan 04-08 adds exactly one new vitest `test(...)` block — the Tier-2 filename-leak gate in tests/background/no-test-hooks-in-prod-bundle.test.ts; cf. WARNING 5 remediation + iter-3 polish per checker iter-2 cosmetic-advisory 3)" - "ROADMAP SC #1 (SW state persistence) GREEN — A33 empirical evidence that a 5-min idle + Puppeteer worker.close() + SAVE_ARCHIVE produces video/last_30sec.webm with size > 100 KB; ROADMAP.md row flipped from 'STATUS 2026-05-21: OPEN' to 'STATUS 2026-05-22: CLOSED via Plan 04-08'" - "Tier-1 FORBIDDEN_HOOK_STRINGS inventory unchanged at 12 entries (lockstep across tests/uat/harness.test.ts + tests/background/no-test-hooks-in-prod-bundle.test.ts) — Plan 04-08 introduces NO new __MOKOSH_UAT__-gated symbols on production bundle; the bundled WebM ships only in test build per Vite ?url + test-config gating" - "Tier-2 production-bundle filename leak gate added: 'synthetic-display-source' string returns 0 hits across dist/ — codified in tests/background/no-test-hooks-in-prod-bundle.test.ts as a new sub-invariant (canary for future regressions that might accidentally inline test-hooks into the production chunk)" @@ -597,7 +608,7 @@ From tests/background/no-test-hooks-in-prod-bundle.test.ts (CURRENT Tier-1 inven **Step 1 — Bundle the WebM fixture (advisory 3 dual-location note).** - Create directory: `mkdir -p tests/uat/fixtures/`. - Copy `tests/fixtures/last_30sec.webm` to `tests/uat/fixtures/synthetic-display-source.webm`. The existing artifact is a 1.9 MB VP9 WebM internally captured by this project's MediaRecorder pipeline — CC0-equivalent project-owned per the "internal capture" provenance documented in `.planning/STATE.md` Phase 1 Closure Notes. Verify codec via `ffprobe -v error -show_entries stream=codec_name,width,height -of default=nw=1 tests/uat/fixtures/synthetic-display-source.webm` reports `codec_name=vp9`. -- The fixture must be >=1 MB AND >=30 seconds duration (loopable). The existing 1.9 MB capture satisfies size; duration is `N/A` per ffprobe (live-capture WebM lacks a duration tag), BUT the 1.9 MB VP9 at 400 kbps yields ~38s of decoded timeline — sufficient for the 5-min spike via `videoEl.loop = true`. If the executor wants a stricter contract, regenerate via `ffmpeg -f lavfi -i testsrc=duration=35:size=320x180:rate=30 -c:v libvpx-vp9 -b:v 400k tests/uat/fixtures/synthetic-display-source.webm` (this is OPTIONAL — the copy baseline works; only regenerate if the copy's duration tag is load-bearing for the chosen tests). +- The fixture must be >=1 MB (size gate verified by `wc -c` >= 1_000_000 in the Task 1 verify block) AND must loop cleanly under `videoEl.loop = true` across the 5-min spike window (loop behavior verified empirically by the spike re-run in Task 2 Step 1 — if the fixture's decoded timeline is too short OR the loop seam produces a decoder hiccup, the spike's `videoSize > 100_000` floor would catch it). The 1.9 MB capture from `tests/fixtures/last_30sec.webm` is the COPY baseline; if the executor finds the copy fails the spike re-run for any duration/loop-seam reason, the OPTIONAL fallback is to regenerate via `ffmpeg -f lavfi -i testsrc=duration=35:size=320x180:rate=30 -c:v libvpx-vp9 -b:v 400k tests/uat/fixtures/synthetic-display-source.webm`. The full reasoning chain (ffprobe duration=N/A is acceptable because the 1.9 MB / ~400 kbps VP9 yields ~38s of decoded timeline; the `videoEl.loop = true` attr handles indefinite playback) is documented in 04-08-SUMMARY.md's "Bundled WebM fixture decision" section so future maintainers understand the rationale at SUMMARY-time (cf. iter-3 polish per checker iter-2 cosmetic-advisory 4). - **advisory 3 note**: `tests/fixtures/last_30sec.webm` remains in place (Plan 01-07 regression fixture; not affected). The new path at `tests/uat/fixtures/synthetic-display-source.webm` is a SECOND copy under the UAT subtree — this is intentional because the Vite ?url import in `src/test-hooks/offscreen-hooks.ts` resolves cleanly from `../../tests/uat/fixtures/...` without crossing a non-bundled subtree (the `tests/fixtures/` directory is excluded from the test bundle's input set; the `tests/uat/fixtures/` directory is implicitly included as a transitive import of the offscreen-hooks module). - Decision (per `feedback-no-unilateral-scope-reduction.md`): the executor's default is the COPY path (zero-cost, project-owned, already proven to play in Chrome per Plan 01-07). Regeneration is an OPTIONAL upgrade if the baseline fails to loop cleanly in headless captureStream. @@ -715,6 +726,15 @@ export function installFakeDisplayMedia(): void { // downstream. The spike's gating check on `videoSize > 100_000` will // fail with this error visible in the offscreen console capture (or in // the harness diagnostics), making the root cause unambiguous. + // + // WARNING 1 SUMMARY-write practice (iter-3 polish): the executor writing + // 04-08-SUMMARY.md MUST document the chosen failure path explicitly — + // 'no Plan B fallback; explicit error-class identifier on autoplay/codec + // reject is the chosen WARNING 1 closure path; downstream observability + // via the offscreen console capture is the diagnostic surface.' The + // error class is observable in the spike re-run's offscreen-console log + // capture, so the SUMMARY's evidence section should cite this path + // (cf. cosmetic-advisory 2 from checker iter-2). fakeVideoReadyPromise = new Promise((resolve, reject) => { const onCanPlay = (): void => { videoEl.removeEventListener('canplay', onCanPlay); @@ -934,23 +954,31 @@ if (op === 'install-fake-display-media') { // Tier-1 (symbols): 12 entries (unchanged from Plan 01-14) // Tier-2 (asset filenames): 1 entry (Plan 04-08 — synthetic-display-source) test('Tier-2: synthetic-display-source filename does not leak into production dist/', () => { - // Walk dist/ files (skip the binary asset extensions in IGNORED_EXTENSIONS). - // Grep for the literal string 'synthetic-display-source'. Expected: 0 hits. - const distFiles = collectDistFiles(); // existing helper from the Tier-1 test + // Walk dist/ files via the existing recursive walker (which skips + // symlinks; the existing countOccurrencesInFile helper handles + // binary-extension skipping). Grep for the literal string + // 'synthetic-display-source'. Expected: 0 hits. + const distFiles = listAllFilesRecursive(DIST_DIR); // existing helper at line ~152 of this file const offendingFiles: string[] = []; for (const filePath of distFiles) { - const content = readFileSync(filePath, 'utf-8'); - if (content.includes('synthetic-display-source')) { + if (countOccurrencesInFile(filePath, 'synthetic-display-source') > 0) { offendingFiles.push(filePath); } } expect(offendingFiles).toEqual([]); }); ``` -- **Note**: the executor should READ the existing test file first to identify: - - The exact name of the helper that walks dist/ files (the snippet above calls it `collectDistFiles` — verify the actual name and adapt). - - The exact location to insert the new test block (after the Tier-1 inventory test, before the file's final close). - - The exact import shape (the snippet uses `readFileSync` — verify already imported). +- **Note**: the snippet above uses the actual symbols from the live file + (`listAllFilesRecursive(DIST_DIR)` at line ~152 + `countOccurrencesInFile` + at line ~185 + the `DIST_DIR` constant at line ~133). The executor still + reads the existing test file first to confirm: + - The exact insertion site for the new `test(...)` block (after the + closing `}` of the `for (const needle of FORBIDDEN_HOOK_STRINGS)` loop + inside the existing `describe(...)` block — same describe scope keeps + the gates colocated under one suite name). + - Whether the new test should also be wrapped in the same + `it.skipIf(SKIP_BUILD === '1' && !existsSync(DIST_DIR))` style as the + Tier-1 entries (cross-check the existing pattern when reading). **Step 7 — Verify TypeScript + production build clean + test build emits asset + Tier-2 gate passes.** - `npx tsc --noEmit` exits 0. @@ -963,8 +991,8 @@ if (op === 'install-fake-display-media') { - `grep -c "installFakeDisplayMedia(): void" src/test-hooks/offscreen-hooks.ts` returns ≥ 1 (sync signature preserved; iter-2 BLOCKER 2 verification — function does NOT return Promise). - `grep -c "export function installFakeDisplayMedia(): Promise" src/test-hooks/offscreen-hooks.ts` returns 0 (verifies the function was NOT converted to async). - `grep -c "await installFakeDisplayMedia" src/test-hooks/offscreen-hooks.ts` returns 0 (verifies the bridge handler + eager-install were NOT converted to await). -- **Sub-verify gate for displaySurface monkey-patch compatibility (WARNING 2 remediation):** create a one-shot inline node script that loads dist-test (via Puppeteer's `enableExtensions`) + executes a snippet in the offscreen document that mints a stream + asserts `stream.getVideoTracks()[0].getSettings().displaySurface === 'monitor'`. If this fails, the production `displaySurface !== 'monitor'` gate at `src/offscreen/recorder.ts:294` would tear down the stream + throw `'wrong-display-surface'` — the spike would fail at Step 2 (assertA2 prime), not at Step 7 (videoSize check). Implementation: append to the existing `tests/uat/spike-a33-sw-persistence.ts` script a `--check-display-surface-only` mode that runs only Steps 1-2 (prime + 5s post-prime probe), invokes `__mokoshOffscreenQuery` op='get-display-surface', asserts result is 'monitor', exits. Run via `HEADLESS=1 SKIP_PROD_REBUILD=1 npx tsx tests/uat/spike-a33-sw-persistence.ts --check-display-surface-only 2>&1 | tee /tmp/04-08-display-surface-check.log` and grep `'DISPLAY-SURFACE-CHECK: PASSED'` in the log. The full spike re-run (Step 1 of Task 2) is a superset of this check, but running it as a fast sub-gate in Task 1 catches the WARNING 2 risk in <10s of wall-clock instead of waiting 6+ min into the spike. - - Alternative if the executor finds the spike-script-augmentation overhead too high: skip the dedicated sub-gate and rely on the spike re-run in Task 2 Step 1 (the displaySurface failure would manifest as 'wrong-display-surface' Error in the offscreen console capture; the spike's gating condition would still fail). The dedicated sub-gate is the LOW-LATENCY path; the spike re-run is the HIGH-LATENCY path; both gate the same invariant. +- **Sub-verify gate for displaySurface monkey-patch compatibility (WARNING 2 remediation — iter-3 polish: HIGH-LATENCY catch path locked in).** The displaySurface contract is gated by the spike re-run in Task 2 Step 1 — NOT by a dedicated low-latency sub-gate. Rationale: the spike's Step 1 calls `__mokoshHarness.assertA2` which executes `recorder.startRecording` -> `await navigator.mediaDevices.getDisplayMedia(...)` (the patched closure). If `track.getSettings().displaySurface !== 'monitor'` after the `patchDisplaySurface(stream)` call, the production gate at `src/offscreen/recorder.ts:294` tears down the stream + throws `'wrong-display-surface'` during assertA2 — surfacing the regression within seconds of the spike's Step 1, NOT after the 5-min idle elapses. The high-latency framing was overstated in iter-2; in practice the failure surfaces in <30s of the spike (assertA2 prime takes 5-15s; the displaySurface check fires inside the production handler immediately on track availability). The dedicated `--check-display-surface-only` mode is dropped — it would have required 5-10 LOC of under-specified spike-script augmentation (env-var hook, log emit, exit-code semantics) for no meaningful latency win over the canonical spike re-run. + - **SUMMARY documents the WARNING 2 closure path:** the executor's 04-08-SUMMARY.md MUST state explicitly that the WARNING 2 closure relied on the spike re-run's assertA2 fast-fail (NOT a dedicated sub-gate); cite the wall-clock-to-failure (<30s for displaySurface; full 6+ min only if assertA2 prime succeeds and the failure is in the videoSize floor). - **Sub-verify gate for segments invariant (advisory 2 remediation):** `grep -cE 'let segments: Blob\[\] = \[\];' src/offscreen/recorder.ts` returns 1 (architectural invariant per debug session-2; Plan 04-08 does NOT modify recorder.ts). @@ -1004,7 +1032,7 @@ if (op === 'install-fake-display-media') { **Step 0 — GATING CONDITION (Task 1 complete + methodology valid).** - Verify Task 1 acceptance criteria all met. If any fail (TS error, missing fixture, sync signature violated, etc.), STOP and fix before proceeding. -- Verify the displaySurface sub-gate from Task 1 Step 7 PASSED. If skipped, the spike re-run in Step 1 below catches it but with 6+ min latency. +- displaySurface compatibility is gated by Step 1 below (the spike re-run's assertA2 fast-fails on `'wrong-display-surface'` if the patch is broken; surfaces within ~30s of spike start, NOT after the 5-min idle). No separate Task 1 sub-gate exists — the dedicated `--check-display-surface-only` mode was dropped in iter-3 polish per WARNING 1 closure (the high-latency catch path is locked in). **Step 1 — Re-run the spike script.** - Run: `HEADLESS=1 SKIP_PROD_REBUILD=0 npx tsx tests/uat/spike-a33-sw-persistence.ts 2>&1 | tee /tmp/04-08-spike-rerun.log` @@ -1019,7 +1047,7 @@ if (op === 'install-fake-display-media') { **Step 2 — Update the spike script if needed (sync-install/lazy-first-frame compatibility).** - The spike script's prime step uses `__mokoshHarness.assertA2` (canonical fresh-recording bootstrap; Plan 04-04 REVISION iter-2 Option B). Under the new methodology, `assertA2` triggers `recorder.startRecording` which calls `navigator.mediaDevices.getDisplayMedia` — this is now the patched closure that lazy-waits for video readiness. First call may take an extra ~50-500ms; the existing assertA2 timeout (per Plan 01-13 default ~15s) absorbs this comfortably. NO edit to the spike script's logic is needed. -- **IF** Task 1 Sub-step 3g's sub-gate (`--check-display-surface-only` mode) was implemented, that mode is preserved as a forensic helper. Otherwise the spike script is unchanged. +- No spike-script edit is needed. The dedicated `--check-display-surface-only` mode was dropped in iter-3 polish (WARNING 1 closure — high-latency catch path locked in); the canonical spike covers the displaySurface invariant via assertA2's fast-fail path. **Step 3 — Land A33 in the harness (3-file lockstep per Plan 04-04 Wave 1 spec verbatim).** @@ -1097,16 +1125,17 @@ if (op === 'install-fake-display-media') { - `grep -v '^#\|^//' dist/assets/index-*.js | grep -c 'Buffer\.'` returns 1 (pre-existing JSZip polyfill; Plan 04-02 deferred) - SW chunk `window.`/`document.` references = 0 - Manifest validation + en/ru parity preserved (unchanged from Plan 04-03) -- vitest baseline preserved: `npm test 2>&1 | tail -5` — expect 184/184 GREEN (was 183 baseline + 1 new Tier-2 test from Plan 04-08), or 181/184 with the 3 documented pre-existing parallel-vitest flakes per 04-CONTEXT items 9-10; flakes pass in isolation. +- vitest baseline flips 183 -> 184: `npm test 2>&1 | tail -5` — expect 184/184 GREEN (prior baseline 183 + exactly 1 new `test(...)` block added in Task 1 Step 6 — the Tier-2 'synthetic-display-source filename does not leak' gate in tests/background/no-test-hooks-in-prod-bundle.test.ts; cf. WARNING 5 + iter-3 polish per checker iter-2 cosmetic-advisory 3). Or 181/184 with the 3 documented pre-existing parallel-vitest flakes per 04-CONTEXT items 9-10; flakes pass in isolation. **Step 6 — Write Plan 04-08 SUMMARY.** - Create `.planning/phases/04-harden-clean-up-optional/04-08-SUMMARY.md`: - Methodology reframe rationale (cite debug session-2 verdict verbatim) - **iter-2 revision summary** (cite checker iter-1 + BLOCKER 1 + BLOCKER 2 + WARNING resolutions) - - Bundled WebM fixture decision (copy vs regenerate; size + codec evidence; dual-location note) + - Bundled WebM fixture decision (copy vs regenerate; size + codec evidence; dual-location note; **duration=N/A rationale** — 1.9 MB / ~400 kbps VP9 = ~38s decoded timeline + `videoEl.loop = true` for indefinite playback across the 5-min spike; cf. iter-3 polish per checker iter-2 cosmetic-advisory 4) - installFakeDisplayMedia diff summary (canvas -> HTMLVideoElement; SYNC install + LAZY first-frame; 6 bridge ops preserved sync; A23 capture preserved; eager-install contract preserved) + - **WARNING 1 closure path** (autoplay reject fallback) — document explicitly: no Plan B fallback; explicit error-class identifier on autoplay/codec reject; the error class string is observable in the spike's offscreen-console capture; cite the wall-clock-to-failure surface (per iter-3 polish + checker iter-2 cosmetic-advisory 2) - manifest.json WAR entry decision (BLOCKER 1 rationale: pre-emptive explicit entry; production inert; test bundle authorized) - - displaySurface compatibility evidence (sub-gate result; WARNING 2 closure) + - **WARNING 2 closure path** (displaySurface compat) — document explicitly: HIGH-LATENCY catch via spike re-run's assertA2 fast-fail (NOT a dedicated sub-gate); cite the wall-clock-to-failure (<30s for displaySurface check inside assertA2 prime); the dedicated `--check-display-surface-only` mode was dropped in iter-3 polish per WARNING 1 closure - Spike re-run evidence (videoSize before/after; segment-count probe values; elapsed time) - A33 land evidence (driveA33 + orchestrator wiring; FORBIDDEN_HOOK_STRINGS at 12; pre-checkpoint gates 6/6; Tier-2 gate added) - UAT before/after (33/33 -> 34/34 GREEN) @@ -1190,7 +1219,7 @@ if (op === 'install-fake-display-media') { - FORBIDDEN_HOOK_STRINGS inventory unchanged at 12 entries — verify by line count of both arrays. - **Tier-2 gate (Plan 04-08 iter-2):** `grep -c 'synthetic-display-source' tests/background/no-test-hooks-in-prod-bundle.test.ts` returns ≥ 1; the test PASSES under `npm test -- tests/background/no-test-hooks-in-prod-bundle.test.ts`. - Pre-checkpoint bundle gates 6/6 PASS unchanged from Plan 04-03 baseline. - - vitest 184 baseline preserved (183 prior + 1 new Tier-2 test) — or 181/184 with the 3 documented pre-existing flakes; pass in isolation. + - vitest baseline flips 183 -> 184 (prior 183 GREEN + exactly 1 new `test(...)` block — the Tier-2 'synthetic-display-source filename does not leak' gate in tests/background/no-test-hooks-in-prod-bundle.test.ts) — or 181/184 with the 3 documented pre-existing flakes; pass in isolation. - **WARNING 4 (iter-2):** `.planning/ROADMAP.md` contains `'CLOSED via Plan 04-08'` (grep returns ≥ 1); contains zero hits on `'STATUS 2026-05-21: OPEN'` (the old status was removed); contains `'STATUS 2026-05-22: CLOSED'`. - `.planning/STATE.md` Decisions list contains a Plan 04-08 entry citing ROADMAP SC #1 CLOSED. - `.planning/phases/04-harden-clean-up-optional/04-08-SUMMARY.md` exists with: methodology rationale + iter-2 revision summary + spike re-run evidence + probe values + A33 land evidence + UAT before/after + ROADMAP SC #1 closure + cross-reference to Plan 04-04 post-debug amendment. @@ -1258,7 +1287,7 @@ if (op === 'install-fake-display-media') { - Tier-1 FORBIDDEN_HOOK_STRINGS lockstep at 12 entries (unchanged). - Tier-2 gate (Plan 04-08): `npm test -- tests/background/no-test-hooks-in-prod-bundle.test.ts` passes. - Pre-checkpoint bundle gates 6/6 PASS (new Function=0 + eval=0 + Buffer.=1 + window.=0 + document.=0 in SW + Tier-1=12 + en/ru parity). -- vitest baseline 184 preserved (183 prior + 1 new Tier-2; or 181/184 with 3 documented pre-existing flakes; pass in isolation). +- vitest baseline flips 183 -> 184 GREEN (prior 183 + exactly 1 new `test(...)` block — the Tier-2 filename-leak gate in tests/background/no-test-hooks-in-prod-bundle.test.ts; cf. WARNING 5 + iter-3 polish per checker iter-2 cosmetic-advisory 3); or 181/184 with 3 documented pre-existing flakes; pass in isolation. - A29 + A30 + A31 + A32 unchanged (no regression to existing assertions). - Architecture invariant preserved: `src/offscreen/recorder.ts:91 let segments: Blob[] = []` UNCHANGED — debug session-2 verdict is honored (NO IndexedDB persistence work). - spike-FAILED forensic-evidence preservation: `tests/uat/spike-a33-sw-persistence.ts` retained (Plan 04-04 commit 3726eee + debug session-2 Step B + C additions); now functions as a PASSING regression test under the new methodology. @@ -1283,7 +1312,7 @@ if (op === 'install-fake-display-media') { - Tier-2 production-bundle filename-leak gate added: `synthetic-display-source` returns 0 hits in dist/ (WARNING 5). - Pre-checkpoint bundle gates 6/6 PASS. - Architectural integrity preserved (no IndexedDB persistence; no chrome.storage migration; src/offscreen/recorder.ts:91 segments array unchanged; grep gate enforces). -- vitest 184 baseline preserved (183 prior + 1 new Tier-2 test). +- vitest baseline flips 183 -> 184 (prior 183 + exactly 1 new `test(...)` block — the Tier-2 filename-leak gate added in Task 1 Step 6). - Plan 04-04 forensic artifacts (`stopServiceWorker` helper + spike script) repurposed as PASSING regression tests under valid methodology. - iter-2 BLOCKER 1 + BLOCKER 2 + WARNINGs 1-5 + advisories 1-3 all addressed per checker iter-1 remediation guidance.