@mergesignal/shared 0.8.1 → 0.9.0

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.
Files changed (72) hide show
  1. package/dist/deriveScanNarrative.test.js +2 -2
  2. package/dist/fixtures/engineAbi4Fixtures.d.ts +4 -0
  3. package/dist/fixtures/engineAbi4Fixtures.d.ts.map +1 -0
  4. package/dist/fixtures/engineAbi4Fixtures.js +5 -0
  5. package/dist/index.d.ts +2 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +2 -1
  8. package/dist/prRiskBand.d.ts +23 -0
  9. package/dist/prRiskBand.d.ts.map +1 -0
  10. package/dist/prRiskBand.js +66 -0
  11. package/dist/prRiskBand.test.d.ts +2 -0
  12. package/dist/prRiskBand.test.d.ts.map +1 -0
  13. package/dist/prRiskBand.test.js +57 -0
  14. package/dist/prRiskWire.d.ts +57 -0
  15. package/dist/prRiskWire.d.ts.map +1 -0
  16. package/dist/prRiskWire.js +98 -0
  17. package/dist/prRiskWire.test.d.ts +2 -0
  18. package/dist/prRiskWire.test.d.ts.map +1 -0
  19. package/dist/prRiskWire.test.js +106 -0
  20. package/dist/presentGitHubPrComment.d.ts.map +1 -1
  21. package/dist/presentGitHubPrComment.js +0 -1
  22. package/dist/presentation/dto/githubAndCliPresentation.d.ts +3 -0
  23. package/dist/presentation/dto/githubAndCliPresentation.d.ts.map +1 -1
  24. package/dist/presentation/dto/scanDetailsPresentation.d.ts +5 -2
  25. package/dist/presentation/dto/scanDetailsPresentation.d.ts.map +1 -1
  26. package/dist/presentation/orchestration/buildScanCardPresentation.d.ts +2 -1
  27. package/dist/presentation/orchestration/buildScanCardPresentation.d.ts.map +1 -1
  28. package/dist/presentation/orchestration/buildScanCardPresentation.js +7 -6
  29. package/dist/presentation/orchestration/buildScanDetailsPresentation.d.ts +1 -1
  30. package/dist/presentation/orchestration/buildScanDetailsPresentation.d.ts.map +1 -1
  31. package/dist/presentation/orchestration/buildScanDetailsPresentation.js +0 -1
  32. package/dist/presentation/orchestration/buildScanPresentationBundle.d.ts +0 -1
  33. package/dist/presentation/orchestration/buildScanPresentationBundle.d.ts.map +1 -1
  34. package/dist/presentation/presenters/presentCliScanSummary.d.ts.map +1 -1
  35. package/dist/presentation/presenters/presentCliScanSummary.js +9 -4
  36. package/dist/presentation/presenters/presentGitHubCheckRun.d.ts.map +1 -1
  37. package/dist/presentation/presenters/presentGitHubCheckRun.js +10 -0
  38. package/dist/presentation/presenters/presentGitHubPrComment.d.ts.map +1 -1
  39. package/dist/presentation/presenters/presentGitHubPrComment.js +6 -0
  40. package/dist/presentation/presenters/presentScanDetails.d.ts.map +1 -1
  41. package/dist/presentation/presenters/presentScanDetails.js +46 -3
  42. package/dist/presentation/render/renderCliScanSummaryText.d.ts.map +1 -1
  43. package/dist/presentation/render/renderCliScanSummaryText.js +4 -1
  44. package/dist/productMessaging.d.ts +2 -2
  45. package/dist/productMessaging.d.ts.map +1 -1
  46. package/dist/productMessaging.js +3 -3
  47. package/dist/productMessaging.test.js +6 -6
  48. package/dist/resolvePipelineStatus.d.ts +4 -3
  49. package/dist/resolvePipelineStatus.d.ts.map +1 -1
  50. package/dist/resolvePipelineStatus.js +3 -3
  51. package/dist/riskSignals.d.ts +6 -6
  52. package/dist/riskSignals.d.ts.map +1 -1
  53. package/dist/riskSignals.js +9 -10
  54. package/dist/riskVocabulary.js +7 -7
  55. package/dist/scanPresentationBundle.golden.test.js +3 -3
  56. package/dist/scanResultSchema.d.ts +42 -1
  57. package/dist/scanResultSchema.d.ts.map +1 -1
  58. package/dist/scanResultSchema.js +35 -2
  59. package/dist/scanResultSchema.test.js +15 -2
  60. package/dist/scanSurfaceCopy.d.ts +4 -2
  61. package/dist/scanSurfaceCopy.d.ts.map +1 -1
  62. package/dist/scanSurfaceCopy.js +4 -2
  63. package/dist/trustedScanGuards.test.js +3 -2
  64. package/dist/types.d.ts +17 -0
  65. package/dist/types.d.ts.map +1 -1
  66. package/package.json +1 -1
  67. package/dist/formatCardExposureDisplay.d.ts +0 -22
  68. package/dist/formatCardExposureDisplay.d.ts.map +0 -1
  69. package/dist/formatCardExposureDisplay.js +0 -63
  70. package/dist/formatCardExposureDisplay.test.d.ts +0 -2
  71. package/dist/formatCardExposureDisplay.test.d.ts.map +0 -1
  72. package/dist/formatCardExposureDisplay.test.js +0 -44
