Files
editor/packages/mcp/test-reports/research/R1-persistence.md
T
Adrian PerezandClaude Opus 4.7 42bd05db9c docs(mcp): add 10-agent research on scene-save workflow
10 parallel research agents (R1-R10) investigated whether MCP can save
scenes as saveable entities that the user later opens in the editor —
rather than injecting via a dev-only window.__pascalScene hook.

Key findings:
- Editor is already backend-agnostic via onLoad/onSave callbacks (R2,R7)
- Current persistence is localStorage-only, single key (R1)
- Zero dynamic routes and no backend code yet — env declared (R4,R5)
- File import exists as "Load Build" but lacks Zod validation (R6)
- MCP-written scenes load cleanly into the editor today (R6, Casa del
  Sol test already proved this)
- Best path: filesystem-handoff this week, Supabase in weeks 2-4,
  Supabase Realtime for live mode in Q2. Skip Yjs for now. (R8)
- 4-5 weeks to private beta, 10-14 to GA (R9)
- 10 high-value ideas ranked; "photo -> scene" is the unblocker (R10)

SYNTHESIS.md pulls all 10 reports together with the recommended
implementation plan.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 18:47:36 +02:00

2.6 KiB
Raw Blame History

R1 — Persistence layer

TL;DR

  • Scene data: single-key localStorage, pascal-editor-scene, shape { nodes, rootNodeIds }. Written by the autosave hook with 1 s debounce; flushed on beforeunload.
  • UI preferences, viewer prefs, audio: three separate Zustand-persist stores, each with its own localStorage key.
  • Asset binaries (textures): IndexedDB via idb-keyval, keys asset_data:<uuid>.
  • Backend persistence: NONE in this repo. No Supabase calls, no API routes for scenes, no database integration.
  • Scene identity / listing: NONE. One scene per origin per browser.

Write pathways

When What Where
1 s after any scene mutation { nodes, rootNodeIds }onSave callback (if provided) else localStorage['pascal-editor-scene'] packages/editor/src/hooks/use-auto-save.ts:104135
Every UI state mutation pascal-editor-ui-preferences Zustand persist in use-editor.tsx:372607
Every viewer state mutation viewer-preferences Zustand persist in use-viewer.ts:81220
Every audio state mutation pascal-audio-settings use-audio.tsx:2243
On beforeunload Final scene snapshot use-auto-save.ts:137147

Read pathways

  1. Editor mount (editor/index.tsx:765796):
    • If host supplied onLoadawait onLoad()
    • Else → loadSceneFromLocalStorage()
    • Apply via useScene.setScene(nodes, rootNodeIds)
  2. Selection hydrationsyncEditorSelectionFromCurrentScene() (lib/scene.ts:251332)
  3. Zustand persist hydrates UI/viewer/audio stores automatically on first subscriber

What's NOT persisted

  • Undo/redo history (useScene.temporal — in-memory only)
  • Active tool state (movingNode, editingHole, curvingWall)
  • Camera position/rotation
  • Collections (stored in nodes array but not in the persist partialize)
  • Three.js mesh/material cache

Multi-scene support

  • Single global key pascal-editor-scene. No scene id, name, thumbnail, version.
  • projectId prop scopes UI selection (building/level/zone) but NOT scene data.
  • No listing, no metadata, no per-project isolation of the scene itself.

Gap to "MCP writes → user opens saved scene"

Needs:

  1. Scene entity layer: id, name, projectId, created_at, thumbnail_url.
  2. Backend table (or filesystem for local dev).
  3. MCP tools for scene lifecycle (save_scene, list_scenes, load_scene, delete_scene).
  4. Editor route /scene/[id] that reads scene by id on mount.
  5. Host-app onLoad(() => fetchScene(sceneId)).

Foundation is solid — SceneGraph type + applySceneGraphToEditor are production-ready; only the entity layer is missing.