Two regressions in the Stage D port surfaced the same gap: the wiki already said "the mesh offset must mirror the useLiveTransforms entry" but didn't spell out that for polygon-based kinds (slab / fence / ceiling / wall), the value to mirror is the DELTA (the group's local position) — not the world location of the polygon's center. Expanded the live-drag rule with a position-based vs polygon-based split and an explicit note that ParametricNodeRenderer reconciles the group's position via React on every Zustand notification, so the two writes must agree to the exact value or they fight every frame. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Architecture
Canonical rules for code that touches packages/core, packages/viewer, packages/editor, packages/mcp, or apps/editor. Read on demand from AGENTS.md and from .agents/skills/review-architecture/SKILL.md.
Pages
| Page | Covers |
|---|---|
| layers | Three.js layer constants, ownership, and rendering separation |
| systems | Core and viewer systems architecture |
| renderers | Node renderer pattern in packages/viewer |
| node-definitions | Three-checkbox composition model for registry-driven kinds (geometry / renderer / system) |
| tools | Editor tools structure in apps/editor |
| viewer-isolation | Keeping @pascal-app/viewer editor-agnostic |
| selection-managers | Two-layer selection (viewer + editor), events, outliner |
| scene-registry | Global node ID → Object3D map and useRegistry |
| spatial-queries | Placement validation (canPlaceOnFloor/Wall/Ceiling) for tools |
| node-schemas | Zod schema pattern for node types, createNode, updateNode |
| events | Typed event bus — emitting and listening to node and grid events |
| creating-rules | How to add or update a page in this folder |
Reading order for an architecture review
- layers, systems, renderers, tools, viewer-isolation — required every review.
- The remaining pages on demand, based on what the diff touches.