{"version":3,"file":"failures.d.ts","sourceRoot":"","sources":["../../../src/core/evaluation/failures.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,MAAM,WAAW,cAAc;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE;QACJ,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,EAAE,CAAC;QACvB,iBAAiB,EAAE,MAAM,EAAE,CAAC;QAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,kBAAkB,GAAG,cAAc,GAAG,SAAS,CA6BvF;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,cAAc,EAAE,CAqBjF","sourcesContent":["import { sha256, stableStringify } from \"./identity.js\";\nimport type { EvaluationArtifact } from \"./types.js\";\n\nexport interface FailureCluster {\n\tclusterId: string;\n\tkey: {\n\t\terrorCode: string;\n\t\tassertionIds: string[];\n\t\teventFingerprints: string[];\n\t\ttools: string[];\n\t\tphases: string[];\n\t\tprovider: string;\n\t\tplatform: string;\n\t\trecoveryState: string;\n\t\tcomponent: string;\n\t};\n\trunIds: string[];\n\trecurrenceCount: number;\n\tfirstOccurrence: string;\n\tlastOccurrence: string;\n\tartifactIds: string[];\n}\n\nexport function clusterFailure(artifact: EvaluationArtifact): FailureCluster | undefined {\n\tconst failed = artifact.assertions.filter((assertion) => assertion.status !== \"pass\");\n\tif (failed.length === 0 && artifact.verdict === \"pass\") return undefined;\n\tconst key = {\n\t\terrorCode:\n\t\t\tfailed\n\t\t\t\t.map((assertion) => assertion.reasonCode)\n\t\t\t\t.sort()\n\t\t\t\t.join(\"|\") || artifact.verdict,\n\t\tassertionIds: failed.map((assertion) => assertion.assertionId).sort(),\n\t\teventFingerprints: [],\n\t\ttools: [],\n\t\tphases: [],\n\t\tprovider: artifact.candidate.provider,\n\t\tplatform: artifact.run.environmentIdentity.os,\n\t\trecoveryState: artifact.run.status,\n\t\tcomponent: artifact.scenario.scenarioId,\n\t};\n\tconst clusterId = `failure-${sha256(stableStringify(key)).slice(0, 16)}`;\n\tconst timestamp = artifact.run.completedAt ?? artifact.run.startedAt;\n\treturn {\n\t\tclusterId,\n\t\tkey,\n\t\trunIds: [artifact.run.evaluationRunId],\n\t\trecurrenceCount: 1,\n\t\tfirstOccurrence: timestamp,\n\t\tlastOccurrence: timestamp,\n\t\tartifactIds: [artifact.artifactHash],\n\t};\n}\n\nexport function mergeFailureClusters(clusters: FailureCluster[]): FailureCluster[] {\n\tconst merged = new Map<string, FailureCluster>();\n\tfor (const cluster of clusters) {\n\t\tconst existing = merged.get(cluster.clusterId);\n\t\tif (!existing) {\n\t\t\tmerged.set(cluster.clusterId, {\n\t\t\t\t...cluster,\n\t\t\t\trunIds: [...cluster.runIds],\n\t\t\t\tartifactIds: [...cluster.artifactIds],\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\texisting.runIds = [...new Set([...existing.runIds, ...cluster.runIds])].sort();\n\t\texisting.artifactIds = [...new Set([...existing.artifactIds, ...cluster.artifactIds])].sort();\n\t\texisting.recurrenceCount = existing.runIds.length;\n\t\texisting.firstOccurrence =\n\t\t\texisting.firstOccurrence < cluster.firstOccurrence ? existing.firstOccurrence : cluster.firstOccurrence;\n\t\texisting.lastOccurrence =\n\t\t\texisting.lastOccurrence > cluster.lastOccurrence ? existing.lastOccurrence : cluster.lastOccurrence;\n\t}\n\treturn [...merged.values()].sort((left, right) => left.clusterId.localeCompare(right.clusterId));\n}\n"]}