Files
editor/packages/mcp/test-reports/research/R6-file-io.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.7 KiB
Raw Blame History

R6 — File I/O pathways

TL;DR

  • Export: 2 JSON pathways + 3 binary (GLB/STL/OBJ) pathways.
  • Import: 1 JSON pathway ("Load Build"), no Zod validation at boundary.
  • No drag-drop, no clipboard-paste JSON import.
  • Round-trip export → re-import works; MCP-written JSON loads cleanly IF structure matches.

Exports

Trigger Handler File Output
Settings → "Save Build" handleSaveBuild settings-panel/index.tsx:205216 layout_YYYY-MM-DD.json
Cmd palette → "Export Scene (JSON)" editor.export.json command-palette/editor-commands.tsx:329346 scene_YYYY-MM-DD.json
Settings/palette → "Export GLB/STL/OBJ" export-manager.tsx editor/export-manager.tsx:7178 binary 3D geometry

Both JSON paths serialise { nodes: useScene.getState().nodes, rootNodeIds: useScene.getState().rootNodeIds }. No metadata (no name, no created_at, no projectId).

Import

"Load Build"

  • settings-panel/index.tsx:218239
  • Accept: application/json
  • Handler: JSON.parse → check data.nodes && data.rootNodeIds → call useScene.setScene(nodes, rootNodeIds)
  • No Zod validation. Confirmed the security-audit flag from Phase 3.

setScene behaviour (core/store/use-scene.ts:242271)

  1. migrateNodes() — runs a few backward-compat patches. Stair nodes are zod-safeParsed and SILENTLY DROPPED on failure; other types are unvalidated.
  2. Orphan pruning — deletes any node whose parentId isn't present in the dict.
  3. setState with cleaned nodes + dirtyNodes: new Set().
  4. Marks every node dirty to trigger re-render.

Critical gap: Invalid type strings silently load. Systems will later fail to find a renderer for them and the node will be invisible but consume state.

Round-trip fidelity

Scenario Loads clean?
Export → re-import
MCP writes well-formed { nodes, rootNodeIds } (confirmed: Casa del Sol scene.json loads into the editor)
MCP writes bad node.type ⚠️ Silent load, invisible node
MCP writes broken parentId chain ⚠️ Orphans silently deleted
MCP writes missing children: [] on container ⚠️ Core treats as undefined → system ignores

Missing / nice-to-have

  • Drag-drop JSON onto viewport
  • URL-param load: ?load=<publicJsonUrl>
  • Clipboard paste of JSON blob
  • importFromFile with Zod validation at the boundary
  • File-format version field (formatVersion: "1") for forward-compat

Recommendation

Every "save to cloud" implementation MUST Zod-validate at the boundary with AnyNode.safeParse per node + structural checks on rootNodeIds. The tool in MCP (validate_scene) already does this — run it before any save.