@mergesignal/shared 0.12.3 → 0.14.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 (178) 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/assessmentLabels.js +2 -2
  22. package/dist/assessmentPresentationUtils.d.ts +1 -1
  23. package/dist/assessmentPresentationUtils.d.ts.map +1 -1
  24. package/dist/assessmentProjection.d.ts +1 -1
  25. package/dist/assessmentProjection.d.ts.map +1 -1
  26. package/dist/assessmentProjection.js +2 -2
  27. package/dist/deriveScanNarrative.d.ts.map +1 -1
  28. package/dist/deriveScanNarrative.js +2 -1
  29. package/dist/fixtures/assessmentFixtures.d.ts +1 -1
  30. package/dist/fixtures/assessmentFixtures.js +12 -12
  31. package/dist/fixtures/assessmentScopeFixtures.d.ts +1 -1
  32. package/dist/index.d.ts +2 -0
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +2 -0
  35. package/dist/lockfileEvidence.d.ts +22 -0
  36. package/dist/lockfileEvidence.d.ts.map +1 -0
  37. package/dist/lockfileEvidence.js +32 -0
  38. package/dist/presentation/dto/assessmentPresentationFields.d.ts +1 -1
  39. package/dist/presentation/dto/assessmentPresentationFields.d.ts.map +1 -1
  40. package/dist/presentation/orchestration/buildScanPresentationBundle.d.ts.map +1 -1
  41. package/dist/presentation/orchestration/buildScanPresentationBundle.js +2 -1
  42. package/dist/presentation/orchestration/scanPresentationBundle.d.ts +2 -1
  43. package/dist/presentation/orchestration/scanPresentationBundle.d.ts.map +1 -1
  44. package/dist/presentation/profile/buildProfileFromAssessment.d.ts +1 -1
  45. package/dist/presentation/profile/buildProfileFromAssessment.d.ts.map +1 -1
  46. package/dist/presentation/profile/buildProfileFromAssessment.js +14 -6
  47. package/dist/repoIntelligenceSchema.d.ts +5 -5
  48. package/dist/scanResultSchema.d.ts +8 -8
  49. package/dist/scanResultSchema.js +1 -1
  50. package/dist/scanSurfaceCopy.d.ts +1 -0
  51. package/dist/scanSurfaceCopy.d.ts.map +1 -1
  52. package/dist/scanSurfaceCopy.js +1 -0
  53. package/dist/types.d.ts +6 -2
  54. package/dist/types.d.ts.map +1 -1
  55. package/package.json +2 -3
  56. package/dist/actionsStepSummary.test.d.ts +0 -2
  57. package/dist/actionsStepSummary.test.d.ts.map +0 -1
  58. package/dist/actionsStepSummary.test.js +0 -53
  59. package/dist/assessmentProjection.verificationChannel.test.d.ts +0 -2
  60. package/dist/assessmentProjection.verificationChannel.test.d.ts.map +0 -1
  61. package/dist/assessmentProjection.verificationChannel.test.js +0 -110
  62. package/dist/deriveScanNarrative.test.d.ts +0 -2
  63. package/dist/deriveScanNarrative.test.d.ts.map +0 -1
  64. package/dist/deriveScanNarrative.test.js +0 -274
  65. package/dist/engineWireRegression.test.d.ts +0 -2
  66. package/dist/engineWireRegression.test.d.ts.map +0 -1
  67. package/dist/engineWireRegression.test.js +0 -77
  68. package/dist/fixtures/engineAbi4Fixtures.d.ts +0 -16
  69. package/dist/fixtures/engineAbi4Fixtures.d.ts.map +0 -1
  70. package/dist/fixtures/engineAbi4Fixtures.js +0 -26
  71. package/dist/fixtures/legacyEngineRepoIntelligence.d.ts +0 -28
  72. package/dist/fixtures/legacyEngineRepoIntelligence.d.ts.map +0 -1
  73. package/dist/fixtures/legacyEngineRepoIntelligence.js +0 -28
  74. package/dist/fixtures/repoIntelligenceFixtures.d.ts +0 -8
  75. package/dist/fixtures/repoIntelligenceFixtures.d.ts.map +0 -1
  76. package/dist/fixtures/repoIntelligenceFixtures.js +0 -123
  77. package/dist/fixtures/repoIntelligenceTestHelpers.d.ts +0 -5
  78. package/dist/fixtures/repoIntelligenceTestHelpers.d.ts.map +0 -1
  79. package/dist/fixtures/repoIntelligenceTestHelpers.js +0 -28
  80. package/dist/formatInsight.test.d.ts +0 -2
  81. package/dist/formatInsight.test.d.ts.map +0 -1
  82. package/dist/formatInsight.test.js +0 -102
  83. package/dist/narrativeParity.test.d.ts +0 -2
  84. package/dist/narrativeParity.test.d.ts.map +0 -1
  85. package/dist/narrativeParity.test.js +0 -35
  86. package/dist/narrativePresentation.test.d.ts +0 -2
  87. package/dist/narrativePresentation.test.d.ts.map +0 -1
  88. package/dist/narrativePresentation.test.js +0 -54
  89. package/dist/normalizeGeneratedText.test.d.ts +0 -2
  90. package/dist/normalizeGeneratedText.test.d.ts.map +0 -1
  91. package/dist/normalizeGeneratedText.test.js +0 -18
  92. package/dist/prRiskBand.test.d.ts +0 -2
  93. package/dist/prRiskBand.test.d.ts.map +0 -1
  94. package/dist/prRiskBand.test.js +0 -68
  95. package/dist/prRiskWire.test.d.ts +0 -2
  96. package/dist/prRiskWire.test.d.ts.map +0 -1
  97. package/dist/prRiskWire.test.js +0 -106
  98. package/dist/prRiskWiringRegression.test.d.ts +0 -2
  99. package/dist/prRiskWiringRegression.test.d.ts.map +0 -1
  100. package/dist/prRiskWiringRegression.test.js +0 -102
  101. package/dist/presentation/abi3Expression.test.d.ts +0 -13
  102. package/dist/presentation/abi3Expression.test.d.ts.map +0 -1
  103. package/dist/presentation/abi3Expression.test.js +0 -392
  104. package/dist/presentation/buildGitHubCheckRunOutput.test.d.ts +0 -2
  105. package/dist/presentation/buildGitHubCheckRunOutput.test.d.ts.map +0 -1
  106. package/dist/presentation/buildGitHubCheckRunOutput.test.js +0 -163
  107. package/dist/presentation/bundleAccessorParity.test.d.ts +0 -9
  108. package/dist/presentation/bundleAccessorParity.test.d.ts.map +0 -1
  109. package/dist/presentation/bundleAccessorParity.test.js +0 -126
  110. package/dist/presentation/cliParity.test.d.ts +0 -2
  111. package/dist/presentation/cliParity.test.d.ts.map +0 -1
  112. package/dist/presentation/cliParity.test.js +0 -49
  113. package/dist/presentation/compose/narrativeChannels.test.d.ts +0 -2
  114. package/dist/presentation/compose/narrativeChannels.test.d.ts.map +0 -1
  115. package/dist/presentation/compose/narrativeChannels.test.js +0 -42
  116. package/dist/presentation/decisionSurface.test.d.ts +0 -2
  117. package/dist/presentation/decisionSurface.test.d.ts.map +0 -1
  118. package/dist/presentation/decisionSurface.test.js +0 -290
  119. package/dist/presentation/fixtures/dashboardCardGolden.test.d.ts +0 -2
  120. package/dist/presentation/fixtures/dashboardCardGolden.test.d.ts.map +0 -1
  121. package/dist/presentation/fixtures/dashboardCardGolden.test.js +0 -38
  122. package/dist/presentation/fixtures/presentationPersonaFixtures.d.ts +0 -11
  123. package/dist/presentation/fixtures/presentationPersonaFixtures.d.ts.map +0 -1
  124. package/dist/presentation/fixtures/presentationPersonaFixtures.js +0 -208
  125. package/dist/presentation/fixtures/scanResultFixtures.d.ts +0 -5
  126. package/dist/presentation/fixtures/scanResultFixtures.d.ts.map +0 -1
  127. package/dist/presentation/fixtures/scanResultFixtures.js +0 -123
  128. package/dist/presentation/intent/postureVocabularyGuard.test.d.ts +0 -2
  129. package/dist/presentation/intent/postureVocabularyGuard.test.d.ts.map +0 -1
  130. package/dist/presentation/intent/postureVocabularyGuard.test.js +0 -23
  131. package/dist/presentation/orchestration/buildScanPresentationBundle.test.d.ts +0 -2
  132. package/dist/presentation/orchestration/buildScanPresentationBundle.test.d.ts.map +0 -1
  133. package/dist/presentation/orchestration/buildScanPresentationBundle.test.js +0 -99
  134. package/dist/presentation/presentation.test.d.ts +0 -2
  135. package/dist/presentation/presentation.test.d.ts.map +0 -1
  136. package/dist/presentation/presentation.test.js +0 -126
  137. package/dist/presentation/presentationPersonas.test.d.ts +0 -2
  138. package/dist/presentation/presentationPersonas.test.d.ts.map +0 -1
  139. package/dist/presentation/presentationPersonas.test.js +0 -164
  140. package/dist/presentation/surfaceParity.test.d.ts +0 -2
  141. package/dist/presentation/surfaceParity.test.d.ts.map +0 -1
  142. package/dist/presentation/surfaceParity.test.js +0 -156
  143. package/dist/presentation/verificationChannelParity.test.d.ts +0 -2
  144. package/dist/presentation/verificationChannelParity.test.d.ts.map +0 -1
  145. package/dist/presentation/verificationChannelParity.test.js +0 -57
  146. package/dist/productMessaging.test.d.ts +0 -2
  147. package/dist/productMessaging.test.d.ts.map +0 -1
  148. package/dist/productMessaging.test.js +0 -97
  149. package/dist/repoIntelligenceSchema.contract.test.d.ts +0 -2
  150. package/dist/repoIntelligenceSchema.contract.test.d.ts.map +0 -1
  151. package/dist/repoIntelligenceSchema.contract.test.js +0 -51
  152. package/dist/repoIntelligenceSemantics.test.d.ts +0 -2
  153. package/dist/repoIntelligenceSemantics.test.d.ts.map +0 -1
  154. package/dist/repoIntelligenceSemantics.test.js +0 -63
  155. package/dist/repoIntelligenceValidation.persist.test.d.ts +0 -2
  156. package/dist/repoIntelligenceValidation.persist.test.d.ts.map +0 -1
  157. package/dist/repoIntelligenceValidation.persist.test.js +0 -44
  158. package/dist/riskSignals.test.d.ts +0 -2
  159. package/dist/riskSignals.test.d.ts.map +0 -1
  160. package/dist/riskSignals.test.js +0 -32
  161. package/dist/riskVocabulary.test.d.ts +0 -2
  162. package/dist/riskVocabulary.test.d.ts.map +0 -1
  163. package/dist/riskVocabulary.test.js +0 -14
  164. package/dist/scanPresentationBundle.golden.test.d.ts +0 -2
  165. package/dist/scanPresentationBundle.golden.test.d.ts.map +0 -1
  166. package/dist/scanPresentationBundle.golden.test.js +0 -78
  167. package/dist/scanResultSchema.test.d.ts +0 -2
  168. package/dist/scanResultSchema.test.d.ts.map +0 -1
  169. package/dist/scanResultSchema.test.js +0 -162
  170. package/dist/scanSurfaceCopy.test.d.ts +0 -2
  171. package/dist/scanSurfaceCopy.test.d.ts.map +0 -1
  172. package/dist/scanSurfaceCopy.test.js +0 -14
  173. package/dist/selectTopAffectedAreas.test.d.ts +0 -2
  174. package/dist/selectTopAffectedAreas.test.d.ts.map +0 -1
  175. package/dist/selectTopAffectedAreas.test.js +0 -179
  176. package/dist/trustedScanGuards.test.d.ts +0 -2
  177. package/dist/trustedScanGuards.test.d.ts.map +0 -1
  178. 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":""}