Plan 01-12 D-07 (commit5efc2a8) migrated manifest.json:name + tooltip + extName/extDesc keys to chrome.i18n placeholders + _locales/{en,ru}/ messages.json resolving to 'Mokosh — Session Capture' (EN) / 'Mokosh — Запись сессии' (RU). However, 4 trailing references to the pre-D-07 literal 'AI Call Recorder' in non-manifest content surfaces were never propagated. Operator noticed during Plan 01-10 cycle-2 UAT 2026-05-20. This commit applies the user-approved 4-file surgical rename: - src/welcome/copy.ts: welcome.body.cta.toolbar RU CTA "иконку AI Call Recorder" → "иконку Mokosh" (matches toolbar tooltip i18n key tooltipOff = "Mokosh — щёлкните, чтобы начать запись"). Inline rationale comment added cross-ref'ing the i18n key + this debug session. - README.md: H1 + first paragraph rewritten to "# Mokosh — Session Capture" + EN tagline line. Rest of README body preserved verbatim (technical-stack section historical mentions left as project history, not brand surface). - package.json: name "ai-call-extension" → "mokosh-session-capture", description rewritten to "Mokosh — Session Capture: Chrome MV3 extension for operator session recording." version, scripts, dependencies, devDependencies untouched. - tests/i18n/manifest-i18n.test.ts: header comment block rewritten to label the "AI Call Recorder" string as Wave-0 historical state + describe the post-D-07 regression-pin role. Test bodies + assertions unchanged (already pin the post-D-07 canonical state). Preservation rationale: .planning/intel/* (brand-decisions-v1.md D-07, design-system.md, brand-identity.md, classifications/README-*.json, design-incoming/system/bundle/mokosh-handoff/handoff.html) is audit trail documenting the "why" of D-07 — kept verbatim. _locales/{en,ru}/ messages.json and manifest.json already post-D-07 canonical — untouched. Acceptance gates (all PASS 2026-05-20): - Empirical grep src/ tests/ README.md package.json: ZERO non-historical "AI Call Recorder" matches (only the labeled audit anchor in tests/i18n/manifest-i18n.test.ts:8). - npx tsc --noEmit: clean. - npm run build: ✓ built in 5.29s. - npx vitest run tests/i18n/manifest-i18n.test.ts: 10/10 GREEN. - npx vitest run tests/background/no-test-hooks-in-prod-bundle.test.ts (Tier-1 hook-string grep gate): 13/13 GREEN; FORBIDDEN_HOOK_STRINGS list intact. - npm test: 151/153 (2 pre-existing ffprobe/ffmpeg timeout flakes in webm-remux + webm-playback — verified identical to pristine HEADa2dfc8cvia git stash baseline; unrelated to rename). - npm run test:uat: 24/24 GREEN. - Production bundle grep dist/: ZERO "AI Call Recorder" + ZERO "ai-call-extension" matches. Unblocks Plan 01-10 closure + Phase 1 final closure (REQUIREMENTS / ROADMAP / STATE marker flip). Debug record: .planning/debug/resolved/01-12-stale-ai-call-recorder-references.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
92 lines
4.0 KiB
TypeScript
92 lines
4.0 KiB
TypeScript
// tests/i18n/manifest-i18n.test.ts — Plan 01-12 i18n migration regression
|
|
// pin (post-D-07 state).
|
|
//
|
|
// Asserts manifest.json uses chrome i18n placeholders with default_locale='en'
|
|
// + _locales/{en,ru}/messages.json carrying the D-07 + D-08 canonical strings.
|
|
//
|
|
// History: Plan 01-12 D-07 migrated manifest.json:name from the literal
|
|
// 'AI Call Recorder' (no default_locale; no _locales/) to the
|
|
// '__MSG_extName__' i18n placeholder that resolves to
|
|
// 'Mokosh — Session Capture' (en) / 'Mokosh — Запись сессии' (ru). The
|
|
// test was Wave-0 RED against the pre-migration state and flipped GREEN
|
|
// after Wave-3 Task 1 landed the manifest + messages.json files. This
|
|
// file now pins the post-D-07 state as a regression guard.
|
|
//
|
|
// References:
|
|
// - RESEARCH §10 + §11 (Chrome i18n schema; __MSG_* placeholder rules)
|
|
// - brand-decisions-v1.md D-07 override (`Mokosh — Session Capture`)
|
|
// - brand-decisions-v1.md D-08 tagline (`Thirty seconds ago, always at hand.`)
|
|
|
|
import { describe, expect, it } from 'vitest';
|
|
import { existsSync, readFileSync } from 'node:fs';
|
|
import { resolve as resolvePath } from 'node:path';
|
|
|
|
const MANIFEST_PATH = resolvePath(process.cwd(), 'manifest.json');
|
|
const EN_LOCALE_PATH = resolvePath(process.cwd(), '_locales/en/messages.json');
|
|
const RU_LOCALE_PATH = resolvePath(process.cwd(), '_locales/ru/messages.json');
|
|
|
|
interface I18nEntry {
|
|
message: string;
|
|
description?: string;
|
|
}
|
|
|
|
type LocaleFile = Record<string, I18nEntry>;
|
|
|
|
describe('Plan 01-12: manifest i18n migration (__MSG_*__ + default_locale)', () => {
|
|
it('manifest.json:name === "__MSG_extName__" (i18n placeholder)', () => {
|
|
const manifest = JSON.parse(readFileSync(MANIFEST_PATH, 'utf8'));
|
|
expect(manifest.name).toBe('__MSG_extName__');
|
|
});
|
|
|
|
it('manifest.json:description === "__MSG_extDesc__"', () => {
|
|
const manifest = JSON.parse(readFileSync(MANIFEST_PATH, 'utf8'));
|
|
expect(manifest.description).toBe('__MSG_extDesc__');
|
|
});
|
|
|
|
it('manifest.json:default_locale === "en"', () => {
|
|
const manifest = JSON.parse(readFileSync(MANIFEST_PATH, 'utf8'));
|
|
expect(manifest.default_locale).toBe('en');
|
|
});
|
|
|
|
it('manifest.json:action.default_title === "__MSG_tooltipOff__"', () => {
|
|
const manifest = JSON.parse(readFileSync(MANIFEST_PATH, 'utf8'));
|
|
expect(manifest.action?.default_title).toBe('__MSG_tooltipOff__');
|
|
});
|
|
});
|
|
|
|
describe('Plan 01-12: _locales/en/messages.json (default_locale fallback)', () => {
|
|
it('_locales/en/messages.json exists + parses', () => {
|
|
expect(existsSync(EN_LOCALE_PATH), `Expected ${EN_LOCALE_PATH}`).toBe(true);
|
|
const en = JSON.parse(readFileSync(EN_LOCALE_PATH, 'utf8'));
|
|
expect(typeof en).toBe('object');
|
|
});
|
|
|
|
it('en:extName === "Mokosh — Session Capture" (D-07 override)', () => {
|
|
const en: LocaleFile = JSON.parse(readFileSync(EN_LOCALE_PATH, 'utf8'));
|
|
expect(en.extName?.message).toBe('Mokosh — Session Capture');
|
|
});
|
|
|
|
it('en:extDesc === "Thirty seconds ago, always at hand." (D-08 tagline)', () => {
|
|
const en: LocaleFile = JSON.parse(readFileSync(EN_LOCALE_PATH, 'utf8'));
|
|
expect(en.extDesc?.message).toBe('Thirty seconds ago, always at hand.');
|
|
});
|
|
});
|
|
|
|
describe('Plan 01-12: _locales/ru/messages.json (primary operator locale)', () => {
|
|
it('_locales/ru/messages.json exists + parses', () => {
|
|
expect(existsSync(RU_LOCALE_PATH), `Expected ${RU_LOCALE_PATH}`).toBe(true);
|
|
const ru = JSON.parse(readFileSync(RU_LOCALE_PATH, 'utf8'));
|
|
expect(typeof ru).toBe('object');
|
|
});
|
|
|
|
it('ru:extName === "Mokosh — Запись сессии"', () => {
|
|
const ru: LocaleFile = JSON.parse(readFileSync(RU_LOCALE_PATH, 'utf8'));
|
|
expect(ru.extName?.message).toBe('Mokosh — Запись сессии');
|
|
});
|
|
|
|
it('ru:extDesc === "Тридцать секунд назад, всегда под рукой."', () => {
|
|
const ru: LocaleFile = JSON.parse(readFileSync(RU_LOCALE_PATH, 'utf8'));
|
|
expect(ru.extDesc?.message).toBe('Тридцать секунд назад, всегда под рукой.');
|
|
});
|
|
});
|