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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/README.md +13 -0
  2. package/dist/declarations/bidirectional-target-change-source-edit.d.ts +30 -0
  3. package/dist/declarations/bidirectional-target-change.d.ts +10 -0
  4. package/dist/declarations/js-ts-safe-member-merge.d.ts +58 -0
  5. package/dist/declarations/js-ts-safe-merge.d.ts +120 -0
  6. package/dist/declarations/js-ts-semantic-conflict-sidecars.d.ts +235 -0
  7. package/dist/declarations/js-ts-semantic-merge-contracts.d.ts +287 -0
  8. package/dist/declarations/js-ts-semantic-merge.d.ts +4 -0
  9. package/dist/declarations/native-import-losses.d.ts +3 -0
  10. package/dist/declarations/native-project-admission-semantic-evidence.d.ts +34 -0
  11. package/dist/declarations/native-project-admission.d.ts +6 -10
  12. package/dist/declarations/semantic-edit-replay-diagnostics.d.ts +12 -0
  13. package/dist/declarations/semantic-edit-script.d.ts +10 -4
  14. package/dist/declarations/semantic-patch-bundle-index.d.ts +45 -0
  15. package/dist/declarations/semantic-patch-bundle-overlaps.d.ts +1 -0
  16. package/dist/declarations/semantic-patch-bundle.d.ts +6 -4
  17. package/dist/declarations/semantic-sidecar-example.d.ts +18 -0
  18. package/dist/declarations/semantic-transform-identity.d.ts +3 -0
  19. package/dist/declarations/source-preservation.d.ts +72 -0
  20. package/dist/declarations/universal-capability.d.ts +4 -0
  21. package/dist/declarations/universal-conversion-artifacts.d.ts +61 -1
  22. package/dist/declarations/universal-conversion-compact-counts.d.ts +51 -0
  23. package/dist/declarations/universal-conversion-plan.d.ts +6 -1
  24. package/dist/declarations/universal-representation-coverage.d.ts +90 -0
  25. package/dist/index.d.ts +4 -0
  26. package/dist/index.js +3 -0
  27. package/dist/internal/index-impl/bidirectionalExactSourceBackprojection.js +199 -0
  28. package/dist/internal/index-impl/bidirectionalSameLanguageSourceProjection.js +112 -0
  29. package/dist/internal/index-impl/bidirectionalSourceEditProjection.js +319 -0
  30. package/dist/internal/index-impl/bidirectionalSourceEditProjectionArtifacts.js +67 -0
  31. package/dist/internal/index-impl/bidirectionalTargetChangeRecordInternals.js +17 -5
  32. package/dist/internal/index-impl/bidirectionalTargetRoundtripEvidence.js +58 -20
  33. package/dist/internal/index-impl/createBidirectionalTargetChangeRecord.js +60 -7
  34. package/dist/internal/index-impl/createLightweightNativeImport.js +1 -0
  35. package/dist/internal/index-impl/createNativeSourcePreservation.js +28 -2
  36. package/dist/internal/index-impl/createProjectImportAdmissionRecord.js +14 -2
  37. package/dist/internal/index-impl/diffNativeSymbols.js +82 -1
  38. package/dist/internal/index-impl/nativeChangeProjectionSourceMapLinks.js +2 -0
  39. package/dist/internal/index-impl/projectImportAdmissionImportEvidence.js +1 -1
  40. package/dist/internal/index-impl/projectImportAdmissionSemanticWarnings.js +178 -0
  41. package/dist/internal/index-impl/projectImportAdmissionSummaries.js +22 -3
  42. package/dist/internal/index-impl/projectSemanticEditScriptToSource.js +54 -69
  43. package/dist/internal/index-impl/replaySemanticEditLineEndings.js +34 -0
  44. package/dist/internal/index-impl/replaySemanticEditProjection.js +78 -78
  45. package/dist/internal/index-impl/semanticEditBundleAdmission.js +7 -3
  46. package/dist/internal/index-impl/semanticEditBundleIndex.js +47 -1
  47. package/dist/internal/index-impl/semanticEditExplicitSourceReplacement.js +40 -0
  48. package/dist/internal/index-impl/semanticEditImportProjection.js +53 -0
  49. package/dist/internal/index-impl/semanticEditOperationCoverage.js +33 -3
  50. package/dist/internal/index-impl/semanticEditProjectionRecord.js +108 -0
  51. package/dist/internal/index-impl/semanticEditReplayAnchors.js +63 -0
  52. package/dist/internal/index-impl/semanticEditReplayDiagnostics.js +39 -0
  53. package/dist/internal/index-impl/semanticEditReplaySourceReplacement.js +85 -0
  54. package/dist/internal/index-impl/semanticEditScripts.js +4 -0
  55. package/dist/internal/index-impl/semanticEditSourceRanges.js +32 -0
  56. package/dist/internal/index-impl/semanticIndexFromNativeDeclarations.js +1 -0
  57. package/dist/internal/index-impl/semanticPatchBundleAdmission.js +92 -9
  58. package/dist/internal/index-impl/semanticPatchBundleOverlaps.js +33 -16
  59. package/dist/internal/index-impl/semanticPatchBundleRecords.js +16 -0
  60. package/dist/internal/index-impl/semanticPatchBundleSourceRecords.js +2 -0
  61. package/dist/internal/index-impl/semanticSidecarQuality.js +111 -0
  62. package/dist/internal/index-impl/semanticSourceEditDedupe.js +69 -9
  63. package/dist/internal/index-impl/semanticTransformIdentityRecords.js +85 -9
  64. package/dist/js-ts-safe-member-merge-result.js +158 -0
  65. package/dist/js-ts-safe-member-merge.js +202 -0
  66. package/dist/js-ts-safe-merge-analyze.js +279 -0
  67. package/dist/js-ts-safe-merge-constants.js +50 -0
  68. package/dist/js-ts-safe-merge-context.js +118 -0
  69. package/dist/js-ts-safe-merge-ledger-validation.js +92 -0
  70. package/dist/js-ts-safe-merge-ledger.js +85 -0
  71. package/dist/js-ts-safe-merge-parse-declarations.js +210 -0
  72. package/dist/js-ts-safe-merge-parse-statements.js +155 -0
  73. package/dist/js-ts-safe-merge-plan.js +190 -0
  74. package/dist/js-ts-safe-merge.js +175 -0
  75. package/dist/js-ts-semantic-conflict-sidecar-constants.js +77 -0
  76. package/dist/js-ts-semantic-conflict-sidecar-detectors.js +195 -0
  77. package/dist/js-ts-semantic-conflict-sidecar-normalize.js +203 -0
  78. package/dist/js-ts-semantic-conflict-sidecar-utils.js +190 -0
  79. package/dist/js-ts-semantic-conflict-sidecars.js +81 -0
  80. package/dist/js-ts-semantic-merge-contract-helpers.js +128 -0
  81. package/dist/js-ts-semantic-merge-contracts.js +217 -0
  82. package/dist/js-ts-semantic-merge-member-containers.js +100 -0
  83. package/dist/js-ts-semantic-merge-member-keys.js +142 -0
  84. package/dist/js-ts-semantic-merge-member-segments.js +185 -0
  85. package/dist/js-ts-semantic-merge-member-source.js +64 -0
  86. package/dist/js-ts-semantic-merge-member-utils.js +18 -0
  87. package/dist/js-ts-semantic-merge-parse.js +15 -0
  88. package/dist/js-ts-semantic-merge.js +21 -0
  89. package/dist/lightweight-dependency-effects.js +51 -0
  90. package/dist/lightweight-dependency-language.js +12 -1
  91. package/dist/lightweight-dependency-relations.js +14 -27
  92. package/dist/native-region-scanner-core.js +33 -1
  93. package/dist/native-region-scanner-csharp.js +151 -0
  94. package/dist/native-region-scanner-dart.js +91 -0
  95. package/dist/native-region-scanner-dynamic.js +21 -151
  96. package/dist/native-region-scanner-functional.js +40 -13
  97. package/dist/native-region-scanner-java.js +97 -0
  98. package/dist/native-region-scanner-js-class.js +100 -0
  99. package/dist/native-region-scanner-js-helpers.js +28 -86
  100. package/dist/native-region-scanner-js-imports.js +121 -1
  101. package/dist/native-region-scanner-js-nested.js +96 -8
  102. package/dist/native-region-scanner-js-structure.js +27 -0
  103. package/dist/native-region-scanner-js-types.js +99 -0
  104. package/dist/native-region-scanner-js.js +70 -118
  105. package/dist/native-region-scanner-kotlin.js +94 -0
  106. package/dist/native-region-scanner-main.js +15 -181
  107. package/dist/native-region-scanner-php.js +80 -0
  108. package/dist/native-region-scanner-python.js +62 -0
  109. package/dist/native-region-scanner-ruby.js +72 -0
  110. package/dist/native-region-scanner-scala.js +91 -0
  111. package/dist/native-region-scanner-spans.js +74 -0
  112. package/dist/native-region-scanner-swift.js +155 -0
  113. package/dist/native-region-scanner.js +14 -10
  114. package/dist/native-source-ledger-helpers.js +195 -0
  115. package/dist/native-source-ledger.js +306 -0
  116. package/dist/native-source-preservation-scanner.js +4 -0
  117. package/dist/semantic-import-callsite-regions.js +136 -0
  118. package/dist/semantic-import-effect-regions.js +283 -0
  119. package/dist/semantic-import-regions.js +11 -2
  120. package/dist/semantic-import-sidecar-entry.js +16 -2
  121. package/dist/semantic-import-sidecar-types.d.ts +2 -0
  122. package/dist/semantic-sidecar-example.js +68 -0
  123. package/dist/universal-capability-matrix.js +23 -0
  124. package/dist/universal-conversion-artifact-query.js +79 -2
  125. package/dist/universal-conversion-artifact-semantic-edit.js +103 -0
  126. package/dist/universal-conversion-artifact-summary.js +33 -1
  127. package/dist/universal-conversion-artifacts.js +13 -48
  128. package/dist/universal-conversion-plan-scoring.js +21 -1
  129. package/dist/universal-conversion-plan-summary.js +30 -0
  130. package/dist/universal-conversion-plan.js +25 -9
  131. package/dist/universal-conversion-route-metadata.js +96 -0
  132. package/dist/universal-conversion-route-operations.js +7 -0
  133. package/dist/universal-representation-coverage.js +193 -0
  134. package/package.json +1 -1
