@mergesignal/shared 0.2.2 → 0.2.3
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/cardObservationCatalog.d.ts +55 -0
- package/dist/cardObservationCatalog.d.ts.map +1 -0
- package/dist/cardObservationCatalog.js +320 -0
- package/dist/cardSummaryCopy.d.ts +12 -0
- package/dist/cardSummaryCopy.d.ts.map +1 -0
- package/dist/cardSummaryCopy.js +36 -0
- package/dist/deriveCardDisplaySummary.d.ts +16 -0
- package/dist/deriveCardDisplaySummary.d.ts.map +1 -0
- package/dist/deriveCardDisplaySummary.js +56 -0
- package/dist/deriveCardDisplaySummary.test.d.ts +2 -0
- package/dist/deriveCardDisplaySummary.test.d.ts.map +1 -0
- package/dist/deriveCardDisplaySummary.test.js +89 -0
- package/dist/deriveCardOperationalObservations.d.ts +19 -0
- package/dist/deriveCardOperationalObservations.d.ts.map +1 -0
- package/dist/deriveCardOperationalObservations.js +180 -0
- package/dist/deriveCardOperationalObservations.test.d.ts +2 -0
- package/dist/deriveCardOperationalObservations.test.d.ts.map +1 -0
- package/dist/deriveCardOperationalObservations.test.js +268 -0
- package/dist/formatCardAreaLabels.d.ts +8 -0
- package/dist/formatCardAreaLabels.d.ts.map +1 -0
- package/dist/formatCardAreaLabels.js +65 -0
- package/dist/formatCardEvidenceCounts.d.ts +7 -0
- package/dist/formatCardEvidenceCounts.d.ts.map +1 -0
- package/dist/formatCardEvidenceCounts.js +19 -0
- package/dist/formatCardExposureDisplay.d.ts +20 -0
- package/dist/formatCardExposureDisplay.d.ts.map +1 -0
- package/dist/formatCardExposureDisplay.js +56 -0
- package/dist/formatCardExposureDisplay.test.d.ts +2 -0
- package/dist/formatCardExposureDisplay.test.d.ts.map +1 -0
- package/dist/formatCardExposureDisplay.test.js +36 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/productMessaging.d.ts +85 -0
- package/dist/productMessaging.d.ts.map +1 -0
- package/dist/productMessaging.js +109 -0
- package/dist/productMessaging.test.d.ts +2 -0
- package/dist/productMessaging.test.d.ts.map +1 -0
- package/dist/productMessaging.test.js +97 -0
- package/dist/riskVocabulary.d.ts +8 -2
- package/dist/riskVocabulary.d.ts.map +1 -1
- package/dist/riskVocabulary.js +26 -9
- package/dist/scanCardSummary.d.ts +9 -0
- package/dist/scanCardSummary.d.ts.map +1 -1
- package/dist/scanCardSummary.js +19 -29
- package/dist/scanCardSummary.test.js +45 -8
- package/dist/truncateCardSummary.d.ts +5 -0
- package/dist/truncateCardSummary.d.ts.map +1 -0
- package/dist/truncateCardSummary.js +23 -0
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { isCatalogPhrase } from "./cardObservationCatalog.js";
|
|
2
3
|
import { aggregateFindingCounts, deriveRiskIndexBand, deriveScanCardSummary, deriveScanCardSummaryFromDenormalized, isPipelineCardSummary, isPipelinePlaceholderCopy, resolvePipelineStatus, resolvePrScanCardSummary, staleScanSubline, } from "./scanCardSummary.js";
|
|
3
4
|
const baseResult = {
|
|
4
5
|
totalScore: 10,
|
|
@@ -71,15 +72,26 @@ describe("deriveScanCardSummary", () => {
|
|
|
71
72
|
confidence: "high",
|
|
72
73
|
reasoning: ["Auth boundary change"],
|
|
73
74
|
},
|
|
75
|
+
explain: {
|
|
76
|
+
reasons: [
|
|
77
|
+
{
|
|
78
|
+
id: "upgrade.1",
|
|
79
|
+
layer: "upgradeImpact",
|
|
80
|
+
title: "Large upgrade blast radius",
|
|
81
|
+
scoreImpact: 20,
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
},
|
|
74
85
|
};
|
|
75
86
|
const summary = deriveScanCardSummary(r, "done");
|
|
76
87
|
expect(summary.mergePosture).toBe("risky");
|
|
77
88
|
expect(summary.headline).toBe("Risky");
|
|
78
89
|
expect(summary.riskIndex).toBe(72);
|
|
79
90
|
expect(summary.riskIndexBand).toBe("high");
|
|
80
|
-
expect(summary.summaryLine).
|
|
91
|
+
expect(summary.summaryLine).toBeNull();
|
|
92
|
+
expect(summary.operationalObservations).toContain("Large upgrade blast radius");
|
|
81
93
|
});
|
|
82
|
-
it("
|
|
94
|
+
it("keeps quiet safe cards posture-only without observations", () => {
|
|
83
95
|
const r = {
|
|
84
96
|
...baseResult,
|
|
85
97
|
totalScore: 12,
|
|
@@ -90,9 +102,10 @@ describe("deriveScanCardSummary", () => {
|
|
|
90
102
|
},
|
|
91
103
|
};
|
|
92
104
|
const summary = deriveScanCardSummary(r, "done");
|
|
93
|
-
expect(summary.summaryLine).
|
|
105
|
+
expect(summary.summaryLine).toBeNull();
|
|
106
|
+
expect(summary.operationalObservations).toEqual([]);
|
|
94
107
|
});
|
|
95
|
-
it("
|
|
108
|
+
it("surfaces catalog observations from explain signals", () => {
|
|
96
109
|
const r = {
|
|
97
110
|
...baseResult,
|
|
98
111
|
decision: {
|
|
@@ -102,14 +115,28 @@ describe("deriveScanCardSummary", () => {
|
|
|
102
115
|
},
|
|
103
116
|
explain: {
|
|
104
117
|
reasons: [
|
|
105
|
-
{
|
|
106
|
-
|
|
118
|
+
{
|
|
119
|
+
id: "1",
|
|
120
|
+
layer: "ecosystem",
|
|
121
|
+
title: "graph.transitive volume",
|
|
122
|
+
scoreImpact: 18,
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
id: "2",
|
|
126
|
+
layer: "ecosystem",
|
|
127
|
+
title: "graph.duplicates",
|
|
128
|
+
scoreImpact: 12,
|
|
129
|
+
},
|
|
107
130
|
{ id: "3", layer: "security", title: "C", scoreImpact: -8 },
|
|
108
131
|
],
|
|
109
132
|
},
|
|
110
133
|
};
|
|
111
134
|
const summary = deriveScanCardSummary(r, "done");
|
|
112
135
|
expect(summary.topAffectedAreas).toHaveLength(2);
|
|
136
|
+
expect(summary.operationalObservations.length).toBeGreaterThan(0);
|
|
137
|
+
for (const phrase of summary.operationalObservations) {
|
|
138
|
+
expect(isCatalogPhrase(phrase)).toBe(true);
|
|
139
|
+
}
|
|
113
140
|
});
|
|
114
141
|
it("exports stale subline constant", () => {
|
|
115
142
|
expect(staleScanSubline()).toBe("Based on earlier commit");
|
|
@@ -149,6 +176,8 @@ describe("isPipelineCardSummary", () => {
|
|
|
149
176
|
summaryLine: "Waiting for results…",
|
|
150
177
|
findingCounts: null,
|
|
151
178
|
topAffectedAreas: [],
|
|
179
|
+
operationalObservations: [],
|
|
180
|
+
supportingLine: null,
|
|
152
181
|
})).toBe(true);
|
|
153
182
|
});
|
|
154
183
|
it("detects hybrid completed posture with pipeline summary line", () => {
|
|
@@ -160,6 +189,8 @@ describe("isPipelineCardSummary", () => {
|
|
|
160
189
|
summaryLine: "Waiting for results…",
|
|
161
190
|
findingCounts: null,
|
|
162
191
|
topAffectedAreas: [],
|
|
192
|
+
operationalObservations: [],
|
|
193
|
+
supportingLine: null,
|
|
163
194
|
})).toBe(true);
|
|
164
195
|
});
|
|
165
196
|
});
|
|
@@ -170,18 +201,24 @@ describe("isPipelinePlaceholderCopy", () => {
|
|
|
170
201
|
});
|
|
171
202
|
});
|
|
172
203
|
describe("deriveScanCardSummaryFromDenormalized", () => {
|
|
173
|
-
it("builds risky summary from denormalized columns", () => {
|
|
204
|
+
it("builds risky summary from denormalized columns without generic narration", () => {
|
|
174
205
|
const summary = deriveScanCardSummaryFromDenormalized("risky", 72, "Auth boundary change", "done");
|
|
175
206
|
expect(summary.mergePosture).toBe("risky");
|
|
176
207
|
expect(summary.headline).toBe("Risky");
|
|
177
208
|
expect(summary.riskIndex).toBe(72);
|
|
178
|
-
expect(summary.summaryLine).
|
|
209
|
+
expect(summary.summaryLine).toBeNull();
|
|
210
|
+
expect(summary.operationalObservations).toEqual([]);
|
|
179
211
|
});
|
|
180
212
|
it("does not inject pipeline placeholder summaryText", () => {
|
|
181
213
|
const summary = deriveScanCardSummaryFromDenormalized("risky", 72, "Waiting for results…", "done");
|
|
182
214
|
expect(summary.mergePosture).toBe("risky");
|
|
183
215
|
expect(summary.summaryLine).not.toBe("Waiting for results…");
|
|
184
216
|
});
|
|
217
|
+
it("does not inject raw generic summaryText on quiet safe cards", () => {
|
|
218
|
+
const summary = deriveScanCardSummaryFromDenormalized("safe", 12, "No high-confidence merge risks from this PR dependency change", "done");
|
|
219
|
+
expect(summary.mergePosture).toBe("safe");
|
|
220
|
+
expect(summary.summaryLine).toBeNull();
|
|
221
|
+
});
|
|
185
222
|
});
|
|
186
223
|
describe("resolvePrScanCardSummary", () => {
|
|
187
224
|
it("returns risk summary when wire status is running but decision exists", () => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncateCardSummary.d.ts","sourceRoot":"","sources":["../src/truncateCardSummary.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,MAAoB,GAC3B,MAAM,CA+BR"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic truncation for dashboard card summaries (~90 chars default).
|
|
3
|
+
*/
|
|
4
|
+
const DEFAULT_MAX = 90;
|
|
5
|
+
export function truncateCardSummary(text, maxLen = DEFAULT_MAX) {
|
|
6
|
+
const trimmed = text.trim();
|
|
7
|
+
if (trimmed.length <= maxLen)
|
|
8
|
+
return trimmed;
|
|
9
|
+
const slice = trimmed.slice(0, maxLen + 1);
|
|
10
|
+
const sentenceEnd = Math.max(slice.lastIndexOf(". "), slice.lastIndexOf("! "), slice.lastIndexOf("? "));
|
|
11
|
+
if (sentenceEnd >= Math.floor(maxLen * 0.45)) {
|
|
12
|
+
return trimmed.slice(0, sentenceEnd + 1).trim();
|
|
13
|
+
}
|
|
14
|
+
const clauseEnd = Math.max(slice.lastIndexOf(", "), slice.lastIndexOf("; "), slice.lastIndexOf(" — "), slice.lastIndexOf(" - "));
|
|
15
|
+
if (clauseEnd >= Math.floor(maxLen * 0.45)) {
|
|
16
|
+
return `${trimmed.slice(0, clauseEnd).trim()}…`;
|
|
17
|
+
}
|
|
18
|
+
const lastSpace = slice.lastIndexOf(" ");
|
|
19
|
+
if (lastSpace >= Math.floor(maxLen * 0.6)) {
|
|
20
|
+
return `${trimmed.slice(0, lastSpace).trim()}…`;
|
|
21
|
+
}
|
|
22
|
+
return `${trimmed.slice(0, maxLen).trim()}…`;
|
|
23
|
+
}
|