@shapeshift-labs/frontier-lang-compiler 0.2.103 → 0.2.104

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.
Files changed (124) hide show
  1. package/README.md +13 -0
  2. package/dist/declarations/bidirectional-target-change-source-edit.d.ts +30 -0
  3. package/dist/declarations/bidirectional-target-change.d.ts +10 -0
  4. package/dist/declarations/js-ts-safe-member-merge.d.ts +58 -0
  5. package/dist/declarations/js-ts-safe-merge.d.ts +120 -0
  6. package/dist/declarations/js-ts-semantic-conflict-sidecars.d.ts +235 -0
  7. package/dist/declarations/js-ts-semantic-merge-contracts.d.ts +287 -0
  8. package/dist/declarations/js-ts-semantic-merge.d.ts +4 -0
  9. package/dist/declarations/native-import-losses.d.ts +3 -0
  10. package/dist/declarations/semantic-edit-replay-diagnostics.d.ts +12 -0
  11. package/dist/declarations/semantic-edit-script.d.ts +7 -4
  12. package/dist/declarations/semantic-patch-bundle-index.d.ts +45 -0
  13. package/dist/declarations/semantic-patch-bundle.d.ts +6 -4
  14. package/dist/declarations/semantic-sidecar-example.d.ts +18 -0
  15. package/dist/declarations/semantic-transform-identity.d.ts +3 -0
  16. package/dist/declarations/source-preservation.d.ts +72 -0
  17. package/dist/declarations/universal-capability.d.ts +4 -0
  18. package/dist/declarations/universal-conversion-artifacts.d.ts +61 -1
  19. package/dist/declarations/universal-conversion-compact-counts.d.ts +51 -0
  20. package/dist/declarations/universal-conversion-plan.d.ts +6 -1
  21. package/dist/declarations/universal-representation-coverage.d.ts +90 -0
  22. package/dist/index.d.ts +4 -0
  23. package/dist/index.js +3 -0
  24. package/dist/internal/index-impl/bidirectionalExactSourceBackprojection.js +199 -0
  25. package/dist/internal/index-impl/bidirectionalSameLanguageSourceProjection.js +112 -0
  26. package/dist/internal/index-impl/bidirectionalSourceEditProjection.js +319 -0
  27. package/dist/internal/index-impl/bidirectionalSourceEditProjectionArtifacts.js +67 -0
  28. package/dist/internal/index-impl/bidirectionalTargetChangeRecordInternals.js +17 -5
  29. package/dist/internal/index-impl/bidirectionalTargetRoundtripEvidence.js +58 -20
  30. package/dist/internal/index-impl/createBidirectionalTargetChangeRecord.js +60 -7
  31. package/dist/internal/index-impl/createLightweightNativeImport.js +1 -0
  32. package/dist/internal/index-impl/createNativeSourcePreservation.js +28 -2
  33. package/dist/internal/index-impl/diffNativeSymbols.js +3 -3
  34. package/dist/internal/index-impl/nativeChangeProjectionSourceMapLinks.js +2 -0
  35. package/dist/internal/index-impl/projectSemanticEditScriptToSource.js +43 -8
  36. package/dist/internal/index-impl/replaySemanticEditLineEndings.js +34 -0
  37. package/dist/internal/index-impl/replaySemanticEditProjection.js +39 -19
  38. package/dist/internal/index-impl/semanticEditBundleAdmission.js +7 -3
  39. package/dist/internal/index-impl/semanticEditBundleIndex.js +47 -1
  40. package/dist/internal/index-impl/semanticEditExplicitSourceReplacement.js +40 -0
  41. package/dist/internal/index-impl/semanticEditOperationCoverage.js +33 -3
  42. package/dist/internal/index-impl/semanticEditProjectionRecord.js +29 -0
  43. package/dist/internal/index-impl/semanticEditReplayDiagnostics.js +39 -0
  44. package/dist/internal/index-impl/semanticEditReplaySourceReplacement.js +85 -0
  45. package/dist/internal/index-impl/semanticEditScripts.js +4 -0
  46. package/dist/internal/index-impl/semanticEditSourceRanges.js +27 -0
  47. package/dist/internal/index-impl/semanticIndexFromNativeDeclarations.js +1 -0
  48. package/dist/internal/index-impl/semanticPatchBundleAdmission.js +41 -7
  49. package/dist/internal/index-impl/semanticPatchBundleRecords.js +16 -0
  50. package/dist/internal/index-impl/semanticPatchBundleSourceRecords.js +2 -0
  51. package/dist/internal/index-impl/semanticSidecarQuality.js +111 -0
  52. package/dist/internal/index-impl/semanticSourceEditDedupe.js +69 -9
  53. package/dist/internal/index-impl/semanticTransformIdentityRecords.js +85 -9
  54. package/dist/js-ts-safe-member-merge-result.js +158 -0
  55. package/dist/js-ts-safe-member-merge.js +202 -0
  56. package/dist/js-ts-safe-merge-analyze.js +279 -0
  57. package/dist/js-ts-safe-merge-constants.js +50 -0
  58. package/dist/js-ts-safe-merge-context.js +118 -0
  59. package/dist/js-ts-safe-merge-ledger-validation.js +92 -0
  60. package/dist/js-ts-safe-merge-ledger.js +85 -0
  61. package/dist/js-ts-safe-merge-parse-declarations.js +210 -0
  62. package/dist/js-ts-safe-merge-parse-statements.js +155 -0
  63. package/dist/js-ts-safe-merge-plan.js +190 -0
  64. package/dist/js-ts-safe-merge.js +175 -0
  65. package/dist/js-ts-semantic-conflict-sidecar-constants.js +77 -0
  66. package/dist/js-ts-semantic-conflict-sidecar-detectors.js +195 -0
  67. package/dist/js-ts-semantic-conflict-sidecar-normalize.js +203 -0
  68. package/dist/js-ts-semantic-conflict-sidecar-utils.js +190 -0
  69. package/dist/js-ts-semantic-conflict-sidecars.js +81 -0
  70. package/dist/js-ts-semantic-merge-contract-helpers.js +128 -0
  71. package/dist/js-ts-semantic-merge-contracts.js +217 -0
  72. package/dist/js-ts-semantic-merge-member-containers.js +100 -0
  73. package/dist/js-ts-semantic-merge-member-keys.js +142 -0
  74. package/dist/js-ts-semantic-merge-member-segments.js +185 -0
  75. package/dist/js-ts-semantic-merge-member-source.js +64 -0
  76. package/dist/js-ts-semantic-merge-member-utils.js +18 -0
  77. package/dist/js-ts-semantic-merge-parse.js +15 -0
  78. package/dist/js-ts-semantic-merge.js +21 -0
  79. package/dist/lightweight-dependency-effects.js +51 -0
  80. package/dist/lightweight-dependency-language.js +12 -1
  81. package/dist/lightweight-dependency-relations.js +14 -27
  82. package/dist/native-region-scanner-core.js +33 -1
  83. package/dist/native-region-scanner-csharp.js +151 -0
  84. package/dist/native-region-scanner-dart.js +91 -0
  85. package/dist/native-region-scanner-dynamic.js +21 -151
  86. package/dist/native-region-scanner-functional.js +40 -13
  87. package/dist/native-region-scanner-java.js +97 -0
  88. package/dist/native-region-scanner-js-class.js +100 -0
  89. package/dist/native-region-scanner-js-helpers.js +28 -86
  90. package/dist/native-region-scanner-js-imports.js +121 -1
  91. package/dist/native-region-scanner-js-nested.js +96 -8
  92. package/dist/native-region-scanner-js-structure.js +27 -0
  93. package/dist/native-region-scanner-js-types.js +99 -0
  94. package/dist/native-region-scanner-js.js +70 -118
  95. package/dist/native-region-scanner-kotlin.js +94 -0
  96. package/dist/native-region-scanner-main.js +15 -181
  97. package/dist/native-region-scanner-php.js +80 -0
  98. package/dist/native-region-scanner-python.js +62 -0
  99. package/dist/native-region-scanner-ruby.js +72 -0
  100. package/dist/native-region-scanner-scala.js +91 -0
  101. package/dist/native-region-scanner-spans.js +74 -0
  102. package/dist/native-region-scanner-swift.js +155 -0
  103. package/dist/native-region-scanner.js +14 -10
  104. package/dist/native-source-ledger-helpers.js +195 -0
  105. package/dist/native-source-ledger.js +306 -0
  106. package/dist/native-source-preservation-scanner.js +4 -0
  107. package/dist/semantic-import-callsite-regions.js +136 -0
  108. package/dist/semantic-import-effect-regions.js +283 -0
  109. package/dist/semantic-import-regions.js +11 -2
  110. package/dist/semantic-import-sidecar-entry.js +16 -2
  111. package/dist/semantic-import-sidecar-types.d.ts +2 -0
  112. package/dist/semantic-sidecar-example.js +68 -0
  113. package/dist/universal-capability-matrix.js +23 -0
  114. package/dist/universal-conversion-artifact-query.js +79 -2
  115. package/dist/universal-conversion-artifact-semantic-edit.js +103 -0
  116. package/dist/universal-conversion-artifact-summary.js +33 -1
  117. package/dist/universal-conversion-artifacts.js +13 -48
  118. package/dist/universal-conversion-plan-scoring.js +21 -1
  119. package/dist/universal-conversion-plan-summary.js +30 -0
  120. package/dist/universal-conversion-plan.js +25 -9
  121. package/dist/universal-conversion-route-metadata.js +96 -0
  122. package/dist/universal-conversion-route-operations.js +7 -0
  123. package/dist/universal-representation-coverage.js +193 -0
  124. package/package.json +1 -1