@@ -10,6 +10,8 @@ import { diffNativeSourceImports } from './diffNativeSourceImports.js';
10
10
  import { normalizeNativeDiffImport } from './normalizeNativeDiffImport.js';
11
11
  import { attachBidirectionalMatchPortability, classifyBidirectionalTargetPortability } from './bidirectionalTargetPortability.js';
12
12
  import { createRoundtripEvidence, createSemanticMergeAdmissionEvidence, summarizeSourceMapBackprojection } from './bidirectionalTargetRoundtripEvidence.js';
13
+ import { createBidirectionalSourceEditProjection } from './bidirectionalSourceEditProjection.js';
14
+ import { createSameLanguageTargetSourceProjection } from './bidirectionalSameLanguageSourceProjection.js';
13
15
  import {
14
16
  anchorsFromSourceSidecar,
15
17
  classifyBidirectionalReadiness,
@@ -86,6 +88,20 @@ export function createBidirectionalTargetChangeRecord(input = {}, options = {})
86
88
  ...array(targetPortability.reasonCodes),
87
89
  ...sourceAnchorMatches.flatMap((match) => match.reasonCodes)
88
90
  ]);
91
+ const sourceMapEditProjection = createBidirectionalSourceEditProjection({
92
+ id,
93
+ source,
94
+ targetChangeSet,
95
+ sourceAnchorMatches,
96
+ targetPortability,
97
+ reasons
98
+ });
99
+ const sourceEditProjection = sourceMapEditProjection.sourceEditScript ? sourceMapEditProjection : createSameLanguageTargetSourceProjection({
100
+ id,
101
+ source,
102
+ targetChangeSet,
103
+ generatedAt: input.generatedAt
104
+ });
89
105
  const evidenceId = input.evidenceId ?? `evidence_${idFragment(id)}_bidirectional_target_change`;
