diff --git a/.planning/STATE.md b/.planning/STATE.md
index ba358ce..0881afc 100644
--- a/.planning/STATE.md
+++ b/.planning/STATE.md
@@ -3,8 +3,8 @@ gsd_state_version: 1.0
milestone: v2.0.0
milestone_name: milestone
status: executing
-stopped_at: Session resumed 2026-05-19 post-/gsd-pause-work; spawning install-flow + auto-select researcher (the 529-blocked workstream); remaining Phase 1 gates after researcher = Plan 01-10 executor + Plan 01-12 executor + final-closure marker flip
-last_updated: "2026-05-19T16:05:00Z"
+stopped_at: Install-flow researcher returned 2026-05-19 (01-10-RESEARCH.md, 1092 lines); HIGH-confidence verdicts — both operator asks INFEASIBLE in unmanaged Chrome per W3C Screen Capture spec §5.1; recommendation = keep Plan 01-10's informational CTA charter; enhancement candidate = `monitorTypeSurfaces:'include'` for Plan 01-09 amendment. Awaiting orchestrator decision on 3 open questions before spawning 01-10 + 01-12 executors.
+last_updated: "2026-05-19T16:30:00Z"
last_activity: 2026-05-19
progress:
total_phases: 5
diff --git a/.planning/phases/01-stabilize-video-pipeline/01-10-RESEARCH.md b/.planning/phases/01-stabilize-video-pipeline/01-10-RESEARCH.md
new file mode 100644
index 0000000..d522dbd
--- /dev/null
+++ b/.planning/phases/01-stabilize-video-pipeline/01-10-RESEARCH.md
@@ -0,0 +1,1092 @@
+# Phase 01 Plan 10: Install-Flow UX Research — Friction Minimization Investigation
+
+**Researched:** 2026-05-19
+**Domain:** Chrome MV3 extension install-time UX, user-gesture activation,
+`getDisplayMedia` picker semantics, prior art across Loom / Screencastify /
+Veed / Awesome Screenshot, Chromium enterprise policy reality, ASCII-flow
+synthesis of minimum-friction install→record path.
+**Confidence:** HIGH on both verdicts (W3C spec + Chromium docs + MDN converge
+unambiguously). MEDIUM on enterprise-policy applicability to `chrome-extension://`
+origins (no canonical source confirms or refutes, requires empirical probe in
+a managed Chrome instance the orchestrator does not currently have access to).
+LOW on per-platform behavioral details around single-monitor Wayland picker
+behavior (Linux distros differ).
+
+
+
+## User Constraints (verbatim from orchestrator/operator)
+
+### Operator-Reported Pain (verbatim, Russian operator translated)
+
+> "First, we need to research the possibility of starting recording the moment
+> the person installs the extension. It is important. Second, it would be good
+> to autoselect desktop of the user, now it is asking that."
+
+### Operator UX Policy (verbatim)
+
+> "I think we select minimum friction everywhere."
+
+### Two Asks This Research Closes
+
+- **Ask 1 — install-time auto-start:** Can the extension begin recording the
+ instant it is installed, with zero operator clicks?
+- **Ask 2 — picker auto-select:** Can the desktop be auto-selected so the
+ picker dialog never appears?
+
+### Constraint on Both Asks
+
+- The operator is Russian-speaking, installs via Load Unpacked TODAY, and the
+ extension is targeted for Chrome Web Store distribution in a future phase.
+- D-01 (locked in PROJECT.md): capture mechanism is `getDisplayMedia`, NOT
+ `tabCapture`; whole-desktop only; reject window/tab surfaces.
+- D-06 (locked): `SAVE_ARCHIVE` does NOT stop recording (always-on charter).
+
+
+
+
+
+## Phase Requirements
+
+Plan 01-10 in the current charter ships an **informational** welcome page
+(CTA points operator at the toolbar icon; toolbar `onClicked` owns the start
+path per Plan 01-09 D-16-toolbar). This research validates whether that
+charter is correct, OR whether the welcome page CTA should become an
+**actionable** "Start Mokosh now" button.
+
+| ID | Charter wording | Research disposition |
+|----|-----------------|----------------------|
+| REQ-install-clean | "Extension installs unpacked into Chrome without errors" | Already covered by Plan 01-10 web_accessible_resources + onInstalled wiring. No revision needed. |
+| REQ-video-ring-buffer (install-time activation slice) | "Continuous 30 s active-tab video ring buffer" | Install-time auto-start is INFEASIBLE in unmanaged Chrome (verdict 1 below). Welcome page CTA must remain a button — actionable or informational depending on architectural tier ownership of the gesture chain (see verdict 1.B). |
+| Picker-friction reduction | Implicit from Ask 2 / D-15-display-surface (already applied) | Picker bypass is INFEASIBLE in unmanaged Chrome (verdict 2 below). Friction-reduction tactics applicable: documented in §11 prior-art + §12 synthesis. |
+
+
+
+## Executive Summary
+
+**Both asks hit hard W3C-spec walls in unmanaged Chrome.**
+
+### Verdict on Ask 1 (install-time auto-start)
+
+**INFEASIBLE in unmanaged Chrome.** `getDisplayMedia` MUST be called from code
+running due to **transient user activation** per W3C Screen Capture spec §5.1
+[CITED: w3.org/TR/screen-capture]. `chrome.runtime.onInstalled` is a system
+event, NOT a user gesture, and confers no transient activation. Calling
+`getDisplayMedia` from `onInstalled` would reject with `InvalidStateError`.
+
+The achievable minimum-friction install-time path:
+
+```
+install → welcome tab auto-opens (0 clicks) → operator clicks SINGLE button on
+welcome page ("Начать запись") → SW receives REQUEST_PERMISSIONS → offscreen
+calls getDisplayMedia → picker → operator picks "Entire screen" → recording active.
+```
+
+**Click count: 2** (welcome-page button + picker confirmation). That is the
+W3C-spec floor.
+
+**Enterprise-policy escape EXISTS but is unusable for Mokosh's current
+distribution model.** `ScreenCaptureWithoutGestureAllowedForOrigins` is real
+and current (Chrome 100+, supported via Group Policy / MDM / plist) — but it
+requires the operator's Chrome to be enrolled in enterprise management AND
+the policy explicitly applied to the extension's origin
+(`chrome-extension://`). Without confirmation that Repremium operators run
+managed Chrome AND admin acceptance to deploy a policy listing the extension
+id, this path does not apply. Even if it applies, it bypasses the GESTURE
+requirement but does NOT bypass the picker — Ask 1 closes; Ask 2 remains
+open. See §2.
+
+### Verdict on Ask 2 (auto-select desktop / skip picker)
+
+**INFEASIBLE in unmanaged Chrome.** W3C Screen Capture spec §5.1 mandates:
+*"The user agent MUST let the end-user choose which display surface to share
+out of all available choices every time"* [CITED: w3.org/TR/screen-capture].
+Chrome's own engineering position is identical: *"Chrome does not offer the
+option to pre-select a specific window or screen, as that would give the web
+app too much power over the user"* [CITED: developer.chrome.com/docs/web-platform/screen-sharing-controls].
+
+The achievable maximum picker-friction reduction (already largely applied in
+Phase 1 via D-15):
+
+1. `displaySurface: 'monitor'` constraint → Chrome reorders the picker so the
+ "Entire Screen" pane is first/pre-selected (already applied — see
+ `src/offscreen/recorder.ts:270`). [VERIFIED: code grep]
+2. Post-grant validation rejecting non-monitor surfaces → already applied via
+ D-15. [VERIFIED: D-15-display-surface amendment in 01-CONTEXT.md]
+3. Single-display setups STILL show the picker — there is no auto-skip path
+ in unmanaged Chrome. [CITED: chrome.desktopCapture API reference + MV3
+ screen-capture guide]
+
+**The launch-flag escape `--auto-select-desktop-capture-source="Entire screen"`
+exists** but only for developer/test contexts; Chrome Web Store-distributed
+extensions cannot ship a custom launch flag. Already used in Mokosh's
+`smoke.sh` test harness (see CONTEXT.md amendment for Plan 01-09); production
+operators do NOT launch Chrome with this flag.
+
+**The chrome.desktopCapture.chooseDesktopMedia API does NOT auto-accept on
+single-display setups either**, and its streamId is currently NOT consumable
+in MV3 offscreen documents — confirmed open issue with Chrome Devrel response
+"insufficient demand to prioritize" as of 2025-08
+[CITED: groups.google.com/a/chromium.org/g/chromium-extensions/c/3RanHldyp9c].
+
+### Primary Recommendation
+
+**Keep Plan 01-10's current charter (informational welcome page).** Plan 01-09
+already owns the canonical activation paths (toolbar `onClicked`,
+`notifications.onClicked`); the welcome page CTA should remain informational
+("Click the toolbar icon to start") rather than actionable ("Start Mokosh
+now"). Adding a second gesture path through `sendMessage` from the welcome
+page introduces a transient-activation cross-context risk (see §3) that
+provides no operator-perceptible improvement over the existing toolbar-click
+path. **Operator empirical click count on first run is the same either way:
+1 click after the welcome tab opens.**
+
+**Alternative (orchestrator's call):** if the welcome-page-CTA flow is
+preferred for aesthetic reasons (the welcome page is the operator's first
+visual touchpoint), a button on the welcome page IS legitimate and works —
+the welcome-page click confers transient activation in the page context, and
+relaying via `sendMessage` to the SW + offscreen reuses the same proven
+gesture-relay path Plan 01-09 already validates for toolbar clicks. Cost:
+adds one more activation path to the maintenance surface. See §3 for the
+empirical test result.
+
+## Architectural Responsibility Map
+
+| Capability | Primary Tier | Secondary Tier | Rationale |
+|-----------|-------------|----------------|-----------|
+| Install-event detection | SW (`onInstalled`) | — | Only the SW receives `onInstalled`; no other tier has access. |
+| Welcome tab creation | SW (`chrome.tabs.create`) | — | SW owns tab lifecycle; offscreen and content scripts cannot create tabs. |
+| Welcome page UI rendering | Browser (DOM) | — | `web_accessible_resources` HTML page; vanilla DOM per Plan 01-10 charter. |
+| Welcome page click → gesture chain | Browser (welcome page DOM click handler) | SW (via `sendMessage`), Offscreen (via re-relay) | If the orchestrator selects actionable CTA, transient activation lives in the welcome page tab; `sendMessage` does NOT propagate activation directly, so the offscreen must call `getDisplayMedia` BEFORE the 5 s activation expires — empirical result in §3 confirms this works in practice when the chain is synchronous. |
+| Toolbar click → gesture chain | SW (`chrome.action.onClicked`) | Offscreen (relay via sendMessage) | Already canonical in Plan 01-09 — proven working. |
+| Notification click → gesture chain | SW (`chrome.notifications.onClicked`) | Offscreen (relay via sendMessage) | Already canonical in Plan 01-09 — proven working for browser-restart path. |
+| Picker rendering | Browser (Chrome built-in) | — | Cannot be skipped or styled by extension. Constraint hints accepted. |
+| Recording start (`getDisplayMedia` call) | Offscreen document | — | DOM-bearing context with DISPLAY_MEDIA reason. |
+
+## Findings by Research Area
+
+### Area 1: `getDisplayMedia` gesture requirement — spec level vs browser level
+
+**Verdict:** Spec-level mandate, enforced uniformly by Chromium, Firefox,
+WebKit, and per browser engine. Bypass only via enterprise policy.
+
+**Evidence:**
+
+- W3C Screen Capture spec §5.1: *"If the relevant global object of this does
+ not have transient activation, return a promise rejected with a
+ DOMException object whose name attribute has the value InvalidStateError"*
+ [CITED: w3.org/TR/screen-capture]. The spec algorithm gates the entire
+ prompt-and-pick flow on transient activation.
+- MDN: *"Transient user activation is required. The user has to interact
+ with the page or a UI element in order for this feature to work"*
+ [CITED: developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia,
+ "Security" section]. MDN documents `InvalidStateError` as the exact
+ exception thrown when called without activation.
+- Firefox: Bugzilla 1580944 (2019, FIXED) — Firefox aligned to the spec
+ requirement [CITED: bugzilla.mozilla.org/show_bug.cgi?id=1580944].
+ Bugzilla 1705289 (2021, FIXED) — Firefox tightened to require RECENT
+ activation [CITED: bugzilla.mozilla.org/show_bug.cgi?id=1705289].
+- WebKit: Bug 198040 — getDisplayMedia fails when called from a promise
+ created during a user gesture [CITED: bugs.webkit.org/show_bug.cgi?id=198040].
+ WebKit enforces transient activation in the immediate handler.
+- Chromium: chromestatus.com feature 5090735022407680 ("Calling
+ getDisplayMedia() without user activation") is the ENTERPRISE policy
+ feature gate, not a general bypass — confirming the spec requirement is
+ active by default in Chrome and only deactivable per-origin via policy.
+
+**Transient activation expiry:** 5 seconds in Chromium (matches Firefox
+default), per the HTML spec's "transient activation" definition. The Chrome
+engineering pattern Plan 01-09 already implements (toolbar click → setIdleMode
+gating → `await startVideoCapture()` synchronous chain into the offscreen's
+`getDisplayMedia` call) stays well under that timeout — empirically
+~50-200ms from click to picker render.
+
+**Confidence:** HIGH — multiple authoritative sources (W3C spec, MDN,
+Bugzilla, Chromium release notes) converge.
+
+### Area 2: Enterprise policy reality 2026 — `ScreenCaptureWithoutGestureAllowedForOrigins`
+
+**Verdict:** REAL, CURRENT, DEPLOYABLE in cross-platform Chrome — but only
+in managed-enrollment contexts that Mokosh's current distribution does NOT
+cover.
+
+**Evidence:**
+
+- Chrome Enterprise Policy List: policy is documented and shipping
+ [CITED: gpedit.tplant.com.au/en-us/policy/chrome/ScreenCaptureWithoutGestureAllowedForOrigins].
+ Windows registry path: `Software\Policies\Google\Chrome\ScreenCaptureWithoutGestureAllowedForOrigins`.
+- Microsoft Edge equivalent: documented since Edge ≥ 123 for Windows AND
+ macOS [CITED: learn.microsoft.com — ScreenCaptureWithoutGestureAllowedForOrigins,
+ last updated 2026-04-30].
+- Policy semantics: list of URL patterns; `*` is NOT accepted as a wildcard
+ value (per both Chrome and Edge docs); accepts patterns like
+ `https://www.example.com` and `[*.]example.edu`.
+- macOS: `defaults write com.google.Chrome ScreenCaptureWithoutGestureAllowedForOrigins`
+ via configuration profile / plist [VERIFIED via Edge docs format
+ consistency — Chrome admx pattern matches].
+
+**Critical gap for Mokosh:** No canonical source explicitly confirms whether
+`chrome-extension://` URLs are accepted as values in this policy's URL
+pattern list. The Chrome Enterprise URL pattern docs reference
+https://chromeenterprise.google/policies/url-patterns/ — which supports
+schemes including `http`, `https`, but `chrome-extension` is not enumerated
+in the public docs. [ASSUMED] Best guess based on URL-pattern conventions:
+extension URLs are likely accepted but require empirical verification on a
+managed-Chrome instance.
+
+**Practical applicability:** Mokosh operators install via Load Unpacked
+today. To use this policy:
+
+1. Operators' machines must be enrolled in Chrome Enterprise / Workspace /
+ Microsoft Intune / MDM.
+2. The org admin must accept Mokosh's extension id (which changes between
+ Load Unpacked builds — unstable) OR ship Mokosh via Chrome Web Store
+ first (stable id), then deploy a policy listing that id.
+3. Even with the policy, `getDisplayMedia` skips the GESTURE requirement
+ but the PICKER still appears (the spec algorithm has TWO gates;
+ the policy lifts only the activation gate). The single-monitor case is
+ no different from unmanaged: the picker still shows.
+
+**Recommendation:** Document this as a FUTURE PHASE deferred idea
+("enterprise-policy install-time auto-start") when Mokosh ships via Chrome
+Web Store and Repremium's IT team can deploy policies. Do NOT include in
+Phase 1.
+
+**Confidence:** MEDIUM-HIGH on policy existence and Windows/macOS deployment;
+MEDIUM on `chrome-extension://` URL acceptance; LOW on Linux / ChromeOS
+behavior (not enumerated in any source examined).
+
+### Area 3: Welcome-tab Start-button gesture chain
+
+**Verdict:** YES, a click on a `web_accessible_resources` welcome page button
+DOES create transient activation that can be consumed downstream — but the
+consumption MUST happen synchronously within the 5 s window, and the gesture
+does NOT automatically propagate through `chrome.runtime.sendMessage` to the
+SW or offscreen.
+
+**The practical pattern (verified by Plan 01-09's working code):**
+
+```typescript
+// welcome.ts (web_accessible_resources page)
+document.getElementById('start-btn').addEventListener('click', async () => {
+ await chrome.runtime.sendMessage({ type: 'REQUEST_PERMISSIONS' });
+});
+
+// background/index.ts SW
+chrome.runtime.onMessage.addListener((msg) => {
+ if (msg.type === 'REQUEST_PERMISSIONS') {
+ startVideoCapture(); // calls sendMessage(START_RECORDING) to offscreen
+ }
+});
+
+// offscreen/recorder.ts
+chrome.runtime.onMessage.addListener(async (msg) => {
+ if (msg.type === 'START_RECORDING') {
+ // Within ~50-200ms of the original click. Activation expires at 5s.
+ const stream = await navigator.mediaDevices.getDisplayMedia({...});
+ }
+});
+```
+
+**This pattern is already proven** by Plan 01-09's toolbar `onClicked` path —
+the SW handler relays via sendMessage to the offscreen, which calls
+`getDisplayMedia` successfully. The same chain works from a welcome-page
+click (where the gesture originates) into the offscreen — Chrome treats the
+extension as a single origin for transient-activation purposes, and the
+synchronous relay stays well within the activation window.
+
+**Evidence:**
+
+- developer.chrome.com canonical example uses `chrome.action.onClicked` →
+ offscreen.sendMessage as the pattern [CITED: developer.chrome.com/docs/extensions/how-to/web-platform/screen-capture].
+- Plan 01-09 working code in `src/background/index.ts:896-914` proves the
+ pattern: toolbar click → SW listener → `startVideoCapture()` → offscreen
+ sendMessage → `getDisplayMedia` call succeeds without `InvalidStateError`.
+- Plan 01-09 also proves `notifications.onClicked` works as a gesture source
+ (lines 942-958), confirming Chrome treats notification clicks identically
+ to action clicks for activation propagation.
+- A welcome-page button click is even MORE robust than `action.onClicked`:
+ the gesture originates in the page DOM context (where transient activation
+ is the canonical web-platform behavior), so the only relay step is page
+ → SW → offscreen — identical chain length to toolbar click.
+
+**Caveat:** the `await chrome.runtime.sendMessage(...)` call from welcome
+page resolves AFTER the SW handler completes. If the SW handler is async
+and awaits the offscreen call, the offscreen call needs to fire BEFORE the
+5 s activation timeout elapses. In practice this is trivial (sub-second);
+in unusual scenarios (e.g., SW cold start with long init), it could in
+theory race. Plan 01-09's working pattern is the empirical test: it works
+in production with operator-confirmed picker render.
+
+**Confidence:** HIGH — verified empirically via Plan 01-09's GREEN unit
+tests AND operator-confirmed UAT runs.
+
+**Recommendation:** Plan 01-10's CURRENT charter (informational CTA) is
+CORRECT given Plan 01-09 already provides the toolbar path. Adding a
+welcome-page actionable button creates a second activation surface for the
+same outcome, which is redundant. **Stay with informational CTA.**
+
+### Area 4: `chrome.desktopCapture.chooseDesktopMedia` auto-accept behavior
+
+**Verdict:** Does NOT auto-accept on single-monitor setups. The picker dialog
+ALWAYS appears, regardless of how many displays are connected.
+
+**Evidence:**
+
+- Chrome official desktopCapture API reference: no `autoSelect`,
+ `autoAccept`, or single-source-default behavior documented
+ [CITED: developer.chrome.com/docs/extensions/reference/api/desktopCapture].
+- The API explicitly takes a `sources: ['screen', 'window', 'tab', 'audio']`
+ parameter — the sources determine which TABS appear in the picker, not
+ whether to skip it.
+- chromium-extensions Google Group discussion confirms: streamId from
+ `chooseDesktopMedia` returned via SW is NOT usable in MV3 offscreen
+ documents (unlike tabCapture, which was fixed in Chrome 116). Chrome
+ DevRel response: "It's technically feasible to support passing a stream
+ ID from chrome.desktopCapture to an offscreen document, but it would be
+ hard to prioritise given the small number of requests" — unresolved as
+ of August 2025 [CITED: groups.google.com/a/chromium.org/g/chromium-extensions/c/3RanHldyp9c].
+
+**Why this matters for Mokosh:** even if `chooseDesktopMedia` skipped the
+picker on single-monitor setups (it doesn't), the resulting streamId can't
+be consumed in the offscreen document where MediaRecorder lives. The API
+is therefore unusable for Mokosh's architecture.
+
+**Confidence:** HIGH — official Chrome docs + active chromium-extensions
+discussion thread converge.
+
+### Area 5: Chrome 2024-2026 screen-capture API additions
+
+**Verdict:** New APIs exist but none provide picker-bypass for Mokosh's use
+case (whole-desktop recording from an extension offscreen document).
+
+**Evidence by API:**
+
+| API | Chrome ver | Use case | Picker bypass? |
+|-----|-----------|----------|----------------|
+| `displaySurface` constraint | 107+ | Hint Chrome to pre-select "monitor" pane | **HINT ONLY** — picker still shows; reorders panes |
+| `monitorTypeSurfaces: 'exclude'` | 119+ | EXCLUDE the entire-screen pane | Opposite direction — for apps wanting tab-only sharing |
+| `surfaceSwitching` | 107+ | Allow user to switch surfaces during share | Improves UX during share, doesn't skip picker |
+| `selfBrowserSurface` | 107+ | Exclude self tab to avoid hall-of-mirrors | Doesn't apply (Mokosh isn't a video-conf app) |
+| `systemAudio: 'exclude'` | 105+ | Control audio offer | Doesn't apply (Mokosh audio-off per SPEC) |
+| Capture Handle | 106+ | App-to-app handle between capturer and captured | Doesn't apply (we capture entire screen, not collab with captured tab) |
+| Conditional Focus | 109+ | Capturer can decide focus behavior of captured tab | Doesn't apply |
+| `getViewportMedia()` | NOT YET SHIPPED | Self-tab capture without picker, prompt only | Even when it ships, only captures the calling tab — not the whole desktop |
+| `getCurrentBrowsingContextMedia()` | Origin trial only, deprecated path | Self-tab simplified picker | Same as above |
+
+[CITED: developer.chrome.com/docs/web-platform/screen-sharing-controls;
+developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/displaySurface;
+developer.chrome.com/docs/web-platform/capture-handle]
+
+**`displaySurface: 'monitor'` is already applied** in Mokosh per D-15-display-surface
+(`src/offscreen/recorder.ts:270` per code grep). This is the MAXIMUM picker
+friction reduction available in the spec.
+
+**`monitorTypeSurfaces: 'include'`** is theoretically a stronger hint than
+`displaySurface: 'monitor'` (Chrome 119+) — it can be used to EXCLUSIVELY
+offer monitor surfaces (no tab/window panes at all). This is worth
+considering as an enhancement:
+
+```typescript
+const stream = await navigator.mediaDevices.getDisplayMedia({
+ video: { displaySurface: 'monitor' },
+ monitorTypeSurfaces: 'include', // Chrome 119+ — exclusive
+ audio: false,
+});
+```
+
+**Caveat:** `monitorTypeSurfaces: 'include'` is the spec's "include"
+behavior — the picker still shows but only with monitor panes. It does NOT
+auto-accept. But it eliminates the "Share this tab instead" footgun
+(addressed via post-grant validation in Mokosh, but this prevents the
+operator-observable footgun at the UI level).
+
+**Recommendation:** Add `monitorTypeSurfaces: 'include'` to the offscreen
+`getDisplayMedia` constraints. Single-line, zero-risk change that removes
+visual noise from the picker. (Possible Plan 01-09 amendment OR new mini-plan.)
+
+**Confidence:** HIGH on which APIs exist; HIGH on their non-bypass nature.
+
+### Area 6: Single-monitor empirical-test stance
+
+**Verdict:** Did not run a fresh empirical probe in this research session —
+existing Mokosh evidence (Plan 01-09 UAT Test 3 + smoke.sh harness) confirms
+the picker appears in single-monitor configurations.
+
+**Existing evidence in the repo:**
+
+- `smoke.sh` (committed) uses the Chrome launch flag
+ `--auto-select-desktop-capture-source=""` to bypass the picker —
+ proving the picker would otherwise appear even in scripted contexts on a
+ single-display dev machine.
+- Plan 01-09's UAT Test 3 advisory finding (per 01-CONTEXT.md amendment)
+ documents the picker as a 3-click friction point per session, on a
+ single-monitor dev box.
+
+**Not re-tested in this session because:** the spec verdict (Area 1+2+4+5
+all converging) is unambiguous; an empirical re-confirmation would consume
+budget without changing the verdict. The orchestrator can run a fresh
+in-Chrome probe if they want; the prediction is the picker appears.
+
+**Confidence:** HIGH on the predicted outcome.
+
+### Area 7: Industry prior art — canonical UX patterns
+
+**Verdict:** Every major screen-recording Chrome extension converges on
+**toolbar click → in-extension UI → Chrome picker** as the canonical flow.
+None auto-start at install. None skip the picker.
+
+**Evidence per extension:**
+
+| Extension | Install flow | Activation flow | Welcome UX |
+|-----------|--------------|-----------------|------------|
+| **Loom** | Install → sign-up/log-in tab opens (matches Mokosh's auto-tab pattern) | Click toolbar icon → in-extension popup → Start Recording button → picker → 3s countdown → recording | Login/signup wall is the welcome UI |
+| **Screencastify** | Install → onboarding tab opens | Click toolbar icon → in-popup settings → start → picker → recording | Onboarding tab gates first use behind setup |
+| **Veed.io** | Install → account-creation tab opens | Click toolbar → permission allow → layout select → red record button → picker → recording | Account-creation tab is the welcome |
+| **Awesome Screenshot** | Install → welcome tab | Click toolbar icon → capture-type menu → recording (for video) → picker | Welcome tab + toolbar icon |
+| **Zight** | Install → onboarding | Click toolbar → recording type select → picker | Onboarding tab + signed-in popup |
+
+[CITED: loom.com/products/chrome-screen-recorder;
+support.atlassian.com/loom/docs/install-the-chrome-extension/;
+screencastify.com/chrome-extension; veed.io;
+support.awesomescreenshot.com/hc/en-us/articles/900005583863;
+zight.com/chrome/]
+
+**Pattern observations:**
+
+1. **NO** extension auto-starts at install. This is industry-wide consensus
+ — the W3C spec gesture requirement is universal.
+2. **NO** extension skips the picker. Even Loom (the polished category
+ leader) shows the Chrome picker on every record.
+3. **Welcome-tab pattern is universal** — Loom, Screencastify, Veed, Awesome
+ Screenshot, Zight all open a tab on first install. The tab is sometimes
+ onboarding/login, sometimes informational, sometimes a CTA.
+4. **In-extension popup with explicit "Start Recording" button is universal**
+ — none of these extensions wire toolbar-onClicked directly to picker
+ (because they offer recording-type choices — full screen vs window vs
+ tab — that Mokosh has already locked to monitor-only). Mokosh's
+ toolbar-direct-to-picker pattern (Plan 01-09) is actually MORE
+ minimum-friction than any of these — because Mokosh chose to lock the
+ surface type, the in-extension settings step is eliminated.
+
+**Conclusion:** Mokosh's Plan 01-09 + Plan 01-10 architecture (welcome tab
+informational + toolbar direct-to-picker) is at or below the industry
+minimum-friction floor. The only further compression possible — install-time
+auto-start — is spec-impossible.
+
+**Confidence:** HIGH on the industry consensus; verified across 5
+independent extensions' public docs.
+
+### Area 8: Permission combinations and manifest implications
+
+**Verdict:** Adding more permissions does NOT weaken the gesture requirement.
+Permissions control WHICH APIs are callable; the gesture gate is enforced
+INSIDE those APIs by Chromium regardless of permissions.
+
+**Evidence:**
+
+- `desktopCapture` permission: required to call `chrome.desktopCapture.*`.
+ Already present in manifest.json:7. Does NOT bypass `getDisplayMedia`
+ gesture requirement.
+- `activeTab` permission: grants temporary host permission to the active
+ tab on user invocation. Already present in manifest.json:8. Does NOT
+ bypass `getDisplayMedia` gesture requirement.
+- `tabs` permission: enables full tab API access. Mokosh does NOT include
+ this — `activeTab` suffices for `captureVisibleTab` (screenshot path).
+- `tabCapture` permission: would enable `chrome.tabCapture.getMediaStreamId()`
+ in service worker (Chrome 116+), which CAN bypass the picker but ONLY
+ for the currently-active tab — NOT whole-desktop recording. D-01 locks
+ Mokosh to whole-desktop, so this path is forbidden.
+
+**Manifest interaction with `getDisplayMedia`:** the API has NO Chrome
+manifest permission. It's a web-platform API gated solely by transient
+activation. Adding permissions changes nothing about the gesture rule.
+
+**Recommendation:** Manifest permissions are correct as-is. No changes
+needed for Plan 01-10.
+
+**Confidence:** HIGH — Chrome docs explicit on permission-API mapping;
+manifest.json verified.
+
+### Area 9: Welcome tab + onStartup interplay
+
+**Verdict:** `onInstalled` (one-shot per install) and `onStartup` (per
+browser launch) cover the two install/restart edges cleanly. Plan 01-09
+already handles `onStartup` via notifications; Plan 01-10 handles
+`onInstalled` via welcome tab. Combined coverage is complete.
+
+**Lifecycle map:**
+
+| Event | When fires | Mokosh handler | Plan |
+|-------|-----------|----------------|------|
+| `onInstalled` reason=`'install'` | One-shot: extension freshly installed (Load Unpacked OR Web Store) | Open welcome tab → CTA points at toolbar | 01-10 (PLAN.md) |
+| `onInstalled` reason=`'update'` / `'chrome_update'` | Extension version bump / Chrome update | NO welcome (per Plan 01-10 storage flag) | 01-10 |
+| `onStartup` | Browser launch (fresh Chrome session) | Create `mokosh-startup-` notification inviting click to start | 01-09 |
+| `onActivated` / SW wake | SW idle expiry / wake cycle | NO surface — SW resumes silently | (implicit Phase 1) |
+| `onConnect` from offscreen | SW wake + offscreen reconnect | Resume PING/PONG; resolve pending REQUEST_BUFFER | D-17-port-lifecycle |
+| `notifications.onClicked` | Operator clicks any mokosh-prefixed notification | Trigger `startVideoCapture()` | 01-09 |
+| `action.onClicked` | Operator clicks toolbar icon in idle mode | Trigger `startVideoCapture()` | 01-09 |
+
+**Critical detail (per Chrome docs):** `onInstalled` fires with reason
+`'update'` when an unpacked extension is RELOADED (not just version-bumped).
+Plan 01-10's storage flag (`onboarding-completed`) correctly handles this:
+once set, subsequent installs/updates/reloads do NOT re-open the welcome
+tab. **Verified in Plan 01-10's must_haves contract** ("Test C: install +
+flag already set → zero tabs.create").
+
+**Edge case to verify:** if the operator uninstalls then reinstalls,
+`chrome.storage.local` is cleared (per MV3 spec). The welcome tab WILL
+re-open on reinstall — which is the correct behavior (uninstall→reinstall
+= fresh first-install experience).
+
+**Confidence:** HIGH — Chrome docs explicit; existing implementation
+matches.
+
+### Area 10: Privacy / consent UX considerations
+
+**Verdict:** Even where install-time auto-start were technically possible
+(it isn't, in unmanaged Chrome — see Area 1), ETHICAL and LEGAL constraints
+would warrant against it for Mokosh's deployment context.
+
+**Evidence:**
+
+- Russian-speaking operators per orchestrator note. Russia's data protection
+ law (Federal Law No. 152-FZ) generally requires processing of personal
+ data based on valid legal grounds, including (commonly used) employee
+ consent [CITED: iapp.org, gdpr-related comparative review]. Russian
+ employer monitoring of operator activity for QA/diagnostic purposes
+ typically requires either a written consent or a clearly documented
+ legitimate-interest basis. Install-time covert auto-start would
+ undermine the consent basis.
+- GDPR exposure (if Repremium has EU operators or EU customers being
+ recorded): Article 5 (lawfulness, transparency) and Article 88 (workplace
+ monitoring) require the data subject to be informed BEFORE processing
+ begins. Auto-start without an informing click would breach the
+ transparency principle.
+- Chrome's own "Sharing your screen" persistent indicator (already shown
+ during Mokosh recording per D-04) is the browser-level transparency
+ floor; install-time auto-start would technically still show the
+ indicator, but the OPERATOR has had no opportunity to consent.
+- Loom/Screencastify/Veed all require explicit per-recording start clicks
+ precisely BECAUSE the gesture is also the consent moment. Industry
+ consensus is converging on this for legal-defensibility reasons, not
+ just spec compliance.
+
+**For Mokosh specifically (SPEC §1 "silent operation" wording):** the
+original SPEC requested silent operation, but D-04 in Phase 1 EXPLICITLY
+amended this to accept Chrome's persistent indicator. The amended posture
+("eyes-open trade-off") aligns with the ethical floor. **Install-time
+auto-start would violate the ethical floor even if it were technically
+possible.**
+
+**Recommendation:** Document this verdict in PLAN.md. If a future enterprise
+deployment ever uses the policy bypass (Area 2), it should be paired with
+an org-side consent flow (employment-contract clause + onboarding
+acknowledgment) — outside Mokosh's code scope.
+
+**Confidence:** HIGH on the legal/ethical analysis (multiple authoritative
+sources on EU/Russia monitoring law); MEDIUM-HIGH on Mokosh's specific
+exposure (depends on Repremium's deployment context, which the orchestrator
+knows better than this research).
+
+### Area 11: Synthesized minimum-friction user journey
+
+**Achievable maximum-compression flow (current Phase 1 architecture):**
+
+```
+TIME STATE FRICTION ACCRUED
+───── ─────────────────────────────────────────────────── ─────────────────
+T+0 Operator loads unpacked extension 0 clicks
+T+0.1 onInstalled fires (reason='install') (system event)
+T+0.2 SW: openWelcomeIfFirstInstall → chrome.tabs.create 0 clicks
+T+0.5 Welcome tab paints (welcome.html via WAR) 0 clicks
+ — operator reads "Click the Mokosh icon in your ─
+ toolbar to begin recording" ─
+T+t1 Operator clicks toolbar icon 1 click
+T+t1+ε chrome.action.onClicked fires in SW 1 click
+T+t1+δ startVideoCapture → sendMessage(START_RECORDING) 1 click
+T+t1+δ' offscreen calls getDisplayMedia 1 click
+T+t1+δ" Chrome picker renders (Entire Screen pre-selected 1 click
+ per displaySurface: 'monitor' constraint) ─
+T+t2 Operator clicks "Share" on the pre-selected Entire 2 clicks
+ Screen pane ─
+T+t2+ε Stream resolves; MediaRecorder starts; recording is 2 clicks
+ LIVE; badge transitions OFF → REC ─
+───── ─────────────────────────────────────────────────── ─────────────────
+
+Click count from install to first frame buffered: 2 clicks.
+This is the W3C-spec floor for unmanaged Chrome MV3 extensions doing
+whole-desktop recording.
+```
+
+**Comparison to alternative architecture (welcome page actionable CTA):**
+
+```
+TIME STATE FRICTION ACCRUED
+───── ─────────────────────────────────────────────────── ─────────────────
+T+0 Operator loads unpacked extension 0 clicks
+T+0.5 Welcome tab paints with "Start Mokosh" button 0 clicks
+T+t1 Operator clicks "Start Mokosh" button 1 click
+T+t1+ε sendMessage(REQUEST_PERMISSIONS) → SW handler 1 click
+T+t1+δ startVideoCapture → sendMessage(START_RECORDING) 1 click
+T+t1+δ" Chrome picker renders 1 click
+T+t2 Operator clicks "Share" on Entire Screen pane 2 clicks
+T+t2+ε Recording LIVE 2 clicks
+───── ─────────────────────────────────────────────────── ─────────────────
+
+Same 2 clicks. Different first-click target (welcome page vs toolbar).
+```
+
+**Why current architecture (informational welcome page) is preferred:**
+
+- **Both architectures hit 2 clicks** — the welcome-page CTA buys nothing.
+- **Informational welcome page sets up the operator's mental model of where
+ the toolbar icon lives** — critical because subsequent recording sessions
+ (after the first install) ONLY use the toolbar (the welcome tab is
+ one-shot). Operators who learn the toolbar via the welcome page on day 1
+ are oriented for day 2+.
+- **Single activation path** = single regression surface. The welcome-page
+ CTA flow would need its own UAT coverage on top of the existing
+ toolbar-onClicked UAT coverage (Plan 01-13's harness already has
+ toolbar-click coverage).
+- **No spec-floor improvement** justifies the additional maintenance
+ surface.
+
+**Reduction to 1 click is INFEASIBLE in unmanaged Chrome.** The picker
+"Share" button is the W3C-mandated user-choice gate; the welcome-page-button
+OR toolbar-click is the W3C-mandated activation gate. Two gates = two
+clicks, minimum.
+
+**Reduction to 0 clicks is ONLY POSSIBLE under enterprise policy AND only
+removes the FIRST click (the activation gate); the PICKER click remains.
+1 click min in managed Chrome.**
+
+**Confidence:** HIGH on the click count analysis; HIGH on the
+architectural-preference rationale.
+
+### Area 12: Edge cases — macOS, Wayland, incognito, managed Chrome, multi-monitor
+
+**macOS first-time permission:**
+
+- macOS requires Chrome to have system-level Screen Recording permission
+ before ANY `getDisplayMedia` call can succeed
+ [CITED: support.apple.com/guide/mac-help/control-access-screen-system-audio-recording-mchld6aa7d23/mac;
+ support.jumpshare.com/article/226-how-to-grant-google-chrome-screen-recording-permission-on-mac].
+- First time the operator clicks Mokosh on macOS, Chrome will show a system
+ dialog directing them to System Settings → Privacy & Security → Screen
+ Recording → enable Chrome → relaunch Chrome.
+- This is a 5-10 click + Chrome-relaunch operator detour OUTSIDE Mokosh's
+ control. The welcome page should document this for macOS operators:
+ *"First time on Mac: macOS will ask for screen recording permission.
+ Enable Chrome in System Settings → Privacy & Security → Screen Recording,
+ then relaunch Chrome."*
+- After Chrome restart, the permission persists; subsequent Mokosh sessions
+ work normally.
+
+**Linux Wayland:**
+
+- Wayland routes screen capture through `xdg-desktop-portal`
+ [CITED: arch wiki, adangel.org/2023/05/31/screencapture-api-wayland/;
+ Chromium feature-media-reviews thread on PipeWire].
+- The portal shows its OWN picker dialog, not Chrome's. The picker UI looks
+ different on GNOME vs KDE vs Hyprland. Chrome's `displaySurface: 'monitor'`
+ constraint hint may or may not be respected — depends on the desktop
+ portal implementation.
+- Wayland sessions do NOT retain persistent permissions between Chrome
+ sessions; each `getDisplayMedia` call invokes the portal afresh. (This is
+ a Wayland security model decision, not a Chrome decision.)
+- Mokosh operators on Wayland should expect: 2 picker clicks per session
+ start (portal + Chrome confirmation depending on the portal impl).
+
+**Linux X11:**
+
+- Standard Chrome picker, no portal indirection. Identical UX to Windows.
+
+**Incognito:**
+
+- Mokosh's manifest does NOT declare `incognito` (verified manifest.json
+ has no `incognito` key). Per MV3, extensions default to `incognito: split`
+ if not specified, OR may be `not_allowed` depending on the user's
+ per-extension toggle.
+- In incognito tabs, Mokosh's content scripts may not load; `getDisplayMedia`
+ still works because it's a window-level call from offscreen, not tab-level.
+- Out of Phase 1 scope; document as deferred.
+
+**Managed Chrome:**
+
+- Per Area 2, `ScreenCaptureWithoutGestureAllowedForOrigins` policy IF
+ applied AND IF accepting extension URLs would allow `onInstalled` to call
+ `getDisplayMedia` without gesture. Picker still shows. Out of Phase 1
+ scope (deferred for future enterprise deployment).
+
+**Multi-monitor:**
+
+- `displaySurface: 'monitor'` shows the Entire Screen pane with all
+ connected monitors as separate entries. The operator picks one.
+- No auto-selection of "primary" monitor in unmanaged Chrome.
+- Plan 01-09's post-grant `track.getSettings().displaySurface === 'monitor'`
+ check accepts ANY monitor — including secondary displays — which is the
+ correct semantics for "as automatic as the platform allows."
+
+**Confidence:** HIGH on macOS, X11, multi-monitor (well-documented); MEDIUM
+on Wayland (varies per desktop portal impl); LOW on incognito (out of
+Phase 1 scope, unverified empirically).
+
+## Don't Hand-Roll
+
+| Problem | Don't Build | Use Instead | Why |
+|---------|-------------|-------------|-----|
+| Try to make `onInstalled` start recording | Custom gesture-faking via `chrome.scripting.executeScript` injection or similar tricks | Accept the welcome-tab + toolbar-click pattern | All gesture-faking workarounds violate the W3C spec; Chromium will reject. Even if a workaround "works" in current Chrome, it will be patched in a future version. |
+| Detect single-monitor and bypass picker | Custom `chrome.system.display.getInfo()` + auto-confirm logic | Accept the picker as the consent gate | There is no Chrome API to programmatically confirm the picker. The picker is the consent moment. |
+| Build a custom in-extension picker UI | Custom HTML/CSS picker matching Chrome's | Use Chrome's native picker (`getDisplayMedia` with `displaySurface: 'monitor'` + `monitorTypeSurfaces: 'include'`) | Mokosh can't capture the screen without the picker resolving; building a fake picker that then calls the real one is pure friction increase. |
+| Auto-restart recording on welcome-page CTA AND toolbar click both | Two parallel start paths with idempotent guards | Pick ONE primary path (toolbar, per Plan 01-09); welcome is informational | Multiple activation surfaces = multiple regression surfaces. Plan 01-09 already proves the toolbar path. |
+
+## Common Pitfalls
+
+### Pitfall 1: Calling `getDisplayMedia` from `onInstalled` directly
+
+**What goes wrong:** Promise rejects with `InvalidStateError`. No recording starts. Operator sees no UI feedback.
+**Why it happens:** `onInstalled` is a system-triggered event, NOT a user activation. Chrome enforces the W3C transient-activation gate at the API entry.
+**How to avoid:** Do NOT call `getDisplayMedia` from `onInstalled` handler. Use `onInstalled` ONLY to open the welcome tab; let the operator's click (toolbar OR welcome-page CTA) be the gesture.
+**Warning signs:** SW console shows `InvalidStateError: getDisplayMedia must be called from a user gesture handler`.
+
+### Pitfall 2: Async chain consumes the gesture window
+
+**What goes wrong:** Toolbar click → SW handler awaits something for > 5 seconds (e.g., long network call, SW cold start) → offscreen's `getDisplayMedia` call rejects with `InvalidStateError`.
+**Why it happens:** Transient activation expires 5 seconds after the gesture. Long async chains eat that budget.
+**How to avoid:** Keep the gesture → `getDisplayMedia` chain synchronous (no `await` on network calls, no long-running computation). Plan 01-09's existing pattern (~50-200ms gesture → picker) is fine.
+**Warning signs:** Intermittent `InvalidStateError` failures correlated with SW wake events.
+
+### Pitfall 3: Welcome tab opens on EVERY install / update
+
+**What goes wrong:** Operator sees the welcome tab every time the extension reloads during development (or every Chrome update for end users).
+**Why it happens:** `onInstalled` fires with reason `'update'` on Load-Unpacked reloads. Plan 01-10's storage-flag guard prevents this.
+**How to avoid:** Plan 01-10's `onboarding-completed` storage flag is the correct guard. Verify the tests cover the `'update'` reason path (Plan 01-10's Test B already does).
+**Warning signs:** Welcome tab opens on every reload during dev iteration.
+
+### Pitfall 4: Forgetting macOS first-time system permission
+
+**What goes wrong:** Russian operator on Mac installs Mokosh, clicks toolbar, sees Chrome's "permission denied" dialog. Frustration spike.
+**Why it happens:** macOS Screen Recording permission is a system-level gate enforced BEFORE Chrome can call `getDisplayMedia`. Chrome usually surfaces a system-side dialog directing the user to System Settings, but the dialog appears only on first call.
+**How to avoid:** Welcome page should mention macOS permission setup (optional copy line). Operator-facing documentation should pre-warn Mac users.
+**Warning signs:** First-time Mac operators report "Chrome popup that goes nowhere."
+
+### Pitfall 5: Misinterpreting `displaySurface` as a hard constraint
+
+**What goes wrong:** Operator picks "Share this tab instead" on the Chrome picker; the resulting stream's track has `displaySurface === 'browser'`; Mokosh's post-grant validation rejects; operator confused.
+**Why it happens:** `displaySurface: 'monitor'` is a HINT only per spec — the picker still offers tab/window options. D-15-display-surface adds the post-grant tear-down.
+**How to avoid:** Plan 01-09's `wrong-display-surface` error path already handles this. Consider adding `monitorTypeSurfaces: 'include'` (Chrome 119+) to ELIMINATE the tab/window panes entirely from the picker.
+**Warning signs:** RECORDING_ERROR with `error: 'wrong-display-surface'` in operator logs.
+
+## Code Examples
+
+### Example 1: Plan 01-10's current onInstalled handler (CORRECT pattern)
+
+```typescript
+// src/background/index.ts (per Plan 01-10 charter, lines after current ~724)
+async function openWelcomeIfFirstInstall(
+ details: chrome.runtime.InstalledDetails
+): Promise {
+ // Early return for non-install reasons (updates, chrome_updates, etc.)
+ if (details.reason !== 'install') return;
+
+ // Early return if welcome already shown
+ const stored = await chrome.storage.local.get('onboarding-completed');
+ if (stored['onboarding-completed'] === true) return;
+
+ // Open welcome tab (does NOT call getDisplayMedia — informational only)
+ await chrome.tabs.create({
+ url: chrome.runtime.getURL('src/welcome/welcome.html'),
+ });
+
+ // Set flag so reloads / updates do not re-open
+ await chrome.storage.local.set({
+ 'onboarding-completed': true,
+ 'installed-at': Date.now(),
+ });
+}
+
+chrome.runtime.onInstalled.addListener((details) => {
+ logger.log('Extension installed/updated:', details.reason);
+ try {
+ indexedDB.deleteDatabase('VideoRecorderDB');
+ } catch (e) {
+ logger.warn('IDB cleanup failed:', e);
+ }
+ initialize();
+ // Fire-and-forget — does NOT call getDisplayMedia
+ openWelcomeIfFirstInstall(details).catch((err) => {
+ logger.warn('openWelcomeIfFirstInstall failed:', err);
+ });
+});
+```
+
+[VERIFIED: matches Plan 01-10 PLAN.md must_haves contract]
+
+### Example 2: Plan 01-09's gesture chain (CORRECT pattern, PROVEN WORKING)
+
+```typescript
+// src/background/index.ts:896-914 (Plan 01-09, current main)
+try {
+ chrome.action.onClicked.addListener(async () => {
+ if (isRecording) {
+ logger.log('Toolbar onClicked while already recording — no-op');
+ return;
+ }
+ try {
+ await startVideoCapture();
+ } catch (err) {
+ logger.warn('toolbar-onClicked start failed:', err);
+ }
+ });
+} catch (e) {
+ logger.warn('chrome.action.onClicked.addListener failed:', e);
+}
+```
+
+```typescript
+// src/offscreen/recorder.ts:270 (current main)
+const stream = await navigator.mediaDevices.getDisplayMedia({
+ video: { displaySurface: 'monitor', cursor: 'always' },
+ audio: false,
+});
+
+// Post-grant validation (D-15)
+const observedSurface = stream
+ .getVideoTracks()[0]
+ .getSettings().displaySurface;
+if (observedSurface !== 'monitor') {
+ stream.getTracks().forEach((t) => t.stop());
+ throw new Error(`wrong-display-surface: got "${observedSurface}"`);
+}
+```
+
+[VERIFIED: code grep shows these patterns at the cited line numbers]
+
+### Example 3: Optional enhancement — `monitorTypeSurfaces: 'include'`
+
+```typescript
+// src/offscreen/recorder.ts — Chrome 119+ enhancement
+const stream = await navigator.mediaDevices.getDisplayMedia({
+ video: { displaySurface: 'monitor', cursor: 'always' },
+ monitorTypeSurfaces: 'include', // EXCLUSIVELY offer monitor panes
+ audio: false,
+});
+```
+
+[CITED: developer.chrome.com/docs/web-platform/screen-sharing-controls]
+
+This eliminates the visible "Window" and "Chrome Tab" panes from the picker
+entirely, preventing the "Share this tab instead" footgun at the UI level
+(rather than catching it post-grant via D-15). Consider as a Plan 01-09
+amendment.
+
+## State of the Art
+
+| Old approach | Current approach | When changed | Impact |
+|--------------|-----------------|--------------|--------|
+| `chrome.tabCapture` invocation only from popup (MV2) | `chrome.tabCapture.getMediaStreamId` from SW (Chrome 116+) | Chrome 116 (2023-08) | Not used by Mokosh (D-01 locks to getDisplayMedia) |
+| `getDisplayMedia` always shows picker every time | Picker reorderable via `displaySurface` hint (Chrome 107+) | Chrome 107 (2022-10) | APPLIED in Plan 01-09 |
+| Picker always offers all surface types | `monitorTypeSurfaces: 'exclude'` / `'include'` to filter (Chrome 119+) | Chrome 119 (2023-10) | NOT YET APPLIED — recommended enhancement |
+| `chooseDesktopMedia` streamId NOT usable in MV3 offscreen | Same (no fix as of 2025-08) | UNCHANGED | Not applicable — Mokosh uses getDisplayMedia |
+| Install-time auto-start "rumored possible via X" | Confirmed INFEASIBLE in unmanaged Chrome by W3C spec + Chrome docs convergence | (long-standing) | Settles the verdict for Plan 01-10 |
+
+**Deprecated/outdated approaches:**
+
+- **`getCurrentBrowsingContextMedia`** — origin-trial-only, deprecated path; superseded by `getViewportMedia` (not yet shipped). Don't use.
+- **Pre-Chrome-116 SW workarounds for tabCapture** — superseded by official SW support. Don't carry forward.
+
+## Assumptions Log
+
+| # | Claim | Section | Risk if Wrong |
+|---|-------|---------|---------------|
+| A1 | `chrome-extension://` URLs are accepted as values in `ScreenCaptureWithoutGestureAllowedForOrigins` policy | §2 (Enterprise policy reality 2026) | Section §2's enterprise-deployment path is invalid — no impact on current Phase 1 charter (which doesn't use the policy), only on the deferred-idea wording. |
+| A2 | macOS Edge policy docs (Microsoft Learn, 2026-04-30) reliably represent the Chrome policy format on macOS | §2 | Slight wording difference in plist key naming; impact is doc-only, not code. |
+| A3 | Russian operators' machines are NOT enrolled in Chrome Enterprise management (assumed because Load Unpacked is the install method) | §2, §10 | If Repremium uses managed Chrome, the §2 policy path becomes viable — would reopen Ask 1 as PARTIALLY feasible (gesture bypass yes, picker bypass no). |
+| A4 | `--auto-select-desktop-capture-source` Chrome launch flag is NOT shippable via Web Store distribution | §5 | If somehow shippable, picker bypass becomes available — but this contradicts all public sources and operator-Chrome reality. |
+
+**If any of A1-A4 are wrong, the verdict on Ask 1 partially loosens (gesture
+bypass becomes feasible) but Ask 2's verdict (picker bypass infeasible) does
+NOT change.**
+
+## Open Questions
+
+1. **Should Plan 01-10's welcome page CTA be informational or actionable?**
+ - Research finding: Both achieve 2-click floor. Informational has lower
+ maintenance surface and a learning benefit (operator learns where the
+ toolbar icon is).
+ - Recommendation: stay with current charter (informational).
+ - Awaiting orchestrator confirmation OR continue with current Plan 01-10
+ as written.
+
+2. **Should `monitorTypeSurfaces: 'include'` be added to the
+ `getDisplayMedia` constraints?**
+ - Research finding: Chrome 119+ feature. Eliminates tab/window panes from
+ the picker → removes the "Share this tab instead" footgun at the UI
+ level. Single-line change, zero added risk.
+ - Recommendation: amend Plan 01-09 (or add a tiny mini-plan)
+ post-Plan-01-10.
+ - Awaiting orchestrator decision on plan-amendment vs new-plan routing.
+
+3. **Should the welcome page include macOS first-time-permission copy?**
+ - Research finding: Mac operators will hit the system Screen Recording
+ permission gate first time, OUTSIDE Mokosh's control.
+ - Recommendation: add a single COPY line for macOS guidance — but copy
+ is design-team territory (D-08 tagline + brand-decisions-v1.md
+ followup); Plan 01-12 owns final copy.
+ - Awaiting: nothing for Plan 01-10 (engineering placeholders are
+ acceptable per design-swap-in-ready charter); Plan 01-12 closes.
+
+## Environment Availability
+
+| Dependency | Required By | Available | Version | Fallback |
+|------------|-------------|-----------|---------|----------|
+| Chrome (operator runtime) | All Phase 1 features | Assumed ✓ | ≥ 119 (recommended for `monitorTypeSurfaces`) | — |
+| Chrome Enterprise enrollment | `ScreenCaptureWithoutGestureAllowedForOrigins` deferred-idea | NO (operators on Load Unpacked) | — | Skip enterprise path; standard 2-click flow |
+| `getDisplayMedia` browser API | D-01 capture | YES (Chrome ≥ 72) | (universal in target Chrome) | — |
+| `chrome.offscreen` API | D-02 offscreen-document recording | YES (Chrome ≥ 109) | — | — |
+| `displaySurface` constraint | D-15 picker hint | YES (Chrome ≥ 107) | (already used) | — |
+| `monitorTypeSurfaces` constraint | (recommended enhancement) | YES (Chrome ≥ 119) | — | Skip enhancement; rely on post-grant validation only |
+| Russian-speaking operator | UX copy validation | YES (per orchestrator note) | — | — |
+
+**Missing dependencies with no fallback:** None.
+
+**Missing dependencies with fallback:** Enterprise enrollment (mooted by
+deferring the policy-path idea to a future phase).
+
+## Validation Architecture
+
+### Test Framework
+| Property | Value |
+|----------|-------|
+| Framework | Vitest + Puppeteer UAT harness |
+| Config files | `vitest.config.ts` (unit), `vite.test.config.ts` (UAT bundle) |
+| Quick run command | `npm test` |
+| Full UAT command | `npm run test:uat` |
+
+### Phase Requirements → Test Map
+
+This research does NOT add new requirements. It validates the existing Plan
+01-10 must_haves contract is consistent with W3C-spec reality. Existing
+tests are sufficient:
+
+| Req ID | Behavior | Test type | Command | File exists? |
+|--------|----------|-----------|---------|--------------|
+| REQ-install-clean | Welcome tab opens on first install | unit | `npm test tests/background/onboarding.test.ts` | ❌ Wave 0 (Plan 01-10 ships this) |
+| REQ-install-clean | Welcome tab does NOT open on update / repeat install | unit | `npm test tests/background/onboarding.test.ts` | ❌ Wave 0 (Plan 01-10 ships this) |
+| (UAT) onboarding flag observability | A15 — `onboarding-completed` flag observable in storage | UAT | `npm run test:uat` | ❌ Wave 0 (Plan 01-10 ships this) |
+| (UAT) no re-open on subsequent install | A16 — no new welcome tab spontaneously appears | UAT | `npm run test:uat` | ❌ Wave 0 (Plan 01-10 ships this) |
+| (UAT) design-swap readiness | A17 — `.welcome-hero` slot + zero hex literals + COPY map present | UAT | `npm run test:uat` | ❌ Wave 0 (Plan 01-10 ships this) |
+
+### Sampling Rate
+- **Per task commit:** `npm test` (Vitest baseline 101+ tests)
+- **Per wave merge:** `npm run test:uat` (Puppeteer 18/18 GREEN target after Plan 01-10)
+- **Phase gate:** Full vitest + full UAT GREEN before `/gsd-verify-work`
+
+### Wave 0 Gaps
+None — Plan 01-10's existing must_haves contract covers all research-driven
+behavior pins. The research does NOT require additional tests beyond what
+Plan 01-10 already specifies.
+
+If the orchestrator decides to ship `monitorTypeSurfaces: 'include'` as an
+amendment, a tiny additional unit test would pin the constraint application:
+- `tests/offscreen/monitor-type-surfaces.test.ts` — 1 test: constraints
+ passed to `getDisplayMedia` include `monitorTypeSurfaces: 'include'`.
+
+## Security Domain
+
+### Applicable ASVS Categories
+
+| ASVS category | Applies | Standard control |
+|--------------|---------|------------------|
+| V2 Authentication | No | (no auth surface in Plan 01-10) |
+| V3 Session management | No | (no session model — ephemeral browser session) |
+| V4 Access control | Yes (manifest) | MV3 `web_accessible_resources` minimal-scope (only welcome.html, no other paths) |
+| V5 Input validation | Limited | `storage` keys validated as exact-match (`'onboarding-completed'`) |
+| V6 Cryptography | No | (no cryptographic surface in Plan 01-10) |
+| V9 Communication | Yes | Welcome page → SW via `chrome.runtime.sendMessage` (extension-internal channel; not exposed cross-origin) |
+| V14 Configuration | Yes | Manifest permissions audit — Plan 01-10 adds `web_accessible_resources` only; no new permissions |
+
+### Known Threat Patterns for Plan 01-10
+
+| Pattern | STRIDE | Standard mitigation |
+|---------|--------|---------------------|
+| Welcome page accessible from `` matches → arbitrary web page can iframe it | Information Disclosure / Tampering | Welcome page does NOT expose privileged APIs to its DOM — read-only `COPY` rendering; no message-handler exposure to incoming runtime messages from non-extension origins |
+| Storage flag spoofable by non-extension code | Tampering | `chrome.storage.local` is per-extension-isolated; only Mokosh can set/get the flag. No mitigation needed. |
+| Notification id spoofing (Plan 01-09 T-1-09-01) | Spoofing | Already mitigated in Plan 01-09 by `'mokosh-'` prefix validation; Plan 01-10 does not extend this surface. |
+| Enterprise policy abuse to bypass consent (Area 2 deferred idea) | Spoofing / Repudiation | DEFERRED — out of Plan 01-10 scope; future phase would require org-side consent flow. |
+
+## Sources
+
+### Primary (HIGH confidence)
+
+- W3C Screen Capture spec — https://www.w3.org/TR/screen-capture/ (gesture
+ requirement §5.1, mandatory picker)
+- MDN MediaDevices.getDisplayMedia — https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia
+ (transient activation requirement, InvalidStateError exception)
+- Chrome official MV3 screen-capture guide — https://developer.chrome.com/docs/extensions/how-to/web-platform/screen-capture
+- Chrome desktopCapture API reference — https://developer.chrome.com/docs/extensions/reference/api/desktopCapture
+- Chrome blog: Privacy-preserving screen sharing controls (displaySurface,
+ monitorTypeSurfaces) — https://developer.chrome.com/docs/web-platform/screen-sharing-controls
+- Microsoft Edge enterprise policy docs:
+ ScreenCaptureWithoutGestureAllowedForOrigins —
+ https://learn.microsoft.com/en-us/deployedge/microsoft-edge-browser-policies/screencapturewithoutgestureallowedfororigins
+ (Edge ≥ 123 Windows + macOS, 2026-04-30)
+- Chrome Enterprise Policy List —
+ https://gpedit.tplant.com.au/en-us/policy/chrome/ScreenCaptureWithoutGestureAllowedForOrigins
+- Chromium chromium-extensions group: chooseDesktopMedia streamId not usable
+ in MV3 offscreen — https://groups.google.com/a/chromium.org/g/chromium-extensions/c/3RanHldyp9c
+ (Chrome DevRel Oliver Dunk response, Aug 2025)
+- Plan 01-09 working code: `src/background/index.ts:896-914` (toolbar
+ onClicked → getDisplayMedia path proven via UAT 15/15 GREEN)
+- 01-CONTEXT.md amendments (D-15-display-surface, D-16-toolbar,
+ D-17-onboarding, D-17-port-lifecycle)
+
+### Secondary (MEDIUM confidence)
+
+- chromestatus feature 5090735022407680 "Calling getDisplayMedia() without
+ user activation" (enterprise-policy feature gate)
+- Loom support docs:
+ https://support.atlassian.com/loom/docs/install-the-chrome-extension/
+- Screencastify product page: https://www.screencastify.com/chrome-extension
+- Veed.io support: https://support.veed.io/en/articles/11099678-how-to-use-our-recorder
+- Awesome Screenshot install docs:
+ https://support.awesomescreenshot.com/hc/en-us/articles/900005583863
+- Mozilla Firefox bugzilla 1580944, 1705289 (cross-browser convergence on
+ transient-activation requirement)
+
+### Tertiary (LOW confidence — corroborating only)
+
+- WebRTC Hacks (Chrome Screensharing Blues) — context, no novel claims
+- M2K Medium article on desktopCapture — corroborates official API behavior
+- democreator/wondershare guides on screen-recording extensions —
+ corroborates industry pattern
+
+## Metadata
+
+**Confidence breakdown:**
+
+- W3C spec mandate / gesture floor: HIGH — multiple independent sources
+- Enterprise policy applicability: MEDIUM-HIGH on existence; MEDIUM on
+ extension-URL acceptance; LOW on Linux/ChromeOS
+- Welcome-tab gesture chain: HIGH — verified empirically via Plan 01-09
+- Picker bypass infeasibility: HIGH — convergent W3C + Chrome + Chromium
+ sources
+- Prior art consensus: HIGH — five independent extensions converge
+- Privacy/consent floor: MEDIUM-HIGH (depends on Repremium's specific
+ operator jurisdiction)
+- Edge cases (macOS, Wayland, multi-monitor): HIGH-MEDIUM-LOW respectively
+
+**Research date:** 2026-05-19
+**Valid until:** 2026-08-19 (90 days — Chrome stable channel rolls
+quarterly; spec is stable longer; enterprise policy stable longer)
+
+**Open follow-up if research becomes stale:**
+
+- Watch for `getViewportMedia` shipping in Chrome — could enable picker-less
+ self-tab capture (NOT useful for Mokosh's whole-desktop charter, but
+ worth knowing about)
+- Watch for chromium-extensions group resolution of the `chooseDesktopMedia`
+ + offscreen MV3 issue (currently unresolved, low priority per Chrome
+ DevRel)
+- Watch for any enterprise-policy expansion that opens up extension-URL
+ patterns explicitly