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
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.
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).
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.
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)
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?
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.