Skip to content

core: shared pure plan-footprint math for spatial-grid and MCP - #600

Open
ActArtech wants to merge 2 commits into
pascalorg:mainfrom
ActArtech:feat/core-plan-footprint
Open

core: shared pure plan-footprint math for spatial-grid and MCP#600
ActArtech wants to merge 2 commits into
pascalorg:mainfrom
ActArtech:feat/core-plan-footprint

Conversation

@ActArtech

@ActArtech ActArtech commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Extracts rotation-aware plan (XZ) footprint math into a pure, Node-safe core module so spatial-grid, alignment anchors, and (later) MCP layout clearance share one formula after #569.

  • Add packages/core/src/lib/plan-footprint.ts: corners, AABB, expand-then-intersect gap overlap, scaled item helper (null for wall/ceiling hosts)
  • Spatial-grid manager and alignment-anchors delegate to it (no third parallel AABB path)
  • Export @pascal-app/core/plan-footprint (pure) and re-export from @pascal-app/core/spatial-grid
  • Design note: wiki/architecture/plan-footprint.md (one source; packing gap ~0.08 vs check/verify gap: 0)
  • Unit tests for rotation, scale, gap semantics, corner/AABB parity

Out of scope: rewiring MCP furnish_room / verify_scene / door keep-outs to call these helpers (follow-up).

How to test

  1. bun test packages/core/src/lib/plan-footprint.test.ts — expect all pass
  2. bun test packages/core/src/services/alignment-anchors.test.ts — still green
  3. bun run --cwd packages/core buildtsc --build clean
  4. Optional: bun run check packages/core/src/lib/plan-footprint.ts packages/core/src/lib/plan-footprint.test.ts packages/core/src/hooks/spatial-grid/spatial-grid-manager.ts packages/core/src/services/alignment-anchors.ts
  5. Optional smoke: import from @pascal-app/core/plan-footprint and @pascal-app/core/spatial-grid and confirm planFootprintAABB returns the same box

Screenshots / screen recording

N/A — non-visual change (pure geometry helpers + tests + wiki note).

Checklist

  • I've tested this locally with bun test / bun run --cwd packages/core build
  • My code follows the existing code style (bun run check on changed files)
  • I've updated relevant documentation (wiki/architecture/plan-footprint.md)
  • This PR targets the main branch

Note

Medium Risk
Unifies alignment and floor-collision footprint math (intentionally); wrong rotation convention would affect placement, snapping, and future MCP clearance, though tests and delegation to prior spatial-grid formulas mitigate that.

Overview
Introduces packages/core/src/lib/plan-footprint.ts as the single pure XZ source for rotation-aware footprint corners, conservative AABBs, expand-then-intersect overlap with configurable gap, and a scaled planFootprintAABBForItem helper (null for wall/ceiling hosts).

Spatial-grid and alignment-anchors stop inlining duplicate math and delegate to this module; the spatial-grid entry also re-exports the helpers. A new @pascal-app/core/plan-footprint package export targets Node/MCP callers without pulling the grid manager.

Adds unit tests for rotation, corner/AABB parity, gap semantics, and item scaling; documents the module in wiki/architecture/plan-footprint.md. MCP furnish/verify rewires are explicitly out of scope.

Reviewed by Cursor Bugbot for commit 6384a73. Bugbot is set up for automated code reviews on this repo. Configure here.

alaa541 added 2 commits August 5, 2026 02:38
Extract rotation-aware XZ footprint AABB/corners and expand-then-intersect
gap overlap into packages/core/lib/plan-footprint. Spatial-grid and
alignment-anchors delegate to it. Export via @pascal-app/core/plan-footprint
and spatial-grid. Design note documents one source and gap call-site rules
after pascalorg#569.

@Aymericr Aymericr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for picking up the note I left at the end of #569 — this is the right direction and I checked the math rather than assuming: planFootprintAABB's abs-cos/abs-sin extents are provably the same box as the rotated-corner loop it replaces in alignment-anchors.ts, planFootprintCorners preserves spatial-grid's rotation convention exactly (different corner order, nothing depends on order), the attachTo null-list matches the enum in item.ts, and it stays clear of the R3F guard in architecture.test.ts. The alignment-anchors.ts comment admitting it "mirrors the rotated-corner math the spatial-grid manager uses" was a real duplication and −58 lines is a real removal.

But as it stands the PR moves the number in the wrong direction, and that's what I want to fix before it lands.

The ask on #569 was that MCP stop being a third copy. With the rewire declared out of scope, aabbsOverlap in door-clearance.ts survives — and the new aabbsOverlapPlan is a line-for-line reimplementation of it. Post-merge there are three copies of expand-then-intersect instead of two, and MCP still uses its own. The extraction is the easy half; the consolidation was the point.

Three of the five exports have no callers. aabbsOverlapPlan and planFootprintAABBForItem exist for the deferred MCP work; planFootprintAABBFromCorners is called only by tests, which then assert it's identical to planFootprintAABB — so it's an identity helper proving itself. On #569 I asked you to delete aabbFromPlan and nodeItemAabb for exactly this, and AGENTS.md names dead code and speculative abstractions specifically.

Two paths, either fine by me:

  • Finish it. Keep all five exports and rewire door-clearance.ts / layout-clearance.ts / check-collisions.ts to import from @pascal-app/core/plan-footprint, deleting MCP's aabbsOverlap and PlanAabb. Heads-up on the trap that probably made you defer: @pascal-app/core is only a devDependency of packages/mcp while door-clearance.ts already runtime-imports getScaledDimensions from @pascal-app/core/schema — that's a latent packaging bug, and moving more runtime code across that edge means promoting it to a real dependency. Please also keep the gap: 0 versus 0.08 distinction from #569 intact per call site; that's the bug I'd most want a test to hold.
  • Or narrow it. Ship only planFootprintCorners and planFootprintAABB, drop the other three exports and their tests, and leave the subpath export in as the seam for the follow-up.

On the wiki page: I'd rather it didn't say "Aymericr noted…" — the other wiki/architecture/ pages state the rule, not who asked for it, and 43 lines of page restating the header of a 133-line math module is more provenance than durable rule. Fold the gap-semantics table into the module header and skip the page, or cut it to the invariant plus the call-site table.

Useful side-finding worth carrying into the rewire: your aabbsOverlapPlan comment ("expand each box by gap") is right and MCP's existing one ("expand each box by gap/2") describes something the code doesn't do. Fix that comment while you're in there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants