feat(mcp): detect floorplan openings stairs and furniture - #875
zoechow412-ui wants to merge 1 commit into
Conversation
|
I hit an error while handling your request (Model unavailable on AI Gateway free tier: Free tier users do not have access to this model. Upgrade to paid credits at https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai%3Fmodal%3Dtop-up for unrestricted…). Please try again, rephrase, or reach out if it keeps failing. Error id: 79791c5c-5f59-484e-8476-c41244f630fc |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 596a8db. Configure here.
| }).map((entry) => entry.aabb) | ||
| const doorKeepouts = collectDoorKeepouts(Object.values(nodes), { levelId }).map( | ||
| (entry) => entry.aabb, | ||
| ) |
There was a problem hiding this comment.
Door keepouts ignored during placement
High Severity
Furniture placement calls collectDoorKeepouts with a levelId filter before the level node is inserted into nodes. resolveNodeLevelId then returns null for every wall, so the keepout list is always empty and items can sit in door swing zones.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 596a8db. Configure here.
| nodes[stair.id as AnyNodeId] = linkedStair as AnyNodeT | ||
| nodes[segment.id as AnyNodeId] = segment as AnyNodeT | ||
| levelChildren.push(stair.id) | ||
| stairsAdded++ |
There was a problem hiding this comment.
Stairs and furniture missing parentId
Medium Severity
New StairNode and ItemNode records are pushed onto levelChildren without parentId, unlike walls and zones in the same builder. Core spatial-grid lookup only walks parentId and then treats them as level default, so editor queries and elevation can miss them.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 596a8db. Configure here.
| const door = DoorNode.parse({ | ||
| wallId: wall.id, | ||
| parentId: wall.id, | ||
| position: [localX, height / 2, 0], |
There was a problem hiding this comment.
Openings can exceed host wall
Low Severity
When a detected door or window is wider than its nearest wall, localX still clamps to width / 2 and the opening is created. cut_opening rejects that case; here the opening extends past both wall ends.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 596a8db. Configure here.


What does this PR do?
How to test
Screenshots / screen recording
Checklist
bun devbun checkto verify)mainbranchNote
Medium Risk
Expands vision parsing and scene graph construction (wall parenting, placement heuristics); failures are mostly soft via notes, but bad placements or opening attachment could produce misleading scenes.
Overview
Extends floor-plan vision and
photo_to_sceneso a single photo can yield more than walls and rooms: doors, windows, stairs, and catalog furniture.Vision contract:
analyze_floorplan_imageand thephoto_to_scenesampling prompt/Zod schema now include optionaldoors,windows,stairs, andfurniturearrays (defaults to empty for backward-compatible JSON).Scene build: After walls/zones, openings are snapped to the nearest wall (skipped with
notesif farther than ~0.75 m), converted to wall-localDoorNode/WindowNode, stairs becomeStairNode+StairSegmentNode, and furniture is resolved via catalog aliases then placed with existing layout-clearance (findValidPlacement, door keepouts, room bounds). Unmatched or unplaceable items are recorded innotes, not silently dropped.API surface: Tool responses add
doors,windows,stairs, andfurniturecounts alongsidewalls/rooms; docs and the happy-path test mock the richer vision payload and assert the new node types in the bridge.Reviewed by Cursor Bugbot for commit 596a8db. Bugbot is set up for automated code reviews on this repo. Configure here.