@mergesignal/shared 0.12.2 → 0.13.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 (172) hide show
  1. package/dist/assessment/authoredCommunication.d.ts +30 -0
  2. package/dist/assessment/authoredCommunication.d.ts.map +1 -0
  3. package/dist/assessment/authoredCommunication.js +18 -0
  4. package/dist/assessment/index.d.ts +6 -0
  5. package/dist/assessment/index.d.ts.map +1 -0
  6. package/dist/assessment/index.js +5 -0
  7. package/dist/assessment/literals.d.ts +44 -0
  8. package/dist/assessment/literals.d.ts.map +1 -0
  9. package/dist/assessment/literals.js +140 -0
  10. package/dist/assessment/schema.d.ts +311 -0
  11. package/dist/assessment/schema.d.ts.map +1 -0
  12. package/dist/assessment/schema.js +162 -0
  13. package/dist/assessment/types.d.ts +197 -0
  14. package/dist/assessment/types.d.ts.map +1 -0
  15. package/dist/assessment/types.js +1 -0
  16. package/dist/assessment/version.d.ts +11 -0
  17. package/dist/assessment/version.d.ts.map +1 -0
  18. package/dist/assessment/version.js +9 -0
  19. package/dist/assessmentLabels.d.ts +1 -1
  20. package/dist/assessmentLabels.d.ts.map +1 -1
  21. package/dist/assessmentPresentationUtils.d.ts +1 -1
  22. package/dist/assessmentPresentationUtils.d.ts.map +1 -1
  23. package/dist/assessmentProjection.d.ts +1 -1
  24. package/dist/assessmentProjection.d.ts.map +1 -1
  25. package/dist/deriveScanNarrative.d.ts.map +1 -1
  26. package/dist/deriveScanNarrative.js +2 -1
  27. package/dist/fixtures/assessmentFixtures.d.ts +1 -1
  28. package/dist/fixtures/assessmentScopeFixtures.d.ts +1 -1
  29. package/dist/index.d.ts +2 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +2 -0
  32. package/dist/lockfileEvidence.d.ts +22 -0
  33. package/dist/lockfileEvidence.d.ts.map +1 -0
  34. package/dist/lockfileEvidence.js +32 -0
  35. package/dist/presentation/dto/assessmentPresentationFields.d.ts +1 -1
  36. package/dist/presentation/dto/assessmentPresentationFields.d.ts.map +1 -1
  37. package/dist/presentation/orchestration/buildScanPresentationBundle.d.ts.map +1 -1
  38. package/dist/presentation/orchestration/buildScanPresentationBundle.js +2 -1
  39. package/dist/presentation/orchestration/scanPresentationBundle.d.ts +2 -1
  40. package/dist/presentation/orchestration/scanPresentationBundle.d.ts.map +1 -1
  41. package/dist/presentation/profile/buildProfileFromAssessment.d.ts +1 -1
  42. package/dist/presentation/profile/buildProfileFromAssessment.d.ts.map +1 -1
  43. package/dist/presentation/profile/buildProfileFromAssessment.js +13 -5
  44. package/dist/repoIntelligenceSchema.d.ts +5 -5
  45. package/dist/scanResultSchema.d.ts +6 -6
  46. package/dist/scanResultSchema.js +1 -1
  47. package/dist/types.d.ts +6 -2
  48. package/dist/types.d.ts.map +1 -1
  49. package/package.json +1 -2
  50. package/dist/actionsStepSummary.test.d.ts +0 -2
  51. package/dist/actionsStepSummary.test.d.ts.map +0 -1
  52. package/dist/actionsStepSummary.test.js +0 -53
  53. package/dist/assessmentProjection.verificationChannel.test.d.ts +0 -2
  54. package/dist/assessmentProjection.verificationChannel.test.d.ts.map +0 -1
  55. package/dist/assessmentProjection.verificationChannel.test.js +0 -110
  56. package/dist/deriveScanNarrative.test.d.ts +0 -2
  57. package/dist/deriveScanNarrative.test.d.ts.map +0 -1
  58. package/dist/deriveScanNarrative.test.js +0 -274
  59. package/dist/engineWireRegression.test.d.ts +0 -2
  60. package/dist/engineWireRegression.test.d.ts.map +0 -1
  61. package/dist/engineWireRegression.test.js +0 -77
  62. package/dist/fixtures/engineAbi4Fixtures.d.ts +0 -16
  63. package/dist/fixtures/engineAbi4Fixtures.d.ts.map +0 -1
  64. package/dist/fixtures/engineAbi4Fixtures.js +0 -26
  65. package/dist/fixtures/legacyEngineRepoIntelligence.d.ts +0 -28
  66. package/dist/fixtures/legacyEngineRepoIntelligence.d.ts.map +0 -1
  67. package/dist/fixtures/legacyEngineRepoIntelligence.js +0 -28
  68. package/dist/fixtures/repoIntelligenceFixtures.d.ts +0 -8
  69. package/dist/fixtures/repoIntelligenceFixtures.d.ts.map +0 -1
  70. package/dist/fixtures/repoIntelligenceFixtures.js +0 -123
  71. package/dist/fixtures/repoIntelligenceTestHelpers.d.ts +0 -5
  72. package/dist/fixtures/repoIntelligenceTestHelpers.d.ts.map +0 -1
  73. package/dist/fixtures/repoIntelligenceTestHelpers.js +0 -28
  74. package/dist/formatInsight.test.d.ts +0 -2
  75. package/dist/formatInsight.test.d.ts.map +0 -1
  76. package/dist/formatInsight.test.js +0 -102
  77. package/dist/narrativeParity.test.d.ts +0 -2
  78. package/dist/narrativeParity.test.d.ts.map +0 -1
  79. package/dist/narrativeParity.test.js +0 -35
  80. package/dist/narrativePresentation.test.d.ts +0 -2
  81. package/dist/narrativePresentation.test.d.ts.map +0 -1
  82. package/dist/narrativePresentation.test.js +0 -54
  83. package/dist/normalizeGeneratedText.test.d.ts +0 -2
  84. package/dist/normalizeGeneratedText.test.d.ts.map +0 -1
  85. package/dist/normalizeGeneratedText.test.js +0 -18
  86. package/dist/prRiskBand.test.d.ts +0 -2
  87. package/dist/prRiskBand.test.d.ts.map +0 -1
  88. package/dist/prRiskBand.test.js +0 -68
  89. package/dist/prRiskWire.test.d.ts +0 -2
  90. package/dist/prRiskWire.test.d.ts.map +0 -1
  91. package/dist/prRiskWire.test.js +0 -106
  92. package/dist/prRiskWiringRegression.test.d.ts +0 -2
  93. package/dist/prRiskWiringRegression.test.d.ts.map +0 -1
  94. package/dist/prRiskWiringRegression.test.js +0 -102
  95. package/dist/presentation/abi3Expression.test.d.ts +0 -13
  96. package/dist/presentation/abi3Expression.test.d.ts.map +0 -1
  97. package/dist/presentation/abi3Expression.test.js +0 -392
  98. package/dist/presentation/buildGitHubCheckRunOutput.test.d.ts +0 -2
  99. package/dist/presentation/buildGitHubCheckRunOutput.test.d.ts.map +0 -1
  100. package/dist/presentation/buildGitHubCheckRunOutput.test.js +0 -163
  101. package/dist/presentation/bundleAccessorParity.test.d.ts +0 -9
  102. package/dist/presentation/bundleAccessorParity.test.d.ts.map +0 -1
  103. package/dist/presentation/bundleAccessorParity.test.js +0 -126
  104. package/dist/presentation/cliParity.test.d.ts +0 -2
  105. package/dist/presentation/cliParity.test.d.ts.map +0 -1
  106. package/dist/presentation/cliParity.test.js +0 -49
  107. package/dist/presentation/compose/narrativeChannels.test.d.ts +0 -2
  108. package/dist/presentation/compose/narrativeChannels.test.d.ts.map +0 -1
  109. package/dist/presentation/compose/narrativeChannels.test.js +0 -42
  110. package/dist/presentation/decisionSurface.test.d.ts +0 -2
  111. package/dist/presentation/decisionSurface.test.d.ts.map +0 -1
  112. package/dist/presentation/decisionSurface.test.js +0 -290
  113. package/dist/presentation/fixtures/dashboardCardGolden.test.d.ts +0 -2
  114. package/dist/presentation/fixtures/dashboardCardGolden.test.d.ts.map +0 -1
  115. package/dist/presentation/fixtures/dashboardCardGolden.test.js +0 -38
  116. package/dist/presentation/fixtures/presentationPersonaFixtures.d.ts +0 -11
  117. package/dist/presentation/fixtures/presentationPersonaFixtures.d.ts.map +0 -1
  118. package/dist/presentation/fixtures/presentationPersonaFixtures.js +0 -208
  119. package/dist/presentation/fixtures/scanResultFixtures.d.ts +0 -5
  120. package/dist/presentation/fixtures/scanResultFixtures.d.ts.map +0 -1
  121. package/dist/presentation/fixtures/scanResultFixtures.js +0 -123
  122. package/dist/presentation/intent/postureVocabularyGuard.test.d.ts +0 -2
  123. package/dist/presentation/intent/postureVocabularyGuard.test.d.ts.map +0 -1
  124. package/dist/presentation/intent/postureVocabularyGuard.test.js +0 -23
  125. package/dist/presentation/orchestration/buildScanPresentationBundle.test.d.ts +0 -2
  126. package/dist/presentation/orchestration/buildScanPresentationBundle.test.d.ts.map +0 -1
  127. package/dist/presentation/orchestration/buildScanPresentationBundle.test.js +0 -99
  128. package/dist/presentation/presentation.test.d.ts +0 -2
  129. package/dist/presentation/presentation.test.d.ts.map +0 -1
  130. package/dist/presentation/presentation.test.js +0 -126
  131. package/dist/presentation/presentationPersonas.test.d.ts +0 -2
  132. package/dist/presentation/presentationPersonas.test.d.ts.map +0 -1
  133. package/dist/presentation/presentationPersonas.test.js +0 -164
  134. package/dist/presentation/surfaceParity.test.d.ts +0 -2
  135. package/dist/presentation/surfaceParity.test.d.ts.map +0 -1
  136. package/dist/presentation/surfaceParity.test.js +0 -156
  137. package/dist/presentation/verificationChannelParity.test.d.ts +0 -2
  138. package/dist/presentation/verificationChannelParity.test.d.ts.map +0 -1
  139. package/dist/presentation/verificationChannelParity.test.js +0 -57
  140. package/dist/productMessaging.test.d.ts +0 -2
  141. package/dist/productMessaging.test.d.ts.map +0 -1
  142. package/dist/productMessaging.test.js +0 -97
  143. package/dist/repoIntelligenceSchema.contract.test.d.ts +0 -2
  144. package/dist/repoIntelligenceSchema.contract.test.d.ts.map +0 -1
  145. package/dist/repoIntelligenceSchema.contract.test.js +0 -51
  146. package/dist/repoIntelligenceSemantics.test.d.ts +0 -2
  147. package/dist/repoIntelligenceSemantics.test.d.ts.map +0 -1
  148. package/dist/repoIntelligenceSemantics.test.js +0 -63
  149. package/dist/repoIntelligenceValidation.persist.test.d.ts +0 -2
  150. package/dist/repoIntelligenceValidation.persist.test.d.ts.map +0 -1
  151. package/dist/repoIntelligenceValidation.persist.test.js +0 -44
  152. package/dist/riskSignals.test.d.ts +0 -2
  153. package/dist/riskSignals.test.d.ts.map +0 -1
  154. package/dist/riskSignals.test.js +0 -32
  155. package/dist/riskVocabulary.test.d.ts +0 -2
  156. package/dist/riskVocabulary.test.d.ts.map +0 -1
  157. package/dist/riskVocabulary.test.js +0 -14
  158. package/dist/scanPresentationBundle.golden.test.d.ts +0 -2
  159. package/dist/scanPresentationBundle.golden.test.d.ts.map +0 -1
  160. package/dist/scanPresentationBundle.golden.test.js +0 -78
  161. package/dist/scanResultSchema.test.d.ts +0 -2
  162. package/dist/scanResultSchema.test.d.ts.map +0 -1
  163. package/dist/scanResultSchema.test.js +0 -162
  164. package/dist/scanSurfaceCopy.test.d.ts +0 -2
  165. package/dist/scanSurfaceCopy.test.d.ts.map +0 -1
  166. package/dist/scanSurfaceCopy.test.js +0 -14
  167. package/dist/selectTopAffectedAreas.test.d.ts +0 -2
  168. package/dist/selectTopAffectedAreas.test.d.ts.map +0 -1
  169. package/dist/selectTopAffectedAreas.test.js +0 -179
  170. package/dist/trustedScanGuards.test.d.ts +0 -2
  171. package/dist/trustedScanGuards.test.d.ts.map +0 -1
  172. package/dist/trustedScanGuards.test.js +0 -151