@@ -256,10 +256,10 @@ describe("deriveScanNarrative", () => {
256
256
  expect(apiArea?.hotspotPackages).toContain("fastify");
257
257
  expect(apiArea?.verificationFocus).toContain("routes");
258
258
  });
259
- it("derives riskSignals with exposure layers", () => {
259
+ it("derives riskSignals with PR Risk bands", () => {
260
260
  const facts = deriveScanNarrative(baseResult);
261
261
  expect(facts.riskSignals?.riskIndex).toBe(10);
262
- expect(facts.riskSignals?.exposure).toBe("minimal");
262
+ expect(facts.riskSignals?.band).toBe("very_low");
263
263
  expect(facts.riskSignals?.layers).toHaveLength(4);
264
264
  expect(facts.riskIndex).toBe(10);
265
265
  });
@@ -0,0 +1,4 @@
1
+ import type { ScanResult } from "../types.js";
2
+ /** Attach ABI-4 prRisk + repositoryHealth wire blocks for strict engine validation tests. */
3
+ export declare function withAbi4EngineScores<T extends ScanResult>(result: T): T;
4
+ //# sourceMappingURL=engineAbi4Fixtures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engineAbi4Fixtures.d.ts","sourceRoot":"","sources":["../../src/fixtures/engineAbi4Fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,6FAA6F;AAC7F,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,UAAU,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAEvE"}
@@ -0,0 +1,5 @@
1
+ import { normalizeEngineOutputAbi4 } from "../scanResultSchema.js";
2
+ /** Attach ABI-4 prRisk + repositoryHealth wire blocks for strict engine validation tests. */
3
+ export function withAbi4EngineScores(result) {
4
+ return normalizeEngineOutputAbi4(result);
5
+ }
package/dist/index.d.ts CHANGED
@@ -7,7 +7,8 @@ export * from "./selectTopAffectedAreas.js";
7
7
  export * from "./cardSummaryCopy.js";
8
8
  export * from "./truncateCardSummary.js";
9
9
  export * from "./formatCardAreaLabels.js";
10
- export * from "./formatCardExposureDisplay.js";
10
+ export * from "./prRiskBand.js";
11
+ export * from "./prRiskWire.js";
11
12
  export * from "./cardObservationCatalog.js";
12
13
  export * from "./scanNarrativeFacts.js";
13
14
  export * from "./repoIntelligenceSchema.js";
@@ -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,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gCAAgC,CAAC;AAC/C,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,+BAA+B,CAAC;AAC9C,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,uBAAuB,EACvB,aAAa,EACb,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,cAAc,EACd,yBAAyB,GAC1B,MAAM,kCAAkC,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,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,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,+BAA+B,CAAC;AAC9C,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,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
@@ -7,7 +7,8 @@ export * from "./selectTopAffectedAreas.js";
7
7
  export * from "./cardSummaryCopy.js";
8
8
  export * from "./truncateCardSummary.js";
9
9
  export * from "./formatCardAreaLabels.js";
10
- export * from "./formatCardExposureDisplay.js";
10
+ export * from "./prRiskBand.js";
11
+ export * from "./prRiskWire.js";
11
12
  export * from "./cardObservationCatalog.js";
12
13
  export * from "./scanNarrativeFacts.js";
13
14
  export * from "./repoIntelligenceSchema.js";
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Canonical PR Risk band contract — sole authority for PR Risk band derivation.
3
+ * Independent from legacy exposure presentation and merge verdict (`assessment.posture`).
4
+ */
5
+ export declare const PR_RISK_BAND_ABI: "1";
6
+ /** Inclusive upper bounds (0–100). Five stable PR Risk bands. */
7
+ export declare const PR_RISK_BAND_THRESHOLDS: readonly [19, 44, 64, 84, 100];
8
+ export type PrRiskBand = "very_low" | "low" | "medium" | "high" | "critical";
9
+ /** User-facing PR Risk band labels (low → high). */
10
+ export declare const PR_RISK_BAND_LABELS: readonly string[];
11
+ /** Scan-detail gauge projection — not a second threshold table. */
12
+ export type PrRiskGaugeBand = "low" | "moderate" | "high";
13
+ /** Map numeric PR risk score to canonical band enum. */
14
+ export declare function scoreToBand(score: number | null | undefined): PrRiskBand | null;
15
+ /** Map numeric PR risk score to user-facing band label (presentation only). */
16
+ export declare function scoreToBandLabel(score: number | null | undefined): string | null;
17
+ /** Label for a known band enum value. */
18
+ export declare function prRiskBandLabel(band: PrRiskBand): string;
19
+ /** Fragment for composite aria labels on PR surfaces. */
20
+ export declare function prRiskBandAriaFragment(score: number | null | undefined): string | null;
21
+ /** Project 5-band PR Risk to 3-bucket scan-detail gauge band. */
22
+ export declare function prRiskBandToGaugeBand(band: PrRiskBand): PrRiskGaugeBand;
23
+ //# sourceMappingURL=prRiskBand.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Canonical PR Risk band contract — sole authority for PR Risk band derivation.
3
+ * Independent from legacy exposure presentation and merge verdict (`assessment.posture`).
4
+ */
5
+ export const PR_RISK_BAND_ABI = "1";
6
+ /** Inclusive upper bounds (0–100). Five stable PR Risk bands. */
7
+ export const PR_RISK_BAND_THRESHOLDS = [19, 44, 64, 84, 100];
8
+ const BAND_LABEL = {
9
+ very_low: "Very Low",
10
+ low: "Low",
11
+ medium: "Medium",
12
+ high: "High",
13
+ critical: "Critical",
14
+ };
15
+ /** User-facing PR Risk band labels (low → high). */
16
+ export const PR_RISK_BAND_LABELS = [
17
+ BAND_LABEL.very_low,
18
+ BAND_LABEL.low,
19
+ BAND_LABEL.medium,
20
+ BAND_LABEL.high,
21
+ BAND_LABEL.critical,
22
+ ];
23
+ const BAND_ORDER = [
24
+ "very_low",
25
+ "low",
26
+ "medium",
27
+ "high",
28
+ "critical",
29
+ ];
30
+ function clampScore(score) {
31
+ if (!Number.isFinite(score))
32
+ return 0;
33
+ return Math.min(100, Math.max(0, Math.round(score)));
34
+ }
35
+ /** Map numeric PR risk score to canonical band enum. */
36
+ export function scoreToBand(score) {
37
+ if (score == null || !Number.isFinite(score))
38
+ return null;
39
+ const value = clampScore(score);
40
+ const idx = PR_RISK_BAND_THRESHOLDS.findIndex((bound) => value <= bound);
41
+ return BAND_ORDER[idx >= 0 ? idx : BAND_ORDER.length - 1];
42
+ }
43
+ /** Map numeric PR risk score to user-facing band label (presentation only). */
44
+ export function scoreToBandLabel(score) {
45
+ const band = scoreToBand(score);
46
+ return band ? BAND_LABEL[band] : null;
47
+ }
48
+ /** Label for a known band enum value. */
49
+ export function prRiskBandLabel(band) {
50
+ return BAND_LABEL[band];
51
+ }
52
+ /** Fragment for composite aria labels on PR surfaces. */
53
+ export function prRiskBandAriaFragment(score) {
54
+ const label = scoreToBandLabel(score);
55
+ if (!label)
56
+ return null;
57
+ return `PR Risk: ${label}`;
58
+ }
59
+ /** Project 5-band PR Risk to 3-bucket scan-detail gauge band. */
60
+ export function prRiskBandToGaugeBand(band) {
61
+ if (band === "critical" || band === "high")
62
+ return "high";
63
+ if (band === "medium")
64
+ return "moderate";
65
+ return "low";
66
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=prRiskBand.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prRiskBand.test.d.ts","sourceRoot":"","sources":["../src/prRiskBand.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,57 @@
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";
3
+ describe("PR_RISK_BAND_ABI", () => {
4
+ it("is stable v1", () => {
5
+ expect(PR_RISK_BAND_ABI).toBe("1");
6
+ expect(PR_RISK_BAND_THRESHOLDS).toEqual([19, 44, 64, 84, 100]);
7
+ });
8
+ });
9
+ describe("scoreToBand", () => {
10
+ it("maps approved boundary cut points", () => {
11
+ expect(scoreToBand(0)).toBe("very_low");
12
+ expect(scoreToBand(19)).toBe("very_low");
13
+ expect(scoreToBand(20)).toBe("low");
14
+ expect(scoreToBand(44)).toBe("low");
15
+ expect(scoreToBand(45)).toBe("medium");
16
+ expect(scoreToBand(64)).toBe("medium");
17
+ expect(scoreToBand(65)).toBe("high");
18
+ expect(scoreToBand(84)).toBe("high");
19
+ expect(scoreToBand(85)).toBe("critical");
20
+ expect(scoreToBand(100)).toBe("critical");
21
+ });
22
+ it("returns null for invalid input", () => {
23
+ expect(scoreToBand(null)).toBeNull();
24
+ expect(scoreToBand(NaN)).toBeNull();
25
+ });
26
+ it("clamps out-of-range values", () => {
27
+ expect(scoreToBand(150)).toBe("critical");
28
+ expect(scoreToBand(-5)).toBe("very_low");
29
+ expect(scoreToBand(71.6)).toBe("high");
30
+ });
31
+ });
32
+ describe("scoreToBandLabel", () => {
33
+ it("returns presentation labels", () => {
34
+ expect(scoreToBandLabel(10)).toBe("Very Low");
35
+ expect(scoreToBandLabel(55)).toBe("Medium");
36
+ expect(scoreToBandLabel(90)).toBe("Critical");
37
+ });
38
+ });
39
+ describe("prRiskBandLabel", () => {
40
+ it("labels enum values", () => {
41
+ expect(prRiskBandLabel("medium")).toBe("Medium");
42
+ });
43
+ });
44
+ describe("prRiskBandAriaFragment", () => {
45
+ it("prefixes PR Risk", () => {
46
+ expect(prRiskBandAriaFragment(55)).toBe("PR Risk: Medium");
47
+ });
48
+ });
49
+ describe("prRiskBandToGaugeBand", () => {
50
+ it("projects to three gauge buckets", () => {
51
+ expect(prRiskBandToGaugeBand("very_low")).toBe("low");
52
+ expect(prRiskBandToGaugeBand("low")).toBe("low");
53
+ expect(prRiskBandToGaugeBand("medium")).toBe("moderate");
54
+ expect(prRiskBandToGaugeBand("high")).toBe("high");
55
+ expect(prRiskBandToGaugeBand("critical")).toBe("high");
56
+ });
57
+ });
@@ -0,0 +1,57 @@
1
+ import type { LayerScores, PrRiskWire, RepositoryHealthWire, ScanResult, ScoreLayer } from "./types.js";
2
+ export type { PrRiskWire, RepositoryHealthWire };
3
+ export type PrRiskScoreContext = {
4
+ /** Denormalized pr_risk_score column when result JSON is absent. */
5
+ prRiskScore?: number | null;
6
+ /**
7
+ * Historical scans.total_score column — fallback only when prRisk wire and
8
+ * pr_risk_score are both absent (pre-migration rows).
9
+ */
10
+ legacyTotalScore?: number | null;
11
+ };
12
+ export type RepositoryHealthScoreContext = {
13
+ /** Denormalized repository_health_score column when result JSON is absent. */
14
+ repositoryHealthScore?: number | null;
15
+ /** When true, legacy totalScore must not be used as repository health. */
16
+ isPrScan?: boolean;
17
+ /**
18
+ * Historical scans.total_score column — fallback only for non-PR scans when
19
+ * repositoryHealth wire and repository_health_score are both absent.
20
+ */
21
+ legacyTotalScore?: number | null;
22
+ };
23
+ export type ScanScoreRow = {
24
+ pr_risk_score?: number | null;
25
+ repository_health_score?: number | null;
26
+ /** Historical scans.total_score column — never authoritative for new rows. */
27
+ total_score?: number | null;
28
+ github_pr_number?: number | null;
29
+ result?: unknown;
30
+ };
31
+ /**
32
+ * PR Risk score authority chain:
33
+ * 1. result.prRisk.score
34
+ * 2. denormalized pr_risk_score (when provided)
35
+ * 3. historical scans.total_score column (when provided)
36
+ * 4. result.totalScore (historical JSON fallback only)
37
+ */
38
+ export declare function resolvePrRiskScore(result: ScanResult | null | undefined, ctx?: PrRiskScoreContext): number | null;
39
+ /** Layer scores for PR Risk — prRisk.layerScores when present, else legacy layerScores. */
40
+ export declare function resolvePrRiskLayerScores(result: ScanResult | null | undefined): LayerScores | null;
41
+ export declare function resolvePrRiskLayerEntries(result: ScanResult | null | undefined): Array<{
42
+ layer: ScoreLayer;
43
+ score: number;
44
+ }>;
45
+ /**
46
+ * Repository health score authority chain:
47
+ * 1. result.repositoryHealth.totalScore
48
+ * 2. denormalized repository_health_score
49
+ * 3. historical scans.total_score column (non-PR scans only)
50
+ * 4. result.totalScore (non-PR JSON fallback only)
51
+ */
52
+ export declare function resolveRepositoryHealthScore(result: ScanResult | null | undefined, ctx?: RepositoryHealthScoreContext): number | null;
53
+ /** Resolve PR risk from a DB scan row (wire + denorm + historical column). */
54
+ export declare function resolvePrRiskScoreFromRow(row: ScanScoreRow): number | null;
55
+ /** Resolve repository health from a DB scan row (wire + denorm + historical column). */
56
+ export declare function resolveRepositoryHealthScoreFromRow(row: ScanScoreRow): number | null;
57
+ //# sourceMappingURL=prRiskWire.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prRiskWire.d.ts","sourceRoot":"","sources":["../src/prRiskWire.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,UAAU,EACV,UAAU,EACX,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,UAAU,EAAE,oBAAoB,EAAE,CAAC;AAEjD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,8EAA8E;IAC9E,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,uBAAuB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAWF;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,EACrC,GAAG,GAAE,kBAAuB,GAC3B,MAAM,GAAG,IAAI,CAef;AASD,2FAA2F;AAC3F,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,GACpC,WAAW,GAAG,IAAI,CAMpB;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,GACpC,KAAK,CAAC;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAO7C;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,EACrC,GAAG,GAAE,4BAAiC,GACrC,MAAM,GAAG,IAAI,CAqBf;AAED,8EAA8E;AAC9E,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAK1E;AAED,wFAAwF;AACxF,wBAAgB,mCAAmC,CACjD,GAAG,EAAE,YAAY,GAChB,MAAM,GAAG,IAAI,CAQf"}
@@ -0,0 +1,98 @@
1
+ function finiteScore(value) {
2
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
3
+ }
4
+ function asScanResult(result) {
5
+ if (!result || typeof result !== "object")
6
+ return null;
7
+ return result;
8
+ }
9
+ /**
10
+ * PR Risk score authority chain:
11
+ * 1. result.prRisk.score
12
+ * 2. denormalized pr_risk_score (when provided)
13
+ * 3. historical scans.total_score column (when provided)
14
+ * 4. result.totalScore (historical JSON fallback only)
15
+ */
16
+ export function resolvePrRiskScore(result, ctx = {}) {
17
+ if (!result && ctx.prRiskScore == null && ctx.legacyTotalScore == null) {
18
+ return null;
19
+ }
20
+ const fromWire = finiteScore(result?.prRisk?.score);
21
+ if (fromWire != null)
22
+ return fromWire;
23
+ const fromDenorm = finiteScore(ctx.prRiskScore);
24
+ if (fromDenorm != null)
25
+ return fromDenorm;
26
+ const fromLegacyColumn = finiteScore(ctx.legacyTotalScore);
27
+ if (fromLegacyColumn != null)
28
+ return fromLegacyColumn;
29
+ return finiteScore(result?.totalScore);
30
+ }
31
+ const LAYER_ORDER = [
32
+ "security",
33
+ "maintainability",
34
+ "ecosystem",
35
+ "upgradeImpact",
36
+ ];
37
+ /** Layer scores for PR Risk — prRisk.layerScores when present, else legacy layerScores. */
38
+ export function resolvePrRiskLayerScores(result) {
39
+ if (!result)
40
+ return null;
41
+ const fromPrRisk = result.prRisk?.layerScores;
42
+ if (fromPrRisk)
43
+ return fromPrRisk;
44
+ if (result.layerScores)
45
+ return result.layerScores;
46
+ return null;
47
+ }
48
+ export function resolvePrRiskLayerEntries(result) {
49
+ const layerScores = resolvePrRiskLayerScores(result);
50
+ if (!layerScores)
51
+ return [];
52
+ return LAYER_ORDER.map((layer) => ({
53
+ layer,
54
+ score: layerScores[layer],
55
+ }));
56
+ }
57
+ /**
58
+ * Repository health score authority chain:
59
+ * 1. result.repositoryHealth.totalScore
60
+ * 2. denormalized repository_health_score
61
+ * 3. historical scans.total_score column (non-PR scans only)
62
+ * 4. result.totalScore (non-PR JSON fallback only)
63
+ */
64
+ export function resolveRepositoryHealthScore(result, ctx = {}) {
65
+ if (!result &&
66
+ ctx.repositoryHealthScore == null &&
67
+ ctx.legacyTotalScore == null) {
68
+ return null;
69
+ }
70
+ const fromWire = finiteScore(result?.repositoryHealth?.totalScore);
71
+ if (fromWire != null)
72
+ return fromWire;
73
+ const fromDenorm = finiteScore(ctx.repositoryHealthScore);
74
+ if (fromDenorm != null)
75
+ return fromDenorm;
76
+ if (ctx.isPrScan)
77
+ return null;
78
+ const fromLegacyColumn = finiteScore(ctx.legacyTotalScore);
79
+ if (fromLegacyColumn != null)
80
+ return fromLegacyColumn;
81
+ return finiteScore(result?.totalScore);
82
+ }
83
+ /** Resolve PR risk from a DB scan row (wire + denorm + historical column). */
84
+ export function resolvePrRiskScoreFromRow(row) {
85
+ return resolvePrRiskScore(asScanResult(row.result), {
86
+ prRiskScore: row.pr_risk_score,
87
+ legacyTotalScore: row.total_score,
88
+ });
89
+ }
90
+ /** Resolve repository health from a DB scan row (wire + denorm + historical column). */
91
+ export function resolveRepositoryHealthScoreFromRow(row) {
92
+ const isPrScan = row.github_pr_number != null && Number.isFinite(row.github_pr_number);
93
+ return resolveRepositoryHealthScore(asScanResult(row.result), {
94
+ repositoryHealthScore: row.repository_health_score,
95
+ isPrScan,
96
+ legacyTotalScore: row.total_score,
97
+ });
98
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=prRiskWire.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prRiskWire.test.d.ts","sourceRoot":"","sources":["../src/prRiskWire.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,106 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { resolvePrRiskLayerScores, resolvePrRiskScore, resolvePrRiskScoreFromRow, resolveRepositoryHealthScore, resolveRepositoryHealthScoreFromRow, } from "./prRiskWire.js";
3
+ function baseResult(overrides = {}) {
4
+ return {
5
+ totalScore: 50,
6
+ layerScores: {
7
+ security: 10,
8
+ maintainability: 20,
9
+ ecosystem: 30,
10
+ upgradeImpact: 40,
11
+ },
12
+ findings: [],
13
+ generatedAt: "2026-01-01T00:00:00.000Z",
14
+ ...overrides,
15
+ };
16
+ }
17
+ describe("resolvePrRiskScore", () => {
18
+ it("prefers prRisk.score", () => {
19
+ const result = baseResult({
20
+ prRisk: { score: 72 },
21
+ totalScore: 50,
22
+ });
23
+ expect(resolvePrRiskScore(result)).toBe(72);
24
+ });
25
+ it("falls back to denormalized column", () => {
26
+ expect(resolvePrRiskScore(null, { prRiskScore: 61 })).toBe(61);
27
+ });
28
+ it("falls back to legacy total_score column before JSON totalScore", () => {
29
+ expect(resolvePrRiskScore(null, { legacyTotalScore: 48 })).toBe(48);
30
+ });
31
+ it("falls back to JSON totalScore for historical scans", () => {
32
+ expect(resolvePrRiskScore(baseResult({ totalScore: 48 }))).toBe(48);
33
+ });
34
+ it("returns null when no score available", () => {
35
+ expect(resolvePrRiskScore(baseResult({ totalScore: NaN }))).toBeNull();
36
+ });
37
+ });
38
+ describe("resolvePrRiskScoreFromRow", () => {
39
+ it("uses pr_risk_score for new rows without legacy column", () => {
40
+ expect(resolvePrRiskScoreFromRow({
41
+ pr_risk_score: 55,
42
+ total_score: null,
43
+ })).toBe(55);
44
+ });
45
+ it("uses legacy total_score only when pr_risk_score is absent", () => {
46
+ expect(resolvePrRiskScoreFromRow({
47
+ pr_risk_score: null,
48
+ total_score: 40,
49
+ })).toBe(40);
50
+ });
51
+ });
52
+ describe("resolvePrRiskLayerScores", () => {
53
+ it("prefers prRisk.layerScores", () => {
54
+ const layers = {
55
+ security: 1,
56
+ maintainability: 2,
57
+ ecosystem: 3,
58
+ upgradeImpact: 4,
59
+ };
60
+ const result = baseResult({ prRisk: { score: 10, layerScores: layers } });
61
+ expect(resolvePrRiskLayerScores(result)).toEqual(layers);
62
+ });
63
+ });
64
+ describe("resolveRepositoryHealthScore", () => {
65
+ it("prefers repositoryHealth.totalScore", () => {
66
+ const result = baseResult({
67
+ repositoryHealth: { totalScore: 80 },
68
+ totalScore: 50,
69
+ });
70
+ expect(resolveRepositoryHealthScore(result)).toBe(80);
71
+ });
72
+ it("falls back to denormalized column", () => {
73
+ expect(resolveRepositoryHealthScore(null, { repositoryHealthScore: 66 })).toBe(66);
74
+ });
75
+ it("falls back to legacy total_score column for non-PR scans", () => {
76
+ expect(resolveRepositoryHealthScore(null, { legacyTotalScore: 55 })).toBe(55);
77
+ });
78
+ it("uses JSON totalScore only for non-PR scans", () => {
79
+ expect(resolveRepositoryHealthScore(baseResult({ totalScore: 55 }))).toBe(55);
80
+ });
81
+ it("does not use legacy scores for PR scans", () => {
82
+ expect(resolveRepositoryHealthScore(null, {
83
+ legacyTotalScore: 55,
84
+ isPrScan: true,
85
+ })).toBeNull();
86
+ expect(resolveRepositoryHealthScore(baseResult({ totalScore: 55 }), {
87
+ isPrScan: true,
88
+ })).toBeNull();
89
+ });
90
+ });
91
+ describe("resolveRepositoryHealthScoreFromRow", () => {
92
+ it("uses repository_health_score for new rows", () => {
93
+ expect(resolveRepositoryHealthScoreFromRow({
94
+ repository_health_score: 70,
95
+ total_score: null,
96
+ github_pr_number: null,
97
+ })).toBe(70);
98
+ });
99
+ it("does not use total_score for PR scans", () => {
100
+ expect(resolveRepositoryHealthScoreFromRow({
101
+ repository_health_score: null,
102
+ total_score: 40,
103
+ github_pr_number: 12,
104
+ })).toBeNull();
105
+ });
106
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"presentGitHubPrComment.d.ts","sourceRoot":"","sources":["../src/presentGitHubPrComment.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;GAEG;AACH,wBAAgB,wCAAwC,CACtD,MAAM,EAAE,UAAU,GACjB,MAAM,CAWR"}
1
+ {"version":3,"file":"presentGitHubPrComment.d.ts","sourceRoot":"","sources":["../src/presentGitHubPrComment.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;GAEG;AACH,wBAAgB,wCAAwC,CACtD,MAAM,EAAE,UAAU,GACjB,MAAM,CAUR"}
@@ -9,7 +9,6 @@ export function presentGitHubPrCommentMarkdownFromResult(result) {
9
9
  result,
10
10
  pipelineStatus: "done",
11
11
  decision: result.decision?.recommendation,
12
- totalScore: result.totalScore,
13
12
  });
14
13
  if (!bundle)
15
14
  return "";
@@ -44,6 +44,9 @@ export type CliScanPresentation = AssessmentPresentationFields & {
44
44
  keyPoints: string[];
45
45
  verificationActions: string[];
46
46
  metrics?: {
47
+ prRiskScore: number;
48
+ prRiskBandLabel?: string;
49
+ /** @deprecated Use prRiskScore */
47
50
  riskIndex: number;
48
51
  layerLine: string;
49
52
  findingCount: number;
@@ -1 +1 @@
1
- {"version":3,"file":"githubAndCliPresentation.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/githubAndCliPresentation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;AACtF,OAAO,KAAK,EACV,sBAAsB,EACtB,mBAAmB,EACnB,2BAA2B,EAC3B,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,0BAA0B,GAAG,4BAA4B,GAAG;IACtE,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,UAAU,EAAE,sBAAsB,CAAC;IACnC,eAAe,EAAE,2BAA2B,CAAC;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,KAAK,CAAC;QACd,EAAE,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,GAAG,QAAQ,GAAG,QAAQ,CAAC;QACtE,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB,CAAC,CAAC;IACH,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG,4BAA4B,GAAG;IACvE,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,UAAU,EAAE,sBAAsB,CAAC;IACnC,eAAe,EAAE,2BAA2B,CAAC;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,cAAc,EAAE,KAAK,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACJ,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,4BAA4B,GAAG;IAC/D,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzE,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,UAAU,EAAE,sBAAsB,CAAC;IACnC,eAAe,EAAE,2BAA2B,CAAC;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE;QACR,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,mBAAmB,EAAE,MAAM,CAAC;KAC7B,CAAC;IACF,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B,CAAC"}
1
+ {"version":3,"file":"githubAndCliPresentation.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/githubAndCliPresentation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;AACtF,OAAO,KAAK,EACV,sBAAsB,EACtB,mBAAmB,EACnB,2BAA2B,EAC3B,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,0BAA0B,GAAG,4BAA4B,GAAG;IACtE,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,UAAU,EAAE,sBAAsB,CAAC;IACnC,eAAe,EAAE,2BAA2B,CAAC;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,KAAK,CAAC;QACd,EAAE,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,GAAG,QAAQ,GAAG,QAAQ,CAAC;QACtE,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB,CAAC,CAAC;IACH,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG,4BAA4B,GAAG;IACvE,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,UAAU,EAAE,sBAAsB,CAAC;IACnC,eAAe,EAAE,2BAA2B,CAAC;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,cAAc,EAAE,KAAK,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACJ,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,4BAA4B,GAAG;IAC/D,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzE,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,UAAU,EAAE,sBAAsB,CAAC;IACnC,eAAe,EAAE,2BAA2B,CAAC;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE;QACR,WAAW,EAAE,MAAM,CAAC;QACpB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,kCAAkC;QAClC,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,mBAAmB,EAAE,MAAM,CAAC;KAC7B,CAAC;IACF,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B,CAAC"}
@@ -13,6 +13,9 @@ export type ScanDetailsPresentation = AssessmentPresentationFields & {
13
13
  verdictLine: string;
14
14
  scopeChip?: string;
15
15
  postureLabel: string;
16
+ prRiskScore?: number | null;
17
+ prRiskBandLabel?: string;
18
+ /** @deprecated Use prRiskScore */
16
19
  riskIndex?: number | null;
17
20
  };
18
21
  narrative: {
@@ -38,12 +41,12 @@ export type ScanDetailsPresentation = AssessmentPresentationFields & {
38
41
  }>;
39
42
  };
40
43
  signalSummary?: {
41
- riskIndex: number;
44
+ prRiskScore: number;
42
45
  band: "low" | "medium" | "high";
43
46
  layers: Array<{
44
47
  layer: ScoreLayer;
45
48
  score: number;
46
- band: string;
49
+ band: "low" | "medium" | "high";
47
50
  label: string;
48
51
  }>;
49
52
  };
@@ -1 +1 @@
1
- {"version":3,"file":"scanDetailsPresentation.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/scanDetailsPresentation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scanDetailsPresentation.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/scanDetailsPresentation.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,8 @@ export type BuildScanCardPresentationInput = {
5
5
  pipelineStatus: PipelineStatus;
6
6
  result: ScanResult | null;
7
7
  decision?: string | null;
8
- totalScore?: number | null;
8
+ /** Denormalized PR risk score (preferred). */
9
+ prRiskScore?: number | null;
9
10
  };
10
11
  export declare function buildScanCardPresentation(input: BuildScanCardPresentationInput): DashboardCardPresentation;
11
12
  //# sourceMappingURL=buildScanCardPresentation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"buildScanCardPresentation.d.ts","sourceRoot":"","sources":["../../../src/presentation/orchestration/buildScanCardPresentation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAUjD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AAErF,MAAM,MAAM,8BAA8B,GAAG;IAC3C,cAAc,EAAE,cAAc,CAAC;IAC/B,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AA+BF,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,8BAA8B,GACpC,yBAAyB,CA2B3B"}
1
+ {"version":3,"file":"buildScanCardPresentation.d.ts","sourceRoot":"","sources":["../../../src/presentation/orchestration/buildScanCardPresentation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAUjD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AAErF,MAAM,MAAM,8BAA8B,GAAG;IAC3C,cAAc,EAAE,cAAc,CAAC;IAC/B,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,CAAC;AAiCF,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,8BAA8B,GACpC,yBAAyB,CA0B3B"}
@@ -2,14 +2,16 @@ import { assessmentLimitedContext } from "../../fixtures/assessmentFixtures.js";
2
2
  import { mergePostureFromDecision, } from "../../riskVocabulary.js";
3
3
  import { buildScanPresentationBundle } from "./buildScanPresentationBundle.js";
4
4
  import { presentDashboardCard, presentPipelineDashboardCard, } from "../presenters/presentDashboardCard.js";
5
- function minimalResultFromDenormalized(decision, totalScore) {
5
+ function minimalResultFromDenormalized(decision, prRiskScore) {
6
6
  const posture = mergePostureFromDecision(decision ?? undefined);
7
- if (!posture && (totalScore == null || !Number.isFinite(totalScore))) {
7
+ if (!posture && (prRiskScore == null || !Number.isFinite(prRiskScore))) {
8
8
  return null;
9
9
  }
10
+ const score = prRiskScore ?? 0;
10
11
  const resolvedPosture = posture;
11
12
  return {
12
- totalScore: totalScore ?? 0,
13
+ totalScore: score,
14
+ prRisk: { score },
13
15
  layerScores: {
14
16
  security: 0,
15
17
  maintainability: 0,
@@ -30,8 +32,8 @@ export function buildScanCardPresentation(input) {
30
32
  if (input.pipelineStatus !== "done") {
31
33
  return presentPipelineDashboardCard(input.pipelineStatus === "failed" ? "failed" : input.pipelineStatus);
32
34
  }
33
- const result = input.result ??
34
- minimalResultFromDenormalized(input.decision, input.totalScore);
35
+ const prRiskScore = input.prRiskScore ?? null;
36
+ const result = input.result ?? minimalResultFromDenormalized(input.decision, prRiskScore);
35
37
  if (!result) {
36
38
  return presentPipelineDashboardCard("failed");
37
39
  }
@@ -39,7 +41,6 @@ export function buildScanCardPresentation(input) {
39
41
  result,
40
42
  pipelineStatus: input.pipelineStatus,
41
43
  decision: input.decision,
42
- totalScore: input.totalScore,
43
44
  });
44
45
  if (!bundle) {
45
46
  return presentPipelineDashboardCard("failed");
@@ -8,7 +8,7 @@ export type BuildScanDetailsPresentationInput = {
8
8
  methodologyVersion?: string | null;
9
9
  prNumber?: number | null;
10
10
  decision?: string | null;
11
- totalScore?: number | null;
11
+ prRiskScore?: number | null;
12
12
  };
13
13
  export declare function buildScanDetailsPresentation(input: BuildScanDetailsPresentationInput): ScanDetailsPresentation | null;
14
14
  //# sourceMappingURL=buildScanDetailsPresentation.d.ts.map