@mergesignal/shared 0.2.8 → 0.4.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 (128) hide show
  1. package/dist/deriveScanNarrative.d.ts +0 -3
  2. package/dist/deriveScanNarrative.d.ts.map +1 -1
  3. package/dist/deriveScanNarrative.js +30 -19
  4. package/dist/deriveScanNarrative.test.js +37 -8
  5. package/dist/engineWireRegression.test.d.ts +2 -0
  6. package/dist/engineWireRegression.test.d.ts.map +1 -0
  7. package/dist/engineWireRegression.test.js +57 -0
  8. package/dist/fixtures/legacyEngineRepoIntelligence.d.ts +28 -0
  9. package/dist/fixtures/legacyEngineRepoIntelligence.d.ts.map +1 -0
  10. package/dist/fixtures/legacyEngineRepoIntelligence.js +28 -0
  11. package/dist/fixtures/repoIntelligenceFixtures.d.ts +0 -2
  12. package/dist/fixtures/repoIntelligenceFixtures.d.ts.map +1 -1
  13. package/dist/fixtures/repoIntelligenceFixtures.js +14 -4
  14. package/dist/fixtures/repoIntelligenceTestHelpers.d.ts +5 -0
  15. package/dist/fixtures/repoIntelligenceTestHelpers.d.ts.map +1 -0
  16. package/dist/fixtures/repoIntelligenceTestHelpers.js +28 -0
  17. package/dist/index.d.ts +4 -2
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +4 -2
  20. package/dist/narrativeParity.test.js +21 -19
  21. package/dist/narrativePresentation.test.js +2 -1
  22. package/dist/presentGitHubPrComment.d.ts +3 -4
  23. package/dist/presentGitHubPrComment.d.ts.map +1 -1
  24. package/dist/presentGitHubPrComment.js +15 -61
  25. package/dist/presentation/compose/narrativeCompose.d.ts +16 -0
  26. package/dist/presentation/compose/narrativeCompose.d.ts.map +1 -0
  27. package/dist/presentation/compose/narrativeCompose.js +167 -0
  28. package/dist/presentation/dto/githubAndCliPresentation.d.ts +53 -0
  29. package/dist/presentation/dto/githubAndCliPresentation.d.ts.map +1 -0
  30. package/dist/presentation/dto/githubAndCliPresentation.js +1 -0
  31. package/dist/presentation/dto/scanCardPresentation.d.ts +25 -0
  32. package/dist/presentation/dto/scanCardPresentation.d.ts.map +1 -0
  33. package/dist/presentation/dto/scanCardPresentation.js +1 -0
  34. package/dist/presentation/dto/scanDetailsPresentation.d.ts +111 -0
  35. package/dist/presentation/dto/scanDetailsPresentation.d.ts.map +1 -0
  36. package/dist/presentation/dto/scanDetailsPresentation.js +1 -0
  37. package/dist/presentation/dto/types.d.ts +24 -0
  38. package/dist/presentation/dto/types.d.ts.map +1 -0
  39. package/dist/presentation/dto/types.js +22 -0
  40. package/dist/presentation/fixtures/scanResultFixtures.d.ts +5 -0
  41. package/dist/presentation/fixtures/scanResultFixtures.d.ts.map +1 -0
  42. package/dist/presentation/fixtures/scanResultFixtures.js +83 -0
  43. package/dist/presentation/index.d.ts +25 -0
  44. package/dist/presentation/index.d.ts.map +1 -0
  45. package/dist/presentation/index.js +13 -0
  46. package/dist/presentation/orchestration/buildScanCardPresentation.d.ts +11 -0
  47. package/dist/presentation/orchestration/buildScanCardPresentation.d.ts.map +1 -0
  48. package/dist/presentation/orchestration/buildScanCardPresentation.js +44 -0
  49. package/dist/presentation/orchestration/buildScanDetailsPresentation.d.ts +14 -0
  50. package/dist/presentation/orchestration/buildScanDetailsPresentation.d.ts.map +1 -0
  51. package/dist/presentation/orchestration/buildScanDetailsPresentation.js +19 -0
  52. package/dist/presentation/orchestration/buildScanPresentationBundle.d.ts +15 -0
  53. package/dist/presentation/orchestration/buildScanPresentationBundle.d.ts.map +1 -0
  54. package/dist/presentation/orchestration/buildScanPresentationBundle.js +23 -0
  55. package/dist/presentation/orchestration/scanPresentationBundle.d.ts +15 -0
  56. package/dist/presentation/orchestration/scanPresentationBundle.d.ts.map +1 -0
  57. package/dist/presentation/orchestration/scanPresentationBundle.js +1 -0
  58. package/dist/presentation/presentation.test.d.ts +2 -0
  59. package/dist/presentation/presentation.test.d.ts.map +1 -0
  60. package/dist/presentation/presentation.test.js +95 -0
  61. package/dist/presentation/presenters/presentCliScanSummary.d.ts +6 -0
  62. package/dist/presentation/presenters/presentCliScanSummary.d.ts.map +1 -0
  63. package/dist/presentation/presenters/presentCliScanSummary.js +30 -0
  64. package/dist/presentation/presenters/presentGitHubCheckRun.d.ts +8 -0
  65. package/dist/presentation/presenters/presentGitHubCheckRun.d.ts.map +1 -0
  66. package/dist/presentation/presenters/presentGitHubCheckRun.js +32 -0
  67. package/dist/presentation/presenters/presentGitHubPrComment.d.ts +4 -0
  68. package/dist/presentation/presenters/presentGitHubPrComment.d.ts.map +1 -0
  69. package/dist/presentation/presenters/presentGitHubPrComment.js +40 -0
  70. package/dist/presentation/presenters/presentPipelineScanCard.d.ts +3 -0
  71. package/dist/presentation/presenters/presentPipelineScanCard.d.ts.map +1 -0
  72. package/dist/presentation/presenters/presentPipelineScanCard.js +23 -0
  73. package/dist/presentation/presenters/presentScanCard.d.ts +7 -0
  74. package/dist/presentation/presenters/presentScanCard.d.ts.map +1 -0
  75. package/dist/presentation/presenters/presentScanCard.js +43 -0
  76. package/dist/presentation/presenters/presentScanDetails.d.ts +9 -0
  77. package/dist/presentation/presenters/presentScanDetails.d.ts.map +1 -0
  78. package/dist/presentation/presenters/presentScanDetails.js +177 -0
  79. package/dist/presentation/profile/derivePresentationProfile.d.ts +12 -0
  80. package/dist/presentation/profile/derivePresentationProfile.d.ts.map +1 -0
  81. package/dist/presentation/profile/derivePresentationProfile.js +86 -0
  82. package/dist/presentation/profile/presentationProfile.d.ts +9 -0
  83. package/dist/presentation/profile/presentationProfile.d.ts.map +1 -0
  84. package/dist/presentation/profile/presentationProfile.js +1 -0
  85. package/dist/presentation/render/renderCliScanSummaryText.d.ts +3 -0
  86. package/dist/presentation/render/renderCliScanSummaryText.d.ts.map +1 -0
  87. package/dist/presentation/render/renderCliScanSummaryText.js +30 -0
  88. package/dist/presentation/render/renderGitHubCheckRunMarkdown.d.ts +3 -0
  89. package/dist/presentation/render/renderGitHubCheckRunMarkdown.d.ts.map +1 -0
  90. package/dist/presentation/render/renderGitHubCheckRunMarkdown.js +23 -0
  91. package/dist/presentation/render/renderGitHubPrCommentMarkdown.d.ts +3 -0
  92. package/dist/presentation/render/renderGitHubPrCommentMarkdown.d.ts.map +1 -0
  93. package/dist/presentation/render/renderGitHubPrCommentMarkdown.js +24 -0
  94. package/dist/repoIntelligenceMappers.d.ts +20 -0
  95. package/dist/repoIntelligenceMappers.d.ts.map +1 -0
  96. package/dist/repoIntelligenceMappers.js +60 -0
  97. package/dist/repoIntelligenceSchema.contract.test.d.ts +2 -0
  98. package/dist/repoIntelligenceSchema.contract.test.d.ts.map +1 -0
  99. package/dist/repoIntelligenceSchema.contract.test.js +19 -0
  100. package/dist/repoIntelligenceSchema.d.ts +52 -83
  101. package/dist/repoIntelligenceSchema.d.ts.map +1 -1
  102. package/dist/repoIntelligenceSchema.js +99 -141
  103. package/dist/repoIntelligenceValidation.d.ts +18 -0
  104. package/dist/repoIntelligenceValidation.d.ts.map +1 -0
  105. package/dist/repoIntelligenceValidation.js +76 -0
  106. package/dist/repoIntelligenceValidation.persist.test.d.ts +2 -0
  107. package/dist/repoIntelligenceValidation.persist.test.d.ts.map +1 -0
  108. package/dist/repoIntelligenceValidation.persist.test.js +44 -0
  109. package/dist/scanCardSummary.d.ts +4 -35
  110. package/dist/scanCardSummary.d.ts.map +1 -1
  111. package/dist/scanCardSummary.js +12 -63
  112. package/dist/scanCardSummary.test.js +56 -75
  113. package/dist/scanDetailViewModel.d.ts +1 -0
  114. package/dist/scanDetailViewModel.d.ts.map +1 -1
  115. package/dist/scanDetailViewModel.js +1 -1
  116. package/dist/scanDetailViewModel.test.js +2 -1
  117. package/dist/scanNarrativeFacts.d.ts +2 -0
  118. package/dist/scanNarrativeFacts.d.ts.map +1 -1
  119. package/dist/scanNarrativeFacts.js +1 -0
  120. package/dist/scanSurfaceCopy.d.ts +25 -0
  121. package/dist/scanSurfaceCopy.d.ts.map +1 -1
  122. package/dist/scanSurfaceCopy.js +25 -0
  123. package/dist/types.d.ts +15 -3
  124. package/dist/types.d.ts.map +1 -1
  125. package/package.json +1 -1
  126. package/dist/presentScanCardSummary.d.ts +0 -16
  127. package/dist/presentScanCardSummary.d.ts.map +0 -1
  128. package/dist/presentScanCardSummary.js +0 -212
