{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/core/benchmark/report.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,yBAAyB,EAAwB,MAAM,YAAY,CAAC;AAMlF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,yBAAyB,GAAG,MAAM,CAqJ5E;AAMD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,yBAAyB,GAAG,MAAM,CAE5E","sourcesContent":["/**\n * Human-readable and machine-readable report generation.\n */\n\nimport type { BenchmarkEvaluationResult, EvaluatedRequirement } from \"./types.js\";\n\n// =============================================================================\n// Text Report\n// =============================================================================\n\nexport function generateTextReport(result: BenchmarkEvaluationResult): string {\n\tconst lines: string[] = [];\n\tconst pad = (label: string, value: string, indent = \"\") => {\n\t\tlines.push(`${indent}${label.padEnd(28)} ${value}`);\n\t};\n\n\tlines.push(\"=\".repeat(72));\n\tlines.push(\"  LONG-HORIZON BENCHMARK EVALUATION REPORT\");\n\tlines.push(\"=\".repeat(72));\n\tlines.push(\"\");\n\n\t// Identity\n\tlines.push(\"BENCHMARK IDENTITY\");\n\tlines.push(\"-\".repeat(72));\n\tpad(\"Benchmark\", result.benchmarkId);\n\tpad(\"Run\", result.runId);\n\tpad(\"Agent\", result.agent);\n\tpad(\"Model\", result.model);\n\tlines.push(\"\");\n\n\t// Schema validation\n\tlines.push(\"SCHEMA VALIDATION\");\n\tlines.push(\"-\".repeat(72));\n\tpad(\"Valid\", result.schemaValidation.valid ? \"PASS\" : \"FAIL\");\n\tfor (const err of result.schemaValidation.errors) {\n\t\tlines.push(`  ERROR: ${err}`);\n\t}\n\tfor (const warn of result.schemaValidation.warnings) {\n\t\tlines.push(`  WARNING: ${warn}`);\n\t}\n\tif (!result.schemaValidation.valid) {\n\t\tlines.push(\"\");\n\t\tlines.push(\"Evaluation aborted due to schema errors.\");\n\t\treturn lines.join(\"\\n\");\n\t}\n\tlines.push(\"\");\n\n\t// Completion gate\n\tlines.push(\"COMPLETION GATE\");\n\tlines.push(\"-\".repeat(72));\n\tpad(\"Verdict\", result.completionGate.passed ? \"PASS\" : \"FAIL\");\n\tpad(\"Requested Termination\", result.completionGate.requestedTermination);\n\tpad(\"Effective Termination\", result.completionGate.effectiveTermination);\n\tif (result.completionGate.blockingFindings.length > 0) {\n\t\tlines.push(\"  Blocking findings:\");\n\t\tfor (const f of result.completionGate.blockingFindings) {\n\t\t\tlines.push(`    [${f.code}] ${f.message}`);\n\t\t}\n\t}\n\tlines.push(\"\");\n\n\t// Metrics\n\tlines.push(\"METRICS\");\n\tlines.push(\"-\".repeat(72));\n\tconst m = result.metrics;\n\tpad(\"Verified Completion Ratio\", `${(m.verifiedCompletionRatio * 100).toFixed(1)}%`);\n\tpad(\"Implementation Ratio\", `${(m.implementationRatio * 100).toFixed(1)}%`);\n\tpad(\"Requirement Coverage\", `${(m.requirementCoverage * 100).toFixed(1)}%`);\n\tpad(\"Omission Count\", String(m.omissionCount));\n\tpad(\"Unsupported Claims\", String(m.unsupportedClaimCount));\n\tpad(\"Forbidden Actions\", String(m.forbiddenActionCount));\n\tpad(\"Premature Completion\", m.prematureCompletion ? \"YES\" : \"No\");\n\tif (m.prematureCompletionReasons.length > 0) {\n\t\tfor (const reason of m.prematureCompletionReasons) {\n\t\t\tlines.push(`  Reason: ${reason}`);\n\t\t}\n\t}\n\tpad(\"Operator Interventions\", String(m.operatorInterventionCount));\n\tpad(\"Validation Completion\", `${(m.validationCompletion * 100).toFixed(1)}%`);\n\tlines.push(\"\");\n\n\t// Usage / cost (when available)\n\tif (m.usage) {\n\t\tlines.push(\"USAGE\");\n\t\tlines.push(\"-\".repeat(72));\n\t\tconst u = m.usage;\n\t\tif (u.inputTokens !== undefined) pad(\"Input Tokens\", formatNumber(u.inputTokens));\n\t\tif (u.outputTokens !== undefined) pad(\"Output Tokens\", formatNumber(u.outputTokens));\n\t\tif (u.cachedTokens !== undefined) pad(\"Cached Tokens\", formatNumber(u.cachedTokens));\n\t\tif (u.totalTokens !== undefined) pad(\"Total Tokens\", formatNumber(u.totalTokens));\n\t\tif (u.toolCalls !== undefined) pad(\"Tool Calls\", String(u.toolCalls));\n\t\tif (u.durationMs !== undefined) pad(\"Duration\", formatDuration(u.durationMs));\n\t\tif (u.costUSD !== undefined) pad(\"Cost\", `$${u.costUSD.toFixed(4)}`);\n\t\tlines.push(\"\");\n\t}\n\n\t// Requirement summary\n\tlines.push(\"REQUIREMENT SUMMARY\");\n\tlines.push(\"-\".repeat(72));\n\n\tconst byStatus: Record<string, EvaluatedRequirement[]> = {};\n\tfor (const req of result.requirementResults) {\n\t\tconst s = req.evaluatedStatus;\n\t\tbyStatus[s] = byStatus[s] ?? [];\n\t\tbyStatus[s]!.push(req);\n\t}\n\n\tconst statusOrder: Array<{ status: string; label: string }> = [\n\t\t{ status: \"SATISFIED\", label: \"SATISFIED\" },\n\t\t{ status: \"IMPLEMENTED_UNVERIFIED\", label: \"IMPLEMENTED_UNVERIFIED\" },\n\t\t{ status: \"FAILED\", label: \"FAILED\" },\n\t\t{ status: \"BLOCKED\", label: \"BLOCKED\" },\n\t\t{ status: \"UNASSESSED\", label: \"UNASSESSED / OMITTED\" },\n\t\t{ status: \"IN_PROGRESS\", label: \"IN_PROGRESS\" },\n\t\t{ status: \"PENDING\", label: \"PENDING\" },\n\t\t{ status: \"NOT_APPLICABLE\", label: \"NOT_APPLICABLE\" },\n\t];\n\n\tfor (const { status, label } of statusOrder) {\n\t\tconst reqs = byStatus[status];\n\t\tif (!reqs || reqs.length === 0) continue;\n\t\tlines.push(`  ${label}: ${reqs.length}`);\n\t\tfor (const req of reqs) {\n\t\t\tconst marker = req.required ? \"*\" : \" \";\n\t\t\tlines.push(`    ${marker} ${req.id}: ${req.description}`);\n\t\t\tif (req.evaluatedStatus !== req.manifestStatus) {\n\t\t\t\tlines.push(`      Claimed: ${req.manifestStatus} → Evaluated: ${req.evaluatedStatus}`);\n\t\t\t}\n\t\t\tif (req.statusRationale) {\n\t\t\t\tlines.push(`      ${req.statusRationale}`);\n\t\t\t}\n\t\t}\n\t}\n\tlines.push(\"\");\n\n\t// All findings\n\tif (result.findings.length > 0) {\n\t\tlines.push(\"FINDINGS\");\n\t\tlines.push(\"-\".repeat(72));\n\t\tconst bySeverity = {\n\t\t\terror: result.findings.filter((f) => f.severity === \"error\"),\n\t\t\twarning: result.findings.filter((f) => f.severity === \"warning\"),\n\t\t\tinfo: result.findings.filter((f) => f.severity === \"info\"),\n\t\t};\n\t\tfor (const sev of [\"error\", \"warning\", \"info\"] as const) {\n\t\t\tconst fList = bySeverity[sev];\n\t\t\tif (fList.length === 0) continue;\n\t\t\tlines.push(`  ${sev.toUpperCase()}: ${fList.length}`);\n\t\t\tfor (const f of fList) {\n\t\t\t\tlines.push(`    [${f.code}] ${f.message}`);\n\t\t\t}\n\t\t\tlines.push(\"\");\n\t\t}\n\t}\n\n\tlines.push(\"=\".repeat(72));\n\tlines.push(\"END OF REPORT\");\n\n\treturn lines.join(\"\\n\");\n}\n\n// =============================================================================\n// JSON Report\n// =============================================================================\n\nexport function generateJsonReport(result: BenchmarkEvaluationResult): string {\n\treturn JSON.stringify(result, null, 2);\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\nfunction formatNumber(n: number): string {\n\tif (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n\tif (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n\treturn String(n);\n}\n\nfunction formatDuration(ms: number): string {\n\tif (ms >= 60_000) {\n\t\tconst min = Math.floor(ms / 60_000);\n\t\tconst sec = Math.round((ms % 60_000) / 1_000);\n\t\treturn `${min}m ${sec}s`;\n\t}\n\tif (ms >= 1_000) return `${(ms / 1_000).toFixed(1)}s`;\n\treturn `${ms}ms`;\n}\n"]}