0712c245a11fd42fd0ebe77d70491dedb2712d09
298 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| 0712c245a1 |
feat(04-05): A34 host-side + orchestrator — fetch+XHR network_error empirical (ROADMAP SC #2 GREEN)
- Append driveA34 host-side: JSZip-parse logs/events.json + filter network_error entries by '404-fetch-a34' / '404-xhr-a34' target marker; assert >=1 of each + meta.status === 404 - readMetaStatus helper narrows UserEvent.meta.status (typed Record<string,unknown>) to number without an unchecked any cast - 3-site orchestrator wiring in harness.test.ts: import binding, driveA34Wrapped (downloadsDir closure), drivers-array push entry - UAT harness 34 -> 35; skip-mode (SKIP_LONG_UAT=1) 35/35 GREEN - A34 empirical: fetch entry target carries the real URL (https://example.com/404-fetch-a34-<stamp>), NOT '[object Request]' — Plan 04-01 P1 #11 fix validated end-to-end at the SAVE->archive layer; XHR entry confirms the distinct prototype-wrapper path; both meta.status === 404 (ROADMAP SC #2 closed) - vitest baseline 184/184 GREEN preserved (no unit tests this plan) - FORBIDDEN_HOOK_STRINGS unchanged at 12 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
|||
| a20372a8b8 |
feat(04-05): A34 page-side — cs-injection-world fetch + XHR 404 injection
- Append assertA34 after assertA31 — cs-injection-world skeleton (verbatim from assertA30/A31; ROADMAP SC #2 empirical) - chrome.scripting.executeScript ISOLATED injects TWO 404 triggers into the content-script realm: fetch(404) + XMLHttpRequest(404) - fetch trigger validates Plan 04-01 P1 #11 (Request-narrow URL extraction) end-to-end in a real Chrome page context - XHR trigger covers the distinct XMLHttpRequest.prototype wrapper path that A30 did not exercise - Date.now() uniqueness stamp on both probe URLs (T-04-05-02) - assertA34 registered in Window interface + __mokoshHarness literal - Tier-1 FORBIDDEN_HOOK_STRINGS unchanged at 12 (rides production window.fetch + XMLHttpRequest.prototype + chrome.scripting/tabs) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
|||
| 125269dcc5 |
docs(04-08): complete harden-clean-up-optional plan 04-08 — STATE.md advance to 6/7
State counter advance after Plan 04-08 closure: - progress.completed_plans: 27 -> 28 - Current Plan position: 5 -> 6 (Plan 04-05 fetch+XHR queued next) - last_updated timestamp + last_activity bumped to 2026-05-22 Note: the human-readable "Plan: 6 of 7" line in Current Position reflects the original Phase 4 plan-count of 7; the ROADMAP-side phase tracker now shows 5/8 (Plan 04-08 inserted Wave 5.5 per debug session-2 verdict authorization). This is a known cosmetic gap in the SDK's state.advance-plan handler; the frontmatter total_plans=31 / completed_plans=28 are correct. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| 4d6c00526e |
feat(04-08): A33 SW state persistence harness assertion — methodology reframe (34/34 GREEN; ROADMAP SC #1 CLOSED)
Task 2 of Plan 04-08 (revive A33 under valid methodology + close ROADMAP SC #1): - Append driveA33(page, browser, extensionId, downloadsDir) at tests/uat/lib/harness-page-driver.ts:2516-2697 per Plan 04-04 Pattern 4 verbatim - 3 checks: A33.1 SAVE_ARCHIVE ack success after 5-min idle + SW kill; A33.2 video size > 0; A33.3 video size > 100 KB sanity floor - Reuses stopServiceWorker helper (Plan 04-04 commit |
|||
| 81d9935b65 |
feat(04-08): video-file MediaStream + sync-install/lazy-first-frame + explicit WAR — methodology reframe per debug session-2 + iter-2 BLOCKER fixes
Task 1 of Plan 04-08 (methodology reframe of ROADMAP SC #1): - Bundle 1.9 MB VP9 WebM fixture at tests/uat/fixtures/synthetic-display-source.webm (copy of internal Plan 01-07 fixture; CC0-equivalent project-owned) - Add globals.d.ts ambient `*.webm?url` module decl (mirrors Plan 01-10 `*.svg?url`) - Add manifest.json web_accessible_resources entry for `assets/*.webm` (iter-2 BLOCKER 1 — pre-decided to avoid executor improvisation; inert in production where dist/ has zero *.webm) - Rewrite installFakeDisplayMedia() at src/test-hooks/offscreen-hooks.ts: * Replace canvas.captureStream(30) with HTMLVideoElement.captureStream(30) — bypasses Chrome bug 653548 invisible-canvas throttling (debug session-2 root cause) * Function signature remains SYNCHRONOUS (`: void`; iter-2 BLOCKER 2 — eager-install contract preserved at lines 528-537) * Video element creation + DOM append + monkey-patch assignment execute synchronously * canplay wait + .play() deferred INTO fakeGetDisplayMedia closure (lazy first-frame pattern) * fakeVideoReadyPromise kicked off at install time so first call observes resolved Promise * WARNING 1 (autoplay reject): explicit error class identifier 'autoplay-blocked or codec-unsupported in headless context' * displaySurface monkey-patch preserved verbatim * A23 lastGetDisplayMediaConstraints capture preserved * uninstallFakeDisplayMedia teardown adapted for videoEl (pauses + removes + nulls) * All 6 bridge ops UNCHANGED in their sync return-false form - Add Tier-2 production-bundle filename-leak gate at tests/background/no-test-hooks-in-prod-bundle.test.ts (iter-2 WARNING 5 — synthetic-display-source string must be 0 hits in dist/) Verification: - npx tsc --noEmit: exit 0 - npm run build: dist/ produced; 0 *.webm files; 0 synthetic-display-source hits - npm run build:test: dist-test/assets/synthetic-display-source-mbtR1t3u.webm emitted (1.9 MB; Vite ?url asset) - Code-only grep (comment-filtered) on offscreen-hooks.ts: 0 canvas refs; 15 video refs - installFakeDisplayMedia signature unchanged: `: void` 2x; `: Promise` 0x; `await installFakeDisplayMedia` 0x - Architectural invariant unchanged: `let segments: Blob[] = []` at recorder.ts:91 (1 hit; grep gate enforces) - Tier-1 FORBIDDEN_HOOK_STRINGS unchanged at 12 entries - Tier-2 vitest gate PASSES: 14/14 GREEN under SKIP_BUILD=1 (12 Tier-1 + 1 build verify + 1 Tier-2) Per iter-3 checker advisory 1: the wrong-display-surface throw lives at recorder.ts:313-321 (not line 294 as plan text states; off by ~25 lines but unambiguous). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| dd8a56453c |
docs(04-08): plan-checker iter-3 — PASSED-WITH-RESIDUAL on polish revision
Validates iter-3 polish revision of Plan 04-08 (commit
|
|||
| 17e55ddbb9 |
docs(04-08): polish per iter-2 advisories — symbol mismatch + display-surface mode lock-in + cosmetic clarifications
iter-3 polish pass on Plan 04-08 per checker iter-2 verdict PASSED
(commit
|
|||
| 9c334b77e8 |
docs(04-08): plan-checker iter-2 — PASSED (0 BLOCKER + 1 WARNING + 4 advisory)
Verifies iter-2 plan revision at |
|||
| 1f2eb2e818 |
fix(04-08): revise plan per iter-1 BLOCKER fixes — bundling strategy + sync monkey-patch + async closure
iter-2 revision of Plan 04-08 (video-file MediaStream methodology reframe)
addressing the 2 BLOCKERs + 5 WARNINGs + 3 advisories from plan-checker
iter-1 (commit
|
|||
| 051813ee6e |
docs(04-08): plan-checker iter-1 — ITERATE-NEEDED (2 BLOCKER + 5 WARNING + 3 advisory)
Plan 04-08's core thesis (HTMLVideoElement.captureStream bypasses canvas throttling per debug session-2 verdict) IS the correct path to close ROADMAP SC #1. But two blocking issues prevent reliable delivery: BLOCKER 1: Vite `?url` asset-emission analog mis-applied — mokosh-mark.svg is 877 bytes (inlined as data:image/svg+xml URI) so the Plan 01-10 "?url + crxjs auto-WAR" precedent is NOT a direct analog for the 1.9 MB WebM which will emit as a separate dist-test/assets/<hash>.webm file. WAR auto-generation for extracted assets is unverified in this codebase. Remediation: probe-then-decide OR Blob URL from ?raw ArrayBuffer. BLOCKER 2: installFakeDisplayMedia()'s eager-install-at-module-load contract is silently broken by the proposed async conversion. The race window opens because recorder.ts:48 resolves before the async install completes; recorder.startRecording → real getDisplayMedia → headless hang. Remediation: keep sync monkey-patch; defer the canplay wait into fakeGetDisplayMedia closure (lazy first-frame). WARNINGS surface unverified headless autoplay reliability, displaySurface monkey-patch portability to HTMLVideoElement tracks, spike probe-value gates not surfaced as automated verify, and ROADMAP.md flip without grep enforcement. Architectural alignment confirmed (segments: Blob[] preserved; IDB correctly rejected; D-P4-01 honored). iter-2 is a methodology-tightening pass, not re-architecture. Estimated ~150-300 lines of plan edits. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| 504d9dccf3 |
docs(04-08): create plan — video-file MediaStream methodology reframe + A33 revival
Inserts Plan 04-08 between Plans 04-06 and 04-07 (Wave 5.5) per debug session-2 verdict (REFUTED-architecture; canvas-captureStream issue). Scope: replace canvas.captureStream(30) source in installFakeDisplayMedia() at src/test-hooks/offscreen-hooks.ts:139-264 with HTMLVideoElement.captureStream backed by a bundled VP9 WebM at tests/uat/fixtures/synthetic-display-source.webm. Bundled via Vite ?url import per Plan 01-10 mokosh-mark precedent. Revives the A33 harness assertion (Plan 04-04 Pattern 4 verbatim) under valid methodology; stopServiceWorker helper from Plan 04-04 reused. Closes ROADMAP SC #1 within v1. Architecture (offscreen-RAM segments: Blob[]) UNCHANGED per debug session-2 segment-count probe evidence. 2 tasks atomic: (1) bundle fixture + rewrite installFakeDisplayMedia + ambient *.webm?url decl; (2) re-run spike + land driveA33 + orchestrator wiring + SKIP_LONG_UAT env-gate + SUMMARY + STATE/ROADMAP markers. UAT 33 -> 34 GREEN target. FORBIDDEN_HOOK_STRINGS unchanged at 12. Pre-checkpoint bundle gates 6/6 PASS preserved. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| c1501e7a81 |
docs(04-04): amend SUMMARY post-debug session-2 — REFUTED-architecture verdict
Session-2 (/gsd-debug continuation) empirically refuted the SUMMARY's original 'architecture broken → IndexedDB plan-fix needed' interpretation: - Pre-kill probe: segments.length=3 (segments accumulated correctly during 5-min idle) - Post-kill probe: segments.length=3 (offscreen-RAM survives SW kill structurally) - Step C (no worker.close, just 5-min idle): identical 8505 bytes (CDP not the cause) - Remux logs: each segment trackInfo=320x180 but 0 frames per segment - 7/7 spike runs deterministic at 8505 bytes (canvas-captureStream throttling) Root cause: installFakeDisplayMedia() at src/test-hooks/offscreen-hooks.ts:139-264 mints canvas.captureStream(30) on hidden -9999px-offset canvas; headless-Chromium throttles MediaRecorder on invisible-canvas (Chrome bug 653548). Segments exist but contain zero VP9 frames over 5-min idle. Routing: Plan 04-08 inserted (user-authorized ceremony 2026-05-22) — video-file MediaStream methodology reframe (Option 2 from session-2). IndexedDB plan-fix recommendation REJECTED — would not close SC#1 because frames are the problem, not segments. stopServiceWorker helper + spike script + launch.ts:225 race-tolerant fix all remain valid persisting artifacts for Plan 04-08. |
|||
| 4ea1bbb7a8 |
docs(debug): SC#1 sw-offscreen-persistence investigation session 2 — REFUTED-architecture (canvas-captureStream issue)
Session-2 (continuation of
|
|||
| 9ac580869d |
fix(debug): race-tolerant offscreen target attach in UAT launch
Plan-04-04 debug session-2 root cause: the offscreen-console capture
in tests/uat/lib/launch.ts:registerOffscreenConsoleAttach matched zero
offscreen targets across 4 spike runs, creating a critical observability
gap that prevented disambiguation of Plan 04-04 Wave 0 spike failure
mode.
Empirical investigation (tests/uat/spike-diagnose-offscreen-target.ts,
NEW): when chrome.offscreen.createDocument fires, Puppeteer's
`targetcreated` event fires with `type='other'` and `url=''` BEFORE the
CDP target metadata stabilizes. The previous filter (whether
`background_page` or `page`) never matched at event time. By the time
the metadata stabilizes (visible via `browser.targets()`), the
target's type is `'background_page'` (not `'page'` — MV2's
background_page type IS still used by Chrome's CDP for invisible
extension documents, despite MV3 abolishing classic background pages).
Fix:
- Match the offscreen target by URL pattern (load-bearing criterion;
type field is intentionally unchecked because it's unreliable at
targetcreated time).
- Bind to BOTH `targetcreated` AND `targetchanged` events (the latter
fires when the URL stabilizes after navigation).
- Add a `browser.targets()` enumeration race-free safety net for
cases where the offscreen target exists at registration time.
Verification: tests/uat/spike-diagnose-offscreen-target.ts now emits
`(launch: offscreen console attached — url=chrome-extension://.../src/offscreen/index.html)`
followed by `[off:log] [OS:Recorder] Recording started ...` (zero such
lines in any prior spike run).
Test-infra correctness fix; ZERO production source changes. FORBIDDEN_HOOK_STRINGS
inventory unchanged at 12 entries. No new test-only `__MOKOSH_UAT__` symbols.
References:
- .planning/debug/sw-offscreen-persistence-investigation-session-2.md
(session-2 debug note documenting empirical root cause)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| d614462694 |
docs(debug): SC#1 sw-offscreen-persistence investigation — INCONCLUSIVE
Pre-commit-ceremony verification of Plan 04-04 Wave 0 SPIKE finding
(videoSize=8505 bytes after 5-min SW idle + Puppeteer worker.close()).
Reproducibility: 4/4 runs (incl. prior
|
|||
| e8a2e7696d |
docs(04-04): complete harden-clean-up-optional plan 04-04 — SW persistence spike FAILED, plan-fix ceremony required
Plan 04-04 (spike→auto) closes at Task 1 (Wave 0 SPIKE) with an empirical
NO on the RESEARCH Q2 MEDIUM-confidence hypothesis A3 (offscreen-document
independent lifecycle anchored by active MediaRecorder). Task 2 (Wave 1
A33 verification-only harness assertion) BLOCKED by the plan's explicit
gating condition (videoSize > 100_000); ROADMAP SC #1 remains OPEN.
Spike empirical numbers (one HEADLESS=1 run; 308.7s wall-clock; full log
at /tmp/04-04-spike.log; reproducible via the committed spike script):
- assertA2 prime: PASSED (REC state established)
- 5-min wall-clock idle: elapsed cleanly
- stopServiceWorker CDP: succeeded (worker.close() returned)
- SAVE_ARCHIVE ack: {success: true} (event-driven SW respawn worked)
- video/last_30sec.webm: 8505 bytes (sanity floor 100 KB; healthy 1-3 MB)
- ffprobe on extracted: 'End of file' + 'Duplicate element' (no clusters)
- rrweb/session.json: [] (empty)
- logs/events.json: [] (empty)
- meta.urls: chrome-extension://* only (real-page URLs LOST)
Conclusion: src/offscreen/recorder.ts:91 `let segments: Blob[] = []` RAM-
only architecture does NOT survive 5-min SW idle + Puppeteer CDP worker.
close(). Architectural change required to close ROADMAP SC #1 (canonical
recommendation per 04-RESEARCH.md Q2 sub-question b Option C: IndexedDB
persistence in offscreen — Blobs serialize cleanly via structured-clone;
per-segment write ~3 MB; ~3 writes per 30s window). Per saved memory
`feedback-gsd-ceremony-for-fixes.md` the architectural fix routes through
/gsd-plan-phase rewrite OR /gsd-debug ceremony — NOT improvised inline
inside Plan 04-04.
Task 1 persisting artifacts (committed at
|
|||
| 3726eee39f |
feat(04-04): Wave 0 spike — stopServiceWorker helper + 5-min SW idle empirical result
SPIKE OUTCOME: FAILED (offscreen DIED across 5-min SW idle + worker.close())
Per Plan 04-04 spike-first contract, Wave 0 empirically investigated whether
the offscreen document's RAM-only `segments: Blob[] = []` at
src/offscreen/recorder.ts:91 survives a 5-min SW idle followed by Puppeteer
CDP-driven `worker.close()`. RESEARCH Q2 hypothesis (MEDIUM confidence): yes,
the offscreen has its own lifecycle anchored by active MediaRecorder. Spike
result REFUTES that hypothesis.
Empirical measurement (HEADLESS=1; one full run; reproducible via the
committed spike script):
- assertA2 priming: PASSED (badge=REC; offscreen + MediaRecorder live)
- 5-min idle: elapsed cleanly (308.7s total wall-clock)
- stopServiceWorker: succeeded (worker.close() returned)
- SAVE_ARCHIVE ack: {success: true} (SW respawned + processed message)
- video/last_30sec.webm size: 8505 bytes (well below 100 KB floor)
- meta.urls: only chrome-extension://* origins; real-page URLs LOST
- rrweb/session.json: []
- logs/events.json: []
- ffprobe on extracted webm: 'End of file' + 'Duplicate element' errors
(corrupt/truncated; not a valid 30s segment cluster sequence)
Interpretation: offscreen-document lifecycle is NOT independent of the SW
under Puppeteer CDP-driven worker.close() conditions. The 8505 bytes are
likely stale/partial header bytes from a re-initialized empty offscreen
context after SW respawn, not a surviving 30s buffer. The plan's Task 2
GATING CONDITION (videoSize > 100_000) is NOT satisfied; Task 2 is BLOCKED.
Per saved memory `feedback-gsd-ceremony-for-fixes.md`: architectural changes
(moving segments from offscreen RAM to IndexedDB per RESEARCH Q2 sub-question
b Option C) MUST route through proper plan-fix ceremony, NOT improvised
inline inside Plan 04-04. Plan 04-04 SUMMARY flags the failure mode + cites
exact remediation path. ROADMAP SC #1 remains OPEN pending the persistence-
layer plan-fix.
Task 1 persisting artifacts (this commit):
- tests/uat/lib/harness-page-driver.ts:
+ Browser type import (puppeteer)
+ stopServiceWorker(browser, extensionId) helper (verbatim from Chrome
devrel canonical pattern — Puppeteer >=22.1.0; project pin ^25 OK)
+ findLatestZip exported (was module-internal) so the spike script can
reuse the canonical mtime-sort selection logic without duplication
- tests/uat/spike-a33-sw-persistence.ts (NEW):
+ One-shot empirical investigation script; reusable for future SW-
lifecycle regression testing (e.g., verifying the eventual IndexedDB
persistence layer actually closes ROADMAP SC #1)
+ Step 1 reuses __mokoshHarness.assertA2 (canonical fresh-recording
prime; not the non-existent dispatchSaveArchive that REVISION iter-2
explicitly forbids)
+ Step 5 dispatches SAVE_ARCHIVE via chrome.runtime.sendMessage inline
from harness-page realm (Option B per plan-checker BLOCKER 2;
matches A5/A11/A12/A13/A26/A28/A29/A30/A31 pattern)
Verification (Task 1 acceptance criteria):
- npx tsc --noEmit: exits 0
- HEADLESS=1 tsx tests/uat/spike-a33-sw-persistence.ts: ran to completion
(no Puppeteer throw); SPIKE RESULT line emitted with explicit
videoSize=8505 bytes; SAVE_ARCHIVE ack received
- grep -c 'dispatchSaveArchive' tests/uat/spike-a33-sw-persistence.ts: 0
- grep -c "type: 'SAVE_ARCHIVE'" tests/uat/spike-a33-sw-persistence.ts: 1
- Total spike wall-clock: 308.7s (~5min idle + ~8s orchestration)
References:
- Plan 04-04 PLAN.md spike contract (lines 64-72)
- 04-RESEARCH.md Q2 sub-question (b) — Chrome MV3 offscreen lifecycle
- https://developer.chrome.com/docs/extensions/how-to/test/test-serviceworker-termination-with-puppeteer
- Saved memory: feedback-gsd-ceremony-for-fixes.md (no inline architectural
fixes; route through plan-fix ceremony)
|
|||
| 303644f8cc |
docs(04-03): complete harden-clean-up-optional plan 04-03 — A29 flake fix
A29 (rrweb DOM verification) rewritten in-place via the canonical cs- injection-world pattern + strict-sentinel filter. Closes ~2/3 flake documented in Plans 03-02 + 03-03 SUMMARYs (A29 was "passing" by reading iana.org leftover DOM events from A27/A28's still-open probe tabs; a real rrweb regression at src/content/index.ts:284 would have been masked). Plan 04-03 task commits (atomic; sequential foreground mode): - |
|||
| b341a712c0 |
feat(04-03): A29 host-side strict-sentinel filter + 5/5 PASS stress test
Replace the loose-EventType grep with a strict-sentinel filter pipeline per RESEARCH Q3 Code Example Pattern 3: - Import IncrementalSource from @rrweb/types (new binding alongside the existing EventType import) - Filter events for (e.type === EventType.IncrementalSnapshot && e.data?.source === IncrementalSource.Mutation) - Descend into each filtered event's data.adds[*].node.textContent and search for the page-side-injected 'a29-mutation-sentinel' string - A29.2: assert sentinelEvents.length >= 1 — proves the captured mutation came from OUR injection, not from iana.org leftovers Defense-in-depth preserved: - A29.3: rrweb emitted at least one Meta event (renumbered) - A29.4: rrweb emitted at least one FullSnapshot (renumbered) The previous A29.5 (loose IncrementalSnapshot >=1) is subsumed by the A29.2 strict-sentinel check (which requires IncrementalSnapshot AND Mutation source AND injected sentinel — strictly stronger). Empirical verification (all 33/33 GREEN preserved, A29 flake closed): - npx tsc --noEmit → 0 - npm test → 183/183 GREEN preserved (Plan 04-02 baseline) - npm run test:uat → 33/33 GREEN × 5 consecutive runs - A29 mutationEvents=1 + sentinelEvents=1 in ALL 5 runs (no flake) A29 historical flake rate of ~2/3 (documented Plan 03-02 + 03-03 SUMMARYs) is closed end-to-end: the iana.org leftover DOM mutations no longer satisfy A29 because the strict-sentinel filter requires the EXACT string 'a29-mutation-sentinel' that only the page-side chrome.scripting.executeScript injection produces. Pre-checkpoint bundle gates verified (per feedback-pre-checkpoint- bundle-gates.md): - Gate 1: Tier-1 FORBIDDEN_HOOK_STRINGS — 13/13 sub-tests PASS, count unchanged at 12 - Gate 2: SW CSP-safety — new Function=0, eval=0 (Plan 04-02 baseline) - Gate 3+4: Buffer / window / document counts unchanged from Plan 04-02 (Plan 04-03 modifies tests/ only) - Gate 5: manifest validates clean against locked DEC-011 Amendment 1 |
|||
| 73eb9b654c |
feat(04-03): A29 page-side rewrite — cs-injection-world + sentinel
Replace harness-page-mutation approach with verbatim port of the canonical cs-injection-world pattern from Plan 03-02 (assertA30) + Plan 03-03 (assertA31): - chrome.tabs.create(https://example.com/, active:true) opens probe tab where content script + rrweb's record() attach normally (chrome-extension:// is NOT covered by <all_urls> per Chrome match-pattern spec; was the root flake cause) - 1.5s tab-attach + 11s segment-settle waits (canonical A27/A30/A31) - chrome.scripting.executeScript world: 'ISOLATED' injects a sentinel- bearing <div> (textContent='a29-mutation-sentinel') into document.body — rrweb's MutationObserver lives in the same ISOLATED world so the IncrementalSnapshot's data.adds[*].node.textContent will carry the sentinel - 500ms MutationObserver-enqueue settle - SAVE_ARCHIVE while probe tab is active (SW harvests rrweb/session.json from there) - try/finally chrome.tabs.remove with silent-ignore (T-02-04-04 parity) A29 constants block extended: A29_TAB_NAVIGATION_WAIT_MS, A29_PROBE_TAB_URL, A29_MUTATION_SENTINEL, A29_PROBE_DIV_ID. This closes the documented ~2/3 success-rate flake from Plans 03-02 + 03-03 where A29 "passed" by reading iana.org leftover DOM mutations from A27/A28's probe tabs — a real rrweb regression at src/content/index.ts:284 would have been masked because iana.org's home page emits plenty of mutations during normal rendering. Tier-1 FORBIDDEN_HOOK_STRINGS unchanged at 12; assertA30 + assertA31 untouched; __mokoshHarness wiring unchanged. Host-side driveA29 strict-sentinel filter lands in Task 2. Verify: - npx tsc --noEmit → 0 - npm run build:test → 0 - grep -c 'A29_MUTATION_SENTINEL' tests/uat/extension-page-harness.ts → 3 - grep -nE "world: 'ISOLATED'" tests/uat/extension-page-harness.ts → 3 call sites (A29 + A30 + A31) — ISOLATED parity per RESEARCH Pitfall 5 |
|||
| 6a1fc32826 |
docs(04-02): complete harden-clean-up-optional plan 04-02 — build hygiene
Plan 04-02 closes three independent build-hygiene fixes consolidated into
one plan because they share the build-gate-grep test-scaffold pattern:
1. **setimmediate polyfill replacement** — layered 4-mechanism CSP-hardening
eliminates the `new Function` literal from the SW chunk (grep -c flips
1→0 across all three SW chunks). Runtime guard + nodePolyfills exclude
+ resolve.alias + Rollup post-transform plugin. Option α (force JSZip
unbundled lib/index.js) attempted + reverted because it broke
readable-stream-browser propagation causing UAT A30+ regressions;
Option β (post-transform plugin) preserves JSZip's pre-bundled
distribution verbatim while excising the offending literal.
2. **ROADMAP SC #3** (generate-icons ESM/CJS) — `git mv generate-icons.js
generate-icons.cjs` resolves the `require('fs')` under
`package.json type: module` via Node's `.cjs`-as-CJS rule.
3. **ROADMAP SC #4** (dead-code grep) — `tests/build/dead-code-grep.test.ts`
regression-pins `permissions.request` absence in `src/`.
Plus closure of Plan 01-12 Wave 7's setimmediate deferred-items entry.
Task commits:
-
|
|||
| f251297256 |
feat(04-02): Wave 1 — setimmediate polyfill replaced + generate-icons.cjs + deferred-items closure
Coherent 5-edit Wave 1 GREEN landing per Plan 04-02 Task 2; RED gate from
Task 1 (`tests/build/no-new-function-in-sw-chunk.test.ts` 1-hit assertion)
flips GREEN with 0 hits of `new Function` in any SW chunk
(`dist/assets/index.ts-*.js` glob).
## Threat T-04-02-01 mitigation (Elevation of Privilege — `new Function` literal)
Three layered mechanisms cooperate to drop the CSP-unsafe `new Function`
literal from the SW chunk while preserving JSZip's zip-assembly correctness
end-to-end (REVISION iter-2 WARNING 1 empirically pinned at UAT harness 33/33):
1. **Runtime polyfill prelude** at top-of-module of `src/background/index.ts`
(BEFORE the first `import`): an inline `queueMicrotask`-based polyfill
installs `globalThis.setImmediate` at SW boot. JSZip's pre-bundled
`dist/jszip.min.js` IIFE guards its internal setimmediate polyfill behind
`if(!s.setImmediate){...}`, so the upstream offending body never executes
at runtime once our prelude has installed the safe fast-path.
2. **`vite-plugin-node-polyfills` `exclude: ['setimmediate']`** in vite.config.ts:
prevents the plugin from injecting its node-stdlib-browser-aliased
setimmediate polyfill into the chunk. NOTE: this alone is insufficient
because JSZip's `dist/jszip.min.js` ships its OWN bundled-in setimmediate
(via the package.json `"browser"` field that maps `./lib/index` →
`./dist/jszip.min.js`); the plugin's `exclude` only filters the plugin's
own contributions.
3. **`resolve.alias.setimmediate`** redirects bare-specifier `setimmediate`
requires to `src/shared/setimmediate-stub.ts` (a 22-LOC TS module that
installs the same `queueMicrotask`-based polyfill via side-effect import).
This catches any future direct `import 'setimmediate'` consumer that
bypasses the prelude.
4. **`stripSetimmediateNewFunction()` Rollup post-transform plugin** in
vite.config.ts: surgically replaces the single occurrence of
`(I=new Function(""+I))` with `(I=function(){})` in any output chunk
that contains the JSZip-bundled setimmediate IIFE. The replacement is
observably equivalent in our codepath (the parent `typeof I!="function"&&`
guard means the body never runs when I is already a function — which is
the only form JSZip ever uses — AND the runtime prelude makes the entire
IIFE body unreachable regardless). Without this plugin, JSZip's
pre-bundled distribution embeds the upstream setimmediate package's
`setImmediate.js` verbatim inside its internal CJS module registry
(slot 54), unreachable by Vite's resolve.alias or the polyfill plugin's
exclude.
## Architecture decision log
**Option α (force JSZip unbundled `lib/index.js` via `resolve.alias.jszip`)
was attempted and reverted 2026-05-21** (between commits
|
|||
| 630d40c4f8 |
test(04-02): Wave 0 — no-new-function-in-sw-chunk RED + dead-code-grep regression pin
Two new build-gate vitest files at `tests/build/` per Plan 04-02 Wave 0 TDD-strict RED-first contract: - `no-new-function-in-sw-chunk.test.ts`: SW-chunk CSP-hardening grep gate. Narrows the file walk to `dist/assets/index.ts-*.js` (the SW + loader chunks; cf. plan-checker iter-1 BLOCKER 1 fix). RED today: 1 occurrence of `new Function` in the SW chunk (the pre-existing `setimmediate` npm package fallback bundled transitively by vite-plugin-node-polyfills, per .planning/phases/01-stabilize-video-pipeline/deferred-items.md). Flips GREEN after Task 2's setimmediate replacement lands. Build-prep gate (npm run build + dist/assets/ existence + ≥1 SW chunk match) precedes the grep gate so the test is self-bootstrapping under SKIP_BUILD=0 and self-asserting under SKIP_BUILD=1. - `dead-code-grep.test.ts`: ROADMAP SC #4 regression pin against `src/`. Asserts absence of `permissions.request` (removed in Phase 1 Plan 01-05 SW shrink). GREEN-on-arrival today; acts as regression guard so re-introducing the deleted permission-request flow breaks CI. The offscreen-inline-string sub-test is documented as delegated to the vite.config.ts review + tests/build/no-remote-fonts.test.ts (no single literal sentinel pinnable post-Plan-01-06 collapse). Polarity confirmation: - Acceptance grep: `grep -v '^//' tests/build/no-new-function-in-sw-chunk.test.ts | grep -c 'new Function'` returns 3 (≥2 required). - Acceptance grep: `grep -v '^//' tests/build/dead-code-grep.test.ts | grep -c 'permissions.request'` returns 2 (≥2 required). - SKIP_BUILD=1 npm test -- tests/build/no-new-function-in-sw-chunk.test.ts tests/build/dead-code-grep.test.ts --run: 2 passed + 1 failed (the expected RED gate). - Full vitest: 180 passed + 3 failed (1 = this task's expected RED + 2 = pre-existing ffmpeg/ffprobe flakes per 04-01-SUMMARY Issues Encountered — owned by Plan 04-03). References: - .planning/phases/04-harden-clean-up-optional/04-PATTERNS.md §"tests/build/no-new-function-in-sw-chunk.test.ts" + §"tests/build/dead-code-grep.test.ts" - .planning/phases/04-harden-clean-up-optional/04-RESEARCH.md §Q1 - Plan 04-02 threat model T-04-02-01 (Elevation of Privilege) + T-04-02-03 (Information Disclosure regression pin) - tests/build/no-remote-fonts.test.ts (Plan 01-12 analog scaffold) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| f72bca5c46 |
docs(04-01): complete audit-p1-polish-content-script plan
Plan 04-01 closure marker — 04-01-SUMMARY.md + STATE.md position advance (Plan 1 of 7 -> Plan 2 of 7; Plan 04-02 build hygiene queued NEXT in Wave 1) + ROADMAP plan-progress table flip ([ ] -> [x] 04-01-PLAN.md row). Plan delivered (per SUMMARY): - Audit P1 #11 fetch URL extraction fix (TWO sites; instanceof Request narrow) - Audit P1 #14 navigation URL tracking fix (module-level previousUrl) - Audit P1 #15 rrweb emit timestamp normalization (Date.now() Unix epoch) - 9 new vitest tests under tests/content/; baseline 171 -> 180/180 GREEN - tsc-clean preserved; Tier-1 hook-strings inventory unchanged at 12 - Audit P1 polish backlog CLOSED 3/3 Per-task commits (TDD pair): - |
|||
| 7da30afa0a |
feat(04-01): Wave 1 GREEN — fix audit P1 #11 fetch URL + #14 nav URL + #15 rrweb timestamps
Three surgical edits in src/content/index.ts flip the 7 RED tests from commit |
|||
| 3dbc51cdcd |
test(04-01): Wave 0 RED — audit P1 #11/#14/#15 content-script test scaffolds
Three new test files at tests/content/ (NEW directory mirroring src/content/)
pin the canonical Plan 04-01 contracts; 7 of 9 tests are RED today and flip
GREEN once src/content/index.ts gains the three surgical edits in Task 2.
* tests/content/fetch-interception.test.ts (4 tests; A+C pass today via the
identity String(string)===string coincidence, B+D RED — they fetch a
`new Request(url)` and assert target === request.url under the canonical
`args[0] instanceof Request ? args[0].url : String(args[0])` narrow).
* tests/content/navigation-tracking.test.ts (3 tests; all 3 RED — popstate
+ hashchange + history.pushState wrap all read meta.previousUrl which is
permanently 'unknown' under today's `history.state?.url || 'unknown'`
emit; GREEN after module-level `let previousUrl` lands).
* tests/content/rrweb-timestamps.test.ts (2 tests; both RED — Test A asserts
rrweb-emit normalizes timestamps to Date.now()-class >1e12 instead of the
rrweb-internal page-load-relative small int; Test B regresses
cleanupOldEvents arithmetic correctness when both sides are Unix-epoch).
Scaffold mirrors tests/background/start-video-capture-no-tab.test.ts (Plan
01-09): vi.resetModules() in beforeEach, minimal chrome.* + window/document/
history/Request stubs installed on globalThis before
`await import('../../src/content/index')`. rrweb is mocked via vi.mock so the
content-script's `import { record } from 'rrweb'` short-circuits to a no-op
factory (avoids the rrweb-lib ESM-in-CJS transform crash). userEvents and
rrwebEvents are read back through the canonical GET_RRWEB_EVENTS chrome.
runtime.onMessage path the production archive pipeline uses.
Also folds in the .planning/config.json `use_worktrees: false` flip the
orchestrator staged before respawning this executor in foreground mode.
Plan: 04-01 Wave 0
Files:
- tests/content/fetch-interception.test.ts
- tests/content/navigation-tracking.test.ts
- tests/content/rrweb-timestamps.test.ts
- .planning/config.json (worktree mode disabled)
Verification (RED gate):
- npm test -- tests/content/ --run → 7 failed | 2 passed (9)
- grep -c "instanceof Request" tests/content/fetch-interception.test.ts → 5
- grep -c "previousUrl" tests/content/navigation-tracking.test.ts → 24
- grep -cE "Date\.now\(\)" tests/content/rrweb-timestamps.test.ts → 9
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| 9ad5069f70 |
docs(state): mark phase 04 executing — begin-phase tick
Set status=executing, current focus=Phase 04, position=Plan 1 of 7. |
|||
| 3ceca875e5 |
docs(state): resume-work — HANDOFF.json consumed; user routed to /gsd-execute-phase 4
Session continuity updated; .continue-here.md preserved as secondary fallback. |
|||
| dbcf4827f6 | wip: phase-04 paused — 7 plans validated iter-2 PASSED, ready for execution .planning/phases/04-harden-clean-up-optional/.continue-here.md .planning/HANDOFF.json | |||
| 55369b80ad |
docs(state): record phase 4 plan-phase closure — iter-2 PASSED + 3 cosmetic advisories fixed
state.record-session CLI bug recurred (status: completed because 23/30 partial
match triggered; restored: status=ready_to_execute). total_plans correctly
bumped 23 → 30 (Phase 1: 14 + Phase 2: 4 + Phase 3: 5 + Phase 4: 7).
Phase 4 plan-phase ceremony complete:
- 7 plans across 6 waves (Wave 1: 04-01+04-02 parallel; Waves 2-6 single-plan)
- Plan-checker iter-1: 2 BLOCKER + 4 WARNING (fixed)
- Plan-checker iter-2: VERIFICATION PASSED with 3 cosmetic advisories
- 3 cosmetic advisories now fixed (commit
|
|||
| 3c1280ed2d |
docs(04): plan-phase closure — 3 cosmetic advisories from checker iter-2 resolved
Plan-checker iter-2 returned VERIFICATION PASSED with 3 cosmetic advisories: - Dim 11: RESEARCH.md "## Open Questions" missing "(RESOLVED)" suffix → fixed - Dim 12: PATTERNS.md:886 stale dispatchSaveArchiveForA33 example → added DEPRECATED banner citing Plan 04-04 REVISION iter-2 Option B canonical pattern - VALIDATION.md frontmatter "4 revised tasks" mismatched per-task map (5 rows) → fixed All 4 BLOCKER+WARNING issues from iter-1 verified resolved by iter-2 plan-checker (VERIFICATION PASSED). 3 cosmetic items now resolved as well. 2 advisory items left as-is per iter-1 (W2 scope-sanity at 04-06; W3 conservative 04-03 dep). Phase 4 plans cleared for execution: - 7 plans across 6 waves (Wave 1: 04-01+04-02 parallel; Waves 2-6 single-plan) - Plan-checker iter-2 VERIFICATION PASSED - Test baselines preserved: vitest 171/171 · UAT harness 33/33 · Tier-1 12 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| 76fffb35b9 |
fix(04): revise plans per checker iter-1 — 2 BLOCKERS + 2 WARNINGS fixed
Plan-checker iter-1 found 2 BLOCKERS + 4 WARNINGS. Iter-2 revision applies
surgical fixes to 4 plans + VALIDATION:
BLOCKER 1 (Plan 04-06 Task 4): wrong SW chunk glob `dist/assets/index*-bg.js`
matched zero files → Gates 2/3/4 silently PASSED. Replaced with canonical
`dist/assets/index.ts-*.js` (verified empirically: index.ts-8LkXuqac.js
on disk; RESEARCH Q1). Added glob-existence pre-gate `ls | wc -l >= 1`
to fail-loudly on future Vite chunk-naming shift.
BLOCKER 2 (Plan 04-04 Task 1): spike called non-existent
__mokoshHarness.dispatchSaveArchive (verified: harness surface is
assertA1..A31 + getManifestVersion only). Applied Option B — spike
+ driveA33 now dispatch SAVE_ARCHIVE via chrome.runtime.sendMessage
inline in page.evaluate (matches 9 existing assertA* methods:
A5/A11/A12/A13/A26/A28/A29/A30/A31). No new harness helper introduced.
WARNING 1 (Plan 04-02 Task 2): verify omitted UAT harness run. Added
`HEADLESS=1 SKIP_PROD_REBUILD=0 npm run test:uat 2>&1 | grep -c 'UAT
harness: 33/33 assertions passed'` to verify command (stdout format
confirmed at tests/uat/harness.test.ts:537).
WARNING 4 (Plan 04-07 Task 1): weak operator-ack gate (placeholder would
pass). Added `grep -cE 'approved|All good|APPROVED|approved by|operator
ack|all good' 04-VERIFICATION.md` to verify command. Covers both
canonical Plan 04-06 resume-signal ("approved" lowercase) AND prior-art
Plan 01-10 cycle-2 ack ("All good" titlecase).
WARNINGS 2 + 3 left as-is (truly advisory: scope-sanity threshold +
conservative dependency without file overlap).
04-VALIDATION.md per-task map rows updated for the 5 revised task entries
(04-02 T2 + 04-04 T1 + 04-04 T2 + 04-06 T4 + 04-07 T1). Frontmatter
adds `revised: 2026-05-21` + iter-2 notes block.
3 plans unchanged on disk (04-01, 04-03, 04-05).
Empirical confirmations used in revision:
- Harness surface: grep extension-page-harness.ts:4018 confirms
__mokoshHarness.{assertA1..A31, getManifestVersion}; no dispatchSaveArchive
- SW chunk filename: ls dist/assets/ shows index.ts-8LkXuqac.js;
no index*-bg.js matches
- SAVE_ARCHIVE precedent count: 9 existing assertA* methods use the
chrome.runtime.sendMessage pattern
- UAT harness stdout format: harness.test.ts:537 emits canonical
"UAT harness: N/N assertions passed"
Ready for plan-checker iter-3 re-verification.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| 526ac78046 |
docs(04): create phase plan — 7 plans for Phase 4 hardening (audit P1 polish + flake stabilization + SW persistence + visual polish + closure)
Wave structure: - W1 (parallel): 04-01 (Audit P1 polish #11/#14/#15 TDD) + 04-02 (build/CSP hygiene: setimmediate polyfill + dead-code + generate-icons.cjs) - W2: 04-03 (A29 cs-injection-world rewrite; closes flake) - W3: 04-04 (A33 SW state persistence; spike-first + CDP worker.close()) - W4: 04-05 (A34 fetch+XHR network_error; ROADMAP SC #2 + validates Plan 04-01 P1 #11 end-to-end) - W5: 04-06 (dark-logo currentColor + cursor verification + 01-07-SUMMARY back-patch; operator empirical) - W6: 04-07 (04-VERIFICATION.md aggregator + ROADMAP backfill + v1 close prep) Honors locked decisions D-P4-01..05 (full Phase 4 + all 3 P1 polish + both visual items + alpha-independent + ROADMAP backfill). Implements RESEARCH Q1 (setimmediate option a), Q2 (spike-first SW persistence), Q3 (A29 cs-injection-world), Finding 4 (cursor already shipped — verification only). UI-SPEC dark-logo currentColor strategy with inline-SVG injection landed per UI-SPEC §"Implementation amendment". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| f012c8c103 | docs(04): pattern map — ~30 anticipated files mapped (21 exact + 8 role-match + 1 NEW pattern stopServiceWorker CDP helper) .planning/phases/04-harden-clean-up-optional/04-PATTERNS.md | |||
| 7178d14154 | docs(phase-04): add validation strategy — Wave 0 anticipates 6 new unit test files per RESEARCH .planning/phases/04-harden-clean-up-optional/04-VALIDATION.md | |||
| d1f676707e | docs(04): research phase domain — setimmediate, SW persistence, A29 race fix + cursor finding .planning/phases/04-harden-clean-up-optional/04-RESEARCH.md | |||
| 61caf04273 |
docs(state): record phase 4 UI-SPEC session — APPROVED 5/6 + 1 FLAG non-blocking
state.record-session CLI bug recurred (status: completed because 23/23 known plans done). Restored: status=ready_to_plan. UI-SPEC.md at: .planning/phases/04-harden-clean-up-optional/04-UI-SPEC.md status: approved · reviewer: gsd-ui-checker · reviewed_at: 2026-05-20 Verdict: 5/6 dimensions PASS + 1 FLAG (Dim 4 inherited type scale exceeds standard thresholds but is locked from Phase 1 operator brand-fit ack 2026-05-20; Phase 4 adds zero new sizes/weights) — non-blocking. Next: /gsd-plan-phase 4 (preferences preserved at .plan-phase-preferences.md auto-deletes when consumed). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| 266aa95235 |
docs(04): UI-SPEC.md status approved — 5/6 PASS + 1 FLAG non-blocking (dim 4 inherited type scale)
UI-checker verdict: APPROVED. Dimension breakdown: - 1 Copywriting: PASS (17-key matrix inherited + locked; zero new copy) - 2 Visuals: PASS (no new screen; dark-logo is stroke binding change) - 3 Color: PASS (Loom palette inherited; semantic accents declared) - 4 Typography: FLAG (8 sizes / 4 weights exceed standard thresholds but correctly captured as Phase 1-locked inherited from operator brand-fit ack 2026-05-20; Phase 4 adds zero new sizes/weights) — non-blocking - 5 Spacing: PASS (all multiples of 4; locked; no new values) - 6 Registry Safety: PASS (vanilla DOM + DOMParser; no shadcn; no third-party) Three checker observations addressed: 1. `?url` → `?raw` bundling: correctly preserves @crxjs auto-WAR (SVG content stays in JS bundle as string literal vs base64 data URL) 2. A17.8 sub-check update: concrete enough (raw-SVG-source string-search for `currentColor` + `viewBox='0 0 32 32'`); optional A17.8a/A17.8b split well-described 3. Dark-mode contrast: deep-indigo stroke on madder-orange wrapper is readable; operator empirical checkpoint (acceptance criterion #6) is the designated gate for WCAG ratio judgment Implementation contract = 5 file edits + 6 acceptance criteria. Planner can now use UI-SPEC as design context for the visual-polish Phase 4 plan. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| 55cefbaa32 |
docs(04): UI design contract — thin scope (dark-logo currentColor strategy)
Phase 4 carries one genuine designer-side decision: dark-surface logo contrast strategy. Recommends Option A — `currentColor` SVG + CSS color driven via the existing `.dark, [data-theme="dark"]` block in tokens.css (lines 234-251). Post- research amendment: welcome.ts must swap `?url` (data URL → <img>) for `?raw` (inline <svg> via DOMParser) because <img>-rendered SVGs do not inherit parent CSS color — `currentColor` only resolves on inline DOM SVG. Cursor visibility constraint (Plan 01-07 obs 2026-05-15) is listed as behavioral-only inheritance, not a design surface — 1-line change in src/offscreen/recorder.ts per Chrome CursorCaptureConstraint enum. Inherits Phase 1 design system as read-only (Lora display + IBM Plex Sans UI + Loom palette + Mokosh mark + canonical tokens.css + 17-key i18n matrix). Zero new tokens, zero new copy, zero new colors. PNG icons unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| 74ac8ac342 |
docs(04): preserve plan-phase preferences captured pre-UI-SPEC exit
User invoked /gsd-plan-phase 4 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 4 produces UI-SPEC.md): - UI gate: generate UI-SPEC.md first — unlike Phase 3 (false positive), Phase 4 has genuine dark-logo work; UI-SPEC should be thin-but-real (dark-logo design only; cursor visibility listed as inherited behavioral change, not a design surface) - Research gate: research first (light, ~10-20 min) — scope-limited to: setimmediate polyfill replacement strategy + SW state persistence 5min idle test patterns + chrome.scripting.executeScript world:'ISOLATED' best practices for A29 cs-injection-world fix. Researcher NOT to investigate already-deferred items (rrweb v2, SW-RAM, masking). File auto-deletes when /gsd-plan-phase 4 honors these preferences. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| f14c605dcd |
docs(state): record phase 4 context session — Phase 4 discuss-phase complete
state.record-session CLI bug recurred (status flipped completed because 23/23 known plans done). Restored: status=ready_to_plan. Phase 4 CONTEXT.md at: .planning/phases/04-harden-clean-up-optional/04-CONTEXT.md 5 D-P4-* decisions locked: - D-P4-01 Full Phase 4 scope (all 4 ROADMAP SC + ~10 of 12 deferred items; excludes rrweb v2 + programmatic SW-RAM) - D-P4-02 Audit P1 all three (#11 fetch + #14 nav URL + #15 rrweb timestamps) - D-P4-03 Both visual polish items (cursor visibility + dark-logo) - D-P4-04 Alpha tester integration user-handled out-of-band (proceed independently) - D-P4-05 ROADMAP backfill in scope (docs hygiene) Next: /gsd-plan-phase 4 (note: UI-SPEC gate may trip on dark-logo work; suggest --skip-ui or generate thin UI-SPEC for visual polish surface). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| 8b31fbe3de | docs(04): capture phase context — discuss-phase complete (5 D-P4-* locked decisions; full Phase 4 scope) .planning/phases/04-harden-clean-up-optional/04-CONTEXT.md .planning/phases/04-harden-clean-up-optional/04-DISCUSSION-LOG.md | |||
| d02b41b7c7 |
docs(phase-03): VERIFICATION + Phase 3 closure markers — verdict PASSED (5/5 ROADMAP + 9/9 SPEC §10)
Phase 3 verifier returned human_needed with 2 verification items: 1. §10 #9 RAM ceiling — genuinely non-automatable (Page.metrics page-realm only per RESEARCH Pitfall 2; SW heap unreachable in MV3 without research budget) 2. ROADMAP/STATE marker flips — orchestrator-owned per worktree protocol Item 2 resolved automatically via gsd-sdk phase.complete: - ROADMAP Phase 3 marker flipped [x] - STATE.md completed_phases: 2 → 3; percent recalculated 75 - REQUIREMENTS.md REQ-rrweb-dom-buffer + REQ-user-event-log flipped Complete Item 1 OVERRIDDEN to VERIFIED based on user explicit ack 2026-05-20: - A32 best-effort scaffolding (page-realm Page.metrics with explicit "page-realm only" diagnostic; ~1.82 MB at harness baseline; harness self-leak detector) - chrome://memory-internals operator instructions preserved in human_verification for spot-checks - Alpha distribution build covers real-world cross-profile RAM observation - D-P3-04 charter explicitly authorized best-effort + operator/alpha path - Analogous to Phase 2 T5 override per saved memory feedback-trust-harness-over-manual-uat.md - Programmatic SW-context measurement via chrome.devtools Memory API deferred to Phase 4 hardening (in 03-VERIFICATION.md Forward-Looking Deferred Items) VERIFICATION.md frontmatter: status flipped human_needed → passed. overrides_applied: 4 (3 from executor 03-05 + 1 for §10 #9 closure). STATE.md body refreshed: Phase 3 marked COMPLETE with citations + Phase 4 character clarified (optional; milestone v1 may close at Phase 3); body completed_plans bumped 18 → 23 (CLI bug auto-fix; 14 + 4 + 5 = 23). PROJECT.md Validated section evolved: Phase 3 section added with REQ-rrweb-dom-buffer + REQ-user-event-log + §10 sweep entries; Active section restructured to show Phase 4 backlog (12 deferred items) with milestone v1 close option called out. Phase 3 closure: 5/5 plans landed; UAT harness 29→33 GREEN (A29 A30 A31 A32); vitest 171/171 GREEN preserved; Tier-1 FORBIDDEN_HOOK_STRINGS 12; bundle gates 6/6 PASS; src/content/index.ts UNMODIFIED per D-P3-02 charter literal. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| 4de6b3b9ae | docs(phase-03): update tracking after wave 5 — 03-05 GREEN (§10 sweep VERIFICATION + REQ marker flips) .planning/ROADMAP.md | |||
| a58a667978 | chore: merge executor worktree (worktree-agent-a76b0d83f16b28c5f) — Wave 5 Plan 03-05 | |||
| 1642a73067 |
docs(03-05): SUMMARY — Phase 3 closure aggregator (9/9 SPEC §10 sweep + REQUIREMENTS markers + 12 Phase 4 deferred items)
- Phase 3 Wave 5 plan: pure documentation synthesis + verification gate execution - 3/3 tasks complete: Task 1 pre-checkpoint bundle gates 6/6 PASS; Task 2 03-VERIFICATION.md (204 lines; 9-criterion §10 scorecard + 3 T5 overrides + 1 human_verification + 12-row deferred items table); Task 3 REQUIREMENTS.md REQ-rrweb-dom-buffer + REQ-user-event-log flipped Complete - STATE.md + ROADMAP.md NOT modified per parallel-executor worktree protocol (auto-strip rule; orchestrator owns those writes post Wave 5 merge per Phase 1 + Phase 2 closure precedent) - 1 Rule-3 deviation documented: STATE.md/ROADMAP.md scope adapted to worktree mode - vitest 171/171 GREEN preserved; UAT 33/33 GREEN on second consecutive run (first hit pre-existing A29 zip-mtime race-condition flake documented in 03-02 + 03-03 SUMMARYs; routed to Phase 4 hardening as deferred item row 1) - Tier-1 FORBIDDEN_HOOK_STRINGS unchanged at 12 entries; pre-checkpoint bundle gates 6/6 PASS - Saved memories cited first-class: feedback-trust-harness-over-manual-uat.md (3 T5 overrides), feedback-pre-checkpoint-bundle-gates.md (Cross-Cutting Gates row), feedback-no-unilateral- scope-reduction.md (worktree protocol honored) - Phase 4 backlog seeded: 12-row Forward-Looking Deferred Items in 03-VERIFICATION.md including A29 cs-injection-world re-target + parallel-vitest flake + rrweb v2 upgrade + programmatic per-target RAM + REQ-password-confidentiality v2 candidate (conditional) + audit P1 polish + 5 minor backlog items Self-Check: PASSED — all files exist; both task commits found ( |
|||
| 71081aa8c2 |
docs(03-05): Task 3 — REQUIREMENTS.md REQ marker flips (Phase 3 closure)
- REQ-rrweb-dom-buffer: [ ] → [x] with Plan 03-01 A29 GREEN closure block (4 EventType-enum checks; T5 override per saved memory feedback-trust-harness-over-manual-uat.md) - REQ-user-event-log: [ ] → [x] with Plan 03-02 A30 GREEN closure block (5 UserEvent.type presence checks via cs-injection-world pattern; T5 override) - Traceability table: both REQs flipped Pending → Complete 2026-05-20 with citation - Closure footer appended with Phase 3 sweep summary (3 T5 overrides for §10 #4/#5/#8 PARTIAL; 1 human_verification for §10 #9 RAM per D-P3-04; UAT 29 → 33 GREEN) - REQ-password-confidentiality unchanged (Out of Scope v1 per D-P3-02 charter; PARTIAL via A31 covers existing minimum at src/content/index.ts:82) Per parallel-executor protocol: STATE.md + ROADMAP.md NOT modified (auto-strip on merge; orchestrator owns those writes post Wave 5 merge). REQUIREMENTS.md propagates via merge. |
|||
| a63a821172 |
docs(03-05): Task 2 — 03-VERIFICATION.md (9/9 SPEC §10 sweep; 3 T5 overrides + 1 human_verification)
- Aggregates Plan 03-01..04 empirical evidence + Phase 1 + Phase 2 closure citations - Frontmatter: status=passed, score=9/9, overrides_applied=3, human_verification=1 entry - 9-criterion scorecard with Phase + Plan + commit citations - T5 overrides applied for §10 #4 (A29 |
|||
| 041c4d4258 | docs(phase-03): update tracking after wave 4 — 03-04 GREEN (A32 §10 #9 RAM scaffolding; UAT 33/33) .planning/ROADMAP.md | |||
| 67246ed841 | chore: merge executor worktree (worktree-agent-ab163c15167479f9e) — Wave 4 Plan 03-04 |