@shapeshift-labs/frontier-lang-compiler 0.2.100 → 0.2.102

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 (47) hide show
  1. package/dist/declarations/bidirectional-target-change-evidence.d.ts +299 -0
  2. package/dist/declarations/bidirectional-target-change.d.ts +19 -120
  3. package/dist/declarations/import-adapter-core.d.ts +6 -0
  4. package/dist/declarations/native-project-admission.d.ts +43 -22
  5. package/dist/declarations/semantic-edit-replay-diagnostics.d.ts +24 -0
  6. package/dist/declarations/semantic-edit-script.d.ts +20 -15
  7. package/dist/declarations/semantic-lineage.d.ts +3 -21
  8. package/dist/declarations/semantic-merge-candidates.d.ts +39 -0
  9. package/dist/declarations/semantic-sidecar-admission.d.ts +14 -0
  10. package/dist/declarations/semantic-sidecar.d.ts +12 -14
  11. package/dist/internal/index-impl/bidirectionalTargetRoundtripEvidence.js +200 -0
  12. package/dist/internal/index-impl/createBidirectionalTargetChangeRecord.js +62 -17
  13. package/dist/internal/index-impl/createLightweightNativeImport.js +9 -1
  14. package/dist/internal/index-impl/createNativeSourcePreservation.js +16 -1
  15. package/dist/internal/index-impl/createProjectImportAdmissionRecord.js +151 -1
  16. package/dist/internal/index-impl/createSemanticImportSidecar.js +5 -0
  17. package/dist/internal/index-impl/createSemanticImportSidecarAdmission.js +29 -11
  18. package/dist/internal/index-impl/importNativeSource.js +14 -14
  19. package/dist/internal/index-impl/nativeChangeProjectionEndpoint.js +56 -16
  20. package/dist/internal/index-impl/nativeImportSemanticIndex.js +33 -0
  21. package/dist/internal/index-impl/projectImportAdmissionMergeScore.js +26 -74
  22. package/dist/internal/index-impl/projectImportAdmissionProjectionCoverage.js +74 -0
  23. package/dist/internal/index-impl/projectSemanticEditScriptToSource.js +39 -13
  24. package/dist/internal/index-impl/replaySemanticEditProjection.js +65 -23
  25. package/dist/internal/index-impl/semanticEditInsertionAnchors.js +8 -5
  26. package/dist/internal/index-impl/semanticEditReplayDiagnostics.js +167 -0
  27. package/dist/internal/index-impl/semanticEditSourceRanges.js +94 -15
  28. package/dist/internal/index-impl/semanticHistoryLineageResolution.js +21 -2
  29. package/dist/internal/index-impl/semanticLineageHashEvidence.js +97 -0
  30. package/dist/internal/index-impl/semanticLineageInferenceMatching.js +8 -0
  31. package/dist/internal/index-impl/semanticLineageResolutionRecords.js +18 -1
  32. package/dist/internal/index-impl/semanticMergeCandidateRecords.js +22 -2
  33. package/dist/internal/index-impl/semanticMergeCandidateScoreFacets.js +221 -0
  34. package/dist/internal/index-impl/semanticPatchBundleOverlaps.js +23 -1
  35. package/dist/internal/index-impl/sourcePreservationFromProjectionContext.js +9 -2
  36. package/dist/native-import-language-profiles.js +10 -2
  37. package/dist/native-region-scanner-js-helpers.js +8 -2
  38. package/dist/native-region-scanner-js-imports.js +7 -0
  39. package/dist/native-region-scanner-js.js +4 -4
  40. package/dist/native-region-scanner.js +2 -1
  41. package/dist/semantic-import-regions.js +18 -5
  42. package/dist/semantic-import-sidecar-admission-types.d.ts +14 -0
  43. package/dist/semantic-import-sidecar-entry.js +151 -7
  44. package/dist/semantic-import-sidecar-types.d.ts +18 -13
  45. package/dist/semantic-import-source-preservation-utils.js +55 -0
  46. package/dist/semantic-import-source-preservation.js +98 -3
  47. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import { uniqueRecordsById, uniqueStrings } from './native-import-utils.js';
2
2
  import { summarizeSemanticImportDependencyRelations } from './semantic-import-dependencies.js';
3
- import { semanticOwnershipRegionForSymbol, summarizeSemanticImportRegionTaxonomy } from './semantic-import-regions.js';
3
+ import { semanticOwnershipRegionForSymbol, semanticPatchHintForRegion, summarizeSemanticImportRegionTaxonomy } from './semantic-import-regions.js';
4
4
  import { collectKernelSourcePreservationFromImport } from './semantic-import-source-preservation.js';
