@shapeshift-labs/frontier-lang-compiler 0.2.34 → 0.2.36

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.
package/dist/index.d.ts CHANGED
@@ -18,7 +18,11 @@ import type {
18
18
  SemanticPatchBundle,
19
19
  SourceMapMappingRecord,
20
20
  SourceMapRecord,
21
- SourceSpan
21
+ SourcePreservationLevel,
22
+ SourcePreservationRecord,
23
+ SourceSpan,
24
+ UniversalAstLayerMap,
25
+ UniversalAstLayerRecord
22
26
  } from '@shapeshift-labs/frontier-lang-kernel';
23
27
  import type { Diagnostic } from '@shapeshift-labs/frontier-lang-checker';
24
28
  import type { EmitTypeScriptOptions, TypeScriptAstModule, TypeScriptDocumentSourceMapResult, TypeScriptGeneratedSourceMapResult } from '@shapeshift-labs/frontier-lang-typescript';
@@ -959,11 +963,42 @@ export interface SemanticImportSidecarImportEntry {
959
963
  readonly symbolCount: number;
960
964
  readonly sourceMapCount: number;
961
965
  readonly sourceMapMappingCount: number;
966
+ readonly sourcePreservationRecordCount: number;
967
+ readonly sourcePreservationLevels: readonly SourcePreservationLevel[];
968
+ readonly universalAstLayerCount: number;
969
+ readonly universalAstLayerNames: readonly string[];
970
+ readonly universalAstLayerIds: readonly string[];
962
971
  readonly readiness: SemanticMergeReadiness;
963
972
  readonly emptySemanticIndex: boolean;
964
973
  readonly regionTaxonomy?: SemanticImportRegionTaxonomySummary;
965
974
  }
966
975
 
