@shapeshift-labs/frontier-lang-compiler 0.2.52 → 0.2.53

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 CHANGED
@@ -183,6 +183,7 @@ console.log(pythonToRust.mergeScore.value); // sortable merge-review score, not
183
183
  const conversionArtifacts = createUniversalConversionArtifacts(conversionPlan);
184
184
  console.log(conversionArtifacts.historyRecords[0].kind); // "frontier.lang.semanticHistoryRecord"
185
185
  console.log(conversionArtifacts.patchBundleRecords[0].admission.autoMergeClaim); // false
186
+ console.log(conversionArtifacts.admissionRecords[0].admissionBucket); // "blocked", "needs-evidence", "merge-ready", etc.
186
187
  console.log(conversionArtifacts.index.semanticOperationKinds); // sourcePreservation/projection/merge
187
188
  console.log(conversionArtifacts.routeArtifacts[0].semanticOperations.summary.conflictKeys);
188
189
  ```
@@ -199,7 +200,7 @@ The projection target matrix separates five runtime/API classes:
199
200
 
200
201
  `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.
201
202
 
202
- `createUniversalConversionArtifacts` materializes those route refs into compact `SemanticHistoryRecord`, `SemanticPatchBundleRecord`, and semantic-operation artifacts that swarm collectors can index by route, history ID, patch-bundle ID, operation kind, source path, ownership key, conflict key, evidence, proof, readiness, and admission status. It is still review evidence, not target-code proof: blocked and semantic-index-only routes stay blocked/needs-review, and every artifact keeps `autoMergeClaim: false` plus `semanticEquivalenceClaim: false`.
203
+ `createUniversalConversionArtifacts` materializes those route refs into compact `SemanticHistoryRecord`, `SemanticPatchBundleRecord`, semantic operation sets, and `UniversalConversionAdmissionRecord` rows that swarm collectors can index by route, history ID, patch-bundle ID, admission-record ID, admission bucket, risk, operation kind, source path, ownership key, conflict key, evidence, proof, readiness, and admission status. It is still review evidence, not target-code proof: blocked and semantic-index-only routes stay blocked/needs-review, and every artifact keeps `autoMergeClaim: false` plus `semanticEquivalenceClaim: false`.
203
204
 
204
205
  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:
205
206
 
