fix(01-09): notifStartup text split — notifStartupCta for onStartup; notifRecordingStarted for manual-start
Operator UAT 2026-05-20 rejected the build because the OS notification fired
on `chrome.runtime.onStartup` ("Recording started. I'm watching the last 30
seconds.") implied recording had auto-started when in fact recording was
not running. Per Phase 1 always-on charter recording does NOT auto-start;
the notification is the gesture surface that invites the operator to start
one (notifications.onClicked → startVideoCapture, src/background/index.ts:1038).
Root cause: a single i18n key `notifStartup` conflated the pre-recording
CTA-with-gesture path (the only path actually wired today) and a future
post-manual-start confirmation path. The key's own `.description` field
acknowledged the conflation. Operator-facing text leaned toward the
confirmation phrasing.
Fix (key split, no behavior change):
- `notifStartupCta` — EN: "Mokosh ready. Click to start a recording." /
RU: "Mokosh готов. Нажмите, чтобы начать запись." — wired into the
onStartup handler.
- `notifRecordingStarted` — preserves the original text ("Recording
started. I'm watching the last 30 seconds." / "Запись запущена…") for
a future post-manual-start confirmation flow.
- Fallback constant renamed `NOTIF_STARTUP_FALLBACK` →
`NOTIF_STARTUP_CTA_FALLBACK`; value updated to match the new CTA text.
- Inline test comment in tests/background/onstartup-notification.test.ts
refreshed to reference the new key + fallback. Assertion regex
/recording|recor|click/i covers both fallback + resolved locale variants,
no logic change.
Notification behavior preserved: same id prefix `mokosh-startup-`, same
priority, same icon, same onClicked → startVideoCapture wiring. No new
test-mode symbols (FORBIDDEN_HOOK_STRINGS inventory stays at 12).
Files modified:
- _locales/en/messages.json
- _locales/ru/messages.json
- src/background/index.ts
- tests/background/onstartup-notification.test.ts
Verification:
- npx vitest run --exclude tests/build/** --exclude tests/background/no-test-hooks-in-prod-bundle.test.ts: 104/104 GREEN
- npx vitest run tests/i18n/ tests/background/onstartup-notification.test.ts: 18/18 GREEN (locale-parity 4/4 + onstartup-notification 14/14)
- npx tsc --noEmit clean on src/background/index.ts
The 2 build-dependent vitest gates (tests/build/no-remote-fonts.test.ts +
tests/background/no-test-hooks-in-prod-bundle.test.ts) and npm run test:uat
are deferred to orchestrator-level re-verification after the parallel
Plan 01-10 mark-bundling fix also lands (operator-UAT re-spawn coordinated
by orchestrator).
Debug record: .planning/debug/resolved/01-09-startup-notification-misleading-text.md
Operator UAT rejection event: 2026-05-20
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -159,12 +159,15 @@ describe('Plan 01-09 Task 3: chrome.runtime.onStartup notification contract', ()
|
||||
expect(typeof opts.title).toBe('string');
|
||||
expect(/Mokosh/i.test(String(opts.title))).toBe(true);
|
||||
expect(typeof opts.message).toBe('string');
|
||||
// Plan 01-12 Wave 4: notification message migrated from literal
|
||||
// 'Click here to start recording your session.' to
|
||||
// chrome.i18n.getMessage('notifStartup') with fallback
|
||||
// 'Recording started. Click here to start a recording.'. Tests
|
||||
// without a chrome.i18n stub observe the fallback; both contain
|
||||
// 'recording' (case-insensitive).
|
||||
// Plan 01-12 Wave 4: notification message migrated to chrome.i18n.
|
||||
// Plan 01-09 amendment 2026-05-20: key split — onStartup handler now
|
||||
// reads `notifStartupCta` with fallback `NOTIF_STARTUP_CTA_FALLBACK`
|
||||
// ('Mokosh ready. Click to start a recording.'); the prior conflated
|
||||
// `notifStartup` key was retired (`notifRecordingStarted` reserved
|
||||
// for post-manual-start confirmation). Tests without a chrome.i18n
|
||||
// stub observe the CTA fallback; the regex matches both 'click' and
|
||||
// 'recording' (case-insensitive) so it survives both the fallback
|
||||
// and the resolved locale value.
|
||||
expect(/recording|recor|click/i.test(String(opts.message))).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user