agentskeptic 8.0.1 → 8.2.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 (40) hide show
  1. package/README.md +10 -0
  2. package/dist/certificateVerificationDiff.d.ts +77 -0
  3. package/dist/certificateVerificationDiff.d.ts.map +1 -0
  4. package/dist/certificateVerificationDiff.js +249 -0
  5. package/dist/certificateVerificationDiff.js.map +1 -0
  6. package/dist/certificateVerificationDiff.test.d.ts +2 -0
  7. package/dist/certificateVerificationDiff.test.d.ts.map +1 -0
  8. package/dist/certificateVerificationDiff.test.js +53 -0
  9. package/dist/certificateVerificationDiff.test.js.map +1 -0
  10. package/dist/cli.js +96 -4
  11. package/dist/cli.js.map +1 -1
  12. package/dist/compareCertificatesCli.test.d.ts +2 -0
  13. package/dist/compareCertificatesCli.test.d.ts.map +1 -0
  14. package/dist/compareCertificatesCli.test.js +144 -0
  15. package/dist/compareCertificatesCli.test.js.map +1 -0
  16. package/dist/evidenceCompleteness.d.ts +3 -0
  17. package/dist/evidenceCompleteness.d.ts.map +1 -1
  18. package/dist/evidenceCompleteness.js +3 -0
  19. package/dist/evidenceCompleteness.js.map +1 -1
  20. package/dist/execution-identity.v1.json +1 -1
  21. package/dist/publicDistribution.generated.d.ts +1 -1
  22. package/dist/publicDistribution.generated.js +1 -1
  23. package/dist/remediationDecision.parity.test.js +12 -0
  24. package/dist/remediationDecision.parity.test.js.map +1 -1
  25. package/dist/schemaLoad.d.ts +1 -1
  26. package/dist/schemaLoad.d.ts.map +1 -1
  27. package/dist/schemaLoad.js +3 -0
  28. package/dist/schemaLoad.js.map +1 -1
  29. package/dist/witnessCoverageRollup.d.ts +23 -0
  30. package/dist/witnessCoverageRollup.d.ts.map +1 -0
  31. package/dist/witnessCoverageRollup.js +138 -0
  32. package/dist/witnessCoverageRollup.js.map +1 -0
  33. package/dist/witnessCoverageRollup.test.d.ts +2 -0
  34. package/dist/witnessCoverageRollup.test.d.ts.map +1 -0
  35. package/dist/witnessCoverageRollup.test.js +187 -0
  36. package/dist/witnessCoverageRollup.test.js.map +1 -0
  37. package/package.json +1 -1
  38. package/schemas/evidence-completeness-v1.schema.json +53 -0
  39. package/schemas/openapi-commercial-v1.yaml +1 -1
  40. package/schemas/verification-diff-certificate-v1.schema.json +229 -0
