@mmnto/totem 1.92.0 → 1.93.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.
@@ -0,0 +1,1088 @@
1
+ /**
2
+ * Verdict-artifact contract — the single convergence point both review lanes
3
+ * emit (mmnto-ai/totem#2106, Proposal 302 / 304 R2 local review runner).
4
+ *
5
+ * A verdict artifact is the immutable, content-addressed record of ONE review
6
+ * round over ONE masked diff: the fan of lanes that attempted it (each a
7
+ * terminal {@link RunArtifact} reference, one hop from provenance), the
8
+ * deterministic #2103 post-checks, the normalized findings, the optional #2104
9
+ * panel it assembled, and the derived round/lineage bookkeeping. Everything
10
+ * downstream (the CLI round loop, the pilot ledger's covariate PR-line, the
11
+ * Phase-2 disposition ledger) consumes this shape, so it stays minimal but
12
+ * versioned.
13
+ *
14
+ * ── LANE-BLINDNESS INVARIANT (Proposal 302, DELIBERATE EXCLUSION) ────────────
15
+ * There is NO warm/cold runner-lane discriminator field ANYWHERE in this schema
16
+ * — not at the top level, not on a lane. This exclusion is deliberate: a
17
+ * contract consumer reads the verdict and CANNOT discriminate WHICH runner lane
18
+ * (a warm resident agent vs a cold SDK invocation) produced it. The wording
19
+ * matters (strategy 1a): "consumers cannot discriminate lanes FROM the
20
+ * artifact", NOT "lane identity is unknowable" — `lanes[].runArtifactHash`
21
+ * reaches provenance one hop away and `resolvedBackend` is panel-DIVERSITY data,
22
+ * neither of which is a warm/cold runner discriminator. The absence is enforced
23
+ * by a structural test (snapshots the key set) IN ADDITION to this note.
24
+ *
25
+ * The KEY-set structural test is not enough on its own: a runner class could be
26
+ * smuggled through a laneId VALUE. So `laneId` is additionally constrained to a
27
+ * backend-derived vocabulary — `lane-<index>:<resolvedBackendOrConfiguredLane>`
28
+ * (see {@link LaneIdSchema}) — with a refinement rejecting warm/cold/headless/
29
+ * sdk-runner substrings (strategy-codex G1). Net invariant: a consumer can
30
+ * identify WHICH backend participated (diversity), NEVER whether the producer was
31
+ * warm / cold / headless.
32
+ *
33
+ * Schema-evolution policy mirrors {@link RunArtifactSchema} / the panel artifact
34
+ * (F1): the reader is version-tolerant WITHIN the major — `schemaVersion`
35
+ * validates as `1.x`, every post-1.0.0 field is additive-optional, and a MAJOR
36
+ * bump requires a migration entry in `loadVerdictArtifact` before the writer
37
+ * ships. Hard-reject only unknown majors. Zod is the persisted-JSON boundary
38
+ * (read back from disk), per the repo's Zod-at-boundaries-only rule.
39
+ */
40
+ import { z } from 'zod';
41
+ import { type PersistedPostCheckFinding } from './panel.js';
42
+ /** The verdict schemaVersion WRITTEN by this code. Readers accept any 1.x (F1). */
43
+ export declare const VERDICT_ARTIFACT_SCHEMA_VERSION = "1.0.0";
44
+ /** The major this reader understands; other majors need a migration entry. */
45
+ export declare const VERDICT_ARTIFACT_KNOWN_MAJOR = 1;
46
+ /**
47
+ * The four `getDiffForReview` sources. Canonical order matches the design doc.
48
+ */
49
+ export declare const VERDICT_DIFF_SOURCES: readonly ["explicit-range", "staged", "uncommitted", "branch-vs-base"];
50
+ export type VerdictDiffSource = (typeof VERDICT_DIFF_SOURCES)[number];
51
+ /**
52
+ * The reviewed diff's scope, DISCRIMINATED by `source`. `diffHash` is ALWAYS
53
+ * required (sha256 over the MASKED review-payload bytes the lanes actually
54
+ * reviewed — hash symmetry with the artifact chain, never binds secret-bearing
55
+ * bytes; agy fold 5). The git ref fields are required only where the source
56
+ * makes them meaningful:
57
+ * - `explicit-range` — `base` AND `head` (the two endpoints).
58
+ * - `branch-vs-base` — `base` only (head is the working ref, implicit).
59
+ * - `staged` / `uncommitted` — NO refs (the index / worktree has none).
60
+ */
61
+ export declare const VerdictDiffScopeSchema: z.ZodDiscriminatedUnion<"source", [z.ZodObject<{
62
+ source: z.ZodLiteral<"explicit-range">;
63
+ diffHash: z.ZodString;
64
+ base: z.ZodString;
65
+ head: z.ZodString;
66
+ }, "strip", z.ZodTypeAny, {
67
+ source: "explicit-range";
68
+ diffHash: string;
69
+ base: string;
70
+ head: string;
71
+ }, {
72
+ source: "explicit-range";
73
+ diffHash: string;
74
+ base: string;
75
+ head: string;
76
+ }>, z.ZodObject<{
77
+ source: z.ZodLiteral<"branch-vs-base">;
78
+ diffHash: z.ZodString;
79
+ base: z.ZodString;
80
+ }, "strip", z.ZodTypeAny, {
81
+ source: "branch-vs-base";
82
+ diffHash: string;
83
+ base: string;
84
+ }, {
85
+ source: "branch-vs-base";
86
+ diffHash: string;
87
+ base: string;
88
+ }>, z.ZodObject<{
89
+ source: z.ZodLiteral<"staged">;
90
+ diffHash: z.ZodString;
91
+ }, "strip", z.ZodTypeAny, {
92
+ source: "staged";
93
+ diffHash: string;
94
+ }, {
95
+ source: "staged";
96
+ diffHash: string;
97
+ }>, z.ZodObject<{
98
+ source: z.ZodLiteral<"uncommitted">;
99
+ diffHash: z.ZodString;
100
+ }, "strip", z.ZodTypeAny, {
101
+ source: "uncommitted";
102
+ diffHash: string;
103
+ }, {
104
+ source: "uncommitted";
105
+ diffHash: string;
106
+ }>]>;
107
+ export type VerdictDiffScope = z.infer<typeof VerdictDiffScopeSchema>;
108
+ /**
109
+ * Typed terminal-failure reasons for a `failed` lane. A failed lane is never
110
+ * handed to `assemblePanelArtifact` and never stamps the cache. NOTE (Prop 302
111
+ * lane-blindness): these classify the FAILURE, never the runner lane — none of
112
+ * them names warm/cold.
113
+ */
114
+ export declare const VERDICT_LANE_FAILURE_REASONS: readonly ["invoke-error", "quota-exhausted", "missing-artifact-emission", "config-error"];
115
+ export type VerdictLaneFailureReason = (typeof VERDICT_LANE_FAILURE_REASONS)[number];
116
+ /** A `completed` lane's own severity tally (from its extracted structured verdict). */
117
+ export declare const VerdictLaneSummarySchema: z.ZodObject<{
118
+ critical: z.ZodNumber;
119
+ warn: z.ZodNumber;
120
+ info: z.ZodNumber;
121
+ }, "strip", z.ZodTypeAny, {
122
+ warn: number;
123
+ info: number;
124
+ critical: number;
125
+ }, {
126
+ warn: number;
127
+ info: number;
128
+ critical: number;
129
+ }>;
130
+ export type VerdictLaneSummary = z.infer<typeof VerdictLaneSummarySchema>;
131
+ /**
132
+ * The EXACT laneId shape — `lane-<index>:<resolvedBackendOrConfiguredLane>`:
133
+ * - `lane-` literal prefix,
134
+ * - `<index>` — the lane's zero-based position in the fan (`\d+`),
135
+ * - `:` separator,
136
+ * - `<resolvedBackendOrConfiguredLane>` — the resolved backend (`provider:model`,
137
+ * which itself carries a colon) for a lane that reached a backend, or the
138
+ * CONFIGURED lane string for a lane that failed before one resolved. Non-empty,
139
+ * opaque backend/lane text (`.+` — newlines excluded).
140
+ *
141
+ * This is backend-DERIVED vocabulary: a consumer can read the id and identify
142
+ * WHICH backend participated (panel-diversity data), and NOTHING about whether the
143
+ * producer was warm / cold / headless.
144
+ */
145
+ export declare const LANE_ID_SHAPE_RE: RegExp;
146
+ /**
147
+ * laneId: shape-validated here; the VALUE channel of lane-blindness (Prop 302
148
+ * G1) is closed STRUCTURALLY by the schema's superRefine — every lane's suffix
149
+ * must equal its binding field (`resolvedBackend` for completed/abstained,
150
+ * `configuredLane` for failed), so a laneId cannot carry free text at all and a
151
+ * runner class (`warm`/`cold`/`headless`) has no channel to ride. An earlier
152
+ * substring blacklist here was removed: with structural binding as the primary
153
+ * guard it added only false-positive risk against legitimate future model names
154
+ * (e.g. a model literally named `*-cold-*`; PR #2337 greptile P2).
155
+ */
156
+ export declare const LaneIdSchema: z.ZodString;
157
+ /**
158
+ * One lane's terminal outcome, DISCRIMINATED by `status`. The union makes
159
+ * impossible records unrepresentable (codex fold 2): a `completed` lane STRUCTURALLY
160
+ * requires its `runArtifactHash` (a response-cache hit emits no run artifact and so
161
+ * can never be `completed`); a `failed` lane carries a typed reason and never a
162
+ * `runArtifactHash`. `resolvedBackend` records what actually ran (post quota
163
+ * fallback) and is panel-diversity data — NOT a runner discriminator.
164
+ */
165
+ export declare const VerdictLaneSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<{
166
+ status: z.ZodLiteral<"completed">;
167
+ laneId: z.ZodString;
168
+ resolvedBackend: z.ZodString;
169
+ runArtifactHash: z.ZodString;
170
+ verdictSummary: z.ZodObject<{
171
+ critical: z.ZodNumber;
172
+ warn: z.ZodNumber;
173
+ info: z.ZodNumber;
174
+ }, "strip", z.ZodTypeAny, {
175
+ warn: number;
176
+ info: number;
177
+ critical: number;
178
+ }, {
179
+ warn: number;
180
+ info: number;
181
+ critical: number;
182
+ }>;
183
+ }, "strip", z.ZodTypeAny, {
184
+ status: "completed";
185
+ laneId: string;
186
+ resolvedBackend: string;
187
+ runArtifactHash: string;
188
+ verdictSummary: {
189
+ warn: number;
190
+ info: number;
191
+ critical: number;
192
+ };
193
+ }, {
194
+ status: "completed";
195
+ laneId: string;
196
+ resolvedBackend: string;
197
+ runArtifactHash: string;
198
+ verdictSummary: {
199
+ warn: number;
200
+ info: number;
201
+ critical: number;
202
+ };
203
+ }>, z.ZodObject<{
204
+ status: z.ZodLiteral<"abstained">;
205
+ laneId: z.ZodString;
206
+ resolvedBackend: z.ZodString;
207
+ runArtifactHash: z.ZodString;
208
+ /** Why no usable structured verdict was extractable (invoke happened, output unparseable). */
209
+ reason: z.ZodString;
210
+ }, "strip", z.ZodTypeAny, {
211
+ status: "abstained";
212
+ reason: string;
213
+ laneId: string;
214
+ resolvedBackend: string;
215
+ runArtifactHash: string;
216
+ }, {
217
+ status: "abstained";
218
+ reason: string;
219
+ laneId: string;
220
+ resolvedBackend: string;
221
+ runArtifactHash: string;
222
+ }>, z.ZodObject<{
223
+ status: z.ZodLiteral<"failed">;
224
+ laneId: z.ZodString;
225
+ typedReason: z.ZodEnum<["invoke-error", "quota-exhausted", "missing-artifact-emission", "config-error"]>;
226
+ /**
227
+ * REQUIRED (rev-6 item 3): the configured `provider:model` string the lane was
228
+ * created from. A failed lane can have NO `resolvedBackend` (it failed before a
229
+ * backend resolved — e.g. `config-error` / `missing-artifact-emission`), so the
230
+ * laneId suffix has nothing to bind to unless the configured lane is persisted.
231
+ * The `superRefine` binds `laneId` suffix === `configuredLane` (closing the
232
+ * `lane-0:gemini:completely-invented` tautology): the suffix is no longer free —
233
+ * it must equal this declared field.
234
+ */
235
+ configuredLane: z.ZodString;
236
+ /**
237
+ * OPTIONAL supplementary provenance: the backend that ACTUALLY ran before the
238
+ * lane failed (present only when a backend resolved — e.g. a quota fallback that
239
+ * then failed). NOT the id binding: after a quota fallback it can legitimately
240
+ * DIFFER from `configuredLane`, so the laneId suffix binds to `configuredLane`
241
+ * (stable at lane creation), never to this field.
242
+ */
243
+ resolvedBackend: z.ZodOptional<z.ZodString>;
244
+ }, "strip", z.ZodTypeAny, {
245
+ status: "failed";
246
+ laneId: string;
247
+ typedReason: "invoke-error" | "quota-exhausted" | "missing-artifact-emission" | "config-error";
248
+ configuredLane: string;
249
+ resolvedBackend?: string | undefined;
250
+ }, {
251
+ status: "failed";
252
+ laneId: string;
253
+ typedReason: "invoke-error" | "quota-exhausted" | "missing-artifact-emission" | "config-error";
254
+ configuredLane: string;
255
+ resolvedBackend?: string | undefined;
256
+ }>]>;
257
+ export type VerdictLane = z.infer<typeof VerdictLaneSchema>;
258
+ /** Severity vocabulary — aligned VERBATIM with cli `ShieldFindingSeveritySchema` (defined here so core stays cli-independent). */
259
+ export declare const VerdictFindingSeveritySchema: z.ZodEnum<["CRITICAL", "WARN", "INFO"]>;
260
+ export type VerdictFindingSeverity = z.infer<typeof VerdictFindingSeveritySchema>;
261
+ /**
262
+ * A normalized finding from the shared review-output extractor. Field names
263
+ * align with cli `ShieldFinding` (`severity` / `confidence` / `message` /
264
+ * `file` / `line`); `confidence` is optional here because not every extracted
265
+ * lane output carries one, but when present it is a 0..1 probability (same
266
+ * bound as ShieldFinding). The diagnostic `message` is NEVER dropped or
267
+ * renamed.
268
+ */
269
+ export declare const VerdictFindingSchema: z.ZodObject<{
270
+ severity: z.ZodEnum<["CRITICAL", "WARN", "INFO"]>;
271
+ confidence: z.ZodOptional<z.ZodNumber>;
272
+ file: z.ZodOptional<z.ZodString>;
273
+ line: z.ZodOptional<z.ZodNumber>;
274
+ message: z.ZodString;
275
+ }, "strip", z.ZodTypeAny, {
276
+ message: string;
277
+ severity: "CRITICAL" | "WARN" | "INFO";
278
+ confidence?: number | undefined;
279
+ file?: string | undefined;
280
+ line?: number | undefined;
281
+ }, {
282
+ message: string;
283
+ severity: "CRITICAL" | "WARN" | "INFO";
284
+ confidence?: number | undefined;
285
+ file?: string | undefined;
286
+ line?: number | undefined;
287
+ }>;
288
+ export type VerdictFinding = z.infer<typeof VerdictFindingSchema>;
289
+ /**
290
+ * Round bookkeeping (all DERIVED — see the CLI lifecycle). `lineageKey` is the
291
+ * composite hash over the RESOLVED scope selector (see {@link computeLineageKey}
292
+ * — worktree identity + branch + source + the meaningful range selectors), NOT
293
+ * the diff bytes, so legitimate fix rounds still chain; `priorVerdictHash` links
294
+ * the implicit prior round (latest verdict sharing the lineage key) or an
295
+ * explicit `--continues` override; absent at round 0.
296
+ */
297
+ export declare const VerdictRoundSchema: z.ZodObject<{
298
+ index: z.ZodNumber;
299
+ priorVerdictHash: z.ZodOptional<z.ZodString>;
300
+ lineageKey: z.ZodString;
301
+ }, "strip", z.ZodTypeAny, {
302
+ index: number;
303
+ lineageKey: string;
304
+ priorVerdictHash?: string | undefined;
305
+ }, {
306
+ index: number;
307
+ lineageKey: string;
308
+ priorVerdictHash?: string | undefined;
309
+ }>;
310
+ export type VerdictRound = z.infer<typeof VerdictRoundSchema>;
311
+ /**
312
+ * The subset of a verdict the pure predicates read. The persisted boundary AND
313
+ * every CLI caller derive `settled` / cache-eligibility from THESE fields — the
314
+ * stored `settled` boolean is re-derived and checked at parse, never trusted
315
+ * (totem-codex finding 5). `findings` is the exemption-FILTERED union the CLI
316
+ * lands on the artifact; the R2 severity map is pinned `INFO = cosmetic`,
317
+ * `WARN | CRITICAL = actionable`.
318
+ */
319
+ export interface VerdictPredicateInput {
320
+ lanes: readonly VerdictLane[];
321
+ findings: readonly VerdictFinding[];
322
+ postChecks: readonly PersistedPostCheckFinding[];
323
+ reviewedState: 'matched' | 'drifted';
324
+ }
325
+ /**
326
+ * `settled` — the current-round dryness predicate, PURE over artifact content (no
327
+ * cross-round input, no model output):
328
+ *
329
+ * settled = (every attempted lane completed)
330
+ * AND (zero actionable — WARN|CRITICAL — findings)
331
+ * AND (no decidable-tier post-check row with verdict 'fail')
332
+ * AND (reviewedState === 'matched')
333
+ *
334
+ * A failed/abstained lane ⇒ fan incomplete ⇒ never settled (a persistent CRITICAL
335
+ * can never settle by lane dropout — agy fold 1, satisfied structurally); drift ⇒
336
+ * the verdict is bound to the pre-fan diff and does NOT cover the current tree ⇒
337
+ * not settled (codex rev-2 fold 1). This export is the SINGLE SOURCE OF TRUTH: the
338
+ * CLI derives its loop-termination signal from it and {@link VerdictArtifactSchema}
339
+ * re-derives + checks the stored `settled` (finding 5) — a crafted lane output
340
+ * cannot flip it (pure function; the exemption filter is the only removal
341
+ * mechanism, upstream of this boundary).
342
+ */
343
+ export declare function deriveSettled(v: VerdictPredicateInput): boolean;
344
+ /**
345
+ * Cache eligibility — the DISTINCT, weaker predicate (codex fold 4). Identical to
346
+ * {@link deriveSettled} except it tolerates WARNs (matching today's PASS
347
+ * semantics — the drip class the runner absorbs is WARN-shaped):
348
+ *
349
+ * cacheEligible = (every attempted lane completed)
350
+ * AND (zero CRITICAL findings)
351
+ * AND (no decidable-tier post-check row with verdict 'fail')
352
+ * AND (reviewedState === 'matched')
353
+ *
354
+ * A degraded fan (any failed/abstained lane) fails the first conjunct and is
355
+ * therefore never cache-eligible; drift blocks the stamp. `settled` (no WARNs) is
356
+ * deliberately STRICTER than cache-eligible (no CRITICALs).
357
+ */
358
+ export declare function deriveCacheEligible(v: VerdictPredicateInput): boolean;
359
+ /**
360
+ * The verdict artifact. See the module docstring for the LANE-BLINDNESS
361
+ * invariant (Prop 302): NO warm/cold runner-lane discriminator field exists,
362
+ * deliberately.
363
+ *
364
+ * `superRefine` enforces the cross-field invariants that a hand-edited or
365
+ * builder-buggy record could otherwise violate silently — mirrored counts are
366
+ * NEVER accepted on trust (codex):
367
+ * - `attemptedLaneCount === lanes.length`; `completedLaneCount === #completed`.
368
+ * - lanes nonempty, laneIds unique (finding 9c).
369
+ * - panel ⟺ diversity AND panel ⟺ ≥2 completed lanes, BOTH directions
370
+ * (finding 9a): a panel is assembled from — and only from — ≥2 usable lanes,
371
+ * and always emits its diversity summary.
372
+ * - round-chain shape (finding 9b): `round.index === 0` ⟺ `priorVerdictHash`
373
+ * absent (round 0 starts a chain; round N>0 links its prior).
374
+ * - stored `settled === deriveSettled(value)` (finding 5): the persisted
375
+ * boundary re-derives the dryness predicate, never trusting a fabricated flag.
376
+ */
377
+ export declare const VerdictArtifactSchema: z.ZodEffects<z.ZodObject<{
378
+ schemaVersion: z.ZodEffects<z.ZodString, string, string>;
379
+ /** The reviewed diff's scope + masked-payload hash (source-discriminated). */
380
+ diffScope: z.ZodDiscriminatedUnion<"source", [z.ZodObject<{
381
+ source: z.ZodLiteral<"explicit-range">;
382
+ diffHash: z.ZodString;
383
+ base: z.ZodString;
384
+ head: z.ZodString;
385
+ }, "strip", z.ZodTypeAny, {
386
+ source: "explicit-range";
387
+ diffHash: string;
388
+ base: string;
389
+ head: string;
390
+ }, {
391
+ source: "explicit-range";
392
+ diffHash: string;
393
+ base: string;
394
+ head: string;
395
+ }>, z.ZodObject<{
396
+ source: z.ZodLiteral<"branch-vs-base">;
397
+ diffHash: z.ZodString;
398
+ base: z.ZodString;
399
+ }, "strip", z.ZodTypeAny, {
400
+ source: "branch-vs-base";
401
+ diffHash: string;
402
+ base: string;
403
+ }, {
404
+ source: "branch-vs-base";
405
+ diffHash: string;
406
+ base: string;
407
+ }>, z.ZodObject<{
408
+ source: z.ZodLiteral<"staged">;
409
+ diffHash: z.ZodString;
410
+ }, "strip", z.ZodTypeAny, {
411
+ source: "staged";
412
+ diffHash: string;
413
+ }, {
414
+ source: "staged";
415
+ diffHash: string;
416
+ }>, z.ZodObject<{
417
+ source: z.ZodLiteral<"uncommitted">;
418
+ diffHash: z.ZodString;
419
+ }, "strip", z.ZodTypeAny, {
420
+ source: "uncommitted";
421
+ diffHash: string;
422
+ }, {
423
+ source: "uncommitted";
424
+ diffHash: string;
425
+ }>]>;
426
+ /** Every attempted lane's terminal outcome (status-discriminated union). */
427
+ lanes: z.ZodArray<z.ZodDiscriminatedUnion<"status", [z.ZodObject<{
428
+ status: z.ZodLiteral<"completed">;
429
+ laneId: z.ZodString;
430
+ resolvedBackend: z.ZodString;
431
+ runArtifactHash: z.ZodString;
432
+ verdictSummary: z.ZodObject<{
433
+ critical: z.ZodNumber;
434
+ warn: z.ZodNumber;
435
+ info: z.ZodNumber;
436
+ }, "strip", z.ZodTypeAny, {
437
+ warn: number;
438
+ info: number;
439
+ critical: number;
440
+ }, {
441
+ warn: number;
442
+ info: number;
443
+ critical: number;
444
+ }>;
445
+ }, "strip", z.ZodTypeAny, {
446
+ status: "completed";
447
+ laneId: string;
448
+ resolvedBackend: string;
449
+ runArtifactHash: string;
450
+ verdictSummary: {
451
+ warn: number;
452
+ info: number;
453
+ critical: number;
454
+ };
455
+ }, {
456
+ status: "completed";
457
+ laneId: string;
458
+ resolvedBackend: string;
459
+ runArtifactHash: string;
460
+ verdictSummary: {
461
+ warn: number;
462
+ info: number;
463
+ critical: number;
464
+ };
465
+ }>, z.ZodObject<{
466
+ status: z.ZodLiteral<"abstained">;
467
+ laneId: z.ZodString;
468
+ resolvedBackend: z.ZodString;
469
+ runArtifactHash: z.ZodString;
470
+ /** Why no usable structured verdict was extractable (invoke happened, output unparseable). */
471
+ reason: z.ZodString;
472
+ }, "strip", z.ZodTypeAny, {
473
+ status: "abstained";
474
+ reason: string;
475
+ laneId: string;
476
+ resolvedBackend: string;
477
+ runArtifactHash: string;
478
+ }, {
479
+ status: "abstained";
480
+ reason: string;
481
+ laneId: string;
482
+ resolvedBackend: string;
483
+ runArtifactHash: string;
484
+ }>, z.ZodObject<{
485
+ status: z.ZodLiteral<"failed">;
486
+ laneId: z.ZodString;
487
+ typedReason: z.ZodEnum<["invoke-error", "quota-exhausted", "missing-artifact-emission", "config-error"]>;
488
+ /**
489
+ * REQUIRED (rev-6 item 3): the configured `provider:model` string the lane was
490
+ * created from. A failed lane can have NO `resolvedBackend` (it failed before a
491
+ * backend resolved — e.g. `config-error` / `missing-artifact-emission`), so the
492
+ * laneId suffix has nothing to bind to unless the configured lane is persisted.
493
+ * The `superRefine` binds `laneId` suffix === `configuredLane` (closing the
494
+ * `lane-0:gemini:completely-invented` tautology): the suffix is no longer free —
495
+ * it must equal this declared field.
496
+ */
497
+ configuredLane: z.ZodString;
498
+ /**
499
+ * OPTIONAL supplementary provenance: the backend that ACTUALLY ran before the
500
+ * lane failed (present only when a backend resolved — e.g. a quota fallback that
501
+ * then failed). NOT the id binding: after a quota fallback it can legitimately
502
+ * DIFFER from `configuredLane`, so the laneId suffix binds to `configuredLane`
503
+ * (stable at lane creation), never to this field.
504
+ */
505
+ resolvedBackend: z.ZodOptional<z.ZodString>;
506
+ }, "strip", z.ZodTypeAny, {
507
+ status: "failed";
508
+ laneId: string;
509
+ typedReason: "invoke-error" | "quota-exhausted" | "missing-artifact-emission" | "config-error";
510
+ configuredLane: string;
511
+ resolvedBackend?: string | undefined;
512
+ }, {
513
+ status: "failed";
514
+ laneId: string;
515
+ typedReason: "invoke-error" | "quota-exhausted" | "missing-artifact-emission" | "config-error";
516
+ configuredLane: string;
517
+ resolvedBackend?: string | undefined;
518
+ }>]>, "many">;
519
+ /** MUST equal `lanes.length` (validated below — never trusted). */
520
+ attemptedLaneCount: z.ZodNumber;
521
+ /** MUST equal the count of `completed` lanes (validated below — never trusted). */
522
+ completedLaneCount: z.ZodNumber;
523
+ /** Present IFF a #2104 panel was actually assembled (≥2 completed lanes; guarded below). */
524
+ panelArtifactHash: z.ZodOptional<z.ZodString>;
525
+ /** Deterministic #2103 post-checks — the persisted vocabulary VERBATIM (`ruleName`/`tier`/`verdict`/`message`). */
526
+ postChecks: z.ZodArray<z.ZodObject<{
527
+ ruleName: z.ZodString;
528
+ tier: z.ZodEnum<["decidable", "sensor"]>;
529
+ verdict: z.ZodEnum<["pass", "fail", "abstain"]>;
530
+ message: z.ZodString;
531
+ }, "strip", z.ZodTypeAny, {
532
+ message: string;
533
+ tier: "decidable" | "sensor";
534
+ ruleName: string;
535
+ verdict: "pass" | "fail" | "abstain";
536
+ }, {
537
+ message: string;
538
+ tier: "decidable" | "sensor";
539
+ ruleName: string;
540
+ verdict: "pass" | "fail" | "abstain";
541
+ }>, "many">;
542
+ /** Normalized findings from the shared extractor (exemption-filtered by the CLI before it lands here). */
543
+ findings: z.ZodArray<z.ZodObject<{
544
+ severity: z.ZodEnum<["CRITICAL", "WARN", "INFO"]>;
545
+ confidence: z.ZodOptional<z.ZodNumber>;
546
+ file: z.ZodOptional<z.ZodString>;
547
+ line: z.ZodOptional<z.ZodNumber>;
548
+ message: z.ZodString;
549
+ }, "strip", z.ZodTypeAny, {
550
+ message: string;
551
+ severity: "CRITICAL" | "WARN" | "INFO";
552
+ confidence?: number | undefined;
553
+ file?: string | undefined;
554
+ line?: number | undefined;
555
+ }, {
556
+ message: string;
557
+ severity: "CRITICAL" | "WARN" | "INFO";
558
+ confidence?: number | undefined;
559
+ file?: string | undefined;
560
+ line?: number | undefined;
561
+ }>, "many">;
562
+ /** A SINGLE top-level panel-diversity summary (classifyDiversity output) — present only with a panel; NEVER mirrored per finding. */
563
+ diversity: z.ZodOptional<z.ZodObject<{
564
+ providers: z.ZodArray<z.ZodString, "many">;
565
+ distinctProviders: z.ZodNumber;
566
+ class: z.ZodEnum<["cross-vendor", "same-vendor-isolated"]>;
567
+ unrecognizedProviders: z.ZodArray<z.ZodString, "many">;
568
+ diversityConfidence: z.ZodEnum<["verified", "coarse"]>;
569
+ }, "strip", z.ZodTypeAny, {
570
+ class: "cross-vendor" | "same-vendor-isolated";
571
+ providers: string[];
572
+ distinctProviders: number;
573
+ unrecognizedProviders: string[];
574
+ diversityConfidence: "verified" | "coarse";
575
+ }, {
576
+ class: "cross-vendor" | "same-vendor-isolated";
577
+ providers: string[];
578
+ distinctProviders: number;
579
+ unrecognizedProviders: string[];
580
+ diversityConfidence: "verified" | "coarse";
581
+ }>>;
582
+ round: z.ZodObject<{
583
+ index: z.ZodNumber;
584
+ priorVerdictHash: z.ZodOptional<z.ZodString>;
585
+ lineageKey: z.ZodString;
586
+ }, "strip", z.ZodTypeAny, {
587
+ index: number;
588
+ lineageKey: string;
589
+ priorVerdictHash?: string | undefined;
590
+ }, {
591
+ index: number;
592
+ lineageKey: string;
593
+ priorVerdictHash?: string | undefined;
594
+ }>;
595
+ /**
596
+ * Post-fan tree compare against the PRE-fan content hash (codex rev-2 fold 1):
597
+ * `'matched'` when the tracked-source tree is byte-identical before and after
598
+ * the fan, `'drifted'` when it changed mid-fan. A DERIVED, non-sentinel field
599
+ * (the two hash domains stay separate — this records the OUTCOME of the compare,
600
+ * not the content hash itself). Drift forces `settled=false` and blocks the
601
+ * cache stamp: the verdict is bound to the pre-fan diff, so a dry fan over a
602
+ * mutated tree does NOT cover the current tree and must not settle the loop.
603
+ */
604
+ reviewedState: z.ZodEnum<["matched", "drifted"]>;
605
+ /** Current-round dryness predicate (see the CLI lifecycle) — pure over artifact content. */
606
+ settled: z.ZodBoolean;
607
+ /**
608
+ * ISO-8601 emission time — a VALIDATED datetime (rev-5 item 8): a malformed
609
+ * `createdAt` is rejected at the persisted boundary rather than trusted.
610
+ * EXCLUDED from the content address (identical rounds dedup to one artifact
611
+ * regardless of when they ran) — observability only, and it is never a
612
+ * lineage tie-breaker (see {@link findLatestVerdictForLineage}). See
613
+ * {@link computeVerdictArtifactContentHash}.
614
+ */
615
+ createdAt: z.ZodString;
616
+ }, "strip", z.ZodTypeAny, {
617
+ createdAt: string;
618
+ diffScope: {
619
+ source: "explicit-range";
620
+ diffHash: string;
621
+ base: string;
622
+ head: string;
623
+ } | {
624
+ source: "branch-vs-base";
625
+ diffHash: string;
626
+ base: string;
627
+ } | {
628
+ source: "staged";
629
+ diffHash: string;
630
+ } | {
631
+ source: "uncommitted";
632
+ diffHash: string;
633
+ };
634
+ schemaVersion: string;
635
+ lanes: ({
636
+ status: "completed";
637
+ laneId: string;
638
+ resolvedBackend: string;
639
+ runArtifactHash: string;
640
+ verdictSummary: {
641
+ warn: number;
642
+ info: number;
643
+ critical: number;
644
+ };
645
+ } | {
646
+ status: "abstained";
647
+ reason: string;
648
+ laneId: string;
649
+ resolvedBackend: string;
650
+ runArtifactHash: string;
651
+ } | {
652
+ status: "failed";
653
+ laneId: string;
654
+ typedReason: "invoke-error" | "quota-exhausted" | "missing-artifact-emission" | "config-error";
655
+ configuredLane: string;
656
+ resolvedBackend?: string | undefined;
657
+ })[];
658
+ findings: {
659
+ message: string;
660
+ severity: "CRITICAL" | "WARN" | "INFO";
661
+ confidence?: number | undefined;
662
+ file?: string | undefined;
663
+ line?: number | undefined;
664
+ }[];
665
+ attemptedLaneCount: number;
666
+ completedLaneCount: number;
667
+ postChecks: {
668
+ message: string;
669
+ tier: "decidable" | "sensor";
670
+ ruleName: string;
671
+ verdict: "pass" | "fail" | "abstain";
672
+ }[];
673
+ round: {
674
+ index: number;
675
+ lineageKey: string;
676
+ priorVerdictHash?: string | undefined;
677
+ };
678
+ reviewedState: "matched" | "drifted";
679
+ settled: boolean;
680
+ diversity?: {
681
+ class: "cross-vendor" | "same-vendor-isolated";
682
+ providers: string[];
683
+ distinctProviders: number;
684
+ unrecognizedProviders: string[];
685
+ diversityConfidence: "verified" | "coarse";
686
+ } | undefined;
687
+ panelArtifactHash?: string | undefined;
688
+ }, {
689
+ createdAt: string;
690
+ diffScope: {
691
+ source: "explicit-range";
692
+ diffHash: string;
693
+ base: string;
694
+ head: string;
695
+ } | {
696
+ source: "branch-vs-base";
697
+ diffHash: string;
698
+ base: string;
699
+ } | {
700
+ source: "staged";
701
+ diffHash: string;
702
+ } | {
703
+ source: "uncommitted";
704
+ diffHash: string;
705
+ };
706
+ schemaVersion: string;
707
+ lanes: ({
708
+ status: "completed";
709
+ laneId: string;
710
+ resolvedBackend: string;
711
+ runArtifactHash: string;
712
+ verdictSummary: {
713
+ warn: number;
714
+ info: number;
715
+ critical: number;
716
+ };
717
+ } | {
718
+ status: "abstained";
719
+ reason: string;
720
+ laneId: string;
721
+ resolvedBackend: string;
722
+ runArtifactHash: string;
723
+ } | {
724
+ status: "failed";
725
+ laneId: string;
726
+ typedReason: "invoke-error" | "quota-exhausted" | "missing-artifact-emission" | "config-error";
727
+ configuredLane: string;
728
+ resolvedBackend?: string | undefined;
729
+ })[];
730
+ findings: {
731
+ message: string;
732
+ severity: "CRITICAL" | "WARN" | "INFO";
733
+ confidence?: number | undefined;
734
+ file?: string | undefined;
735
+ line?: number | undefined;
736
+ }[];
737
+ attemptedLaneCount: number;
738
+ completedLaneCount: number;
739
+ postChecks: {
740
+ message: string;
741
+ tier: "decidable" | "sensor";
742
+ ruleName: string;
743
+ verdict: "pass" | "fail" | "abstain";
744
+ }[];
745
+ round: {
746
+ index: number;
747
+ lineageKey: string;
748
+ priorVerdictHash?: string | undefined;
749
+ };
750
+ reviewedState: "matched" | "drifted";
751
+ settled: boolean;
752
+ diversity?: {
753
+ class: "cross-vendor" | "same-vendor-isolated";
754
+ providers: string[];
755
+ distinctProviders: number;
756
+ unrecognizedProviders: string[];
757
+ diversityConfidence: "verified" | "coarse";
758
+ } | undefined;
759
+ panelArtifactHash?: string | undefined;
760
+ }>, {
761
+ createdAt: string;
762
+ diffScope: {
763
+ source: "explicit-range";
764
+ diffHash: string;
765
+ base: string;
766
+ head: string;
767
+ } | {
768
+ source: "branch-vs-base";
769
+ diffHash: string;
770
+ base: string;
771
+ } | {
772
+ source: "staged";
773
+ diffHash: string;
774
+ } | {
775
+ source: "uncommitted";
776
+ diffHash: string;
777
+ };
778
+ schemaVersion: string;
779
+ lanes: ({
780
+ status: "completed";
781
+ laneId: string;
782
+ resolvedBackend: string;
783
+ runArtifactHash: string;
784
+ verdictSummary: {
785
+ warn: number;
786
+ info: number;
787
+ critical: number;
788
+ };
789
+ } | {
790
+ status: "abstained";
791
+ reason: string;
792
+ laneId: string;
793
+ resolvedBackend: string;
794
+ runArtifactHash: string;
795
+ } | {
796
+ status: "failed";
797
+ laneId: string;
798
+ typedReason: "invoke-error" | "quota-exhausted" | "missing-artifact-emission" | "config-error";
799
+ configuredLane: string;
800
+ resolvedBackend?: string | undefined;
801
+ })[];
802
+ findings: {
803
+ message: string;
804
+ severity: "CRITICAL" | "WARN" | "INFO";
805
+ confidence?: number | undefined;
806
+ file?: string | undefined;
807
+ line?: number | undefined;
808
+ }[];
809
+ attemptedLaneCount: number;
810
+ completedLaneCount: number;
811
+ postChecks: {
812
+ message: string;
813
+ tier: "decidable" | "sensor";
814
+ ruleName: string;
815
+ verdict: "pass" | "fail" | "abstain";
816
+ }[];
817
+ round: {
818
+ index: number;
819
+ lineageKey: string;
820
+ priorVerdictHash?: string | undefined;
821
+ };
822
+ reviewedState: "matched" | "drifted";
823
+ settled: boolean;
824
+ diversity?: {
825
+ class: "cross-vendor" | "same-vendor-isolated";
826
+ providers: string[];
827
+ distinctProviders: number;
828
+ unrecognizedProviders: string[];
829
+ diversityConfidence: "verified" | "coarse";
830
+ } | undefined;
831
+ panelArtifactHash?: string | undefined;
832
+ }, {
833
+ createdAt: string;
834
+ diffScope: {
835
+ source: "explicit-range";
836
+ diffHash: string;
837
+ base: string;
838
+ head: string;
839
+ } | {
840
+ source: "branch-vs-base";
841
+ diffHash: string;
842
+ base: string;
843
+ } | {
844
+ source: "staged";
845
+ diffHash: string;
846
+ } | {
847
+ source: "uncommitted";
848
+ diffHash: string;
849
+ };
850
+ schemaVersion: string;
851
+ lanes: ({
852
+ status: "completed";
853
+ laneId: string;
854
+ resolvedBackend: string;
855
+ runArtifactHash: string;
856
+ verdictSummary: {
857
+ warn: number;
858
+ info: number;
859
+ critical: number;
860
+ };
861
+ } | {
862
+ status: "abstained";
863
+ reason: string;
864
+ laneId: string;
865
+ resolvedBackend: string;
866
+ runArtifactHash: string;
867
+ } | {
868
+ status: "failed";
869
+ laneId: string;
870
+ typedReason: "invoke-error" | "quota-exhausted" | "missing-artifact-emission" | "config-error";
871
+ configuredLane: string;
872
+ resolvedBackend?: string | undefined;
873
+ })[];
874
+ findings: {
875
+ message: string;
876
+ severity: "CRITICAL" | "WARN" | "INFO";
877
+ confidence?: number | undefined;
878
+ file?: string | undefined;
879
+ line?: number | undefined;
880
+ }[];
881
+ attemptedLaneCount: number;
882
+ completedLaneCount: number;
883
+ postChecks: {
884
+ message: string;
885
+ tier: "decidable" | "sensor";
886
+ ruleName: string;
887
+ verdict: "pass" | "fail" | "abstain";
888
+ }[];
889
+ round: {
890
+ index: number;
891
+ lineageKey: string;
892
+ priorVerdictHash?: string | undefined;
893
+ };
894
+ reviewedState: "matched" | "drifted";
895
+ settled: boolean;
896
+ diversity?: {
897
+ class: "cross-vendor" | "same-vendor-isolated";
898
+ providers: string[];
899
+ distinctProviders: number;
900
+ unrecognizedProviders: string[];
901
+ diversityConfidence: "verified" | "coarse";
902
+ } | undefined;
903
+ panelArtifactHash?: string | undefined;
904
+ }>;
905
+ export type VerdictArtifact = z.infer<typeof VerdictArtifactSchema>;
906
+ /**
907
+ * The round-chain lineage key is composite over the RESOLVED scope selector (agy
908
+ * fold 3; codex rev-2 fold 2) — NOT the source enum alone. The selector fields
909
+ * describe the *lineage*, never the changing diff bytes, so legitimate fix rounds
910
+ * still chain. Per-source contribution (the CLI resolver populates only the fields
911
+ * a source makes meaningful):
912
+ * - `repoIdentity` — the stable worktree identity (absolute resolved
913
+ * `git rev-parse --show-toplevel`), ALWAYS present.
914
+ * - `branch` — the current branch (or the `DETACHED:<sha>` marker), ALWAYS present.
915
+ * - `source` — the `getDiffForReview` source, ALWAYS present.
916
+ * - `explicit-range` — normalized `base` + `head` (the two endpoints).
917
+ * - `branch-vs-base` — resolved `base` + `mergeBase`.
918
+ * - `staged` / `uncommitted` — NO range fields (worktree identity + branch +
919
+ * source carry the lineage).
920
+ */
921
+ /** Fields every lineage-key variant carries, regardless of source. */
922
+ interface LineageKeyCommon {
923
+ /** Stable worktree identity — the absolute resolved `git rev-parse --show-toplevel`. */
924
+ repoIdentity: string;
925
+ /** The current branch, or the `DETACHED:<sha>` marker. */
926
+ branch: string;
927
+ /**
928
+ * The raw CLI selector FORM (finding 10) — accepted on EVERY variant now so the
929
+ * key shape is stable before the CLI populates it. It distinguishes selectors
930
+ * that resolve to the same refs but describe different lineages, e.g. `--diff main`
931
+ * (working-tree mode) vs `main..HEAD` (range mode). Absent today (⇒ hashed as
932
+ * `null`); when the CLI agent supplies it (finding 10) the key already accounts
933
+ * for it — no further domain-tag bump needed.
934
+ */
935
+ selectorForm?: string;
936
+ }
937
+ /**
938
+ * `computeLineageKey` input, SOURCE-DISCRIMINATED (totem-codex finding 9d): each
939
+ * variant carries ONLY the range fields its source makes meaningful, so an
940
+ * impossible record (e.g. a `staged` scope with a `head` endpoint) is
941
+ * unrepresentable.
942
+ * - `explicit-range` — `base` + `head` (the two endpoints).
943
+ * - `branch-vs-base` — `base` (resolved base ref) + `mergeBase` (resolved sha).
944
+ * - `staged` / `uncommitted` — NO range fields; repoIdentity + branch + source
945
+ * (+ optional selectorForm) carry the lineage (the index/worktree has no endpoint).
946
+ */
947
+ export type LineageKeyInput = (LineageKeyCommon & {
948
+ source: 'explicit-range';
949
+ base: string;
950
+ head: string;
951
+ }) | (LineageKeyCommon & {
952
+ source: 'branch-vs-base';
953
+ base: string;
954
+ mergeBase: string;
955
+ }) | (LineageKeyCommon & {
956
+ source: 'staged';
957
+ }) | (LineageKeyCommon & {
958
+ source: 'uncommitted';
959
+ });
960
+ /**
961
+ * The composite round-chain lineage key: a domain-tagged sha256 over the resolved
962
+ * scope selector (agy fold 3; codex rev-2 fold 2). Two branches sharing `base=main`
963
+ * can NEVER cross-link because `branch` participates, and two DIFFERENT explicit
964
+ * ranges on one branch + merge-base cannot cross-link because `base`/`head`
965
+ * participate.
966
+ *
967
+ * The domain tag is `verdict-lineage/3` — bumped from `/2` because the selector
968
+ * shape changed (source-discriminated input + `selectorForm`), so keys under the
969
+ * two tags are deliberately incompatible.
970
+ *
971
+ * Only the fields VALID for the discriminated `source` participate (the switch
972
+ * reads them per-variant), pinning the others to `null`. The selector is hashed as
973
+ * a canonicalized (recursively key-sorted) JSON object with the fixed domain tag,
974
+ * so there is NO delimiter-injection ambiguity — `branch='a', mergeBase='b|c'` and
975
+ * `branch='a|b', mergeBase='c'` serialize to distinct JSON and therefore distinct
976
+ * keys, which a naive `join('|')` would collide. A `null` hole (a source that omits
977
+ * a field) can never collide with an empty string a source supplies for it.
978
+ */
979
+ export declare function computeLineageKey(input: LineageKeyInput): string;
980
+ /** Absolute verdicts directory for a given absolute totem dir. */
981
+ export declare function verdictsDir(totemDirAbs: string): string;
982
+ /**
983
+ * Content address of a verdict: deterministic hash over everything EXCEPT
984
+ * `createdAt` (observability, not identity). Identical rounds dedup to one
985
+ * artifact regardless of when they ran.
986
+ */
987
+ export declare function computeVerdictArtifactContentHash(artifact: VerdictArtifact): string;
988
+ /**
989
+ * A loaded verdict paired with its VERIFIED content address (the filename stem = the
990
+ * raw-payload hash). The address SURVIVES the tolerant Zod parse (rev-6 item 1): a
991
+ * forward-minor artifact whose writer addressed a raw payload with an additive field
992
+ * THIS reader strips keeps its on-disk address here, so no downstream consumer
993
+ * (covariate line, lineage tie-break, round linkage) recomputes a DIVERGING identity
994
+ * over the normalized shape — the covariate line would otherwise advertise a hash with
995
+ * no file, and round linkage would point at a nonexistent prior. Every load/scan entry
996
+ * point returns this pair so the stored address is the single identity every consumer uses.
997
+ */
998
+ export interface VerdictWithAddress {
999
+ artifact: VerdictArtifact;
1000
+ /** The verified content address = the filename stem (raw-payload hash, `createdAt` excluded). */
1001
+ contentHash: string;
1002
+ }
1003
+ /**
1004
+ * Render the machine-readable covariate line — the CORE-OWNED signal every caller
1005
+ * (CLI print, headless, `/review-reply`) emits identically so the skill stays pure
1006
+ * transport (strategy-codex G4; resolves finding 14). Format, EXACTLY:
1007
+ *
1008
+ * `local-lane: <hash8> round=<n> settled=<true|false> lanes=<completed>/<attempted>`
1009
+ *
1010
+ * where `<hash8>` is the first 8 hex of the artifact's STORED content address. The
1011
+ * signature takes a {@link VerdictWithAddress} (rev-6 item 1) so the rendered `<hash8>`
1012
+ * is the VERIFIED on-disk address that survived the tolerant parse — NOT a recompute
1013
+ * over the Zod-stripped shape, which would diverge for a forward-minor artifact and
1014
+ * advertise a hash with no backing file. A caller with a freshly-assembled verdict
1015
+ * pairs it with the address `saveVerdictArtifact` returned.
1016
+ *
1017
+ * @remarks Covariate line format v1 — do NOT alter without a spec amendment (the
1018
+ * pilot ledger joins on this grep-able line; the format is contract, versioned with
1019
+ * the `review-loop` skill).
1020
+ */
1021
+ export declare function renderCovariateLine(verdict: VerdictWithAddress): string;
1022
+ export interface SaveVerdictArtifactResult {
1023
+ /** The content address (= filename stem). */
1024
+ hash: string;
1025
+ /** Absolute path of the stored artifact. */
1026
+ path: string;
1027
+ /** True when an identical logical verdict was already recorded (no write happened). */
1028
+ existed: boolean;
1029
+ }
1030
+ /**
1031
+ * Persist a verdict at its content address, write-if-absent (`wx` create-
1032
+ * exclusive). Validates on the way OUT so a writer bug never poisons the ledger
1033
+ * with a record the reader would reject.
1034
+ *
1035
+ * EEXIST is LOGICAL-IDENTITY DEDUP (`createdAt` excluded from the address; codex
1036
+ * fold 8 / agy fold 4): the existing record is loaded and its content hash
1037
+ * recomputed. If it matches this address (equal MODULO `createdAt`), the stored
1038
+ * record IS this save's outcome — first-write-wins, dedup return. If the record
1039
+ * at this address recomputes to a DIFFERENT hash, its bytes disagree with the
1040
+ * content address — a hard identity violation (a corrupted/tampered record or a
1041
+ * sha256 collision), never silently accepted.
1042
+ */
1043
+ export declare function saveVerdictArtifact(totemDirAbs: string, artifact: VerdictArtifact): SaveVerdictArtifactResult;
1044
+ /**
1045
+ * Load + validate a verdict by content address, returning the artifact WITH its
1046
+ * verified content address (rev-6 item 1 — {@link VerdictWithAddress}). Throws
1047
+ * {@link TotemParseError} on a missing file, corrupt JSON, schema violation, or an
1048
+ * unknown major with no migration entry, and {@link TotemError} (`DATABASE_MISMATCH`)
1049
+ * when the stored bytes do not hash back to their filename address (finding 4) — loud,
1050
+ * never a silent partial (Tenet 4).
1051
+ *
1052
+ * Order (rev-6 item 5): the RAW stored address is verified FIRST — the content-address
1053
+ * guarantee is over the on-disk bytes (minus `createdAt`), MAJOR-agnostic and
1054
+ * migration-independent, so a mis-addressed / tampered file fails before it is
1055
+ * transformed. Only THEN is any migration applied and its output validated against the
1056
+ * current schema (a separate concern — migration correctness, not address integrity).
1057
+ * The returned `contentHash` is always this verified filename address.
1058
+ */
1059
+ export declare function loadVerdictArtifact(totemDirAbs: string, hash: string): VerdictWithAddress;
1060
+ /**
1061
+ * Load every stored verdict under `artifacts/verdicts/`, verifying each through
1062
+ * the SAME content-address check as {@link loadVerdictArtifact}. A missing
1063
+ * directory yields `[]` (nothing written yet). Non-verdict file names are skipped
1064
+ * silently; a corrupt / mis-addressed verdict is skipped LOUDLY via `onWarn`.
1065
+ * `onWarn` is REQUIRED — core stays console-free (no presentation-layer default),
1066
+ * and the caller must decide where scan warnings land rather than inheriting a
1067
+ * silent noop (Tenet 4); see {@link loadVerifiedVerdictForScan}. (PR #2337 CR.)
1068
+ */
1069
+ export declare function listVerdictArtifacts(totemDirAbs: string, onWarn: (message: string) => void): VerdictWithAddress[];
1070
+ /**
1071
+ * The latest verdict sharing `lineageKey` — highest `round.index`, ties broken by
1072
+ * the lexical STORED content address (rev-5 item 8 / rev-6 item 1), NOT `createdAt`.
1073
+ * Returns the winning {@link VerdictWithAddress} (artifact + verified address) or
1074
+ * `undefined` when no verdict carries the key. Used for implicit round linkage (the
1075
+ * next round's `priorVerdictHash` = the returned `contentHash`, so the link always
1076
+ * points at the on-disk file even for a forward-minor artifact). Goes through the same
1077
+ * verified scan load as {@link listVerdictArtifacts}: a corrupt / mis-addressed
1078
+ * artifact is warned + skipped (never silently winning or losing the lineage). `onWarn`
1079
+ * is REQUIRED — core is console-free and the caller owns where warnings land (Tenet 4).
1080
+ *
1081
+ * The tie-break is IDENTITY-BOUND and deterministic: two same-round verdicts break on
1082
+ * their STORED content address (the on-disk identity, `createdAt` excluded), so
1083
+ * selection never depends on wall-clock emission time (observability-only) — the same
1084
+ * corpus always resolves the same latest verdict regardless of when each round ran.
1085
+ */
1086
+ export declare function findLatestVerdictForLineage(totemDirAbs: string, lineageKey: string, onWarn: (message: string) => void): VerdictWithAddress | undefined;
1087
+ export {};
1088
+ //# sourceMappingURL=verdict.d.ts.map