Skip to content

collab: structured entity branches (psets/quantities/classifications/materials/geometryRef) are not serialized by the IFCX snapshot pipeline #1031

@louistrue

Description

@louistrue

Context

Surfaced by CodeRabbit on PR #1027 (#1027 (comment)).

@ifc-lite/collab entities carry structured branches beyond attributes / children / inherits: psets, quantities, classifications, materials, geometryRef, meta (see entityToJSON in packages/collab/src/doc/entity.ts). The IFCX wire type IfcxNode has no fields for these, so neither snapshot writer carries them:

  • snapshotToIfcx (packages/collab/src/snapshot/to-ifcx.ts) — the full-snapshot writer, predating PR Layer PRs: three-way merge, provenance, and agent draft workflow #1027 — only emits attributes / children / inherits.
  • extractMinimalLayer (packages/collab/src/snapshot/minimal-layer.ts) diffs the same three branches, deliberately matching the full writer's coverage so that baseline + minimal layer composes to the same IFCX state as a full snapshot.

This is a pre-existing limitation of the IFCX serialization scope, not a regression from the layer-PRs work. Today, property sets that need to travel through layers are written as namespaced attribute keys (e.g. bsi::ifc::v5a::Pset_FireSafety::FireRating), which is the convention the MCP draft tools, the merge engine (pset:<Name> component keys), and scope verification all share. Structured-branch edits made via collab APIs (setPsetProp, quantities, classifications, materials, geometry refs) round-trip inside the Y.Doc but are dropped on any IFCX export.

What needs to happen

Decide on and implement one of:

  1. Serialize structured branches into namespaced attributes at the snapshot boundary (e.g. fold psets into …::Pset_X::Prop attribute keys on write, and re-inflate on seedFromIfcx), keeping IfcxNode unchanged; or
  2. Extend the wire format with explicit branches and update composition, canonical hashing, merge component-state extraction, and seeding accordingly.

Whichever is chosen, snapshotToIfcx and extractMinimalLayer must stay in lockstep so the layer-composition contract (baseline + minimal layer == live doc) keeps holding, and computeLayerId canonicalization must cover the new representation.

Acceptance criteria

  • Structured pset/quantity/classification/material/geometryRef edits survive snapshot → seed round-trips.
  • extractMinimalLayer emits diffs (including deletions) for whichever representation is chosen.
  • Round-trip and minimal-layer tests cover the new branches.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions