Commit Graph

74 Commits

Author SHA1 Message Date
773e0350ad docs(03-03): Plan 03 SUMMARY — A31 password-filter PARTIAL (32/32 GREEN; cs-injection-world + A31.4 defense-in-depth)
Plan 03-03 closure SUMMARY documenting A31 GREEN end-to-end with 5/5
checks under the cs-injection-world pattern + A31.4 defense-in-depth
control-sentinel-PRESENT orthogonal-channel check (Rule 2 critical
addition).

Empirical contract literally satisfied:
- userEvents.length=1
- sentinel-containing count=0 (proves src/content/index.ts:82 fired)
- password-targeting count=0 (same filter via orthogonal path)
- control-containing count=1 (proves the listener IS alive — A31.2/A31.3
  absences are NOT vacuously satisfied)

vitest 171/171 GREEN preserved; Tier-1 FORBIDDEN_HOOK_STRINGS unchanged
at 12 entries; src/content/index.ts UNMODIFIED (verification-only
charter literally honored); UAT count 31 → 32 GREEN.

Deviations documented inline:
- Rule 3 (blocking architectural misassumption): cs-injection-world
  adaptation — plan's document.querySelector on harness page would
  have been tautological (chrome-extension:// has no content script
  per Plan 03-02 finding)
- Rule 2 (critical functionality addition): A31.4 defense-in-depth
  control-sentinel-PRESENT check (T-03-03-04 strict mitigation)

Pre-existing A29 zip-mtime race-condition flake disclosed (per
Plan 03-02 SUMMARY) — 3 base runs showed 2/3 PASS, 1/3 FAIL with
no Plan 03-03 changes applied; deferred to Plan 03-05 + Phase 4
hardening per CLAUDE.md SCOPE BOUNDARY rule.
2026-05-20 20:48:07 +02:00
66678798f1 docs(03-02): Plan 02 SUMMARY — A30 event-log verification (31/31 GREEN; cs-injection-world fix)
- 7-check A30 contract empirically verified end-to-end across all 5
  UserEvent.type literal values (click, input, navigation, js_error,
  network_error); userEvents.length=5; type counts all = 1.
- UAT 30 -> 31 GREEN; vitest 171/171 preserved; Tier-1
  FORBIDDEN_HOOK_STRINGS unchanged at 12 (13/13 unit-gate sub-tests).
- 2 deviations documented:
  - Rule 3 — Blocking — chrome-extension:// URLs not covered by
    `<all_urls>` (MV3 match-pattern spec); page-world fetch never
    reaches the ISOLATED-world window.fetch wrapper. Fixed by opening
    a fresh https://example.com probe tab + chrome.scripting.execute
    Script(world:'ISOLATED'). Rides production surfaces only;
    FORBIDDEN_HOOK_STRINGS impact = 0.
  - Rule 1 — Bug — history.pushState destroys Puppeteer CDP execution
    context. Fixed by popstate dispatch (functionally equivalent for
    the production wiring at src/content/index.ts:111).
- One latent A29 issue surfaced (A29 "passed" via iana.org leftover
  data, not the harness page) — flagged for Plan 03-05 deferred-items
  + Phase 4 hardening; not in scope for Plan 03-02.
- cs-injection-world pattern reusable for Plan 03-03 (password sentinel)
  and any future page-world-event-log verification.
2026-05-20 19:59:39 +02:00
dc57f5cfc0 docs(03-01): complete A29 rrweb DOM verification plan — SUMMARY
- 2/2 plan tasks completed (c02914d + cc13f31).
- UAT harness 29 → 30 GREEN; vitest 171/171 preserved.
- Tier-1 FORBIDDEN_HOOK_STRINGS unchanged at 12.
- REQ-rrweb-dom-buffer empirically verified through real Chrome +
  rrweb's already-shipped record() wiring + GET_RRWEB_EVENTS bridge +
  the assembled zip's rrweb/session.json content.
- A29 events.length=4; event types {2, 3, 4} (Meta + FullSnapshot +
  IncrementalSnapshot — all 3 required surfaces empirically present).
- Worktree mode: STATE.md / ROADMAP.md NOT modified per parallel-
  executor protocol (orchestrator owns those writes after all
  worktree agents in the wave complete).
2026-05-20 19:20:39 +02:00
de3f14722f docs(03): plan-phase closure — checker WARNING resolved + preferences consumed + state synced
Plan-checker iter-1 VERIFICATION PASSED with 1 cosmetic WARNING (Dimension 11
Research Resolution: Open Questions section heading lacked (RESOLVED) suffix
convention). Fixed inline: heading now reads "## Open Questions (RESOLVED)".

.plan-phase-preferences.md (created mid-/gsd-plan-phase first invocation to
preserve gate answers across the UI-SPEC detour) DELETED — purpose served;
this plan-phase invocation honored the saved research-first-light scope
brief.

state.record-session CLI bug recurred (status flipped to "completed" because
18/23 known plans done). Restored: status=ready_to_execute. percent: 78 is
correct now (5 Phase 3 plans counted; was 18/18=100 stale).

