import type { DatasetEntry } from "./dataset.ts"; export type BenchmarkVerificationMode = "all" | "sample"; export type BenchmarkVerificationResult = { verificationMode: BenchmarkVerificationMode; verifiedFiles: number; verificationComplete: boolean; datasetDigestSha256: string; }; function toHex(bytes: ArrayBuffer): string { return [...new Uint8Array(bytes)].map((value) => value.toString(16).padStart(2, "0")).join(""); } async function sha256(bytes: Uint8Array): Promise { const input = new ArrayBuffer(bytes.byteLength); new Uint8Array(input).set(bytes); return toHex(await crypto.subtle.digest("SHA-256", input)); } export function parseBenchmarkVerificationMode( raw: string | undefined, fallback: BenchmarkVerificationMode = "sample" ): BenchmarkVerificationMode { const value = raw?.trim().toLowerCase(); if (!value) return fallback; if (value === "all" || value === "sample") return value; throw new Error(`BENCH_VERIFY_MODE must be 'all' or 'sample', got '${raw}'`); } export function selectVerificationEntries(entries: DatasetEntry[], mode: BenchmarkVerificationMode): DatasetEntry[] { if (mode === "all" || entries.length === 0) return [...entries]; const md = entries.find((entry) => entry.kind === "md"); const bin = entries.find((entry) => entry.kind === "bin"); const middle = entries[Math.floor(entries.length / 2)]; const last = entries[entries.length - 1]; const selected = new Map(); for (const entry of [md, bin, middle, last]) { if (entry) selected.set(entry.relativePath, entry); } return [...selected.values()]; } export async function computeDatasetDigestSha256(entries: DatasetEntry[]): Promise { const manifest: string[] = []; for (const entry of entries) { const contentDigest = await sha256(await Deno.readFile(entry.absolutePath)); manifest.push(`${entry.kind}\t${entry.relativePath}\t${entry.size}\t${contentDigest}`); } return await sha256(new TextEncoder().encode(manifest.join("\n"))); } export async function verifyBenchmarkDataset( entries: DatasetEntry[], mode: BenchmarkVerificationMode, verifyEntry: (entry: DatasetEntry) => Promise ): Promise { const selected = selectVerificationEntries(entries, mode); for (const entry of selected) { await verifyEntry(entry); } return { verificationMode: mode, verifiedFiles: selected.length, verificationComplete: selected.length === entries.length, datasetDigestSha256: await computeDatasetDigestSha256(entries), }; }