@mergesignal/shared 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/dist/deriveScanNarrative.d.ts.map +1 -1
  2. package/dist/deriveScanNarrative.js +20 -3
  3. package/dist/deriveScanNarrative.test.js +6 -3
  4. package/dist/engineWireRegression.test.js +2 -2
  5. package/dist/fixtures/repoIntelligenceFixtures.d.ts.map +1 -1
  6. package/dist/fixtures/repoIntelligenceFixtures.js +13 -0
  7. package/dist/index.d.ts +3 -2
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +3 -2
  10. package/dist/narrativeParity.test.js +19 -18
  11. package/dist/narrativePresentation.d.ts.map +1 -1
  12. package/dist/narrativePresentation.js +6 -3
  13. package/dist/presentGitHubPrComment.d.ts +3 -4
  14. package/dist/presentGitHubPrComment.d.ts.map +1 -1
  15. package/dist/presentGitHubPrComment.js +15 -61
  16. package/dist/presentation/compose/narrativeCompose.d.ts +16 -0
  17. package/dist/presentation/compose/narrativeCompose.d.ts.map +1 -0
  18. package/dist/presentation/compose/narrativeCompose.js +167 -0
  19. package/dist/presentation/dto/githubAndCliPresentation.d.ts +53 -0
  20. package/dist/presentation/dto/githubAndCliPresentation.d.ts.map +1 -0
  21. package/dist/presentation/dto/githubAndCliPresentation.js +1 -0
  22. package/dist/presentation/dto/scanCardPresentation.d.ts +25 -0
  23. package/dist/presentation/dto/scanCardPresentation.d.ts.map +1 -0
  24. package/dist/presentation/dto/scanCardPresentation.js +1 -0
  25. package/dist/presentation/dto/scanDetailsPresentation.d.ts +111 -0
  26. package/dist/presentation/dto/scanDetailsPresentation.d.ts.map +1 -0
  27. package/dist/presentation/dto/scanDetailsPresentation.js +1 -0
  28. package/dist/presentation/dto/types.d.ts +24 -0
  29. package/dist/presentation/dto/types.d.ts.map +1 -0
  30. package/dist/presentation/dto/types.js +22 -0
  31. package/dist/presentation/fixtures/scanResultFixtures.d.ts +5 -0
  32. package/dist/presentation/fixtures/scanResultFixtures.d.ts.map +1 -0
  33. package/dist/presentation/fixtures/scanResultFixtures.js +83 -0
  34. package/dist/presentation/index.d.ts +25 -0
  35. package/dist/presentation/index.d.ts.map +1 -0
  36. package/dist/presentation/index.js +13 -0
  37. package/dist/presentation/orchestration/buildScanCardPresentation.d.ts +11 -0
  38. package/dist/presentation/orchestration/buildScanCardPresentation.d.ts.map +1 -0
  39. package/dist/presentation/orchestration/buildScanCardPresentation.js +44 -0
  40. package/dist/presentation/orchestration/buildScanDetailsPresentation.d.ts +14 -0
  41. package/dist/presentation/orchestration/buildScanDetailsPresentation.d.ts.map +1 -0
  42. package/dist/presentation/orchestration/buildScanDetailsPresentation.js +19 -0
  43. package/dist/presentation/orchestration/buildScanPresentationBundle.d.ts +15 -0
  44. package/dist/presentation/orchestration/buildScanPresentationBundle.d.ts.map +1 -0
  45. package/dist/presentation/orchestration/buildScanPresentationBundle.js +23 -0
  46. package/dist/presentation/orchestration/scanPresentationBundle.d.ts +15 -0
  47. package/dist/presentation/orchestration/scanPresentationBundle.d.ts.map +1 -0
  48. package/dist/presentation/orchestration/scanPresentationBundle.js +1 -0
  49. package/dist/presentation/presentation.test.d.ts +2 -0
  50. package/dist/presentation/presentation.test.d.ts.map +1 -0
  51. package/dist/presentation/presentation.test.js +95 -0
  52. package/dist/presentation/presenters/presentCliScanSummary.d.ts +6 -0
  53. package/dist/presentation/presenters/presentCliScanSummary.d.ts.map +1 -0
  54. package/dist/presentation/presenters/presentCliScanSummary.js +30 -0
  55. package/dist/presentation/presenters/presentGitHubCheckRun.d.ts +8 -0
  56. package/dist/presentation/presenters/presentGitHubCheckRun.d.ts.map +1 -0
  57. package/dist/presentation/presenters/presentGitHubCheckRun.js +32 -0
  58. package/dist/presentation/presenters/presentGitHubPrComment.d.ts +4 -0
  59. package/dist/presentation/presenters/presentGitHubPrComment.d.ts.map +1 -0
  60. package/dist/presentation/presenters/presentGitHubPrComment.js +40 -0
  61. package/dist/presentation/presenters/presentPipelineScanCard.d.ts +3 -0
  62. package/dist/presentation/presenters/presentPipelineScanCard.d.ts.map +1 -0
  63. package/dist/presentation/presenters/presentPipelineScanCard.js +23 -0
  64. package/dist/presentation/presenters/presentScanCard.d.ts +7 -0
  65. package/dist/presentation/presenters/presentScanCard.d.ts.map +1 -0
  66. package/dist/presentation/presenters/presentScanCard.js +43 -0
  67. package/dist/presentation/presenters/presentScanDetails.d.ts +9 -0
  68. package/dist/presentation/presenters/presentScanDetails.d.ts.map +1 -0
  69. package/dist/presentation/presenters/presentScanDetails.js +177 -0
  70. package/dist/presentation/profile/derivePresentationProfile.d.ts +12 -0
  71. package/dist/presentation/profile/derivePresentationProfile.d.ts.map +1 -0
  72. package/dist/presentation/profile/derivePresentationProfile.js +94 -0
  73. package/dist/presentation/profile/presentationProfile.d.ts +9 -0
  74. package/dist/presentation/profile/presentationProfile.d.ts.map +1 -0
  75. package/dist/presentation/profile/presentationProfile.js +1 -0
  76. package/dist/presentation/render/renderCliScanSummaryText.d.ts +3 -0
  77. package/dist/presentation/render/renderCliScanSummaryText.d.ts.map +1 -0
  78. package/dist/presentation/render/renderCliScanSummaryText.js +30 -0
  79. package/dist/presentation/render/renderGitHubCheckRunMarkdown.d.ts +3 -0
  80. package/dist/presentation/render/renderGitHubCheckRunMarkdown.d.ts.map +1 -0
  81. package/dist/presentation/render/renderGitHubCheckRunMarkdown.js +23 -0
  82. package/dist/presentation/render/renderGitHubPrCommentMarkdown.d.ts +3 -0
  83. package/dist/presentation/render/renderGitHubPrCommentMarkdown.d.ts.map +1 -0
  84. package/dist/presentation/render/renderGitHubPrCommentMarkdown.js +24 -0
  85. package/dist/repoIntelligenceMappers.d.ts.map +1 -1
  86. package/dist/repoIntelligenceMappers.js +8 -1
  87. package/dist/repoIntelligenceSchema.d.ts +75 -1
  88. package/dist/repoIntelligenceSchema.d.ts.map +1 -1
  89. package/dist/repoIntelligenceSchema.js +74 -1
  90. package/dist/repoIntelligenceSemantics.d.ts +29 -0
  91. package/dist/repoIntelligenceSemantics.d.ts.map +1 -0
  92. package/dist/repoIntelligenceSemantics.js +146 -0
  93. package/dist/repoIntelligenceSemantics.test.d.ts +2 -0
  94. package/dist/repoIntelligenceSemantics.test.d.ts.map +1 -0
  95. package/dist/repoIntelligenceSemantics.test.js +63 -0
  96. package/dist/scanCardSummary.d.ts +4 -35
  97. package/dist/scanCardSummary.d.ts.map +1 -1
  98. package/dist/scanCardSummary.js +12 -63
  99. package/dist/scanCardSummary.test.js +56 -75
  100. package/dist/scanDetailViewModel.d.ts +1 -0
  101. package/dist/scanDetailViewModel.d.ts.map +1 -1
  102. package/dist/scanDetailViewModel.js +1 -1
  103. package/dist/scanNarrativeFacts.d.ts +7 -0
  104. package/dist/scanNarrativeFacts.d.ts.map +1 -1
  105. package/dist/scanNarrativeFacts.js +1 -0
  106. package/dist/scanSurfaceCopy.d.ts +25 -0
  107. package/dist/scanSurfaceCopy.d.ts.map +1 -1
  108. package/dist/scanSurfaceCopy.js +25 -0
  109. package/package.json +1 -1
  110. package/dist/presentScanCardSummary.d.ts +0 -16
  111. package/dist/presentScanCardSummary.d.ts.map +0 -1
  112. package/dist/presentScanCardSummary.js +0 -212
