Repository navigation
Underground: the ground steps aside over a basement, the world turns to earth below it, a ground line in the levels, and a foundation under every house - #1097
Conversation
…y the person and the agent With a level below grade active, the site's ground (the lot's fill, its sculpted terrain and the horizon disc) no longer lies over it: the owner's villa Lower Ground and the Victor's parking were under an opaque lid. - core: isLevelBelowGrade(nodes, levelId): the level's world floor (stack base, building height on the site, highest standing slab top) more than 0.3 m under the flat ground. Villa Lower Ground and Victor Parking are below; the Victor's Floor 1 (-0.11 m) and the villa's Piano Nobile are not. - viewer: groundAside (not persisted) and a 'ground-aside' hidden reason in scene-visibility: a held surface is out of the colour passes, the shadow map, every raycaster and Follow's sight, so a click reaches the floor the eye sees. siteSurfaces() moves here from bake-thumbnail, with siteGroundSurfaces() for the surfaces flagged as ground. - nodes: the site's ground meshes carry the flag and hold themselves aside through a ref while groundAside is set; the lot line and contours stay. - editor: both level displays keep groundAside on the rule (levels above hidden, selected level below grade), never in the site phase. - capture: an interior view sets the ground aside under a floor below grade and stands it under one at grade; a picture of the whole building (view_scene, hero, sheets) stands on its ground whatever the person's level. sceneViewPlan looks into a below-grade level targeted alone, so view_scene does on both lanes. The live hold uses scene-visibility's layer reasons, not visible=false: a capture can then lift or apply it for one render without touching what the sheets hide by visibility. Tests: the predicate on the owner numbers; the plan's default interior; the hold and its capture lift; the site renderer's surfaces held and released (flat and terrain); the flag's rule and the site-phase exception; the agent's planned eye sees the basement floor, not the lawn, on both owner scenes (trimmed fixtures). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s pictures Step 2 of the ground veil (Design A): where step 1 set the ground aside, a faint veil is now drawn in its place, so grade still reads. - Each solid ground surface (the lot's fill, the terrain's surface, cut edges and skirt, the horizon disc) has a veil twin: same geometry and place, a direct child of the site. The veil is a MeshBasicNodeMaterial (TSL): 10% of the theme's ground colour, unlit, double-sided, no depth write, alpha 0 to the scene pass's normal and diffuse attachments (as the dust and the circulation ribbon), never picked, stripped from exports. The disc's veil covers only the ground past the lot (positionWorld even-odd test, insideLotNode now takes the point) and fades out by twice the lot's radius. - The veil is on the scene layer, not GRID_LAYER: the capture camera disables GRID_LAYER (thumbnail-generator), and the agent's pictures must show the same veil. - State: the host's level display sets belowGrade (the fact); groundMode 'auto' | 'solid' is the person's override (not persisted); groundVeiled() derives what the renderers read. The capture ignores the override: an agent looking into a basement needs the floor. - Capture: temporarilyVeilGround(veiled) holds the solid ground and shows the twins for one render (a below-grade interior), or the reverse (a picture of the whole building), then gives the person's view back. - Follow's sight: the veil is never hit (no-op raycast) and its plain opacity is the veil's, under Follow's 0.1 see-through bar. - view_scene: the note says a floor below grade is seen through the veiled ground (MCP lane here; the chat lane passes the plan's interior too), and the description says a below-grade level targeted alone is looked into. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… and the grade ring The rest of the ground veil's step 2 (Design A): - View bar: over a level below grade, "Below grade · ground veiled" (or "solid") with Auto / Solid, the person's override (useViewer.groundMode), beside the Flow switch of each 3D view. - Lights: while the ground is veiled, a shadowless directional light shines from the eye along the view and the hemisphere's ground colour takes its sky colour (lerped like the rest): the live counterpart of the interior capture's lightInterior. Intensity 1, to be judged on screen. - Grade ring: core's belowGradeFootprints(nodes) joins each below-grade level's floor slabs into outlines in the site's plan (through the building's transform, terrain-support-query's levelLocalToWorldXZ, now exported within core); the site draws an unbroken dark ribbon along each, as a veil (shown with it, in captures too). For every below-grade level, not only the active one, so an agent's picture of another basement has it. - Terrain no longer shades a veiled basement: the held solid surfaces are out of the shadow map too (the key light's shadow camera sees layers 0 and SHADOW_ONLY only), so no new code was needed for castShadow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… hill stands in the way A level counted as below grade only under the flat datum, so a hillside raised 6 m at the street left every floor 'at grade' and the ground never veiled. Core now answers a level's standing against the sculpted terrain over its own footprint (levelGradeStanding: at, partly, or below grade, the flat-datum answer untouched on flat sites); the view bar names a partly-buried floor, the grade ring follows it, and view_scene's notes state the facts. Where terrain stands between the eye and the shown level or building — the owner's plateau beside a flattened pad — a ground window opens: per fragment in TSL, a ray from the eye through a ground fragment that goes on to meet the shown box is veiled there and solid elsewhere, mask-cut from the solid ground (shadows too) with the veil sheet drawn only in the window. A few throttled CPU sight lines (terrainBetweenEyeAndBox) decide whether it opens and what the bar says, and keep clicks honest through the veiled patch. The site phase keeps solid ground; Ground: Auto/Solid stays the person's override. Captures apply the same window from their own camera (temporarilyGroundWindowForCapture in interior and view_scene poses), so a picture from uphill sees the house on both agent lanes.
…e, partly buried from above Three review blockers on the ground window and roof veil: - Both agent lanes ask with perspective/ortho poses, not cameraPose, so exterior view_scene inherited the person's window while its note claimed a veil. Posed exterior captures now go through exteriorGroundForCapture and decide from their own camera; the person's window is restored by the same restore owner, on failure too. - Exterior and whole-building captures inherited the person's hidden or cut roof. They now emit wholeRoof beside wholeWalls; the roof renderer lifts its veil for the frame (clip off, layers, materials and picks restored) and the next live frame puts it back. Interior captures emit no wholeRoof and keep the veil. - A partly buried floor could stay solid from above: sight samples over the footprint were discarded, and the five corner/centre lines never met ground sculpted over the middle rooms. Sight lines now run to a grid over the floor with in-footprint samples counted (the straight-down line included), so the window opens there; and sceneViewNote's partly-below-grade line states only the standing — the veil claim comes from the pose-based fact, which the capture now backs.
…st the shown level, vignette, the sky's light down and warm, the veil in the earth's tone, eased over 0.7 s One factor drives it: the shown level below grade with the ground on Auto, or the eye under the ground at its own position (a free orbit under the lid). It eases in and out over a short crossing, instant when the animation setting is Off or motion is reduced, and Solid turns it off with the veil. The shown level's materials are untouched; the eye's own light comes up as the sky's comes down. A capture is taken in the world's own light. The view bar names the level quietly once the scene says it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…e, the eye's light up as the sky's comes down, the grade ring as the lid's rim Rendered on a real GPU against both owner scenes: the rooms keep 90-100% of their light, the backdrop turns to a warm soil, the grade ring reads as a light rim. The wiki says what each piece is and where it lives. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ure; the fog's box comes from the selection when the host keeps no ground window; the hero bake holds the ambiance off The fill no longer mounts at full: the ambiance owns its intensity (0 to 2.4 over the crossing, 0 in a capture, so a picture taken from elsewhere gets no live light from the person's eye). Without a ground window box from the host (Preview, the embed) the fog keeps the shown level, or the building, clear from the selection alone. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…er a level below grade seen from above, the dark mode only when the eye is under the ground Above the ground the ground stays solid and a hole opens in it over the below-grade footprint (a signed-distance texture baked from the grade ring's polygons, one texture fetch and one perlin lookup per ground fragment, a thin slate rim along the cut, no shadows on the solid ground while it is open); picks and Follow's sight fall through its guaranteed core. The faint veil sheets remain for the ground window and for a capture. Below the ground the scene goes to the dark scene theme's own tokens (backdrop, fog, vignette, sky light, grade ring), the crossing a noise mask closing over the screen, eased 0.7 s, instant with Animation Off. The trigger is only the eye crossing the ground surface (0.10 m band each side). The view bar's label is as it was. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ys the day before the blobs reveal it The dark mode's palette is one place beside the scene theme tokens (UNDERGROUND_PALETTE): every stop a grey, since neither dark scene theme is neutral (night is navy). Backdrop gradient stops, vignette, the hole's rim, the grade ring and the sky light's tint read from it. During the crossing the day's backdrop greys and dims over the first half, so the anthracite blobs spread over a neutral picture, not a blue sky. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ent the scene has a level below grade, so changing floors changes uniforms only Measured on the villa: the switch to the basement had a 430-450 ms frame, its CPU time in TSL node builds (the fill light mounting changes every lit material's shader). With the fill always mounted the warm switch is 17 ms. A viewer store flag hasLevelBelowGrade (set by GroundHole from the below-grade footprints) makes the ground materials carry the hole's mask only when it is true, and the fill is mounted once from then on. Tests: the mask is in the ground from the first level below grade, the eye's fill stays once mounted, and switching floors adds no light and rebuilds no ground material.
…t feather and a thin light line (rim variant a)
…building where it stands (a new lowest floor at offset 0 had lifted every floor above it by its height)
…tween it and grade, per level standing computed once), and the stack's box for the underground's fog
…n level and those between it and grade, fog over the shown stack, eye kept over the ground when the pivot goes down) and the walkthrough (solid ground, no dive, the earth outside a basement window)
…s to a deep level; wiki: several levels below grade and the walkthrough
…e, as core's groundHeightAt takes it on this base
…rade (groundLevelId, default read off the elevations), levels under it read below grade, set_ground_level seats the building and renumbers, a basement stacks under the lowest floor without moving the ground floor (add_level), list_levels and verify_scene read it; the reference inventory classifies groundLevelId
…one undo step), set_ground_level on the MCP, the building's groundLevelId as a plain level id
…-basement mansion
…t under the hole goes
…along the hole's own contour down to the shown level's floor, a dark floor under what the level does not cover; uniforms only, none while the eye is under the ground
…ple 0.4 s fade, switched by a uniform
…at or hatched face), quiet noise, today's — all uniforms; wiki
…et's earth walls); the hatched look removed; the fade is the default transition
…earth walls and the simple fade Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ng and stem, derived), the standard foundation numbers in one place, a drawsFoundation capability, the deepest drawn Y and the lowest ground
… terrain and wall helpers (terrainFieldOf and groundHeightAt take the site alone; getWallCenterlineSegments joins the wall curve helpers)
deepestDrawnY took the highest standing slab top and subtracted the thickest slab of the level, recessed plates included. On a split-level floor that is too shallow (the lowest underside is a different slab), and a thick recessed plate could deepen it past anything drawn. Each slab now gives its own underside (elevation less thickness); the footing sits under the lowest floor underside, never above the walls' base, as the generic foundation places it, and a recessed slab (a basin) counts by its own underside with no footing. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Heads up: the latest push fails the It's just over the limit, so it may be a perf regression from the basement changes rather than flakiness. Could you take a look and get it green? Once CI passes we'll do a visual review. |
Eleven files conflicted; main wins what it solved, the underground work stays beside it.
view_scene (core, MCP): main's Solo/Exploded presentation and room interior ({zoneId}) stay as they
are; the underground branch's below-grade reading is added to them. A level below grade targeted
alone is looked into when no interior is asked (belowGradeInterior, after main's interiorRequest);
sceneViewNote carries the below-grade, ground-in-the-way and room-eye notes together; the contract
text is main's with the sentence on a level below grade; the MCP result keeps main's
presentation field.
Viewer: temporarilySetGroundAside beside main's temporarilyHideFromScene; DEFAULT_UNDERGROUND_LOOK
beside main's resolveLook / chooseLook and both tests; lights.tsx keeps main's store-driven look
(getSceneTheme is no longer used there) and the underground sky lights. lights.test.tsx was added
on both sides: main keeps the name, the underground ambiance tests move to lights-ambiance.test.tsx.
Nodes: the site ground keeps the underground veil and takes main's showGround gate, on the horizon
disc's veil too, so an authored landscape that replaces the ground replaces its veil.
shared-tools.ts: setGroundLevelTool and validateDesignTool are both imported.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
showGround false says other geometry (an authored landscape, hosted on a level above the ground) supplies the ground. Shown over a basement, the level display hides the storeys above it, the landscape with them, and the site drew nothing: the basement's outer walls and footing were seen through nothing. While a level below grade is shown (belowGrade, set by the level display), the site's ground now stands in, with its hole, veil and pit, drawn as with showGround on, so only the opening is seen and the walls only when diving. With a level at or above grade shown, or no level below grade in the scene, showGround is the author's and the two grounds never draw together. siteGroundShown (viewer store) is the rule; the site renderer reads it. Tests: the pure rule, the stand-in on, off, live with the display, on a sculpted site, with the hole in its mask, and main's showGround behaviour with no level below grade. Wiki and the pascal-3d skill say it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The footing under a level below grade tops out at the underside of its floor plate, and the pit seen through the hole drew its dark floor 5 cm under the top of that plate: for the default plate (0.05 thick) the two are one plane, so the 10 cm of footing outside the wall flickered against the pit floor. The same holds for a thinner plate and for one whose top is the level plane. core: levelPlateUndersideWorldY is the one reading of that underside (genericFoundation took it from its own copy), groundPitFloorY is where the pit draws its floor: 5 cm under the plate's top as before, and 2 cm under the underside where those would meet. The pit draws its floor and its walls' foot there; the footing and the stems are untouched, so the footing stays visible through the hole as it was meant to be. Tests: the footing's top against the pit floor on four plates (red at the previous head, with the owner's numbers: footing -2.9002..-2.697, pit floor -2.697), the pit floor function, the underside, and the renderer's uniform end to end. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
With a level below grade shown (the floors above hidden, the ground open over it), Follow's look at the whole house, which comes after furniture lands and after every finished commit, showed the floors above and so closed the ground; the next piece on the basement opened it again. In a turn of seven pieces on the basement and one over it the hole closed six times and opened five. That look is now a look at the shown level (stayOnLevel: the level whole, no roof to clear, no floor to change) while the ground is veiled over it. An edit on a floor the basement view hides still switches to that floor and back, and the person's own display is what Follow keeps, not the finished house. Tests: the basement's standing under three pieces (red at the previous head: six flips instead of none), one excursion to the ground floor (one close and one reopening), and stayOnLevel. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The ground was a closed sheet across the whole footprint of a basement until its level was shown, so a stairwell, a floor opening, a section or a walkthrough on the basement stair met a plate of ground instead of the basement. The part of a basement under the footprint of the levels over it is now cut open in the ground whatever level is shown, the walkthrough included. From outside nothing changes (the storeys stand over it); a basement reaching out under the garden stays closed past the house, no pit in the garden, until its level is shown, and the hole of the level shown does the rest as it did. coveredBelowGradeFootprints (core) is the rule: per building, the part of each visible level below grade (a walk-out only where the ground stands over it) under the floor slabs of the visible levels over it that are not fully buried, a slab's own openings not counted; a courtyard outline is left closed. The site renderer cuts it as geometry, like a recessed slab (ground fill, horizon disc and sculpted terrain, clipped to the lot), so picks pass through with no CPU twin and the hole, ring, pit and fog are untouched. It closes in one case: a level below grade shown with the ground on Solid, where nothing covers it and Solid asks for solid ground. Tests: the cover rule (under the house, under the garden, deep levels, openings, placement, hidden levels, another building, courtyard, a cellar under a walk-out) and the ground (ground floor, walkthrough, basement on Auto and Solid, live with the display, no basement, hidden levels, a sunken room beside it, sculpted ground, a ray, showGround off). Wiki says it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…branch The footing z-fight and Follow Pascal fixes (drawnFloorY, groundPitFloorY, levelPlateUndersideWorldY) come in beside the ground stand-in and the always-open ground. Conflicts were textual only: the core imports and exports of below-grade-footprints, its test file (both sides appended tests), and the `buried` selector of the site renderer, which now carries drawnFloorY and covered together. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A level shown fully below grade is seen through the hole in solid ground. The ground window also opened over it on any site that has a terrain field (terrainBetweenEyeAndBox asks the height at the eye's own XZ, which is above a buried floor on any ground, sculpted or not). The window cuts the solid ground in the box's silhouette and stands the 10% veil in its place: the basement's outer walls were seen through a translucent ground in front of the opening instead of only the opening. GroundWindowSystem now closes the window while the ground is wholesale-veiled (groundVeiled: a level below grade shown, Ground on Auto, not partly below grade, not the walkthrough). A level at grade, or only partly below it, keeps the window, as the view bar and the wiki say; Solid keeps it closed. A capture still asks the window: it sets the solid ground aside already, so the cut lands on nothing. Test: at grade the window opens; fully below grade it does not (the word, the box, the veil sheets); partly below it does; Solid closes it. Red without the change. The wiki says it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
add_site_surface lays a lawn, a driveway or a path as a slab on the building's ground level, marked metadata.flatwork. The grade logic read it as a floor of that level: a lot-wide lawn under a hill made the ground level read partly below grade, and the hole opened over the lawn's buried part (the hillside); the same lawn would cover every basement reaching under the garden, and stretches the level's ground box over the whole lot. isSiteFlatwork (core) names it, with the check agent-operations/site.ts already made inline, and the three slab walkers leave it out: levelGradeStanding's footprint samples, the buried and cover plates of belowGradeFootprints and coveredBelowGradeFootprints, and the level's ground box. Tests: a lawn on the ground level over a hill leaves it at grade and the hole the basement's (control: the same lawn as a plain slab is a floor, partly below grade, the hole reaches x = 15); a lawn does not cover a basement reaching under the garden (control: a plain slab does, up to the hill); the ground floor's box is the house. The three are red without the change. The wiki says it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
belowGradeFloorY read levelFloorWorldY, the top of the highest standing slab, and groundPitFloorY hung the dark floor 5 cm under it. On a level with a raised part and a sunken room the pit sat at the raised plate, so the dark floor passed through the sunken room instead of under it. levelLowestFloorWorldY gives the top of the lowest floor slab (a recessed slab and site flatwork are not floors, as for the other storey walkers); the pit hangs from it, so no floor of the level lies under the dark floor. The same value now sizes the wall's topsoil band, which scales with the depth to the floor. A level with one floor reads as before. Tests (the first red without the change): a split-level basement puts the pit 5 cm under the sunken room's top and above none of its floors; a basin and a lawn laid lower do not take the pit down. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…depth The flatwork commit left it out of the grade samples, the buried and cover plates and the ground box, but levelPlateUndersideWorldY (the pit's clearance and the generic foundation's footing plane), levelFloorWorldY's standing top and deepestDrawnY still read a lawn or driveway on the level as a floor slab. A driveway laid lower than the house's slab took the pit floor, the footing and the dive depth down with it. One isFloorSlab predicate (not recessed, not flatwork) in storey.ts serves the standing top, the lowest top and the underside; deepestDrawnY skips flatwork. The wiki lists them. Tests (all three red without the change): a driveway deeper than the house's slab leaves the dive depth, the pit's clearance from the plate underside and the footing's top where the house puts them. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
# Conflicts: # packages/core/src/agent-tools/view-scene.ts
…ts highest floor The hole's cut over a level partly below grade (belowGradeFootprints) and the standing's buried-sample count (levelGradeStanding) compared every slab to levelFloorWorldY, the top of the highest floor. The sunken room of a split level was judged against the raised part's top, so the ground over the room was not "over the floor" until it stood 0.3 m above the raised part, and the hole stayed closed (or the level read at grade) over space that was already under the terrain. Each slab is now judged at its own floor: levelPlaneWorldY (the level's stacked base and the building's height) plus the slab's elevation. footprintFloorSamples carries that Y with each sample; footprintSamples is its plan-only view. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
levelGroundBox floored its box at levelFloorWorldY, the top of the highest floor. The ground window aims its sight lines at that floor, so ground standing over the sunken room of a split level but under the raised part's top did not arm the window, and the fog's clear region and the window's box stopped above the room. The box now runs from the lowest floor (levelLowestFloorWorldY) to the same top as before, the highest floor's ceiling. A level with one floor is boxed as before. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… of its basement The walker's floor is the merged collider mesh, and the site ground in it (the flat slab, or the terrain) was a sheet across the whole lot. The ground is drawn open over the covered below-grade footprint (coveredBelowGradeFootprints) so the stairs show, but the sheet stayed in the collider: a walker going down the stair from the ground floor met it at grade and could go no deeper. cutGroundCollider cuts the ground's triangles against the same rings in plan (heights and normals interpolated from the source triangle, facing kept; a failed clip keeps the triangle whole), for the flat slab and the terrain alike. Outside the rings the ground is as before. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
levelGradeStanding fell back, with no terrain field, to isLevelBelowGrade, which reads the highest floor slab. A split level whose raised part sits at the datum read at grade, so the ring, the hole footprint and the pit's depth never took in the sunken room beside it. With no field and no ground line named, each floor slab is now judged against the datum (the sampled path's reading, with a flat ground): none buried is at grade, all buried is below grade, some is partly below grade. levelPlates puts only the buried slabs of such a level in its buried set. A level of floors at one height reads as it did. isLevelBelowGrade stays the whole-level predicate (it derives the ground level); its doc says so. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A habitable room (bedroom, living, kitchen) needs a window to outside or the IRC R303.1 exceptions:
artificial light and mechanical ventilation. The declaration had no writer both surfaces share. The
shared set_zone_intent patch now takes daylight: { artificialLight, mechanicalVentilation } | null,
kept in the zone's metadata under daylight (no schema field, no migration; null clears it, other
metadata stays). The tool contract and the command's patch schema both carry it, so the chat and
the hosted MCP offer it from one contract; the description says what it is for.
Tests: the command (set, beside other metadata, cleared, untouched by other patches, both booleans
or a refusal), the tool's patch, and two shared cases (declare; clear) that the table runs on the
core operations, the MCP and the chat alike. The metadata-key inventory lists daylight as a value,
not a reference. The wiki says it (space-detection).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…dation does A basement's outline walls are built as foundation walls (FOUNDATION_CONSTRUCTIONS): CMU block with furring, or insulated and waterproofed cast concrete. Their assembly has no finish layer, so the exterior face fell back to the white slot default, above grade and from under the ground, unlike the generic foundation drawn under them. wallAssemblyExposedStructure (core) names what a wall's exterior face shows when its assembly has no cladding and no lining over a masonry or concrete core: 'cmu' or 'concrete', null for a wall with a cladding, a lined partition, a framed or foam core, or an unresolved exterior side. The viewer's wall materials dress that face with the generic foundation's own materials, moved to viewer/src/lib/foundation-materials.ts and shared with generic-foundation.tsx: courses of block with joints and the block colours (courses from the world's Y, bonded along the face's world planar U), the same grained concrete; solid shading keeps a flat colour. Paint on the face still wins, interior faces are unchanged, and no WALL_ASSEMBLY_PRESETS entry changes its look. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Thanks for flagging. That run (88042f5) was a one-off: the scaling test compares two timings and landed at 6.14 against a limit of 6. It has passed on every CI run of this PR since then, at every later head including the current one, and the full CI on c4b8822 went green. The PR doesn't touch ifc-converter, so this reads as runner load rather than a regression. The remaining red on some runs is the 5 verify_scene tests that fail on main too. |
Conflicts resolved keeping main's behavior, carried into the scene runtime: - history-control: main's commit authors, write guards and derived-write notes; the derived-write notes and write guards are per scene environment, like the PR's other commit state, so a detached scene's writes never reach the live commit or end the editor's preview. - roof elevation: main's wall-top support (#1097) and roofsKeptOverStorey (#1112 era roof levels) run in both the editor's system and reconcileDocument; roofsKeptOverStorey selects roofs and reads level elevations only once a roof stands over a storey. - DECISIONS.md: main's E-017 stays; the scene runtime entry is E-018. - MCP: main's tool executor and recorder wrap the PR's scene scope; compileObject reads the scene before its first await and takes a pre-minted id; main's activeLevelId, briefs, bpy and materials go through the bridge's runtime. - agent operations: main's new code selects what it reads (queryNodes) or says why it reads the whole scene, per the raw-scene-enumeration rule.
…ot how the scene is built Trims nine test files of the underground work (ground veil/hole/standin/covered, generic foundation, lights ambiance, underground ambiance, thumbnail capture, below-grade follow) by 960 lines. Each file keeps its owner- and Bugbot-reported defects as behaviour checks and drops mesh, material and userData inventories and cases that re-prove a core rule. Scene builders and tables are shared. Tests only. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 55d7251. Configure here.
| .join(' ') | ||
| .split(',') | ||
| .map((name) => name.trim()), | ||
| ) |
There was a problem hiding this comment.
Dutch addresses miss European region
Medium Severity
regionOfAddress folds the last address token and looks it up in EUROPEAN_COUNTRY_NAMES, which lists netherlands and nederland but not the netherlands. A dossier that ends with the common English form therefore stays generic and new basement walls get the 8 in CMU stack instead of cast concrete.
Reviewed by Cursor Bugbot for commit 55d7251. Configure here.