@@ -95,6 +95,22 @@ export function measureNativeTransformations(nativeImportResults) {
95
95
  conversionArtifacts: conversionArtifacts.summary.routes,
96
96
  conversionArtifactHistories: conversionArtifacts.summary.histories,
97
97
  conversionArtifactPatchBundles: conversionArtifacts.summary.patchBundles,
98
+ conversionArtifactAdmissionRecords: conversionArtifacts.summary.admissionRecords,
99
+ conversionArtifactMergeReady: conversionArtifacts.summary.mergeReady,
100
+ conversionArtifactNeedsEvidence: conversionArtifacts.summary.needsEvidence,
101
+ conversionArtifactNeedsAdapter: conversionArtifacts.summary.needsAdapter,
102
+ conversionArtifactNeedsReview: conversionArtifacts.summary.needsReview,
103
+ conversionArtifactAdmissionBlocked: conversionArtifacts.summary.admissionBlocked,
104
+ conversionArtifactLowRisk: conversionArtifacts.summary.lowRisk,
105
+ conversionArtifactMediumRisk: conversionArtifacts.summary.mediumRisk,
106
+ conversionArtifactHighRisk: conversionArtifacts.summary.highRisk,
107
+ conversionArtifactQueued: conversionArtifacts.summary.queued,
108
+ conversionArtifactAdmissionReasonCodes: conversionArtifacts.summary.reasonCodes,
109
+ conversionArtifactAdmissionMissingEvidence: conversionArtifacts.summary.missingEvidence,
110
+ conversionArtifactAdmissionBlockers: conversionArtifacts.summary.blockers,
111
+ conversionArtifactAdmissionReviewReasons: conversionArtifacts.summary.reviewReasons,
112
+ conversionArtifactAdmissionEvidenceIds: conversionArtifacts.summary.evidenceIds,
113
+ conversionArtifactAdmissionProofIds: conversionArtifacts.summary.proofIds,
98
114
  conversionArtifactsDurationMs,
99
115
  featureEvidencePolicyMatches,
100
116
  featureEvidenceDurationMs,
package/bench/smoke.mjs CHANGED
@@ -63,6 +63,22 @@ console.log(JSON.stringify({
63
63
  conversionArtifacts: transformMetrics.conversionArtifacts,
64
64
  conversionArtifactHistories: transformMetrics.conversionArtifactHistories,
65
65
  conversionArtifactPatchBundles: transformMetrics.conversionArtifactPatchBundles,
66
+ conversionArtifactAdmissionRecords: transformMetrics.conversionArtifactAdmissionRecords,
67
+ conversionArtifactMergeReady: transformMetrics.conversionArtifactMergeReady,
68
+ conversionArtifactNeedsEvidence: transformMetrics.conversionArtifactNeedsEvidence,
69
+ conversionArtifactNeedsAdapter: transformMetrics.conversionArtifactNeedsAdapter,
70
+ conversionArtifactNeedsReview: transformMetrics.conversionArtifactNeedsReview,
71
+ conversionArtifactAdmissionBlocked: transformMetrics.conversionArtifactAdmissionBlocked,
72
+ conversionArtifactLowRisk: transformMetrics.conversionArtifactLowRisk,
73
+ conversionArtifactMediumRisk: transformMetrics.conversionArtifactMediumRisk,
74
+ conversionArtifactHighRisk: transformMetrics.conversionArtifactHighRisk,
75
+ conversionArtifactQueued: transformMetrics.conversionArtifactQueued,
76
+ conversionArtifactAdmissionReasonCodes: transformMetrics.conversionArtifactAdmissionReasonCodes,
77
+ conversionArtifactAdmissionMissingEvidence: transformMetrics.conversionArtifactAdmissionMissingEvidence,
78
+ conversionArtifactAdmissionBlockers: transformMetrics.conversionArtifactAdmissionBlockers,
79
+ conversionArtifactAdmissionReviewReasons: transformMetrics.conversionArtifactAdmissionReviewReasons,
80
+ conversionArtifactAdmissionEvidenceIds: transformMetrics.conversionArtifactAdmissionEvidenceIds,
81
+ conversionArtifactAdmissionProofIds: transformMetrics.conversionArtifactAdmissionProofIds,
66
82
  conversionArtifactsDurationMs: Number(transformMetrics.conversionArtifactsDurationMs.toFixed(2)),
67
83
  featureEvidencePolicyMatches: transformMetrics.featureEvidencePolicyMatches,
68
84
  featureEvidenceDurationMs: Number(transformMetrics.featureEvidenceDurationMs.toFixed(2)),
@@ -14,10 +14,18 @@ import type {
14
14
  UniversalConversionRoute,
15
15
  UniversalConversionRouteAction,
16
16
  UniversalConversionRouteMode,
17
- UniversalConversionMergeScore
17
+ UniversalConversionMergeScore,
18
+ UniversalConversionRisk
18
19
  } from './universal-conversion-plan.js';
19
20
 
20
21
  export type UniversalConversionArtifactAdmissionStatus = 'queued' | 'needs-review' | 'blocked' | string;
22
+ export type UniversalConversionArtifactAdmissionBucket =
23
+ | 'merge-ready'
24
+ | 'needs-evidence'
25
+ | 'needs-adapter'
26
+ | 'needs-review'
27
+ | 'blocked'
28
+ | string;
21
29
  export type UniversalConversionArtifactMaterializationStatus = 'materialized' | 'planned-only' | 'missing' | 'failed' | string;
22
30
 
23
31
  export interface UniversalConversionArtifactMaterialization {
@@ -33,6 +41,69 @@ export interface UniversalConversionArtifactMaterialization {
33
41
  readonly semanticEquivalenceClaim: false;
34
42
  }
35
43
 
44
+ export interface UniversalConversionAdmissionRecord {
45
+ readonly kind: 'frontier.lang.universalConversionAdmissionRecord';
46
+ readonly version: 1;
47
+ readonly schema: 'frontier.lang.universalConversionAdmissionRecord.v1';
48
+ readonly id: string;
49
+ readonly routeId: string;
50
+ readonly planId?: string;
51
+ readonly sourceLanguage?: FrontierSourceLanguage | string;
52
+ readonly target?: FrontierCompileTarget | string;
53
+ readonly mode: UniversalConversionRouteMode;
54
+ readonly routeAction: UniversalConversionRouteAction;
55
+ readonly admissionStatus: UniversalConversionArtifactAdmissionStatus;
56
+ readonly admissionAction: UniversalConversionAdmissionAction;
57
+ readonly admissionBucket: UniversalConversionArtifactAdmissionBucket;
58
+ readonly reviewRequired: true;
59
+ readonly readiness: SemanticMergeReadiness | string;
60
+ readonly risk: UniversalConversionRisk | string;
61
+ readonly score: {
62
+ readonly value: number;
63
+ readonly uncappedValue: number;
64
+ readonly sortKey: number;
65
+ readonly higherIsBetter: true;
66
+ readonly componentStatuses: Record<string, string>;
67
+ readonly penalties: readonly string[];
68
+ };
69
+ readonly ids: {
70
+ readonly historyId?: string;
71
+ readonly patchBundleId?: string;
72
+ readonly semanticOperationIds: readonly string[];
73
+ readonly sourceMapLinkIds: readonly string[];
74
+ readonly evidenceIds: readonly string[];
75
+ readonly proofIds: readonly string[];
76
+ };
77
+ readonly semanticOperations: {
78
+ readonly total: number;
79
+ readonly byKind: Record<string, number>;
80
+ readonly kinds: readonly string[];
81
+ readonly dynamic: readonly string[];
82
+ readonly opaque: readonly string[];
83
+ };
84
+ readonly ownership: {
85
+ readonly keys: readonly string[];
86
+ readonly conflictKeys: readonly string[];
87
+ };
88
+ readonly source: {
89
+ readonly paths: readonly string[];
90
+ readonly hashes: readonly string[];
91
+ readonly baseHashes: readonly string[];
92
+ readonly targetHashes: readonly string[];
93
+ };
94
+ readonly evidence: {
95
+ readonly total: number;
96
+ readonly proofArtifacts: number;
97
+ readonly missing: readonly string[];
98
+ readonly blockers: readonly string[];
99
+ readonly review: readonly string[];
100
+ };
101
+ readonly reasons: readonly string[];
102
+ readonly autoMergeClaim: false;
103
+ readonly semanticEquivalenceClaim: false;
104
+ readonly metadata: Record<string, unknown>;
105
+ }
106
+
36
107
  export interface UniversalConversionRouteArtifact {
37
108
  readonly kind: 'frontier.lang.universalConversionRouteArtifact';
38
109
  readonly version: 1;
@@ -50,9 +121,11 @@ export interface UniversalConversionRouteArtifact {
50
121
  readonly reviewRequired: true;
51
122
  readonly history: SemanticHistoryRecord;
52
123
  readonly patchBundle: SemanticPatchBundleRecord;
124
+ readonly admissionRecord: UniversalConversionAdmissionRecord;
53
125
  readonly semanticOperations: SemanticOperationSet;
54
126
  readonly materialization: UniversalConversionArtifactMaterialization;
55
127
  readonly mergeScore?: UniversalConversionMergeScore;
128
+ readonly admissionBucket: UniversalConversionArtifactAdmissionBucket;
56
129
  readonly autoMergeClaim: false;
57
130
  readonly semanticEquivalenceClaim: false;
58
131
  readonly metadata: Record<string, unknown>;
@@ -62,11 +135,14 @@ export interface UniversalConversionArtifactIndex {
62
135
  readonly routeIds: readonly string[];
63
136
  readonly historyIds: readonly string[];
64
137
  readonly patchBundleIds: readonly string[];
138
+ readonly admissionRecordIds: readonly string[];
65
139
  readonly languages: readonly string[];
66
140
  readonly targets: readonly string[];
67
141
  readonly modes: readonly string[];
68
142
  readonly readinesses: readonly string[];
69
143
  readonly admissionStatuses: readonly string[];
144
+ readonly admissionBuckets: readonly string[];
145
+ readonly admissionRisks: readonly string[];
70
146
  readonly sourcePaths: readonly string[];
71
147
  readonly sourceHashes: readonly string[];
72
148
  readonly ownershipKeys: readonly string[];
@@ -87,14 +163,31 @@ export interface UniversalConversionArtifacts {
87
163
  readonly routeArtifacts: readonly UniversalConversionRouteArtifact[];
88
164
  readonly historyRecords: readonly SemanticHistoryRecord[];
89
165
  readonly patchBundleRecords: readonly SemanticPatchBundleRecord[];
166
+ readonly admissionRecords: readonly UniversalConversionAdmissionRecord[];
90
167
  readonly index: UniversalConversionArtifactIndex;
91
168
  readonly summary: {
92
169
  readonly routes: number;
93
170
  readonly histories: number;
94
171
  readonly patchBundles: number;
172
+ readonly admissionRecords: number;
95
173
  readonly semanticOperations: number;
174
+ readonly mergeReady: number;
175
+ readonly needsEvidence: number;
176
+ readonly needsAdapter: number;
177
+ readonly needsReview: number;
178
+ readonly admissionBlocked: number;
179
+ readonly lowRisk: number;
180
+ readonly mediumRisk: number;
181
+ readonly highRisk: number;
182
+ readonly queued: number;
96
183
  readonly reviewRequired: number;
97
184
  readonly blocked: number;
185
+ readonly reasonCodes: number;
186
+ readonly missingEvidence: number;
187
+ readonly blockers: number;
188
+ readonly reviewReasons: number;
189
+ readonly evidenceIds: number;
190
+ readonly proofIds: number;
98
191
  readonly autoMergeClaims: 0;
99
192
  readonly semanticEquivalenceClaims: 0;
100
193
  };
@@ -128,12 +221,15 @@ export interface UniversalConversionArtifactQuery {
128
221
  readonly routeId?: string | readonly string[];
129
222
  readonly historyId?: string | readonly string[];
130
223
  readonly patchBundleId?: string | readonly string[];
224
+ readonly admissionRecordId?: string | readonly string[];
131
225
  readonly sourceLanguage?: FrontierSourceLanguage | string | readonly string[];
132
226
  readonly target?: FrontierCompileTarget | string | readonly string[];
133
227
  readonly mode?: UniversalConversionRouteMode | readonly string[];
134
228
  readonly readiness?: SemanticMergeReadiness | string | readonly string[];
135
229
  readonly admissionAction?: UniversalConversionAdmissionAction | readonly string[];
136
230
  readonly admissionStatus?: UniversalConversionArtifactAdmissionStatus | readonly string[];
231
+ readonly admissionBucket?: UniversalConversionArtifactAdmissionBucket | readonly string[];
232
+ readonly risk?: UniversalConversionRisk | string | readonly string[];
137
233
  readonly priority?: UniversalConversionPriority | readonly string[];
138
234
  readonly routeAction?: UniversalConversionRouteAction | readonly string[];
139
235
  readonly sourcePath?: string | readonly string[];
@@ -0,0 +1,122 @@
1
+ import { countBy, idFragment, uniqueStrings } from './native-import-utils.js';
2
+
3
+ export function createUniversalConversionAdmissionRecord(input) {
4
+ const route = input.route;
5
+ const operations = input.semanticOperations?.operations ?? [];
6
+ const operationKinds = uniqueStrings(operations.map((operation) => operation.operationKind));
7
+ const sourceRecords = input.patchBundle?.sources ?? input.history?.sources ?? [];
8
+ const evidenceIds = uniqueStrings([
9
+ ...(input.history?.evidenceIds ?? []),
10
+ ...(input.patchBundle?.evidenceIds ?? []),
11
+ ...(input.materialization?.evidenceIds ?? [])
12
+ ]);
13
+ const proofIds = uniqueStrings([
14
+ ...(input.history?.proofIds ?? []),
15
+ ...(input.patchBundle?.proofIds ?? []),
16
+ ...(input.materialization?.proofIds ?? [])
17
+ ]);
18
+ const score = route.mergeScore ?? {};
19
+ const missingEvidence = route.missingEvidence ?? [];
20
+ const blockers = route.blockers ?? [];
21
+ const bucket = admissionBucket({
22
+ action: score.action ?? route.admissionAction,
23
+ blockers,
24
+ missingEvidence,
25
+ mode: route.mode,
26
+ operationKinds,
27
+ opaqueOperations: operations.filter((operation) => operation.opaque).length,
28
+ scoreValue: score.value,
29
+ status: input.admissionStatus
30
+ });
31
+ return {
32
+ kind: 'frontier.lang.universalConversionAdmissionRecord',
33
+ version: 1,
34
+ schema: 'frontier.lang.universalConversionAdmissionRecord.v1',
35
+ id: `admission_${idFragment(route.id)}`,
36
+ routeId: route.id,
37
+ planId: input.planId,
38
+ sourceLanguage: route.sourceLanguage,
39
+ target: route.target,
40
+ mode: route.mode,
41
+ routeAction: route.routeAction,
42
+ admissionStatus: input.admissionStatus,
43
+ admissionAction: score.action ?? route.admissionAction,
44
+ admissionBucket: bucket,
45
+ reviewRequired: true,
46
+ readiness: route.readiness,
47
+ risk: score.risk ?? riskForRoute(route, input.admissionStatus),
48
+ score: {
49
+ value: Number(score.value ?? 0),
50
+ uncappedValue: Number(score.uncappedValue ?? score.value ?? 0),
51
+ sortKey: Number(score.sortKey ?? score.value ?? 0),
52
+ higherIsBetter: true,
53
+ componentStatuses: componentStatuses(score.components),
54
+ penalties: score.penalties ?? []
55
+ },
56
+ ids: {
57
+ historyId: input.history?.id,
58
+ patchBundleId: input.patchBundle?.id,
59
+ semanticOperationIds: operations.map((operation) => operation.id),
60
+ sourceMapLinkIds: input.materialization?.sourceMapLinkIds ?? [],
61
+ evidenceIds,
62
+ proofIds
63
+ },
64
+ semanticOperations: {
65
+ total: operations.length,
66
+ byKind: countBy(operations.map((operation) => operation.operationKind)),
67
+ kinds: operationKinds,
68
+ dynamic: operations.filter((operation) => operation.dynamic).map((operation) => operation.id),
69
+ opaque: operations.filter((operation) => operation.opaque).map((operation) => operation.id)
70
+ },
71
+ ownership: {
72
+ keys: uniqueStrings(input.history?.index?.ownershipKeys ?? input.patchBundle?.index?.ownershipKeys ?? []),
73
+ conflictKeys: uniqueStrings(input.history?.index?.conflictKeys ?? input.patchBundle?.index?.conflictKeys ?? [])
74
+ },
75
+ source: {
76
+ paths: uniqueStrings(sourceRecords.map((source) => source.sourcePath)),
77
+ hashes: uniqueStrings(sourceRecords.map((source) => source.sourceHash)),
78
+ baseHashes: uniqueStrings(sourceRecords.map((source) => source.baseHash)),
79
+ targetHashes: uniqueStrings(sourceRecords.map((source) => source.targetHash))
80
+ },
81
+ evidence: {
82
+ total: evidenceIds.length,
83
+ proofArtifacts: proofIds.length,
84
+ missing: missingEvidence,
85
+ blockers,
86
+ review: route.review ?? []
87
+ },
88
+ reasons: uniqueStrings([
89
+ ...(input.reasonCodes ?? []),
90
+ ...missingEvidence.map((reason) => `missing:${reason}`),
91
+ ...blockers.map((reason) => `blocker:${reason}`),
92
+ ...(route.review ?? []).map((reason) => `review:${reason}`),
93
+ ...(score.penalties ?? [])
94
+ ]),
95
+ autoMergeClaim: false,
96
+ semanticEquivalenceClaim: false,
97
+ metadata: {
98
+ routeId: route.id,
99
+ planId: input.planId,
100
+ mergeScoreSchema: score.schema,
101
+ note: 'Admission records are sortable merge-review evidence, not proof of target semantic equivalence.'
102
+ }
103
+ };
104
+ }
105
+
106
+ function admissionBucket(input) {
107
+ if (input.status === 'blocked' || input.action === 'reject' || input.blockers.length) return 'blocked';
108
+ if (input.mode === 'semantic-index-only' || input.missingEvidence.includes('target-adapter')) return 'needs-adapter';
109
+ if (input.missingEvidence.length || input.opaqueOperations || input.operationKinds.includes('merge')) return 'needs-evidence';
110
+ if (Number(input.scoreValue ?? 0) >= 80) return 'merge-ready';
111
+ return 'needs-review';
112
+ }
113
+
114
+ function riskForRoute(route, status) {
115
+ if (status === 'blocked' || route.readiness === 'blocked') return 'high';
116
+ if (route.readiness === 'needs-review' || route.mode === 'stub-only') return 'medium';
117
+ return 'low';
118
+ }
119
+
120
+ function componentStatuses(components = {}) {
121
+ return Object.fromEntries(Object.entries(components).map(([key, component]) => [key, component.status]));
122
+ }
@@ -12,11 +12,14 @@ export function artifactIndex(routeArtifacts) {
12
12
  routeIds: uniqueStrings(routeArtifacts.map((artifact) => artifact.routeId)),
13
13
  historyIds: uniqueStrings(routeArtifacts.map((artifact) => artifact.history.id)),
14
14
  patchBundleIds: uniqueStrings(routeArtifacts.map((artifact) => artifact.patchBundle.id)),
15
+ admissionRecordIds: uniqueStrings(routeArtifacts.map((artifact) => artifact.admissionRecord.id)),
15
16
  languages: uniqueStrings(routeArtifacts.map((artifact) => artifact.sourceLanguage)),
16
17
  targets: uniqueStrings(routeArtifacts.map((artifact) => artifact.target)),
17
18
  modes: uniqueStrings(routeArtifacts.map((artifact) => artifact.mode)),
18
19
  readinesses: uniqueStrings(routeArtifacts.map((artifact) => artifact.readiness)),
19
20
  admissionStatuses: uniqueStrings(routeArtifacts.map((artifact) => artifact.admissionStatus)),
21
+ admissionBuckets: uniqueStrings(routeArtifacts.map((artifact) => artifact.admissionRecord.admissionBucket)),
22
+ admissionRisks: uniqueStrings(routeArtifacts.map((artifact) => artifact.admissionRecord.risk)),
20
23
  sourcePaths: uniqueStrings(routeArtifacts.flatMap((artifact) => artifact.history.index.sourcePaths)),
21
24
  sourceHashes: uniqueStrings(routeArtifacts.flatMap((artifact) => artifact.history.index.sourceHashes)),
22
25
  ownershipKeys: uniqueStrings(routeArtifacts.flatMap((artifact) => artifact.history.index.ownershipKeys)),
@@ -39,6 +42,7 @@ function matchesArtifact(record, query) {
39
42
  return match(query.routeId, [record.routeId])
40
43
  && match(query.historyId, [record.history.id])
41
44
  && match(query.patchBundleId, [record.patchBundle.id])
45
+ && match(query.admissionRecordId, [record.admissionRecord.id])
42
46
  && match(query.sourceLanguage, [record.sourceLanguage])
43
47
  && match(query.target, [record.target])
44
48
  && match(query.mode, [record.mode])
@@ -46,6 +50,8 @@ function matchesArtifact(record, query) {
46
50
  && match(query.priority, [record.priority])
47
51
  && match(query.readiness, [record.readiness])
48
52
  && match(query.admissionStatus, [record.admissionStatus])
53
+ && match(query.admissionBucket, [record.admissionRecord.admissionBucket])
54
+ && match(query.risk, [record.admissionRecord.risk])
49
55
  && match(query.sourcePath, record.history.index.sourcePaths)
50
56
  && match(query.sourceHash, record.history.index.sourceHashes)
51
57
  && match(query.ownershipKey, record.history.index.ownershipKeys)
@@ -0,0 +1,37 @@
1
+ export function universalConversionArtifactSummary(routeArtifacts, records) {
2
+ const admissionRecords = records.admissionRecords;
3
+ return {
4
+ routes: routeArtifacts.length,
5
+ histories: records.historyRecords.length,
6
+ patchBundles: records.patchBundleRecords.length,
7
+ admissionRecords: admissionRecords.length,
8
+ semanticOperations: routeArtifacts.reduce((sum, artifact) => sum + artifact.semanticOperations.operations.length, 0),
9
+ mergeReady: countAdmissionBucket(admissionRecords, 'merge-ready'),
10
+ needsEvidence: countAdmissionBucket(admissionRecords, 'needs-evidence'),
11
+ needsAdapter: countAdmissionBucket(admissionRecords, 'needs-adapter'),
12
+ needsReview: countAdmissionBucket(admissionRecords, 'needs-review'),
13
+ admissionBlocked: countAdmissionBucket(admissionRecords, 'blocked'),
14
+ lowRisk: countAdmissionRisk(admissionRecords, 'low'),
15
+ mediumRisk: countAdmissionRisk(admissionRecords, 'medium'),
16
+ highRisk: countAdmissionRisk(admissionRecords, 'high'),
17
+ queued: routeArtifacts.filter((artifact) => artifact.admissionStatus === 'queued').length,
18
+ reviewRequired: routeArtifacts.filter((artifact) => artifact.reviewRequired).length,
19
+ blocked: routeArtifacts.filter((artifact) => artifact.admissionStatus === 'blocked').length,
20
+ reasonCodes: admissionRecords.reduce((sum, record) => sum + record.reasons.length, 0),
21
+ missingEvidence: admissionRecords.reduce((sum, record) => sum + record.evidence.missing.length, 0),
22
+ blockers: admissionRecords.reduce((sum, record) => sum + record.evidence.blockers.length, 0),
23
+ reviewReasons: admissionRecords.reduce((sum, record) => sum + record.evidence.review.length, 0),
24
+ evidenceIds: admissionRecords.reduce((sum, record) => sum + record.ids.evidenceIds.length, 0),
25
+ proofIds: admissionRecords.reduce((sum, record) => sum + record.ids.proofIds.length, 0),
26
+ autoMergeClaims: 0,
27
+ semanticEquivalenceClaims: 0
28
+ };
29
+ }
30
+
31
+ function countAdmissionBucket(records, bucket) {
32
+ return records.filter((record) => record.admissionBucket === bucket).length;
33
+ }
34
+
35
+ function countAdmissionRisk(records, risk) {
36
+ return records.filter((record) => record.risk === risk).length;
37
+ }
@@ -1,6 +1,8 @@
1
1
  import { idFragment, uniqueStrings } from './native-import-utils.js';
2
+ import { universalConversionArtifactSummary } from './universal-conversion-artifact-summary.js';
2
3
  import { createUniversalConversionPlan } from './universal-conversion-plan.js';
3
4
  import { artifactIndex } from './universal-conversion-artifact-query.js';
5
+ import { createUniversalConversionAdmissionRecord } from './universal-conversion-admission-record.js';
4
6
  import { routeSemanticOperations } from './universal-conversion-route-operations.js';
5
7
  import { createSemanticHistoryRecord } from './internal/index-impl/semanticHistoryRecords.js';
6
8
  import { createSemanticPatchBundleRecord } from './internal/index-impl/semanticPatchBundleRecords.js';
@@ -23,6 +25,7 @@ export function createUniversalConversionArtifacts(input = {}, options = {}) {
23
25
  }));
24
26
  const historyRecords = routeArtifacts.map((artifact) => artifact.history);
25
27
  const patchBundleRecords = routeArtifacts.map((artifact) => artifact.patchBundle);
28
+ const admissionRecords = routeArtifacts.map((artifact) => artifact.admissionRecord);
26
29
  const index = artifactIndex(routeArtifacts);
27
30
  return {
28
31
  kind: 'frontier.lang.universalConversionArtifacts',
@@ -34,17 +37,13 @@ export function createUniversalConversionArtifacts(input = {}, options = {}) {
34
37
  routeArtifacts,
35
38
  historyRecords,
36
39
  patchBundleRecords,
40
+ admissionRecords,
37
41
  index,
38
- summary: {
39
- routes: routeArtifacts.length,
40
- histories: historyRecords.length,
41
- patchBundles: patchBundleRecords.length,
42
- semanticOperations: routeArtifacts.reduce((sum, artifact) => sum + artifact.semanticOperations.operations.length, 0),
43
- reviewRequired: routeArtifacts.filter((artifact) => artifact.reviewRequired).length,
44
- blocked: routeArtifacts.filter((artifact) => artifact.admissionStatus === 'blocked').length,
45
- autoMergeClaims: 0,
46
- semanticEquivalenceClaims: 0
47
- },
42
+ summary: universalConversionArtifactSummary(routeArtifacts, {
43
+ historyRecords,
44
+ patchBundleRecords,
45
+ admissionRecords
46
+ }),
48
47
  metadata: {
49
48
  autoMergeClaim: false,
50
49
  semanticEquivalenceClaim: false,
@@ -121,6 +120,16 @@ function createRouteArtifact(route, options) {
121
120
  autoMergeClaim: false,
122
121
  semanticEquivalenceClaim: false
123
122
  };
123
+ const admissionRecord = createUniversalConversionAdmissionRecord({
124
+ route,
125
+ planId,
126
+ admissionStatus,
127
+ reasonCodes,
128
+ history,
129
+ patchBundle,
130
+ semanticOperations,
131
+ materialization
132
+ });
124
133
  return {
125
134
  kind: 'frontier.lang.universalConversionRouteArtifact',
126
135
  version: 1,
@@ -138,9 +147,11 @@ function createRouteArtifact(route, options) {
138
147
  reviewRequired: true,
139
148
  history,
140
149
  patchBundle,
150
+ admissionRecord,
141
151
  semanticOperations,
142
152
  materialization,
143
153
  mergeScore: route.mergeScore,
154
+ admissionBucket: admissionRecord.admissionBucket,
144
155
  autoMergeClaim: false,
145
156
  semanticEquivalenceClaim: false,
146
157
  metadata: { ...routeRecordMetadata(route, planId, options.metadata), materialization }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshift-labs/frontier-lang-compiler",
3
- "version": "0.2.52",
3
+ "version": "0.2.53",
4
4
  "description": "Compiler facade for Frontier Lang source documents and language projection adapters.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",