# Phase 01 Deferred Items

Out-of-scope discoveries surfaced during plan execution that didn't directly
caused-by the current plan's changes. Per `<deviation_rules>` SCOPE
BOUNDARY: log here, don't fix.

## Plan 01-12 (Wave 7 pre-checkpoint bundle gates discovery)

### `new Function("" + I)` reachable in SW chunk via setimmediate polyfill

- **Discovered:** 2026-05-20 during Wave 7 pre-checkpoint bundle gates
- **Location:** `dist/assets/index.ts-<hash>.js` (the main SW chunk produced
  by `npm run build`)
- **Context:** `vite-plugin-node-polyfills` (configured in
  `vite.config.ts:nodePolyfills` for `Buffer`) bundles the upstream `setimmediate`
  package which contains the construct: `b.setImmediate=function(I){typeof
  I!="function"&&(I=new Function(""+I));...}`. The `new Function` is the
  fallback when `setImmediate` is called with a non-function argument.
- **Reachability check:** Production code path `src/background/index.ts` +
  `src/offscreen/recorder.ts` + their transitive deps DO NOT call
  `setImmediate(string)`. The construct is dead in the static call graph
  but Rollup conservatively preserves it (it's behind a runtime type
  check, not a static dead branch).
- **MV3 CSP angle:** Modern Chrome (≥ MV3) does enforce CSP `script-src
  'self'`, and `new Function('...')` evaluates a string-as-code which
  some CSPs reject. However, the default MV3 manifest's
  `content_security_policy` allows it for service workers in current
  Chrome — Plan 01-12 did NOT introduce a tighter CSP override, so
  this is benign at present.
- **Scope:** Pre-existing across all of Phase 1 history. Verified by
  `git checkout main -- src/background/index.ts vite.config.ts &&
  npm run build && grep -c 'new Function' dist/assets/index.ts-*.js`
  returning the same count. Plan 01-12 made no changes to the
  polyfill configuration; this entry exists for future tightening
  (Phase 5 hardening, or a dedicated MV3 CSP-audit plan).
- **Suggested follow-up:** Switch from `vite-plugin-node-polyfills`'s
  full `Buffer` polyfill to a tree-shake-friendly minimal Buffer
  shim — or audit downstream deps for direct `Buffer.*` usage and
  inline the few needed primitives. Either approach drops the
  setimmediate polyfill entirely.

Documented in 01-12-SUMMARY.md "Known Limitations" section.

### Resolved in Phase 4 Plan 04-02 (2026-05-21)

The setimmediate polyfill `new Function` literal was dropped from the
SW chunk via a 2-edit coherent landing in Plan 04-02 Wave 1 (commit
hash recorded post-commit in 04-02-SUMMARY.md):

1. **vite.config.ts:** `nodePolyfills({ include: ['buffer'], exclude:
   ['setimmediate'], ... })` — explicit `exclude` array per the plugin's
   public TypeScript-typed config. Drops the transitive `setimmediate`
   bundle from the SW chunk.

2. **src/background/index.ts (top-of-module prelude, BEFORE first import):**
   ```ts
   if (typeof globalThis.setImmediate === 'undefined') {
     (globalThis as { setImmediate?: ... }).setImmediate =
       (fn, ...args) => queueMicrotask(() => fn(...args));
   }
   ```
   Inline `queueMicrotask`-based fast-path; JSZip detects
   `globalThis.setImmediate` already-defined and uses it directly (no
   fallback to its own MessageChannel chain — though that chain remains
   intact and would handle a future world where this prelude is removed).

**Verification gates (Plan 04-02):**
- `grep -c 'new Function' dist/assets/index.ts-*.js` returns **0** (was 1).
- `tests/build/no-new-function-in-sw-chunk.test.ts` GREEN (was RED in Task 1).
- UAT harness 33/33 GREEN preserved (JSZip's zip-assembly path empirically
  validated end-to-end at the SAVE→zip layer).
- vitest baseline +2 (the new build-gate tests) flipped GREEN.

Approach (a) from RESEARCH §Q1 was adopted; approach (b) failed (the
plugin's `globals` type does not expose `setImmediate`); approach (c)
was rejected for v1 close (Phase 4 charter is hardening — ship the fix).

This entry is now CLOSED.
