* Add roof surface placement support for items Items (e.g. solar panels) can now be placed on sloped roof surfaces. The placement system computes euler rotation from the roof surface normal so items sit flush on the slope instead of going inside. - Add roofStrategy to placement-strategies with enter/move/click/leave - Wire roof:enter/move/click/leave events in the placement coordinator - Add calculateRoofRotation in placement-math using surface normals - Support full 3D cursor rotation for sloped surfaces - Items on roofs are parented to the level with world-space rotation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fixed conflict * fix(viewer): keep outlines during camera movement * fix(editor): prevent floorplan clipping during rotation * fix(editor): keep compass rotation in sync Stream live headings in 2D and 3D, and defer restoring the compositor rotation preview until the committed floor-plan state is ready to paint so pointer release cannot snap back. * fix(editor): stabilize floorplan and camera sync * fix floorplan registry scale subscriptions --------- Co-authored-by: Claude Opus 4.6 <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) |
| materials-and-themes | Surface colour: surface roles, colour presets, the textures axis, and scene themes (appearance / ground / clay tints) |
| item-authoring | Content-author contract for catalog item GLBs: slot_ material naming, authored defaults + pascal_material extras, the cutout reserved mesh, UV world scale, and the validated Blender/export recipe |
| plugin-authoring | Public contract for external plugins — Plugin shape, setPluginDiscovery, lifecycle, what's in and out of v1 |
| tools | Editor tools structure, 2D↔3D behavioral parity, manipulation constraints, and Shift bypass defaults |
| measurements | Persistent measurement data, 2D/3D draft ownership, snapping, units, and visibility |
| interaction-scope | The authoritative interaction state machine ("the spine"): InteractionScope union, the begin/update/end/endIf contract, the raycast hot-set, and the overlay scope matrix |
| 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 |
| vertical-model | Stored level heights, plane-bound wall/ceiling tops, slab placement + thickness, support hosts, clamp rules, and the load migration |
| 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.
- When the diff touches placement / move / handle / reshape / box-select / paint or any overlay or picking behaviour, also read interaction-scope.
- The remaining pages on demand, based on what the diff touches.