90
106
  const sourcePatchBundleId = input.sourcePatchBundleId ?? `semantic_patch_bundle_${idFragment(id)}_source_port`;
91
107
  const historyRecordId = input.historyRecordId ?? `semantic_history_${idFragment(id)}_target_change`;
@@ -101,7 +117,8 @@ export function createBidirectionalTargetChangeRecord(input = {}, options = {})
101
117
  targetPortability,
102
118
  readiness,
103
119
  reasons,
104
- sourceMapBackprojection
120
+ sourceMapBackprojection,
121
+ sourceEditProjection
105
122
  });
106
123
  const semanticMergeAdmission = createSemanticMergeAdmissionEvidence({
107
124
  id,
@@ -113,7 +130,8 @@ export function createBidirectionalTargetChangeRecord(input = {}, options = {})
113
130
  targetPortability,
114
131
  readiness,
115
132
  reasons,
116
- roundtripEvidence
133
+ roundtripEvidence,
134
+ sourceEditProjection
117
135
  });
118
136
  const bidirectionalEvidence = createBidirectionalEvidence({
119
137
  id,
@@ -131,9 +149,20 @@ export function createBidirectionalTargetChangeRecord(input = {}, options = {})
131
149
  ...bidirectionalEvidence.metadata,
132
150
  roundtripEvidenceId: roundtripEvidence.id,
133
151
  roundtripEvidence,
134
- semanticMergeAdmission
152
+ semanticMergeAdmission,
153
+ sourceEditProjectionId: sourceEditProjection.sourceEditProjection?.id,
154
+ sourceEditReplayId: sourceEditProjection.sourceEditReplay?.id,
155
+ sourceEditScriptId: sourceEditProjection.sourceEditScript?.id,
156
+ sourceProjectionHintId: sourceEditProjection.sourceProjectionHint?.id,
157
+ sourceProjectionHint: sourceEditProjection.sourceProjectionHint
135
158
  }
136
- }];
159
+ }, ...(sourceEditProjection.evidence ?? [])];
160
+ const sourceReplayStatus = sourceEditProjection.sourceEditReplay?.status;
161
+ const sourcePatchAdmission = sourceReplayStatus === 'accepted-clean'
162
+ ? { readiness: 'ready', reasonCodes: ['bidirectional-source-edit-replay-accepted-clean'] }
163
+ : sourceReplayStatus === 'already-applied'
164
+ ? { status: 'admitted', readiness: 'ready', reasonCodes: ['bidirectional-source-edit-replay-already-applied'] }
165
+ : { status: readiness === 'blocked' ? 'blocked' : 'needs-review', readiness };
137
166
  const sourceChangedRegions = sourceAnchorMatches.flatMap((match) => sourceRegionsForMatch(match, readiness));
138
167
  const sourcePatchBundle = createSemanticPatchBundleRecord({
139
168
  id: `${id}_source_port_projection`,
@@ -159,7 +188,10 @@ export function createBidirectionalTargetChangeRecord(input = {}, options = {})
159
188
  id: sourcePatchBundleId,
160
189
  patchId: targetChangeSet.patch?.id,
161
190
  mergeCandidateId: targetChangeSet.mergeCandidate?.id,
162
- admission: { status: readiness === 'blocked' ? 'blocked' : 'needs-review', readiness },
191
+ semanticEditScripts: [sourceEditProjection.sourceEditScript].filter(Boolean),
192
+ semanticEditProjections: [sourceEditProjection.sourceEditProjection].filter(Boolean),
193
+ semanticEditReplays: [sourceEditProjection.sourceEditReplay].filter(Boolean),
194
+ admission: sourcePatchAdmission,
163
195
  metadata: {
164
196
  source: 'createBidirectionalTargetChangeRecord',
165
197
  targetChangeSetId: targetChangeSet.id,
@@ -169,6 +201,11 @@ export function createBidirectionalTargetChangeRecord(input = {}, options = {})
169
201
  sourceMapBackprojection,
170
202
  roundtripEvidenceId: roundtripEvidence.id,
171
203
  semanticMergeAdmission,
204
+ sourceEditScriptId: sourceEditProjection.sourceEditScript?.id,
205
+ sourceEditProjectionId: sourceEditProjection.sourceEditProjection?.id,
206
+ sourceEditReplayId: sourceEditProjection.sourceEditReplay?.id,
207
+ sourceProjectionHintId: sourceEditProjection.sourceProjectionHint?.id,
208
+ sourceProjectionHint: sourceEditProjection.sourceProjectionHint,
172
209
  autoMergeClaim: false,
173
210
  semanticEquivalenceClaim: false
174
211
  }
@@ -191,7 +228,7 @@ export function createBidirectionalTargetChangeRecord(input = {}, options = {})
191
228
  conflictKeys: targetChangeSet.mergeCandidate?.conflictKeys,
192
229
  metadata: { direction: 'target-to-source' }
193
230
  }] : [],
