@shapeshift-labs/frontier-lang-compiler 0.2.48 → 0.2.49
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 +18 -0
- package/bench/native-transform-suite.mjs +11 -0
- package/bench/smoke.mjs +3 -0
- package/dist/declarations/runtime.d.ts +6 -0
- package/dist/declarations/universal-conversion-plan.d.ts +203 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/internal/index-impl/createUniversalConversionPlan.js +5 -0
- package/dist/internal/index-impl/queryUniversalConversionPlan.js +5 -0
- package/dist/universal-conversion-plan-merge-refs.js +125 -0
- package/dist/universal-conversion-plan-scoring.js +134 -0
- package/dist/universal-conversion-plan.js +279 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -129,6 +129,8 @@ import {
|
|
|
129
129
|
createNativeParserAstFormatMatrix,
|
|
130
130
|
createProjectionTargetLossMatrix,
|
|
131
131
|
createUniversalCapabilityMatrix,
|
|
132
|
+
createUniversalConversionPlan,
|
|
133
|
+
queryUniversalConversionPlan,
|
|
132
134
|
importNativeSource
|
|
133
135
|
} from '@shapeshift-labs/frontier-lang-compiler';
|
|
134
136
|
|
|
@@ -162,6 +164,20 @@ const pythonUniversal = universalMatrix.languages.find((entry) => entry.language
|
|
|
162
164
|
|
|
163
165
|
console.log(pythonUniversal.readiness); // combined import/parser/projection readiness
|
|
164
166
|
console.log(pythonUniversal.blockers); // missing evidence/adapters that prevent merge admission
|
|
167
|
+
|
|
168
|
+
const conversionPlan = createUniversalConversionPlan({
|
|
169
|
+
imports: [imported],
|
|
170
|
+
targets: ['python', 'rust'],
|
|
171
|
+
requiredFeatures: ['syntax', 'semantic', 'sourcePreservation']
|
|
172
|
+
});
|
|
173
|
+
const pythonToRust = queryUniversalConversionPlan(conversionPlan, {
|
|
174
|
+
sourceLanguage: 'python',
|
|
175
|
+
target: 'rust'
|
|
176
|
+
}).bestRoute;
|
|
177
|
+
|
|
178
|
+
console.log(pythonToRust.mode); // "semantic-index-only", "target-adapter", "stub-only", etc.
|
|
179
|
+
console.log(pythonToRust.missingEvidence); // adapter/proof/source-map gaps for swarm workers
|
|
180
|
+
console.log(pythonToRust.mergeScore.value); // sortable merge-review score, not a proof
|
|
165
181
|
```
|
|
166
182
|
|
|
167
183
|
The projection target matrix separates five runtime/API classes:
|
|
@@ -174,6 +190,8 @@ The projection target matrix separates five runtime/API classes:
|
|
|
174
190
|
|
|
175
191
|
`createUniversalCapabilityMatrix` composes the import coverage, parser AST format, parser feature, and projection target matrices into a single language row per source language. It is the coordinator-facing view for universal-language work: it shows imports, symbols, source-map mappings, parser feature readiness, projection targets, missing adapters, unsupported target features, blockers, and review reasons without claiming lossless conversion where evidence is absent.
|
|
176
192
|
|
|
193
|
+
`createUniversalConversionPlan` turns that capability evidence into coordinator tasks: preserve exact source, run a target adapter, emit stubs, attach semantic-index evidence, or block the route until missing parser/adapter/proof evidence exists. Every route carries `autoMergeClaim: false`, `semanticEquivalenceClaim: false`, missing evidence, task hints, and a `frontier.lang.semanticMergeScore.v1` score for swarm merge admission.
|
|
194
|
+
|
|
177
195
|
Preserve exact native source text, token/trivia hashes, comments, whitespace, and source directives as evidence. This does not claim full semantic understanding; it keeps round-trip material available while exact parser adapters catch up:
|
|
178
196
|
|
|
179
197
|
```js
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
createSemanticImportSidecar,
|
|
6
6
|
createSemanticSlice,
|
|
7
7
|
createSemanticSliceAdmissionRecord,
|
|
8
|
+
createUniversalConversionPlan,
|
|
8
9
|
projectNativeImportToSource,
|
|
9
10
|
summarizeNativeImportFeatureEvidence,
|
|
10
11
|
testSemanticSlice
|
|
@@ -47,6 +48,13 @@ export function measureNativeTransformations(nativeImportResults) {
|
|
|
47
48
|
}));
|
|
48
49
|
const sliceAdmissionDurationMs = performance.now() - sliceAdmissionStart;
|
|
49
50
|
|
|
51
|
+
const conversionPlanStart = performance.now();
|
|
52
|
+
const conversionPlan = createUniversalConversionPlan({
|
|
53
|
+
imports: nativeImportResults.slice(0, 100),
|
|
54
|
+
targets: ['javascript', 'rust', 'python']
|
|
55
|
+
});
|
|
56
|
+
const conversionPlanDurationMs = performance.now() - conversionPlanStart;
|
|
57
|
+
|
|
50
58
|
const featureEvidenceStart = performance.now();
|
|
51
59
|
const featureEvidenceSummaries = nativeImportResults.map((imported) => summarizeNativeImportFeatureEvidence(imported.losses, {
|
|
52
60
|
evidence: imported.evidence
|
|
@@ -77,6 +85,9 @@ export function measureNativeTransformations(nativeImportResults) {
|
|
|
77
85
|
sliceGateFailures,
|
|
78
86
|
sliceAdmissions: semanticSliceAdmissions.length,
|
|
79
87
|
sliceAdmissionRejected: semanticSliceAdmissions.filter((admission) => admission.action === 'reject').length,
|
|
88
|
+
conversionPlanRoutes: conversionPlan.routes.length,
|
|
89
|
+
conversionPlanBlocked: conversionPlan.summary.blockedRoutes,
|
|
90
|
+
conversionPlanDurationMs,
|
|
80
91
|
featureEvidencePolicyMatches,
|
|
81
92
|
featureEvidenceDurationMs,
|
|
82
93
|
nativeProjections: nativeProjections.length,
|
package/bench/smoke.mjs
CHANGED
|
@@ -57,6 +57,9 @@ console.log(JSON.stringify({
|
|
|
57
57
|
sliceGateFailures: transformMetrics.sliceGateFailures,
|
|
58
58
|
sliceAdmissions: transformMetrics.sliceAdmissions,
|
|
59
59
|
sliceAdmissionRejected: transformMetrics.sliceAdmissionRejected,
|
|
60
|
+
conversionPlanRoutes: transformMetrics.conversionPlanRoutes,
|
|
61
|
+
conversionPlanBlocked: transformMetrics.conversionPlanBlocked,
|
|
62
|
+
conversionPlanDurationMs: Number(transformMetrics.conversionPlanDurationMs.toFixed(2)),
|
|
60
63
|
featureEvidencePolicyMatches: transformMetrics.featureEvidencePolicyMatches,
|
|
61
64
|
featureEvidenceDurationMs: Number(transformMetrics.featureEvidenceDurationMs.toFixed(2)),
|
|
62
65
|
nativeProjections: transformMetrics.nativeProjections,
|
|
@@ -37,6 +37,7 @@ import type { NativeParserFeatureCategory, NativeParserFeatureCoverageStatus, Na
|
|
|
37
37
|
import type { NativeImportCoverageLanguage, NativeImportCoverageMatrix, NativeImportCoverageMatrixOptions } from './native-import-coverage.js';
|
|
38
38
|
import type { ProjectionTargetLossClass, ProjectionSourceProjectionCoverage, ProjectionTargetCoverageEntry, ProjectionTargetLanguageCoverage, ProjectionTargetLossMatrix, ProjectionTargetLossMatrixOptions } from './projection-coverage.js';
|
|
39
39
|
import type { UniversalCapabilityLanguageRow, UniversalCapabilityMatrix, UniversalCapabilityMatrixOptions } from './universal-capability.js';
|
|
40
|
+
import type { UniversalConversionPlan, UniversalConversionPlanOptions, UniversalConversionPlanQuery, UniversalConversionPlanQueryResult } from './universal-conversion-plan.js';
|
|
40
41
|
import type { UniversalDialectRegistry, UniversalDialectRegistryInput, UniversalDialectRecordInput, UniversalExternRecordInput } from './universal-dialects.js';
|
|
41
42
|
import type { NativeImportContractSource, NativeImportSourcePreservationRecordSummary, NativeImportSourcePreservationContract, NativeImportAdapterCoverageRecordSummary, NativeImportAdapterCoverageContract, NativeImportRegionSummary, NativeImportSourceMapSummary, NativeImportReadinessContract, NativeImportResultContract, NativeImportResultContractOptions } from './native-import-contracts.js';
|
|
42
43
|
import type { NativeSourceTokenKind, NativeSourcePreservedToken, NativeSourcePreservedDirective, NativeSourcePreservation, CreateNativeSourcePreservationOptions } from './source-preservation.js';
|
|
@@ -87,6 +88,11 @@ export declare function createNativeParserFeatureMatrix(options?: NativeParserFe
|
|
|
87
88
|
export declare function queryNativeParserFeatureMatrix(matrixOrOptions?: NativeParserFeatureMatrix | NativeParserFeatureMatrixOptions, query?: NativeParserFeatureMatrixQuery): NativeParserFeatureMatrixQueryResult;
|
|
88
89
|
export declare function createProjectionTargetLossMatrix(options?: ProjectionTargetLossMatrixOptions): ProjectionTargetLossMatrix;
|
|
89
90
|
export declare function createUniversalCapabilityMatrix(options?: UniversalCapabilityMatrixOptions): UniversalCapabilityMatrix;
|
|
91
|
+
export declare function createUniversalConversionPlan(options?: UniversalConversionPlanOptions): UniversalConversionPlan;
|
|
92
|
+
export declare function queryUniversalConversionPlan(
|
|
93
|
+
planOrOptions?: UniversalConversionPlan | UniversalConversionPlanOptions,
|
|
94
|
+
query?: UniversalConversionPlanQuery
|
|
95
|
+
): UniversalConversionPlanQueryResult;
|
|
90
96
|
export declare function createNativeSourcePreservation(options: CreateNativeSourcePreservationOptions): NativeSourcePreservation;
|
|
91
97
|
export declare function createSemanticImportSidecar(importResult: NativeSourceImportResult | NativeProjectImportResult, options?: SemanticImportSidecarOptions): SemanticImportSidecar;
|
|
92
98
|
export declare function createNativeImportResultContract(importResult: NativeSourceImportResult | NativeProjectImportResult, options?: NativeImportResultContractOptions): NativeImportResultContract;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
EvidenceRecord,
|
|
3
|
+
FrontierSourceLanguage,
|
|
4
|
+
SemanticMergeReadiness
|
|
5
|
+
} from '@shapeshift-labs/frontier-lang-kernel';
|
|
6
|
+
import type { FrontierCompileTarget } from './compile.js';
|
|
7
|
+
import type { NativeImportKnownLossKind } from './native-import-losses.js';
|
|
8
|
+
import type { NativeParserFeatureCategory } from './native-parser-features.js';
|
|
9
|
+
import type { ProjectionSourceProjectionCoverage, ProjectionTargetCoverageEntry } from './projection-coverage.js';
|
|
10
|
+
import type { ProjectionReadinessTargetCell } from './projection-readiness.js';
|
|
11
|
+
import type { UniversalCapabilityMatrix, UniversalCapabilityMatrixOptions } from './universal-capability.js';
|
|
12
|
+
|
|
13
|
+
export type UniversalConversionRouteMode =
|
|
14
|
+
| 'preserve-source'
|
|
15
|
+
| 'target-adapter'
|
|
16
|
+
| 'stub-only'
|
|
17
|
+
| 'semantic-index-only'
|
|
18
|
+
| 'blocked';
|
|
19
|
+
|
|
20
|
+
export type UniversalConversionRouteAction =
|
|
21
|
+
| 'preserve-source'
|
|
22
|
+
| 'run-target-adapter'
|
|
23
|
+
| 'attach-adapter-evidence'
|
|
24
|
+
| 'emit-stub'
|
|
25
|
+
| 'add-target-adapter'
|
|
26
|
+
| 'blocked';
|
|
27
|
+
|
|
28
|
+
export type UniversalConversionAdmissionAction = 'admit' | 'prioritize' | 'reject';
|
|
29
|
+
export type UniversalConversionPriority = 'low' | 'normal' | 'high' | 'blocker';
|
|
30
|
+
export type UniversalConversionRisk = 'low' | 'medium' | 'high';
|
|
31
|
+
|
|
32
|
+
export type UniversalConversionScoreComponentKey =
|
|
33
|
+
| 'importEvidence'
|
|
34
|
+
| 'parserEvidence'
|
|
35
|
+
| 'semanticIndex'
|
|
36
|
+
| 'projectionPath'
|
|
37
|
+
| 'proofEvidence';
|
|
38
|
+
|
|
39
|
+
export interface UniversalConversionScoreComponent {
|
|
40
|
+
readonly key: UniversalConversionScoreComponentKey;
|
|
41
|
+
readonly score: number;
|
|
42
|
+
readonly weight: number;
|
|
43
|
+
readonly weightedScore: number;
|
|
44
|
+
readonly status: 'strong' | 'partial' | 'weak' | 'blocked';
|
|
45
|
+
readonly reasons: readonly string[];
|
|
46
|
+
readonly signals: Record<string, unknown>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface UniversalConversionMergeScore {
|
|
50
|
+
readonly schema: 'frontier.lang.semanticMergeScore.v1';
|
|
51
|
+
readonly version: 1;
|
|
52
|
+
readonly value: number;
|
|
53
|
+
readonly uncappedValue: number;
|
|
54
|
+
readonly sortKey: number;
|
|
55
|
+
readonly higherIsBetter: true;
|
|
56
|
+
readonly readiness: SemanticMergeReadiness;
|
|
57
|
+
readonly risk: UniversalConversionRisk;
|
|
58
|
+
readonly action: UniversalConversionAdmissionAction;
|
|
59
|
+
readonly components: Readonly<Record<UniversalConversionScoreComponentKey, UniversalConversionScoreComponent>>;
|
|
60
|
+
readonly penalties: readonly string[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface UniversalConversionRouteEvidence {
|
|
64
|
+
readonly imports: number;
|
|
65
|
+
readonly importReadiness: SemanticMergeReadiness;
|
|
66
|
+
readonly symbols: number;
|
|
67
|
+
readonly sourceMaps: number;
|
|
68
|
+
readonly sourceMapMappings: number;
|
|
69
|
+
readonly losses: number;
|
|
70
|
+
readonly parserRows: number;
|
|
71
|
+
readonly mergeReadyParsers: number;
|
|
72
|
+
readonly exactSourceImports: number;
|
|
73
|
+
readonly declarationImports: number;
|
|
74
|
+
readonly targetSupported: boolean;
|
|
75
|
+
readonly targetAdapter?: string;
|
|
76
|
+
readonly targetLossKinds: readonly NativeImportKnownLossKind[];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface UniversalConversionRouteMergeRefs {
|
|
80
|
+
readonly planId: string;
|
|
81
|
+
readonly routeId: string;
|
|
82
|
+
readonly historyIds: readonly string[];
|
|
83
|
+
readonly patchBundleIds: readonly string[];
|
|
84
|
+
readonly patchIds: readonly string[];
|
|
85
|
+
readonly mergeCandidateIds: readonly string[];
|
|
86
|
+
readonly replayLinks: readonly unknown[];
|
|
87
|
+
readonly evidenceIds: readonly string[];
|
|
88
|
+
readonly proofIds: readonly string[];
|
|
89
|
+
readonly sources: readonly {
|
|
90
|
+
readonly sourceId?: string;
|
|
91
|
+
readonly importId?: string;
|
|
92
|
+
readonly sourcePath?: string;
|
|
93
|
+
readonly sourceHash?: string;
|
|
94
|
+
readonly baseHash?: string;
|
|
95
|
+
readonly targetHash?: string;
|
|
96
|
+
}[];
|
|
97
|
+
readonly semanticOwnershipKeys: readonly string[];
|
|
98
|
+
readonly conflictKeys: readonly string[];
|
|
99
|
+
readonly sourceMapIds: readonly string[];
|
|
100
|
+
readonly sourceMapMappingIds: readonly string[];
|
|
101
|
+
readonly sourceMapLinkIds: readonly string[];
|
|
102
|
+
readonly readiness: SemanticMergeReadiness;
|
|
103
|
+
readonly admissionStatus: UniversalConversionAdmissionAction;
|
|
104
|
+
readonly metadata: Record<string, unknown>;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface UniversalConversionRoute {
|
|
108
|
+
readonly id: string;
|
|
109
|
+
readonly sourceLanguage: FrontierSourceLanguage | string;
|
|
110
|
+
readonly languageIds: readonly string[];
|
|
111
|
+
readonly target: FrontierCompileTarget | string;
|
|
112
|
+
readonly mode: UniversalConversionRouteMode;
|
|
113
|
+
readonly routeAction: UniversalConversionRouteAction;
|
|
114
|
+
readonly admissionAction: UniversalConversionAdmissionAction;
|
|
115
|
+
readonly priority: UniversalConversionPriority;
|
|
116
|
+
readonly readiness: SemanticMergeReadiness;
|
|
117
|
+
readonly lossClass: string;
|
|
118
|
+
readonly adapter?: string;
|
|
119
|
+
readonly adapterKind?: string;
|
|
120
|
+
readonly sourceProjection?: {
|
|
121
|
+
readonly exactSource: ProjectionSourceProjectionCoverage;
|
|
122
|
+
readonly stubs: ProjectionSourceProjectionCoverage;
|
|
123
|
+
};
|
|
124
|
+
readonly projectionReadiness?: ProjectionReadinessTargetCell;
|
|
125
|
+
readonly evidence: UniversalConversionRouteEvidence;
|
|
126
|
+
readonly missingEvidence: readonly string[];
|
|
127
|
+
readonly blockers: readonly string[];
|
|
128
|
+
readonly review: readonly string[];
|
|
129
|
+
readonly tasks: readonly string[];
|
|
130
|
+
readonly mergeScore: UniversalConversionMergeScore;
|
|
131
|
+
readonly mergeRefs: UniversalConversionRouteMergeRefs;
|
|
132
|
+
readonly autoMergeClaim: false;
|
|
133
|
+
readonly semanticEquivalenceClaim: false;
|
|
134
|
+
readonly metadata: Record<string, unknown>;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface UniversalConversionPlan {
|
|
138
|
+
readonly kind: 'frontier.lang.universalConversionPlan';
|
|
139
|
+
readonly version: 1;
|
|
140
|
+
readonly id: string;
|
|
141
|
+
readonly generatedAt: number;
|
|
142
|
+
readonly routes: readonly UniversalConversionRoute[];
|
|
143
|
+
readonly summary: {
|
|
144
|
+
readonly routes: number;
|
|
145
|
+
readonly byMode: Readonly<Record<UniversalConversionRouteMode, number>>;
|
|
146
|
+
readonly byReadiness: Readonly<Record<SemanticMergeReadiness, number>>;
|
|
147
|
+
readonly byAdmissionAction: Readonly<Record<UniversalConversionAdmissionAction, number>>;
|
|
148
|
+
readonly readyRoutes: number;
|
|
149
|
+
readonly reviewRoutes: number;
|
|
150
|
+
readonly blockedRoutes: number;
|
|
151
|
+
readonly preserveSourceRoutes: number;
|
|
152
|
+
readonly targetAdapterRoutes: number;
|
|
153
|
+
readonly stubOnlyRoutes: number;
|
|
154
|
+
readonly semanticIndexOnlyRoutes: number;
|
|
155
|
+
readonly missingEvidence: number;
|
|
156
|
+
readonly blockers: number;
|
|
157
|
+
readonly reviewReasons: number;
|
|
158
|
+
readonly autoMergeClaims: 0;
|
|
159
|
+
readonly semanticEquivalenceClaims: 0;
|
|
160
|
+
};
|
|
161
|
+
readonly matrices: {
|
|
162
|
+
readonly universalCapability: UniversalCapabilityMatrix;
|
|
163
|
+
readonly projectionReadiness?: UniversalCapabilityMatrix['matrices']['projectionReadiness'];
|
|
164
|
+
readonly projectionTargets?: UniversalCapabilityMatrix['matrices']['projectionTargets'];
|
|
165
|
+
};
|
|
166
|
+
readonly metadata: {
|
|
167
|
+
readonly compileTargets: readonly (FrontierCompileTarget | string)[];
|
|
168
|
+
readonly requiredFeatures: readonly NativeParserFeatureCategory[];
|
|
169
|
+
readonly autoMergeClaim: false;
|
|
170
|
+
readonly semanticEquivalenceClaim: false;
|
|
171
|
+
readonly note: string;
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export interface UniversalConversionPlanOptions extends UniversalCapabilityMatrixOptions {
|
|
176
|
+
readonly id?: string;
|
|
177
|
+
readonly universalCapabilityMatrix?: UniversalCapabilityMatrix;
|
|
178
|
+
readonly evidence?: readonly EvidenceRecord[];
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export interface UniversalConversionPlanQuery {
|
|
182
|
+
readonly sourceLanguage?: FrontierSourceLanguage | string;
|
|
183
|
+
readonly language?: FrontierSourceLanguage | string;
|
|
184
|
+
readonly target?: FrontierCompileTarget | string;
|
|
185
|
+
readonly mode?: UniversalConversionRouteMode;
|
|
186
|
+
readonly readiness?: SemanticMergeReadiness;
|
|
187
|
+
readonly admissionAction?: UniversalConversionAdmissionAction;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export interface UniversalConversionPlanQueryResult {
|
|
191
|
+
readonly kind: 'frontier.lang.universalConversionPlanQuery';
|
|
192
|
+
readonly version: 1;
|
|
193
|
+
readonly found: boolean;
|
|
194
|
+
readonly routes: readonly UniversalConversionRoute[];
|
|
195
|
+
readonly bestRoute?: UniversalConversionRoute;
|
|
196
|
+
readonly reasons: readonly string[];
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export declare function createUniversalConversionPlan(options?: UniversalConversionPlanOptions): UniversalConversionPlan;
|
|
200
|
+
export declare function queryUniversalConversionPlan(
|
|
201
|
+
planOrOptions?: UniversalConversionPlan | UniversalConversionPlanOptions,
|
|
202
|
+
query?: UniversalConversionPlanQuery
|
|
203
|
+
): UniversalConversionPlanQueryResult;
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export * from './declarations/native-import-coverage.js';
|
|
|
6
6
|
export * from './declarations/projection-coverage.js';
|
|
7
7
|
export * from './declarations/projection-readiness.js';
|
|
8
8
|
export * from './declarations/universal-capability.js';
|
|
9
|
+
export * from './declarations/universal-conversion-plan.js';
|
|
9
10
|
export * from './declarations/universal-dialects.js';
|
|
10
11
|
export * from './declarations/language-adapter-package-contracts.js';
|
|
11
12
|
export * from './declarations/native-import-contracts.js';
|
package/dist/index.js
CHANGED
|
@@ -29,6 +29,7 @@ export { createTreeSitterNativeImporterAdapter } from './internal/index-impl/cre
|
|
|
29
29
|
export { createTypeScriptCompilerNativeImporterAdapter } from './internal/index-impl/createTypeScriptCompilerNativeImporterAdapter.js';
|
|
30
30
|
export { createUniversalAstFromDocument } from './internal/index-impl/createUniversalAstFromDocument.js';
|
|
31
31
|
export { createUniversalCapabilityMatrix } from './internal/index-impl/createUniversalCapabilityMatrix.js';
|
|
32
|
+
export { createUniversalConversionPlan } from './internal/index-impl/createUniversalConversionPlan.js';
|
|
32
33
|
export { attachUniversalDialectRegistry, createUniversalDialectRecord, createUniversalDialectRegistry, createUniversalExternRecord, summarizeUniversalDialectRegistry, UniversalDialectConstructKinds, UniversalDialectProjectionDispositions } from './universal-dialect-registry.js';
|
|
33
34
|
export { diffNativeSourceImports } from './internal/index-impl/diffNativeSourceImports.js';
|
|
34
35
|
export { diffNativeSources } from './internal/index-impl/diffNativeSources.js';
|
|
@@ -62,6 +63,7 @@ export { queryNativeParserFeatureMatrix } from './internal/index-impl/queryNativ
|
|
|
62
63
|
export { queryProjectionReadinessMatrix } from './internal/index-impl/queryProjectionReadinessMatrix.js';
|
|
63
64
|
export { createSemanticPatchBundleRecord, querySemanticPatchBundleRecords, SemanticPatchBundleAdmissionStatuses } from './internal/index-impl/semanticPatchBundleRecords.js';
|
|
64
65
|
export { querySemanticMergeConflictClasses, SemanticMergeConflictClasses, semanticMergeConflictRiskScore, sortSemanticMergeCandidatesByConflictRisk, summarizeSemanticMergeConflicts } from './internal/index-impl/semanticMergeConflicts.js';
|
|
66
|
+
export { queryUniversalConversionPlan } from './internal/index-impl/queryUniversalConversionPlan.js';
|
|
65
67
|
export { createSemanticHistoryRecord, querySemanticHistoryRecordOverlaps, SemanticHistoryAdmissionStatuses, SemanticHistoryConflictReasons, SemanticHistoryOverlapKinds, SemanticHistoryReviewerStatuses, semanticHistoryRecordsConflict, semanticHistoryRecordsOverlap } from './internal/index-impl/semanticHistoryRecords.js';
|
|
66
68
|
export { readSemanticSliceJson } from './internal/index-impl/readSemanticSliceJson.js';
|
|
67
69
|
export { readUniversalAstJson } from './internal/index-impl/readUniversalAstJson.js';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{createUniversalConversionPlan as createUniversalConversionPlanImpl}from'../../universal-conversion-plan.js';
|
|
2
|
+
import{coverageMatrixContext}from'./coverageMatrixContext.js';
|
|
3
|
+
export function createUniversalConversionPlan(input = {}) {
|
|
4
|
+
return createUniversalConversionPlanImpl(input, coverageMatrixContext());
|
|
5
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{queryUniversalConversionPlan as queryUniversalConversionPlanImpl}from'../../universal-conversion-plan.js';
|
|
2
|
+
import{coverageMatrixContext}from'./coverageMatrixContext.js';
|
|
3
|
+
export function queryUniversalConversionPlan(planOrInput = {}, query = {}) {
|
|
4
|
+
return queryUniversalConversionPlanImpl(planOrInput, query, coverageMatrixContext());
|
|
5
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import {
|
|
2
|
+
idFragment,
|
|
3
|
+
normalizeNativeLanguageId,
|
|
4
|
+
uniqueStrings
|
|
5
|
+
} from './native-import-utils.js';
|
|
6
|
+
|
|
7
|
+
export function importsForConversionLanguage(imports, language) {
|
|
8
|
+
const ids = new Set([language?.language, ...(language?.aliases ?? [])].map(normalizeNativeLanguageId).filter(Boolean));
|
|
9
|
+
return (imports ?? []).filter((imported) => ids.has(normalizeNativeLanguageId(imported?.language ?? imported?.nativeAst?.language)));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function conversionMergeRefs(input) {
|
|
13
|
+
const routeImports = input.imports ?? [];
|
|
14
|
+
const routeId = input.routeId;
|
|
15
|
+
const sourceMaps = routeImports.flatMap(sourceMapsForImport);
|
|
16
|
+
return {
|
|
17
|
+
planId: input.planId,
|
|
18
|
+
routeId,
|
|
19
|
+
historyIds: [`history_${routeId}`],
|
|
20
|
+
patchBundleIds: [],
|
|
21
|
+
patchIds: [],
|
|
22
|
+
mergeCandidateIds: uniqueStrings(routeImports.flatMap(mergeCandidateIds)),
|
|
23
|
+
replayLinks: routeImports.flatMap((imported) => imported?.replayLinks ?? imported?.universalAst?.replayLinks ?? []),
|
|
24
|
+
evidenceIds: uniqueStrings(routeImports.flatMap((imported) => evidenceRecords(imported).map((record) => record.id))),
|
|
25
|
+
proofIds: uniqueStrings(routeImports.flatMap(proofIdsForImport)),
|
|
26
|
+
sources: routeImports.map(conversionSourceRef),
|
|
27
|
+
semanticOwnershipKeys: uniqueStrings(routeImports.flatMap(semanticOwnershipKeysForImport)),
|
|
28
|
+
conflictKeys: uniqueStrings(routeImports.flatMap(conflictKeysForImport)),
|
|
29
|
+
sourceMapIds: uniqueStrings(sourceMaps.map((sourceMap) => sourceMap?.id)),
|
|
30
|
+
sourceMapMappingIds: uniqueStrings(sourceMaps.flatMap((sourceMap) => (sourceMap?.mappings ?? []).map((mapping) => mapping.id))),
|
|
31
|
+
sourceMapLinkIds: [],
|
|
32
|
+
readiness: input.readiness,
|
|
33
|
+
admissionStatus: input.admissionStatus,
|
|
34
|
+
metadata: {
|
|
35
|
+
plannedHistoryId: true,
|
|
36
|
+
note: 'Merge refs are compact route provenance for semantic history and patch-bundle builders; planned IDs are not proof records until materialized.'
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function conversionSourceRef(imported) {
|
|
42
|
+
return {
|
|
43
|
+
sourceId: imported?.nativeSource?.id ?? imported?.id,
|
|
44
|
+
importId: imported?.id,
|
|
45
|
+
sourcePath: imported?.sourcePath ?? imported?.nativeSource?.sourcePath,
|
|
46
|
+
sourceHash: imported?.sourceHash
|
|
47
|
+
?? imported?.nativeSource?.sourceHash
|
|
48
|
+
?? imported?.metadata?.sourcePreservation?.sourceHash,
|
|
49
|
+
baseHash: imported?.baseHash ?? imported?.metadata?.baseHash,
|
|
50
|
+
targetHash: imported?.targetHash ?? imported?.metadata?.targetHash
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function evidenceRecords(imported) {
|
|
55
|
+
return [
|
|
56
|
+
...(imported?.evidence ?? []),
|
|
57
|
+
...(imported?.universalAst?.evidence ?? []),
|
|
58
|
+
...(imported?.patch?.evidence ?? [])
|
|
59
|
+
].filter((record) => record?.id);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function proofIdsForImport(imported) {
|
|
63
|
+
return [
|
|
64
|
+
...(imported?.proofIds ?? []),
|
|
65
|
+
...evidenceRecords(imported).filter((record) => record?.kind === 'proof' || record?.type === 'proof').map((record) => record.id)
|
|
66
|
+
];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function mergeCandidateIds(imported) {
|
|
70
|
+
return (imported?.mergeCandidates ?? []).map((candidate) => candidate.id);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function sourceMapsForImport(imported) {
|
|
74
|
+
return [
|
|
75
|
+
...(imported?.sourceMaps ?? []),
|
|
76
|
+
...(imported?.universalAst?.sourceMaps ?? [])
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function semanticOwnershipKeysForImport(imported) {
|
|
81
|
+
return uniqueStrings([
|
|
82
|
+
...ownershipKeysFromCandidates(imported),
|
|
83
|
+
...ownershipKeysFromSourceMaps(imported),
|
|
84
|
+
...ownershipKeysFromSymbols(imported)
|
|
85
|
+
]);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function conflictKeysForImport(imported) {
|
|
89
|
+
return uniqueStrings([
|
|
90
|
+
...conflictKeysFromCandidates(imported),
|
|
91
|
+
...ownershipKeysFromSourceMaps(imported)
|
|
92
|
+
]);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function ownershipKeysFromCandidates(imported) {
|
|
96
|
+
return uniqueStrings((imported?.mergeCandidates ?? []).flatMap((candidate) => [
|
|
97
|
+
...(candidate?.ownershipKeys ?? []),
|
|
98
|
+
...(candidate?.semanticOwnershipKeys ?? []),
|
|
99
|
+
...(candidate?.changedRegions ?? []).map((region) => region?.key)
|
|
100
|
+
]));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function conflictKeysFromCandidates(imported) {
|
|
104
|
+
return uniqueStrings((imported?.mergeCandidates ?? []).flatMap((candidate) => [
|
|
105
|
+
...(candidate?.conflictKeys ?? []),
|
|
106
|
+
...(candidate?.changedRegions ?? []).flatMap((region) => [region?.conflictKey, ...(region?.admission?.conflictKeys ?? [])])
|
|
107
|
+
]));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function ownershipKeysFromSourceMaps(imported) {
|
|
111
|
+
return uniqueStrings(sourceMapsForImport(imported).flatMap((sourceMap) => (sourceMap?.mappings ?? []).flatMap((mapping) => [
|
|
112
|
+
mapping?.ownershipRegionKey,
|
|
113
|
+
mapping?.ownershipRegionId,
|
|
114
|
+
mapping?.ownershipRegionKind ? `${mapping.sourceSpan?.path ?? imported?.sourcePath ?? 'source'}#${mapping.ownershipRegionKind}` : undefined
|
|
115
|
+
])));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function ownershipKeysFromSymbols(imported) {
|
|
119
|
+
const symbols = imported?.semanticIndex?.symbols ?? imported?.universalAst?.semanticIndex?.symbols ?? [];
|
|
120
|
+
return uniqueStrings(symbols.flatMap((symbol) => [
|
|
121
|
+
symbol?.metadata?.ownershipRegionKey,
|
|
122
|
+
symbol?.metadata?.ownershipRegionId,
|
|
123
|
+
symbol?.metadata?.ownershipRegionKind ? `${symbol.language ?? imported?.language ?? 'source'}#${idFragment(symbol.name)}#${symbol.metadata.ownershipRegionKind}` : undefined
|
|
124
|
+
]));
|
|
125
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { uniqueStrings } from './native-import-utils.js';
|
|
2
|
+
|
|
3
|
+
const readinessScore = Object.freeze({ ready: 100, 'ready-with-losses': 76, 'needs-review': 48, blocked: 0 });
|
|
4
|
+
const readinessRank = Object.freeze({ ready: 3, 'ready-with-losses': 2, 'needs-review': 1, blocked: 0 });
|
|
5
|
+
const actionRank = Object.freeze({ admit: 2, prioritize: 1, reject: 0 });
|
|
6
|
+
const modeRank = Object.freeze({
|
|
7
|
+
'preserve-source': 5,
|
|
8
|
+
'target-adapter': 4,
|
|
9
|
+
'stub-only': 3,
|
|
10
|
+
'semantic-index-only': 2,
|
|
11
|
+
blocked: 0
|
|
12
|
+
});
|
|
13
|
+
const componentWeights = Object.freeze({
|
|
14
|
+
importEvidence: 22,
|
|
15
|
+
parserEvidence: 18,
|
|
16
|
+
semanticIndex: 18,
|
|
17
|
+
projectionPath: 24,
|
|
18
|
+
proofEvidence: 18
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export function conversionScoreComponents(language, targetCell, readiness, mode, evidence) {
|
|
22
|
+
return {
|
|
23
|
+
importEvidence: scoreComponent('importEvidence', readinessScore[language.imports.readiness] ?? 48, [
|
|
24
|
+
...(language.imports.total ? [] : ['No source import evidence.']),
|
|
25
|
+
...(language.imports.readiness === 'ready' ? [] : [`Import readiness is ${language.imports.readiness}.`])
|
|
26
|
+
], { imports: language.imports.total, losses: language.imports.losses }),
|
|
27
|
+
parserEvidence: scoreComponent('parserEvidence', parserScore(language), [
|
|
28
|
+
...(language.parser.rows ? [] : ['No parser feature row matched this language.']),
|
|
29
|
+
...(language.parser.blockingFeatures ?? []).map((feature) => `Parser feature is blocked: ${feature}.`)
|
|
30
|
+
], { rows: language.parser.rows, mergeReadyParsers: language.parser.mergeReadyParsers.length }),
|
|
31
|
+
semanticIndex: scoreComponent('semanticIndex', semanticIndexScore(language), [
|
|
32
|
+
...(language.imports.symbols ? [] : ['No semantic symbols were imported.']),
|
|
33
|
+
...(language.imports.sourceMapMappings ? [] : ['No source-map mappings were imported.'])
|
|
34
|
+
], { symbols: language.imports.symbols, sourceMapMappings: language.imports.sourceMapMappings }),
|
|
35
|
+
projectionPath: scoreComponent('projectionPath', projectionPathScore(targetCell, mode, readiness), projectionPathReasons(targetCell, mode), {
|
|
36
|
+
mode,
|
|
37
|
+
lossClass: targetCell?.lossClass,
|
|
38
|
+
adapter: targetCell?.adapter,
|
|
39
|
+
readiness
|
|
40
|
+
}),
|
|
41
|
+
proofEvidence: scoreComponent('proofEvidence', proofEvidenceScore(evidence), proofEvidenceReasons(evidence), {
|
|
42
|
+
records: evidence.length,
|
|
43
|
+
passed: evidence.filter((record) => passedEvidence(record)).length,
|
|
44
|
+
failed: evidence.filter((record) => record?.status === 'failed').length
|
|
45
|
+
})
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function conversionMergeScore(input) {
|
|
50
|
+
const weighted = Object.values(input.components).reduce((sum, component) => sum + component.weightedScore, 0);
|
|
51
|
+
const weight = Object.values(input.components).reduce((sum, component) => sum + component.weight, 0);
|
|
52
|
+
const uncappedValue = Math.round(weight ? weighted * 100 / weight : 0);
|
|
53
|
+
const action = input.blockers.length || input.readiness === 'blocked' || input.mode === 'blocked' ? 'reject'
|
|
54
|
+
: input.readiness === 'ready' && input.mode !== 'stub-only' && input.mode !== 'semantic-index-only' ? 'admit'
|
|
55
|
+
: 'prioritize';
|
|
56
|
+
const value = action === 'reject' ? Math.min(35, uncappedValue) : uncappedValue;
|
|
57
|
+
return {
|
|
58
|
+
schema: 'frontier.lang.semanticMergeScore.v1',
|
|
59
|
+
version: 1,
|
|
60
|
+
value,
|
|
61
|
+
uncappedValue,
|
|
62
|
+
sortKey: value + (actionRank[action] ?? 0) * 1000 + (modeRank[input.mode] ?? 0) * 100 + (readinessRank[input.readiness] ?? 0) * 10,
|
|
63
|
+
higherIsBetter: true,
|
|
64
|
+
readiness: input.readiness,
|
|
65
|
+
risk: input.readiness === 'blocked' ? 'high' : input.readiness === 'needs-review' ? 'medium' : 'low',
|
|
66
|
+
action,
|
|
67
|
+
components: input.components,
|
|
68
|
+
penalties: uniqueStrings([
|
|
69
|
+
...(action === 'reject' ? ['Conversion route is rejected until blockers are resolved.'] : []),
|
|
70
|
+
...Object.values(input.components).flatMap((component) => component.score < 100 ? component.reasons : [])
|
|
71
|
+
])
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function parserScore(language) {
|
|
76
|
+
if (!language.parser.rows) return 0;
|
|
77
|
+
return Math.min(100, (readinessScore[language.parser.readiness] ?? 48) + Math.min(16, language.parser.mergeReadyParsers.length * 8));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function semanticIndexScore(language) {
|
|
81
|
+
const symbols = language.imports.symbols ?? 0;
|
|
82
|
+
const mappings = language.imports.sourceMapMappings ?? 0;
|
|
83
|
+
if (!symbols) return 0;
|
|
84
|
+
return Math.min(100, 62 + Math.min(22, symbols * 3) + Math.min(16, mappings * 2));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function projectionPathScore(targetCell, mode, readiness) {
|
|
88
|
+
if (mode === 'blocked') return 0;
|
|
89
|
+
if (mode === 'preserve-source') return 92;
|
|
90
|
+
if (mode === 'target-adapter') return Math.min(92, (readinessScore[readiness] ?? 48) + (targetCell?.adapter ? 12 : 0));
|
|
91
|
+
if (mode === 'stub-only') return 44;
|
|
92
|
+
if (mode === 'semantic-index-only') return 30;
|
|
93
|
+
return 10;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function proofEvidenceScore(evidence) {
|
|
97
|
+
if (!evidence.length) return 45;
|
|
98
|
+
const passed = evidence.filter((record) => passedEvidence(record)).length;
|
|
99
|
+
const failed = evidence.filter((record) => record?.status === 'failed').length;
|
|
100
|
+
return Math.max(0, Math.min(100, 55 + passed * 12 - failed * 35));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function projectionPathReasons(targetCell, mode) {
|
|
104
|
+
return uniqueStrings([
|
|
105
|
+
...(targetCell?.reason ? [targetCell.reason] : []),
|
|
106
|
+
...(mode === 'blocked' ? ['Projection path is blocked.'] : []),
|
|
107
|
+
...(mode === 'semantic-index-only' ? ['Semantic index can guide review, but code emission needs a target adapter.'] : [])
|
|
108
|
+
]);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function proofEvidenceReasons(evidence) {
|
|
112
|
+
return uniqueStrings([
|
|
113
|
+
...(!evidence.length ? ['No proof, oracle, test, or replay evidence was attached to this conversion route.'] : []),
|
|
114
|
+
...(evidence.filter((record) => record?.status === 'failed').length ? ['At least one attached evidence record failed.'] : [])
|
|
115
|
+
]);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function scoreComponent(key, score, reasons, signals) {
|
|
119
|
+
const normalized = Math.max(0, Math.min(100, Math.round(score)));
|
|
120
|
+
const weight = componentWeights[key];
|
|
121
|
+
return {
|
|
122
|
+
key,
|
|
123
|
+
score: normalized,
|
|
124
|
+
weight,
|
|
125
|
+
weightedScore: normalized * weight / 100,
|
|
126
|
+
status: normalized >= 80 ? 'strong' : normalized >= 50 ? 'partial' : normalized > 0 ? 'weak' : 'blocked',
|
|
127
|
+
reasons: uniqueStrings(reasons),
|
|
128
|
+
signals
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function passedEvidence(record) {
|
|
133
|
+
return record?.status === 'passed' || record?.status === 'ok' || record?.status === 'success';
|
|
134
|
+
}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import {
|
|
2
|
+
idFragment,
|
|
3
|
+
maxSemanticMergeReadiness,
|
|
4
|
+
normalizeNativeLanguageId,
|
|
5
|
+
uniqueStrings
|
|
6
|
+
} from './native-import-utils.js';
|
|
7
|
+
import {
|
|
8
|
+
nativeLanguageCompileTarget,
|
|
9
|
+
normalizeProjectionMatrixTargets
|
|
10
|
+
} from './coverage-matrix-profiles.js';
|
|
11
|
+
import { createUniversalCapabilityMatrix } from './universal-capability-matrix.js';
|
|
12
|
+
import {
|
|
13
|
+
conversionMergeRefs,
|
|
14
|
+
importsForConversionLanguage
|
|
15
|
+
} from './universal-conversion-plan-merge-refs.js';
|
|
16
|
+
import {
|
|
17
|
+
conversionMergeScore,
|
|
18
|
+
conversionScoreComponents
|
|
19
|
+
} from './universal-conversion-plan-scoring.js';
|
|
20
|
+
|
|
21
|
+
export function createUniversalConversionPlan(input = {}, context = {}) {
|
|
22
|
+
const generatedAt = input.generatedAt ?? Date.now();
|
|
23
|
+
const id = input.id ?? conversionPlanId(input, generatedAt);
|
|
24
|
+
const matrix = input.universalCapabilityMatrix?.kind === 'frontier.lang.universalCapabilityMatrix'
|
|
25
|
+
? input.universalCapabilityMatrix
|
|
26
|
+
: createUniversalCapabilityMatrix({ ...input, generatedAt }, context);
|
|
27
|
+
const targets = conversionTargets(input, matrix, context);
|
|
28
|
+
const evidence = input.evidence ?? [];
|
|
29
|
+
const routes = (matrix.languages ?? []).flatMap((language) => targets.map((target) => conversionRoute(language, target, {
|
|
30
|
+
evidence,
|
|
31
|
+
generatedAt,
|
|
32
|
+
imports: input.imports ?? [],
|
|
33
|
+
matrix
|
|
34
|
+
}, id)));
|
|
35
|
+
return {
|
|
36
|
+
kind: 'frontier.lang.universalConversionPlan',
|
|
37
|
+
version: 1,
|
|
38
|
+
id,
|
|
39
|
+
generatedAt,
|
|
40
|
+
routes,
|
|
41
|
+
summary: conversionPlanSummary(routes),
|
|
42
|
+
matrices: {
|
|
43
|
+
universalCapability: matrix,
|
|
44
|
+
projectionReadiness: matrix.matrices?.projectionReadiness,
|
|
45
|
+
projectionTargets: matrix.matrices?.projectionTargets
|
|
46
|
+
},
|
|
47
|
+
metadata: {
|
|
48
|
+
compileTargets: targets,
|
|
49
|
+
requiredFeatures: matrix.metadata?.requiredFeatures ?? [],
|
|
50
|
+
autoMergeClaim: false,
|
|
51
|
+
semanticEquivalenceClaim: false,
|
|
52
|
+
note: 'Conversion plans rank source-to-target routes and missing evidence for agent coordination. They do not prove semantic equivalence or grant auto-merge.'
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function queryUniversalConversionPlan(planOrInput = {}, query = {}, context = {}) {
|
|
58
|
+
const plan = planOrInput?.kind === 'frontier.lang.universalConversionPlan'
|
|
59
|
+
? planOrInput
|
|
60
|
+
: createUniversalConversionPlan(planOrInput, context);
|
|
61
|
+
const sourceLanguage = normalizeNativeLanguageId(query.sourceLanguage ?? query.language);
|
|
62
|
+
const target = normalizeProjectionMatrixTargets(query.target ? [query.target] : [])[0];
|
|
63
|
+
const routes = (plan.routes ?? []).filter((route) => {
|
|
64
|
+
if (sourceLanguage && !route.languageIds.includes(sourceLanguage)) return false;
|
|
65
|
+
if (target && route.target !== target) return false;
|
|
66
|
+
if (query.mode && route.mode !== query.mode) return false;
|
|
67
|
+
if (query.readiness && route.readiness !== query.readiness) return false;
|
|
68
|
+
if (query.admissionAction && route.admissionAction !== query.admissionAction) return false;
|
|
69
|
+
return true;
|
|
70
|
+
});
|
|
71
|
+
return {
|
|
72
|
+
kind: 'frontier.lang.universalConversionPlanQuery',
|
|
73
|
+
version: 1,
|
|
74
|
+
found: routes.length > 0,
|
|
75
|
+
routes,
|
|
76
|
+
bestRoute: routes.slice().sort((a, b) => b.mergeScore.sortKey - a.mergeScore.sortKey)[0],
|
|
77
|
+
reasons: routes.length ? [] : [`No conversion route matched source=${query.sourceLanguage ?? query.language ?? '*'} target=${query.target ?? '*'}.`]
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function conversionTargets(input, matrix, context) {
|
|
82
|
+
const explicit = normalizeProjectionMatrixTargets(input.targets ?? []);
|
|
83
|
+
if (explicit.length) return explicit;
|
|
84
|
+
const matrixTargets = normalizeProjectionMatrixTargets(matrix.metadata?.compileTargets ?? []);
|
|
85
|
+
if (matrixTargets.length) return matrixTargets;
|
|
86
|
+
return normalizeProjectionMatrixTargets(context.compileTargets ?? []);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function conversionRoute(language, target, input, planId) {
|
|
90
|
+
const sourceTarget = nativeLanguageCompileTarget(language.language, language.aliases) ?? normalizeNativeLanguageId(language.language);
|
|
91
|
+
const targetCell = (language.projection?.targets ?? []).find((entry) => entry.target === target);
|
|
92
|
+
const readinessCell = projectionReadinessCell(input.matrix, language, target);
|
|
93
|
+
const mode = conversionMode(language, target, sourceTarget, targetCell);
|
|
94
|
+
const blockers = conversionBlockers(language, targetCell, mode);
|
|
95
|
+
const review = conversionReviewReasons(language, targetCell, mode);
|
|
96
|
+
const readiness = blockers.length
|
|
97
|
+
? 'blocked'
|
|
98
|
+
: maxSemanticMergeReadiness(language.readiness, targetCell?.readiness ?? readinessCell?.readiness ?? 'needs-review');
|
|
99
|
+
const components = conversionScoreComponents(language, targetCell, readiness, mode, input.evidence);
|
|
100
|
+
const mergeScore = conversionMergeScore({ readiness, mode, components, blockers, review });
|
|
101
|
+
const id = `conversion_${idFragment(language.language)}_to_${idFragment(target)}`;
|
|
102
|
+
const routeImports = importsForConversionLanguage(input.imports, language);
|
|
103
|
+
return {
|
|
104
|
+
id,
|
|
105
|
+
sourceLanguage: language.language,
|
|
106
|
+
languageIds: uniqueStrings([language.language, ...(language.aliases ?? [])].map(normalizeNativeLanguageId)),
|
|
107
|
+
target,
|
|
108
|
+
mode,
|
|
109
|
+
routeAction: conversionRouteAction(mode, targetCell, readiness),
|
|
110
|
+
admissionAction: mergeScore.action,
|
|
111
|
+
priority: conversionPriority(mergeScore.action, readiness, mode),
|
|
112
|
+
readiness,
|
|
113
|
+
lossClass: mode === 'preserve-source' ? 'exactSourceProjection' : targetCell?.lossClass ?? 'missingAdapter',
|
|
114
|
+
adapter: targetCell?.adapter,
|
|
115
|
+
adapterKind: targetCell?.adapterKind,
|
|
116
|
+
sourceProjection: language.projection?.sourceProjection,
|
|
117
|
+
projectionReadiness: readinessCell,
|
|
118
|
+
evidence: conversionEvidence(language, targetCell),
|
|
119
|
+
missingEvidence: conversionMissingEvidence(language, targetCell, mode),
|
|
120
|
+
blockers,
|
|
121
|
+
review,
|
|
122
|
+
tasks: conversionTasks(language, target, mode, blockers, review),
|
|
123
|
+
mergeScore,
|
|
124
|
+
mergeRefs: conversionMergeRefs({
|
|
125
|
+
planId,
|
|
126
|
+
routeId: id,
|
|
127
|
+
imports: routeImports,
|
|
128
|
+
readiness,
|
|
129
|
+
admissionStatus: mergeScore.action
|
|
130
|
+
}),
|
|
131
|
+
autoMergeClaim: false,
|
|
132
|
+
semanticEquivalenceClaim: false,
|
|
133
|
+
metadata: {
|
|
134
|
+
generatedAt: input.generatedAt,
|
|
135
|
+
note: 'Route readiness is merge-review evidence for a conversion attempt, not proof that emitted target code is semantically equivalent.'
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function conversionPlanId(input, generatedAt) {
|
|
141
|
+
const languages = uniqueStrings((input.imports ?? []).map((imported) => imported?.language ?? imported?.nativeAst?.language));
|
|
142
|
+
const targets = normalizeProjectionMatrixTargets(input.targets ?? []);
|
|
143
|
+
return `universal_conversion_plan_${idFragment([...languages, 'to', ...targets, String(generatedAt)].join('_'))}`;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function conversionMode(language, target, sourceTarget, targetCell) {
|
|
147
|
+
const exactSourceImports = language.projection?.sourceProjection?.exactSource?.evidence?.importsWithExactSource ?? 0;
|
|
148
|
+
if (target === sourceTarget && exactSourceImports > 0) return 'preserve-source';
|
|
149
|
+
if (targetCell?.lossClass === 'targetAdapterProjection') return 'target-adapter';
|
|
150
|
+
if (targetCell?.lossClass === 'nativeSourceStubs') return 'stub-only';
|
|
151
|
+
if (targetCell?.lossClass === 'unsupportedTargetFeatures') return 'target-adapter';
|
|
152
|
+
if ((language.imports?.symbols ?? 0) > 0 && targetCell?.lossClass === 'missingAdapter') return 'semantic-index-only';
|
|
153
|
+
return 'blocked';
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function conversionBlockers(language, targetCell, mode) {
|
|
157
|
+
return uniqueStrings([
|
|
158
|
+
...(language.imports.total === 0 ? ['No source import exists for this language.'] : []),
|
|
159
|
+
...(mode === 'blocked' ? ['No viable preserve, adapter, stub, or semantic-index conversion route exists.'] : []),
|
|
160
|
+
...(targetCell?.lossClass === 'missingAdapter' && mode !== 'semantic-index-only' ? [targetCell.reason] : []),
|
|
161
|
+
...(language.blockers ?? []).filter((reason) => !reason.includes('Missing native-to-target projection adapter'))
|
|
162
|
+
]);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function conversionReviewReasons(language, targetCell, mode) {
|
|
166
|
+
return uniqueStrings([
|
|
167
|
+
...(language.review ?? []),
|
|
168
|
+
...(targetCell?.reason ? [targetCell.reason] : []),
|
|
169
|
+
...(mode === 'stub-only' ? ['Route can emit declaration stubs only; executable semantics require a target adapter.'] : []),
|
|
170
|
+
...(mode === 'semantic-index-only' ? ['Route has semantic index evidence but no target code projection adapter.'] : []),
|
|
171
|
+
...(mode === 'target-adapter' ? ['Host target adapter evidence must be reviewed before accepting emitted target code.'] : [])
|
|
172
|
+
]);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function projectionReadinessCell(matrix, language, target) {
|
|
176
|
+
const ids = uniqueStrings([language.language, ...(language.aliases ?? [])].map(normalizeNativeLanguageId));
|
|
177
|
+
return (matrix.matrices?.projectionReadiness?.languages ?? [])
|
|
178
|
+
.find((row) => ids.includes(normalizeNativeLanguageId(row.language)))
|
|
179
|
+
?.targets?.find((entry) => entry.target === target);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function conversionRouteAction(mode, targetCell, readiness) {
|
|
183
|
+
if (mode === 'blocked') return 'blocked';
|
|
184
|
+
if (mode === 'preserve-source') return 'preserve-source';
|
|
185
|
+
if (mode === 'stub-only') return 'emit-stub';
|
|
186
|
+
if (mode === 'semantic-index-only') return 'add-target-adapter';
|
|
187
|
+
if (targetCell?.lossClass === 'unsupportedTargetFeatures') return 'attach-adapter-evidence';
|
|
188
|
+
return 'run-target-adapter';
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function conversionPriority(action, readiness, mode) {
|
|
192
|
+
if (action === 'reject' || readiness === 'blocked') return 'blocker';
|
|
193
|
+
if (mode === 'semantic-index-only' || readiness === 'needs-review') return 'high';
|
|
194
|
+
if (mode === 'stub-only' || readiness === 'ready-with-losses') return 'normal';
|
|
195
|
+
return 'low';
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function conversionEvidence(language, targetCell) {
|
|
199
|
+
return {
|
|
200
|
+
imports: language.imports.total,
|
|
201
|
+
importReadiness: language.imports.readiness,
|
|
202
|
+
symbols: language.imports.symbols,
|
|
203
|
+
sourceMaps: language.imports.sourceMaps,
|
|
204
|
+
sourceMapMappings: language.imports.sourceMapMappings,
|
|
205
|
+
losses: language.imports.losses,
|
|
206
|
+
parserRows: language.parser.rows,
|
|
207
|
+
mergeReadyParsers: language.parser.mergeReadyParsers.length,
|
|
208
|
+
exactSourceImports: language.projection?.sourceProjection?.exactSource?.evidence?.importsWithExactSource ?? 0,
|
|
209
|
+
declarationImports: language.projection?.sourceProjection?.stubs?.evidence?.importsWithDeclarations ?? 0,
|
|
210
|
+
targetSupported: targetCell?.supported === true,
|
|
211
|
+
targetAdapter: targetCell?.adapter,
|
|
212
|
+
targetLossKinds: targetCell?.lossKinds ?? []
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function conversionMissingEvidence(language, targetCell, mode) {
|
|
217
|
+
return uniqueStrings([
|
|
218
|
+
...(language.imports.total ? [] : ['source-import']),
|
|
219
|
+
...(language.imports.symbols ? [] : ['semantic-index']),
|
|
220
|
+
...(language.imports.sourceMapMappings ? [] : ['source-map']),
|
|
221
|
+
...(language.parser.mergeReadyParsers.length ? [] : ['merge-ready-parser']),
|
|
222
|
+
...((language.projection?.sourceProjection?.exactSource?.evidence?.importsWithExactSource ?? 0) ? [] : ['source-preservation-hash']),
|
|
223
|
+
...(mode === 'target-adapter' && !targetCell?.adapter ? ['target-adapter-evidence'] : []),
|
|
224
|
+
...(mode === 'semantic-index-only' || targetCell?.lossClass === 'missingAdapter' ? ['target-adapter'] : []),
|
|
225
|
+
...(mode === 'stub-only' ? ['executable-target-semantics'] : []),
|
|
226
|
+
['proof-or-replay-evidence']
|
|
227
|
+
]);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function conversionTasks(language, target, mode, blockers, review) {
|
|
231
|
+
return uniqueStrings([
|
|
232
|
+
...(language.imports.total ? [] : [`import ${language.language} source before planning ${target} output`]),
|
|
233
|
+
...(language.imports.symbols ? [] : [`attach semantic index for ${language.language}`]),
|
|
234
|
+
...(language.parser.mergeReadyParsers.length ? [] : [`provide merge-ready parser evidence for ${language.language}`]),
|
|
235
|
+
...(mode === 'semantic-index-only' || mode === 'blocked' ? [`add ${language.language} to ${target} target adapter`] : []),
|
|
236
|
+
...(mode === 'stub-only' ? [`replace ${target} declaration stubs with executable adapter output`] : []),
|
|
237
|
+
...(mode === 'target-adapter' ? [`run and verify ${language.language} to ${target} target adapter`] : []),
|
|
238
|
+
...(blockers.length || review.length ? [`collect proof, replay, or oracle evidence for ${language.language} to ${target}`] : [])
|
|
239
|
+
]);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function conversionPlanSummary(routes) {
|
|
243
|
+
const summary = {
|
|
244
|
+
routes: routes.length,
|
|
245
|
+
byMode: {},
|
|
246
|
+
byReadiness: {},
|
|
247
|
+
byAdmissionAction: {},
|
|
248
|
+
readyRoutes: 0,
|
|
249
|
+
reviewRoutes: 0,
|
|
250
|
+
blockedRoutes: 0,
|
|
251
|
+
preserveSourceRoutes: 0,
|
|
252
|
+
targetAdapterRoutes: 0,
|
|
253
|
+
stubOnlyRoutes: 0,
|
|
254
|
+
semanticIndexOnlyRoutes: 0,
|
|
255
|
+
missingEvidence: 0,
|
|
256
|
+
blockers: 0,
|
|
257
|
+
reviewReasons: 0,
|
|
258
|
+
autoMergeClaims: 0,
|
|
259
|
+
semanticEquivalenceClaims: 0
|
|
260
|
+
};
|
|
261
|
+
for (const route of routes) {
|
|
262
|
+
summary.byMode[route.mode] = (summary.byMode[route.mode] ?? 0) + 1;
|
|
263
|
+
summary.byReadiness[route.readiness] = (summary.byReadiness[route.readiness] ?? 0) + 1;
|
|
264
|
+
summary.byAdmissionAction[route.admissionAction] = (summary.byAdmissionAction[route.admissionAction] ?? 0) + 1;
|
|
265
|
+
if (route.readiness === 'ready') summary.readyRoutes += 1;
|
|
266
|
+
if (route.readiness === 'needs-review' || route.readiness === 'ready-with-losses') summary.reviewRoutes += 1;
|
|
267
|
+
if (route.readiness === 'blocked') summary.blockedRoutes += 1;
|
|
268
|
+
if (route.mode === 'preserve-source') summary.preserveSourceRoutes += 1;
|
|
269
|
+
if (route.mode === 'target-adapter') summary.targetAdapterRoutes += 1;
|
|
270
|
+
if (route.mode === 'stub-only') summary.stubOnlyRoutes += 1;
|
|
271
|
+
if (route.mode === 'semantic-index-only') summary.semanticIndexOnlyRoutes += 1;
|
|
272
|
+
summary.missingEvidence += route.missingEvidence.length;
|
|
273
|
+
summary.blockers += route.blockers.length;
|
|
274
|
+
summary.reviewReasons += route.review.length;
|
|
275
|
+
if (route.autoMergeClaim) summary.autoMergeClaims += 1;
|
|
276
|
+
if (route.semanticEquivalenceClaim) summary.semanticEquivalenceClaims += 1;
|
|
277
|
+
}
|
|
278
|
+
return summary;
|
|
279
|
+
}
|
package/package.json
CHANGED