@@ -1,164 +0,0 @@
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 { presentCliScanSummary } from "./presenters/presentCliScanSummary.js";
6
- import { scanResultBullmq, scanResultEslint, scanResultFastifyRuntime, scanResultLimitedContext, scanResultMixedTypescriptFastify, scanResultNextAuth, scanResultPrettier, scanResultTypescriptPatch, scanResultUnknownSafe, scanResultVitest, } from "./fixtures/presentationPersonaFixtures.js";
7
- const SCAN_ID = "22222222-2222-4222-8222-222222222222";
8
- const SAFE_FORBIDDEN = /needs review|high risk|critical concern/i;
9
- const REVIEW_FORBIDDEN = /no action required|no verification required/i;
10
- const personas = [
11
- {
12
- name: "typescript patch",
13
- result: scanResultTypescriptPatch,
14
- intent: "tooling_patch",
15
- status: "safe",
16
- density: "minimal",
17
- headlineMatch: /patch upgrade/i,
18
- headlineMustNot: /needs review/i,
19
- verificationIncludes: ["typecheck"],
20
- },
21
- {
22
- name: "eslint",
23
- result: scanResultEslint,
24
- intent: "tooling_upgrade",
25
- status: "safe",
26
- density: "minimal",
27
- headlineMatch: /patch upgrade/i,
28
- headlineMustNot: /needs review/i,
29
- },
30
- {
31
- name: "prettier",
32
- result: scanResultPrettier,
33
- intent: "tooling_upgrade",
34
- status: "safe",
35
- density: "minimal",
36
- headlineMatch: /patch upgrade/i,
37
- headlineMustNot: /needs review/i,
38
- verificationIncludes: ["format"],
39
- },
40
- {
41
- name: "vitest",
42
- result: scanResultVitest,
43
- intent: "tooling_upgrade",
44
- status: "safe",
45
- density: "minimal",
46
- headlineMatch: /patch upgrade|dependency upgrade/i,
47
- headlineMustNot: /needs review/i,
48
- },
49
- {
50
- name: "fastify runtime",
51
- result: scanResultFastifyRuntime,
52
- intent: "runtime_upgrade",
53
- status: "needs_review",
54
- density: "rich",
55
- headlineMatch: /runtime upgrade affects/i,
56
- verificationIncludes: ["routes", "middleware"],
57
- },
58
- {
59
- name: "nextauth runtime",
60
- result: scanResultNextAuth,
61
- intent: "auth_runtime_upgrade",
62
- status: "needs_review",
63
- density: "rich",
64
- headlineMatch: /runtime upgrade affects/i,
65
- verificationIncludes: ["auth_flow"],
66
- },
67
- {
68
- name: "bullmq runtime",
69
- result: scanResultBullmq,
70
- intent: "queue_runtime_upgrade",
71
- status: "needs_review",
72
- density: "rich",
73
- headlineMatch: /runtime upgrade affects/i,
74
- verificationIncludes: ["workers", "queue"],
75
- },
76
- {
77
- name: "limited context",
78
- result: scanResultLimitedContext,
79
- intent: "limited_context",
80
- status: "needs_review",
81
- density: "minimal",
82
- headlineMatch: /limited scan context/i,
83
- },
84
- {
85
- name: "unknown safe",
86
- result: scanResultUnknownSafe,
87
- intent: "unknown_upgrade",
88
- status: "safe",
89
- density: "standard",
90
- headlineMatch: /dependency upgrade/i,
91
- headlineMustNot: /needs review/i,
92
- },
93
- ];
94
- function cardFor(result) {
95
- const bundle = buildScanPresentationBundle({
96
- result,
97
- pipelineStatus: "done",
98
- });
99
- return presentDashboardCard(bundle);
100
- }
101
- describe("presentation personas", () => {
102
- for (const persona of personas) {
103
- it(`${persona.name}: intent, posture alignment, headline`, () => {
104
- const card = cardFor(persona.result);
105
- expect(card.verdict?.posture).toBe(persona.status);
106
- if (persona.density === "rich") {
107
- expect(card.layout).toBe("expanded");
108
- }
109
- expect(card.headline).toMatch(persona.headlineMatch);
110
- if (persona.headlineMustNot) {
111
- expect(card.headline).not.toMatch(persona.headlineMustNot);
112
- }
113
- if (persona.status === "safe") {
114
- const combined = [
115
- card.headline,
116
- ...card.insights,
117
- ...card.verification,
118
- ].join(" ");
119
- expect(combined).not.toMatch(SAFE_FORBIDDEN);
120
- }
121
- if (persona.status === "needs_review") {
122
- const combined = card.verification.join(" ");
123
- expect(combined).not.toMatch(REVIEW_FORBIDDEN);
124
- }
125
- if (persona.verificationIncludes) {
126
- for (const v of persona.verificationIncludes) {
127
- expect(card.verification.some((a) => a.toLowerCase().includes(v.toLowerCase()))).toBe(true);
128
- }
129
- }
130
- if (persona.verificationMustNot) {
131
- expect(card.verification.join(" ")).not.toMatch(persona.verificationMustNot);
132
- }
133
- });
134
- }
135
- it("mixed typescript+fastify: runtime intent, fastify in headline", () => {
136
- const card = cardFor(scanResultMixedTypescriptFastify);
137
- expect(card.verdict?.posture).toBe("needs_review");
138
- expect(card.headline.toLowerCase()).toContain("fastify");
139
- expect(card.headline).not.toMatch(/patch upgrade/i);
140
- });
141
- it("cross-surface parity: fastify headline matches card, details, CLI", () => {
142
- const bundle = buildScanPresentationBundle({
143
- result: scanResultFastifyRuntime,
144
- pipelineStatus: "done",
145
- });
146
- const card = presentDashboardCard(bundle);
147
- const details = presentScanDetails(bundle, { scanId: SCAN_ID });
148
- const cli = presentCliScanSummary(bundle, { repoLabel: "acme/api" });
149
- expect(details.hero.headline).toBe(card.headline);
150
- expect(cli.headline).toBe(card.headline);
151
- });
152
- it("cross-surface parity: typescript headline matches card, details, CLI", () => {
153
- const bundle = buildScanPresentationBundle({
154
- result: scanResultTypescriptPatch,
155
- pipelineStatus: "done",
156
- });
157
- const card = presentDashboardCard(bundle);
158
- const details = presentScanDetails(bundle, { scanId: SCAN_ID });
159
- const cli = presentCliScanSummary(bundle, { repoLabel: "acme/api" });
160
- expect(details.hero.headline).toBe(card.headline);
161
- expect(cli.headline).toBe(card.headline);
162
- expect(card.headline).not.toMatch(/needs review/i);
163
- });
164
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=surfaceParity.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"surfaceParity.test.d.ts","sourceRoot":"","sources":["../../src/presentation/surfaceParity.test.ts"],"names":[],"mappings":""}
@@ -1,156 +0,0 @@
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
- import { buildNarrativeChannels } from "./compose/narrativeChannels.js";
12
- const SCAN_ID = "22222222-2222-4222-8222-222222222222";
13
- const ORIGIN = "https://app.example.com";
14
- const validationPersonasCore = [
15
- {
16
- id: "validation-pr-26",
17
- name: "PR #26 mixed",
18
- result: scanResultMixedTypescriptFastify,
19
- },
20
- {
21
- id: "validation-pr-27",
22
- name: "PR #27 fastify",
23
- result: scanResultFastifyRuntime,
24
- },
25
- {
26
- id: "validation-pr-28",
27
- name: "PR #28 typescript",
28
- result: scanResultTypescriptPatch,
29
- },
30
- {
31
- id: "validation-pr-29",
32
- name: "PR #29 prettier",
33
- result: scanResultPrettier,
34
- },
35
- { id: "validation-pr-30", name: "PR #30 bullmq", result: scanResultBullmq },
36
- ];
37
- const validationPersonas = [
38
- ...validationPersonasCore,
39
- { name: "eslint", result: scanResultEslint },
40
- { name: "vitest", result: scanResultVitest },
41
- ];
42
- function surfacesFor(result) {
43
- const bundle = buildScanPresentationBundle({
44
- result,
45
- pipelineStatus: "done",
46
- });
47
- const fields = projectAssessmentFields(bundle);
48
- const card = presentDashboardCard(bundle);
49
- const details = presentScanDetails(bundle, { scanId: SCAN_ID });
50
- const check = presentGitHubCheckRun(bundle, {
51
- scanId: SCAN_ID,
52
- webAppOrigin: ORIGIN,
53
- });
54
- const comment = presentGitHubPrComment(bundle);
55
- const checkMd = renderGitHubCheckRunMarkdown(check);
56
- const commentMd = renderGitHubPrCommentMarkdown(comment);
57
- return { bundle, fields, card, details, check, comment, checkMd, commentMd };
58
- }
59
- describe("surfaceParity guardrail", () => {
60
- for (const persona of validationPersonas) {
61
- it(`${persona.name}: posture and assessment fields match across surfaces`, () => {
62
- const s = surfacesFor(persona.result);
63
- expect(s.card.posture).toBe(s.fields.posture);
64
- expect(s.details.posture).toBe(s.fields.posture);
65
- expect(s.check.posture).toBe(s.fields.posture);
66
- expect(s.comment.posture).toBe(s.fields.posture);
67
- expect(s.card.verdict?.posture).toBe(s.fields.posture);
68
- expect(s.card.primaryConcern).toBe(s.fields.primaryConcern);
69
- expect(s.details.primaryConcern).toBe(s.fields.primaryConcern);
70
- expect(s.check.primaryConcern).toBe(s.fields.primaryConcern);
71
- expect(s.comment.primaryConcern).toBe(s.fields.primaryConcern);
72
- expect(s.card.narrativeIntensity).toBe(s.fields.narrativeIntensity);
73
- expect(s.details.narrativeIntensity).toBe(s.fields.narrativeIntensity);
74
- expect(s.check.narrativeIntensity).toBe(s.fields.narrativeIntensity);
75
- expect(s.comment.narrativeIntensity).toBe(s.fields.narrativeIntensity);
76
- expect(s.card.reachVisibility).toBe(s.fields.reachVisibility);
77
- expect(s.details.reachVisibility).toBe(s.fields.reachVisibility);
78
- expect(s.check.reachVisibility).toBe(s.fields.reachVisibility);
79
- expect(s.comment.reachVisibility).toBe(s.fields.reachVisibility);
80
- expect(s.card.reasoning).toEqual(s.fields.reasoning);
81
- expect(s.details.reasoning).toEqual(s.fields.reasoning);
82
- expect(s.check.reasoning).toEqual(s.fields.reasoning);
83
- expect(s.comment.reasoning).toEqual(s.fields.reasoning);
84
- expect(s.card.verificationFocus).toEqual(s.fields.verificationFocus);
85
- expect(s.details.verificationFocus).toEqual(s.fields.verificationFocus);
86
- expect(s.check.verificationFocus).toEqual(s.fields.verificationFocus);
87
- expect(s.comment.verificationFocus).toEqual(s.fields.verificationFocus);
88
- expect(s.card.verificationChannel).toBe(s.fields.verificationChannel);
89
- expect(s.details.verificationChannel).toBe(s.fields.verificationChannel);
90
- expect(s.check.verificationChannel).toBe(s.fields.verificationChannel);
91
- expect(s.comment.verificationChannel).toBe(s.fields.verificationChannel);
92
- expect(s.card.confidenceRationale).toBe(s.fields.confidenceRationale);
93
- expect(s.details.confidenceRationale).toBe(s.fields.confidenceRationale);
94
- expect(s.check.confidenceRationale).toBe(s.fields.confidenceRationale);
95
- expect(s.comment.confidenceRationale).toBe(s.fields.confidenceRationale);
96
- expect(s.card.electionSummary).toBe(s.fields.electionSummary);
97
- expect(s.details.electionSummary).toBe(s.fields.electionSummary);
98
- expect(s.check.electionSummary).toBe(s.fields.electionSummary);
99
- expect(s.comment.electionSummary).toBe(s.fields.electionSummary);
100
- });
101
- it(`${persona.name}: headline matches across card and details`, () => {
102
- const s = surfacesFor(persona.result);
103
- expect(s.details.hero.headline).toBe(s.card.headline);
104
- });
105
- }
106
- it("validation personas #26–#30: pairwise distinct reviewFocalPoint and headlines", () => {
107
- const focalPoints = [];
108
- const headlines = [];
109
- for (const persona of validationPersonasCore) {
110
- const s = surfacesFor(persona.result);
111
- focalPoints.push(persona.result.assessment.reviewFocalPoint);
112
- headlines.push(s.card.headline);
113
- expect(s.check.title).toBe(s.card.headline);
114
- }
115
- for (let i = 0; i < headlines.length; i++) {
116
- for (let j = i + 1; j < headlines.length; j++) {
117
- expect(headlines[i]).not.toBe(headlines[j]);
118
- }
119
- }
120
- for (let i = 0; i < focalPoints.length; i++) {
121
- for (let j = i + 1; j < focalPoints.length; j++) {
122
- expect(focalPoints[i]).not.toEqual(focalPoints[j]);
123
- }
124
- }
125
- });
126
- it("PR #26: headline uses focal fastify, not changedPackages[0] typescript", () => {
127
- const result = scanResultMixedTypescriptFastify;
128
- expect(result.changedPackages?.[0]).toBe("typescript");
129
- const s = surfacesFor(result);
130
- expect(s.card.headline.toLowerCase()).toContain("fastify");
131
- expect(s.card.headline.toLowerCase()).not.toContain("typescript");
132
- });
133
- it("validation personas #28–#30: reach and verification channels differ by scope", () => {
134
- const channelsById = new Map(validationPersonasCore.map((p) => {
135
- const bundle = buildScanPresentationBundle({
136
- result: p.result,
137
- pipelineStatus: "done",
138
- });
139
- return [p.id, buildNarrativeChannels(bundle)];
140
- }));
141
- const ch28 = channelsById.get("validation-pr-28");
142
- const ch29 = channelsById.get("validation-pr-29");
143
- const ch27 = channelsById.get("validation-pr-27");
144
- const ch30 = channelsById.get("validation-pr-30");
145
- const ch26 = channelsById.get("validation-pr-26");
146
- expect(ch28.reachLabel).toBeUndefined();
147
- expect(ch29.reachLabel).toBeUndefined();
148
- expect(ch28.verification.length).toBeGreaterThan(0);
149
- expect(ch29.verification.length).toBeGreaterThan(0);
150
- expect(ch27.verification.length).toBeGreaterThan(0);
151
- expect(ch30.verification.length).toBeGreaterThan(0);
152
- expect(ch27.verification).not.toEqual(ch30.verification);
153
- expect(ch26.verification).not.toEqual(ch27.verification);
154
- expect(ch26.scopeAreas.length).toBeGreaterThan(0);
155
- });
156
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=verificationChannelParity.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"verificationChannelParity.test.d.ts","sourceRoot":"","sources":["../../src/presentation/verificationChannelParity.test.ts"],"names":[],"mappings":""}
@@ -1,57 +0,0 @@
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 { projectAssessmentFields } from "./projectAssessmentFields.js";
8
- import { scanResultFastifyRuntime, scanResultPrettier, scanResultTypescriptPatch, } from "./fixtures/presentationPersonaFixtures.js";
9
- const SCAN_ID = "22222222-2222-4222-8222-222222222222";
10
- const ORIGIN = "https://app.example.com";
11
- describe("verification channel provenance parity", () => {
12
- for (const persona of [
13
- {
14
- name: "fastify runtime",
15
- result: scanResultFastifyRuntime,
16
- channel: "runtime",
17
- focusIncludes: "routes",
18
- },
19
- {
20
- name: "typescript patch",
21
- result: scanResultTypescriptPatch,
22
- channel: "artifact",
23
- focusIncludes: "typecheck",
24
- },
25
- {
26
- name: "prettier",
27
- result: scanResultPrettier,
28
- channel: "artifact",
29
- focusIncludes: "format",
30
- },
31
- ]) {
32
- it(`${persona.name}: verificationChannel and focus match across surfaces`, () => {
33
- const bundle = buildScanPresentationBundle({
34
- result: persona.result,
35
- pipelineStatus: "done",
36
- });
37
- const fields = projectAssessmentFields(bundle);
38
- const card = presentDashboardCard(bundle);
39
- const details = presentScanDetails(bundle, { scanId: SCAN_ID });
40
- const check = presentGitHubCheckRun(bundle, {
41
- scanId: SCAN_ID,
42
- webAppOrigin: ORIGIN,
43
- });
44
- const comment = presentGitHubPrComment(bundle);
45
- expect(fields.verificationChannel).toBe(persona.channel);
46
- expect(card.verificationChannel).toBe(persona.channel);
47
- expect(details.verificationChannel).toBe(persona.channel);
48
- expect(check.verificationChannel).toBe(persona.channel);
49
- expect(comment.verificationChannel).toBe(persona.channel);
50
- expect(fields.verificationFocus).toEqual(card.verificationFocus);
51
- expect(details.verificationFocus).toEqual(fields.verificationFocus);
52
- expect(check.verificationFocus).toEqual(fields.verificationFocus);
53
- expect(comment.verificationFocus).toEqual(fields.verificationFocus);
54
- expect(fields.verificationFocus.some((f) => f.toLowerCase().includes(persona.focusIncludes.toLowerCase()))).toBe(true);
55
- });
56
- }
57
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=productMessaging.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"productMessaging.test.d.ts","sourceRoot":"","sources":["../src/productMessaging.test.ts"],"names":[],"mappings":""}
@@ -1,97 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { homepageSectionRowBodies, primaryPrExample, productMessaging, } from "./productMessaging.js";
3
- const LOCKED_H1 = "See what a dependency upgrade can break.";
4
- const FORBIDDEN_MARKETING_TERMS = [
5
- "runtime-aware",
6
- "AI-powered",
7
- "framework-aware",
8
- "observability",
9
- "exhaustive indexing",
10
- "repo analytics",
11
- "risk platform",
12
- "risk intelligence platform",
13
- "security analysis platform",
14
- "scanner platform",
15
- ];
16
- describe("productMessaging", () => {
17
- it("locks hero H1 exactly including trailing period", () => {
18
- expect(productMessaging.hero.h1).toBe(LOCKED_H1);
19
- expect(productMessaging.hero.h1.endsWith(".")).toBe(true);
20
- });
21
- it("keeps lead separate from H1", () => {
22
- expect(productMessaging.hero.lead).not.toBe(productMessaging.hero.h1);
23
- });
24
- it("uses express middleware example for marketing card", () => {
25
- expect(primaryPrExample.package).toBe("express");
26
- expect(primaryPrExample.message).toContain("middleware ordering");
27
- expect(primaryPrExample.where).toHaveLength(2);
28
- });
29
- it("uses engineering-native example domains", () => {
30
- const text = [primaryPrExample.message, ...primaryPrExample.where].join(" ");
31
- expect(text.toLowerCase()).toMatch(/auth|middleware|routes/);
32
- });
33
- it("keeps section row bodies under 20 words", () => {
34
- for (const body of homepageSectionRowBodies()) {
35
- const wordCount = body.trim().split(/\s+/).length;
36
- expect(wordCount).toBeLessThanOrEqual(20);
37
- }
38
- });
39
- it("avoids em dashes in marketing copy", () => {
40
- const strings = collectMarketingStrings();
41
- for (const s of strings) {
42
- expect(s).not.toMatch(/[\u2013\u2014]/);
43
- }
44
- });
45
- it("avoids forbidden marketing terms in hero and seo", () => {
46
- const heroSeo = [
47
- productMessaging.hero.kicker,
48
- productMessaging.hero.h1,
49
- productMessaging.hero.lead,
50
- productMessaging.seo.title,
51
- productMessaging.seo.description,
52
- productMessaging.formalDefinition,
53
- ].join(" ");
54
- for (const term of FORBIDDEN_MARKETING_TERMS) {
55
- expect(heroSeo.toLowerCase()).not.toContain(term.toLowerCase());
56
- }
57
- });
58
- it("does not expose comparison hooks in hero exports", () => {
59
- expect(productMessaging.hero.kicker).not.toContain("Dependabot");
60
- expect(productMessaging.hero.h1).not.toContain("Dependabot");
61
- expect(productMessaging.hero.lead).not.toContain("Dependabot");
62
- });
63
- it("describes dashboard posture and PR Risk bands without scoring jargon", () => {
64
- const d = productMessaging.dashboardPrCard;
65
- const text = [
66
- d.intro,
67
- d.posture,
68
- d.exposure,
69
- d.prRiskBandsLead,
70
- ...d.prRiskBands,
71
- d.cardBody,
72
- ].join(" ");
73
- expect(text).toContain("merge recommendation");
74
- expect(text).toContain("affected application paths");
75
- expect(text).not.toMatch(/total score|0-100|formula|weight/i);
76
- expect(d.prRiskBands).toHaveLength(5);
77
- expect(d.prRiskBands).toContain("Medium");
78
- });
79
- });
80
- function collectMarketingStrings() {
81
- const out = [
82
- productMessaging.formalDefinition,
83
- productMessaging.hero.kicker,
84
- productMessaging.hero.h1,
85
- productMessaging.hero.lead,
86
- productMessaging.seo.title,
87
- productMessaging.seo.description,
88
- primaryPrExample.message,
89
- ...primaryPrExample.where,
90
- ];
91
- for (const body of homepageSectionRowBodies()) {
92
- out.push(body);
93
- }
94
- const d = productMessaging.dashboardPrCard;
95
- out.push(d.intro, d.posture, d.exposure, d.prRiskBandsLead, d.cardBody, ...d.prRiskBands);
96
- return out;
97
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=repoIntelligenceSchema.contract.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"repoIntelligenceSchema.contract.test.d.ts","sourceRoot":"","sources":["../src/repoIntelligenceSchema.contract.test.ts"],"names":[],"mappings":""}
@@ -1,51 +0,0 @@
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
- it("accepts optional lifecycleStages and promotedAreas on package rows (ABI 3)", () => {
20
- const wire = {
21
- packages: {
22
- "acme-runtime-http-lib": {
23
- runtimeSurface: "runtime",
24
- reachability: "on_runtime_paths",
25
- usage: {
26
- packageName: "acme-runtime-http-lib",
27
- files: ["apps/api/handlers/entry.ts"],
28
- areas: [],
29
- },
30
- lifecycleStages: [
31
- {
32
- stage: "route_registration",
33
- fileCount: 1,
34
- evidenceRefs: ["import_path:apps/api/handlers/entry.ts"],
35
- },
36
- ],
37
- promotedAreas: [
38
- {
39
- area: "api",
40
- structuralAnchor: "http_surface",
41
- evidenceRefs: ["import_path:apps/api/handlers/entry.ts"],
42
- },
43
- ],
44
- },
45
- },
46
- };
47
- const validated = validateRepoIntelligenceWire(wire);
48
- expect(validated.packages["acme-runtime-http-lib"]?.lifecycleStages?.length).toBe(1);
49
- expect(validated.packages["acme-runtime-http-lib"]?.promotedAreas?.length).toBe(1);
50
- });
51
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=repoIntelligenceSemantics.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"repoIntelligenceSemantics.test.d.ts","sourceRoot":"","sources":["../src/repoIntelligenceSemantics.test.ts"],"names":[],"mappings":""}
@@ -1,63 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { isRuntimeNarrativeSafe, sanitizeRepoIntelligenceSemantics, } from "./repoIntelligenceSemantics.js";
3
- function basePkg(overrides = {}) {
4
- return {
5
- runtimeSurface: "runtime",
6
- reachability: "unreachable",
7
- usage: { packageName: "typescript", files: [] },
8
- ...overrides,
9
- };
10
- }
11
- describe("sanitizeRepoIntelligenceSemantics", () => {
12
- it("S1: neutralizes runtime + unreachable", () => {
13
- const draft = {
14
- packages: {
15
- typescript: basePkg({
16
- runtimeImpact: "unknown",
17
- }),
18
- },
19
- };
20
- const { wire, diagnostics } = sanitizeRepoIntelligenceSemantics(draft);
21
- expect(wire.packages.typescript?.runtimeSurface).not.toBe("runtime");
22
- expect(wire.packages.typescript?.reachability).not.toBe("unreachable");
23
- expect(wire.packages.typescript?.suppressRuntimeNarrative).toBe(true);
24
- expect(diagnostics.some((d) => d.ruleId === "S1")).toBe(true);
25
- });
26
- it("S3: tooling class cannot stay confirmed", () => {
27
- const draft = {
28
- packages: {
29
- typescript: basePkg({
30
- dependencyClass: "tooling",
31
- runtimeImpact: "confirmed",
32
- runtimeSurface: "build",
33
- reachability: "build_only",
34
- }),
35
- },
36
- };
37
- const { wire } = sanitizeRepoIntelligenceSemantics(draft);
38
- expect(wire.packages.typescript?.runtimeImpact).toBe("none");
39
- });
40
- it("S4: confirmed without imports downgrades", () => {
41
- const draft = {
42
- packages: {
43
- fastify: basePkg({
44
- runtimeImpact: "confirmed",
45
- usage: { packageName: "fastify", files: [] },
46
- }),
47
- },
48
- };
49
- const { wire } = sanitizeRepoIntelligenceSemantics(draft);
50
- expect(wire.packages.fastify?.runtimeImpact).toBe("none");
51
- });
52
- });
53
- describe("isRuntimeNarrativeSafe", () => {
54
- it("returns false for suppressed runtime narrative", () => {
55
- expect(isRuntimeNarrativeSafe({
56
- runtimeSurface: "runtime",
57
- reachability: "on_runtime_paths",
58
- usage: { packageName: "x", files: ["src/a.ts"] },
59
- suppressRuntimeNarrative: true,
60
- runtimeImpact: "none",
61
- })).toBe(false);
62
- });
63
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=repoIntelligenceValidation.persist.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"repoIntelligenceValidation.persist.test.d.ts","sourceRoot":"","sources":["../src/repoIntelligenceValidation.persist.test.ts"],"names":[],"mappings":""}