194
- admission: { status: readiness === 'blocked' ? 'blocked' : 'needs-review', readiness, reasonCodes: reasons },
231
+ admission: { status: semanticMergeAdmission.status, readiness: semanticMergeAdmission.readiness, reasonCodes: semanticMergeAdmission.reasonCodes },
195
232
  replayLinks: targetChangeSet.patch ? [{
196
233
  id: `replay_${idFragment(targetChangeSet.patch.id)}`,
197
234
  kind: 'patch',
@@ -205,6 +242,11 @@ export function createBidirectionalTargetChangeRecord(input = {}, options = {})
205
242
  sourceMapBackprojection,
206
243
  roundtripEvidenceId: roundtripEvidence.id,
207
244
  semanticMergeAdmission,
245
+ sourceEditProjectionId: sourceEditProjection.sourceEditProjection?.id,
246
+ sourceEditReplayId: sourceEditProjection.sourceEditReplay?.id,
247
+ sourceEditScriptId: sourceEditProjection.sourceEditScript?.id,
248
+ sourceProjectionHintId: sourceEditProjection.sourceProjectionHint?.id,
249
+ sourceProjectionHint: sourceEditProjection.sourceProjectionHint,
208
250
  autoMergeClaim: false,
209
251
  semanticEquivalenceClaim: false
210
252
  }
@@ -222,6 +264,10 @@ export function createBidirectionalTargetChangeRecord(input = {}, options = {})
222
264
  sourceAnchorMatches,
223
265
  targetPortability,
224
266
  roundtripEvidence,
267
+ sourceEditScript: sourceEditProjection.sourceEditScript,
268
+ sourceEditProjection: sourceEditProjection.sourceEditProjection,
269
+ sourceEditReplay: sourceEditProjection.sourceEditReplay,
270
+ sourceProjectionHint: sourceEditProjection.sourceProjectionHint,
225
271
  sourcePatchBundle,
226
272
  historyRecord,
227
273
  evidence,
@@ -237,6 +283,8 @@ export function createBidirectionalTargetChangeRecord(input = {}, options = {})
237
283
  sourceMapBackedMatches: sourceAnchorMatches.filter((match) => match.sourceMapLinks.length > 0).length,
238
284
  sourceMapLinks: sourceMapBackprojection.sourceMapLinks,
239
285
  sourceMapMappingIds: sourceMapBackprojection.sourceMapMappingIds.length,
286
+ sourceEditScripts: sourceEditProjection.sourceEditScript ? 1 : 0,
287
+ sourceProjectionHints: sourceEditProjection.sourceProjectionHint ? 1 : 0,
240
288
  lineageResolutions: roundtripEvidence.lineageEvidence.lineageResolutionIds.length,
241
289
  targetPortabilityStatus: targetPortability.status,
242
290
  portableTargetRegions: targetPortability.status === 'portable' ? targetPortability.targetChangedRegions : 0,
@@ -246,10 +294,15 @@ export function createBidirectionalTargetChangeRecord(input = {}, options = {})
246
294
  metadata: {
247
295
  autoMergeClaim: false,
248
296
  semanticEquivalenceClaim: false,
249
- reviewRequired: true,
297
+ reviewRequired: sourcePatchBundle.admission.reviewRequired,
250
298
  targetPortability,
251
299
  roundtripEvidenceId: roundtripEvidence.id,
252
300
  semanticMergeAdmission,
301
+ sourceEditScriptId: sourceEditProjection.sourceEditScript?.id,
302
+ sourceEditProjectionId: sourceEditProjection.sourceEditProjection?.id,
303
+ sourceEditReplayId: sourceEditProjection.sourceEditReplay?.id,
304
+ sourceProjectionHintId: sourceEditProjection.sourceProjectionHint?.id,
305
+ sourceProjectionHint: sourceEditProjection.sourceProjectionHint,
253
306
  ...input.metadata
254
307
  }
255
308
  };
