Files
mokosh/.planning/phases/01-stabilize-video-pipeline/01-02-SUMMARY.md
Mark edc605d475 docs(01-02): complete wave-0 test infrastructure plan
- 01-02-SUMMARY.md created (Vitest 4.1.6 installed; 4 RED test files
  pinning Plans 03+04 contracts; tests/fixtures/.gitkeep marker)
- STATE.md advanced: plan 2/7 -> 3/7; progress 14% -> 29%; metric row
  added; 3 decisions logged; session continuity updated
- ROADMAP.md progress row updated: Phase 1 = 2/7 In Progress
- REQUIREMENTS.md: REVERTED premature [x] + "Complete" marking of
  REQ-video-ring-buffer (Plan 01-01 mistakenly marked it; the requirement
  is satisfied by Plans 03+04+07's implementation + ffprobe gate, not by
  RED test scaffolding). Now reads "[ ]" + "In Progress" — honest state.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 17:28:49 +02:00

15 KiB

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions patterns-established requirements-completed duration completed
01-stabilize-video-pipeline 02 testing
vitest
tdd
red-tests
ring-buffer
codec-check
offscreen-handshake
port-keepalive
phase provides
01-stabilize-video-pipeline Plan 01-01 doc cascade (DEC-003/DEC-010 amended; manifest swapped)
Vitest 4.1.6 installed under devDependencies
vitest.config.ts at repo root (Node env, tests/**/*.test.ts include)
npm test script wired to vitest run
4 RED test files at tests/offscreen/ pinning the contracts for Plans 03 and 04
tests/fixtures/.gitkeep marker (Plan 07 will drop a known-good last_30sec.webm)
01-03
01-04
01-07
added patterns
vitest@^4 (devDep)
Vitest Node-environment unit tests (Blob shimmed via undici)
RED-first TDD: failing tests committed BEFORE production code (Nyquist sampling)
Hand-rolled chrome.runtime stub (no vitest-chrome dependency — minimize supply chain per T-1-NEW-02-01)
`as unknown as T` cast pattern (no `as any`, no `@ts-ignore` per CLAUDE.md / tsconfig strict)
vi.resetModules() between import-side-effect tests for isolation (handshake + port + codec all run module-load effects)
created modified
vitest.config.ts
tests/offscreen/ring-buffer.test.ts
tests/offscreen/codec-check.test.ts
tests/offscreen/handshake.test.ts
tests/offscreen/port.test.ts
tests/fixtures/.gitkeep
package.json (vitest devDep + npm test script)
package-lock.json (npm install regenerated)
.planning/REQUIREMENTS.md (reverted premature [x] + Complete marking on REQ-video-ring-buffer)
Pinned vitest at ^4 (4.1.6 latest stable; 5.x still beta per npm view vitest versions on 2026-05-15)
No vitest-chrome dependency added — hand-rolled minimal chrome stub in each test (4-file scope doesn't justify the supply-chain widening; T-1-NEW-02-01)
Type cast pattern is 'as unknown as T' uniformly (CLAUDE.md / tsconfig strict): zero 'as any', zero '@ts-ignore' across all four test files (verified by grep)
REQ-video-ring-buffer reverted to in-progress: Plan 01-01 (doc cascade) prematurely marked it Complete; the requirement is satisfied by Plans 03 + 04 + 07's ffprobe gate, not by RED test scaffolding
Vitest config minimal: Node env, no globals, no path aliases, typecheck disabled (tsc runs separately in npm run build)
Tests in tests/offscreen/*.test.ts; production code in src/offscreen/recorder.ts; tests reach into src via relative '../../src/...' import
Module-load side-effect testing pattern: stub chrome + MediaRecorder on globalThis BEFORE await import(), use vi.resetModules() between tests so import effects re-fire
4min 2026-05-15

Phase 1 Plan 02: Wave-0 Test Infrastructure Summary

Vitest 4.1.6 installed, vitest.config.ts wired for Node-environment tests, and four RED test files (ring-buffer, codec-check, handshake, port) committed against the not-yet-existing src/offscreen/recorder.ts — pinning the contracts Plans 03 and 04 must flip to GREEN.

Performance

  • Duration: ~4 min
  • Started: 2026-05-15T15:21:24Z
  • Completed: 2026-05-15T15:25:57Z
  • Tasks: 5
  • Files modified: 8 (1 modified existing + 6 created + 1 administrative revert)

Accomplishments

  • Vitest 4.1.6 installed as a devDependency; node_modules/vitest/ materialized; npx vitest --version prints vitest/4.1.6 linux-x64 node-v24.14.0.
  • vitest.config.ts at repo root: Node environment, scoped to tests/**/*.test.ts, typecheck disabled (separate tsc --noEmit runs in npm run build). No globals: true; tests explicitly import { describe, it, expect } from 'vitest'.
  • Four RED test files all import from '../../src/offscreen/recorder' (which Plan 03 will create); npx vitest run reports Test Files 4 failed (4); Tests 5 failed (5), every failure with Error: Cannot find module '/src/offscreen/recorder' imported from .... This is the precise Nyquist TDD signal — contract pinned, implementation gap waiting to be filled.
  • tests/fixtures/.gitkeep committed so the directory survives clean checkouts; Plan 07 drops a known-good last_30sec.webm there after the manual smoke pass.
  • Zero as any and zero @ts-ignore across the four test files (verified by grep). The cast pattern is as unknown as T, which narrows progressively without bypassing the type-checker — CLAUDE.md compliant.

Task Commits

Each task was committed atomically:

  1. Task 1: Install Vitest, add npm test scriptebf015a (test)
  2. Task 2: Create vitest.config.ts57fa29e (test)
  3. Task 3: Create tests/offscreen/ring-buffer.test.ts + tests/fixtures/.gitkeep2e73a21 (test)
  4. Task 4: Create tests/offscreen/codec-check.test.tsd7840a8 (test)
  5. Task 5: Create tests/offscreen/handshake.test.ts + tests/offscreen/port.test.ts408aa33 (test)

Files Created/Modified

  • vitest.config.ts (12 lines) — defineConfig wrapper; Node env; include pattern; typecheck off.
  • tests/offscreen/ring-buffer.test.ts (40 lines) — 4 RED tests for D-10 (header pinning) + D-11 (30 s trim).
  • tests/offscreen/codec-check.test.ts (43 lines) — 2 RED tests for D-20 (strict-mode, no silent fallback).
  • tests/offscreen/handshake.test.ts (67 lines) — 1 RED test for Pattern 4 (OFFSCREEN_READY emitted at module load after onMessage.addListener).
  • tests/offscreen/port.test.ts (89 lines) — 2 RED tests for Pattern 5 / Pitfall 4 (port.connect on load + reconnect on onDisconnect).
  • tests/fixtures/.gitkeep (0 bytes) — marker for the fixture dir.
  • package.json — added vitest@^4 devDep + "test": "vitest run" script.
  • package-lock.json — regenerated by npm install (added 126 packages, 127 audited).
  • .planning/REQUIREMENTS.md — reverted premature [x] + Complete marking on REQ-video-ring-buffer (deviation; see below).

Vitest RED Run Output (verbatim summary)

 RUN  v4.1.6 /home/parf/projects/work/repremium

 FAIL  tests/offscreen/ring-buffer.test.ts [ tests/offscreen/ring-buffer.test.ts ]
Error: Cannot find module '../../src/offscreen/recorder' imported from /home/parf/projects/work/repremium/tests/offscreen/ring-buffer.test.ts

 FAIL  tests/offscreen/codec-check.test.ts > codec strict mode > throws on unsupported vp9 and emits RECORDING_ERROR
Error: Cannot find module '/src/offscreen/recorder' imported from /home/parf/projects/work/repremium/tests/offscreen/codec-check.test.ts

 FAIL  tests/offscreen/codec-check.test.ts > codec strict mode > does not throw when vp9 IS supported
Error: Cannot find module '/src/offscreen/recorder' imported from /home/parf/projects/work/repremium/tests/offscreen/codec-check.test.ts

 FAIL  tests/offscreen/handshake.test.ts > OFFSCREEN_READY handshake > sends OFFSCREEN_READY after listener registration
Error: Cannot find module '/src/offscreen/recorder' imported from /home/parf/projects/work/repremium/tests/offscreen/handshake.test.ts

 FAIL  tests/offscreen/port.test.ts > port reconnect > connects on module load
Error: Cannot find module '/src/offscreen/recorder' imported from /home/parf/projects/work/repremium/tests/offscreen/port.test.ts

 FAIL  tests/offscreen/port.test.ts > port reconnect > reconnects when port disconnects
Error: Cannot find module '/src/offscreen/recorder' imported from /home/parf/projects/work/repremium/tests/offscreen/port.test.ts

 Test Files  4 failed (4)
      Tests  5 failed (5)

Every failure is at the IMPORT step, not at the assertion step — that is the RED gate. Plans 03 and 04 flip these tests to GREEN by creating src/offscreen/recorder.ts with the contract specified in the plan's <interfaces> block.

Decisions Made

  • Vitest at ^4, not @latest: Plan instructions said "pin Vitest at a major version" and the latest stable major on install day (2026-05-15) is 4.x (4.1.6); the 5.x line is still in beta. Pinning to ^4 gives deterministic resolution without locking us to a single patch.
  • No vitest-chrome package: The four test files use a hand-rolled minimal chrome.runtime stub via interfaces, which is lighter than pulling a whole mock library for a four-file test setup. Aligns with threat T-1-NEW-02-01 (minimize supply chain).
  • typecheck.enabled: false in vitest.config.ts: TypeScript checking via Vitest would duplicate the work npm run build already does via tsc && vite build. Faster feedback loop, single source of truth for the type errors.
  • include: ['tests/**/*.test.ts']: Scoped strictly to tests/; production code under src/ is never accidentally picked up as a test file even if a *.test.ts lands there.
  • No path aliases: tsconfig.json does not define any; tests use relative imports ('../../src/offscreen/recorder'). Re-confirmed during review.

Deviations from Plan

Auto-fixed Issues

1. [Rule 1 - Bug] Reverted premature REQ-video-ring-buffer marking left over from Plan 01-01

  • Found during: After Task 5, before SUMMARY (administrative correction noted in this plan's prompt context)
  • Issue: Plan 01-01 (doc cascade) prematurely marked REQ-video-ring-buffer as [x] in REQUIREMENTS.md line 19 AND as Complete in the Traceability table at line 189. Per the Plan 01-01 SUMMARY frontmatter, it also listed requirements-completed: [REQ-video-ring-buffer]. This is incorrect — the requirement is satisfied by the implementation in Plans 03 (recorder) + 04 (handshake + port) and the ffprobe gate in Plan 07. The doc cascade in Plan 01-01 only amended decision/constraint wording.
  • Fix: Reverted the two REQUIREMENTS.md markings:
    • line 19: - [x] **REQ-video-ring-buffer**: ...- [ ] **REQ-video-ring-buffer**: ...
    • line 189: | REQ-video-ring-buffer | Phase 1 | Complete || REQ-video-ring-buffer | Phase 1 | In Progress |
  • Files modified: .planning/REQUIREMENTS.md
  • Verification: grep '^- \[x\] \*\*REQ-video-ring-buffer\*\*' .planning/REQUIREMENTS.md returns 0; grep 'In Progress' .planning/REQUIREMENTS.md | grep REQ-video-ring-buffer returns 1.
  • Committed in: SUMMARY commit (administrative revert bundled with this plan's metadata commit, not a per-task commit, because it corrects prior-plan state outside the scope of any Task 1-5 file set).

2. [Rule 3 - Blocking, micro] package-lock.json already existed despite plan wording

  • Found during: Task 1 (npm install)
  • Issue: The plan's Task 1 action block said "If npm install produces a package-lock.json for the first time (it should — there is no committed lockfile today)". A package-lock.json was already in the working tree from a prior baseline commit (Plan 01-00 or earlier). This was not a blocker — npm install updated it in place (1186 line diff, refreshing transitive deps to add Vitest's tree).
  • Fix: Committed the modified package-lock.json alongside package.json in Task 1's commit, as the plan instructed for the first-creation case. Behavior is identical.
  • Files modified: None additional (already included in ebf015a).
  • Verification: test -f package-lock.json returns 0; grep '"vitest"' package-lock.json | head -1 returns the vitest entry.
  • Committed in: ebf015a (Task 1 commit).

Total deviations: 2 auto-fixed (1 prior-plan correction; 1 plan-wording mismatch with reality, no functional change). Impact on plan: Both deviations are pure administrative cleanup; no code-path divergence from the plan. The REQUIREMENTS.md revert is critical to keep the requirements-traceability matrix honest — the in-progress REQ-video-ring-buffer status correctly reflects that the implementation lands in Plans 03/04/07.

Issues Encountered

  • None. The five tasks executed exactly as the plan specified. The RED gate fired as designed at every step; banned-pattern grep checks returned 0 every time; vitest config validation passed on first run.

User Setup Required

None — no external service configuration required. Vitest is a pure dev-time dependency; tests run via npm test or npx vitest run on any machine that has cloned the repo and run npm install.

Next Phase Readiness

  • Plan 01-03 (offscreen recorder TDD) is unblocked. It must export the following surface from src/offscreen/recorder.ts to flip the RED tests to GREEN:

    // Ring-buffer (pure functions; testable in Node)
    export function addChunk(blob: { size: number }, timestamp: number): void;
    export function trimAged(now: number): void;
    export function getBuffer(): Array<{ data: { size: number }; timestamp: number; isFirst?: boolean }>;
    export function resetBuffer(): void;
    
    // Codec strict-mode (D-20)
    export function assertCodecSupported(): void;  // throws Error("vp9 unsupported") + sendMessage({ type: 'RECORDING_ERROR' })
    
    // Constants
    export const VIDEO_BUFFER_DURATION_MS: number;  // = 30_000
    
  • Plan 01-04 (port keepalive + handshake) is also unblocked. Its TDD contract: importing src/offscreen/recorder.ts MUST as a side-effect:

    1. Call chrome.runtime.onMessage.addListener(...) at least once.
    2. Call chrome.runtime.sendMessage({ type: 'OFFSCREEN_READY' }) exactly once, AFTER step 1.
    3. Call chrome.runtime.connect({ name: 'video-keepalive' }) exactly once at module load.
    4. On the connected port firing onDisconnect, immediately call chrome.runtime.connect(...) again (synchronous reconnect — Pitfall 4 mitigation).
  • No outstanding blockers. The doc cascade (Plan 01-01) is consistent; the test infrastructure (Plan 01-02) is wired and producing the expected RED signal; Plans 03 through 07 can execute in their declared waves.

Self-Check: PASSED

All claimed files exist on disk:

  • vitest.config.ts, tests/offscreen/{ring-buffer,codec-check,handshake,port}.test.ts, tests/fixtures/.gitkeep, package-lock.json, node_modules/vitest, 01-02-SUMMARY.md — all FOUND.

All five task commits present in git log:

  • ebf015a (Task 1: vitest install)
  • 57fa29e (Task 2: vitest.config.ts)
  • 2e73a21 (Task 3: RED ring-buffer tests + fixtures)
  • d7840a8 (Task 4: RED codec-check tests)
  • 408aa33 (Task 5: RED handshake + port tests)

All plan-level verification gates pass:

  • npx vitest --versionvitest/4.1.6 linux-x64 node-v24.14.0
  • ls tests/offscreen/*.test.ts | wc -l → 4
  • npx vitest run 2>&1 | grep -cE "Failed to resolve|Cannot find module" → 6 (one per test entry, 4 distinct files, all RED at module-resolution)
  • grep -cE "as any|@ts-ignore" tests/offscreen/*.test.ts → 0 across all four files

Phase: 01-stabilize-video-pipeline Completed: 2026-05-15