@mergesignal/shared 0.4.2 → 0.5.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 (193) 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 +24 -4
  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 +6 -37
  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/compose/narrativeChannels.d.ts +17 -0
  35. package/dist/presentation/compose/narrativeChannels.d.ts.map +1 -0
  36. package/dist/presentation/compose/narrativeChannels.js +45 -0
  37. package/dist/presentation/compose/narrativeChannels.test.d.ts +2 -0
  38. package/dist/presentation/compose/narrativeChannels.test.d.ts.map +1 -0
  39. package/dist/presentation/compose/narrativeChannels.test.js +42 -0
  40. package/dist/presentation/compose/narrativeCompose.d.ts +1 -0
  41. package/dist/presentation/compose/narrativeCompose.d.ts.map +1 -1
  42. package/dist/presentation/compose/narrativeCompose.js +5 -7
  43. package/dist/presentation/dto/assessmentPresentationFields.d.ts +13 -0
  44. package/dist/presentation/dto/assessmentPresentationFields.d.ts.map +1 -0
  45. package/dist/presentation/dto/dashboardCardPresentation.d.ts +30 -0
  46. package/dist/presentation/dto/dashboardCardPresentation.d.ts.map +1 -0
  47. package/dist/presentation/dto/dashboardCardPresentation.js +1 -0
  48. package/dist/presentation/dto/githubAndCliPresentation.d.ts +4 -3
  49. package/dist/presentation/dto/githubAndCliPresentation.d.ts.map +1 -1
  50. package/dist/presentation/dto/scanDetailsPresentation.d.ts +2 -1
  51. package/dist/presentation/dto/scanDetailsPresentation.d.ts.map +1 -1
  52. package/dist/presentation/dto/types.d.ts +0 -9
  53. package/dist/presentation/dto/types.d.ts.map +1 -1
  54. package/dist/presentation/dto/types.js +1 -22
  55. package/dist/presentation/fixtures/dashboardCardGolden.test.d.ts +2 -0
  56. package/dist/presentation/fixtures/dashboardCardGolden.test.d.ts.map +1 -0
  57. package/dist/presentation/fixtures/dashboardCardGolden.test.js +38 -0
  58. package/dist/presentation/fixtures/presentationPersonaFixtures.d.ts.map +1 -1
  59. package/dist/presentation/fixtures/presentationPersonaFixtures.js +31 -24
  60. package/dist/presentation/fixtures/scanResultFixtures.d.ts.map +1 -1
  61. package/dist/presentation/fixtures/scanResultFixtures.js +14 -3
  62. package/dist/presentation/index.d.ts +6 -6
  63. package/dist/presentation/index.d.ts.map +1 -1
  64. package/dist/presentation/index.js +2 -4
  65. package/dist/presentation/orchestration/buildScanCardPresentation.d.ts +2 -2
  66. package/dist/presentation/orchestration/buildScanCardPresentation.d.ts.map +1 -1
  67. package/dist/presentation/orchestration/buildScanCardPresentation.js +13 -9
  68. package/dist/presentation/orchestration/buildScanPresentationBundle.d.ts +1 -1
  69. package/dist/presentation/orchestration/buildScanPresentationBundle.d.ts.map +1 -1
  70. package/dist/presentation/orchestration/buildScanPresentationBundle.js +12 -10
  71. package/dist/presentation/orchestration/scanPresentationBundle.d.ts +8 -3
  72. package/dist/presentation/orchestration/scanPresentationBundle.d.ts.map +1 -1
  73. package/dist/presentation/presentation.test.js +16 -18
  74. package/dist/presentation/presentationPersonas.test.js +20 -19
  75. package/dist/presentation/presenters/presentCliScanSummary.d.ts.map +1 -1
  76. package/dist/presentation/presenters/presentCliScanSummary.js +4 -2
  77. package/dist/presentation/presenters/presentDashboardCard.d.ts +5 -0
  78. package/dist/presentation/presenters/presentDashboardCard.d.ts.map +1 -0
  79. package/dist/presentation/presenters/presentDashboardCard.js +119 -0
  80. package/dist/presentation/presenters/presentGitHubCheckRun.d.ts.map +1 -1
  81. package/dist/presentation/presenters/presentGitHubCheckRun.js +4 -2
  82. package/dist/presentation/presenters/presentGitHubPrComment.d.ts.map +1 -1
  83. package/dist/presentation/presenters/presentGitHubPrComment.js +15 -21
  84. package/dist/presentation/presenters/presentScanDetails.d.ts.map +1 -1
  85. package/dist/presentation/presenters/presentScanDetails.js +53 -127
  86. package/dist/presentation/profile/buildProfileFromAssessment.d.ts +5 -0
  87. package/dist/presentation/profile/buildProfileFromAssessment.d.ts.map +1 -0
  88. package/dist/presentation/profile/buildProfileFromAssessment.js +58 -0
  89. package/dist/presentation/projectAssessmentFields.d.ts +4 -0
  90. package/dist/presentation/projectAssessmentFields.d.ts.map +1 -0
  91. package/dist/presentation/projectAssessmentFields.js +13 -0
  92. package/dist/presentation/surfaceParity.test.d.ts +2 -0
  93. package/dist/presentation/surfaceParity.test.d.ts.map +1 -0
  94. package/dist/presentation/surfaceParity.test.js +74 -0
  95. package/dist/productMessaging.d.ts +4 -4
  96. package/dist/productMessaging.d.ts.map +1 -1
  97. package/dist/productMessaging.js +4 -4
  98. package/dist/productMessaging.test.js +2 -2
  99. package/dist/repoIntelligenceSchema.d.ts +2 -2
  100. package/dist/resolvePipelineStatus.d.ts +15 -0
  101. package/dist/resolvePipelineStatus.d.ts.map +1 -0
  102. package/dist/resolvePipelineStatus.js +37 -0
  103. package/dist/scanCardPresentationState.d.ts +4 -0
  104. package/dist/scanCardPresentationState.d.ts.map +1 -0
  105. package/dist/scanCardPresentationState.js +4 -0
  106. package/dist/{scanDetailViewModel.d.ts → scanDetailViewModelTypes.d.ts} +60 -32
  107. package/dist/scanDetailViewModelTypes.d.ts.map +1 -0
  108. package/dist/scanDetailViewModelTypes.js +4 -0
  109. package/dist/scanResultSchema.d.ts +75 -2
  110. package/dist/scanResultSchema.d.ts.map +1 -1
  111. package/dist/scanResultSchema.js +4 -2
  112. package/dist/scanResultSchema.test.js +16 -0
  113. package/dist/trustedScanGuards.test.js +7 -0
  114. package/dist/types.d.ts +3 -0
  115. package/dist/types.d.ts.map +1 -1
  116. package/package.json +1 -1
  117. package/dist/collectNarrativeWhyBullets.d.ts +0 -12
  118. package/dist/collectNarrativeWhyBullets.d.ts.map +0 -1
  119. package/dist/collectNarrativeWhyBullets.js +0 -104
  120. package/dist/deriveCardDisplaySummary.d.ts +0 -16
  121. package/dist/deriveCardDisplaySummary.d.ts.map +0 -1
  122. package/dist/deriveCardDisplaySummary.js +0 -56
  123. package/dist/deriveCardDisplaySummary.test.d.ts +0 -2
  124. package/dist/deriveCardDisplaySummary.test.d.ts.map +0 -1
  125. package/dist/deriveCardDisplaySummary.test.js +0 -89
  126. package/dist/deriveCardOperationalObservations.d.ts +0 -19
  127. package/dist/deriveCardOperationalObservations.d.ts.map +0 -1
  128. package/dist/deriveCardOperationalObservations.js +0 -180
  129. package/dist/deriveCardOperationalObservations.test.d.ts +0 -2
  130. package/dist/deriveCardOperationalObservations.test.d.ts.map +0 -1
  131. package/dist/deriveCardOperationalObservations.test.js +0 -268
  132. package/dist/deriveRiskScoreSummary.d.ts +0 -33
  133. package/dist/deriveRiskScoreSummary.d.ts.map +0 -1
  134. package/dist/deriveRiskScoreSummary.js +0 -90
  135. package/dist/deriveRiskScoreSummary.test.d.ts +0 -2
  136. package/dist/deriveRiskScoreSummary.test.d.ts.map +0 -1
  137. package/dist/deriveRiskScoreSummary.test.js +0 -47
  138. package/dist/deriveScanDetailRecommendations.d.ts +0 -63
  139. package/dist/deriveScanDetailRecommendations.d.ts.map +0 -1
  140. package/dist/deriveScanDetailRecommendations.js +0 -725
  141. package/dist/deriveScanDetailRecommendations.test.d.ts +0 -2
  142. package/dist/deriveScanDetailRecommendations.test.d.ts.map +0 -1
  143. package/dist/deriveScanDetailRecommendations.test.js +0 -181
  144. package/dist/deriveScanSummaryText.d.ts +0 -7
  145. package/dist/deriveScanSummaryText.d.ts.map +0 -1
  146. package/dist/deriveScanSummaryText.js +0 -24
  147. package/dist/deriveScanSummaryText.test.d.ts +0 -2
  148. package/dist/deriveScanSummaryText.test.d.ts.map +0 -1
  149. package/dist/deriveScanSummaryText.test.js +0 -77
  150. package/dist/formatCardEvidenceCounts.d.ts +0 -7
  151. package/dist/formatCardEvidenceCounts.d.ts.map +0 -1
  152. package/dist/formatCardEvidenceCounts.js +0 -19
  153. package/dist/prCheckRunPresentation.d.ts +0 -68
  154. package/dist/prCheckRunPresentation.d.ts.map +0 -1
  155. package/dist/prCheckRunPresentation.js +0 -319
  156. package/dist/prCheckRunPresentation.test.d.ts +0 -2
  157. package/dist/prCheckRunPresentation.test.d.ts.map +0 -1
  158. package/dist/prCheckRunPresentation.test.js +0 -278
  159. package/dist/presentation/dto/scanCardPresentation.d.ts +0 -27
  160. package/dist/presentation/dto/scanCardPresentation.d.ts.map +0 -1
  161. package/dist/presentation/intent/derivePresentationInterpretation.d.ts +0 -4
  162. package/dist/presentation/intent/derivePresentationInterpretation.d.ts.map +0 -1
  163. package/dist/presentation/intent/derivePresentationInterpretation.js +0 -202
  164. package/dist/presentation/intent/formatPresentationCopy.d.ts +0 -7
  165. package/dist/presentation/intent/formatPresentationCopy.d.ts.map +0 -1
  166. package/dist/presentation/intent/formatPresentationCopy.js +0 -153
  167. package/dist/presentation/intent/presentationIntent.test.d.ts +0 -2
  168. package/dist/presentation/intent/presentationIntent.test.d.ts.map +0 -1
  169. package/dist/presentation/intent/presentationIntent.test.js +0 -29
  170. package/dist/presentation/intent/verificationFocusLabels.d.ts +0 -2
  171. package/dist/presentation/intent/verificationFocusLabels.d.ts.map +0 -1
  172. package/dist/presentation/intent/verificationFocusLabels.js +0 -45
  173. package/dist/presentation/presenters/presentPipelineScanCard.d.ts +0 -3
  174. package/dist/presentation/presenters/presentPipelineScanCard.d.ts.map +0 -1
  175. package/dist/presentation/presenters/presentPipelineScanCard.js +0 -23
  176. package/dist/presentation/presenters/presentScanCard.d.ts +0 -7
  177. package/dist/presentation/presenters/presentScanCard.d.ts.map +0 -1
  178. package/dist/presentation/presenters/presentScanCard.js +0 -44
  179. package/dist/presentation/profile/derivePresentationProfile.d.ts +0 -12
  180. package/dist/presentation/profile/derivePresentationProfile.d.ts.map +0 -1
  181. package/dist/presentation/profile/derivePresentationProfile.js +0 -85
  182. package/dist/scanCardSummary.d.ts +0 -59
  183. package/dist/scanCardSummary.d.ts.map +0 -1
  184. package/dist/scanCardSummary.js +0 -146
  185. package/dist/scanCardSummary.test.d.ts +0 -2
  186. package/dist/scanCardSummary.test.d.ts.map +0 -1
  187. package/dist/scanCardSummary.test.js +0 -234
  188. package/dist/scanDetailViewModel.d.ts.map +0 -1
  189. package/dist/scanDetailViewModel.js +0 -636
  190. package/dist/scanDetailViewModel.test.d.ts +0 -2
  191. package/dist/scanDetailViewModel.test.d.ts.map +0 -1
  192. package/dist/scanDetailViewModel.test.js +0 -530
  193. /package/dist/presentation/dto/{scanCardPresentation.js → assessmentPresentationFields.js} +0 -0
