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 433ee280f3 - Show all commits

View File

@@ -8,6 +8,7 @@ files_modified:
- src/offscreen/recorder.ts - src/offscreen/recorder.ts
- src/test-hooks/offscreen-hooks.ts - src/test-hooks/offscreen-hooks.ts
- src/test-hooks/types.ts - src/test-hooks/types.ts
- tests/offscreen/display-surface-constraint.test.ts
- tests/uat/extension-page-harness.ts - tests/uat/extension-page-harness.ts
- tests/uat/lib/harness-page-driver.ts - tests/uat/lib/harness-page-driver.ts
- tests/uat/harness.test.ts - tests/uat/harness.test.ts
@@ -30,7 +31,7 @@ must_haves:
- "`src/offscreen/recorder.ts` `getDisplayMedia()` call passes `monitorTypeSurfaces: 'include'` as a top-level constraint (sibling of `video:`, NOT nested inside `video:`) per W3C Screen Capture spec — the option is a `DisplayMediaStreamOptions` member, not a `MediaTrackConstraints` member." - "`src/offscreen/recorder.ts` `getDisplayMedia()` call passes `monitorTypeSurfaces: 'include'` as a top-level constraint (sibling of `video:`, NOT nested inside `video:`) per W3C Screen Capture spec — the option is a `DisplayMediaStreamOptions` member, not a `MediaTrackConstraints` member."
- "UAT harness assertion A23 verifies the constraint reaches the call site: extends `installFakeDisplayMedia` to record the last-received constraints object; new `__mokoshOffscreenQuery` op `get-last-getDisplayMedia-constraints` returns it; `assertA23` reads it and asserts `monitorTypeSurfaces === 'include'`." - "UAT harness assertion A23 verifies the constraint reaches the call site: extends `installFakeDisplayMedia` to record the last-received constraints object; new `__mokoshOffscreenQuery` op `get-last-getDisplayMedia-constraints` returns it; `assertA23` reads it and asserts `monitorTypeSurfaces === 'include'`."
- "`npm run test:uat` exit 0 with 16/16 GREEN (A0 grep gate + A1..A14 preserved + A23 new). A23 chains AFTER A14 (A14 is the final read-only post-SAVE state check; A23 makes a fresh getDisplayMedia call to inspect the constraint, which is independent of A14's no-side-effects contract because A23 only reads the recorded constraints from the LAST call — A2's setupFreshRecording already invoked it)." - "`npm run test:uat` exit 0 with 16/16 GREEN (A0 grep gate + A1..A14 preserved + A23 new). A23 chains AFTER A14 (A14 is the final read-only post-SAVE state check; A23 makes a fresh getDisplayMedia call to inspect the constraint, which is independent of A14's no-side-effects contract because A23 only reads the recorded constraints from the LAST call — A2's setupFreshRecording already invoked it)."
- "Existing vitest baseline preserved at 98/98 GREEN. The change is additive at the source level; no existing unit test references the constraints object structure explicitly (verified via `grep -rn 'displaySurface.*monitor' tests/` → only documentation comments, no test inspects the constraint payload)." - "Existing vitest baseline preserved at 98/98 GREEN. The strict-deep-equality assertion at `tests/offscreen/display-surface-constraint.test.ts:223-226` is updated in lockstep to include `monitorTypeSurfaces: 'include'`, preserving the test author's intent (catches future drops of any constraint field). The plan delivers both the source change AND the test-expectation update as a single atomic commit so the baseline remains 98/98 GREEN at every revision boundary — no transient RED state crosses commit boundaries."
- "`npm run build` exits 0; `tsc --noEmit` exits 0 (no new types beyond extending the existing `MokoshTestSurface` cross-cast)." - "`npm run build` exits 0; `tsc --noEmit` exits 0 (no new types beyond extending the existing `MokoshTestSurface` cross-cast)."
- "Tier-1 grep gate preserved: `tests/background/no-test-hooks-in-prod-bundle.test.ts` FORBIDDEN_HOOK_STRINGS extended with `lastGetDisplayMediaConstraints` and `get-last-getDisplayMedia-constraints`; production `dist/` contains ZERO occurrences of either string (gated identically to the Plan 01-13 hook surface — `__MOKOSH_UAT__` dead-branch tree-shake)." - "Tier-1 grep gate preserved: `tests/background/no-test-hooks-in-prod-bundle.test.ts` FORBIDDEN_HOOK_STRINGS extended with `lastGetDisplayMediaConstraints` and `get-last-getDisplayMedia-constraints`; production `dist/` contains ZERO occurrences of either string (gated identically to the Plan 01-13 hook surface — `__MOKOSH_UAT__` dead-branch tree-shake)."
- "Production bundle hook-free: `npm run build` produces `dist/` with no test-hook leakage. The grep gate's mirror in `tests/uat/harness.test.ts:85` (FORBIDDEN_HOOK_STRINGS — UAT-level A0) is extended in lockstep with the unit-gate inventory." - "Production bundle hook-free: `npm run build` produces `dist/` with no test-hook leakage. The grep gate's mirror in `tests/uat/harness.test.ts:85` (FORBIDDEN_HOOK_STRINGS — UAT-level A0) is extended in lockstep with the unit-gate inventory."
@@ -44,6 +45,9 @@ must_haves:
contains: "lastGetDisplayMediaConstraints" contains: "lastGetDisplayMediaConstraints"
- path: "src/test-hooks/types.ts" - path: "src/test-hooks/types.ts"
provides: "Extends `MokoshTestSurface` (or the equivalent typed surface contract per Plan 01-13 Wave 3 extension) with optional `lastGetDisplayMediaConstraints?: DisplayMediaStreamOptions | null` field IF the cross-cast in `offscreen-hooks.ts` needs it for clean typing; if the bridge op route (op string match → response) does not require the surface to expose this directly, this file may need no change. Defer to the implementer's read of the current cross-cast shape." provides: "Extends `MokoshTestSurface` (or the equivalent typed surface contract per Plan 01-13 Wave 3 extension) with optional `lastGetDisplayMediaConstraints?: DisplayMediaStreamOptions | null` field IF the cross-cast in `offscreen-hooks.ts` needs it for clean typing; if the bridge op route (op string match → response) does not require the surface to expose this directly, this file may need no change. Defer to the implementer's read of the current cross-cast shape."
- path: "tests/offscreen/display-surface-constraint.test.ts"
provides: "Single-line in-place update to the strict-deep-equality expectation at lines 223-226 of Test 1 (`'1: startRecording calls getDisplayMedia with the exact D-15 constraints object'`). The expected object grows from `{ video: {...}, audio: false }` to `{ video: {...}, monitorTypeSurfaces: 'include', audio: false }` — placement of `monitorTypeSurfaces` matches the planner's chosen ordering in the source change (between `video:` and `audio:`, per the interfaces block in this plan's context). The preserved-line comment at 221-222 stays intact: the strict deep-equality contract still catches future drops of ANY field (now including the new `monitorTypeSurfaces`). The test author's no-`expect.objectContaining` discipline is honored."
contains: "monitorTypeSurfaces"
- path: "tests/uat/extension-page-harness.ts" - path: "tests/uat/extension-page-harness.ts"
provides: "New `assertA23` function added BEFORE the `getManifestVersion` helper at line ~1906. Mirrors the `assertA3` pattern (offscreenQuery bridge call → structured AssertionResult). Verifies the recorded constraints object contains `monitorTypeSurfaces === 'include'`. The `__mokoshHarness` global surface (declared at line 1922) is extended with `assertA23: () => Promise<AssertionResult>`; the export at line 1942 adds `assertA23`. Console-log + status-bar message at line 1965 updated to reference A23." provides: "New `assertA23` function added BEFORE the `getManifestVersion` helper at line ~1906. Mirrors the `assertA3` pattern (offscreenQuery bridge call → structured AssertionResult). Verifies the recorded constraints object contains `monitorTypeSurfaces === 'include'`. The `__mokoshHarness` global surface (declared at line 1922) is extended with `assertA23: () => Promise<AssertionResult>`; the export at line 1942 adds `assertA23`. Console-log + status-bar message at line 1965 updated to reference A23."
min_lines: 70 min_lines: 70
@@ -59,6 +63,10 @@ must_haves:
to: "Chrome picker UI" to: "Chrome picker UI"
via: "navigator.mediaDevices.getDisplayMedia({ video: { displaySurface: 'monitor', cursor: 'always' }, monitorTypeSurfaces: 'include', audio: false })" via: "navigator.mediaDevices.getDisplayMedia({ video: { displaySurface: 'monitor', cursor: 'always' }, monitorTypeSurfaces: 'include', audio: false })"
pattern: "monitorTypeSurfaces:\\s*['\"]include['\"]" pattern: "monitorTypeSurfaces:\\s*['\"]include['\"]"
- from: "tests/offscreen/display-surface-constraint.test.ts Test 1 strict deep-equality assertion"
to: "src/offscreen/recorder.ts getDisplayMedia call site"
via: "expect(getDisplayMediaSpy).toHaveBeenCalledWith({ video: {...}, monitorTypeSurfaces: 'include', audio: false }) — updated in lockstep with the source change"
pattern: "monitorTypeSurfaces:\\s*['\"]include['\"]"
- from: "src/test-hooks/offscreen-hooks.ts:installFakeDisplayMedia" - from: "src/test-hooks/offscreen-hooks.ts:installFakeDisplayMedia"
to: "src/test-hooks/offscreen-hooks.ts:__mokoshOffscreenQuery dispatcher 'get-last-getDisplayMedia-constraints' op" to: "src/test-hooks/offscreen-hooks.ts:__mokoshOffscreenQuery dispatcher 'get-last-getDisplayMedia-constraints' op"
via: "module-scoped lastGetDisplayMediaConstraints cell populated on every fakeGetDisplayMedia call; bridge op reads it" via: "module-scoped lastGetDisplayMediaConstraints cell populated on every fakeGetDisplayMedia call; bridge op reads it"
@@ -79,7 +87,7 @@ must_haves:
## Scope Sanity Note ## Scope Sanity Note
**1 task, autonomous, single executor.** This is the canonical-floor "small surgical plan" shape: one source change + one harness regression assertion + grep-gate inventory update. Per `<scope_estimation>` Light context weight: ~10-15% context cost for a single executor. No split signals; no checkpoint (UAT harness coverage suffices per `feedback-pre-checkpoint-bundle-gates.md` — A23 + A0 grep gates are the empirical floor that replaces operator-time-spend for this enhancement). **1 task, autonomous, single executor.** This is the canonical-floor "small surgical plan" shape: one source change + one in-place test-expectation update (lockstep with the source change) + one harness regression assertion + grep-gate inventory update. Per `<scope_estimation>` Light context weight: ~10-15% context cost for a single executor. No split signals; no checkpoint (UAT harness coverage suffices per `feedback-pre-checkpoint-bundle-gates.md` — A23 + A0 grep gates are the empirical floor that replaces operator-time-spend for this enhancement).
**Genesis note.** This plan ships a Plan 01-10 RESEARCH §5 + §Pitfall-5 recommendation ("Add `monitorTypeSurfaces: 'include'` to the offscreen `getDisplayMedia` constraints. Single-line, zero-risk change that removes visual noise from the picker"). The prior attempt to ship the same change as an AMENDMENT-A.md anti-pattern was retired per `01-11-SUMMARY.md` Architectural Notes — this plan replaces that improvised path with canonical GSD ceremony (plan → checker → executor → SUMMARY). **Genesis note.** This plan ships a Plan 01-10 RESEARCH §5 + §Pitfall-5 recommendation ("Add `monitorTypeSurfaces: 'include'` to the offscreen `getDisplayMedia` constraints. Single-line, zero-risk change that removes visual noise from the picker"). The prior attempt to ship the same change as an AMENDMENT-A.md anti-pattern was retired per `01-11-SUMMARY.md` Architectural Notes — this plan replaces that improvised path with canonical GSD ceremony (plan → checker → executor → SUMMARY).
@@ -91,7 +99,7 @@ Ship the W3C Screen Capture `monitorTypeSurfaces: 'include'` parameter (Chrome
The change is consistent with PROJECT.md D-01 (whole-desktop only via getDisplayMedia; reject window/tab surfaces) — `monitorTypeSurfaces: 'include'` is the picker-UI realization of D-01's intent. D-15 post-grant validation stays as belt-and-suspenders. The change is consistent with PROJECT.md D-01 (whole-desktop only via getDisplayMedia; reject window/tab surfaces) — `monitorTypeSurfaces: 'include'` is the picker-UI realization of D-01's intent. D-15 post-grant validation stays as belt-and-suspenders.
Purpose: reduce operator picker friction within W3C-spec bounds; ship a research-validated single-line enhancement via canonical GSD ceremony (not amendment improvisation). Purpose: reduce operator picker friction within W3C-spec bounds; ship a research-validated single-line enhancement via canonical GSD ceremony (not amendment improvisation).
Output: 1 source line + A23 harness regression assertion + Tier-1 grep gate inventory update; UAT 16/16 GREEN; vitest 98/98 GREEN; production bundle hook-free. Output: 1 source line + 1 in-place test-expectation update (lockstep) + A23 harness regression assertion + Tier-1 grep gate inventory update; UAT 16/16 GREEN; vitest 98/98 GREEN; production bundle hook-free.
</objective> </objective>
<execution_context> <execution_context>
@@ -109,6 +117,7 @@ Output: 1 source line + A23 harness regression assertion + Tier-1 grep gate inve
@src/offscreen/recorder.ts @src/offscreen/recorder.ts
@src/test-hooks/offscreen-hooks.ts @src/test-hooks/offscreen-hooks.ts
@src/test-hooks/types.ts @src/test-hooks/types.ts
@tests/offscreen/display-surface-constraint.test.ts
@tests/uat/extension-page-harness.ts @tests/uat/extension-page-harness.ts
@tests/uat/lib/harness-page-driver.ts @tests/uat/lib/harness-page-driver.ts
@tests/uat/harness.test.ts @tests/uat/harness.test.ts
@@ -158,6 +167,16 @@ const stream = await navigator.mediaDevices.getDisplayMedia({
}); });
``` ```
**Test-expectation lockstep update** (tests/offscreen/display-surface-constraint.test.ts:223-226) — Test 1's strict-deep-equality assertion grows to match the new source shape EXACTLY (no `expect.objectContaining` — the test author's contract preserves "catches future drops of ANY field"). The key ordering matches the source change above (between `video:` and `audio:`):
```typescript
expect(getDisplayMediaSpy).toHaveBeenCalledWith({
video: { displaySurface: 'monitor', cursor: 'always' },
monitorTypeSurfaces: 'include',
audio: false,
});
```
Existing offscreen-hooks bridge dispatcher pattern (src/test-hooks/offscreen-hooks.ts:370-468): Existing offscreen-hooks bridge dispatcher pattern (src/test-hooks/offscreen-hooks.ts:370-468):
```typescript ```typescript
@@ -197,18 +216,38 @@ Existing FORBIDDEN_HOOK_STRINGS inventory locations (both kept in lockstep per P
<tasks> <tasks>
<task type="auto"> <task type="auto">
<name>Task 1: Add monitorTypeSurfaces:'include' to getDisplayMedia constraints + wire A23 harness assertion + extend Tier-1 grep gate inventory in lockstep</name> <name>Task 1: Add monitorTypeSurfaces:'include' to getDisplayMedia constraints + lockstep test-expectation update + wire A23 harness assertion + extend Tier-1 grep gate inventory</name>
<files> <files>
src/offscreen/recorder.ts, src/offscreen/recorder.ts,
src/test-hooks/offscreen-hooks.ts, src/test-hooks/offscreen-hooks.ts,
src/test-hooks/types.ts, src/test-hooks/types.ts,
tests/offscreen/display-surface-constraint.test.ts,
tests/uat/extension-page-harness.ts, tests/uat/extension-page-harness.ts,
tests/uat/lib/harness-page-driver.ts, tests/uat/lib/harness-page-driver.ts,
tests/uat/harness.test.ts, tests/uat/harness.test.ts,
tests/background/no-test-hooks-in-prod-bundle.test.ts tests/background/no-test-hooks-in-prod-bundle.test.ts
</files> </files>
<action> <action>
**Step 1: Source change**`src/offscreen/recorder.ts` line ~270. Add `monitorTypeSurfaces: 'include'` as a top-level constraint sibling of `video:` (NOT nested inside `video:` — per W3C spec §6.1 DisplayMediaStreamOptions structure). Extend the existing typed widening cast (line ~273-275) to include `monitorTypeSurfaces: 'include'` so the explicit-typing contract is preserved (no `as any`). Add an inline comment citing Plan 01-10 RESEARCH §5 + W3C spec §6.1 + Chrome 119+ feature-gate URL (https://developer.chrome.com/docs/web-platform/screen-sharing-controls). Leave the D-15 post-grant validation block (line ~294) UNCHANGED — `monitorTypeSurfaces: 'include'` is belt-and-suspenders at the picker UI level; D-15 remains the actual enforcement (operator can still defeat the constraint via picker click, per spec HINT semantics). **Step 1: Source change**`src/offscreen/recorder.ts` line ~270. Add `monitorTypeSurfaces: 'include'` as a top-level constraint sibling of `video:` (NOT nested inside `video:` — per W3C spec §6.1 DisplayMediaStreamOptions structure). Extend the existing typed widening cast (line ~273-275) to include `monitorTypeSurfaces: 'include'` so the explicit-typing contract is preserved (no `as any`). Add an inline comment citing Plan 01-10 RESEARCH §5 + W3C spec §6.1 + Chrome 119+ feature-gate URL (https://developer.chrome.com/docs/web-platform/screen-sharing-controls). Leave the D-15 post-grant validation block (line ~294) UNCHANGED — `monitorTypeSurfaces: 'include'` is belt-and-suspenders at the picker UI level; D-15 remains the actual enforcement (operator can still defeat the constraint via picker click, per spec HINT semantics). Final key ordering inside the call: `video:``monitorTypeSurfaces:``audio:`.
**Step 1b: Lockstep test-expectation update (BLOCKER B-01-14-01 fix)**`tests/offscreen/display-surface-constraint.test.ts` lines 223-226. Test 1 (`'1: startRecording calls getDisplayMedia with the exact D-15 constraints object'`) does **strict deep-equality** on the constraints object via `expect(getDisplayMediaSpy).toHaveBeenCalledWith({...})` — NOT `expect.objectContaining`. The test author's intent (per the preserved comment at lines 221-222) is to catch future drops of ANY constraint field. Adding `monitorTypeSurfaces: 'include'` to the source call without updating this expectation will drop vitest from 98/98 GREEN to 97/98 RED.
Update the expected object at lines 223-226 in lockstep with the source change. The new expected shape:
```typescript
expect(getDisplayMediaSpy).toHaveBeenCalledWith({
video: { displaySurface: 'monitor', cursor: 'always' },
monitorTypeSurfaces: 'include',
audio: false,
});
```
Key ordering MUST match Step 1's source change (`video:``monitorTypeSurfaces:``audio:`) — strict deep-equality in Vitest/Jest is structural, but matching the source ordering keeps diffs reviewable and the contract obvious.
DO NOT switch this expectation from `toHaveBeenCalledWith` to `expect.objectContaining` — the test author's "no objectContaining" discipline is the whole point of the test, and the preserved comment at 221-222 explicitly states the contract. The strict deep-equality MUST stay, just with the updated expected shape.
Leave the preserved comment block at lines 221-222 intact (or extend it with a one-line note about Plan 01-14's addition of `monitorTypeSurfaces`, at the implementer's discretion — if extending, keep the original "catches future drops" wording).
This edit + Step 1's source change MUST land in the same atomic commit so the 98/98 baseline never crosses a commit boundary in RED state.
**Step 2: offscreen-hooks bridge**`src/test-hooks/offscreen-hooks.ts`. (a) At module scope (near line 97 where `fakeInstalled` lives), declare `let lastGetDisplayMediaConstraints: DisplayMediaStreamOptions | null = null;` with a docstring referencing Plan 01-14 A23 contract. (b) Inside `installFakeDisplayMedia`'s `fakeGetDisplayMedia` closure (line ~236 where `_constraints?: DisplayMediaStreamOptions` is currently received-but-unused), rename `_constraints``constraints` and add the first line in the function body: `lastGetDisplayMediaConstraints = constraints ?? null;`. (c) In the `__mokoshOffscreenQuery` dispatcher (line ~370), add a new `if (op === 'get-last-getDisplayMedia-constraints')` block AFTER the `get-display-surface` handler (line ~407) and BEFORE `get-segment-count` (line ~436). Response shape: `{ constraints: lastGetDisplayMediaConstraints }`. Follow the existing try/catch + sendResponse pattern — no exceptions allowed to propagate to chrome.runtime.sendMessage. **Step 2: offscreen-hooks bridge**`src/test-hooks/offscreen-hooks.ts`. (a) At module scope (near line 97 where `fakeInstalled` lives), declare `let lastGetDisplayMediaConstraints: DisplayMediaStreamOptions | null = null;` with a docstring referencing Plan 01-14 A23 contract. (b) Inside `installFakeDisplayMedia`'s `fakeGetDisplayMedia` closure (line ~236 where `_constraints?: DisplayMediaStreamOptions` is currently received-but-unused), rename `_constraints``constraints` and add the first line in the function body: `lastGetDisplayMediaConstraints = constraints ?? null;`. (c) In the `__mokoshOffscreenQuery` dispatcher (line ~370), add a new `if (op === 'get-last-getDisplayMedia-constraints')` block AFTER the `get-display-surface` handler (line ~407) and BEFORE `get-segment-count` (line ~436). Response shape: `{ constraints: lastGetDisplayMediaConstraints }`. Follow the existing try/catch + sendResponse pattern — no exceptions allowed to propagate to chrome.runtime.sendMessage.
@@ -226,9 +265,9 @@ Then extend the `Window.__mokoshHarness` declaration (line 1922) with `assertA23
**Step 8: verify the build chain**`npm run build` (production); `npm run build:test` (test bundle); `tsc --noEmit`. Production `dist/` must have zero occurrences of `lastGetDisplayMediaConstraints` and `get-last-getDisplayMedia-constraints` (the `__MOKOSH_UAT__` Vite define-token dead-branch tree-shake elides them). **Step 8: verify the build chain**`npm run build` (production); `npm run build:test` (test bundle); `tsc --noEmit`. Production `dist/` must have zero occurrences of `lastGetDisplayMediaConstraints` and `get-last-getDisplayMedia-constraints` (the `__MOKOSH_UAT__` Vite define-token dead-branch tree-shake elides them).
**Step 9: verify the test chain**`npm test` (vitest 98/98 GREEN, plus the Tier-1 grep gate now exercises the new forbidden-strings against a fresh production build); `npm run test:uat` (UAT 16/16 GREEN — A0 grep gate + A1..A14 + A23). **Step 9: verify the test chain**`npm test` (vitest 98/98 GREEN — Step 1b's lockstep update is what preserves the count; without it, this step would fail at 97/98 RED on the strict-deep-equality assertion at display-surface-constraint.test.ts:223); `npm run test:uat` (UAT 16/16 GREEN — A0 grep gate + A1..A14 + A23).
**Atomic commit** with message: `feat(01-14): monitorTypeSurfaces:'include' — narrow picker to monitor surfaces only`. Commit body includes: (a) link to Plan 01-10 RESEARCH §5 + §Pitfall-5 + W3C spec §6.1 + Chrome screen-sharing-controls doc URL; (b) D-01 + D-15 references (consistency with whole-desktop-only intent + belt-and-suspenders relationship with post-grant validation); (c) UAT 16/16 PASS report (counts before/after); (d) vitest 98/98 PASS report; (e) Tier-1 grep gate post-build clean confirmation. **Atomic commit** with message: `feat(01-14): monitorTypeSurfaces:'include' — narrow picker to monitor surfaces only`. Commit body includes: (a) link to Plan 01-10 RESEARCH §5 + §Pitfall-5 + W3C spec §6.1 + Chrome screen-sharing-controls doc URL; (b) D-01 + D-15 references (consistency with whole-desktop-only intent + belt-and-suspenders relationship with post-grant validation); (c) explicit mention that the source change AND the strict-deep-equality test update at `tests/offscreen/display-surface-constraint.test.ts:223-226` land in the same commit (lockstep) so the 98/98 baseline never crosses a commit boundary in RED state; (d) UAT 16/16 PASS report (counts before/after); (e) vitest 98/98 PASS report; (f) Tier-1 grep gate post-build clean confirmation.
</action> </action>
<verify> <verify>
<verify> <verify>
@@ -239,7 +278,7 @@ Expected outputs:
- `npm run build` exits 0; `dist/` produced. - `npm run build` exits 0; `dist/` produced.
- `npm run build:test` exits 0; `dist-test/` produced. - `npm run build:test` exits 0; `dist-test/` produced.
- `npx tsc --noEmit` exits 0; no type errors. - `npx tsc --noEmit` exits 0; no type errors.
- `npm test` exits 0; 98+ vitest tests GREEN (the no-test-hooks-in-prod-bundle gate now greps for the two new forbidden strings against the freshly-built `dist/` and confirms zero occurrences). - `npm test` exits 0; **98/98 vitest tests GREEN** (count UNCHANGED — Step 1b's lockstep update to `tests/offscreen/display-surface-constraint.test.ts:223-226` is what preserves this baseline; without that edit, Test 1 of `display-surface-constraint.test.ts` would fail at strict-deep-equality due to the new `monitorTypeSurfaces` sibling in the source call). The no-test-hooks-in-prod-bundle gate now greps for the two new forbidden strings against the freshly-built `dist/` and confirms zero occurrences.
- `npm run test:uat` exits 0; final line reads `UAT harness: 16/16 assertions passed`. - `npm run test:uat` exits 0; final line reads `UAT harness: 16/16 assertions passed`.
Production-bundle hook-free spot-check (orchestrator may run as a sanity gate before checkpointing): Production-bundle hook-free spot-check (orchestrator may run as a sanity gate before checkpointing):
@@ -250,12 +289,13 @@ grep -rc 'lastGetDisplayMediaConstraints\|get-last-getDisplayMedia-constraints'
</verify> </verify>
<done> <done>
- `src/offscreen/recorder.ts` `getDisplayMedia` call passes `monitorTypeSurfaces: 'include'` at the top level (sibling of `video:`), with the typed widening cast updated to match. - `src/offscreen/recorder.ts` `getDisplayMedia` call passes `monitorTypeSurfaces: 'include'` at the top level (sibling of `video:`), with the typed widening cast updated to match.
- `tests/offscreen/display-surface-constraint.test.ts:223-226` strict-deep-equality expectation updated in lockstep to include `monitorTypeSurfaces: 'include'`; the `toHaveBeenCalledWith` contract is preserved (no `expect.objectContaining`); the preserved-line comment at 221-222 remains intact.
- `src/test-hooks/offscreen-hooks.ts` records the last-received constraints object on every `fakeGetDisplayMedia` call and exposes it via the `get-last-getDisplayMedia-constraints` bridge op. - `src/test-hooks/offscreen-hooks.ts` records the last-received constraints object on every `fakeGetDisplayMedia` call and exposes it via the `get-last-getDisplayMedia-constraints` bridge op.
- `tests/uat/extension-page-harness.ts` exposes `window.__mokoshHarness.assertA23` that verifies `monitorTypeSurfaces === 'include'` round-trips through the fake getDisplayMedia path. - `tests/uat/extension-page-harness.ts` exposes `window.__mokoshHarness.assertA23` that verifies `monitorTypeSurfaces === 'include'` round-trips through the fake getDisplayMedia path.
- `tests/uat/lib/harness-page-driver.ts` exports `driveA23` page.evaluate wrapper. - `tests/uat/lib/harness-page-driver.ts` exports `driveA23` page.evaluate wrapper.
- `tests/uat/harness.test.ts` runs A23 as the final functional assertion; final report reads `16/16 assertions passed`. - `tests/uat/harness.test.ts` runs A23 as the final functional assertion; final report reads `16/16 assertions passed`.
- `tests/background/no-test-hooks-in-prod-bundle.test.ts` and `tests/uat/harness.test.ts` FORBIDDEN_HOOK_STRINGS lists both contain `lastGetDisplayMediaConstraints` and `get-last-getDisplayMedia-constraints`; production `dist/` is hook-free per both gates. - `tests/background/no-test-hooks-in-prod-bundle.test.ts` and `tests/uat/harness.test.ts` FORBIDDEN_HOOK_STRINGS lists both contain `lastGetDisplayMediaConstraints` and `get-last-getDisplayMedia-constraints`; production `dist/` is hook-free per both gates.
- Single atomic commit with the prescribed message lands on the working branch. - Single atomic commit (source change + test-expectation update + harness wiring + grep gate inventory all together) with the prescribed message lands on the working branch — no transient 97/98 RED state across commit boundaries.
- vitest 98/98 GREEN; UAT 16/16 GREEN; `tsc --noEmit` clean. - vitest 98/98 GREEN; UAT 16/16 GREEN; `tsc --noEmit` clean.
</done> </done>
</task> </task>
@@ -291,33 +331,35 @@ grep -rc 'lastGetDisplayMediaConstraints\|get-last-getDisplayMedia-constraints'
**Phase gate** (executor → /gsd-verify-work): **Phase gate** (executor → /gsd-verify-work):
1. **Source-line correctness**: `grep -n "monitorTypeSurfaces" src/offscreen/recorder.ts` returns the new line at the expected position. The string `monitorTypeSurfaces: 'include'` appears as a TOP-LEVEL constraint (sibling of `video:`), NOT nested inside `video:`. (W3C spec §6.1 compliance check.) 1. **Source-line correctness**: `grep -n "monitorTypeSurfaces" src/offscreen/recorder.ts` returns the new line at the expected position. The string `monitorTypeSurfaces: 'include'` appears as a TOP-LEVEL constraint (sibling of `video:`), NOT nested inside `video:`. (W3C spec §6.1 compliance check.)
2. **A23 round-trips**: `npm run test:uat` final summary line shows `16/16 assertions passed` with `[PASS] A23` in the per-assertion roll-up. 2. **Test-expectation lockstep**: `grep -n "monitorTypeSurfaces" tests/offscreen/display-surface-constraint.test.ts` returns the updated `toHaveBeenCalledWith` expectation; the assertion at lines 223-226 includes `monitorTypeSurfaces: 'include'` between `video:` and `audio:`; `expect.objectContaining` is NOT used (preserves the test author's strict-deep-equality contract).
3. **Tier-1 grep gates GREEN**: `npm test` shows `no-test-hooks-in-prod-bundle.test.ts` GREEN with the new forbidden strings in the inventory; `npm run test:uat` A0 grep gate confirms zero occurrences of `lastGetDisplayMediaConstraints` and `get-last-getDisplayMedia-constraints` in `dist/`. 3. **A23 round-trips**: `npm run test:uat` final summary line shows `16/16 assertions passed` with `[PASS] A23` in the per-assertion roll-up.
4. **No vitest regression**: full vitest run produces 98 GREEN tests (no change in count from pre-plan baseline; the change is additive at the source level and does not introduce or remove unit-test cases). 4. **Tier-1 grep gates GREEN**: `npm test` shows `no-test-hooks-in-prod-bundle.test.ts` GREEN with the new forbidden strings in the inventory; `npm run test:uat` A0 grep gate confirms zero occurrences of `lastGetDisplayMediaConstraints` and `get-last-getDisplayMedia-constraints` in `dist/`.
5. **Type cleanliness**: `npx tsc --noEmit` exits 0; the typed widening cast on the `getDisplayMedia` constraints includes `monitorTypeSurfaces: 'include'` explicitly. 5. **No vitest regression**: full vitest run produces **98/98 GREEN tests** (no change in count from pre-plan baseline; the source change is additive AND the strict-deep-equality expectation in `display-surface-constraint.test.ts` is updated in lockstep so Test 1 stays GREEN through the transition).
6. **Commit shape**: single atomic commit on the working branch with the prescribed message and the documented commit body (research link, decision references, test reports). 6. **Type cleanliness**: `npx tsc --noEmit` exits 0; the typed widening cast on the `getDisplayMedia` constraints includes `monitorTypeSurfaces: 'include'` explicitly.
7. **Commit shape**: single atomic commit on the working branch with the prescribed message and the documented commit body (research link, decision references, lockstep test-update note, test reports).
</verification> </verification>
<success_criteria> <success_criteria>
- Operator picker dialog presents ONLY monitor surfaces under Chrome ≥ 119 (W3C `monitorTypeSurfaces: 'include'` semantics). Verified empirically via the UAT A23 assertion's bridge-inspection of the recorded constraints object. The 1-click W3C consent gate remains (spec floor; not bypassable in unmanaged Chrome per Plan 01-10 RESEARCH). - Operator picker dialog presents ONLY monitor surfaces under Chrome ≥ 119 (W3C `monitorTypeSurfaces: 'include'` semantics). Verified empirically via the UAT A23 assertion's bridge-inspection of the recorded constraints object. The 1-click W3C consent gate remains (spec floor; not bypassable in unmanaged Chrome per Plan 01-10 RESEARCH).
- The change is consistent with PROJECT.md D-01 (whole-desktop only via getDisplayMedia; reject window/tab surfaces) — the new constraint is the picker-UI realization of D-01's intent. - The change is consistent with PROJECT.md D-01 (whole-desktop only via getDisplayMedia; reject window/tab surfaces) — the new constraint is the picker-UI realization of D-01's intent.
- D-15 post-grant validation block (recorder.ts:294-307) is UNCHANGED; belt-and-suspenders chain preserved. - D-15 post-grant validation block (recorder.ts:294-307) is UNCHANGED; belt-and-suspenders chain preserved.
- Lockstep test-expectation update at `tests/offscreen/display-surface-constraint.test.ts:223-226` preserves the strict-deep-equality contract under the new constraints shape — test author's "no objectContaining" discipline is honored.
- UAT harness exits 0 with `16/16 assertions passed`. - UAT harness exits 0 with `16/16 assertions passed`.
- vitest exits 0 with 98/98 GREEN; production-bundle Tier-1 grep gate confirms zero hook-surface leakage. - vitest exits 0 with **98/98 GREEN** (baseline preserved through the lockstep edit); production-bundle Tier-1 grep gate confirms zero hook-surface leakage.
- TypeScript compilation clean (`tsc --noEmit` exit 0). - TypeScript compilation clean (`tsc --noEmit` exit 0).
- Single atomic commit on the working branch (no fixup/squash commits). - Single atomic commit on the working branch (no fixup/squash commits, no transient RED state at commit boundaries).
</success_criteria> </success_criteria>
<output> <output>
After completion, create `.planning/phases/01-stabilize-video-pipeline/01-14-SUMMARY.md` per the standard PLAN → SUMMARY contract. SUMMARY MUST include: After completion, create `.planning/phases/01-stabilize-video-pipeline/01-14-SUMMARY.md` per the standard PLAN → SUMMARY contract. SUMMARY MUST include:
1. **What shipped** — the single source line + A23 harness assertion + grep gate inventory updates + commit SHA. 1. **What shipped** — the single source line + lockstep test-expectation update at `tests/offscreen/display-surface-constraint.test.ts:223-226` + A23 harness assertion + grep gate inventory updates + commit SHA.
2. **Verification evidence**`npm test` count (98/98), `npm run test:uat` count (16/16), `tsc --noEmit` clean, production-bundle grep-gate clean. 2. **Verification evidence**`npm test` count (98/98), `npm run test:uat` count (16/16), `tsc --noEmit` clean, production-bundle grep-gate clean.
3. **Research linkage** — citation to Plan 01-10 RESEARCH §5, §Pitfall-5, §Environment-Availability + W3C spec §6.1 + Chrome screen-sharing-controls doc URL. 3. **Research linkage** — citation to Plan 01-10 RESEARCH §5, §Pitfall-5, §Environment-Availability + W3C spec §6.1 + Chrome screen-sharing-controls doc URL.
4. **Decision linkage** — D-01 (consistency: monitor-only intent realized at the picker UI level); D-15 (relationship: monitorTypeSurfaces is picker-UI belt; D-15 post-grant validation is the enforcement suspenders). 4. **Decision linkage** — D-01 (consistency: monitor-only intent realized at the picker UI level); D-15 (relationship: monitorTypeSurfaces is picker-UI belt; D-15 post-grant validation is the enforcement suspenders).
5. **Ceremony note** — confirm this plan replaces the prior AMENDMENT-A.md improvisation path retired per 01-11-SUMMARY Architectural Notes; canonical GSD ceremony (plan → checker → executor → summary) is what landed. 5. **Ceremony note** — confirm this plan replaces the prior AMENDMENT-A.md improvisation path retired per 01-11-SUMMARY Architectural Notes; canonical GSD ceremony (plan → checker → executor → summary) is what landed.
6. **Architectural delta** — ZERO new permissions; ZERO new manifest changes; ZERO new web_accessible_resources; new internal test-hook surface gated identically to Plan 01-13's inventory. 6. **Revision linkage** — note that the plan was revised once after the plan-checker flagged BLOCKER B-01-14-01 (the original plan's must_haves truth #5 understated baseline regression risk; the revision added Step 1b lockstep test-expectation update + corresponding frontmatter/file/key-link entries).
7. **What did not change** — D-15 post-grant validation block; Plan 01-09 toolbar `onClicked` chain; Plan 01-10 welcome-page architecture; Plan 01-12 design-integration scope; Plan 01-13 harness architecture (the 14 existing assertions are unmodified; A23 is purely additive). 7. **Architectural delta** — ZERO new permissions; ZERO new manifest changes; ZERO new web_accessible_resources; new internal test-hook surface gated identically to Plan 01-13's inventory.
8. **What did not change** — D-15 post-grant validation block; Plan 01-09 toolbar `onClicked` chain; Plan 01-10 welcome-page architecture; Plan 01-12 design-integration scope; Plan 01-13 harness architecture (the 14 existing assertions are unmodified; A23 is purely additive).
</output> </output>
</content> </content>
</invoke>