@@ -0,0 +1,283 @@
1
+ import { caseSensitiveIdFragment, idFragment, uniqueRecordsById, uniqueStrings } from './native-import-utils.js';
2
+
3
+ const semanticFactRegionKinds = new Set(['controlFlow', 'effect', 'mutation']);
4
+
5
+ export function semanticEffectRegionRecordsForImport(imported, semanticIndex, options = {}) {
6
+ const symbolsById = new Map((semanticIndex?.symbols ?? []).map((symbol) => [symbol.id, symbol]));
7
+ const facts = (semanticIndex?.facts ?? []).filter((fact) => semanticFactRegionKinds.has(fact?.predicate)
8
+ && semanticFactSubjectCanOwnRuntimeRegion(symbolsById.get(fact.subjectId)));
9
+ if (!facts.length) return { symbols: [], ownershipRegions: [] };
10
+ const sourceText = nativeImportSourceText(imported);
11
+ const groups = semanticFactRegionGroups(facts);
12
+ const ordinals = new Map();
13
+ const records = groups.map((group, index) => {
14
+ const fact = group.facts[0];
15
+ const spanInfo = semanticFactSpanInfo(sourceText, group, fact, imported);
16
+ const owner = symbolsById.get(fact.subjectId);
17
+ const sourcePath = fact.value?.sourcePath ?? imported?.sourcePath ?? imported?.nativeSource?.sourcePath;
18
+ const language = imported?.language ?? imported?.nativeSource?.language ?? imported?.nativeAst?.language;
19
+ const signature = semanticFactRegionSignature(group);
20
+ const ordinal = nextSemanticFactOrdinal(ordinals, group, fact, signature);
21
+ const symbolName = `${owner?.name ?? fact.subjectId}:${group.regionKind}:${signature}#${ordinal}`;
22
+ const key = semanticFactRegionKey(options.regionPrefix, sourcePath, group.regionKind, symbolName, index);
23
+ const region = {
24
+ id: `region_${caseSensitiveIdFragment(key)}`,
25
+ key,
26
+ regionKind: group.regionKind,
27
+ granularity: 'semantic-fact-line',
28
+ language,
29
+ sourcePath,
30
+ sourceHash: imported?.nativeSource?.sourceHash ?? imported?.nativeAst?.sourceHash ?? imported?.sourceHash,
31
+ symbolId: `symbol:${language ?? 'source'}:${group.regionKind}:${idFragment(key)}`,
32
+ symbolName,
33
+ symbolKind: group.regionKind,
34
+ nativeAstNodeId: owner?.nativeAstNodeId,
35
+ sourceSpan: spanInfo.span,
36
+ precision: spanInfo.precision,
37
+ mergePolicy: semanticFactRegionMergePolicy(group.regionKind),
38
+ metadata: {
39
+ semanticRegionTaxonomy: true,
40
+ factIds: group.facts.map((item) => item.id).filter(Boolean),
41
+ factKinds: group.factKinds,
42
+ factLine: group.line,
43
+ predicate: group.regionKind,
44
+ spanKind: spanInfo.kind,
45
+ occurrenceOrdinal: ordinal,
46
+ subjectId: fact.subjectId,
47
+ subjectName: owner?.name
48
+ }
49
+ };
50
+ return {
51
+ region,
52
+ symbol: {
53
+ id: region.symbolId,
54
+ name: symbolName,
55
+ kind: group.regionKind,
56
+ language,
57
+ nativeAstNodeId: region.nativeAstNodeId,
58
+ sourceSpan: region.sourceSpan,
59
+ ownershipRegionId: region.id,
60
+ ownershipKey: region.key,
61
+ ownershipRegionKind: group.regionKind,
62
+ readiness: 'needs-review'
63
+ }
64
+ };
65
+ });
66
+ return {
67
+ symbols: uniqueRecordsById(records.map((record) => record.symbol)),
68
+ ownershipRegions: uniqueRecordsById(records.map((record) => record.region))
69
+ };
70
+ }
71
+
72
+ function semanticFactRegionGroups(facts) {
73
+ const groups = new Map();
74
+ for (const fact of facts) {
75
+ const line = Number(fact?.value?.line);
76
+ if (!Number.isFinite(line)) continue;
77
+ const regionKind = String(fact.predicate);
78
+ const key = [regionKind, fact.subjectId, fact.value?.sourcePath, line].join('\0');
79
+ const group = groups.get(key) ?? { regionKind, line, sourcePath: fact.value?.sourcePath, facts: [] };
80
+ group.facts.push(fact);
81
+ group.factKinds = uniqueStrings(group.facts.map((item) => item.value?.kind).filter(Boolean));
82
+ groups.set(key, group);
83
+ }
84
+ return [...groups.values()].flatMap(splitSemanticFactGroup);
85
+ }
86
+
87
+ function splitSemanticFactGroup(group) {
88
+ if (group.regionKind === 'effect') return splitEffectFactGroup(group);
89
+ return group.factKinds.map((factKind) => ({
90
+ ...group,
91
+ facts: group.facts.filter((fact) => fact.value?.kind === factKind),
92
+ factKinds: [factKind]
93
+ }));
94
+ }
95
+
96
+ function splitEffectFactGroup(group) {
97
+ const concreteKinds = group.factKinds.filter((kind) => kind !== 'async');
98
+ if (!concreteKinds.length) return [group];
99
+ return concreteKinds.map((factKind, index) => ({
100
+ ...group,
101
+ facts: group.facts.filter((fact) => fact.value?.kind === factKind
102
+ || (index === 0 && fact.value?.kind === 'async')),
103
+ factKinds: uniqueStrings([factKind, index === 0 && group.factKinds.includes('async') ? 'async' : undefined])
104
+ }));
105
+ }
106
+
107
+ function semanticFactRegionSignature(group) {
108
+ return (group.factKinds?.length ? group.factKinds : [group.regionKind]).join('+');
109
+ }
110
+
111
+ function nextSemanticFactOrdinal(ordinals, group, fact, signature) {
112
+ const key = [group.regionKind, fact.subjectId, group.sourcePath, signature].join('\0');
113
+ const next = (ordinals.get(key) ?? 0) + 1;
114
+ ordinals.set(key, next);
115
+ return next;
116
+ }
117
+
118
+ function semanticFactSubjectCanOwnRuntimeRegion(symbol) {
119
+ if (!symbol) return true;
120
+ if (symbol.metadata?.ownershipRegionKind === 'body') return true;
121
+ return /function|method|action|effect|handler|constructor/
122
+ .test(String(symbol.kind ?? '').toLowerCase());
123
+ }
124
+
125
+ function semanticFactSpanInfo(sourceText, group, fact, imported) {
126
+ const lineNumber = Number(fact?.value?.line);
127
+ if (!Number.isFinite(lineNumber)) return { span: undefined, precision: 'unknown', kind: 'unknown' };
128
+ const line = String(sourceText ?? '').split(/\r\n|\n|\r/)[lineNumber - 1] ?? '';
129
+ const leading = line.match(/^\s*/)?.[0].length ?? 0;
130
+ const expression = semanticFactExpressionRange(line, group) ?? { start: leading, end: line.length, kind: 'line' };
131
+ return {
132
+ span: {
133
+ sourceId: imported?.nativeSource?.sourceHash ?? imported?.nativeAst?.sourceHash ?? imported?.sourceHash,
134
+ path: fact.value?.sourcePath ?? imported?.sourcePath ?? imported?.nativeSource?.sourcePath,
135
+ startLine: lineNumber,
136
+ endLine: lineNumber,
137
+ startColumn: expression.start + 1,
138
+ endColumn: expression.end + 1
139
+ },
140
+ precision: expression.kind === 'line' ? 'line' : 'expression',
141
+ kind: expression.kind
142
+ };
143
+ }
144
+
145
+ function semanticFactExpressionRange(line, group) {
146
+ if (group.regionKind === 'effect') return effectRange(line, group.factKinds);
147
+ if (group.regionKind === 'mutation') return mutationRange(line, group.factKinds);
148
+ if (group.regionKind === 'controlFlow') return controlFlowRange(line, group.factKinds);
149
+ return undefined;
150
+ }
151
+
152
+ function effectRange(line, kinds) {
153
+ if (kinds.includes('network')) return namedCallRange(line, ['fetch', 'XMLHttpRequest', 'WebSocket', 'EventSource'], 'network-call');
154
+ if (kinds.includes('scheduler')) return namedCallRange(line, ['setTimeout', 'setInterval', 'requestAnimationFrame', 'queueMicrotask'], 'scheduler-call');
155
+ if (kinds.includes('storage')) return tokenExpressionRange(line, ['localStorage', 'sessionStorage', 'indexedDB', 'caches', 'cookie'], 'storage-effect');
156
+ if (kinds.includes('host')) return tokenExpressionRange(line, ['console', 'process', 'Deno', 'Bun'], 'host-effect');
157
+ if (kinds.includes('browser')) return tokenExpressionRange(line, ['document', 'window', 'navigator', 'location', 'history'], 'browser-effect');
158
+ if (kinds.includes('async')) return keywordExpressionRange(line, 'await', 'async-effect');
159
+ return undefined;
160
+ }
161
+
162
+ function mutationRange(line, kinds) {
163
+ if (kinds.includes('mutating-call')) return mutatingCallRange(line);
164
+ if (kinds.includes('delete')) return keywordExpressionRange(line, 'delete', 'delete-mutation');
165
+ if (kinds.includes('assignment')) return assignmentRange(line);
166
+ if (kinds.includes('update')) return updateRange(line);
167
+ return undefined;
168
+ }
169
+
170
+ function controlFlowRange(line, kinds) {
171
+ if (kinds.includes('exit')) return keywordExpressionRange(line, /(return|yield)\b/, 'control-exit');
172
+ if (kinds.includes('branch')) return controlHeadRange(line, /(if|switch)\b/, 'control-branch')
173
+ ?? caseHeadRange(line) ?? keywordExpressionRange(line, /else\b/, 'control-branch');
174
+ if (kinds.includes('loop')) return controlHeadRange(line, /(for|while)\b/, 'control-loop')
175
+ ?? keywordExpressionRange(line, /do\b/, 'control-loop');
176
+ if (kinds.includes('exception')) return keywordExpressionRange(line, /(throw|catch|finally|try)\b/, 'control-exception');
177
+ if (kinds.includes('async')) return keywordExpressionRange(line, /(await|async)\b/, 'control-async');
178
+ return undefined;
179
+ }
180
+
181
+ function namedCallRange(line, names, kind) {
182
+ for (const name of names) {
183
+ const pattern = new RegExp(`(?:^|[^\\w$.])((?:window|globalThis|self)\\s*\\.\\s*)?${name}\\s*\\(`);
184
+ const match = pattern.exec(line);
185
+ if (!match) continue;
186
+ const start = match.index + match[0].search(new RegExp(`((?:window|globalThis|self)\\s*\\.\\s*)?${name}\\s*\\(`));
187
+ const open = line.indexOf('(', start);
188
+ const close = matchingParenIndex(line, open);
189
+ return { start, end: close === undefined ? statementEnd(line, open) : close + 1, kind };
190
+ }
191
+ return undefined;
192
+ }
193
+
194
+ function controlHeadRange(line, keyword, kind) {
195
+ const match = keyword.exec(line);
196
+ if (!match) return undefined;
197
+ const open = line.indexOf('(', match.index);
198
+ const close = matchingParenIndex(line, open);
199
+ return close === undefined ? undefined : { start: match.index, end: close + 1, kind };
200
+ }
201
+
202
+ function caseHeadRange(line) {
203
+ const match = /\b(case|default)\b/.exec(line);
204
+ if (!match) return undefined;
205
+ const colon = line.indexOf(':', match.index);
206
+ return { start: match.index, end: colon === -1 ? statementEnd(line, match.index) : colon + 1, kind: 'control-branch' };
207
+ }
208
+
209
+ function mutatingCallRange(line) {
210
+ const match = /[A-Za-z_$][\w$.[\]]*(?:\s*\.\s*[A-Za-z_$][\w$.[\]]*)*\s*\.\s*(?:push|pop|shift|unshift|splice|sort|reverse|set|add|delete|clear)\s*\(/.exec(line);
211
+ if (!match) return undefined;
212
+ const open = line.indexOf('(', match.index);
213
+ const close = matchingParenIndex(line, open);
214
+ return { start: match.index, end: close === undefined ? statementEnd(line, open) : close + 1, kind: 'mutating-call' };
215
+ }
216
+
217
+ function assignmentRange(line) {
218
+ const match = /\b[A-Za-z_$][\w$.[\]]*\s*=(?!=|>)/.exec(line);
219
+ return match ? { start: match.index, end: statementEnd(line, match.index), kind: 'assignment' } : undefined;
220
+ }
221
+
222
+ function updateRange(line) {
223
+ const match = /\b[A-Za-z_$][\w$.[\]]*(?:\+\+|--|\s*(?:\+=|-=|\*=|\/=|%=|\|\|=|&&=|\?\?=))/.exec(line);
224
+ return match ? { start: match.index, end: statementEnd(line, match.index), kind: 'update' } : undefined;
225
+ }
226
+
227
+ function tokenExpressionRange(line, tokens, kind) {
228
+ const pattern = new RegExp(`\\b(?:${tokens.join('|')})\\b`);
229
+ const match = pattern.exec(line);
230
+ return match ? { start: match.index, end: statementEnd(line, match.index), kind } : undefined;
231
+ }
232
+
233
+ function keywordExpressionRange(line, keyword, kind) {
234
+ const match = keyword instanceof RegExp ? keyword.exec(line) : new RegExp(`\\b${keyword}\\b`).exec(line);
235
+ return match ? { start: match.index, end: statementEnd(line, match.index), kind } : undefined;
236
+ }
237
+
238
+ function statementEnd(line, start) {
239
+ const semicolon = line.indexOf(';', Math.max(0, start));
240
+ return semicolon === -1 ? line.length : semicolon + 1;
241
+ }
242
+
243
+ function matchingParenIndex(line, open) {
244
+ if (open < 0) return undefined;
245
+ let depth = 0;
246
+ let quote;
247
+ let escaped = false;
248
+ for (let index = open; index < line.length; index += 1) {
249
+ const char = line[index];
250
+ if (quote) {
251
+ if (escaped) escaped = false;
252
+ else if (char === '\\') escaped = true;
253
+ else if (char === quote) quote = undefined;
254
+ continue;
255
+ }
256
+ if (char === '\'' || char === '"' || char === '`') {
257
+ quote = char;
258
+ continue;
259
+ }
260
+ if (char === '(') depth += 1;
261
+ else if (char === ')' && --depth === 0) return index;
262
+ }
263
+ return undefined;
264
+ }
265
+
266
+ function semanticFactRegionKey(prefix = 'source', sourcePath, regionKind, symbolName, index) {
267
+ return [prefix, sourcePath ?? 'memory', regionKind, symbolName || `unknown#${index + 1}`]
268
+ .map((part) => String(part).replace(/\s+/g, ' ').trim())
269
+ .join('#');
270
+ }
271
+
272
+ function semanticFactRegionMergePolicy(regionKind) {
273
+ if (regionKind === 'controlFlow') return 'control-flow-review-required';
274
+ if (regionKind === 'mutation') return 'mutation-boundary-review-required';
275
+ return 'effect-boundary-review-required';
276
+ }
277
+
278
+ function nativeImportSourceText(imported) {
279
+ return imported?.metadata?.sourcePreservation?.sourceText
280
+ ?? imported?.nativeSource?.metadata?.sourcePreservation?.sourceText
281
+ ?? imported?.nativeAst?.metadata?.sourcePreservation?.sourceText
282
+ ?? imported?.universalAst?.metadata?.sourcePreservation?.sourceText;
283
+ }
@@ -4,10 +4,13 @@ const NativeImportRegionTaxonomyKinds = Object.freeze([
4
4
  'symbol',
5
5
  'declaration',
6
6
  'import',
7
+ 'export',
7
8
  'body',
8
9
  'call',
9
10
  'type',
11
+ 'controlFlow',
10
12
  'effect',
13
+ 'mutation',
11
14
  'property',
12
15
  'config',
13
16
  'content',
@@ -52,9 +55,10 @@ function semanticOwnershipRegionForDeclaration(input, declaration, documentId) {
52
55
  const kind = declaration.symbolKind ?? declaration.kind ?? declaration.nativeNode?.kind ?? 'symbol';
53
56
  const sourcePath = declaration.span?.path ?? declaration.nativeNode?.span?.path ?? input.sourcePath ?? `${input.language}:memory`;
54
57
  const regionKind = semanticRegionKindForDeclaration(declaration);
55
- const key = ['source', sourcePath, regionKind, name].map((part) => String(part).replace(/\s+/g, ' ').trim()).join('#');
58
+ const key = declaration.metadata?.ownershipRegionKey
59
+ ?? ['source', sourcePath, regionKind, name].map((part) => String(part).replace(/\s+/g, ' ').trim()).join('#');
56
60
  return {
57
- id: `region_${caseSensitiveIdFragment(key)}`,
61
+ id: declaration.metadata?.ownershipRegionId ?? `region_${caseSensitiveIdFragment(key)}`,
58
62
  key,
59
63
  regionKind,
60
64
  granularity: 'symbol',
@@ -131,17 +135,22 @@ function semanticRegionMergePolicy(regionKind) {
131
135
  if (regionKind === 'body') return 'implementation-single-writer-review-required';
132
136
  if (regionKind === 'call') return 'callsite-overlap-review-required';
133
137
  if (regionKind === 'type') return 'type-surface-review-required';
138
+ if (regionKind === 'controlFlow') return 'control-flow-review-required';
134
139
  if (regionKind === 'effect') return 'effect-boundary-review-required';
140
+ if (regionKind === 'mutation') return 'mutation-boundary-review-required';
135
141
  if (regionKind === 'generatedOutput') return 'generated-output-source-map-review-required';
136
142
  return 'single-writer-review-required';
137
143
  }
138
144
 
139
145
  function semanticRegionSupportedOperations(region) {
140
146
  if (region.regionKind === 'import') return ['replace-import', 'insert-import-before', 'insert-import-after', 'replace-region'];
147
+ if (region.regionKind === 'export') return ['replace-export', 'insert-export-before', 'insert-export-after', 'replace-region'];
141
148
  if (region.regionKind === 'body') return ['replace-body', 'insert-before-body', 'insert-after-body'];
142
149
  if (region.regionKind === 'call') return ['replace-callsite', 'review-callsite'];
143
150
  if (region.regionKind === 'type') return ['replace-type-declaration', 'merge-type-members', 'replace-region'];
151
+ if (region.regionKind === 'controlFlow') return ['replace-control-flow', 'review-control-flow'];
144
152
  if (region.regionKind === 'effect') return ['route-effect', 'replace-effect-boundary', 'review-effect-policy'];
153
+ if (region.regionKind === 'mutation') return ['replace-mutation', 'review-mutation'];
145
154
  if (region.regionKind === 'generatedOutput') return ['replace-generated-output', 'attach-generated-source-map', 'review-generator-input'];
146
155
  return ['replace-region', 'insert-before-region', 'insert-after-region'];
147
156
  }
@@ -1,5 +1,7 @@
1
1
  import { uniqueRecordsById, uniqueStrings } from './native-import-utils.js';
2
+ import { semanticCallsiteRecordsForImport } from './semantic-import-callsite-regions.js';
2
3
  import { summarizeSemanticImportDependencyRelations } from './semantic-import-dependencies.js';
4
+ import { semanticEffectRegionRecordsForImport } from './semantic-import-effect-regions.js';
3
5
  import { semanticOwnershipRegionForSymbol, semanticPatchHintForRegion, summarizeSemanticImportRegionTaxonomy } from './semantic-import-regions.js';
4
6
  import { collectKernelSourcePreservationFromImport } from './semantic-import-source-preservation.js';
5
7
  import {
@@ -23,16 +25,22 @@ function semanticImportSidecarEntry(imported, index, options) {
23
25
  const dependencies = summarizeSemanticImportDependencyRelations(semanticIndex?.relations ?? []);
24
26
  const factSummary = summarizeSemanticFacts(semanticFacts);
25
27
  const readiness = semanticImportEntryReadiness(imported);
28
+ const callsites = semanticCallsiteRecordsForImport(imported, semanticIndex, options);
29
+ const effectRegions = semanticEffectRegionRecordsForImport(imported, semanticIndex, options);
26
30
  const mappingsBySymbolId = new Map();
31
+ const mappingsBySymbolAndNode = new Map();
27
32
  for (const mapping of sourceMapMappings) {
28
33
  if (mapping.semanticSymbolId && !mappingsBySymbolId.has(mapping.semanticSymbolId)) {
29
34
  mappingsBySymbolId.set(mapping.semanticSymbolId, mapping);
30
35
  }
36
+ if (mapping.semanticSymbolId && mapping.nativeAstNodeId) {
37
+ mappingsBySymbolAndNode.set(`${mapping.semanticSymbolId}\0${mapping.nativeAstNodeId}`, mapping);
38
+ }
31
39
  }
32
40
  const symbols = [];
33
41
  const regions = [];
34
42
  for (const symbol of semanticSymbols) {
35
- const mapping = mappingsBySymbolId.get(symbol.id);
43
+ const mapping = mappingsBySymbolAndNode.get(`${symbol.id}\0${symbol.nativeAstNodeId}`) ?? mappingsBySymbolId.get(symbol.id);
36
44
  const nativeNode = symbol.nativeAstNodeId ? nativeAst?.nodes?.[symbol.nativeAstNodeId] : undefined;
37
45
  const generatedRegion = semanticOwnershipRegionForSymbol(imported, symbol, mapping, nativeNode, options);
38
46
  const region = mergeSemanticOwnershipRegion(
@@ -48,8 +56,10 @@ function semanticImportSidecarEntry(imported, index, options) {
48
56
  nativeAstNodeId: symbol.nativeAstNodeId,
49
57
  semanticOccurrenceId: mapping?.semanticOccurrenceId,
50
58
  sourceMapMappingId: mapping?.id,
51
- sourceSpan: region.sourceSpan ?? mapping?.sourceSpan ?? symbol.definitionSpan ?? nativeNode?.span,
59
+ sourceSpan: mapping?.sourceSpan ?? symbol.definitionSpan ?? nativeNode?.span ?? region.sourceSpan,
52
60
  signatureHash: symbol.signatureHash,
61
+ signatureOnly: symbol.metadata?.signatureOnly === true || undefined,
62
+ hasBody: typeof symbol.metadata?.hasBody === 'boolean' ? symbol.metadata.hasBody : undefined,
53
63
  ownershipRegionId: region.id,
54
64
  ownershipKey: region.key,
55
65
  ownershipRegionKind: region.regionKind,
@@ -59,6 +69,10 @@ function semanticImportSidecarEntry(imported, index, options) {
59
69
  for (const [regionIndex, region] of importedOwnershipRegions.entries()) {
60
70
  regions.push(normalizeImportedOwnershipRegion(imported, region, regionIndex, options));
61
71
  }
72
+ regions.push(...callsites.ownershipRegions);
73
+ regions.push(...effectRegions.ownershipRegions);
74
+ symbols.push(...callsites.symbols.map((symbol) => ({ ...symbol, readiness })));
75
+ symbols.push(...effectRegions.symbols.map((symbol) => ({ ...symbol, readiness })));
62
76
  const ownershipRegions = uniqueRecordsById(regions);
63
77
  const regionTaxonomy = summarizeSemanticImportRegionTaxonomy(ownershipRegions);
64
78
  const patchHints = ownershipRegions.map((region) => semanticPatchHintForRegion(region, readiness, options));
@@ -37,6 +37,8 @@ export interface SemanticImportSidecarSymbol {
37
37
  readonly sourceMapMappingId?: string;
38
38
  readonly sourceSpan?: SourceSpan;
39
39
  readonly signatureHash?: string;
40
+ readonly signatureOnly?: boolean;
41
+ readonly hasBody?: boolean;
40
42
  readonly ownershipRegionId: string;
41
43
  readonly ownershipKey: string;
42
44
  readonly ownershipRegionKind?: NativeImportRegionTaxonomyKind;
@@ -0,0 +1,68 @@
1
+ import { createSemanticImportSidecar } from './internal/index-impl/createSemanticImportSidecar.js';
2
+
3
+ const compactExampleSource = Object.freeze({
4
+ schema: 'frontier.lang.semanticImportSidecar.example.compact.v1',
5
+ baseSource: {
6
+ path: 'src/compact-sidecar.ts',
7
+ hash: 'sha256:base-compact-sidecar-v1',
8
+ identityHash: 'sha256:identity-compact-sidecar-example-v1',
9
+ text: 'export function compactSidecarExample(value: number) {\n return value + 1;\n}\n'
10
+ },
11
+ headSource: {
12
+ path: 'src/compact-sidecar.ts',
13
+ hash: 'sha256:head-compact-sidecar-v2',
14
+ identityHash: 'sha256:identity-compact-sidecar-example-v1',
15
+ text: 'export function compactSidecarExample(value: number) {\n return value + 2;\n}\n'
16
+ },
17
+ identityHashes: {
18
+ source: 'sha256:identity-compact-sidecar-example-v1',
19
+ symbol: 'sha256:symbol-compact-sidecar-example-v1',
20
+ signature: 'sha256:signature-compact-sidecar-example-v1'
21
+ }
22
+ });
23
+
24
+ const compactExampleImport = Object.freeze({
25
+ id: 'compact_sidecar_example_import',
26
+ language: 'typescript',
27
+ sourcePath: compactExampleSource.headSource.path,
28
+ sourceHash: compactExampleSource.headSource.hash,
29
+ semanticIndex: {
30
+ id: 'semantic_index_compact_sidecar_example',
31
+ symbols: [{
32
+ id: 'symbol:compactSidecarExample',
33
+ name: 'compactSidecarExample',
34
+ kind: 'function',
35
+ language: 'typescript',
36
+ definitionSpan: {
37
+ path: compactExampleSource.headSource.path,
38
+ startLine: 1,
39
+ startColumn: 1,
40
+ endLine: 3,
41
+ endColumn: 2
42
+ },
43
+ signatureHash: compactExampleSource.identityHashes.signature,
44
+ metadata: { ownershipRegionKind: 'body' }
45
+ }],
46
+ relations: [],
47
+ facts: []
48
+ },
49
+ evidence: [{
50
+ id: 'evidence_compact_sidecar_example',
51
+ kind: 'semantic-sidecar-example',
52
+ status: 'passed'
53
+ }]
54
+ });
55
+
56
+ export const compactSemanticSidecarExample = Object.freeze({
57
+ ...compactExampleSource,
58
+ sidecar: createSemanticImportSidecar(compactExampleImport, {
59
+ id: 'semantic_import_compact_sidecar_example',
60
+ generatedAt: 132,
61
+ targetPath: 'dist/compact-sidecar.js',
62
+ metadata: {
63
+ baseSource: compactExampleSource.baseSource,
64
+ headSource: compactExampleSource.headSource,
65
+ identityHashes: compactExampleSource.identityHashes
66
+ }
67
+ })
68
+ });
@@ -11,6 +11,7 @@ import { createNativeParserAstFormatMatrix } from './native-parser-ast-format-ma
11
11
  import { createNativeParserFeatureMatrix } from './native-parser-feature-matrix.js';
12
12
  import { createProjectionReadinessMatrix } from './projection-readiness-matrix.js';
13
13
  import { createProjectionTargetLossMatrix } from './projection-target-loss-matrix.js';
14
+ import { createUniversalRepresentationCoverage } from './universal-representation-coverage.js';
14
15
 
15
16
  export function createUniversalCapabilityMatrix(input = {}, context = {}) {
16
17
  const generatedAt = input.generatedAt ?? Date.now();
@@ -110,6 +111,21 @@ function universalCapabilityLanguageRow(importCoverage, context) {
110
111
  unsupportedTargets,
111
112
  readiness
112
113
  });
114
+ const representation = createUniversalRepresentationCoverage({
115
+ sourceLanguage: importCoverage.language,
116
+ imports: importCoverage.imports,
117
+ parser: {
118
+ rows: parserRows.length,
119
+ mergeReadyParsers: parserRows.filter((row) => row.merge?.mergeReady).map((row) => row.parser),
120
+ reviewFeatures: parserReviewFeatures
121
+ },
122
+ projection: {
123
+ sourceProjection: projection?.sourceProjection,
124
+ targets: projection?.targets ?? [],
125
+ missingTargets,
126
+ unsupportedTargets
127
+ }
128
+ });
113
129
  return {
114
130
  language: importCoverage.language,
115
131
  aliases: importCoverage.aliases,
@@ -156,6 +172,7 @@ function universalCapabilityLanguageRow(importCoverage, context) {
156
172
  knownLossKinds: importCoverage.knownLossKinds,
157
173
  sourceMapMappings: importCoverage.imports.sourceMapMappings
158
174
  },
175
+ representation,
159
176
  blockers,
160
177
  review
161
178
  };
@@ -225,6 +242,8 @@ function universalCapabilityMatrixSummary(rows) {
225
242
  let unsupportedTargetFeatures = 0;
226
243
  let exactSourceProjection = 0;
227
244
  let nativeSourceStubs = 0;
245
+ let representationConstructs = 0;
246
+ let representationMissing = 0;
228
247
  let blockers = 0;
229
248
  let reviewReasons = 0;
230
249
  for (const row of rows) {
@@ -243,6 +262,8 @@ function universalCapabilityMatrixSummary(rows) {
243
262
  unsupportedTargetFeatures += row.projection.unsupportedTargets.length;
244
263
  exactSourceProjection += row.projection.summary.byLossClass?.exactSourceProjection ?? 0;
245
264
  nativeSourceStubs += row.projection.summary.byLossClass?.nativeSourceStubs ?? 0;
265
+ representationConstructs += row.representation?.summary?.representedConstructs ?? 0;
266
+ representationMissing += row.representation?.summary?.missing ?? 0;
246
267
  blockers += row.blockers.length;
247
268
  reviewReasons += row.review.length;
248
269
  }
@@ -259,6 +280,8 @@ function universalCapabilityMatrixSummary(rows) {
259
280
  unsupportedTargetFeatures,
260
281
  exactSourceProjection,
261
282
  nativeSourceStubs,
283
+ representationConstructs,
284
+ representationMissing,
262
285
  blockers,
263
286
  reviewReasons,
264
287
  readyLanguages: rows.filter((row) => row.readiness === 'ready').length,
@@ -1,4 +1,5 @@
1
1
  import { uniqueStrings } from './native-import-utils.js';
2
+ import { artifactSemanticEditIndex } from './universal-conversion-artifact-semantic-edit.js';
2
3
 
3
4
  export function queryUniversalConversionArtifacts(records, query = {}) {
4
5
  return artifactRecords(records)
@@ -8,6 +9,7 @@ export function queryUniversalConversionArtifacts(records, query = {}) {
8
9
  }
9
10
 
10
11
  export function artifactIndex(routeArtifacts) {
12
+ const semanticEditIndexes = routeArtifacts.map(artifactSemanticEditIndex);
11
13
  return {
12
14
  routeIds: uniqueStrings(routeArtifacts.map((artifact) => artifact.routeId)),
13
15
  historyIds: uniqueStrings(routeArtifacts.map((artifact) => artifact.history.id)),
@@ -27,7 +29,28 @@ export function artifactIndex(routeArtifacts) {
27
29
  evidenceIds: uniqueStrings(routeArtifacts.flatMap((artifact) => artifact.history.evidenceIds)),
28
30
  proofIds: uniqueStrings(routeArtifacts.flatMap((artifact) => artifact.history.proofIds)),
29
31
  semanticOperationIds: uniqueStrings(routeArtifacts.flatMap((artifact) => artifact.semanticOperations?.operations ?? []).map((operation) => operation.id)),
30
- semanticOperationKinds: uniqueStrings(routeArtifacts.flatMap((artifact) => artifact.semanticOperations?.operations ?? []).map((operation) => operation.operationKind))
32
+ semanticOperationKinds: uniqueStrings(routeArtifacts.flatMap((artifact) => artifact.semanticOperations?.operations ?? []).map((operation) => operation.operationKind)),
33
+ semanticEditStatuses: uniqueStrings(semanticEditIndexes.flatMap((index) => index.semanticEditStatuses)),
34
+ semanticEditScriptIds: uniqueStrings(semanticEditIndexes.flatMap((index) => index.semanticEditScriptIds)),
35
+ semanticEditProjectionIds: uniqueStrings(semanticEditIndexes.flatMap((index) => index.semanticEditProjectionIds)),
36
+ semanticEditReplayIds: uniqueStrings(semanticEditIndexes.flatMap((index) => index.semanticEditReplayIds)),
37
+ semanticEditReplayStatuses: uniqueStrings(semanticEditIndexes.flatMap((index) => index.semanticEditReplayStatuses)),
38
+ semanticEditReplayActions: uniqueStrings(semanticEditIndexes.flatMap((index) => index.semanticEditReplayActions)),
39
+ semanticEditAdmissionStatuses: uniqueStrings(semanticEditIndexes.flatMap((index) => index.semanticEditAdmissionStatuses)),
40
+ semanticEditAdmissionActions: uniqueStrings(semanticEditIndexes.flatMap((index) => index.semanticEditAdmissionActions)),
41
+ semanticEditAdmissionReadinesses: uniqueStrings(semanticEditIndexes.flatMap((index) => index.semanticEditAdmissionReadinesses)),
42
+ semanticEditReplayCurrentHashes: uniqueStrings(semanticEditIndexes.flatMap((index) => index.semanticEditReplayCurrentHashes)),
43
+ semanticEditReplayOutputHashes: uniqueStrings(semanticEditIndexes.flatMap((index) => index.semanticEditReplayOutputHashes)),
44
+ semanticEditKeys: uniqueStrings(semanticEditIndexes.flatMap((index) => index.semanticEditKeys)),
45
+ semanticEditHashes: uniqueStrings(semanticEditIndexes.flatMap((index) => index.semanticEditHashes)),
46
+ semanticIdentityHashes: uniqueStrings(semanticEditIndexes.flatMap((index) => index.semanticIdentityHashes)),
47
+ sourceIdentityHashes: uniqueStrings(semanticEditIndexes.flatMap((index) => index.sourceIdentityHashes)),
48
+ operationContentHashes: uniqueStrings(semanticEditIndexes.flatMap((index) => index.operationContentHashes)),
49
+ editContentHashes: uniqueStrings(semanticEditIndexes.flatMap((index) => index.editContentHashes)),
50
+ representationConstructKinds: uniqueStrings(routeArtifacts.flatMap(artifactConstructKinds)),
51
+ runtimeCapabilities: uniqueStrings(routeArtifacts.flatMap(artifactRuntimeCapabilities)),
52
+ sourceMapPrecisions: uniqueStrings(routeArtifacts.flatMap(artifactSourceMapPrecisions)),
53
+ transformIdentityHashes: uniqueStrings(routeArtifacts.flatMap(artifactTransformIdentityHashes))
31
54
  };
32
55
  }
33
56
 
@@ -39,6 +62,7 @@ function artifactRecords(records) {
39
62
  }
40
63
 
41
64
  function matchesArtifact(record, query) {
65
+ const semanticEditIndex = artifactSemanticEditIndex(record);
42
66
  return match(query.routeId, [record.routeId])
43
67
  && match(query.historyId, [record.history.id])
44
68
  && match(query.patchBundleId, [record.patchBundle.id])
@@ -59,7 +83,60 @@ function matchesArtifact(record, query) {
59
83
  && match(query.evidenceId, record.history.evidenceIds)
60
84
  && match(query.proofId, record.history.proofIds)
61
85
  && match(query.semanticOperationId, (record.semanticOperations?.operations ?? []).map((operation) => operation.id))
62
- && match(query.semanticOperationKind, (record.semanticOperations?.operations ?? []).map((operation) => operation.operationKind));
86
+ && match(query.semanticOperationKind, (record.semanticOperations?.operations ?? []).map((operation) => operation.operationKind))
87
+ && match(query.semanticEditStatus ?? query.semanticEditStatuses, semanticEditIndex.semanticEditStatuses)
88
+ && match(query.semanticEditScriptId ?? query.semanticEditScriptIds, semanticEditIndex.semanticEditScriptIds)
89
+ && match(query.semanticEditProjectionId ?? query.semanticEditProjectionIds, semanticEditIndex.semanticEditProjectionIds)
90
+ && match(query.semanticEditReplayId ?? query.semanticEditReplayIds, semanticEditIndex.semanticEditReplayIds)
91
+ && match(query.semanticEditReplayStatus ?? query.semanticEditReplayStatuses, semanticEditIndex.semanticEditReplayStatuses)
92
+ && match(query.semanticEditReplayAction ?? query.semanticEditReplayActions, semanticEditIndex.semanticEditReplayActions)
93
+ && match(query.semanticEditAdmission ?? query.semanticEditAdmissionStatus ?? query.semanticEditAdmissionStatuses, semanticEditIndex.semanticEditAdmissionStatuses)
94
+ && match(query.semanticEditAdmissionAction ?? query.semanticEditAdmissionActions, semanticEditIndex.semanticEditAdmissionActions)
95
+ && match(query.semanticEditAdmissionReadiness ?? query.semanticEditAdmissionReadinesses, semanticEditIndex.semanticEditAdmissionReadinesses)
96
+ && match(query.semanticEditReplayCurrentHash ?? query.semanticEditReplayCurrentHashes, semanticEditIndex.semanticEditReplayCurrentHashes)
97
+ && match(query.semanticEditReplayOutputHash ?? query.semanticEditReplayOutputHashes, semanticEditIndex.semanticEditReplayOutputHashes)
98
+ && match(query.semanticEditKey ?? query.semanticEditKeys, semanticEditIndex.semanticEditKeys)
99
+ && match(query.semanticEditHash ?? query.semanticEditHashes, semanticEditIndex.semanticEditHashes)
100
+ && match(query.semanticIdentityHash ?? query.semanticIdentityHashes, semanticEditIndex.semanticIdentityHashes)
101
+ && match(query.sourceIdentityHash ?? query.sourceIdentityHashes, semanticEditIndex.sourceIdentityHashes)
102
+ && match(query.operationContentHash ?? query.operationContentHashes, semanticEditIndex.operationContentHashes)
103
+ && match(query.editContentHash ?? query.editContentHashes, semanticEditIndex.editContentHashes)
104
+ && match(query.constructKind ?? query.representationConstructKind, artifactConstructKinds(record))
105
+ && match(query.runtimeCapability, artifactRuntimeCapabilities(record))
106
+ && match(query.sourceMapPrecision, artifactSourceMapPrecisions(record))
107
+ && match(query.transformIdentityHash, artifactTransformIdentityHashes(record));
108
+ }
109
+
110
+ function artifactConstructKinds(record) {
111
+ return uniqueStrings([
112
+ ...(record.metadata?.representation?.constructKinds ?? []),
113
+ ...(record.mergeScore?.components?.representationCoverage?.signals?.constructKinds ?? []),
114
+ ...(record.semanticOperations?.operations ?? []).flatMap((operation) => operation.metadata?.representation?.constructKinds ?? [])
115
+ ]);
116
+ }
117
+
118
+ function artifactRuntimeCapabilities(record) {
119
+ return uniqueStrings([
120
+ ...(record.metadata?.representation?.runtimeCapabilities ?? []),
121
+ ...(record.mergeScore?.components?.representationCoverage?.signals?.runtimeCapabilities ?? []),
122
+ ...(record.semanticOperations?.operations ?? []).flatMap((operation) => operation.metadata?.representation?.runtimeCapabilities ?? [])
123
+ ]);
124
+ }
125
+
126
+ function artifactSourceMapPrecisions(record) {
127
+ return uniqueStrings([
128
+ ...(record.metadata?.representation?.sourceMapPrecisions ?? []),
129
+ ...(record.mergeScore?.components?.representationCoverage?.signals?.sourceMapPrecisions ?? []),
130
+ ...(record.semanticOperations?.operations ?? []).flatMap((operation) => operation.metadata?.representation?.sourceMapPrecisions ?? [])
131
+ ]);
132
+ }
133
+
134
+ function artifactTransformIdentityHashes(record) {
135
+ return uniqueStrings([
136
+ ...(record.metadata?.representation?.transformIdentityHashes ?? []),
137
+ ...(record.patchBundle?.index?.transformIdentityHashes ?? []),
138
+ ...(record.history?.index?.transformIdentityHashes ?? [])
139
+ ]);
63
140
  }
64
141
 
65
142
  function match(filter, values) {