@mergesignal/shared 0.2.7 → 0.2.8
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/actionsStepSummary.d.ts.map +1 -1
- package/dist/actionsStepSummary.js +2 -29
- package/dist/collectNarrativeWhyBullets.d.ts +12 -0
- package/dist/collectNarrativeWhyBullets.d.ts.map +1 -0
- package/dist/collectNarrativeWhyBullets.js +104 -0
- package/dist/deriveScanNarrative.d.ts.map +1 -1
- package/dist/deriveScanNarrative.js +157 -54
- package/dist/deriveScanNarrative.test.js +56 -1
- package/dist/fixtures/repoIntelligenceFixtures.d.ts +2 -0
- package/dist/fixtures/repoIntelligenceFixtures.d.ts.map +1 -1
- package/dist/fixtures/repoIntelligenceFixtures.js +46 -0
- package/dist/formatInsight.d.ts +2 -2
- package/dist/formatInsight.d.ts.map +1 -1
- package/dist/formatInsight.js +2 -7
- package/dist/formatInsight.test.js +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/narrativeParity.test.d.ts +2 -0
- package/dist/narrativeParity.test.d.ts.map +1 -0
- package/dist/narrativeParity.test.js +64 -0
- package/dist/narrativePresentation.d.ts +50 -0
- package/dist/narrativePresentation.d.ts.map +1 -0
- package/dist/narrativePresentation.js +180 -0
- package/dist/narrativePresentation.test.d.ts +2 -0
- package/dist/narrativePresentation.test.d.ts.map +1 -0
- package/dist/narrativePresentation.test.js +53 -0
- package/dist/normalizeGeneratedText.d.ts +8 -0
- package/dist/normalizeGeneratedText.d.ts.map +1 -0
- package/dist/normalizeGeneratedText.js +31 -0
- package/dist/normalizeGeneratedText.test.d.ts +2 -0
- package/dist/normalizeGeneratedText.test.d.ts.map +1 -0
- package/dist/normalizeGeneratedText.test.js +18 -0
- package/dist/prCheckRunPresentation.d.ts +4 -3
- package/dist/prCheckRunPresentation.d.ts.map +1 -1
- package/dist/prCheckRunPresentation.js +56 -51
- package/dist/prCheckRunPresentation.test.js +2 -2
- package/dist/presentGitHubPrComment.d.ts +9 -0
- package/dist/presentGitHubPrComment.d.ts.map +1 -0
- package/dist/presentGitHubPrComment.js +80 -0
- package/dist/presentScanCardSummary.d.ts.map +1 -1
- package/dist/presentScanCardSummary.js +69 -64
- package/dist/riskVocabulary.js +1 -1
- package/dist/scanCardSummary.d.ts +9 -1
- package/dist/scanCardSummary.d.ts.map +1 -1
- package/dist/scanCardSummary.js +1 -1
- package/dist/scanCardSummary.test.js +12 -8
- package/dist/scanDetailViewModel.d.ts +9 -1
- package/dist/scanDetailViewModel.d.ts.map +1 -1
- package/dist/scanDetailViewModel.js +164 -37
- package/dist/scanDetailViewModel.test.js +27 -1
- package/dist/scanNarrativeFacts.d.ts +21 -8
- package/dist/scanNarrativeFacts.d.ts.map +1 -1
- package/dist/scanNarrativeFacts.js +6 -0
- package/dist/scanSurfaceCopy.d.ts +26 -26
- package/dist/scanSurfaceCopy.d.ts.map +1 -1
- package/dist/scanSurfaceCopy.js +26 -26
- package/package.json +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ScanNarrativeFacts } from "./scanNarrativeFacts.js";
|
|
1
2
|
import { type ScanDetailRecommendationCenter } from "./deriveScanDetailRecommendations.js";
|
|
2
3
|
import { type ScanDetailSignalSummary } from "./deriveRiskScoreSummary.js";
|
|
3
4
|
import { type MergePosture } from "./riskVocabulary.js";
|
|
@@ -66,6 +67,12 @@ export type ScanDetailNarrativeContext = {
|
|
|
66
67
|
blastRadiusLabel: string | null;
|
|
67
68
|
affectedAreas: string[];
|
|
68
69
|
structuralOnlyDisclaimer: string | null;
|
|
70
|
+
usageHighlights: string[];
|
|
71
|
+
frameworks: string[];
|
|
72
|
+
blastRadiusFactors: string[];
|
|
73
|
+
hotspotNames: string[];
|
|
74
|
+
usageContextLine: string | null;
|
|
75
|
+
upgradeContextLine: string | null;
|
|
69
76
|
};
|
|
70
77
|
export type ScanDetailViewModel = {
|
|
71
78
|
verdict: ScanDetailVerdict;
|
|
@@ -114,8 +121,9 @@ export declare function sanitizeAct2Theme(raw: string): string | null;
|
|
|
114
121
|
export declare function deriveVerdictLine(posture: MergePosture | null, totalScore: number | null | undefined): string;
|
|
115
122
|
export declare function deriveAct2Themes(result: ScanResult): string[];
|
|
116
123
|
export declare function deriveOperationalImpact(result: ScanResult, verifyLabels?: Set<string>): ScanDetailOperationalImpact;
|
|
124
|
+
export declare function presentScanDetailNarrativeContext(facts: ScanNarrativeFacts): ScanDetailNarrativeContext;
|
|
117
125
|
/** Scan detail presentation from shared narrative facts. */
|
|
118
|
-
export declare function presentScanDetailViewModel(facts:
|
|
126
|
+
export declare function presentScanDetailViewModel(facts: ScanNarrativeFacts, result: ScanResult, options: DeriveScanDetailOptions): ScanDetailViewModel;
|
|
119
127
|
export declare function deriveScanDetailViewModel(result: ScanResult | null | undefined, options: DeriveScanDetailOptions): ScanDetailViewModel | null;
|
|
120
128
|
/** Tier 1 recall test helper — true when message describes application-level impact. */
|
|
121
129
|
export declare function tier1PassesRecallTest(operationalImpact: ScanDetailOperationalImpact): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanDetailViewModel.d.ts","sourceRoot":"","sources":["../src/scanDetailViewModel.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scanDetailViewModel.d.ts","sourceRoot":"","sources":["../src/scanDetailViewModel.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { humanizeEngineSurfaceText, layerRiskBandLabel, sortPRInsightsForDisplay, truncateWithEllipsis, } from "./actionsStepSummary.js";
|
|
2
2
|
import { mapFindingToCatalogPhrase, mapGraphInsightsToCatalogPhrases, phraseForFamily, } from "./cardObservationCatalog.js";
|
|
3
3
|
import { deriveScanNarrative } from "./deriveScanNarrative.js";
|
|
4
|
-
import {
|
|
4
|
+
import { formatCardAreaLabels } from "./formatCardAreaLabels.js";
|
|
5
|
+
import { composeContextLineFromFacts, formatChangedPackagesShort, formatUsageSummaryLine, labelBlastRadiusLevel, labelReachabilityKind, labelRuntimeSurface, summarizeBlastRadius, } from "./narrativePresentation.js";
|
|
6
|
+
import { normalizeGeneratedText, normalizeGeneratedTextNullable, } from "./normalizeGeneratedText.js";
|
|
5
7
|
import { deriveCardOperationalObservations } from "./deriveCardOperationalObservations.js";
|
|
6
8
|
import { deriveScanDetailRecommendations, recommendationTitlesForDedupe, } from "./deriveScanDetailRecommendations.js";
|
|
7
9
|
import { deriveSignalSummary, } from "./deriveRiskScoreSummary.js";
|
|
@@ -208,6 +210,72 @@ function graphInsightToPackage(item, severity, evidence) {
|
|
|
208
210
|
evidence,
|
|
209
211
|
};
|
|
210
212
|
}
|
|
213
|
+
function usageWhereFromFacts(facts) {
|
|
214
|
+
const primary = facts.changedPackages.primary;
|
|
215
|
+
const row = facts.packageUsage.find((u) => u.packageName === primary) ??
|
|
216
|
+
facts.packageUsage[0];
|
|
217
|
+
if (!row)
|
|
218
|
+
return undefined;
|
|
219
|
+
const paths = [...row.paths, ...row.criticalPaths, ...row.files].filter(Boolean);
|
|
220
|
+
if (paths.length === 0 && row.areas.length > 0) {
|
|
221
|
+
return row.areas.slice(0, 3).join(", ");
|
|
222
|
+
}
|
|
223
|
+
if (paths.length === 0)
|
|
224
|
+
return undefined;
|
|
225
|
+
const sample = paths.slice(0, 3).join(", ");
|
|
226
|
+
if (paths.length > 3) {
|
|
227
|
+
return `${sample} (+${paths.length - 3} more)`;
|
|
228
|
+
}
|
|
229
|
+
return sample;
|
|
230
|
+
}
|
|
231
|
+
function buildAttentionAreasFromFacts(facts) {
|
|
232
|
+
const areas = [];
|
|
233
|
+
if (facts.hotspots.length > 0) {
|
|
234
|
+
const packages = facts.hotspots.map((h) => ({
|
|
235
|
+
name: h.packageName,
|
|
236
|
+
direct: true,
|
|
237
|
+
evidence: h.paths[0],
|
|
238
|
+
}));
|
|
239
|
+
areas.push({
|
|
240
|
+
problemLabel: "Dependency hotspots",
|
|
241
|
+
problemDescription: "Packages where paths converge or corpus analysis flagged critical usage.",
|
|
242
|
+
packages: packages.slice(0, ACT3_EVIDENCE_COLLAPSE_THRESHOLD),
|
|
243
|
+
overflowCount: Math.max(0, packages.length - ACT3_EVIDENCE_COLLAPSE_THRESHOLD),
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
const blast = facts.blastRadius;
|
|
247
|
+
if (blast &&
|
|
248
|
+
(blast.level === "wide" || (blast.changedPackageCount ?? 0) >= 8)) {
|
|
249
|
+
const names = facts.changedPackages.all;
|
|
250
|
+
if (names.length > 0) {
|
|
251
|
+
const packages = names
|
|
252
|
+
.slice(0, ACT3_EVIDENCE_COLLAPSE_THRESHOLD)
|
|
253
|
+
.map((name) => ({ name, direct: true }));
|
|
254
|
+
areas.push({
|
|
255
|
+
problemLabel: phraseForFamily("blast_radius"),
|
|
256
|
+
problemDescription: blast.factors.length > 0
|
|
257
|
+
? `Wide blast radius: ${blast.factors.slice(0, 3).join(", ").replace(/_/g, " ")}`
|
|
258
|
+
: "Many packages changed in this upgrade.",
|
|
259
|
+
packages,
|
|
260
|
+
overflowCount: Math.max(0, names.length - ACT3_EVIDENCE_COLLAPSE_THRESHOLD),
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return areas;
|
|
265
|
+
}
|
|
266
|
+
function mergeAttentionAreas(fromFacts, fromGraph) {
|
|
267
|
+
if (fromFacts.length === 0)
|
|
268
|
+
return fromGraph;
|
|
269
|
+
const factPackageNames = new Set(fromFacts.flatMap((a) => a.packages.map((p) => p.name)));
|
|
270
|
+
const filteredGraph = fromGraph.filter((area) => {
|
|
271
|
+
if (area.problemLabel !== phraseForFamily("transitive_hotspots")) {
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
const onlyDupes = area.packages.every((p) => factPackageNames.has(p.name));
|
|
275
|
+
return !onlyDupes;
|
|
276
|
+
});
|
|
277
|
+
return [...fromFacts, ...filteredGraph];
|
|
278
|
+
}
|
|
211
279
|
function buildAttentionAreas(result) {
|
|
212
280
|
const areas = [];
|
|
213
281
|
const gi = result.graphInsights;
|
|
@@ -312,7 +380,7 @@ function buildTopology(result) {
|
|
|
312
380
|
}))
|
|
313
381
|
: [];
|
|
314
382
|
return {
|
|
315
|
-
summaryLine: `${nodes} packages
|
|
383
|
+
summaryLine: normalizeGeneratedText(`${nodes} packages | ${edges} edges | max depth ${maxDepth}`),
|
|
316
384
|
deepest,
|
|
317
385
|
};
|
|
318
386
|
}
|
|
@@ -346,28 +414,64 @@ function deriveConfidenceCaveat(result) {
|
|
|
346
414
|
}
|
|
347
415
|
return undefined;
|
|
348
416
|
}
|
|
349
|
-
function
|
|
350
|
-
const
|
|
417
|
+
export function presentScanDetailNarrativeContext(facts) {
|
|
418
|
+
const affectedAreas = [];
|
|
419
|
+
for (const area of facts.affectedAreas) {
|
|
420
|
+
const formatted = formatCardAreaLabels([area.label], 1);
|
|
421
|
+
if (formatted[0])
|
|
422
|
+
affectedAreas.push(formatted[0]);
|
|
423
|
+
if (affectedAreas.length >= 4)
|
|
424
|
+
break;
|
|
425
|
+
}
|
|
426
|
+
const usageHighlights = [];
|
|
427
|
+
for (const row of facts.packageUsage.slice(0, 4)) {
|
|
428
|
+
const paths = [...row.paths, ...row.criticalPaths, ...row.files];
|
|
429
|
+
if (paths[0])
|
|
430
|
+
usageHighlights.push(paths[0]);
|
|
431
|
+
}
|
|
432
|
+
const blast = summarizeBlastRadius(facts, 5);
|
|
351
433
|
return {
|
|
352
|
-
mode:
|
|
353
|
-
codeIntelligenceAvailable:
|
|
354
|
-
changedPackagesDisplay:
|
|
355
|
-
runtimeSurfaceLabel:
|
|
356
|
-
reachabilityLabel:
|
|
357
|
-
blastRadiusLabel:
|
|
358
|
-
affectedAreas
|
|
359
|
-
structuralOnlyDisclaimer:
|
|
434
|
+
mode: facts.availability.mode,
|
|
435
|
+
codeIntelligenceAvailable: facts.availability.codeIntelligenceAvailable,
|
|
436
|
+
changedPackagesDisplay: formatChangedPackagesShort(facts, 4),
|
|
437
|
+
runtimeSurfaceLabel: labelRuntimeSurface(facts),
|
|
438
|
+
reachabilityLabel: labelReachabilityKind(facts),
|
|
439
|
+
blastRadiusLabel: labelBlastRadiusLevel(facts),
|
|
440
|
+
affectedAreas,
|
|
441
|
+
structuralOnlyDisclaimer: facts.availability.mode === "graph_fallback" &&
|
|
442
|
+
!facts.availability.tiersPresent.tier1
|
|
443
|
+
? scanSurfaceCopy.narrativeCard.structuralOnlyDisclaimer
|
|
444
|
+
: null,
|
|
445
|
+
usageHighlights: usageHighlights.slice(0, 5),
|
|
446
|
+
frameworks: facts.frameworks.slice(0, 5),
|
|
447
|
+
blastRadiusFactors: blast.factors.map((f) => f.replace(/_/g, " ")),
|
|
448
|
+
hotspotNames: facts.hotspots.map((h) => h.packageName).slice(0, 8),
|
|
449
|
+
usageContextLine: normalizeGeneratedTextNullable(formatUsageSummaryLine(facts, 2)),
|
|
450
|
+
upgradeContextLine: normalizeGeneratedTextNullable(composeContextLineFromFacts(facts, {
|
|
451
|
+
includePathSample: true,
|
|
452
|
+
maxAreas: 4,
|
|
453
|
+
})),
|
|
360
454
|
};
|
|
361
455
|
}
|
|
362
|
-
function
|
|
456
|
+
function narrativeContextFromFacts(facts) {
|
|
457
|
+
return presentScanDetailNarrativeContext(facts);
|
|
458
|
+
}
|
|
459
|
+
function guidanceToImpactItem(g, verifyLabels, facts) {
|
|
363
460
|
const verify = g.remediation &&
|
|
364
461
|
!verifyLabels.has(g.remediation.toLowerCase().replace(/\s+/g, " ").trim())
|
|
365
462
|
? g.remediation
|
|
366
463
|
: undefined;
|
|
464
|
+
let where = g.context?.trim() || undefined;
|
|
465
|
+
if (!where &&
|
|
466
|
+
facts &&
|
|
467
|
+
(facts.availability.mode === "pr_intelligence" ||
|
|
468
|
+
facts.availability.tiersPresent.tier1)) {
|
|
469
|
+
where = usageWhereFromFacts(facts);
|
|
470
|
+
}
|
|
367
471
|
return {
|
|
368
|
-
message: g.message,
|
|
369
|
-
where:
|
|
370
|
-
verify,
|
|
472
|
+
message: normalizeGeneratedText(g.message),
|
|
473
|
+
where: where ? normalizeGeneratedText(where) : undefined,
|
|
474
|
+
verify: verify ? normalizeGeneratedText(verify) : undefined,
|
|
371
475
|
affectedFiles: g.affectedFiles,
|
|
372
476
|
};
|
|
373
477
|
}
|
|
@@ -377,7 +481,7 @@ function deriveOperationalImpactFromFacts(facts, result, verifyLabels) {
|
|
|
377
481
|
(facts.availability.tiersPresent.tier1 && changedGuidance.length > 0)) {
|
|
378
482
|
const items = changedGuidance
|
|
379
483
|
.slice(0, 6)
|
|
380
|
-
.map((g) => guidanceToImpactItem(g, verifyLabels));
|
|
484
|
+
.map((g) => guidanceToImpactItem(g, verifyLabels, facts));
|
|
381
485
|
if (items.length > 0) {
|
|
382
486
|
return { status: "rich", items };
|
|
383
487
|
}
|
|
@@ -393,41 +497,60 @@ function deriveOperationalImpactFromFacts(facts, result, verifyLabels) {
|
|
|
393
497
|
status: "rich",
|
|
394
498
|
items: changedGuidance
|
|
395
499
|
.slice(0, 6)
|
|
396
|
-
.map((g) => guidanceToImpactItem(g, verifyLabels)),
|
|
500
|
+
.map((g) => guidanceToImpactItem(g, verifyLabels, facts)),
|
|
397
501
|
};
|
|
398
502
|
}
|
|
399
503
|
return deriveOperationalImpact(result, verifyLabels);
|
|
400
504
|
}
|
|
505
|
+
function themeCandidateFromLabel(label) {
|
|
506
|
+
const trimmed = label.trim();
|
|
507
|
+
if (!trimmed)
|
|
508
|
+
return null;
|
|
509
|
+
return sanitizeAct2Theme(trimmed) ?? trimmed.slice(0, ACT2_MAX_THEME_CHARS);
|
|
510
|
+
}
|
|
401
511
|
function deriveBecauseThemesFromFacts(facts) {
|
|
402
512
|
const themes = [];
|
|
403
513
|
const seen = new Set();
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
514
|
+
const prIntelligence = facts.availability.mode === "pr_intelligence" ||
|
|
515
|
+
facts.availability.tiersPresent.tier1;
|
|
516
|
+
const pushTheme = (raw) => {
|
|
517
|
+
if (!raw)
|
|
518
|
+
return;
|
|
519
|
+
const normalized = normalizeGeneratedText(raw);
|
|
520
|
+
const key = normalized.toLowerCase();
|
|
409
521
|
if (seen.has(key))
|
|
410
|
-
|
|
522
|
+
return;
|
|
411
523
|
seen.add(key);
|
|
412
|
-
themes.push(
|
|
524
|
+
themes.push(normalized);
|
|
525
|
+
};
|
|
526
|
+
if (prIntelligence) {
|
|
527
|
+
for (const area of facts.affectedAreas) {
|
|
528
|
+
pushTheme(themeCandidateFromLabel(area.label));
|
|
529
|
+
if (themes.length >= ACT2_MAX_THEMES)
|
|
530
|
+
return themes;
|
|
531
|
+
}
|
|
532
|
+
for (const factor of facts.blastRadius?.factors ?? []) {
|
|
533
|
+
pushTheme(themeCandidateFromLabel(factor.replace(/_/g, " ")));
|
|
534
|
+
if (themes.length >= ACT2_MAX_THEMES)
|
|
535
|
+
return themes;
|
|
536
|
+
}
|
|
537
|
+
const reachLabel = labelReachabilityKind(facts);
|
|
538
|
+
if (reachLabel)
|
|
539
|
+
pushTheme(reachLabel);
|
|
540
|
+
}
|
|
541
|
+
for (const g of facts.reviewerGuidance.slice(0, ACT2_MAX_THEMES + 2)) {
|
|
542
|
+
pushTheme(sanitizeAct2Theme(g.message));
|
|
413
543
|
if (themes.length >= ACT2_MAX_THEMES)
|
|
414
|
-
|
|
544
|
+
return themes;
|
|
415
545
|
}
|
|
416
|
-
if (themes.length < ACT2_MAX_THEMES) {
|
|
546
|
+
if (themes.length < ACT2_MAX_THEMES && !prIntelligence) {
|
|
417
547
|
for (const ctx of facts.repositoryContext) {
|
|
418
|
-
|
|
419
|
-
if (!sanitized)
|
|
420
|
-
continue;
|
|
421
|
-
const key = sanitized.toLowerCase();
|
|
422
|
-
if (seen.has(key))
|
|
423
|
-
continue;
|
|
424
|
-
seen.add(key);
|
|
425
|
-
themes.push(sanitized);
|
|
548
|
+
pushTheme(sanitizeAct2Theme(phraseForFamily(ctx.family)));
|
|
426
549
|
if (themes.length >= ACT2_MAX_THEMES)
|
|
427
550
|
break;
|
|
428
551
|
}
|
|
429
552
|
}
|
|
430
|
-
return themes;
|
|
553
|
+
return themes.slice(0, ACT2_MAX_THEMES);
|
|
431
554
|
}
|
|
432
555
|
function deriveVerdictLineFromFacts(facts, result) {
|
|
433
556
|
const topGuidance = facts.reviewerGuidance.find((g) => (g.scope === "changed" || g.kind === "insight") && g.message.trim());
|
|
@@ -450,7 +573,11 @@ export function presentScanDetailViewModel(facts, result, options) {
|
|
|
450
573
|
const themes = deriveBecauseThemesFromFacts(facts);
|
|
451
574
|
const confidenceCaveat = deriveConfidenceCaveat(result);
|
|
452
575
|
const because = themes.length > 0 || confidenceCaveat ? { themes, confidenceCaveat } : null;
|
|
453
|
-
const
|
|
576
|
+
const factsAttention = facts.availability.mode === "pr_intelligence" ||
|
|
577
|
+
facts.availability.tiersPresent.tier1
|
|
578
|
+
? buildAttentionAreasFromFacts(facts)
|
|
579
|
+
: [];
|
|
580
|
+
const attentionAreas = mergeAttentionAreas(factsAttention, buildAttentionAreas(result));
|
|
454
581
|
const allFindings = annotateFindingsWithCoverage(buildFindingRows(result), recommendedActions);
|
|
455
582
|
const topology = buildTopology(result);
|
|
456
583
|
const hasEvidence = attentionAreas.length > 0 || allFindings.length > 0 || topology != null;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
2
|
import { primaryPrExample } from "./productMessaging.js";
|
|
3
3
|
import { ACT2_MAX_THEMES, TIER1_MAX_VISIBLE_IMPACTS, deriveAct2Themes, deriveOperationalImpact, deriveFollowUpBridgeNote, deriveScanDetailViewModel, deriveVerdictLine, sanitizeAct2Theme, tier1PassesRecallTest, } from "./scanDetailViewModel.js";
|
|
4
|
+
import { fixtureRepoIntelligenceFastify } from "./fixtures/repoIntelligenceFixtures.js";
|
|
4
5
|
const baseResult = {
|
|
5
6
|
totalScore: 10,
|
|
6
7
|
layerScores: {
|
|
@@ -58,7 +59,7 @@ describe("reach vocabulary on fixtures", () => {
|
|
|
58
59
|
changedPackages: Array.from({ length: 14 }, (_, i) => `pkg-${i}`),
|
|
59
60
|
}, { scanId: "s2", status: "done" });
|
|
60
61
|
expect(vm?.verdict.scopeChip).toBe("Wide reach");
|
|
61
|
-
expect(vm?.verdict.verdictLine).toBe("No merge blockers
|
|
62
|
+
expect(vm?.verdict.verdictLine).toBe("No merge blockers - wide upgrade footprint");
|
|
62
63
|
});
|
|
63
64
|
it("needs review + limited reach — minimalResult score 42", () => {
|
|
64
65
|
const vm = deriveScanDetailViewModel(minimalResult(), {
|
|
@@ -128,6 +129,31 @@ describe("deriveVerdictLine", () => {
|
|
|
128
129
|
});
|
|
129
130
|
});
|
|
130
131
|
describe("Tier 1 success criterion", () => {
|
|
132
|
+
it("surfaces package usage paths in narrative context and evidence when corpus available", () => {
|
|
133
|
+
const vm = deriveScanDetailViewModel({
|
|
134
|
+
...baseResult,
|
|
135
|
+
changedPackages: ["fastify"],
|
|
136
|
+
analysisPreparation: { codeIntelligenceAvailable: true, warnings: [] },
|
|
137
|
+
repoIntelligence: fixtureRepoIntelligenceFastify,
|
|
138
|
+
insights: [
|
|
139
|
+
{
|
|
140
|
+
type: "usage_risk",
|
|
141
|
+
priority: "high",
|
|
142
|
+
confidence: "confirmed",
|
|
143
|
+
scope: "changed",
|
|
144
|
+
message: "Fastify middleware ordering may shift",
|
|
145
|
+
context: "",
|
|
146
|
+
remediation: "Run auth integration tests",
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
}, { scanId: "corpus", status: "done" });
|
|
150
|
+
expect(vm?.narrativeContext.usageHighlights.length).toBeGreaterThan(0);
|
|
151
|
+
expect(vm?.narrativeContext.usageContextLine).toMatch(/Used in/);
|
|
152
|
+
expect(vm?.narrativeContext.blastRadiusFactors.length).toBeGreaterThan(0);
|
|
153
|
+
const hotspotArea = vm?.evidence?.attentionAreas.find((a) => a.problemLabel.includes("hotspot"));
|
|
154
|
+
expect(hotspotArea?.packages[0]?.name).toBe("fastify");
|
|
155
|
+
expect(tier1PassesRecallTest(vm.operationalImpact)).toBe(true);
|
|
156
|
+
});
|
|
131
157
|
it("insight-rich scan passes recall test", () => {
|
|
132
158
|
const vm = deriveScanDetailViewModel({
|
|
133
159
|
...minimalResult(),
|
|
@@ -7,6 +7,13 @@ export type BlastRadiusLevel = "narrow" | "moderate" | "wide";
|
|
|
7
7
|
export type ReviewerGuidanceKind = "insight" | "finding" | "recommendation";
|
|
8
8
|
export type ReviewerGuidanceScope = "changed" | "all" | "unknown";
|
|
9
9
|
export type RepositoryContextSource = "graphInsights" | "explain" | "finding";
|
|
10
|
+
export type NarrativePackageUsage = {
|
|
11
|
+
packageName: string;
|
|
12
|
+
paths: string[];
|
|
13
|
+
criticalPaths: string[];
|
|
14
|
+
files: string[];
|
|
15
|
+
areas: string[];
|
|
16
|
+
};
|
|
10
17
|
export type ScanNarrativeFacts = {
|
|
11
18
|
availability: {
|
|
12
19
|
mode: NarrativeAvailabilityMode;
|
|
@@ -22,24 +29,26 @@ export type ScanNarrativeFacts = {
|
|
|
22
29
|
others: string[];
|
|
23
30
|
all: string[];
|
|
24
31
|
};
|
|
32
|
+
packageUsage: NarrativePackageUsage[];
|
|
33
|
+
frameworks: string[];
|
|
25
34
|
runtimeSurface: {
|
|
26
35
|
kind: RuntimeSurfaceKind;
|
|
27
|
-
evidence
|
|
28
|
-
packages
|
|
29
|
-
paths
|
|
36
|
+
evidence: {
|
|
37
|
+
packages: string[];
|
|
38
|
+
paths: string[];
|
|
30
39
|
};
|
|
31
40
|
} | null;
|
|
32
41
|
reachability: {
|
|
33
42
|
kind: ReachabilityKind;
|
|
34
|
-
evidence
|
|
35
|
-
paths
|
|
36
|
-
frameworks
|
|
43
|
+
evidence: {
|
|
44
|
+
paths: string[];
|
|
45
|
+
frameworks: string[];
|
|
37
46
|
};
|
|
38
47
|
} | null;
|
|
39
48
|
blastRadius: {
|
|
40
49
|
level: BlastRadiusLevel;
|
|
41
50
|
changedPackageCount?: number;
|
|
42
|
-
factors
|
|
51
|
+
factors: string[];
|
|
43
52
|
} | null;
|
|
44
53
|
affectedAreas: Array<{
|
|
45
54
|
id: string;
|
|
@@ -49,7 +58,7 @@ export type ScanNarrativeFacts = {
|
|
|
49
58
|
packageName: string;
|
|
50
59
|
source: "code" | "graph";
|
|
51
60
|
depth?: number;
|
|
52
|
-
paths
|
|
61
|
+
paths: string[];
|
|
53
62
|
}>;
|
|
54
63
|
reviewerGuidance: Array<{
|
|
55
64
|
kind: ReviewerGuidanceKind;
|
|
@@ -76,4 +85,8 @@ export type ScanNarrativeFacts = {
|
|
|
76
85
|
riskIndex: number | null;
|
|
77
86
|
};
|
|
78
87
|
export declare const EMPTY_SCAN_NARRATIVE_FACTS: ScanNarrativeFacts;
|
|
88
|
+
/** Derivation caps — presenters apply tighter channel limits. */
|
|
89
|
+
export declare const NARRATIVE_FACT_MAX_PATHS = 20;
|
|
90
|
+
export declare const NARRATIVE_FACT_MAX_AREAS = 12;
|
|
91
|
+
export declare const NARRATIVE_FACT_MAX_HOTSPOTS = 15;
|
|
79
92
|
//# sourceMappingURL=scanNarrativeFacts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanNarrativeFacts.d.ts","sourceRoot":"","sources":["../src/scanNarrativeFacts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAC3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,MAAM,yBAAyB,GACjC,iBAAiB,GACjB,UAAU,GACV,gBAAgB,GAChB,cAAc,CAAC;AAEnB,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAE1E,MAAM,MAAM,gBAAgB,GACxB,kBAAkB,GAClB,YAAY,GACZ,WAAW,GACX,aAAa,GACb,SAAS,CAAC;AAEd,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;AAE9D,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,SAAS,GAAG,gBAAgB,CAAC;AAE5E,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,KAAK,GAAG,SAAS,CAAC;AAElE,MAAM,MAAM,uBAAuB,GAAG,eAAe,GAAG,SAAS,GAAG,SAAS,CAAC;AAE9E,MAAM,MAAM,kBAAkB,GAAG;IAC/B,YAAY,EAAE;QACZ,IAAI,EAAE,yBAAyB,CAAC;QAChC,yBAAyB,EAAE,OAAO,CAAC;QACnC,YAAY,EAAE;YAAE,KAAK,EAAE,OAAO,CAAC;YAAC,KAAK,EAAE,OAAO,CAAC;YAAC,KAAK,EAAE,OAAO,CAAA;SAAE,CAAC;KAClE,CAAC;IAEF,eAAe,EAAE;QACf,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,GAAG,EAAE,MAAM,EAAE,CAAC;KACf,CAAC;IAEF,cAAc,EAAE;QACd,IAAI,EAAE,kBAAkB,CAAC;QACzB,QAAQ,
|
|
1
|
+
{"version":3,"file":"scanNarrativeFacts.d.ts","sourceRoot":"","sources":["../src/scanNarrativeFacts.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,8 @@ export const EMPTY_SCAN_NARRATIVE_FACTS = {
|
|
|
5
5
|
tiersPresent: { tier1: false, tier2: false, tier3: false },
|
|
6
6
|
},
|
|
7
7
|
changedPackages: { primary: null, others: [], all: [] },
|
|
8
|
+
packageUsage: [],
|
|
9
|
+
frameworks: [],
|
|
8
10
|
runtimeSurface: null,
|
|
9
11
|
reachability: null,
|
|
10
12
|
blastRadius: null,
|
|
@@ -16,3 +18,7 @@ export const EMPTY_SCAN_NARRATIVE_FACTS = {
|
|
|
16
18
|
mergePosture: null,
|
|
17
19
|
riskIndex: null,
|
|
18
20
|
};
|
|
21
|
+
/** Derivation caps — presenters apply tighter channel limits. */
|
|
22
|
+
export const NARRATIVE_FACT_MAX_PATHS = 20;
|
|
23
|
+
export const NARRATIVE_FACT_MAX_AREAS = 12;
|
|
24
|
+
export const NARRATIVE_FACT_MAX_HOTSPOTS = 15;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Single source for short scan pipeline / Actions copy (not i18n
|
|
2
|
+
* Single source for short scan pipeline / Actions copy (not i18n - keep flat and small).
|
|
3
3
|
* Risk / merge posture labels stay in riskVocabulary / MERGE_POSTURE_LABEL.
|
|
4
4
|
*/
|
|
5
5
|
export declare const scanSurfaceCopy: {
|
|
@@ -14,7 +14,7 @@ export declare const scanSurfaceCopy: {
|
|
|
14
14
|
readonly failureTitle: "MergeSignal";
|
|
15
15
|
readonly failureBody: "Analysis could not be completed. Check the workflow logs for details.";
|
|
16
16
|
readonly demoSummaryTitle: "MergeSignal (demo output)";
|
|
17
|
-
readonly demoSummaryBanner: "Sample analysis only
|
|
17
|
+
readonly demoSummaryBanner: "Sample analysis only - not production MergeSignal results. Do not use for merge decisions.";
|
|
18
18
|
readonly trustedSummaryMethodologyLine: "Methodology";
|
|
19
19
|
/** Dogfood workflow: secret missing on same-repo runs (annotation + logs). */
|
|
20
20
|
readonly trustedWorkflowSecretMissing: "Trusted MergeSignal analysis is unavailable in this repository. Complete engine access setup, then re-run the workflow.";
|
|
@@ -35,7 +35,7 @@ export declare const scanSurfaceCopy: {
|
|
|
35
35
|
readonly pushTrustedScanSkippedNoEngineToken: "Trusted MergeSignal analysis was skipped because no engine access token is configured for this repository.";
|
|
36
36
|
/** Step summary when trusted scan cannot start (canonical repo, token missing). */
|
|
37
37
|
readonly trustedWorkflowCredentialHintBody: "The engine checkout token was not available to this workflow run. Add it under this repository's Actions secrets, or grant this repository access to an organization secret. Secrets that exist only on a GitHub Environment are not available here unless this job declares that environment.";
|
|
38
|
-
/** Trusted step summary H1 product line (before posture
|
|
38
|
+
/** Trusted step summary H1 product line (before posture | risk index). */
|
|
39
39
|
readonly trustedStepSummaryTitlePrefix: "MergeSignal dependency review";
|
|
40
40
|
/** GitHub Actions step summary: risk index direction (shared with web/CLI where imported). */
|
|
41
41
|
readonly riskIndexDirectionShort: "0 = lowest merge risk, 100 = highest merge risk";
|
|
@@ -43,13 +43,13 @@ export declare const scanSurfaceCopy: {
|
|
|
43
43
|
readonly mergePostureUnavailableShort: "Posture unavailable";
|
|
44
44
|
readonly mergePostureUnavailableDetail: "This scan did not include a merge posture verdict; use the risk index as a coarse signal only.";
|
|
45
45
|
/** `<summary>` lines for collapsible sections (keep short for GitHub UI). */
|
|
46
|
-
readonly scoreBreakdownDetailsSummary: "Layer scores
|
|
46
|
+
readonly scoreBreakdownDetailsSummary: "Layer scores - this scan";
|
|
47
47
|
readonly dependencyGraphDetailsSummary: "Graph context";
|
|
48
48
|
readonly moreActionsDetailsSummary: "More guidance";
|
|
49
49
|
readonly moreInsightsDetailsSummary: "More insights";
|
|
50
50
|
/** Inside dependency graph `<details>`. */
|
|
51
|
-
readonly supportingGraphContextNote: "Supporting context
|
|
52
|
-
readonly layerScoreGlossary: "*Higher column scores = more risk in that dimension (0 best
|
|
51
|
+
readonly supportingGraphContextNote: "Supporting context - not a merge verdict by itself.";
|
|
52
|
+
readonly layerScoreGlossary: "*Higher column scores = more risk in that dimension (0 best ??? 100 worst).*";
|
|
53
53
|
/** After layer table: scan-specific drivers from explain/contributions. */
|
|
54
54
|
readonly layerDriversHeading: "Signals behind elevated scores";
|
|
55
55
|
/** When surfacing recommendation rationale first (trusted default fold). */
|
|
@@ -58,7 +58,7 @@ export declare const scanSurfaceCopy: {
|
|
|
58
58
|
/** Development profile: no recommendations or actionable insights. */
|
|
59
59
|
readonly devNoImmediateActions: "No immediate actions required";
|
|
60
60
|
};
|
|
61
|
-
/** GitHub App Check Run (PR)
|
|
61
|
+
/** GitHub App Check Run (PR) - calm, concise; not Actions step summary. */
|
|
62
62
|
readonly checkRun: {
|
|
63
63
|
readonly titleBase: "PR dependency change";
|
|
64
64
|
readonly titleBaselineSuffix: "baseline scan only";
|
|
@@ -73,9 +73,9 @@ export declare const scanSurfaceCopy: {
|
|
|
73
73
|
};
|
|
74
74
|
readonly product: {
|
|
75
75
|
/** Single line for UI/CLI/Actions parity (risk index semantics). */
|
|
76
|
-
readonly riskIndexDirectionShort: "0 is best
|
|
76
|
+
readonly riskIndexDirectionShort: "0 is best | 100 is worst";
|
|
77
77
|
};
|
|
78
|
-
/** Scan detail page (`/scan/[id]`)
|
|
78
|
+
/** Scan detail page (`/scan/[id]`) - show-don't-teach reviewer copy. */
|
|
79
79
|
readonly scanDetail: {
|
|
80
80
|
readonly recommendedActionsHeading: "Recommended actions";
|
|
81
81
|
readonly signalSummaryHeading: "Signal summary";
|
|
@@ -88,7 +88,7 @@ export declare const scanSurfaceCopy: {
|
|
|
88
88
|
readonly proofHeading: "Proof";
|
|
89
89
|
readonly nextStepsHeading: "Recommended next steps";
|
|
90
90
|
readonly topologySummary: "Dependency topology";
|
|
91
|
-
readonly topologyCollapsedHint: "Supporting detail
|
|
91
|
+
readonly topologyCollapsedHint: "Supporting detail - graph paths and depth";
|
|
92
92
|
readonly whereLabel: "Where";
|
|
93
93
|
readonly verifyLabel: "Verify";
|
|
94
94
|
readonly moreImpactsSummary: "More impacts";
|
|
@@ -101,15 +101,15 @@ export declare const scanSurfaceCopy: {
|
|
|
101
101
|
readonly wide: "Wide reach";
|
|
102
102
|
};
|
|
103
103
|
readonly verdictLine: {
|
|
104
|
-
readonly safeNoBlockersNarrow: "No merge blockers
|
|
105
|
-
readonly safeNoBlockersModerate: "No merge blockers
|
|
106
|
-
readonly safeNoBlockersWide: "No merge blockers
|
|
107
|
-
readonly reviewBeforeMergeNarrow: "Review before merge
|
|
108
|
-
readonly reviewBeforeMergeModerate: "Review before merge
|
|
109
|
-
readonly reviewBeforeMergeWide: "Review before merge
|
|
110
|
-
readonly riskyResolveNarrow: "Resolve blockers before merge
|
|
111
|
-
readonly riskyResolveModerate: "Resolve blockers before merge
|
|
112
|
-
readonly riskyResolveWide: "Resolve blockers before merge
|
|
104
|
+
readonly safeNoBlockersNarrow: "No merge blockers - narrow footprint";
|
|
105
|
+
readonly safeNoBlockersModerate: "No merge blockers - moderate dependency footprint";
|
|
106
|
+
readonly safeNoBlockersWide: "No merge blockers - wide upgrade footprint";
|
|
107
|
+
readonly reviewBeforeMergeNarrow: "Review before merge - narrow footprint";
|
|
108
|
+
readonly reviewBeforeMergeModerate: "Review before merge - moderate dependency footprint";
|
|
109
|
+
readonly reviewBeforeMergeWide: "Review before merge - wide dependency footprint";
|
|
110
|
+
readonly riskyResolveNarrow: "Resolve blockers before merge - focused footprint";
|
|
111
|
+
readonly riskyResolveModerate: "Resolve blockers before merge - moderate dependency footprint";
|
|
112
|
+
readonly riskyResolveWide: "Resolve blockers before merge - wide transitive tree";
|
|
113
113
|
};
|
|
114
114
|
readonly tier1Fallback: {
|
|
115
115
|
/** Graph-only / lightweight PR baseline (pattern F3). */
|
|
@@ -123,9 +123,9 @@ export declare const scanSurfaceCopy: {
|
|
|
123
123
|
};
|
|
124
124
|
readonly confidenceCaveat: {
|
|
125
125
|
readonly medium: "Based on partial dependency signal";
|
|
126
|
-
readonly low: "Limited signal
|
|
126
|
+
readonly low: "Limited signal - treat this as directional";
|
|
127
127
|
};
|
|
128
|
-
readonly codeAnalysisTimeout: "Code analysis timed out
|
|
128
|
+
readonly codeAnalysisTimeout: "Code analysis timed out - runtime impact may be incomplete";
|
|
129
129
|
readonly scanPipelineNote: "This page updates automatically.";
|
|
130
130
|
readonly recommendationDetail: {
|
|
131
131
|
readonly selectPrompt: "Select a recommendation to understand it";
|
|
@@ -189,7 +189,7 @@ export declare const scanSurfaceCopy: {
|
|
|
189
189
|
readonly why: "Dependency health is stable now but benefits from ongoing observation.";
|
|
190
190
|
readonly whyNow: "Monitoring catches regressions that appear only after merge.";
|
|
191
191
|
readonly expectedBenefit: "Earlier detection of dependency regressions in production.";
|
|
192
|
-
readonly signals: readonly ["No immediate blockers
|
|
192
|
+
readonly signals: readonly ["No immediate blockers - monitor after merge"];
|
|
193
193
|
};
|
|
194
194
|
readonly mergeAfterVerification: {
|
|
195
195
|
readonly why: "Wide upgrade footprints warrant a quick sanity check before merge.";
|
|
@@ -249,7 +249,7 @@ export declare const scanSurfaceCopy: {
|
|
|
249
249
|
readonly signalSummary: {
|
|
250
250
|
readonly scoreCaption: "Dependency signal score";
|
|
251
251
|
readonly layersHeading: "Layer signals";
|
|
252
|
-
readonly gaugeAriaLabel: "Dependency signal score {score}
|
|
252
|
+
readonly gaugeAriaLabel: "Dependency signal score {score} - {band}";
|
|
253
253
|
readonly followUpImprovementIdentified: "1 follow-up improvement was identified";
|
|
254
254
|
readonly followUpImprovementsIdentified: "{count} follow-up improvements were identified";
|
|
255
255
|
readonly bandLabel: {
|
|
@@ -264,7 +264,7 @@ export declare const scanSurfaceCopy: {
|
|
|
264
264
|
};
|
|
265
265
|
};
|
|
266
266
|
};
|
|
267
|
-
/** PR narrative presentation
|
|
267
|
+
/** PR narrative presentation - channel-specific copy built from ScanNarrativeFacts. */
|
|
268
268
|
readonly narrativeCard: {
|
|
269
269
|
readonly structuralOnlyDisclaimer: "Structural dependency analysis only";
|
|
270
270
|
readonly runtimeSurface: {
|
|
@@ -285,8 +285,8 @@ export declare const scanSurfaceCopy: {
|
|
|
285
285
|
readonly moderate: "Moderate";
|
|
286
286
|
readonly wide: "Wide";
|
|
287
287
|
};
|
|
288
|
-
readonly areasSeparator: "
|
|
289
|
-
readonly contextSeparator: "
|
|
288
|
+
readonly areasSeparator: " | ";
|
|
289
|
+
readonly contextSeparator: " | ";
|
|
290
290
|
};
|
|
291
291
|
readonly cli: {
|
|
292
292
|
readonly stderrAnalysisIncomplete: "Analysis could not be completed.";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanSurfaceCopy.d.ts","sourceRoot":"","sources":["../src/scanSurfaceCopy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;QAgBxB,8EAA8E;;QAG9E,6DAA6D;;;;QAO7D,qDAAqD;;;;;QASrD,mEAAmE;;;;QAOnE,yFAAyF;;QAGzF,mFAAmF;;QAGnF,
|
|
1
|
+
{"version":3,"file":"scanSurfaceCopy.d.ts","sourceRoot":"","sources":["../src/scanSurfaceCopy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;QAgBxB,8EAA8E;;QAG9E,6DAA6D;;;;QAO7D,qDAAqD;;;;;QASrD,mEAAmE;;;;QAOnE,yFAAyF;;QAGzF,mFAAmF;;QAGnF,4EAA4E;;QAE5E,8FAA8F;;QAE9F,+DAA+D;;;QAI/D,6EAA6E;;;;;QAK7E,2CAA2C;;;QAK3C,2EAA2E;;QAE3E,4EAA4E;;;QAI5E,sEAAsE;;;IAGxE,2EAA2E;;;;;;;;;;;;;;QAiBzE,oEAAoE;;;IAGtE,wEAAwE;;;;;;QAOtE,2CAA2C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAkCzC,yDAAyD;;YAGzD,mDAAmD;;YAGnD,8BAA8B;;YAE9B,oDAAoD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA4CtD,6CAA6C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAsI/C,uFAAuF;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA4BvF,sEAAsE;;;;;CAO9D,CAAC;AAEX,iEAAiE;AACjE,wBAAgB,mBAAmB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAa5D"}
|