@mergesignal/shared 0.12.0 → 0.12.1
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/deriveScanNarrative.d.ts.map +1 -1
- package/dist/deriveScanNarrative.js +4 -0
- package/dist/formatInsight.d.ts +3 -3
- package/dist/formatInsight.d.ts.map +1 -1
- package/dist/formatInsight.js +0 -9
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -3
- package/dist/prRiskBand.d.ts +7 -0
- package/dist/prRiskBand.d.ts.map +1 -1
- package/dist/prRiskBand.js +12 -0
- package/dist/prRiskBand.test.js +12 -1
- package/dist/presentation/abi3Expression.test.js +46 -0
- package/dist/presentation/cliParity.test.d.ts +2 -0
- package/dist/presentation/cliParity.test.d.ts.map +1 -0
- package/dist/presentation/cliParity.test.js +49 -0
- package/dist/presentation/compose/narrativeCompose.d.ts +0 -4
- package/dist/presentation/compose/narrativeCompose.d.ts.map +1 -1
- package/dist/presentation/compose/narrativeCompose.js +0 -20
- package/dist/presentation/dto/assessmentPresentationFields.d.ts +4 -0
- package/dist/presentation/dto/assessmentPresentationFields.d.ts.map +1 -1
- package/dist/presentation/index.d.ts +1 -1
- package/dist/presentation/index.d.ts.map +1 -1
- package/dist/presentation/index.js +1 -1
- package/dist/presentation/orchestration/buildScanPresentationBundle.d.ts +1 -0
- package/dist/presentation/orchestration/buildScanPresentationBundle.d.ts.map +1 -1
- package/dist/presentation/orchestration/buildScanPresentationBundle.js +1 -0
- package/dist/presentation/presenters/presentCliScanSummary.d.ts.map +1 -1
- package/dist/presentation/presenters/presentCliScanSummary.js +9 -7
- package/dist/presentation/presenters/presentGitHubCheckRun.d.ts.map +1 -1
- package/dist/presentation/presenters/presentGitHubCheckRun.js +11 -12
- package/dist/presentation/presenters/presentGitHubPrComment.d.ts.map +1 -1
- package/dist/presentation/presenters/presentGitHubPrComment.js +11 -10
- package/dist/presentation/presenters/presentScanDetails.d.ts.map +1 -1
- package/dist/presentation/presenters/presentScanDetails.js +8 -11
- package/dist/presentation/projectAssessmentFields.d.ts.map +1 -1
- package/dist/presentation/projectAssessmentFields.js +6 -0
- package/dist/presentation/surfaceParity.test.js +8 -0
- package/package.json +1 -1
- package/dist/scanDetailViewModelTypes.d.ts +0 -159
- package/dist/scanDetailViewModelTypes.d.ts.map +0 -1
- package/dist/scanDetailViewModelTypes.js +0 -4
- package/dist/truncateCardSummary.d.ts +0 -5
- package/dist/truncateCardSummary.d.ts.map +0 -1
- package/dist/truncateCardSummary.js +0 -23
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deriveScanNarrative.d.ts","sourceRoot":"","sources":["../src/deriveScanNarrative.ts"],"names":[],"mappings":"AAYA,OAAO,EAgBL,KAAK,kBAAkB,EACxB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,KAAK,EAMV,UAAU,EACX,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"deriveScanNarrative.d.ts","sourceRoot":"","sources":["../src/deriveScanNarrative.ts"],"names":[],"mappings":"AAYA,OAAO,EAgBL,KAAK,kBAAkB,EACxB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,KAAK,EAMV,UAAU,EACX,MAAM,YAAY,CAAC;AAwiBpB;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,GACpC,kBAAkB,CAsIpB"}
|
|
@@ -304,6 +304,10 @@ function guidanceFromRecommendation(rec) {
|
|
|
304
304
|
remediation: rec.impact,
|
|
305
305
|
};
|
|
306
306
|
}
|
|
307
|
+
/**
|
|
308
|
+
* Legacy insight/finding/recommendation synthesis for narrative availability tiers.
|
|
309
|
+
* Not presentation authority — shared surfaces use assessment expression fields instead.
|
|
310
|
+
*/
|
|
307
311
|
function collectReviewerGuidance(result) {
|
|
308
312
|
const guidance = [];
|
|
309
313
|
const insights = Array.isArray(result.insights) ? result.insights : [];
|
package/dist/formatInsight.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { PRInsight, PRDecision
|
|
2
|
-
|
|
1
|
+
import type { PRInsight, PRDecision } from "./types.js";
|
|
2
|
+
type FormattedInsight = {
|
|
3
3
|
message: string;
|
|
4
4
|
where: string;
|
|
5
5
|
action: string;
|
|
6
6
|
};
|
|
7
|
-
export declare function decisionTitle(recommendation: PRDecisionRecommendation): string;
|
|
8
7
|
export declare function formatInsight(insight: PRInsight): FormattedInsight;
|
|
9
8
|
/** Legacy markdown renderer for raw PR insights (format-only; no bundle inference). */
|
|
10
9
|
export declare function renderInsightsAsMarkdown(insights: PRInsight[], decision: PRDecision): string;
|
|
10
|
+
export {};
|
|
11
11
|
//# sourceMappingURL=formatInsight.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatInsight.d.ts","sourceRoot":"","sources":["../src/formatInsight.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"formatInsight.d.ts","sourceRoot":"","sources":["../src/formatInsight.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGxD,KAAK,gBAAgB,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAgBF,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,GAAG,gBAAgB,CAMlE;AA+BD,uFAAuF;AACvF,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,SAAS,EAAE,EACrB,QAAQ,EAAE,UAAU,GACnB,MAAM,CAUR"}
|
package/dist/formatInsight.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
import { MERGE_POSTURE_LABEL } from "./riskVocabulary.js";
|
|
2
|
-
const DECISION_TITLES = {
|
|
3
|
-
safe: "No significant dependency risks detected",
|
|
4
|
-
needs_review: "Elevated dependency merge risk",
|
|
5
|
-
risky: "Merge blocked - critical dependency risk",
|
|
6
|
-
};
|
|
7
|
-
// Title rendered once per PR comment, not per insight
|
|
8
|
-
export function decisionTitle(recommendation) {
|
|
9
|
-
return DECISION_TITLES[recommendation];
|
|
10
|
-
}
|
|
11
2
|
/**
|
|
12
3
|
* Normalizes typographic punctuation to ASCII equivalents so that LLM output
|
|
13
4
|
* renders consistently across PR comments, the web UI, and CLI output.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
export * from "./types.js";
|
|
2
2
|
export * from "./assessmentLabels.js";
|
|
3
3
|
export * from "./assessmentProjection.js";
|
|
4
|
-
export * from "./formatInsight.js";
|
|
5
4
|
export * from "./riskVocabulary.js";
|
|
6
5
|
export * from "./selectTopAffectedAreas.js";
|
|
7
6
|
export * from "./cardSummaryCopy.js";
|
|
8
|
-
export * from "./truncateCardSummary.js";
|
|
9
7
|
export * from "./formatCardAreaLabels.js";
|
|
10
8
|
export * from "./prRiskBand.js";
|
|
11
9
|
export * from "./prRiskWire.js";
|
|
@@ -20,7 +18,6 @@ export * from "./extractRepositoryContextFacts.js";
|
|
|
20
18
|
export * from "./narrativePresentation.js";
|
|
21
19
|
export * from "./normalizeGeneratedText.js";
|
|
22
20
|
export { presentGitHubPrCommentMarkdownFromResult } from "./presentGitHubPrComment.js";
|
|
23
|
-
export * from "./scanDetailViewModelTypes.js";
|
|
24
21
|
export * from "./scanCardPresentationState.js";
|
|
25
22
|
export * from "./scanResultSchema.js";
|
|
26
23
|
export * from "./scanSurfaceCopy.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC;AAChD,cAAc,0BAA0B,CAAC;AACzC,cAAc,oCAAoC,CAAC;AACnD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,OAAO,EAAE,wCAAwC,EAAE,MAAM,6BAA6B,CAAC;AACvF,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,wBAAwB,EACxB,uBAAuB,EACvB,aAAa,EACb,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,cAAc,EACd,yBAAyB,GAC1B,MAAM,kCAAkC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
export * from "./types.js";
|
|
2
2
|
export * from "./assessmentLabels.js";
|
|
3
3
|
export * from "./assessmentProjection.js";
|
|
4
|
-
export * from "./formatInsight.js";
|
|
5
4
|
export * from "./riskVocabulary.js";
|
|
6
5
|
export * from "./selectTopAffectedAreas.js";
|
|
7
6
|
export * from "./cardSummaryCopy.js";
|
|
8
|
-
export * from "./truncateCardSummary.js";
|
|
9
7
|
export * from "./formatCardAreaLabels.js";
|
|
10
8
|
export * from "./prRiskBand.js";
|
|
11
9
|
export * from "./prRiskWire.js";
|
|
@@ -20,7 +18,6 @@ export * from "./extractRepositoryContextFacts.js";
|
|
|
20
18
|
export * from "./narrativePresentation.js";
|
|
21
19
|
export * from "./normalizeGeneratedText.js";
|
|
22
20
|
export { presentGitHubPrCommentMarkdownFromResult } from "./presentGitHubPrComment.js";
|
|
23
|
-
export * from "./scanDetailViewModelTypes.js";
|
|
24
21
|
export * from "./scanCardPresentationState.js";
|
|
25
22
|
export * from "./scanResultSchema.js";
|
|
26
23
|
export * from "./scanSurfaceCopy.js";
|
package/dist/prRiskBand.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ScanNarrativeFacts } from "./scanNarrativeFacts.js";
|
|
1
2
|
/**
|
|
2
3
|
* Canonical PR Risk band contract — sole authority for PR Risk band derivation.
|
|
3
4
|
* Independent from legacy exposure presentation and merge verdict (`assessment.posture`).
|
|
@@ -18,6 +19,12 @@ export declare function scoreToBandLabel(score: number | null | undefined): stri
|
|
|
18
19
|
export declare function prRiskBandLabel(band: PrRiskBand): string;
|
|
19
20
|
/** Fragment for composite aria labels on PR surfaces. */
|
|
20
21
|
export declare function prRiskBandAriaFragment(score: number | null | undefined): string | null;
|
|
22
|
+
export type PrRiskSummary = {
|
|
23
|
+
prRiskScore: number;
|
|
24
|
+
prRiskBandLabel: string;
|
|
25
|
+
};
|
|
26
|
+
/** Format PR Risk score + band from narrative facts (not assessment projection). */
|
|
27
|
+
export declare function formatPrRiskSummary(facts: Pick<ScanNarrativeFacts, "riskSignals" | "riskIndex">): PrRiskSummary | undefined;
|
|
21
28
|
/** Project 5-band PR Risk to 3-bucket scan-detail gauge band. */
|
|
22
29
|
export declare function prRiskBandToGaugeBand(band: PrRiskBand): PrRiskGaugeBand;
|
|
23
30
|
//# sourceMappingURL=prRiskBand.d.ts.map
|
package/dist/prRiskBand.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prRiskBand.d.ts","sourceRoot":"","sources":["../src/prRiskBand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,gBAAgB,EAAG,GAAY,CAAC;AAE7C,iEAAiE;AACjE,eAAO,MAAM,uBAAuB,gCAAiC,CAAC;AAEtE,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;AAU7E,oDAAoD;AACpD,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAMhD,CAAC;AAUF,mEAAmE;AACnE,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,UAAU,GAAG,MAAM,CAAC;AAO1D,wDAAwD;AACxD,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC/B,UAAU,GAAG,IAAI,CAKnB;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC/B,MAAM,GAAG,IAAI,CAGf;AAED,yCAAyC;AACzC,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAExD;AAED,yDAAyD;AACzD,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC/B,MAAM,GAAG,IAAI,CAIf;AAED,iEAAiE;AACjE,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,UAAU,GAAG,eAAe,CAIvE"}
|
|
1
|
+
{"version":3,"file":"prRiskBand.d.ts","sourceRoot":"","sources":["../src/prRiskBand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAElE;;;GAGG;AAEH,eAAO,MAAM,gBAAgB,EAAG,GAAY,CAAC;AAE7C,iEAAiE;AACjE,eAAO,MAAM,uBAAuB,gCAAiC,CAAC;AAEtE,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;AAU7E,oDAAoD;AACpD,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAMhD,CAAC;AAUF,mEAAmE;AACnE,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,UAAU,GAAG,MAAM,CAAC;AAO1D,wDAAwD;AACxD,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC/B,UAAU,GAAG,IAAI,CAKnB;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC/B,MAAM,GAAG,IAAI,CAGf;AAED,yCAAyC;AACzC,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAExD;AAED,yDAAyD;AACzD,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC/B,MAAM,GAAG,IAAI,CAIf;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,oFAAoF;AACpF,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,IAAI,CAAC,kBAAkB,EAAE,aAAa,GAAG,WAAW,CAAC,GAC3D,aAAa,GAAG,SAAS,CAW3B;AAED,iEAAiE;AACjE,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,UAAU,GAAG,eAAe,CAIvE"}
|
package/dist/prRiskBand.js
CHANGED
|
@@ -56,6 +56,18 @@ export function prRiskBandAriaFragment(score) {
|
|
|
56
56
|
return null;
|
|
57
57
|
return `PR Risk: ${label}`;
|
|
58
58
|
}
|
|
59
|
+
/** Format PR Risk score + band from narrative facts (not assessment projection). */
|
|
60
|
+
export function formatPrRiskSummary(facts) {
|
|
61
|
+
const prRiskScore = facts.riskSignals?.riskIndex;
|
|
62
|
+
if (prRiskScore == null || !Number.isFinite(prRiskScore))
|
|
63
|
+
return undefined;
|
|
64
|
+
const prRiskBandLabelText = facts.riskSignals?.band != null
|
|
65
|
+
? prRiskBandLabel(facts.riskSignals.band)
|
|
66
|
+
: scoreToBandLabel(prRiskScore);
|
|
67
|
+
if (!prRiskBandLabelText)
|
|
68
|
+
return undefined;
|
|
69
|
+
return { prRiskScore, prRiskBandLabel: prRiskBandLabelText };
|
|
70
|
+
}
|
|
59
71
|
/** Project 5-band PR Risk to 3-bucket scan-detail gauge band. */
|
|
60
72
|
export function prRiskBandToGaugeBand(band) {
|
|
61
73
|
if (band === "critical" || band === "high")
|
package/dist/prRiskBand.test.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { PR_RISK_BAND_ABI, PR_RISK_BAND_THRESHOLDS, prRiskBandAriaFragment, prRiskBandLabel, prRiskBandToGaugeBand, scoreToBand, scoreToBandLabel, } from "./prRiskBand.js";
|
|
2
|
+
import { PR_RISK_BAND_ABI, PR_RISK_BAND_THRESHOLDS, formatPrRiskSummary, prRiskBandAriaFragment, prRiskBandLabel, prRiskBandToGaugeBand, scoreToBand, scoreToBandLabel, } from "./prRiskBand.js";
|
|
3
3
|
describe("PR_RISK_BAND_ABI", () => {
|
|
4
4
|
it("is stable v1", () => {
|
|
5
5
|
expect(PR_RISK_BAND_ABI).toBe("1");
|
|
@@ -46,6 +46,17 @@ describe("prRiskBandAriaFragment", () => {
|
|
|
46
46
|
expect(prRiskBandAriaFragment(55)).toBe("PR Risk: Medium");
|
|
47
47
|
});
|
|
48
48
|
});
|
|
49
|
+
describe("formatPrRiskSummary", () => {
|
|
50
|
+
it("returns score and band label from riskSignals", () => {
|
|
51
|
+
expect(formatPrRiskSummary({
|
|
52
|
+
riskSignals: { riskIndex: 55, band: "medium", layers: [] },
|
|
53
|
+
riskIndex: 55,
|
|
54
|
+
})).toEqual({ prRiskScore: 55, prRiskBandLabel: "Medium" });
|
|
55
|
+
});
|
|
56
|
+
it("returns undefined when risk index is missing", () => {
|
|
57
|
+
expect(formatPrRiskSummary({ riskSignals: null, riskIndex: null })).toBeUndefined();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
49
60
|
describe("prRiskBandToGaugeBand", () => {
|
|
50
61
|
it("projects to three gauge buckets", () => {
|
|
51
62
|
expect(prRiskBandToGaugeBand("very_low")).toBe("low");
|
|
@@ -13,6 +13,7 @@ import { describe, expect, it } from "vitest";
|
|
|
13
13
|
import { minimalReviewFocalPoint, reachScopeFor, verificationScopeFor, withAssessmentScope, } from "../fixtures/assessmentScopeFixtures.js";
|
|
14
14
|
import { projectReasoningLines, projectVerificationActions, } from "../assessmentProjection.js";
|
|
15
15
|
import { toPublicPresentation } from "../assessmentPresentationUtils.js";
|
|
16
|
+
import { projectAssessmentFields } from "./projectAssessmentFields.js";
|
|
16
17
|
import { buildScanPresentationBundle } from "./orchestration/buildScanPresentationBundle.js";
|
|
17
18
|
import { presentGitHubPrComment } from "./presenters/presentGitHubPrComment.js";
|
|
18
19
|
import { presentGitHubCheckRun } from "./presenters/presentGitHubCheckRun.js";
|
|
@@ -190,6 +191,51 @@ describe("projectVerificationActions — ABI 3 guidance", () => {
|
|
|
190
191
|
});
|
|
191
192
|
});
|
|
192
193
|
// ---------------------------------------------------------------------------
|
|
194
|
+
// projectAssessmentFields — ABI 3 expression projection
|
|
195
|
+
// ---------------------------------------------------------------------------
|
|
196
|
+
describe("projectAssessmentFields — ABI 3 expression", () => {
|
|
197
|
+
it("projects confidenceRationale and electionSummary from assessment", () => {
|
|
198
|
+
const result = scanResultWithAssessment(assessmentExpressAbi3);
|
|
199
|
+
const bundle = buildScanPresentationBundle({
|
|
200
|
+
result,
|
|
201
|
+
pipelineStatus: "done",
|
|
202
|
+
});
|
|
203
|
+
const fields = projectAssessmentFields(bundle);
|
|
204
|
+
expect(fields.confidenceRationale).toBe("Confidence is high: propagation from express to application entry points was directly observed.");
|
|
205
|
+
expect(fields.electionSummary).toBe(expressElectionSummary);
|
|
206
|
+
expect(fields.reasoning).toEqual(expressReasoning);
|
|
207
|
+
});
|
|
208
|
+
it("omits empty confidenceRationale and electionSummary after trim", () => {
|
|
209
|
+
const assessment = {
|
|
210
|
+
...assessmentExpressAbi3,
|
|
211
|
+
confidenceRationale: " ",
|
|
212
|
+
reviewFocalPoint: {
|
|
213
|
+
...assessmentExpressAbi3.reviewFocalPoint,
|
|
214
|
+
electionSummary: "",
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
const result = scanResultWithAssessment(assessment);
|
|
218
|
+
const bundle = buildScanPresentationBundle({
|
|
219
|
+
result,
|
|
220
|
+
pipelineStatus: "done",
|
|
221
|
+
});
|
|
222
|
+
const fields = projectAssessmentFields(bundle);
|
|
223
|
+
expect(fields.confidenceRationale).toBeUndefined();
|
|
224
|
+
expect(fields.electionSummary).toBeUndefined();
|
|
225
|
+
});
|
|
226
|
+
it("projects reasoning when assessment has concerns", () => {
|
|
227
|
+
const result = scanResultWithAssessment(assessmentExpressAbi3);
|
|
228
|
+
const bundle = buildScanPresentationBundle({
|
|
229
|
+
result,
|
|
230
|
+
pipelineStatus: "done",
|
|
231
|
+
});
|
|
232
|
+
const fields = projectAssessmentFields(bundle);
|
|
233
|
+
expect(assessmentExpressAbi3.concerns.length).toBeGreaterThan(0);
|
|
234
|
+
expect(fields.reasoning.length).toBeGreaterThan(0);
|
|
235
|
+
expect(fields.reasoning).toEqual(expressReasoning);
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
// ---------------------------------------------------------------------------
|
|
193
239
|
// PR comment — electionSummary and reasoning
|
|
194
240
|
// ---------------------------------------------------------------------------
|
|
195
241
|
describe("presentGitHubPrComment — ABI 3 expression", () => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cliParity.test.d.ts","sourceRoot":"","sources":["../../src/presentation/cliParity.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { buildScanPresentationBundle } from "./orchestration/buildScanPresentationBundle.js";
|
|
3
|
+
import { presentCliScanSummary } from "./presenters/presentCliScanSummary.js";
|
|
4
|
+
import { presentDashboardCard } from "./presenters/presentDashboardCard.js";
|
|
5
|
+
import { presentGitHubCheckRun } from "./presenters/presentGitHubCheckRun.js";
|
|
6
|
+
import { presentGitHubPrComment } from "./presenters/presentGitHubPrComment.js";
|
|
7
|
+
import { presentScanDetails } from "./presenters/presentScanDetails.js";
|
|
8
|
+
import { projectAssessmentFields } from "./projectAssessmentFields.js";
|
|
9
|
+
import { scanResultBullmq, scanResultEslint, scanResultFastifyRuntime, scanResultMixedTypescriptFastify, scanResultPrettier, scanResultTypescriptPatch, scanResultVitest, } from "./fixtures/presentationPersonaFixtures.js";
|
|
10
|
+
const SCAN_ID = "22222222-2222-4222-8222-222222222222";
|
|
11
|
+
const ORIGIN = "https://app.example.com";
|
|
12
|
+
const validationPersonas = [
|
|
13
|
+
{ name: "mixed-ts-fastify", result: scanResultMixedTypescriptFastify },
|
|
14
|
+
{ name: "fastify-runtime", result: scanResultFastifyRuntime },
|
|
15
|
+
{ name: "typescript-patch", result: scanResultTypescriptPatch },
|
|
16
|
+
{ name: "prettier", result: scanResultPrettier },
|
|
17
|
+
{ name: "bullmq", result: scanResultBullmq },
|
|
18
|
+
{ name: "eslint", result: scanResultEslint },
|
|
19
|
+
{ name: "vitest", result: scanResultVitest },
|
|
20
|
+
];
|
|
21
|
+
describe("cliParity guardrail", () => {
|
|
22
|
+
for (const persona of validationPersonas) {
|
|
23
|
+
it(`${persona.name}: CLI shares assessment fields with other surfaces`, () => {
|
|
24
|
+
const bundle = buildScanPresentationBundle({
|
|
25
|
+
result: persona.result,
|
|
26
|
+
pipelineStatus: "done",
|
|
27
|
+
});
|
|
28
|
+
const fields = projectAssessmentFields(bundle);
|
|
29
|
+
const cli = presentCliScanSummary(bundle, { repoLabel: "acme/api" });
|
|
30
|
+
const card = presentDashboardCard(bundle);
|
|
31
|
+
const details = presentScanDetails(bundle, { scanId: SCAN_ID });
|
|
32
|
+
const check = presentGitHubCheckRun(bundle, {
|
|
33
|
+
scanId: SCAN_ID,
|
|
34
|
+
webAppOrigin: ORIGIN,
|
|
35
|
+
});
|
|
36
|
+
const comment = presentGitHubPrComment(bundle);
|
|
37
|
+
expect(cli.posture).toBe(fields.posture);
|
|
38
|
+
expect(cli.reasoning).toEqual(fields.reasoning);
|
|
39
|
+
expect(cli.verificationChannel).toBe(fields.verificationChannel);
|
|
40
|
+
expect(cli.verificationFocus).toEqual(fields.verificationFocus);
|
|
41
|
+
expect(cli.confidenceRationale).toBe(fields.confidenceRationale);
|
|
42
|
+
expect(cli.electionSummary).toBe(fields.electionSummary);
|
|
43
|
+
expect(cli.reasoning).toEqual(card.reasoning);
|
|
44
|
+
expect(cli.reasoning).toEqual(details.reasoning);
|
|
45
|
+
expect(cli.reasoning).toEqual(check.reasoning);
|
|
46
|
+
expect(cli.reasoning).toEqual(comment.reasoning);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
});
|
|
@@ -5,10 +5,6 @@ export declare function composeSubheadline(bundle: ScanPresentationBundle): stri
|
|
|
5
5
|
export declare function composeKeyPoints(bundle: ScanPresentationBundle, max: number): string[];
|
|
6
6
|
export declare function composeVerificationActions(bundle: ScanPresentationBundle, max: number): string[];
|
|
7
7
|
export declare function composeAffectedAreaLabels(bundle: ScanPresentationBundle, max: number): string[];
|
|
8
|
-
export declare function composeEvidenceRows(bundle: ScanPresentationBundle, max: number): Array<{
|
|
9
|
-
label: string;
|
|
10
|
-
value: string;
|
|
11
|
-
}>;
|
|
12
8
|
export declare function composeSupportingContext(bundle: ScanPresentationBundle): string[] | undefined;
|
|
13
9
|
export declare function evidenceContextFromProfile(bundle: ScanPresentationBundle): {
|
|
14
10
|
priority: "pr_intelligence" | "limited";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"narrativeCompose.d.ts","sourceRoot":"","sources":["../../../src/presentation/compose/narrativeCompose.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"narrativeCompose.d.ts","sourceRoot":"","sources":["../../../src/presentation/compose/narrativeCompose.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AAMzF,OAAO,EACL,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,wBAAwB,CAAC;AAShC,wBAAgB,eAAe,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,CAEtE;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,sBAAsB,GAC7B,MAAM,GAAG,SAAS,CAIpB;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,sBAAsB,EAC9B,GAAG,EAAE,MAAM,GACV,MAAM,EAAE,CAEV;AAED,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,sBAAsB,EAC9B,GAAG,EAAE,MAAM,GACV,MAAM,EAAE,CAEV;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,sBAAsB,EAC9B,GAAG,EAAE,MAAM,GACV,MAAM,EAAE,CAQV;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,sBAAsB,GAC7B,MAAM,EAAE,GAAG,SAAS,CAwBtB;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,sBAAsB,GAAG;IAC1E,QAAQ,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACxC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAKA"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { formatCardAreaLabels } from "../../formatCardAreaLabels.js";
|
|
2
|
-
import { formatChangedPackagesShort, labelBlastRadiusLevel, labelReachabilityKind, labelRuntimeSurface, } from "../../narrativePresentation.js";
|
|
3
2
|
import { scanSurfaceCopy } from "../../scanSurfaceCopy.js";
|
|
4
3
|
import { buildNarrativeChannels, projectCompactKeyPoints, } from "./narrativeChannels.js";
|
|
5
4
|
export { buildNarrativeChannels, projectCompactKeyPoints, } from "./narrativeChannels.js";
|
|
@@ -36,25 +35,6 @@ export function composeAffectedAreaLabels(bundle, max) {
|
|
|
36
35
|
}
|
|
37
36
|
return labels;
|
|
38
37
|
}
|
|
39
|
-
export function composeEvidenceRows(bundle, max) {
|
|
40
|
-
const { facts, profile } = bundle;
|
|
41
|
-
const rows = [];
|
|
42
|
-
if (!profile.interpretation.suppressRuntimeNarrative) {
|
|
43
|
-
const runtime = labelRuntimeSurface(facts);
|
|
44
|
-
if (runtime)
|
|
45
|
-
rows.push({ label: "Runtime", value: runtime });
|
|
46
|
-
const reach = labelReachabilityKind(facts);
|
|
47
|
-
if (reach)
|
|
48
|
-
rows.push({ label: "Reachability", value: reach });
|
|
49
|
-
}
|
|
50
|
-
const blast = labelBlastRadiusLevel(facts);
|
|
51
|
-
if (blast)
|
|
52
|
-
rows.push({ label: "Blast radius", value: blast });
|
|
53
|
-
const changed = formatChangedPackagesShort(facts, 3);
|
|
54
|
-
if (changed)
|
|
55
|
-
rows.push({ label: "Changed", value: changed });
|
|
56
|
-
return rows.slice(0, max);
|
|
57
|
-
}
|
|
58
38
|
export function composeSupportingContext(bundle) {
|
|
59
39
|
const { facts, profile, result } = bundle;
|
|
60
40
|
if (profile.density === "minimal")
|
|
@@ -10,5 +10,9 @@ export type AssessmentPresentationFields = {
|
|
|
10
10
|
verificationChannel: VerificationChannel;
|
|
11
11
|
reachVisibility: ReachVisibility;
|
|
12
12
|
narrativeIntensity: NarrativeIntensity;
|
|
13
|
+
/** ABI 3 expression — optional confidence explanation. */
|
|
14
|
+
confidenceRationale?: string;
|
|
15
|
+
/** ABI 3 expression — optional focal-election narrative. */
|
|
16
|
+
electionSummary?: string;
|
|
13
17
|
};
|
|
14
18
|
//# sourceMappingURL=assessmentPresentationFields.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assessmentPresentationFields.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/assessmentPresentationFields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EAEhB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,uEAAuE;AACvE,MAAM,MAAM,4BAA4B,GAAG;IACzC,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,OAAO,CAAC;IAC3C,cAAc,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACxC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,eAAe,EAAE,eAAe,CAAC;IACjC,kBAAkB,EAAE,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"assessmentPresentationFields.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/assessmentPresentationFields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EAEhB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,uEAAuE;AACvE,MAAM,MAAM,4BAA4B,GAAG;IACzC,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,OAAO,CAAC;IAC3C,cAAc,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACxC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,eAAe,EAAE,eAAe,CAAC;IACjC,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,0DAA0D;IAC1D,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,4DAA4D;IAC5D,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC"}
|
|
@@ -24,5 +24,5 @@ export { renderGitHubCheckRunMarkdown } from "./render/renderGitHubCheckRunMarkd
|
|
|
24
24
|
export { buildGitHubCheckRunOutput, resolveWebAppOrigin, type GitHubCheckRunConclusion, type GitHubCheckRunOutput, type BuildGitHubCheckRunOutputOptions, } from "./buildGitHubCheckRunOutput.js";
|
|
25
25
|
export { renderGitHubPrCommentMarkdown } from "./render/renderGitHubPrCommentMarkdown.js";
|
|
26
26
|
export { renderCliScanSummaryText } from "./render/renderCliScanSummaryText.js";
|
|
27
|
-
export { buildNarrativeChannels, projectCompactKeyPoints, composeHeadline, composeSubheadline, composeKeyPoints, composeVerificationActions, composeAffectedAreaLabels,
|
|
27
|
+
export { buildNarrativeChannels, projectCompactKeyPoints, composeHeadline, composeSubheadline, composeKeyPoints, composeVerificationActions, composeAffectedAreaLabels, composeSupportingContext, evidenceContextFromProfile, } from "./compose/narrativeCompose.js";
|
|
28
28
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/presentation/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AACxF,OAAO,EAAE,2BAA2B,EAAE,MAAM,gDAAgD,CAAC;AAC7F,YAAY,EAAE,gCAAgC,EAAE,MAAM,gDAAgD,CAAC;AACvG,OAAO,EAAE,yBAAyB,EAAE,MAAM,8CAA8C,CAAC;AACzF,YAAY,EAAE,8BAA8B,EAAE,MAAM,8CAA8C,CAAC;AACnG,OAAO,EAAE,4BAA4B,EAAE,MAAM,iDAAiD,CAAC;AAC/F,YAAY,EAAE,iCAAiC,EAAE,MAAM,iDAAiD,CAAC;AAEzG,YAAY,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,YAAY,EACV,kBAAkB,EAClB,0BAA0B,GAC3B,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACV,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,2BAA2B,EAC3B,uBAAuB,GACxB,MAAM,gBAAgB,CAAC;AAExB,YAAY,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AACpF,YAAY,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,gDAAgD;AAChD,YAAY,EAAE,yBAAyB,IAAI,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC5G,YAAY,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAChF,YAAY,EACV,0BAA0B,EAC1B,2BAA2B,EAC3B,mBAAmB,GACpB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,sCAAsC,GACvC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,YAAY,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AACpF,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAE9E,OAAO,EAAE,4BAA4B,EAAE,MAAM,0CAA0C,CAAC;AACxF,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,gCAAgC,GACtC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,6BAA6B,EAAE,MAAM,2CAA2C,CAAC;AAC1F,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAEhF,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,0BAA0B,EAC1B,yBAAyB,EACzB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/presentation/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AACxF,OAAO,EAAE,2BAA2B,EAAE,MAAM,gDAAgD,CAAC;AAC7F,YAAY,EAAE,gCAAgC,EAAE,MAAM,gDAAgD,CAAC;AACvG,OAAO,EAAE,yBAAyB,EAAE,MAAM,8CAA8C,CAAC;AACzF,YAAY,EAAE,8BAA8B,EAAE,MAAM,8CAA8C,CAAC;AACnG,OAAO,EAAE,4BAA4B,EAAE,MAAM,iDAAiD,CAAC;AAC/F,YAAY,EAAE,iCAAiC,EAAE,MAAM,iDAAiD,CAAC;AAEzG,YAAY,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,YAAY,EACV,kBAAkB,EAClB,0BAA0B,GAC3B,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACV,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,2BAA2B,EAC3B,uBAAuB,GACxB,MAAM,gBAAgB,CAAC;AAExB,YAAY,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AACpF,YAAY,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,gDAAgD;AAChD,YAAY,EAAE,yBAAyB,IAAI,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC5G,YAAY,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAChF,YAAY,EACV,0BAA0B,EAC1B,2BAA2B,EAC3B,mBAAmB,GACpB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,sCAAsC,GACvC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,YAAY,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AACpF,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAE9E,OAAO,EAAE,4BAA4B,EAAE,MAAM,0CAA0C,CAAC;AACxF,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,gCAAgC,GACtC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,6BAA6B,EAAE,MAAM,2CAA2C,CAAC;AAC1F,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAEhF,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,0BAA0B,EAC1B,yBAAyB,EACzB,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,+BAA+B,CAAC"}
|
|
@@ -10,4 +10,4 @@ export { renderGitHubCheckRunMarkdown } from "./render/renderGitHubCheckRunMarkd
|
|
|
10
10
|
export { buildGitHubCheckRunOutput, resolveWebAppOrigin, } from "./buildGitHubCheckRunOutput.js";
|
|
11
11
|
export { renderGitHubPrCommentMarkdown } from "./render/renderGitHubPrCommentMarkdown.js";
|
|
12
12
|
export { renderCliScanSummaryText } from "./render/renderCliScanSummaryText.js";
|
|
13
|
-
export { buildNarrativeChannels, projectCompactKeyPoints, composeHeadline, composeSubheadline, composeKeyPoints, composeVerificationActions, composeAffectedAreaLabels,
|
|
13
|
+
export { buildNarrativeChannels, projectCompactKeyPoints, composeHeadline, composeSubheadline, composeKeyPoints, composeVerificationActions, composeAffectedAreaLabels, composeSupportingContext, evidenceContextFromProfile, } from "./compose/narrativeCompose.js";
|
|
@@ -9,6 +9,7 @@ export type BuildScanPresentationBundleInput = {
|
|
|
9
9
|
/**
|
|
10
10
|
* Mandatory orchestration entrypoint for completed-scan presentation.
|
|
11
11
|
* Assessment is the sole authority; profile is a thin projection.
|
|
12
|
+
* Consumes only the public ScanResult contract — see docs/engineering/presentation-ownership.md.
|
|
12
13
|
*/
|
|
13
14
|
export declare function buildScanPresentationBundle(input: BuildScanPresentationBundleInput): ScanPresentationBundle | null;
|
|
14
15
|
//# sourceMappingURL=buildScanPresentationBundle.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildScanPresentationBundle.d.ts","sourceRoot":"","sources":["../../../src/presentation/orchestration/buildScanPresentationBundle.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAE1E,MAAM,MAAM,gCAAgC,GAAG;IAC7C,MAAM,EAAE,UAAU,CAAC;IACnB,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"buildScanPresentationBundle.d.ts","sourceRoot":"","sources":["../../../src/presentation/orchestration/buildScanPresentationBundle.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAE1E,MAAM,MAAM,gCAAgC,GAAG;IAC7C,MAAM,EAAE,UAAU,CAAC;IACnB,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,gCAAgC,GACtC,sBAAsB,GAAG,IAAI,CA4B/B"}
|
|
@@ -5,6 +5,7 @@ import { buildProfileFromAssessment } from "../profile/buildProfileFromAssessmen
|
|
|
5
5
|
/**
|
|
6
6
|
* Mandatory orchestration entrypoint for completed-scan presentation.
|
|
7
7
|
* Assessment is the sole authority; profile is a thin projection.
|
|
8
|
+
* Consumes only the public ScanResult contract — see docs/engineering/presentation-ownership.md.
|
|
8
9
|
*/
|
|
9
10
|
export function buildScanPresentationBundle(input) {
|
|
10
11
|
if (input.pipelineStatus !== "done" || !input.result)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentCliScanSummary.d.ts","sourceRoot":"","sources":["../../../src/presentation/presenters/presentCliScanSummary.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"presentCliScanSummary.d.ts","sourceRoot":"","sources":["../../../src/presentation/presenters/presentCliScanSummary.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AAGzF,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,sBAAsB,EAC9B,GAAG,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,mBAAmB,CAmCrB"}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { formatPrRiskSummary } from "../../prRiskBand.js";
|
|
2
2
|
import { resolvePrRiskLayerScores } from "../../prRiskWire.js";
|
|
3
|
-
import { buildNarrativeChannels,
|
|
3
|
+
import { buildNarrativeChannels, composeSubheadline, composeSupportingContext, evidenceContextFromProfile, projectCompactKeyPoints, } from "../compose/narrativeCompose.js";
|
|
4
4
|
import { projectAssessmentFields } from "../projectAssessmentFields.js";
|
|
5
5
|
export function presentCliScanSummary(bundle, ctx = {}) {
|
|
6
6
|
const { facts, profile, result } = bundle;
|
|
7
|
+
const channels = buildNarrativeChannels(bundle);
|
|
7
8
|
const layerScores = resolvePrRiskLayerScores(result);
|
|
8
9
|
const layerLine = layerScores
|
|
9
10
|
? `security=${layerScores.security} maintainability=${layerScores.maintainability} ecosystem=${layerScores.ecosystem} upgradeImpact=${layerScores.upgradeImpact}`
|
|
10
11
|
: "";
|
|
11
|
-
const
|
|
12
|
+
const prRisk = formatPrRiskSummary(facts);
|
|
13
|
+
const prRiskScore = prRisk?.prRiskScore ?? facts.riskIndex ?? 0;
|
|
12
14
|
return {
|
|
13
15
|
...projectAssessmentFields(bundle),
|
|
14
16
|
header: {
|
|
@@ -20,13 +22,13 @@ export function presentCliScanSummary(bundle, ctx = {}) {
|
|
|
20
22
|
density: profile.density,
|
|
21
23
|
confidence: profile.confidence,
|
|
22
24
|
evidenceContext: evidenceContextFromProfile(bundle),
|
|
23
|
-
headline:
|
|
25
|
+
headline: channels.headline,
|
|
24
26
|
subheadline: composeSubheadline(bundle),
|
|
25
|
-
keyPoints: projectCompactKeyPoints(
|
|
26
|
-
verificationActions:
|
|
27
|
+
keyPoints: projectCompactKeyPoints(channels, 6),
|
|
28
|
+
verificationActions: channels.verification.slice(0, 5),
|
|
27
29
|
metrics: {
|
|
28
30
|
prRiskScore,
|
|
29
|
-
prRiskBandLabel:
|
|
31
|
+
prRiskBandLabel: prRisk?.prRiskBandLabel ?? undefined,
|
|
30
32
|
riskIndex: prRiskScore,
|
|
31
33
|
layerLine,
|
|
32
34
|
findingCount: result.findings?.length ?? 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentGitHubCheckRun.d.ts","sourceRoot":"","sources":["../../../src/presentation/presenters/presentGitHubCheckRun.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"presentGitHubCheckRun.d.ts","sourceRoot":"","sources":["../../../src/presentation/presenters/presentGitHubCheckRun.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AACrF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AAGzF,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,sBAAsB,EAC9B,GAAG,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAChE,0BAA0B,CAkD5B"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { buildNarrativeChannels,
|
|
1
|
+
import { formatPrRiskSummary } from "../../prRiskBand.js";
|
|
2
|
+
import { buildNarrativeChannels, composeSubheadline, evidenceContextFromProfile, projectCompactKeyPoints, } from "../compose/narrativeCompose.js";
|
|
3
3
|
import { projectAssessmentFields } from "../projectAssessmentFields.js";
|
|
4
4
|
export function presentGitHubCheckRun(bundle, ctx) {
|
|
5
|
-
const { profile } = bundle;
|
|
6
|
-
const
|
|
5
|
+
const { facts, profile } = bundle;
|
|
6
|
+
const channels = buildNarrativeChannels(bundle);
|
|
7
7
|
const assessmentFields = projectAssessmentFields(bundle);
|
|
8
|
-
const actions =
|
|
8
|
+
const actions = channels.verification.slice(0, 3);
|
|
9
9
|
const detailsUrl = `${ctx.webAppOrigin.replace(/\/$/, "")}/scan/${ctx.scanId}`;
|
|
10
10
|
const conclusion = profile.status === "safe"
|
|
11
11
|
? "success"
|
|
@@ -13,13 +13,12 @@ export function presentGitHubCheckRun(bundle, ctx) {
|
|
|
13
13
|
? "failure"
|
|
14
14
|
: "neutral";
|
|
15
15
|
const sections = [];
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
if (prRiskScore != null && prRiskBandLabelText) {
|
|
16
|
+
const prRisk = formatPrRiskSummary(facts);
|
|
17
|
+
if (prRisk) {
|
|
19
18
|
sections.push({
|
|
20
19
|
id: "why",
|
|
21
20
|
title: "PR Risk",
|
|
22
|
-
bullets: [`${prRiskScore} (${
|
|
21
|
+
bullets: [`${prRisk.prRiskScore} (${prRisk.prRiskBandLabel})`],
|
|
23
22
|
});
|
|
24
23
|
}
|
|
25
24
|
// Use assessment.reasoning directly for the Why section (ABI 3).
|
|
@@ -27,7 +26,7 @@ export function presentGitHubCheckRun(bundle, ctx) {
|
|
|
27
26
|
const reasoningLines = assessmentFields.reasoning.slice(0, 3);
|
|
28
27
|
const whyBullets = reasoningLines.length > 0
|
|
29
28
|
? reasoningLines
|
|
30
|
-
: projectCompactKeyPoints(
|
|
29
|
+
: projectCompactKeyPoints(channels, 3);
|
|
31
30
|
if (whyBullets.length > 0) {
|
|
32
31
|
sections.push({ id: "why", title: "Why", bullets: whyBullets });
|
|
33
32
|
}
|
|
@@ -41,9 +40,9 @@ export function presentGitHubCheckRun(bundle, ctx) {
|
|
|
41
40
|
density: profile.density,
|
|
42
41
|
confidence: profile.confidence,
|
|
43
42
|
evidenceContext: evidenceContextFromProfile(bundle),
|
|
44
|
-
title: headline,
|
|
43
|
+
title: channels.headline,
|
|
45
44
|
conclusion,
|
|
46
|
-
summaryLead: composeSubheadline(bundle) ?? headline,
|
|
45
|
+
summaryLead: composeSubheadline(bundle) ?? channels.headline,
|
|
47
46
|
sections,
|
|
48
47
|
detailsUrl,
|
|
49
48
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentGitHubPrComment.d.ts","sourceRoot":"","sources":["../../../src/presentation/presenters/presentGitHubPrComment.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"presentGitHubPrComment.d.ts","sourceRoot":"","sources":["../../../src/presentation/presenters/presentGitHubPrComment.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AAGzF,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,sBAAsB,GAC7B,2BAA2B,CAyC7B"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MERGE_POSTURE_LABEL } from "../../riskVocabulary.js";
|
|
2
|
-
import {
|
|
2
|
+
import { formatPrRiskSummary } from "../../prRiskBand.js";
|
|
3
3
|
import { buildNarrativeChannels, evidenceContextFromProfile, } from "../compose/narrativeCompose.js";
|
|
4
4
|
import { formatChangedPackagesShort } from "../../narrativePresentation.js";
|
|
5
5
|
import { projectAssessmentFields } from "../projectAssessmentFields.js";
|
|
@@ -11,22 +11,23 @@ export function presentGitHubPrComment(bundle) {
|
|
|
11
11
|
const changed = formatChangedPackagesShort(facts, 3);
|
|
12
12
|
if (changed)
|
|
13
13
|
introLines.push(`Changed: ${changed}`);
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
const prRisk = formatPrRiskSummary(facts);
|
|
15
|
+
if (prRisk) {
|
|
16
|
+
introLines.push(`PR Risk: ${prRisk.prRiskScore} (${prRisk.prRiskBandLabel})`);
|
|
17
|
+
}
|
|
18
|
+
if (assessmentFields.electionSummary) {
|
|
19
|
+
introLines.push(assessmentFields.electionSummary);
|
|
18
20
|
}
|
|
19
|
-
const electionSummary = bundle.assessment.reviewFocalPoint.electionSummary;
|
|
20
|
-
if (electionSummary)
|
|
21
|
-
introLines.push(electionSummary);
|
|
22
21
|
for (const line of assessmentFields.reasoning.slice(0, 2)) {
|
|
23
22
|
introLines.push(line);
|
|
24
23
|
}
|
|
25
24
|
const verify = channels.verification[0];
|
|
26
25
|
if (verify)
|
|
27
26
|
introLines.push(`Verify: ${verify}`);
|
|
28
|
-
const guidanceBlocks = channels.verification
|
|
29
|
-
|
|
27
|
+
const guidanceBlocks = channels.verification
|
|
28
|
+
.slice(0, 3)
|
|
29
|
+
.map((action, index) => ({
|
|
30
|
+
message: assessmentFields.reasoning[index] ?? action,
|
|
30
31
|
where: changed ?? "See scan detail for affected paths.",
|
|
31
32
|
action,
|
|
32
33
|
}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentScanDetails.d.ts","sourceRoot":"","sources":["../../../src/presentation/presenters/presentScanDetails.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"presentScanDetails.d.ts","sourceRoot":"","sources":["../../../src/presentation/presenters/presentScanDetails.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AACjF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AAGzF,MAAM,MAAM,yBAAyB,GAAG;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AA6FF,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,sBAAsB,EAC9B,GAAG,EAAE,yBAAyB,GAC7B,uBAAuB,CA6EzB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MERGE_CONCERN_LABELS } from "../../assessmentLabels.js";
|
|
2
2
|
import { normalizedPackageUsagePaths } from "../../narrativePresentation.js";
|
|
3
|
-
import {
|
|
3
|
+
import { formatPrRiskSummary, prRiskBandToGaugeBand, } from "../../prRiskBand.js";
|
|
4
4
|
import { MERGE_POSTURE_LABEL } from "../../riskVocabulary.js";
|
|
5
5
|
import { buildNarrativeChannels, composeSubheadline, composeSupportingContext, evidenceContextFromProfile, projectCompactKeyPoints, } from "../compose/narrativeCompose.js";
|
|
6
6
|
import { normalizeGeneratedText, normalizeGeneratedTextNullable, } from "../../normalizeGeneratedText.js";
|
|
@@ -79,7 +79,7 @@ function mapEvidence(bundle) {
|
|
|
79
79
|
};
|
|
80
80
|
}
|
|
81
81
|
export function presentScanDetails(bundle, ctx) {
|
|
82
|
-
const {
|
|
82
|
+
const { facts, profile } = bundle;
|
|
83
83
|
const assessmentFields = projectAssessmentFields(bundle);
|
|
84
84
|
const channels = buildNarrativeChannels(bundle);
|
|
85
85
|
const keyPoints = projectCompactKeyPoints(channels, 6);
|
|
@@ -93,8 +93,8 @@ export function presentScanDetails(bundle, ctx) {
|
|
|
93
93
|
: undefined;
|
|
94
94
|
const postureLabel = MERGE_POSTURE_LABEL[profile.status];
|
|
95
95
|
const verdictLine = assessmentFields.reasoning[0] ??
|
|
96
|
-
(
|
|
97
|
-
? MERGE_CONCERN_LABELS[
|
|
96
|
+
(assessmentFields.primaryConcern
|
|
97
|
+
? MERGE_CONCERN_LABELS[assessmentFields.primaryConcern]
|
|
98
98
|
: postureLabel);
|
|
99
99
|
const verificationActions = channels.verification.map((title, index) => ({
|
|
100
100
|
title: normalizeGeneratedText(title),
|
|
@@ -110,10 +110,7 @@ export function presentScanDetails(bundle, ctx) {
|
|
|
110
110
|
: "low",
|
|
111
111
|
rationale: action.detail,
|
|
112
112
|
}));
|
|
113
|
-
const
|
|
114
|
-
const prRiskBandLabelText = facts.riskSignals?.band != null
|
|
115
|
-
? prRiskBandLabel(facts.riskSignals.band)
|
|
116
|
-
: scoreToBandLabel(prRiskScore);
|
|
113
|
+
const prRisk = formatPrRiskSummary(facts);
|
|
117
114
|
return {
|
|
118
115
|
...assessmentFields,
|
|
119
116
|
evidenceContext: evidenceContextFromProfile(bundle),
|
|
@@ -127,9 +124,9 @@ export function presentScanDetails(bundle, ctx) {
|
|
|
127
124
|
verdictLine: normalizeGeneratedText(verdictLine),
|
|
128
125
|
scopeChip: channels.reachLabel,
|
|
129
126
|
postureLabel,
|
|
130
|
-
prRiskScore,
|
|
131
|
-
prRiskBandLabel:
|
|
132
|
-
riskIndex: prRiskScore,
|
|
127
|
+
prRiskScore: prRisk?.prRiskScore ?? null,
|
|
128
|
+
prRiskBandLabel: prRisk?.prRiskBandLabel,
|
|
129
|
+
riskIndex: prRisk?.prRiskScore ?? null,
|
|
133
130
|
},
|
|
134
131
|
signalSummary: mapSignalSummary(bundle),
|
|
135
132
|
narrative: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projectAssessmentFields.d.ts","sourceRoot":"","sources":["../../src/presentation/projectAssessmentFields.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,uCAAuC,CAAC;AAC1F,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"projectAssessmentFields.d.ts","sourceRoot":"","sources":["../../src/presentation/projectAssessmentFields.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,uCAAuC,CAAC;AAC1F,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AAOxF,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,sBAAsB,GAC7B,4BAA4B,CAoB9B"}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { collectVerificationFocusForPresentation, projectReasoningLines, } from "../assessmentProjection.js";
|
|
2
|
+
function trimOptionalExpression(value) {
|
|
3
|
+
const trimmed = value?.trim();
|
|
4
|
+
return trimmed ? trimmed : undefined;
|
|
5
|
+
}
|
|
2
6
|
export function projectAssessmentFields(bundle) {
|
|
3
7
|
const { assessment, presentation, result } = bundle;
|
|
4
8
|
const { channel, focus } = collectVerificationFocusForPresentation(presentation, result);
|
|
@@ -11,5 +15,7 @@ export function projectAssessmentFields(bundle) {
|
|
|
11
15
|
verificationChannel: channel,
|
|
12
16
|
reachVisibility: presentation.reachVisibility,
|
|
13
17
|
narrativeIntensity: presentation.narrativeIntensity,
|
|
18
|
+
confidenceRationale: trimOptionalExpression(assessment.confidenceRationale),
|
|
19
|
+
electionSummary: trimOptionalExpression(assessment.reviewFocalPoint.electionSummary),
|
|
14
20
|
};
|
|
15
21
|
}
|
|
@@ -89,6 +89,14 @@ describe("surfaceParity guardrail", () => {
|
|
|
89
89
|
expect(s.details.verificationChannel).toBe(s.fields.verificationChannel);
|
|
90
90
|
expect(s.check.verificationChannel).toBe(s.fields.verificationChannel);
|
|
91
91
|
expect(s.comment.verificationChannel).toBe(s.fields.verificationChannel);
|
|
92
|
+
expect(s.card.confidenceRationale).toBe(s.fields.confidenceRationale);
|
|
93
|
+
expect(s.details.confidenceRationale).toBe(s.fields.confidenceRationale);
|
|
94
|
+
expect(s.check.confidenceRationale).toBe(s.fields.confidenceRationale);
|
|
95
|
+
expect(s.comment.confidenceRationale).toBe(s.fields.confidenceRationale);
|
|
96
|
+
expect(s.card.electionSummary).toBe(s.fields.electionSummary);
|
|
97
|
+
expect(s.details.electionSummary).toBe(s.fields.electionSummary);
|
|
98
|
+
expect(s.check.electionSummary).toBe(s.fields.electionSummary);
|
|
99
|
+
expect(s.comment.electionSummary).toBe(s.fields.electionSummary);
|
|
92
100
|
});
|
|
93
101
|
it(`${persona.name}: headline matches across card and details`, () => {
|
|
94
102
|
const s = surfacesFor(persona.result);
|
package/package.json
CHANGED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import type { ObservationSignalFamily } from "./cardObservationCatalog.js";
|
|
2
|
-
import type { NarrativeAvailabilityMode } from "./scanNarrativeFacts.js";
|
|
3
|
-
import type { MergePosture } from "./riskVocabulary.js";
|
|
4
|
-
import type { FindingSeverity, ScoreLayer } from "./types.js";
|
|
5
|
-
/** Max operational-impact rows before collapse on scan detail. */
|
|
6
|
-
export declare const TIER1_MAX_VISIBLE_IMPACTS = 3;
|
|
7
|
-
/** Findings list collapse threshold on scan detail evidence panel. */
|
|
8
|
-
export declare const ACT3_EVIDENCE_COLLAPSE_THRESHOLD = 10;
|
|
9
|
-
export type ScanDetailOverallRiskBand = "low" | "moderate" | "high";
|
|
10
|
-
export type ScanDetailLayerConcernLevel = "low" | "medium" | "high";
|
|
11
|
-
export type ScanDetailSignalLayer = {
|
|
12
|
-
layer: ScoreLayer;
|
|
13
|
-
label: string;
|
|
14
|
-
score: number;
|
|
15
|
-
concernLevel: ScanDetailLayerConcernLevel;
|
|
16
|
-
concernLabel: string;
|
|
17
|
-
};
|
|
18
|
-
export type RiskScoreGaugeModel = {
|
|
19
|
-
fillPercent: number;
|
|
20
|
-
band: ScanDetailOverallRiskBand;
|
|
21
|
-
ariaLabel: string;
|
|
22
|
-
};
|
|
23
|
-
export type ScanDetailSignalSummary = {
|
|
24
|
-
score: number;
|
|
25
|
-
overallBand: ScanDetailOverallRiskBand;
|
|
26
|
-
overallLabel: string;
|
|
27
|
-
gauge: RiskScoreGaugeModel;
|
|
28
|
-
layers: ScanDetailSignalLayer[];
|
|
29
|
-
};
|
|
30
|
-
export type RecommendationPriority = "high" | "medium" | "low";
|
|
31
|
-
export type GuidanceSource = "insight" | "recommendation" | "verification";
|
|
32
|
-
export type ScanDetailRecommendationDetail = {
|
|
33
|
-
why: string;
|
|
34
|
-
whyNow: string;
|
|
35
|
-
signals: string[];
|
|
36
|
-
affectedPackages?: {
|
|
37
|
-
names: string[];
|
|
38
|
-
overflowCount: number;
|
|
39
|
-
};
|
|
40
|
-
expectedBenefit: string;
|
|
41
|
-
};
|
|
42
|
-
export type ScanDetailRecommendation = {
|
|
43
|
-
id: string;
|
|
44
|
-
rank: number;
|
|
45
|
-
title: string;
|
|
46
|
-
priority: RecommendationPriority;
|
|
47
|
-
source: GuidanceSource;
|
|
48
|
-
signalFamily?: ObservationSignalFamily | null;
|
|
49
|
-
detail: ScanDetailRecommendationDetail;
|
|
50
|
-
proofRefs?: {
|
|
51
|
-
findingIds?: string[];
|
|
52
|
-
};
|
|
53
|
-
};
|
|
54
|
-
export type ScanDetailRecommendationCenter = {
|
|
55
|
-
heading: string;
|
|
56
|
-
defaultSelectedId: string;
|
|
57
|
-
items: ScanDetailRecommendation[];
|
|
58
|
-
posture: MergePosture | null;
|
|
59
|
-
scanContext?: string;
|
|
60
|
-
};
|
|
61
|
-
export type ScanDetailOperationalImpactItem = {
|
|
62
|
-
message: string;
|
|
63
|
-
where?: string;
|
|
64
|
-
verify?: string;
|
|
65
|
-
affectedFiles?: string[];
|
|
66
|
-
};
|
|
67
|
-
export type ScanDetailOperationalImpact = {
|
|
68
|
-
status: "rich" | "fallback" | "hidden";
|
|
69
|
-
items: ScanDetailOperationalImpactItem[];
|
|
70
|
-
fallbackMessage?: string;
|
|
71
|
-
};
|
|
72
|
-
export type ScanDetailVerdict = {
|
|
73
|
-
posture: MergePosture | null;
|
|
74
|
-
scopeChip: string | null;
|
|
75
|
-
verdictLine: string;
|
|
76
|
-
prLabel?: string;
|
|
77
|
-
statusLabel?: string;
|
|
78
|
-
};
|
|
79
|
-
export type ScanDetailAttentionPackage = {
|
|
80
|
-
name: string;
|
|
81
|
-
version?: string;
|
|
82
|
-
direct: boolean;
|
|
83
|
-
severity?: FindingSeverity;
|
|
84
|
-
evidence?: string;
|
|
85
|
-
};
|
|
86
|
-
export type ScanDetailAttentionArea = {
|
|
87
|
-
problemLabel: string;
|
|
88
|
-
problemDescription: string;
|
|
89
|
-
packages: ScanDetailAttentionPackage[];
|
|
90
|
-
overflowCount: number;
|
|
91
|
-
};
|
|
92
|
-
export type ScanDetailFindingRow = {
|
|
93
|
-
id: string;
|
|
94
|
-
severity: FindingSeverity;
|
|
95
|
-
title: string;
|
|
96
|
-
description: string;
|
|
97
|
-
packageName: string;
|
|
98
|
-
recommendation?: string;
|
|
99
|
-
source: "dependency" | "code";
|
|
100
|
-
coveredByRecommendationRank?: number;
|
|
101
|
-
};
|
|
102
|
-
export type ScanDetailTopology = {
|
|
103
|
-
summaryLine: string;
|
|
104
|
-
deepest: Array<{
|
|
105
|
-
packageName: string;
|
|
106
|
-
depth: number;
|
|
107
|
-
direct: boolean;
|
|
108
|
-
via: string[];
|
|
109
|
-
}>;
|
|
110
|
-
};
|
|
111
|
-
export type ScanDetailNarrativeContext = {
|
|
112
|
-
mode: NarrativeAvailabilityMode;
|
|
113
|
-
codeIntelligenceAvailable: boolean;
|
|
114
|
-
changedPackagesDisplay: string | null;
|
|
115
|
-
runtimeSurfaceLabel: string | null;
|
|
116
|
-
reachabilityLabel: string | null;
|
|
117
|
-
blastRadiusLabel: string | null;
|
|
118
|
-
affectedAreas: string[];
|
|
119
|
-
structuralOnlyDisclaimer: string | null;
|
|
120
|
-
usageHighlights: string[];
|
|
121
|
-
frameworks: string[];
|
|
122
|
-
blastRadiusFactors: string[];
|
|
123
|
-
hotspotNames: string[];
|
|
124
|
-
usageContextLine: string | null;
|
|
125
|
-
upgradeContextLine: string | null;
|
|
126
|
-
};
|
|
127
|
-
export type ScanDetailViewModel = {
|
|
128
|
-
verdict: ScanDetailVerdict;
|
|
129
|
-
signalSummary: ScanDetailSignalSummary | null;
|
|
130
|
-
followUpBridgeNote: string | null;
|
|
131
|
-
recommendedActions: ScanDetailRecommendationCenter;
|
|
132
|
-
operationalImpact: ScanDetailOperationalImpact;
|
|
133
|
-
because: {
|
|
134
|
-
themes: string[];
|
|
135
|
-
confidenceCaveat?: string;
|
|
136
|
-
} | null;
|
|
137
|
-
evidence: {
|
|
138
|
-
attentionAreas: ScanDetailAttentionArea[];
|
|
139
|
-
findings: ScanDetailFindingRow[];
|
|
140
|
-
findingsOverflowCount: number;
|
|
141
|
-
topology: ScanDetailTopology | null;
|
|
142
|
-
} | null;
|
|
143
|
-
repoContext: {
|
|
144
|
-
status: "hidden";
|
|
145
|
-
} | {
|
|
146
|
-
status: "loaded";
|
|
147
|
-
comparisonLine: string;
|
|
148
|
-
};
|
|
149
|
-
narrativeContext: ScanDetailNarrativeContext;
|
|
150
|
-
metadata: {
|
|
151
|
-
scanId: string;
|
|
152
|
-
generatedAt?: string;
|
|
153
|
-
methodologyVersion?: string | null;
|
|
154
|
-
changedPackagesSummary?: string;
|
|
155
|
-
codeAnalysisTimedOut?: boolean;
|
|
156
|
-
codeIntelligenceAvailable?: boolean;
|
|
157
|
-
};
|
|
158
|
-
};
|
|
159
|
-
//# sourceMappingURL=scanDetailViewModelTypes.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scanDetailViewModelTypes.d.ts","sourceRoot":"","sources":["../src/scanDetailViewModelTypes.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1,23 +0,0 @@
|
|
|
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
|
-
}
|