@shapeshift-labs/frontier-lang-compiler 0.2.66 → 0.2.68
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/README.md +6 -2
- package/bench/smoke.mjs +15 -1
- package/bench/universal-fixture-suite.mjs +183 -0
- package/dist/declarations/native-project-admission.d.ts +115 -0
- package/dist/declarations/roundtrip-audit.d.ts +186 -0
- package/dist/declarations/roundtrip.d.ts +2 -53
- package/dist/declarations/runtime.d.ts +0 -11
- package/dist/declarations/semantic-history-records.d.ts +277 -0
- package/dist/declarations/semantic-history.d.ts +45 -92
- package/dist/declarations/semantic-slice-admission.d.ts +111 -0
- package/dist/declarations/semantic-slice.d.ts +36 -1
- package/dist/declarations/universal-conversion-plan.d.ts +59 -0
- package/dist/declarations/universal-runtime-capabilities.d.ts +171 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/internal/index-impl/createNativeRoundtripEvidence.js +54 -49
- package/dist/internal/index-impl/createSemanticSlice.js +1 -1
- package/dist/internal/index-impl/createSemanticSliceAdmissionRecord.js +10 -1
- package/dist/internal/index-impl/expandSemanticSliceSelection.js +0 -1
- package/dist/internal/index-impl/nativeRoundtripAudit.js +217 -0
- package/dist/internal/index-impl/projectImportAdmissionImportEvidence.js +160 -0
- package/dist/internal/index-impl/projectImportAdmissionLanguageSummaries.js +247 -0
- package/dist/internal/index-impl/projectImportAdmissionRanks.js +52 -0
- package/dist/internal/index-impl/projectImportAdmissionSummaries.js +46 -111
- package/dist/internal/index-impl/projectImportAdmissionTasks.js +239 -0
- package/dist/internal/index-impl/semanticHistoryRecordNormalizers.js +151 -0
- package/dist/internal/index-impl/semanticHistoryRecordOverlaps.js +113 -0
- package/dist/internal/index-impl/semanticHistoryRecords.js +210 -149
- package/dist/internal/index-impl/semanticSliceAdmissionSurface.js +142 -0
- package/dist/internal/index-impl/semanticSliceExpectationAssertions.js +100 -0
- package/dist/internal/index-impl/semanticSliceExpectationRecords.js +75 -0
- package/dist/internal/index-impl/semanticSliceExpectedAssertions.js +5 -2
- package/dist/internal/index-impl/testSemanticSlice.js +4 -1
- package/dist/language-adapter-package-contracts.js +12 -57
- package/dist/language-adapter-package-rows.js +116 -0
- package/dist/universal-conversion-plan-summary.js +42 -0
- package/dist/universal-conversion-plan.js +46 -40
- package/dist/universal-runtime-capabilities.js +92 -0
- package/dist/universal-runtime-host-selectors.js +192 -0
- package/dist/universal-runtime-profiles.js +109 -0
- package/dist/universal-runtime-route-records.js +162 -0
- package/examples/js-frontier-rust-workbench-client.mjs +58 -1
- package/examples/js-frontier-rust-workbench-convert.mjs +161 -0
- package/examples/js-frontier-rust-workbench-route-styles.mjs +126 -0
- package/examples/js-frontier-rust-workbench-route.mjs +190 -0
- package/examples/js-frontier-rust-workbench-styles.mjs +3 -38
- package/examples/js-frontier-rust-workbench.mjs +22 -128
- package/package.json +1 -1
|
@@ -1,8 +1,10 @@
|
|
|
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';
|
|
4
|
+
import{sourceMissingEvidence,sourceMissingTasks,sourceSemanticMergeScore}from'./projectImportAdmissionTasks.js';
|
|
5
|
+
import{candidateRisk,maxPreservationQuality,maxRisk,normalizeRisk}from'./projectImportAdmissionRanks.js';
|
|
3
6
|
|
|
4
|
-
|
|
5
|
-
const preservationRank=Object.freeze({exact:0,lossy:1,missing:2,stale:3,empty:4});
|
|
7
|
+
export{admissionLanguages}from'./projectImportAdmissionLanguageSummaries.js';
|
|
6
8
|
|
|
7
9
|
export function projectAdmissionImports(imports,sourceRows,mergeCandidates){
|
|
8
10
|
return imports.map((imported,index)=>{
|
|
@@ -18,49 +20,59 @@ export function projectAdmissionImports(imports,sourceRows,mergeCandidates){
|
|
|
18
20
|
relations:semanticIndex?.relations?.length??0,
|
|
19
21
|
facts:semanticIndex?.facts?.length??0
|
|
20
22
|
};
|
|
23
|
+
const readiness=source.readiness??imported?.metadata?.semanticMergeReadiness??candidates[0]?.readiness??'ready';
|
|
24
|
+
const emptySemanticEvidence=Object.values(semanticCounts).reduce((sum,value)=>sum+value,0)===0;
|
|
25
|
+
const sourcePreservation=summarizeImportPreservation(imported,source);
|
|
26
|
+
const losses=importLosses(imported);
|
|
27
|
+
const lossClasses=sourceLossClasses(imported,losses);
|
|
28
|
+
const parserEvidence=summarizeParserEvidence(imported,source,losses);
|
|
29
|
+
const missingEvidence=sourceMissingEvidence({
|
|
30
|
+
imported,
|
|
31
|
+
source,
|
|
32
|
+
losses,
|
|
33
|
+
semanticCounts,
|
|
34
|
+
emptySemanticEvidence,
|
|
35
|
+
sourcePreservation,
|
|
36
|
+
parserEvidence
|
|
37
|
+
});
|
|
38
|
+
const nextMissingTasks=sourceMissingTasks({
|
|
39
|
+
source,
|
|
40
|
+
readiness,
|
|
41
|
+
semanticCounts,
|
|
42
|
+
emptySemanticEvidence,
|
|
43
|
+
sourcePreservation,
|
|
44
|
+
parserEvidence,
|
|
45
|
+
lossClasses,
|
|
46
|
+
losses,
|
|
47
|
+
missingEvidence,
|
|
48
|
+
candidates
|
|
49
|
+
});
|
|
21
50
|
return {
|
|
22
51
|
id:source.id??imported?.id,
|
|
23
52
|
language:source.language??imported?.language??'unknown',
|
|
24
53
|
sourcePath,
|
|
25
54
|
sourceHash:source.sourceHash,
|
|
26
|
-
readiness
|
|
55
|
+
readiness,
|
|
27
56
|
semanticCounts,
|
|
28
|
-
emptySemanticEvidence
|
|
29
|
-
|
|
57
|
+
emptySemanticEvidence,
|
|
58
|
+
parserEvidence,
|
|
59
|
+
lossClasses,
|
|
60
|
+
missingEvidence,
|
|
61
|
+
nextMissingTasks,
|
|
62
|
+
semanticMergeScore:sourceSemanticMergeScore({
|
|
63
|
+
readiness,
|
|
64
|
+
emptySemanticEvidence,
|
|
65
|
+
sourcePreservation,
|
|
66
|
+
parserEvidence,
|
|
67
|
+
missingEvidence,
|
|
68
|
+
candidates
|
|
69
|
+
}),
|
|
70
|
+
sourcePreservation,
|
|
30
71
|
mergeCandidates:candidates
|
|
31
72
|
};
|
|
32
73
|
});
|
|
33
74
|
}
|
|
34
75
|
|
|
35
|
-
export function admissionLanguages(importSummaries){
|
|
36
|
-
const grouped=new Map();
|
|
37
|
-
for(const entry of importSummaries){
|
|
38
|
-
const key=entry.language??'unknown';
|
|
39
|
-
if(!grouped.has(key)) grouped.set(key,emptyLanguageRow(key));
|
|
40
|
-
const row=grouped.get(key);
|
|
41
|
-
row.sourceCount+=1;
|
|
42
|
-
row.sourcePaths.push(entry.sourcePath);
|
|
43
|
-
row.readiness=maxSemanticMergeReadiness(row.readiness,entry.readiness);
|
|
44
|
-
row.semanticSymbols+=entry.semanticCounts.symbols;
|
|
45
|
-
if(entry.emptySemanticEvidence) row.emptySemanticEvidenceSources+=1;
|
|
46
|
-
row.sourcePreservationQuality=maxPreservationQuality(row.sourcePreservationQuality,entry.sourcePreservation.quality);
|
|
47
|
-
if(entry.sourcePreservation.stale&&entry.sourcePath) row.staleSourcePaths.push(entry.sourcePath);
|
|
48
|
-
row.mergeCandidates+=entry.mergeCandidates.length;
|
|
49
|
-
row.highestRisk=maxRisk(row.highestRisk,entry.mergeCandidates.reduce((current,candidate)=>maxRisk(current,candidateRisk(candidate)),'low'));
|
|
50
|
-
}
|
|
51
|
-
const rows=[...grouped.values()].map((row)=>({
|
|
52
|
-
...row,
|
|
53
|
-
sourcePaths:uniqueStrings(row.sourcePaths.filter(Boolean)),
|
|
54
|
-
staleSourcePaths:uniqueStrings(row.staleSourcePaths.filter(Boolean))
|
|
55
|
-
})).sort((left,right)=>left.language.localeCompare(right.language));
|
|
56
|
-
return {
|
|
57
|
-
total:rows.length,
|
|
58
|
-
byReadiness:countBy(rows.map((row)=>row.readiness)),
|
|
59
|
-
bySourcePreservationQuality:countBy(rows.map((row)=>row.sourcePreservationQuality)),
|
|
60
|
-
rows
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
76
|
export function admissionSemanticEvidence(projectResult,imports,importSummaries){
|
|
65
77
|
const projectIndex=projectResult?.semanticIndex??projectResult?.universalAst?.semanticIndex;
|
|
66
78
|
const indexes=projectIndex?[projectIndex]:imports.flatMap((imported)=>[
|
|
@@ -198,80 +210,3 @@ export function admissionMergeCandidates(projectResult,imports,mergeCandidates,l
|
|
|
198
210
|
patchRisk:normalizeRisk(projectResult?.patch?.risk)
|
|
199
211
|
};
|
|
200
212
|
}
|
|
201
|
-
|
|
202
|
-
export function candidateRisk(candidate,patch){
|
|
203
|
-
return normalizeRisk(candidate?.risk)??normalizeRisk(patch?.risk)??readinessRisk(candidate?.readiness);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
export function maxRisk(left,right){
|
|
207
|
-
return riskRank[left]>=riskRank[right]?left:right;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
export function maxPreservationQuality(left,right){
|
|
211
|
-
return preservationRank[left]>=preservationRank[right]?left:right;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
function compactAdmissionSource(imported,index){
|
|
215
|
-
const semanticIndex=imported?.semanticIndex??imported?.universalAst?.semanticIndex;
|
|
216
|
-
const nativeAst=imported?.nativeAst??imported?.nativeSource?.ast;
|
|
217
|
-
const sourceMaps=imported?.sourceMaps??imported?.universalAst?.sourceMaps??[];
|
|
218
|
-
return {
|
|
219
|
-
id:imported?.id??`import_${index+1}`,
|
|
220
|
-
language:imported?.language??imported?.nativeSource?.language??nativeAst?.language,
|
|
221
|
-
sourcePath:imported?.sourcePath??imported?.nativeSource?.sourcePath??nativeAst?.sourcePath,
|
|
222
|
-
sourceHash:imported?.nativeSource?.sourceHash??nativeAst?.sourceHash,
|
|
223
|
-
parser:nativeAst?.parser??imported?.nativeSource?.parser,
|
|
224
|
-
sourceMapIds:sourceMaps.map((sourceMap)=>sourceMap.id).filter(Boolean),
|
|
225
|
-
sourceMapMappings:sourceMaps.reduce((sum,sourceMap)=>sum+(sourceMap.mappings?.length??0),0),
|
|
226
|
-
symbolCount:semanticIndex?.symbols?.length??0,
|
|
227
|
-
lossCount:imported?.losses?.length??nativeAst?.losses?.length??0,
|
|
228
|
-
evidenceCount:imported?.evidence?.length??0,
|
|
229
|
-
readiness:imported?.metadata?.semanticMergeReadiness??imported?.mergeCandidates?.[0]?.readiness
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
function summarizeImportPreservation(imported,source){
|
|
234
|
-
const nativeAst=imported?.nativeAst??imported?.nativeSource?.ast;
|
|
235
|
-
const record=imported?.metadata?.sourcePreservation
|
|
236
|
-
??imported?.nativeSource?.metadata?.sourcePreservation
|
|
237
|
-
??nativeAst?.metadata?.sourcePreservation
|
|
238
|
-
??imported?.universalAst?.metadata?.sourcePreservation;
|
|
239
|
-
const sourceHash=source?.sourceHash??imported?.nativeSource?.sourceHash??nativeAst?.sourceHash;
|
|
240
|
-
const sourcePreservationLosses=(imported?.losses??nativeAst?.losses??[]).filter((loss)=>loss.kind==='sourcePreservation');
|
|
241
|
-
const stale=imported?.metadata?.sourceHashVerified===false
|
|
242
|
-
||imported?.nativeSource?.metadata?.sourceHashVerified===false
|
|
243
|
-
||nativeAst?.metadata?.sourceHashVerified===false
|
|
244
|
-
||record?.metadata?.sourceHashVerified===false
|
|
245
|
-
||Boolean(record?.sourceHash&&sourceHash&&record.sourceHash!==sourceHash);
|
|
246
|
-
const missing=!record;
|
|
247
|
-
const truncated=record?.summary?.truncated===true;
|
|
248
|
-
const exactSourceAvailable=record?.summary?.exactSourceAvailable===true;
|
|
249
|
-
const quality=stale?'stale':missing?'missing':truncated||!exactSourceAvailable||sourcePreservationLosses.length?'lossy':'exact';
|
|
250
|
-
return {quality,missing,stale,truncated,exactSourceAvailable,lossCount:sourcePreservationLosses.length,id:record?.id};
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
function emptyLanguageRow(language){
|
|
254
|
-
return {
|
|
255
|
-
language,
|
|
256
|
-
sourceCount:0,
|
|
257
|
-
sourcePaths:[],
|
|
258
|
-
readiness:'ready',
|
|
259
|
-
semanticSymbols:0,
|
|
260
|
-
emptySemanticEvidenceSources:0,
|
|
261
|
-
sourcePreservationQuality:'exact',
|
|
262
|
-
staleSourcePaths:[],
|
|
263
|
-
mergeCandidates:0,
|
|
264
|
-
highestRisk:'low'
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
function readinessRisk(readiness){
|
|
269
|
-
if(readiness==='blocked') return 'high';
|
|
270
|
-
if(readiness==='needs-review'||readiness==='ready-with-losses') return 'medium';
|
|
271
|
-
return 'low';
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
function normalizeRisk(value){
|
|
275
|
-
const risk=String(value??'').toLowerCase();
|
|
276
|
-
return Object.prototype.hasOwnProperty.call(riskRank,risk)?risk:undefined;
|
|
277
|
-
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import{maxSemanticMergeReadiness,uniqueStrings}from'../../native-import-utils.js';
|
|
2
|
+
import{nativeImportCategoryForLossKind}from'./nativeImportCategoryForLossKind.js';
|
|
3
|
+
import{candidateRisk,clampScore,maxRisk,maxTaskPriority,readinessSort,sourceScoreByReadiness,taskPriorityForReadiness,taskPriorityRank}from'./projectImportAdmissionRanks.js';
|
|
4
|
+
|
|
5
|
+
export function sourceMissingEvidence(input){
|
|
6
|
+
const lossSummary=input.imported?.metadata?.nativeImportLossSummary
|
|
7
|
+
??input.imported?.nativeSource?.metadata?.nativeImportLossSummary
|
|
8
|
+
??input.imported?.nativeAst?.metadata?.nativeImportLossSummary
|
|
9
|
+
??input.imported?.universalAst?.metadata?.nativeImportLossSummary;
|
|
10
|
+
const sourcePath=input.source?.sourcePath??input.imported?.sourcePath;
|
|
11
|
+
const language=input.source?.language??input.imported?.language??'unknown';
|
|
12
|
+
const hints=[];
|
|
13
|
+
for(const missing of lossSummary?.featureEvidence?.missingRequiredEvidence??[]){
|
|
14
|
+
const lossClass=nativeImportCategoryForLossKind(missing.kind??missing.policyKind);
|
|
15
|
+
hints.push(evidenceHint({
|
|
16
|
+
evidenceKey:missing.evidenceKey,
|
|
17
|
+
task:`Add ${missing.evidenceKey} evidence for ${missing.kind??missing.policyKind}.`,
|
|
18
|
+
sourcePath,
|
|
19
|
+
language,
|
|
20
|
+
lossId:missing.lossId,
|
|
21
|
+
lossKind:missing.kind??missing.policyKind,
|
|
22
|
+
lossClass,
|
|
23
|
+
readiness:'needs-review'
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
if(input.emptySemanticEvidence){
|
|
27
|
+
hints.push(evidenceHint({
|
|
28
|
+
evidenceKey:'semantic-index',
|
|
29
|
+
task:'Import semantic symbols for sources with empty semantic indexes.',
|
|
30
|
+
sourcePath,
|
|
31
|
+
language,
|
|
32
|
+
lossKind:'partialSemanticIndex',
|
|
33
|
+
lossClass:'partialSemanticIndex',
|
|
34
|
+
readiness:'blocked'
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
if(input.parserEvidence.missing){
|
|
38
|
+
hints.push(evidenceHint({
|
|
39
|
+
evidenceKey:'parser-result',
|
|
40
|
+
task:'Attach a native parser AST instead of missing-parser fallback evidence.',
|
|
41
|
+
sourcePath,
|
|
42
|
+
language,
|
|
43
|
+
lossKind:'unsupportedSyntax',
|
|
44
|
+
lossClass:'parserDiagnostics',
|
|
45
|
+
readiness:'blocked'
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
if(input.sourcePreservation.stale){
|
|
49
|
+
hints.push(evidenceHint({
|
|
50
|
+
evidenceKey:'source-hash-verification',
|
|
51
|
+
task:'Refresh source hashes or re-import the stale source text.',
|
|
52
|
+
sourcePath,
|
|
53
|
+
language,
|
|
54
|
+
lossKind:'sourcePreservation',
|
|
55
|
+
lossClass:'sourcePreservation',
|
|
56
|
+
readiness:'blocked'
|
|
57
|
+
}));
|
|
58
|
+
}else if(input.sourcePreservation.quality==='missing'||input.sourcePreservation.quality==='lossy'){
|
|
59
|
+
hints.push(evidenceHint({
|
|
60
|
+
evidenceKey:'source-preservation',
|
|
61
|
+
task:'Attach exact source-preservation evidence for lossy or missing source text.',
|
|
62
|
+
sourcePath,
|
|
63
|
+
language,
|
|
64
|
+
lossKind:'sourcePreservation',
|
|
65
|
+
lossClass:'sourcePreservation',
|
|
66
|
+
readiness:'needs-review'
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
return uniqueEvidenceHints(hints);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function sourceMissingTasks(input){
|
|
73
|
+
const sourcePath=input.source?.sourcePath;
|
|
74
|
+
const language=input.source?.language??'unknown';
|
|
75
|
+
const tasks=[];
|
|
76
|
+
for(const hint of input.missingEvidence??[]){
|
|
77
|
+
tasks.push(taskHint({
|
|
78
|
+
id:`evidence:${hint.evidenceKey}`,
|
|
79
|
+
task:hint.task,
|
|
80
|
+
reason:'missing-evidence',
|
|
81
|
+
priority:taskPriorityForReadiness(hint.readiness),
|
|
82
|
+
readiness:hint.readiness,
|
|
83
|
+
sourcePath,
|
|
84
|
+
language,
|
|
85
|
+
lossClasses:hint.lossClasses,
|
|
86
|
+
evidenceKeys:[hint.evidenceKey]
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
for(const lossClass of input.lossClasses??[]){
|
|
90
|
+
const task=taskForLossClass(lossClass);
|
|
91
|
+
if(task){
|
|
92
|
+
tasks.push(taskHint({
|
|
93
|
+
...task,
|
|
94
|
+
sourcePath,
|
|
95
|
+
language,
|
|
96
|
+
readiness:input.readiness,
|
|
97
|
+
lossClasses:[lossClass]
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const reviewCandidates=(input.candidates??[]).filter((candidate)=>
|
|
102
|
+
candidate.readiness==='needs-review'
|
|
103
|
+
|| candidate.readiness==='blocked'
|
|
104
|
+
|| candidateRisk(candidate)!=='low'
|
|
105
|
+
);
|
|
106
|
+
if(reviewCandidates.length){
|
|
107
|
+
tasks.push(taskHint({
|
|
108
|
+
id:'semantic-merge-review',
|
|
109
|
+
task:'Review semantic merge candidates that carry elevated risk or review readiness.',
|
|
110
|
+
reason:'merge-candidate-risk',
|
|
111
|
+
priority:reviewCandidates.some((candidate)=>candidateRisk(candidate)==='high'||candidate.readiness==='blocked')?'critical':'high',
|
|
112
|
+
readiness:reviewCandidates.reduce((current,candidate)=>maxSemanticMergeReadiness(current,candidate.readiness??'ready'),input.readiness),
|
|
113
|
+
sourcePath,
|
|
114
|
+
language,
|
|
115
|
+
lossClasses:[],
|
|
116
|
+
evidenceKeys:[]
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
if(!tasks.length&&input.readiness!=='ready'){
|
|
120
|
+
tasks.push(taskHint({
|
|
121
|
+
id:'native-import-review',
|
|
122
|
+
task:'Review native import losses before admitting this source.',
|
|
123
|
+
reason:'readiness-review',
|
|
124
|
+
priority:taskPriorityForReadiness(input.readiness),
|
|
125
|
+
readiness:input.readiness,
|
|
126
|
+
sourcePath,
|
|
127
|
+
language,
|
|
128
|
+
lossClasses:input.lossClasses,
|
|
129
|
+
evidenceKeys:[]
|
|
130
|
+
}));
|
|
131
|
+
}
|
|
132
|
+
return uniqueTaskHints(tasks);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function taskForLossClass(lossClass){
|
|
136
|
+
if(lossClass==='exactAstImport'||lossClass==='none') return undefined;
|
|
137
|
+
if(lossClass==='partialSemanticIndex'){
|
|
138
|
+
return {id:'semantic-index-completeness',task:'Complete semantic index coverage for partial imports.',reason:'partial-semantic-index',priority:'high',evidenceKeys:['semantic-index']};
|
|
139
|
+
}
|
|
140
|
+
if(lossClass==='declarationsOnly'||lossClass==='opaqueBodies'){
|
|
141
|
+
return {id:'body-semantics',task:'Import body-level semantic evidence beyond declaration-only coverage.',reason:'declaration-only-or-opaque-body',priority:'normal',evidenceKeys:['body-semantics']};
|
|
142
|
+
}
|
|
143
|
+
if(lossClass==='sourceMapApproximation'){
|
|
144
|
+
return {id:'source-map-ranges',task:'Attach precise source-map ranges for approximated native mappings.',reason:'source-map-approximation',priority:'normal',evidenceKeys:['source-map']};
|
|
145
|
+
}
|
|
146
|
+
if(lossClass==='sourcePreservation'||lossClass==='commentsTrivia'){
|
|
147
|
+
return {id:'source-preservation',task:'Attach exact source-preservation evidence for lossy or missing source text.',reason:'source-preservation-loss',priority:'high',evidenceKeys:['source-preservation']};
|
|
148
|
+
}
|
|
149
|
+
if(lossClass==='parserDiagnostics'||lossClass==='unsupportedSyntax'){
|
|
150
|
+
return {id:'parser-evidence',task:'Resolve parser diagnostics or attach exact parser evidence.',reason:'parser-loss',priority:'blocker',evidenceKeys:['parser-result']};
|
|
151
|
+
}
|
|
152
|
+
if(lossClass==='unsupportedSyntax'||lossClass==='unsupportedSemantic'){
|
|
153
|
+
return {id:'unsupported-language-feature',task:'Add host semantic evidence for unsupported native language features.',reason:'unsupported-feature-loss',priority:'high',evidenceKeys:['host-semantics']};
|
|
154
|
+
}
|
|
155
|
+
if(lossClass==='targetProjectionLoss'||lossClass==='missingAdapter'||lossClass==='unsupportedTargetFeatures'||lossClass==='nativeSourceStubs'){
|
|
156
|
+
return {id:'target-projection-coverage',task:'Add target projection adapter coverage or mark unsupported target features.',reason:'target-projection-loss',priority:'high',evidenceKeys:['target-projection']};
|
|
157
|
+
}
|
|
158
|
+
if(lossClass==='macroExpansion'||lossClass==='preprocessor'||lossClass==='conditionalCompilation'||lossClass==='metaprogramming'||lossClass==='overloadTypeInference'||lossClass==='generatedCode'){
|
|
159
|
+
return {id:`host-evidence:${lossClass}`,task:`Attach host ${lossClass} evidence for native import losses.`,reason:'host-evidence-loss',priority:'high',evidenceKeys:[lossClass]};
|
|
160
|
+
}
|
|
161
|
+
return {id:`loss-class:${lossClass}`,task:`Review ${lossClass} native import loss evidence.`,reason:'native-loss-class',priority:'normal',evidenceKeys:[lossClass]};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function evidenceHint(input){
|
|
165
|
+
return {
|
|
166
|
+
evidenceKey:input.evidenceKey,
|
|
167
|
+
task:input.task,
|
|
168
|
+
count:1,
|
|
169
|
+
sourcePaths:uniqueStrings([input.sourcePath].filter(Boolean)),
|
|
170
|
+
languages:uniqueStrings([input.language].filter(Boolean)),
|
|
171
|
+
lossIds:uniqueStrings([input.lossId].filter(Boolean)),
|
|
172
|
+
lossKinds:uniqueStrings([input.lossKind].filter(Boolean)),
|
|
173
|
+
lossClasses:uniqueStrings([input.lossClass].filter(Boolean)),
|
|
174
|
+
readiness:input.readiness??'needs-review'
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function taskHint(input){
|
|
179
|
+
return {
|
|
180
|
+
id:input.id,
|
|
181
|
+
task:input.task,
|
|
182
|
+
reason:input.reason,
|
|
183
|
+
priority:input.priority??'normal',
|
|
184
|
+
readiness:input.readiness??'needs-review',
|
|
185
|
+
count:1,
|
|
186
|
+
sourcePaths:uniqueStrings([input.sourcePath].filter(Boolean)),
|
|
187
|
+
languages:uniqueStrings([input.language].filter(Boolean)),
|
|
188
|
+
lossClasses:uniqueStrings(input.lossClasses??[]),
|
|
189
|
+
evidenceKeys:uniqueStrings(input.evidenceKeys??[])
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function uniqueEvidenceHints(hints){
|
|
194
|
+
const grouped=new Map();
|
|
195
|
+
for(const hint of hints){
|
|
196
|
+
const key=`${hint.evidenceKey}\u0000${hint.lossIds.join('|')}\u0000${hint.sourcePaths.join('|')}`;
|
|
197
|
+
if(!grouped.has(key)) grouped.set(key,hint);
|
|
198
|
+
}
|
|
199
|
+
return [...grouped.values()];
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function uniqueTaskHints(tasks){
|
|
203
|
+
const grouped=new Map();
|
|
204
|
+
for(const task of tasks){
|
|
205
|
+
const key=task.id??task.task;
|
|
206
|
+
if(!grouped.has(key)){
|
|
207
|
+
grouped.set(key,{...task});
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
const entry=grouped.get(key);
|
|
211
|
+
entry.count+=task.count??1;
|
|
212
|
+
entry.priority=maxTaskPriority(entry.priority,task.priority);
|
|
213
|
+
entry.readiness=maxSemanticMergeReadiness(entry.readiness,task.readiness);
|
|
214
|
+
entry.sourcePaths=uniqueStrings([...entry.sourcePaths,...task.sourcePaths]);
|
|
215
|
+
entry.languages=uniqueStrings([...entry.languages,...task.languages]);
|
|
216
|
+
entry.lossClasses=uniqueStrings([...entry.lossClasses,...task.lossClasses]);
|
|
217
|
+
entry.evidenceKeys=uniqueStrings([...entry.evidenceKeys,...task.evidenceKeys]);
|
|
218
|
+
}
|
|
219
|
+
return [...grouped.values()].sort((left,right)=>
|
|
220
|
+
taskPriorityRank[right.priority]-taskPriorityRank[left.priority]
|
|
221
|
+
|| readinessSort(right.readiness)-readinessSort(left.readiness)
|
|
222
|
+
|| String(left.task).localeCompare(String(right.task))
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export function sourceSemanticMergeScore(input){
|
|
227
|
+
const readinessScore=sourceScoreByReadiness[input.readiness]??sourceScoreByReadiness['needs-review'];
|
|
228
|
+
const preservationPenalty=input.sourcePreservation.quality==='stale'?35
|
|
229
|
+
:input.sourcePreservation.quality==='missing'?26
|
|
230
|
+
:input.sourcePreservation.quality==='lossy'?12
|
|
231
|
+
:input.sourcePreservation.quality==='empty'?18
|
|
232
|
+
:0;
|
|
233
|
+
const risk=(input.candidates??[]).reduce((current,candidate)=>maxRisk(current,candidateRisk(candidate)),'low');
|
|
234
|
+
const riskPenalty=risk==='high'?24:risk==='medium'?10:risk==='unknown'?8:0;
|
|
235
|
+
const parserPenalty=input.parserEvidence.missing?25:Math.min(16,(input.parserEvidence.diagnosticCount??0)*4);
|
|
236
|
+
const missingEvidencePenalty=Math.min(24,(input.missingEvidence?.length??0)*6);
|
|
237
|
+
const semanticBonus=input.emptySemanticEvidence?-25:5;
|
|
238
|
+
return clampScore(readinessScore+semanticBonus-preservationPenalty-riskPenalty-parserPenalty-missingEvidencePenalty);
|
|
239
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import{hashSemanticValue}from'@shapeshift-labs/frontier-lang-kernel';
|
|
2
|
+
import{idFragment,normalizeSemanticMergeReadiness,uniqueStrings as uniqueRawStrings}from'../../native-import-utils.js';
|
|
3
|
+
|
|
4
|
+
export function normalizeSources(input,imported){
|
|
5
|
+
const entries=[...(array(input.sources)),...(array(input.sourceRefs)),...(array(input.source)),...(array(imported))];
|
|
6
|
+
if(entries.length===0&&(input.sourcePath||input.sourceHash||input.baseHash||input.targetHash||input.sourceId||input.importId)){
|
|
7
|
+
entries.push(input);
|
|
8
|
+
}
|
|
9
|
+
return entries.map((source,index)=>compactRecord({
|
|
10
|
+
id:source?.id??source?.sourceId,
|
|
11
|
+
importId:source?.importId??source?.importResultId??(source?.kind==='frontier.lang.importResult'?source.id:undefined),
|
|
12
|
+
language:source?.language??input.language,
|
|
13
|
+
sourcePath:source?.sourcePath??source?.path??input.sourcePath,
|
|
14
|
+
sourceHash:source?.sourceHash??source?.hash,
|
|
15
|
+
baseHash:source?.baseHash??source?.beforeHash??input.baseHash??input.beforeHash,
|
|
16
|
+
targetHash:source?.targetHash??source?.afterHash??input.targetHash??input.afterHash,
|
|
17
|
+
metadata:source?.metadata,
|
|
18
|
+
ordinal:index
|
|
19
|
+
})).filter((source)=>source.id||source.importId||source.sourcePath||source.sourceHash||source.baseHash||source.targetHash);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function normalizeOwnershipRegions(regions){
|
|
23
|
+
const seen=new Set();
|
|
24
|
+
const normalized=[];
|
|
25
|
+
for(const region of regions){
|
|
26
|
+
const key=firstString(region?.key,region?.ownershipKey,region?.conflictKey,region?.id);
|
|
27
|
+
if(!key||seen.has(key))continue;
|
|
28
|
+
seen.add(key);
|
|
29
|
+
normalized.push(compactRecord({
|
|
30
|
+
id:region?.id,
|
|
31
|
+
key,
|
|
32
|
+
regionKind:region?.regionKind??region?.ownershipRegionKind,
|
|
33
|
+
granularity:region?.granularity??'semantic',
|
|
34
|
+
language:region?.language,
|
|
35
|
+
sourcePath:region?.sourcePath,
|
|
36
|
+
sourceHash:region?.sourceHash,
|
|
37
|
+
symbolId:region?.symbolId,
|
|
38
|
+
symbolName:region?.symbolName??region?.name,
|
|
39
|
+
sourceSpan:region?.sourceSpan??region?.span,
|
|
40
|
+
metadata:region?.metadata
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
return normalized;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function normalizeSemanticCandidates(candidates){
|
|
47
|
+
return candidates.filter(Boolean).map((candidate,index)=>compactRecord({
|
|
48
|
+
id:candidate.id??candidate.candidateId??`semantic_candidate_${index+1}`,
|
|
49
|
+
importResultId:candidate.importResultId,
|
|
50
|
+
patchId:candidate.patchId,
|
|
51
|
+
sourcePath:candidate.sourcePath,
|
|
52
|
+
baseHash:candidate.baseHash,
|
|
53
|
+
targetHash:candidate.targetHash,
|
|
54
|
+
readiness:normalizeSemanticMergeReadiness(candidate.readiness)??candidate.readiness,
|
|
55
|
+
conflictKeys:uniqueStrings([...(strings(candidate.conflictKeys)),...(array(candidate.touchedSymbols)).map((entry)=>entry?.conflictKey),...(array(candidate.touchedSemanticNodes)).map((entry)=>entry?.conflictKey),...(array(candidate.nativeSpans)).map((entry)=>entry?.conflictKey),...(array(candidate.conflictClasses??candidate.metadata?.conflictClasses)).flatMap((entry)=>entry?.conflictKeys??[]),...(candidate.conflictSummary?.conflictKeys??candidate.metadata?.conflictSummary?.conflictKeys??[])]),
|
|
56
|
+
ownershipKeys:uniqueStrings([...(strings(candidate.ownershipKeys)),...(strings(candidate.regionKeys))]),
|
|
57
|
+
evidenceIds:uniqueStrings([...(strings(candidate.evidenceIds)),...(array(candidate.evidence)).map((record)=>record?.id),...(array(candidate.conflictClasses??candidate.metadata?.conflictClasses)).flatMap((entry)=>entry?.evidenceIds??[])]),
|
|
58
|
+
proofIds:uniqueStrings([...(strings(candidate.proofIds)),...(array(candidate.evidence)).filter((record)=>record?.kind==='proof').map((record)=>record?.id)]),
|
|
59
|
+
replayIds:uniqueStrings([...(strings(candidate.replayIds)),...(array(candidate.evidence)).filter((record)=>record?.kind==='replay').map((record)=>record?.id)]),
|
|
60
|
+
metadata:compactRecord({risk:candidate.risk,reasons:candidate.reasons,...candidate.metadata})
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function normalizeSemanticClaims(claims,defaults){
|
|
65
|
+
return claims.filter(Boolean).map((claim,index)=>{
|
|
66
|
+
const text=typeof claim==='string'?claim:undefined;
|
|
67
|
+
const source=typeof claim==='string'?{}:claim;
|
|
68
|
+
const record=compactRecord({
|
|
69
|
+
kind:'frontier.lang.semanticHistoryClaim',
|
|
70
|
+
version:1,
|
|
71
|
+
claimKind:source.claimKind??source.semanticClaimKind??source.kind??defaults.claimKind,
|
|
72
|
+
status:source.status??defaults.status,
|
|
73
|
+
subject:firstString(source.subject,source.symbolId,source.semanticNodeId,source.conflictKey,source.key,text),
|
|
74
|
+
predicate:source.predicate??source.relation,
|
|
75
|
+
object:source.object??source.value??source.expected,
|
|
76
|
+
text,
|
|
77
|
+
language:source.language??defaults.language,
|
|
78
|
+
sourcePath:source.sourcePath??defaults.sourcePath,
|
|
79
|
+
sourceHash:source.sourceHash??defaults.sourceHash,
|
|
80
|
+
baseHash:source.baseHash??defaults.baseHash,
|
|
81
|
+
targetHash:source.targetHash??defaults.targetHash,
|
|
82
|
+
conflictKeys:uniqueStrings([...(strings(source.conflictKeys)),source.conflictKey,source.key]),
|
|
83
|
+
evidenceIds:uniqueStrings(source.evidenceIds),
|
|
84
|
+
proofIds:uniqueStrings(source.proofIds),
|
|
85
|
+
replayIds:uniqueStrings(source.replayIds),
|
|
86
|
+
actor:normalizeActor(source.actor)??defaults.actor,
|
|
87
|
+
recordSource:normalizeRecordSource(source.recordSource??source.historySource??defaults.recordSource,defaults),
|
|
88
|
+
metadata:source.metadata
|
|
89
|
+
});
|
|
90
|
+
return withStableSubrecordIdentity(defaults.prefix??'semantic_claim',record,source,index);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function semanticClaimsByStatus(input,status){
|
|
95
|
+
return [...array(input.semanticClaims),...array(input.claims)].filter((claim)=>{
|
|
96
|
+
const claimStatus=String(claim?.status??'').toLowerCase();
|
|
97
|
+
if(claimStatus===status)return true;
|
|
98
|
+
if(status==='accepted'&&claim?.accepted===true)return true;
|
|
99
|
+
if(status==='rejected'&&(claim?.rejected===true||claim?.status===false))return true;
|
|
100
|
+
return false;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function withStableSubrecordIdentity(prefix,record,source,index){
|
|
104
|
+
const hash=source.hash??hashSemanticValue(record);
|
|
105
|
+
return{
|
|
106
|
+
...record,
|
|
107
|
+
id:source.id??`${prefix}_${idFragment(firstString(record.subject,record.evidenceId,record.proofId,record.patchId,record.decision,hash,index+1))}`,
|
|
108
|
+
hash
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function normalizeActor(value){
|
|
113
|
+
const actor=typeof value==='string'?{id:value}:value;
|
|
114
|
+
const normalized=compactRecord({
|
|
115
|
+
id:actor?.id??actor?.actorId,
|
|
116
|
+
kind:actor?.kind??actor?.actorKind??actor?.type,
|
|
117
|
+
role:actor?.role,
|
|
118
|
+
displayName:actor?.displayName??actor?.name,
|
|
119
|
+
runId:actor?.runId,
|
|
120
|
+
lane:actor?.lane,
|
|
121
|
+
taskId:actor?.taskId,
|
|
122
|
+
metadata:actor?.metadata
|
|
123
|
+
});
|
|
124
|
+
return nonEmptyRecord(normalized);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function normalizeRecordSource(value,context={}){
|
|
128
|
+
const source=typeof value==='string'?{id:value}:value;
|
|
129
|
+
const normalized=compactRecord({
|
|
130
|
+
id:source?.id??source?.sourceId??context.recordSourceId??context.historySourceId,
|
|
131
|
+
sourceId:source?.sourceId??source?.id??context.recordSourceId??context.historySourceId,
|
|
132
|
+
sourceKind:source?.sourceKind??source?.kind??source?.type,
|
|
133
|
+
sourcePath:source?.sourcePath??source?.path,
|
|
134
|
+
sourceHash:source?.sourceHash??source?.hash,
|
|
135
|
+
href:source?.href??source?.url,
|
|
136
|
+
importId:source?.importId??context.importId??context.importResultId,
|
|
137
|
+
runId:source?.runId??context.runId,
|
|
138
|
+
jobId:source?.jobId??context.jobId,
|
|
139
|
+
lane:source?.lane??context.lane,
|
|
140
|
+
taskId:source?.taskId??context.taskId,
|
|
141
|
+
metadata:source?.metadata
|
|
142
|
+
});
|
|
143
|
+
return nonEmptyRecord(normalized);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function array(value){if(value===undefined||value===null)return[];return Array.isArray(value)?value:[value];}
|
|
147
|
+
function strings(value){return array(value).map((entry)=>String(entry??'')).filter(Boolean);}
|
|
148
|
+
function uniqueStrings(values){return uniqueRawStrings((values??[]).filter((entry)=>entry!==undefined&&entry!==null&&String(entry)!==''));}
|
|
149
|
+
function firstString(...values){return values.map((value)=>value===undefined||value===null?'':String(value)).find(Boolean);}
|
|
150
|
+
function compactRecord(value){return Object.fromEntries(Object.entries(value??{}).filter(([,entry])=>entry!==undefined&&(!Array.isArray(entry)||entry.length>0)));}
|
|
151
|
+
function nonEmptyRecord(value){return Object.keys(value??{}).length?value:undefined;}
|