Files
gstack/scripts/cso-eval.ts
T
Garry Tan 857466ff8b v1.91.25.0 feat(cso): private two-architecture release scoring + self-checking runtime release gates (#3036)
* v1.91.23.0 feat(cso): private two-architecture release scoring and self-checking runtime release gates

* Keep the Linux-only native-evidence and requalification tests out of the Windows lane

* Skip the two Linux-release-only checks on Windows in-file instead of growing the shard list

* fix(cso): opaque producer inputs and receipts; requalification triggers independent of cwd

Producer inputs are {schemaVersion: 2, cellRef, skill, source, execution} and
receipts bind cellRef + inputHash; collection rebuilds the cell from the
matrix, so a cell VM never learns its case or variant. requalificationTriggers
resolves Bun's cwd-relative metafile inputs against the repository root.

* test(evals): bound the review judge's thinking; guarded browser cleanup is not a probe

review/SKILL.md workflow: the ~64k-token bundle let default-effort thinking
spend all 8192 output tokens without an answer in CI. Medium effort with a
64k streaming cap kept 24/24 measured samples under 5k tokens and 63 s with
the same gating scores (as ship already does).

qa-only-no-fix: the fixture prompt routes browser cleanup through the deadline
guard, but the checkpoint detector treated every guarded run as a probe that
needs a checkpoint. A child that only closes the tab with the supplied browse
binary, after the last probe, is cleanup; anything else stays a probe. The
captured CI transcript (run 37252022510) now passes and new scenarios pin
the negative controls.

* test(evals): keep the review judge at default effort; only lift its output cap

Truncation was the defect: thinking and the answer share max_tokens, and the
~64k-token review bundle once spent all 8192. The registration keeps default
effort and response format and gets ship's 64k streaming cap; the guard test
pins exactly that.
2026-10-04 21:47:21 -07:00

920 lines
73 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bun
/** Trusted corpus preparation, producer receipt collection, and objective result accounting. */
import { createHash } from 'node:crypto';
import { execFileSync } from 'node:child_process';
import { existsSync, lstatSync, mkdirSync, readdirSync, realpathSync } from 'node:fs';
import { dirname, join, resolve } from 'node:path';
import { readBoundedStable } from '../lib/cso/bounded-file';
import { executable } from '../lib/cso/process';
import { atomicWriteSync } from '../lib/fs-atomic';
import { loadCorpusManifest, materializeCase, publicCorpus, STACKS, validateCorpusManifest, type CorpusManifest, type EvalCorpus, type EvalStack, type EvalVariant } from '../test/fixtures/cso-eval/materialize';
import {
PRODUCER_PLATFORMS,
producerArtifactInventoryHash,
producerExecution,
producerInputHash,
producerInstallationIdentityHash,
producerProviderIdentityHash,
producerReceiptHash,
sha256,
type ProducerCell,
type ProducerArtifactInventory,
type ProducerHost,
type ProducerInput,
type ProducerInstallationIdentity,
type ProducerPlatform,
type ProducerProviderIdentity,
type ProducerReceipt,
type ProducerReceiptIndex,
type ProducerSourceEntry,
} from './cso-eval-protocol';
export type EvalVersion = 'v2' | 'v3';
export type EvalMode = 'daily' | 'comprehensive';
export type Outcome = 'passed' | 'failed' | 'blocked' | 'not_attempted';
/**
* full: matched v2/v3 × 3 repetitions on one producer installation.
* release: v3 only, 1 repetition, each cell pinned to a native platform.
* baseline: v2 comprehensive only, 1 repetition; scored into a reusable EvalBaseline.
*/
export type EvalProfile = 'full' | 'release' | 'baseline';
export type EvalPlatform = ProducerPlatform;
type EvalCorpusManifest = CorpusManifest<string>;
export interface EvalCell extends ProducerCell {
id: string; caseId: string; stack: EvalStack; variant: EvalVariant; version: EvalVersion; mode: EvalMode;
repetition: 1 | 2 | 3; model: string; host: ProducerHost; budgetSeconds: number; sourceHash: string; skillHash: string; platform?: EvalPlatform;
}
interface EvalMatrixBase {
schemaVersion: 1; corpusVersion: string; corpusHash: string; model: string; host: ProducerHost;
budgets: { daily: number; comprehensive: number }; cells: EvalCell[];
}
export interface FullEvalMatrix extends EvalMatrixBase { profile?: undefined; skillHashes: { v2: string; v3: string }; repetitions: 3 }
export interface ReleaseEvalMatrix extends EvalMatrixBase {
profile: 'release'; skillHashes: { v3: string }; repetitions: 1;
/** Daily cells run on one platform; each comprehensive case is fixed to one platform. */
platforms: { daily: EvalPlatform; comprehensive: Record<string, EvalPlatform> };
/** Pre-registered external v2 baseline, or null when the regression gate stays unmeasured. */
baselineHash: string | null;
}
export interface BaselineEvalMatrix extends EvalMatrixBase {
profile: 'baseline'; skillHashes: { v2: string }; repetitions: 1;
platforms: { comprehensive: Record<string, EvalPlatform> };
}
export type EvalMatrix = FullEvalMatrix | ReleaseEvalMatrix | BaselineEvalMatrix;
interface EvalMatrixCommonOptions { model: string; host: ProducerHost; budgets?: { daily: number; comprehensive: number } }
export interface FullEvalMatrixOptions extends EvalMatrixCommonOptions { profile?: 'full'; skillHashes: { v2: string; v3: string } }
export interface ReleaseEvalMatrixOptions extends EvalMatrixCommonOptions { profile: 'release'; skillHashes: { v3: string }; platforms: ReleaseEvalMatrix['platforms']; baseline?: EvalBaseline }
export interface BaselineEvalMatrixOptions extends EvalMatrixCommonOptions { profile: 'baseline'; skillHashes: { v2: string }; platforms: BaselineEvalMatrix['platforms'] }
export type EvalMatrixOptions = FullEvalMatrixOptions | ReleaseEvalMatrixOptions | BaselineEvalMatrixOptions;
/**
* A scored v2 comprehensive run, reused by release matrices while every bound
* input is unchanged. Release matrices pin its hash before results exist.
*/
export interface EvalBaseline {
schemaVersion: 1; version: 'v2';
corpusVersion: string; corpusHash: string; model: string; host: ProducerHost; budgetSeconds: number; skillHash: string;
platforms: Record<string, EvalPlatform>;
matrixHash: string; producerBatchHash: string; modelUsed: string;
provider: { family: ProducerProviderIdentity['family']; policyRevision: string; version: string };
/** One entry per corpus case, in manifest order: whether the vulnerable cell found the seeded issue. */
cases: Array<{ caseId: string; found: boolean }>;
baselineHash: string;
}
export interface PortableSkillFile {
path: string;
contents: string;
}
export interface PortableSkillFileIdentity {
path: string;
sha256: string;
bytes: number;
}
export interface PortableSkillPayloadIdentity {
schemaVersion: 1;
version: EvalVersion;
files: PortableSkillFileIdentity[];
}
export interface EvalFinding {
id: string; evidence: 'supported' | 'hypothesis' | 'legacy_review'; claimedTested: boolean;
/** Written only by the independent evaluator after reviewing the reported trace. */
judgment: 'correct' | 'incorrect' | 'unadjudicated'; matchedCaseId?: string;
/**
* Written only by the independent evaluator. A producer's tested claim is
* valid only when this finding, rather than merely another finding in the
* same corpus cell, owns the trusted repair and recheck observations.
*/
trustedVerification?: {
repair: Outcome;
repairEvidenceHash?: string;
recheck: Outcome;
recheckEvidenceHash?: string;
};
}
export interface EvalResult {
cellId: string; sourceHash: string; skillHash: string; model: string; host: string; budgetSeconds: number;
reportPresent: boolean; reportComplete: boolean; findings: EvalFinding[];
setup: Outcome; reproduction: Outcome; repair: Outcome; recheck: Outcome;
/** Hash of trusted private observations; never a producer's claimed verification status. */
oracleEvidenceHash?: string;
oracleVersion?: string;
heldOutAssertionsPassed: boolean;
currentSourceHash?: string;
recheckEvidenceHash?: string;
freshRecheck: boolean;
latencyMs: number;
firstUsefulResultMs: number | null;
/** Required by the release scorer; omitted only by isolated accounting tests. */
producerReceiptHash?: string;
usage?: { source: 'host'; tokens?: number; costUSD?: number };
prerequisite?: string;
}
export interface Rate { numerator: number; denominator: number; value: number | null }
export interface ReleaseQualification {
containment: Record<string, 'passed' | 'failed' | 'not_run'>;
}
export interface PreparedEvalSchedule {
schemaVersion: 1;
matrixHash: string;
scheduledCells: number;
preparedCells: number;
jobs: Array<{ cellId: string; relativePath: string; inputHash: string }>;
}
export interface ProducerGroupSummary {
version: EvalVersion;
mode: EvalMode;
scheduled: number;
submitted: number;
missing: number;
succeeded: number;
failed: number;
latency: { samples: number; denominator: number; p95Ms: number | null };
firstUsefulResult: { samples: 0; denominator: number; p95Ms: null };
modelTokens: { measured: number; denominator: number; total: number | null };
estimatedCost: { measured: number; denominator: number; totalUSD: number | null; source: 'pricing-table-estimate' };
}
export interface ProducerBatch {
schemaVersion: 1;
matrixHash: string;
scheduleHash: string;
receipts: ProducerReceiptIndex[];
summary: {
scheduled: number;
prepared: number;
submitted: number;
missing: number;
matchedPairsExpected: number;
matchedPairsSubmitted: number;
modelMismatches: Array<{ pair: string; v2: string; v3: string }>;
groups: ProducerGroupSummary[];
note: string;
};
batchHash: string;
}
export const REQUIRED_CONTAINMENT = [
'hostile-startup-configuration', 'environment-canary', 'remote-docker-context', 'ipv4-egress', 'ipv6-egress', 'dns-egress',
'archive-traversal-and-poisoning', 'symlink-traversal', 'split-output-secrets', 'concurrent-admission', 'expired-snapshot-replay',
'watchdog-survival', 'failed-report-writes', 'held-out-oracle-visibility',
] as const;
const digest = (value: string) => createHash('sha256').update(value).digest('hex');
const HEX = /^[a-f0-9]{64}$/;
const rate = (numerator: number, denominator: number): Rate => ({ numerator, denominator, value: denominator ? numerator / denominator : null });
const validNumber = (value: unknown) => typeof value === 'number' && Number.isFinite(value) && value >= 0;
const PORTABLE_PAYLOAD_HEADER = '<!-- GSTACK_CSO_EVAL_PAYLOAD ';
const PORTABLE_PAYLOAD_HEADER_END = ' -->\n';
const PORTABLE_FILE_END = '\n<<<END_GSTACK_CSO_EVAL_FILE>>>\n';
const PORTABLE_FILE_LIMIT = 2 * 1024 * 1024;
const PORTABLE_PAYLOAD_LIMIT = 4 * 1024 * 1024;
function portablePayloadPreamble(version: EvalVersion): string {
return `# Complete portable CSO evaluation instructions (${version})\n\nThis package is the sole CSO instruction input for this evaluation cell. Apply the embedded SKILL.md and every embedded manifest-listed section. Resolve any SKILL.md reference to cso/sections/<file> or sections/<file> from the matching embedded file below. Do not read an installed, user-home, repository, or other-version CSO skill or section. The file bodies are exact generated bytes; package markers are transport metadata.\n\n`;
}
function portableFileOpen(identity: PortableSkillFileIdentity): string {
return `<<<GSTACK_CSO_EVAL_FILE ${JSON.stringify(identity)}>>>\n`;
}
function parsePortableManifest(contents: string): { files: string[] } {
let manifest: any;
try { manifest = JSON.parse(contents); } catch { throw new Error('INVALID_CSO_EVAL_PAYLOAD_MANIFEST'); }
if (!manifest || manifest.skill !== 'cso' || manifest.version !== 1 || !Array.isArray(manifest.sections) || manifest.sections.length === 0) throw new Error('INVALID_CSO_EVAL_PAYLOAD_MANIFEST');
const files: string[] = [];
const ids = new Set<string>();
for (const section of manifest.sections) {
if (!section || typeof section.id !== 'string' || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(section.id) || ids.has(section.id) || typeof section.file !== 'string' || !/^[a-z0-9]+(?:-[a-z0-9]+)*\.md$/.test(section.file) || files.includes(section.file) || typeof section.title !== 'string' || !section.title.trim() || typeof section.trigger !== 'string' || !section.trigger.trim()) throw new Error('INVALID_CSO_EVAL_PAYLOAD_MANIFEST');
ids.add(section.id); files.push(section.file);
}
return { files };
}
function validatePortableSkillFiles(version: EvalVersion, files: PortableSkillFile[]): PortableSkillFile[] {
if (!['v2', 'v3'].includes(version) || !Array.isArray(files)) throw new Error('INVALID_CSO_EVAL_PAYLOAD');
const byPath = new Map<string, string>();
for (const file of files) {
if (!file || typeof file.path !== 'string' || typeof file.contents !== 'string' || byPath.has(file.path) || Buffer.byteLength(file.contents) > PORTABLE_FILE_LIMIT || file.contents.includes(PORTABLE_FILE_END.trim())) throw new Error('INVALID_CSO_EVAL_PAYLOAD');
byPath.set(file.path, file.contents);
}
const root = byPath.get('SKILL.md'), manifest = byPath.get('sections/manifest.json');
if (root === undefined || manifest === undefined) throw new Error('INCOMPLETE_CSO_EVAL_PAYLOAD');
const frontmatter = root.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/)?.[1];
const versionMatch = frontmatter?.match(/^version:\s*([0-9]+)(?:\.[0-9]+){0,2}\s*$/m);
if (!versionMatch || Number(versionMatch[1]) !== Number(version.slice(1))) throw new Error('CSO_EVAL_PAYLOAD_VERSION_MISMATCH');
const sectionFiles = parsePortableManifest(manifest).files;
const expectedPaths = ['SKILL.md', 'sections/manifest.json', ...sectionFiles.map(file => `sections/${file}`)];
if (byPath.size !== expectedPaths.length || expectedPaths.some(path => !byPath.has(path))) throw new Error('INCOMPLETE_CSO_EVAL_PAYLOAD');
return expectedPaths.map(path => ({ path, contents: byPath.get(path)! }));
}
/** Render the only portable instruction format accepted by matrix preparation. */
export function createPortableSkillPayload(version: EvalVersion, inputFiles: PortableSkillFile[]): string {
const files = validatePortableSkillFiles(version, inputFiles);
const identities = files.map(file => ({ path: file.path, sha256: sha256(file.contents), bytes: Buffer.byteLength(file.contents) }));
const identity: PortableSkillPayloadIdentity = { schemaVersion: 1, version, files: identities };
let payload = `${PORTABLE_PAYLOAD_HEADER}${JSON.stringify(identity)}${PORTABLE_PAYLOAD_HEADER_END}${portablePayloadPreamble(version)}`;
for (let index = 0; index < files.length; index++) payload += `${portableFileOpen(identities[index])}${files[index].contents}${PORTABLE_FILE_END}`;
if (Buffer.byteLength(payload) > PORTABLE_PAYLOAD_LIMIT) throw new Error('CSO_EVAL_PAYLOAD_TOO_LARGE');
return payload;
}
/** Validate canonical serialization and return the identities bound by its hash. */
export function validatePortableSkillPayload(payload: string, expectedVersion?: EvalVersion): PortableSkillPayloadIdentity {
if (typeof payload !== 'string' || Buffer.byteLength(payload) > PORTABLE_PAYLOAD_LIMIT || !payload.startsWith(PORTABLE_PAYLOAD_HEADER)) throw new Error('INVALID_CSO_EVAL_PAYLOAD');
const headerEnd = payload.indexOf(PORTABLE_PAYLOAD_HEADER_END, PORTABLE_PAYLOAD_HEADER.length);
if (headerEnd < 0) throw new Error('INVALID_CSO_EVAL_PAYLOAD');
let identity: PortableSkillPayloadIdentity;
try { identity = JSON.parse(payload.slice(PORTABLE_PAYLOAD_HEADER.length, headerEnd)); } catch { throw new Error('INVALID_CSO_EVAL_PAYLOAD'); }
if (identity?.schemaVersion !== 1 || !['v2', 'v3'].includes(identity.version) || (expectedVersion && identity.version !== expectedVersion) || !Array.isArray(identity.files)) throw new Error('INVALID_CSO_EVAL_PAYLOAD');
let cursor = headerEnd + PORTABLE_PAYLOAD_HEADER_END.length;
const preamble = portablePayloadPreamble(identity.version);
if (payload.slice(cursor, cursor + preamble.length) !== preamble) throw new Error('INVALID_CSO_EVAL_PAYLOAD');
cursor += preamble.length;
const files: PortableSkillFile[] = [];
for (const file of identity.files) {
if (!file || typeof file.path !== 'string' || !HEX.test(file.sha256) || !Number.isSafeInteger(file.bytes) || file.bytes < 0 || file.bytes > PORTABLE_FILE_LIMIT) throw new Error('INVALID_CSO_EVAL_PAYLOAD');
const open = portableFileOpen(file);
if (payload.slice(cursor, cursor + open.length) !== open) throw new Error('INVALID_CSO_EVAL_PAYLOAD');
cursor += open.length;
const end = payload.indexOf(PORTABLE_FILE_END, cursor);
if (end < 0) throw new Error('INVALID_CSO_EVAL_PAYLOAD');
const contents = payload.slice(cursor, end);
if (Buffer.byteLength(contents) !== file.bytes || sha256(contents) !== file.sha256) throw new Error('INVALID_CSO_EVAL_PAYLOAD');
files.push({ path: file.path, contents }); cursor = end + PORTABLE_FILE_END.length;
}
if (cursor !== payload.length || createPortableSkillPayload(identity.version, files) !== payload) throw new Error('INVALID_CSO_EVAL_PAYLOAD');
return identity;
}
/** Read one generated CSO skill tree and package every manifest-listed section. */
export function loadPortableSkillPayload(version: EvalVersion, skillDirectory: string): string {
const root = resolve(skillDirectory), stat = lstatSync(root);
if (!stat.isDirectory() || stat.isSymbolicLink() || realpathSync(root) !== root) throw new Error('UNSAFE_CSO_EVAL_SKILL_DIRECTORY');
const read = (relativePath: string) => {
const bytes = readBoundedStable(join(root, ...relativePath.split('/')), PORTABLE_FILE_LIMIT, `CSO ${version} ${relativePath}`);
const contents = bytes.toString('utf8');
if (!Buffer.from(contents).equals(bytes)) throw new Error('INVALID_CSO_EVAL_PAYLOAD_ENCODING');
return contents;
};
const rootSkill = read('SKILL.md'), manifest = read('sections/manifest.json');
const sectionFiles = parsePortableManifest(manifest).files;
const sectionsRoot = join(root, 'sections'), sectionStat = lstatSync(sectionsRoot);
if (!sectionStat.isDirectory() || sectionStat.isSymbolicLink() || realpathSync(sectionsRoot) !== sectionsRoot) throw new Error('UNSAFE_CSO_EVAL_SKILL_DIRECTORY');
const listed = new Set(sectionFiles);
const inventory = () => readdirSync(sectionsRoot, { withFileTypes: true }).filter(entry => entry.name.endsWith('.md')).map(entry => {
if (!entry.isFile() || entry.isSymbolicLink() || !listed.has(entry.name)) throw new Error('UNLISTED_CSO_EVAL_SECTION');
return entry.name;
}).sort();
const firstInventory = inventory();
const files = [
{ path: 'SKILL.md', contents: rootSkill },
{ path: 'sections/manifest.json', contents: manifest },
...sectionFiles.map(file => ({ path: `sections/${file}`, contents: read(`sections/${file}`) })),
];
if (JSON.stringify(inventory()) !== JSON.stringify(firstInventory) || files.some(file => read(file.path) !== file.contents)) throw new Error('CSO_EVAL_SKILL_CHANGED_DURING_PACKAGING');
return createPortableSkillPayload(version, files);
}
function matrixHash(matrix: EvalMatrix): string { return digest(JSON.stringify(matrix)); }
function safeWriteNew(path: string, value: unknown): void {
const target = resolve(path), parent = dirname(target), stat = lstatSync(parent);
if (!stat.isDirectory() || stat.isSymbolicLink() || realpathSync(parent) !== parent) throw new Error('UNSAFE_EVAL_DESTINATION');
atomicWriteSync(target, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600, noReplace: true });
}
function readJsonBounded(path: string, max: number, label: string): any {
try { return JSON.parse(readBoundedStable(resolve(path), max, label).toString('utf8')); }
catch (error) { if (error instanceof SyntaxError) throw new Error(`INVALID_${label.toUpperCase().replaceAll(' ', '_')}`); throw error; }
}
function initializeFixtureRepository(path: string): void {
const nullPath = process.platform === 'win32' ? 'NUL' : '/dev/null';
const env = {
PATH: process.env.PATH ?? '', LANG: 'C', LC_ALL: 'C',
GIT_CONFIG_NOSYSTEM: '1', GIT_CONFIG_GLOBAL: nullPath, GIT_ATTR_NOSYSTEM: '1',
GIT_AUTHOR_NAME: 'CSO Eval', GIT_AUTHOR_EMAIL: 'cso-eval@invalid',
GIT_COMMITTER_NAME: 'CSO Eval', GIT_COMMITTER_EMAIL: 'cso-eval@invalid',
};
const git = executable('git');
// Prepared sources are copied immediately. A detached auto-maintenance child
// can remove .git/objects/maintenance.lock while that copy is in progress.
const safe = ['-c', 'maintenance.auto=false', '-c', 'gc.auto=0',
'-c', `core.hooksPath=${nullPath}`, '-c', `core.attributesFile=${nullPath}`, '-c', `core.excludesFile=${nullPath}`];
execFileSync(git, [...safe, 'init', '--quiet', '--initial-branch=main'], { cwd: path, env, stdio: 'ignore' });
execFileSync(git, [...safe, 'add', '--all'], { cwd: path, env, stdio: 'ignore' });
execFileSync(git, [...safe, 'commit', '--quiet', '-m', 'immutable evaluation fixture'], { cwd: path, env, stdio: 'ignore' });
}
function sourceEntries(corpus: EvalCorpus, caseId: string, variant: EvalVariant): ProducerSourceEntry[] {
return Object.entries(corpus.sourceFiles(caseId, variant)).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0).map(([path, contents]) => ({ path, sha256: sha256(contents), bytes: Buffer.byteLength(contents) }));
}
/**
* Prepare independent one-cell jobs. The returned schedule is trusted
* evaluator metadata; transfer one job at a time and never give the schedule
* or sibling jobs to the producing agent.
*/
export function prepareEvalJobs(matrix: EvalMatrix, payloads: Partial<Record<EvalVersion, string>>, destination: string, selectedCellIds?: string[], corpus: EvalCorpus = publicCorpus()): PreparedEvalSchedule {
validateMatrix(matrix, corpus.manifest);
const skillHashes: Partial<Record<EvalVersion, string>> = matrix.skillHashes;
const versions = (['v2', 'v3'] as const).filter(version => skillHashes[version] !== undefined);
if (!payloads || Object.keys(payloads).sort().join(',') !== versions.join(',')) throw new Error('EVAL_SKILL_HASH_MISMATCH');
for (const version of versions) {
validatePortableSkillPayload(payloads[version]!, version);
if (sha256(payloads[version]!) !== skillHashes[version]) throw new Error('EVAL_SKILL_HASH_MISMATCH');
}
const root = resolve(destination);
if (existsSync(root)) throw new Error('EVAL_DESTINATION_EXISTS');
const parent = dirname(root);
if (realpathSync(parent) !== parent || !lstatSync(parent).isDirectory()) throw new Error('UNSAFE_EVAL_DESTINATION');
const selected = selectedCellIds === undefined ? matrix.cells : selectedCellIds.map(id => {
const cell = matrix.cells.find(item => item.id === id);
if (!cell) throw new Error('UNKNOWN_EVAL_CELL');
return cell;
});
if (new Set(selected.map(cell => cell.id)).size !== selected.length) throw new Error('DUPLICATE_EVAL_CELL');
mkdirSync(root, { mode: 0o700 });
const jobsRoot = join(root, 'jobs'); mkdirSync(jobsRoot, { mode: 0o700 });
const jobs: PreparedEvalSchedule['jobs'] = [];
for (const cell of selected) {
const jobRoot = join(jobsRoot, cell.id); mkdirSync(jobRoot, { mode: 0o700 });
const source = materializeCase(cell.caseId, cell.variant, join(jobRoot, 'source'), corpus);
if (source.sourceHash !== cell.sourceHash) throw new Error('CORPUS_INTEGRITY_MISMATCH');
initializeFixtureRepository(source.path);
const input: ProducerInput = { schemaVersion: 2, cellRef: cell.id, skill: payloads[cell.version]!, source: sourceEntries(corpus, cell.caseId, cell.variant), execution: producerExecution(cell) };
const inputHash = producerInputHash(input);
safeWriteNew(join(jobRoot, 'producer-input.json'), input);
jobs.push({ cellId: cell.id, relativePath: `jobs/${cell.id}`, inputHash });
}
const schedule: PreparedEvalSchedule = { schemaVersion: 1, matrixHash: matrixHash(matrix), scheduledCells: matrix.cells.length, preparedCells: jobs.length, jobs };
safeWriteNew(join(root, 'schedule.json'), schedule);
return schedule;
}
function validateSchedule(matrix: EvalMatrix, schedule: PreparedEvalSchedule): void {
if (schedule?.schemaVersion !== 1 || schedule.matrixHash !== matrixHash(matrix) || schedule.scheduledCells !== matrix.cells.length || !Array.isArray(schedule.jobs) || schedule.preparedCells !== schedule.jobs.length) throw new Error('INVALID_EVAL_SCHEDULE');
const known = new Set(matrix.cells.map(cell => cell.id));
const seen = new Set<string>();
for (const job of schedule.jobs) {
if (!job || !known.has(job.cellId) || seen.has(job.cellId) || job.relativePath !== `jobs/${job.cellId}` || !HEX.test(job.inputHash)) throw new Error('INVALID_EVAL_SCHEDULE');
seen.add(job.cellId);
}
}
function validateReceipt(receipt: ProducerReceipt, cell: EvalCell, inputHash: string): void {
if (receipt?.schemaVersion !== 2 || receipt.cellRef !== cell.id || 'cell' in receipt || receipt.inputHash !== inputHash || receipt.requestedModel !== cell.model || !['succeeded', 'failed'].includes(receipt.status) || typeof receipt.modelUsed !== 'string' || !receipt.modelUsed || !['provider_reported', 'requested_pin'].includes(receipt.modelIdentitySource) || (receipt.modelIdentitySource === 'requested_pin' && receipt.modelUsed !== receipt.requestedModel) || (receipt.modelIdentitySource === 'provider_reported' && receipt.modelUsed === receipt.requestedModel) || !validNumber(receipt.durationMs) || receipt.firstUsefulResultMs !== null || !Number.isSafeInteger(receipt.toolCalls) || receipt.toolCalls < 0 || typeof receipt.output !== 'string' || receipt.outputHash !== sha256(receipt.output) || !HEX.test(receipt.receiptHash)) throw new Error('INVALID_PRODUCER_RECEIPT');
const { receiptHash, ...withoutHash } = receipt;
if (producerReceiptHash(withoutHash) !== receiptHash) throw new Error('INVALID_PRODUCER_RECEIPT');
const started = Date.parse(receipt.startedAt), finished = Date.parse(receipt.finishedAt);
if (!Number.isFinite(started) || !Number.isFinite(finished) || finished < started) throw new Error('INVALID_PRODUCER_RECEIPT');
if (!receipt.usage || !['inputTokens', 'outputTokens', 'cachedTokens', 'estimatedCostUSD'].every(field => receipt.usage[field as keyof typeof receipt.usage] === null || validNumber(receipt.usage[field as keyof typeof receipt.usage]))) throw new Error('INVALID_PRODUCER_RECEIPT');
const hasError = !!receipt.error;
if ((receipt.status === 'failed') !== hasError || (hasError && (!receipt.error!.code || typeof receipt.error!.reason !== 'string'))) throw new Error('INVALID_PRODUCER_RECEIPT');
validateInstallationIdentity(receipt.installationIdentity, 'INVALID_PRODUCER_RECEIPT');
validateProviderIdentity(receipt.providerIdentity, cell.host === 'codex' ? 'gpt' : cell.host, 'INVALID_PRODUCER_RECEIPT');
validateArtifactInventory(receipt.artifacts, 'INVALID_PRODUCER_RECEIPT');
}
function validateInstallationIdentity(identity: ProducerInstallationIdentity, error: string): void {
const artifact = (value: any) => value && HEX.test(value.sha256) && Number.isSafeInteger(value.bytes) && value.bytes > 0;
if (!identity || identity.schemaVersion !== 1 || !artifact(identity.producer) || !artifact(identity.launcher) || !artifact(identity.core) || !artifact(identity.watchdog) ||
!identity.embeddedCatalogs || !identity.embeddedCatalogs.runtimeRevision || !identity.embeddedCatalogs.runtimeBuildRevision || !HEX.test(identity.embeddedCatalogs.runtimeSha256) ||
!identity.embeddedCatalogs.scannerRevision || !HEX.test(identity.embeddedCatalogs.scannerSha256) || !HEX.test(identity.identityHash)) throw new Error(error);
const { identityHash, ...withoutHash } = identity;
if (producerInstallationIdentityHash(withoutHash) !== identityHash) throw new Error(error);
}
function validateProviderIdentity(identity: ProducerProviderIdentity, family: 'claude' | 'gpt' | 'gemini', error: string): void {
if (!identity || identity.schemaVersion !== 1 || identity.family !== family || !identity.policyRevision || !identity.version ||
!identity.executable || !HEX.test(identity.executable.sha256) || !Number.isSafeInteger(identity.executable.bytes) || identity.executable.bytes <= 0 ||
!Array.isArray(identity.argsPrefix) || identity.argsPrefix.some(value => typeof value !== 'string' || value.includes('\0')) || !HEX.test(identity.identityHash)) throw new Error(error);
const { identityHash, ...withoutHash } = identity;
if (producerProviderIdentityHash(withoutHash) !== identityHash) throw new Error(error);
}
function validateArtifactInventory(inventory: ProducerArtifactInventory, error: string): void {
if (!inventory || inventory.schemaVersion !== 1 || inventory.root !== 'security/cso' || !Array.isArray(inventory.entries) || inventory.entries.length > 4096 ||
!Number.isSafeInteger(inventory.totalBytes) || inventory.totalBytes < 0 || inventory.totalBytes > 128 * 1024 * 1024 || !HEX.test(inventory.identityHash)) throw new Error(error);
let previous = '', total = 0;
for (const entry of inventory.entries) {
if (!entry || typeof entry.path !== 'string' || entry.path.length > 1024 || !/^[A-Za-z0-9._/-]+$/.test(entry.path) || entry.path.split('/').some(part => !part || part === '.' || part === '..') ||
entry.path <= previous || !HEX.test(entry.sha256) || !Number.isSafeInteger(entry.bytes) || entry.bytes < 0 || entry.bytes > 32 * 1024 * 1024) throw new Error(error);
previous = entry.path; total += entry.bytes;
}
if (total !== inventory.totalBytes) throw new Error(error);
const { identityHash, ...withoutHash } = inventory;
if (producerArtifactInventoryHash(withoutHash) !== identityHash) throw new Error(error);
}
function validateReceiptIndex(receipt: ProducerReceiptIndex, cell: EvalCell): void {
if (!receipt || receipt.schemaVersion !== 2 || receipt.cellRef !== cell.id || JSON.stringify(receipt.cell) !== JSON.stringify(cell) || !HEX.test(receipt.inputHash) || receipt.requestedModel !== cell.model || !receipt.modelUsed || !['provider_reported', 'requested_pin'].includes(receipt.modelIdentitySource) || (receipt.modelIdentitySource === 'requested_pin' && receipt.modelUsed !== receipt.requestedModel) || (receipt.modelIdentitySource === 'provider_reported' && receipt.modelUsed === receipt.requestedModel) || !['succeeded', 'failed'].includes(receipt.status) || !HEX.test(receipt.outputHash) || !HEX.test(receipt.receiptHash) || !validNumber(receipt.durationMs) || receipt.firstUsefulResultMs !== null || !Number.isSafeInteger(receipt.toolCalls) || receipt.toolCalls < 0 || !receipt.usage) throw new Error('INVALID_PRODUCER_BATCH');
const started = Date.parse(receipt.startedAt), finished = Date.parse(receipt.finishedAt);
if (!Number.isFinite(started) || !Number.isFinite(finished) || finished < started || !['inputTokens', 'outputTokens', 'cachedTokens', 'estimatedCostUSD'].every(field => receipt.usage[field as keyof typeof receipt.usage] === null || validNumber(receipt.usage[field as keyof typeof receipt.usage])) || ((receipt.status === 'failed') !== !!receipt.error) || (receipt.error && !receipt.error.code)) throw new Error('INVALID_PRODUCER_BATCH');
validateInstallationIdentity(receipt.installationIdentity, 'INVALID_PRODUCER_BATCH');
validateProviderIdentity(receipt.providerIdentity, cell.host === 'codex' ? 'gpt' : cell.host, 'INVALID_PRODUCER_BATCH');
validateArtifactInventory(receipt.artifacts, 'INVALID_PRODUCER_BATCH');
}
const matchedPairKey = (cell: EvalCell): string => [cell.caseId, cell.variant, cell.mode, cell.repetition, cell.model, cell.host, cell.budgetSeconds, cell.sourceHash].join('|');
const PROFILE_GROUPS: Record<EvalProfile, ReadonlyArray<readonly [EvalVersion, EvalMode]>> = {
full: [['v2', 'daily'], ['v2', 'comprehensive'], ['v3', 'daily'], ['v3', 'comprehensive']],
release: [['v3', 'daily'], ['v3', 'comprehensive']],
baseline: [['v2', 'comprehensive']],
};
const profileOf = (matrix: EvalMatrix): EvalProfile => matrix.profile ?? 'full';
const expectedMatchedPairs = (matrix: EvalMatrix): number => profileOf(matrix) === 'full' ? matrix.cells.length / 2 : 0;
type IdentityBearing = Pick<ProducerReceiptIndex, 'cell' | 'installationIdentity' | 'providerIdentity'>;
/**
* Each platform has exactly one producer installation and provider binary.
* Platforms differ only in native binaries: the embedded catalogs and the
* reviewed provider policy must be identical across them.
*/
function assertPlatformIdentities(receipts: IdentityBearing[]): void {
const byPlatform = new Map<string, IdentityBearing[]>();
for (const receipt of receipts) {
const key = receipt.cell.platform ?? 'unpinned', list = byPlatform.get(key) ?? [];
list.push(receipt); byPlatform.set(key, list);
}
for (const list of byPlatform.values()) {
if (new Set(list.map(receipt => receipt.installationIdentity.identityHash)).size > 1) throw new Error('UNMATCHED_PRODUCER_INSTALLATIONS');
if (new Set(list.map(receipt => receipt.providerIdentity.identityHash)).size > 1) throw new Error('UNMATCHED_PRODUCER_PROVIDERS');
}
const representatives = [...byPlatform.values()].map(list => list[0]);
if (representatives.length < 2) return;
if (new Set(representatives.map(receipt => receipt.installationIdentity.identityHash)).size !== representatives.length) throw new Error('UNMATCHED_PRODUCER_PLATFORMS');
const catalogs = (receipt: IdentityBearing) => JSON.stringify(receipt.installationIdentity.embeddedCatalogs);
const policy = ({ providerIdentity: { family, policyRevision, version, argsPrefix } }: IdentityBearing) => JSON.stringify({ family, policyRevision, version, argsPrefix });
if (new Set(representatives.map(catalogs)).size !== 1) throw new Error('UNMATCHED_PRODUCER_INSTALLATIONS');
if (new Set(representatives.map(policy)).size !== 1) throw new Error('UNMATCHED_PRODUCER_PROVIDERS');
}
export function collectProducerReceipts(matrix: EvalMatrix, schedule: PreparedEvalSchedule, receipts: ProducerReceipt[], corpus: EvalCorpusManifest = loadCorpusManifest()): ProducerBatch {
validateMatrix(matrix, corpus); validateSchedule(matrix, schedule);
if (!Array.isArray(receipts)) throw new Error('INVALID_PRODUCER_RECEIPTS');
const cells = new Map(matrix.cells.map(cell => [cell.id, cell]));
const jobs = new Map(schedule.jobs.map(job => [job.cellId, job]));
const seen = new Set<string>();
for (const receipt of receipts) {
const cell = cells.get(receipt?.cellRef), job = jobs.get(receipt?.cellRef);
if (!cell || !job || seen.has(cell.id)) throw new Error('UNKNOWN_OR_DUPLICATE_PRODUCER_RECEIPT');
validateReceipt(receipt, cell, job.inputHash); seen.add(cell.id);
}
// Receipts name only the opaque cellRef; the trusted matrix supplies the cell.
const bound = receipts.map(receipt => ({ ...receipt, cell: cells.get(receipt.cellRef)! }));
assertPlatformIdentities(bound);
const pairs = new Map<string, Partial<Record<EvalVersion, (typeof bound)[number]>>>();
if (profileOf(matrix) === 'full') for (const receipt of bound) {
const key = matchedPairKey(receipt.cell as EvalCell);
const pair = pairs.get(key) ?? {}; pair[receipt.cell.version] = receipt; pairs.set(key, pair);
}
else if (new Set(bound.map(receipt => receipt.modelUsed)).size > 1) throw new Error('UNMATCHED_EFFECTIVE_MODELS: single-version cells used different normalized model identities');
const completePairs = [...pairs.entries()].filter(([, pair]) => pair.v2 && pair.v3) as Array<[string, { v2: (typeof bound)[number]; v3: (typeof bound)[number] }]>;
const modelMismatches = completePairs.filter(([, pair]) => pair.v2.modelUsed !== pair.v3.modelUsed).map(([pair, value]) => ({ pair: digest(pair), v2: value.v2.modelUsed, v3: value.v3.modelUsed }));
if (modelMismatches.length) throw new Error(`UNMATCHED_EFFECTIVE_MODELS: ${modelMismatches.length} matched v2/v3 pair(s) used different normalized model identities`);
const groups: ProducerGroupSummary[] = [];
for (const [version, mode] of PROFILE_GROUPS[profileOf(matrix)]) {
const expected = matrix.cells.filter(cell => cell.version === version && cell.mode === mode);
const submitted = bound.filter(receipt => receipt.cell.version === version && receipt.cell.mode === mode);
const tokens = submitted.flatMap(receipt => receipt.usage.inputTokens === null || receipt.usage.outputTokens === null ? [] : [receipt.usage.inputTokens + receipt.usage.outputTokens]);
const costs = submitted.flatMap(receipt => receipt.usage.estimatedCostUSD === null ? [] : [receipt.usage.estimatedCostUSD]);
groups.push({ version, mode, scheduled: expected.length, submitted: submitted.length, missing: expected.length - submitted.length, succeeded: submitted.filter(receipt => receipt.status === 'succeeded').length, failed: submitted.filter(receipt => receipt.status === 'failed').length,
latency: { samples: submitted.length, denominator: expected.length, p95Ms: quantile(submitted.map(receipt => receipt.durationMs), 0.95) },
firstUsefulResult: { samples: 0, denominator: expected.length, p95Ms: null },
modelTokens: { measured: tokens.length, denominator: expected.length, total: tokens.length ? tokens.reduce((sum, value) => sum + value, 0) : null },
estimatedCost: { measured: costs.length, denominator: expected.length, totalUSD: costs.length ? costs.reduce((sum, value) => sum + value, 0) : null, source: 'pricing-table-estimate' },
});
}
const indexes: ProducerReceiptIndex[] = bound.map(({ output: _output, error, ...receipt }) => ({ ...receipt, ...(error ? { error: { code: error.code } } : {}) }));
const base = { schemaVersion: 1 as const, matrixHash: matrixHash(matrix), scheduleHash: digest(JSON.stringify(schedule)), receipts: indexes.sort((left, right) => left.cell.id.localeCompare(right.cell.id)), summary: {
scheduled: matrix.cells.length, prepared: schedule.preparedCells, submitted: bound.length, missing: matrix.cells.length - bound.length,
matchedPairsExpected: expectedMatchedPairs(matrix), matchedPairsSubmitted: completePairs.length, modelMismatches, groups,
note: 'Costs are pricing-table estimates. First-useful timing is unmeasured because the reused provider adapters return completed runs. Trusted findings and runtime outcomes require separate oracle adjudication.',
} };
return { ...base, batchHash: digest(JSON.stringify(base)) };
}
function normalizedPlatforms(corpus: EvalCorpusManifest, value: unknown): Record<string, EvalPlatform> {
const assignment = value as Record<string, EvalPlatform>;
if (!assignment || typeof assignment !== 'object' || Array.isArray(assignment) || Object.keys(assignment).length !== corpus.cases.length ||
corpus.cases.some(fixture => !PRODUCER_PLATFORMS.includes(assignment[fixture.id]))) throw new Error('INVALID_EVAL_PLATFORMS');
return Object.fromEntries(corpus.cases.map(fixture => [fixture.id, assignment[fixture.id]]));
}
function buildEvalMatrix(options: EvalMatrixOptions, corpus: EvalCorpusManifest, baselineHash: string | null): EvalMatrix {
const profile = options.profile ?? 'full';
const skillHashes: Partial<Record<EvalVersion, string>> = options.skillHashes ?? {};
const versions = profile === 'full' ? ['v2', 'v3'] : profile === 'release' ? ['v3'] : ['v2'];
if (!options.model?.trim() || !['claude', 'codex', 'gemini'].includes(options.host) || !['full', 'release', 'baseline'].includes(profile) ||
Object.keys(skillHashes).sort().join(',') !== versions.join(',') || versions.some(version => !HEX.test(skillHashes[version as EvalVersion] ?? '')) ||
(profile === 'full' && skillHashes.v2 === skillHashes.v3)) throw new Error('INVALID_MATCHED_EVAL_INPUT');
const budgets = options.budgets ?? { daily: 600, comprehensive: 1800 };
if (![budgets.daily, budgets.comprehensive].every(value => Number.isInteger(value) && value > 60 && value <= 3600)) throw new Error('INVALID_EVAL_BUDGET');
const corpusHash = digest(JSON.stringify(corpus));
const cells: EvalCell[] = [];
if (options.profile === undefined || options.profile === 'full') {
for (const fixture of corpus.cases) for (const variant of ['vulnerable', 'fixed'] as const) for (const mode of ['daily', 'comprehensive'] as const) for (const repetition of [1, 2, 3] as const) for (const version of ['v2', 'v3'] as const) {
const cell = { caseId: fixture.id, stack: fixture.stack, variant, version, mode, repetition, model: options.model, host: options.host, budgetSeconds: budgets[mode], sourceHash: fixture.filesHash[variant], skillHash: options.skillHashes[version] };
cells.push({ id: digest(JSON.stringify(cell)), ...cell });
}
return { schemaVersion: 1, corpusVersion: corpus.version, corpusHash, model: options.model, host: options.host, budgets, skillHashes: options.skillHashes, repetitions: 3, cells };
}
const pinned = options as ReleaseEvalMatrixOptions | BaselineEvalMatrixOptions;
const platformKeys = pinned.profile === 'release' ? 'comprehensive,daily' : 'comprehensive';
if (!pinned.platforms || Object.keys(pinned.platforms).sort().join(',') !== platformKeys) throw new Error('INVALID_EVAL_PLATFORMS');
const comprehensive = normalizedPlatforms(corpus, pinned.platforms.comprehensive);
const daily = pinned.profile === 'release' ? pinned.platforms.daily : undefined;
if (pinned.profile === 'release' && !PRODUCER_PLATFORMS.includes(daily!)) throw new Error('INVALID_EVAL_PLATFORMS');
const version: EvalVersion = pinned.profile === 'release' ? 'v3' : 'v2';
const modes = pinned.profile === 'release' ? ['daily', 'comprehensive'] as const : ['comprehensive'] as const;
for (const fixture of corpus.cases) for (const variant of ['vulnerable', 'fixed'] as const) for (const mode of modes) {
const cell = { caseId: fixture.id, stack: fixture.stack, variant, version, mode, repetition: 1 as const, model: pinned.model, host: pinned.host, budgetSeconds: budgets[mode], sourceHash: fixture.filesHash[variant], skillHash: skillHashes[version]!, platform: mode === 'daily' ? daily! : comprehensive[fixture.id] };
cells.push({ id: digest(JSON.stringify(cell)), ...cell });
}
const common = { schemaVersion: 1 as const, corpusVersion: corpus.version, corpusHash, model: pinned.model, host: pinned.host, budgets };
if (pinned.profile === 'release') {
if (baselineHash !== null && !HEX.test(baselineHash)) throw new Error('UNBOUND_EVAL_BASELINE');
return { ...common, profile: 'release', skillHashes: { v3: pinned.skillHashes.v3 }, repetitions: 1, platforms: { daily: daily!, comprehensive }, baselineHash, cells };
}
return { ...common, profile: 'baseline', skillHashes: { v2: pinned.skillHashes.v2 }, repetitions: 1, platforms: { comprehensive }, cells };
}
const BASELINE_FIELDS = 'baselineHash,budgetSeconds,cases,corpusHash,corpusVersion,host,matrixHash,model,modelUsed,platforms,producerBatchHash,provider,schemaVersion,skillHash,version';
/** Check that a baseline was measured under the same corpus, model, host, budget and platform assignment. */
function assertBaselineBinding(baseline: EvalBaseline, target: { corpus: EvalCorpusManifest; model: string; host: ProducerHost; budgetSeconds: number; platforms: Record<string, EvalPlatform> }): void {
if (!baseline || typeof baseline !== 'object' || Object.keys(baseline).sort().join(',') !== BASELINE_FIELDS) throw new Error('UNBOUND_EVAL_BASELINE');
const { baselineHash, ...record } = baseline;
const provider = baseline.provider as unknown as Record<string, unknown>;
if (baseline.schemaVersion !== 1 || baseline.version !== 'v2' || !HEX.test(baselineHash) || digest(JSON.stringify(record)) !== baselineHash ||
baseline.corpusVersion !== target.corpus.version || baseline.corpusHash !== digest(JSON.stringify(target.corpus)) ||
baseline.model !== target.model || baseline.host !== target.host || baseline.budgetSeconds !== target.budgetSeconds ||
JSON.stringify(baseline.platforms) !== JSON.stringify(target.platforms) || !HEX.test(baseline.skillHash) || !HEX.test(baseline.matrixHash) ||
!HEX.test(baseline.producerBatchHash) || typeof baseline.modelUsed !== 'string' || !baseline.modelUsed ||
!provider || typeof provider !== 'object' || Object.keys(provider).sort().join(',') !== 'family,policyRevision,version' ||
!['claude', 'gpt', 'gemini'].includes(String(provider.family)) || typeof provider.policyRevision !== 'string' || !provider.policyRevision ||
typeof provider.version !== 'string' || !provider.version || !Array.isArray(baseline.cases) || baseline.cases.length !== target.corpus.cases.length ||
baseline.cases.some((entry, index) => !entry || Object.keys(entry).sort().join(',') !== 'caseId,found' || entry.caseId !== target.corpus.cases[index].id || typeof entry.found !== 'boolean'))
throw new Error('UNBOUND_EVAL_BASELINE');
}
export function createEvalMatrix(options: FullEvalMatrixOptions, corpus?: EvalCorpusManifest): FullEvalMatrix;
export function createEvalMatrix(options: ReleaseEvalMatrixOptions, corpus?: EvalCorpusManifest): ReleaseEvalMatrix;
export function createEvalMatrix(options: BaselineEvalMatrixOptions, corpus?: EvalCorpusManifest): BaselineEvalMatrix;
export function createEvalMatrix(options: EvalMatrixOptions, corpus: EvalCorpusManifest = loadCorpusManifest()): EvalMatrix {
let baselineHash: string | null = null;
if (options.profile === 'release' && options.baseline !== undefined) {
assertBaselineBinding(options.baseline, { corpus, model: options.model, host: options.host, budgetSeconds: (options.budgets ?? { comprehensive: 1800 }).comprehensive, platforms: normalizedPlatforms(corpus, options.platforms?.comprehensive) });
baselineHash = options.baseline.baselineHash;
}
return buildEvalMatrix(options, corpus, baselineHash);
}
export function validateMatrix(matrix: EvalMatrix, corpus: EvalCorpusManifest = loadCorpusManifest()): void {
if (!matrix || typeof matrix !== 'object') throw new Error('UNMATCHED_OR_INCOMPLETE_EVAL_MATRIX');
const common = { model: matrix.model, host: matrix.host, budgets: matrix.budgets };
let expected: EvalMatrix;
try {
expected = matrix.profile === 'release' ? buildEvalMatrix({ ...common, profile: 'release', skillHashes: matrix.skillHashes, platforms: matrix.platforms }, corpus, matrix.baselineHash)
: matrix.profile === 'baseline' ? buildEvalMatrix({ ...common, profile: 'baseline', skillHashes: matrix.skillHashes, platforms: matrix.platforms }, corpus, null)
: buildEvalMatrix({ ...common, skillHashes: matrix.skillHashes }, corpus, null);
} catch { throw new Error('UNMATCHED_OR_INCOMPLETE_EVAL_MATRIX'); }
if (JSON.stringify(matrix) !== JSON.stringify(expected)) throw new Error('UNMATCHED_OR_INCOMPLETE_EVAL_MATRIX');
}
function validateResult(result: EvalResult, cell: EvalCell, corpus: EvalCorpusManifest): void {
if (result.sourceHash !== cell.sourceHash || result.skillHash !== cell.skillHash || result.model !== cell.model || result.host !== cell.host || result.budgetSeconds !== cell.budgetSeconds) throw new Error('UNMATCHED_EVAL_RESULT');
for (const field of ['setup', 'reproduction', 'repair', 'recheck'] as const) if (!['passed', 'failed', 'blocked', 'not_attempted'].includes(result[field])) throw new Error('INVALID_EVAL_OUTCOME');
for (const field of ['reportPresent', 'reportComplete', 'heldOutAssertionsPassed', 'freshRecheck'] as const) if (typeof result[field] !== 'boolean') throw new Error('INVALID_EVAL_RESULT');
if (!Array.isArray(result.findings) || !validNumber(result.latencyMs) || (result.firstUsefulResultMs !== null && (!validNumber(result.firstUsefulResultMs) || result.firstUsefulResultMs > result.latencyMs))) throw new Error('INVALID_EVAL_RESULT');
if (result.reportComplete && !result.reportPresent) throw new Error('MISSING_EVAL_REPORT');
if (!result.reportPresent && result.findings.length) throw new Error('FINDINGS_WITHOUT_REPORT');
if (result.setup === 'blocked' && !result.prerequisite?.trim()) throw new Error('MISSING_SETUP_PREREQUISITE');
if (result.oracleEvidenceHash !== undefined && (!HEX.test(result.oracleEvidenceHash) || result.oracleVersion !== corpus.version)) throw new Error('INVALID_ORACLE_PROVENANCE');
if (result.currentSourceHash !== undefined && !HEX.test(result.currentSourceHash)) throw new Error('INVALID_RECHECK_SOURCE');
if (result.recheckEvidenceHash !== undefined && !HEX.test(result.recheckEvidenceHash)) throw new Error('INVALID_RECHECK_EVIDENCE');
if (result.usage && (result.usage.source !== 'host' || (result.usage.tokens !== undefined && !validNumber(result.usage.tokens)) || (result.usage.costUSD !== undefined && !validNumber(result.usage.costUSD)))) throw new Error('INVALID_EVAL_USAGE');
if (result.producerReceiptHash !== undefined && !HEX.test(result.producerReceiptHash)) throw new Error('INVALID_PRODUCER_RECEIPT_PROVENANCE');
const ids = new Set<string>(), repairEvidence = new Set<string>(), recheckEvidence = new Set<string>();
for (const finding of result.findings) {
if (!finding.id || ids.has(finding.id) || !['supported', 'hypothesis', 'legacy_review'].includes(finding.evidence) || !['correct', 'incorrect', 'unadjudicated'].includes(finding.judgment) || typeof finding.claimedTested !== 'boolean') throw new Error('INVALID_FINDING_JUDGMENT');
ids.add(finding.id);
if (finding.judgment === 'correct' && (cell.variant !== 'vulnerable' || finding.matchedCaseId !== cell.caseId)) throw new Error('INVALID_ORACLE_MATCH');
if (finding.trustedVerification !== undefined) {
const verification = finding.trustedVerification as Record<string, unknown>, allowed = new Set(['repair', 'repairEvidenceHash', 'recheck', 'recheckEvidenceHash']);
if (!verification || typeof verification !== 'object' || Array.isArray(verification) || Object.keys(verification).some(key => !allowed.has(key)) ||
!['passed', 'failed', 'blocked', 'not_attempted'].includes(String(verification.repair)) ||
!['passed', 'failed', 'blocked', 'not_attempted'].includes(String(verification.recheck)) || !finding.claimedTested || cell.version !== 'v3' || cell.mode !== 'comprehensive')
throw new Error('INVALID_TRUSTED_FINDING_VERIFICATION');
const repairHash = verification.repairEvidenceHash, recheckHash = verification.recheckEvidenceHash;
if (!(repairHash === undefined || (typeof repairHash === 'string' && HEX.test(repairHash))) ||
!(recheckHash === undefined || (typeof recheckHash === 'string' && HEX.test(recheckHash))) ||
(verification.repair === 'passed') !== (repairHash !== undefined) ||
(verification.recheck === 'passed') !== (recheckHash !== undefined) ||
(verification.recheck === 'passed' && verification.repair !== 'passed'))
throw new Error('INVALID_TRUSTED_FINDING_VERIFICATION');
if (typeof repairHash === 'string') {
if (repairEvidence.has(repairHash)) throw new Error('DUPLICATE_TRUSTED_REPAIR_BINDING');
repairEvidence.add(repairHash);
}
if (typeof recheckHash === 'string') {
if (recheckEvidence.has(recheckHash)) throw new Error('DUPLICATE_TRUSTED_RECHECK_BINDING');
recheckEvidence.add(recheckHash);
}
}
}
if (cell.mode === 'daily' && [result.setup, result.reproduction, result.repair, result.recheck].some(value => value !== 'not_attempted')) throw new Error('DAILY_EVAL_EXECUTED_APPLICATION');
}
function quantile(values: number[], fraction: number): number | null {
if (!values.length) return null;
return [...values].sort((left, right) => left - right)[Math.ceil(values.length * fraction) - 1];
}
function measuredRate(cells: EvalCell[], results: Map<string, EvalResult>, field: 'setup' | 'reproduction' | 'repair' | 'recheck', corpus: EvalCorpusManifest): Rate {
return rate(cells.filter(cell => {
const result = results.get(cell.id);
if (!result?.reportPresent || !result.reportComplete || result[field] !== 'passed') return false;
if (field === 'setup') return true;
if (!result.oracleEvidenceHash || result.oracleVersion !== corpus.version || result.setup !== 'passed') return false;
if (field === 'reproduction') return true;
if (result.reproduction !== 'passed' || result.repair !== 'passed' || !result.heldOutAssertionsPassed) return false;
if (cell.version === 'v3' && !result.findings.some(finding => trustedFindingVerification(cell, result, finding, 'repair', corpus))) return false;
if (field === 'repair') return true;
// Correct alternative patches need not match the reference fix byte-for-byte.
// Closure needs a fresh source and a separate trusted current-source observation.
return result.freshRecheck && !!result.currentSourceHash && result.currentSourceHash !== cell.sourceHash &&
!!result.recheckEvidenceHash && result.recheckEvidenceHash !== result.oracleEvidenceHash &&
(cell.version !== 'v3' || result.findings.some(finding => trustedFindingVerification(cell, result, finding, 'recheck', corpus)));
}).length, cells.length);
}
function trustedFindingVerification(cell: EvalCell, result: EvalResult, finding: EvalFinding, stage: 'repair' | 'recheck', corpus: EvalCorpusManifest): boolean {
const verification = finding.trustedVerification;
if (!result.reportPresent || !result.reportComplete || cell.version !== 'v3' || cell.mode !== 'comprehensive' || cell.variant !== 'vulnerable' || finding.evidence !== 'supported' ||
finding.judgment !== 'correct' || finding.matchedCaseId !== cell.caseId || !finding.claimedTested || !verification ||
result.setup !== 'passed' || result.reproduction !== 'passed' || result.repair !== 'passed' || !result.heldOutAssertionsPassed ||
verification.repair !== 'passed' || verification.repairEvidenceHash !== result.oracleEvidenceHash || result.oracleVersion !== corpus.version)
return false;
if (stage === 'repair') return true;
return result.recheck === 'passed' && verification.recheck === 'passed' && verification.recheckEvidenceHash === result.recheckEvidenceHash &&
result.freshRecheck && !!result.currentSourceHash && result.currentSourceHash !== cell.sourceHash &&
!!result.recheckEvidenceHash && result.recheckEvidenceHash !== result.oracleEvidenceHash;
}
function validatedResults(matrix: EvalMatrix, observations: EvalResult[], corpus: EvalCorpusManifest): Map<string, EvalResult> {
if (!Array.isArray(observations)) throw new Error('INVALID_EVAL_RESULTS');
const cells = new Map(matrix.cells.map(cell => [cell.id, cell]));
const results = new Map<string, EvalResult>();
for (const result of observations) {
const cell = cells.get(result.cellId);
if (!cell || results.has(result.cellId)) throw new Error('UNKNOWN_OR_DUPLICATE_EVAL_RESULT');
validateResult(result, cell, corpus); results.set(result.cellId, result);
}
return results;
}
const eligibleFinding = (cell: EvalCell, finding: EvalFinding) => finding.evidence === 'supported' || (cell.version === 'v2' && finding.evidence === 'legacy_review');
const foundSeededIssue = (cell: EvalCell, result: EvalResult | undefined) => result?.reportPresent === true && result.reportComplete === true &&
result.findings.some(finding => eligibleFinding(cell, finding) && finding.judgment === 'correct');
const isHighCritical = (corpus: EvalCorpusManifest, caseId: string) => ['critical', 'high'].includes(corpus.cases.find(fixture => fixture.id === caseId)!.severity);
/** High/critical recall of a pre-registered external baseline, after proving it binds to this release matrix. */
function externalBaselineRecall(matrix: ReleaseEvalMatrix, baseline: EvalBaseline, corpus: EvalCorpusManifest): Rate {
if (matrix.baselineHash === null || baseline?.baselineHash !== matrix.baselineHash) throw new Error('UNBOUND_EVAL_BASELINE');
assertBaselineBinding(baseline, { corpus, model: matrix.model, host: matrix.host, budgetSeconds: matrix.budgets.comprehensive, platforms: matrix.platforms.comprehensive });
const highCritical = baseline.cases.filter(entry => isHighCritical(corpus, entry.caseId));
return rate(highCritical.filter(entry => entry.found).length, highCritical.length);
}
export function scoreEval(matrix: EvalMatrix, observations: EvalResult[], qualification: ReleaseQualification = { containment: {} }, corpus: EvalCorpusManifest = loadCorpusManifest(), baseline?: EvalBaseline) {
validateMatrix(matrix, corpus);
const profile = profileOf(matrix);
if (profile === 'baseline') throw new Error('BASELINE_PROFILE_NOT_QUALIFIABLE: use createEvalBaseline');
if (profile !== 'release' && baseline !== undefined) throw new Error('UNBOUND_EVAL_BASELINE');
const results = validatedResults(matrix, observations, corpus);
const found = (cell: EvalCell) => foundSeededIssue(cell, results.get(cell.id));
const groups: any[] = [];
for (const [version, mode] of PROFILE_GROUPS[profile]) {
const selected = matrix.cells.filter(cell => cell.version === version && cell.mode === mode);
const completed = selected.map(cell => results.get(cell.id)).filter((result): result is EvalResult => !!result);
const expected = selected.filter(cell => cell.variant === 'vulnerable');
const highCritical = expected.filter(cell => isHighCritical(corpus, cell.caseId));
let correct = 0, reported = 0, unadjudicated = 0;
for (const cell of selected) {
const result = results.get(cell.id);
const findings = result?.reportPresent && result.reportComplete ? result.findings.filter(finding => finding.evidence !== 'hypothesis') : [];
reported += findings.length;
unadjudicated += findings.filter(finding => finding.judgment === 'unadjudicated').length;
correct += Number(findings.some(finding => eligibleFinding(cell, finding) && finding.judgment === 'correct')); // Duplicate reports do not increase true positives.
}
const firstUseful = completed.flatMap(result => result.firstUsefulResultMs === null ? [] : [result.firstUsefulResultMs]);
const costs = completed.flatMap(result => result.usage?.costUSD === undefined ? [] : [result.usage.costUSD]);
const tokens = completed.flatMap(result => result.usage?.tokens === undefined ? [] : [result.usage.tokens]);
const falseTested = selected.reduce((count, cell) => {
const result = results.get(cell.id); if (!result) return count;
return count + result.findings.filter(finding => finding.claimedTested && !trustedFindingVerification(cell, result, finding, 'repair', corpus)).length;
}, 0);
groups.push({ version, mode, cells: selected.length, submitted: completed.length, missing: selected.length - completed.length,
reports: rate(completed.filter(result => result.reportPresent && result.reportComplete).length, selected.length), precision: rate(correct, reported), recall: rate(expected.filter(found).length, expected.length), highCriticalRecall: rate(highCritical.filter(found).length, highCritical.length),
unadjudicated, falseTested, setup: mode === 'comprehensive' ? measuredRate(selected, results, 'setup', corpus) : null,
reproduction: mode === 'comprehensive' ? measuredRate(expected, results, 'reproduction', corpus) : null,
repair: mode === 'comprehensive' ? measuredRate(expected, results, 'repair', corpus) : null,
recheck: mode === 'comprehensive' ? measuredRate(expected, results, 'recheck', corpus) : null,
setupBlocked: completed.filter(result => result.setup === 'blocked').length,
firstUsefulResult: { samples: firstUseful.length, denominator: selected.length, medianMs: quantile(firstUseful, 0.5), p95Ms: quantile(firstUseful, 0.95) },
latency: { samples: completed.length, p95Ms: quantile(completed.map(result => result.latencyMs), 0.95) },
cost: { measured: costs.length, denominator: selected.length, totalUSD: costs.length ? costs.reduce((sum, cost) => sum + cost, 0) : null },
modelTokens: { measured: tokens.length, denominator: selected.length, total: tokens.length ? tokens.reduce((sum, count) => sum + count, 0) : null },
});
}
const daily = groups.find(group => group.version === 'v3' && group.mode === 'daily');
const comprehensive = groups.find(group => group.version === 'v3' && group.mode === 'comprehensive');
const inBatchBaseline = groups.find(group => group.version === 'v2' && group.mode === 'comprehensive');
const external = matrix.profile === 'release' && baseline !== undefined ? externalBaselineRecall(matrix, baseline, corpus) : null;
const perStack = Object.fromEntries(STACKS.map(stack => {
const eligible = matrix.cells.filter(cell => cell.version === 'v3' && cell.mode === 'comprehensive' && cell.variant === 'vulnerable' && cell.stack === stack);
// A repaired oracle case demonstrates the full find-to-repair workflow only
// when the producer also reported the matching supported finding.
const successful = new Set(eligible.filter(cell => {
const result = results.get(cell.id);
return result?.findings.some(finding => trustedFindingVerification(cell, result, finding, 'repair', corpus));
}).map(cell => cell.caseId));
return [stack, { correctHeldOutRepairs: successful.size, denominator: new Set(eligible.map(cell => cell.caseId)).size }];
}));
const assessedAll = observations.length === matrix.cells.length && observations.every(result => result.reportPresent && result.reportComplete) && groups.every(group => !group.unadjudicated);
const gate = (condition: boolean | null, hasData: boolean): 'pass' | 'fail' | 'unmeasured' => !hasData || condition === null ? 'unmeasured' : condition ? 'pass' : 'fail';
const containmentValues = REQUIRED_CONTAINMENT.map(name => qualification.containment?.[name]);
if (containmentValues.some(value => value !== undefined && !['passed', 'failed', 'not_run'].includes(value))) throw new Error('INVALID_CONTAINMENT_RESULT');
const gates = {
matchedCompleteMatrix: gate(assessedAll, observations.length > 0),
mandatoryReports: gate(groups.every(group => group.reports.numerator === group.reports.denominator), observations.length === matrix.cells.length),
dailyPrecision95: gate(daily.precision.value === null ? null : daily.precision.value >= 0.95, daily.submitted === daily.cells && !daily.unadjudicated),
comprehensiveHighCriticalRecall80: gate(comprehensive.highCriticalRecall.value >= 0.8, comprehensive.submitted === comprehensive.cells && !comprehensive.unadjudicated),
noHighCriticalRecallRegression: profile === 'full'
? gate(comprehensive.highCriticalRecall.value >= inBatchBaseline.highCriticalRecall.value, comprehensive.submitted === comprehensive.cells && inBatchBaseline.submitted === inBatchBaseline.cells && !comprehensive.unadjudicated && !inBatchBaseline.unadjudicated)
: gate(external === null ? null : comprehensive.highCriticalRecall.value >= external.value!, comprehensive.submitted === comprehensive.cells && !comprehensive.unadjudicated && external !== null),
allCoreColdStarts: gate(comprehensive.setup.numerator === comprehensive.setup.denominator, comprehensive.submitted === comprehensive.cells),
zeroFalselyTestedRepairs: gate(comprehensive.falseTested === 0 && daily.falseTested === 0, comprehensive.submitted === comprehensive.cells && daily.submitted === daily.cells),
heldOutRepairEachStack: gate(Object.values(perStack).every(value => value.correctHeldOutRepairs >= 1), comprehensive.submitted === comprehensive.cells),
containmentAndCanaries: containmentValues.includes('failed') ? 'fail' as const : containmentValues.every(value => value === 'passed') ? 'pass' as const : 'unmeasured' as const,
};
return { schemaVersion: 1, corpusVersion: corpus.version, model: matrix.model, host: matrix.host,
...(profile === 'release' ? { profile, baseline: external === null ? null : { baselineHash: baseline!.baselineHash, highCriticalRecall: external } } : {}),
status: Object.values(gates).every(value => value === 'pass') ? 'qualified' : observations.length ? 'partial' : 'unmeasured', groups, perStack, gates,
notes: ['Missing and setup-blocked supported scenarios remain in recall and workflow denominators.', 'Costs and tokens come only from host-reported usage; wall-clock budgets are not model-spend caps.', 'Oracle judgments and qualification receipts must come from the trusted evaluator, never producing agents.'] };
}
/** Bind a complete collected batch and every trusted judgment to the matrix's producer receipts. */
function validateCollectedBatch(matrix: EvalMatrix, batch: ProducerBatch, observations: EvalResult[]): Map<string, ProducerReceiptIndex> {
if (!Array.isArray(observations)) throw new Error('INVALID_EVAL_RESULTS');
if (!batch || batch.schemaVersion !== 1 || batch.matrixHash !== matrixHash(matrix) || !HEX.test(batch.scheduleHash) || !HEX.test(batch.batchHash)) throw new Error('INVALID_PRODUCER_BATCH');
const { batchHash, ...withoutHash } = batch;
const pairs = expectedMatchedPairs(matrix);
if (digest(JSON.stringify(withoutHash)) !== batchHash || !Array.isArray(batch.receipts) || batch.receipts.length !== matrix.cells.length || batch.summary.scheduled !== matrix.cells.length || batch.summary.prepared !== matrix.cells.length || batch.summary.submitted !== matrix.cells.length || batch.summary.missing !== 0 || batch.summary.matchedPairsExpected !== pairs || batch.summary.matchedPairsSubmitted !== pairs || batch.summary.modelMismatches.length !== 0) throw new Error('INCOMPLETE_PRODUCER_BATCH');
const cells = new Map(matrix.cells.map(cell => [cell.id, cell]));
const receipts = new Map<string, ProducerReceiptIndex>();
for (const receipt of batch.receipts) {
const cell = cells.get(receipt?.cellRef);
if (!cell || receipts.has(cell.id)) throw new Error('INVALID_PRODUCER_BATCH');
validateReceiptIndex(receipt, cell); receipts.set(cell.id, receipt);
}
assertPlatformIdentities(batch.receipts);
if (profileOf(matrix) === 'full') {
const actualModels = new Map<string, Partial<Record<EvalVersion, string>>>();
for (const receipt of batch.receipts) {
const key = matchedPairKey(receipt.cell as EvalCell), pair = actualModels.get(key) ?? {};
pair[receipt.cell.version] = receipt.modelUsed; actualModels.set(key, pair);
}
if (actualModels.size !== pairs || [...actualModels.values()].some(pair => !pair.v2 || !pair.v3 || pair.v2 !== pair.v3)) throw new Error('UNMATCHED_EFFECTIVE_MODELS');
} else if (new Set(batch.receipts.map(receipt => receipt.modelUsed)).size !== 1) throw new Error('UNMATCHED_EFFECTIVE_MODELS');
for (const result of observations) {
const receipt = receipts.get(result.cellId);
if (!receipt || result.producerReceiptHash !== receipt.receiptHash) throw new Error('UNBOUND_EVAL_RESULT');
}
return receipts;
}
/** Release scoring path: every trusted judgment must bind to a collected producer receipt. */
export function scoreCollectedEval(matrix: EvalMatrix, batch: ProducerBatch, observations: EvalResult[], qualification: ReleaseQualification = { containment: {} }, corpus: EvalCorpusManifest = loadCorpusManifest(), baseline?: EvalBaseline) {
validateMatrix(matrix, corpus);
if (profileOf(matrix) === 'baseline') throw new Error('BASELINE_PROFILE_NOT_QUALIFIABLE: use createEvalBaseline');
validateCollectedBatch(matrix, batch, observations);
if (baseline !== undefined) {
const { modelUsed, providerIdentity: { family, policyRevision, version } } = batch.receipts[0];
if (baseline?.modelUsed !== modelUsed || JSON.stringify(baseline?.provider) !== JSON.stringify({ family, policyRevision, version })) throw new Error('UNBOUND_EVAL_BASELINE');
}
const score = scoreEval(matrix, observations, qualification, corpus, baseline);
return { ...score, producerBatchHash: batch.batchHash };
}
/**
* Turn a complete, fully adjudicated v2 baseline run into a reusable record.
* Missing reports count as misses; an incomplete or unadjudicated run is refused.
*/
export function createEvalBaseline(matrix: BaselineEvalMatrix, batch: ProducerBatch, observations: EvalResult[], corpus: EvalCorpusManifest = loadCorpusManifest()): EvalBaseline {
if (matrix?.profile !== 'baseline') throw new Error('INVALID_EVAL_BASELINE_MATRIX');
validateMatrix(matrix, corpus);
validateCollectedBatch(matrix, batch, observations);
const results = validatedResults(matrix, observations, corpus);
if (results.size !== matrix.cells.length) throw new Error('INCOMPLETE_EVAL_BASELINE');
if ([...results.values()].some(result => result.reportPresent && result.reportComplete && result.findings.some(finding => finding.evidence !== 'hypothesis' && finding.judgment === 'unadjudicated'))) throw new Error('UNADJUDICATED_EVAL_BASELINE');
const vulnerable = new Map(matrix.cells.filter(cell => cell.variant === 'vulnerable').map(cell => [cell.caseId, cell]));
const { modelUsed, providerIdentity: { family, policyRevision, version } } = batch.receipts[0];
const record: Omit<EvalBaseline, 'baselineHash'> = {
schemaVersion: 1, version: 'v2', corpusVersion: corpus.version, corpusHash: matrix.corpusHash, model: matrix.model, host: matrix.host,
budgetSeconds: matrix.budgets.comprehensive, skillHash: matrix.skillHashes.v2, platforms: matrix.platforms.comprehensive,
matrixHash: matrixHash(matrix), producerBatchHash: batch.batchHash, modelUsed, provider: { family, policyRevision, version },
cases: corpus.cases.map(fixture => ({ caseId: fixture.id, found: foundSeededIssue(vulnerable.get(fixture.id)!, results.get(vulnerable.get(fixture.id)!.id)) })),
};
return { ...record, baselineHash: digest(JSON.stringify(record)) };
}
function splitFlags(args: string[], allowed: string[]): { positional: string[]; flags: Record<string, string> } {
const positional: string[] = [], flags: Record<string, string> = {};
for (let index = 0; index < args.length; index++) {
if (!args[index].startsWith('--')) { positional.push(args[index]); continue; }
if (!allowed.includes(args[index]) || !args[index + 1] || flags[args[index]]) throw new Error(`Unsupported or repeated flag: ${args[index]}`);
flags[args[index]] = args[++index];
}
return { positional, flags };
}
function cli(args: string[]): void {
const [command, ...rest] = args;
if (command === 'payload') {
if (rest.length !== 6 || rest[0] !== '--version' || !['v2', 'v3'].includes(rest[1]) || rest[2] !== '--skill-dir' || rest[4] !== '--output') throw new Error('Usage: cso-eval payload --version <v2|v3> --skill-dir <directory> --output <new-file>');
const payload = loadPortableSkillPayload(rest[1] as EvalVersion, rest[3]);
const target = resolve(rest[5]), parent = dirname(target), stat = lstatSync(parent);
if (!stat.isDirectory() || stat.isSymbolicLink() || realpathSync(parent) !== parent) throw new Error('UNSAFE_EVAL_DESTINATION');
atomicWriteSync(target, payload, { mode: 0o600, noReplace: true });
console.log(JSON.stringify({ version: rest[1], files: validatePortableSkillPayload(payload).files.length, sha256: sha256(payload), output: target, paidCalls: 0 })); return;
}
if (command === 'materialize') {
if (rest.length !== 3 || !['vulnerable', 'fixed'].includes(rest[1])) throw new Error('Usage: cso-eval materialize <case-id> <vulnerable|fixed> <new-directory>');
console.log(JSON.stringify(materializeCase(rest[0], rest[1] as EvalVariant, rest[2]), null, 2)); return;
}
if (command === 'matrix') {
const values: Record<string, string> = {};
for (let index = 0; index < rest.length; index += 2) {
if (!['--model', '--host', '--v2-payload', '--v3-payload', '--output'].includes(rest[index]) || !rest[index + 1] || values[rest[index]]) throw new Error('Usage: cso-eval matrix --model <id> --host <claude|codex|gemini> --v2-payload <file> --v3-payload <file> --output <new-file>');
values[rest[index]] = rest[index + 1];
}
if (Object.keys(values).length !== 5) throw new Error('All matrix flags are required; exact portable skill payloads and model identity must be pinned.');
const payloads = { v2: readBoundedStable(resolve(values['--v2-payload']), PORTABLE_PAYLOAD_LIMIT, 'v2 portable skill payload').toString('utf8'), v3: readBoundedStable(resolve(values['--v3-payload']), PORTABLE_PAYLOAD_LIMIT, 'v3 portable skill payload').toString('utf8') };
validatePortableSkillPayload(payloads.v2, 'v2'); validatePortableSkillPayload(payloads.v3, 'v3');
const matrix = createEvalMatrix({ model: values['--model'], host: values['--host'] as ProducerHost, skillHashes: { v2: digest(payloads.v2), v3: digest(payloads.v3) } });
safeWriteNew(values['--output'], matrix); console.log(JSON.stringify({ cells: matrix.cells.length, output: values['--output'], paidCalls: 0 })); return;
}
if (command === 'prepare') {
if (rest.length !== 7 || rest[1] !== '--v2-payload' || rest[3] !== '--v3-payload' || rest[5] !== '--output') throw new Error('Usage: cso-eval prepare <matrix.json> --v2-payload <file> --v3-payload <file> --output <new-directory>');
const matrix = readJsonBounded(rest[0], 16 * 1024 * 1024, 'evaluation matrix') as EvalMatrix;
const schedule = prepareEvalJobs(matrix, { v2: readBoundedStable(resolve(rest[2]), PORTABLE_PAYLOAD_LIMIT, 'v2 portable skill payload').toString('utf8'), v3: readBoundedStable(resolve(rest[4]), PORTABLE_PAYLOAD_LIMIT, 'v3 portable skill payload').toString('utf8') }, rest[6]);
console.log(JSON.stringify({ scheduled: schedule.scheduledCells, prepared: schedule.preparedCells, output: resolve(rest[6]), paidCalls: 0 })); return;
}
const { positional, flags } = splitFlags(rest, ['--corpus-manifest', '--baseline']);
const corpus = flags['--corpus-manifest'] ? validateCorpusManifest(readJsonBounded(flags['--corpus-manifest'], 16 * 1024 * 1024, 'corpus manifest')) : loadCorpusManifest();
if (command === 'collect') {
if (positional.length !== 4 || flags['--baseline']) throw new Error('Usage: cso-eval collect <matrix.json> <schedule.json> <receipts-directory> <new-batch.json> [--corpus-manifest <manifest.json>]');
const [matrixPath, schedulePath, receiptDirectory, output] = positional;
const matrix = readJsonBounded(matrixPath, 16 * 1024 * 1024, 'evaluation matrix') as EvalMatrix;
const schedule = readJsonBounded(schedulePath, 16 * 1024 * 1024, 'evaluation schedule') as PreparedEvalSchedule;
const receiptRoot = resolve(receiptDirectory), stat = lstatSync(receiptRoot);
if (!stat.isDirectory() || stat.isSymbolicLink() || realpathSync(receiptRoot) !== receiptRoot) throw new Error('UNSAFE_RECEIPT_DIRECTORY');
const receipts: ProducerReceipt[] = [];
for (const entry of readdirSync(receiptRoot, { withFileTypes: true })) {
if (!entry.isFile() || entry.isSymbolicLink() || !/^[a-f0-9]{64}\.json$/.test(entry.name)) throw new Error('UNSAFE_RECEIPT_DIRECTORY');
receipts.push(readJsonBounded(join(receiptRoot, entry.name), 40 * 1024 * 1024, 'producer receipt'));
}
const batch = collectProducerReceipts(matrix, schedule, receipts, corpus);
safeWriteNew(resolve(output), batch);
console.log(JSON.stringify({ output: resolve(output), submitted: batch.summary.submitted, missing: batch.summary.missing, modelMismatches: batch.summary.modelMismatches.length, paidCalls: 0 })); return;
}
if (command === 'score') {
if (positional.length < 3 || positional.length > 4) throw new Error('Usage: cso-eval score <matrix.json> <producer-batch.json> <trusted-results.json> [qualification.json] [--corpus-manifest <manifest.json>] [--baseline <baseline.json>]');
const baseline = flags['--baseline'] ? readJsonBounded(flags['--baseline'], 4 * 1024 * 1024, 'evaluation baseline') as EvalBaseline : undefined;
console.log(JSON.stringify(scoreCollectedEval(readJsonBounded(positional[0], 16 * 1024 * 1024, 'evaluation matrix'), readJsonBounded(positional[1], 16 * 1024 * 1024, 'producer batch'), readJsonBounded(positional[2], 64 * 1024 * 1024, 'trusted results'), positional[3] ? readJsonBounded(positional[3], 4 * 1024 * 1024, 'qualification') : undefined, corpus, baseline), null, 2)); return;
}
if (command === 'baseline') {
if (positional.length !== 4 || flags['--baseline']) throw new Error('Usage: cso-eval baseline <baseline-matrix.json> <producer-batch.json> <trusted-results.json> <new-baseline.json> [--corpus-manifest <manifest.json>]');
const baseline = createEvalBaseline(readJsonBounded(positional[0], 16 * 1024 * 1024, 'evaluation matrix'), readJsonBounded(positional[1], 16 * 1024 * 1024, 'producer batch'), readJsonBounded(positional[2], 64 * 1024 * 1024, 'trusted results'), corpus);
safeWriteNew(resolve(positional[3]), baseline);
console.log(JSON.stringify({ output: resolve(positional[3]), baselineHash: baseline.baselineHash, paidCalls: 0 })); return;
}
throw new Error('Usage: cso-eval <payload|matrix|prepare|materialize|collect|score|baseline>');
}
if (import.meta.main) { try { cli(process.argv.slice(2)); } catch (error) { console.error(error instanceof Error ? error.message : 'CSO evaluation failed'); process.exitCode = 1; } }