976
+ export interface SemanticImportSidecarSourcePreservationRecord {
977
+ readonly id: string;
978
+ readonly level: SourcePreservationLevel;
979
+ readonly precision?: string;
980
+ readonly sourceMapId?: string;
981
+ readonly sourceMapMappingId?: string;
982
+ readonly semanticNodeId?: string;
983
+ readonly nativeSourceId?: string;
984
+ readonly nativeAstNodeId?: string;
985
+ readonly semanticSymbolId?: string;
986
+ readonly semanticOccurrenceId?: string;
987
+ readonly sourcePath?: string;
988
+ readonly generatedPath?: string;
989
+ readonly lossIds: readonly string[];
990
+ readonly evidenceIds: readonly string[];
991
+ readonly reasons: readonly string[];
992
+ }
993
+
994
+ export interface SemanticImportSidecarUniversalAstLayerSummary {
995
+ readonly total: number;
996
+ readonly names: readonly string[];
997
+ readonly ids: readonly string[];
998
+ readonly byName: Readonly<Record<string, number>>;
999
+ readonly empty: boolean;
1000
+ }
1001
+
967
1002
  export interface SemanticImportSidecar {
968
1003
  readonly kind: 'frontier.lang.semanticImportSidecar';
969
1004
  readonly version: 1;
@@ -979,6 +1014,20 @@ export interface SemanticImportSidecar {
979
1014
  readonly mappings: number;
980
1015
  readonly ids: readonly string[];
981
1016
  };
1017
+ readonly sourcePreservation: {
1018
+ readonly total: number;
1019
+ readonly ids: readonly string[];
1020
+ readonly byLevel: Readonly<Record<string, number>>;
1021
+ readonly exact: number;
1022
+ readonly declaration: number;
1023
+ readonly estimated: number;
1024
+ readonly blocked: number;
1025
+ readonly sourcePaths: readonly string[];
1026
+ readonly sourceMapIds: readonly string[];
1027
+ readonly sourceMapMappingIds: readonly string[];
1028
+ readonly records: readonly SemanticImportSidecarSourcePreservationRecord[];
1029
+ };
1030
+ readonly universalAstLayers: SemanticImportSidecarUniversalAstLayerSummary;
982
1031
  readonly patchHints: readonly SemanticImportPatchHint[];
983
1032
  readonly mergeCandidates: readonly {
984
1033
  readonly id?: string;
@@ -1007,6 +1056,9 @@ export interface SemanticImportSidecar {
1007
1056
  readonly ownershipRegions: number;
1008
1057
  readonly regionKinds: number;
1009
1058
  readonly sourceMapMappings: number;
1059
+ readonly sourcePreservationRecords: number;
1060
+ readonly universalAstLayers: number;
1061
+ readonly universalAstLayerNames: readonly string[];
1010
1062
  readonly readiness: SemanticMergeReadiness;
1011
1063
  readonly emptySemanticIndex: boolean;
1012
1064
  };
@@ -1392,10 +1444,14 @@ export interface ImportNativeSourceOptions {
1392
1444
  readonly metadata?: Record<string, unknown>;
1393
1445
  }
1394
1446
 
1395
- export type NativeSourceImportResult = LanguageImportResult & {
1447
+ export type NativeSourceImportResult = Omit<LanguageImportResult, 'metadata'> & {
1396
1448
  readonly nativeSource: NativeSourceNode;
1397
1449
  readonly semanticIndex?: SemanticIndexRecord;
1398
1450
  readonly universalAst: FrontierUniversalAstEnvelope;
1451
+ readonly metadata?: Record<string, unknown> & {
1452
+ readonly sourcePreservationRecords?: readonly SourcePreservationRecord[];
1453
+ readonly kernelSourcePreservationRecords?: readonly SourcePreservationRecord[];
1454
+ };
1399
1455
  };
1400
1456
 
1401
1457
  export type ExternalSemanticIndexFormat =
@@ -2150,9 +2206,13 @@ export declare function diffNativeSourceImports(input: DiffNativeSourceImportsOp
2150
2206
  export declare function importNativeProject(input: ImportNativeProjectOptions): Promise<NativeProjectImportResult>;
2151
2207
  export declare function createUniversalAstFromDocument(document: FrontierLangDocument, input?: {
2152
2208
  readonly id?: string;
2209
+ readonly nativeSources?: readonly NativeSourceNode[];
2153
2210
  readonly semanticIndex?: SemanticIndexRecord;
2154
2211
  readonly sourceMaps?: readonly SourceMapRecord[];
2212
+ readonly losses?: readonly NativeAstLossRecord[];
2155
2213
  readonly evidence?: readonly EvidenceRecord[];
2214
+ readonly mergeCandidates?: readonly SemanticMergeCandidateRecord[];
2215
+ readonly layers?: UniversalAstLayerMap | readonly UniversalAstLayerRecord[];
2156
2216
  readonly metadata?: Record<string, unknown>;
2157
2217
  }): FrontierUniversalAstEnvelope;
2158
2218
  export declare function readUniversalAstJson(source: string): FrontierUniversalAstEnvelope;
package/dist/index.js CHANGED
@@ -6,7 +6,9 @@ import {
6
6
  createSemanticIndexRecord,
7
7
  createSemanticMergeCandidateRecord,
8
8
  createSourceMapRecord,
9
+ createSourcePreservationRecord,
9
10
  createUniversalAstEnvelope,
11
+ explainSourcePreservation,
10
12
  hashDocumentBase,
11
13
  hashSemanticValue,
12
14
  nativeSourceNode,
@@ -2562,6 +2564,8 @@ export function createSemanticImportSidecar(importResult, options = {}) {
2562
2564
  const mergeCandidates = imports.flatMap((imported) => imported?.mergeCandidates ?? []);
2563
2565
  const lossSummary = summarizeNativeImportLosses(losses, { evidence });
2564
2566
  const regionTaxonomy = summarizeSemanticImportRegionTaxonomy(ownershipRegions);
2567
+ const sourcePreservation = summarizeKernelSourcePreservation(importResult, imports);
2568
+ const universalAstLayers = summarizeSemanticImportSidecarUniversalAstLayers(importEntries);
2565
2569
  const readiness = mergeCandidates.reduce(
2566
2570
  (current, candidate) => maxSemanticMergeReadiness(current, candidate.readiness),
2567
2571
  lossSummary.semanticMergeReadiness
@@ -2582,6 +2586,8 @@ export function createSemanticImportSidecar(importResult, options = {}) {
2582
2586
  mappings: sourceMapMappings.length,
2583
2587
  ids: sourceMaps.map((sourceMap) => sourceMap.id).filter(Boolean)
2584
2588
  },
2589
+ sourcePreservation,
2590
+ universalAstLayers,
2585
2591
  patchHints,
2586
2592
  mergeCandidates: mergeCandidates.map((candidate) => ({
2587
2593
  id: candidate.id,
@@ -2610,6 +2616,9 @@ export function createSemanticImportSidecar(importResult, options = {}) {
2610
2616
  ownershipRegions: ownershipRegions.length,
2611
2617
  regionKinds: regionTaxonomy.presentKinds.length,
2612
2618
  sourceMapMappings: sourceMapMappings.length,
2619
+ sourcePreservationRecords: sourcePreservation.total,
2620
+ universalAstLayers: universalAstLayers.total,
2621
+ universalAstLayerNames: universalAstLayers.names,
2613
2622
  readiness,
2614
2623
  emptySemanticIndex: symbols.length === 0
2615
2624
  },
@@ -3809,6 +3818,7 @@ export function importNativeSource(input) {
3809
3818
  nativeSource,
3810
3819
  evidence,
3811
3820
  losses,
3821
+ sourcePreservation,
3812
3822
  target: input.target,
3813
3823
  targetPath,
3814
3824
  targetHash
@@ -3843,6 +3853,7 @@ export function importNativeSource(input) {
3843
3853
  semanticIndex,
3844
3854
  evidence,
3845
3855
  losses,
3856
+ sourcePreservation,
3846
3857
  target: input.target,
3847
3858
  targetPath: inferredTargetPath,
3848
3859
  targetHash,
@@ -3850,6 +3861,20 @@ export function importNativeSource(input) {
3850
3861
  sourceHash,
3851
3862
  defaultSourceMapId: `source_map_${importIdPart}`
3852
3863
  });
3864
+ const sourcePreservationRecords = createKernelSourcePreservationRecords({
3865
+ idPart: importIdPart,
3866
+ language,
3867
+ sourcePath,
3868
+ sourceHash,
3869
+ sourcePreservation,
3870
+ sourceMaps,
3871
+ losses,
3872
+ evidence,
3873
+ nativeSource,
3874
+ nativeAst,
3875
+ semanticIndex
3876
+ });
3877
+ const kernelSourcePreservationSummary = summarizeKernelSourcePreservationRecords(sourcePreservationRecords);
3853
3878
  const resultSourceMapMappings = sourceMaps.flatMap((sourceMap) => sourceMap.mappings ?? []);
3854
3879
  const universalAst = createUniversalAstEnvelope({
3855
3880
  id: input.universalAstId ?? `universal_ast_${importIdPart}`,
@@ -3868,6 +3893,11 @@ export function importNativeSource(input) {
3868
3893
  sourcePreservationId: sourcePreservation.id,
3869
3894
  sourcePreservation
3870
3895
  } : {}),
3896
+ ...(sourcePreservationRecords.length ? {
3897
+ sourcePreservationRecords,
3898
+ kernelSourcePreservationRecords: sourcePreservationRecords,
3899
+ kernelSourcePreservationSummary
3900
+ } : {}),
3871
3901
  ...(declaredSourceHash && declaredSourceHash !== sourceHash ? {
3872
3902
  declaredSourceHash,
3873
3903
  sourceHashVerified: false
@@ -3895,6 +3925,10 @@ export function importNativeSource(input) {
3895
3925
  sourcePreservationId: sourcePreservation.id,
3896
3926
  sourcePreservationSummary: sourcePreservation.summary
3897
3927
  } : {}),
3928
+ ...(sourcePreservationRecords.length ? {
3929
+ kernelSourcePreservationRecordIds: sourcePreservationRecords.map((record) => record.id),
3930
+ kernelSourcePreservationSummary
3931
+ } : {}),
3898
3932
  ...(declaredSourceHash && declaredSourceHash !== sourceHash ? {
3899
3933
  declaredSourceHash,
3900
3934
  sourceHashVerified: false
@@ -3925,6 +3959,11 @@ export function importNativeSource(input) {
3925
3959
  sourcePreservationId: sourcePreservation.id,
3926
3960
  sourcePreservation
3927
3961
  } : {}),
3962
+ ...(sourcePreservationRecords.length ? {
3963
+ sourcePreservationRecords,
3964
+ kernelSourcePreservationRecords: sourcePreservationRecords,
3965
+ kernelSourcePreservationSummary
3966
+ } : {}),
3928
3967
  ...(declaredSourceHash && declaredSourceHash !== sourceHash ? {
3929
3968
  declaredSourceHash,
3930
3969
  sourceHashVerified: false
@@ -6571,6 +6610,8 @@ function normalizeSourceMapMappings(mappings, context) {
6571
6610
  const sourceSpan = mapping.sourceSpan ?? occurrence?.span ?? nativeNode?.span;
6572
6611
  const target = mapping.target ?? mapping.generatedSpan?.target ?? context.target;
6573
6612
  const generatedSpan = normalizeGeneratedSpan(mapping.generatedSpan, target, context.targetPath, context.targetHash);
6613
+ const mappingLossIds = normalizeReferenceIds(mapping.lossIds, lossIdsForNativeNode(context.losses ?? nativeAst?.losses ?? [], nativeAstNodeId));
6614
+ const precision = normalizeSourceMapPrecision(mapping.precision, sourceSpan, generatedSpan);
6574
6615
  if (
6575
6616
  !nativeAstNodeId &&
6576
6617
  !mapping.semanticNodeId &&
@@ -6593,11 +6634,17 @@ function normalizeSourceMapMappings(mappings, context) {
6593
6634
  generatedSpan,
6594
6635
  target,
6595
6636
  evidenceIds: normalizeReferenceIds(mapping.evidenceIds, evidenceIds),
6596
- lossIds: normalizeReferenceIds(mapping.lossIds, lossIdsForNativeNode(context.losses ?? nativeAst?.losses ?? [], nativeAstNodeId)),
6637
+ lossIds: mappingLossIds,
6597
6638
  ownershipRegionId: mapping.ownershipRegionId ?? symbol?.metadata?.ownershipRegionId,
6598
6639
  ownershipRegionKey: mapping.ownershipRegionKey ?? symbol?.metadata?.ownershipRegionKey,
6599
6640
  ownershipRegionKind: mapping.ownershipRegionKind ?? symbol?.metadata?.ownershipRegionKind,
6600
- precision: normalizeSourceMapPrecision(mapping.precision, sourceSpan, generatedSpan)
6641
+ precision,
6642
+ preservation: normalizeSourcePreservationLevel(mapping.preservation, {
6643
+ precision,
6644
+ lossIds: mappingLossIds,
6645
+ losses: context.losses ?? nativeAst?.losses ?? [],
6646
+ sourcePreservation: context.sourcePreservation
6647
+ })
6601
6648
  };
6602
6649
  return {
6603
6650
  ...normalizedMapping,
@@ -6678,10 +6725,19 @@ function normalizeSourceMapPrecision(value, sourceSpan, generatedSpan) {
6678
6725
  const explicit = value === undefined || value === null ? '' : String(value).trim();
6679
6726
  if (explicit) {
6680
6727
  const normalized = explicit.toLowerCase();
6681
- if (normalized === 'exact' || normalized === 'declaration' || normalized === 'line' || normalized === 'estimated' || normalized === 'unknown') return normalized;
6728
+ if (normalized === 'exact') {
6729
+ return hasExactSpan(sourceSpan) && hasExactSpan(generatedSpan)
6730
+ ? 'exact'
6731
+ : inferSourceMapPrecisionFromSpans(sourceSpan, generatedSpan);
6732
+ }
6733
+ if (normalized === 'declaration' || normalized === 'line' || normalized === 'estimated' || normalized === 'unknown') return normalized;
6682
6734
  if (normalized === 'estimate' || normalized === 'approx' || normalized === 'approximate' || normalized === 'approximated') return 'estimated';
6683
6735
  return explicit;
6684
6736
  }
6737
+ return inferSourceMapPrecisionFromSpans(sourceSpan, generatedSpan);
6738
+ }
6739
+
6740
+ function inferSourceMapPrecisionFromSpans(sourceSpan, generatedSpan) {
6685
6741
  if (hasExactSpan(sourceSpan) && hasExactSpan(generatedSpan)) return 'exact';
6686
6742
  if (sourceSpan?.startLine && generatedSpan?.startLine) return 'line';
6687
6743
  if (sourceSpan?.startLine) return 'declaration';
@@ -6689,6 +6745,25 @@ function normalizeSourceMapPrecision(value, sourceSpan, generatedSpan) {
6689
6745
  return 'unknown';
6690
6746
  }
6691
6747
 
6748
+ function normalizeSourcePreservationLevel(value, context = {}) {
6749
+ const explicit = value === undefined || value === null ? '' : String(value).trim();
6750
+ if (explicit) {
6751
+ const normalized = explicit.toLowerCase();
6752
+ if (normalized === 'exact' || normalized === 'declaration' || normalized === 'estimated' || normalized === 'blocked') return normalized;
6753
+ if (normalized === 'estimate' || normalized === 'approx' || normalized === 'approximate' || normalized === 'approximated' || normalized === 'line') return 'estimated';
6754
+ return explicit;
6755
+ }
6756
+
6757
+ const lossIds = new Set(context.lossIds ?? []);
6758
+ const linkedLosses = (context.losses ?? []).filter((loss) => lossIds.has(loss.id));
6759
+ if (linkedLosses.some((loss) => loss.severity === 'error')) return 'blocked';
6760
+ if (context.precision === 'exact') return 'exact';
6761
+ if (context.precision === 'declaration') return 'declaration';
6762
+ if (context.precision === 'line' || context.precision === 'estimated' || context.precision === 'unknown') return 'estimated';
6763
+ if (context.sourcePreservation?.summary?.exactSourceAvailable === true) return 'estimated';
6764
+ return 'estimated';
6765
+ }
6766
+
6692
6767
  function hasExactSpan(span) {
6693
6768
  return Boolean(span && (
6694
6769
  (typeof span.start === 'number' && typeof span.end === 'number') ||
@@ -7402,6 +7477,12 @@ function nativeSourceCompilePreservedMappings(input) {
7402
7477
  ownershipRegionKey: mapping.ownershipRegionKey,
7403
7478
  ownershipRegionKind: mapping.ownershipRegionKind,
7404
7479
  precision: exact ? 'exact' : mapping.precision === 'exact' ? 'line' : mapping.precision ?? 'line',
7480
+ preservation: exact ? 'exact' : normalizeSourcePreservationLevel(mapping.preservation, {
7481
+ precision: mapping.precision === 'exact' ? 'line' : mapping.precision ?? 'line',
7482
+ lossIds: mapping.lossIds,
7483
+ losses: input.losses ?? [],
7484
+ sourcePreservation: input.importResult.metadata?.sourcePreservation
7485
+ }),
7405
7486
  metadata: {
7406
7487
  ...mapping.metadata,
7407
7488
  compileResultId: input.compileResultId,
@@ -7429,6 +7510,7 @@ function nativeSourceCompileDeclarationMappings(input) {
7429
7510
  ownershipRegionKey: declaration.metadata?.ownershipRegionKey,
7430
7511
  ownershipRegionKind: declaration.metadata?.ownershipRegionKind,
7431
7512
  precision: generated.exactName ? 'declaration' : 'estimated',
7513
+ preservation: generated.exactName ? 'declaration' : 'estimated',
7432
7514
  metadata: {
7433
7515
  ...declaration.metadata,
7434
7516
  compileResultId: input.compileResultId,
@@ -7451,6 +7533,7 @@ function nativeSourceCompileFileMapping(input) {
7451
7533
  target: input.target,
7452
7534
  evidenceIds: (input.evidence ?? []).map((record) => record.id).filter(Boolean),
7453
7535
  precision: input.projection.mode === 'preserved-source' && input.outputHash === input.projection.sourceHash ? 'line' : 'estimated',
7536
+ preservation: input.losses?.some((loss) => loss.severity === 'error') ? 'blocked' : 'estimated',
7454
7537
  metadata: {
7455
7538
  compileResultId: input.compileResultId,
7456
7539
  sourceMapOrigin: 'file-fallback'
@@ -8497,6 +8580,8 @@ function semanticImportSidecarEntry(imported, index, options) {
8497
8580
  const nativeAst = imported?.nativeAst ?? imported?.nativeSource?.ast;
8498
8581
  const sourceMaps = imported?.sourceMaps ?? imported?.universalAst?.sourceMaps ?? [];
8499
8582
  const sourceMapMappings = sourceMaps.flatMap((sourceMap) => sourceMap?.mappings ?? []);
8583
+ const sourcePreservationRecords = collectKernelSourcePreservationFromImport(imported);
8584
+ const universalAstLayers = summarizeUniversalAstLayers(imported?.universalAst);
8500
8585
  const mappingsBySymbolId = new Map();
8501
8586
  for (const mapping of sourceMapMappings) {
8502
8587
  if (mapping.semanticSymbolId && !mappingsBySymbolId.has(mapping.semanticSymbolId)) {
@@ -8541,6 +8626,11 @@ function semanticImportSidecarEntry(imported, index, options) {
8541
8626
  symbolCount: symbols.length,
8542
8627
  sourceMapCount: sourceMaps.length,
8543
8628
  sourceMapMappingCount: sourceMapMappings.length,
8629
+ sourcePreservationRecordCount: sourcePreservationRecords.length,
8630
+ sourcePreservationLevels: uniqueStrings(sourcePreservationRecords.map((record) => record.level).filter(Boolean)),
8631
+ universalAstLayerCount: universalAstLayers.total,
8632
+ universalAstLayerNames: universalAstLayers.names,
8633
+ universalAstLayerIds: universalAstLayers.ids,
8544
8634
  readiness: imported?.metadata?.semanticMergeReadiness ?? imported?.mergeCandidates?.[0]?.readiness ?? 'needs-review',
8545
8635
  emptySemanticIndex: symbols.length === 0,
8546
8636
  regionTaxonomy,
@@ -8549,6 +8639,52 @@ function semanticImportSidecarEntry(imported, index, options) {
8549
8639
  };
8550
8640
  }
8551
8641
 
8642
+ function summarizeSemanticImportSidecarUniversalAstLayers(importEntries) {
8643
+ const names = [];
8644
+ const ids = [];
8645
+ const byName = {};
8646
+ for (const entry of importEntries) {
8647
+ names.push(...(entry.universalAstLayerNames ?? []));
8648
+ ids.push(...(entry.universalAstLayerIds ?? []));
8649
+ for (const name of entry.universalAstLayerNames ?? []) {
8650
+ byName[name] = (byName[name] ?? 0) + 1;
8651
+ }
8652
+ }
8653
+ const uniqueNames = uniqueStrings(names);
8654
+ return {
8655
+ total: ids.length,
8656
+ names: uniqueNames,
8657
+ ids: uniqueStrings(ids),
8658
+ byName,
8659
+ empty: ids.length === 0
8660
+ };
8661
+ }
8662
+
8663
+ function summarizeUniversalAstLayers(universalAst) {
8664
+ const layers = collectUniversalAstLayerRecords(universalAst?.layers);
8665
+ const names = uniqueStrings(layers.map((layer) => layer.layer).filter(Boolean));
8666
+ const ids = uniqueStrings(layers.map((layer) => layer.id).filter(Boolean));
8667
+ const byName = {};
8668
+ for (const layer of layers) {
8669
+ if (!layer?.layer) continue;
8670
+ byName[layer.layer] = (byName[layer.layer] ?? 0) + 1;
8671
+ }
8672
+ return {
8673
+ total: layers.length,
8674
+ names,
8675
+ ids,
8676
+ byName,
8677
+ empty: layers.length === 0
8678
+ };
8679
+ }
8680
+
8681
+ function collectUniversalAstLayerRecords(layers) {
8682
+ if (!layers) return [];
8683
+ if (Array.isArray(layers)) return layers.filter(Boolean);
8684
+ if (typeof layers !== 'object') return [];
8685
+ return Object.values(layers).flatMap((value) => Array.isArray(value) ? value : [value]).filter(Boolean);
8686
+ }
8687
+
8552
8688
  function semanticOwnershipRegionForSymbol(imported, symbol, mapping, nativeNode, options = {}) {
8553
8689
  const sourcePath = mapping?.sourceSpan?.path ?? symbol.definitionSpan?.path ?? nativeNode?.span?.path ?? imported?.sourcePath ?? imported?.nativeSource?.sourcePath ?? imported?.nativeAst?.sourcePath;
8554
8690
  const language = symbol.language ?? imported?.language ?? imported?.nativeAst?.language ?? imported?.nativeSource?.language;
@@ -8935,6 +9071,127 @@ function summarizeImportRegions(importResult, imports, options = {}) {
8935
9071
  };
8936
9072
  }
8937
9073
 
9074
+ function createKernelSourcePreservationRecords(input) {
9075
+ const records = [];
9076
+ if (input.sourcePreservation) {
9077
+ const exactSource = input.sourcePreservation.summary?.exactSourceAvailable === true &&
9078
+ (!input.sourceHash || input.sourcePreservation.sourceHash === input.sourceHash);
9079
+ const hashMismatch = input.sourceHash &&
9080
+ input.sourcePreservation.sourceHash &&
9081
+ input.sourcePreservation.sourceHash !== input.sourceHash;
9082
+ records.push(createSourcePreservationRecord({
9083
+ id: `source_preservation_${idFragment(input.idPart ?? input.sourcePath ?? input.language)}_file`,
9084
+ level: hashMismatch ? 'blocked' : exactSource ? 'exact' : 'estimated',
9085
+ precision: exactSource ? 'exact' : 'estimated',
9086
+ nativeSourceId: input.nativeSource?.id,
9087
+ nativeAstNodeId: input.nativeAst?.rootId,
9088
+ sourceSpan: {
9089
+ sourceId: input.sourceHash,
9090
+ path: input.sourcePath,
9091
+ startLine: 1,
9092
+ startColumn: 1
9093
+ },
9094
+ lossIds: (input.losses ?? []).filter((loss) => loss.kind === 'sourcePreservation' || loss.sourceMapId).map((loss) => loss.id),
9095
+ evidenceIds: (input.evidence ?? []).map((record) => record.id).filter(Boolean),
9096
+ losses: input.losses ?? [],
9097
+ evidence: input.evidence ?? [],
9098
+ reasons: hashMismatch
9099
+ ? [`Preserved source hash ${input.sourcePreservation.sourceHash} does not match import hash ${input.sourceHash}.`]
9100
+ : exactSource
9101
+ ? ['Exact native source text is preserved for source-level replay and semantic merge review.']
9102
+ : ['Native source preservation metadata exists, but exact source text is unavailable or unverified.'],
9103
+ metadata: {
9104
+ compilerRecord: 'nativeSourcePreservation',
9105
+ nativeSourcePreservationId: input.sourcePreservation.id,
9106
+ sourceBytes: input.sourcePreservation.sourceBytes,
9107
+ lineCount: input.sourcePreservation.lineCount,
9108
+ tokens: input.sourcePreservation.summary?.tokens ?? 0,
9109
+ trivia: input.sourcePreservation.summary?.trivia ?? 0,
9110
+ directives: input.sourcePreservation.summary?.directives ?? 0,
9111
+ comments: input.sourcePreservation.summary?.comments ?? 0,
9112
+ whitespace: input.sourcePreservation.summary?.whitespace ?? 0,
9113
+ truncated: input.sourcePreservation.summary?.truncated === true
9114
+ }
9115
+ }));
9116
+ }
9117
+
9118
+ for (const sourceMap of input.sourceMaps ?? []) {
9119
+ for (const mapping of sourceMap.mappings ?? []) {
9120
+ records.push(explainSourcePreservation({
9121
+ id: `source_preservation_${idFragment(sourceMap.id)}_${idFragment(mapping.id)}`,
9122
+ sourceMap,
9123
+ mapping,
9124
+ level: mapping.preservation,
9125
+ losses: input.losses ?? [],
9126
+ evidence: uniqueRecordsById([...(input.evidence ?? []), ...(sourceMap.evidence ?? [])]),
9127
+ metadata: {
9128
+ compilerRecord: 'sourceMapMapping',
9129
+ language: input.language,
9130
+ semanticIndexId: input.semanticIndex?.id,
9131
+ sourceMapId: sourceMap.id,
9132
+ sourceMapMappingId: mapping.id
9133
+ }
9134
+ }));
9135
+ }
9136
+ }
9137
+
9138
+ return uniqueRecordsById(records);
9139
+ }
9140
+
9141
+ function summarizeKernelSourcePreservationRecords(records) {
9142
+ const compactRecords = records.map(compactKernelSourcePreservationRecord);
9143
+ const byLevel = countBy(compactRecords.map((record) => record.level ?? 'unknown'));
9144
+ return {
9145
+ total: compactRecords.length,
9146
+ ids: compactRecords.map((record) => record.id).filter(Boolean),
9147
+ byLevel,
9148
+ exact: byLevel.exact ?? 0,
9149
+ declaration: byLevel.declaration ?? 0,
9150
+ estimated: byLevel.estimated ?? 0,
9151
+ blocked: byLevel.blocked ?? 0,
9152
+ sourcePaths: uniqueStrings(compactRecords.map((record) => record.sourcePath).filter(Boolean)),
9153
+ sourceMapIds: uniqueStrings(compactRecords.map((record) => record.sourceMapId).filter(Boolean)),
9154
+ sourceMapMappingIds: uniqueStrings(compactRecords.map((record) => record.sourceMapMappingId).filter(Boolean)),
9155
+ records: compactRecords
9156
+ };
9157
+ }
9158
+
9159
+ function collectKernelSourcePreservationFromImport(imported) {
9160
+ return uniqueRecordsById([
9161
+ ...(imported?.metadata?.kernelSourcePreservationRecords ?? []),
9162
+ ...(imported?.metadata?.sourcePreservationRecords ?? []),
9163
+ ...(imported?.universalAst?.metadata?.kernelSourcePreservationRecords ?? []),
9164
+ ...(imported?.universalAst?.metadata?.sourcePreservationRecords ?? [])
9165
+ ].filter((record) => record?.kind === 'frontier.lang.sourcePreservation'));
9166
+ }
9167
+
9168
+ function summarizeKernelSourcePreservation(importResult, imports) {
9169
+ return summarizeKernelSourcePreservationRecords(uniqueRecordsById([
9170
+ ...collectKernelSourcePreservationFromImport(importResult),
9171
+ ...imports.flatMap((imported) => collectKernelSourcePreservationFromImport(imported))
9172
+ ]));
9173
+ }
9174
+
9175
+ function compactKernelSourcePreservationRecord(record) {
9176
+ return {
9177
+ id: record.id,
9178
+ level: record.level,
9179
+ precision: record.precision,
9180
+ sourceMapId: record.sourceMapId,
9181
+ sourceMapMappingId: record.sourceMapMappingId,
9182
+ semanticNodeId: record.semanticNodeId,
9183
+ nativeSourceId: record.nativeSourceId,
9184
+ nativeAstNodeId: record.nativeAstNodeId,
9185
+ semanticSymbolId: record.semanticSymbolId,
9186
+ semanticOccurrenceId: record.semanticOccurrenceId,
9187
+ sourcePath: record.sourceSpan?.path,
9188
+ generatedPath: record.generatedSpan?.path ?? record.generatedSpan?.targetPath,
9189
+ lossIds: record.lossIds ?? [],
9190
+ evidenceIds: record.evidenceIds ?? [],
9191
+ reasons: record.reasons ?? []
9192
+ };
9193
+ }
9194
+
8938
9195
  function summarizeImportSourcePreservation(importResult, imports) {
8939
9196
  const records = uniqueSourcePreservationRecords([
8940
9197
  ...collectSourcePreservationFromImport(importResult),
@@ -9156,9 +9413,13 @@ export function createUniversalAstFromDocument(document, input = {}) {
9156
9413
  return createUniversalAstEnvelope({
9157
9414
  id: input.id ?? `universal_ast_${idFragment(document.id)}`,
9158
9415
  document,
9416
+ nativeSources: input.nativeSources,
9159
9417
  semanticIndex: input.semanticIndex,
9160
9418
  sourceMaps: input.sourceMaps ?? [],
9419
+ losses: input.losses,
9161
9420
  evidence: input.evidence ?? [],
9421
+ mergeCandidates: input.mergeCandidates,
9422
+ layers: input.layers,
9162
9423
  metadata: input.metadata
9163
9424
  });
9164
9425
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshift-labs/frontier-lang-compiler",
3
- "version": "0.2.34",
3
+ "version": "0.2.36",
4
4
  "description": "Compiler facade for Frontier Lang source documents and language projection adapters.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -59,7 +59,7 @@
59
59
  "@shapeshift-labs/frontier-lang-c": "0.2.5",
60
60
  "@shapeshift-labs/frontier-lang-checker": "0.3.4",
61
61
  "@shapeshift-labs/frontier-lang-javascript": "0.2.5",
62
- "@shapeshift-labs/frontier-lang-kernel": "0.3.4",
62
+ "@shapeshift-labs/frontier-lang-kernel": "0.3.6",
63
63
  "@shapeshift-labs/frontier-lang-parser": "0.3.4",
64
64
  "@shapeshift-labs/frontier-lang-python": "0.2.5",
65
65
  "@shapeshift-labs/frontier-lang-rust": "0.2.5",