@@ -0,0 +1,177 @@
1
+ import { deriveDetailReachChip } from "../../formatCardExposureDisplay.js";
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";
5
+ import { normalizeGeneratedText, normalizeGeneratedTextNullable, } from "../../normalizeGeneratedText.js";
6
+ 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
+ }
86
+ function mapUsage(bundle) {
87
+ const { facts } = bundle;
88
+ if (facts.packageUsage.length === 0 && facts.frameworks.length === 0) {
89
+ return undefined;
90
+ }
91
+ return {
92
+ summary: facts.packageUsage[0]
93
+ ? `${facts.packageUsage.length} package(s) with usage data`
94
+ : undefined,
95
+ items: facts.packageUsage.map((row) => ({
96
+ packageName: row.packageName,
97
+ paths: row.paths,
98
+ areas: row.areas,
99
+ criticalPaths: row.criticalPaths,
100
+ })),
101
+ frameworks: facts.frameworks,
102
+ };
103
+ }
104
+ 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);
114
+ const subheadline = composeSubheadline(bundle);
115
+ const keyPoints = composeKeyPoints(bundle, 6);
116
+ const verificationTitles = composeVerificationActions(bundle, 6);
117
+ const supportingLines = composeSupportingContext(bundle);
118
+ const supportingContext = supportingLines
119
+ ? {
120
+ title: scanSurfaceCopy.scanDetail.topologyCollapsedHint,
121
+ lines: supportingLines,
122
+ }
123
+ : undefined;
124
+ const posture = profile.status;
125
+ const postureLabel = MERGE_POSTURE_LABEL[posture];
126
+ return {
127
+ evidenceContext: evidenceContextFromProfile(bundle),
128
+ status: profile.status,
129
+ density: profile.density,
130
+ confidence: profile.confidence,
131
+ hero: {
132
+ headline: normalizeGeneratedText(headline),
133
+ subheadline: normalizeGeneratedTextNullable(subheadline) ?? undefined,
134
+ verdictLine: deriveVerdictLineFromFacts(facts, result),
135
+ scopeChip: deriveDetailReachChip(result.totalScore) ?? undefined,
136
+ postureLabel,
137
+ riskIndex: facts.riskIndex,
138
+ },
139
+ narrative: {
140
+ keyPoints: keyPoints.map((k) => normalizeGeneratedText(k)),
141
+ changedPackages: facts.changedPackages.all,
142
+ primaryPackage: facts.changedPackages.primary ?? undefined,
143
+ },
144
+ usage: mapUsage(bundle),
145
+ verification: {
146
+ actions: verificationTitles.map((title) => ({
147
+ title: normalizeGeneratedText(title),
148
+ })),
149
+ },
150
+ signalSummary: vm.signalSummary
151
+ ? {
152
+ riskIndex: vm.signalSummary.score,
153
+ band: vm.signalSummary.overallBand === "moderate"
154
+ ? "medium"
155
+ : vm.signalSummary.overallBand === "high"
156
+ ? "high"
157
+ : "low",
158
+ layers: vm.signalSummary.layers.map((l) => ({
159
+ layer: l.layer,
160
+ score: l.score,
161
+ band: l.concernLabel,
162
+ label: l.label,
163
+ })),
164
+ }
165
+ : undefined,
166
+ operationalImpact: mapOperationalImpact(vm),
167
+ recommendations: mapRecommendations(vm),
168
+ evidence: mapEvidence(bundle, vm),
169
+ supportingContext,
170
+ metadata: {
171
+ scanId: ctx.scanId,
172
+ generatedAt: result.generatedAt,
173
+ methodologyVersion: ctx.methodologyVersion,
174
+ changedPackagesSummary: facts.changedPackages.primary ?? facts.changedPackages.all.join(", "),
175
+ },
176
+ };
177
+ }
@@ -0,0 +1,12 @@
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
@@ -0,0 +1 @@
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;AAGtE,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;AA+FF,8DAA8D;AAC9D,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,kBAAkB,EACzB,GAAG,EAAE,gCAAgC,GACpC,mBAAmB,GAAG,IAAI,CAsB5B"}
@@ -0,0 +1,86 @@
1
+ import { mergePostureFromDecision } from "../../riskVocabulary.js";
2
+ import { scanSurfaceCopy } from "../../scanSurfaceCopy.js";
3
+ function statusFromScore(totalScore) {
4
+ if (totalScore == null || !Number.isFinite(totalScore))
5
+ return "needs_review";
6
+ if (totalScore <= 30)
7
+ return "safe";
8
+ if (totalScore <= 60)
9
+ return "needs_review";
10
+ return "risky";
11
+ }
12
+ function resolveStatus(facts, ctx) {
13
+ const fromFacts = facts.mergePosture;
14
+ if (fromFacts)
15
+ return fromFacts;
16
+ const fromDecision = mergePostureFromDecision(ctx.decision ?? undefined);
17
+ if (fromDecision)
18
+ return fromDecision;
19
+ return statusFromScore(ctx.totalScore ?? facts.riskIndex);
20
+ }
21
+ function hasStrongPrIntelligence(facts) {
22
+ return (facts.availability.tiersPresent.tier1 &&
23
+ facts.availability.repoIntelligenceParse === "ok");
24
+ }
25
+ function hasHighSeverityFindings(facts) {
26
+ return facts.reviewerGuidance.some((g) => g.kind === "finding" &&
27
+ (g.priority === "critical" || g.priority === "high"));
28
+ }
29
+ function hasRuntimeUsage(facts) {
30
+ if (facts.runtimeSurface?.kind === "runtime")
31
+ return true;
32
+ return facts.packageUsage.some((u) => u.paths.length > 0 || u.criticalPaths.length > 0);
33
+ }
34
+ function deriveDensity(facts, priority) {
35
+ if (priority === "limited") {
36
+ return hasHighSeverityFindings(facts) ? "standard" : "minimal";
37
+ }
38
+ const runtime = facts.runtimeSurface?.kind === "runtime";
39
+ const wideOrModerate = facts.blastRadius?.level === "wide" ||
40
+ facts.blastRadius?.level === "moderate";
41
+ const hasAreas = facts.affectedAreas.length > 0;
42
+ const hasRuntimePaths = hasRuntimeUsage(facts);
43
+ if (runtime && (wideOrModerate || hasAreas || hasRuntimePaths)) {
44
+ return "rich";
45
+ }
46
+ const buildOnly = facts.runtimeSurface?.kind === "build" ||
47
+ facts.reachability?.kind === "build_only";
48
+ const narrowBlast = !facts.blastRadius || facts.blastRadius.level === "narrow";
49
+ if (buildOnly && narrowBlast && !hasAreas) {
50
+ return "minimal";
51
+ }
52
+ return "standard";
53
+ }
54
+ function deriveConfidence(facts, priority) {
55
+ if (priority === "limited")
56
+ return "low";
57
+ const decisionConf = facts.confidence.decision;
58
+ if (decisionConf === "high" || decisionConf === "medium")
59
+ return "high";
60
+ const sparseUsage = facts.packageUsage.length === 0 ||
61
+ facts.packageUsage.every((u) => u.paths.length === 0 && u.criticalPaths.length === 0);
62
+ if (sparseUsage)
63
+ return "medium";
64
+ return "high";
65
+ }
66
+ /** INTERNAL - only called from buildScanPresentationBundle */
67
+ export function derivePresentationProfile(facts, ctx) {
68
+ if (ctx.pipelineStatus !== "done")
69
+ return null;
70
+ const priority = hasStrongPrIntelligence(facts)
71
+ ? "pr_intelligence"
72
+ : "limited";
73
+ const status = resolveStatus(facts, ctx);
74
+ const density = deriveDensity(facts, priority);
75
+ const confidence = deriveConfidence(facts, priority);
76
+ const degradedMessage = priority === "limited"
77
+ ? scanSurfaceCopy.presentation.limitedContextMessage
78
+ : undefined;
79
+ return {
80
+ status,
81
+ density,
82
+ confidence,
83
+ priority,
84
+ degradedMessage,
85
+ };
86
+ }
@@ -0,0 +1,9 @@
1
+ import type { PresentationConfidence, PresentationDensity, PresentationPriority, PresentationStatus } from "../dto/types.js";
2
+ export type PresentationProfile = {
3
+ status: PresentationStatus;
4
+ density: PresentationDensity;
5
+ confidence: PresentationConfidence;
6
+ priority: PresentationPriority;
7
+ degradedMessage?: string;
8
+ };
9
+ //# sourceMappingURL=presentationProfile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentationProfile.d.ts","sourceRoot":"","sources":["../../../src/presentation/profile/presentationProfile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,UAAU,EAAE,sBAAsB,CAAC;IACnC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { CliScanPresentation } from "../dto/githubAndCliPresentation.js";
2
+ export declare function renderCliScanSummaryText(p: CliScanPresentation): string;
3
+ //# sourceMappingURL=renderCliScanSummaryText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderCliScanSummaryText.d.ts","sourceRoot":"","sources":["../../../src/presentation/render/renderCliScanSummaryText.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAE9E,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,mBAAmB,GAAG,MAAM,CA+BvE"}
@@ -0,0 +1,30 @@
1
+ import { scanSurfaceCopy } from "../../scanSurfaceCopy.js";
2
+ export function renderCliScanSummaryText(p) {
3
+ const lines = [
4
+ `MergeSignal - ${p.header.repoLabel}`,
5
+ "",
6
+ p.headline,
7
+ ];
8
+ if (p.subheadline)
9
+ lines.push(p.subheadline);
10
+ lines.push("", `Status: ${p.status} | Density: ${p.density} | Confidence: ${p.confidence}`);
11
+ if (p.metrics) {
12
+ lines.push(`Risk index: ${p.metrics.riskIndex} (${scanSurfaceCopy.actions.riskIndexDirectionShort})`, p.metrics.layerLine, `Findings: ${p.metrics.findingCount} | Recommendations: ${p.metrics.recommendationCount}`);
13
+ }
14
+ if (p.keyPoints.length > 0) {
15
+ lines.push("", "Key points:");
16
+ for (const point of p.keyPoints)
17
+ lines.push(` - ${point}`);
18
+ }
19
+ if (p.verificationActions.length > 0) {
20
+ lines.push("", "Verify:");
21
+ for (const action of p.verificationActions)
22
+ lines.push(` - ${action}`);
23
+ }
24
+ if (p.supportingContext?.length) {
25
+ lines.push("", "Supporting context:");
26
+ for (const line of p.supportingContext)
27
+ lines.push(` - ${line}`);
28
+ }
29
+ return lines.join("\n");
30
+ }
@@ -0,0 +1,3 @@
1
+ import type { GitHubCheckRunPresentation } from "../dto/githubAndCliPresentation.js";
2
+ export declare function renderGitHubCheckRunMarkdown(p: GitHubCheckRunPresentation): string;
3
+ //# sourceMappingURL=renderGitHubCheckRunMarkdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderGitHubCheckRunMarkdown.d.ts","sourceRoot":"","sources":["../../../src/presentation/render/renderGitHubCheckRunMarkdown.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAErF,wBAAgB,4BAA4B,CAC1C,CAAC,EAAE,0BAA0B,GAC5B,MAAM,CAuBR"}
@@ -0,0 +1,23 @@
1
+ import { normalizeGeneratedText } from "../../normalizeGeneratedText.js";
2
+ export function renderGitHubCheckRunMarkdown(p) {
3
+ const parts = [
4
+ `**${normalizeGeneratedText(p.title)}**`,
5
+ "",
6
+ p.summaryLead,
7
+ "",
8
+ ];
9
+ for (const section of p.sections) {
10
+ if (section.id === "footer") {
11
+ parts.push(section.bullets.join("\n"));
12
+ continue;
13
+ }
14
+ if (section.title) {
15
+ parts.push(`### ${section.title}`, "");
16
+ }
17
+ for (const bullet of section.bullets) {
18
+ parts.push(`- ${normalizeGeneratedText(bullet)}`);
19
+ }
20
+ parts.push("");
21
+ }
22
+ return parts.join("\n").trimEnd();
23
+ }
@@ -0,0 +1,3 @@
1
+ import type { GitHubPrCommentPresentation } from "../dto/githubAndCliPresentation.js";
2
+ export declare function renderGitHubPrCommentMarkdown(p: GitHubPrCommentPresentation): string;
3
+ //# sourceMappingURL=renderGitHubPrCommentMarkdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderGitHubPrCommentMarkdown.d.ts","sourceRoot":"","sources":["../../../src/presentation/render/renderGitHubPrCommentMarkdown.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AAoBtF,wBAAgB,6BAA6B,CAC3C,CAAC,EAAE,2BAA2B,GAC7B,MAAM,CAmBR"}
@@ -0,0 +1,24 @@
1
+ import { normalizeGeneratedText } from "../../normalizeGeneratedText.js";
2
+ function renderGuidanceBlock(message, where, action) {
3
+ return [
4
+ normalizeGeneratedText(message),
5
+ "",
6
+ "**Where it shows up**",
7
+ "",
8
+ normalizeGeneratedText(where),
9
+ "",
10
+ "**What to do**",
11
+ "",
12
+ normalizeGeneratedText(action),
13
+ ].join("\n");
14
+ }
15
+ export function renderGitHubPrCommentMarkdown(p) {
16
+ const parts = [`**${normalizeGeneratedText(p.title)}**`];
17
+ if (p.introLines.length > 0) {
18
+ parts.push("", p.introLines.map((l) => normalizeGeneratedText(l)).join("\n"));
19
+ }
20
+ for (const block of p.guidanceBlocks) {
21
+ parts.push("", renderGuidanceBlock(block.message, block.where ?? "See scan detail.", block.action ?? "Review before merge."));
22
+ }
23
+ return parts.join("\n\n---\n\n").trimEnd();
24
+ }
@@ -0,0 +1,20 @@
1
+ import type { BlastRadiusLevel, ReachabilityKind, RuntimeSurfaceKind } from "./scanNarrativeFacts.js";
2
+ /** Engine-internal blast radius vocabulary → canonical wire. */
3
+ export type EngineBlastRadiusLevel = "small" | "moderate" | "large";
4
+ /** Engine-internal reachability spread buckets. */
5
+ export type EngineReachabilityBucket = "very_low" | "low" | "moderate" | "high";
6
+ /** Engine-internal runtime surface labels. */
7
+ export type EngineRuntimeSurface = "runtime" | "test" | "build" | "dev" | "ci";
8
+ export declare function mapBlastRadiusLevel(level: EngineBlastRadiusLevel): BlastRadiusLevel;
9
+ export declare function mapRuntimeSurfaceKind(surface: EngineRuntimeSurface): RuntimeSurfaceKind;
10
+ /**
11
+ * Maps engine reachability spread + runtime classification to narrative reachability kind.
12
+ * Documented in repoIntelligenceSchema.ts header.
13
+ */
14
+ export declare function mapReachabilityKind(input: {
15
+ bucket: EngineReachabilityBucket;
16
+ reachesRuntime: boolean;
17
+ dominantSurface: EngineRuntimeSurface;
18
+ }): ReachabilityKind;
19
+ export declare function areaSlugToLabel(slug: string): string;
20
+ //# sourceMappingURL=repoIntelligenceMappers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repoIntelligenceMappers.d.ts","sourceRoot":"","sources":["../src/repoIntelligenceMappers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,yBAAyB,CAAC;AAEjC,gEAAgE;AAChE,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,CAAC;AAEpE,mDAAmD;AACnD,MAAM,MAAM,wBAAwB,GAAG,UAAU,GAAG,KAAK,GAAG,UAAU,GAAG,MAAM,CAAC;AAEhF,8CAA8C;AAC9C,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,IAAI,CAAC;AAE/E,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,sBAAsB,GAC5B,gBAAgB,CAalB;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,oBAAoB,GAC5B,kBAAkB,CAapB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,MAAM,EAAE,wBAAwB,CAAC;IACjC,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,EAAE,oBAAoB,CAAC;CACvC,GAAG,gBAAgB,CAwBnB;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKpD"}
@@ -0,0 +1,60 @@
1
+ export function mapBlastRadiusLevel(level) {
2
+ switch (level) {
3
+ case "small":
4
+ return "narrow";
5
+ case "moderate":
6
+ return "moderate";
7
+ case "large":
8
+ return "wide";
9
+ default: {
10
+ const x = level;
11
+ return x;
12
+ }
13
+ }
14
+ }
15
+ export function mapRuntimeSurfaceKind(surface) {
16
+ switch (surface) {
17
+ case "runtime":
18
+ return "runtime";
19
+ case "test":
20
+ return "test";
21
+ case "build":
22
+ case "dev":
23
+ case "ci":
24
+ return "build";
25
+ default:
26
+ return "unknown";
27
+ }
28
+ }
29
+ /**
30
+ * Maps engine reachability spread + runtime classification to narrative reachability kind.
31
+ * Documented in repoIntelligenceSchema.ts header.
32
+ */
33
+ export function mapReachabilityKind(input) {
34
+ const { bucket, reachesRuntime, dominantSurface } = input;
35
+ if (dominantSurface === "test" && !reachesRuntime) {
36
+ return "test_only";
37
+ }
38
+ if ((dominantSurface === "build" ||
39
+ dominantSurface === "dev" ||
40
+ dominantSurface === "ci") &&
41
+ !reachesRuntime) {
42
+ return "build_only";
43
+ }
44
+ if (reachesRuntime) {
45
+ return "on_runtime_paths";
46
+ }
47
+ if (bucket === "very_low" || bucket === "low") {
48
+ return "unreachable";
49
+ }
50
+ if (bucket === "moderate" || bucket === "high") {
51
+ return "on_runtime_paths";
52
+ }
53
+ return "unknown";
54
+ }
55
+ export function areaSlugToLabel(slug) {
56
+ return slug
57
+ .split("_")
58
+ .map((w) => (w ? w[0].toUpperCase() + w.slice(1) : w))
59
+ .join(" ");
60
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=repoIntelligenceSchema.contract.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repoIntelligenceSchema.contract.test.d.ts","sourceRoot":"","sources":["../src/repoIntelligenceSchema.contract.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { fixtureRepoIntelligenceFastify, fixtureRepoIntelligenceMultiPackage, } from "./fixtures/repoIntelligenceFixtures.js";
3
+ import { legacyEngineRepoIntelligenceJwt } from "./fixtures/legacyEngineRepoIntelligence.js";
4
+ import { safeParseRepoIntelligence, validateRepoIntelligenceWire, } from "./repoIntelligenceSchema.js";
5
+ describe("repoIntelligenceWireSchema contract", () => {
6
+ it("accepts canonical consumer fixtures", () => {
7
+ expect(() => validateRepoIntelligenceWire(fixtureRepoIntelligenceFastify)).not.toThrow();
8
+ expect(() => validateRepoIntelligenceWire(fixtureRepoIntelligenceMultiPackage)).not.toThrow();
9
+ });
10
+ it("rejects legacy engine wire (name, large blast, object frameworks, file hotspots)", () => {
11
+ const r = safeParseRepoIntelligence(legacyEngineRepoIntelligenceJwt);
12
+ expect(r.ok).toBe(false);
13
+ if (r.ok)
14
+ return;
15
+ expect(r.issueCount).toBeGreaterThan(0);
16
+ const joined = r.issues.join(" ");
17
+ expect(joined.length).toBeGreaterThan(0);
18
+ });
19
+ });