{"version":3,"file":"baselines.d.ts","sourceRoot":"","sources":["../../../src/core/evaluation/baselines.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,MAAM,WAAW,kBAAkB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,kBAAkB,CAAC,WAAW,CAAC,CAAC;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC7B;AAED,wBAAsB,cAAc,CACnC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,IAAI,CAAC,kBAAkB,EAAE,YAAY,GAAG,aAAa,GAAG,QAAQ,CAAC,EACxE,SAAS,EAAE,kBAAkB,EAAE,GAC7B,OAAO,CAAC,kBAAkB,CAAC,CAmB7B;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAQ/E;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAIvF","sourcesContent":["import { mkdir, readdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { verifyArtifact } from \"./artifacts.js\";\nimport { sha256, stableStringify } from \"./identity.js\";\nimport type { EvaluationArtifact } from \"./types.js\";\n\nexport interface EvaluationBaseline {\n\tbaselineId: string;\n\tartifactIds: string[];\n\tcreatedAt: string;\n\tcandidate: EvaluationArtifact[\"candidate\"];\n\tpackId: string;\n\tpackVersion: string;\n\tcontentHash: string;\n\tstatus: \"active\" | \"retired\";\n}\n\nexport async function createBaseline(\n\troot: string,\n\tinput: Omit<EvaluationBaseline, \"baselineId\" | \"contentHash\" | \"status\">,\n\tartifacts: EvaluationArtifact[],\n): Promise<EvaluationBaseline> {\n\tif (artifacts.length === 0 || artifacts.some((artifact) => !verifyArtifact(artifact) || artifact.verdict !== \"pass\"))\n\t\tthrow new Error(\"baseline requires passing valid artifacts\");\n\tconst unsigned = { ...input, status: \"active\" as const };\n\tconst baseline = {\n\t\t...unsigned,\n\t\tbaselineId: `baseline-${sha256(stableStringify(unsigned)).slice(0, 16)}`,\n\t\tcontentHash: sha256(stableStringify(unsigned)),\n\t};\n\tconst path = join(root, `${baseline.baselineId}.json`);\n\tawait mkdir(root, { recursive: true });\n\ttry {\n\t\tawait writeFile(path, `${JSON.stringify(baseline, null, 2)}\\n`, { flag: \"wx\" });\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n\t\tconst existing = JSON.parse(await readFile(path, \"utf8\")) as EvaluationBaseline;\n\t\tif (existing.contentHash !== baseline.contentHash) throw new Error(\"baseline identity collision\");\n\t}\n\treturn baseline;\n}\n\nexport async function listBaselines(root: string): Promise<EvaluationBaseline[]> {\n\tconst names = await readdir(root).catch(() => [] as string[]);\n\tconst baselines: EvaluationBaseline[] = [];\n\tfor (const name of names.filter((item) => item.endsWith(\".json\")).sort()) {\n\t\tconst baseline = JSON.parse(await readFile(join(root, name), \"utf8\")) as EvaluationBaseline;\n\t\tif (baseline.status === \"active\") baselines.push(baseline);\n\t}\n\treturn baselines;\n}\n\nexport async function verifyBaseline(root: string, baselineId: string): Promise<boolean> {\n\tconst baseline = JSON.parse(await readFile(join(root, `${baselineId}.json`), \"utf8\")) as EvaluationBaseline;\n\tconst { baselineId: storedId, contentHash, ...unsigned } = baseline;\n\treturn storedId === baselineId && baseline.status === \"active\" && contentHash === sha256(stableStringify(unsigned));\n}\n"]}