@@ -0,0 +1,119 @@
1
+ import { MERGE_POSTURE_LABEL, MERGE_POSTURE_SORT_ORDER, } from "../../riskVocabulary.js";
2
+ import { normalizeGeneratedText, normalizeGeneratedTextNullable, } from "../../normalizeGeneratedText.js";
3
+ import { scanSurfaceCopy } from "../../scanSurfaceCopy.js";
4
+ import { buildNarrativeChannels } from "../compose/narrativeChannels.js";
5
+ import { projectAssessmentFields } from "../projectAssessmentFields.js";
6
+ const INSIGHTS_CAP = 3;
7
+ const SCOPE_AREAS_CAP = 2;
8
+ const EVIDENCE_CAP = 2;
9
+ const VERIFICATION_CAP = 2;
10
+ function formatVerificationLine(action) {
11
+ const trimmed = action.trim();
12
+ if (/^verify\b/i.test(trimmed))
13
+ return trimmed;
14
+ return `Verify ${trimmed}`;
15
+ }
16
+ function deriveLayout(channels, profile) {
17
+ const bodyCount = channels.insights.length +
18
+ channels.scopeAreas.length +
19
+ channels.evidence.length +
20
+ channels.verification.length;
21
+ if (profile.status === "safe" &&
22
+ profile.density === "minimal" &&
23
+ bodyCount === 0 &&
24
+ !channels.limitedContextMessage) {
25
+ return "quiet";
26
+ }
27
+ if (profile.density === "rich") {
28
+ return "expanded";
29
+ }
30
+ return "standard";
31
+ }
32
+ function normalizeDashboardCard(card) {
33
+ return {
34
+ ...card,
35
+ headline: normalizeGeneratedText(card.headline),
36
+ limitedContext: card.limitedContext
37
+ ? {
38
+ message: normalizeGeneratedText(card.limitedContext.message),
39
+ }
40
+ : undefined,
41
+ insights: card.insights.map((i) => normalizeGeneratedText(i)),
42
+ scopeAreas: card.scopeAreas?.map((a) => normalizeGeneratedText(a)),
43
+ verification: card.verification.map((v) => normalizeGeneratedText(v)),
44
+ evidenceChips: card.evidenceChips?.map((e) => ({
45
+ label: normalizeGeneratedText(e.label),
46
+ value: normalizeGeneratedText(e.value),
47
+ })),
48
+ pipeline: card.pipeline
49
+ ? {
50
+ ...card.pipeline,
51
+ headline: normalizeGeneratedText(card.pipeline.headline),
52
+ subheadline: normalizeGeneratedTextNullable(card.pipeline.subheadline) ??
53
+ undefined,
54
+ }
55
+ : undefined,
56
+ };
57
+ }
58
+ export function presentDashboardCard(bundle) {
59
+ const { facts, profile } = bundle;
60
+ const channels = buildNarrativeChannels(bundle);
61
+ const posture = profile.status;
62
+ const riskIndex = facts.riskIndex != null && Number.isFinite(facts.riskIndex)
63
+ ? facts.riskIndex
64
+ : -1;
65
+ const insights = channels.insights.slice(0, INSIGHTS_CAP);
66
+ const scopeAreas = channels.scopeAreas.length > 0
67
+ ? channels.scopeAreas.slice(0, SCOPE_AREAS_CAP)
68
+ : undefined;
69
+ const evidenceChips = channels.evidence.length > 0
70
+ ? channels.evidence.slice(0, EVIDENCE_CAP)
71
+ : undefined;
72
+ const verification = channels.verification
73
+ .slice(0, VERIFICATION_CAP)
74
+ .map(formatVerificationLine);
75
+ const card = {
76
+ ...projectAssessmentFields(bundle),
77
+ verdict: {
78
+ posture,
79
+ postureLabel: MERGE_POSTURE_LABEL[posture],
80
+ scopeLabel: channels.reachLabel,
81
+ },
82
+ headline: channels.headline,
83
+ limitedContext: channels.limitedContextMessage
84
+ ? { message: channels.limitedContextMessage }
85
+ : undefined,
86
+ insights,
87
+ scopeAreas,
88
+ verification,
89
+ evidenceChips,
90
+ layout: deriveLayout(channels, profile),
91
+ detailActionLabel: scanSurfaceCopy.presentation.actionLabelReview,
92
+ sortKey: {
93
+ postureRank: MERGE_POSTURE_SORT_ORDER[posture],
94
+ riskIndex,
95
+ },
96
+ };
97
+ return normalizeDashboardCard(card);
98
+ }
99
+ export function presentPipelineDashboardCard(pipelineStatus) {
100
+ const isRunning = pipelineStatus === "queued" || pipelineStatus === "running";
101
+ const headline = isRunning
102
+ ? scanSurfaceCopy.pipeline.scanRunning
103
+ : scanSurfaceCopy.pipeline.analysisIncomplete;
104
+ return normalizeDashboardCard({
105
+ pipeline: {
106
+ status: pipelineStatus,
107
+ headline,
108
+ subheadline: isRunning
109
+ ? scanSurfaceCopy.pipeline.scanIncomplete
110
+ : undefined,
111
+ },
112
+ headline,
113
+ insights: [],
114
+ verification: [],
115
+ layout: "standard",
116
+ detailActionLabel: scanSurfaceCopy.presentation.actionLabelReview,
117
+ sortKey: { postureRank: -1, riskIndex: -1 },
118
+ });
119
+ }
@@ -1 +1 @@
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;AAEzF,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,CAkC5B"}
1
+ {"version":3,"file":"presentGitHubCheckRun.d.ts","sourceRoot":"","sources":["../../../src/presentation/presenters/presentGitHubCheckRun.ts"],"names":[],"mappings":"AAQA,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,CAmC5B"}
@@ -1,8 +1,9 @@
1
- import { composeHeadline, composeKeyPoints, composeSubheadline, composeVerificationActions, evidenceContextFromProfile, } from "../compose/narrativeCompose.js";
1
+ import { buildNarrativeChannels, composeHeadline, composeSubheadline, composeVerificationActions, evidenceContextFromProfile, projectCompactKeyPoints, } from "../compose/narrativeCompose.js";
2
+ import { projectAssessmentFields } from "../projectAssessmentFields.js";
2
3
  export function presentGitHubCheckRun(bundle, ctx) {
3
4
  const { profile } = bundle;
4
5
  const headline = composeHeadline(bundle);
5
- const keyPoints = composeKeyPoints(bundle, 3);
6
+ const keyPoints = projectCompactKeyPoints(buildNarrativeChannels(bundle), 3);
6
7
  const actions = composeVerificationActions(bundle, 3);
7
8
  const detailsUrl = `${ctx.webAppOrigin.replace(/\/$/, "")}/scan/${ctx.scanId}`;
8
9
  const conclusion = profile.status === "safe"
@@ -19,6 +20,7 @@ export function presentGitHubCheckRun(bundle, ctx) {
19
20
  }
20
21
  sections.push({ id: "footer", bullets: [`Full scan: ${detailsUrl}`] });
21
22
  return {
23
+ ...projectAssessmentFields(bundle),
22
24
  status: profile.status,
23
25
  density: profile.density,
24
26
  confidence: profile.confidence,
@@ -1 +1 @@
1
- {"version":3,"file":"presentGitHubPrComment.d.ts","sourceRoot":"","sources":["../../../src/presentation/presenters/presentGitHubPrComment.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AAEzF,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,sBAAsB,GAC7B,2BAA2B,CAwC7B"}
1
+ {"version":3,"file":"presentGitHubPrComment.d.ts","sourceRoot":"","sources":["../../../src/presentation/presenters/presentGitHubPrComment.ts"],"names":[],"mappings":"AASA,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,CA8B7B"}
@@ -1,34 +1,28 @@
1
1
  import { MERGE_POSTURE_LABEL } from "../../riskVocabulary.js";
2
- import { composeVerificationActions, evidenceContextFromProfile, } from "../compose/narrativeCompose.js";
3
- import { formatChangedPackagesShort, formatUsageSummaryLine, selectReviewerGuidance, } from "../../narrativePresentation.js";
2
+ import { buildNarrativeChannels, evidenceContextFromProfile, } from "../compose/narrativeCompose.js";
3
+ import { formatChangedPackagesShort } from "../../narrativePresentation.js";
4
+ import { projectAssessmentFields } from "../projectAssessmentFields.js";
4
5
  export function presentGitHubPrComment(bundle) {
5
6
  const { facts, profile } = bundle;
7
+ const channels = buildNarrativeChannels(bundle);
8
+ const assessmentFields = projectAssessmentFields(bundle);
6
9
  const introLines = [];
7
10
  const changed = formatChangedPackagesShort(facts, 3);
8
11
  if (changed)
9
12
  introLines.push(`Changed: ${changed}`);
10
- const usage = formatUsageSummaryLine(facts, 1);
11
- if (usage)
12
- introLines.push(usage);
13
- const verify = composeVerificationActions(bundle, 1)[0];
13
+ for (const line of assessmentFields.reasoning.slice(0, 2)) {
14
+ introLines.push(line);
15
+ }
16
+ const verify = channels.verification[0];
14
17
  if (verify)
15
18
  introLines.push(`Verify: ${verify}`);
16
- const guidance = selectReviewerGuidance(facts, { scope: "changed", max: 3 });
17
- const selected = guidance.length === 0
18
- ? selectReviewerGuidance(facts, { max: 3 })
19
- : guidance;
20
- const guidanceBlocks = selected.map((g) => {
21
- const where = g.context?.trim() ||
22
- facts.packageUsage
23
- .flatMap((u) => u.paths.slice(0, 1))
24
- .filter(Boolean)[0] ||
25
- "See scan detail for affected paths.";
26
- const action = g.remediation?.trim() ||
27
- composeVerificationActions(bundle, 1)[0] ||
28
- "Review before merge.";
29
- return { message: g.message, where, action };
30
- });
19
+ const guidanceBlocks = channels.verification.slice(0, 3).map((action) => ({
20
+ message: assessmentFields.reasoning[0] ?? action,
21
+ where: changed ?? "See scan detail for affected paths.",
22
+ action,
23
+ }));
31
24
  return {
25
+ ...assessmentFields,
32
26
  status: profile.status,
33
27
  density: profile.density,
34
28
  confidence: profile.confidence,
@@ -1 +1 @@
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;AAEzF,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;AAoHF,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,sBAAsB,EAC9B,GAAG,EAAE,yBAAyB,GAC7B,uBAAuB,CAyFzB"}
1
+ {"version":3,"file":"presentScanDetails.d.ts","sourceRoot":"","sources":["../../../src/presentation/presenters/presentScanDetails.ts"],"names":[],"mappings":"AAcA,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;AAmDF,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,sBAAsB,EAC9B,GAAG,EAAE,yBAAyB,GAC7B,uBAAuB,CAwEzB"}
@@ -1,88 +1,9 @@
1
- import { deriveDetailReachChip } from "../../formatCardExposureDisplay.js";
1
+ import { MERGE_CONCERN_LABELS } from "../../assessmentLabels.js";
2
2
  import { MERGE_POSTURE_LABEL } from "../../riskVocabulary.js";
3
- import { deriveVerdictLineFromFacts, presentScanDetailViewModel, } from "../../scanDetailViewModel.js";
4
- import { composeHeadline, composeKeyPoints, composeSubheadline, composeSupportingContext, composeVerificationActions, evidenceContextFromProfile, } from "../compose/narrativeCompose.js";
3
+ import { buildNarrativeChannels, composeSubheadline, composeSupportingContext, evidenceContextFromProfile, projectCompactKeyPoints, } from "../compose/narrativeCompose.js";
5
4
  import { normalizeGeneratedText, normalizeGeneratedTextNullable, } from "../../normalizeGeneratedText.js";
6
5
  import { scanSurfaceCopy } from "../../scanSurfaceCopy.js";
7
- function mapOperationalImpact(vm) {
8
- const oi = vm.operationalImpact;
9
- if (oi.status === "hidden") {
10
- return { status: "hidden", items: [] };
11
- }
12
- if (oi.status === "rich") {
13
- return {
14
- status: "rich",
15
- items: oi.items.map((item) => ({
16
- message: item.message,
17
- where: item.where,
18
- verify: item.verify,
19
- affectedFiles: item.affectedFiles,
20
- })),
21
- };
22
- }
23
- return {
24
- status: "compact",
25
- items: oi.items,
26
- fallbackMessage: oi.fallbackMessage,
27
- };
28
- }
29
- function mapRecommendations(vm) {
30
- const items = vm.recommendedActions.items.map((item) => ({
31
- rank: item.rank,
32
- title: item.title,
33
- priority: item.priority === "high" ||
34
- item.priority === "medium" ||
35
- item.priority === "low"
36
- ? item.priority
37
- : "medium",
38
- rationale: item.detail?.why,
39
- }));
40
- return { items };
41
- }
42
- function mapEvidence(bundle, vm) {
43
- const defaultCollapsed = bundle.profile.priority === "pr_intelligence" &&
44
- bundle.profile.density === "rich";
45
- const ev = vm.evidence;
46
- if (!ev) {
47
- return {
48
- defaultCollapsed,
49
- attentionAreas: [],
50
- findings: [],
51
- findingsOverflowCount: 0,
52
- };
53
- }
54
- return {
55
- defaultCollapsed,
56
- attentionAreas: ev.attentionAreas.map((area) => ({
57
- problemLabel: area.problemLabel,
58
- problemDescription: area.problemDescription,
59
- packages: area.packages.map((p) => ({
60
- name: p.name,
61
- version: p.version,
62
- direct: p.direct,
63
- severity: p.severity,
64
- evidence: p.evidence,
65
- })),
66
- overflowCount: area.overflowCount,
67
- })),
68
- findings: ev.findings.map((f) => ({
69
- id: f.id,
70
- severity: f.severity,
71
- title: f.title,
72
- description: f.description,
73
- packageName: f.packageName,
74
- recommendation: f.recommendation,
75
- source: f.source,
76
- })),
77
- findingsOverflowCount: ev.findingsOverflowCount,
78
- topology: ev.topology
79
- ? {
80
- summaryLine: ev.topology.summaryLine,
81
- deepest: ev.topology.deepest,
82
- }
83
- : undefined,
84
- };
85
- }
6
+ import { projectAssessmentFields } from "../projectAssessmentFields.js";
86
7
  function mapUsage(bundle) {
87
8
  const { facts } = bundle;
88
9
  if (facts.packageUsage.length === 0 && facts.frameworks.length === 0) {
@@ -101,19 +22,31 @@ function mapUsage(bundle) {
101
22
  frameworks: facts.frameworks,
102
23
  };
103
24
  }
25
+ function mapEvidence(bundle) {
26
+ const defaultCollapsed = bundle.profile.priority === "pr_intelligence" &&
27
+ bundle.profile.density === "rich";
28
+ const findings = (bundle.result.findings ?? []).slice(0, 8).map((f) => ({
29
+ id: f.id,
30
+ severity: f.severity,
31
+ title: f.title,
32
+ description: f.description,
33
+ packageName: f.packageName,
34
+ recommendation: f.recommendation,
35
+ source: "dependency",
36
+ }));
37
+ return {
38
+ defaultCollapsed,
39
+ attentionAreas: [],
40
+ findings,
41
+ findingsOverflowCount: Math.max(0, (bundle.result.findings?.length ?? 0) - findings.length),
42
+ };
43
+ }
104
44
  export function presentScanDetails(bundle, ctx) {
105
- const { facts, profile, result } = bundle;
106
- const vm = presentScanDetailViewModel(facts, result, {
107
- scanId: ctx.scanId,
108
- status: "done",
109
- methodologyVersion: ctx.methodologyVersion,
110
- prNumber: ctx.prNumber,
111
- repoContext: { status: "hidden" },
112
- });
113
- const headline = composeHeadline(bundle);
45
+ const { assessment, facts, profile, result } = bundle;
46
+ const assessmentFields = projectAssessmentFields(bundle);
47
+ const channels = buildNarrativeChannels(bundle);
48
+ const keyPoints = projectCompactKeyPoints(channels, 6);
114
49
  const subheadline = composeSubheadline(bundle);
115
- const keyPoints = composeKeyPoints(bundle, 6);
116
- const verificationTitles = composeVerificationActions(bundle, 6);
117
50
  const supportingLines = composeSupportingContext(bundle);
118
51
  const supportingContext = supportingLines
119
52
  ? {
@@ -121,26 +54,39 @@ export function presentScanDetails(bundle, ctx) {
121
54
  lines: supportingLines,
122
55
  }
123
56
  : undefined;
124
- const posture = profile.status;
125
- const postureLabel = MERGE_POSTURE_LABEL[posture];
126
- const toolingIntent = profile.interpretation.intent === "tooling_patch" ||
127
- profile.interpretation.intent === "tooling_upgrade";
128
- const verdictLine = profile.priority === "pr_intelligence" && toolingIntent && keyPoints[0]
129
- ? keyPoints[0]
130
- : deriveVerdictLineFromFacts(facts, result);
57
+ const postureLabel = MERGE_POSTURE_LABEL[profile.status];
58
+ const verdictLine = assessmentFields.reasoning[0] ??
59
+ (assessment.primaryConcern
60
+ ? MERGE_CONCERN_LABELS[assessment.primaryConcern]
61
+ : postureLabel);
62
+ const verificationActions = channels.verification.map((title, index) => ({
63
+ title: normalizeGeneratedText(title),
64
+ detail: assessmentFields.reasoning[index + 1],
65
+ }));
66
+ const recommendations = verificationActions.map((action, index) => ({
67
+ rank: index + 1,
68
+ title: action.title,
69
+ priority: profile.status === "risky"
70
+ ? "high"
71
+ : profile.status === "needs_review"
72
+ ? "medium"
73
+ : "low",
74
+ rationale: action.detail,
75
+ }));
131
76
  return {
77
+ ...assessmentFields,
132
78
  evidenceContext: evidenceContextFromProfile(bundle),
133
79
  status: profile.status,
134
80
  density: profile.density,
135
81
  confidence: profile.confidence,
136
82
  presentationIntent: profile.interpretation.intent,
137
83
  hero: {
138
- headline: normalizeGeneratedText(headline),
84
+ headline: normalizeGeneratedText(channels.headline),
139
85
  subheadline: normalizeGeneratedTextNullable(subheadline) ?? undefined,
140
86
  verdictLine: normalizeGeneratedText(verdictLine),
141
- scopeChip: deriveDetailReachChip(result.totalScore) ?? undefined,
87
+ scopeChip: channels.reachLabel,
142
88
  postureLabel,
143
- riskIndex: facts.riskIndex,
89
+ riskIndex: result.totalScore,
144
90
  },
145
91
  narrative: {
146
92
  keyPoints: keyPoints.map((k) => normalizeGeneratedText(k)),
@@ -148,30 +94,10 @@ export function presentScanDetails(bundle, ctx) {
148
94
  primaryPackage: facts.changedPackages.primary ?? undefined,
149
95
  },
150
96
  usage: mapUsage(bundle),
151
- verification: {
152
- actions: verificationTitles.map((title) => ({
153
- title: normalizeGeneratedText(title),
154
- })),
155
- },
156
- signalSummary: vm.signalSummary
157
- ? {
158
- riskIndex: vm.signalSummary.score,
159
- band: vm.signalSummary.overallBand === "moderate"
160
- ? "medium"
161
- : vm.signalSummary.overallBand === "high"
162
- ? "high"
163
- : "low",
164
- layers: vm.signalSummary.layers.map((l) => ({
165
- layer: l.layer,
166
- score: l.score,
167
- band: l.concernLabel,
168
- label: l.label,
169
- })),
170
- }
171
- : undefined,
172
- operationalImpact: mapOperationalImpact(vm),
173
- recommendations: mapRecommendations(vm),
174
- evidence: mapEvidence(bundle, vm),
97
+ verification: { actions: verificationActions },
98
+ operationalImpact: { status: "hidden", items: [] },
99
+ recommendations: { items: recommendations },
100
+ evidence: mapEvidence(bundle),
175
101
  supportingContext,
176
102
  metadata: {
177
103
  scanId: ctx.scanId,
@@ -0,0 +1,5 @@
1
+ import type { Assessment, AssessmentPresentationPublic } from "../../assessmentSchema.js";
2
+ import type { ScanResult } from "../../types.js";
3
+ import type { PresentationProfile } from "./presentationProfile.js";
4
+ export declare function buildProfileFromAssessment(assessment: Assessment, presentation: AssessmentPresentationPublic, result: ScanResult): PresentationProfile;
5
+ //# sourceMappingURL=buildProfileFromAssessment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildProfileFromAssessment.d.ts","sourceRoot":"","sources":["../../../src/presentation/profile/buildProfileFromAssessment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,4BAA4B,EAC7B,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAIjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAwCpE,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,4BAA4B,EAC1C,MAAM,EAAE,UAAU,GACjB,mBAAmB,CAuBrB"}
@@ -0,0 +1,58 @@
1
+ import { narrativeIntensityToDensity } from "../../assessmentSchema.js";
2
+ import { safeParseRepoIntelligence } from "../../repoIntelligenceSchema.js";
3
+ import { scanSurfaceCopy } from "../../scanSurfaceCopy.js";
4
+ import { collectVerificationFocus } from "../../assessmentProjection.js";
5
+ function buildInterpretation(assessment, presentation, result) {
6
+ const verificationLabels = collectVerificationFocus(result);
7
+ const anchorPackage = result.changedPackages?.[0] ?? null;
8
+ const suppressRuntimeNarrative = presentation.reachVisibility === "hidden";
9
+ let intent = "unknown_upgrade";
10
+ if (assessment.primaryConcern === "insufficient_evidence") {
11
+ intent = "limited_context";
12
+ }
13
+ else if (assessment.changeClasses.includes("tooling_maintenance")) {
14
+ intent = "tooling_patch";
15
+ }
16
+ else if (assessment.primaryConcern === "confirmed_runtime_usage") {
17
+ if (assessment.factors.includes("queue_infrastructure")) {
18
+ intent = "queue_runtime_upgrade";
19
+ }
20
+ else if (assessment.factors.includes("auth_infrastructure")) {
21
+ intent = "auth_runtime_upgrade";
22
+ }
23
+ else {
24
+ intent = "runtime_upgrade";
25
+ }
26
+ }
27
+ return {
28
+ intent,
29
+ anchorPackage,
30
+ suppressRuntimeNarrative,
31
+ allowRuntimeNarrative: !suppressRuntimeNarrative,
32
+ showLimitedEvidence: assessment.confidence === "low",
33
+ expectedImpactKey: null,
34
+ verificationLabels,
35
+ runtimeSurfaceLabel: null,
36
+ runtimePackages: [],
37
+ };
38
+ }
39
+ export function buildProfileFromAssessment(assessment, presentation, result) {
40
+ const riParse = safeParseRepoIntelligence(result.repoIntelligence);
41
+ const priority = riParse.ok && (result.changedPackages?.length ?? 0) > 0
42
+ ? "pr_intelligence"
43
+ : "limited";
44
+ const degradedMessage = assessment.primaryConcern === "insufficient_evidence" ||
45
+ assessment.confidence === "low"
46
+ ? scanSurfaceCopy.presentation.limitedContextMessage
47
+ : priority === "limited"
48
+ ? scanSurfaceCopy.presentation.limitedContextMessage
49
+ : undefined;
50
+ return {
51
+ status: assessment.posture,
52
+ density: narrativeIntensityToDensity(presentation.narrativeIntensity),
53
+ confidence: assessment.confidence,
54
+ priority,
55
+ degradedMessage,
56
+ interpretation: buildInterpretation(assessment, presentation, result),
57
+ };
58
+ }
@@ -0,0 +1,4 @@
1
+ import type { AssessmentPresentationFields } from "./dto/assessmentPresentationFields.js";
2
+ import type { ScanPresentationBundle } from "./orchestration/scanPresentationBundle.js";
3
+ export declare function projectAssessmentFields(bundle: ScanPresentationBundle): AssessmentPresentationFields;
4
+ //# sourceMappingURL=projectAssessmentFields.d.ts.map
@@ -0,0 +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;AAExF,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,sBAAsB,GAC7B,4BAA4B,CAW9B"}
@@ -0,0 +1,13 @@
1
+ import { collectVerificationFocus, projectReasoningLines, } from "../assessmentProjection.js";
2
+ export function projectAssessmentFields(bundle) {
3
+ const { assessment, presentation, result } = bundle;
4
+ return {
5
+ posture: assessment.posture,
6
+ primaryConcern: assessment.primaryConcern,
7
+ factors: [...assessment.factors],
8
+ reasoning: projectReasoningLines(result),
9
+ verificationFocus: collectVerificationFocus(result),
10
+ reachVisibility: presentation.reachVisibility,
11
+ narrativeIntensity: presentation.narrativeIntensity,
12
+ };
13
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=surfaceParity.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceParity.test.d.ts","sourceRoot":"","sources":["../../src/presentation/surfaceParity.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,74 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { buildScanPresentationBundle } from "./orchestration/buildScanPresentationBundle.js";
3
+ import { presentDashboardCard } from "./presenters/presentDashboardCard.js";
4
+ import { presentScanDetails } from "./presenters/presentScanDetails.js";
5
+ import { presentGitHubCheckRun } from "./presenters/presentGitHubCheckRun.js";
6
+ import { presentGitHubPrComment } from "./presenters/presentGitHubPrComment.js";
7
+ import { renderGitHubCheckRunMarkdown } from "./render/renderGitHubCheckRunMarkdown.js";
8
+ import { renderGitHubPrCommentMarkdown } from "./render/renderGitHubPrCommentMarkdown.js";
9
+ import { scanResultBullmq, scanResultEslint, scanResultFastifyRuntime, scanResultMixedTypescriptFastify, scanResultPrettier, scanResultTypescriptPatch, scanResultVitest, } from "./fixtures/presentationPersonaFixtures.js";
10
+ import { projectAssessmentFields } from "./projectAssessmentFields.js";
11
+ const SCAN_ID = "22222222-2222-4222-8222-222222222222";
12
+ const ORIGIN = "https://app.example.com";
13
+ const validationPersonas = [
14
+ { name: "PR #26 mixed", result: scanResultMixedTypescriptFastify },
15
+ { name: "PR #27 fastify", result: scanResultFastifyRuntime },
16
+ { name: "PR #28 typescript", result: scanResultTypescriptPatch },
17
+ { name: "PR #29 prettier", result: scanResultPrettier },
18
+ { name: "PR #30 bullmq", result: scanResultBullmq },
19
+ { name: "eslint", result: scanResultEslint },
20
+ { name: "vitest", result: scanResultVitest },
21
+ ];
22
+ function surfacesFor(result) {
23
+ const bundle = buildScanPresentationBundle({
24
+ result,
25
+ pipelineStatus: "done",
26
+ });
27
+ const fields = projectAssessmentFields(bundle);
28
+ const card = presentDashboardCard(bundle);
29
+ const details = presentScanDetails(bundle, { scanId: SCAN_ID });
30
+ const check = presentGitHubCheckRun(bundle, {
31
+ scanId: SCAN_ID,
32
+ webAppOrigin: ORIGIN,
33
+ });
34
+ const comment = presentGitHubPrComment(bundle);
35
+ const checkMd = renderGitHubCheckRunMarkdown(check);
36
+ const commentMd = renderGitHubPrCommentMarkdown(comment);
37
+ return { bundle, fields, card, details, check, comment, checkMd, commentMd };
38
+ }
39
+ describe("surfaceParity guardrail", () => {
40
+ for (const persona of validationPersonas) {
41
+ it(`${persona.name}: posture and assessment fields match across surfaces`, () => {
42
+ const s = surfacesFor(persona.result);
43
+ expect(s.card.posture).toBe(s.fields.posture);
44
+ expect(s.details.posture).toBe(s.fields.posture);
45
+ expect(s.check.posture).toBe(s.fields.posture);
46
+ expect(s.comment.posture).toBe(s.fields.posture);
47
+ expect(s.card.verdict?.posture).toBe(s.fields.posture);
48
+ expect(s.card.primaryConcern).toBe(s.fields.primaryConcern);
49
+ expect(s.details.primaryConcern).toBe(s.fields.primaryConcern);
50
+ expect(s.check.primaryConcern).toBe(s.fields.primaryConcern);
51
+ expect(s.comment.primaryConcern).toBe(s.fields.primaryConcern);
52
+ expect(s.card.narrativeIntensity).toBe(s.fields.narrativeIntensity);
53
+ expect(s.details.narrativeIntensity).toBe(s.fields.narrativeIntensity);
54
+ expect(s.check.narrativeIntensity).toBe(s.fields.narrativeIntensity);
55
+ expect(s.comment.narrativeIntensity).toBe(s.fields.narrativeIntensity);
56
+ expect(s.card.reachVisibility).toBe(s.fields.reachVisibility);
57
+ expect(s.details.reachVisibility).toBe(s.fields.reachVisibility);
58
+ expect(s.check.reachVisibility).toBe(s.fields.reachVisibility);
59
+ expect(s.comment.reachVisibility).toBe(s.fields.reachVisibility);
60
+ expect(s.card.reasoning).toEqual(s.fields.reasoning);
61
+ expect(s.details.reasoning).toEqual(s.fields.reasoning);
62
+ expect(s.check.reasoning).toEqual(s.fields.reasoning);
63
+ expect(s.comment.reasoning).toEqual(s.fields.reasoning);
64
+ expect(s.card.verificationFocus).toEqual(s.fields.verificationFocus);
65
+ expect(s.details.verificationFocus).toEqual(s.fields.verificationFocus);
66
+ expect(s.check.verificationFocus).toEqual(s.fields.verificationFocus);
67
+ expect(s.comment.verificationFocus).toEqual(s.fields.verificationFocus);
68
+ });
69
+ it(`${persona.name}: headline matches across card and details`, () => {
70
+ const s = surfacesFor(persona.result);
71
+ expect(s.details.hero.headline).toBe(s.card.headline);
72
+ });
73
+ }
74
+ });
@@ -2,7 +2,7 @@
2
2
  * Canonical marketing / category copy. Operational scan strings stay in scanSurfaceCopy.
3
3
  */
4
4
  export declare const productMessaging: {
5
- readonly formalDefinition: "MergeSignal analyzes dependency upgrades, identifies affected application flows, and provides reviewer guidance before merge.";
5
+ readonly formalDefinition: "MergeSignal analyzes dependency upgrades in context, inspects relevant code paths, and provides focused reviewer guidance before merge - without requiring a full repository scan.";
6
6
  readonly hero: {
7
7
  readonly kicker: "Merge-decision intelligence for dependency upgrades";
8
8
  readonly h1: "See what a dependency upgrade can break.";
@@ -68,10 +68,10 @@ export declare const productMessaging: {
68
68
  readonly dashboardPrCard: {
69
69
  readonly intro: "The repository dashboard is a runtime-aware review surface for open upgrade pull requests: triage by merge recommendation, then read operational context on each card.";
70
70
  readonly posture: `Posture indicates the merge recommendation (${string}, ${string}, ${string}).`;
71
- readonly exposure: "Exposure indicates how broadly the upgrade touches runtime-relevant application areas.";
72
- readonly exposureCategoriesLead: "On each scanned card, exposure reads as one of:";
71
+ readonly exposure: "Reach indicates how prominently affected application paths are surfaced for this upgrade.";
72
+ readonly exposureCategoriesLead: "Risk index bands (supporting context) read as one of:";
73
73
  readonly exposureCategories: readonly string[];
74
- readonly cardBody: "Below the verdict, scanned cards lead with the changed package, runtime surface, reachability, blast radius, and affected areas when code intelligence is available; repository-wide graph signals appear only as supporting context.";
74
+ readonly cardBody: "Below the verdict, scanned cards lead with the changed package, affected areas, verification checks, and blast radius when code intelligence is available - focused on this PR, not the whole repository.";
75
75
  };
76
76
  };
77
77
  /** Illustrative scan-card example for homepage proof band and getting-started. */
@@ -1 +1 @@
1
- {"version":3,"file":"productMessaging.d.ts","sourceRoot":"","sources":["../src/productMessaging.ts"],"names":[],"mappings":"AAGA;;GAEG;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAmF3B,6FAA6F;;;;;;;;;CAYrF,CAAC;AAEX,kFAAkF;AAClF,eAAO,MAAM,gBAAgB;;;;CAOnB,CAAC;AAEX,iEAAiE;AACjE,wBAAgB,wBAAwB,IAAI,MAAM,EAAE,CAOnD"}
1
+ {"version":3,"file":"productMessaging.d.ts","sourceRoot":"","sources":["../src/productMessaging.ts"],"names":[],"mappings":"AAGA;;GAEG;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAmF3B,6FAA6F;;;;;;;;;CAarF,CAAC;AAEX,kFAAkF;AAClF,eAAO,MAAM,gBAAgB;;;;CAOnB,CAAC;AAEX,iEAAiE;AACjE,wBAAgB,wBAAwB,IAAI,MAAM,EAAE,CAOnD"}