@mergesignal/shared 0.4.3 → 0.6.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 (181) hide show
  1. package/dist/actionsStepSummary.d.ts +1 -22
  2. package/dist/actionsStepSummary.d.ts.map +1 -1
  3. package/dist/actionsStepSummary.js +19 -716
  4. package/dist/actionsStepSummary.test.js +34 -329
  5. package/dist/assessmentLabels.d.ts +6 -0
  6. package/dist/assessmentLabels.d.ts.map +1 -0
  7. package/dist/assessmentLabels.js +33 -0
  8. package/dist/assessmentProjection.d.ts +12 -0
  9. package/dist/assessmentProjection.d.ts.map +1 -0
  10. package/dist/assessmentProjection.js +100 -0
  11. package/dist/assessmentSchema.d.ts +155 -0
  12. package/dist/assessmentSchema.d.ts.map +1 -0
  13. package/dist/assessmentSchema.js +110 -0
  14. package/dist/cardObservationCatalog.d.ts +2 -0
  15. package/dist/cardObservationCatalog.d.ts.map +1 -1
  16. package/dist/cardObservationCatalog.js +47 -1
  17. package/dist/engineWireRegression.test.js +22 -2
  18. package/dist/fixtures/assessmentFixtures.d.ts +13 -0
  19. package/dist/fixtures/assessmentFixtures.d.ts.map +1 -0
  20. package/dist/fixtures/assessmentFixtures.js +164 -0
  21. package/dist/formatCardExposureDisplay.d.ts +0 -4
  22. package/dist/formatCardExposureDisplay.d.ts.map +1 -1
  23. package/dist/formatCardExposureDisplay.js +0 -15
  24. package/dist/formatInsight.d.ts +3 -2
  25. package/dist/formatInsight.d.ts.map +1 -1
  26. package/dist/formatInsight.js +26 -1
  27. package/dist/index.d.ts +7 -11
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +7 -11
  30. package/dist/narrativeParity.test.js +4 -34
  31. package/dist/presentGitHubPrComment.d.ts +1 -3
  32. package/dist/presentGitHubPrComment.d.ts.map +1 -1
  33. package/dist/presentGitHubPrComment.js +0 -17
  34. package/dist/presentation/buildGitHubCheckRunOutput.d.ts +20 -0
  35. package/dist/presentation/buildGitHubCheckRunOutput.d.ts.map +1 -0
  36. package/dist/presentation/buildGitHubCheckRunOutput.js +42 -0
  37. package/dist/presentation/buildGitHubCheckRunOutput.test.d.ts +2 -0
  38. package/dist/presentation/buildGitHubCheckRunOutput.test.d.ts.map +1 -0
  39. package/dist/presentation/buildGitHubCheckRunOutput.test.js +188 -0
  40. package/dist/presentation/compose/narrativeChannels.d.ts.map +1 -1
  41. package/dist/presentation/compose/narrativeChannels.js +13 -43
  42. package/dist/presentation/compose/narrativeCompose.d.ts.map +1 -1
  43. package/dist/presentation/compose/narrativeCompose.js +2 -5
  44. package/dist/presentation/dto/assessmentPresentationFields.d.ts +13 -0
  45. package/dist/presentation/dto/assessmentPresentationFields.d.ts.map +1 -0
  46. package/dist/presentation/dto/assessmentPresentationFields.js +1 -0
  47. package/dist/presentation/dto/dashboardCardPresentation.d.ts +2 -1
  48. package/dist/presentation/dto/dashboardCardPresentation.d.ts.map +1 -1
  49. package/dist/presentation/dto/githubAndCliPresentation.d.ts +4 -3
  50. package/dist/presentation/dto/githubAndCliPresentation.d.ts.map +1 -1
  51. package/dist/presentation/dto/scanDetailsPresentation.d.ts +2 -1
  52. package/dist/presentation/dto/scanDetailsPresentation.d.ts.map +1 -1
  53. package/dist/presentation/fixtures/dashboardCardGolden.test.js +21 -14
  54. package/dist/presentation/fixtures/presentationPersonaFixtures.d.ts.map +1 -1
  55. package/dist/presentation/fixtures/presentationPersonaFixtures.js +31 -24
  56. package/dist/presentation/fixtures/scanResultFixtures.d.ts.map +1 -1
  57. package/dist/presentation/fixtures/scanResultFixtures.js +14 -3
  58. package/dist/presentation/index.d.ts +2 -2
  59. package/dist/presentation/index.d.ts.map +1 -1
  60. package/dist/presentation/index.js +2 -2
  61. package/dist/presentation/orchestration/buildScanCardPresentation.d.ts.map +1 -1
  62. package/dist/presentation/orchestration/buildScanCardPresentation.js +8 -3
  63. package/dist/presentation/orchestration/buildScanPresentationBundle.d.ts +1 -1
  64. package/dist/presentation/orchestration/buildScanPresentationBundle.d.ts.map +1 -1
  65. package/dist/presentation/orchestration/buildScanPresentationBundle.js +12 -10
  66. package/dist/presentation/orchestration/scanPresentationBundle.d.ts +8 -3
  67. package/dist/presentation/orchestration/scanPresentationBundle.d.ts.map +1 -1
  68. package/dist/presentation/presentationPersonas.test.js +6 -6
  69. package/dist/presentation/presenters/presentCliScanSummary.d.ts.map +1 -1
  70. package/dist/presentation/presenters/presentCliScanSummary.js +2 -0
  71. package/dist/presentation/presenters/presentDashboardCard.d.ts +1 -0
  72. package/dist/presentation/presenters/presentDashboardCard.d.ts.map +1 -1
  73. package/dist/presentation/presenters/presentDashboardCard.js +18 -0
  74. package/dist/presentation/presenters/presentGitHubCheckRun.d.ts.map +1 -1
  75. package/dist/presentation/presenters/presentGitHubCheckRun.js +2 -0
  76. package/dist/presentation/presenters/presentGitHubPrComment.d.ts.map +1 -1
  77. package/dist/presentation/presenters/presentGitHubPrComment.js +15 -21
  78. package/dist/presentation/presenters/presentScanDetails.d.ts.map +1 -1
  79. package/dist/presentation/presenters/presentScanDetails.js +52 -129
  80. package/dist/presentation/profile/buildProfileFromAssessment.d.ts +5 -0
  81. package/dist/presentation/profile/buildProfileFromAssessment.d.ts.map +1 -0
  82. package/dist/presentation/profile/buildProfileFromAssessment.js +58 -0
  83. package/dist/presentation/projectAssessmentFields.d.ts +4 -0
  84. package/dist/presentation/projectAssessmentFields.d.ts.map +1 -0
  85. package/dist/presentation/projectAssessmentFields.js +13 -0
  86. package/dist/presentation/surfaceParity.test.d.ts +2 -0
  87. package/dist/presentation/surfaceParity.test.d.ts.map +1 -0
  88. package/dist/presentation/surfaceParity.test.js +74 -0
  89. package/dist/productMessaging.d.ts +4 -4
  90. package/dist/productMessaging.d.ts.map +1 -1
  91. package/dist/productMessaging.js +4 -4
  92. package/dist/productMessaging.test.js +2 -2
  93. package/dist/repoIntelligenceSchema.d.ts +2 -2
  94. package/dist/resolvePipelineStatus.d.ts +15 -0
  95. package/dist/resolvePipelineStatus.d.ts.map +1 -0
  96. package/dist/resolvePipelineStatus.js +37 -0
  97. package/dist/scanCardPresentationState.d.ts +10 -0
  98. package/dist/scanCardPresentationState.d.ts.map +1 -0
  99. package/dist/scanCardPresentationState.js +4 -0
  100. package/dist/{scanDetailViewModel.d.ts → scanDetailViewModelTypes.d.ts} +60 -32
  101. package/dist/scanDetailViewModelTypes.d.ts.map +1 -0
  102. package/dist/scanDetailViewModelTypes.js +4 -0
  103. package/dist/scanResultSchema.d.ts +75 -2
  104. package/dist/scanResultSchema.d.ts.map +1 -1
  105. package/dist/scanResultSchema.js +4 -2
  106. package/dist/scanResultSchema.test.js +16 -0
  107. package/dist/scanSurfaceCopy.d.ts +2 -0
  108. package/dist/scanSurfaceCopy.d.ts.map +1 -1
  109. package/dist/scanSurfaceCopy.js +2 -0
  110. package/dist/trustedScanGuards.test.js +7 -0
  111. package/dist/types.d.ts +3 -0
  112. package/dist/types.d.ts.map +1 -1
  113. package/package.json +1 -1
  114. package/dist/collectNarrativeWhyBullets.d.ts +0 -12
  115. package/dist/collectNarrativeWhyBullets.d.ts.map +0 -1
  116. package/dist/collectNarrativeWhyBullets.js +0 -104
  117. package/dist/deriveCardDisplaySummary.d.ts +0 -16
  118. package/dist/deriveCardDisplaySummary.d.ts.map +0 -1
  119. package/dist/deriveCardDisplaySummary.js +0 -56
  120. package/dist/deriveCardDisplaySummary.test.d.ts +0 -2
  121. package/dist/deriveCardDisplaySummary.test.d.ts.map +0 -1
  122. package/dist/deriveCardDisplaySummary.test.js +0 -89
  123. package/dist/deriveCardOperationalObservations.d.ts +0 -19
  124. package/dist/deriveCardOperationalObservations.d.ts.map +0 -1
  125. package/dist/deriveCardOperationalObservations.js +0 -180
  126. package/dist/deriveCardOperationalObservations.test.d.ts +0 -2
  127. package/dist/deriveCardOperationalObservations.test.d.ts.map +0 -1
  128. package/dist/deriveCardOperationalObservations.test.js +0 -268
  129. package/dist/deriveRiskScoreSummary.d.ts +0 -33
  130. package/dist/deriveRiskScoreSummary.d.ts.map +0 -1
  131. package/dist/deriveRiskScoreSummary.js +0 -90
  132. package/dist/deriveRiskScoreSummary.test.d.ts +0 -2
  133. package/dist/deriveRiskScoreSummary.test.d.ts.map +0 -1
  134. package/dist/deriveRiskScoreSummary.test.js +0 -47
  135. package/dist/deriveScanDetailRecommendations.d.ts +0 -63
  136. package/dist/deriveScanDetailRecommendations.d.ts.map +0 -1
  137. package/dist/deriveScanDetailRecommendations.js +0 -725
  138. package/dist/deriveScanDetailRecommendations.test.d.ts +0 -2
  139. package/dist/deriveScanDetailRecommendations.test.d.ts.map +0 -1
  140. package/dist/deriveScanDetailRecommendations.test.js +0 -181
  141. package/dist/deriveScanSummaryText.d.ts +0 -7
  142. package/dist/deriveScanSummaryText.d.ts.map +0 -1
  143. package/dist/deriveScanSummaryText.js +0 -24
  144. package/dist/deriveScanSummaryText.test.d.ts +0 -2
  145. package/dist/deriveScanSummaryText.test.d.ts.map +0 -1
  146. package/dist/deriveScanSummaryText.test.js +0 -77
  147. package/dist/formatCardEvidenceCounts.d.ts +0 -7
  148. package/dist/formatCardEvidenceCounts.d.ts.map +0 -1
  149. package/dist/formatCardEvidenceCounts.js +0 -19
  150. package/dist/prCheckRunPresentation.d.ts +0 -68
  151. package/dist/prCheckRunPresentation.d.ts.map +0 -1
  152. package/dist/prCheckRunPresentation.js +0 -319
  153. package/dist/prCheckRunPresentation.test.d.ts +0 -2
  154. package/dist/prCheckRunPresentation.test.d.ts.map +0 -1
  155. package/dist/prCheckRunPresentation.test.js +0 -278
  156. package/dist/presentation/intent/derivePresentationInterpretation.d.ts +0 -4
  157. package/dist/presentation/intent/derivePresentationInterpretation.d.ts.map +0 -1
  158. package/dist/presentation/intent/derivePresentationInterpretation.js +0 -202
  159. package/dist/presentation/intent/formatPresentationCopy.d.ts +0 -8
  160. package/dist/presentation/intent/formatPresentationCopy.d.ts.map +0 -1
  161. package/dist/presentation/intent/formatPresentationCopy.js +0 -140
  162. package/dist/presentation/intent/presentationIntent.test.d.ts +0 -2
  163. package/dist/presentation/intent/presentationIntent.test.d.ts.map +0 -1
  164. package/dist/presentation/intent/presentationIntent.test.js +0 -29
  165. package/dist/presentation/intent/verificationFocusLabels.d.ts +0 -2
  166. package/dist/presentation/intent/verificationFocusLabels.d.ts.map +0 -1
  167. package/dist/presentation/intent/verificationFocusLabels.js +0 -45
  168. package/dist/presentation/profile/derivePresentationProfile.d.ts +0 -12
  169. package/dist/presentation/profile/derivePresentationProfile.d.ts.map +0 -1
  170. package/dist/presentation/profile/derivePresentationProfile.js +0 -85
  171. package/dist/scanCardSummary.d.ts +0 -58
  172. package/dist/scanCardSummary.d.ts.map +0 -1
  173. package/dist/scanCardSummary.js +0 -146
  174. package/dist/scanCardSummary.test.d.ts +0 -2
  175. package/dist/scanCardSummary.test.d.ts.map +0 -1
  176. package/dist/scanCardSummary.test.js +0 -234
  177. package/dist/scanDetailViewModel.d.ts.map +0 -1
  178. package/dist/scanDetailViewModel.js +0 -636
  179. package/dist/scanDetailViewModel.test.d.ts +0 -2
  180. package/dist/scanDetailViewModel.test.d.ts.map +0 -1
  181. package/dist/scanDetailViewModel.test.js +0 -530