package/README.md CHANGED
@@ -70,6 +70,16 @@ Full verdict and stderr contract: [`docs/first-truth-check.md`](docs/first-truth
70
70
  2. Emit observations via the canonical SDK emitter, then append emitted rows to the gate buffer. Optionally mirror the same JSON lines to **`agentskeptic/events.ndjson`** for CI replay.
71
71
  3. On the code path **before** irreversible work you control (ship, bill, ticket close), call **`await gate.assertSafeForIrreversibleAction()`** so **unsafe** trust (or required emissions that never reached the gate) blocks **that** branch — it is not a substitute for wiring the gate everywhere it matters, and outcomes can still be **`unknown`** when **`highStakesReliance`** is not **`permitted`** (see [`docs/outcome-certificate-normative.md`](docs/outcome-certificate-normative.md)).
72
72
 
73
+ ### Compare two saved Outcome Certificates (semantic diff)
74
+
75
+ To compare **trust posture** between two saved **`schemaVersion: 3`** Outcome Certificate JSON files (no workflow payloads or event streams):
76
+
77
+ ```bash
78
+ npx agentskeptic compare certificates --before ./prior-outcome.json --after ./current-outcome.json
79
+ ```
80
+
81
+ **Stdout** is **`VerificationDiffCertificateV1`** ([`schemas/verification-diff-certificate-v1.schema.json`](schemas/verification-diff-certificate-v1.schema.json)); **stderr** is human-readable text (not JSON). Multi-run **structural** regression compare still uses **`agentskeptic compare --manifest`** ([`docs/regression-artifact-normative.md`](docs/regression-artifact-normative.md)). Full CLI contract: **[`docs/agentskeptic.md`](docs/agentskeptic.md#verification-diff-outcome-certificate-v3)**.
82
+
73
83
  ### Install
74
84
 
75
85
  ```bash
@@ -0,0 +1,77 @@
1
+ import type { OutcomeCertificateV3, OutcomeCertificateStateRelation } from "./outcomeCertificate.js";
2
+ export declare const VERIFICATION_DIFF_SCHEMA_URL: "https://agentskeptic.com/schemas/verification-diff-certificate-v1.schema.json";
3
+ export declare const VERIFICATION_DIFF_NEXT_STEP: {
4
+ readonly command: "agentskeptic compare --manifest <compare-run-manifest.json>";
5
+ readonly docAnchor: "docs/agentskeptic.md#cross-run-comparison-normative";
6
+ };
7
+ export declare const VERIFICATION_DIFF_LIMITS: {
8
+ readonly certificateOnly: true;
9
+ readonly noEvents: true;
10
+ readonly noStepStructuralDiff: true;
11
+ };
12
+ export type PostureMovement = "improved" | "weakened" | "unchanged" | "less_determinate" | "drifted";
13
+ export type DeterminacyClass = "established_positive" | "established_negative" | "not_established";
14
+ export type EvidenceProjection = {
15
+ blockerCategory: string;
16
+ supportLabel: string | null;
17
+ };
18
+ export type VerificationDiffCertificateV1 = {
19
+ $schema: typeof VERIFICATION_DIFF_SCHEMA_URL;
20
+ schemaVersion: 1;
21
+ comparisonKind: "outcome_certificate_v3_semantic";
22
+ workflowId: string;
23
+ prior: {
24
+ certificateSha256: string;
25
+ runKind: OutcomeCertificateV3["runKind"];
26
+ stateRelation: OutcomeCertificateStateRelation;
27
+ releaseCriticalVerdict: OutcomeCertificateV3["releaseCriticalVerdict"];
28
+ highStakesReliance: OutcomeCertificateV3["highStakesReliance"];
29
+ };
30
+ current: VerificationDiffCertificateV1["prior"];
31
+ stateRelation: {
32
+ prior: OutcomeCertificateStateRelation;
33
+ current: OutcomeCertificateStateRelation;
34
+ changed: boolean;
35
+ };
36
+ releaseCriticalVerdict: {
37
+ prior: OutcomeCertificateV3["releaseCriticalVerdict"];
38
+ current: OutcomeCertificateV3["releaseCriticalVerdict"];
39
+ changed: boolean;
40
+ };
41
+ highStakesReliance: {
42
+ prior: OutcomeCertificateV3["highStakesReliance"];
43
+ current: OutcomeCertificateV3["highStakesReliance"];
44
+ changed: boolean;
45
+ };
46
+ runKind: {
47
+ prior: OutcomeCertificateV3["runKind"];
48
+ current: OutcomeCertificateV3["runKind"];
49
+ changed: boolean;
50
+ };
51
+ evidenceCompletenessProjection: {
52
+ prior: EvidenceProjection;
53
+ current: EvidenceProjection;
54
+ };
55
+ completenessChanged: boolean;
56
+ determinacy: {
57
+ priorClass: DeterminacyClass;
58
+ currentClass: DeterminacyClass;
59
+ priorRank: 0 | 1 | 2;
60
+ currentRank: 0 | 1 | 2;
61
+ };
62
+ lessDeterminate: boolean;
63
+ postureMovement: PostureMovement;
64
+ headline: string;
65
+ recommendedNextAction: string;
66
+ limits: typeof VERIFICATION_DIFF_LIMITS;
67
+ nextStepHint: typeof VERIFICATION_DIFF_NEXT_STEP;
68
+ };
69
+ export declare function verificationDiffStderrFirstLine(): string;
70
+ export declare function evidenceProjection(c: OutcomeCertificateV3): EvidenceProjection;
71
+ export declare function canonicalEvidenceFingerprint(proj: EvidenceProjection): string;
72
+ /** Build Verification Diff from two validated Outcome Certificate v3 objects (before = prior artifact, after = current). */
73
+ export declare function buildVerificationDiffFromOutcomeCertificates(before: OutcomeCertificateV3, after: OutcomeCertificateV3): VerificationDiffCertificateV1;
74
+ /** Multi-line stderr block (no JSON) after deterministic first line. */
75
+ export declare function buildVerificationDiffHumanText(diff: VerificationDiffCertificateV1): string;
76
+ export declare function stringifyVerificationDiffCertificate(diff: VerificationDiffCertificateV1): string;
77
+ //# sourceMappingURL=certificateVerificationDiff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"certificateVerificationDiff.d.ts","sourceRoot":"","sources":["../src/certificateVerificationDiff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Certificate-only Verification Diff kernel (Outcome Certificate v3).
3
+ * CLASSIFICATION_RULES_SYNC: docs/agentskeptic.md#verification-diff-outcome-certificate-v3 (normative prose)
4
+ *
5
+ * Invariant: no workflow results, events, or traces — semantic posture projection only.
6
+ */
7
+ import { certificateCanonicalDigestHex } from "./certificateDigest.js";
8
+ import { CLI_OPERATIONAL_CODES } from "./cliOperationalCodes.js";
9
+ import { TruthLayerError } from "./truthLayerError.js";
10
+ import { stringifyWithSortedKeys } from "./sortedJsonStringify.js";
11
+ export const VERIFICATION_DIFF_SCHEMA_URL = "https://agentskeptic.com/schemas/verification-diff-certificate-v1.schema.json";
12
+ export const VERIFICATION_DIFF_NEXT_STEP = {
13
+ command: "agentskeptic compare --manifest <compare-run-manifest.json>",
14
+ docAnchor: "docs/agentskeptic.md#cross-run-comparison-normative",
15
+ };
16
+ export const VERIFICATION_DIFF_LIMITS = {
17
+ certificateOnly: true,
18
+ noEvents: true,
19
+ noStepStructuralDiff: true,
20
+ };
21
+ export function verificationDiffStderrFirstLine() {
22
+ return "verification_diff_certificate: certificate-only semantic comparison (not structural run compare)";
23
+ }
24
+ export function evidenceProjection(c) {
25
+ const ec = c.evidenceCompleteness;
26
+ return {
27
+ blockerCategory: ec.blockerCategory,
28
+ supportLabel: ec.witnessCoverage?.supportLabel ?? null,
29
+ };
30
+ }
31
+ export function canonicalEvidenceFingerprint(proj) {
32
+ return stringifyWithSortedKeys({ blockerCategory: proj.blockerCategory, supportLabel: proj.supportLabel });
33
+ }
34
+ function determinacyClass(sr) {
35
+ if (sr === "matches_expectations")
36
+ return "established_positive";
37
+ if (sr === "does_not_match")
38
+ return "established_negative";
39
+ return "not_established";
40
+ }
41
+ function determinacyRank(c) {
42
+ if (c === "established_positive")
43
+ return 2;
44
+ if (c === "established_negative")
45
+ return 1;
46
+ return 0;
47
+ }
48
+ function rcScore(rc) {
49
+ if (rc === "not_trusted")
50
+ return 0;
51
+ if (rc === "unknown")
52
+ return 1;
53
+ return 2;
54
+ }
55
+ function headlineFor(pm) {
56
+ switch (pm) {
57
+ case "unchanged":
58
+ return "Verification posture unchanged between the two Outcome Certificates (projection-equal).";
59
+ case "less_determinate":
60
+ return "Verification became less determinate: trust dimensions lost a determinate established conclusion.";
61
+ case "improved":
62
+ return "Verification posture improved between prior and current Outcome Certificates.";
63
+ case "weakened":
64
+ return "Verification posture weakened between prior and current Outcome Certificates.";
65
+ case "drifted":
66
+ return "Verification posture drifted: material certificate fields changed without a single clear improved/weakened trust story.";
67
+ default: {
68
+ const _e = pm;
69
+ return _e;
70
+ }
71
+ }
72
+ }
73
+ function recommendedNextActionFor(pm) {
74
+ const boundary = "This conclusion is certificate-only semantic diff; it does not inspect events, traces, or step-level workflow structure.";
75
+ const deeper = ` For structural compare use \`${VERIFICATION_DIFF_NEXT_STEP.command}\` (${VERIFICATION_DIFF_NEXT_STEP.docAnchor}).`;
76
+ switch (pm) {
77
+ case "unchanged":
78
+ return `${boundary}${deeper}`;
79
+ case "less_determinate":
80
+ return `Treat the current artifact as withholding a determinate grounding that the prior certificate had; restore observability inputs or rerun verification.${deeper}`;
81
+ case "improved":
82
+ return `Promotion decision may proceed consistent with improved trust projections; archive both certificates.${deeper}`;
83
+ case "weakened":
84
+ return `Hold promotion or widen review: trust projections regressed versus the prior certificate; remediate downstream state / inputs before relying on current.${deeper}`;
85
+ case "drifted":
86
+ return `Reviewer should reconcile why evidence or run posture labels moved while primary trust projections stayed aligned; optionally rerun live verification.${deeper}`;
87
+ default: {
88
+ const _e = pm;
89
+ return _e;
90
+ }
91
+ }
92
+ }
93
+ function certificatesSemanticallyEqualForDiff(before, after, fpBefore, fpAfter) {
94
+ return (before.workflowId === after.workflowId &&
95
+ before.stateRelation === after.stateRelation &&
96
+ before.releaseCriticalVerdict === after.releaseCriticalVerdict &&
97
+ before.highStakesReliance === after.highStakesReliance &&
98
+ before.runKind === after.runKind &&
99
+ fpBefore === fpAfter);
100
+ }
101
+ function classifyPostureMovement(before, after, completenessChanged) {
102
+ const SB = before.stateRelation;
103
+ const SA = after.stateRelation;
104
+ /** Steps 2–6 matched earlier (explicit for step 10 guard). */
105
+ const steps2through6Matched = (SA === "not_established" && SB !== "not_established") ||
106
+ (SB === "does_not_match" && SA === "matches_expectations") ||
107
+ (SB === "matches_expectations" && SA === "does_not_match") ||
108
+ (SB === "not_established" && SA === "matches_expectations") ||
109
+ (SB === "not_established" && SA === "does_not_match");
110
+ const fb = canonicalEvidenceFingerprint(evidenceProjection(before));
111
+ const fa = canonicalEvidenceFingerprint(evidenceProjection(after));
112
+ // Step 1
113
+ if (certificatesSemanticallyEqualForDiff(before, after, fb, fa))
114
+ return "unchanged";
115
+ // Step 2
116
+ if (SA === "not_established" && SB !== "not_established")
117
+ return "less_determinate";
118
+ // Step 3
119
+ if (SB === "does_not_match" && SA === "matches_expectations")
120
+ return "improved";
121
+ // Step 4
122
+ if (SB === "matches_expectations" && SA === "does_not_match")
123
+ return "weakened";
124
+ // Step 5
125
+ if (SB === "not_established" && SA === "matches_expectations")
126
+ return "improved";
127
+ // Step 6
128
+ if (SB === "not_established" && SA === "does_not_match")
129
+ return "weakened";
130
+ // Step 7
131
+ if (before.runKind !== after.runKind &&
132
+ SB === SA &&
133
+ before.releaseCriticalVerdict === after.releaseCriticalVerdict &&
134
+ before.highStakesReliance === after.highStakesReliance &&
135
+ !completenessChanged) {
136
+ return "drifted";
137
+ }
138
+ // Step 8: RC improved + SR not strictly worse (before=matches ∧ after≠matches would be strictly worse SR)
139
+ if (rcScore(after.releaseCriticalVerdict) > rcScore(before.releaseCriticalVerdict) &&
140
+ !(SB === "matches_expectations" && SA !== "matches_expectations")) {
141
+ return "improved";
142
+ }
143
+ // Step 9
144
+ if (rcScore(after.releaseCriticalVerdict) < rcScore(before.releaseCriticalVerdict))
145
+ return "weakened";
146
+ // Step 10
147
+ if (before.highStakesReliance === "prohibited" && after.highStakesReliance === "permitted" && !steps2through6Matched) {
148
+ return "improved";
149
+ }
150
+ // Step 11
151
+ if (before.highStakesReliance === "permitted" && after.highStakesReliance === "prohibited")
152
+ return "weakened";
153
+ // Step 12
154
+ if (completenessChanged &&
155
+ SB === SA &&
156
+ before.releaseCriticalVerdict === after.releaseCriticalVerdict &&
157
+ before.highStakesReliance === after.highStakesReliance &&
158
+ before.runKind === after.runKind) {
159
+ return "drifted";
160
+ }
161
+ return "unchanged";
162
+ }
163
+ /** Build Verification Diff from two validated Outcome Certificate v3 objects (before = prior artifact, after = current). */
164
+ export function buildVerificationDiffFromOutcomeCertificates(before, after) {
165
+ if (before.workflowId !== after.workflowId) {
166
+ throw new TruthLayerError(CLI_OPERATIONAL_CODES.COMPARE_WORKFLOW_ID_MISMATCH, `Compare certificates: workflowId differs (before=${before.workflowId}, after=${after.workflowId}).`);
167
+ }
168
+ const projBefore = evidenceProjection(before);
169
+ const projAfter = evidenceProjection(after);
170
+ const completenessChanged = canonicalEvidenceFingerprint(projBefore) !== canonicalEvidenceFingerprint(projAfter);
171
+ const dcB = determinacyClass(before.stateRelation);
172
+ const dcA = determinacyClass(after.stateRelation);
173
+ const pr = determinacyRank(dcB);
174
+ const cr = determinacyRank(dcA);
175
+ const lessDeterminate = dcB !== "not_established" && dcA === "not_established";
176
+ const postureMovement = classifyPostureMovement(before, after, completenessChanged);
177
+ const priorFace = {
178
+ certificateSha256: certificateCanonicalDigestHex(before),
179
+ runKind: before.runKind,
180
+ stateRelation: before.stateRelation,
181
+ releaseCriticalVerdict: before.releaseCriticalVerdict,
182
+ highStakesReliance: before.highStakesReliance,
183
+ };
184
+ const currentFace = {
185
+ certificateSha256: certificateCanonicalDigestHex(after),
186
+ runKind: after.runKind,
187
+ stateRelation: after.stateRelation,
188
+ releaseCriticalVerdict: after.releaseCriticalVerdict,
189
+ highStakesReliance: after.highStakesReliance,
190
+ };
191
+ return {
192
+ $schema: VERIFICATION_DIFF_SCHEMA_URL,
193
+ schemaVersion: 1,
194
+ comparisonKind: "outcome_certificate_v3_semantic",
195
+ workflowId: before.workflowId,
196
+ prior: priorFace,
197
+ current: currentFace,
198
+ stateRelation: {
199
+ prior: before.stateRelation,
200
+ current: after.stateRelation,
201
+ changed: before.stateRelation !== after.stateRelation,
202
+ },
203
+ releaseCriticalVerdict: {
204
+ prior: before.releaseCriticalVerdict,
205
+ current: after.releaseCriticalVerdict,
206
+ changed: before.releaseCriticalVerdict !== after.releaseCriticalVerdict,
207
+ },
208
+ highStakesReliance: {
209
+ prior: before.highStakesReliance,
210
+ current: after.highStakesReliance,
211
+ changed: before.highStakesReliance !== after.highStakesReliance,
212
+ },
213
+ runKind: {
214
+ prior: before.runKind,
215
+ current: after.runKind,
216
+ changed: before.runKind !== after.runKind,
217
+ },
218
+ evidenceCompletenessProjection: { prior: projBefore, current: projAfter },
219
+ completenessChanged,
220
+ determinacy: { priorClass: dcB, currentClass: dcA, priorRank: pr, currentRank: cr },
221
+ lessDeterminate,
222
+ postureMovement,
223
+ headline: headlineFor(postureMovement),
224
+ recommendedNextAction: recommendedNextActionFor(postureMovement),
225
+ limits: { ...VERIFICATION_DIFF_LIMITS },
226
+ nextStepHint: { ...VERIFICATION_DIFF_NEXT_STEP },
227
+ };
228
+ }
229
+ /** Multi-line stderr block (no JSON) after deterministic first line. */
230
+ export function buildVerificationDiffHumanText(diff) {
231
+ const lines = [
232
+ verificationDiffStderrFirstLine(),
233
+ "",
234
+ diff.headline,
235
+ "",
236
+ diff.recommendedNextAction,
237
+ "",
238
+ `Posture classification: ${diff.postureMovement}`,
239
+ "",
240
+ `State relation: prior=${diff.stateRelation.prior} current=${diff.stateRelation.current}`,
241
+ "",
242
+ `Limits: certificateOnly semantic diff (noEvents, noStepStructuralDiff).`,
243
+ ];
244
+ return lines.join("\n");
245
+ }
246
+ export function stringifyVerificationDiffCertificate(diff) {
247
+ return stringifyWithSortedKeys(diff);
248
+ }
249
+ //# sourceMappingURL=certificateVerificationDiff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"certificateVerificationDiff.js","sourceRoot":"","sources":["../src/certificateVerificationDiff.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAC;AAEvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,MAAM,CAAC,MAAM,4BAA4B,GACvC,+EAAwF,CAAC;AAE3F,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,OAAO,EAAE,6DAA6D;IACtE,SAAS,EAAE,qDAAqD;CACxD,CAAC;AAEX,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,eAAe,EAAE,IAAI;IACrB,QAAQ,EAAE,IAAI;IACd,oBAAoB,EAAE,IAAI;CAClB,CAAC;AAoDX,MAAM,UAAU,+BAA+B;IAC7C,OAAO,kGAAkG,CAAC;AAC5G,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,CAAuB;IACxD,MAAM,EAAE,GAAG,CAAC,CAAC,oBAGZ,CAAC;IACF,OAAO;QACL,eAAe,EAAE,EAAE,CAAC,eAAe;QACnC,YAAY,EAAE,EAAE,CAAC,eAAe,EAAE,YAAY,IAAI,IAAI;KACvD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,IAAwB;IACnE,OAAO,uBAAuB,CAAC,EAAE,eAAe,EAAE,IAAI,CAAC,eAAe,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;AAC7G,CAAC;AAED,SAAS,gBAAgB,CAAC,EAAmC;IAC3D,IAAI,EAAE,KAAK,sBAAsB;QAAE,OAAO,sBAAsB,CAAC;IACjE,IAAI,EAAE,KAAK,gBAAgB;QAAE,OAAO,sBAAsB,CAAC;IAC3D,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,SAAS,eAAe,CAAC,CAAmB;IAC1C,IAAI,CAAC,KAAK,sBAAsB;QAAE,OAAO,CAAC,CAAC;IAC3C,IAAI,CAAC,KAAK,sBAAsB;QAAE,OAAO,CAAC,CAAC;IAC3C,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,OAAO,CAAC,EAAkD;IACjE,IAAI,EAAE,KAAK,aAAa;QAAE,OAAO,CAAC,CAAC;IACnC,IAAI,EAAE,KAAK,SAAS;QAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,WAAW,CAAC,EAAmB;IACtC,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,WAAW;YACd,OAAO,yFAAyF,CAAC;QACnG,KAAK,kBAAkB;YACrB,OAAO,mGAAmG,CAAC;QAC7G,KAAK,UAAU;YACb,OAAO,+EAA+E,CAAC;QACzF,KAAK,UAAU;YACb,OAAO,+EAA+E,CAAC;QACzF,KAAK,SAAS;YACZ,OAAO,yHAAyH,CAAC;QACnI,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,EAAE,GAAU,EAAE,CAAC;YACrB,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAAC,EAAmB;IACnD,MAAM,QAAQ,GACZ,0HAA0H,CAAC;IAC7H,MAAM,MAAM,GAAG,iCAAiC,2BAA2B,CAAC,OAAO,OAAO,2BAA2B,CAAC,SAAS,IAAI,CAAC;IACpI,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,WAAW;YACd,OAAO,GAAG,QAAQ,GAAG,MAAM,EAAE,CAAC;QAChC,KAAK,kBAAkB;YACrB,OAAO,wJAAwJ,MAAM,EAAE,CAAC;QAC1K,KAAK,UAAU;YACb,OAAO,wGAAwG,MAAM,EAAE,CAAC;QAC1H,KAAK,UAAU;YACb,OAAO,2JAA2J,MAAM,EAAE,CAAC;QAC7K,KAAK,SAAS;YACZ,OAAO,yJAAyJ,MAAM,EAAE,CAAC;QAC3K,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,EAAE,GAAU,EAAE,CAAC;YACrB,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,oCAAoC,CAC3C,MAA4B,EAC5B,KAA2B,EAC3B,QAAgB,EAChB,OAAe;IAEf,OAAO,CACL,MAAM,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU;QACtC,MAAM,CAAC,aAAa,KAAK,KAAK,CAAC,aAAa;QAC5C,MAAM,CAAC,sBAAsB,KAAK,KAAK,CAAC,sBAAsB;QAC9D,MAAM,CAAC,kBAAkB,KAAK,KAAK,CAAC,kBAAkB;QACtD,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO;QAChC,QAAQ,KAAK,OAAO,CACrB,CAAC;AACJ,CAAC;AAED,SAAS,uBAAuB,CAC9B,MAA4B,EAC5B,KAA2B,EAC3B,mBAA4B;IAE5B,MAAM,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;IAChC,MAAM,EAAE,GAAG,KAAK,CAAC,aAAa,CAAC;IAE/B,8DAA8D;IAC9D,MAAM,qBAAqB,GACzB,CAAC,EAAE,KAAK,iBAAiB,IAAI,EAAE,KAAK,iBAAiB,CAAC;QACtD,CAAC,EAAE,KAAK,gBAAgB,IAAI,EAAE,KAAK,sBAAsB,CAAC;QAC1D,CAAC,EAAE,KAAK,sBAAsB,IAAI,EAAE,KAAK,gBAAgB,CAAC;QAC1D,CAAC,EAAE,KAAK,iBAAiB,IAAI,EAAE,KAAK,sBAAsB,CAAC;QAC3D,CAAC,EAAE,KAAK,iBAAiB,IAAI,EAAE,KAAK,gBAAgB,CAAC,CAAC;IAExD,MAAM,EAAE,GAAG,4BAA4B,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC;IACpE,MAAM,EAAE,GAAG,4BAA4B,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;IAEnE,SAAS;IACT,IAAI,oCAAoC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC;QAAE,OAAO,WAAW,CAAC;IAEpF,SAAS;IACT,IAAI,EAAE,KAAK,iBAAiB,IAAI,EAAE,KAAK,iBAAiB;QAAE,OAAO,kBAAkB,CAAC;IAEpF,SAAS;IACT,IAAI,EAAE,KAAK,gBAAgB,IAAI,EAAE,KAAK,sBAAsB;QAAE,OAAO,UAAU,CAAC;IAEhF,SAAS;IACT,IAAI,EAAE,KAAK,sBAAsB,IAAI,EAAE,KAAK,gBAAgB;QAAE,OAAO,UAAU,CAAC;IAEhF,SAAS;IACT,IAAI,EAAE,KAAK,iBAAiB,IAAI,EAAE,KAAK,sBAAsB;QAAE,OAAO,UAAU,CAAC;IAEjF,SAAS;IACT,IAAI,EAAE,KAAK,iBAAiB,IAAI,EAAE,KAAK,gBAAgB;QAAE,OAAO,UAAU,CAAC;IAE3E,SAAS;IACT,IACE,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO;QAChC,EAAE,KAAK,EAAE;QACT,MAAM,CAAC,sBAAsB,KAAK,KAAK,CAAC,sBAAsB;QAC9D,MAAM,CAAC,kBAAkB,KAAK,KAAK,CAAC,kBAAkB;QACtD,CAAC,mBAAmB,EACpB,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,0GAA0G;IAC1G,IACE,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAAC;QAC9E,CAAC,CAAC,EAAE,KAAK,sBAAsB,IAAI,EAAE,KAAK,sBAAsB,CAAC,EACjE,CAAC;QACD,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,SAAS;IACT,IAAI,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAAC;QAAE,OAAO,UAAU,CAAC;IAEtG,UAAU;IACV,IAAI,MAAM,CAAC,kBAAkB,KAAK,YAAY,IAAI,KAAK,CAAC,kBAAkB,KAAK,WAAW,IAAI,CAAC,qBAAqB,EAAE,CAAC;QACrH,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,UAAU;IACV,IAAI,MAAM,CAAC,kBAAkB,KAAK,WAAW,IAAI,KAAK,CAAC,kBAAkB,KAAK,YAAY;QAAE,OAAO,UAAU,CAAC;IAE9G,UAAU;IACV,IACE,mBAAmB;QACnB,EAAE,KAAK,EAAE;QACT,MAAM,CAAC,sBAAsB,KAAK,KAAK,CAAC,sBAAsB;QAC9D,MAAM,CAAC,kBAAkB,KAAK,KAAK,CAAC,kBAAkB;QACtD,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,EAChC,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,4HAA4H;AAC5H,MAAM,UAAU,4CAA4C,CAC1D,MAA4B,EAC5B,KAA2B;IAE3B,IAAI,MAAM,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU,EAAE,CAAC;QAC3C,MAAM,IAAI,eAAe,CACvB,qBAAqB,CAAC,4BAA4B,EAClD,oDAAoD,MAAM,CAAC,UAAU,WAAW,KAAK,CAAC,UAAU,IAAI,CACrG,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,mBAAmB,GAAG,4BAA4B,CAAC,UAAU,CAAC,KAAK,4BAA4B,CAAC,SAAS,CAAC,CAAC;IAEjH,MAAM,GAAG,GAAG,gBAAgB,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACnD,MAAM,GAAG,GAAG,gBAAgB,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAClD,MAAM,EAAE,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,EAAE,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,eAAe,GAAG,GAAG,KAAK,iBAAiB,IAAI,GAAG,KAAK,iBAAiB,CAAC;IAE/E,MAAM,eAAe,GAAG,uBAAuB,CAAC,MAAM,EAAE,KAAK,EAAE,mBAAmB,CAAC,CAAC;IAEpF,MAAM,SAAS,GAAG;QAChB,iBAAiB,EAAE,6BAA6B,CAAC,MAAM,CAAC;QACxD,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,sBAAsB,EAAE,MAAM,CAAC,sBAAsB;QACrD,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;KAC9C,CAAC;IACF,MAAM,WAAW,GAAG;QAClB,iBAAiB,EAAE,6BAA6B,CAAC,KAAK,CAAC;QACvD,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,sBAAsB,EAAE,KAAK,CAAC,sBAAsB;QACpD,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;KAC7C,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,4BAA4B;QACrC,aAAa,EAAE,CAAC;QAChB,cAAc,EAAE,iCAAiC;QACjD,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,KAAK,EAAE,SAAS;QAChB,OAAO,EAAE,WAAW;QACpB,aAAa,EAAE;YACb,KAAK,EAAE,MAAM,CAAC,aAAa;YAC3B,OAAO,EAAE,KAAK,CAAC,aAAa;YAC5B,OAAO,EAAE,MAAM,CAAC,aAAa,KAAK,KAAK,CAAC,aAAa;SACtD;QACD,sBAAsB,EAAE;YACtB,KAAK,EAAE,MAAM,CAAC,sBAAsB;YACpC,OAAO,EAAE,KAAK,CAAC,sBAAsB;YACrC,OAAO,EAAE,MAAM,CAAC,sBAAsB,KAAK,KAAK,CAAC,sBAAsB;SACxE;QACD,kBAAkB,EAAE;YAClB,KAAK,EAAE,MAAM,CAAC,kBAAkB;YAChC,OAAO,EAAE,KAAK,CAAC,kBAAkB;YACjC,OAAO,EAAE,MAAM,CAAC,kBAAkB,KAAK,KAAK,CAAC,kBAAkB;SAChE;QACD,OAAO,EAAE;YACP,KAAK,EAAE,MAAM,CAAC,OAAO;YACrB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,OAAO,EAAE,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO;SAC1C;QACD,8BAA8B,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE;QACzE,mBAAmB;QACnB,WAAW,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE;QACnF,eAAe;QACf,eAAe;QACf,QAAQ,EAAE,WAAW,CAAC,eAAe,CAAC;QACtC,qBAAqB,EAAE,wBAAwB,CAAC,eAAe,CAAC;QAChE,MAAM,EAAE,EAAE,GAAG,wBAAwB,EAAE;QACvC,YAAY,EAAE,EAAE,GAAG,2BAA2B,EAAE;KACjD,CAAC;AACJ,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,8BAA8B,CAAC,IAAmC;IAChF,MAAM,KAAK,GAAG;QACZ,+BAA+B,EAAE;QACjC,EAAE;QACF,IAAI,CAAC,QAAQ;QACb,EAAE;QACF,IAAI,CAAC,qBAAqB;QAC1B,EAAE;QACF,2BAA2B,IAAI,CAAC,eAAe,EAAE;QACjD,EAAE;QACF,yBAAyB,IAAI,CAAC,aAAa,CAAC,KAAK,YAAY,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE;QACzF,EAAE;QACF,yEAAyE;KAC1E,CAAC;IACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,oCAAoC,CAAC,IAAmC;IACtF,OAAO,uBAAuB,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=certificateVerificationDiff.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"certificateVerificationDiff.test.d.ts","sourceRoot":"","sources":["../src/certificateVerificationDiff.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,53 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { describe, expect, it } from "vitest";
5
+ import { CLI_OPERATIONAL_CODES } from "./cliOperationalCodes.js";
6
+ import { buildVerificationDiffFromOutcomeCertificates, stringifyVerificationDiffCertificate, } from "./certificateVerificationDiff.js";
7
+ import { loadSchemaValidator } from "./schemaLoad.js";
8
+ import { TruthLayerError } from "./truthLayerError.js";
9
+ const __dirname = dirname(fileURLToPath(import.meta.url));
10
+ const root = join(__dirname, "..");
11
+ const casesDir = join(root, "test/fixtures/certificate-diff/cases");
12
+ const expectedDir = join(root, "test/fixtures/certificate-diff/expected");
13
+ const FIXTURE_CASES = [
14
+ { base: "A.less_determinate", expectedFile: "A.less_determinate.verification-diff.json" },
15
+ { base: "B.improved", expectedFile: "B.improved.verification-diff.json" },
16
+ { base: "C.weakened", expectedFile: "C.weakened.verification-diff.json" },
17
+ { base: "D.improved", expectedFile: "D.improved.verification-diff.json" },
18
+ { base: "E.weakened", expectedFile: "E.weakened.verification-diff.json" },
19
+ { base: "F.rc_improved", expectedFile: "F.rc_improved.verification-diff.json" },
20
+ { base: "G.drifted_runkind", expectedFile: "G.drifted_runkind.verification-diff.json" },
21
+ { base: "H.drifted_evidence", expectedFile: "H.drifted_evidence.verification-diff.json" },
22
+ ];
23
+ describe("certificateVerificationDiff", () => {
24
+ const validateOutcome = loadSchemaValidator("outcome-certificate-v3");
25
+ const validateDiff = loadSchemaValidator("verification-diff-certificate-v1");
26
+ for (const { base, expectedFile } of FIXTURE_CASES) {
27
+ it(`golden ${base}`, () => {
28
+ const before = JSON.parse(readFileSync(join(casesDir, `${base}.before.json`), "utf8"));
29
+ const after = JSON.parse(readFileSync(join(casesDir, `${base}.after.json`), "utf8"));
30
+ expect(validateOutcome(before), JSON.stringify(validateOutcome.errors)).toBe(true);
31
+ expect(validateOutcome(after), JSON.stringify(validateOutcome.errors)).toBe(true);
32
+ const diff = buildVerificationDiffFromOutcomeCertificates(before, after);
33
+ expect(validateDiff(diff), JSON.stringify(validateDiff.errors)).toBe(true);
34
+ const expected = readFileSync(join(expectedDir, expectedFile), "utf8").trim();
35
+ expect(stringifyVerificationDiffCertificate(diff)).toBe(expected);
36
+ });
37
+ }
38
+ it("workflowId mismatch throws TruthLayerError COMPARE_WORKFLOW_ID_MISMATCH", () => {
39
+ const a = JSON.parse(readFileSync(join(casesDir, "A.less_determinate.before.json"), "utf8"));
40
+ const b = { ...a, workflowId: "other_wf" };
41
+ try {
42
+ buildVerificationDiffFromOutcomeCertificates(a, b);
43
+ expect.fail("expected throw");
44
+ }
45
+ catch (e) {
46
+ expect(e).toBeInstanceOf(TruthLayerError);
47
+ const err = e;
48
+ expect(err.code).toBe(CLI_OPERATIONAL_CODES.COMPARE_WORKFLOW_ID_MISMATCH);
49
+ expect(err.message).toBe("Compare certificates: workflowId differs (before=wf_fixture_diff, after=other_wf).");
50
+ }
51
+ });
52
+ });
53
+ //# sourceMappingURL=certificateVerificationDiff.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"certificateVerificationDiff.test.js","sourceRoot":"","sources":["../src/certificateVerificationDiff.test.ts"],"names":[],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { randomUUID } from "node:crypto";
3
- import { readFileSync, statSync, writeSync } from "fs";
3
+ import { existsSync, readFileSync, statSync, writeSync } from "fs";
4
4
  import path from "path";
5
5
  import { CLI_OPERATIONAL_CODES, cliErrorEnvelope, formatOperationalMessage, } from "./failureCatalog.js";
6
+ import { buildVerificationDiffFromOutcomeCertificates, buildVerificationDiffHumanText, stringifyVerificationDiffCertificate, } from "./certificateVerificationDiff.js";
6
7
  import { buildRegressionArtifactFromCompareManifest, stringifyRegressionArtifact } from "./regressionArtifact.js";
7
8
  import { assertValidRunEventParentGraph, buildExecutionTraceView, formatExecutionTraceText } from "./executionTrace.js";
8
9
  import { loadEventsForWorkflow } from "./loadEvents.js";
@@ -200,6 +201,9 @@ Exit codes:
200
201
  agentskeptic compare --manifest <compare-run-manifest.json>
201
202
  Compare runs from a manifest (workflow results + events paths; see docs/regression-artifact-normative.md).
202
203
 
204
+ agentskeptic compare certificates --before <prior.json> --after <current.json>
205
+ Compare two saved Outcome Certificate v3 JSON files (semantic projection only; see docs/agentskeptic.md).
206
+
203
207
  agentskeptic validate-registry --registry <path>
204
208
  agentskeptic validate-registry --registry <path> --events <path> --workflow-id <id>
205
209
  Validate tools registry JSON (and optionally resolution vs events) without a database.
@@ -467,6 +471,12 @@ function usageCompare() {
467
471
  Manifest schema: schemas/compare-run-manifest-v1.schema.json.
468
472
  Success: stdout is UTF-8 RegressionArtifactV1 JSON (sorted keys); stderr is artifact.humanText only.
469
473
 
474
+ agentskeptic compare certificates --before <prior.json> --after <current.json>
475
+
476
+ Validates both inputs as Outcome Certificate v3 (schemas/outcome-certificate-v3.schema.json).
477
+ Success: stdout is UTF-8 VerificationDiffCertificateV1 JSON (sorted keys); stderr is multi-line human text (not JSON).
478
+ Do not combine this form with --manifest.
479
+
470
480
  Exit codes:
471
481
  0 comparison succeeded
472
482
  3 operational failure (stderr: JSON envelope only; stdout empty)
@@ -1067,9 +1077,91 @@ function runCompareSubcommand(args) {
1067
1077
  console.log(usageCompare());
1068
1078
  process.exit(0);
1069
1079
  }
1070
- const manifestPath = argValue(args, "--manifest");
1071
- if (!manifestPath) {
1072
- writeCliError(CLI_OPERATIONAL_CODES.COMPARE_USAGE, "compare requires --manifest <path>.");
1080
+ const certSubcommand = args[0] === "certificates";
1081
+ const tail = certSubcommand ? args.slice(1) : args;
1082
+ const beforePath = argValue(tail, "--before");
1083
+ const afterPath = argValue(tail, "--after");
1084
+ const manifestPath = argValue(certSubcommand ? tail : args, "--manifest");
1085
+ const certPairRequested = beforePath !== undefined || afterPath !== undefined;
1086
+ if (certPairRequested && !certSubcommand) {
1087
+ writeCliError(CLI_OPERATIONAL_CODES.COMPARE_USAGE, "Outcome certificate compare requires: agentskeptic compare certificates --before <path> --after <path>.");
1088
+ process.exit(3);
1089
+ }
1090
+ if (certSubcommand) {
1091
+ if (manifestPath !== undefined) {
1092
+ writeCliError(CLI_OPERATIONAL_CODES.COMPARE_USAGE, "Do not combine `compare certificates` with --manifest.");
1093
+ process.exit(3);
1094
+ }
1095
+ if (beforePath === undefined || afterPath === undefined) {
1096
+ writeCliError(CLI_OPERATIONAL_CODES.COMPARE_USAGE, "compare certificates requires both --before <path> and --after <path>.");
1097
+ process.exit(3);
1098
+ }
1099
+ const validateOutcome = loadSchemaValidator("outcome-certificate-v3");
1100
+ const absBefore = path.resolve(beforePath);
1101
+ const absAfter = path.resolve(afterPath);
1102
+ let rawPrior;
1103
+ let rawCurrent;
1104
+ try {
1105
+ if (!existsSync(absBefore)) {
1106
+ throw new Error(`prior file not found: ${absBefore}`);
1107
+ }
1108
+ if (!existsSync(absAfter)) {
1109
+ throw new Error(`current file not found: ${absAfter}`);
1110
+ }
1111
+ rawPrior = readFileSync(absBefore, "utf8");
1112
+ rawCurrent = readFileSync(absAfter, "utf8");
1113
+ }
1114
+ catch (e) {
1115
+ const msg = e instanceof Error ? e.message : String(e);
1116
+ writeCliError(CLI_OPERATIONAL_CODES.COMPARE_INPUT_READ_FAILED, formatOperationalMessage(msg));
1117
+ process.exit(3);
1118
+ }
1119
+ let prior;
1120
+ let current;
1121
+ try {
1122
+ prior = JSON.parse(rawPrior);
1123
+ }
1124
+ catch (e) {
1125
+ const m = e instanceof Error ? e.message : String(e);
1126
+ writeCliError(CLI_OPERATIONAL_CODES.COMPARE_INPUT_JSON_SYNTAX, `prior: ${m}`);
1127
+ process.exit(3);
1128
+ }
1129
+ try {
1130
+ current = JSON.parse(rawCurrent);
1131
+ }
1132
+ catch (e) {
1133
+ const m = e instanceof Error ? e.message : String(e);
1134
+ writeCliError(CLI_OPERATIONAL_CODES.COMPARE_INPUT_JSON_SYNTAX, `current: ${m}`);
1135
+ process.exit(3);
1136
+ }
1137
+ if (!validateOutcome(prior)) {
1138
+ writeCliError(CLI_OPERATIONAL_CODES.COMPARE_INPUT_SCHEMA_INVALID, `prior: ${JSON.stringify(validateOutcome.errors ?? [])}`);
1139
+ process.exit(3);
1140
+ }
1141
+ if (!validateOutcome(current)) {
1142
+ writeCliError(CLI_OPERATIONAL_CODES.COMPARE_INPUT_SCHEMA_INVALID, `current: ${JSON.stringify(validateOutcome.errors ?? [])}`);
1143
+ process.exit(3);
1144
+ }
1145
+ let diff;
1146
+ try {
1147
+ diff = buildVerificationDiffFromOutcomeCertificates(prior, current);
1148
+ }
1149
+ catch (e) {
1150
+ if (e instanceof TruthLayerError) {
1151
+ writeCliError(e.code, e.message);
1152
+ process.exit(3);
1153
+ }
1154
+ const msg = e instanceof Error ? e.message : String(e);
1155
+ writeCliError(CLI_OPERATIONAL_CODES.INTERNAL_ERROR, formatOperationalMessage(msg));
1156
+ process.exit(3);
1157
+ }
1158
+ const human = buildVerificationDiffHumanText(diff);
1159
+ process.stderr.write(human.endsWith("\n") ? human : `${human}\n`);
1160
+ process.stdout.write(`${stringifyVerificationDiffCertificate(diff)}\n`);
1161
+ process.exit(0);
1162
+ }
1163
+ if (manifestPath === undefined) {
1164
+ writeCliError(CLI_OPERATIONAL_CODES.COMPARE_USAGE, "compare requires either --manifest <path> or `compare certificates --before … --after …`.");
1073
1165
  process.exit(3);
1074
1166
  }
1075
1167
  let artifact;