@@ -1 +1 @@
1
- {"version":3,"file":"deriveScanNarrative.d.ts","sourceRoot":"","sources":["../src/deriveScanNarrative.ts"],"names":[],"mappings":"AAMA,OAAO,EAaL,KAAK,kBAAkB,EACxB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,KAAK,EAKV,UAAU,EACX,MAAM,YAAY,CAAC;AAgapB;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,GACpC,kBAAkB,CAsGpB"}
1
+ {"version":3,"file":"deriveScanNarrative.d.ts","sourceRoot":"","sources":["../src/deriveScanNarrative.ts"],"names":[],"mappings":"AAOA,OAAO,EAaL,KAAK,kBAAkB,EACxB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,KAAK,EAKV,UAAU,EACX,MAAM,YAAY,CAAC;AAsbpB;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,GACpC,kBAAkB,CAuGpB"}
@@ -1,5 +1,6 @@
1
1
  import { extractRepositoryContextFacts } from "./extractRepositoryContextFacts.js";
2
2
  import { readBlastLevel, safeParseRepoIntelligence, } from "./repoIntelligenceSchema.js";
3
+ import { isRuntimeNarrativeSafe } from "./repoIntelligenceSemantics.js";
3
4
  import { EMPTY_SCAN_NARRATIVE_FACTS, NARRATIVE_FACT_MAX_AREAS, NARRATIVE_FACT_MAX_HOTSPOTS, NARRATIVE_FACT_MAX_PATHS, } from "./scanNarrativeFacts.js";
4
5
  import { mergePostureFromDecision } from "./riskVocabulary.js";
5
6
  import { selectTopAffectedAreas } from "./selectTopAffectedAreas.js";
