From 3fe018beb9a79e9684615db0de090e696e2782b9 Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 19 May 2026 21:45:58 +0200 Subject: [PATCH] =?UTF-8?q?fix(01-12):=20revise=20plan=20baselines=20per?= =?UTF-8?q?=20Plan=2001-14=20landing=20(vitest=2098=E2=86=92100,=20UAT=201?= =?UTF-8?q?5=E2=86=9216,=20FORBIDDEN=5FHOOK=5FSTRINGS=2010=E2=86=9212)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Surgical amendment — Plan 01-12 is unexecuted; safe for in-place revision. Plan 01-14 landed (b467123 → 5254145 → 9792c0f) since 01-12 was authored, adding monitorTypeSurfaces:'include' + UAT A23 + 2 FORBIDDEN_HOOK_STRINGS entries. Plan 01-12 baseline arithmetic updated to reflect post-01-14 floors and depends_on chain extended. Changes: - frontmatter depends_on: append 01-14 (canonical sequential-dependency declaration) - must_haves truth #11: 10 strings → 12 strings post-Plan-01-14, with provenance note - must_haves truth #13: vitest 98→100→106; UAT 15→16→21 (or 19→24 with 01-10); A23 added to no-regression list alongside A0-A14 + (A15-A17 if 01-10) - Embedded FORBIDDEN_HOOK_STRINGS code block: 10 → 12 entries (lastGetDisplayMediaConstraints, get-last-getDisplayMedia-constraints) with attribution comment - Wave 6 task narrative + verify + done: 20/20 → 21/21; 23/23 → 24/24 - Wave 7 closure narrative + one-liner + checkpoint copy: same arithmetic update - Threat model T-01-12-08: inheritance updated to include T-1-14-*; grep-gate floor 10→12 - Verify-block harness orchestrator grep gate: strengthened with `grep -v '^#'` filter to prevent self-invalidating count from comment lines (per planner.md gate hygiene) - Success criteria items 3, 4, 9: vitest 98→100; UAT 20→21; inventory 10→12 Preserved verbatim (per surgeon-not-architect): - 7-wave structure (Wave 0 fonts/tokens/icons/i18n RED scaffolds, Wave 1 fonts+tokens.css, Wave 2 icons, Wave 3 manifest i18n, Wave 4 popup/welcome adoption, Wave 5 8 i18n strings, Wave 6 harness A18-A22, Wave 7 operator brand-fit checkpoint) - 10 tasks (validated via gsd-sdk verify.plan-structure) - R2 Lora baked-in decision - D-01..D-09 decision references - All files_modified entries - Threat model entries other than T-01-12-08 inheritance line - Designer ack references - Operator checkpoint (Wave 7) - Must_have truths #1-10 and #12 Validation: - gsd-sdk frontmatter.validate → valid:true - gsd-sdk verify.plan-structure → valid:true, errors:0, task_count:10 - grep verification: zero stale references to 98/104/15/15/20/20/23/23/18/18/"at 10" - All new baselines present at 32 update sites - diff: 1 file changed, 34 insertions(+), 30 deletions(-) Next step: plan-checker re-validation of arithmetic + consistency before executor spawn. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../01-stabilize-video-pipeline/01-12-PLAN.md | 64 ++++++++++--------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/.planning/phases/01-stabilize-video-pipeline/01-12-PLAN.md b/.planning/phases/01-stabilize-video-pipeline/01-12-PLAN.md index dbe8f68..290cf35 100644 --- a/.planning/phases/01-stabilize-video-pipeline/01-12-PLAN.md +++ b/.planning/phases/01-stabilize-video-pipeline/01-12-PLAN.md @@ -6,6 +6,7 @@ wave: 6 depends_on: - 01-09 - 01-13 + - 01-14 files_modified: - src/shared/tokens.css - src/shared/fonts/Lora-VariableFont.woff2 @@ -91,9 +92,9 @@ must_haves: - "src/popup/index.html title element becomes '__MSG_extName__' (or empty, populated by JS via chrome.i18n.getMessage('extName')); span.button-text remains empty (populated by JS per RESEARCH Pitfall 3); src/popup/index.ts updateUI() reads buttonText.textContent = chrome.i18n.getMessage('popupSaveCta') in idle case, 'popupSaveDone' in done case; the 'Архив успешно сохранён!' literal at saveArchive() success branch (line 91) becomes chrome.i18n.getMessage('popupSaveDone'); the info-text 'Последние 30 сек видео + 10 мин лога' at index.html line 15 becomes a data-mks-key='popupInfoText' attribute populated by JS. src/popup/style.css imports `../shared/tokens.css` and ALL hardcoded hex literals (#2563eb, #1d4ed8, #94a3b8, #f8f9fa, #0891b2, #059669, #dc2626, #64748b) are replaced with var(--mks-*) references (--mks-rec for save button, --mks-success for done state, --mks-error for error, --mks-fg-2 for info text, --mks-surface for body bg, --mks-fg-disabled for disabled, --mks-warning for warning info)." - "If Plan 01-10 (welcome tab) has landed before Plan 01-12 executes: src/welcome/welcome-tokens.css placeholder is REPLACED with a one-liner `@import '../shared/tokens.css';`, and any per-key copy literals in src/welcome/copy.ts are migrated to chrome.i18n.getMessage('') reads (welcomeHeroRu, welcomeHeroEn) with the in-file COPY map removed or reduced to a fallback shim. If Plan 01-10 has NOT yet landed: src/welcome/* files are NOT created by Plan 01-12; the canonical tokens.css is import-ready from src/shared/tokens.css and Plan 01-10 executor can swap to it from day 1 (no placeholder welcome-tokens.css needed)." - "vite.config.ts gains a `define` block setting __VITE_DEV__ = JSON.stringify(process.env.VITE_DEV === '1') per RESEARCH §12 D-09 spirit-satisfaction (defensive flag for any future inline smoke-mode check; smoke.sh continues to live outside Vite's input set entirely — verified by `grep -rn 'smoke\\|SMOKE\\|data:text/html' src/` returning empty). vite.test.config.ts inherits via mergeConfig. scripts/README.md (NEW) documents the smoke isolation invariant in one paragraph." - - "Tier-1 forbidden-strings inventory in tests/background/no-test-hooks-in-prod-bundle.test.ts AND tests/uat/harness.test.ts is UNCHANGED at 10 strings (no new test-mode symbols introduced by Plan 01-12; the i18n + tokens + font work uses production chrome.* APIs end-to-end). Verified by file-diff after plan close." + - "Tier-1 forbidden-strings inventory in tests/background/no-test-hooks-in-prod-bundle.test.ts AND tests/uat/harness.test.ts is UNCHANGED at 12 strings post-Plan-01-14 (no new test-mode symbols introduced by Plan 01-12; the i18n + tokens + font work uses production chrome.* APIs end-to-end). Plan 01-14 established the 12-string baseline by adding `lastGetDisplayMediaConstraints` + `get-last-getDisplayMedia-constraints` for its monitorTypeSurfaces harness. Verified by file-diff after plan close." - "UAT harness extended with 5 new assertions A18-A22: A18 = Lora WOFF2 loads from chrome.runtime.getURL('shared/fonts/Lora-VariableFont.woff2') OR equivalent emitted asset path (response.ok && content-length > 50000 — Lora variable Latin+Cyrillic is ~80-120KB after subsetting). A19 = icons are NOT the Bug A placeholders (icon128.png file size differs from the known 2615-byte 16-bit-RGB placeholder; OR icon128.png file content hash differs from the placeholder content hash). A20 = chrome.runtime.getManifest().name === 'Mokosh — Session Capture' (i18n resolution test; the en-locale fallback always returns this exact string per default_locale='en'). A21 = getComputedStyle on a test element with CSS class .mks-display-1 inside the harness page resolves to a font-family stack starting with 'Lora' (not 'Newsreader', not system fallback). A22 = welcome page tokens.css is loaded if 01-10 has landed (fetch chrome.runtime.getURL('src/welcome/welcome.html') returns 200 + welcome.css resolves --mks-rec to '#b2543d'); skip with a documented diagnostic if 01-10 has not landed." - - "Every Plan 01-13 harness assertion (A0-A14) and Plan 01-10 assertion (A15-A17, IF landed) remains GREEN after Plan 01-12 changes (no regression). vitest baseline grows by 6 tests (icons-present + tokens-adopted + fonts-present + no-remote-fonts + manifest-i18n + locale-parity) from 98 GREEN to 104 GREEN; npm run test:uat grows from 15/15 (or 18/18 with 01-10) to 20/20 (or 23/23 with 01-10 + 01-12) — all GREEN." + - "Every Plan 01-13 harness assertion (A0-A14), Plan 01-14 assertion (A23), and Plan 01-10 assertion (A15-A17, IF landed) remains GREEN after Plan 01-12 changes (no regression). vitest baseline grows by 6 tests (icons-present + tokens-adopted + fonts-present + no-remote-fonts + manifest-i18n + locale-parity) from 100 GREEN (post-01-14) to 106 GREEN; npm run test:uat grows from 16/16 (post-01-14, or 19/19 with 01-10) to 21/21 (or 24/24 with 01-10 + 01-12) — all GREEN." - "MV3 architectural constraints from 01-11-SUMMARY enforced: NO `await import(...)` anywhere in src/background/index.ts (chrome.i18n.getMessage is a synchronous API; no dynamic imports required); test-mode symbols stay in dist-test/ only via __MOKOSH_UAT__ define-token (Plan 01-12 introduces no new test-mode symbols)." artifacts: - path: "src/shared/tokens.css" @@ -202,10 +203,10 @@ must_haves: provides: "Adds driveA18, driveA19, driveA20, driveA21, driveA22 host-side wrappers following the existing driveA4 pattern (page.evaluate → window.__mokoshHarness.assertXX). No new host-side filesystem or ffprobe primitives; all A18-A22 work runs page-side via fetch + getComputedStyle + chrome.runtime.getManifest." min_lines: 60 - path: "tests/uat/harness.test.ts" - provides: "Orchestrator extended with A18-A22 entries. FORBIDDEN_HOOK_STRINGS list UNCHANGED at 10 entries (no new test-mode symbols introduced). Assertion count grows from 15/15 (post-01-13) or 18/18 (post-01-10+01-13) to 20/20 or 23/23 (post-01-12). Bail-on-first-failure orchestration unchanged." + provides: "Orchestrator extended with A18-A22 entries. FORBIDDEN_HOOK_STRINGS list UNCHANGED at 12 entries post-Plan-01-14 (no new test-mode symbols introduced by Plan 01-12). Assertion count grows from 16/16 (post-01-13+01-14) or 19/19 (post-01-10+01-13+01-14) to 21/21 or 24/24 (post-01-12). Bail-on-first-failure orchestration unchanged." contains: "A18" - path: ".planning/STATE.md" - provides: "Wave 7 closure update: completed_plans increments by 1 (Plan 01-12 closes); decision-log appends '[Phase 01-12]: design integration landed — Lora self-hosted (R2 per designer 2026-05-19) + tokens.css canonical + 8 i18n strings + branded icons + manifest:name i18n; UAT harness 20/20 GREEN (or 23/23 if 01-10 also landed); operator brand-fit ack received'. percent recomputed." + provides: "Wave 7 closure update: completed_plans increments by 1 (Plan 01-12 closes); decision-log appends '[Phase 01-12]: design integration landed — Lora self-hosted (R2 per designer 2026-05-19) + tokens.css canonical + 8 i18n strings + branded icons + manifest:name i18n; UAT harness 21/21 GREEN (or 24/24 if 01-10 also landed); operator brand-fit ack received'. percent recomputed." - path: ".planning/ROADMAP.md" provides: "Phase 1 Plans list gains `- [x] 01-12-PLAN.md — Design integration (R2 Lora, tokens.css, 8 i18n strings, branded icons, manifest i18n)` entry after 01-13. If Plan 01-10 not yet in list, also add its entry as `- [ ]` placeholder unless already present." key_links: @@ -304,9 +305,9 @@ Output: - Wave 1: src/shared/fonts/ + src/shared/tokens.css + scripts/subset-fonts.sh; fonts-present + no-remote-fonts flip GREEN. - Wave 2: icons/icon{16,48,128}.png + scripts/rasterize-icons.sh + src/shared/brand/; icons-present flips GREEN. - Wave 3: manifest.json + _locales/{en,ru}/messages.json; manifest-i18n + locale-parity flip GREEN; manifest:name resolves to "Mokosh — Session Capture" on extension reload. -- Wave 4: src/popup/style.css + src/popup/index.html + src/popup/index.ts + src/background/index.ts; tokens-adopted flips GREEN; existing 98+ vitest tests stay GREEN (i18n-call-site migration is behavior-equivalent for the chrome.* mock pattern used by existing tests). +- Wave 4: src/popup/style.css + src/popup/index.html + src/popup/index.ts + src/background/index.ts; tokens-adopted flips GREEN; existing 100+ vitest tests stay GREEN (i18n-call-site migration is behavior-equivalent for the chrome.* mock pattern used by existing tests). - Wave 5: src/welcome/* conditional migration (if 01-10 landed) OR skip; vite.config.ts __VITE_DEV__ define-token + scripts/README.md. -- Wave 6: tests/uat/extension-page-harness.ts + tests/uat/lib/harness-page-driver.ts + tests/uat/harness.test.ts extended with A18-A22; npm run test:uat reports 20/20 (or 23/23 with 01-10) GREEN. +- Wave 6: tests/uat/extension-page-harness.ts + tests/uat/lib/harness-page-driver.ts + tests/uat/harness.test.ts extended with A18-A22; npm run test:uat reports 21/21 (or 24/24 with 01-10) GREEN. - Wave 7: operator checkpoint; STATE.md + ROADMAP.md sync; SUMMARY produced. @@ -645,7 +646,7 @@ async function assertA21(): Promise { } ``` -### Tier-1 forbidden-strings inventory (UNCHANGED at 10) +### Tier-1 forbidden-strings inventory (UNCHANGED at 12 post-Plan-01-14) ```ts const FORBIDDEN_HOOK_STRINGS: ReadonlyArray = [ @@ -659,9 +660,12 @@ const FORBIDDEN_HOOK_STRINGS: ReadonlyArray = [ '__mokoshOffscreenQuery', 'get-display-surface', 'get-segment-count', + 'lastGetDisplayMediaConstraints', // added by Plan 01-14 + 'get-last-getDisplayMedia-constraints', // added by Plan 01-14 ]; // Plan 01-12 introduces NO new test-mode symbols (A18-A22 use production chrome.* APIs -// + fetch + getComputedStyle exclusively). Do NOT extend this list. +// + fetch + getComputedStyle exclusively). Do NOT extend this list beyond the 12 entries +// established by Plan 01-14. ``` ### Locale-parity test shape @@ -729,7 +733,7 @@ describe('_locales/ key parity', () => { - 6 test files exist at the documented paths - vitest discovers all 6 + reports them in `npx vitest run tests/build tests/i18n` - At least one case per file is RED today (per behavior above) - - npm run build / build:test still pass (these tests do not change source code yet — the existing 98 vitest GREEN baseline stays GREEN; only the 6 new tests are RED) + - npm run build / build:test still pass (these tests do not change source code yet — the existing 100 vitest GREEN baseline (post-01-14) stays GREEN; only the 6 new tests are RED) - Atomic commit `test(01-12): wave-0 — scaffold RED unit tests for tokens / fonts / icons / no-remote-fonts / manifest-i18n / locale-parity` @@ -931,7 +935,7 @@ describe('_locales/ key parity', () => { - manifest.json:name === '__MSG_extName__'; :description === '__MSG_extDesc__'; :default_locale === 'en'; :action.default_title === '__MSG_tooltipOff__' - npm run build succeeds + dist/_locales/{en,ru}/messages.json exist + dist/manifest.json carries the new i18n shape - tests/i18n/manifest-i18n.test.ts + tests/i18n/locale-parity.test.ts GREEN - - Existing 98 vitest baseline + 6 new tests = 104 vitest GREEN + - Existing 100 vitest baseline (post-01-14) + 6 new tests = 106 vitest GREEN - Atomic commit `feat(01-12): wave-3 task-1 — manifest i18n (__MSG_*__ + default_locale='en') + _locales/{en,ru}/messages.json (12 keys; D-07 + D-08 baked in)` @@ -989,7 +993,7 @@ describe('_locales/ key parity', () => { The fallback `|| ` pattern reduces the need for chrome.i18n stubs in tests that don't depend on the displayed text; tests that DO depend on text shape need the identity-passthrough stub. - 6. Run `npm test` — expect 104+ GREEN (98 existing + 6 new tests + any new copy in popup tests adjusted via chrome.i18n stub). + 6. Run `npm test` — expect 106+ GREEN (100 existing post-01-14 + 6 new tests + any new copy in popup tests adjusted via chrome.i18n stub). 7. Run `npm run build` then re-run `tests/build/no-remote-fonts.test.ts` — expect GREEN (dist/tokens.css contains zero `googleapis` / `https://fonts`). @@ -1002,7 +1006,7 @@ describe('_locales/ key parity', () => { - src/background/index.ts uses chrome.i18n.getMessage at every operator-facing copy site (badge titles + 2 notification call sites; verified by grep ≥ 4 occurrences); BADGE_REC_COLOR === '#b2543d' - tests/build/tokens-adopted.test.ts ALL cases GREEN (including (b)+(c) which were RED in Wave 0) - tests/build/no-remote-fonts.test.ts GREEN (after npm run build) - - vitest baseline 104+ GREEN (existing 98 + 6 new); no regressions in tests/background/* + - vitest baseline 106+ GREEN (existing 100 post-01-14 + 6 new); no regressions in tests/background/* - Atomic commit `feat(01-12): wave-4 task-1 — adopt tokens.css + chrome.i18n.getMessage in src/popup/ + src/background/ (loom palette + RU i18n + en fallback)` @@ -1036,7 +1040,7 @@ describe('_locales/ key parity', () => { 5. Create scripts/README.md (single paragraph per RESEARCH §12): document that smoke.sh + future dev-only scripts live in this directory + are NOT bundled by npm run build + the production dist/ contains no smoke artifacts. Cross-reference RESEARCH.md §12 for the no-op-confirmation rationale. - 6. Run npm test + npm run build + npm run build:test — expect all GREEN baseline + 6 new tests. + 6. Run npm test + npm run build + npm run build:test — expect all GREEN baseline (100 post-01-14) + 6 new tests = 106 GREEN. 7. (Optional but recommended per RESEARCH §12 + the existing Tier-1 gate pattern): add a `tests/build/no-smoke-in-dist.test.ts` test asserting `grep -rn smoke dist/` returns 0 matches post-build. RED today if any smoke string leaks; GREEN per current architecture. Keep this OPTIONAL — if context budget tight, defer to a follow-up plan. @@ -1048,7 +1052,7 @@ describe('_locales/ key parity', () => { - IF 01-10 NOT landed: src/welcome/* unchanged; STATE.md gains deferral note - vite.config.ts:define block contains __VITE_DEV__ entry - scripts/README.md exists + documents smoke-isolation invariant - - vitest baseline 104+ GREEN (+ N welcome keys added to messages.json if 01-10 landed; locale-parity stays GREEN) + - vitest baseline 106+ GREEN (+ N welcome keys added to messages.json if 01-10 landed; locale-parity stays GREEN) - Atomic commit `feat(01-12): wave-5 task-1 — welcome i18n migration (conditional on 01-10) + __VITE_DEV__ define + scripts/README.md` @@ -1057,9 +1061,9 @@ describe('_locales/ key parity', () => { Wave 6 Task 1: Extend UAT harness with A18-A22 (font / icon / manifest-i18n / Lora-resolved / welcome-tokens) tests/uat/extension-page-harness.ts, tests/uat/lib/harness-page-driver.ts, tests/uat/harness.test.ts - The 01-13 harness gains 5 new assertions following the established Approach-B pattern (page-side assertA* + host-side driveA* wrapper + harness.test.ts orchestrator entry). Each assertion uses production chrome.* APIs + fetch + getComputedStyle (no new test-mode symbols). After this wave: `npm run test:uat` reports 20/20 GREEN (or 23/23 with 01-10's A15-A17 already in place). + The 01-13 + 01-14 harness gains 5 new assertions following the established Approach-B pattern (page-side assertA* + host-side driveA* wrapper + harness.test.ts orchestrator entry). Each assertion uses production chrome.* APIs + fetch + getComputedStyle (no new test-mode symbols). After this wave: `npm run test:uat` reports 21/21 GREEN (or 24/24 with 01-10's A15-A17 already in place). A0-A14 (Plan 01-13) and A23 (Plan 01-14) remain GREEN as no-regression guarantees. - Tier-1 FORBIDDEN_HOOK_STRINGS list stays at 10 entries (no new test-mode surface introduced). + Tier-1 FORBIDDEN_HOOK_STRINGS list stays at 12 entries post-Plan-01-14 (no new test-mode surface introduced by Plan 01-12). 1. Extend tests/uat/extension-page-harness.ts: add 5 page-side methods to window.__mokoshHarness per the `` block shapes: @@ -1071,21 +1075,21 @@ describe('_locales/ key parity', () => { 2. Extend tests/uat/lib/harness-page-driver.ts: add driveA18 / driveA19 / driveA20 / driveA21 / driveA22 wrappers following the established driveA4 pattern (page.evaluate(() => window.__mokoshHarness.assertXX())). No new host-side fs / ffprobe / zip primitives. - 3. Extend tests/uat/harness.test.ts: import driveA18..A22; add entries to the orchestrator's assertion list in sequence (after A14, or A17 if 01-10 landed). Keep FORBIDDEN_HOOK_STRINGS UNCHANGED at 10 entries — verify by `wc -l` diff before/after this task. + 3. Extend tests/uat/harness.test.ts: import driveA18..A22; add entries to the orchestrator's assertion list in sequence (after A14, or A17 if 01-10 landed, with A23 from 01-14 elsewhere in the list). Keep FORBIDDEN_HOOK_STRINGS UNCHANGED at 12 entries (the 01-14-established baseline) — verify by `wc -l` diff before/after this task. - 4. Run npm run build:test (rebuilds dist-test/). Then run `npm run test:uat` (or just `tsx tests/uat/harness.test.ts`). Expected output: 20/20 (or 23/23) GREEN. + 4. Run npm run build:test (rebuilds dist-test/). Then run `npm run test:uat` (or just `tsx tests/uat/harness.test.ts`). Expected output: 21/21 (or 24/24) GREEN. 5. Run `npx vitest run tests/background/no-test-hooks-in-prod-bundle.test.ts` — confirm Tier-1 grep gate GREEN (no new hook strings leaked into dist/). - grep -c "assertA1[89]\|assertA2[012]" tests/uat/extension-page-harness.ts && grep -c "driveA1[89]\|driveA2[012]" tests/uat/lib/harness-page-driver.ts && grep -c "driveA1[89]\|driveA2[012]" tests/uat/harness.test.ts && (wc -l tests/uat/harness.test.ts && grep "FORBIDDEN_HOOK_STRINGS" tests/uat/harness.test.ts -A 13 | grep -c "'") && npx vitest run tests/background/no-test-hooks-in-prod-bundle.test.ts 2>&1 | tail -5 && (npm run test:uat 2>&1 | tail -25 || echo "test:uat invocation needs verification; check for 20/20 or 23/23 GREEN") + grep -c "assertA1[89]\|assertA2[012]" tests/uat/extension-page-harness.ts && grep -c "driveA1[89]\|driveA2[012]" tests/uat/lib/harness-page-driver.ts && grep -c "driveA1[89]\|driveA2[012]" tests/uat/harness.test.ts && (wc -l tests/uat/harness.test.ts && grep "FORBIDDEN_HOOK_STRINGS" tests/uat/harness.test.ts -A 15 | grep -v "^#" | grep -c "'") && npx vitest run tests/background/no-test-hooks-in-prod-bundle.test.ts 2>&1 | tail -5 && (npm run test:uat 2>&1 | tail -25 || echo "test:uat invocation needs verification; check for 21/21 or 24/24 GREEN") - 5 new assertA* methods on window.__mokoshHarness (verified by grep ≥ 5) - 5 new driveA* wrappers in harness-page-driver.ts - harness.test.ts orchestrator runs all 20 (or 23 with 01-10) assertions sequentially - - npm run test:uat exits 0 with 20/20 (or 23/23) GREEN - - Tier-1 forbidden-strings inventory in no-test-hooks-in-prod-bundle.test.ts UNCHANGED at 10 entries (no new test-mode symbols) + - npm run test:uat exits 0 with 21/21 (or 24/24) GREEN + - Tier-1 forbidden-strings inventory in no-test-hooks-in-prod-bundle.test.ts UNCHANGED at 12 entries post-Plan-01-14 (no new test-mode symbols added by Plan 01-12) - Atomic commit `feat(01-12): wave-6 task-1 — harness A18-A22 (font reachability + icon-distinct + manifest-i18n + Lora-resolved + welcome-tokens)` @@ -1099,7 +1103,7 @@ describe('_locales/ key parity', () => { Operator types 'approved' after running the how-to-verify steps. See . - Plan 01-12 lands the full design integration: Lora self-hosted (R2 designer reply); IBM Plex Sans + Mono self-hosted (Latin + Cyrillic); src/shared/tokens.css canonical (Newsreader → Lora substitution + .mks-word class + zero remote @import); icons rasterized from Loom mark (replaces Bug A placeholders); manifest:name + :description + :default_title migrated to chrome i18n (__MSG_*__ + _locales/{en,ru}/messages.json); 12 i18n keys land with D-07 + D-08 + Brief §02 verbatim Russian copy; src/popup/ + src/background/ use chrome.i18n.getMessage at every operator-facing site + tokens.css palette; BADGE_REC_COLOR madder-rust per D-04; welcome page (if 01-10 landed) inherits canonical tokens; vite __VITE_DEV__ defensive define; UAT harness 20/20 (or 23/23) GREEN with A18-A22 covering font reachability + icon-distinct + manifest-i18n + Lora-resolved + welcome-tokens. + Plan 01-12 lands the full design integration: Lora self-hosted (R2 designer reply); IBM Plex Sans + Mono self-hosted (Latin + Cyrillic); src/shared/tokens.css canonical (Newsreader → Lora substitution + .mks-word class + zero remote @import); icons rasterized from Loom mark (replaces Bug A placeholders); manifest:name + :description + :default_title migrated to chrome i18n (__MSG_*__ + _locales/{en,ru}/messages.json); 12 i18n keys land with D-07 + D-08 + Brief §02 verbatim Russian copy; src/popup/ + src/background/ use chrome.i18n.getMessage at every operator-facing site + tokens.css palette; BADGE_REC_COLOR madder-rust per D-04; welcome page (if 01-10 landed) inherits canonical tokens; vite __VITE_DEV__ defensive define; UAT harness 21/21 (or 24/24) GREEN with A18-A22 covering font reachability + icon-distinct + manifest-i18n + Lora-resolved + welcome-tokens (A0-A14 from 01-13 and A23 from 01-14 remain GREEN as no-regression guarantees). 1. Fresh build + load: @@ -1130,7 +1134,7 @@ describe('_locales/ key parity', () => { - Verify: welcome hero renders D-08 tagline in Lora; warm-linen background; mark slot shows the Loom mark; Russian + English parallel-text copy renders correctly. 7. Harness gate: - - `npm run test:uat` exits 0 with 20/20 GREEN (or 23/23 with 01-10). + - `npm run test:uat` exits 0 with 21/21 GREEN (or 24/24 with 01-10). - Tier-1 grep gate GREEN: `npx vitest run tests/background/no-test-hooks-in-prod-bundle.test.ts`. 8. Type "approved" if brand fit accepted, OR describe specific issues for follow-up. @@ -1145,7 +1149,7 @@ describe('_locales/ key parity', () => { 1. Create .planning/phases/01-stabilize-video-pipeline/01-12-SUMMARY.md following the template at $HOME/.claude/get-shit-done/templates/summary.md AND mirroring the structural choices of 01-13-SUMMARY.md (frontmatter with phase/plan/subsystem/tags/requires/provides/affects/tech-stack/key-files/decisions/metrics; body sections One-Liner / What Landed by Wave / Test Counts / Deviations from Plan / Architectural Notes Worth Carrying Forward / Self-Check / Known Limitations / Bridge to Phase 1 Closure). Key content: - - One-Liner: "Design integration landed end-to-end: Lora self-hosted (R2 designer reply 2026-05-19); src/shared/tokens.css canonical; 12 i18n keys via _locales/{en,ru}; branded Loom icons replace placeholders; src/popup + src/background use chrome.i18n.getMessage + loom palette; harness 20/20 (or 23/23) GREEN with A18-A22; operator brand-fit ack received." + - One-Liner: "Design integration landed end-to-end: Lora self-hosted (R2 designer reply 2026-05-19); src/shared/tokens.css canonical; 12 i18n keys via _locales/{en,ru}; branded Loom icons replace placeholders; src/popup + src/background use chrome.i18n.getMessage + loom palette; harness 21/21 (or 24/24) GREEN with A18-A22; operator brand-fit ack received." - Wave-by-wave breakdown with commit refs. - Test Counts table: vitest before/after; harness before/after. - Architectural Notes: R2 substitution rationale; OFL attribution pattern; tokens.css as single source of truth; chrome.i18n.getMessage fallback pattern (|| ); .mks-word class as engineering working-defn (designer overridable); icons-as-static-artifacts (NOT regenerated in prebuild per RESEARCH §3 anti-pattern). @@ -1201,7 +1205,7 @@ describe('_locales/ key parity', () => { | T-01-12-05 | Tampering | Vite asset hashing breaking @font-face url() resolution at runtime | mitigate | RESEARCH §2 Pattern A validated empirically (tokens.css → relative url(./fonts/x.woff2) → Vite rebases → @crxjs auto-WAR). UAT harness A18 walks document.styleSheets to resolve the actual emitted URL (handles hashing); fetch + size check verifies runtime reachability. Pattern B fallback (public/fonts/) documented in RESEARCH §2 if Pattern A misfires. | | T-01-12-06 | Spoofing | `__MSG_@@extension_id__` substitution in manifest fields (not supported per Chrome docs) | accept | Plan 01-12 does NOT use @@extension_id; documented as RESEARCH §11 anti-pattern + per the explicit "Anti-pattern" subsection. Low blast radius (only affects if engineer ignores docs). | | T-01-12-07 | Information Disclosure | chrome.i18n.getMessage returning empty string when default_locale lacks key (RESEARCH Pitfall 4) | mitigate | The `|| ` fallback pattern uniformly applied in src/popup/index.ts + src/background/index.ts (Wave 4) ensures missing-key cases degrade to literal English-ish text rather than blank UI. tests/i18n/locale-parity.test.ts asserts key-parity to catch missing keys at unit-test time. | -| T-01-12-08 | Elevation of Privilege | Test-mode hook strings leaking into production dist/ (T-1-11-01 + T-1-13-* inheritance) | accept | Plan 01-12 introduces ZERO new test-mode symbols (A18-A22 use production chrome.* + fetch + getComputedStyle exclusively). Tier-1 grep gate at tests/background/no-test-hooks-in-prod-bundle.test.ts remains at 10 entries; no extension needed. Verified by file-diff at task end. | +| T-01-12-08 | Elevation of Privilege | Test-mode hook strings leaking into production dist/ (T-1-11-01 + T-1-13-* + T-1-14-* inheritance) | accept | Plan 01-12 introduces ZERO new test-mode symbols (A18-A22 use production chrome.* + fetch + getComputedStyle exclusively). Tier-1 grep gate at tests/background/no-test-hooks-in-prod-bundle.test.ts remains at 12 entries post-Plan-01-14; no extension needed. Verified by file-diff at task end. | | T-01-12-09 | Tampering | OFL license/attribution non-compliance | mitigate | src/shared/fonts/LICENSE-Lora.txt + LICENSE-IBM-Plex.txt ship verbatim per OFL-1.1 attribution best practice (RESEARCH §7); src/shared/fonts/README.md cross-references upstream URLs + R2 substitution rationale. | @@ -1210,13 +1214,13 @@ Phase-level invariants to assert post-plan: 1. **Build cleanliness:** `npm run build` exits 0; `npm run build:test` exits 0; `npx tsc --noEmit` exits 0. 2. **MV3 CSP compliance:** zero `googleapis` / `https://fonts` matches in dist/ (tests/build/no-remote-fonts.test.ts). -3. **Vitest baseline grown:** 98 → 104+ GREEN (+6 new unit tests; +N if welcome migration adds keys). -4. **UAT harness 20/20 (or 23/23 with 01-10) GREEN:** `npm run test:uat` exits 0; A0 Tier-1 grep gate GREEN; A1-A14 (or A1-A17 with 01-10) GREEN; A18-A22 GREEN. +3. **Vitest baseline grown:** 100 (post-01-14) → 106+ GREEN (+6 new unit tests; +N if welcome migration adds keys). +4. **UAT harness 21/21 (or 24/24 with 01-10) GREEN:** `npm run test:uat` exits 0; A0 Tier-1 grep gate GREEN; A1-A14 (or A1-A17 with 01-10) + A23 (Plan 01-14) GREEN; A18-A22 GREEN. 5. **Font bundle present:** all 7 or 8 WOFF2 files exist under src/shared/fonts/; total bundle ≤ 350KB; LICENSE files + README.md present. 6. **Icons rasterized:** icons/icon{16,48,128}.png are 8-bit RGBA PNGs at correct dims + clearing FLOOR; differ in content from the Bug A placeholders. 7. **Manifest i18n wired:** chrome://extensions name reads "Mokosh — Session Capture" (en) or "Mokosh — Запись сессии" (ru); operator-facing tooltips + notification copy + popup CTA all resolve via chrome.i18n.getMessage. 8. **Tokens adopted:** src/popup/style.css has 0 hex literals + imports tokens.css; src/welcome/welcome.css (if 01-10 landed) imports tokens.css; BADGE_REC_COLOR is madder-rust #b2543d. -9. **Tier-1 forbidden-strings inventory UNCHANGED at 10 entries.** +9. **Tier-1 forbidden-strings inventory UNCHANGED at 12 entries post-Plan-01-14.** 10. **R2 substitution complete:** zero `Newsreader` references anywhere in src/shared/tokens.css; --mks-font-display === '"Lora", "Iowan Old Style", "Times New Roman", serif'. 11. **Operator brand-fit ack:** Wave 7 checkpoint received "approved". @@ -1234,8 +1238,8 @@ Phase-level invariants to assert post-plan: - [ ] If Plan 01-10 landed: welcome-tokens.css = `@import '../shared/tokens.css';`; welcome.ts uses chrome.i18n.getMessage - [ ] vite.config.ts has `__VITE_DEV__` defensive define - [ ] scripts/{rasterize-icons.sh,subset-fonts.sh,README.md} all present -- [ ] UAT harness A18-A22 implemented + GREEN; npm run test:uat exits 0 with 20/20 (or 23/23 with 01-10) GREEN -- [ ] Tier-1 forbidden-strings inventory UNCHANGED at 10 entries +- [ ] UAT harness A18-A22 implemented + GREEN; npm run test:uat exits 0 with 21/21 (or 24/24 with 01-10) GREEN +- [ ] Tier-1 forbidden-strings inventory UNCHANGED at 12 entries post-Plan-01-14 - [ ] Operator empirical brand-fit ack ("approved") received at Wave 7 checkpoint - [ ] 01-12-SUMMARY.md exists + STATE.md + ROADMAP.md synced - [ ] All commits atomic + follow `feat(01-12)/test(01-12)/docs(01-12): wave-N task-M — ` convention