{"version":3,"file":"release-convergence.d.ts","sourceRoot":"","sources":["../../../src/core/evaluation/release-convergence.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,yBAAyB,EACzB,kBAAkB,EAClB,oBAAoB,EACpB,uBAAuB,EACvB,MAAM,YAAY,CAAC;AAEpB,wBAAgB,6BAA6B,CAC5C,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,GACnB,uBAAuB,CAwBzB;AAED,wBAAgB,6BAA6B,CAAC,SAAS,EAAE,kBAAkB,EAAE,GAAG,oBAAoB,CAoCnG;AAED,wBAAgB,6BAA6B,CAC5C,KAAK,EAAE,uBAAuB,EAC9B,MAAM,EAAE,OAAO,CACd,IAAI,CAAC,uBAAuB,EAAE,WAAW,GAAG,SAAS,GAAG,eAAe,GAAG,cAAc,GAAG,mBAAmB,CAAC,CAC/G,GAAG;IAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,yBAAyB,CAAC,CAAA;CAAE,GAC5D,uBAAuB,CA6CzB;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAehE","sourcesContent":["import { sha256, stableStringify } from \"./identity.js\";\nimport type {\n\tArtifactRuntimeAcceptance,\n\tEvaluationArtifact,\n\tEvaluationGateResult,\n\tReleaseConvergenceState,\n} from \"./types.js\";\n\nexport function createReleaseConvergenceState(\n\treleaseId: string,\n\tversion: string,\n\treleaseCommit: string,\n): ReleaseConvergenceState {\n\tconst runtimeAcceptance: ArtifactRuntimeAcceptance = {\n\t\tsource: \"pending\",\n\t\tpackedNpm: \"pending\",\n\t\tregistryNpm: \"pending\",\n\t\tbuiltBinary: \"pending\",\n\t\tdownloadedBinary: \"pending\",\n\t};\n\treturn {\n\t\treleaseId,\n\t\tversion,\n\t\treleaseCommit,\n\t\tfunctionalEvaluation: \"pending\",\n\t\tpackageBuild: \"pending\",\n\t\tnpmPublication: \"pending\",\n\t\tsourceTag: \"pending\",\n\t\tbinaryBuild: \"pending\",\n\t\tbinarySmoke: \"pending\",\n\t\tassetUpload: \"pending\",\n\t\tassetVerification: \"pending\",\n\t\tgithubRelease: \"pending\",\n\t\truntimeAcceptance,\n\t\tfinalVerdict: \"incomplete\",\n\t};\n}\n\nexport function checkFunctionalEvaluationGate(artifacts: EvaluationArtifact[]): EvaluationGateResult {\n\tconst checks = [\n\t\t{\n\t\t\tcheckId: \"artifacts_present\",\n\t\t\tpassed: artifacts.length > 0,\n\t\t\treason:\n\t\t\t\tartifacts.length > 0 ? \"evaluation artifacts are present\" : \"functional evaluation produced no artifacts\",\n\t\t},\n\t\t{\n\t\t\tcheckId: \"deterministic_pass\",\n\t\t\tpassed: artifacts.length > 0 && artifacts.every((artifact) => artifact.verdict === \"pass\"),\n\t\t\treason: \"deterministic assertions remain authoritative\",\n\t\t},\n\t\t{\n\t\t\tcheckId: \"no_flakiness\",\n\t\t\tpassed: artifacts.every((artifact) => artifact.stability?.classification !== \"flaky\"),\n\t\t\treason: \"flaky repetitions cannot pass the release gate\",\n\t\t},\n\t\t{\n\t\t\tcheckId: \"no_safety_failure\",\n\t\t\tpassed: artifacts.every((artifact) =>\n\t\t\t\tartifact.assertions.every(\n\t\t\t\t\t(assertion) =>\n\t\t\t\t\t\t(assertion.severity !== \"critical\" && assertion.severity !== \"high\") || assertion.status === \"pass\",\n\t\t\t\t),\n\t\t\t),\n\t\t\treason: \"safety failures cannot be averaged away\",\n\t\t},\n\t];\n\treturn {\n\t\tgateId: \"functional-evaluation\",\n\t\tpassed: checks.every((check) => check.passed),\n\t\tchecks,\n\t\tartifactIds: artifacts.map((artifact) => artifact.artifactHash),\n\t\tverdict: checks.every((check) => check.passed) ? \"pass\" : \"fail\",\n\t};\n}\n\nexport function updateReleaseConvergenceState(\n\tstate: ReleaseConvergenceState,\n\tupdate: Partial<\n\t\tOmit<ReleaseConvergenceState, \"releaseId\" | \"version\" | \"releaseCommit\" | \"finalVerdict\" | \"runtimeAcceptance\">\n\t> & { runtimeAcceptance?: Partial<ArtifactRuntimeAcceptance> },\n): ReleaseConvergenceState {\n\tconst runtimeAcceptance = { ...state.runtimeAcceptance, ...update.runtimeAcceptance };\n\tconst next: ReleaseConvergenceState = {\n\t\t...state,\n\t\t...update,\n\t\treleaseId: state.releaseId,\n\t\tversion: state.version,\n\t\treleaseCommit: state.releaseCommit,\n\t\truntimeAcceptance,\n\t};\n\tconst required = [\n\t\tnext.functionalEvaluation,\n\t\tnext.packageBuild,\n\t\tnext.npmPublication,\n\t\tnext.sourceTag,\n\t\tnext.binaryBuild,\n\t\tnext.binarySmoke,\n\t\tnext.assetUpload,\n\t\tnext.assetVerification,\n\t\tnext.githubRelease,\n\t];\n\tconst runtimeRequired = [\n\t\tnext.runtimeAcceptance.source,\n\t\tnext.runtimeAcceptance.packedNpm,\n\t\tnext.runtimeAcceptance.registryNpm,\n\t\tnext.runtimeAcceptance.builtBinary,\n\t\tnext.runtimeAcceptance.downloadedBinary,\n\t];\n\tif (required.some((value) => value === \"failed\") || runtimeRequired.some((value) => value === \"fail\"))\n\t\tnext.finalVerdict = \"blocked\";\n\telse if (\n\t\tnext.functionalEvaluation === \"passed\" &&\n\t\tnext.packageBuild === \"passed\" &&\n\t\tnext.npmPublication === \"complete\" &&\n\t\tnext.sourceTag === \"created\" &&\n\t\tnext.binaryBuild === \"passed\" &&\n\t\tnext.binarySmoke === \"passed\" &&\n\t\tnext.assetUpload === \"complete\" &&\n\t\tnext.assetVerification === \"passed\" &&\n\t\tnext.githubRelease === \"published\" &&\n\t\truntimeRequired.every((value) => value === \"pass\")\n\t)\n\t\tnext.finalVerdict = \"pass\";\n\telse next.finalVerdict = \"incomplete\";\n\treturn next;\n}\n\nexport function verifyReleaseProvenance(input: {\n\treleaseCommit: string;\n\tversionCommit: string;\n\ttagCommit: string;\n\tgithubReleaseCommit: string;\n\tbinaryManifestCommit: string;\n\tpackageSourceCommit?: string;\n\tembeddedBinaryCommits?: string[];\n}): { valid: boolean; mismatches: string[]; contentHash: string } {\n\tconst values: Record<string, string> = {\n\t\treleaseCommit: input.releaseCommit,\n\t\tversionCommit: input.versionCommit,\n\t\ttagCommit: input.tagCommit,\n\t\tgithubReleaseCommit: input.githubReleaseCommit,\n\t\tbinaryManifestCommit: input.binaryManifestCommit,\n\t\t...(input.packageSourceCommit ? { packageSourceCommit: input.packageSourceCommit } : {}),\n\t};\n\tconst mismatches = Object.entries(values)\n\t\t.filter(([, value]) => value !== input.releaseCommit)\n\t\t.map(([key]) => key);\n\tfor (const commit of input.embeddedBinaryCommits ?? [])\n\t\tif (commit !== input.releaseCommit) mismatches.push(\"embeddedBinaryCommit\");\n\treturn { valid: mismatches.length === 0, mismatches, contentHash: sha256(stableStringify(values)) };\n}\n"]}