@shapeshift-labs/frontier-lang-compiler 0.2.121 → 0.2.122
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 +6 -0
- package/dist/declarations/js-ts-safe-project-merge.d.ts +8 -0
- package/dist/declarations/native-project.d.ts +8 -5
- package/dist/internal/index-impl/semanticIndexFromNativeDeclarations.js +10 -17
- package/dist/js-ts-safe-merge-semantic-artifacts.js +12 -0
- package/dist/js-ts-safe-project-merge-graph-conflicts.js +45 -0
- package/dist/js-ts-safe-project-merge-graph.js +61 -2
- package/dist/js-ts-safe-project-merge.js +18 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -286,6 +286,12 @@ re-export, export-star, local export, `export default`, and TypeScript
|
|
|
286
286
|
`importedName`, `exportedName`, `isTypeOnly`, and public-contract metadata into
|
|
287
287
|
the semantic index and project symbol graph.
|
|
288
288
|
|
|
289
|
+
`safeMergeJsTsProject` stays synchronous. When a caller already has parser-backed
|
|
290
|
+
native import results for merged output files, pass them as `outputProjectImports`
|
|
291
|
+
with `includeOutputProjectSymbolGraph`. The graph builder matches supplied
|
|
292
|
+
imports by `sourcePath` and `sourceHash`, uses them for output graph artifacts,
|
|
293
|
+
and falls back to the lightweight scanner for missing or stale files.
|
|
294
|
+
|
|
289
295
|
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.
|
|
290
296
|
|
|
291
297
|
```js
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
JsTsSafeMergeSummary
|
|
8
8
|
} from './js-ts-safe-merge.js';
|
|
9
9
|
import type { JsTsSafeMemberMergePolicy, JsTsSafeMemberMergePolicyRegion } from './js-ts-safe-member-merge.js';
|
|
10
|
+
import type { NativeSourceImportResult } from './import-adapter-core.js';
|
|
10
11
|
import type { NativeProjectImportResult, NativeProjectSymbolGraphSummary } from './native-project.js';
|
|
11
12
|
import type { NativeProjectModuleResolutionOptions } from './native-project-module-resolution.js';
|
|
12
13
|
|
|
@@ -45,6 +46,11 @@ export type JsTsProjectSafeMergeFileMap =
|
|
|
45
46
|
| ReadonlyMap<string, string>
|
|
46
47
|
| readonly { readonly sourcePath?: string; readonly path?: string; readonly sourceText?: string; readonly text?: string }[];
|
|
47
48
|
|
|
49
|
+
export type JsTsProjectSafeMergeOutputProjectImports =
|
|
50
|
+
| readonly NativeSourceImportResult[]
|
|
51
|
+
| ReadonlyMap<string, NativeSourceImportResult>
|
|
52
|
+
| Readonly<Record<string, NativeSourceImportResult>>;
|
|
53
|
+
|
|
48
54
|
export interface JsTsProjectSafeMergeInput {
|
|
49
55
|
readonly id?: string;
|
|
50
56
|
readonly language?: FrontierSourceLanguage | string;
|
|
@@ -56,6 +62,7 @@ export interface JsTsProjectSafeMergeInput {
|
|
|
56
62
|
readonly allowFileAdditions?: boolean;
|
|
57
63
|
readonly allowFileDeletes?: boolean;
|
|
58
64
|
readonly includeOutputProjectSymbolGraph?: boolean;
|
|
65
|
+
readonly outputProjectImports?: JsTsProjectSafeMergeOutputProjectImports;
|
|
59
66
|
readonly moduleResolution?: NativeProjectModuleResolutionOptions;
|
|
60
67
|
readonly tsconfig?: NativeProjectModuleResolutionOptions;
|
|
61
68
|
readonly workerChangeSetId?: string;
|
|
@@ -126,6 +133,7 @@ export interface JsTsProjectSafeMergeResult {
|
|
|
126
133
|
readonly mergedFiles: number;
|
|
127
134
|
readonly blockedFiles: number;
|
|
128
135
|
readonly outputFiles: number;
|
|
136
|
+
readonly projectGraphConflicts: number;
|
|
129
137
|
readonly semanticArtifactFiles: number;
|
|
130
138
|
readonly operations: Readonly<Record<string, number>>;
|
|
131
139
|
};
|
|
@@ -182,13 +182,16 @@ export interface NativeProjectSymbolGraphSummary {
|
|
|
182
182
|
readonly remainingFields: readonly NativeProjectSymbolGraphRemainingField[];
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
+
export interface NativeProjectSourcePreservationSummary { readonly total: number; readonly exactSourceAvailable: number; readonly sourceBytes: number; readonly tokens: number; readonly trivia: number; readonly directives: number; readonly truncated: boolean; readonly ids: readonly string[]; }
|
|
186
|
+
|
|
185
187
|
export interface NativeProjectImportResultMetadata extends Record<string, unknown> {
|
|
186
|
-
readonly
|
|
187
|
-
readonly projectAdmission?: NativeProjectImportAdmission;
|
|
188
|
-
readonly semanticMergeAdmission?: NativeProjectImportAdmission;
|
|
189
|
-
readonly
|
|
190
|
-
readonly semanticMergeReadiness?: SemanticMergeReadiness;
|
|
188
|
+
readonly sourceCount?: number; readonly sourcePaths?: readonly string[];
|
|
189
|
+
readonly importResultContract?: NativeImportResultContract; readonly projectAdmission?: NativeProjectImportAdmission;
|
|
190
|
+
readonly semanticMergeAdmission?: NativeProjectImportAdmission; readonly nativeImportLossSummary?: NativeImportLossSummary;
|
|
191
|
+
readonly sourcePreservationSummary?: NativeProjectSourcePreservationSummary; readonly semanticMergeReadiness?: SemanticMergeReadiness;
|
|
191
192
|
readonly readinessReasons?: readonly string[];
|
|
193
|
+
readonly regionSummary?: NativeImportRegionSummary; readonly sourceMapSummary?: NativeImportSourceMapSummary;
|
|
194
|
+
readonly adapterCoverageSummary?: NativeImportAdapterCoverageContract;
|
|
192
195
|
readonly projectSymbolGraph?: NativeProjectSymbolGraphSummary;
|
|
193
196
|
}
|
|
194
197
|
|
|
@@ -244,24 +244,17 @@ function publicContractRegionForDeclaration(declaration, ownershipRegion, module
|
|
|
244
244
|
|
|
245
245
|
function reExportIdentityForDeclaration(declaration, input, documentId, relationId, ownershipRegion, moduleEdge) {
|
|
246
246
|
if (!moduleEdge?.isReExport && !declaration.reExport) return undefined;
|
|
247
|
+
const bindingCount = Number(declaration.nativeNode?.metadata?.bindingCount ?? declaration.metadata?.bindingCount ?? 0);
|
|
248
|
+
if (declaration.symbolKind === 'module' && !declaration.exportStar && !declaration.metadata?.exportStar && bindingCount > 1) return undefined;
|
|
249
|
+
const identityId = hashSemanticValue([relationId, declaration.symbolId, declaration.exportedName ?? declaration.metadata?.exportedName, declaration.importedName ?? declaration.metadata?.importedName, declaration.localName ?? declaration.metadata?.localName]);
|
|
250
|
+
const stableId = bindingCount > 1 ? idFragment(identityId) : idFragment(relationId);
|
|
247
251
|
return compactRecord({
|
|
248
|
-
kind: 'frontier.lang.reExportIdentity',
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
moduleSpecifier: moduleEdge?.moduleSpecifier,
|
|
255
|
-
exportedName: declaration.exportedName ?? declaration.metadata?.exportedName,
|
|
256
|
-
importedName: declaration.importedName ?? declaration.metadata?.importedName,
|
|
257
|
-
localName: declaration.localName ?? declaration.metadata?.localName,
|
|
258
|
-
namespace: declaration.namespace ?? declaration.metadata?.namespace,
|
|
259
|
-
isTypeOnly: declaration.isTypeOnly ?? declaration.metadata?.isTypeOnly ?? declaration.metadata?.typeOnly,
|
|
260
|
-
exportStar: declaration.exportStar ?? declaration.metadata?.exportStar,
|
|
261
|
-
symbolId: declaration.symbolId,
|
|
262
|
-
relationId,
|
|
263
|
-
ownershipRegionId: ownershipRegion.id,
|
|
264
|
-
ownershipRegionKey: ownershipRegion.key,
|
|
252
|
+
kind: 'frontier.lang.reExportIdentity', version: 1, id: `reexport_${stableId}`, sourceDocumentId: documentId,
|
|
253
|
+
sourcePath: input.sourcePath, sourceHash: input.sourceHash, moduleSpecifier: moduleEdge?.moduleSpecifier,
|
|
254
|
+
exportedName: declaration.exportedName ?? declaration.metadata?.exportedName, importedName: declaration.importedName ?? declaration.metadata?.importedName,
|
|
255
|
+
localName: declaration.localName ?? declaration.metadata?.localName, namespace: declaration.namespace ?? declaration.metadata?.namespace,
|
|
256
|
+
isTypeOnly: declaration.isTypeOnly ?? declaration.metadata?.isTypeOnly ?? declaration.metadata?.typeOnly, exportStar: declaration.exportStar ?? declaration.metadata?.exportStar,
|
|
257
|
+
symbolId: declaration.symbolId, relationId, ownershipRegionId: ownershipRegion.id, ownershipRegionKey: ownershipRegion.key,
|
|
265
258
|
publicContract: true
|
|
266
259
|
});
|
|
267
260
|
}
|
|
@@ -59,6 +59,7 @@ function createJsTsSafeMergeSemanticArtifacts(input = {}, merge = {}) {
|
|
|
59
59
|
id: `js_ts_safe_merge_replay_${idFragment(id)}`,
|
|
60
60
|
projection,
|
|
61
61
|
currentSourceText: headSourceText,
|
|
62
|
+
currentSourceHash: headReplaySourceHash(input),
|
|
62
63
|
currentSourcePath: sourcePath,
|
|
63
64
|
language
|
|
64
65
|
});
|
|
@@ -66,6 +67,7 @@ function createJsTsSafeMergeSemanticArtifacts(input = {}, merge = {}) {
|
|
|
66
67
|
id: `js_ts_safe_merge_replay_already_applied_${idFragment(id)}`,
|
|
67
68
|
projection,
|
|
68
69
|
currentSourceText: mergedSourceText,
|
|
70
|
+
currentSourceHash: projection.projectedHash,
|
|
69
71
|
currentSourcePath: sourcePath,
|
|
70
72
|
language
|
|
71
73
|
});
|
|
@@ -74,6 +76,8 @@ function createJsTsSafeMergeSemanticArtifacts(input = {}, merge = {}) {
|
|
|
74
76
|
const status = !blocked && replayReady && alreadyAppliedReady ? 'verified' : 'blocked';
|
|
75
77
|
const finalReasonCodes = uniqueStrings([
|
|
76
78
|
...reasonCodes,
|
|
79
|
+
...(replayReady ? [] : replay.admission?.reasonCodes ?? replay.summary?.reasonCodes ?? []),
|
|
80
|
+
...(alreadyAppliedReady ? [] : alreadyAppliedReplay.admission?.reasonCodes ?? alreadyAppliedReplay.summary?.reasonCodes ?? []),
|
|
77
81
|
replayReady ? undefined : `semantic-replay-${replay.status}`,
|
|
78
82
|
alreadyAppliedReady ? undefined : `semantic-replay-already-applied-${alreadyAppliedReplay.status}`
|
|
79
83
|
]);
|
|
@@ -263,4 +267,12 @@ function countBy(values, keyFor) {
|
|
|
263
267
|
return result;
|
|
264
268
|
}
|
|
265
269
|
|
|
270
|
+
function headReplaySourceHash(input) {
|
|
271
|
+
return nativeSemanticHash(input.currentSourceHash) ?? nativeSemanticHash(input.headHash);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function nativeSemanticHash(value) {
|
|
275
|
+
return typeof value === 'string' && /^fnv1a32:[0-9a-f]+$/i.test(value) ? value : undefined;
|
|
276
|
+
}
|
|
277
|
+
|
|
266
278
|
export { createJsTsSafeMergeSemanticArtifacts };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { compactRecord } from './js-ts-safe-merge-context.js';
|
|
2
|
+
|
|
3
|
+
function outputProjectGraphConflicts(projectSymbolGraph) {
|
|
4
|
+
const importEdges = Array.isArray(projectSymbolGraph?.importEdges) ? projectSymbolGraph.importEdges : [];
|
|
5
|
+
const groups = new Map();
|
|
6
|
+
for (const edge of importEdges) {
|
|
7
|
+
if (!isMissingProjectImportEdge(edge)) continue;
|
|
8
|
+
const key = [edge.sourcePath, edge.moduleSpecifier, edge.resolutionKind, edge.resolvedModulePath].join('\u0000');
|
|
9
|
+
const group = groups.get(key) ?? [];
|
|
10
|
+
group.push(edge);
|
|
11
|
+
groups.set(key, group);
|
|
12
|
+
}
|
|
13
|
+
return [...groups.values()].map(projectGraphMissingImportConflict);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function projectGraphMissingImportConflict(group) {
|
|
17
|
+
const edge = group[0] ?? {};
|
|
18
|
+
return {
|
|
19
|
+
code: 'project-output-module-unresolved',
|
|
20
|
+
gateId: 'project-symbol-graph',
|
|
21
|
+
message: `Output project graph contains unresolved ${edge.resolutionKind ?? 'missing'} import ${JSON.stringify(edge.moduleSpecifier ?? edge.resolvedModulePath ?? 'unknown')}.`,
|
|
22
|
+
sourcePath: edge.sourcePath,
|
|
23
|
+
details: compactRecord({
|
|
24
|
+
reasonCode: 'project-output-module-unresolved',
|
|
25
|
+
conflictKey: `project-module#${edge.sourcePath ?? 'unknown'}#${edge.moduleSpecifier ?? edge.resolvedModulePath ?? 'unknown'}`,
|
|
26
|
+
sourcePath: edge.sourcePath,
|
|
27
|
+
moduleSpecifier: edge.moduleSpecifier,
|
|
28
|
+
resolutionKind: edge.resolutionKind,
|
|
29
|
+
resolvedModulePath: edge.resolvedModulePath,
|
|
30
|
+
edgeIds: uniqueStrings(group.map((record) => record.id)),
|
|
31
|
+
importKinds: uniqueStrings(group.map((record) => record.importKind)),
|
|
32
|
+
importedNames: uniqueStrings(group.map((record) => record.importedName))
|
|
33
|
+
})
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function isMissingProjectImportEdge(edge) {
|
|
38
|
+
return typeof edge?.resolutionKind === 'string' && edge.resolutionKind.endsWith('-missing');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function uniqueStrings(values) {
|
|
42
|
+
return [...new Set(values.filter((value) => typeof value === 'string' && value.length > 0))];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { outputProjectGraphConflicts };
|
|
@@ -8,9 +8,18 @@ function createJsTsProjectSafeMergeGraphArtifacts(input, outputFiles, mergeId) {
|
|
|
8
8
|
language: file.language ?? input.language ?? languageForPath(file.sourcePath),
|
|
9
9
|
sourcePath: file.sourcePath,
|
|
10
10
|
sourceText: file.sourceText,
|
|
11
|
+
sourceHash: file.sourceHash,
|
|
11
12
|
metadata: { semanticImportExpected: true, projectSafeMergeOutput: true }
|
|
12
13
|
}));
|
|
13
|
-
const
|
|
14
|
+
const suppliedImports = normalizeOutputProjectImports(input.outputProjectImports);
|
|
15
|
+
const importSelections = sources.map((source) => {
|
|
16
|
+
const suppliedImport = matchingOutputProjectImport(source, suppliedImports);
|
|
17
|
+
return {
|
|
18
|
+
importResult: suppliedImport ?? importNativeSource(source),
|
|
19
|
+
sourceKind: suppliedImport ? 'supplied-output-project-import' : 'lightweight-output-project-scan'
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
const imports = importSelections.map((selection) => selection.importResult);
|
|
14
23
|
const projectImport = createNativeProjectImportResult({
|
|
15
24
|
id: `${mergeId}_output_project_import`,
|
|
16
25
|
projectRoot: input.projectRoot,
|
|
@@ -18,7 +27,12 @@ function createJsTsProjectSafeMergeGraphArtifacts(input, outputFiles, mergeId) {
|
|
|
18
27
|
sources,
|
|
19
28
|
metadata: {
|
|
20
29
|
projectSafeMergeId: mergeId,
|
|
21
|
-
outputProjectSymbolGraph: true
|
|
30
|
+
outputProjectSymbolGraph: true,
|
|
31
|
+
outputProjectImportSource: {
|
|
32
|
+
suppliedImports: suppliedImports.length,
|
|
33
|
+
matchedSuppliedImports: importSelections.filter((selection) => selection.sourceKind === 'supplied-output-project-import').length,
|
|
34
|
+
scannerFallbackImports: importSelections.filter((selection) => selection.sourceKind === 'lightweight-output-project-scan').length
|
|
35
|
+
}
|
|
22
36
|
}
|
|
23
37
|
}, imports);
|
|
24
38
|
return {
|
|
@@ -27,10 +41,55 @@ function createJsTsProjectSafeMergeGraphArtifacts(input, outputFiles, mergeId) {
|
|
|
27
41
|
};
|
|
28
42
|
}
|
|
29
43
|
|
|
44
|
+
function normalizeOutputProjectImports(value) {
|
|
45
|
+
if (!value) return [];
|
|
46
|
+
if (Array.isArray(value)) return value.filter(Boolean);
|
|
47
|
+
if (value instanceof Map) return [...value.values()].filter(Boolean);
|
|
48
|
+
if (typeof value === 'object') return Object.values(value).filter(Boolean);
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function matchingOutputProjectImport(source, imports) {
|
|
53
|
+
const sourcePath = String(source.sourcePath ?? '');
|
|
54
|
+
const sourceHash = String(source.sourceHash ?? '');
|
|
55
|
+
return imports.find((importResult) => {
|
|
56
|
+
const importSourcePath = sourcePathForImport(importResult);
|
|
57
|
+
if (importSourcePath && sourcePath && importSourcePath !== sourcePath) return false;
|
|
58
|
+
const importSourceHash = sourceHashForImport(importResult);
|
|
59
|
+
if (importSourceHash && sourceHash && importSourceHash !== sourceHash) return false;
|
|
60
|
+
return importSourcePath === sourcePath || importSourceHash === sourceHash;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function sourcePathForImport(importResult) {
|
|
65
|
+
return firstString(
|
|
66
|
+
importResult?.sourcePath,
|
|
67
|
+
importResult?.nativeSource?.sourcePath,
|
|
68
|
+
importResult?.nativeAst?.sourcePath,
|
|
69
|
+
importResult?.semanticIndex?.documents?.[0]?.path
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function sourceHashForImport(importResult) {
|
|
74
|
+
return firstString(
|
|
75
|
+
importResult?.sourceHash,
|
|
76
|
+
importResult?.nativeSource?.sourceHash,
|
|
77
|
+
importResult?.nativeAst?.sourceHash,
|
|
78
|
+
importResult?.semanticIndex?.documents?.[0]?.sourceHash
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
30
82
|
function languageForPath(sourcePath) {
|
|
31
83
|
const path = String(sourcePath ?? '').toLowerCase();
|
|
32
84
|
if (path.endsWith('.js') || path.endsWith('.jsx') || path.endsWith('.mjs') || path.endsWith('.cjs')) return 'javascript';
|
|
33
85
|
return 'typescript';
|
|
34
86
|
}
|
|
35
87
|
|
|
88
|
+
function firstString(...values) {
|
|
89
|
+
for (const value of values) {
|
|
90
|
+
if (value !== undefined && value !== null && String(value)) return String(value);
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
|
|
36
95
|
export { createJsTsProjectSafeMergeGraphArtifacts };
|
|
@@ -2,13 +2,13 @@ import { hashSemanticValue } from '@shapeshift-labs/frontier-lang-kernel';
|
|
|
2
2
|
import { safeMergeJsTsSource } from './js-ts-safe-merge-composed.js';
|
|
3
3
|
import { compactRecord } from './js-ts-safe-merge-context.js';
|
|
4
4
|
import { createJsTsProjectSafeMergeGraphArtifacts } from './js-ts-safe-project-merge-graph.js';
|
|
5
|
+
import { outputProjectGraphConflicts } from './js-ts-safe-project-merge-graph-conflicts.js';
|
|
5
6
|
|
|
6
7
|
function safeMergeJsTsProject(input = {}) {
|
|
7
8
|
const id = String(input.id ?? 'js_ts_project_safe_merge');
|
|
8
9
|
const files = normalizeProjectFiles(input);
|
|
9
10
|
const fileResults = files.map((file) => mergeProjectFile(file, input, id));
|
|
10
11
|
const blockedFiles = fileResults.filter((file) => file.status === 'blocked');
|
|
11
|
-
const status = blockedFiles.length ? 'blocked' : 'merged';
|
|
12
12
|
const outputFiles = fileResults
|
|
13
13
|
.filter((file) => typeof file.outputSourceText === 'string')
|
|
14
14
|
.map((file) => compactRecord({
|
|
@@ -18,10 +18,19 @@ function safeMergeJsTsProject(input = {}) {
|
|
|
18
18
|
sourceHash: file.outputHash,
|
|
19
19
|
operation: file.operation
|
|
20
20
|
}));
|
|
21
|
-
const
|
|
22
|
-
const graphArtifacts = status === 'merged' && input.includeOutputProjectSymbolGraph
|
|
21
|
+
const graphArtifacts = blockedFiles.length === 0 && input.includeOutputProjectSymbolGraph
|
|
23
22
|
? createJsTsProjectSafeMergeGraphArtifacts(input, outputFiles, id)
|
|
24
23
|
: undefined;
|
|
24
|
+
const graphConflicts = outputProjectGraphConflicts(graphArtifacts?.projectSymbolGraph);
|
|
25
|
+
const status = blockedFiles.length || graphConflicts.length ? 'blocked' : 'merged';
|
|
26
|
+
const reasonCodes = uniqueStrings([
|
|
27
|
+
...blockedFiles.flatMap((file) => file.admission.reasonCodes),
|
|
28
|
+
...graphConflicts.map((conflict) => conflict.code)
|
|
29
|
+
]);
|
|
30
|
+
const conflictKeys = uniqueStrings([
|
|
31
|
+
...fileResults.flatMap((file) => file.conflictKeys),
|
|
32
|
+
...graphConflicts.map((conflict) => conflict.details?.conflictKey)
|
|
33
|
+
]);
|
|
25
34
|
const core = {
|
|
26
35
|
kind: 'frontier.lang.jsTsProjectSafeMerge',
|
|
27
36
|
version: 1,
|
|
@@ -32,7 +41,7 @@ function safeMergeJsTsProject(input = {}) {
|
|
|
32
41
|
outputFiles,
|
|
33
42
|
outputProjectImport: graphArtifacts?.projectImport,
|
|
34
43
|
outputProjectSymbolGraph: graphArtifacts?.projectSymbolGraph,
|
|
35
|
-
conflicts: fileResults.flatMap((file) => file.conflicts),
|
|
44
|
+
conflicts: [...fileResults.flatMap((file) => file.conflicts), ...graphConflicts],
|
|
36
45
|
admission: {
|
|
37
46
|
status: status === 'merged' ? 'auto-merge-candidate' : 'blocked',
|
|
38
47
|
action: status === 'merged' ? 'apply-project' : 'human-review',
|
|
@@ -41,15 +50,16 @@ function safeMergeJsTsProject(input = {}) {
|
|
|
41
50
|
autoMergeClaim: false,
|
|
42
51
|
semanticEquivalenceClaim: false,
|
|
43
52
|
reasonCodes,
|
|
44
|
-
conflictKeys
|
|
53
|
+
conflictKeys
|
|
45
54
|
},
|
|
46
|
-
summary: projectSummary(fileResults),
|
|
55
|
+
summary: projectSummary(fileResults, graphConflicts),
|
|
47
56
|
metadata: compactRecord({
|
|
48
57
|
workerChangeSetId: input.workerChangeSetId,
|
|
49
58
|
headChangeSetId: input.headChangeSetId,
|
|
50
59
|
projectRoot: input.projectRoot,
|
|
51
60
|
filesInput: Array.isArray(input.files) ? 'records' : 'maps',
|
|
52
61
|
outputProjectSymbolGraph: Boolean(graphArtifacts?.projectSymbolGraph),
|
|
62
|
+
projectGraphConflicts: graphConflicts.length || undefined,
|
|
53
63
|
autoMergeClaim: false,
|
|
54
64
|
semanticEquivalenceClaim: false
|
|
55
65
|
})
|
|
@@ -235,7 +245,7 @@ function sourceLedgersForFile(input, sourcePath) {
|
|
|
235
245
|
return undefined;
|
|
236
246
|
}
|
|
237
247
|
|
|
238
|
-
function projectSummary(files) {
|
|
248
|
+
function projectSummary(files, graphConflicts = []) {
|
|
239
249
|
const byOperation = {};
|
|
240
250
|
for (const file of files) byOperation[file.operation] = (byOperation[file.operation] ?? 0) + 1;
|
|
241
251
|
return {
|
|
@@ -243,6 +253,7 @@ function projectSummary(files) {
|
|
|
243
253
|
mergedFiles: files.filter((file) => file.status === 'merged').length,
|
|
244
254
|
blockedFiles: files.filter((file) => file.status === 'blocked').length,
|
|
245
255
|
outputFiles: files.filter((file) => typeof file.outputSourceText === 'string').length,
|
|
256
|
+
projectGraphConflicts: graphConflicts.length,
|
|
246
257
|
semanticArtifactFiles: files.filter((file) => file.semanticArtifacts).length,
|
|
247
258
|
operations: byOperation
|
|
248
259
|
};
|
package/package.json
CHANGED