@shapeshift-labs/frontier-lang-compiler 0.2.90 → 0.2.91

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.
@@ -81,6 +81,8 @@ export interface SemanticPatchBundleAdmission {
81
81
  readonly readiness: SemanticMergeReadiness | string;
82
82
  readonly reviewRequired: boolean;
83
83
  readonly autoMergeClaim: false;
84
+ readonly autoApplyCandidate?: boolean;
85
+ readonly transformAdmission?: SemanticPatchBundleTransformAdmission;
84
86
  readonly reasonCodes?: readonly string[];
85
87
  readonly conflictKeys?: readonly string[];
86
88
  readonly admittedAt?: number | string;
@@ -89,6 +91,23 @@ export interface SemanticPatchBundleAdmission {
89
91
  readonly metadata?: Record<string, unknown>;
90
92
  }
91
93
 
94
+ export interface SemanticPatchBundleTransformAdmission {
95
+ readonly status: 'none' | 'ready' | 'needs-review' | 'blocked' | string;
96
+ readonly action: 'none' | 'admit' | 'review' | 'block' | string;
97
+ readonly readiness: SemanticMergeReadiness | string;
98
+ readonly crossLanguage?: boolean;
99
+ readonly reasonCodes?: readonly string[];
100
+ readonly transformIds?: readonly string[];
101
+ readonly transformKeys?: readonly string[];
102
+ readonly contentHashes?: readonly string[];
103
+ readonly projectionIdentityHashes?: readonly string[];
104
+ readonly sourceLanguages?: readonly string[];
105
+ readonly targetLanguages?: readonly string[];
106
+ readonly sourcePaths?: readonly string[];
107
+ readonly targetPaths?: readonly string[];
108
+ readonly evidenceIds?: readonly string[];
109
+ }
110
+
92
111
  export interface SemanticPatchBundleRecordIndex {
93
112
  readonly baseHashes: readonly string[];
94
113
  readonly targetHashes: readonly string[];
@@ -116,6 +135,8 @@ export interface SemanticPatchBundleRecordIndex {
116
135
  readonly semanticTransformIdentityHashes: readonly string[];
117
136
  readonly semanticTransformContentHashes: readonly string[];
118
137
  readonly projectionIdentityHashes: readonly string[];
138
+ readonly semanticTransformReadinesses: readonly string[];
139
+ readonly semanticTransformEvidenceIds: readonly string[];
119
140
  readonly transformSourceLanguages: readonly string[];
120
141
  readonly transformTargetLanguages: readonly string[];
121
142
  readonly transformSourcePaths: readonly string[];
@@ -263,6 +284,10 @@ export interface SemanticPatchBundleRecordQuery {
263
284
  readonly semanticTransformContentHashes?: readonly string[];
264
285
  readonly projectionIdentityHash?: string | readonly string[];
265
286
  readonly projectionIdentityHashes?: readonly string[];
287
+ readonly semanticTransformReadiness?: string | readonly string[];
288
+ readonly semanticTransformReadinesses?: readonly string[];
289
+ readonly semanticTransformEvidenceId?: string | readonly string[];
290
+ readonly semanticTransformEvidenceIds?: readonly string[];
266
291
  readonly transformSourceLanguage?: string | readonly string[];
267
292
  readonly transformSourceLanguages?: readonly string[];
268
293
  readonly transformTargetLanguage?: string | readonly string[];
@@ -0,0 +1,97 @@
1
+ import { normalizeSemanticMergeReadiness, uniqueStrings } from '../../native-import-utils.js';
2
+
3
+ export function createSemanticPatchBundleAdmission(input = {}, context = {}) {
4
+ const transformAdmission = semanticTransformAdmission(context);
5
+ const fallbackReadiness = transformAdmission.readiness === 'ready' ? 'ready' : context.readiness;
6
+ const readiness = normalizeSemanticMergeReadiness(input.readiness ?? fallbackReadiness) ?? input.readiness ?? fallbackReadiness;
7
+ const status = input.status ?? admissionStatusForReadiness(readiness, transformAdmission);
8
+ const autoApplyCandidate = input.autoApplyCandidate ?? (status === 'admitted' && transformAdmission.action === 'admit');
9
+ return compactRecord({
10
+ status,
11
+ readiness,
12
+ reviewRequired: input.reviewRequired ?? status !== 'admitted',
13
+ autoMergeClaim: false,
14
+ autoApplyCandidate,
15
+ transformAdmission,
16
+ reasonCodes: uniqueStrings([
17
+ ...strings(input.reasonCodes),
18
+ ...strings(context.source?.reasons),
19
+ ...strings(context.mergeCandidate?.reasons),
20
+ ...transformAdmission.reasonCodes
21
+ ]),
22
+ conflictKeys: uniqueStrings([...strings(input.conflictKeys), ...context.conflictKeys]),
23
+ admittedAt: input.admittedAt,
24
+ reviewerId: input.reviewerId,
25
+ evidenceIds: uniqueStrings([...strings(input.evidenceIds), ...strings(transformAdmission.evidenceIds)]),
26
+ metadata: input.metadata
27
+ });
28
+ }
29
+
30
+ function semanticTransformAdmission(context) {
31
+ const records = array(context.semanticTransformIdentities);
32
+ const index = context.semanticTransformIndex ?? {};
33
+ if (!records.length && !strings(index.semanticTransformIds).length) {
34
+ return { status: 'none', action: 'none', readiness: 'needs-review', reasonCodes: [] };
35
+ }
36
+ const readinesses = uniqueStrings([...strings(index.semanticTransformReadinesses), ...records.map((record) => record.readiness)]);
37
+ const normalizedReadinesses = uniqueStrings(readinesses.map(transformReadiness).filter(Boolean));
38
+ const blocked = normalizedReadinesses.includes('blocked');
39
+ const complete = strings(index.semanticTransformContentHashes).length > 0 &&
40
+ strings(index.projectionIdentityHashes).length > 0 &&
41
+ strings(index.transformSourceLanguages).length > 0 &&
42
+ strings(index.transformTargetLanguages).length > 0 &&
43
+ strings(index.transformSourcePaths).length > 0 &&
44
+ strings(index.transformTargetPaths).length > 0;
45
+ const ready = !blocked && complete && (normalizedReadinesses.length === 0 || normalizedReadinesses.every((entry) => entry === 'ready'));
46
+ const status = blocked ? 'blocked' : ready ? 'ready' : 'needs-review';
47
+ return compactRecord({
48
+ status,
49
+ action: blocked ? 'block' : ready ? 'admit' : 'review',
50
+ readiness: blocked ? 'blocked' : ready ? 'ready' : 'needs-review',
51
+ crossLanguage: hasCrossLanguageTransform(index),
52
+ reasonCodes: transformReasonCodes({ blocked, complete, ready, readinesses, index }),
53
+ transformIds: strings(index.semanticTransformIds),
54
+ transformKeys: strings(index.semanticTransformKeys),
55
+ contentHashes: strings(index.semanticTransformContentHashes),
56
+ projectionIdentityHashes: strings(index.projectionIdentityHashes),
57
+ sourceLanguages: strings(index.transformSourceLanguages),
58
+ targetLanguages: strings(index.transformTargetLanguages),
59
+ sourcePaths: strings(index.transformSourcePaths),
60
+ targetPaths: strings(index.transformTargetPaths),
61
+ evidenceIds: strings(index.semanticTransformEvidenceIds)
62
+ });
63
+ }
64
+
65
+ function transformReasonCodes(input) {
66
+ return uniqueStrings([
67
+ input.blocked ? 'transform-readiness-blocked' : undefined,
68
+ !input.complete ? 'transform-evidence-incomplete' : undefined,
69
+ input.ready ? 'transform-auto-apply-candidate' : undefined,
70
+ ...input.readinesses.map((readiness) => `transform-readiness:${readiness}`)
71
+ ]);
72
+ }
73
+
74
+ function transformReadiness(value) {
75
+ const normalized = normalizeSemanticMergeReadiness(value);
76
+ if (normalized) return normalized === 'ready-with-losses' ? 'needs-review' : normalized;
77
+ const status = String(value ?? '').toLowerCase();
78
+ if (['auto-merge-candidate', 'portable', 'projected', 'applied'].includes(status)) return 'ready';
79
+ if (['conflict', 'blocked', 'stale', 'rejected'].includes(status)) return 'blocked';
80
+ if (['needs-port', 'review', 'needs-review', 'candidate'].includes(status)) return 'needs-review';
81
+ return undefined;
82
+ }
83
+
84
+ function admissionStatusForReadiness(readiness, transformAdmission) {
85
+ if (readiness === 'blocked') return 'blocked';
86
+ if (transformAdmission.action === 'admit' && readiness === 'ready') return 'admitted';
87
+ return readiness === 'needs-review' ? 'needs-review' : 'proposed';
88
+ }
89
+
90
+ function hasCrossLanguageTransform(index) {
91
+ const source = new Set(strings(index.transformSourceLanguages));
92
+ return strings(index.transformTargetLanguages).some((target) => !source.has(target));
93
+ }
94
+
95
+ function array(value) { if (value === undefined || value === null) return []; return Array.isArray(value) ? value : [value]; }
96
+ function strings(value) { return array(value).map((entry) => String(entry ?? '')).filter(Boolean); }
97
+ function compactRecord(value) { return Object.fromEntries(Object.entries(value ?? {}).filter(([, entry]) => entry !== undefined && (!Array.isArray(entry) || entry.length > 0))); }
@@ -1,4 +1,5 @@
1
1
  import{idFragment,normalizeSemanticMergeReadiness,uniqueStrings}from'../../native-import-utils.js';
2
+ import{createSemanticPatchBundleAdmission}from'./semanticPatchBundleAdmission.js';
2
3
  import{normalizeSemanticTransformIdentityRecords,semanticTransformInputs,semanticTransformRecordIndex,semanticTransformSummary}from'./semanticTransformIdentityRecords.js';
3
4
 
4
5
  export const SemanticPatchBundleAdmissionStatuses=Object.freeze(['proposed','queued','admitted','needs-review','blocked','rejected']);
@@ -42,7 +43,7 @@ export function createSemanticPatchBundleRecord(input={},options={}){
42
43
  ...changedRegions.flatMap((region)=>[region.conflictKey,...array(region.admission?.conflictKeys)]),
43
44
  ...(source.metadata?.semanticMergeConflictSummary?.conflictKeys??[])
44
45
  ]);
45
- const admission=normalizeAdmission(options.admission??source.admission,{readiness,conflictKeys,source,mergeCandidate});
46
+ const admission=createSemanticPatchBundleAdmission(options.admission??source.admission,{readiness,conflictKeys,source,mergeCandidate,semanticTransformIndex,semanticTransformIdentities});
46
47
  const id=options.id??(source.kind==='frontier.lang.semanticPatchBundleRecord'?source.id:undefined)
47
48
  ??`semantic_patch_bundle_${idFragment(firstString(source.id,patchId,mergeCandidateId,source.sourcePath,source.language,'record'))}`;
48
49
  const language=options.language??source.language??mergeCandidate?.language??sources.find((item)=>item.language)?.language;
@@ -184,23 +185,6 @@ function normalizeSourceMapLinks(links){
184
185
  return result;
185
186
  }
186
187
 
187
- function normalizeAdmission(input={},context){
188
- const readiness=normalizeSemanticMergeReadiness(input.readiness??context.readiness)??input.readiness??context.readiness;
189
- const status=input.status??admissionStatusForReadiness(readiness);
190
- return compactRecord({
191
- status,
192
- readiness,
193
- reviewRequired:input.reviewRequired??status!=='admitted',
194
- autoMergeClaim:false,
195
- reasonCodes:uniqueStrings([...strings(input.reasonCodes),...strings(context.source.reasons),...strings(context.mergeCandidate?.reasons)]),
196
- conflictKeys:uniqueStrings([...strings(input.conflictKeys),...context.conflictKeys]),
197
- admittedAt:input.admittedAt,
198
- reviewerId:input.reviewerId,
199
- evidenceIds:uniqueStrings(input.evidenceIds),
200
- metadata:input.metadata
201
- });
202
- }
203
-
204
188
  function recordIndex(parts){
205
189
  const semanticEditIndex=parts.semanticEditIndex??semanticEditRecordIndex([],[]);
206
190
  const semanticTransformIndex=parts.semanticTransformIndex??semanticTransformRecordIndex([],parts);
@@ -231,6 +215,8 @@ function recordIndex(parts){
231
215
  semanticTransformIdentityHashes:semanticTransformIndex.semanticTransformIdentityHashes,
232
216
  semanticTransformContentHashes:semanticTransformIndex.semanticTransformContentHashes,
233
217
  projectionIdentityHashes:semanticTransformIndex.projectionIdentityHashes,
218
+ semanticTransformReadinesses:semanticTransformIndex.semanticTransformReadinesses,
219
+ semanticTransformEvidenceIds:semanticTransformIndex.semanticTransformEvidenceIds,
234
220
  transformSourceLanguages:semanticTransformIndex.transformSourceLanguages,
235
221
  transformTargetLanguages:semanticTransformIndex.transformTargetLanguages,
236
222
  transformSourcePaths:semanticTransformIndex.transformSourcePaths,
@@ -273,6 +259,8 @@ function matchesRecord(record,query){
273
259
  &&matchAny(queryValues(query.semanticTransformIdentityHash,query.semanticTransformIdentityHashes),index.semanticTransformIdentityHashes)
274
260
  &&matchAny(queryValues(query.semanticTransformContentHash,query.semanticTransformContentHashes),index.semanticTransformContentHashes)
275
261
  &&matchAny(queryValues(query.projectionIdentityHash,query.projectionIdentityHashes),index.projectionIdentityHashes)
262
+ &&matchAny(queryValues(query.semanticTransformReadiness,query.semanticTransformReadinesses),index.semanticTransformReadinesses)
263
+ &&matchAny(queryValues(query.semanticTransformEvidenceId,query.semanticTransformEvidenceIds),index.semanticTransformEvidenceIds)
276
264
  &&matchAny(queryValues(query.transformSourceLanguage,query.transformSourceLanguages),index.transformSourceLanguages)
277
265
  &&matchAny(queryValues(query.transformTargetLanguage,query.transformTargetLanguages),index.transformTargetLanguages)
278
266
  &&matchAny(queryValues(query.transformSourcePath,query.transformSourcePaths),index.transformSourcePaths)
@@ -281,7 +269,6 @@ function matchesRecord(record,query){
281
269
  &&matchAny(queryValues(query.admissionStatus,query.admissionStatuses),index.admissionStatuses);
282
270
  }
283
271
 
284
- function admissionStatusForReadiness(readiness){return readiness==='blocked'?'blocked':readiness==='needs-review'?'needs-review':'proposed';}
285
272
  function semanticEditRecordIndex(scripts,projections,source={}){
286
273
  const operations=scripts.flatMap((script)=>array(script.operations));
287
274
  const edits=projections.flatMap((projection)=>array(projection.edits));
@@ -104,6 +104,8 @@ export function semanticTransformRecordIndex(records, source = {}) {
104
104
  semanticTransformIdentityHashes: uniqueStrings([...strings(source.semanticTransformIdentityHashes), ...strings(index.semanticTransformIdentityHashes), ...records.map((record) => record.transformIdentityHash)]),
105
105
  semanticTransformContentHashes: uniqueStrings([...strings(source.semanticTransformContentHashes), ...strings(index.semanticTransformContentHashes), ...records.map((record) => record.transformContentHash)]),
106
106
  projectionIdentityHashes: uniqueStrings([...strings(source.projectionIdentityHashes), ...strings(index.projectionIdentityHashes), ...records.map((record) => record.projectionIdentityHash)]),
107
+ semanticTransformReadinesses: uniqueStrings([...strings(source.semanticTransformReadinesses), ...strings(index.semanticTransformReadinesses), ...records.map((record) => record.readiness)]),
108
+ semanticTransformEvidenceIds: uniqueStrings([...strings(source.semanticTransformEvidenceIds), ...strings(index.semanticTransformEvidenceIds), ...records.flatMap((record) => record.evidenceIds)]),
107
109
  transformSourceLanguages: uniqueStrings([...strings(source.transformSourceLanguages), ...strings(index.transformSourceLanguages), ...records.map((record) => record.sourceLanguage)]),
108
110
  transformTargetLanguages: uniqueStrings([...strings(source.transformTargetLanguages), ...strings(index.transformTargetLanguages), ...records.map((record) => record.targetLanguage)]),
109
111
  transformSourcePaths: uniqueStrings([...strings(source.transformSourcePaths), ...strings(index.transformSourcePaths), ...records.map((record) => record.sourcePath)]),
@@ -119,6 +121,8 @@ export function semanticTransformSummary(index) {
119
121
  identityHashes: index.semanticTransformIdentityHashes,
120
122
  contentHashes: index.semanticTransformContentHashes,
121
123
  projectionIdentityHashes: index.projectionIdentityHashes,
124
+ readinesses: index.semanticTransformReadinesses,
125
+ evidenceIds: index.semanticTransformEvidenceIds,
122
126
  sourceLanguages: index.transformSourceLanguages,
123
127
  targetLanguages: index.transformTargetLanguages,
124
128
  targetPaths: index.transformTargetPaths
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshift-labs/frontier-lang-compiler",
3
- "version": "0.2.90",
3
+ "version": "0.2.91",
4
4
  "description": "Compiler facade for Frontier Lang source documents and language projection adapters.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",