@mergesignal/shared 0.10.0 → 0.12.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.
@@ -1 +1 @@
1
- {"version":3,"file":"assessmentProjection.d.ts","sourceRoot":"","sources":["../src/assessmentProjection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EACV,UAAU,EACV,4BAA4B,EAC5B,eAAe,EACf,qBAAqB,EACtB,MAAM,wBAAwB,CAAC;AAOhC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AAmDlE,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,qBAAqB,GAC/B,mBAAmB,CAIrB;AAED,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EAAE,CAQ5E;AAED,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EAAE,CAS7E;AAED,wBAAgB,uCAAuC,CACrD,YAAY,EAAE,4BAA4B,EAC1C,MAAM,EAAE,UAAU,GACjB;IAAE,OAAO,EAAE,mBAAmB,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAWnD;AAED,8FAA8F;AAC9F,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EAAE,CAErE;AAED,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,eAAe,GAC1B,MAAM,GAAG,SAAS,CAWpB;AAED,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,kBAAkB,GACzB,MAAM,CAiDR;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EAAE,CAIlE;AAED,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,UAAU,GACjB,MAAM,EAAE,CAaV;AAED,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,4BAA4B,EAC1C,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,MAAM,GACV,MAAM,EAAE,CAOV;AAED,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,gBAAgB,GAAG,IAAI,GAAG,MAAM,EAAE,CAI3E"}
1
+ {"version":3,"file":"assessmentProjection.d.ts","sourceRoot":"","sources":["../src/assessmentProjection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EACV,UAAU,EACV,4BAA4B,EAC5B,eAAe,EACf,qBAAqB,EACtB,MAAM,wBAAwB,CAAC;AAOhC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AAmDlE,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,qBAAqB,GAC/B,mBAAmB,CAIrB;AAED,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EAAE,CAQ5E;AAED,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EAAE,CAS7E;AAED,wBAAgB,uCAAuC,CACrD,YAAY,EAAE,4BAA4B,EAC1C,MAAM,EAAE,UAAU,GACjB;IAAE,OAAO,EAAE,mBAAmB,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAWnD;AAED,8FAA8F;AAC9F,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EAAE,CAErE;AAED,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,eAAe,GAC1B,MAAM,GAAG,SAAS,CAWpB;AAED,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,kBAAkB,GACzB,MAAM,CAiDR;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EAAE,CAMlE;AAED,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,UAAU,GACjB,MAAM,EAAE,CAaV;AAED,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,4BAA4B,EAC1C,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,MAAM,GACV,MAAM,EAAE,CAWV;AAED,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,gBAAgB,GAAG,IAAI,GAAG,MAAM,EAAE,CAI3E"}
@@ -126,10 +126,12 @@ export function formatAssessmentHeadline(assessment, status) {
126
126
  return applyPostureVocabularyGuardHeadline(copy.defaultUpgradeHeadline.replace("{package}", primaryPkg), status, primaryPkg);
127
127
  }
128
128
  export function projectReasoningLines(result) {
129
- const fromDecision = result.decision?.reasoning?.filter(Boolean) ?? [];
130
- if (fromDecision.length > 0)
131
- return fromDecision.slice(0, 3);
132
- return [];
129
+ // ABI 3: assessment.reasoning is the authoritative source for repository-specific prose
130
+ const fromAssessment = result.assessment?.reasoning?.filter(Boolean) ?? [];
131
+ if (fromAssessment.length > 0)
132
+ return fromAssessment;
133
+ // Fallback for pre-ABI-3 scan results still in the database
134
+ return result.decision?.reasoning?.filter(Boolean) ?? [];
133
135
  }
134
136
  export function projectInsightLines(assessment, result) {
135
137
  const reasoning = projectReasoningLines(result);
@@ -149,6 +151,11 @@ export function projectInsightLines(assessment, result) {
149
151
  export function projectVerificationActions(assessment, presentation, result, max) {
150
152
  if (presentation.verificationIntensity === "none")
151
153
  return [];
154
+ // ABI 3: use actionable prose guidance when present
155
+ const guidance = assessment.verificationScope?.guidance;
156
+ if (guidance && guidance.length > 0)
157
+ return guidance.slice(0, max);
158
+ // Fallback: focus tokens from legacy scope or repoIntelligence
152
159
  const { focus } = collectVerificationFocusForPresentation(presentation, result);
153
160
  return focus.slice(0, max);
154
161
  }
@@ -10,8 +10,11 @@ export declare function emptyArtifactGrounded(): ArtifactGroundedVerificationSco
10
10
  export declare function artifactGroundedScopeFor(packages: string[], focus?: string[], artifactPaths?: string[]): ArtifactGroundedVerificationScope;
11
11
  export declare function emptyVerificationScope(): VerificationScope;
12
12
  export declare function verificationScopeFor(packages: string[], focus?: string[], artifactGrounded?: ArtifactGroundedVerificationScope): VerificationScope;
13
- /** Attach focal/scope fields required by assessmentSchema ABI 2. */
14
- export declare function withAssessmentScope(assessment: Omit<Assessment, "reviewFocalPoint" | "reachScope" | "verificationScope">, scope: {
13
+ /** Attach focal/scope fields required by assessmentSchema ABI 3. */
14
+ export declare function withAssessmentScope(assessment: Omit<Assessment, "reviewFocalPoint" | "reachScope" | "verificationScope" | "reasoning" | "confidenceRationale"> & {
15
+ reasoning?: string[];
16
+ confidenceRationale?: string;
17
+ }, scope: {
15
18
  reviewFocalPoint: ReviewFocalPoint;
16
19
  reachScope?: ReachScope;
17
20
  verificationScope?: VerificationScope;
@@ -1 +1 @@
1
- {"version":3,"file":"assessmentScopeFixtures.d.ts","sourceRoot":"","sources":["../../src/fixtures/assessmentScopeFixtures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iCAAiC,EACjC,UAAU,EACV,sBAAsB,EACtB,UAAU,EACV,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,wBAAwB,CAAC;AAEhC,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,CAAC,EAAE;IACL,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,sBAAsB,CAAC;CACpC,GACA,gBAAgB,CAoBlB;AAED,wBAAgB,eAAe,IAAI,UAAU,CAE5C;AAED,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAAE,EAClB,SAAS,GAAE,UAAU,CAAC,WAAW,CAAc,GAC9C,UAAU,CAEZ;AAED,wBAAgB,qBAAqB,IAAI,iCAAiC,CAEzE;AAED,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAAE,EAClB,KAAK,GAAE,MAAM,EAAO,EACpB,aAAa,GAAE,MAAM,EAAO,GAC3B,iCAAiC,CAEnC;AAED,wBAAgB,sBAAsB,IAAI,iBAAiB,CAM1D;AAED,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAAE,EAClB,KAAK,GAAE,MAAM,EAAO,EACpB,gBAAgB,GAAE,iCAA2D,GAC5E,iBAAiB,CAEnB;AAED,oEAAoE;AACpE,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,IAAI,CACd,UAAU,EACV,kBAAkB,GAAG,YAAY,GAAG,mBAAmB,CACxD,EACD,KAAK,EAAE;IACL,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC,GACA,UAAU,CAOZ"}
1
+ {"version":3,"file":"assessmentScopeFixtures.d.ts","sourceRoot":"","sources":["../../src/fixtures/assessmentScopeFixtures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iCAAiC,EACjC,UAAU,EACV,sBAAsB,EACtB,UAAU,EACV,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,wBAAwB,CAAC;AAEhC,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,CAAC,EAAE;IACL,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,sBAAsB,CAAC;CACpC,GACA,gBAAgB,CAoBlB;AAED,wBAAgB,eAAe,IAAI,UAAU,CAE5C;AAED,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAAE,EAClB,SAAS,GAAE,UAAU,CAAC,WAAW,CAAc,GAC9C,UAAU,CAEZ;AAED,wBAAgB,qBAAqB,IAAI,iCAAiC,CAEzE;AAED,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAAE,EAClB,KAAK,GAAE,MAAM,EAAO,EACpB,aAAa,GAAE,MAAM,EAAO,GAC3B,iCAAiC,CAEnC;AAED,wBAAgB,sBAAsB,IAAI,iBAAiB,CAM1D;AAED,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAAE,EAClB,KAAK,GAAE,MAAM,EAAO,EACpB,gBAAgB,GAAE,iCAA2D,GAC5E,iBAAiB,CAEnB;AAED,oEAAoE;AACpE,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,IAAI,CACd,UAAU,EACR,kBAAkB,GAClB,YAAY,GACZ,mBAAmB,GACnB,WAAW,GACX,qBAAqB,CACxB,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAAE,EAC1D,KAAK,EAAE;IACL,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC,GACA,UAAU,CASZ"}
@@ -41,9 +41,11 @@ export function emptyVerificationScope() {
41
41
  export function verificationScopeFor(packages, focus = [], artifactGrounded = emptyArtifactGrounded()) {
42
42
  return { packages, focus, artifactGrounded };
43
43
  }
44
- /** Attach focal/scope fields required by assessmentSchema ABI 2. */
44
+ /** Attach focal/scope fields required by assessmentSchema ABI 3. */
45
45
  export function withAssessmentScope(assessment, scope) {
46
46
  return {
47
+ reasoning: [],
48
+ confidenceRationale: "",
47
49
  ...assessment,
48
50
  reviewFocalPoint: scope.reviewFocalPoint,
49
51
  reachScope: scope.reachScope ?? emptyReachScope(),
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Wave 2.D — ABI 3 expression validation.
3
+ *
4
+ * Validates that:
5
+ * 1. projectReasoningLines reads from assessment.reasoning (ABI 3) when present
6
+ * 2. projectVerificationActions returns assessment.verificationScope.guidance when present
7
+ * 3. PR comment includes reviewFocalPoint.electionSummary when present
8
+ * 4. Check run "Why" section uses assessment.reasoning lines directly
9
+ * 5. No prohibited vocabulary appears in rendered surfaces
10
+ * 6. assessment.reasoning takes priority over decision.reasoning
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=abi3Expression.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abi3Expression.test.d.ts","sourceRoot":"","sources":["../../src/presentation/abi3Expression.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
@@ -0,0 +1,346 @@
1
+ /**
2
+ * Wave 2.D — ABI 3 expression validation.
3
+ *
4
+ * Validates that:
5
+ * 1. projectReasoningLines reads from assessment.reasoning (ABI 3) when present
6
+ * 2. projectVerificationActions returns assessment.verificationScope.guidance when present
7
+ * 3. PR comment includes reviewFocalPoint.electionSummary when present
8
+ * 4. Check run "Why" section uses assessment.reasoning lines directly
9
+ * 5. No prohibited vocabulary appears in rendered surfaces
10
+ * 6. assessment.reasoning takes priority over decision.reasoning
11
+ */
12
+ import { describe, expect, it } from "vitest";
13
+ import { minimalReviewFocalPoint, reachScopeFor, verificationScopeFor, withAssessmentScope, } from "../fixtures/assessmentScopeFixtures.js";
14
+ import { projectReasoningLines, projectVerificationActions, } from "../assessmentProjection.js";
15
+ import { toPublicPresentation } from "../assessmentPresentationUtils.js";
16
+ import { buildScanPresentationBundle } from "./orchestration/buildScanPresentationBundle.js";
17
+ import { presentGitHubPrComment } from "./presenters/presentGitHubPrComment.js";
18
+ import { presentGitHubCheckRun } from "./presenters/presentGitHubCheckRun.js";
19
+ import { buildGitHubCheckRunOutput } from "./buildGitHubCheckRunOutput.js";
20
+ import { presentGitHubPrCommentMarkdownFromResult } from "../presentGitHubPrComment.js";
21
+ // ---------------------------------------------------------------------------
22
+ // ABI 3 — Canonical express/confirmed_runtime_usage fixture
23
+ // ---------------------------------------------------------------------------
24
+ const expressReasoning = [
25
+ "express is used in HTTP request handling in this repository via middleware chains.",
26
+ "Import paths to application entry points were directly observed.",
27
+ "Verification is required: review HTTP route definitions and middleware implementation.",
28
+ ];
29
+ const expressGuidance = [
30
+ "Review HTTP route definitions and middleware implementation in src/app.ts and src/server.ts.",
31
+ "Review handler implementations that use express routing.",
32
+ ];
33
+ const expressElectionSummary = "express was selected as the primary review anchor because it has the highest repository reach among changed packages and confirmed runtime usage in HTTP request handling.";
34
+ const assessmentExpressAbi3 = withAssessmentScope({
35
+ posture: "needs_review",
36
+ confidence: "high",
37
+ primaryConcern: "confirmed_runtime_usage",
38
+ concerns: [
39
+ {
40
+ kind: "confirmed_runtime_usage",
41
+ rank: 1,
42
+ packages: ["express"],
43
+ evidenceRefs: ["fixture:express"],
44
+ context: "express participates in HTTP request handling across 12 files.",
45
+ },
46
+ ],
47
+ factors: ["confirmed_runtime_usage", "http_framework_infrastructure"],
48
+ changeClasses: ["runtime_upgrade"],
49
+ presentation: {
50
+ narrativeIntensity: "elevated",
51
+ reachVisibility: "prominent",
52
+ verificationIntensity: "required",
53
+ insightEmissionFloor: "full",
54
+ reportMode: "high_signal_pr",
55
+ },
56
+ reasoning: expressReasoning,
57
+ confidenceRationale: "Confidence is high: propagation from express to application entry points was directly observed.",
58
+ }, {
59
+ reviewFocalPoint: {
60
+ ...minimalReviewFocalPoint(["express"]),
61
+ electionSummary: expressElectionSummary,
62
+ },
63
+ reachScope: reachScopeFor(["express"], "high"),
64
+ verificationScope: verificationScopeFor(["express"], ["routes", "middleware"], undefined),
65
+ });
66
+ const assessmentExpressAbi3WithGuidance = {
67
+ ...assessmentExpressAbi3,
68
+ verificationScope: {
69
+ ...assessmentExpressAbi3.verificationScope,
70
+ guidance: expressGuidance,
71
+ },
72
+ };
73
+ function scanResultWithAssessment(assessment, overrides = {}) {
74
+ return {
75
+ totalScore: 63,
76
+ layerScores: {
77
+ security: 10,
78
+ maintainability: 20,
79
+ ecosystem: 30,
80
+ upgradeImpact: 15,
81
+ },
82
+ findings: [],
83
+ generatedAt: "2026-01-01T00:00:00.000Z",
84
+ changedPackages: ["express"],
85
+ assessment,
86
+ decision: {
87
+ recommendation: "needs_review",
88
+ confidence: "high",
89
+ reasoning: ["Old generic decision reasoning — should not appear."],
90
+ },
91
+ ...overrides,
92
+ };
93
+ }
94
+ // ---------------------------------------------------------------------------
95
+ // projectReasoningLines — ABI 3 priority
96
+ // ---------------------------------------------------------------------------
97
+ describe("projectReasoningLines — ABI 3", () => {
98
+ it("returns assessment.reasoning when present (ABI 3 takes priority)", () => {
99
+ const result = scanResultWithAssessment(assessmentExpressAbi3);
100
+ const lines = projectReasoningLines(result);
101
+ expect(lines).toEqual(expressReasoning);
102
+ });
103
+ it("assessment.reasoning takes priority over decision.reasoning", () => {
104
+ const result = scanResultWithAssessment(assessmentExpressAbi3);
105
+ const lines = projectReasoningLines(result);
106
+ expect(lines).not.toContain("Old generic decision reasoning — should not appear.");
107
+ });
108
+ it("falls back to decision.reasoning when assessment.reasoning is empty", () => {
109
+ const assessmentWithoutReasoning = {
110
+ ...assessmentExpressAbi3,
111
+ reasoning: [],
112
+ };
113
+ const result = scanResultWithAssessment(assessmentWithoutReasoning);
114
+ const lines = projectReasoningLines(result);
115
+ expect(lines).toEqual([
116
+ "Old generic decision reasoning — should not appear.",
117
+ ]);
118
+ });
119
+ it("returns empty array when both reasoning sources are absent", () => {
120
+ const assessmentEmpty = {
121
+ ...assessmentExpressAbi3,
122
+ reasoning: [],
123
+ };
124
+ const result = scanResultWithAssessment(assessmentEmpty, {
125
+ decision: {
126
+ recommendation: "needs_review",
127
+ confidence: "high",
128
+ reasoning: [],
129
+ },
130
+ });
131
+ const lines = projectReasoningLines(result);
132
+ expect(lines).toEqual([]);
133
+ });
134
+ it("reasoning lines contain no prohibited vocabulary", () => {
135
+ const result = scanResultWithAssessment(assessmentExpressAbi3);
136
+ const lines = projectReasoningLines(result);
137
+ const joined = lines.join(" ");
138
+ const prohibited = [
139
+ "qualityClass",
140
+ "qualityBasis",
141
+ "proofFingerprint",
142
+ "observationId",
143
+ "propagationQualityRank",
144
+ "AssessmentEvidenceBundle",
145
+ "DenseEvidenceHighlight",
146
+ "will affect",
147
+ "will break",
148
+ "breaks compatibility",
149
+ "remain compatible",
150
+ "critical path",
151
+ ];
152
+ for (const term of prohibited) {
153
+ expect(joined).not.toContain(term);
154
+ }
155
+ });
156
+ });
157
+ // ---------------------------------------------------------------------------
158
+ // projectVerificationActions — guidance priority
159
+ // ---------------------------------------------------------------------------
160
+ describe("projectVerificationActions — ABI 3 guidance", () => {
161
+ const presentation = toPublicPresentation(assessmentExpressAbi3WithGuidance.presentation);
162
+ it("returns guidance prose when verificationScope.guidance is present", () => {
163
+ const result = scanResultWithAssessment(assessmentExpressAbi3WithGuidance);
164
+ const actions = projectVerificationActions(assessmentExpressAbi3WithGuidance, presentation, result, 6);
165
+ expect(actions).toEqual(expressGuidance);
166
+ });
167
+ it("guidance respects max limit", () => {
168
+ const result = scanResultWithAssessment(assessmentExpressAbi3WithGuidance);
169
+ const actions = projectVerificationActions(assessmentExpressAbi3WithGuidance, presentation, result, 1);
170
+ expect(actions).toHaveLength(1);
171
+ expect(actions[0]).toBe(expressGuidance[0]);
172
+ });
173
+ it("falls back to focus tokens when guidance is absent", () => {
174
+ const result = scanResultWithAssessment(assessmentExpressAbi3);
175
+ const actions = projectVerificationActions(assessmentExpressAbi3, presentation, result, 6);
176
+ // No guidance — falls back to runtime focus tokens
177
+ expect(actions).toEqual(expect.arrayContaining(["routes", "middleware"]));
178
+ });
179
+ it("returns empty when verificationIntensity is none", () => {
180
+ const noneAssessment = {
181
+ ...assessmentExpressAbi3WithGuidance,
182
+ presentation: {
183
+ ...assessmentExpressAbi3WithGuidance.presentation,
184
+ verificationIntensity: "none",
185
+ },
186
+ };
187
+ const result = scanResultWithAssessment(noneAssessment);
188
+ const actions = projectVerificationActions(noneAssessment, toPublicPresentation(noneAssessment.presentation), result, 6);
189
+ expect(actions).toEqual([]);
190
+ });
191
+ });
192
+ // ---------------------------------------------------------------------------
193
+ // PR comment — electionSummary and reasoning
194
+ // ---------------------------------------------------------------------------
195
+ describe("presentGitHubPrComment — ABI 3 expression", () => {
196
+ function buildBundle(assessment) {
197
+ const result = scanResultWithAssessment(assessment, {
198
+ changedPackages: ["express"],
199
+ });
200
+ return buildScanPresentationBundle({ result, pipelineStatus: "done" });
201
+ }
202
+ it("introLines include electionSummary when present", () => {
203
+ const bundle = buildBundle(assessmentExpressAbi3);
204
+ const comment = presentGitHubPrComment(bundle);
205
+ expect(comment.introLines).toContain(expressElectionSummary);
206
+ });
207
+ it("introLines include assessment.reasoning sentences", () => {
208
+ const bundle = buildBundle(assessmentExpressAbi3);
209
+ const comment = presentGitHubPrComment(bundle);
210
+ const joined = comment.introLines.join(" ");
211
+ expect(joined).toContain("express is used in HTTP request handling");
212
+ expect(joined).toContain("Import paths to application entry points");
213
+ });
214
+ it("electionSummary is absent from introLines when not set", () => {
215
+ const assessmentNoElection = {
216
+ ...assessmentExpressAbi3,
217
+ reviewFocalPoint: {
218
+ ...assessmentExpressAbi3.reviewFocalPoint,
219
+ electionSummary: undefined,
220
+ },
221
+ };
222
+ const bundle = buildBundle(assessmentNoElection);
223
+ const comment = presentGitHubPrComment(bundle);
224
+ expect(comment.introLines).not.toContain(expressElectionSummary);
225
+ });
226
+ it("introLines contain no prohibited vocabulary", () => {
227
+ const bundle = buildBundle(assessmentExpressAbi3);
228
+ const comment = presentGitHubPrComment(bundle);
229
+ const joined = comment.introLines.join(" ");
230
+ const prohibited = [
231
+ "qualityClass",
232
+ "qualityBasis",
233
+ "proofFingerprint",
234
+ "observationId",
235
+ "propagationQualityRank",
236
+ ];
237
+ for (const term of prohibited) {
238
+ expect(joined).not.toContain(term);
239
+ }
240
+ });
241
+ });
242
+ // ---------------------------------------------------------------------------
243
+ // Check run — Why section uses assessment.reasoning
244
+ // ---------------------------------------------------------------------------
245
+ describe("presentGitHubCheckRun — ABI 3 Why section", () => {
246
+ const SCAN_ID = "scan-abi3-test";
247
+ const ORIGIN = "https://app.test";
248
+ function buildBundle(assessment) {
249
+ const result = scanResultWithAssessment(assessment, {
250
+ changedPackages: ["express"],
251
+ });
252
+ return buildScanPresentationBundle({ result, pipelineStatus: "done" });
253
+ }
254
+ it("Why section bullets come from assessment.reasoning (ABI 3)", () => {
255
+ const bundle = buildBundle(assessmentExpressAbi3);
256
+ const checkRun = presentGitHubCheckRun(bundle, {
257
+ scanId: SCAN_ID,
258
+ webAppOrigin: ORIGIN,
259
+ });
260
+ const whySection = checkRun.sections.find((s) => s.id === "why" && s.title === "Why");
261
+ expect(whySection).toBeDefined();
262
+ expect(whySection.bullets).toEqual(expect.arrayContaining([
263
+ "express is used in HTTP request handling in this repository via middleware chains.",
264
+ ]));
265
+ });
266
+ it("Why section does not contain old generic decision reasoning", () => {
267
+ const bundle = buildBundle(assessmentExpressAbi3);
268
+ const checkRun = presentGitHubCheckRun(bundle, {
269
+ scanId: SCAN_ID,
270
+ webAppOrigin: ORIGIN,
271
+ });
272
+ const whySection = checkRun.sections.find((s) => s.id === "why" && s.title === "Why");
273
+ const bulletText = whySection?.bullets.join(" ") ?? "";
274
+ expect(bulletText).not.toContain("Old generic decision reasoning");
275
+ });
276
+ it("check run summary contains no prohibited vocabulary", () => {
277
+ const result = scanResultWithAssessment(assessmentExpressAbi3, {
278
+ changedPackages: ["express"],
279
+ methodologyVersion: "mergesignal-engine/test",
280
+ });
281
+ const output = buildGitHubCheckRunOutput(result, {
282
+ scanId: SCAN_ID,
283
+ webAppOrigin: ORIGIN,
284
+ });
285
+ const prohibited = [
286
+ "qualityClass",
287
+ "qualityBasis",
288
+ "proofFingerprint",
289
+ "observationId",
290
+ "propagationQualityRank",
291
+ "AssessmentEvidenceBundle",
292
+ ];
293
+ for (const term of prohibited) {
294
+ expect(output.summary).not.toContain(term);
295
+ }
296
+ });
297
+ it("Why section respects 3-line limit", () => {
298
+ const bundle = buildBundle(assessmentExpressAbi3);
299
+ const checkRun = presentGitHubCheckRun(bundle, {
300
+ scanId: SCAN_ID,
301
+ webAppOrigin: ORIGIN,
302
+ });
303
+ const whySection = checkRun.sections.find((s) => s.title === "Why");
304
+ if (whySection) {
305
+ expect(whySection.bullets.length).toBeLessThanOrEqual(3);
306
+ }
307
+ });
308
+ });
309
+ // ---------------------------------------------------------------------------
310
+ // End-to-end markdown snapshot — PR comment with ABI 3 fixture
311
+ // ---------------------------------------------------------------------------
312
+ describe("PR comment markdown — ABI 3 end-to-end", () => {
313
+ it("rendered markdown includes repository-specific reasoning", () => {
314
+ const result = scanResultWithAssessment(assessmentExpressAbi3, {
315
+ changedPackages: ["express"],
316
+ });
317
+ const markdown = presentGitHubPrCommentMarkdownFromResult(result);
318
+ expect(markdown).toContain("express is used in HTTP request handling");
319
+ expect(markdown).toContain("Import paths to application entry points");
320
+ });
321
+ it("rendered markdown includes electionSummary", () => {
322
+ const result = scanResultWithAssessment(assessmentExpressAbi3, {
323
+ changedPackages: ["express"],
324
+ });
325
+ const markdown = presentGitHubPrCommentMarkdownFromResult(result);
326
+ expect(markdown).toContain("express was selected as the primary review anchor");
327
+ });
328
+ it("rendered markdown contains no prohibited vocabulary", () => {
329
+ const result = scanResultWithAssessment(assessmentExpressAbi3, {
330
+ changedPackages: ["express"],
331
+ });
332
+ const markdown = presentGitHubPrCommentMarkdownFromResult(result);
333
+ const prohibited = [
334
+ "qualityClass",
335
+ "qualityBasis",
336
+ "proofFingerprint",
337
+ "observationId",
338
+ "propagationQualityRank",
339
+ "AssessmentEvidenceBundle",
340
+ "DenseEvidenceHighlight",
341
+ ];
342
+ for (const term of prohibited) {
343
+ expect(markdown).not.toContain(term);
344
+ }
345
+ });
346
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"presentGitHubCheckRun.d.ts","sourceRoot":"","sources":["../../../src/presentation/presenters/presentGitHubCheckRun.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AACrF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AAGzF,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,sBAAsB,EAC9B,GAAG,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAChE,0BAA0B,CA4C5B"}
1
+ {"version":3,"file":"presentGitHubCheckRun.d.ts","sourceRoot":"","sources":["../../../src/presentation/presenters/presentGitHubCheckRun.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AACrF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AAGzF,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,sBAAsB,EAC9B,GAAG,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAChE,0BAA0B,CAmD5B"}
@@ -4,7 +4,7 @@ import { projectAssessmentFields } from "../projectAssessmentFields.js";
4
4
  export function presentGitHubCheckRun(bundle, ctx) {
5
5
  const { profile } = bundle;
6
6
  const headline = composeHeadline(bundle);
7
- const keyPoints = projectCompactKeyPoints(buildNarrativeChannels(bundle), 3);
7
+ const assessmentFields = projectAssessmentFields(bundle);
8
8
  const actions = composeVerificationActions(bundle, 3);
9
9
  const detailsUrl = `${ctx.webAppOrigin.replace(/\/$/, "")}/scan/${ctx.scanId}`;
10
10
  const conclusion = profile.status === "safe"
@@ -22,15 +22,21 @@ export function presentGitHubCheckRun(bundle, ctx) {
22
22
  bullets: [`${prRiskScore} (${prRiskBandLabelText})`],
23
23
  });
24
24
  }
25
- if (keyPoints.length > 0) {
26
- sections.push({ id: "why", title: "Why", bullets: keyPoints });
25
+ // Use assessment.reasoning directly for the Why section (ABI 3).
26
+ // Fall back to compact key points for pre-ABI-3 scan results.
27
+ const reasoningLines = assessmentFields.reasoning.slice(0, 3);
28
+ const whyBullets = reasoningLines.length > 0
29
+ ? reasoningLines
30
+ : projectCompactKeyPoints(buildNarrativeChannels(bundle), 3);
31
+ if (whyBullets.length > 0) {
32
+ sections.push({ id: "why", title: "Why", bullets: whyBullets });
27
33
  }
28
34
  if (actions.length > 0) {
29
35
  sections.push({ id: "actions", title: "What to verify", bullets: actions });
30
36
  }
31
37
  sections.push({ id: "footer", bullets: [`Full scan: ${detailsUrl}`] });
32
38
  return {
33
- ...projectAssessmentFields(bundle),
39
+ ...assessmentFields,
34
40
  status: profile.status,
35
41
  density: profile.density,
36
42
  confidence: profile.confidence,
@@ -1 +1 @@
1
- {"version":3,"file":"presentGitHubPrComment.d.ts","sourceRoot":"","sources":["../../../src/presentation/presenters/presentGitHubPrComment.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AAGzF,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,sBAAsB,GAC7B,2BAA2B,CAmC7B"}
1
+ {"version":3,"file":"presentGitHubPrComment.d.ts","sourceRoot":"","sources":["../../../src/presentation/presenters/presentGitHubPrComment.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AAGzF,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,sBAAsB,GAC7B,2BAA2B,CAqC7B"}
@@ -16,6 +16,9 @@ export function presentGitHubPrComment(bundle) {
16
16
  if (prRiskScore != null && prRiskBandLabelText) {
17
17
  introLines.push(`PR Risk: ${prRiskScore} (${prRiskBandLabelText})`);
18
18
  }
19
+ const electionSummary = bundle.assessment.reviewFocalPoint.electionSummary;
20
+ if (electionSummary)
21
+ introLines.push(electionSummary);
19
22
  for (const line of assessmentFields.reasoning.slice(0, 2)) {
20
23
  introLines.push(line);
21
24
  }
@@ -16,4 +16,36 @@ describe("repoIntelligenceWireSchema contract", () => {
16
16
  const joined = r.issues.join(" ");
17
17
  expect(joined.length).toBeGreaterThan(0);
18
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
+ });
19
51
  });
@@ -9,7 +9,7 @@ import { z } from "zod";
9
9
  import type { ScanResult } from "./types.js";
10
10
  import type { BlastRadiusLevel } from "./scanNarrativeFacts.js";
11
11
  /** Bump when wire schema changes incompatibly. */
12
- export declare const REPO_INTELLIGENCE_ABI: "2";
12
+ export declare const REPO_INTELLIGENCE_ABI: "3";
13
13
  /** Strict canonical wire schema — single source of truth. */
14
14
  export declare const repoIntelligenceWireSchema: z.ZodObject<{
15
15
  packages: z.ZodRecord<z.ZodString, z.ZodObject<{
@@ -101,6 +101,24 @@ export declare const repoIntelligenceWireSchema: z.ZodObject<{
101
101
  }>;
102
102
  registryEntryId: z.ZodOptional<z.ZodString>;
103
103
  }, z.core.$strip>>;
104
+ lifecycleStages: z.ZodOptional<z.ZodArray<z.ZodObject<{
105
+ stage: z.ZodString;
106
+ fileCount: z.ZodNumber;
107
+ evidenceRefs: z.ZodArray<z.ZodString>;
108
+ }, z.core.$strip>>>;
109
+ promotedAreas: z.ZodOptional<z.ZodArray<z.ZodObject<{
110
+ area: z.ZodString;
111
+ structuralAnchor: z.ZodOptional<z.ZodEnum<{
112
+ http_surface: "http_surface";
113
+ auth_surface: "auth_surface";
114
+ orm_surface: "orm_surface";
115
+ queue_surface: "queue_surface";
116
+ type_surface: "type_surface";
117
+ build_surface: "build_surface";
118
+ testing_surface: "testing_surface";
119
+ }>>;
120
+ evidenceRefs: z.ZodArray<z.ZodString>;
121
+ }, z.core.$strip>>>;
104
122
  }, z.core.$strip>>;
105
123
  packageUsage: z.ZodOptional<z.ZodArray<z.ZodObject<{
106
124
  packageName: z.ZodString;
@@ -1 +1 @@
1
- {"version":3,"file":"repoIntelligenceSchema.d.ts","sourceRoot":"","sources":["../src/repoIntelligenceSchema.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,kDAAkD;AAClD,eAAO,MAAM,qBAAqB,EAAG,GAAY,CAAC;AA+HlD,6DAA6D;AAC7D,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBASrC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE1E,MAAM,MAAM,4BAA4B,GAAG;IACzC,EAAE,EAAE,IAAI,CAAC;IACT,KAAK,EAAE,gBAAgB,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,2BAA2B,GACnC,4BAA4B,GAC5B,4BAA4B,CAAC;AAQjC,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAUlE;AAED,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,OAAO,GACX,2BAA2B,CAyC7B;AAED,uEAAuE;AACvE,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAM3E;AAED,mFAAmF;AACnF,wBAAgB,uCAAuC,CACrD,IAAI,EAAE,UAAU,GACf,IAAI,CAGN;AAED,wBAAgB,cAAc,CAC5B,KAAK,EAAE,gBAAgB,GAAG,SAAS,GAClC,gBAAgB,GAAG,IAAI,CAKzB"}
1
+ {"version":3,"file":"repoIntelligenceSchema.d.ts","sourceRoot":"","sources":["../src/repoIntelligenceSchema.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,kDAAkD;AAClD,eAAO,MAAM,qBAAqB,EAAG,GAAY,CAAC;AAuJlD,6DAA6D;AAC7D,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBASrC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE1E,MAAM,MAAM,4BAA4B,GAAG;IACzC,EAAE,EAAE,IAAI,CAAC;IACT,KAAK,EAAE,gBAAgB,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,2BAA2B,GACnC,4BAA4B,GAC5B,4BAA4B,CAAC;AAQjC,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAUlE;AAED,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,OAAO,GACX,2BAA2B,CAyC7B;AAED,uEAAuE;AACvE,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAM3E;AAED,mFAAmF;AACnF,wBAAgB,uCAAuC,CACrD,IAAI,EAAE,UAAU,GACf,IAAI,CAGN;AAED,wBAAgB,cAAc,CAC5B,KAAK,EAAE,gBAAgB,GAAG,SAAS,GAClC,gBAAgB,GAAG,IAAI,CAKzB"}
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import { z } from "zod";
9
9
  /** Bump when wire schema changes incompatibly. */
10
- export const REPO_INTELLIGENCE_ABI = "2";
10
+ export const REPO_INTELLIGENCE_ABI = "3";
11
11
  const surfaceKindSchema = z.enum(["runtime", "build", "test", "unknown"]);
12
12
  const reachabilityKindSchema = z.enum([
13
13
  "on_runtime_paths",
@@ -86,6 +86,25 @@ const semanticDiagnosticSchema = z.object({
86
86
  after: z.record(z.string(), z.unknown()),
87
87
  reason: z.string().min(1),
88
88
  });
89
+ const structuralRoleWireSchema = z.enum([
90
+ "http_surface",
91
+ "auth_surface",
92
+ "orm_surface",
93
+ "queue_surface",
94
+ "type_surface",
95
+ "build_surface",
96
+ "testing_surface",
97
+ ]);
98
+ const wireLifecycleStageProjectionSchema = z.object({
99
+ stage: z.string().min(1),
100
+ fileCount: z.number().int().nonnegative(),
101
+ evidenceRefs: z.array(z.string()),
102
+ });
103
+ const wirePromotedAreaProjectionSchema = z.object({
104
+ area: z.string().min(1),
105
+ structuralAnchor: structuralRoleWireSchema.optional(),
106
+ evidenceRefs: z.array(z.string()),
107
+ });
89
108
  const packageIntelWireSchema = z.object({
90
109
  runtimeSurface: surfaceKindSchema,
91
110
  reachability: reachabilityKindSchema,
@@ -101,6 +120,8 @@ const packageIntelWireSchema = z.object({
101
120
  verificationFocus: z.array(z.string()).optional(),
102
121
  suppressRuntimeNarrative: z.boolean().optional(),
103
122
  classificationProvenance: classificationProvenanceSchema.optional(),
123
+ lifecycleStages: z.array(wireLifecycleStageProjectionSchema).optional(),
124
+ promotedAreas: z.array(wirePromotedAreaProjectionSchema).optional(),
104
125
  });
105
126
  const areaSchema = z.object({
106
127
  id: z.string().min(1),
@@ -131,6 +131,7 @@ export declare const engineOutputScanResultSchema: z.ZodObject<{
131
131
  concern: "concern";
132
132
  reach: "reach";
133
133
  changeSeverity: "changeSeverity";
134
+ repository_importance: "repository_importance";
134
135
  role_salience_tiebreak: "role_salience_tiebreak";
135
136
  }>;
136
137
  evidenceRefs: z.ZodArray<z.ZodString>;
@@ -142,11 +143,13 @@ export declare const engineOutputScanResultSchema: z.ZodObject<{
142
143
  concern: "concern";
143
144
  reach: "reach";
144
145
  changeSeverity: "changeSeverity";
146
+ repository_importance: "repository_importance";
145
147
  role_salience_tiebreak: "role_salience_tiebreak";
146
148
  }>;
147
149
  evidenceRefs: z.ZodArray<z.ZodString>;
148
150
  }, z.core.$strip>>;
149
151
  }, z.core.$strip>;
152
+ electionSummary: z.ZodOptional<z.ZodString>;
150
153
  }, z.core.$strip>;
151
154
  reachScope: z.ZodObject<{
152
155
  packages: z.ZodArray<z.ZodString>;
@@ -161,6 +164,7 @@ export declare const engineOutputScanResultSchema: z.ZodObject<{
161
164
  verificationScope: z.ZodObject<{
162
165
  packages: z.ZodArray<z.ZodString>;
163
166
  focus: z.ZodArray<z.ZodString>;
167
+ guidance: z.ZodOptional<z.ZodArray<z.ZodString>>;
164
168
  artifactGrounded: z.ZodOptional<z.ZodObject<{
165
169
  packages: z.ZodArray<z.ZodString>;
166
170
  focus: z.ZodArray<z.ZodString>;
@@ -199,6 +203,7 @@ export declare const engineOutputScanResultSchema: z.ZodObject<{
199
203
  rank: z.ZodNumber;
200
204
  packages: z.ZodOptional<z.ZodArray<z.ZodString>>;
201
205
  evidenceRefs: z.ZodArray<z.ZodString>;
206
+ context: z.ZodOptional<z.ZodString>;
202
207
  }, z.core.$strip>>;
203
208
  factors: z.ZodArray<z.ZodString>;
204
209
  changeClasses: z.ZodArray<z.ZodEnum<{
@@ -238,6 +243,8 @@ export declare const engineOutputScanResultSchema: z.ZodObject<{
238
243
  high_signal_pr: "high_signal_pr";
239
244
  }>;
240
245
  }, z.core.$strip>;
246
+ reasoning: z.ZodArray<z.ZodString>;
247
+ confidenceRationale: z.ZodString;
241
248
  }, z.core.$strip>;
242
249
  prRisk: z.ZodObject<{
243
250
  score: z.ZodNumber;
@@ -1 +1 @@
1
- {"version":3,"file":"scanResultSchema.d.ts","sourceRoot":"","sources":["../src/scanResultSchema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,uBAAuB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEtE,wGAAwG;AACxG,eAAO,MAAM,eAAe,EAAG,GAAY,CAAC;AAE5C,+EAA+E;AAC/E,eAAO,MAAM,sBAAsB,EAAG,GAAY,CAAC;AAmBnD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAc/D;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8Bb,CAAC;AAUjB;;;GAGG;AACH,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMvC,CAAC;AAEH,MAAM,MAAM,kCAAkC,GAAG;IAC/C,EAAE,EAAE,KAAK,CAAC;IACV,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,kCAAkC,GAAG;IAC/C,EAAE,EAAE,IAAI,CAAC;IACT,MAAM,EAAE,uBAAuB,CAAC;CACjC,CAAC;AAEF,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,OAAO,GACZ,kCAAkC,GAAG,kCAAkC,CAezE;AAED,uFAAuF;AACvF,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,OAAO,GACZ,uBAAuB,CAMzB;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,EAAE,EAAE,KAAK,CAAC;IACV,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,EAAE,EAAE,IAAI,CAAC;IACT,MAAM,EAAE,UAAU,CAAC;CACpB,CAAC;AAEF,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,OAAO,GACZ,sBAAsB,GAAG,sBAAsB,CAajD;AAED,yEAAyE;AACzE,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,CAMhE"}
1
+ {"version":3,"file":"scanResultSchema.d.ts","sourceRoot":"","sources":["../src/scanResultSchema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,uBAAuB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEtE,wGAAwG;AACxG,eAAO,MAAM,eAAe,EAAG,GAAY,CAAC;AAE5C,+EAA+E;AAC/E,eAAO,MAAM,sBAAsB,EAAG,GAAY,CAAC;AAmBnD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAc/D;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8Bb,CAAC;AAUjB;;;GAGG;AACH,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMvC,CAAC;AAEH,MAAM,MAAM,kCAAkC,GAAG;IAC/C,EAAE,EAAE,KAAK,CAAC;IACV,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,kCAAkC,GAAG;IAC/C,EAAE,EAAE,IAAI,CAAC;IACT,MAAM,EAAE,uBAAuB,CAAC;CACjC,CAAC;AAEF,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,OAAO,GACZ,kCAAkC,GAAG,kCAAkC,CAezE;AAED,uFAAuF;AACvF,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,OAAO,GACZ,uBAAuB,CAMzB;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,EAAE,EAAE,KAAK,CAAC;IACV,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,EAAE,EAAE,IAAI,CAAC;IACT,MAAM,EAAE,UAAU,CAAC;CACpB,CAAC;AAEF,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,OAAO,GACZ,sBAAsB,GAAG,sBAAsB,CAajD;AAED,yEAAyE;AACzE,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,CAMhE"}
@@ -89,6 +89,8 @@ const minimalAssessment = {
89
89
  concerns: [],
90
90
  factors: ["tooling_maintenance"],
91
91
  changeClasses: ["tooling_maintenance"],
92
+ reasoning: [],
93
+ confidenceRationale: "",
92
94
  presentation: {
93
95
  narrativeIntensity: "minimal",
94
96
  reachVisibility: "hidden",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mergesignal/shared",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "description": "MergeSignal shared scan contract, presentation policy, and trusted validation",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",