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
@@ -39,8 +39,10 @@ export const LevelSystem = () => {
obj.position.y = lerp(obj.position.y, targetY, delta * 12) // Smoothly animate to new Y position
obj.visible = levelMode !== 'solo' || level?.id === selectedLevel || !selectedLevel
cumulativeY += getLevelHeight(levelId, nodes, (wallId) =>
sceneRegistry.nodes.get(wallId)?.position.y,
cumulativeY += getLevelHeight(
levelId,
nodes,
(wallId) => sceneRegistry.nodes.get(wallId)?.position.y,
)
}
}, 5) // Using a lower priority so it runs after transforms from other systems have settled