@@ -53,6 +53,7 @@ export function createLightweightNativeImport(input) {
53
53
  signatureHash: hashSemanticValue([input.language, declaration.kind, declaration.name, declaration.fields ?? {}]),
54
54
  definitionSpan: declaration.span,
55
55
  metadata: {
56
+ ...declaration.metadata,
56
57
  ownershipRegionId: ownershipRegion.id,
57
58
  ownershipRegionKey: ownershipRegion.key,
58
59
  ownershipRegionKind: ownershipRegion.regionKind
@@ -1,4 +1,13 @@
1
- import{countBy,idFragment,uniqueStrings}from'../../native-import-utils.js';import{detectNewlineStyle,scanPreservedSourceDirectives,scanPreservedSourceTokens}from'../../native-region-scanner.js';import{hashSemanticValue}from'@shapeshift-labs/frontier-lang-kernel';
1
+ import { hashSemanticValue } from '@shapeshift-labs/frontier-lang-kernel';
2
+ import { countBy, idFragment, uniqueStrings } from '../../native-import-utils.js';
3
+ import {
4
+ detectNewlineStyle,
5
+ isJavaScriptTypeScriptSource,
6
+ scanJavaScriptTypeScriptSourceLedger,
7
+ scanPreservedSourceDirectives,
8
+ scanPreservedSourceTokens
9
+ } from '../../native-region-scanner.js';
10
+
2
11
  export function createNativeSourcePreservation(options) {
3
12
  if (!options || typeof options.sourceText !== 'string') {
4
13
  throw new Error('createNativeSourcePreservation requires sourceText');
@@ -26,6 +35,14 @@ export function createNativeSourcePreservation(options) {
26
35
  maxDirectives: options.maxDirectives
27
36
  });
28
37
  const directives = directiveScan.directives;
38
+ const ledger = options.includeSourceLedger === false || !isJavaScriptTypeScriptSource(language, options.sourcePath)
39
+ ? undefined
40
+ : scanJavaScriptTypeScriptSourceLedger(sourceText, {
41
+ language,
42
+ sourcePath: options.sourcePath,
43
+ sourceHash,
44
+ maxLedgerSpans: options.maxLedgerSpans
45
+ });
29
46
  const triviaByKind = countBy(tokensAndTrivia.trivia.map((entry) => entry.kind ?? 'unknown'));
30
47
  const directivesByKind = countBy(directives.map((entry) => entry.kind ?? 'directive'));
31
48
  const directiveKinds = uniqueStrings(directives.map((entry) => entry.kind ?? 'directive'));
@@ -52,23 +69,32 @@ export function createNativeSourcePreservation(options) {
52
69
  tokens: tokensAndTrivia.tokens,
53
70
  trivia: tokensAndTrivia.trivia,
54
71
  directives,
72
+ ...(ledger ? { ledger } : {}),
55
73
  summary: {
56
74
  tokens: tokensAndTrivia.tokens.length,
57
75
  trivia: tokensAndTrivia.trivia.length,
58
76
  directives: directives.length,
59
77
  comments: tokensAndTrivia.trivia.filter((entry) => entry.kind === 'comment').length,
60
78
  whitespace: tokensAndTrivia.trivia.filter((entry) => entry.kind === 'whitespace' || entry.kind === 'newline').length,
79
+ ...(ledger ? {
80
+ ledger: ledger.summary,
81
+ sourceMapComments: ledger.summary.sourceMapComments,
82
+ protectedRegions: ledger.summary.protectedRegions,
83
+ importExportSpans: ledger.summary.importExportSpans,
84
+ braces: ledger.summary.braces
85
+ } : {}),
61
86
  triviaByKind,
62
87
  directivesByKind,
63
88
  directiveKinds,
64
89
  commentSpanIds,
65
90
  directiveSpanIds,
66
91
  exactSourceAvailable: options.includeSourceText !== false,
67
- truncated: tokensAndTrivia.truncated || directiveScan.truncated
92
+ truncated: tokensAndTrivia.truncated || directiveScan.truncated || Boolean(ledger?.summary?.truncated)
68
93
  },
69
94
  metadata: {
70
95
  preservation: 'source-text-token-trivia-directive-evidence',
71
96
  tokenization: 'frontier-lightweight-lexical-scan',
97
+ ...(ledger ? { sourceLedger: 'frontier-lightweight-js-ts-source-ledger' } : {}),
72
98
  ...(declaredSourceHash ? {
73
99
  declaredSourceHash,
74
100
  sourceHashVerified: declaredSourceHash === computedSourceHash
@@ -19,7 +19,7 @@ export function createProjectImportAdmissionRecord(projectResult,options={}){
19
19
  ...(projectResult?.mergeCandidates??[]),
20
20
  ...imports.flatMap((imported)=>imported?.mergeCandidates??[])
21
21
  ]);
22
- const importSummaries=projectAdmissionImports(imports,contract?.sources??[],mergeCandidates);
22
+ const importSummaries=projectAdmissionImports(imports,contract?.sources??[],mergeCandidates,projectResult);
23
23
  const languages=admissionLanguages(importSummaries);
24
24
  const semanticEvidence=admissionSemanticEvidence(projectResult,imports,importSummaries);
25
25
  const sourceStaleness=admissionSourceStaleness(imports,importSummaries,contract);
@@ -42,7 +42,10 @@ export function createProjectImportAdmissionRecord(projectResult,options={}){
42
42
  failedEvidenceIds,
43
43
  blockingLossIds:contract?.readiness?.blockingLossIds??lossSummary?.blockingLossIds??[]
44
44
  });
45
- const priorityReasons=admissionPriorityReasons({readiness,semanticEvidence,sourcePreservation,ownership,mergeCandidateRisk});
45
+ const priorityReasons=uniqueStrings([
46
+ ...admissionPriorityReasons({readiness,semanticEvidence,sourcePreservation,ownership,mergeCandidateRisk}),
47
+ ...semanticAdmissionWarningReasons(semanticEvidence)
48
+ ]);
46
49
  const action=rejectionReasons.length?'reject':priorityReasons.length?'prioritize':'admit';
47
50
  const priority=admissionPriority(action,readiness,sourcePreservation,mergeCandidateRisk);
48
51
  const mergeScore=admissionMergeScore({
@@ -221,6 +224,15 @@ function admissionSourcePreservationWithStaleness(sourcePreservation,sourceStale
221
224
  };
222
225
  }
223
226
 
227
+ function semanticAdmissionWarningReasons(semanticEvidence){
228
+ return (semanticEvidence?.warnings??[]).map((warning)=>{
229
+ const reasonCode=warning.reasonCode??warning.code;
230
+ const sourcePaths=warning.sourcePaths?.length?warning.sourcePaths:warning.sourcePath?[warning.sourcePath]:[];
231
+ const sourceText=sourcePaths.length?` for ${sourcePaths.join(', ')}`:'';
232
+ return `Project import semantic admission warning ${reasonCode}${sourceText}.`;
233
+ });
234
+ }
235
+
224
236
  function sourcePaths(records){
225
237
  return uniqueStrings(records.map((record)=>record.sourcePath).filter(Boolean));
226
238
  }
@@ -37,5 +37,86 @@ export function diffNativeSymbols(beforeSymbols, afterSymbols) {
37
37
  readiness: maxSemanticMergeReadiness(before?.readiness ?? 'ready', after?.readiness ?? 'ready')
38
38
  });
39
39
  }
40
- return changed;
40
+ return downgradeCoveredContainerSymbols(changed);
41
41
  }
42
+
43
+ function downgradeCoveredContainerSymbols(symbols) {
44
+ return symbols.filter((symbol) => !nativeDiffContainerCoveredByMorePreciseChange(symbol, symbols));
45
+ }
46
+
47
+ function nativeDiffContainerCoveredByMorePreciseChange(symbol, symbols) {
48
+ if (symbol.changeKind !== 'modified') return false;
49
+ if (!nativeDiffSymbolIsContainer(symbol)) return false;
50
+ if (nativeDiffSymbolHasOwnChange(symbol)) return false;
51
+ return symbols.some((candidate) => candidate !== symbol && nativeDiffSymbolIsMorePreciseNestedChange(candidate, symbol));
52
+ }
53
+
54
+ function nativeDiffSymbolHasOwnChange(symbol) {
55
+ return ((symbol.beforeSignatureHash ?? '') !== (symbol.afterSignatureHash ?? ''))
56
+ || ((symbol.beforeOwnershipKey ?? '') !== (symbol.afterOwnershipKey ?? ''))
57
+ || ((symbol.beforeNativeAstNodeId ?? '') !== (symbol.afterNativeAstNodeId ?? ''));
58
+ }
59
+
60
+ function nativeDiffSymbolIsMorePreciseNestedChange(candidate, container) {
61
+ if (candidate.changeKind === 'unchanged') return false;
62
+ if (nativeDiffSymbolIsContainer(candidate) && !nativeDiffSymbolIsMember(candidate)) return false;
63
+ if ((candidate.ownershipKey ?? '') === (container.ownershipKey ?? '')) return false;
64
+ if (!nativeDiffAnySpanContains(container, candidate)) return false;
65
+ return nativeDiffNestedSymbolName(candidate, container) || nativeDiffSymbolIsMember(candidate);
66
+ }
67
+
68
+ function nativeDiffSymbolIsContainer(symbol) {
69
+ return nativeDiffContainerKinds.has(nativeDiffKind(symbol.ownershipRegionKind ?? symbol.kind));
70
+ }
71
+
72
+ function nativeDiffSymbolIsMember(symbol) {
73
+ return nativeDiffMemberKinds.has(nativeDiffKind(symbol.ownershipRegionKind ?? symbol.kind));
74
+ }
75
+
76
+ function nativeDiffNestedSymbolName(candidate, container) {
77
+ const candidateName = String(candidate.name ?? '');
78
+ const containerName = String(container.name ?? '');
79
+ return Boolean(containerName && candidateName && candidateName !== containerName && candidateName.startsWith(`${containerName}.`));
80
+ }
81
+
82
+ function nativeDiffAnySpanContains(container, candidate) {
83
+ return nativeDiffSymbolSpans(container).some((containerSpan) => nativeDiffSymbolSpans(candidate).some((candidateSpan) => (
84
+ nativeDiffSameSourcePath(candidateSpan, containerSpan) && nativeDiffSpanContains(containerSpan, candidateSpan)
85
+ )));
86
+ }
87
+
88
+ function nativeDiffSymbolSpans(symbol) {
89
+ return [symbol.sourceSpan, symbol.beforeSourceSpan, symbol.afterSourceSpan].filter(Boolean);
90
+ }
91
+
92
+ function nativeDiffSameSourcePath(left, right) {
93
+ const leftPath = left?.path;
94
+ const rightPath = right?.path;
95
+ return !leftPath || !rightPath || leftPath === rightPath;
96
+ }
97
+
98
+ function nativeDiffSpanContains(containerSpan, candidateSpan) {
99
+ const container = nativeDiffSpanRange(containerSpan);
100
+ const candidate = nativeDiffSpanRange(candidateSpan);
101
+ if (!container || !candidate) return false;
102
+ return container.start <= candidate.start && candidate.end <= container.end && (container.start !== candidate.start || container.end !== candidate.end);
103
+ }
104
+
105
+ function nativeDiffSpanRange(span) {
106
+ const startLine = Number(span?.startLine ?? span?.line ?? span?.start?.line);
107
+ const endLine = Number(span?.endLine ?? span?.end?.line ?? startLine);
108
+ if (!Number.isFinite(startLine) || !Number.isFinite(endLine)) return undefined;
109
+ const startColumn = Number(span?.startColumn ?? span?.column ?? span?.start?.column ?? 0);
110
+ const endColumn = Number(span?.endColumn ?? span?.end?.column ?? startColumn);
111
+ return {
112
+ start: startLine * 100000 + (Number.isFinite(startColumn) ? startColumn : 0),
113
+ end: endLine * 100000 + Math.max(Number.isFinite(startColumn) ? startColumn : 0, Number.isFinite(endColumn) ? endColumn : 0)
114
+ };
115
+ }
116
+
117
+ function nativeDiffKind(value) {
118
+ return String(value ?? '').toLowerCase();
119
+ }
120
+
121
+ const nativeDiffContainerKinds = new Set(['type', 'class', 'interface', 'trait', 'protocol', 'struct', 'enum', 'record', 'body', 'function', 'method', 'export']);
122
+ const nativeDiffMemberKinds = new Set(['body', 'method', 'function', 'property', 'declaration', 'call', 'effect', 'controlflow', 'mutation']);
@@ -23,6 +23,8 @@ export function nativeChangeProjectionSourceMapLinks(imported, side, region, sym
23
23
  precision: mapping.precision,
24
24
  sourceSpan: mapping.sourceSpan,
25
25
  generatedSpan: mapping.generatedSpan,
26
+ sourceReplacementText: mapping.sourceReplacementText,
27
+ sourceReplacementTextHash: mapping.sourceReplacementTextHash ?? mapping.sourceReplacementHash,
26
28
  ownershipRegionId: mapping.ownershipRegionId,
27
29
  ownershipRegionKey: mapping.ownershipRegionKey,
28
30
  ownershipRegionKind: mapping.ownershipRegionKind
@@ -1,5 +1,6 @@
1
1
  import{uniqueStrings}from'../../native-import-utils.js';
2
2
  import{nativeImportCategoryForLossKind}from'./nativeImportCategoryForLossKind.js';
3
+ export{summarizeSemanticAdmissionWarnings}from'./projectImportAdmissionSemanticWarnings.js';
3
4
 
4
5
  export function importLosses(imported){
5
6
  const nativeAst=imported?.nativeAst??imported?.nativeSource?.ast;
@@ -157,4 +158,3 @@ export function summarizeImportPreservation(imported,source){
157
158
  const quality=stale?'stale':missing?'missing':truncated||!exactSourceAvailable||sourcePreservationLosses.length?'lossy':'exact';
158
159
  return {quality,missing,stale,truncated,exactSourceAvailable,lossCount:sourcePreservationLosses.length,id:record?.id};
159
160
  }
160
-
@@ -0,0 +1,178 @@
1
+ import { uniqueRecordsById, uniqueStrings } from '../../native-import-utils.js';
2
+ import { semanticOwnershipRegionsFromSemanticIndex } from '../../semantic-import-regions.js';
3
+
4
+ export function summarizeSemanticAdmissionWarnings(imported, context = {}) {
5
+ const semanticIndex = imported?.semanticIndex ?? imported?.universalAst?.semanticIndex;
6
+ const symbols = semanticSymbolsForImport(imported, semanticIndex);
7
+ const ownershipRegions = semanticOwnershipRegionsForImport(imported, semanticIndex);
8
+ const patchHints = semanticPatchHintsForImport(imported, semanticIndex);
9
+ const sourcePath = firstString(context.sourcePath, context.source?.sourcePath, imported?.sourcePath, imported?.nativeSource?.sourcePath, imported?.nativeAst?.sourcePath, semanticIndex?.documents?.[0]?.path);
10
+ const semanticImportExpected = isSemanticImportExpected(imported, context);
11
+ const semanticImportExpectedEmpty = isSemanticImportExpectedEmpty(imported, context);
12
+ const changedSource = isChangedSemanticAdmissionSource(imported, { ...context, sourcePath });
13
+ const warnings = [];
14
+ if (semanticImportExpected && !semanticImportExpectedEmpty && changedSource && symbols.length > 0 && ownershipRegions.length === 0) {
15
+ warnings.push(semanticAdmissionWarning({
16
+ code: 'missing-ownership-regions',
17
+ message: 'Semantic import was expected for a changed source and produced symbols, but no ownership regions were available.',
18
+ action: 'rerun-sidecar-generation-with-ownership-regions',
19
+ sourcePath,
20
+ symbols,
21
+ ownershipRegions,
22
+ patchHints,
23
+ semanticImportExpected,
24
+ changedSource
25
+ }));
26
+ }
27
+ if (semanticImportExpected && !semanticImportExpectedEmpty && changedSource && symbols.length > 0 && patchHints.length === 0) {
28
+ warnings.push(semanticAdmissionWarning({
29
+ code: 'missing-patch-hints',
30
+ message: 'Semantic import was expected for a changed source and produced symbols, but no patch hints were available.',
31
+ action: 'generate-semantic-patch-hints',
32
+ sourcePath,
33
+ symbols,
34
+ ownershipRegions,
35
+ patchHints,
36
+ semanticImportExpected,
37
+ changedSource
38
+ }));
39
+ }
40
+ return {
41
+ semanticImportExpected,
42
+ semanticImportExpectedEmpty,
43
+ changedSource,
44
+ symbolCount: symbols.length,
45
+ ownershipRegionCount: ownershipRegions.length,
46
+ patchHintCount: patchHints.length,
47
+ warningCount: warnings.length,
48
+ reasonCodes: uniqueStrings(warnings.map((warning) => warning.reasonCode)),
49
+ warnings
50
+ };
51
+ }
52
+
53
+ function semanticAdmissionWarning(input) {
54
+ return {
55
+ code: input.code,
56
+ reasonCode: input.code,
57
+ severity: 'warning',
58
+ message: input.message,
59
+ action: input.action,
60
+ ...(input.sourcePath ? { sourcePath: input.sourcePath } : {}),
61
+ sourcePaths: uniqueStrings([input.sourcePath].filter(Boolean)),
62
+ semanticSymbols: input.symbols.length,
63
+ ownershipRegions: input.ownershipRegions.length,
64
+ patchHints: input.patchHints.length,
65
+ semanticImportExpected: input.semanticImportExpected,
66
+ changedSource: input.changedSource
67
+ };
68
+ }
69
+
70
+ function semanticSymbolsForImport(imported, semanticIndex) {
71
+ if (Array.isArray(semanticIndex?.symbols)) return semanticIndex.symbols;
72
+ for (const symbols of [
73
+ imported?.semanticSymbols,
74
+ imported?.symbols,
75
+ imported?.metadata?.semanticSymbols,
76
+ imported?.metadata?.symbols
77
+ ]) {
78
+ if (Array.isArray(symbols)) return symbols;
79
+ }
80
+ return [];
81
+ }
82
+
83
+ function semanticOwnershipRegionsForImport(imported, semanticIndex) {
84
+ return uniqueRecordsById([
85
+ ...(Array.isArray(imported?.ownershipRegions) ? imported.ownershipRegions : []),
86
+ ...(Array.isArray(imported?.semanticOwnershipRegions) ? imported.semanticOwnershipRegions : []),
87
+ ...semanticOwnershipRegionsFromSemanticIndex(semanticIndex),
88
+ ...(Array.isArray(imported?.universalAst?.ownershipRegions) ? imported.universalAst.ownershipRegions : []),
89
+ ...(Array.isArray(imported?.metadata?.ownershipRegions) ? imported.metadata.ownershipRegions : [])
90
+ ]);
91
+ }
92
+
93
+ function semanticPatchHintsForImport(imported, semanticIndex) {
94
+ return uniqueRecordsById([
95
+ ...(Array.isArray(imported?.patchHints) ? imported.patchHints : []),
96
+ ...(Array.isArray(imported?.semanticPatchHints) ? imported.semanticPatchHints : []),
97
+ ...(Array.isArray(semanticIndex?.patchHints) ? semanticIndex.patchHints : []),
98
+ ...(Array.isArray(imported?.universalAst?.patchHints) ? imported.universalAst.patchHints : []),
99
+ ...(Array.isArray(imported?.metadata?.patchHints) ? imported.metadata.patchHints : [])
100
+ ]);
101
+ }
102
+
103
+ function isSemanticImportExpected(imported, context) {
104
+ return semanticExpectationRecords(imported, context).some((entry) =>
105
+ entry.semanticImportExpected === true
106
+ || entry.expectedSemanticImport === true
107
+ || entry.semanticSidecarExpected === true
108
+ || entry.expected === true && looksLikeSemanticSidecarQuality(entry)
109
+ );
110
+ }
111
+
112
+ function isSemanticImportExpectedEmpty(imported, context) {
113
+ return semanticExpectationRecords(imported, context).some((entry) =>
114
+ entry.semanticImportExpectedEmpty === true
115
+ || entry.expectedSemanticImportEmpty === true
116
+ || entry.semanticSidecarExpectedEmpty === true
117
+ || entry.expectedEmpty === true && looksLikeSemanticSidecarQuality(entry)
118
+ );
119
+ }
120
+
121
+ function isChangedSemanticAdmissionSource(imported, context) {
122
+ const sourcePath = context.sourcePath;
123
+ const changedSourcePaths = uniqueStrings([
124
+ ...(context.projectResult?.changedSourcePaths ?? []),
125
+ ...(context.projectResult?.metadata?.changedSourcePaths ?? []),
126
+ ...(context.projectResult?.metadata?.semanticChangedSourcePaths ?? []),
127
+ ...(context.projectResult?.metadata?.semanticImportChangedSourcePaths ?? [])
128
+ ]);
129
+ return Boolean(
130
+ (context.candidates?.length ?? 0) > 0
131
+ || (sourcePath && changedSourcePaths.includes(sourcePath))
132
+ || semanticExpectationRecords(imported, context).some((entry) =>
133
+ entry.changedSource === true
134
+ || entry.sourceChanged === true
135
+ || entry.semanticSourceChanged === true
136
+ || entry.semanticImportChangedSource === true
137
+ )
138
+ );
139
+ }
140
+
141
+ function semanticExpectationRecords(imported, context) {
142
+ const nativeAst = imported?.nativeAst ?? imported?.nativeSource?.ast;
143
+ const semanticIndex = imported?.semanticIndex ?? imported?.universalAst?.semanticIndex;
144
+ return [
145
+ context.projectResult?.metadata,
146
+ context.source?.metadata,
147
+ imported?.metadata,
148
+ imported?.nativeSource?.metadata,
149
+ nativeAst?.metadata,
150
+ imported?.universalAst?.metadata,
151
+ imported?.patch?.metadata,
152
+ semanticIndex?.metadata,
153
+ imported?.semanticSidecarQuality,
154
+ imported?.sidecarQuality,
155
+ imported?.semanticSidecar?.quality,
156
+ imported?.sidecar?.quality,
157
+ imported?.metadata?.semanticSidecarQuality,
158
+ imported?.metadata?.sidecarQuality,
159
+ imported?.patch?.metadata?.semanticSidecarQuality
160
+ ].filter((entry) => entry && typeof entry === 'object');
161
+ }
162
+
163
+ function looksLikeSemanticSidecarQuality(value) {
164
+ return value && typeof value === 'object' && (
165
+ value.schema === 'frontier.lang.semanticSidecarQuality.v1'
166
+ || value.imported !== undefined
167
+ || value.expectedSatisfied !== undefined
168
+ || value.warningCount !== undefined
169
+ || value.proofSummary !== undefined
170
+ );
171
+ }
172
+
173
+ function firstString(...values) {
174
+ for (const value of values) {
175
+ if (value !== undefined && value !== null && String(value)) return String(value);
176
+ }
177
+ return undefined;
178
+ }
@@ -1,12 +1,12 @@
1
1
  import{countBy,maxSemanticMergeReadiness,uniqueRecordsById,uniqueStrings}from'../../native-import-utils.js';
2
2
  import{createSemanticMergeCandidateAdmissionRecord,querySemanticMergeCandidateAdmissionOverlaps,sortSemanticMergeCandidateAdmissionRecords}from'./semanticMergeCandidateRecords.js';
3
- import{compactAdmissionSource,importLosses,sourceLossClasses,summarizeImportPreservation,summarizeParserEvidence}from'./projectImportAdmissionImportEvidence.js';
3
+ import{compactAdmissionSource,importLosses,sourceLossClasses,summarizeImportPreservation,summarizeParserEvidence,summarizeSemanticAdmissionWarnings}from'./projectImportAdmissionImportEvidence.js';
4
4
  import{sourceMissingEvidence,sourceMissingTasks,sourceSemanticMergeScore}from'./projectImportAdmissionTasks.js';
5
5
  import{candidateRisk,maxPreservationQuality,maxRisk,normalizeRisk}from'./projectImportAdmissionRanks.js';
6
6
 
7
7
  export{admissionLanguages}from'./projectImportAdmissionLanguageSummaries.js';
8
8
 
9
- export function projectAdmissionImports(imports,sourceRows,mergeCandidates){
9
+ export function projectAdmissionImports(imports,sourceRows,mergeCandidates,projectResult){
10
10
  return imports.map((imported,index)=>{
11
11
  const source=sourceRows?.[index]??compactAdmissionSource(imported,index);
12
12
  const sourcePath=source.sourcePath??imported?.sourcePath;
@@ -22,6 +22,7 @@ export function projectAdmissionImports(imports,sourceRows,mergeCandidates){
22
22
  };
23
23
  const readiness=source.readiness??imported?.metadata?.semanticMergeReadiness??candidates[0]?.readiness??'ready';
24
24
  const emptySemanticEvidence=Object.values(semanticCounts).reduce((sum,value)=>sum+value,0)===0;
25
+ const semanticAdmission=summarizeSemanticAdmissionWarnings(imported,{source,sourcePath,candidates,projectResult});
25
26
  const sourcePreservation=summarizeImportPreservation(imported,source);
26
27
  const losses=importLosses(imported);
27
28
  const lossClasses=sourceLossClasses(imported,losses);
@@ -55,6 +56,7 @@ export function projectAdmissionImports(imports,sourceRows,mergeCandidates){
55
56
  readiness,
56
57
  semanticCounts,
57
58
  emptySemanticEvidence,
59
+ semanticAdmission,
58
60
  parserEvidence,
59
61
  lossClasses,
60
62
  missingEvidence,
@@ -90,6 +92,7 @@ export function admissionSemanticEvidence(projectResult,imports,importSummaries)
90
92
  .filter((entry)=>entry.emptySemanticEvidence)
91
93
  .map((entry)=>entry.sourcePath)
92
94
  .filter(Boolean));
95
+ const warnings=uniqueSemanticAdmissionWarnings(importSummaries.flatMap((entry)=>entry.semanticAdmission?.warnings??[]));
93
96
  return {
94
97
  empty:Object.values(totals).reduce((sum,value)=>sum+value,0)===0,
95
98
  emptySourceCount:importSummaries.filter((entry)=>entry.emptySemanticEvidence).length,
@@ -98,10 +101,26 @@ export function admissionSemanticEvidence(projectResult,imports,importSummaries)
98
101
  evidenceRecords:uniqueRecordsById([
99
102
  ...(projectResult?.evidence??[]),
100
103
  ...imports.flatMap((imported)=>imported?.evidence??[])
101
- ]).length
104
+ ]).length,
105
+ warningCount:warnings.length,
106
+ warningReasonCodes:uniqueStrings(warnings.map((warning)=>warning.reasonCode??warning.code)),
107
+ warningSourcePaths:uniqueStrings(warnings.flatMap((warning)=>warning.sourcePaths??[warning.sourcePath]).filter(Boolean)),
108
+ warnings
102
109
  };
103
110
  }
104
111
 
112
+ function uniqueSemanticAdmissionWarnings(warnings){
113
+ const seen=new Set();
114
+ const result=[];
115
+ for(const warning of warnings.filter(Boolean)){
116
+ const key=[warning.reasonCode??warning.code,(warning.sourcePaths??[warning.sourcePath]).join('|')].join('\u0000');
117
+ if(seen.has(key)) continue;
118
+ seen.add(key);
119
+ result.push(warning);
120
+ }
121
+ return result;
122
+ }
123
+
105
124
  export function admissionSourcePreservation(importSummaries,contract){
106
125
  const qualities=importSummaries.map((entry)=>entry.sourcePreservation.quality);
107
126
  const quality=qualities.length?qualities.reduce(maxPreservationQuality,'exact'):'empty';