@ifc-lite/collab 0.2.7 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,12 @@
1
1
  /* This Source Code Form is subject to the terms of the Mozilla Public
2
2
  * License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ import { IFCLITE_ATTR } from '@ifc-lite/ifcx';
4
5
  import * as Y from 'yjs';
5
6
  import { createCollabDoc, entitiesMap } from '../doc/schema.js';
6
7
  import { entityToJSON } from '../doc/entity.js';
7
8
  import { snapshotToIfcx } from './to-ifcx.js';
9
+ import { flattenStructuredBranches, geometryRecordLookup } from './structured-attrs.js';
8
10
  /**
9
11
  * Build a minimal IFCX layer expressing the diff between `baseline`
10
12
  * and `doc`. `baseline` is whatever `Y.encodeStateAsUpdate(doc)`
@@ -12,85 +14,126 @@ import { snapshotToIfcx } from './to-ifcx.js';
12
14
  */
13
15
  export function extractMinimalLayer(doc, baseline, options = {}) {
14
16
  const includeUpdatedValues = options.includeUpdatedValues ?? true;
17
+ const includeDeletions = options.includeDeletions ?? true;
15
18
  // Reconstruct the "before" state by replaying the baseline update on
16
19
  // a fresh doc.
17
20
  const before = createCollabDoc({ gc: false });
18
- if (baseline.byteLength > 0)
19
- Y.applyUpdate(before, baseline);
20
- // Snapshot the live doc through the standard writer so we get a
21
- // header + imports + schemas template, then trim the data array down
22
- // to the diff.
23
- const live = snapshotToIfcx(doc, options.snapshot);
24
- const beforeEnts = entitiesMap(before);
25
- const liveEnts = entitiesMap(doc);
26
- const diffNodes = [];
27
- liveEnts.forEach((entUntyped, path) => {
28
- const liveJson = entityToJSON(entUntyped);
29
- const beforeUntyped = beforeEnts.get(path);
30
- if (!beforeUntyped) {
31
- // Entity is new — emit it whole (sans empty branches).
21
+ try {
22
+ if (baseline.byteLength > 0)
23
+ Y.applyUpdate(before, baseline);
24
+ // Snapshot the live doc through the standard writer so we get a
25
+ // header + imports + schemas template, then trim the data array down
26
+ // to the diff.
27
+ const live = snapshotToIfcx(doc, options.snapshot);
28
+ const beforeEnts = entitiesMap(before);
29
+ const liveEnts = entitiesMap(doc);
30
+ const liveGeometryFor = geometryRecordLookup(doc);
31
+ const beforeGeometryFor = geometryRecordLookup(before);
32
+ const diffNodes = [];
33
+ liveEnts.forEach((entUntyped, path) => {
34
+ const liveJson = entityToJSON(entUntyped);
35
+ // Diff over the flattened attribute view so structured-branch
36
+ // edits (psets / quantities / classifications / materials /
37
+ // geometryRef) surface exactly like the full writer emits them —
38
+ // the two writers stay in lockstep by construction (#1031).
39
+ const liveAttrs = flattenStructuredBranches(liveJson, { geometryRecordFor: liveGeometryFor });
40
+ const beforeUntyped = beforeEnts.get(path);
41
+ if (!beforeUntyped) {
42
+ // Entity is new — emit it whole (sans empty branches).
43
+ const node = { path };
44
+ if (Object.keys(liveAttrs).length > 0)
45
+ node.attributes = liveAttrs;
46
+ if (Object.keys(liveJson.children).length > 0)
47
+ node.children = { ...liveJson.children };
48
+ if (Object.keys(liveJson.inherits).length > 0)
49
+ node.inherits = { ...liveJson.inherits };
50
+ diffNodes.push(node);
51
+ return;
52
+ }
53
+ const beforeJson = entityToJSON(beforeUntyped);
54
+ const beforeAttrs = flattenStructuredBranches(beforeJson, { geometryRecordFor: beforeGeometryFor });
32
55
  const node = { path };
33
- if (Object.keys(liveJson.attributes).length > 0)
34
- node.attributes = { ...liveJson.attributes };
35
- if (Object.keys(liveJson.children).length > 0)
36
- node.children = { ...liveJson.children };
37
- if (Object.keys(liveJson.inherits).length > 0)
38
- node.inherits = { ...liveJson.inherits };
39
- diffNodes.push(node);
40
- return;
41
- }
42
- const beforeJson = entityToJSON(beforeUntyped);
43
- const node = { path };
44
- let dirty = false;
45
- // Attributes: include keys that are new OR (when configured)
46
- // whose value changed.
47
- const addedAttrs = {};
48
- for (const [key, value] of Object.entries(liveJson.attributes)) {
49
- const wasInBaseline = key in beforeJson.attributes;
50
- if (!wasInBaseline) {
51
- addedAttrs[key] = value;
52
- continue;
56
+ let dirty = false;
57
+ // Attributes: include keys that are new OR (when configured)
58
+ // whose value changed; removed keys emit null.
59
+ const addedAttrs = {};
60
+ for (const [key, value] of Object.entries(liveAttrs)) {
61
+ const wasInBaseline = key in beforeAttrs;
62
+ if (!wasInBaseline) {
63
+ addedAttrs[key] = value;
64
+ continue;
65
+ }
66
+ if (includeUpdatedValues && !deepEqual(value, beforeAttrs[key])) {
67
+ addedAttrs[key] = value;
68
+ }
53
69
  }
54
- if (includeUpdatedValues && !deepEqual(value, beforeJson.attributes[key])) {
55
- addedAttrs[key] = value;
70
+ if (includeDeletions) {
71
+ for (const key of Object.keys(beforeAttrs)) {
72
+ if (!(key in liveAttrs))
73
+ addedAttrs[key] = null;
74
+ }
56
75
  }
57
- }
58
- if (Object.keys(addedAttrs).length > 0) {
59
- node.attributes = addedAttrs;
60
- dirty = true;
61
- }
62
- // Children: same rule.
63
- const addedChildren = {};
64
- for (const [role, child] of Object.entries(liveJson.children)) {
65
- const wasInBaseline = role in beforeJson.children;
66
- if (!wasInBaseline || (includeUpdatedValues && beforeJson.children[role] !== child)) {
67
- addedChildren[role] = child;
76
+ if (Object.keys(addedAttrs).length > 0) {
77
+ node.attributes = addedAttrs;
78
+ dirty = true;
68
79
  }
69
- }
70
- if (Object.keys(addedChildren).length > 0) {
71
- node.children = addedChildren;
72
- dirty = true;
73
- }
74
- // Inherits: same rule.
75
- const addedInherits = {};
76
- for (const [role, inh] of Object.entries(liveJson.inherits)) {
77
- const wasInBaseline = role in beforeJson.inherits;
78
- if (!wasInBaseline || (includeUpdatedValues && beforeJson.inherits[role] !== inh)) {
79
- addedInherits[role] = inh;
80
+ // Children: same rule; removed roles emit null (IFCX removal).
81
+ const addedChildren = {};
82
+ for (const [role, child] of Object.entries(liveJson.children)) {
83
+ const wasInBaseline = role in beforeJson.children;
84
+ if (!wasInBaseline || (includeUpdatedValues && beforeJson.children[role] !== child)) {
85
+ addedChildren[role] = child;
86
+ }
80
87
  }
88
+ if (includeDeletions) {
89
+ for (const role of Object.keys(beforeJson.children)) {
90
+ if (!(role in liveJson.children))
91
+ addedChildren[role] = null;
92
+ }
93
+ }
94
+ if (Object.keys(addedChildren).length > 0) {
95
+ node.children = addedChildren;
96
+ dirty = true;
97
+ }
98
+ // Inherits: same rule.
99
+ const addedInherits = {};
100
+ for (const [role, inh] of Object.entries(liveJson.inherits)) {
101
+ const wasInBaseline = role in beforeJson.inherits;
102
+ if (!wasInBaseline || (includeUpdatedValues && beforeJson.inherits[role] !== inh)) {
103
+ addedInherits[role] = inh;
104
+ }
105
+ }
106
+ if (includeDeletions) {
107
+ for (const role of Object.keys(beforeJson.inherits)) {
108
+ if (!(role in liveJson.inherits))
109
+ addedInherits[role] = null;
110
+ }
111
+ }
112
+ if (Object.keys(addedInherits).length > 0) {
113
+ node.inherits = addedInherits;
114
+ dirty = true;
115
+ }
116
+ if (dirty)
117
+ diffNodes.push(node);
118
+ });
119
+ // Entities deleted since the baseline: tombstone opinions that shadow
120
+ // the entity (and its subtree) when the stack composes.
121
+ if (includeDeletions) {
122
+ beforeEnts.forEach((_entUntyped, path) => {
123
+ if (!liveEnts.has(path)) {
124
+ diffNodes.push({ path, attributes: { [IFCLITE_ATTR.DELETED]: true } });
125
+ }
126
+ });
81
127
  }
82
- if (Object.keys(addedInherits).length > 0) {
83
- node.inherits = addedInherits;
84
- dirty = true;
85
- }
86
- if (dirty)
87
- diffNodes.push(node);
88
- });
89
- before.destroy();
90
- return {
91
- ...live,
92
- data: diffNodes,
93
- };
128
+ return {
129
+ ...live,
130
+ data: diffNodes,
131
+ };
132
+ }
133
+ finally {
134
+ // Deterministic cleanup even when extraction throws.
135
+ before.destroy();
136
+ }
94
137
  }
95
138
  /**
96
139
  * Heuristic deep-equal: handles primitives, arrays, and plain objects.
@@ -1 +1 @@
1
- {"version":3,"file":"minimal-layer.js","sourceRoot":"","sources":["../../src/snapshot/minimal-layer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"minimal-layer.js","sourceRoot":"","sources":["../../src/snapshot/minimal-layer.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAkC/D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAwB,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAmBxF;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,GAAU,EACV,QAAoB,EACpB,UAAsC,EAAE;IAExC,MAAM,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,IAAI,IAAI,CAAC;IAClE,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,IAAI,CAAC;IAC1D,qEAAqE;IACrE,eAAe;IACf,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9C,IAAI,CAAC;QACH,IAAI,QAAQ,CAAC,UAAU,GAAG,CAAC;YAAE,CAAC,CAAC,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAE7D,gEAAgE;QAChE,qEAAqE;QACrE,eAAe;QACf,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QACnD,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,eAAe,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;QAClD,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAEvD,MAAM,SAAS,GAAe,EAAE,CAAC;QAEjC,QAAQ,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE;YACpC,MAAM,QAAQ,GAAG,YAAY,CAAC,UAA4B,CAAC,CAAC;YAC5D,8DAA8D;YAC9D,4DAA4D;YAC5D,iEAAiE;YACjE,4DAA4D;YAC5D,MAAM,SAAS,GAAG,yBAAyB,CAAC,QAAQ,EAAE,EAAE,iBAAiB,EAAE,eAAe,EAAE,CAAC,CAAC;YAC9F,MAAM,aAAa,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC3C,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnB,uDAAuD;gBACvD,MAAM,IAAI,GAAa,EAAE,IAAI,EAAE,CAAC;gBAChC,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC;oBAAE,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;gBACnE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC;oBAAE,IAAI,CAAC,QAAQ,GAAG,EAAE,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBACxF,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC;oBAAE,IAAI,CAAC,QAAQ,GAAG,EAAE,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBACxF,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrB,OAAO;YACT,CAAC;YAED,MAAM,UAAU,GAAG,YAAY,CAAC,aAA+B,CAAC,CAAC;YACjE,MAAM,WAAW,GAAG,yBAAyB,CAAC,UAAU,EAAE,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,CAAC,CAAC;YACpG,MAAM,IAAI,GAAa,EAAE,IAAI,EAAE,CAAC;YAChC,IAAI,KAAK,GAAG,KAAK,CAAC;YAElB,6DAA6D;YAC7D,+CAA+C;YAC/C,MAAM,UAAU,GAA4B,EAAE,CAAC;YAC/C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;gBACrD,MAAM,aAAa,GAAG,GAAG,IAAI,WAAW,CAAC;gBACzC,IAAI,CAAC,aAAa,EAAE,CAAC;oBACnB,UAAU,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;oBACxB,SAAS;gBACX,CAAC;gBACD,IAAI,oBAAoB,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;oBAChE,UAAU,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;gBAC1B,CAAC;YACH,CAAC;YACD,IAAI,gBAAgB,EAAE,CAAC;gBACrB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;oBAC3C,IAAI,CAAC,CAAC,GAAG,IAAI,SAAS,CAAC;wBAAE,UAAU,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;gBAClD,CAAC;YACH,CAAC;YACD,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;gBAC7B,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;YAED,+DAA+D;YAC/D,MAAM,aAAa,GAAkC,EAAE,CAAC;YACxD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC9D,MAAM,aAAa,GAAG,IAAI,IAAI,UAAU,CAAC,QAAQ,CAAC;gBAClD,IAAI,CAAC,aAAa,IAAI,CAAC,oBAAoB,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;oBACpF,aAAa,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;gBAC9B,CAAC;YACH,CAAC;YACD,IAAI,gBAAgB,EAAE,CAAC;gBACrB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACpD,IAAI,CAAC,CAAC,IAAI,IAAI,QAAQ,CAAC,QAAQ,CAAC;wBAAE,aAAa,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;gBAC/D,CAAC;YACH,CAAC;YACD,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1C,IAAI,CAAC,QAAQ,GAAG,aAAa,CAAC;gBAC9B,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;YAED,uBAAuB;YACvB,MAAM,aAAa,GAAkC,EAAE,CAAC;YACxD,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5D,MAAM,aAAa,GAAG,IAAI,IAAI,UAAU,CAAC,QAAQ,CAAC;gBAClD,IAAI,CAAC,aAAa,IAAI,CAAC,oBAAoB,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;oBAClF,aAAa,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC;gBAC5B,CAAC;YACH,CAAC;YACD,IAAI,gBAAgB,EAAE,CAAC;gBACrB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACpD,IAAI,CAAC,CAAC,IAAI,IAAI,QAAQ,CAAC,QAAQ,CAAC;wBAAE,aAAa,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;gBAC/D,CAAC;YACH,CAAC;YACD,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1C,IAAI,CAAC,QAAQ,GAAG,aAAa,CAAC;gBAC9B,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;YAED,IAAI,KAAK;gBAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,sEAAsE;QACtE,wDAAwD;QACxD,IAAI,gBAAgB,EAAE,CAAC;YACrB,UAAU,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE;gBACvC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBACxB,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;gBACzE,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAED,OAAO;YACL,GAAG,IAAI;YACP,IAAI,EAAE,SAAS;SAChB,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,qDAAqD;QACrD,MAAM,CAAC,OAAO,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,SAAS,CAAC,CAAU,EAAE,CAAU;IACvC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACzB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC;IACzC,IAAI,OAAO,CAAC,KAAK,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACrB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAC7D,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,EAAE,GAAG,CAA4B,CAAC;QACxC,MAAM,EAAE,GAAG,CAA4B,CAAC;QACxC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/D,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;gBAAE,OAAO,KAAK,CAAC;QAC7C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * publishLayer: freeze a draft into an immutable, content-addressed,
3
+ * provenance-stamped layer.
4
+ *
5
+ * The draft is a CRDT session (Y.Doc) bound to a base; freezing extracts
6
+ * the minimal layer (including deletion overlays), attaches the
7
+ * provenance manifest (intent, author, scope claims, base, checks), and
8
+ * content-addresses the result: `layerId = blake3(canonical_bytes)`.
9
+ *
10
+ * Check execution and scope-claim verification happen at the calling
11
+ * boundary (MCP/CLI/registry) — pass the results in; they are recorded
12
+ * in the manifest, and signatures never participate in the id.
13
+ *
14
+ * Spec: docs/architecture/layer-prs/02-layer-format.md §2.4,
15
+ * 03-provenance.md, 06-agents.md §6.2.
16
+ */
17
+ import type { IfcxFile, ProvenanceAuthor, ProvenanceBase, ProvenanceCheck, ProvenanceManifest } from '@ifc-lite/ifcx';
18
+ import type * as Y from 'yjs';
19
+ import { type ExtractMinimalLayerOptions } from './minimal-layer.js';
20
+ export interface PublishLayerOptions {
21
+ /** Human-readable why. Mandatory — the `ifc layer log` line. */
22
+ intent: string;
23
+ /** Who authored the draft (human / agent / hybrid). */
24
+ author: ProvenanceAuthor;
25
+ /**
26
+ * Baseline the draft was forked from
27
+ * (`Y.encodeStateAsUpdate` / `captureBaseline` output).
28
+ */
29
+ baseline: Uint8Array;
30
+ /** Identity of the base layer/stack the draft was authored against. */
31
+ base?: ProvenanceBase | null;
32
+ /** Capability-grammar scope claims declared for this layer. */
33
+ scope_claim?: string[];
34
+ /** Results of declared checks, run by the caller before publishing. */
35
+ checks?: ProvenanceCheck[];
36
+ /** blake3 digest of the prompt/task text that produced the layer. */
37
+ instructions_digest?: string;
38
+ /** Parent layer ids in the change DAG (defaults to the base id). */
39
+ parents?: string[];
40
+ /** Manifest timestamp override (defaults to now). */
41
+ created?: string;
42
+ /** Forwarded to the minimal-layer extractor. */
43
+ extract?: ExtractMinimalLayerOptions;
44
+ }
45
+ export interface PublishedLayer {
46
+ /** The immutable layer document, `header.id` set to the content address. */
47
+ file: IfcxFile;
48
+ /** `blake3:` content address over canonical bytes. */
49
+ layerId: string;
50
+ manifest: ProvenanceManifest;
51
+ /** Number of changed nodes the layer carries. */
52
+ opCount: number;
53
+ }
54
+ /**
55
+ * Freeze a draft doc into a published layer. Pure with respect to the
56
+ * draft: the Y.Doc is read, never mutated — publishing again after more
57
+ * edits produces a new layer with a new id.
58
+ */
59
+ export declare function publishLayer(doc: Y.Doc, options: PublishLayerOptions): PublishedLayer;
60
+ //# sourceMappingURL=publish-layer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish-layer.d.ts","sourceRoot":"","sources":["../../src/snapshot/publish-layer.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EACV,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,kBAAkB,EACnB,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,KAAK,CAAC,MAAM,KAAK,CAAC;AAC9B,OAAO,EAAuB,KAAK,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAE1F,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,MAAM,EAAE,gBAAgB,CAAC;IACzB;;;OAGG;IACH,QAAQ,EAAE,UAAU,CAAC;IACrB,uEAAuE;IACvE,IAAI,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAC7B,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,uEAAuE;IACvE,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,qEAAqE;IACrE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,OAAO,CAAC,EAAE,0BAA0B,CAAC;CACtC;AAED,MAAM,WAAW,cAAc;IAC7B,4EAA4E;IAC5E,IAAI,EAAE,QAAQ,CAAC;IACf,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,mBAAmB,GAAG,cAAc,CAkCrF"}
@@ -0,0 +1,43 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ import { computeLayerId, createProvenanceManifest, setProvenance } from '@ifc-lite/ifcx';
5
+ import { extractMinimalLayer } from './minimal-layer.js';
6
+ /**
7
+ * Freeze a draft doc into a published layer. Pure with respect to the
8
+ * draft: the Y.Doc is read, never mutated — publishing again after more
9
+ * edits produces a new layer with a new id.
10
+ */
11
+ export function publishLayer(doc, options) {
12
+ const delta = extractMinimalLayer(doc, options.baseline, options.extract);
13
+ const manifest = createProvenanceManifest({
14
+ author: options.author,
15
+ intent: options.intent,
16
+ base: options.base ?? null,
17
+ created: options.created,
18
+ parents: options.parents ?? (options.base ? [options.base.id] : []),
19
+ scope_claim: options.scope_claim ?? [],
20
+ checks: options.checks ?? [],
21
+ instructions_digest: options.instructions_digest,
22
+ });
23
+ // Normalize the generated snapshot header to the publish event so the
24
+ // content address is a function of content + manifest, not of when the
25
+ // snapshot writer happened to run.
26
+ const normalized = {
27
+ ...delta,
28
+ header: {
29
+ ...delta.header,
30
+ author: options.author.principal,
31
+ timestamp: manifest.created,
32
+ },
33
+ };
34
+ const withManifest = setProvenance(normalized, manifest);
35
+ const layerId = computeLayerId(withManifest);
36
+ return {
37
+ file: { ...withManifest, header: { ...withManifest.header, id: layerId } },
38
+ layerId,
39
+ manifest,
40
+ opCount: delta.data.length,
41
+ };
42
+ }
43
+ //# sourceMappingURL=publish-layer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish-layer.js","sourceRoot":"","sources":["../../src/snapshot/publish-layer.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AA0B/D,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEzF,OAAO,EAAE,mBAAmB,EAAmC,MAAM,oBAAoB,CAAC;AAsC1F;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,GAAU,EAAE,OAA4B;IACnE,MAAM,KAAK,GAAG,mBAAmB,CAAC,GAAG,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAE1E,MAAM,QAAQ,GAAG,wBAAwB,CAAC;QACxC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,IAAI;QAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,EAAE;QACtC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;QAC5B,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;KACjD,CAAC,CAAC;IAEH,sEAAsE;IACtE,uEAAuE;IACvE,mCAAmC;IACnC,MAAM,UAAU,GAAa;QAC3B,GAAG,KAAK;QACR,MAAM,EAAE;YACN,GAAG,KAAK,CAAC,MAAM;YACf,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS;YAChC,SAAS,EAAE,QAAQ,CAAC,OAAO;SAC5B;KACF,CAAC;IACF,MAAM,YAAY,GAAG,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IAE7C,OAAO;QACL,IAAI,EAAE,EAAE,GAAG,YAAY,EAAE,MAAM,EAAE,EAAE,GAAG,YAAY,CAAC,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE;QAC1E,OAAO;QACP,QAAQ;QACR,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM;KAC3B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Structured-branch ↔ namespaced-attribute conversion (#1031).
3
+ *
4
+ * The Y.Doc keeps psets / quantities / classifications / materials /
5
+ * geometryRef as dedicated CRDT branches so concurrent edits to
6
+ * different branches never conflict, but the IFCX wire type only has
7
+ * `attributes` / `children` / `inherits`. At the snapshot boundary the
8
+ * structured branches fold into ordinary attributes; `seedFromIfcx`
9
+ * re-inflates them, so structured edits survive snapshot → seed
10
+ * round-trips.
11
+ *
12
+ * Representation (the convention the MCP draft tools, the merge
13
+ * engine's `pset:`/`qset:` component keys, scope verification, and the
14
+ * IFC4→5 migration already share):
15
+ * - pset property → `bsi::ifc::v5a::<Set>::<Prop>` with the full
16
+ * typed PropertyValue object as the attribute value;
17
+ * - quantity → `bsi::ifc::v5a::<Qto_Set>::<Name>` with the raw
18
+ * number as the attribute value;
19
+ * - classifications / materials / geometryRef → single attributes
20
+ * under the `ifclite::` extension namespace (whole-array values:
21
+ * the Y.Array is the unit users edit, and merge granularity at the
22
+ * array level matches that).
23
+ *
24
+ * Inflation is shape-gated so legacy flat attributes written by the
25
+ * IFC4→IFC5 migration (raw values under the same v5a keys) stay flat:
26
+ * only PropertyValue-shaped objects inflate into psets, and numbers
27
+ * inflate into quantities unless the set is `Pset_`-named — the
28
+ * migration only ever emits `Pset_*` set names, so that exclusion is
29
+ * exactly the legacy population, and custom quantity-set names still
30
+ * round-trip. Both directions are inverse to each other, so
31
+ * flatten(inflate(x)) == x and a doc holding the same key in both the
32
+ * flat and structured branch serializes deterministically (structured
33
+ * wins).
34
+ */
35
+ import { V5A_ATTR_PREFIX } from '@ifc-lite/ifcx';
36
+ import * as Y from 'yjs';
37
+ import { type ClassificationRef, type GeometryRefRecord, type MaterialAssignment, type PropertyValue } from '../doc/schema.js';
38
+ export { V5A_ATTR_PREFIX };
39
+ /**
40
+ * Shape test for the typed PropertyValue record — the canonical wire
41
+ * shape every writer and reader shares (`isTypedPropertyValue` in
42
+ * `@ifc-lite/ifcx`). Strict on purpose: legacy migrated attributes
43
+ * carry raw scalars, never `{type, value}` objects, so this is what
44
+ * disambiguates pset inflation from "leave it as a flat attribute".
45
+ */
46
+ export declare function isPropertyValueShaped(value: unknown): value is PropertyValue;
47
+ /** The structured branches `entityToJSON` exposes alongside attributes. */
48
+ export interface StructuredBranchesJSON {
49
+ psets: Record<string, Record<string, PropertyValue>>;
50
+ quantities: Record<string, Record<string, number>>;
51
+ classifications: ClassificationRef[];
52
+ materials: MaterialAssignment[];
53
+ geometryRefs: string[];
54
+ }
55
+ /**
56
+ * Wire form of a geometry reference whose target record is known at
57
+ * snapshot time: carrying the record (sans CRDT version vector) keeps
58
+ * the round-trip self-contained — a seed can recreate the geometry map
59
+ * entry instead of restoring a dangling ref. A bare `geomId` string is
60
+ * still valid for refs whose geometry hydrates out-of-band (blob sync).
61
+ */
62
+ export interface GeometryRefCarrier {
63
+ geomId: string;
64
+ type?: string;
65
+ source?: string;
66
+ blobHash?: string;
67
+ params?: Record<string, unknown>;
68
+ bbox?: number[];
69
+ }
70
+ export interface FlattenOptions {
71
+ /**
72
+ * Resolve a geometry record for a geomId (typically from the doc's
73
+ * top-level geometry map). When it returns one, the carrier embeds it;
74
+ * otherwise only the id travels.
75
+ */
76
+ geometryRecordFor?: (geomId: string) => Omit<GeometryRefCarrier, 'geomId'> | undefined;
77
+ }
78
+ /** Attribute key for one pset property / quantity. */
79
+ export declare function structuredAttributeKey(setName: string, name: string): string;
80
+ /**
81
+ * Fold an entity's structured branches into its flat attribute record.
82
+ * Structured values overwrite same-key flat attributes — the typed
83
+ * branch is the newer write path, so it wins deterministically.
84
+ */
85
+ export declare function flattenStructuredBranches(json: {
86
+ attributes: Record<string, unknown>;
87
+ } & StructuredBranchesJSON, options?: FlattenOptions): Record<string, unknown>;
88
+ export interface InflatedAttributes extends StructuredBranchesJSON {
89
+ /** Whatever didn't inflate — stays in the flat attributes branch. */
90
+ attributes: Record<string, unknown>;
91
+ geometryRefRecord?: GeometryRefRecord;
92
+ /** Embedded geometry records to recreate in the doc's geometry map, if carried. */
93
+ geometryCarriers: GeometryRefCarrier[];
94
+ }
95
+ /**
96
+ * Inverse of `flattenStructuredBranches`: split an IFCX attribute
97
+ * record into the flat remainder and the structured branches. Keys
98
+ * whose values don't pass the shape gates stay flat (legacy migrated
99
+ * raw values, foreign data under colliding namespaces).
100
+ */
101
+ export declare function inflateStructuredAttributes(attributes: Record<string, unknown>): InflatedAttributes;
102
+ /**
103
+ * `FlattenOptions.geometryRecordFor` backed by `doc`'s geometry map.
104
+ * The CRDT version vector is replica bookkeeping and never travels.
105
+ */
106
+ export declare function geometryRecordLookup(doc: Y.Doc): (geomId: string) => Omit<GeometryRefCarrier, 'geomId'> | undefined;
107
+ //# sourceMappingURL=structured-attrs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structured-attrs.d.ts","sourceRoot":"","sources":["../../src/snapshot/structured-attrs.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAgB,eAAe,EAAqC,MAAM,gBAAgB,CAAC;AAClG,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EACnB,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAE,eAAe,EAAE,CAAC;AAa3B;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAE5E;AAaD,2EAA2E;AAC3E,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;IACrD,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,eAAe,EAAE,iBAAiB,EAAE,CAAC;IACrC,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAChC,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GAAG,SAAS,CAAC;CACxF;AAED,sDAAsD;AACtD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,sBAAsB,EACtE,OAAO,GAAE,cAAmB,GAC3B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA+BzB;AAED,MAAM,WAAW,kBAAmB,SAAQ,sBAAsB;IAChE,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,mFAAmF;IACnF,gBAAgB,EAAE,kBAAkB,EAAE,CAAC;CACxC;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,kBAAkB,CA+FpB;AAOD;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,CAAC,CAAC,GAAG,GACT,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GAAG,SAAS,CAqBpE"}