5
5
  import {
6
6
  summarizeParadigmSemanticsLayer,
@@ -10,10 +10,12 @@ import {
10
10
 
11
11
  function semanticImportSidecarEntry(imported, index, options) {
12
12
  const semanticIndex = imported?.semanticIndex ?? imported?.universalAst?.semanticIndex;
13
+ const semanticSymbols = semanticSymbolsForImport(imported, semanticIndex);
13
14
  const nativeAst = imported?.nativeAst ?? imported?.nativeSource?.ast;
14
15
  const semanticFacts = semanticIndex?.facts ?? [];
15
16
  const sourceMaps = imported?.sourceMaps ?? imported?.universalAst?.sourceMaps ?? [];
16
17
  const sourceMapMappings = sourceMaps.flatMap((sourceMap) => sourceMap?.mappings ?? []);
18
+ const importedOwnershipRegions = semanticOwnershipRegionsForImport(imported);
17
19
  const sourcePreservationRecords = collectKernelSourcePreservationFromImport(imported);
18
20
  const universalAstLayers = summarizeUniversalAstLayers(imported?.universalAst);
19
21
  const proofSpec = summarizeProofSpecLayer(imported?.universalAst?.proof ?? imported?.proof);
@@ -29,10 +31,14 @@ function semanticImportSidecarEntry(imported, index, options) {
29
31
  }
30
32
  const symbols = [];
31
33
  const regions = [];
32
- for (const symbol of semanticIndex?.symbols ?? []) {
34
+ for (const symbol of semanticSymbols) {
33
35
  const mapping = mappingsBySymbolId.get(symbol.id);
34
36
  const nativeNode = symbol.nativeAstNodeId ? nativeAst?.nodes?.[symbol.nativeAstNodeId] : undefined;
35
- const region = semanticOwnershipRegionForSymbol(imported, symbol, mapping, nativeNode, options);
37
+ const generatedRegion = semanticOwnershipRegionForSymbol(imported, symbol, mapping, nativeNode, options);
38
+ const region = mergeSemanticOwnershipRegion(
39
+ generatedRegion,
40
+ semanticOwnershipRegionForImportedSymbol(importedOwnershipRegions, symbol, generatedRegion)
41
+ );
36
42
  regions.push(region);
37
43
  symbols.push({
38
44
  id: symbol.id,
@@ -42,7 +48,7 @@ function semanticImportSidecarEntry(imported, index, options) {
42
48
  nativeAstNodeId: symbol.nativeAstNodeId,
43
49
  semanticOccurrenceId: mapping?.semanticOccurrenceId,
44
50
  sourceMapMappingId: mapping?.id,
45
- sourceSpan: mapping?.sourceSpan ?? symbol.definitionSpan ?? nativeNode?.span,
51
+ sourceSpan: region.sourceSpan ?? mapping?.sourceSpan ?? symbol.definitionSpan ?? nativeNode?.span,
46
52
  signatureHash: symbol.signatureHash,
47
53
  ownershipRegionId: region.id,
48
54
  ownershipKey: region.key,
@@ -50,13 +56,25 @@ function semanticImportSidecarEntry(imported, index, options) {
50
56
  readiness
51
57
  });
52
58
  }
59
+ for (const [regionIndex, region] of importedOwnershipRegions.entries()) {
60
+ regions.push(normalizeImportedOwnershipRegion(imported, region, regionIndex, options));
61
+ }
53
62
  const ownershipRegions = uniqueRecordsById(regions);
54
63
  const regionTaxonomy = summarizeSemanticImportRegionTaxonomy(ownershipRegions);
64
+ const patchHints = ownershipRegions.map((region) => semanticPatchHintForRegion(region, readiness, options));
65
+ const sourcePath = imported?.sourcePath ?? imported?.nativeSource?.sourcePath ?? nativeAst?.sourcePath;
66
+ const qualityRecord = semanticImportSidecarQualityRecord({
67
+ expected: options.expected === true || options.semanticImportExpected === true,
68
+ expectedEmpty: options.expectedEmpty === true || options.semanticImportExpectedEmpty === true,
69
+ importCount: 1,
70
+ symbolCount: symbols.length,
71
+ sourcePaths: [sourcePath]
72
+ });
55
73
  return {
56
74
  id: imported?.id ?? `import_${index + 1}`,
57
75
  language: imported?.language,
58
- sourcePath: imported?.sourcePath ?? imported?.nativeSource?.sourcePath ?? nativeAst?.sourcePath,
59
- sourceHash: imported?.nativeSource?.sourceHash ?? nativeAst?.sourceHash,
76
+ sourcePath,
77
+ sourceHash: imported?.nativeSource?.sourceHash ?? nativeAst?.sourceHash ?? imported?.sourceHash,
60
78
  parser: imported?.nativeAst?.parser ?? nativeAst?.parser,
61
79
  nativeSourceId: imported?.nativeSource?.id,
62
80
  nativeAstId: nativeAst?.id,
@@ -77,14 +95,140 @@ function semanticImportSidecarEntry(imported, index, options) {
77
95
  semanticFactCount: semanticFacts.length,
78
96
  semanticFactPredicates: factSummary.predicates,
79
97
  semanticFactSummary: factSummary.byPredicate,
98
+ patchHintCount: patchHints.length,
99
+ patchHintOperations: uniqueStrings(patchHints.map((hint) => hint.operation).filter(Boolean)),
100
+ patchHints,
80
101
  readiness,
81
102
  emptySemanticIndex: symbols.length === 0,
103
+ qualityRecord,
82
104
  regionTaxonomy,
83
105
  symbols,
84
106
  ownershipRegions
85
107
  };
86
108
  }
87
109
 
110
+ function semanticImportSidecarQualityRecord(input = {}) {
111
+ const expected = input.expected === true;
112
+ const expectedEmpty = input.expectedEmpty === true || input.semanticImportExpectedEmpty === true;
113
+ const importCount = Number(input.importCount ?? 0);
114
+ const symbolCount = Number(input.symbolCount ?? 0);
115
+ const sourcePaths = uniqueStrings(input.sourcePaths ?? []);
116
+ if (importCount === 0) {
117
+ return {
118
+ classification: 'missing',
119
+ reasonCode: expected || expectedEmpty ? 'expected-semantic-import-missing' : 'missing-imports',
120
+ message: 'Semantic import produced no selected import records.',
121
+ action: 'check-semantic-import-include-globs-and-workspace-paths',
122
+ sourcePaths
123
+ };
124
+ }
125
+ if (symbolCount === 0 && expectedEmpty) {
126
+ return {
127
+ classification: 'expected-empty',
128
+ reasonCode: 'semantic-import-expected-empty',
129
+ message: 'Semantic import was expected to produce no semantic symbols for this source set.',
130
+ action: 'skip-expected-empty',
131
+ sourcePaths
132
+ };
133
+ }
134
+ if (symbolCount === 0) {
135
+ return {
136
+ classification: 'unexpectedly-empty',
137
+ reasonCode: expected ? 'expected-semantic-import-empty' : 'empty-semantic-index',
138
+ message: 'Semantic import selected sources but produced zero semantic symbols.',
139
+ action: 'rerun-importer-with-semantic-source-selection',
140
+ sourcePaths
141
+ };
142
+ }
143
+ return {
144
+ classification: 'useful',
145
+ reasonCode: 'semantic-import-useful',
146
+ message: 'Semantic import produced semantic symbols for merge review.',
147
+ action: 'use-semantic-import-evidence',
148
+ sourcePaths
149
+ };
150
+ }
151
+
152
+ function semanticSymbolsForImport(imported, semanticIndex) {
153
+ if (Array.isArray(semanticIndex?.symbols)) return semanticIndex.symbols;
154
+ for (const symbols of [
155
+ imported?.semanticSymbols,
156
+ imported?.symbols,
157
+ imported?.metadata?.semanticSymbols,
158
+ imported?.metadata?.symbols
159
+ ]) {
160
+ if (Array.isArray(symbols)) return symbols;
161
+ }
162
+ return [];
163
+ }
164
+
165
+ function semanticOwnershipRegionsForImport(imported) {
166
+ return [
167
+ ...(Array.isArray(imported?.ownershipRegions) ? imported.ownershipRegions : []),
168
+ ...(Array.isArray(imported?.semanticOwnershipRegions) ? imported.semanticOwnershipRegions : []),
169
+ ...(Array.isArray(imported?.semanticIndex?.ownershipRegions) ? imported.semanticIndex.ownershipRegions : []),
170
+ ...(Array.isArray(imported?.universalAst?.ownershipRegions) ? imported.universalAst.ownershipRegions : []),
171
+ ...(Array.isArray(imported?.metadata?.ownershipRegions) ? imported.metadata.ownershipRegions : [])
172
+ ].filter((region) => region && typeof region === 'object');
173
+ }
174
+
175
+ function semanticOwnershipRegionForImportedSymbol(regions, symbol, generatedRegion) {
176
+ const metadata = symbol?.metadata ?? {};
177
+ return regions.find((region) => metadata.ownershipRegionId && region.id === metadata.ownershipRegionId)
178
+ ?? regions.find((region) => metadata.ownershipRegionKey && region.key === metadata.ownershipRegionKey)
179
+ ?? regions.find((region) => generatedRegion.id && region.id === generatedRegion.id)
180
+ ?? regions.find((region) => generatedRegion.key && region.key === generatedRegion.key)
181
+ ?? regions.find((region) => symbol.id && region.symbolId === symbol.id)
182
+ ?? regions.find((region) => symbol.name && region.symbolName === symbol.name && region.sourcePath === generatedRegion.sourcePath);
183
+ }
184
+
185
+ function normalizeImportedOwnershipRegion(imported, region, index, options) {
186
+ const symbol = {
187
+ id: region.symbolId ?? region.id ?? region.key ?? `ownership_region_${index + 1}`,
188
+ name: region.symbolName ?? region.name ?? region.key ?? region.id,
189
+ kind: region.symbolKind,
190
+ language: region.language ?? imported?.language,
191
+ nativeAstNodeId: region.nativeAstNodeId,
192
+ definitionSpan: region.sourceSpan,
193
+ metadata: {
194
+ ownershipRegionId: region.id,
195
+ ownershipRegionKey: region.key,
196
+ ownershipRegionKind: region.regionKind
197
+ }
198
+ };
199
+ return mergeSemanticOwnershipRegion(
200
+ semanticOwnershipRegionForSymbol(imported, symbol, undefined, undefined, options),
201
+ region
202
+ );
203
+ }
204
+
205
+ function mergeSemanticOwnershipRegion(generatedRegion, importedRegion) {
206
+ if (!importedRegion) return generatedRegion;
207
+ return {
208
+ ...generatedRegion,
209
+ ...importedRegion,
210
+ id: importedRegion.id ?? generatedRegion.id,
211
+ key: importedRegion.key ?? generatedRegion.key,
212
+ regionKind: importedRegion.regionKind ?? generatedRegion.regionKind,
213
+ granularity: importedRegion.granularity ?? generatedRegion.granularity,
214
+ language: importedRegion.language ?? generatedRegion.language,
215
+ sourcePath: importedRegion.sourcePath ?? generatedRegion.sourcePath,
216
+ sourceHash: importedRegion.sourceHash ?? generatedRegion.sourceHash,
217
+ symbolId: importedRegion.symbolId ?? generatedRegion.symbolId,
218
+ symbolName: importedRegion.symbolName ?? generatedRegion.symbolName,
219
+ symbolKind: importedRegion.symbolKind ?? generatedRegion.symbolKind,
220
+ nativeAstNodeId: importedRegion.nativeAstNodeId ?? generatedRegion.nativeAstNodeId,
221
+ sourceSpan: importedRegion.sourceSpan ?? generatedRegion.sourceSpan,
222
+ precision: importedRegion.precision ?? generatedRegion.precision,
223
+ mergePolicy: importedRegion.mergePolicy ?? generatedRegion.mergePolicy,
224
+ metadata: {
225
+ ...generatedRegion.metadata,
226
+ ...importedRegion.metadata,
227
+ semanticRegionTaxonomy: true
228
+ }
229
+ };
230
+ }
231
+
88
232
  function semanticImportEntryReadiness(imported) {
89
233
  const readiness = imported?.metadata?.semanticMergeReadiness
90
234
  ?? imported?.metadata?.nativeImportLossSummary?.semanticMergeReadiness
@@ -105,4 +249,4 @@ function summarizeSemanticFacts(facts) {
105
249
  return { byPredicate, predicates: Object.keys(byPredicate).sort() };
106
250
  }
107
251
 
108
- export { semanticImportSidecarEntry };
252
+ export { semanticImportSidecarEntry, semanticImportSidecarQualityRecord };
@@ -7,9 +7,8 @@ import type {
7
7
  } from '@shapeshift-labs/frontier-lang-kernel';
8
8
  import type { NativeImportRegionTaxonomyKind, NativeImportTaxonomyKind } from './index.js';
9
9
  import type { SemanticImportImpactSummary } from './semantic-import-impact-types.js';
10
- import type { SemanticImportSidecarAdmission, SemanticImportSidecarQuality } from './semantic-import-sidecar-admission-types.js';
10
+ import type { SemanticImportSidecarAdmission, SemanticImportSidecarQuality, SemanticImportSidecarQualityRecord } from './semantic-import-sidecar-admission-types.js';
11
11
  import type { SemanticMergeConflictClass, SemanticMergeConflictSummary } from './declarations/semantic-merge-conflicts.js';
12
-
13
12
  export interface SemanticImportOwnershipRegion {
14
13
  readonly id: string;
15
14
  readonly key: string;
@@ -28,7 +27,6 @@ export interface SemanticImportOwnershipRegion {
28
27
  readonly mergePolicy?: string;
29
28
  readonly metadata?: Record<string, unknown>;
30
29
  }
31
-
32
30
  export interface SemanticImportSidecarSymbol {
33
31
  readonly id: string;
34
32
  readonly name?: string;
@@ -44,7 +42,6 @@ export interface SemanticImportSidecarSymbol {
44
42
  readonly ownershipRegionKind?: NativeImportRegionTaxonomyKind;
45
43
  readonly readiness: SemanticMergeReadiness;
46
44
  }
47
-
48
45
  export interface SemanticImportRegionTaxonomySummary {
49
46
  readonly kinds: readonly NativeImportRegionTaxonomyKind[];
50
47
  readonly presentKinds: readonly NativeImportRegionTaxonomyKind[];
@@ -52,12 +49,12 @@ export interface SemanticImportRegionTaxonomySummary {
52
49
  readonly keys: readonly string[];
53
50
  readonly keysByKind: Readonly<Record<string, readonly string[]>>;
54
51
  }
55
-
56
52
  export interface SemanticImportPatchHint {
57
53
  readonly id: string;
58
54
  readonly kind: 'source-region-patch' | string;
59
55
  readonly ownershipRegionId: string;
60
56
  readonly ownershipKey: string;
57
+ readonly operation: string;
61
58
  readonly sourcePath?: string;
62
59
  readonly sourceHash?: string;
63
60
  readonly sourceSpan?: SourceSpan;
@@ -70,7 +67,6 @@ export interface SemanticImportPatchHint {
70
67
  readonly requiresSourceMap: boolean;
71
68
  };
72
69
  }
73
-
74
70
  export interface SemanticImportSidecarImportEntry {
75
71
  readonly id: string;
76
72
  readonly language?: FrontierSourceLanguage | string;
@@ -93,11 +89,17 @@ export interface SemanticImportSidecarImportEntry {
93
89
  readonly paradigmSemantics: SemanticImportSidecarParadigmSemanticsSummary;
94
90
  readonly dependencyRelationCount: number;
95
91
  readonly dependencyPredicates: readonly string[];
92
+ readonly semanticFactCount?: number;
93
+ readonly semanticFactPredicates?: readonly string[];
94
+ readonly semanticFactSummary?: Readonly<Record<string, number>>;
95
+ readonly patchHintCount?: number;
96
+ readonly patchHintOperations?: readonly string[];
97
+ readonly patchHints?: readonly SemanticImportPatchHint[];
96
98
  readonly readiness: SemanticMergeReadiness;
97
99
  readonly emptySemanticIndex: boolean;
100
+ readonly qualityRecord: SemanticImportSidecarQualityRecord;
98
101
  readonly regionTaxonomy?: SemanticImportRegionTaxonomySummary;
99
102
  }
100
-
101
103
  export interface SemanticImportSidecarSourcePreservationRecord {
102
104
  readonly id: string;
103
105
  readonly level: SourcePreservationLevel;
@@ -115,7 +117,6 @@ export interface SemanticImportSidecarSourcePreservationRecord {
115
117
  readonly evidenceIds: readonly string[];
116
118
  readonly reasons: readonly string[];
117
119
  }
118
-
119
120
  export interface SemanticImportSidecarUniversalAstLayerSummary {
120
121
  readonly total: number;
121
122
  readonly names: readonly string[];
@@ -123,7 +124,6 @@ export interface SemanticImportSidecarUniversalAstLayerSummary {
123
124
  readonly byName: Readonly<Record<string, number>>;
124
125
  readonly empty: boolean;
125
126
  }
126
-
127
127
  export interface SemanticImportSidecarProofSpecSummary {
128
128
  readonly total: number;
129
129
  readonly ids: readonly string[];
@@ -152,7 +152,6 @@ export interface SemanticImportSidecarProofSpecSummary {
152
152
  readonly byArtifactKind: Readonly<Record<string, number>>;
153
153
  readonly empty: boolean;
154
154
  }
155
-
156
155
  export interface SemanticImportSidecarParadigmSemanticsSummary {
157
156
  readonly total: number;
158
157
  readonly ids: readonly string[];
@@ -188,7 +187,6 @@ export interface SemanticImportSidecarParadigmSemanticsSummary {
188
187
  readonly hasLowering: boolean;
189
188
  readonly empty: boolean;
190
189
  }
191
-
192
190
  export interface SemanticImportDependencySummary {
193
191
  readonly total: number;
194
192
  readonly calls: number;
@@ -205,7 +203,6 @@ export interface SemanticImportDependencySummary {
205
203
  readonly sourceSymbolIds: readonly string[];
206
204
  readonly targetSymbolIds: readonly string[];
207
205
  }
208
-
209
206
  export interface SemanticImportSidecar {
210
207
  readonly kind: 'frontier.lang.semanticImportSidecar';
211
208
  readonly version: 1;
@@ -287,12 +284,18 @@ export interface SemanticImportSidecar {
287
284
  readonly semanticImpactRequiredVerificationSteps: number;
288
285
  readonly patchHints: number;
289
286
  readonly evidenceWarnings: number;
287
+ readonly semanticImportExpected: boolean;
288
+ readonly semanticImportExpectedEmpty: boolean;
289
+ readonly semanticImportExpectedSatisfied: boolean;
290
+ readonly semanticImportExpectedMissingReasonCodes: readonly string[];
291
+ readonly semanticImportRecordClassification: string;
292
+ readonly semanticImportRecordReasonCode: string;
293
+ readonly semanticImportRecordAction: string;
290
294
  readonly readiness: SemanticMergeReadiness;
291
295
  readonly emptySemanticIndex: boolean;
292
296
  };
293
297
  readonly metadata?: Record<string, unknown>;
294
298
  }
295
-
296
299
  export interface SemanticImportSidecarOptions {
297
300
  readonly id?: string;
298
301
  readonly generatedAt?: number;
@@ -300,5 +303,7 @@ export interface SemanticImportSidecarOptions {
300
303
  readonly targetPath?: string;
301
304
  readonly expected?: boolean;
302
305
  readonly semanticImportExpected?: boolean;
306
+ readonly expectedEmpty?: boolean;
307
+ readonly semanticImportExpectedEmpty?: boolean;
303
308
  readonly metadata?: Record<string, unknown>;
304
309
  }
@@ -0,0 +1,55 @@
1
+ import { uniqueStrings } from './native-import-utils.js';
2
+
3
+ export function sourcePreservationInspectionTags(input) {
4
+ return uniqueStrings([
5
+ input.compilerRecord,
6
+ input.level,
7
+ input.precision,
8
+ input.exactSource ? 'exact-source-text' : undefined,
9
+ input.sourceMapOrigin,
10
+ input.generatedPath ? 'generated-span' : undefined,
11
+ input.semanticSymbolId ? 'semantic-symbol' : undefined,
12
+ input.ownershipRegionKind ? `region:${input.ownershipRegionKind}` : undefined
13
+ ]);
14
+ }
15
+
16
+ export function sourcePreservationQueryKeys(input) {
17
+ return uniqueStrings([
18
+ input.compilerRecord ? `compiler-record:${input.compilerRecord}` : undefined,
19
+ input.level ? `level:${input.level}` : undefined,
20
+ input.precision ? `precision:${input.precision}` : undefined,
21
+ input.sourcePath ? `source:${input.sourcePath}` : undefined,
22
+ input.generatedPath ? `generated:${input.generatedPath}` : undefined,
23
+ input.sourceMapOrigin ? `source-map-origin:${input.sourceMapOrigin}` : undefined,
24
+ input.ownershipRegionKind ? `region-kind:${input.ownershipRegionKind}` : undefined
25
+ ]);
26
+ }
27
+
28
+ export function compactSpan(span) {
29
+ if (!span) return undefined;
30
+ return {
31
+ sourceId: span.sourceId,
32
+ path: span.path,
33
+ targetPath: span.targetPath,
34
+ targetHash: span.targetHash,
35
+ start: span.start,
36
+ end: span.end,
37
+ startLine: span.startLine,
38
+ startColumn: span.startColumn,
39
+ endLine: span.endLine,
40
+ endColumn: span.endColumn,
41
+ generatedName: span.generatedName
42
+ };
43
+ }
44
+
45
+ export function sumCountObjects(objects) {
46
+ const result = {};
47
+ for (const object of objects ?? []) {
48
+ for (const [key, value] of Object.entries(object ?? {})) {
49
+ const count = Number(value);
50
+ if (!Number.isFinite(count)) continue;
51
+ result[key] = (result[key] ?? 0) + count;
52
+ }
53
+ }
54
+ return result;
55
+ }
@@ -1,5 +1,6 @@
1
1
  import { createSourcePreservationRecord, explainSourcePreservation } from '@shapeshift-labs/frontier-lang-kernel';
2
2
  import { countBy, idFragment, uniqueRecordsById, uniqueStrings } from './native-import-utils.js';
3
+ import { compactSpan, sourcePreservationInspectionTags, sourcePreservationQueryKeys, sumCountObjects } from './semantic-import-source-preservation-utils.js';
3
4
 
4
5
  function createKernelSourcePreservationRecords(input) {
5
6
  const records = [];
@@ -40,7 +41,25 @@ function createKernelSourcePreservationRecords(input) {
40
41
  directives: input.sourcePreservation.summary?.directives ?? 0,
41
42
  comments: input.sourcePreservation.summary?.comments ?? 0,
42
43
  whitespace: input.sourcePreservation.summary?.whitespace ?? 0,
43
- truncated: input.sourcePreservation.summary?.truncated === true
44
+ truncated: input.sourcePreservation.summary?.truncated === true,
45
+ triviaByKind: input.sourcePreservation.summary?.triviaByKind ?? countBy((input.sourcePreservation.trivia ?? []).map((entry) => entry.kind ?? 'unknown')),
46
+ directivesByKind: input.sourcePreservation.summary?.directivesByKind ?? countBy((input.sourcePreservation.directives ?? []).map((entry) => entry.kind ?? 'directive')),
47
+ directiveKinds: input.sourcePreservation.summary?.directiveKinds ?? uniqueStrings((input.sourcePreservation.directives ?? []).map((entry) => entry.kind ?? 'directive')),
48
+ commentSpanIds: input.sourcePreservation.summary?.commentSpanIds ?? (input.sourcePreservation.trivia ?? []).filter((entry) => entry.kind === 'comment').map((entry) => entry.id).filter(Boolean),
49
+ directiveSpanIds: input.sourcePreservation.summary?.directiveSpanIds ?? (input.sourcePreservation.directives ?? []).map((entry) => entry.id).filter(Boolean),
50
+ inspectionTags: sourcePreservationInspectionTags({
51
+ compilerRecord: 'nativeSourcePreservation',
52
+ level: hashMismatch ? 'blocked' : exactSource ? 'exact' : 'estimated',
53
+ precision: exactSource ? 'exact' : 'estimated',
54
+ sourcePath: input.sourcePath,
55
+ exactSource
56
+ }),
57
+ queryKeys: sourcePreservationQueryKeys({
58
+ compilerRecord: 'nativeSourcePreservation',
59
+ level: hashMismatch ? 'blocked' : exactSource ? 'exact' : 'estimated',
60
+ precision: exactSource ? 'exact' : 'estimated',
61
+ sourcePath: input.sourcePath
62
+ })
44
63
  }
45
64
  }));
46
65
  }
@@ -59,7 +78,8 @@ function createKernelSourcePreservationRecords(input) {
59
78
  language: input.language,
60
79
  semanticIndexId: input.semanticIndex?.id,
61
80
  sourceMapId: sourceMap.id,
62
- sourceMapMappingId: mapping.id
81
+ sourceMapMappingId: mapping.id,
82
+ ...sourceMapMappingInspectionMetadata(input, sourceMap, mapping)
63
83
  }
64
84
  }));
65
85
  }
@@ -71,17 +91,31 @@ function createKernelSourcePreservationRecords(input) {
71
91
  function summarizeKernelSourcePreservationRecords(records) {
72
92
  const compactRecords = records.map(compactKernelSourcePreservationRecord);
73
93
  const byLevel = countBy(compactRecords.map((record) => record.level ?? 'unknown'));
94
+ const sourceMapRecords = compactRecords.filter((record) => record.compilerRecord === 'sourceMapMapping' || record.sourceMapMappingId);
74
95
  return {
75
96
  total: compactRecords.length,
76
97
  ids: compactRecords.map((record) => record.id).filter(Boolean),
77
98
  byLevel,
99
+ byPrecision: countBy(compactRecords.map((record) => record.precision ?? 'unknown')),
100
+ byCompilerRecord: countBy(compactRecords.map((record) => record.compilerRecord ?? 'unknown')),
101
+ bySourceMapOrigin: countBy(sourceMapRecords.map((record) => record.sourceMapOrigin ?? 'native-import')),
102
+ byOwnershipRegionKind: countBy(compactRecords.map((record) => record.ownershipRegionKind).filter(Boolean)),
78
103
  exact: byLevel.exact ?? 0,
79
104
  declaration: byLevel.declaration ?? 0,
80
105
  estimated: byLevel.estimated ?? 0,
81
106
  blocked: byLevel.blocked ?? 0,
82
107
  sourcePaths: uniqueStrings(compactRecords.map((record) => record.sourcePath).filter(Boolean)),
108
+ generatedPaths: uniqueStrings(compactRecords.map((record) => record.generatedPath).filter(Boolean)),
109
+ generatedNames: uniqueStrings(compactRecords.map((record) => record.generatedName).filter(Boolean)),
83
110
  sourceMapIds: uniqueStrings(compactRecords.map((record) => record.sourceMapId).filter(Boolean)),
84
111
  sourceMapMappingIds: uniqueStrings(compactRecords.map((record) => record.sourceMapMappingId).filter(Boolean)),
112
+ declarationMappingIds: uniqueStrings(sourceMapRecords.filter((record) => record.level === 'declaration' || record.precision === 'declaration').map((record) => record.sourceMapMappingId).filter(Boolean)),
113
+ generatedSpanMappingIds: uniqueStrings(sourceMapRecords.filter((record) => record.generatedRange || record.generatedPath).map((record) => record.sourceMapMappingId).filter(Boolean)),
114
+ semanticSymbolIds: uniqueStrings(compactRecords.map((record) => record.semanticSymbolId).filter(Boolean)),
115
+ semanticOccurrenceIds: uniqueStrings(compactRecords.map((record) => record.semanticOccurrenceId).filter(Boolean)),
116
+ nativeAstNodeIds: uniqueStrings(compactRecords.map((record) => record.nativeAstNodeId).filter(Boolean)),
117
+ ownershipRegionIds: uniqueStrings(compactRecords.map((record) => record.ownershipRegionId).filter(Boolean)),
118
+ queryKeys: uniqueStrings(compactRecords.flatMap((record) => record.queryKeys ?? [])),
85
119
  records: compactRecords
86
120
  };
87
121
  }
@@ -107,8 +141,11 @@ function compactKernelSourcePreservationRecord(record) {
107
141
  id: record.id,
108
142
  level: record.level,
109
143
  precision: record.precision,
144
+ compilerRecord: record.metadata?.compilerRecord,
145
+ preservation: record.metadata?.preservation ?? record.level,
110
146
  sourceMapId: record.sourceMapId,
111
147
  sourceMapMappingId: record.sourceMapMappingId,
148
+ sourceMapOrigin: record.metadata?.sourceMapOrigin,
112
149
  semanticNodeId: record.semanticNodeId,
113
150
  nativeSourceId: record.nativeSourceId,
114
151
  nativeAstNodeId: record.nativeAstNodeId,
@@ -116,9 +153,21 @@ function compactKernelSourcePreservationRecord(record) {
116
153
  semanticOccurrenceId: record.semanticOccurrenceId,
117
154
  sourcePath: record.sourceSpan?.path,
118
155
  generatedPath: record.generatedSpan?.path ?? record.generatedSpan?.targetPath,
156
+ generatedName: record.generatedSpan?.generatedName ?? record.metadata?.generatedName,
157
+ sourceRange: compactSpan(record.sourceSpan),
158
+ generatedRange: compactSpan(record.generatedSpan),
159
+ target: record.generatedSpan?.target?.language ?? record.generatedSpan?.target ?? record.metadata?.target,
160
+ targetPath: record.generatedSpan?.targetPath ?? record.metadata?.targetPath,
161
+ ownershipRegionId: record.metadata?.ownershipRegionId,
162
+ ownershipRegionKey: record.metadata?.ownershipRegionKey,
163
+ ownershipRegionKind: record.metadata?.ownershipRegionKind,
164
+ declarationKind: record.metadata?.declarationKind,
165
+ semanticKind: record.metadata?.semanticKind,
119
166
  lossIds: record.lossIds ?? [],
120
167
  evidenceIds: record.evidenceIds ?? [],
121
- reasons: record.reasons ?? []
168
+ reasons: record.reasons ?? [],
169
+ inspectionTags: record.metadata?.inspectionTags ?? [],
170
+ queryKeys: record.metadata?.queryKeys ?? []
122
171
  };
123
172
  }
124
173
 
@@ -141,6 +190,11 @@ function summarizeImportSourcePreservation(importResult, imports) {
141
190
  directives: compactRecords.reduce((sum, record) => sum + (record.directives ?? 0), 0),
142
191
  comments: compactRecords.reduce((sum, record) => sum + (record.comments ?? 0), 0),
143
192
  whitespace: compactRecords.reduce((sum, record) => sum + (record.whitespace ?? 0), 0),
193
+ triviaByKind: sumCountObjects(compactRecords.map((record) => record.triviaByKind)),
194
+ directivesByKind: sumCountObjects(compactRecords.map((record) => record.directivesByKind)),
195
+ directiveKinds: uniqueStrings(compactRecords.flatMap((record) => record.directiveKinds ?? [])),
196
+ commentSpanIds: uniqueStrings(compactRecords.flatMap((record) => record.commentSpanIds ?? [])),
197
+ directiveSpanIds: uniqueStrings(compactRecords.flatMap((record) => record.directiveSpanIds ?? [])),
144
198
  truncated: compactRecords.some((record) => record.truncated),
145
199
  records: compactRecords
146
200
  };
@@ -185,10 +239,51 @@ function compactSourcePreservationRecord(record) {
185
239
  directives: record.summary?.directives ?? record.directives?.length ?? 0,
186
240
  comments: record.summary?.comments ?? 0,
187
241
  whitespace: record.summary?.whitespace ?? 0,
242
+ triviaByKind: record.summary?.triviaByKind ?? countBy((record.trivia ?? []).map((entry) => entry.kind ?? 'unknown')),
243
+ directivesByKind: record.summary?.directivesByKind ?? countBy((record.directives ?? []).map((entry) => entry.kind ?? 'directive')),
244
+ directiveKinds: record.summary?.directiveKinds ?? uniqueStrings((record.directives ?? []).map((entry) => entry.kind ?? 'directive')),
245
+ commentSpanIds: record.summary?.commentSpanIds ?? (record.trivia ?? []).filter((entry) => entry.kind === 'comment').map((entry) => entry.id).filter(Boolean),
246
+ directiveSpanIds: record.summary?.directiveSpanIds ?? (record.directives ?? []).map((entry) => entry.id).filter(Boolean),
188
247
  truncated: record.summary?.truncated === true
189
248
  };
190
249
  }
191
250
 
251
+ function sourceMapMappingInspectionMetadata(input, sourceMap, mapping) {
252
+ const sourcePath = mapping.sourceSpan?.path ?? sourceMap.sourcePath ?? input.sourcePath;
253
+ const generatedPath = mapping.generatedSpan?.targetPath ?? mapping.generatedSpan?.path ?? sourceMap.targetPath;
254
+ const generatedName = mapping.generatedName ?? mapping.generatedSpan?.generatedName;
255
+ const origin = mapping.metadata?.sourceMapOrigin ?? (mapping.generatedSpan ? 'generated' : 'native-import');
256
+ const base = {
257
+ compilerRecord: 'sourceMapMapping',
258
+ level: mapping.preservation,
259
+ precision: mapping.precision,
260
+ sourcePath,
261
+ generatedPath,
262
+ sourceMapOrigin: origin,
263
+ ownershipRegionKind: mapping.ownershipRegionKind,
264
+ semanticSymbolId: mapping.semanticSymbolId
265
+ };
266
+ return {
267
+ preservation: mapping.preservation,
268
+ precision: mapping.precision,
269
+ sourceMapOrigin: origin,
270
+ sourcePath,
271
+ generatedPath,
272
+ targetPath: generatedPath,
273
+ generatedName,
274
+ sourceRange: compactSpan(mapping.sourceSpan),
275
+ generatedRange: compactSpan(mapping.generatedSpan),
276
+ target: mapping.target?.language ?? mapping.generatedSpan?.target?.language ?? mapping.target ?? mapping.generatedSpan?.target,
277
+ ownershipRegionId: mapping.ownershipRegionId,
278
+ ownershipRegionKey: mapping.ownershipRegionKey,
279
+ ownershipRegionKind: mapping.ownershipRegionKind,
280
+ declarationKind: mapping.metadata?.declarationKind,
281
+ semanticKind: mapping.metadata?.semanticKind,
282
+ inspectionTags: sourcePreservationInspectionTags(base),
283
+ queryKeys: sourcePreservationQueryKeys(base)
284
+ };
285
+ }
286
+
192
287
  export {
193
288
  collectKernelSourcePreservationFromImport,
194
289
  createKernelSourcePreservationRecords,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshift-labs/frontier-lang-compiler",
3
- "version": "0.2.100",
3
+ "version": "0.2.102",
4
4
  "description": "Compiler facade for Frontier Lang source documents and language projection adapters.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",