@@ -130,8 +131,12 @@ function extractTier1FromRepoIntelligence(ri, changed) {
130
131
  const packageUsage = collectPackageUsageForChanged(ri, changed);
131
132
  const frameworks = collectFrameworks(ri);
132
133
  const paths = allUsagePaths(packageUsage);
133
- const runtimeKind = pkgIntel?.runtimeSurface ?? null;
134
- const reachKind = pkgIntel?.reachability ?? null;
134
+ const suppressRuntime = pkgIntel?.suppressRuntimeNarrative === true;
135
+ const narrativeSafe = isRuntimeNarrativeSafe(pkgIntel);
136
+ const runtimeKind = narrativeSafe && !suppressRuntime
137
+ ? (pkgIntel?.runtimeSurface ?? null)
138
+ : null;
139
+ const reachKind = narrativeSafe && !suppressRuntime ? (pkgIntel?.reachability ?? null) : null;
135
140
  const runtimeSurface = runtimeKind != null
136
141
  ? {
137
142
  kind: runtimeKind,
@@ -150,6 +155,14 @@ function extractTier1FromRepoIntelligence(ri, changed) {
150
155
  },
151
156
  }
152
157
  : null;
158
+ const packageSemantics = pkgIntel
159
+ ? {
160
+ runtimeImpact: pkgIntel.runtimeImpact ?? null,
161
+ expectedImpact: pkgIntel.expectedImpact ?? null,
162
+ suppressRuntimeNarrative: suppressRuntime,
163
+ verificationFocus: pkgIntel.verificationFocus ?? [],
164
+ }
165
+ : null;
153
166
  const blastFromRi = ri.blastRadius;
154
167
  const blastLevel = readBlastLevel(blastFromRi?.level) ??
155
168
  (changed.all.length > 0
@@ -181,6 +194,7 @@ function extractTier1FromRepoIntelligence(ri, changed) {
181
194
  frameworks,
182
195
  runtimeSurface,
183
196
  reachability,
197
+ packageSemantics,
184
198
  blastRadius,
185
199
  affectedAreas: affectedAreas.slice(0, NARRATIVE_FACT_MAX_AREAS),
186
200
  hotspots: codeHotspots.slice(0, NARRATIVE_FACT_MAX_HOTSPOTS),
@@ -191,6 +205,7 @@ function hasMeaningfulTier1(tier1) {
191
205
  tier1.frameworks.length > 0 ||
192
206
  tier1.runtimeSurface != null ||
193
207
  tier1.reachability != null ||
208
+ tier1.packageSemantics?.expectedImpact != null ||
194
209
  tier1.blastRadius != null ||
195
210
  tier1.affectedAreas.length > 0 ||
196
211
  tier1.hotspots.length > 0);
@@ -271,6 +286,7 @@ function emptyTier1Blocks() {
271
286
  frameworks: [],
272
287
  runtimeSurface: null,
273
288
  reachability: null,
289
+ packageSemantics: null,
274
290
  blastRadius: null,
275
291
  affectedAreas: [],
276
292
  hotspots: [],
@@ -347,7 +363,7 @@ export function deriveScanNarrative(result) {
347
363
  tier1Blocks.blastRadius = blastRadiusFromChangedCount(changedPackages.all.length);
348
364
  }
349
365
  let affectedAreas = tier1Blocks.affectedAreas;
350
- if (affectedAreas.length === 0) {
366
+ if (affectedAreas.length === 0 && mode !== "pr_intelligence") {
351
367
  affectedAreas = selectTopAffectedAreas(result, { max: 2 }).map((label) => ({
352
368
  id: label.toLowerCase().replace(/\s+/g, "_").slice(0, 48),
353
369
  label,
@@ -369,6 +385,7 @@ export function deriveScanNarrative(result) {
369
385
  frameworks: tier1Blocks.frameworks,
370
386
  runtimeSurface: tier1Blocks.runtimeSurface,
371
387
  reachability: tier1Blocks.reachability,
388
+ packageSemantics: tier1Blocks.packageSemantics,
372
389
  blastRadius: tier1Blocks.blastRadius,
373
390
  affectedAreas,
374
391
  hotspots: tier1Blocks.hotspots,
@@ -112,7 +112,7 @@ describe("deriveScanNarrative", () => {
112
112
  expect(facts.repositoryContext.length).toBeGreaterThan(0);
113
113
  expect(facts.repositoryContext[0]?.family).toBe("transitive_volume");
114
114
  });
115
- it("populates build-only runtime surface from repoIntelligence", () => {
115
+ it("populates tooling semantics without runtime surface chips for typescript", () => {
116
116
  const result = {
117
117
  ...baseResult,
118
118
  changedPackages: ["typescript"],
@@ -121,8 +121,11 @@ describe("deriveScanNarrative", () => {
121
121
  };
122
122
  const facts = deriveScanNarrative(result);
123
123
  expect(facts.availability.mode).toBe("pr_intelligence");
124
- expect(facts.runtimeSurface?.kind).toBe("build");
125
- expect(facts.reachability?.kind).toBe("build_only");
124
+ expect(facts.runtimeSurface).toBeNull();
125
+ expect(facts.reachability).toBeNull();
126
+ expect(facts.packageSemantics?.runtimeImpact).toBe("none");
127
+ expect(facts.packageSemantics?.expectedImpact).toBe("typecheck");
128
+ expect(facts.packageSemantics?.suppressRuntimeNarrative).toBe(true);
126
129
  expect(facts.blastRadius?.level).toBe("narrow");
127
130
  });
128
131
  it("extracts packageUsage for all changed packages with blast factors and frameworks", () => {
@@ -37,8 +37,8 @@ describe("engine wire regression (canonical fixtures)", () => {
37
37
  expect(facts.availability.repoIntelligenceParse).toBe("ok");
38
38
  expect(facts.packageUsage[0]?.packageName).toBe("fastify");
39
39
  const card = deriveScanCardSummary(result, "done");
40
- expect(card.usageSummary).toBeTruthy();
41
- expect(card.verificationLine).toBeTruthy();
40
+ expect(card.keyPoints.length).toBeGreaterThan(0);
41
+ expect(card.verificationActions.length).toBeGreaterThan(0);
42
42
  });
43
43
  it("multi-package fixture: both packages in packageUsage", () => {
44
44
  validateRepoIntelligenceWire(fixtureRepoIntelligenceMultiPackage);
@@ -1 +1 @@
1
- {"version":3,"file":"repoIntelligenceFixtures.d.ts","sourceRoot":"","sources":["../../src/fixtures/repoIntelligenceFixtures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,iEAAiE;AACjE,eAAO,MAAM,8BAA8B,EAAE,gBAmC5C,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,iCAAiC,EAAE,gBAc/C,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,mCAAmC,EAAE,gBAgDjD,CAAC"}
1
+ {"version":3,"file":"repoIntelligenceFixtures.d.ts","sourceRoot":"","sources":["../../src/fixtures/repoIntelligenceFixtures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,iEAAiE;AACjE,eAAO,MAAM,8BAA8B,EAAE,gBAyC5C,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,iCAAiC,EAAE,gBAqB/C,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,mCAAmC,EAAE,gBAgDjD,CAAC"}
@@ -4,6 +4,12 @@ export const fixtureRepoIntelligenceFastify = {
4
4
  fastify: {
5
5
  runtimeSurface: "runtime",
6
6
  reachability: "on_runtime_paths",
7
+ runtimeImpact: "confirmed",
8
+ expectedImpact: "runtime",
9
+ evidenceStrength: "high",
10
+ suppressRuntimeNarrative: false,
11
+ dependencyClass: "runtime",
12
+ packageRole: "http_framework",
7
13
  usage: {
8
14
  packageName: "fastify",
9
15
  files: [
@@ -41,6 +47,13 @@ export const fixtureRepoIntelligenceTypescript = {
41
47
  typescript: {
42
48
  runtimeSurface: "build",
43
49
  reachability: "build_only",
50
+ runtimeImpact: "none",
51
+ expectedImpact: "typecheck",
52
+ evidenceStrength: "medium",
53
+ suppressRuntimeNarrative: true,
54
+ dependencyClass: "tooling",
55
+ packageRole: "typechecker",
56
+ verificationFocus: ["ci", "typecheck"],
44
57
  usage: {
45
58
  packageName: "typescript",
46
59
  files: ["tsconfig.json"],
package/dist/index.d.ts CHANGED
@@ -14,14 +14,14 @@ export * from "./deriveCardDisplaySummary.js";
14
14
  export * from "./scanNarrativeFacts.js";
15
15
  export * from "./repoIntelligenceSchema.js";
16
16
  export * from "./repoIntelligenceMappers.js";
17
+ export * from "./repoIntelligenceSemantics.js";
17
18
  export * from "./repoIntelligenceValidation.js";
18
19
  export * from "./deriveScanNarrative.js";
19
20
  export * from "./extractRepositoryContextFacts.js";
20
- export * from "./presentScanCardSummary.js";
21
21
  export * from "./narrativePresentation.js";
22
22
  export * from "./normalizeGeneratedText.js";
23
23
  export * from "./collectNarrativeWhyBullets.js";
24
- export * from "./presentGitHubPrComment.js";
24
+ export { presentGitHubPrCommentMarkdownFromResult, renderInsightsAsMarkdown, } from "./presentGitHubPrComment.js";
25
25
  export * from "./scanCardSummary.js";
26
26
  export * from "./deriveScanDetailRecommendations.js";
27
27
  export * from "./deriveRiskScoreSummary.js";
@@ -32,4 +32,5 @@ export * from "./trustedScanGuards.js";
32
32
  export * from "./actionsStepSummary.js";
33
33
  export * from "./prCheckRunPresentation.js";
34
34
  export * from "./productMessaging.js";
35
+ export * from "./presentation/index.js";
35
36
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wCAAwC,CAAC;AACvD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC;AAChD,cAAc,0BAA0B,CAAC;AACzC,cAAc,oCAAoC,CAAC;AACnD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,sCAAsC,CAAC;AACrD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wCAAwC,CAAC;AACvD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC;AAChD,cAAc,0BAA0B,CAAC;AACzC,cAAc,oCAAoC,CAAC;AACnD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,OAAO,EACL,wCAAwC,EACxC,wBAAwB,GACzB,MAAM,6BAA6B,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sCAAsC,CAAC;AACrD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC"}
package/dist/index.js CHANGED
@@ -14,14 +14,14 @@ export * from "./deriveCardDisplaySummary.js";
14
14
  export * from "./scanNarrativeFacts.js";
15
15
  export * from "./repoIntelligenceSchema.js";
16
16
  export * from "./repoIntelligenceMappers.js";
17
+ export * from "./repoIntelligenceSemantics.js";
17
18
  export * from "./repoIntelligenceValidation.js";
18
19
  export * from "./deriveScanNarrative.js";
19
20
  export * from "./extractRepositoryContextFacts.js";
20
- export * from "./presentScanCardSummary.js";
21
21
  export * from "./narrativePresentation.js";
22
22
  export * from "./normalizeGeneratedText.js";
23
23
  export * from "./collectNarrativeWhyBullets.js";
24
- export * from "./presentGitHubPrComment.js";
24
+ export { presentGitHubPrCommentMarkdownFromResult, renderInsightsAsMarkdown, } from "./presentGitHubPrComment.js";
25
25
  export * from "./scanCardSummary.js";
26
26
  export * from "./deriveScanDetailRecommendations.js";
27
27
  export * from "./deriveRiskScoreSummary.js";
@@ -32,3 +32,4 @@ export * from "./trustedScanGuards.js";
32
32
  export * from "./actionsStepSummary.js";
33
33
  export * from "./prCheckRunPresentation.js";
34
34
  export * from "./productMessaging.js";
35
+ export * from "./presentation/index.js";
@@ -1,9 +1,10 @@
1
1
  import { describe, expect, it } from "vitest";
2
- import { deriveScanNarrative } from "./deriveScanNarrative.js";
3
- import { buildPrCheckRunSummaryMarkdown } from "./prCheckRunPresentation.js";
4
- import { deriveScanCardSummary } from "./scanCardSummary.js";
5
- import { deriveScanDetailViewModel } from "./scanDetailViewModel.js";
6
- import { presentGitHubPrComment } from "./presentGitHubPrComment.js";
2
+ import { buildScanPresentationBundle } from "./presentation/orchestration/buildScanPresentationBundle.js";
3
+ import { presentScanCard } from "./presentation/presenters/presentScanCard.js";
4
+ import { presentScanDetails } from "./presentation/presenters/presentScanDetails.js";
5
+ import { presentGitHubPrComment } from "./presentation/presenters/presentGitHubPrComment.js";
6
+ import { renderGitHubCheckRunMarkdown } from "./presentation/render/renderGitHubCheckRunMarkdown.js";
7
+ import { presentGitHubCheckRun } from "./presentation/presenters/presentGitHubCheckRun.js";
7
8
  import { fixtureRepoIntelligenceFastify } from "./fixtures/repoIntelligenceFixtures.js";
8
9
  import { analysisPreparationWithValidRepoIntel } from "./fixtures/repoIntelligenceTestHelpers.js";
9
10
  const ORIGIN = "https://app.example.com";
@@ -40,26 +41,26 @@ describe("narrative parity across consumers", () => {
40
41
  },
41
42
  ],
42
43
  };
43
- const card = deriveScanCardSummary(result, "done");
44
- const detail = deriveScanDetailViewModel(result, {
44
+ const bundle = buildScanPresentationBundle({
45
+ result,
46
+ pipelineStatus: "done",
47
+ });
48
+ const card = presentScanCard(bundle);
49
+ const detail = presentScanDetails(bundle, {
45
50
  scanId: SCAN_ID,
46
- status: "done",
47
51
  });
48
- const checkRun = buildPrCheckRunSummaryMarkdown({
49
- result,
52
+ const checkRun = renderGitHubCheckRunMarkdown(presentGitHubCheckRun(bundle, {
50
53
  scanId: SCAN_ID,
51
54
  webAppOrigin: ORIGIN,
52
55
  baseline: false,
53
- });
54
- const prComment = presentGitHubPrComment(deriveScanNarrative(result), result);
55
- expect(card.changedPackagesDisplay).toContain("fastify");
56
- expect(detail?.narrativeContext.changedPackagesDisplay).toContain("fastify");
57
- expect(card.reachabilityLabel).toBe("On runtime paths");
58
- expect(detail?.narrativeContext.reachabilityLabel).toBe("On runtime paths");
56
+ }));
57
+ const prComment = presentGitHubPrComment(bundle);
58
+ expect(card.primaryPackage).toBe("fastify");
59
+ expect(detail.narrative.primaryPackage).toBe("fastify");
60
+ expect(card.evidence.some((e) => e.label === "Reachability")).toBe(true);
59
61
  const asciiOnly = /^[\x00-\x7F]*$/;
60
62
  expect(asciiOnly.test(checkRun)).toBe(true);
61
- expect(asciiOnly.test(prComment)).toBe(true);
62
63
  expect(checkRun.toLowerCase()).toContain("fastify");
63
- expect(prComment.toLowerCase()).toContain("fastify");
64
+ expect(prComment.title.toLowerCase()).toContain("review");
64
65
  });
65
66
  });
@@ -1 +1 @@
1
- {"version":3,"file":"narrativePresentation.d.ts","sourceRoot":"","sources":["../src/narrativePresentation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"narrativePresentation.d.ts","sourceRoot":"","sources":["../src/narrativePresentation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAGlE,MAAM,MAAM,4BAA4B,GAAG;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC,CAAC;AAEF,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,kBAAkB,GACxB,MAAM,GAAG,IAAI,CAEf;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,kBAAkB,EACzB,QAAQ,SAAI,GACX,MAAM,GAAG,IAAI,CAQf;AAED,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,kBAAkB,GACxB,MAAM,EAAE,CAEV;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,kBAAkB,EACzB,OAAO,GAAE,4BAAiC,GACzC,mBAAmB,GAAG,IAAI,CA6B5B;AAED,iBAAS,mBAAmB,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,GAAG,IAAI,CAIrE;AAED,iBAAS,qBAAqB,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,GAAG,IAAI,CAIvE;AAED,iBAAS,qBAAqB,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,GAAG,IAAI,CAIvE;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,kBAAkB,EACzB,QAAQ,SAAI,GACX,mBAAmB,CAUrB;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,kBAAkB,EACzB,UAAU,SAAI,GACb,kBAAkB,CAOpB;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,kBAAkB,EACzB,GAAG,SAAI,GACN,KAAK,CAAC;IACP,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC,CAMD;AAED,MAAM,MAAM,6BAA6B,GAAG;IAC1C,KAAK,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,KAAK,CAAC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,kBAAkB,EACzB,OAAO,GAAE,6BAAkC,GAC1C,kBAAkB,CAAC,kBAAkB,CAAC,CASxC;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,kBAAkB,GACxB,MAAM,GAAG,IAAI,CAYf;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,kBAAkB,EACzB,QAAQ,SAAI,GACX,MAAM,GAAG,IAAI,CAiBf;AAED,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,kBAAkB,EACzB,UAAU,SAAI,GACb,MAAM,GAAG,IAAI,CAQf;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,kBAAkB,EACzB,GAAG,SAAI,GACN,MAAM,GAAG,IAAI,CAKf;AAED,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,kBAAkB,EACzB,OAAO,GAAE;IAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/D,MAAM,GAAG,IAAI,CAgCf;AAED,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,CAAC"}
@@ -147,12 +147,15 @@ export function formatFrameworksSummary(facts, max = 2) {
147
147
  }
148
148
  export function composeContextLineFromFacts(facts, options = {}) {
149
149
  const parts = [];
150
- const runtime = labelRuntimeSurface(facts);
151
- const reach = summarizeReachability(facts, options.includePathSample ? 1 : 0);
150
+ const suppressRuntime = facts.packageSemantics?.suppressRuntimeNarrative === true;
151
+ const runtime = suppressRuntime ? null : labelRuntimeSurface(facts);
152
+ const reach = suppressRuntime
153
+ ? null
154
+ : summarizeReachability(facts, options.includePathSample ? 1 : 0);
152
155
  const blast = labelBlastRadiusLevel(facts);
153
156
  if (runtime)
154
157
  parts.push(runtime);
155
- if (reach.kindLabel) {
158
+ if (reach?.kindLabel) {
156
159
  if (options.includePathSample && reach.pathSamples[0]) {
157
160
  parts.push(`${reach.kindLabel} (${reach.pathSamples[0]})`);
158
161
  }
@@ -1,9 +1,8 @@
1
- import type { ScanNarrativeFacts } from "./scanNarrativeFacts.js";
2
1
  import type { PRDecision, PRInsight, ScanResult } from "./types.js";
3
2
  /**
4
- * PR comment markdown from narrative facts (compressed dashboard story).
3
+ * PR comment markdown from a completed scan (via presentation bundle).
5
4
  */
6
- export declare function presentGitHubPrComment(facts: ScanNarrativeFacts, result: ScanResult): string;
7
- /** Backward-compatible entry: derives facts then presents. */
5
+ export declare function presentGitHubPrCommentMarkdownFromResult(result: ScanResult): string;
6
+ /** Backward-compatible entry: derives bundle then renders markdown. */
8
7
  export declare function renderInsightsAsMarkdown(insights: PRInsight[], decision: PRDecision): string;
9
8
  //# sourceMappingURL=presentGitHubPrComment.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"presentGitHubPrComment.d.ts","sourceRoot":"","sources":["../src/presentGitHubPrComment.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAoBpE;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,kBAAkB,EACzB,MAAM,EAAE,UAAU,GACjB,MAAM,CA6CR;AAED,8DAA8D;AAC9D,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,SAAS,EAAE,EACrB,QAAQ,EAAE,UAAU,GACnB,MAAM,CAgBR"}
1
+ {"version":3,"file":"presentGitHubPrComment.d.ts","sourceRoot":"","sources":["../src/presentGitHubPrComment.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEpE;;GAEG;AACH,wBAAgB,wCAAwC,CACtD,MAAM,EAAE,UAAU,GACjB,MAAM,CAWR;AAED,uEAAuE;AACvE,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,SAAS,EAAE,EACrB,QAAQ,EAAE,UAAU,GACnB,MAAM,CAeR"}
@@ -1,66 +1,21 @@
1
- import { deriveScanNarrative } from "./deriveScanNarrative.js";
2
- import { composeVerificationPrompt, formatChangedPackagesShort, formatUsageSummaryLine, selectReviewerGuidance, } from "./narrativePresentation.js";
3
- import { normalizeGeneratedText } from "./normalizeGeneratedText.js";
4
- import { MERGE_POSTURE_LABEL, mergePostureFromDecision, } from "./riskVocabulary.js";
5
- import { scanSurfaceCopy } from "./scanSurfaceCopy.js";
6
- function renderGuidanceBlock(message, where, action) {
7
- return [
8
- normalizeGeneratedText(message),
9
- "",
10
- "**Where it shows up**",
11
- "",
12
- normalizeGeneratedText(where),
13
- "",
14
- "**What to do**",
15
- "",
16
- normalizeGeneratedText(action),
17
- ].join("\n");
18
- }
1
+ import { buildScanPresentationBundle } from "./presentation/orchestration/buildScanPresentationBundle.js";
2
+ import { presentGitHubPrComment as presentGitHubPrCommentFromBundle } from "./presentation/presenters/presentGitHubPrComment.js";
3
+ import { renderGitHubPrCommentMarkdown } from "./presentation/render/renderGitHubPrCommentMarkdown.js";
19
4
  /**
20
- * PR comment markdown from narrative facts (compressed dashboard story).
5
+ * PR comment markdown from a completed scan (via presentation bundle).
21
6
  */
22
- export function presentGitHubPrComment(facts, result) {
23
- const posture = facts.mergePosture ??
24
- mergePostureFromDecision(result.decision?.recommendation);
25
- const title = posture
26
- ? `**${MERGE_POSTURE_LABEL[posture]}**`
27
- : `**${scanSurfaceCopy.checkRun.mergePostureUnavailable}**`;
28
- const introLines = [];
29
- const changed = formatChangedPackagesShort(facts, 3);
30
- if (changed)
31
- introLines.push(`Changed: ${changed}`);
32
- const usage = formatUsageSummaryLine(facts, 1);
33
- if (usage)
34
- introLines.push(usage);
35
- const verify = composeVerificationPrompt(facts);
36
- if (verify)
37
- introLines.push(`Verify: ${verify}`);
38
- const guidance = selectReviewerGuidance(facts, { scope: "changed", max: 3 });
39
- if (guidance.length === 0) {
40
- const fallback = selectReviewerGuidance(facts, { max: 3 });
41
- guidance.push(...fallback.slice(0, 3 - guidance.length));
42
- }
43
- const blocks = guidance.map((g) => {
44
- const where = g.context?.trim() ||
45
- facts.packageUsage
46
- .flatMap((u) => u.paths.slice(0, 1))
47
- .filter(Boolean)[0] ||
48
- "See scan detail for affected paths.";
49
- const action = g.remediation?.trim() ||
50
- composeVerificationPrompt(facts) ||
51
- "Review before merge.";
52
- return renderGuidanceBlock(g.message, where, action);
7
+ export function presentGitHubPrCommentMarkdownFromResult(result) {
8
+ const bundle = buildScanPresentationBundle({
9
+ result,
10
+ pipelineStatus: "done",
11
+ decision: result.decision?.recommendation,
12
+ totalScore: result.totalScore,
53
13
  });
54
- const parts = [title];
55
- if (introLines.length > 0) {
56
- parts.push("", introLines.join("\n"));
57
- }
58
- if (blocks.length > 0) {
59
- parts.push("", ...blocks);
60
- }
61
- return parts.join("\n\n---\n\n").trimEnd();
14
+ if (!bundle)
15
+ return "";
16
+ return renderGitHubPrCommentMarkdown(presentGitHubPrCommentFromBundle(bundle));
62
17
  }
63
- /** Backward-compatible entry: derives facts then presents. */
18
+ /** Backward-compatible entry: derives bundle then renders markdown. */
64
19
  export function renderInsightsAsMarkdown(insights, decision) {
65
20
  const result = {
66
21
  totalScore: 0,
@@ -75,6 +30,5 @@ export function renderInsightsAsMarkdown(insights, decision) {
75
30
  insights,
76
31
  decision,
77
32
  };
78
- const facts = deriveScanNarrative(result);
79
- return presentGitHubPrComment(facts, result);
33
+ return presentGitHubPrCommentMarkdownFromResult(result);
80
34
  }
@@ -0,0 +1,16 @@
1
+ import type { ScanPresentationBundle } from "../orchestration/scanPresentationBundle.js";
2
+ export declare function composeHeadline(bundle: ScanPresentationBundle): string;
3
+ export declare function composeSubheadline(bundle: ScanPresentationBundle): string | undefined;
4
+ export declare function composeKeyPoints(bundle: ScanPresentationBundle, max: number): string[];
5
+ export declare function composeVerificationActions(bundle: ScanPresentationBundle, max: number): string[];
6
+ export declare function composeAffectedAreaLabels(bundle: ScanPresentationBundle, max: number): string[];
7
+ export declare function composeEvidenceRows(bundle: ScanPresentationBundle, max: number): Array<{
8
+ label: string;
9
+ value: string;
10
+ }>;
11
+ export declare function composeSupportingContext(bundle: ScanPresentationBundle): string[] | undefined;
12
+ export declare function evidenceContextFromProfile(bundle: ScanPresentationBundle): {
13
+ priority: "pr_intelligence" | "limited";
14
+ degradedMessage?: string;
15
+ };
16
+ //# sourceMappingURL=narrativeCompose.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"narrativeCompose.d.ts","sourceRoot":"","sources":["../../../src/presentation/compose/narrativeCompose.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AASzF,wBAAgB,eAAe,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,CAwCtE;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,sBAAsB,GAC7B,MAAM,GAAG,SAAS,CAIpB;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,sBAAsB,EAC9B,GAAG,EAAE,MAAM,GACV,MAAM,EAAE,CA2EV;AAED,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,sBAAsB,EAC9B,GAAG,EAAE,MAAM,GACV,MAAM,EAAE,CA0BV;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,sBAAsB,EAC9B,GAAG,EAAE,MAAM,GACV,MAAM,EAAE,CAQV;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,sBAAsB,EAC9B,GAAG,EAAE,MAAM,GACV,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAiBzC;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,sBAAsB,GAC7B,MAAM,EAAE,GAAG,SAAS,CAwBtB;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,sBAAsB,GAAG;IAC1E,QAAQ,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACxC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAKA"}
@@ -0,0 +1,167 @@
1
+ import { formatCardAreaLabels } from "../../formatCardAreaLabels.js";
2
+ import { composeVerificationPrompt, formatChangedPackagesShort, labelBlastRadiusLevel, labelReachabilityKind, labelRuntimeSurface, selectReviewerGuidance, summarizeBlastRadius, summarizePackageUsage, } from "../../narrativePresentation.js";
3
+ import { scanSurfaceCopy } from "../../scanSurfaceCopy.js";
4
+ function topAreaLabel(bundle) {
5
+ const area = bundle.facts.affectedAreas[0];
6
+ if (!area)
7
+ return null;
8
+ const formatted = formatCardAreaLabels([area.label], 1);
9
+ return formatted[0] ?? area.label;
10
+ }
11
+ export function composeHeadline(bundle) {
12
+ const { facts, profile } = bundle;
13
+ const primary = facts.changedPackages.primary;
14
+ if (profile.priority === "limited") {
15
+ return scanSurfaceCopy.presentation.limitedContextHeadline;
16
+ }
17
+ if (!primary) {
18
+ return scanSurfaceCopy.presentation.noChangedPackagesHeadline;
19
+ }
20
+ const runtime = facts.runtimeSurface?.kind === "runtime";
21
+ const area = topAreaLabel(bundle);
22
+ if (facts.changedPackages.all.length > 1 && runtime) {
23
+ return scanSurfaceCopy.presentation.multiRuntimeHeadline;
24
+ }
25
+ if (facts.runtimeSurface?.kind === "build" ||
26
+ facts.reachability?.kind === "build_only") {
27
+ return scanSurfaceCopy.presentation.buildOnlyHeadline.replace("{package}", primary);
28
+ }
29
+ if (runtime) {
30
+ const surface = area ?? labelRuntimeSurface(facts) ?? "application code";
31
+ return scanSurfaceCopy.presentation.runtimeHeadline
32
+ .replace("{package}", primary)
33
+ .replace("{surface}", surface);
34
+ }
35
+ return scanSurfaceCopy.presentation.defaultUpgradeHeadline.replace("{package}", primary);
36
+ }
37
+ export function composeSubheadline(bundle) {
38
+ const { profile } = bundle;
39
+ if (profile.degradedMessage)
40
+ return profile.degradedMessage;
41
+ return undefined;
42
+ }
43
+ export function composeKeyPoints(bundle, max) {
44
+ const { facts, profile } = bundle;
45
+ const points = [];
46
+ if (profile.priority === "limited") {
47
+ points.push(scanSurfaceCopy.presentation.limitedContextKeyPoint);
48
+ if (facts.changedPackages.primary) {
49
+ points.push(scanSurfaceCopy.presentation.changedPackageKeyPoint.replace("{package}", facts.changedPackages.primary));
50
+ }
51
+ return points.slice(0, max);
52
+ }
53
+ const usage = summarizePackageUsage(facts, { maxPaths: 2 });
54
+ if (usage && usage.pathCount > 0) {
55
+ if (usage.pathCount === 1 && usage.pathSamples[0]) {
56
+ points.push(scanSurfaceCopy.presentation.usedInPathsSingle.replace("{path}", usage.pathSamples[0]));
57
+ }
58
+ else {
59
+ points.push(scanSurfaceCopy.presentation.usedInPathsMultiple.replace("{count}", String(usage.pathCount)));
60
+ }
61
+ }
62
+ else if (profile.density === "minimal") {
63
+ points.push(scanSurfaceCopy.presentation.noRuntimePathsKeyPoint);
64
+ }
65
+ const blast = summarizeBlastRadius(facts, 2);
66
+ if (blast.levelLabel) {
67
+ if (blast.levelLabel.toLowerCase().includes("wide")) {
68
+ points.push(scanSurfaceCopy.presentation.blastRadiusWideKeyPoint);
69
+ }
70
+ else if (profile.density === "rich") {
71
+ points.push(scanSurfaceCopy.presentation.blastRadiusLevelKeyPoint.replace("{level}", blast.levelLabel));
72
+ }
73
+ }
74
+ if (facts.affectedAreas.length === 0 && profile.density === "minimal") {
75
+ points.push(scanSurfaceCopy.presentation.noAffectedAreasKeyPoint);
76
+ }
77
+ else if (facts.affectedAreas.length > 0) {
78
+ const labels = facts.affectedAreas
79
+ .slice(0, 2)
80
+ .map((a) => a.label)
81
+ .join(", ");
82
+ points.push(scanSurfaceCopy.presentation.affectedAreasKeyPoint.replace("{areas}", labels));
83
+ }
84
+ const guidance = selectReviewerGuidance(facts, { scope: "changed", max: 2 });
85
+ for (const g of guidance) {
86
+ const msg = g.message.trim();
87
+ if (msg && !points.includes(msg))
88
+ points.push(msg);
89
+ if (points.length >= max)
90
+ break;
91
+ }
92
+ return points.slice(0, max);
93
+ }
94
+ export function composeVerificationActions(bundle, max) {
95
+ const { facts, profile } = bundle;
96
+ const actions = [];
97
+ const guidance = selectReviewerGuidance(facts, { scope: "changed", max: 4 });
98
+ for (const g of guidance) {
99
+ const rem = g.remediation?.trim();
100
+ if (rem)
101
+ actions.push(rem);
102
+ }
103
+ const prompt = composeVerificationPrompt(facts);
104
+ if (prompt && !actions.includes(prompt))
105
+ actions.push(prompt);
106
+ if (actions.length === 0) {
107
+ if (profile.density === "minimal" ||
108
+ facts.runtimeSurface?.kind === "build") {
109
+ actions.push(scanSurfaceCopy.presentation.verifyCiTypecheck);
110
+ }
111
+ else if (profile.density === "rich") {
112
+ actions.push(scanSurfaceCopy.presentation.verifyAuthFlow);
113
+ actions.push(scanSurfaceCopy.presentation.verifyErrorResponses);
114
+ }
115
+ }
116
+ return actions.slice(0, max);
117
+ }
118
+ export function composeAffectedAreaLabels(bundle, max) {
119
+ const labels = [];
120
+ for (const area of bundle.facts.affectedAreas) {
121
+ const formatted = formatCardAreaLabels([area.label], 1);
122
+ if (formatted[0])
123
+ labels.push(formatted[0]);
124
+ if (labels.length >= max)
125
+ break;
126
+ }
127
+ return labels;
128
+ }
129
+ export function composeEvidenceRows(bundle, max) {
130
+ const { facts } = bundle;
131
+ const rows = [];
132
+ const runtime = labelRuntimeSurface(facts);
133
+ if (runtime)
134
+ rows.push({ label: "Runtime", value: runtime });
135
+ const reach = labelReachabilityKind(facts);
136
+ if (reach)
137
+ rows.push({ label: "Reachability", value: reach });
138
+ const blast = labelBlastRadiusLevel(facts);
139
+ if (blast)
140
+ rows.push({ label: "Blast radius", value: blast });
141
+ const changed = formatChangedPackagesShort(facts, 3);
142
+ if (changed)
143
+ rows.push({ label: "Changed", value: changed });
144
+ return rows.slice(0, max);
145
+ }
146
+ export function composeSupportingContext(bundle) {
147
+ const { facts, profile, result } = bundle;
148
+ if (profile.density === "minimal")
149
+ return undefined;
150
+ const lines = [];
151
+ const graph = result.graphInsights;
152
+ if (graph?.maxDepth != null) {
153
+ lines.push(scanSurfaceCopy.presentation.graphDepthContext.replace("{depth}", String(graph.maxDepth)));
154
+ }
155
+ if (graph?.nodes != null && graph?.edges != null) {
156
+ lines.push(scanSurfaceCopy.presentation.graphSizeContext
157
+ .replace("{nodes}", String(graph.nodes))
158
+ .replace("{edges}", String(graph.edges)));
159
+ }
160
+ return lines.length > 0 ? lines.slice(0, 3) : undefined;
161
+ }
162
+ export function evidenceContextFromProfile(bundle) {
163
+ return {
164
+ priority: bundle.profile.priority,
165
+ degradedMessage: bundle.profile.degradedMessage,
166
+ };
167
+ }
@@ -0,0 +1,53 @@
1
+ import type { PresentationConfidence, PresentationDensity, PresentationEvidenceContext, PresentationStatus } from "./types.js";
2
+ export type GitHubCheckRunPresentation = {
3
+ status: PresentationStatus;
4
+ density: PresentationDensity;
5
+ confidence: PresentationConfidence;
6
+ evidenceContext: PresentationEvidenceContext;
7
+ title: string;
8
+ conclusion: "success" | "neutral" | "failure";
9
+ summaryLead: string;
10
+ sections: Array<{
11
+ id: "why" | "actions" | "usage" | "repoContext" | "layers" | "footer";
12
+ title?: string;
13
+ bullets: string[];
14
+ collapsed?: boolean;
15
+ }>;
16
+ detailsUrl: string;
17
+ };
18
+ export type GitHubPrCommentPresentation = {
19
+ status: PresentationStatus;
20
+ density: PresentationDensity;
21
+ confidence: PresentationConfidence;
22
+ evidenceContext: PresentationEvidenceContext;
23
+ title: string;
24
+ introLines: string[];
25
+ guidanceBlocks: Array<{
26
+ message: string;
27
+ where?: string;
28
+ action?: string;
29
+ }>;
30
+ };
31
+ export type CliScanPresentation = {
32
+ header: {
33
+ repoLabel: string;
34
+ methodology?: string;
35
+ confidence?: string;
36
+ };
37
+ status: PresentationStatus;
38
+ density: PresentationDensity;
39
+ confidence: PresentationConfidence;
40
+ evidenceContext: PresentationEvidenceContext;
41
+ headline: string;
42
+ subheadline?: string;
43
+ keyPoints: string[];
44
+ verificationActions: string[];
45
+ metrics?: {
46
+ riskIndex: number;
47
+ layerLine: string;
48
+ findingCount: number;
49
+ recommendationCount: number;
50
+ };
51
+ supportingContext?: string[];
52
+ };
53
+ //# sourceMappingURL=githubAndCliPresentation.d.ts.map