Wall-mounted items join doors/windows on roof-segment wall faces, and
the storage model moves to FACE-LOCAL coordinates so hosted children
track segment edits live.
- Children store roofFace + position [u, v, z-from-mid-plane] with
rotation 0 in-frame — the exact wall-child conventions (the wall
volume's mid-plane lands on the nominal footprint). A shared
<RoofFaceHostFrame> derives segment pose + face frame from the
live-override-merged segment: children follow resize handle drags in
real time and never jump on commit. No re-anchor cascade needed —
position is authoritative, the frame is derived. migrateNodes
converts branch-era segment-local data.
- Items: roofWallStrategy + roof:* handlers in the placement
coordinator (surface 'roof-wall'), Shift free-place normalized with
walls, ItemSystem wall-side push extended to segment hosts, correct
2D plan glyphs via face→segment→roof pose composition. The roof
hit resolver + overlap guard moved to @pascal-app/editor (the
coordinator lives there; nodes already depends on editor).
- Cuts: subtractAccessoryCuts extracted and applied in BOTH the
merged-shell and per-segment CSG paths (full edit mode / painted
segments used to lose every hole), built from the CURRENT host
geometry and live-effective children so holes follow segment and
opening drags.
- Handle rig: the grandparent portal now maps the node's world pose
into the portal frame instead of composing parent+node registry
poses — correct for any nesting (the face-frame group broke the
old assumption), identical for walls.
- Host-field hygiene: useDraftNode.commit/adopt and the window panel
duplicate forward roofSegmentId/roofFace/wallId; every roof↔wall
re-anchor clears and every revert restores them.
Codex-reviewed (design consultation, adversarial rounds on the
replaced cascade and on this refactor); frame conventions locked by
unit tests. Record: private-editor plans/editor-roof-wall-openings.md.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>