@mergesignal/shared 0.2.3 → 0.2.5
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 +37 -0
- package/dist/deriveRiskScoreSummary.d.ts +33 -0
- package/dist/deriveRiskScoreSummary.d.ts.map +1 -0
- package/dist/deriveRiskScoreSummary.js +90 -0
- package/dist/deriveRiskScoreSummary.test.d.ts +2 -0
- package/dist/deriveRiskScoreSummary.test.d.ts.map +1 -0
- package/dist/deriveRiskScoreSummary.test.js +47 -0
- package/dist/deriveScanDetailRecommendations.d.ts +63 -0
- package/dist/deriveScanDetailRecommendations.d.ts.map +1 -0
- package/dist/deriveScanDetailRecommendations.js +725 -0
- package/dist/deriveScanDetailRecommendations.test.d.ts +2 -0
- package/dist/deriveScanDetailRecommendations.test.d.ts.map +1 -0
- package/dist/deriveScanDetailRecommendations.test.js +181 -0
- package/dist/formatCardExposureDisplay.d.ts +4 -0
- package/dist/formatCardExposureDisplay.d.ts.map +1 -1
- package/dist/formatCardExposureDisplay.js +15 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/scanDetailViewModel.d.ts +108 -0
- package/dist/scanDetailViewModel.d.ts.map +1 -0
- package/dist/scanDetailViewModel.js +420 -0
- package/dist/scanDetailViewModel.test.d.ts +2 -0
- package/dist/scanDetailViewModel.test.d.ts.map +1 -0
- package/dist/scanDetailViewModel.test.js +503 -0
- package/dist/scanSurfaceCopy.d.ts +187 -0
- package/dist/scanSurfaceCopy.d.ts.map +1 -1
- package/dist/scanSurfaceCopy.js +190 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# @mergesignal/shared
|
|
2
|
+
|
|
3
|
+
Published npm package containing the MergeSignal **scan contract**, presentation policy, and trusted-output validation.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install @mergesignal/shared
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
**Current version:** see [package.json](./package.json). Pin exact semver in downstream consumers (especially the proprietary analysis engine).
|
|
10
|
+
|
|
11
|
+
## What it provides
|
|
12
|
+
|
|
13
|
+
- **Types and schemas** for `ScanRequest`, `ScanResult`, upgrade simulation, and related wire formats
|
|
14
|
+
- **Validation** for scan results and trusted CI output guards
|
|
15
|
+
- **Presentation copy** helpers used by the web app and CI summary renderers
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import {} from /* types, validators, copy */ "@mergesignal/shared";
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
See `dist/index.d.ts` after install for the full export surface.
|
|
24
|
+
|
|
25
|
+
## OSS monorepo vs npm
|
|
26
|
+
|
|
27
|
+
Inside this repository, apps use the workspace package via `pnpm`. External consumers (e.g. `mergesignal-engine`) install from the **public npm registry** with an exact version pin.
|
|
28
|
+
|
|
29
|
+
## License
|
|
30
|
+
|
|
31
|
+
MIT — see [LICENSE](../../LICENSE) for the monorepo; npm package license field in `package.json`.
|
|
32
|
+
|
|
33
|
+
## More
|
|
34
|
+
|
|
35
|
+
- [Engine stub](../engine-stub/README.md) — OSS boundary
|
|
36
|
+
- [GitHub Actions integration](../../.github/actions/merge-signal-scan/README.md)
|
|
37
|
+
- Maintainer release process: [docs/engineering/releasing.md](../../docs/engineering/releasing.md)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ScanResult, ScoreLayer } from "./types.js";
|
|
2
|
+
export declare const SCAN_DETAIL_RISK_BAND_MODERATE_MIN = 40;
|
|
3
|
+
export declare const SCAN_DETAIL_RISK_BAND_HIGH_MIN = 80;
|
|
4
|
+
export type ScanDetailOverallRiskBand = "low" | "moderate" | "high";
|
|
5
|
+
export type ScanDetailLayerConcernLevel = "low" | "medium" | "high";
|
|
6
|
+
export type ScanDetailSignalLayer = {
|
|
7
|
+
layer: ScoreLayer;
|
|
8
|
+
label: string;
|
|
9
|
+
score: number;
|
|
10
|
+
concernLevel: ScanDetailLayerConcernLevel;
|
|
11
|
+
concernLabel: string;
|
|
12
|
+
};
|
|
13
|
+
/** @deprecated Use ScanDetailSignalLayer */
|
|
14
|
+
export type ScanDetailRiskLayer = ScanDetailSignalLayer;
|
|
15
|
+
export type RiskScoreGaugeModel = {
|
|
16
|
+
fillPercent: number;
|
|
17
|
+
band: ScanDetailOverallRiskBand;
|
|
18
|
+
ariaLabel: string;
|
|
19
|
+
};
|
|
20
|
+
export type ScanDetailSignalSummary = {
|
|
21
|
+
score: number;
|
|
22
|
+
overallBand: ScanDetailOverallRiskBand;
|
|
23
|
+
overallLabel: string;
|
|
24
|
+
gauge: RiskScoreGaugeModel;
|
|
25
|
+
layers: ScanDetailSignalLayer[];
|
|
26
|
+
};
|
|
27
|
+
/** @deprecated Use ScanDetailSignalSummary */
|
|
28
|
+
export type ScanDetailRiskSummary = ScanDetailSignalSummary;
|
|
29
|
+
export declare function deriveOverallRiskBand(score: number | null | undefined): ScanDetailOverallRiskBand;
|
|
30
|
+
export declare function overallSignalBandLabel(band: ScanDetailOverallRiskBand): string;
|
|
31
|
+
export declare function deriveRiskScoreGauge(score: number, band: ScanDetailOverallRiskBand): RiskScoreGaugeModel;
|
|
32
|
+
export declare function deriveSignalSummary(result: ScanResult): ScanDetailSignalSummary | null;
|
|
33
|
+
//# sourceMappingURL=deriveRiskScoreSummary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deriveRiskScoreSummary.d.ts","sourceRoot":"","sources":["../src/deriveRiskScoreSummary.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEzD,eAAO,MAAM,kCAAkC,KAAK,CAAC;AACrD,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAgBjD,MAAM,MAAM,yBAAyB,GAAG,KAAK,GAAG,UAAU,GAAG,MAAM,CAAC;AACpE,MAAM,MAAM,2BAA2B,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEpE,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,UAAU,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,2BAA2B,CAAC;IAC1C,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,4CAA4C;AAC5C,MAAM,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;AAExD,MAAM,MAAM,mBAAmB,GAAG;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,yBAAyB,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,yBAAyB,CAAC;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,MAAM,EAAE,qBAAqB,EAAE,CAAC;CACjC,CAAC;AAEF,8CAA8C;AAC9C,MAAM,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AAO5D,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC/B,yBAAyB,CAM3B;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,yBAAyB,GAC9B,MAAM,CAKR;AAgBD,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,yBAAyB,GAC9B,mBAAmB,CASrB;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,GACjB,uBAAuB,GAAG,IAAI,CAoChC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { layerRiskBandLabel } from "./actionsStepSummary.js";
|
|
2
|
+
import { scanSurfaceCopy } from "./scanSurfaceCopy.js";
|
|
3
|
+
export const SCAN_DETAIL_RISK_BAND_MODERATE_MIN = 40;
|
|
4
|
+
export const SCAN_DETAIL_RISK_BAND_HIGH_MIN = 80;
|
|
5
|
+
const LAYER_ORDER = [
|
|
6
|
+
"security",
|
|
7
|
+
"maintainability",
|
|
8
|
+
"ecosystem",
|
|
9
|
+
"upgradeImpact",
|
|
10
|
+
];
|
|
11
|
+
const LAYER_LABEL = {
|
|
12
|
+
security: "Security",
|
|
13
|
+
maintainability: "Maintainability",
|
|
14
|
+
ecosystem: "Ecosystem",
|
|
15
|
+
upgradeImpact: "Upgrade Impact",
|
|
16
|
+
};
|
|
17
|
+
function clampScore(score) {
|
|
18
|
+
if (!Number.isFinite(score))
|
|
19
|
+
return 0;
|
|
20
|
+
return Math.max(0, Math.min(100, Math.round(score)));
|
|
21
|
+
}
|
|
22
|
+
export function deriveOverallRiskBand(score) {
|
|
23
|
+
if (score == null || !Number.isFinite(score))
|
|
24
|
+
return "low";
|
|
25
|
+
const value = clampScore(score);
|
|
26
|
+
if (value >= SCAN_DETAIL_RISK_BAND_HIGH_MIN)
|
|
27
|
+
return "high";
|
|
28
|
+
if (value >= SCAN_DETAIL_RISK_BAND_MODERATE_MIN)
|
|
29
|
+
return "moderate";
|
|
30
|
+
return "low";
|
|
31
|
+
}
|
|
32
|
+
export function overallSignalBandLabel(band) {
|
|
33
|
+
const copy = scanSurfaceCopy.scanDetail.signalSummary.bandLabel;
|
|
34
|
+
if (band === "high")
|
|
35
|
+
return copy.high;
|
|
36
|
+
if (band === "moderate")
|
|
37
|
+
return copy.moderate;
|
|
38
|
+
return copy.low;
|
|
39
|
+
}
|
|
40
|
+
function layerBandToSignal(band) {
|
|
41
|
+
const copy = scanSurfaceCopy.scanDetail.signalSummary.signalLabel;
|
|
42
|
+
if (band === "High") {
|
|
43
|
+
return { level: "high", label: copy.high };
|
|
44
|
+
}
|
|
45
|
+
if (band === "Moderate") {
|
|
46
|
+
return { level: "medium", label: copy.medium };
|
|
47
|
+
}
|
|
48
|
+
return { level: "low", label: copy.low };
|
|
49
|
+
}
|
|
50
|
+
export function deriveRiskScoreGauge(score, band) {
|
|
51
|
+
const clamped = clampScore(score);
|
|
52
|
+
return {
|
|
53
|
+
fillPercent: clamped,
|
|
54
|
+
band,
|
|
55
|
+
ariaLabel: scanSurfaceCopy.scanDetail.signalSummary.gaugeAriaLabel
|
|
56
|
+
.replace("{score}", String(clamped))
|
|
57
|
+
.replace("{band}", overallSignalBandLabel(band)),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export function deriveSignalSummary(result) {
|
|
61
|
+
if (typeof result.totalScore !== "number" ||
|
|
62
|
+
!Number.isFinite(result.totalScore)) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
const score = clampScore(result.totalScore);
|
|
66
|
+
const overallBand = deriveOverallRiskBand(score);
|
|
67
|
+
const overallLabel = overallSignalBandLabel(overallBand);
|
|
68
|
+
const gauge = deriveRiskScoreGauge(score, overallBand);
|
|
69
|
+
const layers = LAYER_ORDER.map((layer) => {
|
|
70
|
+
const layerScore = typeof result.layerScores?.[layer] === "number"
|
|
71
|
+
? clampScore(result.layerScores[layer])
|
|
72
|
+
: 0;
|
|
73
|
+
const band = layerRiskBandLabel(layerScore);
|
|
74
|
+
const signal = layerBandToSignal(band);
|
|
75
|
+
return {
|
|
76
|
+
layer,
|
|
77
|
+
label: LAYER_LABEL[layer],
|
|
78
|
+
score: layerScore,
|
|
79
|
+
concernLevel: signal.level,
|
|
80
|
+
concernLabel: signal.label,
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
return {
|
|
84
|
+
score,
|
|
85
|
+
overallBand,
|
|
86
|
+
overallLabel,
|
|
87
|
+
gauge,
|
|
88
|
+
layers,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deriveRiskScoreSummary.test.d.ts","sourceRoot":"","sources":["../src/deriveRiskScoreSummary.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { deriveOverallRiskBand, deriveSignalSummary, SCAN_DETAIL_RISK_BAND_HIGH_MIN, SCAN_DETAIL_RISK_BAND_MODERATE_MIN, } from "./deriveRiskScoreSummary.js";
|
|
3
|
+
const baseResult = {
|
|
4
|
+
totalScore: 71,
|
|
5
|
+
layerScores: {
|
|
6
|
+
security: 80,
|
|
7
|
+
maintainability: 65,
|
|
8
|
+
ecosystem: 55,
|
|
9
|
+
upgradeImpact: 70,
|
|
10
|
+
},
|
|
11
|
+
findings: [],
|
|
12
|
+
generatedAt: "2026-01-01T00:00:00.000Z",
|
|
13
|
+
};
|
|
14
|
+
describe("deriveOverallRiskBand", () => {
|
|
15
|
+
it("uses 40/80 thresholds", () => {
|
|
16
|
+
expect(SCAN_DETAIL_RISK_BAND_MODERATE_MIN).toBe(40);
|
|
17
|
+
expect(SCAN_DETAIL_RISK_BAND_HIGH_MIN).toBe(80);
|
|
18
|
+
expect(deriveOverallRiskBand(39)).toBe("low");
|
|
19
|
+
expect(deriveOverallRiskBand(40)).toBe("moderate");
|
|
20
|
+
expect(deriveOverallRiskBand(71)).toBe("moderate");
|
|
21
|
+
expect(deriveOverallRiskBand(79)).toBe("moderate");
|
|
22
|
+
expect(deriveOverallRiskBand(80)).toBe("high");
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
describe("deriveSignalSummary", () => {
|
|
26
|
+
it("returns moderate band for score 71 on safe posture", () => {
|
|
27
|
+
const summary = deriveSignalSummary({
|
|
28
|
+
...baseResult,
|
|
29
|
+
decision: { recommendation: "safe", confidence: "high", reasoning: [] },
|
|
30
|
+
});
|
|
31
|
+
expect(summary?.score).toBe(71);
|
|
32
|
+
expect(summary?.overallBand).toBe("moderate");
|
|
33
|
+
expect(summary?.overallLabel).toBe("Moderate");
|
|
34
|
+
expect(summary?.gauge.fillPercent).toBe(71);
|
|
35
|
+
});
|
|
36
|
+
it("returns null when totalScore is missing", () => {
|
|
37
|
+
expect(deriveSignalSummary({
|
|
38
|
+
...baseResult,
|
|
39
|
+
totalScore: Number.NaN,
|
|
40
|
+
})).toBeNull();
|
|
41
|
+
});
|
|
42
|
+
it("uses short signal labels on layer rows", () => {
|
|
43
|
+
const summary = deriveSignalSummary(baseResult);
|
|
44
|
+
expect(summary?.layers).toHaveLength(4);
|
|
45
|
+
expect(summary?.layers[0]?.concernLabel).toBe("Elevated");
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type ObservationSignalFamily } from "./cardObservationCatalog.js";
|
|
2
|
+
import { type MergePosture } from "./riskVocabulary.js";
|
|
3
|
+
import type { ScanResult } from "./types.js";
|
|
4
|
+
export declare const RECOMMENDATION_MAX_ITEMS = 3;
|
|
5
|
+
export declare const RECOMMENDATION_MAX_TITLE_CHARS = 80;
|
|
6
|
+
export declare const RECOMMENDATION_PREFER_MAX_ON_SAFE = 2;
|
|
7
|
+
export declare const RECOMMENDATION_MAX_SIGNALS = 4;
|
|
8
|
+
export declare const RECOMMENDATION_MAX_PACKAGES = 5;
|
|
9
|
+
export type RecommendationPriority = "high" | "medium" | "low";
|
|
10
|
+
/** @deprecated Use RecommendationPriority */
|
|
11
|
+
export type GuidanceUrgency = RecommendationPriority;
|
|
12
|
+
export type GuidanceSource = "insight" | "recommendation" | "signal" | "finding" | "posture_playbook";
|
|
13
|
+
export type ScanDetailRecommendationDetail = {
|
|
14
|
+
why: string;
|
|
15
|
+
whyNow: string;
|
|
16
|
+
signals: string[];
|
|
17
|
+
affectedPackages?: {
|
|
18
|
+
names: string[];
|
|
19
|
+
overflowCount: number;
|
|
20
|
+
};
|
|
21
|
+
expectedBenefit: string;
|
|
22
|
+
};
|
|
23
|
+
export type ScanDetailRecommendation = {
|
|
24
|
+
id: string;
|
|
25
|
+
rank: number;
|
|
26
|
+
title: string;
|
|
27
|
+
priority: RecommendationPriority;
|
|
28
|
+
source: GuidanceSource;
|
|
29
|
+
signalFamily?: ObservationSignalFamily | null;
|
|
30
|
+
detail: ScanDetailRecommendationDetail;
|
|
31
|
+
proofRefs?: {
|
|
32
|
+
findingIds?: string[];
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
export type ScanDetailRecommendationCenter = {
|
|
36
|
+
heading: string;
|
|
37
|
+
defaultSelectedId: string;
|
|
38
|
+
items: ScanDetailRecommendation[];
|
|
39
|
+
posture: MergePosture | null;
|
|
40
|
+
scanContext?: string;
|
|
41
|
+
};
|
|
42
|
+
/** @deprecated Use ScanDetailRecommendationCenter */
|
|
43
|
+
export type ScanDetailWhatToDo = {
|
|
44
|
+
items: Array<{
|
|
45
|
+
id: string;
|
|
46
|
+
label: string;
|
|
47
|
+
emphasis: "primary" | "secondary";
|
|
48
|
+
priority: RecommendationPriority;
|
|
49
|
+
source: GuidanceSource;
|
|
50
|
+
}>;
|
|
51
|
+
posture: MergePosture | null;
|
|
52
|
+
};
|
|
53
|
+
export declare const GUIDANCE_ACTION_FOR_FAMILY: Record<ObservationSignalFamily, string>;
|
|
54
|
+
/** Derive the scan detail recommendation center — always returns 1–3 enriched items. */
|
|
55
|
+
export declare function deriveScanDetailRecommendations(result: ScanResult): ScanDetailRecommendationCenter;
|
|
56
|
+
export declare function recommendationTitlesForDedupe(center: ScanDetailRecommendationCenter): Set<string>;
|
|
57
|
+
export declare function findingIdsCoveredByRecommendations(center: ScanDetailRecommendationCenter): Set<string>;
|
|
58
|
+
export declare function verifyLabelsForDedupe(center: ScanDetailRecommendationCenter): Set<string>;
|
|
59
|
+
/** @deprecated Use deriveScanDetailRecommendations */
|
|
60
|
+
export declare function deriveScanDetailGuidance(result: ScanResult): ScanDetailWhatToDo;
|
|
61
|
+
/** @deprecated Use recommendationTitlesForDedupe */
|
|
62
|
+
export declare function guidanceLabelsForDedupe(whatToDo: ScanDetailWhatToDo): Set<string>;
|
|
63
|
+
//# sourceMappingURL=deriveScanDetailRecommendations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deriveScanDetailRecommendations.d.ts","sourceRoot":"","sources":["../src/deriveScanDetailRecommendations.ts"],"names":[],"mappings":"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"}
|