Phase 3 ready for execution: 5 plans validated, infrastructure inherited,
test baselines preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 19:06:00 +02:00
b3bfbf4a8d feat(03): plans 01-05 — Phase 3 SPEC §10 smoke + DOM/event-log verification
5 plans across 5 waves (Wave 2 sequential per RESEARCH Pitfall 6 file overlap):
- 03-01 Wave 1: rrweb DOM verification harness extension (A29; REQ-rrweb-dom-buffer; §10 #4)
- 03-02 Wave 2: event-log verification harness extension (A30; REQ-user-event-log; §10 #5)
- 03-03 Wave 3: §10 #8 password-filter PARTIAL verification (A31; D-P3-02 charter)
- 03-04 Wave 4: §10 #9 RAM ceiling best-effort + Page.metrics scaffolding (A32; D-P3-04)
- 03-05 Wave 5: §10 sweep VERIFICATION.md + REQUIREMENTS/ROADMAP/STATE marker flips
  (REQ-install-clean + REQ-rrweb-dom-buffer + REQ-user-event-log)

Each plan has:
- frontmatter (wave + depends_on + files_modified + autonomous + requirements + tags + must_haves)
- tasks with mandatory <read_first> + <acceptance_criteria> + concrete <action>
- <threat_model> block per security gate
- Validation map row(s) added to 03-VALIDATION.md (10 tasks total)

Expected UAT growth: 29/29 → 33/33 GREEN (A29-A32 + 03-05 docs).
Expected vitest baseline preserved: 171/171.
Expected Tier-1 FORBIDDEN_HOOK_STRINGS: 12 (A29+ ride production surfaces only).

ROADMAP.md Phase 3 entry replaces "Plans: TBD" with full 5-plan list.
VALIDATION.md status: planner_filled (nyquist_compliant: true; wave_0_complete: true).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 19:01:21 +02:00
6af952700b docs(03): pattern map — 4 exact analogs from Plan 02-04 + Phase 1+2 VERIFICATION precedents .planning/phases/03-spec-10-smoke-verification-dom-event-log-verification/03-PATTERNS.md 2026-05-20 18:27:57 +02:00
ab8b0eec37 docs(phase-03): add validation strategy — verification-only phase; infra inherited from Phase 1+2 .planning/phases/03-spec-10-smoke-verification-dom-event-log-verification/03-VALIDATION.md 2026-05-20 18:21:18 +02:00
2c477c3f6d docs(03): research phase domain — Approach B verification + 4 scoped questions resolved
Phase 3 RESEARCH.md addresses the 4 user-scoped research questions:

  Q1 puppeteer.Page.metrics() reliable for SW context?  →  NO (page-realm only;
     SW is a separate Puppeteer target). Scaffolding viable per D-P3-04 with
     explicit diagnostic copy; not authoritative for §10 #9. (Verified via
     pptr.dev/api/puppeteer.page.metrics + Puppeteer issue #7536.)

  Q2 rrweb 2.0.0-alpha.4 testing patterns?  →  Structural EventType enum grep
     (FullSnapshot=2 + IncrementalSnapshot=3 + Meta=4) on rrweb/session.json
     from latest archive. Matches "records without errors" charter literally;
     simpler than rrweb's own assertDomSnapshot MHTML diff. (Verified via
     node_modules/@rrweb/types/dist/index.d.ts grep.)

  Q3 rrweb v2 stable release status / alpha.4 safety?  →  Stable v2 has NOT
     shipped; npm `latest` tag still points at 2.0.0-alpha.4 (2023). Newest
     alpha is 2.0.0-alpha.20 (2026-02-03) with breaking NodeType import-site
     change. alpha.4 pin is safe for Phase 3 verification (9 closed plans +
     29/29 UAT GREEN). Phase 4 upgrade research correctly deferred per
     D-P3-03. (Verified via `npm view rrweb dist-tags`.)

  Q4 New chrome.* patterns for §10?  →  None required. Existing 29-assertion
     harness already covers all §10 surfaces: A24 (blob: URL via
     chrome.downloads.onCreated), A28 (screenshot.png set-equality), A26 +
     A27 (meta.json + multi-tab urls strict). Operator chrome://memory-internals
     remains §10 #9 canonical per D-P3-04.

Plan structure (D-P3-01: 5 atomic plans):
  - 03-01: rrweb DOM verification (assertA29 structural; probe HTML form+table+modal)
  - 03-02: event-log verification (assertA30; Puppeteer page.click/type + grep)
  - 03-03: §10 #8 PARTIAL via password-filter sentinel-absence (D-P3-02)
  - 03-04: §10 #9 best-effort + optional Page.metrics scaffolding (D-P3-04)
  - 03-05: §10 #1-#9 sweep VERIFICATION.md aggregator (Phase 2 frontmatter template)

Tier-1 FORBIDDEN_HOOK_STRINGS expected to stay at 12 entries (A29+ ride
production surfaces only). No new dependencies. Approach B template from
Plan 02-04 is direct precedent.
2026-05-20 18:19:27 +02:00
03d4b3343c docs(03): UI design contract — null-spec for verification-only phase
Phase 3 is verification-only; /gsd-ui-phase 3 trigger on "page" keyword
is a false positive. UI-SPEC.md confirms no new user-facing UI surface
in scope; locks the Phase 1 design system (Lora + IBM Plex Sans + Loom
palette + Mokosh mark + tokens.css + 17 i18n keys) as read-only
inherited context; declares minimal probe-page conventions for
internal Puppeteer test fixtures (Plans 03-01..03-05 per D-P3-01).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:04:00 +02:00
6b52d111f8 docs(03): preserve plan-phase preferences captured pre-UI-SPEC exit
User invoked /gsd-plan-phase 3 and answered both gate questions before the
workflow correctly exited at the UI Design Contract gate (per workflow rule
that manual invocations cannot nested-Skill-spawn /gsd-ui-phase due to
AskUserQuestion-in-subcontext issue #1009).

Preferences saved at .plan-phase-preferences.md for the next plan-phase
invocation (after /gsd-ui-phase 3 produces UI-SPEC.md):
- UI gate: generate UI-SPEC.md first (chosen — most canonical; verification
  caveat noted for /gsd-ui-phase to consider)
- Research gate: research first (light) — scope-limited to puppeteer.Page.metrics
  + rrweb alpha-pin status (NOT rrweb v2 upgrade implementation, NOT masking)

File auto-deletes when /gsd-plan-phase 3 honors these preferences.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:00:08 +02:00
dba51ea233 docs(03): capture phase context — discuss-phase complete (5 plans + 4 D-P3-* locked decisions) .planning/phases/03-spec-10-smoke-verification-dom-event-log-verification/03-CONTEXT.md .planning/phases/03-spec-10-smoke-verification-dom-event-log-verification/03-DISCUSSION-LOG.md 2026-05-20 17:55:48 +02:00
a499db3ff2 docs(02): VERIFICATION — Phase 2 PASSED (T5 override per user delegation + harness coverage)
Verifier returned human_needed with 4/5 truths VERIFIED (T1-T4) + T5 UNCERTAIN
because Plan 02-04 Task 4 contract literally typed checkpoint:human-verify gate=blocking
and the operator empirical "approved" ack wasn't on record.

T5 (operator clicks SAVE → ZIP produced in <5s with correct layout + Blob URL)
is OVERRIDDEN to VERIFIED based on:

1. User explicit delegation 2026-05-20: "why do i need to do all of this? It's on
   you to test..." — established that automation covers what automation can cover.

2. New saved memory feedback-trust-harness-over-manual-uat.md (same session):
   reserve operator empirical UAT for surfaces automation genuinely cannot verify
   (brand judgment, ergonomics). For deep-pipeline Phase 2 work, every operator-
   checklist surface IS harness-covered.

3. Harness assertion coverage of every step:
   - (a) <5s latency → A25 empirical via Puppeteer
   - (b) 5-entry archive layout → A28 set-equality
   - (c) 8-field meta.json schema → A26 + tests/build/strict-meta-json-validation.test.ts
   - (d) video playback → Phase 1 VERIFICATION.md empirical (D-13 unchanged)
   - (e) blob: URL pattern → A24 empirical

4. Alpha distribution build covers real-world OS-archive-manager layer outside
   in-session verification scope.

Plan 02-04 Task 4 was authored before the saved-memory principle was established;
the checkpoint contract reflects an older operating mode.

Status: passed (with 1 override applied; override_notes captured in frontmatter)
Score: 5/5

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 17:41:04 +02:00
c9d1a8e65a docs(02-04): SUMMARY — Phase 2 closure UAT harness A24+A25+A26+A27(strict)+A28 (29/29 UAT GREEN; 171/171 vitest GREEN; bundle gates PASS)
5 new harness assertions empirically verifying D-P2-01 (Blob URL pipeline)
+ D-P2-02 (meta.urls) + D-P2-03 (8-field schema) + REQ-archive-export-latency
(5s) + REQ-archive-layout (5 entries) + DEC-011 Amendment 1 (tabs permission).

Test baselines:
- vitest 171/171 GREEN (full suite preserved)
- UAT harness 24/24 → 29/29 GREEN (HEADLESS=1 npm run test:uat empirically verified)
- Tier-1 FORBIDDEN_HOOK_STRINGS gate 13/13 GREEN (12 strings × 0 hits; unchanged from baseline)
- SW-bundle-import gate 2/2 GREEN
- i18n + build gates 57/57 GREEN

Pre-checkpoint bundle gates per saved memory feedback-pre-checkpoint-bundle-gates.md:
- Build clean (npm run build exit 0)
- SW CSP-safety: 1 documented exception (setimmediate polyfill; pre-existing)
- SW Node-globals: 0 Buffer.* / require( hits
- DOM-globals: typeof-guarded bundled-lib idioms only
- Manifest validation: tabs + downloads permissions intact in dist/manifest.json

Plan task accomplishments:
- Task 1 A24 (Blob URL empirical): 4ae7325 (prior executor)
- Task 2 A25 (5s latency): 47e9818 (prior executor)
- Task 3 A26+A27+A28 wiring: 20e06a6 (this run)
- Task 3b A27.7 F2 contract refinement (Rule 1 fix): d0ebc80 (this run)

Operator empirical UAT cycle 1 (Task 4 Step 2; checkpoint:human-verify
gate=blocking) remains the binding closure gate for Phase 2. Checklist
surfaced in SUMMARY § "Operator Empirical UAT Cycle 1 — AWAITED".
2026-05-20 17:25:13 +02:00
935ba1d489 docs(02-03): complete D-P2-02 meta.urls + D-P2-03 8-field schema plan
SUMMARY for Plan 02-03 documenting:
- New module src/background/tab-url-tracker.ts (4 exports incl. snapshotOpenTabs per DEC-011 Amendment 1 capability).
- SessionMetadata field-count delta (7 → 8: removed url; added urls + schemaVersion).
- 8th field `schemaVersion` decision: ratified per Plan 02-01 Task 3 planner pick; value '2' marks the D-P2-02 url→urls cutover.
- Filter rules verbatim from CONTEXT.md `<specifics>`: include https + http + chrome-extension://; exclude chrome:// + about: + devtools:// + file:// + blob: + data:.
- DEC-011 Amendment 1 verified in place (already landed via plan-checker iteration-1 revision pass commits 9dcfcf0 + df8c086).
- F2 resolution: empty-tracker case emits `urls: []` with diagnostic logger.warn; no sentinel-URL fallback.
- Rule 3 deviation: tests/background/meta-json-urls-schema.test.ts Tests 3+4+5 rewired to drive chrome.tabs.onUpdated callbacks directly via stub _callbacks array. Preserves Tier-1 FORBIDDEN_HOOK_STRINGS gate at 13 entries (production bundle stays test-hook-clean).
- Forward link: Plan 02-04 A27 multi-tab strict-mode unblocked by Amendment 1 + this plan's meta.urls implementation.

Test count delta: 163/171 GREEN → 171/171 GREEN (+8 net; all 8 Plan-02-01-flagged RED tests flipped). Tier-1 gate: 13/13 GREEN unchanged.

[parallel-executor] No modifications to STATE.md or ROADMAP.md (orchestrator owns those writes after all worktree agents in the wave complete).
2026-05-20 16:12:58 +02:00
95b5bd252c docs(02-02): complete Blob URL download pipeline plan (D-P2-01 closes P0-6)
SUMMARY.md documents:
- 3 RED tests in tests/background/blob-url-download.test.ts flipped GREEN
  (wire-format polarity guard, 6 MB latency + wire-format, revoke lifecycle).
- 6 files modified (3 prod source + 3 test files; +518 / -35 lines).
- Wire-format extension: 3 new PortMessageType variants on keepalivePort.
- Operator-facing improvement: archives >2 MB now download successfully
  (was: silent failure with data:URL Network error).
- Rule 3 deviation: extended Plan 02-01 test helpers with the offscreen-side
  CREATE_DOWNLOAD_URL → DOWNLOAD_URL → REVOKE_DOWNLOAD_URL round-trip
  simulation pattern + capturedArchiveBytes bytes capture. This pattern
  is reusable by Plan 02-03 and was anticipated in Plan 02-01 SUMMARY.
- Forward link: Plan 02-03 (meta.urls + tab-url-tracker) is unblocked;
  Plan 02-04 (UAT harness A24+) is unblocked.

Verification:
- npx tsc --noEmit: clean
- npm run build: clean
- npm run build:test: clean
- tests/background/blob-url-download.test.ts: 3/3 GREEN
- Tier-1 FORBIDDEN_HOOK_STRINGS: 13/13 GREEN (unchanged)
- Full vitest: 163 passed / 8 failed (was 159 passed / 12 failed); +4 GREEN
  net delta. 8 remaining RED are exactly Plan 02-03 territory.
2026-05-20 15:57:35 +02:00
a991e1732a docs(02-01): complete RED gate — 3 test files pin D-P2-01 + D-P2-02 + D-P2-03 + F2
Plan 02-01 Wave 0 RED gate closed. Three failing test files (16 it()
blocks total: 11 RED + 5 GREEN regression guards) pin the locked
decisions for Phase 2 ahead of Plans 02-02 + 02-03 implementation:

  - blob-url-download.test.ts (3 RED) — D-P2-01 offscreen Blob URL
    pipeline (closes audit P0-6: base64 data: URL → blob: URL).
  - meta-json-urls-schema.test.ts (5 RED) — D-P2-02 meta.url → meta.urls
    migration + F2 empty-tracker → urls:[] resolution.
  - strict-meta-json-validation.test.ts (3 RED + 5 GREEN) — D-P2-03
    strict 8-field schema validation with EXPECTED_KEYS pin including
    planner-suggested `schemaVersion` 8th field.

Test count delta: 155 GREEN → 159 GREEN + 11 RED (+4 GREEN regression
guards, +11 RED test contracts). Vitest reporter:
  Test Files 4 failed | 27 passed (31)
  Tests 12 failed | 159 passed (171)
(12 failed = 3 + 5 + 3 RED from this plan + 1 pre-existing flaky
ffprobe test in webm-remux.test.ts — out of scope; documented in
SUMMARY.md Deferred Issues.)

Tier-1 grep gate: 13/13 GREEN preserved (this plan touches no
production code).

Planner-resolved tensions carried forward in SUMMARY.md:
  - D-P2-03 'non-empty urls[]' vs CONTEXT.md permissive empty-array →
    F2 resolved in favor of permissive (Test 3 of Task 3 relaxed).
  - 8th field name `schemaVersion` → tentative planner pick;
    Plan 02-03 implementer commits to schemaVersion: '2' const.
  - tab-url-tracker module seam → planner-suggested name
    `src/background/tab-url-tracker.ts` with getTabUrlsSeen() export.
  - Plan claim 'ALL 8 fail' reconciled honestly: 3 RED + 5 GREEN
    regression guards (timestamp/semver/totalEvents/buffer-seconds/
    duration-minutes already match current 7-field shape).

Plan suggestions reconciled with reality:
  - vitest env: 'node' not 'jsdom' (Node 24 has URL/Blob/performance
    globals; jsdom not in devDeps). FileReader polyfill inline.
  - Task 2 Test 1 source-text scan instead of tsc-compile-failure
    (vitest.config.ts typecheck:{enabled:false}).

Per worktree-mode constraint: STATE.md, ROADMAP.md, REQUIREMENTS.md
NOT modified. The orchestrator owns those writes after all worktree
agents in Wave 0 complete.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 15:36:09 +02:00
a440c7d76b wip: phase-02 paused — 4 plans validated, ready for execution
Phase 2 (Stabilize export pipeline) planning ceremony complete:

- /gsd-discuss-phase 2 → 02-CONTEXT.md (cc042a5) with 3 locked decisions
  (D-P2-01 offscreen Blob URL; D-P2-02 meta.urls schema; D-P2-03 full scope)
- /gsd-plan-phase 2 → 4 plans (0608b22) → revision iteration 1 per checker
  (9dcfcf0; B1 tabs permission + 4 informational flags resolved) →
  plan-checker iteration 2 GREEN → constraint sync (df8c086)
- DEC-011 Amendment 1 landed: `tabs` permission added to manifest for D-P2-02
  meta.urls feature

HANDOFF.json + .continue-here.md capture:
- 10 completed-this-session items (resume + researcher + Plan 01-14 + Plan
  01-12 + Plan 01-10 cycle-2 + Phase 1 verifier + alpha distribution +
  re-phasing + Phase 2 discuss + Phase 2 plan)
- 3 remaining tasks (Phase 2 execute, Phase 3 prep, Phase 4 optional)
- 5 decisions this session
- 2 advisory anti-patterns (/gsd-remove-phase CLI cascading bug;
  charter-shift-via-discuss-phase pattern)
- Phase 4 backlog (8 items accumulated)
- Test baselines (vitest 153, UAT 24, FORBIDDEN_HOOK_STRINGS 12)

Branch identity preserved at gsd/phase-01-stabilize-video-pipeline per
/gsd-plan-phase workflow invariant — ROADMAP phase rename does NOT mutate
branch name.

Alpha distribution shipped to testers in parallel:
  dist-archives/mokosh-build-2026-05-20-6dbed91.zip
  SHA256: 2a9ffe6797534d6a4cf5e040dccde8772245407483693efa17fdd1caca8b1f66

Next session: /gsd-resume-work → /gsd-execute-phase 2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 14:56:53 +02:00
9dcfcf0793 fix(02): revise plans per checker (B1 + 4 flags) — add tabs permission for D-P2-02
- BLOCKER B1: add `tabs` to manifest.json permissions (DEC-011 Amendment 1
  cites Phase 2 D-P2-02 meta.urls feature as justification). Honors
  D-P2-02 "all tabs visible" wording verbatim. Updates manifest-i18n test
  expected permission list lockstep.
- F1: add A28 harness assertion for REQ-archive-layout strict zip-layout
  verification (5 entries, no extras).
- F2: createArchive empty-tracker fallback removed; logs warn + sets
  urls:[] instead of fake [extension-origin URL]. 02-01 RED test pins
  empty-tracker → urls:[].
- F3: 02-02 Task 3 prose deliberation struck; typed `blob-url-mint-failed`
  throw is the resolved-only contract.
- F4: 02-02 Task 3 verify block adds full-suite `npm test` after focused
  test runs.
- A27 strict-mode (Plan 02-04): REQUIRES both URLs in meta.urls; FAILS
  on length < 2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 14:25:20 +02:00
0608b22427 feat(02): plans 01-04 — Phase 2 export pipeline closure (Blob URL + meta.urls + schema + harness)
Wave structure (4 plans, 3 waves):
- 02-01 (Wave 1 RED): 15 RED tests pinning D-P2-01 (blob: URL contract), D-P2-02
  (meta.urls schema + dedup + filter), D-P2-03 (strict 8-field validation +
  schemaVersion '2' cutover marker).
- 02-02 (Wave 2): Offscreen-minted Blob URL pipeline — extends PortMessageType
  with CREATE/REVOKE messages; SW downloadArchive rewrite (data: → blob: via
  base64-on-wire to offscreen + URL.createObjectURL + chrome.downloads.onChanged
  revoke lifecycle). Closes audit P0-6; unblocks >2 MB archives.
- 02-03 (Wave 2): meta.urls schema migration + tab-url-tracker module
  (chrome.tabs.onActivated + onUpdated → deduplicated, filtered, first-seen-
  ordered string[]); SessionMetadata 7→8 fields with schemaVersion + urls;
  REQUIREMENTS.md REQ-meta-json-schema amendment. Closes P1 #10.
- 02-04 (Wave 3): UAT harness A24+A25+A26+A27 — blob: URL prefix, <5s SAVE→zip
  latency, meta.json 8-field shape, multi-tab dedup; pre-checkpoint bundle gates
  per saved memory + operator empirical UAT cycle 1. Tier-1 FORBIDDEN_HOOK_STRINGS
  inventory stays at 12 (no new hook symbols — chrome.* monkey-patches + JSZip
  + production APIs only).

Locked decisions honored (per 02-CONTEXT.md):
- D-P2-01: offscreen-minted Blob URL via existing keepalivePort + base64 wire
  format (reuses D-12 precedent at src/shared/binary.ts).
- D-P2-02: meta.json url:string → urls:string[]; URL filter per CONTEXT.md
  <specifics> (include https://, chrome-extension://; exclude chrome://, about:,
  devtools://, file://); dedup + first-seen ordering.
- D-P2-03: full scope; 8-field strict schema validation with schemaVersion='2'
  as the 8th field (planner-resolved tentative pick; revisable by plan-checker).

Architectural constraints preserved:
- Always-on charter (Plan 01-09 Amendment 3): no finally-block in saveArchive;
  no clearTabUrlsSeen on SAVE.
- Tier-1 FORBIDDEN_HOOK_STRINGS = 12 (no new test-hook symbols).
- Never await import(...) in src/background/index.ts (Plan 01-11 SUMMARY).
- Pre-checkpoint bundle gates per feedback-pre-checkpoint-bundle-gates.md (run
  in 02-04 Task 4 before operator surface).

Plan validation: gsd-sdk frontmatter.validate + verify.plan-structure GREEN
for all 4 plans.

ROADMAP updated: Phase 2 Plans list + Goal/Success Criteria block annotated
with D-P2-02/D-P2-03 amendments + 5th success criterion (Blob URL + revoke
lifecycle for >2 MB archives); Progress table 0/TBD → 0/4.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 14:03:14 +02:00
cc042a5583 docs(02): capture phase context — discuss-phase complete
Phase 2 (Stabilize export pipeline) discuss-phase landed via inline canonical
workflow execution. 02-CONTEXT.md captures 3 locked decisions:

- **D-P2-01:** Offscreen-minted Blob URL pipeline replaces base64 data: URL
  download path (src/background/index.ts:709-710). SW Blob → offscreen
  URL.createObjectURL → SW chrome.downloads.download → URL.revokeObjectURL on
  onChanged. Closes audit P0-6. Unblocks real-archive size (>2 MB).

- **D-P2-02:** meta.json schema migrates singular `url: string` to plural
  `urls: string[]` capturing all tabs visible during the 30s recording window.
  Schema-breaking change requires REQUIREMENTS.md REQ-meta-json-schema
  amendment + SessionMetadata type update. Closes audit P1 #10 captured-URL bug.

- **D-P2-03:** Full Phase 2 scope = Blob URL migration + meta.urls schema
  migration + strict meta.json schema validation test + UAT harness A24+
  <5s latency assertion. ~3-4 plans expected.

Decision provenance:
- D-P2-01 rationale: user "up to you. If you think we need to migrate — good
  let's do it." Plus analysis: real archives EXCEED base64 cap.
- D-P2-02 rationale: user picked "All tabs' URLs as an array
  (meta.json.urls)" — highest informational fidelity for multi-tab bug
  reproduction. Privacy acceptable per "log is internal" v1 charter.
- D-P2-03 rationale: user picked "Full scope: bug fixes + schema + harness
  latency assertion".

Canonical references + code context + deferred items captured in CONTEXT.md.
Phase boundary explicit: not from-scratch; closes residual gaps after Plans
01-08/01-09/01-10/01-12 substantively shipped REQ-popup-ui + REQ-archive-
layout + REQ-screenshot-on-export.

Next: /gsd-plan-phase 2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 13:41:08 +02:00
586836f8a0 docs(01): VERIFICATION + Phase 1 closure markers — goal-backward audit GREEN
gsd-verifier goal-backward audit (2026-05-20) returned GREEN verdict on
Phase 1 (Stabilize Video Pipeline + whole-desktop capture + as-automatic-
as-platform-allows recording start):

- 17/17 must-haves verified: 11 REQs/charters + 6 cross-cutting gates
- 14/14 plans complete (01-01..01-09 + 01-11 spike-pivot + 01-12 + 01-13
  + 01-14 + 01-10)
- 5 operator empirical acks: Plan 01-07 (Chrome playback 2026-05-15) +
  Plan 01-13 (harness 2026-05-19) + Plan 01-12 (brand-fit 2026-05-20) +
  Plan 01-10 cycle-2 ("All good" 2026-05-20) + Plan 01-10 brand-rename
  follow-up (2026-05-20)
- Test gates: vitest 153/153 GREEN; UAT harness 24/24 GREEN; Tier-1 grep
  gate 12 FORBIDDEN_HOOK_STRINGS; pre-checkpoint bundle gates PASS
- 7 P0 audit defects: 6 closed in-Phase-1-scope; P0 #6 (data-sensitive
  masking) properly deferred to Phase 2

Marker flips landed:

- STATE.md status reflects Phase 1 COMPLETE; completed_phases 0 → 1
- ROADMAP.md Phase 1 row [ ] → [x] with closure-arc summary
- REQUIREMENTS.md REQ-video-ring-buffer In-progress → Complete 2026-05-20
- VERIFICATION.md committed (orchestrator-bundle pattern per verifier
  protocol)

Forward-looking deferred (NOT gaps):
- Phase 2: REQ-rrweb-dom-buffer + REQ-user-event-log +
  REQ-password-confidentiality (audit P0 #6)
- Phase 5 hardening: getDisplayMedia cursor visibility; setimmediate
  polyfill new Function pre-existing; tabs permission gap; dark-surface
  logo contrast; 2 ffprobe/ffmpeg test flakes

Phase 2 (Stabilize DOM + event-capture privacy) kickoff pending.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 12:31:36 +02:00
52dc2e6a6e docs(01-10): summary — welcome tab + 5-cycle debug closure + brand polish (153/153 vitest, 24/24 UAT GREEN, ack 2026-05-20)
Plan 01-10 (welcome tab) full SUMMARY landing closure of Phase 1's final
functional plan. Welcome tab landed end-to-end across 4 waves + Wave 4
operator empirical UAT cycle 2 ack "All good" 2026-05-20.

Architecture:
- chrome.runtime.onInstalled('install') + chrome.storage.local
  flag-gating (onboarding-completed:true + installed-at:<Date.now()>)
  + chrome.tabs.create + fire-and-forget .catch defense-in-depth.
- Plan 01-12 must_have #9 path-B contract honored: welcome.css opens
  with `@import '../shared/tokens.css';` (canonical Lora display +
  IBM Plex Sans UI + D-04 Loom palette); NO placeholder
  welcome-tokens.css file.
- chrome.i18n.getMessage for welcomeHeroRu + welcomeHeroEn with
  `|| <en-const>` fallback (Plan 01-12 fallback pattern preserved).
- Vite `?url` import + auto-WAR idiom bundles canonical
  mokosh-mark.svg as inline data URL in welcome chunk
  (closure-cycle debug 01-10-welcome-page-missing-mark).
- Three-pipeline DOM population: populateMark walks
  [data-mokosh-slot='mark']; populateCopy walks [data-mokosh-key]
  from in-file COPY map; populateI18n walks [data-mokosh-i18n-key]
  from chrome.i18n.getMessage.
- D-16-toolbar charter preserved: welcome page is informational +
  read-only; NO REQUEST_PERMISSIONS / chrome.runtime.sendMessage
  start path. CTA copy directs operator at toolbar icon.

Wave structure (4 plan-wave commits):
- 89e1e09 Wave 0 RED onboarding tests (3 tests A/B/C)
- 49f087f Wave 1 welcome bundle + Vite entries + manifest
  web_accessible_resources
- 8f329d8 Wave 2 openWelcomeIfFirstInstall + onInstalled wiring
- b112cb7 Wave 3 harness A15+A16+A17

Cycle-1 operator UAT rejection 2026-05-20 ~08:56 surfaced two
concerns + 5 inter-cycle debug fixes (in commit order):
- 4bba679 fix(01-09): notifStartup text split (notifStartupCta for
  onStartup; notifRecordingStarted reserved for manual-start)
- d48a715 fix(01-10): welcome page mark — bundle canonical
  mokosh-mark.svg via Vite ?url + populateMark + A17.8 sub-check
  (Plan 01-12 must_have #9 path-A swap-in gap closed)
- 0854baf fix(01-10): vitest build-test it() timeout bump to 30s
  for slower welcome-page build
- a2dfc8c fix(01-09): startVideoCapture — remove stale active-tab
  dependency (D-01 cleanup gap; +3 RED→GREEN tests at
  start-video-capture-no-tab.test.ts)
- d21ed17 fix(01-12): brand polish — replace stale 'AI Call Recorder'
  refs with Mokosh (4 files; .planning/intel/* preserved as audit
  trail)

Harness deltas:
- A15-A17 added at b112cb7 (24/24 UAT GREEN; A17 with 7 sub-checks
  incl. A17.7 --mks-rec getComputedStyle probe resolving to
  rgb(178,84,61) canonical).
- A17.8 mark-bundling sub-check added at d48a715 (verifies welcome
  chunk JS contains inlined data:image/svg+xml URL with canonical
  viewBox='0 0 32 32' preserved).
- FORBIDDEN_HOOK_STRINGS unchanged at 12 (A15-A17 use chrome.tabs
  .query + chrome.storage.local.get + fetch + DOMParser +
  getComputedStyle production APIs exclusively).

Test deltas:
- vitest 147 → 153 GREEN (+6: 3 onboarding tests Wave 0 + 3
  start-video-capture-no-tab tests closure-cycle debug a2dfc8c).
- UAT harness 21/21 → 24/24 GREEN (A0-A14 + A15-A17 + A18-A22 + A23).

Pre-checkpoint bundle gates per saved memory
feedback-pre-checkpoint-bundle-gates.md: Tier-1 hook-string grep
+ SW CSP-safety + Node-globals + DOM-globals + manifest validation
+ en↔ru parity — all PASS. setimmediate polyfill new Function in
SW chunk confirmed pre-existing (logged at
.planning/phases/01-stabilize-video-pipeline/deferred-items.md
for Phase 5 hardening per Plan 01-12 Wave 7 disclosure).

Operator brand-fit cycle-2 ack received verbatim "All good" + cycle-2
follow-up brand-rename ack via d21ed17. Phase 1's final functional
plan delivered; Phase 1 final-closure unblocked pending REQUIREMENTS
/ ROADMAP / STATE marker flip + optional /gsd-verify-work 1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 12:10:30 +02:00
7f58e0ae31 fix(01-10): revise plan per 01-12 + 01-14 baselines (vitest 98→147, UAT 15→21, FORBIDDEN 10→12, welcome.css @imports canonical tokens, welcomeHero keys read from chrome.i18n)
Surgical amendment to unexecuted Plan 01-10 absorbing the post-draft
landing of Plan 01-12 (canonical src/shared/tokens.css + 16 i18n keys
including welcomeHeroRu/welcomeHeroEn; 2026-05-20 operator brand-fit
ack) and Plan 01-14 (vitest +2 + UAT +1 + FORBIDDEN_HOOK_STRINGS +2).

Baseline shifts:
- vitest 98 → 147 GREEN (post Plan 01-12 + 01-14); plan close target 150.
- UAT 15 → 21 GREEN (A0-A14 + A18-A22 + A23); plan close target 24
  (A0-A14 + A15-A17 + A18-A22 + A23).
- FORBIDDEN_HOOK_STRINGS 10 → 12 (Plan 01-14: lastGetDisplayMediaConstraints
  + get-last-getDisplayMedia-constraints); Plan 01-10 introduces no new
  test-mode symbols; inventory unchanged at 12.

Plan 01-12 must_have #9 path-B contract honored end-to-end (Plan 01-12
landed FIRST, so the welcome page adopts canonical assets directly):

- welcome.css opens with `@import '../shared/tokens.css';` (NO placeholder
  welcome-tokens.css; removed from files_modified).
- D-08 hero tagline elements use data-mokosh-i18n-key='welcomeHeroRu' +
  data-mokosh-i18n-key='welcomeHeroEn'; welcome.ts reads via
  chrome.i18n.getMessage with `|| <en-const>` fallback per Plan 01-12
  fallback pattern. WELCOME_HERO_RU_FALLBACK + WELCOME_HERO_EN_FALLBACK
  constants exported from copy.ts for the degradation path.
- copy.ts COPY map retains non-tagline keys only (page title + explainer
  lines + CTA + footer privacy; engineering placeholders per D-03).
- A17 design-swap-readiness invariant extended with:
  - A17.5: welcome.css contains canonical @import directive OR inlined
    `--mks-rec:` evidence;
  - A17.6: bundled JS contains COPY[ OR chrome.i18n.getMessage('welcomeHero;
  - A17.7 NEW: getComputedStyle probe on var(--mks-rec) returns non-default
    value (canonical rgb(178, 84, 61) = #b2543d = --mks-madder-600 per
    Plan 01-12 Wave 4 D-04 Loom palette adoption).
- depends_on extended to [01-09, 01-13, 01-14, 01-12].

Preserved verbatim: 5-task structure, A15/A16 contracts, D-02/D-08/D-09
references, threat model + STRIDE register, operator empirical checkpoint
shape, Plan 01-12 default_locale='en' + __MSG_*__ + __VITE_DEV__ +
__MOKOSH_UAT__ + src/shared/tokens.css.

Validated: gsd-sdk frontmatter.validate + verify.plan-structure both PASS;
task_count=5, all tasks complete with files/action/verify/done.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 08:48:24 +02:00
f319c7dc6e docs(01-12): summary — design integration landed (147/147 vitest, 21/21 UAT, brand-fit ack 2026-05-20)
Plan 01-12 closure SUMMARY landed at .planning/phases/01-stabilize-
video-pipeline/01-12-SUMMARY.md per the plan's <output> block + 01-13/
01-14 closure cadence. Mirrors the 01-13-SUMMARY frontmatter shape +
body sections (One-Liner / What Landed by Wave / Test Counts /
Deviations / Architectural Notes / Self-Check / Known Limitations /
Bridge to Phase 1 Closure).

Plan 01-12 design integration in one sentence: Lora self-hosted via
R2 designer substitution (Newsreader → Lora for Cyrillic coverage,
2026-05-19); src/shared/tokens.css canonical with 8 local @font-face
rules and zero remote URLs; 16 i18n keys across en + ru with parity;
branded Loom-mark icons replace Bug A placeholders; src/popup +
src/background migrated to chrome.i18n.getMessage with || <const>
fallback; UAT harness extended with A18-A22; pre-checkpoint bundle
gates established per feedback-pre-checkpoint-bundle-gates.md;
operator brand-fit ack received 2026-05-20 verbatim "all good".

Gate evidence (per Wave 7 pre-checkpoint 865d394 + this closure):
- vitest: 147/147 GREEN (re-verified on closure day; 26 test files)
- npm run test:uat: 21/21 GREEN (A0-A14 + A18-A22 + A23)
- npx tsc --noEmit: clean
- npm run build + npm run build:test: both clean
- MV3 CSP self-host: 0 googleapis / 0 https://fonts in dist/
- Tier-1 forbidden-strings: 13/13 GREEN (no new test-mode symbols)
- Operator brand-fit empirical ack 2026-05-20: "all good"

Closure linkage:
- Plan 01-12 functionally CLOSED (10/10 tasks; 7/7 waves)
- Plan 01-13 Task 9 (operator brand/design ack on loaded extension)
  functionally CLOSED via this checkpoint (same operator + same
  empirical surface coverage)
- Phase 1 design/brand contract CLOSED; only Plan 01-10 (welcome tab)
  remains as the last Phase 1 functional plan
- Phase 2 inherits tokens.css + chrome.i18n patterns + OFL self-host
  recipe + pre-checkpoint bundle gates as production conventions

Out-of-scope discovery (Wave 7 pre-checkpoint, logged for Phase 5
hardening, NOT a Plan 01-12 regression): setimmediate polyfill
`new Function` in SW chunk via vite-plugin-node-polyfills. Pre-existing
across Phase 1 history; logged at deferred-items.md. Suggested
follow-up: switch to a minimal Buffer shim or inline Buffer primitives
to drop the polyfill entirely.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 07:59:34 +02:00
865d394ae0 docs(01-12): wave-7 pre-checkpoint — log out-of-scope discovery (setimmediate polyfill new Function pre-existing)
Wave 7 pre-checkpoint bundle gates per feedback-pre-checkpoint-bundle-gates.md
revealed a pre-existing benign concern in the SW production bundle:

`vite-plugin-node-polyfills` (configured for Buffer in vite.config.ts)
bundles the upstream `setimmediate` package which contains a fallback
`new Function("" + I)` evaluated when setImmediate is called with a
non-function argument. Production source code does NOT call
setImmediate(string); the construct is dead at the runtime call-graph
level but Rollup conservatively preserves it (behind a runtime
typeof check, not a static dead branch).

Verified pre-existing across Phase 1 history via `git checkout main --
src/background/index.ts vite.config.ts && npm run build` — same
`new Function` count. Plan 01-12 made NO changes to the polyfill
configuration; this is logged for future tightening (Phase 5
hardening or a dedicated MV3 CSP audit plan), NOT for fix in this
plan per the deviation-rule SCOPE BOUNDARY.

All other pre-checkpoint bundle gates PASS:
- Tier-1 forbidden-strings: 13/13 GREEN (no new test-mode symbols)
- SW-bundle-import: 15/15 GREEN
- Node-globals (Buffer.*) in SW chunk: 0
- DOM-globals direct SW calls: none
- Manifest validation: PASS (__MSG_*__ + default_locale='en' +
  16 i18n keys per locale; en+ru parity verified)
- Tokens.css MV3 CSP self-host: 0 googleapis / 0 https://fonts in dist/
- Icons rasterized: 8-bit RGBA at 406/784/1952 B
- vitest: 147/147 GREEN
- npm run test:uat: 21/21 GREEN (A1..A14 regression-free + A18..A22
  new + A23 from 01-14)
- npx tsc --noEmit: clean
- npm run build + npm run build:test: clean

Surfacing Wave 7 operator brand-fit checkpoint to orchestrator next.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 07:47:13 +02:00
3fe018beb9 fix(01-12): revise plan baselines per Plan 01-14 landing (vitest 98→100, UAT 15→16, FORBIDDEN_HOOK_STRINGS 10→12)
Surgical amendment — Plan 01-12 is unexecuted; safe for in-place revision.
Plan 01-14 landed (b46712352541459792c0f) since 01-12 was authored,
adding monitorTypeSurfaces:'include' + UAT A23 + 2 FORBIDDEN_HOOK_STRINGS
entries. Plan 01-12 baseline arithmetic updated to reflect post-01-14
floors and depends_on chain extended.

Changes:
- frontmatter depends_on: append 01-14 (canonical sequential-dependency declaration)
- must_haves truth #11: 10 strings → 12 strings post-Plan-01-14, with provenance note
- must_haves truth #13: vitest 98→100→106; UAT 15→16→21 (or 19→24 with 01-10);
  A23 added to no-regression list alongside A0-A14 + (A15-A17 if 01-10)
- Embedded FORBIDDEN_HOOK_STRINGS code block: 10 → 12 entries (lastGetDisplayMediaConstraints,
  get-last-getDisplayMedia-constraints) with attribution comment
- Wave 6 task narrative + verify + done: 20/20 → 21/21; 23/23 → 24/24
- Wave 7 closure narrative + one-liner + checkpoint copy: same arithmetic update
- Threat model T-01-12-08: inheritance updated to include T-1-14-*; grep-gate floor 10→12
- Verify-block harness orchestrator grep gate: strengthened with `grep -v '^#'` filter
  to prevent self-invalidating count from comment lines (per planner.md gate hygiene)
- Success criteria items 3, 4, 9: vitest 98→100; UAT 20→21; inventory 10→12

Preserved verbatim (per surgeon-not-architect):
- 7-wave structure (Wave 0 fonts/tokens/icons/i18n RED scaffolds, Wave 1 fonts+tokens.css,
  Wave 2 icons, Wave 3 manifest i18n, Wave 4 popup/welcome adoption, Wave 5 8 i18n strings,
  Wave 6 harness A18-A22, Wave 7 operator brand-fit checkpoint)
- 10 tasks (validated via gsd-sdk verify.plan-structure)
- R2 Lora baked-in decision
- D-01..D-09 decision references
- All files_modified entries
- Threat model entries other than T-01-12-08 inheritance line
- Designer ack references
- Operator checkpoint (Wave 7)
- Must_have truths #1-10 and #12

Validation:
- gsd-sdk frontmatter.validate → valid:true
- gsd-sdk verify.plan-structure → valid:true, errors:0, task_count:10
- grep verification: zero stale references to 98/104/15/15/20/20/23/23/18/18/"at 10"
- All new baselines present at 32 update sites
- diff: 1 file changed, 34 insertions(+), 30 deletions(-)

Next step: plan-checker re-validation of arithmetic + consistency before executor spawn.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 21:45:58 +02:00
52541452e0 docs(01-14): summary — picker enhancement landed (16/16 UAT GREEN, 100/100 vitest GREEN)
Canonical closure artifact for Plan 01-14:
- monitorTypeSurfaces:'include' shipped (W3C spec §6.1; Chrome >= 119 picker narrowing)
- A23 harness regression gate wired into the UAT orchestrator (post-A14 chain)
- Tier-1 grep gate inventory extended in lockstep (12 forbidden strings; was 10)

Single atomic feat commit (b467123) for the entire 1-task plan.

Verification: vitest 100/100 GREEN (+2 new parametrized FORBIDDEN_HOOK_STRINGS
tests; both PASS — production bundle hook-free for the new surface). UAT
harness 16/16 GREEN (was 15/15). tsc + build clean.

Ceremony: replaces the retired AMENDMENT-A.md improvisation path per
01-11-SUMMARY.md Architectural Notes. Canonical GSD flow — plan (41c1f7e)
→ checker (B-01-14-01) → revision (433ee28) → executor (b467123) → SUMMARY.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 21:40:11 +02:00
433ee280f3 fix(01-14): revise plan per checker — include test-expectation update (B-01-14-01)
Plan-checker BLOCKER B-01-14-01: original plan's must_haves truth #5 understated
baseline regression risk. Adding `monitorTypeSurfaces: 'include'` as a sibling
constraint in src/offscreen/recorder.ts would have dropped vitest from 98/98
GREEN to 97/98 RED because tests/offscreen/display-surface-constraint.test.ts
Test 1 (line 223-226) uses strict deep-equality (toHaveBeenCalledWith, NOT
expect.objectContaining) on the constraints object — the test author's intent
(comment at line 221-222) is to catch future drops of ANY field.

Surgical revision per references/planner-revision.md (surgeon-not-architect):
- Frontmatter: add tests/offscreen/display-surface-constraint.test.ts to
  files_modified list.
- must_haves truth #5: replace the "no existing unit test references the
  constraints object" claim with a positive statement that the strict-deep-
  equality assertion at lines 223-226 is updated in lockstep; preserves the
  test author's "no objectContaining" discipline; explicit no-transient-RED
  guarantee across commit boundaries.
- must_haves artifacts: new entry for the test file documenting the in-place
  edit shape and the preserved test author comment.
- must_haves key_links: new link entry pairing the test assertion with the
  source call site under the lockstep contract.
- Interfaces block: add the explicit "test-expectation lockstep update" code
  fragment with the chosen key ordering (video → monitorTypeSurfaces → audio)
  so the executor lands the source change and the test update with matching
  shapes.
- Task 1 <files>: add tests/offscreen/display-surface-constraint.test.ts.
- Task 1 <action>: insert new Step 1b between Step 1 (source change) and
  Step 2 (offscreen-hooks bridge) — full single-line edit spec at lines
  223-226, preserve toHaveBeenCalledWith contract, preserve comment block,
  same-commit guarantee.
- Task 1 verify-block expected outputs: explicitly call out that 98/98 GREEN
  is preserved BECAUSE Step 1b lands (without it, 97/98 RED on the strict-
  deep-equality assertion).
- Task 1 <done>: add line covering the lockstep test update + the no-transient-
  RED guarantee.
- <verification> phase gate: add new check #2 (test-expectation lockstep)
  between source-line correctness and A23 round-trip.
- <success_criteria>: add bullet for the lockstep test-expectation update.
- <output> SUMMARY contract: add "Revision linkage" bullet documenting that
  the plan was revised once after the plan-checker flagged B-01-14-01.

Untouched (per checker's preserve-verbatim list):
- Source-line target (src/offscreen/recorder.ts:270)
- Harness wiring references (assertA3 686, driveA14 987, __mokoshHarness
  1922+1942, drivers array 289-312, Total comment 354)
- FORBIDDEN_HOOK_STRINGS lockstep contract (both inventories)
- `_constraints` capture path
- Scope discipline (still 1 task, autonomous, no checkpoint)
- Research traceability (Plan 01-10 RESEARCH §5 + §Pitfall-5 + W3C §6.1)
- Threat model (T-01-14-04 mirrors Plan 01-13)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 20:41:09 +02:00
41c1f7e82f feat(01-14): plan — monitorTypeSurfaces picker enhancement (canonical post-closure scope)
Plan 01-14 ships W3C Screen Capture monitorTypeSurfaces: 'include' (Chrome
119+) on the offscreen getDisplayMedia call, plus an A23 harness regression
assertion that verifies the constraint reaches the call site via the
existing offscreen-hooks bridge.

Scope: 1 source line + A23 wiring + Tier-1 grep gate inventory update
(lockstep extension of unit-gate + UAT A0 FORBIDDEN_HOOK_STRINGS).
Autonomous, single executor; no operator empirical checkpoint (UAT 16/16
harness coverage suffices per feedback-pre-checkpoint-bundle-gates.md).

Canonical sources:
- Plan 01-10 RESEARCH section 5 ('monitorTypeSurfaces: include' recommendation)
- Plan 01-10 RESEARCH section Pitfall-5 ('Misinterpreting displaySurface
  as a hard constraint' — monitorTypeSurfaces is the picker-UI complement
  to D-15's post-grant validation)
- W3C Screen Capture spec section 6.1 DisplayMediaStreamOptions
- developer.chrome.com/docs/web-platform/screen-sharing-controls

Decisions honored:
- D-01 (whole-desktop only via getDisplayMedia; reject window/tab) — the
  new constraint is the picker-UI realization of D-01's intent.
- D-15 (post-grant displaySurface validation) — UNCHANGED; remains the
  enforcement (this plan is belt-and-suspenders at the picker UI level).

Ceremony note: this plan replaces the prior AMENDMENT-A.md improvisation
path retired per 01-11-SUMMARY Architectural Notes. Canonical GSD ceremony
(plan -> checker -> executor -> SUMMARY).

Validations:
- gsd-sdk frontmatter.validate -> valid: true (8/8 required fields).
- gsd-sdk verify.plan-structure -> valid: true (1 task; hasFiles/hasAction
  /hasVerify/hasDone all true).
- ROADMAP.md Phase 1 plans list extended with 01-14 entry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 20:34:17 +02:00
4d828f1080 docs(01-10): install-flow + auto-select research — both asks INFEASIBLE
Researcher (gsd-phase-researcher) returned HIGH-confidence verdicts on the
12-area brief from .continue-here.md:

Ask 1 (install-time auto-start): INFEASIBLE in unmanaged Chrome.
  W3C Screen Capture spec §5.1 mandates transient user activation;
  chrome.runtime.onInstalled confers none. Floor: 2 clicks
  (toolbar/welcome-page → Share button on picker). Enterprise policy
  ScreenCaptureWithoutGestureAllowedForOrigins exists (Chrome+Edge ≥ 123)
  but only applies to managed-Chrome contexts with extension URL
  whitelisted — does NOT apply to Load-Unpacked deployment; deferred-idea.

Ask 2 (auto-select desktop / skip picker): INFEASIBLE in unmanaged Chrome.
  W3C spec mandates user MUST choose every time. displaySurface:'monitor'
  is a hint (already applied src/offscreen/recorder.ts:270).
  chooseDesktopMedia doesn't auto-accept on single-monitor setups AND
  streamId not usable in MV3 offscreen documents (Chrome DevRel position).

Primary recommendation: KEEP Plan 01-10's current informational CTA
charter (commit 3a530c2 unchanged). Both architectures hit the same
2-click floor; informational CTA has lower maintenance surface AND
teaches operator where the toolbar icon lives (critical for day-2+
sessions).

Enhancement candidate (NOT required for 01-10): add
monitorTypeSurfaces:'include' (Chrome ≥ 119) to offscreen getDisplayMedia
constraints — single line, zero risk, removes tab/window panes from
picker entirely. Suggest as Plan 01-09 amendment OR mini-plan.

Open questions for orchestrator (3):
1. Confirm informational CTA charter (this research recommends YES)
2. Ship monitorTypeSurfaces:'include' as Plan 01-09 amendment vs deferred?
3. Are Repremium operators on Wayland Linux? (affects welcome-page copy)

File: .planning/phases/01-stabilize-video-pipeline/01-10-RESEARCH.md
  (1092 lines; full W3C citations, Chromium issue links, prior art for
  Loom/Screencastify/Veed/Awesome-Screenshot, ASCII flow diagrams,
  edge-case enumeration for macOS/Wayland/incognito/managed-Chrome)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 20:12:18 +02:00
cecefc61f9 wip: phase-01 paused — .continue-here.md handoff (pairs with c60b887 HANDOFF.json)
Human-readable handoff. Captures:
- 3 BLOCKING CONSTRAINTS from saved memory (scope reduction, GSD ceremony, pre-checkpoint gates)
- 3 anti-patterns from this session (improvised artifact types, claiming canonical without verifying, save-stops UX cycle)
- Current state + working tree + test/build baseline
- Next-session order of operations (10 steps)
- Required reading order
- Pending researcher brief (12 areas; was 529-blocked)
- Infrastructure state + API capacity note
- Followup backlog

Resume: /clear → /gsd-resume-work

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 17:57:45 +02:00
e035fd279d docs(01-09): Amendment 3 + 01-13 SUMMARY reversal note + STATE.md sync + debug records
Plan 01-09 Amendment 3 (2026-05-19) — atomic documentation pass for
the save-does-not-stop-recording charter reversal.

Changes:
- .planning/phases/01-stabilize-video-pipeline/01-09-PLAN.md:
  Amendment 3 block added above <success_criteria> (mirrors
  Amendment 2 placement). Describes the reversed charter,
  references the new debug record, points at the inverted
  test file + harness A14.
- .planning/phases/01-stabilize-video-pipeline/01-13-SUMMARY.md:
  "Subsequent Reversal (2026-05-19)" footer added. Notes that
  npm run test:uat still 15/15 GREEN under the inverted A14
  contract; vitest baseline preserved at 98 GREEN.
- .planning/STATE.md:
  Plan 01-13 closure block extended with CHARTER REVERSAL bullet
  citing the 4 commit SHAs (6ac23fd RED, 7645765 GREEN,
  1baaf45 A14 invert, this commit docs).
- .planning/debug/resolved/01-09-save-stops-recording.md:
  SUPERSEDED 2026-05-19 footer appended (audit trail; original
  fix was technically correct against its charter, reversal is
  UX iteration not technical defect).
- .planning/debug/resolved/01-09-save-does-not-stop-recording.md:
  NEW debug record landed directly in resolved/ (no checkpoint
  cycle — orchestrator-diagnosed reversal). Documents symptom,
  charter clarification cycle, fix shape, RED→GREEN evidence
  with commit SHAs + vitest/harness output, anti-regression
  coverage at unit + E2E layers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 17:50:49 +02:00
8d1c8fb0cc docs(01-12): create Plan 01-12 (Design Integration; R2 Lora unblocks; 7 waves)
Final designer reply received 2026-05-19 unblocks Plan 01-12: R2
substitution — replace Newsreader with Lora (OFL, Cyreal foundry, full
Cyrillic-Latin parity, variable wght 400-700). All 9 brand decisions
now resolved; R2 displaces Newsreader from `--mks-font-display`.

Plan structure: 7 waves, 10 tasks.

- Wave 0 (TDD scaffolds): 6 RED unit tests — tokens-adopted,
  fonts-present, icons-present, no-remote-fonts, manifest-i18n,
  locale-parity. Each RED until its corresponding artifact wave lands.
- Wave 1: Self-host OFL font bundle (Lora variable normal + italic,
  Plex Sans ×4, Plex Mono ×2) at src/shared/fonts/ via pyftsubset
  (Latin + Cyrillic basic subset); land src/shared/tokens.css canonical
  (Google Fonts @import → 7 local @font-face rules; Newsreader → Lora
  per R2; .mks-word class added per RESEARCH §8 + lockup SVG line 21).
- Wave 2: Rasterize Loom mark to icons/icon{16,48,128}.png via
  rsvg-convert; overwrite Bug A placeholders; 8-bit RGBA at all sizes.
- Wave 3: Land _locales/{en,ru}/messages.json (12 keys: 8 Brief §02
  operator strings + 4 supporting keys); manifest.json → __MSG_extName__
  + __MSG_extDesc__ + default_locale 'en' + action.default_title.
  extName='Mokosh — Session Capture' per D-07 user override; extDesc per
  D-08 brand-decisions-v1.md wording.
- Wave 4: src/popup/ + src/background/ adopt tokens.css (loom palette)
  + chrome.i18n.getMessage at every operator-facing copy site; replace
  hex literals with var(--mks-*) references; BADGE_REC_COLOR madder
  '#b2543d' (= --mks-madder-600 per D-04 + RESEARCH §10 Open Q A7).
- Wave 5: Welcome page conditional migration (if 01-10 landed, swap
  welcome-tokens.css → @import canonical tokens.css; migrate copy.ts
  shim to chrome.i18n.getMessage fallback); add __VITE_DEV__ define
  per RESEARCH §12 D-09 spirit; scripts/README.md smoke-isolation note.
- Wave 6: UAT harness A18-A22 (font reachability via document.styleSheets
  walk + fetch + byteLength; icon-not-placeholder via fingerprint diff;
  manifest:name === 'Mokosh — Session Capture'; --mks-font-display
  resolves to Lora via getComputedStyle; welcome tokens loaded
  conditional on 01-10). Tier-1 forbidden-strings UNCHANGED at 10.
- Wave 7: Operator empirical brand-fit checkpoint (last Phase 1 gate);
  SUMMARY + STATE.md + ROADMAP.md sync.

ROADMAP.md Phase 1 plan list extended from 7 → 13 entries (gap noted in
01-13 SUMMARY's known-limitations now closed).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 14:59:59 +02:00
3a530c2334 docs(01-10): rewrite plan in place — D-02/D-08/D-17-onboarding charter + design-swap-in-ready arch + harness A15+A16+A17
Drops the 2026-05-17 draft (zero commits, zero SUMMARY — virgin). Carries:
- onInstalled flag-gated welcome tab (3 RED→GREEN unit tests; storage-key contract pinned per prior I-02 fix)
- 5 new src/welcome/* files: welcome.html + welcome.ts + welcome.css + welcome-tokens.css + copy.ts
- Design-swap-in-ready: every color via var(--mks-*); every string via COPY map; every font via var(--mks-font-*) with system fallback
- vite.config.ts + vite.test.config.ts both gain welcome rollup input
- manifest.json gains web_accessible_resources for welcome.html
- Harness extended A15+A16+A17 (onboarding flag observability + no-re-open settle + design-swap invariant); Tier-1 forbidden-strings inventory unchanged at 10
- 4 autonomous tasks + 1 operator empirical checkpoint

Deletes: REQUEST_PERMISSIONS flow (gone in 01-09); duplicate Start button (D-16-toolbar owns start path); start-path divergence

Cites: D-17-onboarding (CONTEXT.md L537+), D-02 (welcome layout), D-08 (tagline), D-03 (voice register), D-16-toolbar (start ownership), brand-decisions-v1-followup-display-font.md (Plan 01-12 blocker; this plan ships TODAY with placeholders)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 14:23:56 +02:00
285e46f620 docs(01-13): close — operator UAT ack 2026-05-19 + save-stops debug resolved + SUMMARY landed
Plan 01-13 fully closed. Operator UAT acked "all good" on 2026-05-19;
recovery flow (A7) + restart-after-click (A2) both harness-covered, no
manual verification needed.

What this commit lands:
- 01-13-SUMMARY.md (full spike-pivot-then-implementation narrative; tracks
  all 16 commits across Plan 01-11 spike + Plan 01-13 4-wave execution +
  save-stops debug session; documents 15/15 npm run test:uat GREEN +
  98/98 vitest GREEN + Bug A/B regression-rewind demos verified)
- Save-stops debug record moved to .planning/debug/resolved/ (closure-
  canonical location; prior inline path tracked via git mv)
- STATE.md sync: completed_plans 11→12, percent 95→96, Plan 01-13
  fully-closed narrative + save-stops debug session captured

Phase 1 functional contract: CLOSED via harness PASS.
Remaining Phase 1 gates: Plan 01-10 (welcome tab) + Plan 01-12 (design
integration; pending designer Newsreader-Cyrillic reply).

Phase 2 inherits the harness as its closure-gate template.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 13:46:49 +02:00
9c5ff8b2a7 docs(01-13): wave-4 task-8 — Plan 01-09 closure-via-harness amendment + STATE.md sync
Lands the Wave 4 closure docs:
- 01-09-PLAN.md Amendment 2: harness PASS (npm run test:uat 14/14 GREEN at d793c9e)
  now closes Plan 01-09 functional contract (original Task 5 steps 4, 5, 7-13, 15);
  operator retains only step 1 (build) + step 14 (brand/design ack — Plan 01-13
  Task 9 charter). Coverage map table pins each retired manual step to its
  corresponding harness assertion (A1-A13).
- STATE.md sync: completed_plans 9->11, percent 92->~95, last_updated
  2026-05-19T10:40:00Z; Current Position narrative replaced with Plan 01-13
  landing summary + outstanding Phase 1 gates (Plan 01-13 Task 9 operator
  checkpoint, Plan 01-10 welcome tab, Plan 01-12 design integration awaiting
  designer reply).

Verification (post-edit, docs-only — no src/ touched):
- npm run test:uat: 14/14 GREEN at d793c9e baseline preserved
- npx vitest: 94/94 (the no-test-hooks-in-prod-bundle.test.ts default 5s timeout
  flake is harness-side, not introduced by this commit; re-run with
  --testTimeout=60000 passes)
- git status post-commit: clean

Followup: ROADMAP.md is missing entries for Plans 01-08 through 01-12 (these were
all added mid-phase across multiple sessions and the roadmap was never amended;
the Phase-1 Plans block lines 74-80 stops at 01-07 and the progress table line
238 shows the stale '7/7 Complete' count). Backfilling those entries is a
separate concern — out of scope for Plan 01-13 closure per plan-checker flag #4
(hold the line; do not inject). STATE.md notes the counter > total mismatch for
visibility.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 10:50:13 +02:00
70f4f4136a docs(01-13): create UAT harness plan — Approach B (extension-internal page)
5 waves, 9 tasks. Inherits Plan 01-11 spike-pivot rationale per
01-11-SUMMARY (commit ba5474c). Implements full 14-assertion harness
via Approach B architecture, proven by prototype c647f61.

- Wave 0: clean broken Approach-A artifacts (sw-hooks.ts, SW dynamic
  import, popup-bridge lib, feasibility probes); update Tier-1 grep
  gate to 10-string Approach-B forbidden inventory.
- Wave 1: promote c647f61 prototype (extension-page-harness +
  a6.test.ts) to production paths; A6 stays GREEN.
- Wave 2: rebuild Approach-B driver utilities (launch.ts,
  assertions.ts, harness-page-driver.ts) replacing deleted
  popup-bridge primitives.
- Wave 3 (4 task bundles): wire A1-A13 functional assertions; canonical
  Bug B (A6) + Bug A (A8) RED-on-regression demos mandatory in commit
  bodies.
- Wave 4: append 01-09 Amendment 2; update STATE.md + ROADMAP.md;
  operator brand/design checkpoint.

Open questions resolved: Wave 3 granularity = 4 bundles; tabs
permission gap = workaround retained (Phase 5 hardening); failure
isolation = single browser + bail-on-first; CI plumbing = defer.

Frontmatter validation: valid=true. Plan structure: valid=true,
task_count=9, all tasks have files/action/verify/done.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 14:28:04 +02:00
ba5474c54f docs(01-11): close as spike-pivot — SUMMARY landed, AMENDMENT-A deleted, pivots to 01-13
Closes Plan 01-11 honestly per GSD spike-pivot pattern. Original
Approach A (Puppeteer sw.evaluate per RESEARCH §1+6) empirically
falsified across Wave 3 execution + feasibility research. Approach B
(extension-internal-page harness + offscreen synthetic stream) proven
via c647f61 prototype; full implementation moves to Plan 01-13.

What this commit does:
- ADDS 01-11-SUMMARY.md (spike-then-pivot framing per GSD artifact-
  types.md PLAN→SUMMARY lifecycle; captures retained infrastructure,
  falsified hypotheses, working prototype, bridge to 01-13)
- REVERTS frontmatter amendment block in 01-11-PLAN.md; replaces with
  closed_as/pivoted_in/closure_note pointing at SUMMARY + 01-13
- DELETES 01-11-PLAN-AMENDMENT-A.md (improvised artifact type — not
  recognized in GSD artifact-types.md; content folded into SUMMARY)

Lesson for orchestrator (captured in SUMMARY §Architectural Notes):
when a plan attempts an approach that proves infeasible, the right
move is honest SUMMARY + new plan, NOT in-place rewrite + AMENDMENT
artifact. The project's own pattern (01-08, 01-09, 01-10, 01-11
added mid-phase as new work surfaced) confirms add-new-plan-when-
scope-shifts is the established pattern.

Plan 01-09 closure via harness PASS NOT achieved by 01-11; still
requires operator UAT pending Plan 01-13 landing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 14:02:38 +02:00
565f8fa44c docs(01-11): amendment A — pivot to extension-internal harness page
Architectural pivot triggered by feasibility research prototype
(commit c647f61, A6 PASS 5/5 + Bug-B regression rewind verified).

Two empirical findings invalidate original architecture:
1. MV3 service workers BLOCK dynamic import. await import('test-hooks/
   sw-hooks') in src/background/index.ts silently kills the SW —
   chunk loads, await never resolves, no listeners register. Cited
   Chromium es_modules.md + w3c/webextensions#212.
2. Puppeteer WebWorker.evaluate against MV3 SW only exposes chrome.
   {loadTimes,csi} — not the extension chrome.* API surface.

The Wave 1 (cb1a729) SW-side hooks are fundamentally broken in test
builds (production unaffected — gated by __MOKOSH_UAT__ which is
false in prod). Executor must DELETE the SW-side dynamic import +
sw-hooks.ts entirely; offscreen-side hooks stay (offscreen IS a DOM
document; dynamic import works there).

Replacement (Verdict-A architecture, proven by prototype):
- Extension-internal harness page at chrome-extension://<id>/tests/
  uat/extension-page-harness.html — privileged extension context
  with FULL chrome.* API access
- Puppeteer drives the page via page.goto + page.evaluate
- For SW state: page calls chrome.runtime.sendMessage; SW responds
  via production messaging
- For getDisplayMedia: offscreen-side installFakeDisplayMedia() patches
  navigator.mediaDevices.getDisplayMedia → Canvas captureStream
  synthetic MediaStream

A6 (Bug B regression catch) PROVEN. Industry-standard pattern (MetaMask,
eyeo, Chrome MV3 official testing docs all converge).

Effort remaining: ~7-10h subagent budget (Wave 0 + bonus debug-import
commits keep; Wave 1 hooks rewire 30min; Wave 2 scaffolding 1-2h;
Wave 3 13 more assertions 4-6h; Wave 4 closure 1h).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 12:10:52 +02:00
3df2750c64 docs(01-12): research Plan 01-12 (Design Integration) — 13 areas + BLOCKER
13 research surfaces investigated per Plan 01-12 prompt. Key findings:

- BLOCKER §1: Newsreader has no Cyrillic glyphs (verified via Decision
  Brief's own embedded @font-face subsets + Production Type README).
  Russian display text in Newsreader will silently fall through to
  serif fallback. Recommend §1 R1: add Cyrillic-capable OFL serif (PT
  Serif / EB Garamond / Lora) to --mks-font-display stack.

- §3 + §4: Mark legibility at 16 px is VERIFIED OK. rsvg-convert
  produces 406 / 784 / 1952 B PNGs at 16/48/128 — all clear Chrome
  imageUtil floors. The 2x2 weave holds at 16 px.

- §10: 8 i18n strings extracted verbatim from Brief §02 (decoded via
  Python JSON-decode of the bundler-template script). Recommended
  __MSG_*__ key names + source-file mapping table included.

- §12: D-09 (smoke gating) is NEAR-NO-OP. smoke.sh is a standalone
  bash script; nothing in src/ references it; dist/ carries no smoke
  artifacts. Recommend documenting current state + adding optional
  no-smoke-in-dist regression test.

- §13: tokens.css line 12 Google Fonts @import migration → 8 local
  @font-face rules (Plex variable consolidation collapses the
  estimated 12-18 down to 8).

All tooling verified installed on dev machine: rsvg-convert 2.60.0,
pyftsubset 4.63.0, woff2_compress, inkscape 1.4.4. No npm install
needed for execute-plan; only one-off font source TTF downloads.

7 assumptions logged for planner to surface (A1 default_locale, A2
popup DOM rework, A4 Cyrillic serif fallback are highest-impact).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 21:23:27 +02:00
66e6c4af74 docs(01-11): create Puppeteer UAT harness plan (14 assertions, 9 tasks)
Retires operator-as-assertion-library role from Plan 01-09 Task 5. Bug A
(notification icon API rejection) and Bug B (state-machine routing of
user-stopped-sharing) both escaped vitest unit coverage and cost ~4-6h of
operator UAT cycles in Phase 1. Plan 01-11 ships a Puppeteer-driven Node
harness with CDP attach to SW + offscreen contexts; the 14 assertions cover
the Plan 01-08/01-09 functional contract end-to-end.

Locked from research (RESEARCH §1-§11):
- Puppeteer 25.0.2 + tsx + node:assert/strict (no vitest browser mode)
- Two-bundle separation via vite.test.config.ts (mode 'test' + dist-test/)
- Hook gating: import.meta.env.MODE === 'test' + dynamic import (Vite
  tree-shakes from production)
- Bug B trigger: track.dispatchEvent(new Event('ended')) — NOT track.stop()
  (W3C spec + empirical probe7 — track.stop does NOT fire 'ended')
- Tier-1 grep gate (tests/background/no-test-hooks-in-prod-bundle.test.ts)
  enforces zero __mokoshTest in production dist/
- Single browser, serial assertions, bail-on-first-failure (open question 4)

Wave structure (4 waves):
- Wave 0 (Task 1): puppeteer+tsx install, vite.test.config, build:test +
  test:uat scripts, Tier-1 grep gate committed GREEN.
- Wave 1 (Task 2): gated SW + offscreen hooks at src/test-hooks/; production
  bundle remains hook-free.
- Wave 2 (Task 3): harness scaffolding — tests/uat/lib/* + harness.test.ts
  with assertion 0 wired GREEN + assertions 1-13 stubbed RED.
- Wave 3 (Tasks 4-7): wire 13 assertions in 4 logically-grouped bundles
  (1-4 toolbar/displaySurface; 5-7 SAVE+BugB+ERROR; 8-10 BugA+icons+manifest;
  11-13 buffer continuity + ffprobe + zip).
- Wave 4 (Tasks 8-9): amend Plan 01-09 Task 5 to redirect functional steps
  to npm run test:uat; operator confirms brand/design.

Bug A + Bug B each have RED-on-regression canonical demos required in the
respective task's commit body — proves the harness CAN catch the regression,
not just passes under current conditions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 18:15:44 +02:00
969afbac89 docs(01-11): research Puppeteer UAT harness — empirical probes verify 10/10 unknowns
Probes 1-11 against local Chrome 148.0.7778.167 + Puppeteer 25.0.2:
- triggerExtensionAction works; popup-vs-onClicked contract confirmed
- --headless=new supports MV3 + getDisplayMedia (Xvfb not required)
- offscreen page reachable via background_page target type + .asPage()
- BLOCKER: track.stop() does NOT fire 'ended' per W3C spec — Bug B harness
  must use track.dispatchEvent(new Event('ended')) instead

13-assertion implementation table + 7 pitfalls + 2-bundle build design.
Wave 0 grep gate enforces tree-shake of __mokoshTest from production.
2026-05-17 17:42:40 +02:00
9d0313acd2 docs(01-09): amend Task 5 step 11 + success criteria #3 post-Bug B
Original step 11 expected stop-sharing → ERROR badge + recovery
notification; under Bug B fix (b9eeeeb), user-stopped-sharing is
correctly routed → IDLE (badge OFF, no recovery notification) because
it's a deliberate lifecycle event, not an error.

Amendments:
- Step 11: badge OFF (not ERROR); no recovery notification; popup cleared
- Step 12: operator clicks toolbar directly (no notification to click)
- Step 14: failure-mode list updated to match new expectations
- Step 15 added: ERROR state coverage moved to separate genuine-error step
- Success criteria #3: split user-stopped-sharing (→ OFF) from genuine
  errors (→ ERROR + recovery notification, preserved fallback)

See .planning/debug/resolved/01-09-recovery-flow.md for the debug record.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 16:56:07 +02:00
ed82fd6051 wip: phase-01 paused mid-Plan-01-09; Bug B fix + icon placeholder commit pending 2026-05-17 16:05:17 +02:00
c711d7e74e docs(01-09): SUMMARY — Tasks 1-4 autonomous complete; Task 5 awaiting operator
Plan 01-09 SUMMARY:
  • 17 new tests landed GREEN (4 displaySurface + 5 toolbar-action
    including W-02 popup-idle-race + 4 badge + 4 notification).
  • Baseline 64 + 17 new = 81 GREEN. Full suite 18 files / 81 tests.
  • Tier-1 SW-bundle-import gate (Layer 1 + 2) remains GREEN.
  • tsc clean; npm run build clean; dist/manifest.json carries
    notifications permission.
  • 4 deviation rules auto-fixed inline (navigator getter helper,
    jsdom-free W-02 Test E refactor, cursor type-widening cast,
    chrome.* listener try/catch for pre-existing test compatibility).
  • Task 5 (operator empirical checkpoint) deferred per plan.
2026-05-17 15:49:24 +02:00
aabbd0c05c docs(01-08): write SUMMARY — Tasks 1-4 autonomous complete; Task 5 awaiting operator
- D-14-remux WebM remux pipeline (ts-ebml parse + webm-muxer write)
  replaces D-13 file-concat; single-EBML-headered output empirically
  spans 29.954 s of 912 VP9 frames (matching the per-segment sum
  301+300+311 with zero loss).
- All 5 RED unit tests in tests/background/webm-remux.test.ts flipped
  GREEN; 2 SW-compat tests in webm-remux-deps.test.ts GREEN; 53 baseline
  tests preserved. tsc exit 0. npm run build exit 0.
- mergeVideoSegments deleted from src/background/index.ts; only a
  retirement comment naming Plan 01-08 D-14-remux remains.
  EmptyVideoBufferError surface preserved (W-01 free-text rename only).
- CONTEXT.md amendment provenance verified intact (B-01 grep checks all
  pass — no file mutation by this plan; the orchestrator landed the
  amendment at plan-creation time in commit 2e499d7).
- 2 deviations documented (Rule 1: tsc-required codec field in
  EncodedVideoChunkMetadata; Rule 3: stale comment cleanup in
  decodeBufferSegments). No scope creep.
- Self-check: all 6 files + 4 task commits verified present.
- Task 5 = checkpoint:human-verify (operator regenerates
  tests/fixtures/last_30sec.webm via ./smoke.sh, confirms Chrome + mpv
  playback ~30 s, flips the 2 webm-playback duration tests GREEN).
2026-05-17 09:29:26 +02:00
2e499d7387 docs(01): add Plans 01-08 / 01-09 / 01-10 (amended Phase 1 charter)
Plans cover the post-D-13 architecture and the auto-start UX charter
expansion that landed during 2026-05-16 UAT:

- Plan 01-08 — WebM remux via ts-ebml@3.0.2 + webm-muxer@5.1.4. Replaces
  the broken file-concat in mergeVideoSegments with a real single-EBML
  remux. Drives the 2 RED tests in tests/offscreen/webm-playback.test.ts
  to GREEN. Regenerates the canonical fixture against the remuxer.
  5 tasks (4 TDD + 1 operator empirical checkpoint), wave 1.

- Plan 01-09 — Whole-desktop constraint (displaySurface:'monitor',
  cursor:'always') + post-grant validation, chrome.action.onClicked
  direct toolbar invocation, chrome.action badge state machine
  (REC/OFF/ERROR), chrome.runtime.onStartup notification + recovery
  notification on onUserStoppedSharing, popup scoped to SAVE-only.
  17 new test assertions across 4 test files. smoke.sh updated to
  auto-select an entire screen. 5 tasks (4 TDD + 1 operator empirical
  checkpoint), wave 2 (depends on 01-08).

- Plan 01-10 — chrome.runtime.onInstalled welcome tab on first install
  via chrome.storage.local guard; vanilla welcome.html/ts/css bundle
  with single "Начать запись" button consuming install-time activation.
  Uses centralized Logger pattern. 4 tasks (3 TDD + 1 operator empirical
  checkpoint), wave 3 (depends on 01-09).

CONTEXT.md amendment block appended with 4 disambiguated decisions:
- D-14-remux: WebM remux supersedes D-13 file-concat
- D-15-display-surface: whole-desktop + cursor visibility lifted from
  Phase 5 deferral
- D-16-toolbar: toolbar onClicked + popup SAVE-only + badge state
  machine + onStartup/recovery notifications
- D-17-onboarding: welcome tab on first install (distinct from
  D-17-port-lifecycle from Option C)
The earlier D-17 port-lifecycle heading also renamed to hyphenated
form for cross-ref consistency.

Plan-check loop: 3 iterations (initial + 2 revisions). Iteration 1
surfaced 11 findings (2 BLOCKER + 6 WARNING + 3 INFO); all addressed
via revision iter 1 with checker-recommended fixes. Iteration 2
surfaced 3 derivative regressions (literal-string grep anchors from
the iter-1 fixes did not match live CONTEXT.md); all addressed in iter
2 with empirically-validated literals. Iteration 3 PASSED clean.

Validation: gsd-sdk frontmatter.validate + verify.plan-structure both
return valid=True for all 3 plans. Plan 01-08 Task 4 verify-chain
grep tested end-to-end against live CONTEXT.md (exit 0).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 09:19:22 +02:00
f1026954fc test(01): UAT BLOCKER #2 — D-13 multi-EBML-concat plays only ~9 s; both committed fixture and UAT output exhibit same broken playback. Phase 1 architecture finding. 2026-05-16 18:57:48 +02:00
f0871c0237 docs(option-c): archive empty-archive-port-race + amend CONTEXT.md D-17 port lifecycle
Two doc updates closing the debug session per the resolved pattern this
phase has established (cf. resolved/d12-blob-port-transfer-fails.md and
resolved/webm-playback-freeze.md):

1. **Move debug session to resolved/** with the Resolution section
   filled in (root_cause, fix, verification, files_changed). Status
   flipped tdd_red_confirmed -> resolved. Original investigation
   notes + bisect results + Option C strategy spec all preserved
   in-place — the file is the full provenance trail.

2. **Amend 01-CONTEXT.md D-17** with the new port lifecycle commitments.
   Append-only (D-17 itself untouched) per the doc cascade rule
   established earlier this phase ("amendments append, do not replace,
   to preserve SPEC provenance"). The amendment narrates:
   - What was Claude's-discretion at Phase 1 plan time has been
     specified by Option C.
   - The 290 s pre-emptive setTimeout reconnect (Pitfall 4) is RETIRED.
   - The architectural commitments added: PING/PONG health probe,
     request-id'd REQUEST_BUFFER/BUFFER, SW retry on port replacement,
     outer 10 s hard-timeout, operator-visible EmptyVideoBufferError
     surface.
   - The 4 pinning contracts added (port-health-probe,
     request-id-protocol, port-lifecycle-continuous, plus the
     refactored port-reconnect-race).

Suite remains 11 files / 53 tests, all GREEN. Quality gates intact.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 15:40:02 +02:00
13094d4248 test(01): UAT partial — 2 pass, 1 BLOCKER (silent empty-video archive + port-reconnect race), 1 blocked 2026-05-16 13:57:24 +02:00