Base:
pascalorg/editormain(82153a03c). Head: branchfeat/underground-20261016(cee68cf36). 44 commits; squash-merge.Pairs with the private-editor PR "Underground: the chat and hosted MCP serve set_ground_level, Bones draws its foundation under the ground, the scene program reads grade". That PR pins this head and must be re-pinned to the squash commit once this one merges.
What a person can now do
groundLevelId; absent = the lowest level not under the datum). One undo step. Adding a basement goes under the lowest floor and leaves the building where it stands.drawsFoundation).set_ground_level;list_levelsanswersgroundLevelsand, per level,gradeStandingandisGroundLevel;verify_scenesaysbasement_at_gradeandground_level_unseated; the MCP guide names the ground line.What is in it
core:groundLevelIdon a building, the ground line (ground-level,grade-standing, subpath exports),buildGroundLevelChanges,buildLevelBelowChanges,belowGradeFloorY, the generic foundation andFOUNDATION_STANDARD,foundationReadingOf/ construction by region (block, cast concrete),set_ground_levelcontract and operation,drawsFoundationon a node definition, the hole's box that follows the level shown.viewer: the ground veil and ground window, the underground ambiance, the eye's fill,undergroundLook.nodes/site: the hole, its edges, the pit, the generic foundation renderer.editor: orbit dive and its clearance, view bar toggle, levels panel,addStoreyBelow.mcp:set_ground_leveland README/guide rows. Docs:wiki/architecture/{layers,materials-and-themes,vertical-model}.md, the pascal-3d skill's tool workflows.groundLevelIdis an optional field on the building node.What stays on R&D
noise,quiet,section) and the noise transition: still in the code asEDGE_LOOKSrows and a uniform, unexposed. The shipped look isDEFAULT_UNDERGROUND_LOOK = { edge: 'section-earth', transition: 'fade' }.create_story_shellfoundation walls (MCP-only on main); storey facts onlist_levels; the grade-aware core checks (room-light, enclosure, unroofed storey, facade columns, circulation) and the Flow grade part.Main wins duplicates: Wassim's floor foundations (#976), editing foundations (#1039) and
recessed-slab-ground-holes.tsare untouched; the generic foundation is derived and independent ofset_floor_foundation.Tests
With dists rebuilt, against the baseline at
82153a03c(no new failure in any suite):check-typesThe viewer failure (
R3F 9.8.2 pointer-event differential), the 3 editor failures (standalone history source invalidation) and the 2 type errors (ceiling-bracket-batch.test.ts) exist on main. Biome: 0 errors, 166 warnings (165 on main; the added one is a core fixture imported by relative path inthumbnail-generator.test.ts).Pictures (headless WebGPU, no GPU farm): from above with the section-earth edge, below, the fade midway, a foundation from under the ground, a basement with its walls. Not tested by a person in a browser.
Note
High Risk
Changes vertical stacking, terrain/grade interpretation, and automatic wall construction in agent operations—errors could mis-seat buildings or assign wrong foundation assemblies across regions.
Overview
Underground and ground-line modeling lands in core and agent tools: buildings can name a ground floor (
groundLevelId),set_ground_levelseats the stack (foundation top over grade, renumber indices, optional building Y shift), andadd_levelbelow usesbuildLevelBelowChangesso existing floors keep their world positions.Below-grade behavior is computed from terrain, named ground line, and per-slab floors (excluding site flatwork):
levelGradeStanding, hole/cover footprints (belowGradeFootprints,coveredBelowGradeFootprints), pit depth, and scene-view notes/auto interior for fully buried levels.list_levelsandverify_scenesurface ground seating and mis-seated basements.Foundation walls apply on below-grade
add_wall/create_roomby site region (US CMU+furring vs Europe cast concrete); explicit thickness/assembly unchanged.set_zone_intentcan storedaylight(artificial light + mechanical ventilation) in zone metadata beside other fields.Package subpath exports add
./grade-standingand./ground-level; contracts documentgroundLevelIdanddaylightmetadata.Reviewed by Cursor Bugbot for commit 55d7251. Bugbot is set up for automated code reviews on this repo. Configure here.