{"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../../src/core/evaluation/dashboard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,wBAAwB,EACxB,kBAAkB,EAClB,uBAAuB,EACvB,uBAAuB,EACvB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,6BAA6B;IAC7C,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACnH,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClF,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,eAAe,EAAE,kBAAkB,CAAC,iBAAiB,CAAC,CAAC;IAChE,QAAQ,CAAC,gBAAgB,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACzD,QAAQ,CAAC,cAAc,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IACjE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,eAAe,EAAE,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,wBAAwB,EAAE,CAAC;IACjD,QAAQ,CAAC,WAAW,EAAE,uBAAuB,GAAG,SAAS,CAAC;IAC1D,QAAQ,CAAC,SAAS,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,uBAAuB,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtG,QAAQ,CAAC,mBAAmB,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC;IAChE,QAAQ,CAAC,UAAU,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CACxF;AAED,MAAM,WAAW,oCAAoC;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,wBAAwB,EAAE,CAAC;IACzC,WAAW,CAAC,EAAE,uBAAuB,CAAC;IACtC,SAAS,CAAC,EAAE,6BAA6B,CAAC,WAAW,CAAC,CAAC;IACvD,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,0BAA0B,CACzC,SAAS,EAAE,kBAAkB,EAAE,EAC/B,oBAAoB,GAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,oCAA6C,GAC5F,6BAA6B,CA6E/B","sourcesContent":["import type {\n\tCavecrewComparisonResult,\n\tEvaluationArtifact,\n\tEvaluationPruneManifest,\n\tReleaseConvergenceState,\n} from \"./types.js\";\n\nexport interface EvaluationDashboardProjection {\n\treadonly scenarioPacks: string[];\n\treadonly recentRuns: Array<{ runId: string; scenarioId: string; status: string; verdict: string; stale: boolean }>;\n\treadonly activeRuns: Array<{ runId: string; scenarioId: string; status: string }>;\n\treadonly assertionFailures: number;\n\treadonly safetyFailures: number;\n\treadonly semanticResults: EvaluationArtifact[\"semanticResults\"];\n\treadonly retrievalMetrics: EvaluationArtifact[\"metrics\"];\n\treadonly costAndLatency: { costUsd: number; wallTimeMs: number };\n\treadonly flakyRuns: number;\n\treadonly failureClusters: string[];\n\treadonly comparisons: CavecrewComparisonResult[];\n\treadonly releaseGate: ReleaseConvergenceState | undefined;\n\treadonly retention: { policyVersion?: number; preview?: EvaluationPruneManifest; diskBytes?: number };\n\treadonly artifactStoreHealth: \"healthy\" | \"degraded\" | \"failed\";\n\treadonly pagination: { offset: number; limit: number; total: number; hasMore: boolean };\n}\n\nexport interface EvaluationDashboardProjectionOptions {\n\toffset?: number;\n\tlimit?: number;\n\tcomparisons?: CavecrewComparisonResult[];\n\treleaseGate?: ReleaseConvergenceState;\n\tretention?: EvaluationDashboardProjection[\"retention\"];\n\tstoreHealth?: \"pass\" | \"warn\" | \"fail\";\n\tnow?: number;\n}\n\nexport function projectEvaluationDashboard(\n\tartifacts: EvaluationArtifact[],\n\tstoreHealthOrOptions: \"pass\" | \"warn\" | \"fail\" | EvaluationDashboardProjectionOptions = \"pass\",\n): EvaluationDashboardProjection {\n\tconst options: EvaluationDashboardProjectionOptions =\n\t\ttypeof storeHealthOrOptions === \"string\" ? { storeHealth: storeHealthOrOptions } : storeHealthOrOptions;\n\tconst offset = Math.max(0, options.offset ?? 0);\n\tconst limit = Math.min(100, Math.max(1, options.limit ?? 50));\n\tconst now = options.now ?? Date.now();\n\tconst sorted = [...artifacts].sort((left, right) => left.run.startedAt.localeCompare(right.run.startedAt));\n\tconst page = sorted.slice(offset, offset + limit);\n\tconst recentRuns = page.map((artifact) => ({\n\t\trunId: artifact.run.evaluationRunId,\n\t\tscenarioId: artifact.scenario.scenarioId,\n\t\tstatus: artifact.run.status,\n\t\tverdict: artifact.verdict,\n\t\tstale: artifact.run.completedAt ? now - Date.parse(artifact.run.completedAt) > 86_400_000 : false,\n\t}));\n\tconst cost = artifacts.reduce(\n\t\t(total, artifact) => total + (artifact.usage?.providerReportedCostUsd ?? artifact.usage?.estimatedCostUsd ?? 0),\n\t\t0,\n\t);\n\tconst wallTimeMs = artifacts.reduce((total, artifact) => {\n\t\tif (!artifact.run.completedAt) return total;\n\t\treturn total + Math.max(0, Date.parse(artifact.run.completedAt) - Date.parse(artifact.run.startedAt));\n\t}, 0);\n\treturn {\n\t\tscenarioPacks: [\n\t\t\t...new Set(\n\t\t\t\tartifacts.map((artifact) => artifact.scenario.packId).filter((pack): pack is string => pack !== undefined),\n\t\t\t),\n\t\t].sort(),\n\t\trecentRuns,\n\t\tactiveRuns: artifacts\n\t\t\t.filter(\n\t\t\t\t(artifact) =>\n\t\t\t\t\tartifact.run.status === \"running\" ||\n\t\t\t\t\tartifact.run.status === \"preparing\" ||\n\t\t\t\t\tartifact.run.status === \"evaluating\",\n\t\t\t)\n\t\t\t.map((artifact) => ({\n\t\t\t\trunId: artifact.run.evaluationRunId,\n\t\t\t\tscenarioId: artifact.scenario.scenarioId,\n\t\t\t\tstatus: artifact.run.status,\n\t\t\t})),\n\t\tassertionFailures: artifacts.reduce(\n\t\t\t(count, artifact) => count + artifact.assertions.filter((assertion) => assertion.status === \"fail\").length,\n\t\t\t0,\n\t\t),\n\t\tsafetyFailures: artifacts.reduce(\n\t\t\t(count, artifact) =>\n\t\t\t\tcount +\n\t\t\t\tartifact.assertions.filter(\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).length,\n\t\t\t0,\n\t\t),\n\t\tsemanticResults: artifacts.flatMap((artifact) => artifact.semanticResults),\n\t\tretrievalMetrics: artifacts.flatMap((artifact) =>\n\t\t\tartifact.metrics.filter((metric) => metric.metricId.includes(\"retrieval\")),\n\t\t),\n\t\tcostAndLatency: { costUsd: cost, wallTimeMs },\n\t\tflakyRuns: artifacts.filter((artifact) => artifact.stability?.classification === \"flaky\").length,\n\t\tfailureClusters: [\n\t\t\t...new Set(\n\t\t\t\tartifacts.flatMap((artifact) =>\n\t\t\t\t\tartifact.assertions\n\t\t\t\t\t\t.filter((assertion) => assertion.status !== \"pass\")\n\t\t\t\t\t\t.map((assertion) => assertion.reasonCode),\n\t\t\t\t),\n\t\t\t),\n\t\t].sort(),\n\t\tcomparisons: options.comparisons ?? [],\n\t\treleaseGate: options.releaseGate,\n\t\tretention: options.retention ?? {},\n\t\tartifactStoreHealth:\n\t\t\toptions.storeHealth === \"fail\" ? \"failed\" : options.storeHealth === \"warn\" ? \"degraded\" : \"healthy\",\n\t\tpagination: { offset, limit, total: sorted.length, hasMore: offset + page.length < sorted.length },\n\t};\n}\n"]}