@vostride/agent-qa-eval-local 0.0.0-stage → 0.2.1

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.
package/dist/reader.js ADDED
@@ -0,0 +1,744 @@
1
+ // src/corpus-reader.ts
2
+ import { isProposerVisibleEntry } from "@vostride/agent-qa-eval";
3
+
4
+ // src/committed-corpus-source.ts
5
+ import { existsSync as existsSync4, readdirSync as readdirSync3, readFileSync as readFileSync9, statSync } from "fs";
6
+ import { join as join12 } from "path";
7
+ import {
8
+ activeMarkedCorpusEntries,
9
+ BASELINE_POINTER_SCHEMA_VERSION,
10
+ guardDecisionVectorsDocument as guardDecisionVectorsDocument2,
11
+ guardNoiseFloorArtefact,
12
+ parseCorpusEntry,
13
+ parseStandaloneLabelRecord as parseStandaloneLabelRecord2,
14
+ selectEffectiveLabels as selectEffectiveLabels2,
15
+ partitionManifestSchema,
16
+ runExclusionRecordSchema
17
+ } from "@vostride/agent-qa-eval";
18
+ import { slugBranch as slugBranch7 } from "@vostride/agent-qa-schema";
19
+ import { z as z6 } from "zod";
20
+
21
+ // src/cassette-loader.ts
22
+ import { readFileSync as readFileSync2 } from "fs";
23
+ import { basename, join as join3 } from "path";
24
+ import {
25
+ guardCassette as guardCassette2
26
+ } from "@vostride/agent-qa-eval";
27
+
28
+ // src/artifact-source.ts
29
+ import { readFileSync } from "fs";
30
+ import { join } from "path";
31
+ import { FsEvidenceArtifactStore } from "@vostride/agent-qa-runner-local";
32
+ var BLOB_SHA_RE = /^[0-9a-f]{64}$/;
33
+ var DirArtifactSource = class {
34
+ dir;
35
+ constructor(config) {
36
+ this.dir = config.dir;
37
+ }
38
+ getBlob(sha) {
39
+ if (!BLOB_SHA_RE.test(sha)) return void 0;
40
+ try {
41
+ return new Uint8Array(readFileSync(join(this.dir, sha)));
42
+ } catch (error) {
43
+ if (error.code === "ENOENT") return void 0;
44
+ throw error;
45
+ }
46
+ }
47
+ };
48
+
49
+ // src/cassette-store.ts
50
+ import { createHash } from "crypto";
51
+ import { mkdirSync, rmSync, writeFileSync } from "fs";
52
+ import { join as join2 } from "path";
53
+ import {
54
+ guardCassette
55
+ } from "@vostride/agent-qa-eval";
56
+ import { slugBranch } from "@vostride/agent-qa-schema";
57
+ var CASSETTE_FILE = "cassette.json";
58
+ var BLOBS_SUBDIR = "blobs";
59
+
60
+ // src/cassette-loader.ts
61
+ function refused(cassetteId, reason, detail) {
62
+ return { kind: "refused", refusal: { kind: "integrity-refusal", cassetteId, reason, detail } };
63
+ }
64
+ function recoverCassetteId(document, fallback) {
65
+ if (typeof document === "object" && document !== null) {
66
+ const id = document.id;
67
+ if (typeof id === "string" && id.length > 0) return id;
68
+ }
69
+ return fallback;
70
+ }
71
+ function loadCassetteBundle(bundleDir) {
72
+ const fallbackId = basename(bundleDir);
73
+ const cassettePath = join3(bundleDir, CASSETTE_FILE);
74
+ let raw;
75
+ try {
76
+ raw = readFileSync2(cassettePath, "utf8");
77
+ } catch (error) {
78
+ return refused(
79
+ fallbackId,
80
+ "parse-failed",
81
+ `Failed to read ${cassettePath}: ${error.message}`
82
+ );
83
+ }
84
+ let document;
85
+ try {
86
+ document = JSON.parse(raw);
87
+ } catch (error) {
88
+ return refused(
89
+ fallbackId,
90
+ "parse-failed",
91
+ `Invalid cassette JSON at ${cassettePath}: ${error.message}`
92
+ );
93
+ }
94
+ let cassette;
95
+ try {
96
+ cassette = guardCassette2(document);
97
+ } catch (error) {
98
+ return refused(recoverCassetteId(document, fallbackId), "guard-failed", error.message);
99
+ }
100
+ const artifacts = new DirArtifactSource({ dir: join3(bundleDir, BLOBS_SUBDIR) });
101
+ return { kind: "loaded", cassette, artifacts };
102
+ }
103
+
104
+ // src/committed-root-store.ts
105
+ import { createHash as createHash2 } from "crypto";
106
+ import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
107
+ import { basename as basename2, dirname, join as join4 } from "path";
108
+ import { slugBranch as slugBranch2 } from "@vostride/agent-qa-schema";
109
+ var COMMITTED_CASSETTES_DIR = "cassettes";
110
+ var COMMITTED_CORPUS_DIR = "corpus";
111
+ var COMMITTED_LABELS_DIR = "labels";
112
+ function sluggedIdSegments(cassetteId) {
113
+ return cassetteId.split("/").map((segment) => slugBranch2(segment));
114
+ }
115
+ function sluggedJsonLeaf(cassetteId) {
116
+ const segments = sluggedIdSegments(cassetteId);
117
+ const last = segments.pop() ?? "default";
118
+ return [...segments, `${last}.json`];
119
+ }
120
+ function committedLabelPath(product, cassetteId) {
121
+ return [COMMITTED_LABELS_DIR, slugBranch2(product), ...sluggedJsonLeaf(cassetteId)].join("/");
122
+ }
123
+
124
+ // src/replay-read.ts
125
+ import { existsSync as existsSync2, readFileSync as readFileSync4, readdirSync } from "fs";
126
+ import { basename as basename3, join as join7 } from "path";
127
+ import { scoringContextSchema, hasValidScoreJudgeMetadata } from "@vostride/agent-qa-eval";
128
+
129
+ // src/replay-record-store.ts
130
+ import { mkdirSync as mkdirSync3, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
131
+ import { join as join5 } from "path";
132
+ import { slugBranch as slugBranch3 } from "@vostride/agent-qa-schema";
133
+
134
+ // src/score-store.ts
135
+ import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
136
+ import { join as join6 } from "path";
137
+ import { slugBranch as slugBranch4 } from "@vostride/agent-qa-schema";
138
+
139
+ // src/replay-read.ts
140
+ function listMarkerDirs(root, markerFile) {
141
+ const found = [];
142
+ function walk(dir) {
143
+ let entries;
144
+ try {
145
+ entries = readdirSync(dir, { withFileTypes: true });
146
+ } catch {
147
+ return;
148
+ }
149
+ if (entries.some((entry) => entry.isFile() && entry.name === markerFile)) found.push(dir);
150
+ for (const entry of entries) {
151
+ if (entry.isDirectory()) walk(join7(dir, entry.name));
152
+ }
153
+ }
154
+ walk(root);
155
+ return found.sort();
156
+ }
157
+ function listCassetteBundleDirs(cassettesRoot) {
158
+ return listMarkerDirs(cassettesRoot, CASSETTE_FILE);
159
+ }
160
+
161
+ // src/mark-ledger.ts
162
+ import { closeSync as closeSync2, existsSync as existsSync3, fsyncSync as fsyncSync2, openSync as openSync2, readFileSync as readFileSync6, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync6 } from "fs";
163
+ import { join as join9 } from "path";
164
+ import { canonicalJson } from "@vostride/agent-qa-eval";
165
+ import { HANDOFF_FILE, RUNS_SUBDIR, slugBranch as slugBranch5 } from "@vostride/agent-qa-runner-local";
166
+ import { ImprovementPlanSchema, MarkReceiptSchema, markAddressKey } from "@vostride/agent-qa-schema";
167
+ import { z as z2 } from "zod";
168
+
169
+ // src/mark-lock.ts
170
+ import { randomUUID } from "crypto";
171
+ import { closeSync, fsyncSync, lstatSync, mkdirSync as mkdirSync5, openSync, readFileSync as readFileSync5, renameSync, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "fs";
172
+ import { dirname as dirname2, join as join8 } from "path";
173
+ import { z } from "zod";
174
+ var ownerSchema = z.object({
175
+ schemaVersion: z.literal(2),
176
+ kind: z.literal("mark-ledger-lock"),
177
+ pid: z.number().int().positive(),
178
+ token: z.uuid(),
179
+ runId: z.string().min(1)
180
+ }).strict();
181
+
182
+ // src/mark-ledger.ts
183
+ var MARK_INTENT_STAGES = ["prepared", "evidence", "applied"];
184
+ var intentSchema = z2.object({
185
+ schemaVersion: z2.literal(2),
186
+ mark: MarkReceiptSchema,
187
+ stage: z2.enum(MARK_INTENT_STAGES),
188
+ operationId: z2.uuid(),
189
+ plan: ImprovementPlanSchema.optional()
190
+ }).strict().superRefine((intent, ctx) => {
191
+ if (intent.stage === "applied" && intent.mark.disposition.kind === "drafted") {
192
+ ctx.addIssue({ code: "custom", path: ["mark", "disposition"], message: "a mark applies its fix; it never files a draft" });
193
+ }
194
+ });
195
+
196
+ // src/calibration-source.ts
197
+ import { lstatSync as lstatSync2, readdirSync as readdirSync2, readFileSync as readFileSync7 } from "fs";
198
+ import { dirname as dirname3, join as join10, relative, resolve } from "path";
199
+ import { z as z3 } from "zod";
200
+ import { canonicalJson as canonicalJson2, deriveLabelRevisionId, parseStandaloneLabelRecord, selectEffectiveLabels } from "@vostride/agent-qa-eval";
201
+ import { ORIGIN_PRIORS, sha256hex } from "@vostride/agent-qa-schema";
202
+ var LABEL_CALIBRATION_PATH = "labels/calibration.json";
203
+ var LABEL_CALIBRATION_SCHEMA_VERSION = 2;
204
+ var count = z3.number().int().min(0).max(Number.MAX_SAFE_INTEGER);
205
+ var unit = z3.number().finite().min(0).max(1);
206
+ var digest = z3.string().regex(/^[0-9a-f]{64}$/);
207
+ var noisy = z3.union([
208
+ z3.object({ status: z3.literal("uncalibrated"), n: count, n_gold: count }).strict(),
209
+ z3.object({
210
+ status: z3.literal("calibrated"),
211
+ n: count,
212
+ n_gold: count,
213
+ precision: unit,
214
+ wilson95: z3.object({ lower: unit, upper: unit, halfWidth: unit }).strict().refine((v) => v.lower <= v.upper)
215
+ }).strict()
216
+ ]);
217
+ var gold = z3.object({ n_gold: count, precision: z3.literal("by-construction") }).strict();
218
+ var prior = z3.object({ alpha: z3.number().finite().min(0), beta: z3.number().finite().min(0) }).strict().refine((v) => Number.isFinite(v.alpha + v.beta) && v.alpha + v.beta > 0);
219
+ var rate = z3.object({ numerator: count, denominator: count, rate: unit.optional() }).strict().refine((v) => v.numerator <= v.denominator && (v.denominator === 0 ? v.rate === void 0 : v.rate === v.numerator / v.denominator));
220
+ var accuracy = z3.object({ n: count, correct: count, accuracy: unit.optional() }).strict().refine((v) => v.correct <= v.n && (v.n === 0 ? v.accuracy === void 0 : v.accuracy === v.correct / v.n));
221
+ var artifactSchema = z3.object({
222
+ schemaVersion: z3.literal(LABEL_CALIBRATION_SCHEMA_VERSION),
223
+ generationId: digest,
224
+ evidenceDigest: digest,
225
+ corpusDigest: digest,
226
+ goldSetDigest: digest,
227
+ minGold: z3.object({ value: count.min(2), source: z3.enum(["default", "cli"]) }).strict(),
228
+ channels: z3.object({ "recorded-verdict": noisy, "self-heal-pair": noisy, "user-mark": gold, "overturned-verdict": gold }).strict(),
229
+ priors: z3.object({ "agent-verified": prior.optional(), "agent-observed": prior.optional() }).strict(),
230
+ unchangedOrigins: z3.tuple([z3.literal("user"), z3.literal("import")]),
231
+ verifierFalsePassRate: rate,
232
+ verifierFalseFailRate: rate,
233
+ rootCauseClassifierAccuracy: z3.object({ "analyze-run": accuracy, "deterministic-classifier": accuracy }).strict(),
234
+ rootCauseClassifierGrain: z3.literal("member/producer:app_bug-binary"),
235
+ skippedCounts: z3.object({ "missing-source": count.optional(), "invalid-gold": count.optional(), "conflicting-truth": count.optional(), "missing-verdict": count.optional(), "missing-pairing": count.optional(), "conflicting-observation": count.optional() }).strict(),
236
+ targetRevisions: z3.array(z3.object({ cassetteId: z3.string().min(1), revisionId: digest }).strict())
237
+ }).strict();
238
+ function assertCalibrationPath(root, path) {
239
+ const base = resolve(root), full = resolve(path), rel = relative(base, full);
240
+ if (rel === ".." || rel.startsWith("../") || rel.startsWith("/")) throw new Error("invalid calibration path");
241
+ let cursor = full;
242
+ while (true) {
243
+ try {
244
+ if (lstatSync2(cursor).isSymbolicLink()) throw new Error("invalid calibration path");
245
+ } catch (error) {
246
+ if (error.code !== "ENOENT") throw error;
247
+ }
248
+ if (cursor === base) break;
249
+ const parent = dirname3(cursor);
250
+ if (parent === cursor) break;
251
+ cursor = parent;
252
+ }
253
+ }
254
+ function calibrationGenerationId(body) {
255
+ return sha256hex(canonicalJson2(body));
256
+ }
257
+ function guardLabelCalibration(value) {
258
+ const parsed = artifactSchema.safeParse(value);
259
+ if (!parsed.success) return void 0;
260
+ const artifact = parsed.data;
261
+ const { generationId, ...body } = artifact;
262
+ if (calibrationGenerationId(body) !== generationId) return void 0;
263
+ let previous;
264
+ for (const target of artifact.targetRevisions) {
265
+ if (previous !== void 0 && previous >= target.cassetteId) return void 0;
266
+ previous = target.cassetteId;
267
+ }
268
+ for (const [channel, origin] of [["recorded-verdict", "agent-verified"], ["self-heal-pair", "agent-observed"]]) {
269
+ const row = artifact.channels[channel], emitted = artifact.priors[origin];
270
+ if (row.n !== row.n_gold || row.status === "calibrated" !== row.n >= artifact.minGold.value) return void 0;
271
+ if (row.status === "uncalibrated") {
272
+ if (emitted !== void 0) return void 0;
273
+ } else {
274
+ const mass = ORIGIN_PRIORS[origin].alpha + ORIGIN_PRIORS[origin].beta;
275
+ if (!emitted || emitted.alpha !== row.precision * mass || emitted.beta !== (1 - row.precision) * mass) return void 0;
276
+ }
277
+ }
278
+ return artifact;
279
+ }
280
+ function readLabelCalibration(committedRoot) {
281
+ const marker = join10(committedRoot, LABEL_CALIBRATION_PATH);
282
+ let targetCassetteIds;
283
+ try {
284
+ let walk2 = function(directory) {
285
+ assertCalibrationPath(committedRoot, directory);
286
+ for (const entry of readdirSync2(directory, { withFileTypes: true })) {
287
+ const path = join10(directory, entry.name);
288
+ if (entry.isDirectory()) {
289
+ walk2(path);
290
+ continue;
291
+ }
292
+ if (!entry.isFile() || !entry.name.endsWith(".json") || path === marker) continue;
293
+ let parsed;
294
+ try {
295
+ parsed = parseStandaloneLabelRecord(JSON.parse(readFileSync7(path, "utf8")));
296
+ } catch {
297
+ continue;
298
+ }
299
+ if (!parsed.ok) continue;
300
+ const record = parsed.record, product = relative(join10(committedRoot, "labels"), path).split("/")[0];
301
+ const expected = join10(committedRoot, committedLabelPath(product, record.cassetteId)).replace(/\.json$/, record.revision ? `--revision-${record.revision.id}.json` : ".json");
302
+ if (expected !== path) continue;
303
+ const id = record.revision?.id ?? deriveLabelRevisionId(record);
304
+ if (records.has(id)) throw new Error("duplicate label identity");
305
+ records.set(id, record);
306
+ }
307
+ };
308
+ var walk = walk2;
309
+ assertCalibrationPath(committedRoot, marker);
310
+ try {
311
+ lstatSync2(marker);
312
+ } catch (error) {
313
+ if (error.code === "ENOENT") return { kind: "absent" };
314
+ throw error;
315
+ }
316
+ const artifact = guardLabelCalibration(JSON.parse(readFileSync7(marker, "utf8")));
317
+ if (!artifact) return { kind: "refused", reason: "invalid label calibration artifact" };
318
+ targetCassetteIds = artifact.targetRevisions.map((target) => target.cassetteId);
319
+ const records = /* @__PURE__ */ new Map();
320
+ walk2(join10(committedRoot, "labels"));
321
+ const authorizedRevisionIds = /* @__PURE__ */ new Set();
322
+ for (const target of artifact.targetRevisions) {
323
+ const chain = [], visited = /* @__PURE__ */ new Set(), generations = /* @__PURE__ */ new Set();
324
+ let id = target.revisionId;
325
+ while (id !== void 0) {
326
+ const record = records.get(id);
327
+ if (!record || record.cassetteId !== target.cassetteId || visited.has(id)) throw new Error("incomplete label chain");
328
+ visited.add(id);
329
+ chain.push(record);
330
+ if (record.revision?.generationId) generations.add(record.revision.generationId);
331
+ id = record.revision?.predecessorId;
332
+ }
333
+ const selected = selectEffectiveLabels(chain, { committedGenerationIds: generations });
334
+ const terminal = selected.effective.get(target.cassetteId);
335
+ if (selected.refusals.length || !terminal || (terminal.revision?.id ?? deriveLabelRevisionId(terminal)) !== target.revisionId) throw new Error("invalid label chain");
336
+ for (const id2 of visited) authorizedRevisionIds.add(id2);
337
+ }
338
+ return { kind: "loaded", artifact, authorizedRevisionIds };
339
+ } catch {
340
+ return { kind: "refused", reason: "label calibration or target history unavailable", targetCassetteIds };
341
+ }
342
+ }
343
+
344
+ // src/report-metadata-guard.ts
345
+ import { z as z4 } from "zod";
346
+ import {
347
+ ADVERSARIAL_MUTATORS,
348
+ GENERATOR_KINDS,
349
+ GENERATOR_PROVENANCES
350
+ } from "@vostride/agent-qa-eval";
351
+ var count2 = z4.number().int().nonnegative().safe();
352
+ var amount = z4.number().finite().nonnegative();
353
+ var unit2 = z4.number().finite().min(0).max(1);
354
+ var rate2 = z4.object({ numerator: count2, denominator: count2, rate: unit2.optional() }).passthrough().refine((row) => row.numerator <= row.denominator && (row.denominator === 0 ? row.rate === void 0 : row.rate === row.numerator / row.denominator));
355
+ var recovery = z4.object({
356
+ weightSum: z4.number().finite().nonnegative(),
357
+ pairsWithoutWeight: count2,
358
+ weightedAccuracy: unit2.optional(),
359
+ selfHealPairCount: count2,
360
+ recoveredPositiveCount: count2,
361
+ eligiblePositiveCount: count2,
362
+ recoveryAccuracy: unit2.optional(),
363
+ negativeDecisionCount: count2,
364
+ negativeFullMatchCount: count2
365
+ }).passthrough();
366
+ var cell = z4.object({
367
+ firstAttemptDecisionAccuracy: rate2,
368
+ verifierFalsePassRate: rate2,
369
+ recovery,
370
+ perDecisionCost: z4.object({
371
+ decisionCount: count2,
372
+ promptTokens: amount,
373
+ completionTokens: amount,
374
+ totalTokens: amount,
375
+ durationMs: amount
376
+ }).passthrough()
377
+ }).passthrough();
378
+ var closedCounts = (values) => z4.record(z4.enum(values), count2);
379
+ var openCounts = z4.record(z4.string(), count2);
380
+ var generationMix = z4.object({
381
+ total: count2,
382
+ metadataUnavailable: count2,
383
+ byProvenance: closedCounts(GENERATOR_PROVENANCES),
384
+ byKind: closedCounts(GENERATOR_KINDS),
385
+ byMutator: closedCounts(ADVERSARIAL_MUTATORS),
386
+ byTableVersion: openCounts,
387
+ tableHashesByVersion: z4.record(z4.string(), z4.array(z4.string())),
388
+ byPromptVersion: openCounts,
389
+ byAuthoringModel: openCounts,
390
+ byAuthoringFamily: openCounts
391
+ }).strict();
392
+ var current = z4.object({
393
+ // Additive-optional: absent is the pre-422 shape and stays admissible forever.
394
+ adversarialGenerationMix: generationMix.optional(),
395
+ headline: z4.object({ verifierFalsePassRate: rate2 }).passthrough(),
396
+ recovery,
397
+ calibration: z4.discriminatedUnion("status", [
398
+ z4.object({ status: z4.literal("uncalibrated"), n_gold: count2.optional(), verifierFalsePassRate: rate2.optional() }).passthrough(),
399
+ z4.object({ status: z4.literal("calibrated"), n_gold: count2, verifierFalsePassRate: rate2 }).passthrough()
400
+ ]),
401
+ perSplit: z4.object({
402
+ natural: cell,
403
+ "held-out": z4.object({ shared: cell, private: cell }).passthrough(),
404
+ adversarial: cell,
405
+ unassignedCount: count2
406
+ }).passthrough()
407
+ }).passthrough();
408
+
409
+ // src/report-store.ts
410
+ import { mkdirSync as mkdirSync6, mkdtempSync, readFileSync as readFileSync8, renameSync as renameSync3, rmdirSync, unlinkSync as unlinkSync2, writeFileSync as writeFileSync7 } from "fs";
411
+ import { basename as basename4, dirname as dirname4, join as join11 } from "path";
412
+ import { guardDecisionVectorsDocument, judgeIdentitySchema } from "@vostride/agent-qa-eval";
413
+ import { sha256hex as sha256hex2, slugBranch as slugBranch6 } from "@vostride/agent-qa-schema";
414
+ import { z as z5 } from "zod";
415
+ var calibrationCount = z5.number().int().nonnegative().safe();
416
+ var calibrationUnit = z5.number().finite().min(0).max(1);
417
+ var copiedInterval = z5.object({
418
+ lower: calibrationUnit,
419
+ upper: calibrationUnit,
420
+ halfWidth: calibrationUnit.max(0.5)
421
+ }).strict().refine((value) => value.lower <= value.upper && value.upper - value.lower <= 2 * value.halfWidth + Number.EPSILON * 4);
422
+ var consistentAgreement = (n, agreement) => agreement === Math.round(n * agreement) / n;
423
+ var copiedMember = z5.object({
424
+ judgeModelId: z5.string(),
425
+ n: calibrationCount,
426
+ agreement: calibrationUnit.optional(),
427
+ wilson95: copiedInterval.optional()
428
+ }).strict().refine((value) => value.n === 0 ? value.agreement === void 0 && value.wilson95 === void 0 : value.agreement !== void 0 && value.wilson95 !== void 0 && consistentAgreement(value.n, value.agreement));
429
+ var copiedCalibration = z5.discriminatedUnion("status", [
430
+ z5.object({
431
+ status: z5.literal("calibrated"),
432
+ n: calibrationCount.min(2),
433
+ pooledAgreement: calibrationUnit,
434
+ wilson95: copiedInterval,
435
+ perMember: z5.array(copiedMember).min(2).max(3)
436
+ }).strict().refine((value) => consistentAgreement(value.n, value.pooledAgreement)),
437
+ z5.object({
438
+ status: z5.literal("uncalibrated"),
439
+ n: calibrationCount,
440
+ provenance: z5.literal("unavailable").optional()
441
+ }).strict().refine((value) => value.provenance === void 0 || value.n === 0),
442
+ z5.object({
443
+ status: z5.literal("capability-gap"),
444
+ reason: z5.enum(["panel-not-configured", "no-credential", "single-family-host"])
445
+ }).strict()
446
+ ]);
447
+ var reportJudgeSchema = judgeIdentitySchema.safeExtend({ calibration: copiedCalibration.optional() }).refine((judge) => {
448
+ const calibration = judge.calibration;
449
+ if (calibration === void 0) return true;
450
+ if (judge.panelSize === void 0 || judge.members === void 0) return false;
451
+ if (calibration.status !== "calibrated") return true;
452
+ const memberIds = calibration.perMember.map((member) => member.judgeModelId).sort();
453
+ return calibration.perMember.length === judge.members.length && memberIds.every((id, index) => id === judge.members[index].judgeModelId);
454
+ }, "calibration requires the complete recorded composite identity");
455
+ var stagedReportSchema = z5.object({
456
+ batchKey: z5.string().min(1),
457
+ matcherVersion: z5.number().int().nonnegative(),
458
+ headline: z5.object({
459
+ perDecisionCost: z5.object({ decisionCount: z5.number() }).passthrough()
460
+ }).passthrough(),
461
+ // Optional historical provenance remains optional; malformed mixed identities must never
462
+ // reach the comparator's renderer as though its judge-id list were a string array.
463
+ judgeIdentity: z5.literal("mixed").optional(),
464
+ mixedJudgeModelIds: z5.array(z5.string()).optional(),
465
+ judge: reportJudgeSchema.optional()
466
+ }).passthrough().refine((report) => report.judgeIdentity !== "mixed" || report.judge === void 0);
467
+ var replayGenerationSchema = z5.object({
468
+ seed: z5.number().int().safe(),
469
+ records: z5.array(
470
+ z5.object({
471
+ cassetteId: z5.string().min(1),
472
+ replayDigest: z5.string().regex(/^[a-f0-9]{64}$/),
473
+ scoreDigest: z5.string().regex(/^[a-f0-9]{64}$/).nullable()
474
+ }).strict()
475
+ )
476
+ }).strict();
477
+ var publicationSchema = z5.object({
478
+ schemaVersion: z5.literal(2),
479
+ reportDigest: z5.string().regex(/^[a-f0-9]{64}$/),
480
+ decisionsDigest: z5.string().regex(/^[a-f0-9]{64}$/).nullable(),
481
+ replayGeneration: replayGenerationSchema.optional()
482
+ }).strict();
483
+
484
+ // src/committed-corpus-source.ts
485
+ var reportSchema = z6.object({
486
+ batchKey: z6.string(),
487
+ matcherVersion: z6.number(),
488
+ judgeIdentity: z6.literal("mixed").optional(),
489
+ mixedJudgeModelIds: z6.array(z6.string()).optional(),
490
+ headline: z6.object({ perDecisionCost: z6.object({ decisionCount: z6.number() }).passthrough() }).passthrough(),
491
+ honesty: z6.object({
492
+ unscorableIdentityCounts: z6.record(z6.string(), z6.number()),
493
+ refusalCounts: z6.record(z6.string(), z6.number())
494
+ }).passthrough(),
495
+ judge: reportJudgeSchema.optional()
496
+ }).passthrough().refine((report) => report.judgeIdentity !== "mixed" || report.judge === void 0);
497
+ var baselinePointerSchema = z6.object({
498
+ schemaVersion: z6.literal(BASELINE_POINTER_SCHEMA_VERSION),
499
+ profileKey: z6.string(),
500
+ batchKey: z6.string(),
501
+ fingerprint: z6.string(),
502
+ corpusDigest: z6.string()
503
+ }).passthrough();
504
+ function listDirNames(dir) {
505
+ try {
506
+ return readdirSync3(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort();
507
+ } catch {
508
+ return [];
509
+ }
510
+ }
511
+ function listJsonFiles(dir) {
512
+ const found = [];
513
+ function walk(current2) {
514
+ let entries;
515
+ try {
516
+ entries = readdirSync3(current2, { withFileTypes: true });
517
+ } catch {
518
+ return;
519
+ }
520
+ for (const entry of entries) {
521
+ const path = join12(current2, entry.name);
522
+ if (entry.isDirectory()) walk(path);
523
+ else if (entry.isFile() && entry.name.endsWith(".json")) found.push(path);
524
+ }
525
+ }
526
+ walk(dir);
527
+ return found.sort();
528
+ }
529
+ function readJson(path) {
530
+ let raw;
531
+ try {
532
+ raw = readFileSync9(path, "utf8");
533
+ } catch (error) {
534
+ return { ok: false, reason: `unreadable: ${error.message}` };
535
+ }
536
+ try {
537
+ return { ok: true, value: JSON.parse(raw) };
538
+ } catch (error) {
539
+ return { ok: false, reason: `invalid JSON: ${error.message}` };
540
+ }
541
+ }
542
+ function bumpCounter(counter, key) {
543
+ counter[key] = (counter[key] ?? 0) + 1;
544
+ }
545
+ function blobsPresent(bundleDir) {
546
+ const blobsDir = join12(bundleDir, BLOBS_SUBDIR);
547
+ if (!existsSync4(blobsDir)) return false;
548
+ try {
549
+ return readdirSync3(blobsDir).length > 0;
550
+ } catch {
551
+ return false;
552
+ }
553
+ }
554
+ function readCommittedCorpus(committedRoot, calibrationRead) {
555
+ const notices = [];
556
+ const refusals = [];
557
+ const entries = [];
558
+ const schemaVersionsSeen = {};
559
+ const labelsById = /* @__PURE__ */ new Map();
560
+ const labelHistory = [];
561
+ const excludedLabelIds = /* @__PURE__ */ new Set();
562
+ const cassettesById = /* @__PURE__ */ new Map();
563
+ const blobPresentById = /* @__PURE__ */ new Map();
564
+ if (!existsSync4(committedRoot)) {
565
+ notices.push(`committed root absent: ${committedRoot}`);
566
+ return {
567
+ snapshot: { entries, labelsById, cassettesById, blobPresentById, labelHistory, excludedLabelIds },
568
+ productsSeen: [],
569
+ notices,
570
+ refusals,
571
+ schemaVersionsSeen
572
+ };
573
+ }
574
+ const corpusRoot = join12(committedRoot, COMMITTED_CORPUS_DIR);
575
+ const productsSeen = listDirNames(corpusRoot);
576
+ for (const product of productsSeen) {
577
+ for (const path of listJsonFiles(join12(corpusRoot, product))) {
578
+ const read = readJson(path);
579
+ if (!read.ok) {
580
+ refusals.push({ path, reason: read.reason });
581
+ continue;
582
+ }
583
+ const parsed = parseCorpusEntry(read.value);
584
+ if (!parsed.ok) {
585
+ refusals.push({ path, reason: `corpus entry rejected: ${parsed.issues}` });
586
+ continue;
587
+ }
588
+ if (parsed.entry.product !== product) {
589
+ notices.push(
590
+ `corpus dir '${product}' holds an entry declaring product '${parsed.entry.product}' (${parsed.entry.cassetteId}); the entry field is authoritative`
591
+ );
592
+ }
593
+ entries.push(parsed.entry);
594
+ bumpCounter(schemaVersionsSeen, String(parsed.schemaVersion));
595
+ }
596
+ }
597
+ const labelsRoot = join12(committedRoot, COMMITTED_LABELS_DIR);
598
+ const labelOwners = /* @__PURE__ */ new Map();
599
+ const idsByBasePath = /* @__PURE__ */ new Map();
600
+ for (const entry of entries) {
601
+ const owners = labelOwners.get(entry.cassetteId) ?? /* @__PURE__ */ new Set();
602
+ owners.add(slugBranch7(entry.product));
603
+ labelOwners.set(entry.cassetteId, owners);
604
+ const path = join12(committedRoot, committedLabelPath(entry.product, entry.cassetteId));
605
+ const ids = idsByBasePath.get(path) ?? /* @__PURE__ */ new Set();
606
+ ids.add(entry.cassetteId);
607
+ idsByBasePath.set(path, ids);
608
+ }
609
+ const readInvalidIds = /* @__PURE__ */ new Set();
610
+ const validHistory = [];
611
+ for (const product of listDirNames(labelsRoot)) {
612
+ for (const path of listJsonFiles(join12(labelsRoot, product))) {
613
+ const basePath = path.replace(/--revision-[^/]*\.json$/, ".json");
614
+ const pathIds = idsByBasePath.get(basePath) ?? /* @__PURE__ */ new Set();
615
+ const refuse = (reason, cassetteId) => {
616
+ refusals.push({ path, reason });
617
+ for (const id of pathIds) readInvalidIds.add(id);
618
+ if (cassetteId !== void 0) readInvalidIds.add(cassetteId);
619
+ };
620
+ const read = readJson(path);
621
+ if (!read.ok) {
622
+ refuse("label record unreadable or invalid JSON");
623
+ continue;
624
+ }
625
+ labelHistory.push(read.value);
626
+ const parsed = parseStandaloneLabelRecord2(read.value);
627
+ if (!parsed.ok) {
628
+ const claimedId = typeof read.value === "object" && read.value !== null && "cassetteId" in read.value && typeof read.value.cassetteId === "string" ? read.value.cassetteId : void 0;
629
+ refuse(`label record rejected: ${parsed.issues}`, claimedId);
630
+ continue;
631
+ }
632
+ const record = parsed.record;
633
+ const expectedBase = join12(committedRoot, committedLabelPath(product, record.cassetteId));
634
+ const expectedPath = record.revision === void 0 ? expectedBase : expectedBase.replace(/\.json$/, `--revision-${record.revision.id}.json`);
635
+ const owners = labelOwners.get(record.cassetteId);
636
+ if (path !== expectedPath || owners !== void 0 && (owners.size !== 1 || !owners.has(product))) {
637
+ refuse("label path or product ownership mismatch", record.cassetteId);
638
+ continue;
639
+ }
640
+ validHistory.push(record);
641
+ }
642
+ }
643
+ const calibration = calibrationRead ?? readLabelCalibration(committedRoot);
644
+ const authorized = calibration.kind === "loaded" ? calibration.authorizedRevisionIds : /* @__PURE__ */ new Set();
645
+ const eligibleHistory = validHistory.filter((record) => record.revision?.generationId === void 0 || authorized.has(record.revision.id));
646
+ const generations = new Set(eligibleHistory.flatMap((record) => record.revision?.generationId ? [record.revision.generationId] : []));
647
+ if (calibration.kind === "refused") {
648
+ refusals.push({ path: join12(labelsRoot, "calibration.json"), reason: calibration.reason });
649
+ for (const id of calibration.targetCassetteIds ?? []) readInvalidIds.add(id);
650
+ for (const record of validHistory) if (record.revision?.generationId) readInvalidIds.add(record.cassetteId);
651
+ }
652
+ const selected = selectEffectiveLabels2(eligibleHistory, { committedGenerationIds: generations });
653
+ for (const [id, label] of selected.effective) {
654
+ if (!readInvalidIds.has(id)) labelsById.set(id, label);
655
+ }
656
+ for (const id of [...readInvalidIds, ...selected.excludedLabelIds]) excludedLabelIds.add(id);
657
+ for (const refusal of selected.refusals) {
658
+ refusals.push({ path: labelsRoot, reason: `label history rejected: ${refusal.reason}` });
659
+ }
660
+ for (const bundleDir of listCassetteBundleDirs(join12(committedRoot, COMMITTED_CASSETTES_DIR))) {
661
+ const load = loadCassetteBundle(bundleDir);
662
+ if (load.kind === "refused") {
663
+ refusals.push({
664
+ path: join12(bundleDir, "cassette.json"),
665
+ reason: `${load.refusal.reason}: ${load.refusal.detail}`
666
+ });
667
+ continue;
668
+ }
669
+ if (load.cassette.granularity !== "leaf") {
670
+ notices.push(`skipped non-leaf cassette bundle: ${bundleDir}`);
671
+ continue;
672
+ }
673
+ cassettesById.set(load.cassette.id, load.cassette);
674
+ blobPresentById.set(load.cassette.id, blobsPresent(bundleDir));
675
+ }
676
+ entries.sort(
677
+ (first, second) => first.cassetteId < second.cassetteId ? -1 : first.cassetteId > second.cassetteId ? 1 : 0
678
+ );
679
+ return {
680
+ corpusEntriesById: new Map(entries.map((entry) => [entry.cassetteId, entry])),
681
+ calibration: calibration.kind === "loaded" ? {
682
+ status: calibration.artifact.channels["recorded-verdict"].status,
683
+ n_gold: calibration.artifact.channels["recorded-verdict"].n_gold,
684
+ verifierFalsePassRate: calibration.artifact.verifierFalsePassRate
685
+ } : { status: "uncalibrated" },
686
+ snapshot: {
687
+ entries: entries.filter((entry) => !excludedLabelIds.has(entry.cassetteId)),
688
+ labelsById,
689
+ cassettesById,
690
+ blobPresentById,
691
+ labelHistory,
692
+ excludedLabelIds
693
+ },
694
+ productsSeen,
695
+ notices,
696
+ refusals,
697
+ schemaVersionsSeen
698
+ };
699
+ }
700
+
701
+ // src/corpus-reader.ts
702
+ function openCorpusReader(committedRoot) {
703
+ let slice;
704
+ function load() {
705
+ if (slice === void 0) {
706
+ const read = readCommittedCorpus(committedRoot);
707
+ const visible = read.snapshot.entries.filter(
708
+ (entry) => isProposerVisibleEntry(entry)
709
+ );
710
+ slice = {
711
+ visible,
712
+ visibleIds: new Set(visible.map((entry) => entry.cassetteId)),
713
+ cassettesById: read.snapshot.cassettesById,
714
+ labelsById: read.snapshot.labelsById
715
+ };
716
+ }
717
+ return slice;
718
+ }
719
+ return {
720
+ listEntries(product) {
721
+ const { visible } = load();
722
+ if (product === void 0) return visible;
723
+ return visible.filter((entry) => entry.product === product);
724
+ },
725
+ loadCassette(cassetteId) {
726
+ const { visibleIds, cassettesById } = load();
727
+ if (!visibleIds.has(cassetteId)) return { kind: "not-found" };
728
+ const cassette = cassettesById.get(cassetteId);
729
+ if (cassette === void 0) return { kind: "not-found" };
730
+ return { kind: "loaded", cassette };
731
+ },
732
+ loadLabel(cassetteId) {
733
+ const { visibleIds, labelsById } = load();
734
+ if (!visibleIds.has(cassetteId)) return { kind: "not-found" };
735
+ const record = labelsById.get(cassetteId);
736
+ if (record === void 0) return { kind: "not-found" };
737
+ return { kind: "loaded", record };
738
+ }
739
+ };
740
+ }
741
+ export {
742
+ openCorpusReader
743
+ };
744
+ //# sourceMappingURL=reader.js.map