- Add PORT_PING_MS (25s) and PORT_RECONNECT_MS (290s) constants
- Replace stub bootstrap with full long-lived port lifecycle:
- connectPort() registers onMessage/onDisconnect listeners, schedules
25s PING postMessages and a 290s pre-emptive reconnect (Pitfall 4
belt-and-braces against Chrome's ~5min port lifetime cap)
- onDisconnect handler synchronously calls connectPort() again
(Plan 02 port.test.ts pins this; flips reconnect test to GREEN)
- REQUEST_BUFFER over the port responds with { type: 'BUFFER',
chunks: getBuffer() } (Plan 05 SW-side will issue REQUEST_BUFFER
on export)
- Keep defensive guard on chrome.runtime sub-APIs so pure ring-buffer
and codec-check tests can import the module without a full chrome stub
- Remove the no-longer-needed 'void keepalivePort' workaround (the
variable is now used by onPortMessage + connectPort)
- T-1-04 mitigation: explicit message-shape switch in onPortMessage
(any unknown port message type silently dropped); comment block
documents the SW-side sender.id check contract for Plan 05
GREEN: all 4 test files in tests/offscreen/ pass (9 tests total —
ring-buffer 4 + codec-check 2 + handshake 1 + port 2).
npx tsc --noEmit exits 0. Zero 'as any' / '@ts-ignore' in recorder.ts.