@shapeshift-labs/frontier-lang-compiler 0.2.64 → 0.2.66
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 +31 -6
- package/dist/declarations/import-adapter-core.d.ts +3 -0
- package/dist/declarations/native-project-admission.d.ts +18 -0
- package/dist/declarations/semantic-merge-candidates.d.ts +200 -0
- package/dist/declarations/semantic-merge-conflicts.d.ts +12 -0
- package/dist/declarations/semantic-sidecar.d.ts +8 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/internal/index-impl/attachExternalOwnership.js +18 -10
- package/dist/internal/index-impl/createSemanticImportSidecar.js +6 -0
- package/dist/internal/index-impl/createSemanticSlice.js +3 -2
- package/dist/internal/index-impl/diffNativeSourceImports.js +3 -2
- package/dist/internal/index-impl/externalSemanticBase.js +1 -0
- package/dist/internal/index-impl/importExternalSemanticIndex.js +4 -0
- package/dist/internal/index-impl/projectImportAdmissionSummaries.js +31 -6
- package/dist/internal/index-impl/runNativeImporterAdapter.js +1 -1
- package/dist/internal/index-impl/semanticMergeCandidateRecordInternals.js +314 -0
- package/dist/internal/index-impl/semanticMergeCandidateRecords.js +241 -0
- package/dist/internal/index-impl/withExternalEmptyLoss.js +1 -0
- package/dist/language-adapter-package-contracts.js +6 -6
- package/dist/lightweight-dependency-language.js +8 -0
- package/dist/native-region-scanner-core.js +42 -10
- package/dist/native-region-scanner-js-helpers.js +2 -0
- package/dist/native-region-scanner-js-imports.js +111 -0
- package/dist/native-region-scanner-js.js +111 -28
- package/examples/js-frontier-rust-workbench-adapters.mjs +89 -0
- package/examples/js-frontier-rust-workbench-bounds.mjs +4 -3
- package/examples/js-frontier-rust-workbench-client.mjs +78 -59
- package/examples/js-frontier-rust-workbench-html.mjs +20 -13
- package/examples/js-frontier-rust-workbench-styles.mjs +9 -16
- package/examples/js-frontier-rust-workbench.mjs +67 -121
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,17 +36,19 @@ npm run build
|
|
|
36
36
|
node examples/native-js-to-rust-demo.mjs
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
Run the interactive Frontier-style workbench with
|
|
39
|
+
Run the interactive Frontier-style workbench with a submitted TypeScript source pane,
|
|
40
|
+
Frontier graph/JSON pane, and independent Rust/Python projection panes:
|
|
40
41
|
|
|
41
42
|
```sh
|
|
42
43
|
npm run demo:ts-rust -- --port 4177
|
|
43
44
|
```
|
|
44
45
|
|
|
45
46
|
The workbench converts only when `Run` is pressed. TypeScript edits project through
|
|
46
|
-
the Frontier semantic graph into Rust scaffolding
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
the Frontier semantic graph into Rust and Python scaffolding. The middle pane shows
|
|
48
|
+
symbols, relations, source maps, readiness, losses, patch hints, and the explicit
|
|
49
|
+
supported/review-only/unsupported bounds for the projection. Run
|
|
50
|
+
`npm run demo:ts-rust:smoke` to verify the conversion output and layout scaffold
|
|
51
|
+
without starting the server.
|
|
50
52
|
|
|
51
53
|
The demo prints JavaScript source, the Frontier universal AST/semantic-index summary,
|
|
52
54
|
Rust declaration stubs, a host-adapter Rust projection, and a direct Frontier-source
|
|
@@ -117,11 +119,12 @@ const importedIndex = importExternalSemanticIndex({
|
|
|
117
119
|
});
|
|
118
120
|
|
|
119
121
|
console.log(importedIndex.semanticIndex.symbols.length);
|
|
122
|
+
console.log(importedIndex.ownershipRegions[0]?.key);
|
|
120
123
|
console.log(importedIndex.summary.sourceMapMappings);
|
|
121
124
|
console.log(importedIndex.readiness.readiness); // "ready-with-losses" or review-required
|
|
122
125
|
```
|
|
123
126
|
|
|
124
|
-
External semantic-index imports create Frontier `SemanticIndexRecord`, `SourceMapRecord`, evidence, losses, ownership facts, and a universal AST envelope. They are a bridge from existing language servers/indexers into semantic merge tooling; they do not claim full parser AST coverage, macro expansion, type checking, comments/trivia preservation, or lossless cross-language code generation by themselves.
|
|
127
|
+
External semantic-index imports create Frontier `SemanticIndexRecord`, `SourceMapRecord`, evidence, losses, ownership facts, first-class `ownershipRegions`, and a universal AST envelope. They are a bridge from existing language servers/indexers into semantic merge tooling; they do not claim full parser AST coverage, macro expansion, type checking, comments/trivia preservation, or lossless cross-language code generation by themselves.
|
|
125
128
|
|
|
126
129
|
Native imports include source maps, semantic merge candidates, and a loss summary for admission queues and dashboards. Informational losses produce `ready-with-losses`, warning losses produce `needs-review`, and error losses or failed import evidence produce `blocked`:
|
|
127
130
|
|
|
@@ -137,6 +140,28 @@ console.log(readiness.readiness);
|
|
|
137
140
|
|
|
138
141
|
The loss taxonomy separates broad scanner limits from specific round-trip risks such as conditional compilation, reflection, overload/type-inference gaps, comments/trivia preservation, source-map approximation, parser diagnostics, and target projection loss. These records are evidence labels for merge admission; they are not claims that the lightweight scanner expanded macros, evaluated inactive branches, resolved overloads, or ran a type checker.
|
|
139
142
|
|
|
143
|
+
Semantic merge candidates also expose compiler-normalized admission records for coordinator queues:
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
import {
|
|
147
|
+
createSemanticMergeCandidateAdmissionRecord,
|
|
148
|
+
querySemanticMergeCandidateAdmissionOverlaps,
|
|
149
|
+
sortSemanticMergeCandidateAdmissionRecords
|
|
150
|
+
} from '@shapeshift-labs/frontier-lang-compiler';
|
|
151
|
+
|
|
152
|
+
const record = createSemanticMergeCandidateAdmissionRecord(changeSet);
|
|
153
|
+
|
|
154
|
+
console.log(record.changedSemanticRegions);
|
|
155
|
+
console.log(record.sourceHashes.baseHash, record.sourceHashes.targetHash);
|
|
156
|
+
console.log(record.conflictKeys, record.evidenceIds);
|
|
157
|
+
console.log(record.projectionRisk, record.readiness, record.readinessSortKey);
|
|
158
|
+
|
|
159
|
+
const queue = sortSemanticMergeCandidateAdmissionRecords([record, otherRecord]);
|
|
160
|
+
const overlaps = querySemanticMergeCandidateAdmissionOverlaps(queue);
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
These candidate records are compact merge-admission evidence. They preserve changed semantic regions, source/base/target hashes, conflict keys, evidence IDs, projection risk, readiness, and overlap pairs so swarm coordinators can sort likely-ready candidates first and detect conflicting regions before patch review.
|
|
164
|
+
|
|
140
165
|
High-risk native features also have explicit evidence policies. These policies are advisory in this package: they tell a swarm or admission queue what evidence is missing without silently changing the existing readiness classification.
|
|
141
166
|
|
|
142
167
|
```js
|
|
@@ -154,6 +154,8 @@ export interface ExternalSemanticIndexImportSummary {
|
|
|
154
154
|
readonly occurrences: number;
|
|
155
155
|
readonly relations: number;
|
|
156
156
|
readonly facts: number;
|
|
157
|
+
readonly ownershipRegions: number;
|
|
158
|
+
readonly ownershipRegionKinds: readonly string[];
|
|
157
159
|
readonly sourceMapMappings: number;
|
|
158
160
|
readonly losses: number;
|
|
159
161
|
readonly readiness: SemanticMergeReadiness;
|
|
@@ -170,6 +172,7 @@ export interface ExternalSemanticIndexImportResult {
|
|
|
170
172
|
readonly semanticIndex: SemanticIndexRecord;
|
|
171
173
|
readonly universalAst: FrontierUniversalAstEnvelope;
|
|
172
174
|
readonly sourceMaps: readonly SourceMapRecord[];
|
|
175
|
+
readonly ownershipRegions: readonly SemanticImportOwnershipRegion[];
|
|
173
176
|
readonly losses: readonly NativeAstLossRecord[];
|
|
174
177
|
readonly evidence: readonly EvidenceRecord[];
|
|
175
178
|
readonly readiness: NativeImportReadinessClassification;
|
|
@@ -2,6 +2,7 @@ import type { FrontierSourceLanguage, SemanticMergeReadiness } from '@shapeshift
|
|
|
2
2
|
import type { NativeImportLossSummary } from './native-import-losses.js';
|
|
3
3
|
import type { NativeImportResultContract } from './native-import-contracts.js';
|
|
4
4
|
import type { NativeProjectImportResult } from './native-project.js';
|
|
5
|
+
import type { SemanticMergeCandidateAdmissionRecord, SemanticMergeCandidateOverlapRecord, SemanticMergeCandidateProjectionRisk } from './semantic-merge-candidates.js';
|
|
5
6
|
|
|
6
7
|
export type NativeProjectImportAdmissionAction = 'admit' | 'prioritize' | 'reject';
|
|
7
8
|
export type NativeProjectImportAdmissionPriority = 'low' | 'normal' | 'high' | 'critical' | 'blocker';
|
|
@@ -78,10 +79,27 @@ export interface NativeProjectAdmissionMergeCandidates {
|
|
|
78
79
|
readonly highestRisk: NativeProjectImportAdmissionRisk;
|
|
79
80
|
readonly byRisk: Readonly<Record<string, number>>;
|
|
80
81
|
readonly byReadiness: Readonly<Record<string, number>>;
|
|
82
|
+
readonly byProjectionRisk: Readonly<Record<string, number>>;
|
|
81
83
|
readonly highRiskCandidateIds: readonly string[];
|
|
82
84
|
readonly reviewCandidateIds: readonly string[];
|
|
83
85
|
readonly blockedCandidateIds: readonly string[];
|
|
86
|
+
readonly highProjectionRiskCandidateIds: readonly string[];
|
|
84
87
|
readonly conflictKeys: readonly string[];
|
|
88
|
+
readonly readinessOrderCandidateIds: readonly string[];
|
|
89
|
+
readonly changedSemanticRegions: {
|
|
90
|
+
readonly total: number;
|
|
91
|
+
readonly byKind: Readonly<Record<string, number>>;
|
|
92
|
+
readonly conflictKeys: readonly string[];
|
|
93
|
+
};
|
|
94
|
+
readonly overlaps: {
|
|
95
|
+
readonly total: number;
|
|
96
|
+
readonly candidateIds: readonly string[];
|
|
97
|
+
readonly conflictKeys: readonly string[];
|
|
98
|
+
readonly sourcePaths: readonly string[];
|
|
99
|
+
readonly pairs: readonly SemanticMergeCandidateOverlapRecord[];
|
|
100
|
+
};
|
|
101
|
+
readonly records: readonly SemanticMergeCandidateAdmissionRecord[];
|
|
102
|
+
readonly projectionRisk?: SemanticMergeCandidateProjectionRisk;
|
|
85
103
|
readonly patchRisk?: NativeProjectImportAdmissionRisk;
|
|
86
104
|
}
|
|
87
105
|
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
EvidenceRecord,
|
|
3
|
+
FrontierSourceLanguage,
|
|
4
|
+
SemanticMergeCandidateRecord,
|
|
5
|
+
SemanticMergeReadiness,
|
|
6
|
+
SourceSpan
|
|
7
|
+
} from '@shapeshift-labs/frontier-lang-kernel';
|
|
8
|
+
import type { NativeSourceChangeKind, NativeSourceChangeSet } from './native-diff.js';
|
|
9
|
+
import type { SemanticMergeConflictSummary } from './semantic-merge-conflicts.js';
|
|
10
|
+
|
|
11
|
+
export type SemanticMergeCandidateProjectionRisk = 'low' | 'medium' | 'high' | 'unknown';
|
|
12
|
+
|
|
13
|
+
export interface SemanticMergeCandidateChangedRegion {
|
|
14
|
+
readonly id?: string;
|
|
15
|
+
readonly key?: string;
|
|
16
|
+
readonly conflictKey?: string;
|
|
17
|
+
readonly changeKind?: NativeSourceChangeKind | string;
|
|
18
|
+
readonly regionKind?: string;
|
|
19
|
+
readonly granularity?: string;
|
|
20
|
+
readonly precision?: string;
|
|
21
|
+
readonly projectionRisk?: SemanticMergeCandidateProjectionRisk;
|
|
22
|
+
readonly language?: FrontierSourceLanguage | string;
|
|
23
|
+
readonly sourcePath?: string;
|
|
24
|
+
readonly sourceHash?: string;
|
|
25
|
+
readonly baseHash?: string;
|
|
26
|
+
readonly targetHash?: string;
|
|
27
|
+
readonly symbolId?: string;
|
|
28
|
+
readonly symbolName?: string;
|
|
29
|
+
readonly symbolKind?: string;
|
|
30
|
+
readonly semanticNodeId?: string;
|
|
31
|
+
readonly nativeAstNodeId?: string;
|
|
32
|
+
readonly sourceSpan?: SourceSpan;
|
|
33
|
+
readonly sourceMapLinkIds?: readonly string[];
|
|
34
|
+
readonly sourceMapIds?: readonly string[];
|
|
35
|
+
readonly sourceMapMappingIds?: readonly string[];
|
|
36
|
+
readonly admission?: {
|
|
37
|
+
readonly readiness?: SemanticMergeReadiness | string;
|
|
38
|
+
readonly action?: string;
|
|
39
|
+
readonly reasonCodes?: readonly string[];
|
|
40
|
+
readonly conflictKeys?: readonly string[];
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface SemanticMergeCandidateOverlapRecord {
|
|
45
|
+
readonly schema: 'frontier.lang.semanticMergeCandidateOverlap.v1';
|
|
46
|
+
readonly id: string;
|
|
47
|
+
readonly overlapKind: 'conflict-key' | 'region-key' | 'source-span' | string;
|
|
48
|
+
readonly risk: 'medium' | 'high' | string;
|
|
49
|
+
readonly readiness: SemanticMergeReadiness | string;
|
|
50
|
+
readonly recordIds: readonly string[];
|
|
51
|
+
readonly candidateIds: readonly string[];
|
|
52
|
+
readonly regionIds: readonly string[];
|
|
53
|
+
readonly regionKeys: readonly string[];
|
|
54
|
+
readonly conflictKeys: readonly string[];
|
|
55
|
+
readonly sourcePath?: string;
|
|
56
|
+
readonly leftRegion: Partial<SemanticMergeCandidateChangedRegion>;
|
|
57
|
+
readonly rightRegion: Partial<SemanticMergeCandidateChangedRegion>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface SemanticMergeCandidateAdmissionRecord {
|
|
61
|
+
readonly kind: 'frontier.lang.semanticMergeCandidateAdmissionRecord';
|
|
62
|
+
readonly version: 1;
|
|
63
|
+
readonly schema: 'frontier.lang.semanticMergeCandidateAdmissionRecord.v1';
|
|
64
|
+
readonly id: string;
|
|
65
|
+
readonly candidateId?: string;
|
|
66
|
+
readonly importResultId?: string;
|
|
67
|
+
readonly patchId?: string;
|
|
68
|
+
readonly language?: FrontierSourceLanguage | string;
|
|
69
|
+
readonly sourcePath?: string;
|
|
70
|
+
readonly readiness: SemanticMergeReadiness | string;
|
|
71
|
+
readonly readinessSortKey: number;
|
|
72
|
+
readonly projectionRisk: SemanticMergeCandidateProjectionRisk;
|
|
73
|
+
readonly sourceHashes: {
|
|
74
|
+
readonly baseHash?: string;
|
|
75
|
+
readonly targetHash?: string;
|
|
76
|
+
readonly values: readonly string[];
|
|
77
|
+
};
|
|
78
|
+
readonly baseHash?: string;
|
|
79
|
+
readonly targetHash?: string;
|
|
80
|
+
readonly changedSemanticRegions: readonly SemanticMergeCandidateChangedRegion[];
|
|
81
|
+
readonly conflictKeys: readonly string[];
|
|
82
|
+
readonly evidenceIds: readonly string[];
|
|
83
|
+
readonly proofIds: readonly string[];
|
|
84
|
+
readonly overlapSummary: {
|
|
85
|
+
readonly total: number;
|
|
86
|
+
readonly hasOverlaps: boolean;
|
|
87
|
+
readonly byKind: Readonly<Record<string, number>>;
|
|
88
|
+
readonly conflictKeys: readonly string[];
|
|
89
|
+
readonly pairs: readonly SemanticMergeCandidateOverlapRecord[];
|
|
90
|
+
};
|
|
91
|
+
readonly admission: {
|
|
92
|
+
readonly readiness: SemanticMergeReadiness | string;
|
|
93
|
+
readonly reviewRequired: boolean;
|
|
94
|
+
readonly action: 'admit' | 'prioritize-review' | 'block' | string;
|
|
95
|
+
readonly sortKey: number;
|
|
96
|
+
readonly reasonCodes: readonly string[];
|
|
97
|
+
readonly conflictKeys: readonly string[];
|
|
98
|
+
};
|
|
99
|
+
readonly index: {
|
|
100
|
+
readonly candidateIds: readonly string[];
|
|
101
|
+
readonly importResultIds: readonly string[];
|
|
102
|
+
readonly patchIds: readonly string[];
|
|
103
|
+
readonly sourcePaths: readonly string[];
|
|
104
|
+
readonly sourceHashes: readonly string[];
|
|
105
|
+
readonly baseHashes: readonly string[];
|
|
106
|
+
readonly targetHashes: readonly string[];
|
|
107
|
+
readonly regionIds: readonly string[];
|
|
108
|
+
readonly regionKeys: readonly string[];
|
|
109
|
+
readonly regionKinds: readonly string[];
|
|
110
|
+
readonly conflictKeys: readonly string[];
|
|
111
|
+
readonly evidenceIds: readonly string[];
|
|
112
|
+
readonly proofIds: readonly string[];
|
|
113
|
+
readonly readinesses: readonly string[];
|
|
114
|
+
readonly projectionRisks: readonly string[];
|
|
115
|
+
};
|
|
116
|
+
readonly summary: {
|
|
117
|
+
readonly changedSemanticRegions: number;
|
|
118
|
+
readonly conflictKeys: number;
|
|
119
|
+
readonly evidenceIds: number;
|
|
120
|
+
readonly proofIds: number;
|
|
121
|
+
readonly overlaps: number;
|
|
122
|
+
readonly readiness: SemanticMergeReadiness | string;
|
|
123
|
+
readonly projectionRisk: SemanticMergeCandidateProjectionRisk;
|
|
124
|
+
readonly reviewRequired: boolean;
|
|
125
|
+
};
|
|
126
|
+
readonly metadata?: Record<string, unknown> & {
|
|
127
|
+
readonly conflictSummary?: SemanticMergeConflictSummary;
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export type SemanticMergeCandidateAdmissionInput =
|
|
132
|
+
| NativeSourceChangeSet
|
|
133
|
+
| SemanticMergeCandidateRecord
|
|
134
|
+
| SemanticMergeCandidateAdmissionRecord
|
|
135
|
+
| Record<string, unknown>;
|
|
136
|
+
|
|
137
|
+
export interface CreateSemanticMergeCandidateAdmissionRecordOptions {
|
|
138
|
+
readonly id?: string;
|
|
139
|
+
readonly changeSet?: NativeSourceChangeSet;
|
|
140
|
+
readonly candidate?: SemanticMergeCandidateRecord | Record<string, unknown>;
|
|
141
|
+
readonly patch?: unknown;
|
|
142
|
+
readonly candidateId?: string;
|
|
143
|
+
readonly importResultId?: string;
|
|
144
|
+
readonly patchId?: string;
|
|
145
|
+
readonly language?: FrontierSourceLanguage | string;
|
|
146
|
+
readonly sourcePath?: string;
|
|
147
|
+
readonly sourceHash?: string;
|
|
148
|
+
readonly sourceHashes?: readonly string[] | string;
|
|
149
|
+
readonly baseHash?: string;
|
|
150
|
+
readonly targetHash?: string;
|
|
151
|
+
readonly readiness?: SemanticMergeReadiness | string;
|
|
152
|
+
readonly projectionRisk?: SemanticMergeCandidateProjectionRisk | string;
|
|
153
|
+
readonly changedRegions?: readonly unknown[] | unknown;
|
|
154
|
+
readonly conflictKeys?: readonly string[] | string;
|
|
155
|
+
readonly evidence?: readonly EvidenceRecord[] | EvidenceRecord;
|
|
156
|
+
readonly evidenceIds?: readonly string[] | string;
|
|
157
|
+
readonly proofIds?: readonly string[] | string;
|
|
158
|
+
readonly reasonCodes?: readonly string[] | string;
|
|
159
|
+
readonly metadata?: Record<string, unknown>;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export type SemanticMergeCandidateWithAdmission = SemanticMergeCandidateRecord & {
|
|
163
|
+
readonly changedSemanticRegions?: readonly SemanticMergeCandidateChangedRegion[];
|
|
164
|
+
readonly sourceHashes?: SemanticMergeCandidateAdmissionRecord['sourceHashes'];
|
|
165
|
+
readonly evidenceIds?: readonly string[];
|
|
166
|
+
readonly proofIds?: readonly string[];
|
|
167
|
+
readonly projectionRisk?: SemanticMergeCandidateProjectionRisk;
|
|
168
|
+
readonly readinessSortKey?: number;
|
|
169
|
+
readonly mergeAdmission?: SemanticMergeCandidateAdmissionRecord;
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
export interface SemanticMergeCandidateAdmissionOverlapQuery {
|
|
173
|
+
readonly id?: string | readonly string[];
|
|
174
|
+
readonly ids?: readonly string[];
|
|
175
|
+
readonly candidateId?: string | readonly string[];
|
|
176
|
+
readonly candidateIds?: readonly string[];
|
|
177
|
+
readonly recordId?: string | readonly string[];
|
|
178
|
+
readonly recordIds?: readonly string[];
|
|
179
|
+
readonly regionId?: string | readonly string[];
|
|
180
|
+
readonly regionIds?: readonly string[];
|
|
181
|
+
readonly regionKey?: string | readonly string[];
|
|
182
|
+
readonly regionKeys?: readonly string[];
|
|
183
|
+
readonly conflictKey?: string | readonly string[];
|
|
184
|
+
readonly conflictKeys?: readonly string[];
|
|
185
|
+
readonly sourcePath?: string | readonly string[];
|
|
186
|
+
readonly sourcePaths?: readonly string[];
|
|
187
|
+
readonly overlapKind?: string | readonly string[];
|
|
188
|
+
readonly overlapKinds?: readonly string[];
|
|
189
|
+
readonly readiness?: SemanticMergeReadiness | string | readonly string[];
|
|
190
|
+
readonly readinesses?: readonly string[];
|
|
191
|
+
readonly risk?: string | readonly string[];
|
|
192
|
+
readonly risks?: readonly string[];
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export declare const SemanticMergeCandidateProjectionRisks: readonly SemanticMergeCandidateProjectionRisk[];
|
|
196
|
+
export declare function createSemanticMergeCandidateAdmissionRecord(input?: SemanticMergeCandidateAdmissionInput, options?: CreateSemanticMergeCandidateAdmissionRecordOptions): SemanticMergeCandidateAdmissionRecord;
|
|
197
|
+
export declare function decorateSemanticMergeCandidateForAdmission<T extends SemanticMergeCandidateRecord | Record<string, unknown>>(input?: T, options?: CreateSemanticMergeCandidateAdmissionRecordOptions): T & SemanticMergeCandidateWithAdmission;
|
|
198
|
+
export declare function querySemanticMergeCandidateAdmissionOverlaps(records: SemanticMergeCandidateAdmissionInput | readonly SemanticMergeCandidateAdmissionInput[], query?: SemanticMergeCandidateAdmissionOverlapQuery): readonly SemanticMergeCandidateOverlapRecord[];
|
|
199
|
+
export declare function semanticMergeCandidateReadinessSortKey(candidateOrRecord: Partial<SemanticMergeCandidateAdmissionRecord> | Partial<SemanticMergeCandidateWithAdmission>): number;
|
|
200
|
+
export declare function sortSemanticMergeCandidateAdmissionRecords<T extends SemanticMergeCandidateAdmissionInput>(records: readonly T[], options?: { readonly desc?: boolean }): readonly SemanticMergeCandidateAdmissionRecord[];
|
|
@@ -3,6 +3,11 @@ import type {
|
|
|
3
3
|
SemanticMergeCandidateRecord,
|
|
4
4
|
SemanticMergeReadiness
|
|
5
5
|
} from '@shapeshift-labs/frontier-lang-kernel';
|
|
6
|
+
import type {
|
|
7
|
+
SemanticMergeCandidateAdmissionRecord,
|
|
8
|
+
SemanticMergeCandidateChangedRegion,
|
|
9
|
+
SemanticMergeCandidateProjectionRisk
|
|
10
|
+
} from './semantic-merge-candidates.js';
|
|
6
11
|
|
|
7
12
|
export type SemanticMergeConflictClass =
|
|
8
13
|
| 'same-symbol-edit'
|
|
@@ -45,6 +50,13 @@ export interface SemanticMergeConflictSummary {
|
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
export type SemanticMergeCandidateWithConflicts = SemanticMergeCandidateRecord & {
|
|
53
|
+
readonly changedSemanticRegions?: readonly SemanticMergeCandidateChangedRegion[];
|
|
54
|
+
readonly sourceHashes?: SemanticMergeCandidateAdmissionRecord['sourceHashes'];
|
|
55
|
+
readonly evidenceIds?: readonly string[];
|
|
56
|
+
readonly proofIds?: readonly string[];
|
|
57
|
+
readonly projectionRisk?: SemanticMergeCandidateProjectionRisk;
|
|
58
|
+
readonly readinessSortKey?: number;
|
|
59
|
+
readonly mergeAdmission?: SemanticMergeCandidateAdmissionRecord;
|
|
48
60
|
readonly conflictClasses?: readonly SemanticMergeConflictClassRecord[];
|
|
49
61
|
readonly conflictSummary?: SemanticMergeConflictSummary;
|
|
50
62
|
readonly metadata?: SemanticMergeCandidateRecord['metadata'] & {
|
|
@@ -25,6 +25,7 @@ import type {
|
|
|
25
25
|
UniversalAstLayerRecord
|
|
26
26
|
} from '@shapeshift-labs/frontier-lang-kernel';
|
|
27
27
|
import type { SemanticImportSidecarAdmission, SemanticImportSidecarQuality } from './semantic-sidecar-admission.js';
|
|
28
|
+
import type { SemanticMergeCandidateAdmissionRecord, SemanticMergeCandidateProjectionRisk } from './semantic-merge-candidates.js';
|
|
28
29
|
import type { SemanticMergeConflictClass, SemanticMergeConflictSummary } from './semantic-merge-conflicts.js';
|
|
29
30
|
import type { SemanticImportImpactSummary } from './semantic-impact.js';
|
|
30
31
|
import type { Diagnostic } from '@shapeshift-labs/frontier-lang-checker';
|
|
@@ -274,6 +275,12 @@ export interface SemanticImportSidecar {
|
|
|
274
275
|
readonly reasons: readonly string[];
|
|
275
276
|
readonly conflictClasses?: readonly SemanticMergeConflictClass[];
|
|
276
277
|
readonly conflictSummary?: SemanticMergeConflictSummary;
|
|
278
|
+
readonly changedSemanticRegions?: number;
|
|
279
|
+
readonly sourceHashes?: SemanticMergeCandidateAdmissionRecord['sourceHashes'];
|
|
280
|
+
readonly evidenceIds?: readonly string[];
|
|
281
|
+
readonly projectionRisk?: SemanticMergeCandidateProjectionRisk;
|
|
282
|
+
readonly readinessSortKey?: number;
|
|
283
|
+
readonly overlapSummary?: SemanticMergeCandidateAdmissionRecord['overlapSummary'];
|
|
277
284
|
readonly risk?: string;
|
|
278
285
|
readonly operationCount: number;
|
|
279
286
|
}[];
|
|
@@ -309,7 +316,5 @@ export interface SemanticImportSidecar {
|
|
|
309
316
|
readonly semanticImportExpected: boolean; readonly semanticImportExpectedSatisfied: boolean; readonly semanticImportExpectedMissingReasonCodes: readonly string[];
|
|
310
317
|
readonly readiness: SemanticMergeReadiness; readonly emptySemanticIndex: boolean;
|
|
311
318
|
};
|
|
312
|
-
readonly metadata?: Record<string, unknown>;
|
|
313
|
-
}
|
|
314
|
-
|
|
319
|
+
readonly metadata?: Record<string, unknown>; }
|
|
315
320
|
export interface SemanticImportSidecarOptions { readonly id?: string; readonly generatedAt?: number; readonly regionPrefix?: string; readonly targetPath?: string; readonly expected?: boolean; readonly semanticImportExpected?: boolean; readonly metadata?: Record<string, unknown>; }
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export * from './declarations/language-adapter-package-contracts.js';
|
|
|
13
13
|
export * from './declarations/native-import-contracts.js';
|
|
14
14
|
export * from './declarations/source-preservation.js';
|
|
15
15
|
export * from './declarations/semantic-sidecar-admission.js';
|
|
16
|
+
export * from './declarations/semantic-merge-candidates.js';
|
|
16
17
|
export * from './declarations/semantic-merge-conflicts.js';
|
|
17
18
|
export * from './declarations/semantic-history.js';
|
|
18
19
|
export * from './declarations/semantic-patch-bundle.js';
|
package/dist/index.js
CHANGED
|
@@ -64,6 +64,7 @@ export { projectNativeImportToSource } from './internal/index-impl/projectNative
|
|
|
64
64
|
export { queryNativeParserFeatureMatrix } from './internal/index-impl/queryNativeParserFeatureMatrix.js';
|
|
65
65
|
export { queryProjectionReadinessMatrix } from './internal/index-impl/queryProjectionReadinessMatrix.js';
|
|
66
66
|
export { createSemanticPatchBundleRecord, querySemanticPatchBundleRecords, SemanticPatchBundleAdmissionStatuses } from './internal/index-impl/semanticPatchBundleRecords.js';
|
|
67
|
+
export { createSemanticMergeCandidateAdmissionRecord, decorateSemanticMergeCandidateForAdmission, querySemanticMergeCandidateAdmissionOverlaps, SemanticMergeCandidateProjectionRisks, semanticMergeCandidateReadinessSortKey, sortSemanticMergeCandidateAdmissionRecords } from './internal/index-impl/semanticMergeCandidateRecords.js';
|
|
67
68
|
export { querySemanticMergeConflictClasses, SemanticMergeConflictClasses, semanticMergeConflictRiskScore, sortSemanticMergeCandidatesByConflictRisk, summarizeSemanticMergeConflicts } from './internal/index-impl/semanticMergeConflicts.js';
|
|
68
69
|
export { queryUniversalConversionPlan } from './internal/index-impl/queryUniversalConversionPlan.js';
|
|
69
70
|
export { createSemanticHistoryRecord, querySemanticHistoryRecordOverlaps, SemanticHistoryAdmissionStatuses, SemanticHistoryConflictReasons, SemanticHistoryOverlapKinds, SemanticHistoryReviewerStatuses, semanticHistoryRecordsConflict, semanticHistoryRecordsOverlap } from './internal/index-impl/semanticHistoryRecords.js';
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import{idFragment}from'../../native-import-utils.js';import{semanticRegionKindForSymbol,semanticRegionMergePolicy}from'../../semantic-import-regions.js';
|
|
1
|
+
import{idFragment,uniqueRecordsById}from'../../native-import-utils.js';import{semanticRegionKindForSymbol,semanticRegionMergePolicy}from'../../semantic-import-regions.js';
|
|
2
2
|
import{externalRelationPredicateForOccurrence}from'./externalRelationPredicateForOccurrence.js';
|
|
3
3
|
export function attachExternalOwnership(result, context) {
|
|
4
4
|
const occurrencesBySymbol = new Map();
|
|
5
|
+
const documentsById = new Map((result.documents ?? []).map((document) => [document.id, document]));
|
|
6
|
+
const ownershipRegions = [];
|
|
5
7
|
for (const occurrence of result.occurrences) {
|
|
6
8
|
if (!occurrencesBySymbol.has(occurrence.symbolId)) occurrencesBySymbol.set(occurrence.symbolId, []);
|
|
7
9
|
occurrencesBySymbol.get(occurrence.symbolId).push(occurrence);
|
|
@@ -21,24 +23,28 @@ export function attachExternalOwnership(result, context) {
|
|
|
21
23
|
result.symbols = result.symbols.map((symbol) => {
|
|
22
24
|
const occurrences = occurrencesBySymbol.get(symbol.id) ?? [];
|
|
23
25
|
const definition = occurrences.find((occurrence) => occurrence.role === 'definition') ?? occurrences[0];
|
|
26
|
+
const document = documentsById.get(definition?.documentId);
|
|
24
27
|
const sourceSpan = symbol.definitionSpan ?? definition?.span;
|
|
25
28
|
const regionKind = semanticRegionKindForSymbol(symbol, undefined, undefined);
|
|
29
|
+
const sourcePath = sourceSpan?.path ?? document?.path ?? context.sourcePath;
|
|
30
|
+
const language = symbol.language ?? document?.language ?? context.language;
|
|
31
|
+
const normalizedRegionKind = symbol.metadata?.ownershipRegionKind ?? regionKind;
|
|
26
32
|
const key = [
|
|
27
33
|
'external',
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
34
|
+
language ?? 'unknown',
|
|
35
|
+
sourcePath ?? 'memory',
|
|
36
|
+
normalizedRegionKind,
|
|
31
37
|
symbol.name ?? symbol.id
|
|
32
38
|
].join('#');
|
|
33
39
|
const region = {
|
|
34
|
-
id: `region_${idFragment(key)}`,
|
|
35
|
-
key,
|
|
36
|
-
regionKind,
|
|
40
|
+
id: symbol.metadata?.ownershipRegionId ?? `region_${idFragment(key)}`,
|
|
41
|
+
key: symbol.metadata?.ownershipRegionKey ?? key,
|
|
42
|
+
regionKind: normalizedRegionKind,
|
|
37
43
|
granularity: 'symbol',
|
|
38
|
-
language
|
|
44
|
+
language,
|
|
39
45
|
documentId: definition?.documentId,
|
|
40
|
-
sourcePath
|
|
41
|
-
sourceHash: context.sourceHash,
|
|
46
|
+
sourcePath,
|
|
47
|
+
sourceHash: sourceSpan?.sourceId ?? document?.sourceHash ?? context.sourceHash,
|
|
42
48
|
symbolId: symbol.id,
|
|
43
49
|
symbolName: symbol.name,
|
|
44
50
|
symbolKind: symbol.kind,
|
|
@@ -50,6 +56,7 @@ export function attachExternalOwnership(result, context) {
|
|
|
50
56
|
source: 'external-semantic-index'
|
|
51
57
|
}
|
|
52
58
|
};
|
|
59
|
+
ownershipRegions.push(region);
|
|
53
60
|
result.facts.push({
|
|
54
61
|
id: `fact_${idFragment(symbol.id)}_ownership_region`,
|
|
55
62
|
predicate: 'semanticOwnershipRegion',
|
|
@@ -76,4 +83,5 @@ export function attachExternalOwnership(result, context) {
|
|
|
76
83
|
}
|
|
77
84
|
};
|
|
78
85
|
});
|
|
86
|
+
result.ownershipRegions = uniqueRecordsById([...(result.ownershipRegions ?? []), ...ownershipRegions]);
|
|
79
87
|
}
|
|
@@ -84,6 +84,12 @@ export function createSemanticImportSidecar(importResult, options = {}) {
|
|
|
84
84
|
reasons: candidate.reasons ?? [],
|
|
85
85
|
conflictClasses: (candidate.conflictClasses ?? candidate.metadata?.conflictClasses ?? []).map((record) => record.class).filter(Boolean),
|
|
86
86
|
conflictSummary: candidate.conflictSummary ?? candidate.metadata?.conflictSummary,
|
|
87
|
+
changedSemanticRegions: candidate.changedSemanticRegions?.length ?? candidate.mergeAdmission?.changedSemanticRegions?.length ?? 0,
|
|
88
|
+
sourceHashes: candidate.sourceHashes ?? candidate.mergeAdmission?.sourceHashes,
|
|
89
|
+
evidenceIds: candidate.evidenceIds ?? candidate.mergeAdmission?.evidenceIds ?? [],
|
|
90
|
+
projectionRisk: candidate.projectionRisk ?? candidate.mergeAdmission?.projectionRisk,
|
|
91
|
+
readinessSortKey: candidate.readinessSortKey ?? candidate.mergeAdmission?.readinessSortKey,
|
|
92
|
+
overlapSummary: candidate.mergeAdmission?.overlapSummary,
|
|
87
93
|
risk: candidate.risk,
|
|
88
94
|
operationCount: candidate.operations?.length ?? candidate.patch?.operations?.length ?? 0
|
|
89
95
|
})),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import{idFragment,uniqueStrings}from'../../native-import-utils.js';import{createSemanticMergeCandidateRecord}from'@shapeshift-labs/frontier-lang-kernel';
|
|
2
2
|
import{createSemanticImportSidecar}from'./createSemanticImportSidecar.js';import{nativeNodeId}from'./nativeNodeId.js';import{readStringArray}from'./readStringArray.js';import{selectSemanticSliceRecords}from'./selectSemanticSliceRecords.js';import{semanticSliceContext}from'./semanticSliceContext.js';import{semanticSliceExpectedAssertions}from'./semanticSliceExpectedAssertions.js';import{semanticSliceReadiness}from'./semanticSliceReadiness.js';import{semanticSliceReasons}from'./semanticSliceReasons.js';import{semanticSliceRecords}from'./semanticSliceRecords.js';import{semanticSliceSourceFiles}from'./semanticSliceSourceFiles.js';import{semanticSliceSourceMapLinks}from'./semanticSliceSourceMapLinks.js';import{semanticSliceSourceSpans}from'./semanticSliceSourceSpans.js';import{semanticSliceTouchedSymbol}from'./semanticSliceTouchedSymbol.js';
|
|
3
|
+
import{decorateSemanticMergeCandidateForAdmission}from'./semanticMergeCandidateRecords.js';
|
|
3
4
|
export function createSemanticSlice(input, options = {}) {
|
|
4
5
|
const context = semanticSliceContext(input, options);
|
|
5
6
|
const sidecar = context.sidecar ?? (context.importResult ? createSemanticImportSidecar(context.importResult, {
|
|
@@ -50,7 +51,7 @@ export function createSemanticSlice(input, options = {}) {
|
|
|
50
51
|
sidecarId: sidecar?.id
|
|
51
52
|
}
|
|
52
53
|
}];
|
|
53
|
-
const mergeCandidate = createSemanticMergeCandidateRecord({
|
|
54
|
+
const mergeCandidate = decorateSemanticMergeCandidateForAdmission(createSemanticMergeCandidateRecord({
|
|
54
55
|
id: options.mergeCandidateId ?? `merge_candidate_${idPart}_semantic_slice`,
|
|
55
56
|
importResultId: context.importResult?.id,
|
|
56
57
|
language: context.language,
|
|
@@ -70,7 +71,7 @@ export function createSemanticSlice(input, options = {}) {
|
|
|
70
71
|
dependencyRelationIds: selection.relations.map((relation) => relation.id).filter(Boolean),
|
|
71
72
|
autoMergeClaim: false
|
|
72
73
|
}
|
|
73
|
-
});
|
|
74
|
+
}),{evidence,sourceHash:sourceFiles[0]?.sourceHash,metadata:{source:'createSemanticSlice'}});
|
|
74
75
|
return {
|
|
75
76
|
kind: 'frontier.lang.semanticSlice',
|
|
76
77
|
version: 1,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import{idFragment,maxSemanticMergeReadiness,uniqueByLossId,uniqueRecordsById,uniqueStrings}from'../../native-import-utils.js';import{createPatch,createSemanticMergeCandidateRecord}from'@shapeshift-labs/frontier-lang-kernel';
|
|
2
2
|
import{attachNativeChangeRegionProjectionMetadata}from'./attachNativeChangeRegionProjectionMetadata.js';import{classifyNativeSourceMergeConflicts}from'./semanticMergeConflicts.js';import{createSemanticImportSidecar}from'./createSemanticImportSidecar.js';import{diffNativeOwnershipRegions}from'./diffNativeOwnershipRegions.js';import{diffNativeSymbols}from'./diffNativeSymbols.js';import{fileLevelNativeChangeRegion}from'./fileLevelNativeChangeRegion.js';import{mapDiffSymbols}from'./mapDiffSymbols.js';import{nativeChangeSpans}from'./nativeChangeSpans.js';import{nativeChangeTouchedSymbol}from'./nativeChangeTouchedSymbol.js';import{nativeImportReadiness}from'./nativeImportReadiness.js';import{nativeSourceChangeReasons}from'./nativeSourceChangeReasons.js';import{nativeSourceChangeSummary}from'./nativeSourceChangeSummary.js';import{normalizeNativeDiffImport}from'./normalizeNativeDiffImport.js';import{summarizeNativeChangedRegionProjections}from'./summarizeNativeChangedRegionProjections.js';
|
|
3
|
+
import{decorateSemanticMergeCandidateForAdmission}from'./semanticMergeCandidateRecords.js';
|
|
3
4
|
export function diffNativeSourceImports(input) {
|
|
4
5
|
const before = normalizeNativeDiffImport(input.before, input, 'before');
|
|
5
6
|
const after = normalizeNativeDiffImport(input.after, input, 'after');
|
|
@@ -104,7 +105,7 @@ export function diffNativeSourceImports(input) {
|
|
|
104
105
|
semanticMergeConflictSummary: mergeConflictProfile.conflictSummary
|
|
105
106
|
}
|
|
106
107
|
});
|
|
107
|
-
const mergeCandidate = createSemanticMergeCandidateRecord({
|
|
108
|
+
const mergeCandidate = decorateSemanticMergeCandidateForAdmission(createSemanticMergeCandidateRecord({
|
|
108
109
|
id: input.mergeCandidateId ?? `merge_candidate_${idPart}_native_source_diff`,
|
|
109
110
|
importResultId: after?.id ?? before?.id,
|
|
110
111
|
patchId: patch.id,
|
|
@@ -131,7 +132,7 @@ export function diffNativeSourceImports(input) {
|
|
|
131
132
|
conflictClasses: mergeConflictProfile.conflictClasses,
|
|
132
133
|
conflictSummary: mergeConflictProfile.conflictSummary
|
|
133
134
|
}
|
|
134
|
-
});
|
|
135
|
+
}),{changedRegions,evidence,patch,baseHash:beforeHash,targetHash:afterHash,metadata:{source:'diffNativeSourceImports'}});
|
|
135
136
|
return {
|
|
136
137
|
kind: 'frontier.lang.nativeSourceChangeSet',
|
|
137
138
|
version: 1,
|
|
@@ -7,6 +7,7 @@ export function externalSemanticBase(context, metadata = {}) {
|
|
|
7
7
|
occurrences: [],
|
|
8
8
|
relations: [],
|
|
9
9
|
facts: [],
|
|
10
|
+
ownershipRegions: [],
|
|
10
11
|
evidence: [externalSemanticEvidence(context, 'passed', `Imported ${context.format} semantic index payload.`)],
|
|
11
12
|
losses: [externalSemanticCoverageLoss(context)],
|
|
12
13
|
semanticStatus: 'external-semantic-index',
|
|
@@ -18,6 +18,7 @@ export function importExternalSemanticIndex(input) {
|
|
|
18
18
|
metadata: input?.metadata ?? {}
|
|
19
19
|
};
|
|
20
20
|
const normalized = normalizeExternalSemanticIndexPayload(payload, context);
|
|
21
|
+
const ownershipRegions = normalized.ownershipRegions ?? [];
|
|
21
22
|
const evidence = attachNativeImportLossSummary(
|
|
22
23
|
uniqueByEvidenceId([...(normalized.evidence ?? []), ...(input?.evidence ?? [])]),
|
|
23
24
|
summarizeNativeImportLosses(normalized.losses ?? [], {
|
|
@@ -116,6 +117,7 @@ export function importExternalSemanticIndex(input) {
|
|
|
116
117
|
semanticIndex,
|
|
117
118
|
universalAst,
|
|
118
119
|
sourceMaps,
|
|
120
|
+
ownershipRegions,
|
|
119
121
|
losses,
|
|
120
122
|
evidence,
|
|
121
123
|
readiness,
|
|
@@ -125,6 +127,8 @@ export function importExternalSemanticIndex(input) {
|
|
|
125
127
|
occurrences: semanticIndex.occurrences.length,
|
|
126
128
|
relations: semanticIndex.relations.length,
|
|
127
129
|
facts: semanticIndex.facts.length,
|
|
130
|
+
ownershipRegions: ownershipRegions.length,
|
|
131
|
+
ownershipRegionKinds: [...new Set(ownershipRegions.map((region) => region.regionKind).filter(Boolean))],
|
|
128
132
|
sourceMapMappings: sourceMaps.reduce((sum, sourceMap) => sum + (sourceMap.mappings?.length ?? 0), 0),
|
|
129
133
|
losses: losses.length,
|
|
130
134
|
readiness: readiness.readiness
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import{countBy,maxSemanticMergeReadiness,uniqueRecordsById,uniqueStrings}from'../../native-import-utils.js';
|
|
2
|
+
import{createSemanticMergeCandidateAdmissionRecord,querySemanticMergeCandidateAdmissionOverlaps,sortSemanticMergeCandidateAdmissionRecords}from'./semanticMergeCandidateRecords.js';
|
|
2
3
|
|
|
3
4
|
const riskRank=Object.freeze({low:0,medium:1,unknown:2,high:3});
|
|
4
5
|
const preservationRank=Object.freeze({exact:0,lossy:1,missing:2,stale:3,empty:4});
|
|
@@ -155,21 +156,45 @@ export function admissionMergeCandidates(projectResult,imports,mergeCandidates,l
|
|
|
155
156
|
projectResult?.patch,
|
|
156
157
|
...imports.map((imported)=>imported?.patch)
|
|
157
158
|
].filter((patch)=>patch?.id).map((patch)=>[patch.id,patch]));
|
|
158
|
-
const
|
|
159
|
+
const records=sortSemanticMergeCandidateAdmissionRecords(mergeCandidates.map((candidate)=>createSemanticMergeCandidateAdmissionRecord(candidate,{patch:patchById.get(candidate.patchId)})));
|
|
160
|
+
const recordByCandidateId=new Map(records.map((record)=>[record.candidateId,record]));
|
|
161
|
+
const overlaps=querySemanticMergeCandidateAdmissionOverlaps(records);
|
|
162
|
+
const risks=mergeCandidates.map((candidate)=>{
|
|
163
|
+
const record=recordByCandidateId.get(candidate.id);
|
|
164
|
+
return maxRisk(candidateRisk(candidate,patchById.get(candidate.patchId)),record?.projectionRisk??'low');
|
|
165
|
+
});
|
|
159
166
|
const readiness=mergeCandidates.reduce(
|
|
160
|
-
(current,candidate)=>maxSemanticMergeReadiness(current,candidate.readiness),
|
|
167
|
+
(current,candidate)=>maxSemanticMergeReadiness(current,recordByCandidateId.get(candidate.id)?.readiness??candidate.readiness),
|
|
161
168
|
lossSummary?.semanticMergeReadiness??'ready'
|
|
162
169
|
);
|
|
170
|
+
const overlapCandidateIds=uniqueStrings(overlaps.flatMap((overlap)=>overlap.candidateIds??[]));
|
|
163
171
|
return {
|
|
164
172
|
total:mergeCandidates.length,
|
|
165
173
|
readiness,
|
|
166
174
|
highestRisk:risks.reduce(maxRisk,'low'),
|
|
175
|
+
projectionRisk:records.reduce((current,record)=>maxRisk(current,record.projectionRisk??'unknown'),'low'),
|
|
167
176
|
byRisk:countBy(risks),
|
|
168
|
-
byReadiness:countBy(
|
|
177
|
+
byReadiness:countBy(records.map((record)=>record.readiness??'needs-review')),
|
|
178
|
+
byProjectionRisk:countBy(records.map((record)=>record.projectionRisk??'unknown')),
|
|
169
179
|
highRiskCandidateIds:mergeCandidates.filter((candidate,index)=>risks[index]==='high').map((candidate)=>candidate.id).filter(Boolean),
|
|
170
|
-
reviewCandidateIds:
|
|
171
|
-
blockedCandidateIds:
|
|
172
|
-
|
|
180
|
+
reviewCandidateIds:records.filter((record)=>record.readiness==='needs-review'||record.admission.reviewRequired).map((record)=>record.candidateId).filter(Boolean),
|
|
181
|
+
blockedCandidateIds:records.filter((record)=>record.readiness==='blocked'||record.admission.action==='block').map((record)=>record.candidateId).filter(Boolean),
|
|
182
|
+
highProjectionRiskCandidateIds:records.filter((record)=>record.projectionRisk==='high').map((record)=>record.candidateId).filter(Boolean),
|
|
183
|
+
conflictKeys:uniqueStrings(records.flatMap((record)=>record.conflictKeys??[])),
|
|
184
|
+
readinessOrderCandidateIds:records.map((record)=>record.candidateId).filter(Boolean),
|
|
185
|
+
changedSemanticRegions:{
|
|
186
|
+
total:records.reduce((sum,record)=>sum+record.changedSemanticRegions.length,0),
|
|
187
|
+
byKind:countBy(records.flatMap((record)=>record.changedSemanticRegions.map((region)=>region.regionKind??'unknown'))),
|
|
188
|
+
conflictKeys:uniqueStrings(records.flatMap((record)=>record.changedSemanticRegions.map((region)=>region.conflictKey)))
|
|
189
|
+
},
|
|
190
|
+
overlaps:{
|
|
191
|
+
total:overlaps.length,
|
|
192
|
+
candidateIds:overlapCandidateIds,
|
|
193
|
+
conflictKeys:uniqueStrings(overlaps.flatMap((overlap)=>overlap.conflictKeys??[])),
|
|
194
|
+
sourcePaths:uniqueStrings(overlaps.map((overlap)=>overlap.sourcePath).filter(Boolean)),
|
|
195
|
+
pairs:overlaps
|
|
196
|
+
},
|
|
197
|
+
records,
|
|
173
198
|
patchRisk:normalizeRisk(projectResult?.patch?.risk)
|
|
174
199
|
};
|
|
175
200
|
}
|
|
@@ -71,7 +71,7 @@ export async function runNativeImporterAdapter(adapter, input = {}) {
|
|
|
71
71
|
sourcePath: parseResult.sourcePath ?? input.sourcePath,
|
|
72
72
|
sourceHash: parseResult.sourceHash ?? sourceHash
|
|
73
73
|
});
|
|
74
|
-
const evidence = [...(parseResult.evidence ?? []), sourceEvidence];
|
|
74
|
+
const evidence = [...(input.evidence ?? []), ...(parseResult.evidence ?? []), sourceEvidence];
|
|
75
75
|
const importInput = {
|
|
76
76
|
...input,
|
|
77
77
|
...parseResult,
|