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>
14 KiB
phase, slug, status, nyquist_compliant, wave_0_complete, created, revised, revision_notes
| phase | slug | status | nyquist_compliant | wave_0_complete | created | revised | revision_notes |
|---|---|---|---|---|---|---|---|
| 04 | harden-clean-up-optional | draft | false | false | 2026-05-21 | 2026-05-21 | iter-2 revision — per-task map updated for 5 revised tasks (04-02 T2 UAT grep gate; 04-04 T1 + T2 Option B chrome.runtime.sendMessage; 04-06 T4 canonical SW chunk glob; 04-07 T1 ack-grep gate) |
Phase 04 — Validation Strategy
Per-phase validation contract for feedback sampling during execution.
Phase 4 character: Final v1 hardening phase. Mix of bug fixes + flake stabilization + audit P1 polish + visual polish + build hygiene + closure aggregator. Wave 0 RED test scaffolds for new audit-P1 fixes; existing harness extended for new A33+ assertions; spike-first for SW state persistence (Plan 04-03 per RESEARCH finding 2).
Test Infrastructure
| Property | Value |
|---|---|
| Framework | vitest 4.x (unit) + custom Puppeteer harness (UAT — npm run test:uat) |
| Config file | vitest.config.ts + tests/uat/harness.test.ts (orchestrator) |
| Quick run command | npm test -- --run tests/<focused-file>.test.ts |
| Full suite command | npm test -- --run (vitest) + HEADLESS=1 SKIP_PROD_REBUILD=1 npm run test:uat (UAT harness) |
| Estimated runtime | ~50s (vitest 171→~190 tests post Wave 0) + ~95-300s (UAT harness 33→~37 assertions; 5-min idle test adds ~300s to single run if not gated) ≈ 2.5-6 min full sweep |
Sampling Rate
- After every task commit: Run focused test command (vitest single-file OR
npm run test:uat -- --grep A<NN>for harness) - After every plan wave: Run full vitest + full UAT harness — both MUST be GREEN
- Before
/gsd-verify-work 4: Full suite GREEN + pre-checkpoint bundle gates 6/6 PASS (per saved memoryfeedback-pre-checkpoint-bundle-gates.md) - 5-min idle test (Plan 04-03): dedicated
npm run test:uat:longlane with 6-min timeout; NOT in default sample - Max feedback latency: ~2.5 min (default full sweep); ~10s (focused vitest); ~25s (focused UAT assertion)
Per-Task Verification Map
| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|---|---|---|---|---|---|---|---|---|---|
| 04-01 T1 RED 3 tests | 04-01 | 1 | Audit P1 #11/#14/#15 | T-04-01-01..03 | URL extraction + previousUrl + epoch normalization | unit (vitest jsdom) | npm test -- tests/content/ --run |
❌ NEW (Wave 0) | ⬜ pending |
| 04-01 T2 GREEN edits | 04-01 | 1 | Audit P1 #11/#14/#15 | T-04-01-01..03 | Same; src/content/index.ts edits | unit (vitest) | npm test -- tests/content/ --run (+8 GREEN) + npx tsc --noEmit |
✗ EXISTS (modify) | ⬜ pending |
| 04-02 T1 RED build gates | 04-02 | 1 | SC #4 dead-code + setimmediate hygiene | T-04-02-01/03 | grep gate | unit (vitest + execFile build) | npm test -- tests/build/no-new-function-in-sw-chunk.test.ts tests/build/dead-code-grep.test.ts --run |
❌ NEW (Wave 0) | ⬜ pending |
| 04-02 T2 GREEN polyfill + rename + flip (REVISION iter-2 WARNING 1) | 04-02 | 1 | SC #3 generate-icons + setimmediate Q1 + UAT preserved | T-04-02-01/02/04 | queueMicrotask polyfill; .cjs rename; JSZip fallback verified empirically | build-gate + unit + UAT | npm run build && grep -c 'new Function' dist/assets/index.ts-*.js | head -1; node generate-icons.cjs; npm test -- tests/build/no-new-function-in-sw-chunk.test.ts tests/build/dead-code-grep.test.ts --run; npx tsc --noEmit && HEADLESS=1 SKIP_PROD_REBUILD=0 npm run test:uat 2>&1 | tee /tmp/04-02-task-2-uat.log | tail -3; grep -c 'UAT harness: 33/33 assertions passed' /tmp/04-02-task-2-uat.log -> 0 hits + cjs exit 0 + tests GREEN + tsc-clean + 1 ack-line |
✗ EXISTS (modify + rename) | ⬜ pending |
| 04-03 T1 assertA29 rewrite | 04-03 | 2 | A29 flake stabilization | T-04-03-01/02 | cs-injection-world ISOLATED + sentinel | UAT (page-side) | npx tsc --noEmit && npm run build:test |
✗ EXISTS (modify) | ⬜ pending |
| 04-03 T2 driveA29 strict-sentinel | 04-03 | 2 | A29 sentinel filter | T-04-03-01 | rrweb IncrementalSource.Mutation filter | UAT (host-side) | HEADLESS=1 SKIP_PROD_REBUILD=1 npm run test:uat 33/33 GREEN; 5/5 stress |
✗ EXISTS (modify) | ⬜ pending |
| 04-04 T1 SPIKE (REVISION iter-2 BLOCKER 2 — Option B chrome.runtime.sendMessage) | 04-04 | 3 | SC #1 SW state persistence empirical | T-04-04-01 | offscreen survives SW idle; SAVE_ARCHIVE via canonical chrome.runtime.sendMessage (NOT non-existent __mokoshHarness.dispatchSaveArchive) | spike script | npx tsc --noEmit && HEADLESS=1 tsx tests/uat/spike-a33-sw-persistence.ts 2>&1 | tee /tmp/04-04-spike.log; grep -c 'SPIKE RESULT' /tmp/04-04-spike.log; grep -c "type: 'SAVE_ARCHIVE'" tests/uat/spike-a33-sw-persistence.ts; grep -c 'dispatchSaveArchive' tests/uat/spike-a33-sw-persistence.ts -> SPIKE RESULT line + SAVE_ARCHIVE >= 1 + dispatchSaveArchive == 0 + videoSize > 100_000 |
❌ NEW (Wave 0 spike) | ⬜ pending |
| 04-04 T2 A33 + stopServiceWorker + orchestrator (REVISION iter-2 BLOCKER 2 — Option B) | 04-04 | 3 | SC #1 5-min idle harness | T-04-04-02/03/04 | CDP worker.close() + 5-min wait + SAVE via chrome.runtime.sendMessage inline page.evaluate | UAT | npx tsc --noEmit && npm run build:test && HEADLESS=1 SKIP_PROD_REBUILD=1 SKIP_LONG_UAT=1 npm run test:uat 2>&1 | tail -5 | tee /tmp/04-04-task-2-skip.log; grep -c '34/34' /tmp/04-04-task-2-skip.log; grep -c 'dispatchSaveArchive' tests/uat/lib/harness-page-driver.ts tests/uat/extension-page-harness.ts tests/uat/harness.test.ts -> 34/34 skip-mode + dispatchSaveArchive == 0 + full-mode 34/34 ~6.5 min |
✗ EXISTS (modify) | ⬜ pending |
| 04-05 T1 assertA34 fetch+XHR | 04-05 | 4 | SC #2 fetch+XHR network_error | T-04-05-01 | cs-injection-world dual-trigger | UAT (page-side) | npx tsc --noEmit && npm run build:test |
✗ EXISTS (modify) | ⬜ pending |
| 04-05 T2 driveA34 + orchestrator | 04-05 | 4 | SC #2 + P1 #11 end-to-end empirical | T-04-05-01 | 2 network_error entries with status===404 | UAT | HEADLESS=1 SKIP_LONG_UAT=1 npm run test:uat 35/35 GREEN; full-mode ~7 min |
✗ EXISTS (modify) | ⬜ pending |
| 04-06 T1 RED inline-SVG + cursor-pin | 04-06 | 5 | UI-SPEC dark-logo + RESEARCH Finding 4 | T-04-06-01 | DOMParser inline injection (no innerHTML); cursor: 'always' literal | unit (vitest jsdom + build-grep) | npm test -- tests/welcome/ tests/build/cursor-visibility.test.ts --run |
❌ NEW (Wave 0) | ⬜ pending |
| 04-06 T2 GREEN SVG + welcome.ts + globals | 04-06 | 5 | UI-SPEC stroke recolor + ?raw import | T-04-06-01 | currentColor + DOMParser inline | unit | npm test -- tests/welcome/inline-svg.test.ts --run 3/3 GREEN |
✗ EXISTS (modify) | ⬜ pending |
| 04-06 T3 A17.8 + 01-07 back-patch | 04-06 | 5 | UI-SPEC harness invariant + docs hygiene | T-04-06-01 | A17.8 raw-source grep | UAT + docs | HEADLESS=1 SKIP_LONG_UAT=1 npm run test:uat 35/35 + grep verify |
✗ EXISTS (modify) | ⬜ pending |
| 04-06 T4 Operator empirical (REVISION iter-2 BLOCKER 1 — canonical SW chunk glob) | 04-06 | 5 | UI-SPEC AC #6 aesthetic judgment | T-04-06-01/04 | dark-mode visual contrast; canonical dist/assets/index.ts-*.js glob (NOT non-matching index*-bg.js) |
manual + pre-checkpoint bundle gates | npm run build && ls dist/assets/index.ts-*.js | wc -l; grep -cE 'new Function\(|eval\(' dist/assets/index.ts-*.js; HEADLESS=1 SKIP_PROD_REBUILD=1 SKIP_LONG_UAT=1 npm run test:uat 2>&1 | tail -3 -> glob match >= 1 + 0 hits + UAT 35/35 + operator returns "approved" |
n/a (verification + operator) | ⬜ pending |
| 04-07 T1 04-VERIFICATION.md (REVISION iter-2 WARNING 4 — ack-grep gate) | 04-07 | 6 | Phase 4 closure aggregator + verbatim operator ack | T-04-07-01/04 | scorecard + override notes + deferred items + verbatim operator ack from Plan 04-06 | docs aggregator | test -f .planning/phases/04-harden-clean-up-optional/04-VERIFICATION.md && grep -cE '^## ' .planning/phases/04-harden-clean-up-optional/04-VERIFICATION.md; grep -c 'Plan 04-0' .planning/phases/04-harden-clean-up-optional/04-VERIFICATION.md; grep -cE 'approved|All good|APPROVED|approved by|operator ack|all good' .planning/phases/04-harden-clean-up-optional/04-VERIFICATION.md -> sections >= 5 + Plan-04 citations >= 6 + ack-literal >= 1 |
❌ NEW | ⬜ pending |
| 04-07 T2 Marker flips | 04-07 | 6 | D-P4-05 + ROADMAP/STATE flips | T-04-07-02/03 | Phase 4 [x] + completed_phases: 4 | docs | grep -c '\[x\] \*\*Phase 4' .planning/ROADMAP.md >= 1 |
✗ EXISTS (modify) | ⬜ pending |
Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky
Planner instructions: Populate one row per task. Per RESEARCH finding 5 (6 new Wave-0 test files anticipated), expect ~6 unit-test rows + ~4 harness-A33+ rows + ~4 bundle-gate rows + ~3 docs rows. Format per Phase 3 03-VALIDATION precedent.
REVISION iter-2 notes (2026-05-21):
- 04-02 T2 (WARNING 1):
<automated>now includesHEADLESS=1 SKIP_PROD_REBUILD=0 npm run test:uat+grep -c 'UAT harness: 33/33 assertions passed'to empirically verify JSZip fallback works at the SAVE→zip layer post-polyfill-removal. - 04-04 T1 + T2 (BLOCKER 2): Option B applied — SAVE_ARCHIVE dispatched via
chrome.runtime.sendMessage({type: 'SAVE_ARCHIVE'}, ...)directly from the harness page realm (matches established A5/A11/A12/A13/A26/A28/A29/A30/A31 precedent). The non-existentwindow.__mokoshHarness.dispatchSaveArchiveis NOT introduced; gates verifygrep -c 'dispatchSaveArchive'returns 0 across all harness files + spike script. - 04-06 T4 (BLOCKER 1): Canonical SW chunk glob
dist/assets/index.ts-*.jsused for all bundle gates (Gates 2/3/4) — replaces the misquoteddist/assets/index*-bg.jswhich matched no files (silent 0-grep = spurious PASS). New glob-existence pre-gatels dist/assets/index.ts-*.js | wc -l >= 1validates the glob matches BEFORE running grep gates. - 04-07 T1 (WARNING 4): Ack-literal grep added —
grep -cE 'approved|All good|APPROVED|approved by|operator ack|all good' 04-VERIFICATION.md >= 1ensureshuman_verification[0].evidencecontains a real operator ack (not a placeholder).
Wave 0 Requirements
Per RESEARCH finding 5, 6 new test files anticipated as Wave 0 RED scaffolds for audit-P1 / ROADMAP-SC items:
- ⬜
tests/build/no-new-function-in-sw-chunk.test.ts— grepdist/assets/index.ts-*.jsfornew Function(count = 0 after setimmediate polyfill replacement - ⬜
tests/build/dead-code-grep.test.ts— ROADMAP SC #4: rgpermissions\.request+ duplicate offscreen inline string in src/ = 0 hits - ⬜
tests/content/fetch-interception.test.ts— audit P1 #11: Request-arg vs string-arg case forargs[0] - ⬜
tests/content/navigation-tracking.test.ts— audit P1 #14: module-level previousUrl tracking - ⬜
tests/content/rrweb-timestamps.test.ts— audit P1 #15: epoch vs page-load-relative - ⬜
tests/welcome/inline-svg.test.ts— UI-SPEC:?rawimport + DOMParser inline-SVG + currentColor resolves via CSS
Existing infrastructure already in place (inherited from Phases 1-3):
- ✅
tests/uat/extension-page-harness.ts— page-side assertA* host (extend with assertA33+) - ✅
tests/uat/lib/harness-page-driver.ts— host-side driveA* host (extend with driveA33+ + improved driveA29) - ✅
tests/uat/harness.test.ts— orchestrator (extend) - ✅
tests/uat/lib/assertions.ts— shared helpers - ✅
tests/uat/lib/zip.ts— jszip-based archive parsing - ✅
tests/uat/lib/launch.ts— Puppeteer Chrome launch + extension load - ✅
tests/background/no-test-hooks-in-prod-bundle.test.ts— FORBIDDEN_HOOK_STRINGS lockstep
wave_0_complete: false until 6 new test files committed per planner Wave 0.
Manual-Only Verifications
| Behavior | Requirement | Why Manual | Test Instructions |
|---|---|---|---|
| Dark-surface logo visual contrast judgment (WCAG ratio not specified in UI-SPEC) | UI-SPEC acceptance criterion #2 + operator empirical | Aesthetic judgment of deep-indigo stroke on madder-orange wrapper in dark-OS context — UI-SPEC defers to operator empirical checkpoint | Load extension in OS dark mode; open welcome page; verify mark wrapper still madder, stroke is deep-indigo, contrast is acceptable. Plan 04-06 operator empirical UAT cycle covers this. |
| Cursor visibility verification | ROADMAP cursor visibility item per D-P4-03 | Already shipped at src/offscreen/recorder.ts:285 per Plan 01-09 (RESEARCH finding 4) — Plan 04-06 downgrades to verification + stale-note correction; minor manual check of one captured frame to confirm cursor present | Load extension, start recording, click anywhere, SAVE archive; open video/last_30sec.webm in Chrome; verify cursor visible in playback. |
All other Phase 4 behaviors have automated verification via vitest (Wave 0 unit tests) + UAT harness (A33+) + bundle gates.
Validation Sign-Off
- All tasks have
<automated>verify or Wave 0 dependencies — pending planner fill-in - Sampling continuity: no 3 consecutive tasks without automated verify — verify after planner fills table
- Wave 0 covers all MISSING references — 6 new test files anticipated; planner confirms count
- No watch-mode flags — verify in planner output (focused commands use
--run) - Feedback latency < ~2.5 min default (5-min idle test on dedicated lane) — confirmed by RESEARCH
nyquist_compliant: trueset in frontmatter — pending sign-off after planner completes- REVISION iter-2 gates applied to 4 revised tasks (04-02 T2, 04-04 T1, 04-04 T2, 04-06 T4, 04-07 T1)
Approval: pending (planner fills per-task map; checker validates)