fix: address 2nd-round adversarial review of PR #402 fixes

- core: decouple drag-follow from distributionRole — add
  portConnectivityFollow flag to NodeDefinition; pipe-trap opts out
  (portConnectivityFollow: false) so dragging a connected pipe endpoint
  stretches the trap arm instead of yanking the anchored trap fixture

- core: remove the module-level getLevelHeight cache entirely — it was
  keyed only by nodes-object identity, which could return stale heights
  for in-place mutations by pure/headless callers. The function is now
  fully pure and deterministic; viewer hot path recomputes per frame as
  before (the cache only ever skipped the resolver-free branch)

- test: harden port-connectivity-pipe.test.ts — real DuctSegmentNode
  cross-family isolation case (was waste-vs-vent), new pipe-trap anchor
  case (run drag doesn't move trap; trap drag still stretches run), and
  beforeEach/afterEach registry reset instead of leaky beforeAll

- nit: biome format/import-order on all touched files
This commit is contained in:
Open Pascal
2026-06-16 19:56:31 +00:00
parent 54a24e4c5c
commit 8eab9979ab
8 changed files with 121 additions and 97 deletions
+4 -2
View File
@@ -552,8 +552,10 @@ const DuctSegmentTool = () => {
// ceiling (centerline = ceiling height radius).
const resolveBaseY = (): number => {
if (!ceilingModeRef.current) return 0
const ceiling = getLevelHeight(activeLevelId, useScene.getState().nodes, (wallId) =>
sceneRegistry.nodes.get(wallId)?.position.y,
const ceiling = getLevelHeight(
activeLevelId,
useScene.getState().nodes,
(wallId) => sceneRegistry.nodes.get(wallId)?.position.y,
)
const p = profileRef.current
const verticalIn = p.shape === 'round' ? p.diameter : p.height