Milestone v1 (v2.0.0): Mokosh — Session Capture #1

Merged
strategy155 merged 297 commits from gsd/phase-04-harden-clean-up-optional into main 2026-05-31 15:34:17 +00:00
Showing only changes of commit 8f329d8b74 - Show all commits

View File

@@ -98,6 +98,17 @@ const NOTIFICATION_STARTUP_PREFIX = 'mokosh-startup-';
const NOTIFICATION_RECOVERY_PREFIX = 'mokosh-recovery-';
const POPUP_HTML_PATH = 'src/popup/index.html';
// ─── Plan 01-10 onboarding constants (D-17-onboarding) ───────────────
// Project naming standard: SCREAMING_SNAKE for true constants. These
// drive the first-install welcome-tab flow (chrome.runtime.onInstalled
// → openWelcomeIfFirstInstall; flag persisted via chrome.storage.local).
// The 'onboarding-completed' key is the storage-schema identifier
// preserved across SW respawns (and surveyed by the unit test in
// tests/background/onboarding.test.ts Test A).
const ONBOARDING_FLAG = 'onboarding-completed';
const ONBOARDING_INSTALLED_AT = 'installed-at';
const WELCOME_PATH = 'src/welcome/welcome.html';
// Plan 01-12 Wave 4: operator-facing copy fallbacks for the notification
// title (extName) + the two notification messages. Same `|| fallback`
// pattern as the popup — unit-test contexts without chrome.i18n stub
@@ -217,6 +228,58 @@ async function ensureOffscreen() {
}
}
/**
* Open the welcome page on first install (Plan 01-10 D-17-onboarding).
*
* The 'D-17-onboarding' suffix disambiguates from D-17-port-lifecycle
* per CONTEXT.md lines 540-545. Trigger conditions (all must hold):
* - details.reason === 'install' (NOT 'update' / 'chrome_update' /
* 'shared_module_update');
* - chrome.storage.local key 'onboarding-completed' NOT === true.
*
* Side effects on first install:
* - chrome.tabs.create({url: chrome.runtime.getURL('src/welcome/welcome.html')})
* - chrome.storage.local.set({'onboarding-completed': true,
* 'installed-at': Date.now()})
*
* Failure mode: any thrown chrome.* call is caught + logged via
* logger.warn. The welcome tab failing is NOT fatal — the toolbar
* onClicked path (D-16-toolbar) remains the operator's start path and
* is independent of the onboarding flow.
*
* Architectural note: the fetch of 'onboarding-completed' uses the
* EXACT string key (no array form) so the unit-test contract in
* tests/background/onboarding.test.ts Test A's assertion
* "saw chrome.storage.local.get('onboarding-completed')" holds. The
* storage-schema cross-version-compat pin (I-02 lesson preserved from
* prior plan draft) lives in that test.
*/
async function openWelcomeIfFirstInstall(
details: chrome.runtime.InstalledDetails,
): Promise<void> {
if (details.reason !== 'install') {
return;
}
try {
const stored = await chrome.storage.local.get(ONBOARDING_FLAG);
if (stored[ONBOARDING_FLAG] === true) {
logger.log('Onboarding already completed; skipping welcome tab.');
return;
}
const url = chrome.runtime.getURL(WELCOME_PATH);
await chrome.tabs.create({ url });
await chrome.storage.local.set({
[ONBOARDING_FLAG]: true,
[ONBOARDING_INSTALLED_AT]: Date.now(),
});
logger.log(
'Welcome tab opened (D-17-onboarding); onboarding flag set.',
);
} catch (err) {
logger.warn('openWelcomeIfFirstInstall failed:', err);
}
}
// Outer-bound buffer fetch budget. Larger than the legacy
// BUFFER_FETCH_TIMEOUT_MS (was 2 s; per-port-attempt) because the new
// architecture covers MULTIPLE port-replacement retries inside one outer
@@ -1002,6 +1065,14 @@ chrome.runtime.onInstalled.addListener((details) => {
logger.warn('IDB cleanup failed:', e);
}
initialize();
// Plan 01-10 D-17-onboarding: open welcome tab on first install.
// Fire-and-forget — the helper logs its own errors and rejected
// promises are caught at the .catch boundary so they cannot escape
// the synchronous listener. The toolbar onClicked start path
// (D-16-toolbar) is independent of this flow.
openWelcomeIfFirstInstall(details).catch((err) => {
logger.warn('openWelcomeIfFirstInstall threw:', err);
});
});
// Запуск при старте Service Worker