@shapeshift-labs/frontier-lang-compiler 0.2.85 → 0.2.87

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.
@@ -66,6 +66,9 @@ export interface SemanticEditScriptOperation {
66
66
  readonly reanchor?: {
67
67
  readonly fromAnchorKey?: string;
68
68
  readonly toAnchorKey?: string;
69
+ readonly toSourcePath?: string;
70
+ readonly toSymbolName?: string;
71
+ readonly toSymbolKind?: string;
69
72
  readonly lineageStatus?: string;
70
73
  readonly traversedEventIds?: readonly string[];
71
74
  };
@@ -138,6 +141,11 @@ export interface SemanticEditProjectionEdit {
138
141
  readonly regionId?: string;
139
142
  readonly regionKind?: string;
140
143
  readonly sourcePath?: string;
144
+ readonly originalSourcePath?: string;
145
+ readonly targetAnchorKey?: string;
146
+ readonly targetSourcePath?: string;
147
+ readonly targetSymbolName?: string;
148
+ readonly targetSymbolKind?: string;
141
149
  readonly symbolId?: string;
142
150
  readonly symbolName?: string;
143
151
  readonly symbolKind?: string;
@@ -188,6 +196,7 @@ export interface ProjectSemanticEditScriptToSourceOptions {
188
196
  readonly script: SemanticEditScript;
189
197
  readonly workerSourceText: string;
190
198
  readonly headSourceText: string;
199
+ readonly headSourcePath?: string;
191
200
  readonly metadata?: Record<string, unknown>;
192
201
  }
193
202
 
@@ -207,6 +216,7 @@ export interface CreateSemanticEditScriptOptions {
207
216
  readonly workerSourceText?: string;
208
217
  readonly afterSourceText?: string;
209
218
  readonly headSourceText?: string;
219
+ readonly headSourcePath?: string;
210
220
  readonly currentSourceText?: string;
211
221
  readonly baseSourceHash?: string;
212
222
  readonly workerSourceHash?: string;
@@ -7,6 +7,7 @@ import type {
7
7
  SourceSpan
8
8
  } from '@shapeshift-labs/frontier-lang-kernel';
9
9
  import type { NativeSourceChangeKind, NativeSourceChangeSet } from './native-diff.js';
10
+ import type { SemanticEditProjection, SemanticEditScript } from './semantic-edit-script.js';
10
11
 
11
12
  export type SemanticPatchBundleAdmissionStatus = 'proposed' | 'queued' | 'admitted' | 'needs-review' | 'blocked' | 'rejected' | string;
12
13
 
@@ -102,6 +103,13 @@ export interface SemanticPatchBundleRecordIndex {
102
103
  readonly proofIds: readonly string[];
103
104
  readonly historyIds: readonly string[];
104
105
  readonly semanticOperationIds: readonly string[];
106
+ readonly semanticEditScriptIds: readonly string[];
107
+ readonly semanticEditProjectionIds: readonly string[];
108
+ readonly semanticEditKeys: readonly string[];
109
+ readonly semanticIdentityHashes: readonly string[];
110
+ readonly sourceIdentityHashes: readonly string[];
111
+ readonly operationContentHashes: readonly string[];
112
+ readonly editContentHashes: readonly string[];
105
113
  readonly patchIds: readonly string[];
106
114
  readonly mergeCandidateIds: readonly string[];
107
115
  readonly readinesses: readonly string[];
@@ -127,6 +135,8 @@ export interface SemanticPatchBundleRecord {
127
135
  readonly proofIds: readonly string[];
128
136
  readonly historyIds: readonly string[];
129
137
  readonly semanticOperationIds: readonly string[];
138
+ readonly semanticEditScriptIds: readonly string[];
139
+ readonly semanticEditProjectionIds: readonly string[];
130
140
  readonly admission: SemanticPatchBundleAdmission;
131
141
  readonly index: SemanticPatchBundleRecordIndex;
132
142
  readonly summary: {
@@ -136,6 +146,9 @@ export interface SemanticPatchBundleRecord {
136
146
  readonly proofIds: number;
137
147
  readonly historyIds: number;
138
148
  readonly semanticOperations: number;
149
+ readonly semanticEditScripts: number;
150
+ readonly semanticEditProjections: number;
151
+ readonly semanticEditProjectionEdits: number;
139
152
  readonly reviewRequired: boolean;
140
153
  readonly autoMergeClaim: false;
141
154
  };
@@ -164,6 +177,10 @@ export interface CreateSemanticPatchBundleRecordOptions {
164
177
  readonly historyIds?: readonly string[] | string;
165
178
  readonly semanticOperationId?: string;
166
179
  readonly semanticOperationIds?: readonly string[] | string;
180
+ readonly semanticEditScript?: SemanticEditScript;
181
+ readonly semanticEditScripts?: readonly SemanticEditScript[] | SemanticEditScript;
182
+ readonly semanticEditProjection?: SemanticEditProjection;
183
+ readonly semanticEditProjections?: readonly SemanticEditProjection[] | SemanticEditProjection;
167
184
  readonly conflictKeys?: readonly string[] | string;
168
185
  readonly admission?: Partial<SemanticPatchBundleAdmission>;
169
186
  readonly metadata?: Record<string, unknown>;
@@ -206,6 +223,20 @@ export interface SemanticPatchBundleRecordQuery {
206
223
  readonly historyIds?: readonly string[];
207
224
  readonly semanticOperationId?: string | readonly string[];
208
225
  readonly semanticOperationIds?: readonly string[];
226
+ readonly semanticEditScriptId?: string | readonly string[];
227
+ readonly semanticEditScriptIds?: readonly string[];
228
+ readonly semanticEditProjectionId?: string | readonly string[];
229
+ readonly semanticEditProjectionIds?: readonly string[];
230
+ readonly semanticEditKey?: string | readonly string[];
231
+ readonly semanticEditKeys?: readonly string[];
232
+ readonly semanticIdentityHash?: string | readonly string[];
233
+ readonly semanticIdentityHashes?: readonly string[];
234
+ readonly sourceIdentityHash?: string | readonly string[];
235
+ readonly sourceIdentityHashes?: readonly string[];
236
+ readonly operationContentHash?: string | readonly string[];
237
+ readonly operationContentHashes?: readonly string[];
238
+ readonly editContentHash?: string | readonly string[];
239
+ readonly editContentHashes?: readonly string[];
209
240
  readonly readiness?: SemanticMergeReadiness | string | readonly string[];
210
241
  readonly readinesses?: readonly string[];
211
242
  readonly admissionStatus?: SemanticPatchBundleAdmissionStatus | readonly string[];
@@ -25,7 +25,7 @@ export function projectSemanticEditScriptToSource(input = {}) {
25
25
  id: input.id ?? `semantic_edit_projection_${idFragment(script.id ?? script.hash ?? 'script')}`,
26
26
  scriptId: script.id,
27
27
  status: blocked ? 'blocked' : 'projected',
28
- sourcePath: script.sourcePath,
28
+ sourcePath: input.headSourcePath ?? projectedSourcePath(script, edits),
29
29
  language: script.language,
30
30
  baseHash: script.baseHash,
31
31
  workerHash: script.workerHash,
@@ -54,8 +54,9 @@ export function projectSemanticEditScriptToSource(input = {}) {
54
54
  }
55
55
 
56
56
  function sourceEditForOperation(operation, workerSourceText, headSourceText) {
57
+ const identity = projectionIdentity(operation);
57
58
  if (operation.status === 'already-applied') {
58
- return { ok: true, value: { ...semanticEditIdentity(operation), operationId: operation.id, start: 0, end: 0, replacement: '', current: '', alreadyApplied: true } };
59
+ return { ok: true, value: { ...identity, operationId: operation.id, start: 0, end: 0, replacement: '', current: '', alreadyApplied: true } };
59
60
  }
60
61
  if (operation.status !== 'portable') return { ok: false, reasonCodes: [`operation-not-portable:${operation.id}`] };
61
62
  const workerOffsets = spanOffsets(workerSourceText, operation.spans?.worker);
@@ -78,7 +79,7 @@ function sourceEditForOperation(operation, workerSourceText, headSourceText) {
78
79
  ok: true,
79
80
  value: {
80
81
  operationId: operation.id,
81
- ...semanticEditIdentity(operation),
82
+ ...identity,
82
83
  start: headOffsets.start,
83
84
  end: headOffsets.end,
84
85
  workerStart: workerOffsets.start,
@@ -89,6 +90,11 @@ function sourceEditForOperation(operation, workerSourceText, headSourceText) {
89
90
  };
90
91
  }
91
92
 
93
+ function projectionIdentity(operation) {
94
+ const identity = semanticEditIdentity(operation);
95
+ return { ...identity, sourcePath: operation.reanchor?.toSourcePath ?? identity.sourcePath };
96
+ }
97
+
92
98
  function projectionEditRecord(edit) {
93
99
  const deletedTextHash = hashSemanticValue(edit.current);
94
100
  const replacementTextHash = hashSemanticValue(edit.replacement);
@@ -103,6 +109,11 @@ function projectionEditRecord(edit) {
103
109
  regionId: edit.regionId,
104
110
  regionKind: edit.regionKind,
105
111
  sourcePath: edit.sourcePath,
112
+ originalSourcePath: edit.originalSourcePath,
113
+ targetAnchorKey: edit.targetAnchorKey,
114
+ targetSourcePath: edit.targetSourcePath,
115
+ targetSymbolName: edit.targetSymbolName,
116
+ targetSymbolKind: edit.targetSymbolKind,
106
117
  symbolId: edit.symbolId,
107
118
  symbolName: edit.symbolName,
108
119
  symbolKind: edit.symbolKind,
@@ -136,6 +147,11 @@ function semanticEditIdentity(operation) {
136
147
  regionId: anchor.regionId,
137
148
  regionKind: anchor.regionKind,
138
149
  sourcePath: anchor.sourcePath,
150
+ originalSourcePath: operation.reanchor?.toSourcePath ? anchor.sourcePath : undefined,
151
+ targetAnchorKey: operation.reanchor?.toAnchorKey,
152
+ targetSourcePath: operation.reanchor?.toSourcePath,
153
+ targetSymbolName: operation.reanchor?.toSymbolName,
154
+ targetSymbolKind: operation.reanchor?.toSymbolKind,
139
155
  symbolId: anchor.symbolId,
140
156
  symbolName: anchor.symbolName,
141
157
  symbolKind: anchor.symbolKind,
@@ -152,6 +168,10 @@ function applySourceEdits(sourceText, edits) {
152
168
  .reduce((text, edit) => text.slice(0, edit.start) + edit.replacement + text.slice(edit.end), sourceText);
153
169
  }
154
170
 
171
+ function projectedSourcePath(script, edits) {
172
+ return edits.map((edit) => edit.sourcePath).find(Boolean) ?? script.sourcePath;
173
+ }
174
+
155
175
  function spanOffsets(sourceText, span) {
156
176
  if (typeof sourceText !== 'string' || !span) return undefined;
157
177
  if (typeof span.start === 'number' && typeof span.end === 'number' && span.end >= span.start) return { start: span.start, end: span.end };
@@ -92,12 +92,15 @@ function classifyMissingHeadAnchor(input) {
92
92
  ? resolveSemanticLineage(input.context.headLineage.lineageMap, { anchorKey: input.anchorKey })
93
93
  : undefined;
94
94
  if (resolved?.status === 'resolved' && resolved.currentAnchors.length === 1) {
95
- return editStatus('needs-port', 'needs-review', 0.72, ['anchor-moved-or-renamed'], {
96
- fromAnchorKey: input.anchorKey,
97
- toAnchorKey: resolved.currentAnchors[0].key,
98
- lineageStatus: resolved.status,
99
- traversedEventIds: resolved.traversedEventIds
100
- }, resolved.evidenceIds);
95
+ const target = resolved.currentAnchors[0];
96
+ const reanchor = reanchorRecord(input.anchorKey, target, resolved);
97
+ if (target.bodyHash && input.baseSymbol?.spanHash && target.bodyHash === input.baseSymbol.spanHash) {
98
+ return editStatus('portable', 'ready', 0.86, ['anchor-reanchored-head-matches-base'], reanchor, resolved.evidenceIds);
99
+ }
100
+ if (target.bodyHash && input.workerSymbol?.spanHash && target.bodyHash === input.workerSymbol.spanHash) {
101
+ return editStatus('already-applied', 'ready', 0.87, ['anchor-reanchored-head-matches-worker'], reanchor, resolved.evidenceIds);
102
+ }
103
+ return editStatus('needs-port', 'needs-review', 0.72, ['anchor-moved-or-renamed'], reanchor, resolved.evidenceIds);
101
104
  }
102
105
  if (resolved?.status === 'ambiguous') {
103
106
  return editStatus('blocked', 'blocked', 0.1, ['anchor-lineage-ambiguous'], { fromAnchorKey: input.anchorKey, lineageStatus: resolved.status }, resolved.evidenceIds);
@@ -112,6 +115,18 @@ function editStatus(status, readiness, confidence, reasonCodes, reanchor, eviden
112
115
  return { status, readiness, confidence, reasonCodes, reanchor, evidenceIds };
113
116
  }
114
117
 
118
+ function reanchorRecord(fromAnchorKey, target, resolved) {
119
+ return {
120
+ fromAnchorKey,
121
+ toAnchorKey: target.key,
122
+ toSourcePath: target.sourcePath,
123
+ toSymbolName: target.symbolName,
124
+ toSymbolKind: target.kind,
125
+ lineageStatus: resolved.status,
126
+ traversedEventIds: resolved.traversedEventIds
127
+ };
128
+ }
129
+
115
130
  function admissionStatus(summary) {
116
131
  if (summary.operations === 0) return 'evidence-only';
117
132
  if (summary.blocked > 0) return 'blocked';
@@ -132,8 +132,9 @@ function semanticEditOperation(region, index, context, input) {
132
132
  const anchorKey = region.key ?? region.conflictKey ?? region.id;
133
133
  const baseSymbol = context.baseSymbols.get(anchorKey);
134
134
  const workerSymbol = context.workerSymbols.get(anchorKey);
135
- const headSymbol = context.headSymbols.get(anchorKey);
136
- const classification = classifySemanticEdit({ region, anchorKey, baseSymbol, workerSymbol, headSymbol, context });
135
+ const directHeadSymbol = context.headSymbols.get(anchorKey);
136
+ const classification = classifySemanticEdit({ region, anchorKey, baseSymbol, workerSymbol, headSymbol: directHeadSymbol, context });
137
+ const headSymbol = directHeadSymbol ?? reanchoredHeadSymbol(context, classification);
137
138
  const kind = semanticEditOperationKind(region);
138
139
  const baseText = spanText(context.base, baseSymbol?.sourceSpan ?? region.metadata?.changedRegionProjection?.before?.sourceSpan ?? region.sourceSpan);
139
140
  const workerText = spanText(context.worker, workerSymbol?.sourceSpan ?? region.metadata?.changedRegionProjection?.after?.sourceSpan ?? region.sourceSpan);
@@ -192,6 +193,11 @@ function semanticEditOperation(region, index, context, input) {
192
193
  });
193
194
  }
194
195
 
196
+ function reanchoredHeadSymbol(context, classification) {
197
+ const targetKey = classification.reanchor?.toAnchorKey;
198
+ return targetKey ? context.headSymbols.get(targetKey) : undefined;
199
+ }
200
+
195
201
  function semanticEditIdentityRecord(input) {
196
202
  return {
197
203
  kind: input.kind,
@@ -6,6 +6,9 @@ export function createSemanticPatchBundleRecord(input={},options={}){
6
6
  const source=input?.changeSet??input;
7
7
  const patch=options.patch??source.patch??source.semanticPatch??source.patchBundle;
8
8
  const mergeCandidate=options.mergeCandidate??source.mergeCandidate??source.candidate;
9
+ const semanticEditScripts=array(options.semanticEditScripts??source.semanticEditScripts??source.semanticEditScript);
10
+ const semanticEditProjections=array(options.semanticEditProjections??source.semanticEditProjections??source.semanticEditProjection);
11
+ const semanticEditIndex=semanticEditRecordIndex(semanticEditScripts,semanticEditProjections,source);
9
12
  const regionInputs=array(options.changedRegions??source.changedRegions??source.regions);
10
13
  const sourceMapLinks=normalizeSourceMapLinks([
11
14
  ...array(options.sourceMapLinks??source.sourceMapLinks),
@@ -17,7 +20,7 @@ export function createSemanticPatchBundleRecord(input={},options={}){
17
20
  sourceRef(source.before,'before',source.beforeHash),
18
21
  sourceRef(source.after,'after',source.afterHash)
19
22
  ],source);
20
- const evidenceRecords=[...array(options.evidence??source.evidence),...array(patch?.evidence),...array(mergeCandidate?.evidence)];
23
+ const evidenceRecords=[...array(options.evidence??source.evidence),...array(patch?.evidence),...array(mergeCandidate?.evidence),...semanticEditScripts.flatMap((script)=>array(script.evidence))];
21
24
  const patchId=firstString(options.patchId,source.patchId,patch?.id,mergeCandidate?.patchId);
22
25
  const mergeCandidateId=firstString(options.mergeCandidateId,source.mergeCandidateId,mergeCandidate?.id);
23
26
  const baseHash=firstString(options.baseHash,source.baseHash,source.beforeHash,patch?.baseHash,mergeCandidate?.baseHash,...sources.map((item)=>item.baseHash));
@@ -27,7 +30,7 @@ export function createSemanticPatchBundleRecord(input={},options={}){
27
30
  const evidenceIds=uniqueStrings([...strings(options.evidenceIds),...strings(source.evidenceIds),...evidenceRecords.map((record)=>record?.id),...strings(mergeCandidate?.evidenceIds)]);
28
31
  const proofIds=uniqueStrings([...strings(options.proofIds),...strings(source.proofIds),...evidenceRecords.filter((record)=>record?.kind==='proof').map((record)=>record.id),...strings(mergeCandidate?.proofIds)]);
29
32
  const historyIds=uniqueStrings([...strings(options.historyIds),...strings(options.historyId),...strings(source.historyIds),...strings(source.historyId)]);
30
- const semanticOperationIds=uniqueStrings([...strings(options.semanticOperationIds),...strings(options.semanticOperationId),...strings(source.semanticOperationIds),...strings(source.semanticOperationId),...strings(patch?.semanticOperationIds),...strings(mergeCandidate?.semanticOperationIds)]);
33
+ const semanticOperationIds=uniqueStrings([...strings(options.semanticOperationIds),...strings(options.semanticOperationId),...strings(source.semanticOperationIds),...strings(source.semanticOperationId),...strings(patch?.semanticOperationIds),...strings(mergeCandidate?.semanticOperationIds),...semanticEditIndex.semanticEditOperationIds]);
31
34
  const conflictKeys=uniqueStrings([
32
35
  ...strings(options.conflictKeys),
33
36
  ...strings(source.conflictKeys),
@@ -40,7 +43,7 @@ export function createSemanticPatchBundleRecord(input={},options={}){
40
43
  ??`semantic_patch_bundle_${idFragment(firstString(source.id,patchId,mergeCandidateId,source.sourcePath,source.language,'record'))}`;
41
44
  const language=options.language??source.language??mergeCandidate?.language??sources.find((item)=>item.language)?.language;
42
45
  const sourcePath=options.sourcePath??source.sourcePath??mergeCandidate?.sourcePath??sources.find((item)=>item.sourcePath)?.sourcePath;
43
- const index=recordIndex({baseHash,targetHash,sources,changedRegions,sourceMapLinks,evidenceIds,proofIds,historyIds,semanticOperationIds,patchId,mergeCandidateId,admission});
46
+ const index=recordIndex({baseHash,targetHash,sources,changedRegions,sourceMapLinks,evidenceIds,proofIds,historyIds,semanticOperationIds,patchId,mergeCandidateId,admission,semanticEditIndex});
44
47
  return{
45
48
  kind:'frontier.lang.semanticPatchBundleRecord',
46
49
  version:1,
@@ -60,15 +63,18 @@ export function createSemanticPatchBundleRecord(input={},options={}){
60
63
  proofIds,
61
64
  historyIds,
62
65
  semanticOperationIds,
66
+ semanticEditScriptIds:semanticEditIndex.semanticEditScriptIds,
67
+ semanticEditProjectionIds:semanticEditIndex.semanticEditProjectionIds,
63
68
  admission,
64
69
  index,
65
- summary:{changedRegions:changedRegions.length,sourceMapLinks:sourceMapLinks.length,evidenceIds:evidenceIds.length,proofIds:proofIds.length,historyIds:historyIds.length,semanticOperations:semanticOperationIds.length,reviewRequired:admission.reviewRequired,autoMergeClaim:admission.autoMergeClaim},
70
+ summary:{changedRegions:changedRegions.length,sourceMapLinks:sourceMapLinks.length,evidenceIds:evidenceIds.length,proofIds:proofIds.length,historyIds:historyIds.length,semanticOperations:semanticOperationIds.length,semanticEditScripts:semanticEditScripts.length,semanticEditProjections:semanticEditProjections.length,semanticEditProjectionEdits:semanticEditIndex.semanticEditProjectionEditCount,reviewRequired:admission.reviewRequired,autoMergeClaim:admission.autoMergeClaim},
66
71
  metadata:compactRecord({
67
72
  sourceChangeSetId:source.kind==='frontier.lang.nativeSourceChangeSet'?source.id:undefined,
68
73
  patchRisk:patch?.risk,
69
74
  nativeChangeSummary:source.summary,
70
75
  changedRegionProjectionSummary:source.metadata?.changedRegionProjectionSummary,
71
76
  semanticMergeConflictSummary:source.metadata?.semanticMergeConflictSummary,
77
+ semanticEditSummary:semanticEditSummary(semanticEditIndex),
72
78
  ...options.metadata
73
79
  })
74
80
  };
@@ -190,14 +196,15 @@ function normalizeAdmission(input={},context){
190
196
  }
191
197
 
192
198
  function recordIndex(parts){
199
+ const semanticEditIndex=parts.semanticEditIndex??semanticEditRecordIndex([],[]);
193
200
  return{
194
201
  baseHashes:uniqueStrings([parts.baseHash,...parts.sources.map((item)=>item.baseHash)]),
195
202
  targetHashes:uniqueStrings([parts.targetHash,...parts.sources.map((item)=>item.targetHash)]),
196
203
  sourceHashes:uniqueStrings(parts.sources.map((item)=>item.sourceHash)),
197
- sourcePaths:uniqueStrings(parts.sources.map((item)=>item.sourcePath)),
198
- regionKeys:uniqueStrings(parts.changedRegions.map((region)=>region.key)),
204
+ sourcePaths:uniqueStrings([...parts.sources.map((item)=>item.sourcePath),...semanticEditIndex.projectedSourcePaths]),
205
+ regionKeys:uniqueStrings([...parts.changedRegions.map((region)=>region.key),...semanticEditIndex.anchorKeys]),
199
206
  regionKinds:uniqueStrings(parts.changedRegions.map((region)=>region.regionKind)),
200
- conflictKeys:uniqueStrings(parts.changedRegions.flatMap((region)=>[region.conflictKey,...array(region.admission?.conflictKeys)])),
207
+ conflictKeys:uniqueStrings([...parts.changedRegions.flatMap((region)=>[region.conflictKey,...array(region.admission?.conflictKeys)]),...semanticEditIndex.conflictKeys]),
201
208
  sourceMapIds:uniqueStrings([...parts.sourceMapLinks.map((link)=>link.sourceMapId),...parts.changedRegions.flatMap((region)=>region.sourceMapIds??[])]),
202
209
  sourceMapMappingIds:uniqueStrings([...parts.sourceMapLinks.map((link)=>link.sourceMapMappingId),...parts.changedRegions.flatMap((region)=>region.sourceMapMappingIds??[])]),
203
210
  sourceMapLinkIds:uniqueStrings(parts.sourceMapLinks.map((link)=>link.id)),
@@ -205,6 +212,13 @@ function recordIndex(parts){
205
212
  proofIds:parts.proofIds,
206
213
  historyIds:parts.historyIds,
207
214
  semanticOperationIds:uniqueStrings(parts.semanticOperationIds),
215
+ semanticEditScriptIds:semanticEditIndex.semanticEditScriptIds,
216
+ semanticEditProjectionIds:semanticEditIndex.semanticEditProjectionIds,
217
+ semanticEditKeys:semanticEditIndex.semanticEditKeys,
218
+ semanticIdentityHashes:semanticEditIndex.semanticIdentityHashes,
219
+ sourceIdentityHashes:semanticEditIndex.sourceIdentityHashes,
220
+ operationContentHashes:semanticEditIndex.operationContentHashes,
221
+ editContentHashes:semanticEditIndex.editContentHashes,
208
222
  patchIds:uniqueStrings([parts.patchId]),
209
223
  mergeCandidateIds:uniqueStrings([parts.mergeCandidateId]),
210
224
  readinesses:uniqueStrings([parts.admission.readiness,...parts.changedRegions.map((region)=>region.admission?.readiness)]),
@@ -231,11 +245,48 @@ function matchesRecord(record,query){
231
245
  &&matchAny(queryValues(query.proofId,query.proofIds),index.proofIds)
232
246
  &&matchAny(queryValues(query.historyId,query.historyIds),index.historyIds)
233
247
  &&matchAny(queryValues(query.semanticOperationId,query.semanticOperationIds),index.semanticOperationIds)
248
+ &&matchAny(queryValues(query.semanticEditScriptId,query.semanticEditScriptIds),index.semanticEditScriptIds)
249
+ &&matchAny(queryValues(query.semanticEditProjectionId,query.semanticEditProjectionIds),index.semanticEditProjectionIds)
250
+ &&matchAny(queryValues(query.semanticEditKey,query.semanticEditKeys),index.semanticEditKeys)
251
+ &&matchAny(queryValues(query.semanticIdentityHash,query.semanticIdentityHashes),index.semanticIdentityHashes)
252
+ &&matchAny(queryValues(query.sourceIdentityHash,query.sourceIdentityHashes),index.sourceIdentityHashes)
253
+ &&matchAny(queryValues(query.operationContentHash,query.operationContentHashes),index.operationContentHashes)
254
+ &&matchAny(queryValues(query.editContentHash,query.editContentHashes),index.editContentHashes)
234
255
  &&matchAny(queryValues(query.readiness,query.readinesses),index.readinesses)
235
256
  &&matchAny(queryValues(query.admissionStatus,query.admissionStatuses),index.admissionStatuses);
236
257
  }
237
258
 
238
259
  function admissionStatusForReadiness(readiness){return readiness==='blocked'?'blocked':readiness==='needs-review'?'needs-review':'proposed';}
260
+ function semanticEditRecordIndex(scripts,projections,source={}){
261
+ const operations=scripts.flatMap((script)=>array(script.operations));
262
+ const edits=projections.flatMap((projection)=>array(projection.edits));
263
+ const index=source.index??{};
264
+ return{
265
+ semanticEditScriptIds:uniqueStrings([...strings(source.semanticEditScriptIds),...strings(source.semanticEditScriptId),...strings(index.semanticEditScriptIds),...scripts.map((script)=>script.id)]),
266
+ semanticEditProjectionIds:uniqueStrings([...strings(source.semanticEditProjectionIds),...strings(source.semanticEditProjectionId),...strings(index.semanticEditProjectionIds),...projections.map((projection)=>projection.id)]),
267
+ semanticEditOperationIds:uniqueStrings([...strings(source.semanticOperationIds),...strings(index.semanticOperationIds),...operations.map((operation)=>operation.id)]),
268
+ semanticEditProjectionEditCount:edits.length,
269
+ semanticEditKeys:uniqueStrings([...strings(source.semanticEditKeys),...strings(index.semanticEditKeys),...operations.map((operation)=>operation.semanticKey),...edits.map((edit)=>edit.semanticKey)]),
270
+ semanticIdentityHashes:uniqueStrings([...strings(source.semanticIdentityHashes),...strings(index.semanticIdentityHashes),...operations.map((operation)=>operation.semanticIdentityHash),...edits.map((edit)=>edit.semanticIdentityHash)]),
271
+ sourceIdentityHashes:uniqueStrings([...strings(source.sourceIdentityHashes),...strings(index.sourceIdentityHashes),...operations.map((operation)=>operation.sourceIdentityHash),...edits.map((edit)=>edit.sourceIdentityHash)]),
272
+ operationContentHashes:uniqueStrings([...strings(source.operationContentHashes),...strings(index.operationContentHashes),...operations.map((operation)=>operation.operationContentHash),...edits.map((edit)=>edit.operationContentHash)]),
273
+ editContentHashes:uniqueStrings([...strings(source.editContentHashes),...strings(index.editContentHashes),...edits.map((edit)=>edit.editContentHash)]),
274
+ anchorKeys:uniqueStrings([...operations.map((operation)=>operation.anchor?.key),...edits.map((edit)=>edit.anchorKey)]),
275
+ conflictKeys:uniqueStrings([...operations.map((operation)=>operation.anchor?.conflictKey),...edits.map((edit)=>edit.conflictKey)]),
276
+ projectedSourcePaths:uniqueStrings([...projections.map((projection)=>projection.sourcePath),...edits.flatMap((edit)=>[edit.sourcePath,edit.targetSourcePath])])
277
+ };
278
+ }
279
+ function semanticEditSummary(index){
280
+ if(!index.semanticEditScriptIds.length&&!index.semanticEditProjectionIds.length)return undefined;
281
+ return compactRecord({
282
+ scriptIds:index.semanticEditScriptIds,
283
+ projectionIds:index.semanticEditProjectionIds,
284
+ semanticEditKeys:index.semanticEditKeys,
285
+ operationContentHashes:index.operationContentHashes,
286
+ editContentHashes:index.editContentHashes,
287
+ projectedSourcePaths:index.projectedSourcePaths
288
+ });
289
+ }
239
290
  function queryValues(...values){return uniqueStrings(values.flatMap((value)=>strings(value)));}
240
291
  function matchAny(filters,values){if(filters.length===0)return true;const valueSet=new Set(strings(values));return filters.some((filter)=>valueSet.has(filter));}
241
292
  function array(value){if(value===undefined||value===null)return[];return Array.isArray(value)?value:[value];}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshift-labs/frontier-lang-compiler",
3
- "version": "0.2.85",
3
+ "version": "0.2.87",
4
4
  "description": "Compiler facade for Frontier Lang source documents and language projection adapters.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",