r214.1 VSIL Editor Stability + History Correctness — AI Summary

Status: ✅ All green · 18/18 r214.1 unit · 21/21 r214.1 Playwright · 0 regressions

Branch: feat/id9-r214-editor-polish @ bc3c338 (pushed to origin, on top of cc216ec)

Base: feat/id9-r213-vsil-editor @ 3d51f99

TL;DR

The 7 fixes

1. Synchronous history-applied event — fireHistoryApplied is now called synchronously inside applySnapshot (was queueMicrotask). Subscribers (LayersPanel) update in the same React commit. Tests can use waitForTimeout(50) instead of 800.

2. Snapshot includes zoom + tool — SelectionSnapshot now has zoom?: number and tool?: string. Every push includes them. Undo restores all 5 surfaces (activeRegionId, activeAssetId, layers, zoom, tool).

3. Initial snapshot includes zoom + tool — initSingleton now includes zoom: singleton.currentZoom and tool: singleton.currentTool in the initial snap. Undo from a fresh state restores defaults.

4. setCurrentZoom/setCurrentTool notify subscribers — Without this, zoom/tool updates weren't reflected in the UI. Now both call notifySubscribers() after the mutation.

5. Layer box label: pointer-events: none — The label child was intercepting clicks on the parent box. Now pointerEvents: 'none' lets clicks pass through.

6. VSILEditor refocuses on mouseDown — On any non-input child click, the editor div refocuses itself (via queueMicrotask). Ensures keydown events bubble up to the shortcuts listener reliably.

7. Removed dummy editPreset state counter — Was a hack to force re-renders. Now zoom/tool are in the singleton with notifications.

What this means

The Editor is now actually stable. Undo/redo works consistently across all 5 surfaces (activeRegionId, activeAssetId, layers, zoom, tool). Clicking a child element doesn't lose keyboard focus. Layer click hitboxes work. Tests are deterministic (no more flaky waitForTimeout(800) after Cmd+Z).

The 3 critical r214.1 details

1. Synchronous event dispatch — fireHistoryApplied is called inside applySnapshot, not via queueMicrotask. The canUndo/canRedo flags still use microtask to avoid React warnings, but the layers restoration is now synchronous.

2. Snapshot includes zoom + tool — The singleton's currentZoom and currentTool are read at push time, embedded in the snap, and restored on undo. Initial snap also includes them so undo from a fresh state works.

3. Static imports + focus management — The shortcuts hook is unchanged (still attached to the editor div). The new onMouseDown refocuses the editor div on any non-input child click. The label child has pointer-events: none to not intercept clicks.

Test results

What's next

1. Operator review of the r214.1 stability in the dev server (port 5301)

2. Operator decision on merge (r213 + r214 + r214.1 = the full ID9 chrome + Editor + polish + stability)

3. Production deploy — npm run build + scp to 185.249.73.178?

4. Layer drag-to-reorder in Layers panel

5. Multi-select layers (Shift+click)

6. Context menu on layer boxes (right-click)

Open questions

1. Merge r214.1 (bc3c338) to main now, or wait for r215 (multi-select, drag-to-reorder)?

2. Production deploy — npm run build + scp to 185.249.73.178?

3. Inspector → AI integration (Phase 4.3 Step 2)?

4. Layer drag-to-reorder — high priority, or wait for r215?

Verification

cd /workspace/vibecoder-standalone-r214
npx tsx src/host/editor/__tests__/editor-r214-1.test.tsx  # 18/18
npx vite --port 5301 --host 0.0.0.0 &
R2141_BASE=http://localhost:5301 node scripts/smoke/r214-1-smoke.spec.cjs  # 21/21
grep -l "

Expected: 271/271 total tests pass, 0 iframes, 0 postMessage.