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

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.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'],
@@ -482,6 +493,7 @@ export function createNativeImportCoverageMatrix(input = {}) {
482
493
  for (const [kind, count] of Object.entries(entry.imports.lossKinds)) {
483
494
  totals.lossKinds[kind] = (totals.lossKinds[kind] ?? 0) + count;
484
495
  }
496
+ totals.adapterCoverage = mergeNativeImporterAdapterCoverageAggregates(totals.adapterCoverage, entry.adapterCoverage);
485
497
  return totals;
486
498
  }, {
487
499
  languages: 0,
@@ -493,7 +505,8 @@ export function createNativeImportCoverageMatrix(input = {}) {
493
505
  sourceMapMappings: 0,
494
506
  losses: 0,
495
507
  byReadiness: {},
496
- lossKinds: {}
508
+ lossKinds: {},
509
+ adapterCoverage: emptyNativeImporterAdapterCoverageAggregate()
497
510
  });
498
511
  return {
499
512
  kind: 'frontier.lang.nativeImportCoverageMatrix',
@@ -583,6 +596,7 @@ export function createSemanticImportSidecar(importResult, options = {}) {
583
596
  const evidence = uniqueRecordsById(imports.flatMap((imported) => imported?.evidence ?? []));
584
597
  const mergeCandidates = imports.flatMap((imported) => imported?.mergeCandidates ?? []);
585
598
  const lossSummary = summarizeNativeImportLosses(losses, { evidence });
599
+ const regionTaxonomy = summarizeSemanticImportRegionTaxonomy(ownershipRegions);
586
600
  const readiness = mergeCandidates.reduce(
587
601
  (current, candidate) => maxSemanticMergeReadiness(current, candidate.readiness),
588
602
  lossSummary.semanticMergeReadiness
@@ -619,6 +633,7 @@ export function createSemanticImportSidecar(importResult, options = {}) {
619
633
  blockingLossIds: lossSummary.blockingLossIds,
620
634
  reviewLossIds: lossSummary.reviewLossIds
621
635
  },
636
+ regionTaxonomy,
622
637
  evidence: {
623
638
  total: evidence.length,
624
639
  failed: evidence.filter((record) => record.status === 'failed').map((record) => record.id),
@@ -628,6 +643,7 @@ export function createSemanticImportSidecar(importResult, options = {}) {
628
643
  imports: imports.length,
629
644
  symbols: symbols.length,
630
645
  ownershipRegions: ownershipRegions.length,
646
+ regionKinds: regionTaxonomy.presentKinds.length,
631
647
  sourceMapMappings: sourceMapMappings.length,
632
648
  readiness,
633
649
  emptySemanticIndex: symbols.length === 0
@@ -639,6 +655,83 @@ export function createSemanticImportSidecar(importResult, options = {}) {
639
655
  };
640
656
  }
641
657
 
658
+ export function createNativeImportResultContract(importResult, options = {}) {
659
+ if (!importResult || typeof importResult !== 'object') {
660
+ throw new Error('createNativeImportResultContract requires a native import result');
661
+ }
662
+ const imports = nativeImportEntries(importResult);
663
+ const evidence = uniqueByEvidenceId([
664
+ ...(importResult.evidence ?? []),
665
+ ...imports.flatMap((imported) => imported?.evidence ?? [])
666
+ ]);
667
+ const losses = uniqueByLossId([
668
+ ...(importResult.losses ?? []),
669
+ ...imports.flatMap((imported) => imported?.losses ?? imported?.nativeAst?.losses ?? [])
670
+ ]);
671
+ const sourceMaps = collectImportSourceMaps(importResult, imports);
672
+ const regionSummary = summarizeImportRegions(importResult, imports, options);
673
+ const sourceMapSummary = summarizeImportSourceMaps(sourceMaps);
674
+ const sourcePreservation = summarizeImportSourcePreservation(importResult, imports);
675
+ const adapterCoverage = summarizeImportAdapterCoverage(importResult, imports);
676
+ const primary = imports[0] ?? importResult;
677
+ const nativeSource = importResult.nativeSource ?? importResult.nativeSources?.[0] ?? primary?.nativeSource;
678
+ const nativeAst = importResult.nativeAst ?? nativeSource?.ast ?? primary?.nativeAst ?? primary?.nativeSource?.ast;
679
+ const semanticIndex = importResult.semanticIndex ?? importResult.universalAst?.semanticIndex ?? primary?.semanticIndex ?? primary?.universalAst?.semanticIndex;
680
+ const lossSummary = options.lossSummary ?? importResult.metadata?.nativeImportLossSummary ?? summarizeNativeImportLosses(losses, {
681
+ evidence,
682
+ parser: nativeAst?.parser,
683
+ scanKind: importResult.metadata?.scanKind,
684
+ semanticStatus: importResult.metadata?.semanticStatus ?? importResult.universalAst?.metadata?.semanticStatus
685
+ });
686
+ const mergeCandidates = [
687
+ ...(importResult.mergeCandidates ?? []),
688
+ ...imports.flatMap((imported) => imported?.mergeCandidates ?? [])
689
+ ];
690
+ const readiness = summarizeImportContractReadiness(importResult, mergeCandidates, lossSummary);
691
+ const defaultSidecarId = defaultSemanticImportSidecarId(importResult, imports);
692
+ return {
693
+ kind: 'frontier.lang.nativeImportResultContract',
694
+ version: 1,
695
+ importResultId: importResult.id,
696
+ language: importResult.language ?? (imports.length === 1 ? imports[0]?.language : 'mixed'),
697
+ sourcePath: importResult.sourcePath ?? primary?.sourcePath ?? nativeSource?.sourcePath ?? nativeAst?.sourcePath,
698
+ sourceHash: nativeSource?.sourceHash ?? nativeAst?.sourceHash,
699
+ sourceCount: imports.length,
700
+ sources: imports.map((imported, index) => compactImportContractSource(imported, index)),
701
+ ids: {
702
+ nativeSourceId: nativeSource?.id,
703
+ nativeAstId: nativeAst?.id,
704
+ semanticIndexId: semanticIndex?.id,
705
+ universalAstId: importResult.universalAst?.id ?? primary?.universalAst?.id,
706
+ patchId: importResult.patch?.id,
707
+ sourceMapIds: sourceMapSummary.ids,
708
+ semanticSidecarIds: uniqueStrings([
709
+ ...normalizeStringList(options.semanticSidecarIds ?? options.sidecarIds ?? options.sidecarId),
710
+ defaultSidecarId
711
+ ])
712
+ },
713
+ sourcePreservation,
714
+ adapterCoverage,
715
+ lossSummary,
716
+ regions: regionSummary,
717
+ sourceMaps: sourceMapSummary,
718
+ readiness,
719
+ evidence: {
720
+ total: evidence.length,
721
+ failed: evidence.filter((record) => record?.status === 'failed').map((record) => record.id).filter(Boolean),
722
+ ids: evidence.map((record) => record.id).filter(Boolean)
723
+ },
724
+ metadata: {
725
+ parser: nativeAst?.parser,
726
+ semanticStatus: importResult.metadata?.semanticStatus ?? importResult.universalAst?.metadata?.semanticStatus,
727
+ projectRoot: importResult.projectRoot,
728
+ defaultSemanticSidecarId: defaultSidecarId,
729
+ note: 'Contract summarizes import-result evidence for merge admission; it does not upgrade lightweight scans into exact semantic imports.',
730
+ ...options.metadata
731
+ }
732
+ };
733
+ }
734
+
642
735
  export function createEstreeNativeImporterAdapter(options = {}) {
643
736
  return createJavaScriptSyntaxImporterAdapter({
644
737
  id: 'frontier.estree-native-importer',
@@ -1311,7 +1404,8 @@ function createLightweightNativeImport(input) {
1311
1404
  metadata: {
1312
1405
  ...declaration.metadata,
1313
1406
  ownershipRegionId: ownershipRegion.id,
1314
- ownershipRegionKey: ownershipRegion.key
1407
+ ownershipRegionKey: ownershipRegion.key,
1408
+ ownershipRegionKind: ownershipRegion.regionKind
1315
1409
  }
1316
1410
  };
1317
1411
  if (declaration.symbolId) {
@@ -1327,7 +1421,8 @@ function createLightweightNativeImport(input) {
1327
1421
  definitionSpan: declaration.span,
1328
1422
  metadata: {
1329
1423
  ownershipRegionId: ownershipRegion.id,
1330
- ownershipRegionKey: ownershipRegion.key
1424
+ ownershipRegionKey: ownershipRegion.key,
1425
+ ownershipRegionKind: ownershipRegion.regionKind
1331
1426
  }
1332
1427
  });
1333
1428
  occurrences.push({
@@ -1354,6 +1449,15 @@ function createLightweightNativeImport(input) {
1354
1449
  predicate: 'semanticOwnershipRegion',
1355
1450
  subjectId: declaration.symbolId,
1356
1451
  value: ownershipRegion
1452
+ }, {
1453
+ id: `fact_${idFragment(declaration.nodeId)}_ownership_region_taxonomy`,
1454
+ predicate: 'semanticOwnershipRegionTaxonomy',
1455
+ subjectId: declaration.symbolId,
1456
+ value: {
1457
+ regionKind: ownershipRegion.regionKind,
1458
+ granularity: ownershipRegion.granularity,
1459
+ key: ownershipRegion.key
1460
+ }
1357
1461
  });
1358
1462
  mappings.push({
1359
1463
  id: `map_${idFragment(declaration.nodeId)}`,
@@ -1364,6 +1468,8 @@ function createLightweightNativeImport(input) {
1364
1468
  evidenceIds: [evidenceId],
1365
1469
  lossIds: declaration.loss ? [declaration.loss.id] : [],
1366
1470
  ownershipRegionId: ownershipRegion.id,
1471
+ ownershipRegionKey: ownershipRegion.key,
1472
+ ownershipRegionKind: ownershipRegion.regionKind,
1367
1473
  precision: 'declaration'
1368
1474
  });
1369
1475
  }
@@ -2974,6 +3080,9 @@ function inferSourceMapMappings(input) {
2974
3080
  sourceSpan: occurrence.span ?? nativeNode?.span,
2975
3081
  evidenceIds,
2976
3082
  lossIds: lossIdsForNativeNode(input.losses ?? nativeAst?.losses ?? [], occurrence.nativeAstNodeId),
3083
+ ownershipRegionId: symbol?.metadata?.ownershipRegionId,
3084
+ ownershipRegionKey: symbol?.metadata?.ownershipRegionKey,
3085
+ ownershipRegionKind: symbol?.metadata?.ownershipRegionKind,
2977
3086
  precision: occurrence.span || nativeNode?.span ? 'declaration' : 'unknown'
2978
3087
  };
2979
3088
  });
@@ -3043,6 +3152,9 @@ function normalizeSourceMapMappings(mappings, context) {
3043
3152
  target,
3044
3153
  evidenceIds: normalizeReferenceIds(mapping.evidenceIds, evidenceIds),
3045
3154
  lossIds: normalizeReferenceIds(mapping.lossIds, lossIdsForNativeNode(context.losses ?? nativeAst?.losses ?? [], nativeAstNodeId)),
3155
+ ownershipRegionId: mapping.ownershipRegionId ?? symbol?.metadata?.ownershipRegionId,
3156
+ ownershipRegionKey: mapping.ownershipRegionKey ?? symbol?.metadata?.ownershipRegionKey,
3157
+ ownershipRegionKind: mapping.ownershipRegionKind ?? symbol?.metadata?.ownershipRegionKind,
3046
3158
  precision: normalizeSourceMapPrecision(mapping.precision, sourceSpan, generatedSpan)
3047
3159
  };
3048
3160
  return {
@@ -3330,6 +3442,10 @@ function nativeImportCoverageForProfile(profile, imports, adapters) {
3330
3442
  : profile.supportsLightweightScan ? profile.defaultReadiness : 'blocked';
3331
3443
  const importedParsers = uniqueStrings(matchingImports.map((imported) => imported?.nativeAst?.parser ?? imported?.parser ?? imported?.metadata?.parser).filter(Boolean));
3332
3444
  const sourceMaps = matchingImports.flatMap((imported) => imported?.sourceMaps ?? imported?.universalAst?.sourceMaps ?? []);
3445
+ const adapterCoverage = summarizeNativeImporterAdapterCoverageEntries([
3446
+ ...matchingImports.map((imported) => nativeImporterAdapterCoverageEntryFromImport(imported)).filter(Boolean),
3447
+ ...matchingAdapters.map((adapter) => nativeImporterAdapterCoverageEntryFromAdapter(adapter)).filter(Boolean)
3448
+ ]);
3333
3449
  return {
3334
3450
  language: profile.language,
3335
3451
  aliases: profile.aliases,
@@ -3340,6 +3456,7 @@ function nativeImportCoverageForProfile(profile, imports, adapters) {
3340
3456
  knownLossKinds: uniqueStrings([...(profile.knownLossKinds ?? []), ...Object.keys(lossSummary.byKind)]),
3341
3457
  defaultReadiness: profile.defaultReadiness,
3342
3458
  notes: profile.notes,
3459
+ adapterCoverage,
3343
3460
  imports: {
3344
3461
  total: matchingImports.length,
3345
3462
  parsers: importedParsers,
@@ -3355,6 +3472,125 @@ function nativeImportCoverageForProfile(profile, imports, adapters) {
3355
3472
  };
3356
3473
  }
3357
3474
 
3475
+ function nativeImporterAdapterCoverageEntryFromImport(imported) {
3476
+ const coverage = imported?.adapter?.coverage
3477
+ ?? imported?.metadata?.adapterCoverage
3478
+ ?? imported?.nativeAst?.metadata?.adapterCoverage
3479
+ ?? imported?.nativeSource?.metadata?.adapterCoverage;
3480
+ if (!coverage) return undefined;
3481
+ return {
3482
+ adapterId: imported?.adapter?.id ?? imported?.metadata?.adapterId ?? imported?.nativeAst?.metadata?.adapterId,
3483
+ language: imported?.adapter?.language ?? imported?.language ?? imported?.nativeAst?.language,
3484
+ parser: imported?.adapter?.parser ?? imported?.nativeAst?.parser ?? imported?.nativeSource?.parser,
3485
+ coverage
3486
+ };
3487
+ }
3488
+
3489
+ function nativeImporterAdapterCoverageEntryFromAdapter(adapter) {
3490
+ if (!adapter) return undefined;
3491
+ const summary = normalizeNativeImporterAdapter(adapter);
3492
+ return {
3493
+ adapterId: summary.id,
3494
+ language: summary.language,
3495
+ parser: summary.parser,
3496
+ coverage: summary.coverage
3497
+ };
3498
+ }
3499
+
3500
+ function summarizeNativeImporterAdapterCoverageEntries(entries = []) {
3501
+ const aggregate = emptyNativeImporterAdapterCoverageAggregate();
3502
+ for (const entry of entries) {
3503
+ const coverage = normalizeNativeImporterAdapterCoverageForEvidence(entry.coverage);
3504
+ const capabilityEvidence = coverage.capabilityEvidence;
3505
+ const summary = {
3506
+ adapterId: entry.adapterId,
3507
+ language: entry.language,
3508
+ parser: entry.parser,
3509
+ exactness: coverage.exactness,
3510
+ declared: capabilityNamesByBoolean(capabilityEvidence.capabilities, 'declared'),
3511
+ observed: capabilityNamesByBoolean(capabilityEvidence.capabilities, 'observed'),
3512
+ effective: capabilityNamesByBoolean(capabilityEvidence.capabilities, 'effective'),
3513
+ gaps: capabilityEvidence.gaps,
3514
+ declaredOnly: capabilityEvidence.declaredOnly,
3515
+ observedOnly: capabilityEvidence.observedOnly
3516
+ };
3517
+ aggregate.total += 1;
3518
+ aggregate.summaries.push(summary);
3519
+ incrementCoverageCapabilityCounts(aggregate.declared, summary.declared);
3520
+ incrementCoverageCapabilityCounts(aggregate.observed, summary.observed);
3521
+ incrementCoverageCapabilityCounts(aggregate.effective, summary.effective);
3522
+ incrementCoverageCapabilityCounts(aggregate.gaps, summary.gaps);
3523
+ incrementCoverageCapabilityCounts(aggregate.declaredOnly, summary.declaredOnly);
3524
+ incrementCoverageCapabilityCounts(aggregate.observedOnly, summary.observedOnly);
3525
+ }
3526
+ return {
3527
+ ...aggregate,
3528
+ summaries: Object.freeze(aggregate.summaries)
3529
+ };
3530
+ }
3531
+
3532
+ function normalizeNativeImporterAdapterCoverageForEvidence(coverage = {}) {
3533
+ if (coverage.capabilityEvidence) return coverage;
3534
+ const declared = coverage.declared ?? adapterCoverageSnapshotFromSummary(coverage);
3535
+ const observed = normalizeNativeImporterAdapterObservedCoverage(coverage.observed, declared);
3536
+ const effective = effectiveNativeImporterAdapterCoverage(declared, observed);
3537
+ return {
3538
+ ...coverage,
3539
+ ...effective,
3540
+ declared,
3541
+ observed,
3542
+ capabilityEvidence: nativeImporterAdapterCapabilityEvidence(declared, observed, effective)
3543
+ };
3544
+ }
3545
+
3546
+ function emptyNativeImporterAdapterCoverageAggregate() {
3547
+ return {
3548
+ total: 0,
3549
+ declared: {},
3550
+ observed: {},
3551
+ effective: {},
3552
+ gaps: {},
3553
+ declaredOnly: {},
3554
+ observedOnly: {},
3555
+ summaries: []
3556
+ };
3557
+ }
3558
+
3559
+ function mergeNativeImporterAdapterCoverageAggregates(left, right) {
3560
+ const merged = emptyNativeImporterAdapterCoverageAggregate();
3561
+ for (const aggregate of [left, right]) {
3562
+ if (!aggregate) continue;
3563
+ merged.total += aggregate.total ?? 0;
3564
+ incrementCoverageCapabilityCounts(merged.declared, aggregate.declared ?? {});
3565
+ incrementCoverageCapabilityCounts(merged.observed, aggregate.observed ?? {});
3566
+ incrementCoverageCapabilityCounts(merged.effective, aggregate.effective ?? {});
3567
+ incrementCoverageCapabilityCounts(merged.gaps, aggregate.gaps ?? {});
3568
+ incrementCoverageCapabilityCounts(merged.declaredOnly, aggregate.declaredOnly ?? {});
3569
+ incrementCoverageCapabilityCounts(merged.observedOnly, aggregate.observedOnly ?? {});
3570
+ merged.summaries.push(...(aggregate.summaries ?? []));
3571
+ }
3572
+ return {
3573
+ ...merged,
3574
+ summaries: Object.freeze(merged.summaries)
3575
+ };
3576
+ }
3577
+
3578
+ function capabilityNamesByBoolean(rows, property) {
3579
+ return rows.filter((row) => row[property]).map((row) => row.capability);
3580
+ }
3581
+
3582
+ function incrementCoverageCapabilityCounts(target, capabilities) {
3583
+ if (Array.isArray(capabilities)) {
3584
+ for (const capability of capabilities) {
3585
+ target[capability] = (target[capability] ?? 0) + 1;
3586
+ }
3587
+ return;
3588
+ }
3589
+ for (const [capability, count] of Object.entries(capabilities ?? {})) {
3590
+ target[capability] = (target[capability] ?? 0) + count;
3591
+ }
3592
+ }
3593
+
3358
3594
  function semanticImportSidecarEntry(imported, index, options) {
3359
3595
  const semanticIndex = imported?.semanticIndex ?? imported?.universalAst?.semanticIndex;
3360
3596
  const nativeAst = imported?.nativeAst ?? imported?.nativeSource?.ast;
@@ -3385,9 +3621,12 @@ function semanticImportSidecarEntry(imported, index, options) {
3385
3621
  signatureHash: symbol.signatureHash,
3386
3622
  ownershipRegionId: region.id,
3387
3623
  ownershipKey: region.key,
3624
+ ownershipRegionKind: region.regionKind,
3388
3625
  readiness: imported?.metadata?.semanticMergeReadiness ?? imported?.mergeCandidates?.[0]?.readiness ?? 'needs-review'
3389
3626
  });
3390
3627
  }
3628
+ const ownershipRegions = uniqueRecordsById(regions);
3629
+ const regionTaxonomy = summarizeSemanticImportRegionTaxonomy(ownershipRegions);
3391
3630
  return {
3392
3631
  id: imported?.id ?? `import_${index + 1}`,
3393
3632
  language: imported?.language,
@@ -3403,8 +3642,9 @@ function semanticImportSidecarEntry(imported, index, options) {
3403
3642
  sourceMapMappingCount: sourceMapMappings.length,
3404
3643
  readiness: imported?.metadata?.semanticMergeReadiness ?? imported?.mergeCandidates?.[0]?.readiness ?? 'needs-review',
3405
3644
  emptySemanticIndex: symbols.length === 0,
3645
+ regionTaxonomy,
3406
3646
  symbols,
3407
- ownershipRegions: uniqueRecordsById(regions)
3647
+ ownershipRegions
3408
3648
  };
3409
3649
  }
3410
3650
 
@@ -3412,15 +3652,17 @@ function semanticOwnershipRegionForSymbol(imported, symbol, mapping, nativeNode,
3412
3652
  const sourcePath = mapping?.sourceSpan?.path ?? symbol.definitionSpan?.path ?? nativeNode?.span?.path ?? imported?.sourcePath ?? imported?.nativeSource?.sourcePath ?? imported?.nativeAst?.sourcePath;
3413
3653
  const language = symbol.language ?? imported?.language ?? imported?.nativeAst?.language ?? imported?.nativeSource?.language;
3414
3654
  const sourceSpan = mapping?.sourceSpan ?? symbol.definitionSpan ?? nativeNode?.span;
3655
+ const regionKind = semanticRegionKindForSymbol(symbol, mapping, nativeNode);
3415
3656
  const key = [
3416
3657
  options.regionPrefix ?? 'source',
3417
3658
  sourcePath ?? `${language}:memory`,
3418
- symbol.kind ?? 'symbol',
3659
+ regionKind,
3419
3660
  symbol.name ?? symbol.id
3420
3661
  ].map((part) => String(part).replace(/\s+/g, ' ').trim()).join('#');
3421
3662
  return {
3422
3663
  id: `region_${idFragment(key)}`,
3423
3664
  key,
3665
+ regionKind,
3424
3666
  granularity: 'symbol',
3425
3667
  language,
3426
3668
  sourcePath,
@@ -3431,7 +3673,10 @@ function semanticOwnershipRegionForSymbol(imported, symbol, mapping, nativeNode,
3431
3673
  nativeAstNodeId: symbol.nativeAstNodeId ?? nativeNode?.id,
3432
3674
  sourceSpan,
3433
3675
  precision: mapping?.precision ?? (sourceSpan ? 'declaration' : 'unknown'),
3434
- mergePolicy: 'single-writer-review-required'
3676
+ mergePolicy: semanticRegionMergePolicy(regionKind),
3677
+ metadata: {
3678
+ semanticRegionTaxonomy: true
3679
+ }
3435
3680
  };
3436
3681
  }
3437
3682
 
@@ -3439,10 +3684,12 @@ function semanticOwnershipRegionForDeclaration(input, declaration, documentId) {
3439
3684
  const name = declaration.name ?? declaration.importPath ?? declaration.nodeId ?? declaration.nativeNode?.id;
3440
3685
  const kind = declaration.symbolKind ?? declaration.kind ?? declaration.nativeNode?.kind ?? 'symbol';
3441
3686
  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('#');
3687
+ const regionKind = semanticRegionKindForDeclaration(declaration);
3688
+ const key = ['source', sourcePath, regionKind, name].map((part) => String(part).replace(/\s+/g, ' ').trim()).join('#');
3443
3689
  return {
3444
3690
  id: `region_${idFragment(key)}`,
3445
3691
  key,
3692
+ regionKind,
3446
3693
  granularity: 'symbol',
3447
3694
  language: input.language,
3448
3695
  documentId,
@@ -3454,7 +3701,10 @@ function semanticOwnershipRegionForDeclaration(input, declaration, documentId) {
3454
3701
  nativeAstNodeId: declaration.nodeId ?? declaration.nativeNode?.id,
3455
3702
  sourceSpan: declaration.span ?? declaration.nativeNode?.span,
3456
3703
  precision: declaration.span || declaration.nativeNode?.span ? 'declaration' : 'unknown',
3457
- mergePolicy: 'single-writer-review-required'
3704
+ mergePolicy: semanticRegionMergePolicy(regionKind),
3705
+ metadata: {
3706
+ semanticRegionTaxonomy: true
3707
+ }
3458
3708
  };
3459
3709
  }
3460
3710
 
@@ -3469,7 +3719,7 @@ function semanticPatchHintForRegion(region, readiness, options = {}) {
3469
3719
  sourceSpan: region.sourceSpan,
3470
3720
  readiness,
3471
3721
  precision: region.precision,
3472
- supportedOperations: ['replace-region', 'insert-before-region', 'insert-after-region'],
3722
+ supportedOperations: semanticRegionSupportedOperations(region),
3473
3723
  projection: {
3474
3724
  sourceLanguage: region.language,
3475
3725
  targetPath: options.targetPath ?? region.sourcePath,
@@ -3478,6 +3728,79 @@ function semanticPatchHintForRegion(region, readiness, options = {}) {
3478
3728
  };
3479
3729
  }
3480
3730
 
3731
+ function semanticRegionKindForDeclaration(declaration) {
3732
+ if (declaration.role === 'import' || declaration.importPath) return 'import';
3733
+ const kind = declaration.symbolKind ?? declaration.kind ?? declaration.nativeNode?.kind;
3734
+ if (semanticKindIsType(kind)) return 'type';
3735
+ if (semanticKindCanOwnBody(kind, declaration.span ?? declaration.nativeNode?.span)) return 'body';
3736
+ return 'declaration';
3737
+ }
3738
+
3739
+ function semanticRegionKindForSymbol(symbol, mapping, nativeNode) {
3740
+ if (mapping?.generatedSpan || mapping?.generatedName || mapping?.target?.emitPath) return 'generatedOutput';
3741
+ if (symbol?.metadata?.ownershipRegionKind) return normalizeNativeImportRegionKind(symbol.metadata.ownershipRegionKind);
3742
+ if (String(symbol?.id ?? '').includes(':import:') || symbol?.metadata?.role === 'import') return 'import';
3743
+ if (semanticKindIsType(symbol?.kind ?? nativeNode?.kind)) return 'type';
3744
+ if (semanticKindCanOwnBody(symbol?.kind ?? nativeNode?.kind, nativeNode?.span ?? symbol?.definitionSpan)) return 'body';
3745
+ return 'declaration';
3746
+ }
3747
+
3748
+ function semanticKindIsType(kind) {
3749
+ return ['type', 'class', 'interface', 'trait', 'protocol', 'struct', 'enum', 'record'].includes(String(kind ?? '').toLowerCase());
3750
+ }
3751
+
3752
+ function semanticKindCanOwnBody(kind, span) {
3753
+ const text = String(kind ?? '').toLowerCase();
3754
+ if (/function|method|class|implementation|module|namespace|package|action|effect|capability/.test(text)) return true;
3755
+ return typeof span?.startLine === 'number' && typeof span?.endLine === 'number' && span.endLine > span.startLine;
3756
+ }
3757
+
3758
+ function semanticRegionMergePolicy(regionKind) {
3759
+ if (regionKind === 'import') return 'module-edge-review-required';
3760
+ if (regionKind === 'body') return 'implementation-single-writer-review-required';
3761
+ if (regionKind === 'call') return 'callsite-overlap-review-required';
3762
+ if (regionKind === 'type') return 'type-surface-review-required';
3763
+ if (regionKind === 'effect') return 'effect-boundary-review-required';
3764
+ if (regionKind === 'generatedOutput') return 'generated-output-source-map-review-required';
3765
+ return 'single-writer-review-required';
3766
+ }
3767
+
3768
+ function semanticRegionSupportedOperations(region) {
3769
+ if (region.regionKind === 'import') return ['replace-import', 'insert-import-before', 'insert-import-after', 'replace-region'];
3770
+ if (region.regionKind === 'body') return ['replace-body', 'insert-before-body', 'insert-after-body'];
3771
+ if (region.regionKind === 'call') return ['replace-callsite', 'review-callsite'];
3772
+ if (region.regionKind === 'type') return ['replace-type-declaration', 'merge-type-members', 'replace-region'];
3773
+ if (region.regionKind === 'effect') return ['route-effect', 'replace-effect-boundary', 'review-effect-policy'];
3774
+ if (region.regionKind === 'generatedOutput') return ['replace-generated-output', 'attach-generated-source-map', 'review-generator-input'];
3775
+ return ['replace-region', 'insert-before-region', 'insert-after-region'];
3776
+ }
3777
+
3778
+ function normalizeNativeImportRegionKind(value) {
3779
+ const text = String(value ?? 'symbol').trim();
3780
+ if (text === 'generated' || text === 'generated-output' || text === 'generated_output') return 'generatedOutput';
3781
+ if (NativeImportRegionTaxonomyKinds.includes(text)) return text;
3782
+ return text || 'symbol';
3783
+ }
3784
+
3785
+ function summarizeSemanticImportRegionTaxonomy(regions) {
3786
+ const byKind = {};
3787
+ const keysByKind = {};
3788
+ const keys = [];
3789
+ for (const region of regions ?? []) {
3790
+ const kind = normalizeNativeImportRegionKind(region.regionKind ?? region.granularity);
3791
+ byKind[kind] = (byKind[kind] ?? 0) + 1;
3792
+ keysByKind[kind] = [...(keysByKind[kind] ?? []), region.key].filter(Boolean);
3793
+ if (region.key) keys.push(region.key);
3794
+ }
3795
+ return {
3796
+ kinds: [...NativeImportRegionTaxonomyKinds],
3797
+ presentKinds: uniqueStrings(Object.keys(byKind)),
3798
+ byKind,
3799
+ keys,
3800
+ keysByKind
3801
+ };
3802
+ }
3803
+
3481
3804
  function nativeImportCoverageReasons(profile) {
3482
3805
  if (!profile.supportsLightweightScan) return ['No built-in scanner coverage profile; host must provide an exact adapter or mark unsupported.'];
3483
3806
  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 +3913,30 @@ function withNativeImportReadiness(importResult, lossSummary) {
3590
3913
  }
3591
3914
  };
3592
3915
  });
3916
+ const semanticMergeReadiness = mergeCandidates[0]?.readiness ?? lossSummary.semanticMergeReadiness;
3917
+ const contractInput = {
3918
+ ...importResult,
3919
+ mergeCandidates,
3920
+ metadata: {
3921
+ ...importResult.metadata,
3922
+ nativeImportLossSummary: lossSummary,
3923
+ semanticMergeReadiness
3924
+ }
3925
+ };
3926
+ const importResultContract = createNativeImportResultContract(contractInput, { lossSummary });
3593
3927
  return {
3594
3928
  ...importResult,
3595
3929
  mergeCandidates,
3596
3930
  metadata: {
3597
3931
  ...importResult.metadata,
3932
+ importResultContract,
3598
3933
  nativeImportLossSummary: lossSummary,
3599
- semanticMergeReadiness: mergeCandidates[0]?.readiness ?? lossSummary.semanticMergeReadiness,
3934
+ semanticMergeReadiness,
3935
+ readinessReasons: importResultContract.readiness.reasons,
3936
+ sourcePreservationSummary: importResultContract.sourcePreservation,
3937
+ adapterCoverageSummary: importResultContract.adapterCoverage,
3938
+ regionSummary: importResultContract.regions,
3939
+ sourceMapSummary: importResultContract.sourceMaps,
3600
3940
  lossCategories: lossSummary.categories,
3601
3941
  lossSeverityCounts: lossSummary.bySeverity,
3602
3942
  lossKindCounts: lossSummary.byKind
@@ -3647,6 +3987,257 @@ function nativeImportRoundtripReasons(status, input) {
3647
3987
  return ['Native import roundtrip readiness requires review.'];
3648
3988
  }
3649
3989
 
3990
+ function collectImportSourceMaps(importResult, imports) {
3991
+ return uniqueRecordsById([
3992
+ ...(importResult?.sourceMaps ?? importResult?.universalAst?.sourceMaps ?? []),
3993
+ ...imports.flatMap((imported) => imported?.sourceMaps ?? imported?.universalAst?.sourceMaps ?? [])
3994
+ ]);
3995
+ }
3996
+
3997
+ function summarizeImportSourceMaps(sourceMaps) {
3998
+ const mappings = sourceMaps.flatMap((sourceMap) => sourceMap?.mappings ?? []);
3999
+ return {
4000
+ total: sourceMaps.length,
4001
+ ids: sourceMaps.map((sourceMap) => sourceMap.id).filter(Boolean),
4002
+ mappingCount: mappings.length,
4003
+ sourcePaths: uniqueStrings([
4004
+ ...sourceMaps.map((sourceMap) => sourceMap.sourcePath),
4005
+ ...mappings.map((mapping) => mapping.sourceSpan?.path)
4006
+ ].filter(Boolean)),
4007
+ targetPaths: uniqueStrings([
4008
+ ...sourceMaps.map((sourceMap) => sourceMap.targetPath ?? sourceMap.target?.emitPath),
4009
+ ...mappings.map((mapping) => mapping.generatedSpan?.targetPath ?? mapping.target?.emitPath)
4010
+ ].filter(Boolean)),
4011
+ byPrecision: countBy(mappings.map((mapping) => mapping.precision ?? 'unknown')),
4012
+ sourceRangeMappings: mappings.filter((mapping) => mapping.sourceSpan).length,
4013
+ generatedRangeMappings: mappings.filter((mapping) => mapping.generatedSpan).length
4014
+ };
4015
+ }
4016
+
4017
+ function summarizeImportRegions(importResult, imports, options = {}) {
4018
+ const entries = imports.map((imported, index) => semanticImportSidecarEntry(imported, index, options));
4019
+ const regions = uniqueRecordsById(entries.flatMap((entry) => entry.ownershipRegions ?? []));
4020
+ const taxonomy = summarizeSemanticImportRegionTaxonomy(regions);
4021
+ return {
4022
+ total: regions.length,
4023
+ ids: regions.map((region) => region.id),
4024
+ keys: regions.map((region) => region.key),
4025
+ sourcePaths: uniqueStrings(regions.map((region) => region.sourcePath).filter(Boolean)),
4026
+ byKind: taxonomy.byKind,
4027
+ byGranularity: countBy(regions.map((region) => region.granularity ?? 'unknown')),
4028
+ byPrecision: countBy(regions.map((region) => region.precision ?? 'unknown')),
4029
+ byLanguage: countBy(regions.map((region) => region.language ?? importResult?.language ?? 'unknown')),
4030
+ symbolIds: uniqueStrings(regions.map((region) => region.symbolId).filter(Boolean)),
4031
+ taxonomy
4032
+ };
4033
+ }
4034
+
4035
+ function summarizeImportSourcePreservation(importResult, imports) {
4036
+ const records = uniqueSourcePreservationRecords([
4037
+ ...collectSourcePreservationFromImport(importResult),
4038
+ ...imports.flatMap((imported) => collectSourcePreservationFromImport(imported))
4039
+ ]);
4040
+ const compactRecords = records.map(compactSourcePreservationRecord);
4041
+ return {
4042
+ total: compactRecords.length,
4043
+ ids: compactRecords.map((record) => record.id).filter(Boolean),
4044
+ sourcePaths: uniqueStrings(compactRecords.map((record) => record.sourcePath).filter(Boolean)),
4045
+ sourceHashes: uniqueStrings(compactRecords.map((record) => record.sourceHash).filter(Boolean)),
4046
+ exactSourceAvailable: compactRecords.filter((record) => record.exactSourceAvailable).length,
4047
+ sourceBytes: compactRecords.reduce((sum, record) => sum + (record.sourceBytes ?? 0), 0),
4048
+ lineCount: compactRecords.reduce((sum, record) => sum + (record.lineCount ?? 0), 0),
4049
+ tokens: compactRecords.reduce((sum, record) => sum + (record.tokens ?? 0), 0),
4050
+ trivia: compactRecords.reduce((sum, record) => sum + (record.trivia ?? 0), 0),
4051
+ directives: compactRecords.reduce((sum, record) => sum + (record.directives ?? 0), 0),
4052
+ comments: compactRecords.reduce((sum, record) => sum + (record.comments ?? 0), 0),
4053
+ whitespace: compactRecords.reduce((sum, record) => sum + (record.whitespace ?? 0), 0),
4054
+ truncated: compactRecords.some((record) => record.truncated),
4055
+ records: compactRecords
4056
+ };
4057
+ }
4058
+
4059
+ function collectSourcePreservationFromImport(imported) {
4060
+ const nativeAst = imported?.nativeAst ?? imported?.nativeSource?.ast;
4061
+ return [
4062
+ imported?.metadata?.sourcePreservation,
4063
+ imported?.nativeSource?.metadata?.sourcePreservation,
4064
+ nativeAst?.metadata?.sourcePreservation,
4065
+ imported?.universalAst?.metadata?.sourcePreservation,
4066
+ ...(imported?.nativeSources ?? []).map((nativeSource) => nativeSource?.metadata?.sourcePreservation ?? nativeSource?.ast?.metadata?.sourcePreservation)
4067
+ ].filter(Boolean);
4068
+ }
4069
+
4070
+ function uniqueSourcePreservationRecords(records) {
4071
+ const seen = new Set();
4072
+ const result = [];
4073
+ for (const record of records) {
4074
+ const key = record.id ?? `${record.sourcePath ?? 'source'}#${record.sourceHash ?? result.length}`;
4075
+ if (seen.has(key)) continue;
4076
+ seen.add(key);
4077
+ result.push(record);
4078
+ }
4079
+ return result;
4080
+ }
4081
+
4082
+ function compactSourcePreservationRecord(record) {
4083
+ return {
4084
+ id: record.id,
4085
+ language: record.language,
4086
+ sourcePath: record.sourcePath,
4087
+ sourceHash: record.sourceHash,
4088
+ sourceBytes: record.sourceBytes,
4089
+ lineCount: record.lineCount,
4090
+ newline: record.newline,
4091
+ encoding: record.encoding,
4092
+ exactSourceAvailable: record.summary?.exactSourceAvailable === true,
4093
+ tokens: record.summary?.tokens ?? record.tokens?.length ?? 0,
4094
+ trivia: record.summary?.trivia ?? record.trivia?.length ?? 0,
4095
+ directives: record.summary?.directives ?? record.directives?.length ?? 0,
4096
+ comments: record.summary?.comments ?? 0,
4097
+ whitespace: record.summary?.whitespace ?? 0,
4098
+ truncated: record.summary?.truncated === true
4099
+ };
4100
+ }
4101
+
4102
+ function summarizeImportAdapterCoverage(importResult, imports) {
4103
+ const records = uniqueAdapterCoverageRecords([
4104
+ compactAdapterCoverageRecord(importResult),
4105
+ ...imports.map((imported) => compactAdapterCoverageRecord(imported))
4106
+ ].filter(Boolean));
4107
+ const observed = records.reduce((totals, record) => {
4108
+ for (const key of ['diagnostics', 'losses', 'nativeAstNodes', 'semanticSymbols', 'sourceMapMappings']) {
4109
+ totals[key] += record.observed?.[key] ?? 0;
4110
+ }
4111
+ totals.sourceRanges = totals.sourceRanges || record.observed?.sourceRanges === true;
4112
+ totals.generatedRanges = totals.generatedRanges || record.observed?.generatedRanges === true;
4113
+ return totals;
4114
+ }, {
4115
+ diagnostics: 0,
4116
+ losses: 0,
4117
+ nativeAstNodes: 0,
4118
+ semanticSymbols: 0,
4119
+ sourceMapMappings: 0,
4120
+ sourceRanges: false,
4121
+ generatedRanges: false
4122
+ });
4123
+ return {
4124
+ total: records.length,
4125
+ adapterIds: uniqueStrings(records.map((record) => record.adapterId).filter(Boolean)),
4126
+ parsers: uniqueStrings(records.map((record) => record.parser).filter(Boolean)),
4127
+ exactness: uniqueStrings(records.map((record) => record.exactness).filter(Boolean)),
4128
+ exactAst: records.filter((record) => record.exactAst).length,
4129
+ tokens: records.filter((record) => record.tokens).length,
4130
+ trivia: records.filter((record) => record.trivia).length,
4131
+ diagnostics: records.filter((record) => record.diagnostics).length,
4132
+ sourceRanges: records.filter((record) => record.sourceRanges).length,
4133
+ generatedRanges: records.filter((record) => record.generatedRanges).length,
4134
+ semanticCoverageLevels: uniqueStrings(records.map((record) => record.semanticCoverage?.level).filter(Boolean)),
4135
+ observed,
4136
+ records
4137
+ };
4138
+ }
4139
+
4140
+ function compactAdapterCoverageRecord(imported) {
4141
+ const nativeAst = imported?.nativeAst ?? imported?.nativeSource?.ast;
4142
+ const nativeSource = imported?.nativeSource;
4143
+ const coverage = imported?.adapter?.coverage
4144
+ ?? imported?.metadata?.adapterCoverage
4145
+ ?? nativeAst?.metadata?.adapterCoverage
4146
+ ?? nativeSource?.metadata?.adapterCoverage;
4147
+ if (!coverage) return undefined;
4148
+ return {
4149
+ adapterId: imported?.adapter?.id ?? imported?.metadata?.adapterId ?? nativeAst?.metadata?.adapterId ?? nativeSource?.metadata?.adapterId,
4150
+ adapterVersion: imported?.adapter?.version ?? imported?.metadata?.adapterVersion ?? nativeAst?.metadata?.adapterVersion ?? nativeSource?.metadata?.adapterVersion,
4151
+ parser: imported?.adapter?.parser ?? nativeAst?.parser ?? nativeSource?.parser ?? imported?.metadata?.parser,
4152
+ capabilities: uniqueStrings(imported?.adapter?.capabilities ?? imported?.metadata?.adapterCapabilities ?? []),
4153
+ supportedExtensions: uniqueStrings(imported?.adapter?.supportedExtensions ?? imported?.metadata?.supportedExtensions ?? []),
4154
+ exactness: coverage.exactness,
4155
+ exactAst: Boolean(coverage.exactAst),
4156
+ tokens: Boolean(coverage.tokens),
4157
+ trivia: Boolean(coverage.trivia),
4158
+ diagnostics: Boolean(coverage.diagnostics),
4159
+ sourceRanges: Boolean(coverage.sourceRanges),
4160
+ generatedRanges: Boolean(coverage.generatedRanges),
4161
+ semanticCoverage: coverage.semanticCoverage,
4162
+ observed: coverage.observed,
4163
+ notes: uniqueStrings(coverage.notes ?? [])
4164
+ };
4165
+ }
4166
+
4167
+ function uniqueAdapterCoverageRecords(records) {
4168
+ const seen = new Set();
4169
+ const result = [];
4170
+ for (const record of records) {
4171
+ const key = [record.adapterId, record.adapterVersion, record.parser, record.exactness].join('#');
4172
+ if (seen.has(key)) continue;
4173
+ seen.add(key);
4174
+ result.push(record);
4175
+ }
4176
+ return result;
4177
+ }
4178
+
4179
+ function compactImportContractSource(imported, index) {
4180
+ const nativeAst = imported?.nativeAst ?? imported?.nativeSource?.ast;
4181
+ const nativeSource = imported?.nativeSource;
4182
+ const semanticIndex = imported?.semanticIndex ?? imported?.universalAst?.semanticIndex;
4183
+ const sourceMaps = collectImportSourceMaps(imported, [imported].filter(Boolean));
4184
+ return {
4185
+ id: imported?.id ?? `import_${index + 1}`,
4186
+ language: imported?.language ?? nativeSource?.language ?? nativeAst?.language,
4187
+ sourcePath: imported?.sourcePath ?? nativeSource?.sourcePath ?? nativeAst?.sourcePath,
4188
+ sourceHash: nativeSource?.sourceHash ?? nativeAst?.sourceHash,
4189
+ parser: nativeAst?.parser ?? nativeSource?.parser,
4190
+ nativeSourceId: nativeSource?.id,
4191
+ nativeAstId: nativeAst?.id,
4192
+ semanticIndexId: semanticIndex?.id,
4193
+ universalAstId: imported?.universalAst?.id,
4194
+ patchId: imported?.patch?.id,
4195
+ sourceMapIds: sourceMaps.map((sourceMap) => sourceMap.id).filter(Boolean),
4196
+ sourceMapMappings: sourceMaps.reduce((sum, sourceMap) => sum + (sourceMap.mappings?.length ?? 0), 0),
4197
+ symbolCount: semanticIndex?.symbols?.length ?? 0,
4198
+ lossCount: imported?.losses?.length ?? nativeAst?.losses?.length ?? 0,
4199
+ evidenceCount: imported?.evidence?.length ?? 0,
4200
+ readiness: imported?.metadata?.semanticMergeReadiness ?? imported?.mergeCandidates?.[0]?.readiness
4201
+ };
4202
+ }
4203
+
4204
+ function summarizeImportContractReadiness(importResult, mergeCandidates, lossSummary) {
4205
+ const candidateReadiness = mergeCandidates.reduce(
4206
+ (current, candidate) => maxSemanticMergeReadiness(current, candidate.readiness),
4207
+ lossSummary.semanticMergeReadiness
4208
+ );
4209
+ const semanticMergeReadiness = maxSemanticMergeReadiness(
4210
+ importResult?.metadata?.semanticMergeReadiness ?? lossSummary.semanticMergeReadiness,
4211
+ candidateReadiness
4212
+ );
4213
+ return {
4214
+ semanticMergeReadiness,
4215
+ severityReadiness: lossSummary.semanticMergeReadiness,
4216
+ reasons: uniqueStrings([
4217
+ ...(lossSummary.readinessReasons ?? []),
4218
+ ...mergeCandidates.flatMap((candidate) => candidate?.reasons ?? []),
4219
+ ...normalizeStringList(importResult?.metadata?.readinessReasons)
4220
+ ]),
4221
+ failedEvidenceIds: lossSummary.failedEvidenceIds,
4222
+ blockingLossIds: lossSummary.blockingLossIds,
4223
+ reviewLossIds: lossSummary.reviewLossIds,
4224
+ informationalLossIds: lossSummary.informationalLossIds
4225
+ };
4226
+ }
4227
+
4228
+ function defaultSemanticImportSidecarId(importResult, imports = []) {
4229
+ return `semantic_import_${idFragment(importResult?.id ?? importResult?.projectRoot ?? imports[0]?.sourcePath ?? imports[0]?.language ?? 'source')}`;
4230
+ }
4231
+
4232
+ function countBy(values) {
4233
+ const counts = {};
4234
+ for (const value of values ?? []) {
4235
+ const key = String(value ?? 'unknown');
4236
+ counts[key] = (counts[key] ?? 0) + 1;
4237
+ }
4238
+ return counts;
4239
+ }
4240
+
3650
4241
  function maxSemanticMergeReadiness(left, right) {
3651
4242
  const leftRank = semanticMergeReadinessRank[left] ?? semanticMergeReadinessRank['needs-review'];
3652
4243
  const rightRank = semanticMergeReadinessRank[right] ?? semanticMergeReadinessRank['needs-review'];
@@ -4042,7 +4633,8 @@ function semanticIndexFromNativeDeclarations(declarations, input, options) {
4042
4633
  declaration.nativeNode.metadata = {
4043
4634
  ...declaration.nativeNode.metadata,
4044
4635
  ownershipRegionId: ownershipRegion.id,
4045
- ownershipRegionKey: ownershipRegion.key
4636
+ ownershipRegionKey: ownershipRegion.key,
4637
+ ownershipRegionKind: ownershipRegion.regionKind
4046
4638
  };
4047
4639
  symbols.push({
4048
4640
  id: symbolId,
@@ -4055,7 +4647,8 @@ function semanticIndexFromNativeDeclarations(declarations, input, options) {
4055
4647
  definitionSpan: declaration.nativeNode.span,
4056
4648
  metadata: {
4057
4649
  ownershipRegionId: ownershipRegion.id,
4058
- ownershipRegionKey: ownershipRegion.key
4650
+ ownershipRegionKey: ownershipRegion.key,
4651
+ ownershipRegionKind: ownershipRegion.regionKind
4059
4652
  }
4060
4653
  });
4061
4654
  occurrences.push({
@@ -4082,6 +4675,15 @@ function semanticIndexFromNativeDeclarations(declarations, input, options) {
4082
4675
  predicate: 'semanticOwnershipRegion',
4083
4676
  subjectId: symbolId,
4084
4677
  value: ownershipRegion
4678
+ }, {
4679
+ id: `fact_${idFragment(declaration.nativeNode.id)}_ownership_region_taxonomy`,
4680
+ predicate: 'semanticOwnershipRegionTaxonomy',
4681
+ subjectId: symbolId,
4682
+ value: {
4683
+ regionKind: ownershipRegion.regionKind,
4684
+ granularity: ownershipRegion.granularity,
4685
+ key: ownershipRegion.key
4686
+ }
4085
4687
  });
4086
4688
  mappings.push({
4087
4689
  id: `map_${idFragment(declaration.nativeNode.id)}`,
@@ -4092,6 +4694,8 @@ function semanticIndexFromNativeDeclarations(declarations, input, options) {
4092
4694
  evidenceIds: [evidenceId],
4093
4695
  lossIds: [],
4094
4696
  ownershipRegionId: ownershipRegion.id,
4697
+ ownershipRegionKey: ownershipRegion.key,
4698
+ ownershipRegionKind: ownershipRegion.regionKind,
4095
4699
  precision: declaration.nativeNode.span ? 'declaration' : 'unknown'
4096
4700
  });
4097
4701
  }
@@ -4211,7 +4815,7 @@ function createNativeProjectImportResult(input, imports) {
4211
4815
  sourcePreservationSummary
4212
4816
  }
4213
4817
  });
4214
- return {
4818
+ const projectResult = {
4215
4819
  kind: 'frontier.lang.projectImportResult',
4216
4820
  version: 1,
4217
4821
  id: input.id ?? `project_import_${idPart}`,
@@ -4235,6 +4839,21 @@ function createNativeProjectImportResult(input, imports) {
4235
4839
  ...input.metadata
4236
4840
  }
4237
4841
  };
4842
+ const importResultContract = createNativeImportResultContract(projectResult, {
4843
+ lossSummary: nativeImportLossSummary
4844
+ });
4845
+ return {
4846
+ ...projectResult,
4847
+ metadata: {
4848
+ ...projectResult.metadata,
4849
+ importResultContract,
4850
+ semanticMergeReadiness: importResultContract.readiness.semanticMergeReadiness,
4851
+ readinessReasons: importResultContract.readiness.reasons,
4852
+ regionSummary: importResultContract.regions,
4853
+ sourceMapSummary: importResultContract.sourceMaps,
4854
+ adapterCoverageSummary: importResultContract.adapterCoverage
4855
+ }
4856
+ };
4238
4857
  }
4239
4858
 
4240
4859
  function summarizeProjectSourcePreservation(imports) {
@@ -4335,7 +4954,7 @@ function normalizeNativeImporterAdapterCoverage(value = {}, context = {}) {
4335
4954
  const sourceRanges = Boolean(value.sourceRanges ?? hasCapability('sourceRanges', 'sourceRange', 'ranges', 'sourceMaps'));
4336
4955
  const generatedRanges = Boolean(value.generatedRanges ?? hasCapability('generatedRanges', 'generatedRange', 'generatedSourceMaps'));
4337
4956
  const diagnostics = Boolean(value.diagnostics ?? hasCapability('diagnostics', 'parserDiagnostics'));
4338
- return Object.freeze({
4957
+ const declared = freezeNativeImporterAdapterCoverageSnapshot({
4339
4958
  exactness: String(value.exactness ?? inferredAdapterExactness(exactAst, capabilities)),
4340
4959
  exactAst,
4341
4960
  tokens: Boolean(value.tokens ?? hasCapability('tokens', 'tokenStream')),
@@ -4347,13 +4966,21 @@ function normalizeNativeImporterAdapterCoverage(value = {}, context = {}) {
4347
4966
  capabilities,
4348
4967
  sourceRanges,
4349
4968
  generatedRanges
4350
- }),
4969
+ })
4970
+ });
4971
+ const observed = normalizeNativeImporterAdapterObservedCoverage(value.observed, declared);
4972
+ const effective = effectiveNativeImporterAdapterCoverage(declared, observed);
4973
+ return Object.freeze({
4974
+ ...effective,
4975
+ declared,
4976
+ observed,
4351
4977
  notes: uniqueStrings(value.notes ?? inferredAdapterCoverageNotes(context, {
4352
4978
  exactAst,
4353
4979
  sourceRanges,
4354
4980
  generatedRanges,
4355
4981
  diagnostics
4356
- }))
4982
+ })),
4983
+ capabilityEvidence: nativeImporterAdapterCapabilityEvidence(declared, observed, effective)
4357
4984
  });
4358
4985
  }
4359
4986
 
@@ -4363,31 +4990,297 @@ function observeNativeImporterAdapterCoverage(coverage, parseResult = {}, contex
4363
4990
  const sourceMapMappings = parseResult.sourceMaps?.flatMap((sourceMap) => sourceMap.mappings ?? []) ?? parseResult.mappings ?? [];
4364
4991
  const semanticIndex = parseResult.semanticIndex;
4365
4992
  const semanticSymbols = semanticIndex?.symbols?.length ?? 0;
4366
- const observedSourceRanges = nodeList.some((node) => Boolean(node?.span)) || sourceMapMappings.some((mapping) => Boolean(mapping?.sourceSpan));
4367
- const observedGeneratedRanges = sourceMapMappings.some((mapping) => Boolean(mapping?.generatedSpan));
4368
- const observedSemanticCoverage = normalizeNativeImporterSemanticCoverage({
4369
- ...coverage.semanticCoverage,
4370
- level: semanticSymbols
4371
- ? maxSemanticCoverageLevel(coverage.semanticCoverage?.level, 'declaration-index')
4372
- : coverage.semanticCoverage?.level,
4373
- declarations: coverage.semanticCoverage?.declarations || semanticSymbols > 0,
4374
- symbols: coverage.semanticCoverage?.symbols || semanticSymbols > 0
4375
- }, {});
4993
+ const declared = coverage.declared ?? adapterCoverageSnapshotFromSummary(coverage);
4994
+ const observed = observeNativeImporterAdapterCoverageDetails(parseResult, context, {
4995
+ declared,
4996
+ nodeList,
4997
+ sourceMapMappings,
4998
+ semanticIndex,
4999
+ semanticSymbols
5000
+ });
5001
+ const effective = effectiveNativeImporterAdapterCoverage(declared, observed);
4376
5002
  return Object.freeze({
4377
5003
  ...coverage,
4378
- diagnostics: coverage.diagnostics || (context.diagnostics?.length ?? 0) > 0,
4379
- sourceRanges: coverage.sourceRanges || observedSourceRanges,
4380
- generatedRanges: coverage.generatedRanges || observedGeneratedRanges,
4381
- semanticCoverage: observedSemanticCoverage,
4382
- observed: {
4383
- diagnostics: context.diagnostics?.length ?? 0,
4384
- losses: context.losses?.length ?? 0,
4385
- nativeAstNodes: nodeList.length,
4386
- semanticSymbols,
4387
- sourceMapMappings: sourceMapMappings.length,
4388
- sourceRanges: observedSourceRanges,
4389
- generatedRanges: observedGeneratedRanges
4390
- }
5004
+ ...effective,
5005
+ declared,
5006
+ observed,
5007
+ capabilityEvidence: nativeImporterAdapterCapabilityEvidence(declared, observed, effective)
5008
+ });
5009
+ }
5010
+
5011
+ function adapterCoverageSnapshotFromSummary(coverage = {}) {
5012
+ return freezeNativeImporterAdapterCoverageSnapshot({
5013
+ exactness: coverage.exactness ?? 'unknown',
5014
+ exactAst: coverage.exactAst,
5015
+ tokens: coverage.tokens,
5016
+ trivia: coverage.trivia,
5017
+ diagnostics: coverage.diagnostics,
5018
+ sourceRanges: coverage.sourceRanges,
5019
+ generatedRanges: coverage.generatedRanges,
5020
+ semanticCoverage: coverage.semanticCoverage
5021
+ });
5022
+ }
5023
+
5024
+ function freezeNativeImporterAdapterCoverageSnapshot(value = {}) {
5025
+ return Object.freeze({
5026
+ exactness: String(value.exactness ?? 'unknown'),
5027
+ exactAst: Boolean(value.exactAst),
5028
+ tokens: Boolean(value.tokens),
5029
+ trivia: Boolean(value.trivia),
5030
+ diagnostics: Boolean(value.diagnostics),
5031
+ sourceRanges: Boolean(value.sourceRanges),
5032
+ generatedRanges: Boolean(value.generatedRanges),
5033
+ semanticCoverage: normalizeNativeImporterSemanticCoverage(value.semanticCoverage, {})
5034
+ });
5035
+ }
5036
+
5037
+ function normalizeNativeImporterAdapterObservedCoverage(value = {}, declared = {}) {
5038
+ const diagnostics = Number(value.diagnostics ?? value.parserDiagnostics ?? 0) || 0;
5039
+ const semanticCoverage = normalizeNativeImporterSemanticCoverage({
5040
+ ...(value.semanticCoverage ?? {}),
5041
+ declarations: value.semanticCoverage?.declarations ?? value.declarations,
5042
+ symbols: value.semanticCoverage?.symbols ?? value.symbols,
5043
+ references: value.semanticCoverage?.references ?? value.references,
5044
+ types: value.semanticCoverage?.types ?? value.types,
5045
+ controlFlow: value.semanticCoverage?.controlFlow ?? value.controlFlow
5046
+ }, {});
5047
+ const nativeAstNodes = Number(value.nativeAstNodes ?? 0) || 0;
5048
+ const exactness = String(value.exactness ?? observedAdapterExactness(declared, nativeAstNodes));
5049
+ return Object.freeze({
5050
+ exactness,
5051
+ exactAst: Boolean(value.exactAst ?? (declared.exactAst && nativeAstNodes > 0)),
5052
+ tokens: Boolean(value.tokens),
5053
+ tokenCount: Number(value.tokenCount ?? 0) || 0,
5054
+ trivia: Boolean(value.trivia),
5055
+ triviaCount: Number(value.triviaCount ?? 0) || 0,
5056
+ diagnostics,
5057
+ parserDiagnostics: diagnostics,
5058
+ diagnosticErrors: Number(value.diagnosticErrors ?? 0) || 0,
5059
+ diagnosticWarnings: Number(value.diagnosticWarnings ?? 0) || 0,
5060
+ diagnosticInfos: Number(value.diagnosticInfos ?? 0) || 0,
5061
+ losses: Number(value.losses ?? 0) || 0,
5062
+ nativeAstNodes,
5063
+ semanticSymbols: Number(value.semanticSymbols ?? 0) || 0,
5064
+ semanticReferences: Number(value.semanticReferences ?? 0) || 0,
5065
+ semanticTypes: Number(value.semanticTypes ?? 0) || 0,
5066
+ semanticControlFlow: Number(value.semanticControlFlow ?? 0) || 0,
5067
+ references: Boolean(value.references ?? semanticCoverage.references),
5068
+ types: Boolean(value.types ?? semanticCoverage.types),
5069
+ controlFlow: Boolean(value.controlFlow ?? semanticCoverage.controlFlow),
5070
+ sourceMapMappings: Number(value.sourceMapMappings ?? 0) || 0,
5071
+ sourceRanges: Boolean(value.sourceRanges),
5072
+ sourceRangeNodes: Number(value.sourceRangeNodes ?? 0) || 0,
5073
+ sourceRangeMappings: Number(value.sourceRangeMappings ?? 0) || 0,
5074
+ generatedRanges: Boolean(value.generatedRanges),
5075
+ generatedRangeMappings: Number(value.generatedRangeMappings ?? 0) || 0,
5076
+ semanticCoverage
5077
+ });
5078
+ }
5079
+
5080
+ function observeNativeImporterAdapterCoverageDetails(parseResult = {}, context = {}, observedContext = {}) {
5081
+ const declared = observedContext.declared ?? {};
5082
+ const nodeList = observedContext.nodeList ?? Object.values(parseResult.nativeAst?.nodes ?? parseResult.nodes ?? {});
5083
+ const sourceMapMappings = observedContext.sourceMapMappings
5084
+ ?? parseResult.sourceMaps?.flatMap((sourceMap) => sourceMap.mappings ?? [])
5085
+ ?? parseResult.mappings
5086
+ ?? [];
5087
+ const semanticIndex = observedContext.semanticIndex ?? parseResult.semanticIndex;
5088
+ const semanticSymbols = observedContext.semanticSymbols ?? semanticIndex?.symbols?.length ?? 0;
5089
+ const diagnostics = context.diagnostics ?? [];
5090
+ const diagnosticErrors = diagnostics.filter((diagnostic) => diagnostic.severity === 'error').length;
5091
+ const diagnosticWarnings = diagnostics.filter((diagnostic) => diagnostic.severity === 'warning').length;
5092
+ const diagnosticInfos = diagnostics.filter((diagnostic) => diagnostic.severity === 'info').length;
5093
+ const sourceRangeNodes = nodeList.filter((node) => Boolean(node?.span)).length;
5094
+ const sourceRangeMappings = sourceMapMappings.filter((mapping) => Boolean(mapping?.sourceSpan)).length;
5095
+ const generatedRangeMappings = sourceMapMappings.filter((mapping) => Boolean(mapping?.generatedSpan)).length;
5096
+ const preservation = adapterCoverageSourcePreservation(parseResult);
5097
+ const tokenCount = preservation?.summary?.tokens ?? preservation?.tokens?.length ?? 0;
5098
+ const triviaCount = preservation?.summary?.trivia ?? preservation?.trivia?.length ?? 0;
5099
+ const semanticEvidence = observeNativeImporterSemanticEvidence(semanticIndex);
5100
+ const semanticCoverage = normalizeNativeImporterSemanticCoverage({
5101
+ level: maxSemanticCoverageLevel(
5102
+ semanticSymbols || semanticEvidence.declarations
5103
+ ? 'declaration-index'
5104
+ : 'native-ast',
5105
+ semanticEvidence.references || semanticEvidence.types || semanticEvidence.controlFlow
5106
+ ? 'semantic-index'
5107
+ : semanticSymbols ? 'declaration-index' : 'native-ast'
5108
+ ),
5109
+ declarations: semanticSymbols > 0 || semanticEvidence.declarations > 0,
5110
+ symbols: semanticSymbols > 0,
5111
+ references: semanticEvidence.references > 0,
5112
+ types: semanticEvidence.types > 0,
5113
+ controlFlow: semanticEvidence.controlFlow > 0
5114
+ }, {});
5115
+ return normalizeNativeImporterAdapterObservedCoverage({
5116
+ exactness: observedAdapterExactness(declared, nodeList.length),
5117
+ exactAst: Boolean(declared.exactAst && nodeList.length > 0),
5118
+ tokens: tokenCount > 0,
5119
+ tokenCount,
5120
+ trivia: triviaCount > 0,
5121
+ triviaCount,
5122
+ diagnostics: diagnostics.length,
5123
+ parserDiagnostics: diagnostics.length,
5124
+ diagnosticErrors,
5125
+ diagnosticWarnings,
5126
+ diagnosticInfos,
5127
+ losses: context.losses?.length ?? 0,
5128
+ nativeAstNodes: nodeList.length,
5129
+ semanticSymbols,
5130
+ semanticReferences: semanticEvidence.references,
5131
+ semanticTypes: semanticEvidence.types,
5132
+ semanticControlFlow: semanticEvidence.controlFlow,
5133
+ references: semanticEvidence.references > 0,
5134
+ types: semanticEvidence.types > 0,
5135
+ controlFlow: semanticEvidence.controlFlow > 0,
5136
+ sourceMapMappings: sourceMapMappings.length,
5137
+ sourceRanges: sourceRangeNodes > 0 || sourceRangeMappings > 0,
5138
+ sourceRangeNodes,
5139
+ sourceRangeMappings,
5140
+ generatedRanges: generatedRangeMappings > 0,
5141
+ generatedRangeMappings,
5142
+ semanticCoverage
5143
+ }, declared);
5144
+ }
5145
+
5146
+ function adapterCoverageSourcePreservation(parseResult = {}) {
5147
+ return parseResult.sourcePreservation
5148
+ ?? parseResult.nativeAst?.metadata?.sourcePreservation
5149
+ ?? parseResult.nativeAstMetadata?.sourcePreservation
5150
+ ?? parseResult.metadata?.sourcePreservation;
5151
+ }
5152
+
5153
+ function observeNativeImporterSemanticEvidence(semanticIndex = {}) {
5154
+ const occurrences = semanticIndex?.occurrences ?? [];
5155
+ const relations = semanticIndex?.relations ?? [];
5156
+ const facts = semanticIndex?.facts ?? [];
5157
+ const symbols = semanticIndex?.symbols ?? [];
5158
+ const referenceRelations = relations.filter((relation) => semanticPredicateMatches(relation?.predicate, ['reference', 'call', 'read', 'write', 'use']));
5159
+ const typeFacts = facts.filter((fact) => semanticPredicateMatches(fact?.predicate, ['type', 'declaredtype', 'inferredtype', 'typeof']));
5160
+ const typedSymbols = symbols.filter((symbol) => Boolean(symbol?.declaredType ?? symbol?.inferredType ?? symbol?.typeId ?? symbol?.valueType));
5161
+ const controlFlowRecords = [
5162
+ ...relations.filter((relation) => semanticPredicateMatches(relation?.predicate, ['controlflow', 'cfg', 'flow'])),
5163
+ ...facts.filter((fact) => semanticPredicateMatches(fact?.predicate, ['controlflow', 'cfg', 'flow']))
5164
+ ];
5165
+ return {
5166
+ declarations: occurrences.filter((occurrence) => occurrence?.role === 'definition' || occurrence?.role === 'declaration').length,
5167
+ references: occurrences.filter((occurrence) => {
5168
+ const role = String(occurrence?.role ?? '').toLowerCase();
5169
+ return role && role !== 'definition' && role !== 'declaration';
5170
+ }).length + referenceRelations.length,
5171
+ types: typeFacts.length + typedSymbols.length,
5172
+ controlFlow: controlFlowRecords.length
5173
+ };
5174
+ }
5175
+
5176
+ function semanticPredicateMatches(value, fragments) {
5177
+ const predicate = String(value ?? '').toLowerCase().replace(/[^a-z0-9]+/g, '');
5178
+ return fragments.some((fragment) => predicate.includes(fragment));
5179
+ }
5180
+
5181
+ function observedAdapterExactness(declared = {}, nativeAstNodes = 0) {
5182
+ if (!nativeAstNodes) return 'unknown';
5183
+ if (declared.exactAst) return declared.exactness ?? 'exact-parser-ast';
5184
+ return 'adapter-reported-native-ast';
5185
+ }
5186
+
5187
+ function effectiveNativeImporterAdapterCoverage(declared, observed) {
5188
+ const semanticCoverage = normalizeNativeImporterSemanticCoverage({
5189
+ level: maxSemanticCoverageLevel(declared.semanticCoverage?.level, observed.semanticCoverage?.level),
5190
+ declarations: declared.semanticCoverage?.declarations || observed.semanticCoverage?.declarations,
5191
+ symbols: declared.semanticCoverage?.symbols || observed.semanticCoverage?.symbols,
5192
+ references: declared.semanticCoverage?.references || observed.semanticCoverage?.references,
5193
+ types: declared.semanticCoverage?.types || observed.semanticCoverage?.types,
5194
+ controlFlow: declared.semanticCoverage?.controlFlow || observed.semanticCoverage?.controlFlow
5195
+ }, {});
5196
+ return freezeNativeImporterAdapterCoverageSnapshot({
5197
+ exactness: effectiveAdapterExactness(declared, observed),
5198
+ exactAst: declared.exactAst || observed.exactAst,
5199
+ tokens: declared.tokens || observed.tokens,
5200
+ trivia: declared.trivia || observed.trivia,
5201
+ diagnostics: declared.diagnostics || observed.parserDiagnostics > 0,
5202
+ sourceRanges: declared.sourceRanges || observed.sourceRanges,
5203
+ generatedRanges: declared.generatedRanges || observed.generatedRanges,
5204
+ semanticCoverage
5205
+ });
5206
+ }
5207
+
5208
+ function effectiveAdapterExactness(declared, observed) {
5209
+ if (declared.exactAst || observed.exactAst) return declared.exactness ?? 'exact-parser-ast';
5210
+ if (observed.nativeAstNodes > 0) return observed.exactness ?? 'adapter-reported-native-ast';
5211
+ return declared.exactness ?? 'unknown';
5212
+ }
5213
+
5214
+ function nativeImporterAdapterCapabilityEvidence(declared, observed, effective) {
5215
+ const capabilityRows = [
5216
+ adapterCoverageCapabilityRow('exactAst', declared.exactAst, observed.exactAst, effective.exactAst, observed.nativeAstNodes),
5217
+ adapterCoverageCapabilityRow('tokens', declared.tokens, observed.tokens, effective.tokens, observed.tokenCount),
5218
+ adapterCoverageCapabilityRow('trivia', declared.trivia, observed.trivia, effective.trivia, observed.triviaCount),
5219
+ adapterCoverageCapabilityRow('parserDiagnostics', declared.diagnostics, observed.parserDiagnostics > 0, effective.diagnostics, observed.parserDiagnostics),
5220
+ adapterCoverageCapabilityRow('sourceRanges', declared.sourceRanges, observed.sourceRanges, effective.sourceRanges, observed.sourceRangeNodes + observed.sourceRangeMappings),
5221
+ adapterCoverageCapabilityRow('generatedRanges', declared.generatedRanges, observed.generatedRanges, effective.generatedRanges, observed.generatedRangeMappings),
5222
+ adapterCoverageCapabilityRow('semanticDeclarations', declared.semanticCoverage.declarations, observed.semanticCoverage.declarations, effective.semanticCoverage.declarations, observed.semanticSymbols),
5223
+ adapterCoverageCapabilityRow('semanticSymbols', declared.semanticCoverage.symbols, observed.semanticCoverage.symbols, effective.semanticCoverage.symbols, observed.semanticSymbols),
5224
+ adapterCoverageCapabilityRow('references', declared.semanticCoverage.references, observed.semanticCoverage.references, effective.semanticCoverage.references, observed.semanticReferences),
5225
+ adapterCoverageCapabilityRow('types', declared.semanticCoverage.types, observed.semanticCoverage.types, effective.semanticCoverage.types, observed.semanticTypes),
5226
+ adapterCoverageCapabilityRow('controlFlow', declared.semanticCoverage.controlFlow, observed.semanticCoverage.controlFlow, effective.semanticCoverage.controlFlow, observed.semanticControlFlow)
5227
+ ];
5228
+ const reviewCapabilities = new Set(['exactAst', 'tokens', 'trivia', 'parserDiagnostics', 'sourceRanges', 'generatedRanges', 'references', 'types', 'controlFlow']);
5229
+ return Object.freeze({
5230
+ declared,
5231
+ observed,
5232
+ effective,
5233
+ capabilities: Object.freeze(capabilityRows),
5234
+ gaps: Object.freeze(capabilityRows.filter((row) => reviewCapabilities.has(row.capability) && !row.effective).map((row) => row.capability)),
5235
+ declaredOnly: Object.freeze(capabilityRows.filter((row) => row.declared && !row.observed).map((row) => row.capability)),
5236
+ observedOnly: Object.freeze(capabilityRows.filter((row) => !row.declared && row.observed).map((row) => row.capability)),
5237
+ parserDiagnostics: Object.freeze({
5238
+ declared: declared.diagnostics,
5239
+ observed: observed.parserDiagnostics > 0,
5240
+ count: observed.parserDiagnostics,
5241
+ errors: observed.diagnosticErrors,
5242
+ warnings: observed.diagnosticWarnings,
5243
+ infos: observed.diagnosticInfos
5244
+ }),
5245
+ sourceRanges: Object.freeze({
5246
+ declared: declared.sourceRanges,
5247
+ observed: observed.sourceRanges,
5248
+ nativeAstNodes: observed.nativeAstNodes,
5249
+ sourceRangeNodes: observed.sourceRangeNodes,
5250
+ sourceMapMappings: observed.sourceMapMappings,
5251
+ sourceRangeMappings: observed.sourceRangeMappings,
5252
+ generatedRangeMappings: observed.generatedRangeMappings
5253
+ }),
5254
+ tokensTrivia: Object.freeze({
5255
+ tokens: Object.freeze({ declared: declared.tokens, observed: observed.tokens, count: observed.tokenCount }),
5256
+ trivia: Object.freeze({ declared: declared.trivia, observed: observed.trivia, count: observed.triviaCount })
5257
+ }),
5258
+ semantic: Object.freeze({
5259
+ level: Object.freeze({
5260
+ declared: declared.semanticCoverage.level,
5261
+ observed: observed.semanticCoverage.level,
5262
+ effective: effective.semanticCoverage.level
5263
+ }),
5264
+ declarations: adapterCoverageCapabilityRow('semanticDeclarations', declared.semanticCoverage.declarations, observed.semanticCoverage.declarations, effective.semanticCoverage.declarations, observed.semanticSymbols),
5265
+ symbols: adapterCoverageCapabilityRow('semanticSymbols', declared.semanticCoverage.symbols, observed.semanticCoverage.symbols, effective.semanticCoverage.symbols, observed.semanticSymbols),
5266
+ references: adapterCoverageCapabilityRow('references', declared.semanticCoverage.references, observed.semanticCoverage.references, effective.semanticCoverage.references, observed.semanticReferences),
5267
+ types: adapterCoverageCapabilityRow('types', declared.semanticCoverage.types, observed.semanticCoverage.types, effective.semanticCoverage.types, observed.semanticTypes),
5268
+ controlFlow: adapterCoverageCapabilityRow('controlFlow', declared.semanticCoverage.controlFlow, observed.semanticCoverage.controlFlow, effective.semanticCoverage.controlFlow, observed.semanticControlFlow)
5269
+ })
5270
+ });
5271
+ }
5272
+
5273
+ function adapterCoverageCapabilityRow(capability, declared, observed, effective, count = 0) {
5274
+ const status = declared && observed
5275
+ ? 'declared-and-observed'
5276
+ : declared ? 'declared-unobserved' : observed ? 'observed-undeclared' : 'absent';
5277
+ return Object.freeze({
5278
+ capability,
5279
+ declared: Boolean(declared),
5280
+ observed: Boolean(observed),
5281
+ effective: Boolean(effective),
5282
+ count: Number(count ?? 0) || 0,
5283
+ status
4391
5284
  });
4392
5285
  }
4393
5286