@shapeshift-labs/frontier-lang-compiler 0.2.11 → 0.2.12

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
@@ -118,6 +118,17 @@ export type NativeImportKnownLossKind =
118
118
  | 'targetProjectionLoss'
119
119
  | string;
120
120
 
121
+ export type NativeImportRegionTaxonomyKind =
122
+ | 'symbol'
123
+ | 'declaration'
124
+ | 'import'
125
+ | 'body'
126
+ | 'call'
127
+ | 'type'
128
+ | 'effect'
129
+ | 'generatedOutput'
130
+ | string;
131
+
121
132
  export interface NativeImportLossSummaryOptions {
122
133
  readonly exactAst?: boolean;
123
134
  readonly evidence?: readonly EvidenceRecord[];
@@ -217,6 +228,167 @@ export interface NativeImportCoverageMatrixOptions {
217
228
  readonly generatedAt?: number;
218
229
  }
219
230
 
231
+ export interface NativeImportContractSource {
232
+ readonly id: string;
233
+ readonly language?: FrontierSourceLanguage | string;
234
+ readonly sourcePath?: string;
235
+ readonly sourceHash?: string;
236
+ readonly parser?: string;
237
+ readonly nativeSourceId?: string;
238
+ readonly nativeAstId?: string;
239
+ readonly semanticIndexId?: string;
240
+ readonly universalAstId?: string;
241
+ readonly patchId?: string;
242
+ readonly sourceMapIds: readonly string[];
243
+ readonly sourceMapMappings: number;
244
+ readonly symbolCount: number;
245
+ readonly lossCount: number;
246
+ readonly evidenceCount: number;
247
+ readonly readiness?: SemanticMergeReadiness;
248
+ }
249
+
250
+ export interface NativeImportSourcePreservationRecordSummary {
251
+ readonly id?: string;
252
+ readonly language?: FrontierSourceLanguage | string;
253
+ readonly sourcePath?: string;
254
+ readonly sourceHash?: string;
255
+ readonly sourceBytes?: number;
256
+ readonly lineCount?: number;
257
+ readonly newline?: string;
258
+ readonly encoding?: string;
259
+ readonly exactSourceAvailable: boolean;
260
+ readonly tokens: number;
261
+ readonly trivia: number;
262
+ readonly directives: number;
263
+ readonly comments: number;
264
+ readonly whitespace: number;
265
+ readonly truncated: boolean;
266
+ }
267
+
268
+ export interface NativeImportSourcePreservationContract {
269
+ readonly total: number;
270
+ readonly ids: readonly string[];
271
+ readonly sourcePaths: readonly string[];
272
+ readonly sourceHashes: readonly string[];
273
+ readonly exactSourceAvailable: number;
274
+ readonly sourceBytes: number;
275
+ readonly lineCount: number;
276
+ readonly tokens: number;
277
+ readonly trivia: number;
278
+ readonly directives: number;
279
+ readonly comments: number;
280
+ readonly whitespace: number;
281
+ readonly truncated: boolean;
282
+ readonly records: readonly NativeImportSourcePreservationRecordSummary[];
283
+ }
284
+
285
+ export interface NativeImportAdapterCoverageRecordSummary {
286
+ readonly adapterId?: string;
287
+ readonly adapterVersion?: string;
288
+ readonly parser?: string;
289
+ readonly capabilities: readonly string[];
290
+ readonly supportedExtensions: readonly string[];
291
+ readonly exactness?: NativeImporterAdapterExactness;
292
+ readonly exactAst: boolean;
293
+ readonly tokens: boolean;
294
+ readonly trivia: boolean;
295
+ readonly diagnostics: boolean;
296
+ readonly sourceRanges: boolean;
297
+ readonly generatedRanges: boolean;
298
+ readonly semanticCoverage?: NativeImporterAdapterSemanticCoverage;
299
+ readonly observed?: NativeImporterAdapterCoverageObserved;
300
+ readonly notes: readonly string[];
301
+ }
302
+
303
+ export interface NativeImportAdapterCoverageContract {
304
+ readonly total: number;
305
+ readonly adapterIds: readonly string[];
306
+ readonly parsers: readonly string[];
307
+ readonly exactness: readonly string[];
308
+ readonly exactAst: number;
309
+ readonly tokens: number;
310
+ readonly trivia: number;
311
+ readonly diagnostics: number;
312
+ readonly sourceRanges: number;
313
+ readonly generatedRanges: number;
314
+ readonly semanticCoverageLevels: readonly string[];
315
+ readonly observed: NativeImporterAdapterCoverageObserved;
316
+ readonly records: readonly NativeImportAdapterCoverageRecordSummary[];
317
+ }
318
+
319
+ export interface NativeImportRegionSummary {
320
+ readonly total: number;
321
+ readonly ids: readonly string[];
322
+ readonly keys: readonly string[];
323
+ readonly sourcePaths: readonly string[];
324
+ readonly byKind: Readonly<Record<string, number>>;
325
+ readonly byGranularity: Readonly<Record<string, number>>;
326
+ readonly byPrecision: Readonly<Record<string, number>>;
327
+ readonly byLanguage: Readonly<Record<string, number>>;
328
+ readonly symbolIds: readonly string[];
329
+ readonly taxonomy: SemanticImportRegionTaxonomySummary;
330
+ }
331
+
332
+ export interface NativeImportSourceMapSummary {
333
+ readonly total: number;
334
+ readonly ids: readonly string[];
335
+ readonly mappingCount: number;
336
+ readonly sourcePaths: readonly string[];
337
+ readonly targetPaths: readonly string[];
338
+ readonly byPrecision: Readonly<Record<string, number>>;
339
+ readonly sourceRangeMappings: number;
340
+ readonly generatedRangeMappings: number;
341
+ }
342
+
343
+ export interface NativeImportReadinessContract {
344
+ readonly semanticMergeReadiness: SemanticMergeReadiness;
345
+ readonly severityReadiness: SemanticMergeReadiness;
346
+ readonly reasons: readonly string[];
347
+ readonly failedEvidenceIds: readonly string[];
348
+ readonly blockingLossIds: readonly string[];
349
+ readonly reviewLossIds: readonly string[];
350
+ readonly informationalLossIds: readonly string[];
351
+ }
352
+
353
+ export interface NativeImportResultContract {
354
+ readonly kind: 'frontier.lang.nativeImportResultContract';
355
+ readonly version: 1;
356
+ readonly importResultId?: string;
357
+ readonly language?: FrontierSourceLanguage | 'mixed' | string;
358
+ readonly sourcePath?: string;
359
+ readonly sourceHash?: string;
360
+ readonly sourceCount: number;
361
+ readonly sources: readonly NativeImportContractSource[];
362
+ readonly ids: {
363
+ readonly nativeSourceId?: string;
364
+ readonly nativeAstId?: string;
365
+ readonly semanticIndexId?: string;
366
+ readonly universalAstId?: string;
367
+ readonly patchId?: string;
368
+ readonly sourceMapIds: readonly string[];
369
+ readonly semanticSidecarIds: readonly string[];
370
+ };
371
+ readonly sourcePreservation: NativeImportSourcePreservationContract;
372
+ readonly adapterCoverage: NativeImportAdapterCoverageContract;
373
+ readonly lossSummary: NativeImportLossSummary;
374
+ readonly regions: NativeImportRegionSummary;
375
+ readonly sourceMaps: NativeImportSourceMapSummary;
376
+ readonly readiness: NativeImportReadinessContract;
377
+ readonly evidence: {
378
+ readonly total: number;
379
+ readonly failed: readonly string[];
380
+ readonly ids: readonly string[];
381
+ };
382
+ readonly metadata: Record<string, unknown>;
383
+ }
384
+
385
+ export interface NativeImportResultContractOptions extends SemanticImportSidecarOptions {
386
+ readonly lossSummary?: NativeImportLossSummary;
387
+ readonly semanticSidecarIds?: readonly string[] | string;
388
+ readonly sidecarIds?: readonly string[] | string;
389
+ readonly sidecarId?: string;
390
+ }
391
+
220
392
  export type NativeSourceTokenKind =
221
393
  | 'identifier'
222
394
  | 'keyword'
@@ -296,8 +468,10 @@ export interface CreateNativeSourcePreservationOptions {
296
468
  export interface SemanticImportOwnershipRegion {
297
469
  readonly id: string;
298
470
  readonly key: string;
471
+ readonly regionKind?: NativeImportRegionTaxonomyKind;
299
472
  readonly granularity: 'symbol' | string;
300
473
  readonly language?: FrontierSourceLanguage | string;
474
+ readonly documentId?: string;
301
475
  readonly sourcePath?: string;
302
476
  readonly sourceHash?: string;
303
477
  readonly symbolId?: string;
@@ -307,6 +481,7 @@ export interface SemanticImportOwnershipRegion {
307
481
  readonly sourceSpan?: SourceSpan;
308
482
  readonly precision?: 'exact' | 'declaration' | 'line' | 'estimated' | 'unknown' | string;
309
483
  readonly mergePolicy?: string;
484
+ readonly metadata?: Record<string, unknown>;
310
485
  }
311
486
 
312
487
  export interface SemanticImportSidecarSymbol {
@@ -321,9 +496,18 @@ export interface SemanticImportSidecarSymbol {
321
496
  readonly signatureHash?: string;
322
497
  readonly ownershipRegionId: string;
323
498
  readonly ownershipKey: string;
499
+ readonly ownershipRegionKind?: NativeImportRegionTaxonomyKind;
324
500
  readonly readiness: SemanticMergeReadiness;
325
501
  }
326
502
 
503
+ export interface SemanticImportRegionTaxonomySummary {
504
+ readonly kinds: readonly NativeImportRegionTaxonomyKind[];
505
+ readonly presentKinds: readonly NativeImportRegionTaxonomyKind[];
506
+ readonly byKind: Readonly<Record<string, number>>;
507
+ readonly keys: readonly string[];
508
+ readonly keysByKind: Readonly<Record<string, readonly string[]>>;
509
+ }
510
+
327
511
  export interface SemanticImportPatchHint {
328
512
  readonly id: string;
329
513
  readonly kind: 'source-region-patch' | string;
@@ -357,6 +541,7 @@ export interface SemanticImportSidecarImportEntry {
357
541
  readonly sourceMapMappingCount: number;
358
542
  readonly readiness: SemanticMergeReadiness;
359
543
  readonly emptySemanticIndex: boolean;
544
+ readonly regionTaxonomy?: SemanticImportRegionTaxonomySummary;
360
545
  }
361
546
 
362
547
  export interface SemanticImportSidecar {
@@ -390,6 +575,7 @@ export interface SemanticImportSidecar {
390
575
  readonly blockingLossIds: readonly string[];
391
576
  readonly reviewLossIds: readonly string[];
392
577
  };
578
+ readonly regionTaxonomy: SemanticImportRegionTaxonomySummary;
393
579
  readonly evidence: {
394
580
  readonly total: number;
395
581
  readonly failed: readonly string[];
@@ -399,6 +585,7 @@ export interface SemanticImportSidecar {
399
585
  readonly imports: number;
400
586
  readonly symbols: number;
401
587
  readonly ownershipRegions: number;
588
+ readonly regionKinds: number;
402
589
  readonly sourceMapMappings: number;
403
590
  readonly readiness: SemanticMergeReadiness;
404
591
  readonly emptySemanticIndex: boolean;
@@ -784,6 +971,7 @@ export declare const FrontierCompileTargets: readonly FrontierCompileTarget[];
784
971
  export declare const NativeImportRoundtripReadinessStatuses: readonly NativeImportRoundtripReadinessStatus[];
785
972
  export declare const NativeImportTaxonomyKinds: readonly NativeImportTaxonomyKind[];
786
973
  export declare const NativeImportLossKinds: readonly NativeImportKnownLossKind[];
974
+ export declare const NativeImportRegionTaxonomyKinds: readonly NativeImportRegionTaxonomyKind[];
787
975
  export declare const NativeImportReadinessBySeverity: Readonly<Record<NativeImportLossSummary['highestSeverity'], SemanticMergeReadiness>>;
788
976
  export declare const NativeImportLanguageProfiles: readonly NativeImportLanguageProfile[];
789
977
  export declare function normalizeCompileTarget(target?: string): FrontierCompileTarget;
@@ -798,6 +986,7 @@ export declare function classifyNativeImportRoundtripReadiness(importResult: Nat
798
986
  export declare function createNativeImportCoverageMatrix(options?: NativeImportCoverageMatrixOptions): NativeImportCoverageMatrix;
799
987
  export declare function createNativeSourcePreservation(options: CreateNativeSourcePreservationOptions): NativeSourcePreservation;
800
988
  export declare function createSemanticImportSidecar(importResult: NativeSourceImportResult | NativeProjectImportResult, options?: SemanticImportSidecarOptions): SemanticImportSidecar;
989
+ export declare function createNativeImportResultContract(importResult: NativeSourceImportResult | NativeProjectImportResult, options?: NativeImportResultContractOptions): NativeImportResultContract;
801
990
  export declare function createEstreeNativeImporterAdapter(options?: JavaScriptNativeImporterAdapterOptions): NativeImporterAdapter;
802
991
  export declare function createBabelNativeImporterAdapter(options?: JavaScriptNativeImporterAdapterOptions): NativeImporterAdapter;
803
992
  export declare function createTypeScriptCompilerNativeImporterAdapter(options?: TypeScriptCompilerNativeImporterAdapterOptions): NativeImporterAdapter;
package/dist/index.js CHANGED
@@ -127,6 +127,17 @@ export const NativeImportReadinessBySeverity = Object.freeze({
127
127
  error: 'blocked'
128
128
  });
129
129
 
130
+ export const NativeImportRegionTaxonomyKinds = Object.freeze([
131
+ 'symbol',
132
+ 'declaration',
133
+ 'import',
134
+ 'body',
135
+ 'call',
136
+ 'type',
137
+ 'effect',
138
+ 'generatedOutput'
139
+ ]);
140
+
130
141
  export const NativeImportLanguageProfiles = Object.freeze([
131
142
  nativeImportLanguageProfile('javascript', {
132
143
  aliases: ['js', 'mjs', 'cjs', 'jsx'],
@@ -583,6 +594,7 @@ export function createSemanticImportSidecar(importResult, options = {}) {
583
594
  const evidence = uniqueRecordsById(imports.flatMap((imported) => imported?.evidence ?? []));
584
595
  const mergeCandidates = imports.flatMap((imported) => imported?.mergeCandidates ?? []);
585
596
  const lossSummary = summarizeNativeImportLosses(losses, { evidence });
597
+ const regionTaxonomy = summarizeSemanticImportRegionTaxonomy(ownershipRegions);
586
598
  const readiness = mergeCandidates.reduce(
587
599
  (current, candidate) => maxSemanticMergeReadiness(current, candidate.readiness),
588
600
  lossSummary.semanticMergeReadiness
@@ -619,6 +631,7 @@ export function createSemanticImportSidecar(importResult, options = {}) {
619
631
  blockingLossIds: lossSummary.blockingLossIds,
620
632
  reviewLossIds: lossSummary.reviewLossIds
621
633
  },
634
+ regionTaxonomy,
622
635
  evidence: {
623
636
  total: evidence.length,
624
637
  failed: evidence.filter((record) => record.status === 'failed').map((record) => record.id),
@@ -628,6 +641,7 @@ export function createSemanticImportSidecar(importResult, options = {}) {
628
641
  imports: imports.length,
629
642
  symbols: symbols.length,
630
643
  ownershipRegions: ownershipRegions.length,
644
+ regionKinds: regionTaxonomy.presentKinds.length,
631
645
  sourceMapMappings: sourceMapMappings.length,
632
646
  readiness,
633
647
  emptySemanticIndex: symbols.length === 0
@@ -639,6 +653,83 @@ export function createSemanticImportSidecar(importResult, options = {}) {
639
653
  };
640
654
  }
641
655
 
656
+ export function createNativeImportResultContract(importResult, options = {}) {
657
+ if (!importResult || typeof importResult !== 'object') {
658
+ throw new Error('createNativeImportResultContract requires a native import result');
659
+ }
660
+ const imports = nativeImportEntries(importResult);
661
+ const evidence = uniqueByEvidenceId([
662
+ ...(importResult.evidence ?? []),
663
+ ...imports.flatMap((imported) => imported?.evidence ?? [])
664
+ ]);
665
+ const losses = uniqueByLossId([
666
+ ...(importResult.losses ?? []),
667
+ ...imports.flatMap((imported) => imported?.losses ?? imported?.nativeAst?.losses ?? [])
668
+ ]);
669
+ const sourceMaps = collectImportSourceMaps(importResult, imports);
670
+ const regionSummary = summarizeImportRegions(importResult, imports, options);
671
+ const sourceMapSummary = summarizeImportSourceMaps(sourceMaps);
672
+ const sourcePreservation = summarizeImportSourcePreservation(importResult, imports);
673
+ const adapterCoverage = summarizeImportAdapterCoverage(importResult, imports);
674
+ const primary = imports[0] ?? importResult;
675
+ const nativeSource = importResult.nativeSource ?? importResult.nativeSources?.[0] ?? primary?.nativeSource;
676
+ const nativeAst = importResult.nativeAst ?? nativeSource?.ast ?? primary?.nativeAst ?? primary?.nativeSource?.ast;
677
+ const semanticIndex = importResult.semanticIndex ?? importResult.universalAst?.semanticIndex ?? primary?.semanticIndex ?? primary?.universalAst?.semanticIndex;
678
+ const lossSummary = options.lossSummary ?? importResult.metadata?.nativeImportLossSummary ?? summarizeNativeImportLosses(losses, {
679
+ evidence,
680
+ parser: nativeAst?.parser,
681
+ scanKind: importResult.metadata?.scanKind,
682
+ semanticStatus: importResult.metadata?.semanticStatus ?? importResult.universalAst?.metadata?.semanticStatus
683
+ });
684
+ const mergeCandidates = [
685
+ ...(importResult.mergeCandidates ?? []),
686
+ ...imports.flatMap((imported) => imported?.mergeCandidates ?? [])
687
+ ];
688
+ const readiness = summarizeImportContractReadiness(importResult, mergeCandidates, lossSummary);
689
+ const defaultSidecarId = defaultSemanticImportSidecarId(importResult, imports);
690
+ return {
691
+ kind: 'frontier.lang.nativeImportResultContract',
692
+ version: 1,
693
+ importResultId: importResult.id,
694
+ language: importResult.language ?? (imports.length === 1 ? imports[0]?.language : 'mixed'),
695
+ sourcePath: importResult.sourcePath ?? primary?.sourcePath ?? nativeSource?.sourcePath ?? nativeAst?.sourcePath,
696
+ sourceHash: nativeSource?.sourceHash ?? nativeAst?.sourceHash,
697
+ sourceCount: imports.length,
698
+ sources: imports.map((imported, index) => compactImportContractSource(imported, index)),
699
+ ids: {
700
+ nativeSourceId: nativeSource?.id,
701
+ nativeAstId: nativeAst?.id,
702
+ semanticIndexId: semanticIndex?.id,
703
+ universalAstId: importResult.universalAst?.id ?? primary?.universalAst?.id,
704
+ patchId: importResult.patch?.id,
705
+ sourceMapIds: sourceMapSummary.ids,
706
+ semanticSidecarIds: uniqueStrings([
707
+ ...normalizeStringList(options.semanticSidecarIds ?? options.sidecarIds ?? options.sidecarId),
708
+ defaultSidecarId
709
+ ])
710
+ },
711
+ sourcePreservation,
712
+ adapterCoverage,
713
+ lossSummary,
714
+ regions: regionSummary,
715
+ sourceMaps: sourceMapSummary,
716
+ readiness,
717
+ evidence: {
718
+ total: evidence.length,
719
+ failed: evidence.filter((record) => record?.status === 'failed').map((record) => record.id).filter(Boolean),
720
+ ids: evidence.map((record) => record.id).filter(Boolean)
721
+ },
722
+ metadata: {
723
+ parser: nativeAst?.parser,
724
+ semanticStatus: importResult.metadata?.semanticStatus ?? importResult.universalAst?.metadata?.semanticStatus,
725
+ projectRoot: importResult.projectRoot,
726
+ defaultSemanticSidecarId: defaultSidecarId,
727
+ note: 'Contract summarizes import-result evidence for merge admission; it does not upgrade lightweight scans into exact semantic imports.',
728
+ ...options.metadata
729
+ }
730
+ };
731
+ }
732
+
642
733
  export function createEstreeNativeImporterAdapter(options = {}) {
643
734
  return createJavaScriptSyntaxImporterAdapter({
644
735
  id: 'frontier.estree-native-importer',
@@ -1311,7 +1402,8 @@ function createLightweightNativeImport(input) {
1311
1402
  metadata: {
1312
1403
  ...declaration.metadata,
1313
1404
  ownershipRegionId: ownershipRegion.id,
1314
- ownershipRegionKey: ownershipRegion.key
1405
+ ownershipRegionKey: ownershipRegion.key,
1406
+ ownershipRegionKind: ownershipRegion.regionKind
1315
1407
  }
1316
1408
  };
1317
1409
  if (declaration.symbolId) {
@@ -1327,7 +1419,8 @@ function createLightweightNativeImport(input) {
1327
1419
  definitionSpan: declaration.span,
1328
1420
  metadata: {
1329
1421
  ownershipRegionId: ownershipRegion.id,
1330
- ownershipRegionKey: ownershipRegion.key
1422
+ ownershipRegionKey: ownershipRegion.key,
1423
+ ownershipRegionKind: ownershipRegion.regionKind
1331
1424
  }
1332
1425
  });
1333
1426
  occurrences.push({
@@ -1354,6 +1447,15 @@ function createLightweightNativeImport(input) {
1354
1447
  predicate: 'semanticOwnershipRegion',
1355
1448
  subjectId: declaration.symbolId,
1356
1449
  value: ownershipRegion
1450
+ }, {
1451
+ id: `fact_${idFragment(declaration.nodeId)}_ownership_region_taxonomy`,
1452
+ predicate: 'semanticOwnershipRegionTaxonomy',
1453
+ subjectId: declaration.symbolId,
1454
+ value: {
1455
+ regionKind: ownershipRegion.regionKind,
1456
+ granularity: ownershipRegion.granularity,
1457
+ key: ownershipRegion.key
1458
+ }
1357
1459
  });
1358
1460
  mappings.push({
1359
1461
  id: `map_${idFragment(declaration.nodeId)}`,
@@ -1364,6 +1466,8 @@ function createLightweightNativeImport(input) {
1364
1466
  evidenceIds: [evidenceId],
1365
1467
  lossIds: declaration.loss ? [declaration.loss.id] : [],
1366
1468
  ownershipRegionId: ownershipRegion.id,
1469
+ ownershipRegionKey: ownershipRegion.key,
1470
+ ownershipRegionKind: ownershipRegion.regionKind,
1367
1471
  precision: 'declaration'
1368
1472
  });
1369
1473
  }
@@ -2974,6 +3078,9 @@ function inferSourceMapMappings(input) {
2974
3078
  sourceSpan: occurrence.span ?? nativeNode?.span,
2975
3079
  evidenceIds,
2976
3080
  lossIds: lossIdsForNativeNode(input.losses ?? nativeAst?.losses ?? [], occurrence.nativeAstNodeId),
3081
+ ownershipRegionId: symbol?.metadata?.ownershipRegionId,
3082
+ ownershipRegionKey: symbol?.metadata?.ownershipRegionKey,
3083
+ ownershipRegionKind: symbol?.metadata?.ownershipRegionKind,
2977
3084
  precision: occurrence.span || nativeNode?.span ? 'declaration' : 'unknown'
2978
3085
  };
2979
3086
  });
@@ -3043,6 +3150,9 @@ function normalizeSourceMapMappings(mappings, context) {
3043
3150
  target,
3044
3151
  evidenceIds: normalizeReferenceIds(mapping.evidenceIds, evidenceIds),
3045
3152
  lossIds: normalizeReferenceIds(mapping.lossIds, lossIdsForNativeNode(context.losses ?? nativeAst?.losses ?? [], nativeAstNodeId)),
3153
+ ownershipRegionId: mapping.ownershipRegionId ?? symbol?.metadata?.ownershipRegionId,
3154
+ ownershipRegionKey: mapping.ownershipRegionKey ?? symbol?.metadata?.ownershipRegionKey,
3155
+ ownershipRegionKind: mapping.ownershipRegionKind ?? symbol?.metadata?.ownershipRegionKind,
3046
3156
  precision: normalizeSourceMapPrecision(mapping.precision, sourceSpan, generatedSpan)
3047
3157
  };
3048
3158
  return {
@@ -3385,9 +3495,12 @@ function semanticImportSidecarEntry(imported, index, options) {
3385
3495
  signatureHash: symbol.signatureHash,
3386
3496
  ownershipRegionId: region.id,
3387
3497
  ownershipKey: region.key,
3498
+ ownershipRegionKind: region.regionKind,
3388
3499
  readiness: imported?.metadata?.semanticMergeReadiness ?? imported?.mergeCandidates?.[0]?.readiness ?? 'needs-review'
3389
3500
  });
3390
3501
  }
3502
+ const ownershipRegions = uniqueRecordsById(regions);
3503
+ const regionTaxonomy = summarizeSemanticImportRegionTaxonomy(ownershipRegions);
3391
3504
  return {
3392
3505
  id: imported?.id ?? `import_${index + 1}`,
3393
3506
  language: imported?.language,
@@ -3403,8 +3516,9 @@ function semanticImportSidecarEntry(imported, index, options) {
3403
3516
  sourceMapMappingCount: sourceMapMappings.length,
3404
3517
  readiness: imported?.metadata?.semanticMergeReadiness ?? imported?.mergeCandidates?.[0]?.readiness ?? 'needs-review',
3405
3518
  emptySemanticIndex: symbols.length === 0,
3519
+ regionTaxonomy,
3406
3520
  symbols,
3407
- ownershipRegions: uniqueRecordsById(regions)
3521
+ ownershipRegions
3408
3522
  };
3409
3523
  }
3410
3524
 
@@ -3412,15 +3526,17 @@ function semanticOwnershipRegionForSymbol(imported, symbol, mapping, nativeNode,
3412
3526
  const sourcePath = mapping?.sourceSpan?.path ?? symbol.definitionSpan?.path ?? nativeNode?.span?.path ?? imported?.sourcePath ?? imported?.nativeSource?.sourcePath ?? imported?.nativeAst?.sourcePath;
3413
3527
  const language = symbol.language ?? imported?.language ?? imported?.nativeAst?.language ?? imported?.nativeSource?.language;
3414
3528
  const sourceSpan = mapping?.sourceSpan ?? symbol.definitionSpan ?? nativeNode?.span;
3529
+ const regionKind = semanticRegionKindForSymbol(symbol, mapping, nativeNode);
3415
3530
  const key = [
3416
3531
  options.regionPrefix ?? 'source',
3417
3532
  sourcePath ?? `${language}:memory`,
3418
- symbol.kind ?? 'symbol',
3533
+ regionKind,
3419
3534
  symbol.name ?? symbol.id
3420
3535
  ].map((part) => String(part).replace(/\s+/g, ' ').trim()).join('#');
3421
3536
  return {
3422
3537
  id: `region_${idFragment(key)}`,
3423
3538
  key,
3539
+ regionKind,
3424
3540
  granularity: 'symbol',
3425
3541
  language,
3426
3542
  sourcePath,
@@ -3431,7 +3547,10 @@ function semanticOwnershipRegionForSymbol(imported, symbol, mapping, nativeNode,
3431
3547
  nativeAstNodeId: symbol.nativeAstNodeId ?? nativeNode?.id,
3432
3548
  sourceSpan,
3433
3549
  precision: mapping?.precision ?? (sourceSpan ? 'declaration' : 'unknown'),
3434
- mergePolicy: 'single-writer-review-required'
3550
+ mergePolicy: semanticRegionMergePolicy(regionKind),
3551
+ metadata: {
3552
+ semanticRegionTaxonomy: true
3553
+ }
3435
3554
  };
3436
3555
  }
3437
3556
 
@@ -3439,10 +3558,12 @@ function semanticOwnershipRegionForDeclaration(input, declaration, documentId) {
3439
3558
  const name = declaration.name ?? declaration.importPath ?? declaration.nodeId ?? declaration.nativeNode?.id;
3440
3559
  const kind = declaration.symbolKind ?? declaration.kind ?? declaration.nativeNode?.kind ?? 'symbol';
3441
3560
  const sourcePath = declaration.span?.path ?? declaration.nativeNode?.span?.path ?? input.sourcePath ?? `${input.language}:memory`;
3442
- const key = ['source', sourcePath, kind, name].map((part) => String(part).replace(/\s+/g, ' ').trim()).join('#');
3561
+ const regionKind = semanticRegionKindForDeclaration(declaration);
3562
+ const key = ['source', sourcePath, regionKind, name].map((part) => String(part).replace(/\s+/g, ' ').trim()).join('#');
3443
3563
  return {
3444
3564
  id: `region_${idFragment(key)}`,
3445
3565
  key,
3566
+ regionKind,
3446
3567
  granularity: 'symbol',
3447
3568
  language: input.language,
3448
3569
  documentId,
@@ -3454,7 +3575,10 @@ function semanticOwnershipRegionForDeclaration(input, declaration, documentId) {
3454
3575
  nativeAstNodeId: declaration.nodeId ?? declaration.nativeNode?.id,
3455
3576
  sourceSpan: declaration.span ?? declaration.nativeNode?.span,
3456
3577
  precision: declaration.span || declaration.nativeNode?.span ? 'declaration' : 'unknown',
3457
- mergePolicy: 'single-writer-review-required'
3578
+ mergePolicy: semanticRegionMergePolicy(regionKind),
3579
+ metadata: {
3580
+ semanticRegionTaxonomy: true
3581
+ }
3458
3582
  };
3459
3583
  }
3460
3584
 
@@ -3469,7 +3593,7 @@ function semanticPatchHintForRegion(region, readiness, options = {}) {
3469
3593
  sourceSpan: region.sourceSpan,
3470
3594
  readiness,
3471
3595
  precision: region.precision,
3472
- supportedOperations: ['replace-region', 'insert-before-region', 'insert-after-region'],
3596
+ supportedOperations: semanticRegionSupportedOperations(region),
3473
3597
  projection: {
3474
3598
  sourceLanguage: region.language,
3475
3599
  targetPath: options.targetPath ?? region.sourcePath,
@@ -3478,6 +3602,79 @@ function semanticPatchHintForRegion(region, readiness, options = {}) {
3478
3602
  };
3479
3603
  }
3480
3604
 
3605
+ function semanticRegionKindForDeclaration(declaration) {
3606
+ if (declaration.role === 'import' || declaration.importPath) return 'import';
3607
+ const kind = declaration.symbolKind ?? declaration.kind ?? declaration.nativeNode?.kind;
3608
+ if (semanticKindIsType(kind)) return 'type';
3609
+ if (semanticKindCanOwnBody(kind, declaration.span ?? declaration.nativeNode?.span)) return 'body';
3610
+ return 'declaration';
3611
+ }
3612
+
3613
+ function semanticRegionKindForSymbol(symbol, mapping, nativeNode) {
3614
+ if (mapping?.generatedSpan || mapping?.generatedName || mapping?.target?.emitPath) return 'generatedOutput';
3615
+ if (symbol?.metadata?.ownershipRegionKind) return normalizeNativeImportRegionKind(symbol.metadata.ownershipRegionKind);
3616
+ if (String(symbol?.id ?? '').includes(':import:') || symbol?.metadata?.role === 'import') return 'import';
3617
+ if (semanticKindIsType(symbol?.kind ?? nativeNode?.kind)) return 'type';
3618
+ if (semanticKindCanOwnBody(symbol?.kind ?? nativeNode?.kind, nativeNode?.span ?? symbol?.definitionSpan)) return 'body';
3619
+ return 'declaration';
3620
+ }
3621
+
3622
+ function semanticKindIsType(kind) {
3623
+ return ['type', 'class', 'interface', 'trait', 'protocol', 'struct', 'enum', 'record'].includes(String(kind ?? '').toLowerCase());
3624
+ }
3625
+
3626
+ function semanticKindCanOwnBody(kind, span) {
3627
+ const text = String(kind ?? '').toLowerCase();
3628
+ if (/function|method|class|implementation|module|namespace|package|action|effect|capability/.test(text)) return true;
3629
+ return typeof span?.startLine === 'number' && typeof span?.endLine === 'number' && span.endLine > span.startLine;
3630
+ }
3631
+
3632
+ function semanticRegionMergePolicy(regionKind) {
3633
+ if (regionKind === 'import') return 'module-edge-review-required';
3634
+ if (regionKind === 'body') return 'implementation-single-writer-review-required';
3635
+ if (regionKind === 'call') return 'callsite-overlap-review-required';
3636
+ if (regionKind === 'type') return 'type-surface-review-required';
3637
+ if (regionKind === 'effect') return 'effect-boundary-review-required';
3638
+ if (regionKind === 'generatedOutput') return 'generated-output-source-map-review-required';
3639
+ return 'single-writer-review-required';
3640
+ }
3641
+
3642
+ function semanticRegionSupportedOperations(region) {
3643
+ if (region.regionKind === 'import') return ['replace-import', 'insert-import-before', 'insert-import-after', 'replace-region'];
3644
+ if (region.regionKind === 'body') return ['replace-body', 'insert-before-body', 'insert-after-body'];
3645
+ if (region.regionKind === 'call') return ['replace-callsite', 'review-callsite'];
3646
+ if (region.regionKind === 'type') return ['replace-type-declaration', 'merge-type-members', 'replace-region'];
3647
+ if (region.regionKind === 'effect') return ['route-effect', 'replace-effect-boundary', 'review-effect-policy'];
3648
+ if (region.regionKind === 'generatedOutput') return ['replace-generated-output', 'attach-generated-source-map', 'review-generator-input'];
3649
+ return ['replace-region', 'insert-before-region', 'insert-after-region'];
3650
+ }
3651
+
3652
+ function normalizeNativeImportRegionKind(value) {
3653
+ const text = String(value ?? 'symbol').trim();
3654
+ if (text === 'generated' || text === 'generated-output' || text === 'generated_output') return 'generatedOutput';
3655
+ if (NativeImportRegionTaxonomyKinds.includes(text)) return text;
3656
+ return text || 'symbol';
3657
+ }
3658
+
3659
+ function summarizeSemanticImportRegionTaxonomy(regions) {
3660
+ const byKind = {};
3661
+ const keysByKind = {};
3662
+ const keys = [];
3663
+ for (const region of regions ?? []) {
3664
+ const kind = normalizeNativeImportRegionKind(region.regionKind ?? region.granularity);
3665
+ byKind[kind] = (byKind[kind] ?? 0) + 1;
3666
+ keysByKind[kind] = [...(keysByKind[kind] ?? []), region.key].filter(Boolean);
3667
+ if (region.key) keys.push(region.key);
3668
+ }
3669
+ return {
3670
+ kinds: [...NativeImportRegionTaxonomyKinds],
3671
+ presentKinds: uniqueStrings(Object.keys(byKind)),
3672
+ byKind,
3673
+ keys,
3674
+ keysByKind
3675
+ };
3676
+ }
3677
+
3481
3678
  function nativeImportCoverageReasons(profile) {
3482
3679
  if (!profile.supportsLightweightScan) return ['No built-in scanner coverage profile; host must provide an exact adapter or mark unsupported.'];
3483
3680
  return ['Built-in coverage is declaration-level only; use injected parser adapters for exact AST/CST, tokens, trivia, type resolution, and round-trip evidence.'];
@@ -3590,13 +3787,30 @@ function withNativeImportReadiness(importResult, lossSummary) {
3590
3787
  }
3591
3788
  };
3592
3789
  });
3790
+ const semanticMergeReadiness = mergeCandidates[0]?.readiness ?? lossSummary.semanticMergeReadiness;
3791
+ const contractInput = {
3792
+ ...importResult,
3793
+ mergeCandidates,
3794
+ metadata: {
3795
+ ...importResult.metadata,
3796
+ nativeImportLossSummary: lossSummary,
3797
+ semanticMergeReadiness
3798
+ }
3799
+ };
3800
+ const importResultContract = createNativeImportResultContract(contractInput, { lossSummary });
3593
3801
  return {
3594
3802
  ...importResult,
3595
3803
  mergeCandidates,
3596
3804
  metadata: {
3597
3805
  ...importResult.metadata,
3806
+ importResultContract,
3598
3807
  nativeImportLossSummary: lossSummary,
3599
- semanticMergeReadiness: mergeCandidates[0]?.readiness ?? lossSummary.semanticMergeReadiness,
3808
+ semanticMergeReadiness,
3809
+ readinessReasons: importResultContract.readiness.reasons,
3810
+ sourcePreservationSummary: importResultContract.sourcePreservation,
3811
+ adapterCoverageSummary: importResultContract.adapterCoverage,
3812
+ regionSummary: importResultContract.regions,
3813
+ sourceMapSummary: importResultContract.sourceMaps,
3600
3814
  lossCategories: lossSummary.categories,
3601
3815
  lossSeverityCounts: lossSummary.bySeverity,
3602
3816
  lossKindCounts: lossSummary.byKind
@@ -3647,6 +3861,257 @@ function nativeImportRoundtripReasons(status, input) {
3647
3861
  return ['Native import roundtrip readiness requires review.'];
3648
3862
  }
3649
3863
 
3864
+ function collectImportSourceMaps(importResult, imports) {
3865
+ return uniqueRecordsById([
3866
+ ...(importResult?.sourceMaps ?? importResult?.universalAst?.sourceMaps ?? []),
3867
+ ...imports.flatMap((imported) => imported?.sourceMaps ?? imported?.universalAst?.sourceMaps ?? [])
3868
+ ]);
3869
+ }
3870
+
3871
+ function summarizeImportSourceMaps(sourceMaps) {
3872
+ const mappings = sourceMaps.flatMap((sourceMap) => sourceMap?.mappings ?? []);
3873
+ return {
3874
+ total: sourceMaps.length,
3875
+ ids: sourceMaps.map((sourceMap) => sourceMap.id).filter(Boolean),
3876
+ mappingCount: mappings.length,
3877
+ sourcePaths: uniqueStrings([
3878
+ ...sourceMaps.map((sourceMap) => sourceMap.sourcePath),
3879
+ ...mappings.map((mapping) => mapping.sourceSpan?.path)
3880
+ ].filter(Boolean)),
3881
+ targetPaths: uniqueStrings([
3882
+ ...sourceMaps.map((sourceMap) => sourceMap.targetPath ?? sourceMap.target?.emitPath),
3883
+ ...mappings.map((mapping) => mapping.generatedSpan?.targetPath ?? mapping.target?.emitPath)
3884
+ ].filter(Boolean)),
3885
+ byPrecision: countBy(mappings.map((mapping) => mapping.precision ?? 'unknown')),
3886
+ sourceRangeMappings: mappings.filter((mapping) => mapping.sourceSpan).length,
3887
+ generatedRangeMappings: mappings.filter((mapping) => mapping.generatedSpan).length
3888
+ };
3889
+ }
3890
+
3891
+ function summarizeImportRegions(importResult, imports, options = {}) {
3892
+ const entries = imports.map((imported, index) => semanticImportSidecarEntry(imported, index, options));
3893
+ const regions = uniqueRecordsById(entries.flatMap((entry) => entry.ownershipRegions ?? []));
3894
+ const taxonomy = summarizeSemanticImportRegionTaxonomy(regions);
3895
+ return {
3896
+ total: regions.length,
3897
+ ids: regions.map((region) => region.id),
3898
+ keys: regions.map((region) => region.key),
3899
+ sourcePaths: uniqueStrings(regions.map((region) => region.sourcePath).filter(Boolean)),
3900
+ byKind: taxonomy.byKind,
3901
+ byGranularity: countBy(regions.map((region) => region.granularity ?? 'unknown')),
3902
+ byPrecision: countBy(regions.map((region) => region.precision ?? 'unknown')),
3903
+ byLanguage: countBy(regions.map((region) => region.language ?? importResult?.language ?? 'unknown')),
3904
+ symbolIds: uniqueStrings(regions.map((region) => region.symbolId).filter(Boolean)),
3905
+ taxonomy
3906
+ };
3907
+ }
3908
+
3909
+ function summarizeImportSourcePreservation(importResult, imports) {
3910
+ const records = uniqueSourcePreservationRecords([
3911
+ ...collectSourcePreservationFromImport(importResult),
3912
+ ...imports.flatMap((imported) => collectSourcePreservationFromImport(imported))
3913
+ ]);
3914
+ const compactRecords = records.map(compactSourcePreservationRecord);
3915
+ return {
3916
+ total: compactRecords.length,
3917
+ ids: compactRecords.map((record) => record.id).filter(Boolean),
3918
+ sourcePaths: uniqueStrings(compactRecords.map((record) => record.sourcePath).filter(Boolean)),
3919
+ sourceHashes: uniqueStrings(compactRecords.map((record) => record.sourceHash).filter(Boolean)),
3920
+ exactSourceAvailable: compactRecords.filter((record) => record.exactSourceAvailable).length,
3921
+ sourceBytes: compactRecords.reduce((sum, record) => sum + (record.sourceBytes ?? 0), 0),
3922
+ lineCount: compactRecords.reduce((sum, record) => sum + (record.lineCount ?? 0), 0),
3923
+ tokens: compactRecords.reduce((sum, record) => sum + (record.tokens ?? 0), 0),
3924
+ trivia: compactRecords.reduce((sum, record) => sum + (record.trivia ?? 0), 0),
3925
+ directives: compactRecords.reduce((sum, record) => sum + (record.directives ?? 0), 0),
3926
+ comments: compactRecords.reduce((sum, record) => sum + (record.comments ?? 0), 0),
3927
+ whitespace: compactRecords.reduce((sum, record) => sum + (record.whitespace ?? 0), 0),
3928
+ truncated: compactRecords.some((record) => record.truncated),
3929
+ records: compactRecords
3930
+ };
3931
+ }
3932
+
3933
+ function collectSourcePreservationFromImport(imported) {
3934
+ const nativeAst = imported?.nativeAst ?? imported?.nativeSource?.ast;
3935
+ return [
3936
+ imported?.metadata?.sourcePreservation,
3937
+ imported?.nativeSource?.metadata?.sourcePreservation,
3938
+ nativeAst?.metadata?.sourcePreservation,
3939
+ imported?.universalAst?.metadata?.sourcePreservation,
3940
+ ...(imported?.nativeSources ?? []).map((nativeSource) => nativeSource?.metadata?.sourcePreservation ?? nativeSource?.ast?.metadata?.sourcePreservation)
3941
+ ].filter(Boolean);
3942
+ }
3943
+
3944
+ function uniqueSourcePreservationRecords(records) {
3945
+ const seen = new Set();
3946
+ const result = [];
3947
+ for (const record of records) {
3948
+ const key = record.id ?? `${record.sourcePath ?? 'source'}#${record.sourceHash ?? result.length}`;
3949
+ if (seen.has(key)) continue;
3950
+ seen.add(key);
3951
+ result.push(record);
3952
+ }
3953
+ return result;
3954
+ }
3955
+
3956
+ function compactSourcePreservationRecord(record) {
3957
+ return {
3958
+ id: record.id,
3959
+ language: record.language,
3960
+ sourcePath: record.sourcePath,
3961
+ sourceHash: record.sourceHash,
3962
+ sourceBytes: record.sourceBytes,
3963
+ lineCount: record.lineCount,
3964
+ newline: record.newline,
3965
+ encoding: record.encoding,
3966
+ exactSourceAvailable: record.summary?.exactSourceAvailable === true,
3967
+ tokens: record.summary?.tokens ?? record.tokens?.length ?? 0,
3968
+ trivia: record.summary?.trivia ?? record.trivia?.length ?? 0,
3969
+ directives: record.summary?.directives ?? record.directives?.length ?? 0,
3970
+ comments: record.summary?.comments ?? 0,
3971
+ whitespace: record.summary?.whitespace ?? 0,
3972
+ truncated: record.summary?.truncated === true
3973
+ };
3974
+ }
3975
+
3976
+ function summarizeImportAdapterCoverage(importResult, imports) {
3977
+ const records = uniqueAdapterCoverageRecords([
3978
+ compactAdapterCoverageRecord(importResult),
3979
+ ...imports.map((imported) => compactAdapterCoverageRecord(imported))
3980
+ ].filter(Boolean));
3981
+ const observed = records.reduce((totals, record) => {
3982
+ for (const key of ['diagnostics', 'losses', 'nativeAstNodes', 'semanticSymbols', 'sourceMapMappings']) {
3983
+ totals[key] += record.observed?.[key] ?? 0;
3984
+ }
3985
+ totals.sourceRanges = totals.sourceRanges || record.observed?.sourceRanges === true;
3986
+ totals.generatedRanges = totals.generatedRanges || record.observed?.generatedRanges === true;
3987
+ return totals;
3988
+ }, {
3989
+ diagnostics: 0,
3990
+ losses: 0,
3991
+ nativeAstNodes: 0,
3992
+ semanticSymbols: 0,
3993
+ sourceMapMappings: 0,
3994
+ sourceRanges: false,
3995
+ generatedRanges: false
3996
+ });
3997
+ return {
3998
+ total: records.length,
3999
+ adapterIds: uniqueStrings(records.map((record) => record.adapterId).filter(Boolean)),
4000
+ parsers: uniqueStrings(records.map((record) => record.parser).filter(Boolean)),
4001
+ exactness: uniqueStrings(records.map((record) => record.exactness).filter(Boolean)),
4002
+ exactAst: records.filter((record) => record.exactAst).length,
4003
+ tokens: records.filter((record) => record.tokens).length,
4004
+ trivia: records.filter((record) => record.trivia).length,
4005
+ diagnostics: records.filter((record) => record.diagnostics).length,
4006
+ sourceRanges: records.filter((record) => record.sourceRanges).length,
4007
+ generatedRanges: records.filter((record) => record.generatedRanges).length,
4008
+ semanticCoverageLevels: uniqueStrings(records.map((record) => record.semanticCoverage?.level).filter(Boolean)),
4009
+ observed,
4010
+ records
4011
+ };
4012
+ }
4013
+
4014
+ function compactAdapterCoverageRecord(imported) {
4015
+ const nativeAst = imported?.nativeAst ?? imported?.nativeSource?.ast;
4016
+ const nativeSource = imported?.nativeSource;
4017
+ const coverage = imported?.adapter?.coverage
4018
+ ?? imported?.metadata?.adapterCoverage
4019
+ ?? nativeAst?.metadata?.adapterCoverage
4020
+ ?? nativeSource?.metadata?.adapterCoverage;
4021
+ if (!coverage) return undefined;
4022
+ return {
4023
+ adapterId: imported?.adapter?.id ?? imported?.metadata?.adapterId ?? nativeAst?.metadata?.adapterId ?? nativeSource?.metadata?.adapterId,
4024
+ adapterVersion: imported?.adapter?.version ?? imported?.metadata?.adapterVersion ?? nativeAst?.metadata?.adapterVersion ?? nativeSource?.metadata?.adapterVersion,
4025
+ parser: imported?.adapter?.parser ?? nativeAst?.parser ?? nativeSource?.parser ?? imported?.metadata?.parser,
4026
+ capabilities: uniqueStrings(imported?.adapter?.capabilities ?? imported?.metadata?.adapterCapabilities ?? []),
4027
+ supportedExtensions: uniqueStrings(imported?.adapter?.supportedExtensions ?? imported?.metadata?.supportedExtensions ?? []),
4028
+ exactness: coverage.exactness,
4029
+ exactAst: Boolean(coverage.exactAst),
4030
+ tokens: Boolean(coverage.tokens),
4031
+ trivia: Boolean(coverage.trivia),
4032
+ diagnostics: Boolean(coverage.diagnostics),
4033
+ sourceRanges: Boolean(coverage.sourceRanges),
4034
+ generatedRanges: Boolean(coverage.generatedRanges),
4035
+ semanticCoverage: coverage.semanticCoverage,
4036
+ observed: coverage.observed,
4037
+ notes: uniqueStrings(coverage.notes ?? [])
4038
+ };
4039
+ }
4040
+
4041
+ function uniqueAdapterCoverageRecords(records) {
4042
+ const seen = new Set();
4043
+ const result = [];
4044
+ for (const record of records) {
4045
+ const key = [record.adapterId, record.adapterVersion, record.parser, record.exactness].join('#');
4046
+ if (seen.has(key)) continue;
4047
+ seen.add(key);
4048
+ result.push(record);
4049
+ }
4050
+ return result;
4051
+ }
4052
+
4053
+ function compactImportContractSource(imported, index) {
4054
+ const nativeAst = imported?.nativeAst ?? imported?.nativeSource?.ast;
4055
+ const nativeSource = imported?.nativeSource;
4056
+ const semanticIndex = imported?.semanticIndex ?? imported?.universalAst?.semanticIndex;
4057
+ const sourceMaps = collectImportSourceMaps(imported, [imported].filter(Boolean));
4058
+ return {
4059
+ id: imported?.id ?? `import_${index + 1}`,
4060
+ language: imported?.language ?? nativeSource?.language ?? nativeAst?.language,
4061
+ sourcePath: imported?.sourcePath ?? nativeSource?.sourcePath ?? nativeAst?.sourcePath,
4062
+ sourceHash: nativeSource?.sourceHash ?? nativeAst?.sourceHash,
4063
+ parser: nativeAst?.parser ?? nativeSource?.parser,
4064
+ nativeSourceId: nativeSource?.id,
4065
+ nativeAstId: nativeAst?.id,
4066
+ semanticIndexId: semanticIndex?.id,
4067
+ universalAstId: imported?.universalAst?.id,
4068
+ patchId: imported?.patch?.id,
4069
+ sourceMapIds: sourceMaps.map((sourceMap) => sourceMap.id).filter(Boolean),
4070
+ sourceMapMappings: sourceMaps.reduce((sum, sourceMap) => sum + (sourceMap.mappings?.length ?? 0), 0),
4071
+ symbolCount: semanticIndex?.symbols?.length ?? 0,
4072
+ lossCount: imported?.losses?.length ?? nativeAst?.losses?.length ?? 0,
4073
+ evidenceCount: imported?.evidence?.length ?? 0,
4074
+ readiness: imported?.metadata?.semanticMergeReadiness ?? imported?.mergeCandidates?.[0]?.readiness
4075
+ };
4076
+ }
4077
+
4078
+ function summarizeImportContractReadiness(importResult, mergeCandidates, lossSummary) {
4079
+ const candidateReadiness = mergeCandidates.reduce(
4080
+ (current, candidate) => maxSemanticMergeReadiness(current, candidate.readiness),
4081
+ lossSummary.semanticMergeReadiness
4082
+ );
4083
+ const semanticMergeReadiness = maxSemanticMergeReadiness(
4084
+ importResult?.metadata?.semanticMergeReadiness ?? lossSummary.semanticMergeReadiness,
4085
+ candidateReadiness
4086
+ );
4087
+ return {
4088
+ semanticMergeReadiness,
4089
+ severityReadiness: lossSummary.semanticMergeReadiness,
4090
+ reasons: uniqueStrings([
4091
+ ...(lossSummary.readinessReasons ?? []),
4092
+ ...mergeCandidates.flatMap((candidate) => candidate?.reasons ?? []),
4093
+ ...normalizeStringList(importResult?.metadata?.readinessReasons)
4094
+ ]),
4095
+ failedEvidenceIds: lossSummary.failedEvidenceIds,
4096
+ blockingLossIds: lossSummary.blockingLossIds,
4097
+ reviewLossIds: lossSummary.reviewLossIds,
4098
+ informationalLossIds: lossSummary.informationalLossIds
4099
+ };
4100
+ }
4101
+
4102
+ function defaultSemanticImportSidecarId(importResult, imports = []) {
4103
+ return `semantic_import_${idFragment(importResult?.id ?? importResult?.projectRoot ?? imports[0]?.sourcePath ?? imports[0]?.language ?? 'source')}`;
4104
+ }
4105
+
4106
+ function countBy(values) {
4107
+ const counts = {};
4108
+ for (const value of values ?? []) {
4109
+ const key = String(value ?? 'unknown');
4110
+ counts[key] = (counts[key] ?? 0) + 1;
4111
+ }
4112
+ return counts;
4113
+ }
4114
+
3650
4115
  function maxSemanticMergeReadiness(left, right) {
3651
4116
  const leftRank = semanticMergeReadinessRank[left] ?? semanticMergeReadinessRank['needs-review'];
3652
4117
  const rightRank = semanticMergeReadinessRank[right] ?? semanticMergeReadinessRank['needs-review'];
@@ -4042,7 +4507,8 @@ function semanticIndexFromNativeDeclarations(declarations, input, options) {
4042
4507
  declaration.nativeNode.metadata = {
4043
4508
  ...declaration.nativeNode.metadata,
4044
4509
  ownershipRegionId: ownershipRegion.id,
4045
- ownershipRegionKey: ownershipRegion.key
4510
+ ownershipRegionKey: ownershipRegion.key,
4511
+ ownershipRegionKind: ownershipRegion.regionKind
4046
4512
  };
4047
4513
  symbols.push({
4048
4514
  id: symbolId,
@@ -4055,7 +4521,8 @@ function semanticIndexFromNativeDeclarations(declarations, input, options) {
4055
4521
  definitionSpan: declaration.nativeNode.span,
4056
4522
  metadata: {
4057
4523
  ownershipRegionId: ownershipRegion.id,
4058
- ownershipRegionKey: ownershipRegion.key
4524
+ ownershipRegionKey: ownershipRegion.key,
4525
+ ownershipRegionKind: ownershipRegion.regionKind
4059
4526
  }
4060
4527
  });
4061
4528
  occurrences.push({
@@ -4082,6 +4549,15 @@ function semanticIndexFromNativeDeclarations(declarations, input, options) {
4082
4549
  predicate: 'semanticOwnershipRegion',
4083
4550
  subjectId: symbolId,
4084
4551
  value: ownershipRegion
4552
+ }, {
4553
+ id: `fact_${idFragment(declaration.nativeNode.id)}_ownership_region_taxonomy`,
4554
+ predicate: 'semanticOwnershipRegionTaxonomy',
4555
+ subjectId: symbolId,
4556
+ value: {
4557
+ regionKind: ownershipRegion.regionKind,
4558
+ granularity: ownershipRegion.granularity,
4559
+ key: ownershipRegion.key
4560
+ }
4085
4561
  });
4086
4562
  mappings.push({
4087
4563
  id: `map_${idFragment(declaration.nativeNode.id)}`,
@@ -4092,6 +4568,8 @@ function semanticIndexFromNativeDeclarations(declarations, input, options) {
4092
4568
  evidenceIds: [evidenceId],
4093
4569
  lossIds: [],
4094
4570
  ownershipRegionId: ownershipRegion.id,
4571
+ ownershipRegionKey: ownershipRegion.key,
4572
+ ownershipRegionKind: ownershipRegion.regionKind,
4095
4573
  precision: declaration.nativeNode.span ? 'declaration' : 'unknown'
4096
4574
  });
4097
4575
  }
@@ -4211,7 +4689,7 @@ function createNativeProjectImportResult(input, imports) {
4211
4689
  sourcePreservationSummary
4212
4690
  }
4213
4691
  });
4214
- return {
4692
+ const projectResult = {
4215
4693
  kind: 'frontier.lang.projectImportResult',
4216
4694
  version: 1,
4217
4695
  id: input.id ?? `project_import_${idPart}`,
@@ -4235,6 +4713,21 @@ function createNativeProjectImportResult(input, imports) {
4235
4713
  ...input.metadata
4236
4714
  }
4237
4715
  };
4716
+ const importResultContract = createNativeImportResultContract(projectResult, {
4717
+ lossSummary: nativeImportLossSummary
4718
+ });
4719
+ return {
4720
+ ...projectResult,
4721
+ metadata: {
4722
+ ...projectResult.metadata,
4723
+ importResultContract,
4724
+ semanticMergeReadiness: importResultContract.readiness.semanticMergeReadiness,
4725
+ readinessReasons: importResultContract.readiness.reasons,
4726
+ regionSummary: importResultContract.regions,
4727
+ sourceMapSummary: importResultContract.sourceMaps,
4728
+ adapterCoverageSummary: importResultContract.adapterCoverage
4729
+ }
4730
+ };
4238
4731
  }
4239
4732
 
4240
4733
  function summarizeProjectSourcePreservation(imports) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshift-labs/frontier-lang-compiler",
3
- "version": "0.2.11",
3
+ "version": "0.2.12",
4
4
  "description": "Compiler facade for Frontier Lang source documents and language projection adapters.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",