Skip to content

core: repair null parent links so stored scenes pass authority validation - #574

Merged
Aymericr merged 1 commit into
mainfrom
fix/scene-parent-link-repair
Aug 4, 2026
Merged

core: repair null parent links so stored scenes pass authority validation#574
Aymericr merged 1 commit into
mainfrom
fix/scene-parent-link-repair

Conversation

@Aymericr

@Aymericr Aymericr commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Repairs the stored-scene corruption behind the hosted "Live collaboration is unavailable for this project. Editing is paused to protect the scene." incident (Sentry MONOREPO-EDITOR-JR/JQ/GF): scenes whose children arrays link site → building → level while building/level carry parentId: null. The editor renders these scenes by traversing children, but the hosted scene authority validates parent/child symmetry and rejected every snapshot, locking sessions read-only and silently discarding tool placements (ghost + SFX with no commit).

  • healSceneNodes gains a repair pass: a node with a null parentId that exactly one parent claims via children points back at that parent. Embedded legacy site children claim by id, so the flattened flat-map node is repaired too. Ambiguous multi-claim nodes are left alone.
  • loadScene writes explicit parent links for the default Site → Building → Level hierarchy (it previously relied on the schema's parentId: null default — one of the two writers of the corrupt shape; the other was the legacy embedded-site-child flatten, which pass 3 now covers on load).
  • New @pascal-app/core/scene-migrations barrel exports healSceneNodes alongside removeRetiredDrawingSheetNodes, keeping the entry server-safe so the hosted authority can apply the identical normalization before validating.

How to test

  1. bun test packages/core/src/utils/heal-scene-graph.test.ts — new cases cover the null-parent chain repair, embedded legacy site-child claims, ambiguous multi-claim nodes, and untouched dangling parents.
  2. bun test packages/core/src/store/use-scene-load-scene.test.ts — the default scene now carries symmetric parent links.
  3. bun test packages/core/src — full core suite (930 tests).
  4. In the hosted app, feed a stored graph with building/level at parentId: null through normalizeAuthoritySceneGraph (companion private-editor change) and confirm apiGraphSchema accepts it.

Screenshots / screen recording

N/A — non-visual data-repair change.

Checklist

  • I've tested this locally with bun dev
  • My code follows the existing code style (run bun check to verify)
  • I've updated relevant documentation (if applicable)
  • This PR targets the main branch

Note

Medium Risk
Changes scene graph normalization used on load and by the hosted authority; incorrect repair logic could alter hierarchy, though guards limit repairs to unambiguous single-claim cases.

Overview
Fixes stored scenes where children links site → building → level but parentId stays null on building/level, which blocked hosted scene authority validation and paused live collaboration.

healSceneNodes adds a third pass: if a node has parentId: null and exactly one parent lists it in children (including embedded legacy site children), it sets parentId to that parent; ambiguous multi-parent claims are unchanged.

loadScene now sets explicit parentId on the default Site → Building → Level graph instead of relying on schema defaults, so new default scenes save with symmetric parent/child links.

The @pascal-app/core/scene-migrations export is pointed at a new server-safe barrel that re-exports healSceneNodes and removeRetiredDrawingSheetNodes for shared client/authority normalization.

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

…alidation

Stored scenes could link site → building → level through children arrays
while building/level carried parentId null: loadScene never wrote parent
ids and the legacy embedded-site-child flatten kept the already-flat
node's null parentId. The editor traverses children and renders these
scenes, but the hosted scene authority validates parent/child symmetry
and rejected every snapshot into a fatal read-only session.

healSceneNodes now repairs a null parent link when exactly one parent
claims the node (embedded legacy site children claim by id), loadScene
writes explicit parent links, and both migrations are exported
server-safe through @pascal-app/core/scene-migrations so the hosted
authority can apply the same normalization before validating.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Aymericr
Aymericr merged commit 9488b6f into main Aug 4, 2026
3 checks passed
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.

1 participant