@@ -1,202 +0,0 @@
1
- import { formatCardAreaLabels } from "../../formatCardAreaLabels.js";
2
- import { mergeVerificationFocusLabels } from "./verificationFocusLabels.js";
3
- const TOOLING_CLASSES = new Set([
4
- "tooling",
5
- "test",
6
- "lint",
7
- "format",
8
- "build",
9
- "ci",
10
- ]);
11
- const RUNTIME_IMPACT_RANK = {
12
- confirmed: 3,
13
- possible: 2,
14
- unknown: 1,
15
- none: 0,
16
- };
17
- const EVIDENCE_RANK = {
18
- high: 3,
19
- medium: 2,
20
- low: 1,
21
- };
22
- function isRuntimeEligible(row) {
23
- if (row.suppressRuntimeNarrative)
24
- return false;
25
- if (row.runtimeImpact === "confirmed" || row.runtimeImpact === "possible") {
26
- return true;
27
- }
28
- if (row.dependencyClass === "runtime")
29
- return true;
30
- if (row.usagePathCount > 0)
31
- return true;
32
- return false;
33
- }
34
- function isToolingOriented(row) {
35
- if (row.suppressRuntimeNarrative)
36
- return true;
37
- if (row.dependencyClass && TOOLING_CLASSES.has(row.dependencyClass)) {
38
- return true;
39
- }
40
- return false;
41
- }
42
- function compareRuntimePackages(a, b, order) {
43
- const impactA = RUNTIME_IMPACT_RANK[a.runtimeImpact ?? "none"] ?? 0;
44
- const impactB = RUNTIME_IMPACT_RANK[b.runtimeImpact ?? "none"] ?? 0;
45
- if (impactB !== impactA)
46
- return impactB - impactA;
47
- const evA = EVIDENCE_RANK[a.evidenceStrength ?? "low"] ?? 0;
48
- const evB = EVIDENCE_RANK[b.evidenceStrength ?? "low"] ?? 0;
49
- if (evB !== evA)
50
- return evB - evA;
51
- return order.indexOf(a.packageName) - order.indexOf(b.packageName);
52
- }
53
- function pickAnchorPackage(rows, changedOrder) {
54
- if (rows.length === 0)
55
- return null;
56
- const sorted = [...rows].sort((a, b) => compareRuntimePackages(a, b, changedOrder));
57
- return sorted[0]?.packageName ?? null;
58
- }
59
- function pickToolingAnchor(rows, changedOrder) {
60
- if (rows.length === 0)
61
- return null;
62
- const sorted = [...rows].sort((a, b) => changedOrder.indexOf(a.packageName) - changedOrder.indexOf(b.packageName));
63
- return sorted[0]?.packageName ?? null;
64
- }
65
- function isToolingPatchSet(rows, facts) {
66
- if (rows.length === 0)
67
- return false;
68
- const narrow = !facts.blastRadius || facts.blastRadius.level === "narrow";
69
- if (!narrow)
70
- return false;
71
- return rows.every((row) => row.suppressRuntimeNarrative &&
72
- (row.expectedImpact === "typecheck" ||
73
- row.expectedImpact === "build_time"));
74
- }
75
- function runtimeSurfaceLabelFromFacts(facts, anchorRow) {
76
- const area = facts.affectedAreas[0];
77
- if (area) {
78
- const formatted = formatCardAreaLabels([area.label], 1);
79
- return formatted[0] ?? area.label;
80
- }
81
- if (anchorRow?.packageRole === "http_framework") {
82
- return "API request handling";
83
- }
84
- if (anchorRow?.packageRole === "auth") {
85
- return "authentication flows";
86
- }
87
- if (anchorRow?.packageRole === "queue") {
88
- return "background job processing";
89
- }
90
- return "application code";
91
- }
92
- function collectVerificationLabels(rows) {
93
- return mergeVerificationFocusLabels(rows.map((r) => r.verificationFocus));
94
- }
95
- function showLimitedEvidence(rows) {
96
- return rows.some((r) => r.evidenceStrength === "low");
97
- }
98
- function dominantExpectedImpact(rows) {
99
- for (const row of rows) {
100
- if (row.expectedImpact && row.expectedImpact !== "unknown") {
101
- return row.expectedImpact;
102
- }
103
- }
104
- return null;
105
- }
106
- function emptyInterpretation(intent) {
107
- return {
108
- intent,
109
- anchorPackage: null,
110
- suppressRuntimeNarrative: intent.startsWith("tooling"),
111
- allowRuntimeNarrative: intent.includes("runtime"),
112
- showLimitedEvidence: false,
113
- expectedImpactKey: null,
114
- verificationLabels: [],
115
- runtimeSurfaceLabel: null,
116
- runtimePackages: [],
117
- };
118
- }
119
- export function derivePresentationInterpretation(facts) {
120
- const changedOrder = facts.changedPackages.all;
121
- const semantics = facts.changedPackageSemantics.length > 0
122
- ? facts.changedPackageSemantics
123
- : facts.packageSemantics && facts.changedPackages.primary
124
- ? [
125
- {
126
- packageName: facts.changedPackages.primary,
127
- dependencyClass: facts.packageSemantics.dependencyClass,
128
- packageRole: facts.packageSemantics.packageRole,
129
- runtimeImpact: facts.packageSemantics.runtimeImpact,
130
- expectedImpact: facts.packageSemantics.expectedImpact,
131
- suppressRuntimeNarrative: facts.packageSemantics.suppressRuntimeNarrative,
132
- evidenceStrength: facts.packageSemantics.evidenceStrength,
133
- verificationFocus: facts.packageSemantics.verificationFocus,
134
- usagePathCount: 0,
135
- usageAreaCount: 0,
136
- },
137
- ]
138
- : [];
139
- const tier1Ok = facts.availability.tiersPresent.tier1 &&
140
- facts.availability.repoIntelligenceParse === "ok";
141
- if (!tier1Ok) {
142
- return emptyInterpretation("limited_context");
143
- }
144
- if (!facts.changedPackages.primary) {
145
- return emptyInterpretation("no_changed_packages");
146
- }
147
- const runtimeEligible = semantics.filter(isRuntimeEligible);
148
- if (runtimeEligible.length > 0) {
149
- const anchorPackage = pickAnchorPackage(runtimeEligible, changedOrder);
150
- const anchorRow = runtimeEligible.find((r) => r.packageName === anchorPackage);
151
- const runtimeSurfaceLabel = runtimeSurfaceLabelFromFacts(facts, anchorRow);
152
- const verificationLabels = collectVerificationLabels(runtimeEligible);
153
- let intent = "runtime_upgrade";
154
- if (runtimeEligible.length > 1) {
155
- intent = "multi_runtime_upgrade";
156
- }
157
- else if (runtimeEligible.some((r) => r.packageRole === "auth")) {
158
- intent = "auth_runtime_upgrade";
159
- }
160
- else if (runtimeEligible.some((r) => r.packageRole === "queue")) {
161
- intent = "queue_runtime_upgrade";
162
- }
163
- return {
164
- intent,
165
- anchorPackage,
166
- suppressRuntimeNarrative: false,
167
- allowRuntimeNarrative: true,
168
- showLimitedEvidence: showLimitedEvidence(runtimeEligible),
169
- expectedImpactKey: dominantExpectedImpact(runtimeEligible),
170
- verificationLabels,
171
- runtimeSurfaceLabel,
172
- runtimePackages: runtimeEligible.map((r) => r.packageName),
173
- };
174
- }
175
- const toolingOnly = semantics.length > 0 && semantics.every(isToolingOriented);
176
- if (toolingOnly) {
177
- const anchorPackage = pickToolingAnchor(semantics, changedOrder);
178
- const isPatch = isToolingPatchSet(semantics, facts);
179
- const intent = isPatch
180
- ? "tooling_patch"
181
- : "tooling_upgrade";
182
- const anchorRow = semantics.find((r) => r.packageName === anchorPackage);
183
- return {
184
- intent,
185
- anchorPackage,
186
- suppressRuntimeNarrative: true,
187
- allowRuntimeNarrative: false,
188
- showLimitedEvidence: showLimitedEvidence(semantics),
189
- expectedImpactKey: anchorRow?.expectedImpact ?? null,
190
- verificationLabels: collectVerificationLabels(semantics),
191
- runtimeSurfaceLabel: null,
192
- runtimePackages: [],
193
- };
194
- }
195
- return {
196
- ...emptyInterpretation("unknown_upgrade"),
197
- anchorPackage: facts.changedPackages.primary,
198
- verificationLabels: collectVerificationLabels(semantics),
199
- showLimitedEvidence: showLimitedEvidence(semantics),
200
- expectedImpactKey: dominantExpectedImpact(semantics),
201
- };
202
- }
@@ -1,8 +0,0 @@
1
- import type { ScanNarrativeFacts } from "../../scanNarrativeFacts.js";
2
- import type { PresentationStatus } from "../dto/types.js";
3
- import type { PresentationInterpretation } from "./presentationIntent.js";
4
- export declare function formatPresentationHeadline(interpretation: PresentationInterpretation, facts: ScanNarrativeFacts, status: PresentationStatus | undefined): string;
5
- /** Atomic insight lines — no embedded areas or blast radius (those live in separate channels). */
6
- export declare function formatPresentationInsightLines(interpretation: PresentationInterpretation, facts: ScanNarrativeFacts, status: PresentationStatus | undefined): string[];
7
- export declare function formatPresentationVerification(interpretation: PresentationInterpretation, status: PresentationStatus | undefined, max: number): string[];
8
- //# sourceMappingURL=formatPresentationCopy.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"formatPresentationCopy.d.ts","sourceRoot":"","sources":["../../../src/presentation/intent/formatPresentationCopy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAM1D,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAa1E,wBAAgB,0BAA0B,CACxC,cAAc,EAAE,0BAA0B,EAC1C,KAAK,EAAE,kBAAkB,EACzB,MAAM,EAAE,kBAAkB,GAAG,SAAS,GACrC,MAAM,CAmDR;AA0BD,kGAAkG;AAClG,wBAAgB,8BAA8B,CAC5C,cAAc,EAAE,0BAA0B,EAC1C,KAAK,EAAE,kBAAkB,EACzB,MAAM,EAAE,kBAAkB,GAAG,SAAS,GACrC,MAAM,EAAE,CA0CV;AAuBD,wBAAgB,8BAA8B,CAC5C,cAAc,EAAE,0BAA0B,EAC1C,MAAM,EAAE,kBAAkB,GAAG,SAAS,EACtC,GAAG,EAAE,MAAM,GACV,MAAM,EAAE,CAmBV"}
@@ -1,140 +0,0 @@
1
- import { scanSurfaceCopy } from "../../scanSurfaceCopy.js";
2
- import { applyPostureVocabularyGuardHeadline, applyPostureVocabularyGuardLines, } from "./applyPostureVocabularyGuard.js";
3
- import { formatPackageDisplayName } from "./packageDisplayName.js";
4
- function anchorSemantics(facts, interpretation) {
5
- const name = interpretation.anchorPackage;
6
- if (!name)
7
- return null;
8
- return (facts.changedPackageSemantics.find((r) => r.packageName === name) ?? null);
9
- }
10
- export function formatPresentationHeadline(interpretation, facts, status) {
11
- const anchor = interpretation.anchorPackage ?? facts.changedPackages.primary;
12
- const row = anchorSemantics(facts, interpretation);
13
- const pkgDisplay = formatPackageDisplayName(anchor ?? "dependency", row?.packageRole);
14
- const copy = scanSurfaceCopy.presentation;
15
- let headline;
16
- switch (interpretation.intent) {
17
- case "limited_context":
18
- headline = copy.limitedContextHeadline;
19
- break;
20
- case "no_changed_packages":
21
- headline = copy.noChangedPackagesHeadline;
22
- break;
23
- case "tooling_patch":
24
- headline = copy.toolingPatchHeadline.replace("{package}", pkgDisplay);
25
- break;
26
- case "tooling_upgrade":
27
- headline = copy.toolingUpgradeHeadline.replace("{package}", pkgDisplay);
28
- break;
29
- case "multi_runtime_upgrade":
30
- headline = copy.multiRuntimeHeadline;
31
- break;
32
- case "auth_runtime_upgrade":
33
- case "queue_runtime_upgrade":
34
- case "runtime_upgrade": {
35
- const surface = interpretation.runtimeSurfaceLabel ?? "application code";
36
- headline = copy.runtimeUpgradeHeadline
37
- .replace("{package}", pkgDisplay)
38
- .replace("{surface}", surface);
39
- break;
40
- }
41
- case "unknown_upgrade":
42
- if (status === "safe") {
43
- headline = copy.safeNeutralHeadline.replace("{package}", pkgDisplay);
44
- }
45
- else {
46
- headline = copy.defaultUpgradeHeadline.replace("{package}", pkgDisplay);
47
- }
48
- break;
49
- default:
50
- headline = copy.safeNeutralHeadline.replace("{package}", pkgDisplay);
51
- }
52
- return applyPostureVocabularyGuardHeadline(headline, status, interpretation.anchorPackage);
53
- }
54
- function formatExpectedImpactKeyPoint(interpretation) {
55
- if (interpretation.intent !== "tooling_patch" &&
56
- interpretation.intent !== "tooling_upgrade") {
57
- return null;
58
- }
59
- const key = interpretation.expectedImpactKey;
60
- let workflows = "build and typecheck workflows";
61
- if (key === "test_time")
62
- workflows = "test workflows";
63
- else if (key === "development_only")
64
- workflows = "development workflows";
65
- else if (key === "build_time")
66
- workflows = "build workflows";
67
- return scanSurfaceCopy.presentation.expectedImpactLimitedKeyPoint.replace("{workflows}", workflows);
68
- }
69
- function formatLimitedEvidenceKeyPoint() {
70
- return scanSurfaceCopy.presentation.limitedEvidenceKeyPoint;
71
- }
72
- /** Atomic insight lines — no embedded areas or blast radius (those live in separate channels). */
73
- export function formatPresentationInsightLines(interpretation, facts, status) {
74
- const points = [];
75
- if (interpretation.intent === "limited_context") {
76
- points.push(scanSurfaceCopy.presentation.limitedContextKeyPoint);
77
- if (facts.changedPackages.primary) {
78
- points.push(scanSurfaceCopy.presentation.changedPackageKeyPoint.replace("{package}", facts.changedPackages.primary));
79
- }
80
- return applyPostureVocabularyGuardLines(points, status);
81
- }
82
- if (interpretation.showLimitedEvidence) {
83
- points.push(formatLimitedEvidenceKeyPoint());
84
- }
85
- if (interpretation.suppressRuntimeNarrative) {
86
- points.push(scanSurfaceCopy.presentation.noRuntimePathsKeyPoint);
87
- const impact = formatExpectedImpactKeyPoint(interpretation);
88
- if (impact)
89
- points.push(impact);
90
- }
91
- else if (interpretation.allowRuntimeNarrative) {
92
- const usage = facts.packageUsage.find((u) => u.packageName === interpretation.anchorPackage);
93
- const paths = [...(usage?.paths ?? []), ...(usage?.criticalPaths ?? [])];
94
- if (paths.length > 0) {
95
- points.push(scanSurfaceCopy.presentation.usedInRuntimePathsKeyPoint.replace("{count}", String(paths.length)));
96
- }
97
- else {
98
- points.push(scanSurfaceCopy.presentation.runtimeUsageKeyPoint);
99
- }
100
- }
101
- return applyPostureVocabularyGuardLines(points, status);
102
- }
103
- const AUTH_VERIFICATION = [
104
- "routes",
105
- "middleware/hooks",
106
- "auth flow",
107
- "serialization",
108
- "error handling",
109
- ];
110
- const QUEUE_VERIFICATION = [
111
- "workers",
112
- "queue",
113
- "serialization",
114
- "error handling",
115
- ];
116
- const RUNTIME_DEFAULT_VERIFICATION = [
117
- "routes",
118
- "middleware/hooks",
119
- "error handling",
120
- ];
121
- export function formatPresentationVerification(interpretation, status, max) {
122
- let actions = [];
123
- if (interpretation.verificationLabels.length > 0) {
124
- actions = [...interpretation.verificationLabels];
125
- }
126
- else if (interpretation.intent === "auth_runtime_upgrade") {
127
- actions = [...AUTH_VERIFICATION];
128
- }
129
- else if (interpretation.intent === "queue_runtime_upgrade") {
130
- actions = [...QUEUE_VERIFICATION];
131
- }
132
- else if (interpretation.allowRuntimeNarrative) {
133
- actions = [...RUNTIME_DEFAULT_VERIFICATION];
134
- }
135
- else if (interpretation.intent === "tooling_patch" ||
136
- interpretation.intent === "tooling_upgrade") {
137
- actions = ["CI", "typecheck", "build"];
138
- }
139
- return applyPostureVocabularyGuardLines(actions, status).slice(0, max);
140
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=presentationIntent.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"presentationIntent.test.d.ts","sourceRoot":"","sources":["../../../src/presentation/intent/presentationIntent.test.ts"],"names":[],"mappings":""}
@@ -1,29 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { deriveScanNarrative } from "../../deriveScanNarrative.js";
3
- import { scanResultMixedTypescriptFastify, scanResultTypescriptPatch, scanResultFastifyRuntime, } from "../fixtures/presentationPersonaFixtures.js";
4
- import { derivePresentationInterpretation } from "./derivePresentationInterpretation.js";
5
- describe("derivePresentationInterpretation", () => {
6
- it("typescript patch: tooling_patch intent from engine semantics", () => {
7
- const facts = deriveScanNarrative(scanResultTypescriptPatch);
8
- const interp = derivePresentationInterpretation(facts);
9
- // Engine: suppressRuntimeNarrative=true, expectedImpact=typecheck, dependencyClass=tooling
10
- expect(interp.intent).toBe("tooling_patch");
11
- expect(interp.anchorPackage).toBe("typescript");
12
- expect(interp.suppressRuntimeNarrative).toBe(true);
13
- });
14
- it("fastify: runtime_upgrade from runtimeImpact=confirmed", () => {
15
- const facts = deriveScanNarrative(scanResultFastifyRuntime);
16
- const interp = derivePresentationInterpretation(facts);
17
- expect(interp.intent).toBe("runtime_upgrade");
18
- expect(interp.anchorPackage).toBe("fastify");
19
- expect(interp.allowRuntimeNarrative).toBe(true);
20
- });
21
- it("mixed typescript+fastify: runtime dominates tooling (anchor fastify)", () => {
22
- const facts = deriveScanNarrative(scanResultMixedTypescriptFastify);
23
- const interp = derivePresentationInterpretation(facts);
24
- expect(interp.intent).toBe("runtime_upgrade");
25
- expect(interp.anchorPackage).toBe("fastify");
26
- expect(interp.runtimePackages).toContain("fastify");
27
- expect(interp.runtimePackages).not.toContain("typescript");
28
- });
29
- });
@@ -1,2 +0,0 @@
1
- export declare function mergeVerificationFocusLabels(focusLists: string[][], max?: number): string[];
2
- //# sourceMappingURL=verificationFocusLabels.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"verificationFocusLabels.d.ts","sourceRoot":"","sources":["../../../src/presentation/intent/verificationFocusLabels.ts"],"names":[],"mappings":"AA2BA,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,MAAM,EAAE,EAAE,EACtB,GAAG,SAAI,GACN,MAAM,EAAE,CAeV"}
@@ -1,45 +0,0 @@
1
- const FOCUS_LABELS = {
2
- ci: "CI",
3
- typecheck: "typecheck",
4
- build: "build",
5
- routes: "routes",
6
- middleware: "middleware/hooks",
7
- hooks: "middleware/hooks",
8
- auth_flow: "auth flow",
9
- auth: "auth flow",
10
- serialization: "serialization",
11
- error_handling: "error handling",
12
- handlers: "handlers",
13
- plugins: "plugins",
14
- session: "session",
15
- workers: "workers",
16
- queue: "queue",
17
- test_suite: "test suite",
18
- lint: "lint",
19
- format: "format",
20
- };
21
- function labelVerificationFocus(focus) {
22
- const key = focus.trim().toLowerCase();
23
- if (!key)
24
- return "";
25
- return FOCUS_LABELS[key] ?? focus.replace(/_/g, " ");
26
- }
27
- export function mergeVerificationFocusLabels(focusLists, max = 6) {
28
- const seen = new Set();
29
- const out = [];
30
- for (const list of focusLists) {
31
- for (const f of list) {
32
- const label = labelVerificationFocus(f);
33
- if (!label)
34
- continue;
35
- const norm = label.toLowerCase();
36
- if (seen.has(norm))
37
- continue;
38
- seen.add(norm);
39
- out.push(label);
40
- if (out.length >= max)
41
- return out;
42
- }
43
- }
44
- return out;
45
- }
@@ -1,12 +0,0 @@
1
- import type { ScanNarrativeFacts } from "../../scanNarrativeFacts.js";
2
- import type { PipelineStatus } from "../dto/types.js";
3
- import type { PresentationProfile } from "./presentationProfile.js";
4
- type DerivePresentationProfileContext = {
5
- pipelineStatus: PipelineStatus;
6
- decision?: string | null;
7
- totalScore?: number | null;
8
- };
9
- /** INTERNAL - only called from buildScanPresentationBundle */
10
- export declare function derivePresentationProfile(facts: ScanNarrativeFacts, ctx: DerivePresentationProfileContext): PresentationProfile | null;
11
- export {};
12
- //# sourceMappingURL=derivePresentationProfile.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"derivePresentationProfile.d.ts","sourceRoot":"","sources":["../../../src/presentation/profile/derivePresentationProfile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAKtE,OAAO,KAAK,EAAE,cAAc,EAAsB,MAAM,iBAAiB,CAAC;AAC1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,KAAK,gCAAgC,GAAG;IACtC,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAwFF,8DAA8D;AAC9D,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,kBAAkB,EACzB,GAAG,EAAE,gCAAgC,GACpC,mBAAmB,GAAG,IAAI,CAwB5B"}
@@ -1,85 +0,0 @@
1
- import { mergePostureFromDecision } from "../../riskVocabulary.js";
2
- import { scanSurfaceCopy } from "../../scanSurfaceCopy.js";
3
- import { derivePresentationInterpretation } from "../intent/derivePresentationInterpretation.js";
4
- function statusFromScore(totalScore) {
5
- if (totalScore == null || !Number.isFinite(totalScore))
6
- return "needs_review";
7
- if (totalScore <= 30)
8
- return "safe";
9
- if (totalScore <= 60)
10
- return "needs_review";
11
- return "risky";
12
- }
13
- function resolveStatus(facts, ctx) {
14
- const fromFacts = facts.mergePosture;
15
- if (fromFacts)
16
- return fromFacts;
17
- const fromDecision = mergePostureFromDecision(ctx.decision ?? undefined);
18
- if (fromDecision)
19
- return fromDecision;
20
- return statusFromScore(ctx.totalScore ?? facts.riskIndex);
21
- }
22
- function hasStrongPrIntelligence(facts) {
23
- return (facts.availability.tiersPresent.tier1 &&
24
- facts.availability.repoIntelligenceParse === "ok");
25
- }
26
- function hasHighSeverityFindings(facts) {
27
- return facts.reviewerGuidance.some((g) => g.kind === "finding" &&
28
- (g.priority === "critical" || g.priority === "high"));
29
- }
30
- function deriveDensity(facts, priority, interpretation) {
31
- if (priority === "limited") {
32
- return hasHighSeverityFindings(facts) ? "standard" : "minimal";
33
- }
34
- if (interpretation.allowRuntimeNarrative) {
35
- const wideOrModerate = facts.blastRadius?.level === "wide" ||
36
- facts.blastRadius?.level === "moderate";
37
- const hasAreas = facts.affectedAreas.length > 0;
38
- const hasPaths = facts.packageUsage.some((u) => u.paths.length > 0 || u.criticalPaths.length > 0);
39
- if (wideOrModerate || hasAreas || hasPaths) {
40
- return "rich";
41
- }
42
- }
43
- if (interpretation.suppressRuntimeNarrative) {
44
- const narrow = !facts.blastRadius || facts.blastRadius.level === "narrow";
45
- if (narrow && facts.affectedAreas.length === 0) {
46
- return "minimal";
47
- }
48
- }
49
- return "standard";
50
- }
51
- function deriveConfidence(facts, priority) {
52
- if (priority === "limited")
53
- return "low";
54
- const decisionConf = facts.confidence.decision;
55
- if (decisionConf === "high" || decisionConf === "medium")
56
- return "high";
57
- const sparseUsage = facts.packageUsage.length === 0 ||
58
- facts.packageUsage.every((u) => u.paths.length === 0 && u.criticalPaths.length === 0);
59
- if (sparseUsage)
60
- return "medium";
61
- return "high";
62
- }
63
- /** INTERNAL - only called from buildScanPresentationBundle */
64
- export function derivePresentationProfile(facts, ctx) {
65
- if (ctx.pipelineStatus !== "done")
66
- return null;
67
- const interpretation = derivePresentationInterpretation(facts);
68
- const priority = hasStrongPrIntelligence(facts)
69
- ? "pr_intelligence"
70
- : "limited";
71
- const status = resolveStatus(facts, ctx);
72
- const density = deriveDensity(facts, priority, interpretation);
73
- const confidence = deriveConfidence(facts, priority);
74
- const degradedMessage = priority === "limited"
75
- ? scanSurfaceCopy.presentation.limitedContextMessage
76
- : undefined;
77
- return {
78
- status,
79
- density,
80
- confidence,
81
- priority,
82
- degradedMessage,
83
- interpretation,
84
- };
85
- }
@@ -1,58 +0,0 @@
1
- import type { DashboardCardPresentation } from "./presentation/dto/dashboardCardPresentation.js";
2
- import type { Finding, ScanResult } from "./types.js";
3
- export type ScanPipelineStatus = "queued" | "running" | "done" | "failed";
4
- export type ScanCardPresentationState = "not_scanned" | "scanning" | "analysis_failed" | "ready" | "stale";
5
- export type RiskIndexBand = "low" | "medium" | "high";
6
- export type FindingCountSummary = {
7
- critical: number;
8
- high: number;
9
- medium: number;
10
- low: number;
11
- };
12
- /** @deprecated Use DashboardCardPresentation */
13
- export type ScanCardSummary = DashboardCardPresentation;
14
- export declare const SCAN_CARD_SCANNING_SUMMARY = "Waiting for results...";
15
- export type PipelineCompletionEvidence = {
16
- scannedAt?: string | null;
17
- decision?: string | null;
18
- totalScore?: number | null;
19
- hasResult?: boolean;
20
- };
21
- /** Scan completion signals — decision/totalScore/result are only set after analysis. */
22
- export declare function hasScanCompletionEvidence(evidence: PipelineCompletionEvidence): boolean;
23
- /**
24
- * Resolve wire status using completion evidence (decision, totalScore, result).
25
- * Handles races where denormalized columns are written before status flips to done.
26
- */
27
- export declare function resolvePipelineStatus(status: string | undefined, evidence: PipelineCompletionEvidence): ScanPipelineStatus;
28
- /** Pipeline lifecycle copy that must never appear on completed scan cards. */
29
- export declare function isPipelinePlaceholderCopy(text: string | null | undefined): boolean;
30
- /** True when summary reflects pipeline lifecycle, not merge posture. */
31
- export declare function isPipelineCardSummary(summary: ScanCardSummary): boolean;
32
- /** Single source for risk index color bands (aligns with decision score bands). */
33
- export declare function deriveRiskIndexBand(score: number | null | undefined): RiskIndexBand | null;
34
- export declare function aggregateFindingCounts(findings: Finding[] | null | undefined): FindingCountSummary;
35
- /**
36
- * Server-side card summary for PR dashboard list views.
37
- * Pipeline lifecycle copy is included when `pipelineStatus !== "done"`.
38
- *
39
- * Quiet safe cards with no mappable signals show posture + exposure only.
40
- */
41
- export declare function deriveScanCardSummary(result: ScanResult | null | undefined, pipelineStatus: ScanPipelineStatus): ScanCardSummary;
42
- /** Subline appended when scan results are stale (head SHA mismatch). */
43
- export declare function staleScanSubline(): string;
44
- /** Rebuild card summary from denormalized scan columns when result JSON is unavailable. */
45
- export declare function deriveScanCardSummaryFromDenormalized(decision: string | null, totalScore: number | null, summaryText: string | null, pipelineStatus: ScanPipelineStatus): ScanCardSummary;
46
- export type PrScanCardSummaryInput = {
47
- pipelineStatus: string;
48
- decision: string | null;
49
- totalScore: number | null;
50
- summaryText: string | null;
51
- result: ScanResult | null;
52
- scannedAt?: string | null;
53
- };
54
- /**
55
- * Canonical card summary for PR list/dashboard — single derivation path for API + web.
56
- */
57
- export declare function resolvePrScanCardSummary(input: PrScanCardSummaryInput): ScanCardSummary;
58
- //# sourceMappingURL=scanCardSummary.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scanCardSummary.d.ts","sourceRoot":"","sources":["../src/scanCardSummary.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,iDAAiD,CAAC;AAMjG,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEtD,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE1E,MAAM,MAAM,yBAAyB,GACjC,aAAa,GACb,UAAU,GACV,iBAAiB,GACjB,OAAO,GACP,OAAO,CAAC;AAEZ,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEtD,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,gDAAgD;AAChD,MAAM,MAAM,eAAe,GAAG,yBAAyB,CAAC;AAGxD,eAAO,MAAM,0BAA0B,2BAA2B,CAAC;AAEnE,MAAM,MAAM,0BAA0B,GAAG;IACvC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAsBF,wFAAwF;AACxF,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,0BAA0B,GACnC,OAAO,CAQT;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,QAAQ,EAAE,0BAA0B,GACnC,kBAAkB,CAKpB;AAED,8EAA8E;AAC9E,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC9B,OAAO,CAST;AAED,wEAAwE;AACxE,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAEvE;AAED,mFAAmF;AACnF,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC/B,aAAa,GAAG,IAAI,CAKtB;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI,GAAG,SAAS,GACrC,mBAAmB,CAgBrB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,EACrC,cAAc,EAAE,kBAAkB,GACjC,eAAe,CAOjB;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,2FAA2F;AAC3F,wBAAgB,qCAAqC,CACnD,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,cAAc,EAAE,kBAAkB,GACjC,eAAe,CAuBjB;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,sBAAsB,GAC5B,eAAe,CAcjB"}