@shapeshift-labs/frontier-lang-compiler 0.2.87 → 0.2.89
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/dist/declarations/semantic-patch-bundle-overlaps.d.ts +124 -0
- package/dist/declarations/semantic-patch-bundle.d.ts +34 -0
- package/dist/declarations/semantic-transform-identity.d.ts +57 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/internal/index-impl/semanticPatchBundleOverlaps.js +191 -0
- package/dist/internal/index-impl/semanticPatchBundleRecords.js +28 -3
- package/dist/internal/index-impl/semanticTransformIdentityRecords.js +127 -0
- package/package.json +1 -1
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { SemanticPatchBundleRecord } from './semantic-patch-bundle.js';
|
|
2
|
+
|
|
3
|
+
export type SemanticPatchBundleOverlapKind =
|
|
4
|
+
| 'operation-content'
|
|
5
|
+
| 'edit-content'
|
|
6
|
+
| 'semantic-edit-key'
|
|
7
|
+
| 'semantic-identity'
|
|
8
|
+
| 'source-identity'
|
|
9
|
+
| 'transform-content'
|
|
10
|
+
| 'semantic-transform'
|
|
11
|
+
| 'projection-identity'
|
|
12
|
+
| 'region'
|
|
13
|
+
| 'conflict-key'
|
|
14
|
+
| 'source-path'
|
|
15
|
+
| string;
|
|
16
|
+
|
|
17
|
+
export type SemanticPatchBundleOverlapStatus =
|
|
18
|
+
| 'duplicate'
|
|
19
|
+
| 'semantic-overlap'
|
|
20
|
+
| 'source-overlap'
|
|
21
|
+
| 'independent'
|
|
22
|
+
| string;
|
|
23
|
+
|
|
24
|
+
export interface SemanticPatchBundleOverlapShared {
|
|
25
|
+
readonly operationContentHashes: readonly string[];
|
|
26
|
+
readonly editContentHashes: readonly string[];
|
|
27
|
+
readonly semanticEditKeys: readonly string[];
|
|
28
|
+
readonly semanticIdentityHashes: readonly string[];
|
|
29
|
+
readonly sourceIdentityHashes: readonly string[];
|
|
30
|
+
readonly semanticTransformContentHashes: readonly string[];
|
|
31
|
+
readonly semanticTransformIdentityHashes: readonly string[];
|
|
32
|
+
readonly projectionIdentityHashes: readonly string[];
|
|
33
|
+
readonly regionKeys: readonly string[];
|
|
34
|
+
readonly conflictKeys: readonly string[];
|
|
35
|
+
readonly sourcePaths: readonly string[];
|
|
36
|
+
readonly baseHashes: readonly string[];
|
|
37
|
+
readonly targetHashes: readonly string[];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface SemanticPatchBundleOverlapAdmission {
|
|
41
|
+
readonly status: SemanticPatchBundleOverlapStatus;
|
|
42
|
+
readonly reviewRequired: boolean;
|
|
43
|
+
readonly autoMergeClaim: false;
|
|
44
|
+
readonly reasonCodes: readonly string[];
|
|
45
|
+
readonly sharedKeyCount: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface SemanticPatchBundleOverlapRecord {
|
|
49
|
+
readonly kind: 'frontier.lang.semanticPatchBundleOverlapRecord';
|
|
50
|
+
readonly version: 1;
|
|
51
|
+
readonly schema: 'frontier.lang.semanticPatchBundleOverlapRecord.v1';
|
|
52
|
+
readonly id: string;
|
|
53
|
+
readonly leftBundleId: string;
|
|
54
|
+
readonly rightBundleId: string;
|
|
55
|
+
readonly overlapKinds: readonly SemanticPatchBundleOverlapKind[];
|
|
56
|
+
readonly shared: SemanticPatchBundleOverlapShared;
|
|
57
|
+
readonly admission: SemanticPatchBundleOverlapAdmission;
|
|
58
|
+
readonly score: number;
|
|
59
|
+
readonly summary: {
|
|
60
|
+
readonly sharedKeys: number;
|
|
61
|
+
readonly duplicateSignals: number;
|
|
62
|
+
readonly semanticSignals: number;
|
|
63
|
+
readonly sourceSignals: number;
|
|
64
|
+
readonly baseHashMismatch: boolean;
|
|
65
|
+
readonly targetHashMismatch: boolean;
|
|
66
|
+
};
|
|
67
|
+
readonly metadata?: Record<string, unknown>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface CompareSemanticPatchBundleRecordsOptions {
|
|
71
|
+
readonly id?: string;
|
|
72
|
+
readonly includeSourcePaths?: boolean;
|
|
73
|
+
readonly reviewIndependent?: boolean;
|
|
74
|
+
readonly metadata?: Record<string, unknown>;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface SemanticPatchBundleOverlapQuery {
|
|
78
|
+
readonly includeIndependent?: boolean;
|
|
79
|
+
readonly includeSourcePaths?: boolean;
|
|
80
|
+
readonly reviewIndependent?: boolean;
|
|
81
|
+
readonly metadata?: Record<string, unknown>;
|
|
82
|
+
readonly id?: string | readonly string[];
|
|
83
|
+
readonly ids?: readonly string[];
|
|
84
|
+
readonly bundleId?: string | readonly string[];
|
|
85
|
+
readonly bundleIds?: readonly string[];
|
|
86
|
+
readonly status?: SemanticPatchBundleOverlapStatus | readonly string[];
|
|
87
|
+
readonly statuses?: readonly string[];
|
|
88
|
+
readonly admissionStatus?: SemanticPatchBundleOverlapStatus | readonly string[];
|
|
89
|
+
readonly admissionStatuses?: readonly string[];
|
|
90
|
+
readonly overlapKind?: SemanticPatchBundleOverlapKind | readonly string[];
|
|
91
|
+
readonly overlapKinds?: readonly string[];
|
|
92
|
+
readonly reasonCode?: string | readonly string[];
|
|
93
|
+
readonly reasonCodes?: readonly string[];
|
|
94
|
+
readonly sourcePath?: string | readonly string[];
|
|
95
|
+
readonly sourcePaths?: readonly string[];
|
|
96
|
+
readonly conflictKey?: string | readonly string[];
|
|
97
|
+
readonly conflictKeys?: readonly string[];
|
|
98
|
+
readonly semanticEditKey?: string | readonly string[];
|
|
99
|
+
readonly semanticEditKeys?: readonly string[];
|
|
100
|
+
readonly semanticTransformIdentityHash?: string | readonly string[];
|
|
101
|
+
readonly semanticTransformIdentityHashes?: readonly string[];
|
|
102
|
+
readonly semanticTransformContentHash?: string | readonly string[];
|
|
103
|
+
readonly semanticTransformContentHashes?: readonly string[];
|
|
104
|
+
readonly projectionIdentityHash?: string | readonly string[];
|
|
105
|
+
readonly projectionIdentityHashes?: readonly string[];
|
|
106
|
+
readonly operationContentHash?: string | readonly string[];
|
|
107
|
+
readonly operationContentHashes?: readonly string[];
|
|
108
|
+
readonly editContentHash?: string | readonly string[];
|
|
109
|
+
readonly editContentHashes?: readonly string[];
|
|
110
|
+
readonly reviewRequired?: boolean;
|
|
111
|
+
readonly minScore?: number;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export declare const SemanticPatchBundleOverlapKinds: readonly SemanticPatchBundleOverlapKind[];
|
|
115
|
+
export declare const SemanticPatchBundleOverlapStatuses: readonly SemanticPatchBundleOverlapStatus[];
|
|
116
|
+
export declare function compareSemanticPatchBundleRecords(
|
|
117
|
+
left?: SemanticPatchBundleRecord | Record<string, unknown>,
|
|
118
|
+
right?: SemanticPatchBundleRecord | Record<string, unknown>,
|
|
119
|
+
options?: CompareSemanticPatchBundleRecordsOptions
|
|
120
|
+
): SemanticPatchBundleOverlapRecord;
|
|
121
|
+
export declare function querySemanticPatchBundleOverlaps(
|
|
122
|
+
records: SemanticPatchBundleRecord | readonly SemanticPatchBundleRecord[],
|
|
123
|
+
query?: SemanticPatchBundleOverlapQuery
|
|
124
|
+
): readonly SemanticPatchBundleOverlapRecord[];
|
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
} from '@shapeshift-labs/frontier-lang-kernel';
|
|
9
9
|
import type { NativeSourceChangeKind, NativeSourceChangeSet } from './native-diff.js';
|
|
10
10
|
import type { SemanticEditProjection, SemanticEditScript } from './semantic-edit-script.js';
|
|
11
|
+
import type { SemanticTransformIdentityRecord } from './semantic-transform-identity.js';
|
|
11
12
|
|
|
12
13
|
export type SemanticPatchBundleAdmissionStatus = 'proposed' | 'queued' | 'admitted' | 'needs-review' | 'blocked' | 'rejected' | string;
|
|
13
14
|
|
|
@@ -110,6 +111,15 @@ export interface SemanticPatchBundleRecordIndex {
|
|
|
110
111
|
readonly sourceIdentityHashes: readonly string[];
|
|
111
112
|
readonly operationContentHashes: readonly string[];
|
|
112
113
|
readonly editContentHashes: readonly string[];
|
|
114
|
+
readonly semanticTransformIds: readonly string[];
|
|
115
|
+
readonly semanticTransformKeys: readonly string[];
|
|
116
|
+
readonly semanticTransformIdentityHashes: readonly string[];
|
|
117
|
+
readonly semanticTransformContentHashes: readonly string[];
|
|
118
|
+
readonly projectionIdentityHashes: readonly string[];
|
|
119
|
+
readonly transformSourceLanguages: readonly string[];
|
|
120
|
+
readonly transformTargetLanguages: readonly string[];
|
|
121
|
+
readonly transformSourcePaths: readonly string[];
|
|
122
|
+
readonly transformTargetPaths: readonly string[];
|
|
113
123
|
readonly patchIds: readonly string[];
|
|
114
124
|
readonly mergeCandidateIds: readonly string[];
|
|
115
125
|
readonly readinesses: readonly string[];
|
|
@@ -137,6 +147,7 @@ export interface SemanticPatchBundleRecord {
|
|
|
137
147
|
readonly semanticOperationIds: readonly string[];
|
|
138
148
|
readonly semanticEditScriptIds: readonly string[];
|
|
139
149
|
readonly semanticEditProjectionIds: readonly string[];
|
|
150
|
+
readonly semanticTransformIdentityIds: readonly string[];
|
|
140
151
|
readonly admission: SemanticPatchBundleAdmission;
|
|
141
152
|
readonly index: SemanticPatchBundleRecordIndex;
|
|
142
153
|
readonly summary: {
|
|
@@ -149,6 +160,7 @@ export interface SemanticPatchBundleRecord {
|
|
|
149
160
|
readonly semanticEditScripts: number;
|
|
150
161
|
readonly semanticEditProjections: number;
|
|
151
162
|
readonly semanticEditProjectionEdits: number;
|
|
163
|
+
readonly semanticTransformIdentities: number;
|
|
152
164
|
readonly reviewRequired: boolean;
|
|
153
165
|
readonly autoMergeClaim: false;
|
|
154
166
|
};
|
|
@@ -181,6 +193,10 @@ export interface CreateSemanticPatchBundleRecordOptions {
|
|
|
181
193
|
readonly semanticEditScripts?: readonly SemanticEditScript[] | SemanticEditScript;
|
|
182
194
|
readonly semanticEditProjection?: SemanticEditProjection;
|
|
183
195
|
readonly semanticEditProjections?: readonly SemanticEditProjection[] | SemanticEditProjection;
|
|
196
|
+
readonly semanticTransformIdentity?: SemanticTransformIdentityRecord | Record<string, unknown>;
|
|
197
|
+
readonly semanticTransformIdentities?: readonly (SemanticTransformIdentityRecord | Record<string, unknown>)[];
|
|
198
|
+
readonly sourceLanguage?: FrontierSourceLanguage | string;
|
|
199
|
+
readonly targetLanguage?: FrontierSourceLanguage | string;
|
|
184
200
|
readonly conflictKeys?: readonly string[] | string;
|
|
185
201
|
readonly admission?: Partial<SemanticPatchBundleAdmission>;
|
|
186
202
|
readonly metadata?: Record<string, unknown>;
|
|
@@ -237,6 +253,24 @@ export interface SemanticPatchBundleRecordQuery {
|
|
|
237
253
|
readonly operationContentHashes?: readonly string[];
|
|
238
254
|
readonly editContentHash?: string | readonly string[];
|
|
239
255
|
readonly editContentHashes?: readonly string[];
|
|
256
|
+
readonly semanticTransformId?: string | readonly string[];
|
|
257
|
+
readonly semanticTransformIds?: readonly string[];
|
|
258
|
+
readonly semanticTransformKey?: string | readonly string[];
|
|
259
|
+
readonly semanticTransformKeys?: readonly string[];
|
|
260
|
+
readonly semanticTransformIdentityHash?: string | readonly string[];
|
|
261
|
+
readonly semanticTransformIdentityHashes?: readonly string[];
|
|
262
|
+
readonly semanticTransformContentHash?: string | readonly string[];
|
|
263
|
+
readonly semanticTransformContentHashes?: readonly string[];
|
|
264
|
+
readonly projectionIdentityHash?: string | readonly string[];
|
|
265
|
+
readonly projectionIdentityHashes?: readonly string[];
|
|
266
|
+
readonly transformSourceLanguage?: string | readonly string[];
|
|
267
|
+
readonly transformSourceLanguages?: readonly string[];
|
|
268
|
+
readonly transformTargetLanguage?: string | readonly string[];
|
|
269
|
+
readonly transformTargetLanguages?: readonly string[];
|
|
270
|
+
readonly transformSourcePath?: string | readonly string[];
|
|
271
|
+
readonly transformSourcePaths?: readonly string[];
|
|
272
|
+
readonly transformTargetPath?: string | readonly string[];
|
|
273
|
+
readonly transformTargetPaths?: readonly string[];
|
|
240
274
|
readonly readiness?: SemanticMergeReadiness | string | readonly string[];
|
|
241
275
|
readonly readinesses?: readonly string[];
|
|
242
276
|
readonly admissionStatus?: SemanticPatchBundleAdmissionStatus | readonly string[];
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { FrontierSourceLanguage } from '@shapeshift-labs/frontier-lang-kernel';
|
|
2
|
+
|
|
3
|
+
export interface SemanticTransformIdentityRecord {
|
|
4
|
+
readonly kind: 'frontier.lang.semanticTransformIdentityRecord';
|
|
5
|
+
readonly version: 1;
|
|
6
|
+
readonly schema: 'frontier.lang.semanticTransformIdentityRecord.v1';
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly sourceLanguage?: FrontierSourceLanguage | string;
|
|
9
|
+
readonly targetLanguage?: FrontierSourceLanguage | string;
|
|
10
|
+
readonly sourcePath?: string;
|
|
11
|
+
readonly targetPath?: string;
|
|
12
|
+
readonly baseHash?: string;
|
|
13
|
+
readonly targetHash?: string;
|
|
14
|
+
readonly semanticKey?: string;
|
|
15
|
+
readonly transformKey?: string;
|
|
16
|
+
readonly semanticIdentityHash?: string;
|
|
17
|
+
readonly sourceIdentityHash?: string;
|
|
18
|
+
readonly operationContentHash?: string;
|
|
19
|
+
readonly editContentHash?: string;
|
|
20
|
+
readonly transformIdentityHash?: string;
|
|
21
|
+
readonly projectionIdentityHash?: string;
|
|
22
|
+
readonly transformContentHash?: string;
|
|
23
|
+
readonly readiness?: string;
|
|
24
|
+
readonly confidence?: number;
|
|
25
|
+
readonly evidenceIds?: readonly string[];
|
|
26
|
+
readonly metadata?: {
|
|
27
|
+
readonly autoMergeClaim: false;
|
|
28
|
+
readonly semanticEquivalenceClaim: false;
|
|
29
|
+
readonly sourceTransformId?: string;
|
|
30
|
+
readonly [key: string]: unknown;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface CreateSemanticTransformIdentityRecordOptions extends Partial<SemanticTransformIdentityRecord> {
|
|
35
|
+
readonly language?: FrontierSourceLanguage | string;
|
|
36
|
+
readonly projectedLanguage?: FrontierSourceLanguage | string;
|
|
37
|
+
readonly originalSourcePath?: string;
|
|
38
|
+
readonly targetSourcePath?: string;
|
|
39
|
+
readonly projectedSourcePath?: string;
|
|
40
|
+
readonly symbolName?: string;
|
|
41
|
+
readonly symbolKind?: string;
|
|
42
|
+
readonly anchorKey?: string;
|
|
43
|
+
readonly regionId?: string;
|
|
44
|
+
readonly operationId?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type CreateSemanticTransformIdentityRecordInput =
|
|
48
|
+
| Partial<SemanticTransformIdentityRecord>
|
|
49
|
+
| Record<string, unknown>;
|
|
50
|
+
|
|
51
|
+
export declare function createSemanticTransformIdentityRecord(
|
|
52
|
+
input?: CreateSemanticTransformIdentityRecordInput,
|
|
53
|
+
options?: CreateSemanticTransformIdentityRecordOptions
|
|
54
|
+
): SemanticTransformIdentityRecord;
|
|
55
|
+
export declare function semanticTransformIdentityFields(
|
|
56
|
+
record?: SemanticTransformIdentityRecord | Record<string, unknown>
|
|
57
|
+
): SemanticTransformIdentityRecord;
|
package/dist/index.d.ts
CHANGED
|
@@ -20,6 +20,8 @@ export * from './declarations/semantic-edit-script.js';
|
|
|
20
20
|
export * from './declarations/semantic-lineage.js';
|
|
21
21
|
export * from './declarations/semantic-history.js';
|
|
22
22
|
export * from './declarations/semantic-patch-bundle.js';
|
|
23
|
+
export * from './declarations/semantic-patch-bundle-overlaps.js';
|
|
24
|
+
export * from './declarations/semantic-transform-identity.js';
|
|
23
25
|
export * from './declarations/bidirectional-target-change.js';
|
|
24
26
|
export * from './declarations/semantic-impact.js';
|
|
25
27
|
export * from './declarations/semantic-sidecar.js';
|
package/dist/index.js
CHANGED
|
@@ -67,6 +67,8 @@ export { projectNativeImportToSource } from './internal/index-impl/projectNative
|
|
|
67
67
|
export { queryNativeParserFeatureMatrix } from './internal/index-impl/queryNativeParserFeatureMatrix.js';
|
|
68
68
|
export { queryProjectionReadinessMatrix } from './internal/index-impl/queryProjectionReadinessMatrix.js';
|
|
69
69
|
export { createSemanticPatchBundleRecord, querySemanticPatchBundleRecords, SemanticPatchBundleAdmissionStatuses } from './internal/index-impl/semanticPatchBundleRecords.js';
|
|
70
|
+
export { compareSemanticPatchBundleRecords, querySemanticPatchBundleOverlaps, SemanticPatchBundleOverlapKinds, SemanticPatchBundleOverlapStatuses } from './internal/index-impl/semanticPatchBundleOverlaps.js';
|
|
71
|
+
export { createSemanticTransformIdentityRecord, semanticTransformIdentityFields } from './internal/index-impl/semanticTransformIdentityRecords.js';
|
|
70
72
|
export { createSemanticMergeCandidateAdmissionRecord, decorateSemanticMergeCandidateForAdmission, querySemanticMergeCandidateAdmissionOverlaps, SemanticMergeCandidateProjectionRisks, semanticMergeCandidateReadinessSortKey, sortSemanticMergeCandidateAdmissionRecords } from './internal/index-impl/semanticMergeCandidateRecords.js';
|
|
71
73
|
export { querySemanticMergeConflictClasses, SemanticMergeConflictClasses, semanticMergeConflictRiskScore, sortSemanticMergeCandidatesByConflictRisk, summarizeSemanticMergeConflicts } from './internal/index-impl/semanticMergeConflicts.js';
|
|
72
74
|
export { createSemanticEditScript, SemanticEditScriptAdmissionStatuses } from './internal/index-impl/semanticEditScripts.js';
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import{idFragment,uniqueStrings as uniqueRawStrings}from'../../native-import-utils.js';
|
|
2
|
+
|
|
3
|
+
export const SemanticPatchBundleOverlapKinds=Object.freeze([
|
|
4
|
+
'operation-content',
|
|
5
|
+
'edit-content',
|
|
6
|
+
'semantic-edit-key',
|
|
7
|
+
'semantic-identity',
|
|
8
|
+
'source-identity',
|
|
9
|
+
'transform-content',
|
|
10
|
+
'semantic-transform',
|
|
11
|
+
'projection-identity',
|
|
12
|
+
'region',
|
|
13
|
+
'conflict-key',
|
|
14
|
+
'source-path'
|
|
15
|
+
]);
|
|
16
|
+
|
|
17
|
+
export const SemanticPatchBundleOverlapStatuses=Object.freeze([
|
|
18
|
+
'duplicate',
|
|
19
|
+
'semantic-overlap',
|
|
20
|
+
'source-overlap',
|
|
21
|
+
'independent'
|
|
22
|
+
]);
|
|
23
|
+
|
|
24
|
+
const KIND_FIELDS=Object.freeze({
|
|
25
|
+
'operation-content':'operationContentHashes',
|
|
26
|
+
'edit-content':'editContentHashes',
|
|
27
|
+
'semantic-edit-key':'semanticEditKeys',
|
|
28
|
+
'semantic-identity':'semanticIdentityHashes',
|
|
29
|
+
'source-identity':'sourceIdentityHashes',
|
|
30
|
+
'transform-content':'semanticTransformContentHashes',
|
|
31
|
+
'semantic-transform':'semanticTransformIdentityHashes',
|
|
32
|
+
'projection-identity':'projectionIdentityHashes',
|
|
33
|
+
region:'regionKeys',
|
|
34
|
+
'conflict-key':'conflictKeys',
|
|
35
|
+
'source-path':'sourcePaths'
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export function compareSemanticPatchBundleRecords(left={},right={},options={}){
|
|
39
|
+
const leftIndex=bundleIndex(left);
|
|
40
|
+
const rightIndex=bundleIndex(right);
|
|
41
|
+
const shared=sharedIndex(leftIndex,rightIndex,options);
|
|
42
|
+
const overlapKinds=SemanticPatchBundleOverlapKinds
|
|
43
|
+
.filter((kind)=>shared[KIND_FIELDS[kind]]?.length);
|
|
44
|
+
const admission=overlapAdmission(shared,{leftIndex,rightIndex,options});
|
|
45
|
+
return{
|
|
46
|
+
kind:'frontier.lang.semanticPatchBundleOverlapRecord',
|
|
47
|
+
version:1,
|
|
48
|
+
schema:'frontier.lang.semanticPatchBundleOverlapRecord.v1',
|
|
49
|
+
id:options.id??`semantic_patch_bundle_overlap_${idFragment(left?.id??'left')}_${idFragment(right?.id??'right')}`,
|
|
50
|
+
leftBundleId:String(left?.id??'left'),
|
|
51
|
+
rightBundleId:String(right?.id??'right'),
|
|
52
|
+
overlapKinds,
|
|
53
|
+
shared,
|
|
54
|
+
admission,
|
|
55
|
+
score:overlapScore(admission.status,shared,admission.reasonCodes),
|
|
56
|
+
summary:{
|
|
57
|
+
sharedKeys:countShared(shared),
|
|
58
|
+
duplicateSignals:shared.operationContentHashes.length+shared.editContentHashes.length+shared.semanticTransformContentHashes.length,
|
|
59
|
+
semanticSignals:shared.semanticEditKeys.length+shared.semanticIdentityHashes.length+shared.sourceIdentityHashes.length+shared.semanticTransformIdentityHashes.length+shared.projectionIdentityHashes.length,
|
|
60
|
+
sourceSignals:shared.regionKeys.length+shared.conflictKeys.length+shared.sourcePaths.length,
|
|
61
|
+
baseHashMismatch:admission.reasonCodes.includes('base-hash-mismatch'),
|
|
62
|
+
targetHashMismatch:admission.reasonCodes.includes('target-hash-mismatch')
|
|
63
|
+
},
|
|
64
|
+
metadata:compactRecord(options.metadata)
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function querySemanticPatchBundleOverlaps(records,query={}){
|
|
69
|
+
const list=array(records).filter(Boolean);
|
|
70
|
+
const result=[];
|
|
71
|
+
const compareOptions={
|
|
72
|
+
includeSourcePaths:query.includeSourcePaths,
|
|
73
|
+
reviewIndependent:query.reviewIndependent,
|
|
74
|
+
metadata:query.metadata
|
|
75
|
+
};
|
|
76
|
+
for(let leftIndex=0;leftIndex<list.length;leftIndex+=1){
|
|
77
|
+
for(let rightIndex=leftIndex+1;rightIndex<list.length;rightIndex+=1){
|
|
78
|
+
const overlap=compareSemanticPatchBundleRecords(list[leftIndex],list[rightIndex],compareOptions);
|
|
79
|
+
if(matchesOverlap(overlap,query))result.push(overlap);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return result.sort((left,right)=>right.score-left.score||left.leftBundleId.localeCompare(right.leftBundleId)
|
|
83
|
+
||left.rightBundleId.localeCompare(right.rightBundleId));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function sharedIndex(left,right,options){
|
|
87
|
+
return{
|
|
88
|
+
operationContentHashes:intersect(left.operationContentHashes,right.operationContentHashes),
|
|
89
|
+
editContentHashes:intersect(left.editContentHashes,right.editContentHashes),
|
|
90
|
+
semanticEditKeys:intersect(left.semanticEditKeys,right.semanticEditKeys),
|
|
91
|
+
semanticIdentityHashes:intersect(left.semanticIdentityHashes,right.semanticIdentityHashes),
|
|
92
|
+
sourceIdentityHashes:intersect(left.sourceIdentityHashes,right.sourceIdentityHashes),
|
|
93
|
+
semanticTransformContentHashes:intersect(left.semanticTransformContentHashes,right.semanticTransformContentHashes),
|
|
94
|
+
semanticTransformIdentityHashes:intersect(left.semanticTransformIdentityHashes,right.semanticTransformIdentityHashes),
|
|
95
|
+
projectionIdentityHashes:intersect(left.projectionIdentityHashes,right.projectionIdentityHashes),
|
|
96
|
+
regionKeys:intersect(left.regionKeys,right.regionKeys),
|
|
97
|
+
conflictKeys:intersect(left.conflictKeys,right.conflictKeys),
|
|
98
|
+
sourcePaths:options.includeSourcePaths===false?[]:intersect(left.sourcePaths,right.sourcePaths),
|
|
99
|
+
baseHashes:intersect(left.baseHashes,right.baseHashes),
|
|
100
|
+
targetHashes:intersect(left.targetHashes,right.targetHashes)
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function overlapAdmission(shared,{leftIndex,rightIndex,options}){
|
|
105
|
+
const duplicate=shared.operationContentHashes.length||shared.editContentHashes.length||shared.semanticTransformContentHashes.length;
|
|
106
|
+
const semantic=shared.semanticEditKeys.length||shared.semanticIdentityHashes.length||shared.sourceIdentityHashes.length||shared.semanticTransformIdentityHashes.length||shared.projectionIdentityHashes.length;
|
|
107
|
+
const source=shared.regionKeys.length||shared.conflictKeys.length||shared.sourcePaths.length;
|
|
108
|
+
const status=duplicate?'duplicate':semantic?'semantic-overlap':source?'source-overlap':'independent';
|
|
109
|
+
const reasonCodes=uniqueStrings([
|
|
110
|
+
shared.operationContentHashes.length?'same-operation-content':undefined,
|
|
111
|
+
shared.editContentHashes.length?'same-edit-content':undefined,
|
|
112
|
+
shared.semanticTransformContentHashes.length?'same-transform-content':undefined,
|
|
113
|
+
shared.semanticEditKeys.length?'same-semantic-edit-key':undefined,
|
|
114
|
+
shared.semanticIdentityHashes.length?'same-semantic-identity':undefined,
|
|
115
|
+
shared.sourceIdentityHashes.length?'same-source-identity':undefined,
|
|
116
|
+
shared.semanticTransformIdentityHashes.length?'same-semantic-transform':undefined,
|
|
117
|
+
shared.projectionIdentityHashes.length?'same-projection-identity':undefined,
|
|
118
|
+
shared.regionKeys.length?'same-region-key':undefined,
|
|
119
|
+
shared.conflictKeys.length?'same-conflict-key':undefined,
|
|
120
|
+
shared.sourcePaths.length?'same-source-path':undefined,
|
|
121
|
+
status!=='independent'&&disjointNonEmpty(leftIndex.baseHashes,rightIndex.baseHashes)?'base-hash-mismatch':undefined,
|
|
122
|
+
status!=='independent'&&disjointNonEmpty(leftIndex.targetHashes,rightIndex.targetHashes)?'target-hash-mismatch':undefined
|
|
123
|
+
]);
|
|
124
|
+
return{
|
|
125
|
+
status,
|
|
126
|
+
reviewRequired:options.reviewIndependent?true:status!=='independent',
|
|
127
|
+
autoMergeClaim:false,
|
|
128
|
+
reasonCodes,
|
|
129
|
+
sharedKeyCount:countShared(shared)
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function bundleIndex(record){
|
|
134
|
+
const index=record?.index??{};
|
|
135
|
+
return{
|
|
136
|
+
baseHashes:uniqueStrings([record?.baseHash,...strings(index.baseHashes)]),
|
|
137
|
+
targetHashes:uniqueStrings([record?.targetHash,...strings(index.targetHashes)]),
|
|
138
|
+
sourcePaths:uniqueStrings([record?.sourcePath,...strings(index.sourcePaths)]),
|
|
139
|
+
regionKeys:uniqueStrings(index.regionKeys),
|
|
140
|
+
conflictKeys:uniqueStrings(index.conflictKeys),
|
|
141
|
+
semanticEditKeys:uniqueStrings(index.semanticEditKeys),
|
|
142
|
+
semanticIdentityHashes:uniqueStrings(index.semanticIdentityHashes),
|
|
143
|
+
sourceIdentityHashes:uniqueStrings(index.sourceIdentityHashes),
|
|
144
|
+
semanticTransformContentHashes:uniqueStrings(index.semanticTransformContentHashes),
|
|
145
|
+
semanticTransformIdentityHashes:uniqueStrings(index.semanticTransformIdentityHashes),
|
|
146
|
+
projectionIdentityHashes:uniqueStrings(index.projectionIdentityHashes),
|
|
147
|
+
operationContentHashes:uniqueStrings(index.operationContentHashes),
|
|
148
|
+
editContentHashes:uniqueStrings(index.editContentHashes)
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function matchesOverlap(overlap,query){
|
|
153
|
+
const statusFilters=queryValues(query.status,query.statuses,query.admissionStatus,query.admissionStatuses);
|
|
154
|
+
const includeIndependent=query.includeIndependent===true||statusFilters.includes('independent');
|
|
155
|
+
if(!includeIndependent&&overlap.admission.status==='independent')return false;
|
|
156
|
+
return matchAny(queryValues(query.id,query.ids),[overlap.id])
|
|
157
|
+
&&matchAny(queryValues(query.bundleId,query.bundleIds),[overlap.leftBundleId,overlap.rightBundleId])
|
|
158
|
+
&&matchAny(statusFilters,[overlap.admission.status])
|
|
159
|
+
&&matchAny(queryValues(query.overlapKind,query.overlapKinds),overlap.overlapKinds)
|
|
160
|
+
&&matchAny(queryValues(query.reasonCode,query.reasonCodes),overlap.admission.reasonCodes)
|
|
161
|
+
&&matchAny(queryValues(query.sourcePath,query.sourcePaths),overlap.shared.sourcePaths)
|
|
162
|
+
&&matchAny(queryValues(query.conflictKey,query.conflictKeys),overlap.shared.conflictKeys)
|
|
163
|
+
&&matchAny(queryValues(query.semanticEditKey,query.semanticEditKeys),overlap.shared.semanticEditKeys)
|
|
164
|
+
&&matchAny(queryValues(query.semanticTransformIdentityHash,query.semanticTransformIdentityHashes),overlap.shared.semanticTransformIdentityHashes)
|
|
165
|
+
&&matchAny(queryValues(query.semanticTransformContentHash,query.semanticTransformContentHashes),overlap.shared.semanticTransformContentHashes)
|
|
166
|
+
&&matchAny(queryValues(query.projectionIdentityHash,query.projectionIdentityHashes),overlap.shared.projectionIdentityHashes)
|
|
167
|
+
&&matchAny(queryValues(query.operationContentHash,query.operationContentHashes),overlap.shared.operationContentHashes)
|
|
168
|
+
&&matchAny(queryValues(query.editContentHash,query.editContentHashes),overlap.shared.editContentHashes)
|
|
169
|
+
&&(query.reviewRequired===undefined||overlap.admission.reviewRequired===query.reviewRequired)
|
|
170
|
+
&&(query.minScore===undefined||overlap.score>=Number(query.minScore));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function overlapScore(status,shared,reasonCodes){
|
|
174
|
+
const base=status==='duplicate'?100:status==='semantic-overlap'?75:status==='source-overlap'?35:0;
|
|
175
|
+
const sharedBonus=Math.min(20,countShared(shared));
|
|
176
|
+
const stalePenalty=reasonCodes.includes('base-hash-mismatch')||reasonCodes.includes('target-hash-mismatch')?15:0;
|
|
177
|
+
return Math.max(0,base+sharedBonus-stalePenalty);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function countShared(shared){
|
|
181
|
+
return Object.values(shared).reduce((total,values)=>total+(Array.isArray(values)?values.length:0),0);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function intersect(left,right){const rightSet=new Set(right??[]);return uniqueStrings((left??[]).filter((value)=>rightSet.has(value)));}
|
|
185
|
+
function disjointNonEmpty(left,right){return Boolean(left?.length&&right?.length&&intersect(left,right).length===0);}
|
|
186
|
+
function queryValues(...values){return uniqueStrings(values.flatMap((value)=>strings(value)));}
|
|
187
|
+
function matchAny(filters,values){if(filters.length===0)return true;const valueSet=new Set(strings(values));return filters.some((filter)=>valueSet.has(filter));}
|
|
188
|
+
function array(value){if(value===undefined||value===null)return[];return Array.isArray(value)?value:[value];}
|
|
189
|
+
function strings(value){return array(value).map((entry)=>String(entry??'')).filter(Boolean);}
|
|
190
|
+
function uniqueStrings(values){return uniqueRawStrings((values??[]).filter((entry)=>entry!==undefined&&entry!==null&&String(entry)!==''));}
|
|
191
|
+
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{normalizeSemanticTransformIdentityRecords,semanticTransformInputs,semanticTransformRecordIndex,semanticTransformSummary}from'./semanticTransformIdentityRecords.js';
|
|
2
3
|
|
|
3
4
|
export const SemanticPatchBundleAdmissionStatuses=Object.freeze(['proposed','queued','admitted','needs-review','blocked','rejected']);
|
|
4
5
|
|
|
@@ -9,6 +10,9 @@ export function createSemanticPatchBundleRecord(input={},options={}){
|
|
|
9
10
|
const semanticEditScripts=array(options.semanticEditScripts??source.semanticEditScripts??source.semanticEditScript);
|
|
10
11
|
const semanticEditProjections=array(options.semanticEditProjections??source.semanticEditProjections??source.semanticEditProjection);
|
|
11
12
|
const semanticEditIndex=semanticEditRecordIndex(semanticEditScripts,semanticEditProjections,source);
|
|
13
|
+
const transformContext={sourceLanguage:options.sourceLanguage??source.sourceLanguage??source.language,targetLanguage:options.targetLanguage??source.targetLanguage};
|
|
14
|
+
const semanticTransformIdentities=normalizeSemanticTransformIdentityRecords(semanticTransformInputs(source,options),transformContext);
|
|
15
|
+
const semanticTransformIndex=semanticTransformRecordIndex(semanticTransformIdentities,source);
|
|
12
16
|
const regionInputs=array(options.changedRegions??source.changedRegions??source.regions);
|
|
13
17
|
const sourceMapLinks=normalizeSourceMapLinks([
|
|
14
18
|
...array(options.sourceMapLinks??source.sourceMapLinks),
|
|
@@ -43,7 +47,7 @@ export function createSemanticPatchBundleRecord(input={},options={}){
|
|
|
43
47
|
??`semantic_patch_bundle_${idFragment(firstString(source.id,patchId,mergeCandidateId,source.sourcePath,source.language,'record'))}`;
|
|
44
48
|
const language=options.language??source.language??mergeCandidate?.language??sources.find((item)=>item.language)?.language;
|
|
45
49
|
const sourcePath=options.sourcePath??source.sourcePath??mergeCandidate?.sourcePath??sources.find((item)=>item.sourcePath)?.sourcePath;
|
|
46
|
-
const index=recordIndex({baseHash,targetHash,sources,changedRegions,sourceMapLinks,evidenceIds,proofIds,historyIds,semanticOperationIds,patchId,mergeCandidateId,admission,semanticEditIndex});
|
|
50
|
+
const index=recordIndex({baseHash,targetHash,sources,changedRegions,sourceMapLinks,evidenceIds,proofIds,historyIds,semanticOperationIds,patchId,mergeCandidateId,admission,semanticEditIndex,semanticTransformIndex});
|
|
47
51
|
return{
|
|
48
52
|
kind:'frontier.lang.semanticPatchBundleRecord',
|
|
49
53
|
version:1,
|
|
@@ -65,9 +69,10 @@ export function createSemanticPatchBundleRecord(input={},options={}){
|
|
|
65
69
|
semanticOperationIds,
|
|
66
70
|
semanticEditScriptIds:semanticEditIndex.semanticEditScriptIds,
|
|
67
71
|
semanticEditProjectionIds:semanticEditIndex.semanticEditProjectionIds,
|
|
72
|
+
semanticTransformIdentityIds:semanticTransformIndex.semanticTransformIds,
|
|
68
73
|
admission,
|
|
69
74
|
index,
|
|
70
|
-
summary:{changedRegions:changedRegions.length,sourceMapLinks:sourceMapLinks.length,evidenceIds:evidenceIds.length,proofIds:proofIds.length,historyIds:historyIds.length,semanticOperations:semanticOperationIds.length,semanticEditScripts:semanticEditScripts.length,semanticEditProjections:semanticEditProjections.length,semanticEditProjectionEdits:semanticEditIndex.semanticEditProjectionEditCount,reviewRequired:admission.reviewRequired,autoMergeClaim:admission.autoMergeClaim},
|
|
75
|
+
summary:{changedRegions:changedRegions.length,sourceMapLinks:sourceMapLinks.length,evidenceIds:evidenceIds.length,proofIds:proofIds.length,historyIds:historyIds.length,semanticOperations:semanticOperationIds.length,semanticEditScripts:semanticEditScripts.length,semanticEditProjections:semanticEditProjections.length,semanticEditProjectionEdits:semanticEditIndex.semanticEditProjectionEditCount,semanticTransformIdentities:semanticTransformIdentities.length,reviewRequired:admission.reviewRequired,autoMergeClaim:admission.autoMergeClaim},
|
|
71
76
|
metadata:compactRecord({
|
|
72
77
|
sourceChangeSetId:source.kind==='frontier.lang.nativeSourceChangeSet'?source.id:undefined,
|
|
73
78
|
patchRisk:patch?.risk,
|
|
@@ -75,6 +80,7 @@ export function createSemanticPatchBundleRecord(input={},options={}){
|
|
|
75
80
|
changedRegionProjectionSummary:source.metadata?.changedRegionProjectionSummary,
|
|
76
81
|
semanticMergeConflictSummary:source.metadata?.semanticMergeConflictSummary,
|
|
77
82
|
semanticEditSummary:semanticEditSummary(semanticEditIndex),
|
|
83
|
+
semanticTransformSummary:semanticTransformSummary(semanticTransformIndex),
|
|
78
84
|
...options.metadata
|
|
79
85
|
})
|
|
80
86
|
};
|
|
@@ -197,11 +203,12 @@ function normalizeAdmission(input={},context){
|
|
|
197
203
|
|
|
198
204
|
function recordIndex(parts){
|
|
199
205
|
const semanticEditIndex=parts.semanticEditIndex??semanticEditRecordIndex([],[]);
|
|
206
|
+
const semanticTransformIndex=parts.semanticTransformIndex??semanticTransformRecordIndex([],parts);
|
|
200
207
|
return{
|
|
201
208
|
baseHashes:uniqueStrings([parts.baseHash,...parts.sources.map((item)=>item.baseHash)]),
|
|
202
209
|
targetHashes:uniqueStrings([parts.targetHash,...parts.sources.map((item)=>item.targetHash)]),
|
|
203
210
|
sourceHashes:uniqueStrings(parts.sources.map((item)=>item.sourceHash)),
|
|
204
|
-
sourcePaths:uniqueStrings([...parts.sources.map((item)=>item.sourcePath),...semanticEditIndex.projectedSourcePaths]),
|
|
211
|
+
sourcePaths:uniqueStrings([...parts.sources.map((item)=>item.sourcePath),...semanticEditIndex.projectedSourcePaths,...semanticTransformIndex.transformSourcePaths,...semanticTransformIndex.transformTargetPaths]),
|
|
205
212
|
regionKeys:uniqueStrings([...parts.changedRegions.map((region)=>region.key),...semanticEditIndex.anchorKeys]),
|
|
206
213
|
regionKinds:uniqueStrings(parts.changedRegions.map((region)=>region.regionKind)),
|
|
207
214
|
conflictKeys:uniqueStrings([...parts.changedRegions.flatMap((region)=>[region.conflictKey,...array(region.admission?.conflictKeys)]),...semanticEditIndex.conflictKeys]),
|
|
@@ -219,6 +226,15 @@ function recordIndex(parts){
|
|
|
219
226
|
sourceIdentityHashes:semanticEditIndex.sourceIdentityHashes,
|
|
220
227
|
operationContentHashes:semanticEditIndex.operationContentHashes,
|
|
221
228
|
editContentHashes:semanticEditIndex.editContentHashes,
|
|
229
|
+
semanticTransformIds:semanticTransformIndex.semanticTransformIds,
|
|
230
|
+
semanticTransformKeys:semanticTransformIndex.semanticTransformKeys,
|
|
231
|
+
semanticTransformIdentityHashes:semanticTransformIndex.semanticTransformIdentityHashes,
|
|
232
|
+
semanticTransformContentHashes:semanticTransformIndex.semanticTransformContentHashes,
|
|
233
|
+
projectionIdentityHashes:semanticTransformIndex.projectionIdentityHashes,
|
|
234
|
+
transformSourceLanguages:semanticTransformIndex.transformSourceLanguages,
|
|
235
|
+
transformTargetLanguages:semanticTransformIndex.transformTargetLanguages,
|
|
236
|
+
transformSourcePaths:semanticTransformIndex.transformSourcePaths,
|
|
237
|
+
transformTargetPaths:semanticTransformIndex.transformTargetPaths,
|
|
222
238
|
patchIds:uniqueStrings([parts.patchId]),
|
|
223
239
|
mergeCandidateIds:uniqueStrings([parts.mergeCandidateId]),
|
|
224
240
|
readinesses:uniqueStrings([parts.admission.readiness,...parts.changedRegions.map((region)=>region.admission?.readiness)]),
|
|
@@ -252,6 +268,15 @@ function matchesRecord(record,query){
|
|
|
252
268
|
&&matchAny(queryValues(query.sourceIdentityHash,query.sourceIdentityHashes),index.sourceIdentityHashes)
|
|
253
269
|
&&matchAny(queryValues(query.operationContentHash,query.operationContentHashes),index.operationContentHashes)
|
|
254
270
|
&&matchAny(queryValues(query.editContentHash,query.editContentHashes),index.editContentHashes)
|
|
271
|
+
&&matchAny(queryValues(query.semanticTransformId,query.semanticTransformIds),index.semanticTransformIds)
|
|
272
|
+
&&matchAny(queryValues(query.semanticTransformKey,query.semanticTransformKeys),index.semanticTransformKeys)
|
|
273
|
+
&&matchAny(queryValues(query.semanticTransformIdentityHash,query.semanticTransformIdentityHashes),index.semanticTransformIdentityHashes)
|
|
274
|
+
&&matchAny(queryValues(query.semanticTransformContentHash,query.semanticTransformContentHashes),index.semanticTransformContentHashes)
|
|
275
|
+
&&matchAny(queryValues(query.projectionIdentityHash,query.projectionIdentityHashes),index.projectionIdentityHashes)
|
|
276
|
+
&&matchAny(queryValues(query.transformSourceLanguage,query.transformSourceLanguages),index.transformSourceLanguages)
|
|
277
|
+
&&matchAny(queryValues(query.transformTargetLanguage,query.transformTargetLanguages),index.transformTargetLanguages)
|
|
278
|
+
&&matchAny(queryValues(query.transformSourcePath,query.transformSourcePaths),index.transformSourcePaths)
|
|
279
|
+
&&matchAny(queryValues(query.transformTargetPath,query.transformTargetPaths),index.transformTargetPaths)
|
|
255
280
|
&&matchAny(queryValues(query.readiness,query.readinesses),index.readinesses)
|
|
256
281
|
&&matchAny(queryValues(query.admissionStatus,query.admissionStatuses),index.admissionStatuses);
|
|
257
282
|
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { hashSemanticValue } from '@shapeshift-labs/frontier-lang-kernel';
|
|
2
|
+
import { idFragment, uniqueStrings as uniqueRawStrings } from '../../native-import-utils.js';
|
|
3
|
+
import { semanticEditIdentityFields } from './semanticEditIdentityRecords.js';
|
|
4
|
+
|
|
5
|
+
export function createSemanticTransformIdentityRecord(input = {}, options = {}) {
|
|
6
|
+
const source = input?.transform ?? input;
|
|
7
|
+
const merged = { ...source, ...options };
|
|
8
|
+
const editIdentity = semanticEditIdentityFields(merged);
|
|
9
|
+
const semanticKey = firstString(merged.semanticKey, editIdentity.semanticKey);
|
|
10
|
+
const transformKey = firstString(merged.transformKey, semanticTransformKey({ ...merged, semanticKey }));
|
|
11
|
+
const sourceLanguage = firstString(merged.sourceLanguage, merged.language);
|
|
12
|
+
const targetLanguage = firstString(merged.targetLanguage, merged.projectedLanguage);
|
|
13
|
+
const sourcePath = firstString(merged.sourcePath, merged.originalSourcePath);
|
|
14
|
+
const targetPath = firstString(merged.targetPath, merged.targetSourcePath, merged.projectedSourcePath);
|
|
15
|
+
const semanticIdentityHash = firstString(merged.semanticIdentityHash, editIdentity.semanticIdentityHash);
|
|
16
|
+
const sourceIdentityHash = firstString(merged.sourceIdentityHash, editIdentity.sourceIdentityHash);
|
|
17
|
+
const transformIdentityHash = firstString(merged.transformIdentityHash, hashSemanticValue(compactRecord({
|
|
18
|
+
transformKey,
|
|
19
|
+
semanticIdentityHash,
|
|
20
|
+
sourceLanguage,
|
|
21
|
+
targetLanguage
|
|
22
|
+
})));
|
|
23
|
+
const projectionIdentityHash = firstString(merged.projectionIdentityHash, hashSemanticValue(compactRecord({
|
|
24
|
+
transformIdentityHash,
|
|
25
|
+
sourceIdentityHash,
|
|
26
|
+
sourcePath,
|
|
27
|
+
targetPath
|
|
28
|
+
})));
|
|
29
|
+
const operationContentHash = firstString(merged.operationContentHash);
|
|
30
|
+
const editContentHash = firstString(merged.editContentHash);
|
|
31
|
+
const transformContentHash = firstString(
|
|
32
|
+
merged.transformContentHash,
|
|
33
|
+
operationContentHash || editContentHash ? hashSemanticValue(compactRecord({ transformIdentityHash, operationContentHash, editContentHash })) : undefined
|
|
34
|
+
);
|
|
35
|
+
const id = merged.id && source.kind === 'frontier.lang.semanticTransformIdentityRecord'
|
|
36
|
+
? merged.id
|
|
37
|
+
: firstString(merged.id, `semantic_transform_${idFragment(firstString(transformKey, semanticKey, sourcePath, targetPath, 'record'))}`);
|
|
38
|
+
return compactRecord({
|
|
39
|
+
kind: 'frontier.lang.semanticTransformIdentityRecord',
|
|
40
|
+
version: 1,
|
|
41
|
+
schema: 'frontier.lang.semanticTransformIdentityRecord.v1',
|
|
42
|
+
id,
|
|
43
|
+
sourceLanguage,
|
|
44
|
+
targetLanguage,
|
|
45
|
+
sourcePath,
|
|
46
|
+
targetPath,
|
|
47
|
+
baseHash: firstString(merged.baseHash),
|
|
48
|
+
targetHash: firstString(merged.targetHash, merged.projectedHash),
|
|
49
|
+
semanticKey,
|
|
50
|
+
transformKey,
|
|
51
|
+
semanticIdentityHash,
|
|
52
|
+
sourceIdentityHash,
|
|
53
|
+
operationContentHash,
|
|
54
|
+
editContentHash,
|
|
55
|
+
transformIdentityHash,
|
|
56
|
+
projectionIdentityHash,
|
|
57
|
+
transformContentHash,
|
|
58
|
+
readiness: firstString(merged.readiness),
|
|
59
|
+
confidence: typeof merged.confidence === 'number' ? merged.confidence : undefined,
|
|
60
|
+
evidenceIds: uniqueStrings(merged.evidenceIds),
|
|
61
|
+
metadata: compactRecord({
|
|
62
|
+
autoMergeClaim: false,
|
|
63
|
+
semanticEquivalenceClaim: false,
|
|
64
|
+
sourceTransformId: source.kind === 'frontier.lang.semanticTransformIdentityRecord' ? source.id : undefined,
|
|
65
|
+
...merged.metadata
|
|
66
|
+
})
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function semanticTransformIdentityFields(record = {}) {
|
|
71
|
+
return createSemanticTransformIdentityRecord(record);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function normalizeSemanticTransformIdentityRecords(records, context = {}) {
|
|
75
|
+
return array(records).filter(Boolean).map((record) => createSemanticTransformIdentityRecord(record, context));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function semanticTransformInputs(source = {}, options = {}) {
|
|
79
|
+
return [
|
|
80
|
+
...array(options.semanticTransformIdentities ?? options.semanticTransformIdentity),
|
|
81
|
+
...array(source.semanticTransformIdentities ?? source.semanticTransformIdentity ?? source.semanticTransforms),
|
|
82
|
+
...array(source.index?.semanticTransformIdentities)
|
|
83
|
+
];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function semanticTransformRecordIndex(records, source = {}) {
|
|
87
|
+
const index = source.index ?? {};
|
|
88
|
+
return {
|
|
89
|
+
semanticTransformIds: uniqueStrings([...strings(source.semanticTransformIds), ...strings(index.semanticTransformIds), ...records.map((record) => record.id)]),
|
|
90
|
+
semanticTransformKeys: uniqueStrings([...strings(source.semanticTransformKeys), ...strings(index.semanticTransformKeys), ...records.map((record) => record.transformKey)]),
|
|
91
|
+
semanticTransformIdentityHashes: uniqueStrings([...strings(source.semanticTransformIdentityHashes), ...strings(index.semanticTransformIdentityHashes), ...records.map((record) => record.transformIdentityHash)]),
|
|
92
|
+
semanticTransformContentHashes: uniqueStrings([...strings(source.semanticTransformContentHashes), ...strings(index.semanticTransformContentHashes), ...records.map((record) => record.transformContentHash)]),
|
|
93
|
+
projectionIdentityHashes: uniqueStrings([...strings(source.projectionIdentityHashes), ...strings(index.projectionIdentityHashes), ...records.map((record) => record.projectionIdentityHash)]),
|
|
94
|
+
transformSourceLanguages: uniqueStrings([...strings(source.transformSourceLanguages), ...strings(index.transformSourceLanguages), ...records.map((record) => record.sourceLanguage)]),
|
|
95
|
+
transformTargetLanguages: uniqueStrings([...strings(source.transformTargetLanguages), ...strings(index.transformTargetLanguages), ...records.map((record) => record.targetLanguage)]),
|
|
96
|
+
transformSourcePaths: uniqueStrings([...strings(source.transformSourcePaths), ...strings(index.transformSourcePaths), ...records.map((record) => record.sourcePath)]),
|
|
97
|
+
transformTargetPaths: uniqueStrings([...strings(source.transformTargetPaths), ...strings(index.transformTargetPaths), ...records.map((record) => record.targetPath)])
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function semanticTransformSummary(index) {
|
|
102
|
+
if (!index.semanticTransformIds.length && !index.semanticTransformKeys.length) return undefined;
|
|
103
|
+
return compactRecord({
|
|
104
|
+
ids: index.semanticTransformIds,
|
|
105
|
+
keys: index.semanticTransformKeys,
|
|
106
|
+
identityHashes: index.semanticTransformIdentityHashes,
|
|
107
|
+
contentHashes: index.semanticTransformContentHashes,
|
|
108
|
+
projectionIdentityHashes: index.projectionIdentityHashes,
|
|
109
|
+
sourceLanguages: index.transformSourceLanguages,
|
|
110
|
+
targetLanguages: index.transformTargetLanguages,
|
|
111
|
+
targetPaths: index.transformTargetPaths
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function semanticTransformKey(record) {
|
|
116
|
+
const scope = record.semanticKey ?? (record.symbolName
|
|
117
|
+
? `${record.symbolKind ?? 'symbol'}:${record.symbolName}`
|
|
118
|
+
: record.anchorKey ?? record.regionId ?? record.operationId ?? record.id);
|
|
119
|
+
const route = [record.sourceLanguage ?? record.language, record.targetLanguage ?? record.projectedLanguage].filter(Boolean).join('->');
|
|
120
|
+
return ['semantic-transform', route, scope].filter(Boolean).join(':');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function array(value) { if (value === undefined || value === null) return []; return Array.isArray(value) ? value : [value]; }
|
|
124
|
+
function strings(value) { return array(value).map((entry) => String(entry ?? '')).filter(Boolean); }
|
|
125
|
+
function firstString(...values) { return values.map((value) => value === undefined || value === null ? '' : String(value)).find(Boolean); }
|
|
126
|
+
function uniqueStrings(values) { return uniqueRawStrings((values ?? []).filter((entry) => entry !== undefined && entry !== null && String(entry) !== '')); }
|
|
127
|
+
function compactRecord(value) { return Object.fromEntries(Object.entries(value ?? {}).filter(([, entry]) => entry !== undefined && (!Array.isArray(entry) || entry.length > 0))); }
|
package/package.json
CHANGED