Files
editor/packages/mcp/test-reports/villa-azul/v8-roundtrip.md
T
Adrian PerezandClaude Opus 4.7 f230d9a401 test(mcp): Villa Azul + 10-agent deep verification
Builds a larger, richer house than Casa del Sol via MCP save_scene
(no injection hack), then dispatches 10 parallel verifiers across
schema, geometry, dimensions, openings, HTTP, page render,
parentage, round-trip, spatial, visual.

Villa Azul — 56 nodes, validate_scene=true, 44KB on disk:
- 15x10m building envelope (vs Casa del Sol's 12x8)
- 9 interior zones (master bed/bath, bed 2/3, shared bath,
  living/dining, kitchen, entry hall, corridor)
- 10 doors + 12 windows (all cut successfully)
- 4 exterior zones (pool 8x4 + basin slab at -2m, outdoor kitchen,
  driveway, back patio)
- 5 rail-style fences (vs Casa del Sol's privacy) with 2m entrance gap

Verification: 108 checks, 104 PASS, 4 findings:
- V1 schema: 56/56
- V2 geometry: 7/7 (perimeter closes, interior T-junctions, no
  zone overlaps, fence gap verified)
- V3 dimensions: 13/13 zone areas exact (1 spec mismatch on site
  polygon default, not a build bug)
- V4 openings: 22/22 dimensional fit, surfaced a tool gap in
  cut_opening (no adjacency check) + my build packed too tightly
- V5 HTTP: 10/10 (GET/PUT/PATCH/DELETE/HEAD, If-Match conflicts)
- V6 page: 14/14 (/scene/:id 81KB, /scenes 20KB, 404 fallback)
- V7 parentage: surfaced CROSS_CUTTING §2 site->building->level
  parentId=null (pre-existing in core's loadScene)
- V8 round-trip: 10/10 byte-equal, duplicate_level -> 110 nodes
- V9 spatial: 12/12 (find_nodes, measure, constraints resource)
- V10 visual: HTML fallback (Chrome extension disconnected during
  run); API layer intact

Follow-up tracked: `cut_opening` should check opening-adjacency on
the same wall (minimum gap) to catch tight packing during patch
construction. Currently returns success and relies on the UI to
visualise the overlap.

Live at http://localhost:3002/scene/a6e7919eacbe.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:39:08 +02:00

2.7 KiB

Villa Azul — V8 Load-Save Round-Trip Report

  • Generated: 2026-04-19T18:37:01.857Z
  • Shared source: /tmp/pascal-villa/scenes/a6e7919eacbe.json
  • Isolated data dir: /tmp/pascal-villa-v8
  • Transport: stdio (bun /Users/adrian/Desktop/editor/.worktrees/mcp-server/packages/mcp/dist/bin/pascal-mcp.js --stdio)
  • New sceneId (copy): d346bd83beb9
  • Rebuilt sceneId (apply_patch): 0a264e09564f
  • Duplicated sceneId: db09cfe4a8fc

Original node-type counts

Type Count
building 1
door 10
fence 5
level 1
site 1
slab 1
wall 12
window 12
zone 13
total 56

Results

# Check Status Detail
1 1.read-original PASS nodes=56, roots=1, types={"site":1,"building":1,"level":1,"wall":12,"zone":13,"door":10,"window":12,"slab":1,"fence":5}
2 2.spawn-isolated-stdio PASS PASCAL_DATA_DIR=/tmp/pascal-villa-v8
3 3.save_scene(copy) PASS id=d346bd83beb9 version=1 nodes=56 bytes=44285
4 4a.load→get_scene ids preserved PASS 56 ids, match=true
5 4b.load→get_scene rootNodeIds PASS orig=[site_5mzaasm5o9a9d0sf] loaded=[site_5mzaasm5o9a9d0sf]
6 4c.load→get_scene deep-equal per-node PASS diffs=0
7 5.apply_patch rebuild counts PASS ops=53 created=53 total=56 diffs=none
8 6.duplicate_level + save + reload counts PASS valid=true new=54 total=110 diffs=none
9 7.stableStringify(orig.nodes) === stableStringify(reloaded.nodes) PASS orig=23333ch reloaded=23333ch equal=true
10 7b.on-disk isolated file graph === shared file graph PASS path=/tmp/pascal-villa-v8/scenes/d346bd83beb9.json equal=true

Summary

  • Passed: 10/10
  • Failed: 0/10
  • Overall: PASS

Original vs loaded-after-save — per-type count diff

Type Original Loaded Match
building 1 1 YES
door 10 10 YES
fence 5 5 YES
level 1 1 YES
site 1 1 YES
slab 1 1 YES
wall 12 12 YES
window 12 12 YES
zone 13 13 YES

Notes

  • save_scene({ includeCurrentScene: false, graph }) should persist the graph verbatim, preserving all node ids.
  • stableStringify normalises key order so byte equality is order-independent; this is the canonical "deep-equal" check here.
  • Step 5 rebuilds the scene by save/load-ing a shell (site+building+level) then replaying every remaining node as an apply_patch create op. Only counts-per-type are compared (node ids on the rebuild will equal the originals because we reuse the same ids in the patches).
  • Step 6 exercises duplicate_level against the copied scene; the site/building remain shared (count=1), while per-level types should double.