@vitest-evals/github-reporter 0.16.0 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli-options.ts","../src/report.ts","../src/utils.ts","../src/annotations.ts","../src/collect.ts","../src/gate.ts","../src/summary.ts","../src/github.ts","../src/merge.ts","../src/cli.ts"],"sourcesContent":["export type CliOptions = {\n resultPatterns: string[];\n summaryPath?: string;\n summaryEnabled: boolean;\n annotations: boolean;\n checkRun: boolean;\n failOnFailures: boolean;\n failOnCheckError: boolean;\n minPassRate?: number;\n minScoreAverage?: number;\n maxAnnotations?: number;\n maxFailures?: number;\n checkRunId?: number;\n checkName?: string;\n token?: string;\n repository?: string;\n sha?: string;\n workspace?: string;\n help: boolean;\n};\n\ntype MutableCliOptions = Omit<CliOptions, \"resultPatterns\"> & {\n resultPatterns: string[];\n};\n\n/** Parses GitHub reporter CLI arguments, with explicit arguments taking precedence over environment defaults. */\nexport function parseCliArgs(\n args: string[],\n env: NodeJS.ProcessEnv = process.env,\n): CliOptions {\n const options: MutableCliOptions = {\n summaryPath: env.GITHUB_STEP_SUMMARY,\n summaryEnabled: true,\n annotations: env.GITHUB_ACTIONS === \"true\",\n checkRun: false,\n failOnFailures: false,\n failOnCheckError: false,\n resultPatterns: [],\n help: false,\n };\n\n for (let index = 0; index < args.length; index += 1) {\n const arg = args[index];\n switch (arg) {\n case \"--json\":\n options.resultPatterns.push(readValue(args, ++index, arg));\n break;\n case \"--summary\":\n options.summaryPath = readValue(args, ++index, arg);\n options.summaryEnabled = true;\n break;\n case \"--no-summary\":\n options.summaryEnabled = false;\n break;\n case \"--annotations\":\n options.annotations = true;\n break;\n case \"--no-annotations\":\n options.annotations = false;\n break;\n case \"--check-run\":\n options.checkRun = true;\n break;\n case \"--fail-on-failures\":\n options.failOnFailures = true;\n break;\n case \"--fail-on-check-error\":\n options.failOnCheckError = true;\n break;\n case \"--min-pass-rate\":\n options.minPassRate = readRatio(args, ++index, arg);\n break;\n case \"--min-score-average\":\n options.minScoreAverage = readRatio(args, ++index, arg);\n break;\n case \"--max-annotations\":\n options.maxAnnotations = readInteger(args, ++index, arg);\n break;\n case \"--max-failures\":\n options.maxFailures = readInteger(args, ++index, arg);\n break;\n case \"--check-run-id\":\n options.checkRunId = readInteger(args, ++index, arg);\n options.checkRun = true;\n break;\n case \"--check-name\":\n options.checkName = readValue(args, ++index, arg);\n break;\n case \"--token\":\n options.token = readValue(args, ++index, arg);\n break;\n case \"--repo\":\n options.repository = readValue(args, ++index, arg);\n break;\n case \"--sha\":\n options.sha = readValue(args, ++index, arg);\n break;\n case \"--workspace\":\n options.workspace = readValue(args, ++index, arg);\n break;\n case \"--help\":\n case \"-h\":\n options.help = true;\n return withDefaultJsonPath(options, env);\n default:\n if (!arg.startsWith(\"-\")) {\n options.resultPatterns.push(arg);\n break;\n }\n throw new Error(`Unknown argument: ${arg}`);\n }\n }\n\n return withDefaultJsonPath(options, env);\n}\n\nfunction withDefaultJsonPath(\n options: MutableCliOptions,\n env: NodeJS.ProcessEnv,\n): CliOptions {\n return {\n ...options,\n resultPatterns:\n options.resultPatterns.length > 0\n ? options.resultPatterns\n : [env.VITEST_EVALS_JSON_REPORT || \"vitest-results.json\"],\n };\n}\n\nfunction readValue(args: string[], index: number, flag: string) {\n const value = args[index];\n if (!value) {\n throw new Error(`Missing value for ${flag}`);\n }\n return value;\n}\n\nfunction readInteger(args: string[], index: number, flag: string) {\n const rawValue = readValue(args, index, flag);\n if (!/^\\d+$/.test(rawValue)) {\n throw new Error(`Invalid integer for ${flag}`);\n }\n return Number(rawValue);\n}\n\nfunction readRatio(args: string[], index: number, flag: string) {\n const rawValue = readValue(args, index, flag);\n const parsed = Number(rawValue);\n if (!Number.isFinite(parsed) || parsed < 0 || parsed > 1) {\n throw new Error(`Invalid ratio for ${flag}`);\n }\n return parsed;\n}\n","import { appendFile } from \"node:fs/promises\";\nimport {\n readVitestJsonReportFile,\n resolveResultFiles,\n} from \"@vitest-evals/core/node\";\nimport { renderWorkflowCommands } from \"./annotations\";\nimport { collectEvalReport } from \"./collect\";\nimport {\n type EvalGatePolicy,\n type EvalGateResult,\n evaluateEvalGate,\n renderGateWorkflowCommand,\n} from \"./gate\";\nimport { type PublishCheckRunResult, publishCheckRun } from \"./github\";\nimport { mergeEvalReports } from \"./merge\";\nimport { type SummaryOptions, renderJobSummary } from \"./summary\";\nimport type { EvalReport } from \"./types\";\n\n/** Options for reading eval JSON files and publishing GitHub report surfaces. */\nexport type PublishEvalReportOptions = SummaryOptions &\n EvalGatePolicy & {\n resultPatterns: string[];\n cwd?: string;\n workspace?: string;\n summaryEnabled?: boolean;\n summaryPath?: string;\n annotations?: boolean;\n checkRun?: boolean;\n failOnCheckError?: boolean;\n maxAnnotations?: number;\n checkRunId?: number;\n checkName?: string;\n token?: string;\n repository?: string;\n sha?: string;\n warn?: (message: string) => void;\n };\n\n/** Result from publishing eval reports, including merged report data. */\nexport type PublishEvalReportResult = {\n report: EvalReport;\n resultFiles: string[];\n gate: EvalGateResult;\n /**\n * True when an enforced gate rejects the report. Advisory (ungated) runs\n * never fail the step, matching `fail-on-failures: false` defaults.\n */\n shouldFail: boolean;\n checkRun?: PublishCheckRunResult;\n};\n\n/** Reads, merges, and publishes eval reports to GitHub Actions surfaces. */\nexport async function publishEvalReport(\n options: PublishEvalReportOptions,\n): Promise<PublishEvalReportResult> {\n const resultFiles = await resolveResultFiles(options.resultPatterns, {\n cwd: options.cwd,\n });\n if (resultFiles.length === 0) {\n throw new Error(\n `No eval result files matched: ${options.resultPatterns.join(\", \")}`,\n );\n }\n\n const reports = await Promise.all(\n resultFiles.map(async (resultFile) => {\n const json = await readVitestJsonReportFile(resultFile);\n return collectEvalReport(json, {\n workspace: options.workspace,\n });\n }),\n );\n const report = mergeEvalReports(reports);\n const gate = evaluateEvalGate(report, {\n failOnFailures: options.failOnFailures,\n minPassRate: options.minPassRate,\n minScoreAverage: options.minScoreAverage,\n });\n const summary = renderJobSummary(report, {\n maxFailures: options.maxFailures,\n maxOutputChars: options.maxOutputChars,\n maxReasonChars: options.maxReasonChars,\n maxToolCalls: options.maxToolCalls,\n gate,\n });\n\n if (options.summaryEnabled !== false) {\n if (options.summaryPath) {\n await appendFile(options.summaryPath, `${summary}\\n`);\n } else {\n console.log(summary);\n }\n }\n\n if (options.annotations) {\n const gateCommand = renderGateWorkflowCommand(gate);\n if (gateCommand) {\n console.log(gateCommand);\n }\n for (const command of renderWorkflowCommands(report, {\n maxAnnotations: options.maxAnnotations,\n gate,\n })) {\n console.log(command);\n }\n }\n\n let checkRun: PublishCheckRunResult | undefined;\n if (options.checkRun) {\n try {\n checkRun = await publishCheckRun(report, {\n checkRunId: options.checkRunId,\n maxAnnotations: options.maxAnnotations,\n maxFailures: options.maxFailures,\n maxOutputChars: options.maxOutputChars,\n maxReasonChars: options.maxReasonChars,\n maxToolCalls: options.maxToolCalls,\n name: options.checkName,\n repository: options.repository,\n sha: options.sha,\n token: options.token,\n gate,\n });\n\n if (checkRun.status === \"skipped\") {\n options.warn?.(`GitHub Check Run skipped: ${checkRun.reason}`);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (options.failOnCheckError) {\n throw error;\n }\n options.warn?.(message);\n }\n }\n\n return {\n report,\n resultFiles,\n gate,\n shouldFail: gate.enforced && !gate.ok,\n checkRun,\n };\n}\n","import { posix } from \"node:path\";\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function compactLine(value: string, maxLength: number) {\n const line = value\n .split(/\\r?\\n/)\n .map((part) => part.trim())\n .find((part) => part.length > 0);\n if (!line) {\n return \"\";\n }\n return truncate(line, maxLength);\n}\n\nexport function truncate(value: string, maxLength: number) {\n if (maxLength <= 0) {\n return \"\";\n }\n if (value.length <= maxLength) {\n return value;\n }\n return `${value.slice(0, Math.max(0, maxLength - 15)).trimEnd()}... [truncated]`;\n}\n\nexport function stringifyValue(value: unknown, maxLength: number) {\n if (value === undefined) {\n return \"\";\n }\n if (typeof value === \"string\") {\n return truncate(value, maxLength);\n }\n try {\n return truncate(JSON.stringify(value, null, 2), maxLength);\n } catch {\n return truncate(String(value), maxLength);\n }\n}\n\nexport function formatNumber(value: number) {\n return new Intl.NumberFormat(\"en-US\", {\n maximumFractionDigits: 0,\n }).format(value);\n}\n\nexport function formatScore(value: number | null | undefined) {\n if (value == null || !Number.isFinite(value)) {\n return \"n/a\";\n }\n return value.toFixed(2);\n}\n\nexport function formatDuration(ms: number | undefined) {\n if (ms === undefined || !Number.isFinite(ms)) {\n return \"n/a\";\n }\n if (ms < 1000) {\n return `${Math.round(ms)}ms`;\n }\n const seconds = ms / 1000;\n if (seconds < 60) {\n return `${seconds.toFixed(seconds < 10 ? 1 : 0)}s`;\n }\n const totalSeconds = Math.round(seconds);\n const minutes = Math.floor(totalSeconds / 60);\n const remainingSeconds = totalSeconds % 60;\n return `${minutes}m ${remainingSeconds}s`;\n}\n\nexport function formatLocation(\n file: string,\n location?: { line: number; column: number },\n) {\n if (!location) {\n return file;\n }\n return `${file}:${location.line}`;\n}\n\nexport function normalizePathForGitHub(path: string, workspace?: string) {\n const normalized = path.replace(/\\\\/g, \"/\");\n if (!workspace) {\n return normalized;\n }\n\n const workspacePath = workspace.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n if (\n normalized !== workspacePath &&\n !normalized.startsWith(`${workspacePath}/`)\n ) {\n return normalized;\n }\n\n return posix.relative(workspacePath, normalized);\n}\n\nexport function escapeFence(value: string) {\n return value.replace(/```/g, \"'''\");\n}\n\nexport function escapeHtml(value: string) {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\n}\n\nexport function escapeCommandData(value: string) {\n return value.replace(/%/g, \"%25\").replace(/\\r/g, \"%0D\").replace(/\\n/g, \"%0A\");\n}\n\nexport function escapeCommandProperty(value: string) {\n return escapeCommandData(value).replace(/:/g, \"%3A\").replace(/,/g, \"%2C\");\n}\n","import type { EvalGateResult } from \"./gate\";\nimport type { EvalCase, EvalReport, ToolCallSummary } from \"./types\";\nimport {\n compactLine,\n escapeCommandData,\n escapeCommandProperty,\n formatScore,\n stringifyValue,\n truncate,\n} from \"./utils\";\n\n/** Options for limiting rendered GitHub annotations. */\nexport type AnnotationOptions = {\n maxAnnotations?: number;\n /**\n * Suite gate decision. When the gate passed, quality misses are demoted to\n * warnings so a green score-gated check is not flooded with red failures.\n */\n gate?: EvalGateResult;\n};\n\n/** GitHub Check Run annotation payload. */\nexport type CheckAnnotation = {\n path: string;\n start_line: number;\n end_line: number;\n annotation_level: \"failure\" | \"warning\" | \"notice\";\n message: string;\n title?: string;\n raw_details?: string;\n};\n\nconst DEFAULT_MAX_WORKFLOW_ANNOTATIONS = 10;\nconst DEFAULT_MAX_CHECK_ANNOTATIONS = 50;\nconst MAX_CHECK_FIELD_LENGTH = 64_000;\n\ntype AnnotatedEvalCase = EvalCase & {\n location: { line: number; column: number };\n};\n\n/** Renders GitHub workflow-command annotations for failed eval cases. */\nexport function renderWorkflowCommands(\n report: EvalReport,\n options: AnnotationOptions = {},\n) {\n const maxAnnotations =\n options.maxAnnotations ?? DEFAULT_MAX_WORKFLOW_ANNOTATIONS;\n const command = caseAnnotationCommand(options.gate);\n\n return report.failures\n .filter(hasAnnotationLocation)\n .slice(0, maxAnnotations)\n .map((testCase) =>\n formatWorkflowCommand({\n command,\n properties: {\n file: testCase.displayFile,\n line: String(testCase.location.line),\n col: String(testCase.location.column),\n title: \"vitest-evals\",\n },\n message: formatWorkflowMessage(testCase),\n }),\n );\n}\n\n/** Builds Check Run annotations for failed eval cases. */\nexport function buildCheckAnnotations(\n report: EvalReport,\n options: AnnotationOptions = {},\n): CheckAnnotation[] {\n const maxAnnotations = Math.min(\n options.maxAnnotations ?? DEFAULT_MAX_CHECK_ANNOTATIONS,\n DEFAULT_MAX_CHECK_ANNOTATIONS,\n );\n const annotationLevel = caseAnnotationLevel(options.gate);\n\n return report.failures\n .filter(hasAnnotationLocation)\n .slice(0, maxAnnotations)\n .map((testCase) => ({\n path: testCase.displayFile,\n start_line: testCase.location.line,\n end_line: testCase.location.line,\n annotation_level: annotationLevel,\n title: truncate(\n `${testCase.primaryFailure?.judgeName ?? \"vitest-evals\"} - ${testCase.displayName}`,\n 255,\n ),\n message: truncate(\n formatWorkflowMessage(testCase),\n MAX_CHECK_FIELD_LENGTH,\n ),\n raw_details: truncate(formatRawDetails(testCase), MAX_CHECK_FIELD_LENGTH),\n }));\n}\n\nfunction caseAnnotationCommand(\n gate: EvalGateResult | undefined,\n): \"error\" | \"warning\" {\n return gate?.ok ? \"warning\" : \"error\";\n}\n\nfunction caseAnnotationLevel(\n gate: EvalGateResult | undefined,\n): \"failure\" | \"warning\" {\n return gate?.ok ? \"warning\" : \"failure\";\n}\n\nfunction hasAnnotationLocation(\n testCase: EvalCase,\n): testCase is AnnotatedEvalCase {\n return Boolean(testCase.location);\n}\n\nfunction formatWorkflowMessage(testCase: EvalCase) {\n const failure = testCase.primaryFailure;\n const parts = [\n testCase.displayName,\n `score ${formatScore(failure?.score ?? testCase.eval?.avgScore)}`,\n ];\n\n if (failure?.judgeName) {\n parts.push(failure.judgeName);\n }\n\n const reason = compactLine(failure?.reason ?? \"\", 320);\n if (reason) {\n parts.push(reason);\n }\n\n return parts.join(\" - \");\n}\n\nfunction formatRawDetails(testCase: AnnotatedEvalCase) {\n const lines = [\n `Test: ${testCase.displayName}`,\n `Location: ${testCase.displayFile}:${testCase.location.line}`,\n `Harness: ${testCase.harness?.name ?? \"n/a\"}`,\n `Score: ${formatScore(testCase.primaryFailure?.score ?? testCase.eval?.avgScore)}`,\n `Judge: ${testCase.primaryFailure?.judgeName ?? \"n/a\"}`,\n \"\",\n \"Reason:\",\n testCase.primaryFailure?.reason ?? \"n/a\",\n ];\n\n const finalOutput = testCase.eval?.output ?? testCase.harness?.output;\n if (finalOutput !== undefined) {\n lines.push(\"\", \"Final:\", stringifyValue(finalOutput, 8000));\n }\n\n if (testCase.toolCalls.length) {\n lines.push(\"\", \"Tools:\");\n for (const toolCall of testCase.toolCalls) {\n lines.push(`- ${toolCall.name}: ${formatToolCallStatus(toolCall)}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction formatToolCallStatus(toolCall: ToolCallSummary) {\n if (toolCall.status === \"pending\") {\n return \"pending\";\n }\n\n if (toolCall.status === \"error\") {\n return `error: ${toolCall.error ?? \"unknown error\"}`;\n }\n\n return \"ok\";\n}\n\nfunction formatWorkflowCommand({\n command,\n properties,\n message,\n}: {\n command: \"error\" | \"warning\" | \"notice\";\n properties: Record<string, string>;\n message: string;\n}) {\n const renderedProperties = Object.entries(properties)\n .map(([key, value]) => `${key}=${escapeCommandProperty(value)}`)\n .join(\",\");\n return `::${command} ${renderedProperties}::${escapeCommandData(message)}`;\n}\n","import {\n type HarnessRun,\n type ReportCase,\n type ToolCall,\n type TranscriptToolCallEvent,\n type TranscriptToolResultEvent,\n collectReportWorkspace,\n} from \"@vitest-evals/core\";\nimport type {\n CollectOptions,\n EvalCase,\n EvalFailure,\n EvalReport,\n EvalScore,\n ToolCallSummary,\n UsageSummary,\n VitestJsonReport,\n} from \"./types\";\nimport { compactLine, stringifyValue } from \"./utils\";\n\n/** Converts a Vitest JSON report into the compact eval report model. */\nexport function collectEvalReport(\n input: VitestJsonReport,\n options: CollectOptions = {},\n): EvalReport {\n const workspace = collectReportWorkspace(\n {\n report: input,\n },\n {\n workspace: options.workspace,\n },\n );\n const cases = workspace.cases.map(collectEvalCase);\n const failures = cases.filter((testCase) => testCase.status === \"failed\");\n const evalScores = cases\n .map((testCase) => testCase.eval?.avgScore)\n .filter((score): score is number => isFiniteNumber(score));\n const usage = sumUsage(cases);\n const durationMs = workspace.runs[0]?.durationMs;\n\n return {\n status: input.success && failures.length === 0 ? \"passed\" : \"failed\",\n startedAt: input.startTime,\n durationMs,\n totals: {\n total: input.numTotalTests,\n passed: input.numPassedTests,\n failed: input.numFailedTests,\n skipped: input.numPendingTests + input.numTodoTests,\n evalTotal: cases.length,\n evalPassed: cases.filter((testCase) => testCase.status === \"passed\")\n .length,\n evalFailed: failures.length,\n },\n score:\n evalScores.length > 0\n ? {\n average:\n evalScores.reduce((total, score) => total + score, 0) /\n evalScores.length,\n minimum: Math.min(...evalScores),\n }\n : undefined,\n usage,\n cases,\n failures,\n };\n}\n\nfunction collectEvalCase(reportCase: ReportCase): EvalCase {\n const scores = (reportCase.eval?.scores ?? []).map(normalizeScore);\n const harnessRun = reportCase.harness?.run;\n const toolCalls = collectToolCalls(reportCase);\n const evalCase: EvalCase = {\n id: reportCase.id,\n file: reportCase.file,\n displayFile: reportCase.displayFile,\n title: reportCase.title,\n displayName: reportCase.displayName,\n status: reportCase.status,\n durationMs: numberField(reportCase.durationMs),\n location: reportCase.location,\n failureMessages: reportCase.failureMessages,\n toolCalls,\n eval: reportCase.eval\n ? {\n avgScore: numberField(reportCase.eval.avgScore),\n thresholdFailed: reportCase.eval.thresholdFailed,\n output: reportCase.eval.output,\n scores,\n }\n : undefined,\n harness: reportCase.harness\n ? {\n name: reportCase.harness.name,\n output: harnessRun?.output,\n usage: harnessRun?.usage,\n timingMs: harnessRun?.timings?.totalMs,\n toolCalls,\n errors: harnessRun?.errors ?? [],\n }\n : undefined,\n };\n\n evalCase.primaryFailure = getPrimaryFailure(evalCase);\n return evalCase;\n}\n\nfunction normalizeScore(score: EvalScore): EvalScore {\n return {\n ...score,\n score: numberField(score.score) ?? null,\n };\n}\n\nfunction numberField(value: unknown) {\n return isFiniteNumber(value) ? value : undefined;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction collectToolCalls(reportCase: ReportCase) {\n const harnessCalls = collectSessionToolCalls(\n reportCase.harness?.run?.session,\n );\n return harnessCalls.length > 0\n ? harnessCalls\n : (reportCase.eval?.toolCalls ?? []).map(toToolCallSummary);\n}\n\nfunction collectSessionToolCalls(session: HarnessRun[\"session\"] | undefined) {\n if (!session) {\n return [];\n }\n\n const resultsById = new Map<string, TranscriptToolResultEvent>();\n for (const event of session.events) {\n if (event.type === \"tool_result\" && !resultsById.has(event.toolCallId)) {\n resultsById.set(event.toolCallId, event);\n }\n }\n\n return session.events.flatMap((event) =>\n event.type === \"tool_call\"\n ? [toSessionToolCallSummary(event, resultsById.get(event.id))]\n : [],\n );\n}\n\nfunction toToolCallSummary(call: ToolCall): ToolCallSummary {\n return {\n name: call.name,\n status: call.status,\n error: call.status === \"error\" ? getToolCallError(call.error) : undefined,\n };\n}\n\nfunction toSessionToolCallSummary(\n call: TranscriptToolCallEvent,\n result: TranscriptToolResultEvent | undefined,\n): ToolCallSummary {\n if (!result) {\n return {\n name: call.name,\n status: \"pending\",\n ...(call.durationMs !== undefined ? { durationMs: call.durationMs } : {}),\n };\n }\n\n const durationMs = result.durationMs ?? call.durationMs;\n return {\n name: call.name,\n status: result.error ? \"error\" : \"ok\",\n ...(durationMs !== undefined ? { durationMs } : {}),\n ...(result.error ? { error: getToolCallError(result.error) } : {}),\n };\n}\n\nfunction getToolCallError(value: unknown) {\n const error = value as { message?: unknown };\n if (\n value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n typeof error.message === \"string\"\n ) {\n return error.message;\n }\n if (value !== undefined) {\n return stringifyValue(value, 240);\n }\n return undefined;\n}\n\nfunction getPrimaryFailure(testCase: EvalCase): EvalFailure | undefined {\n const failingScores = [...(testCase.eval?.scores ?? [])]\n .filter(\n (score) =>\n (score.score ?? 0) < 1 ||\n score.metadata?.rationale !== undefined ||\n score.metadata?.output !== undefined,\n )\n .sort((left, right) => (left.score ?? 0) - (right.score ?? 0));\n const primary = failingScores[0];\n const score =\n typeof primary?.score === \"number\"\n ? primary.score\n : testCase.eval?.avgScore;\n const reason =\n stringifyReason(primary?.metadata?.rationale) ??\n compactLine(testCase.failureMessages.join(\"\\n\"), 500);\n\n if (!primary && !reason && score === undefined) {\n return undefined;\n }\n\n return {\n judgeName: primary?.name,\n score,\n reason: reason || undefined,\n };\n}\n\nfunction stringifyReason(value: unknown) {\n if (value === undefined) {\n return undefined;\n }\n return typeof value === \"string\" ? value : stringifyValue(value, 4000);\n}\n\nfunction sumUsage(cases: EvalCase[]) {\n const usage: Required<UsageSummary> = {\n inputTokens: 0,\n outputTokens: 0,\n reasoningTokens: 0,\n totalTokens: 0,\n toolCalls: 0,\n };\n\n for (const testCase of cases) {\n const caseUsage = testCase.harness?.usage;\n usage.inputTokens += caseUsage?.inputTokens ?? 0;\n usage.outputTokens += caseUsage?.outputTokens ?? 0;\n usage.reasoningTokens += caseUsage?.reasoningTokens ?? 0;\n usage.totalTokens +=\n caseUsage?.totalTokens ??\n (caseUsage?.inputTokens ?? 0) +\n (caseUsage?.outputTokens ?? 0) +\n (caseUsage?.reasoningTokens ?? 0);\n usage.toolCalls += toolCallCount(testCase);\n }\n\n return usage;\n}\n\nfunction toolCallCount(testCase: EvalCase) {\n const usageToolCalls = testCase.harness?.usage?.toolCalls;\n if (usageToolCalls !== undefined) {\n return Math.max(usageToolCalls, testCase.toolCalls.length);\n }\n\n return testCase.toolCalls.length;\n}\n","import type { EvalReport } from \"./types\";\nimport {\n escapeCommandData,\n escapeCommandProperty,\n formatNumber,\n formatScore,\n} from \"./utils\";\n\n/** Optional floors and legacy fail-on-any-failure policy for a combined report. */\nexport type EvalGatePolicy = {\n /**\n * Minimum fraction of eval cases that must pass, in the range `[0, 1]`.\n * Example: `0.8` requires at least 80% of eval cases to pass.\n */\n minPassRate?: number;\n /**\n * Minimum average eval score across scored cases, in the range `[0, 1]`.\n */\n minScoreAverage?: number;\n /**\n * When true, require every eval case to pass. Equivalent to setting\n * `minPassRate` to `1`, and combined with an explicit floor by taking the\n * stricter value.\n */\n failOnFailures?: boolean;\n};\n\n/** Result of applying a gate policy to a combined eval report. */\nexport type EvalGateResult = {\n /** Whether the configured policy accepts this report. */\n ok: boolean;\n /** Compact status used by action outputs and summaries. */\n status: \"passed\" | \"failed\";\n /** True when any gate input was configured. */\n enforced: boolean;\n /** Eval pass rate when the report includes at least one eval case. */\n passRate: number | null;\n /** Short title for Check Runs and workflow annotations. */\n title: string;\n /** Longer explanation used in logs, summaries, and annotations. */\n message: string;\n};\n\n/**\n * Decide whether a combined eval report meets the configured CI gate.\n *\n * With no policy inputs, the result mirrors the report status and is not\n * treated as an enforced gate. With floors or `failOnFailures`, non-eval\n * failures and empty eval reports fail closed, and qualitative misses only\n * fail when they break the configured floors.\n */\nexport function evaluateEvalGate(\n report: EvalReport,\n policy: EvalGatePolicy = {},\n): EvalGateResult {\n const minPassRate = resolveMinPassRate(policy);\n const minScoreAverage = policy.minScoreAverage;\n const enforced =\n minPassRate !== undefined ||\n minScoreAverage !== undefined ||\n policy.failOnFailures === true;\n\n const passRate = computePassRate(report);\n const counts = formatEvalCounts(report, passRate);\n\n if (!enforced) {\n const ok = report.status === \"passed\";\n return {\n ok,\n status: ok ? \"passed\" : \"failed\",\n enforced: false,\n passRate,\n title: defaultCheckTitle(report),\n message: ok\n ? `eval report passed: ${counts}`\n : `eval report failed: ${counts}`,\n };\n }\n\n const nonEvalFailures = Math.max(\n 0,\n report.totals.failed - report.totals.evalFailed,\n );\n if (nonEvalFailures > 0) {\n return {\n ok: false,\n status: \"failed\",\n enforced: true,\n passRate,\n title: \"Eval report hard failure\",\n message: `${formatNumber(nonEvalFailures)} non-eval test failure${\n nonEvalFailures === 1 ? \"\" : \"s\"\n }; ${counts}`,\n };\n }\n\n if (report.totals.evalTotal === 0) {\n return {\n ok: false,\n status: \"failed\",\n enforced: true,\n passRate: null,\n title: \"Eval report hard failure\",\n message: \"no eval cases were reported\",\n };\n }\n\n // Preserve Vitest-level hard failures that did not produce counted test\n // failures (for example success:false with empty assertion results).\n if (\n report.status === \"failed\" &&\n report.totals.failed === 0 &&\n report.failures.length === 0\n ) {\n return {\n ok: false,\n status: \"failed\",\n enforced: true,\n passRate,\n title: \"Eval report hard failure\",\n message: `vitest run failed without counted test failures; ${counts}`,\n };\n }\n\n if (\n minPassRate !== undefined &&\n (passRate === null || passRate + Number.EPSILON < minPassRate)\n ) {\n return {\n ok: false,\n status: \"failed\",\n enforced: true,\n passRate,\n title: `Eval pass rate ${formatPercent(passRate)} — required ${formatPercent(minPassRate)}`,\n message: `eval pass rate below floor: ${counts}; required >= ${formatPercent(minPassRate)}`,\n };\n }\n\n if (minScoreAverage !== undefined) {\n const average = report.score?.average;\n if (average === undefined || !Number.isFinite(average)) {\n return {\n ok: false,\n status: \"failed\",\n enforced: true,\n passRate,\n title: \"Eval score gate failed\",\n message: `no score average available; required avg score >= ${formatScore(minScoreAverage)}`,\n };\n }\n if (average + Number.EPSILON < minScoreAverage) {\n return {\n ok: false,\n status: \"failed\",\n enforced: true,\n passRate,\n title: `Avg score ${formatScore(average)} — required ${formatScore(minScoreAverage)}`,\n message: `avg score below floor: ${counts}; required avg score >= ${formatScore(minScoreAverage)}`,\n };\n }\n }\n\n return {\n ok: true,\n status: \"passed\",\n enforced: true,\n passRate,\n title: enforcedPassTitle(report, passRate, minPassRate, minScoreAverage),\n message: `eval gate passed: ${counts}${formatFloorSuffix(minPassRate, minScoreAverage)}`,\n };\n}\n\n/** Compute the eval pass rate for a report, or null when there are no evals. */\nexport function computePassRate(report: EvalReport): number | null {\n if (report.totals.evalTotal <= 0) {\n return null;\n }\n return report.totals.evalPassed / report.totals.evalTotal;\n}\n\n/** Format a 0-1 ratio as a percentage with one decimal place. */\nexport function formatPercent(value: number | null | undefined) {\n if (value == null || !Number.isFinite(value)) {\n return \"n/a\";\n }\n return `${(value * 100).toFixed(1)}%`;\n}\n\n/** Build a suite-level workflow annotation for a failed enforced gate. */\nexport function renderGateWorkflowCommand(gate: EvalGateResult) {\n if (gate.ok || !gate.enforced) {\n return undefined;\n }\n return `::error title=${escapeCommandProperty(gate.title)}::${escapeCommandData(gate.message)}`;\n}\n\nfunction resolveMinPassRate(policy: EvalGatePolicy) {\n const configured = policy.minPassRate;\n if (policy.failOnFailures) {\n if (configured === undefined) {\n return 1;\n }\n return Math.max(configured, 1);\n }\n return configured;\n}\n\nfunction defaultCheckTitle(report: EvalReport) {\n if (report.failures.length === 0 && report.status === \"passed\") {\n return \"No eval failures\";\n }\n if (report.failures.length === 0) {\n return \"Vitest run failed\";\n }\n return `${report.failures.length} eval failure${\n report.failures.length === 1 ? \"\" : \"s\"\n }`;\n}\n\nfunction enforcedPassTitle(\n report: EvalReport,\n passRate: number | null,\n minPassRate: number | undefined,\n minScoreAverage: number | undefined,\n) {\n if (minPassRate !== undefined) {\n return `Eval pass rate ${formatPercent(passRate)} — floor ${formatPercent(minPassRate)}`;\n }\n if (minScoreAverage !== undefined) {\n return `Avg score ${formatScore(report.score?.average)} — floor ${formatScore(minScoreAverage)}`;\n }\n return defaultCheckTitle(report);\n}\n\nfunction formatEvalCounts(report: EvalReport, passRate: number | null) {\n const scoreText =\n report.score?.average === undefined\n ? \"n/a\"\n : formatScore(report.score.average);\n const passRateText = passRate === null ? \"n/a\" : formatPercent(passRate);\n return `${formatNumber(report.totals.evalPassed)}/${formatNumber(\n report.totals.evalTotal,\n )} passed (${passRateText}), avg score ${scoreText}`;\n}\n\nfunction formatFloorSuffix(\n minPassRate: number | undefined,\n minScoreAverage: number | undefined,\n) {\n const parts: string[] = [];\n if (minPassRate !== undefined) {\n parts.push(`pass rate floor ${formatPercent(minPassRate)}`);\n }\n if (minScoreAverage !== undefined) {\n parts.push(`avg score floor ${formatScore(minScoreAverage)}`);\n }\n return parts.length === 0 ? \"\" : `; ${parts.join(\", \")}`;\n}\n","import type { EvalGateResult } from \"./gate\";\nimport { formatPercent } from \"./gate\";\nimport type { EvalCase, EvalReport, ToolCallSummary } from \"./types\";\nimport {\n compactLine,\n escapeFence,\n escapeHtml,\n formatDuration,\n formatLocation,\n formatNumber,\n formatScore,\n stringifyValue,\n truncate,\n} from \"./utils\";\n\n/** Options for rendering GitHub Actions summary markdown. */\nexport type SummaryOptions = {\n maxFailures?: number;\n maxReasonChars?: number;\n maxOutputChars?: number;\n maxToolCalls?: number;\n gate?: EvalGateResult;\n};\n\nconst DEFAULT_MAX_FAILURES = 20;\nconst DEFAULT_MAX_REASON_CHARS = 8000;\nconst DEFAULT_MAX_OUTPUT_CHARS = 4000;\nconst DEFAULT_MAX_TOOL_CALLS = 20;\nconst SCORE_DISTRIBUTION_BUCKETS = [\n \"0-19%\",\n \"20-39%\",\n \"40-59%\",\n \"60-79%\",\n \"80-100%\",\n] as const;\nconst SCORE_DISTRIBUTION_BAR_WIDTH = 20;\n\n/** Renders the GitHub Actions job summary markdown for an eval report. */\nexport function renderJobSummary(\n report: EvalReport,\n options: SummaryOptions = {},\n) {\n const maxFailures = options.maxFailures ?? DEFAULT_MAX_FAILURES;\n const failures = report.failures.slice(0, maxFailures);\n const nonEvalFailures = report.totals.failed - report.totals.evalFailed;\n const lines: string[] = [\n \"# vitest-evals\",\n \"\",\n ...renderSummaryTable(report, nonEvalFailures, options.gate),\n \"\",\n ...renderScoreDistribution(report),\n \"## Results\",\n \"\",\n ];\n\n if (report.failures.length > 0) {\n const failureHeading =\n options.gate?.ok === true ? \"### Quality Misses\" : \"### Failures\";\n lines.push(failureHeading, \"\");\n failures.forEach((testCase, index) => {\n lines.push(...renderFailureDetails(testCase, index + 1, options), \"\");\n });\n\n if (report.failures.length > failures.length) {\n const omittedLabel =\n options.gate?.ok === true ? \"quality misses\" : \"failures\";\n lines.push(\n `${report.failures.length - failures.length} more ${omittedLabel} omitted from this summary.`,\n \"\",\n );\n }\n } else if (report.totals.evalTotal > 0) {\n lines.push(\"### Failures\", \"\", \"No eval failures.\", \"\");\n }\n\n if (report.totals.evalTotal === 0) {\n lines.push(\"No eval metadata was found in the Vitest JSON report.\", \"\");\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction formatCountLine(passed: number, failed: number, total: number) {\n return `${formatNumber(passed)} passed, ${formatNumber(failed)} failed, ${formatNumber(total)} total`;\n}\n\nfunction renderSummaryTable(\n report: EvalReport,\n nonEvalFailures: number,\n gate?: EvalGateResult,\n) {\n const rows: Array<[string, string]> = [\n [\"Status\", gate?.status ?? report.status],\n [\n \"Evals\",\n formatCountLine(\n report.totals.evalPassed,\n report.totals.evalFailed,\n report.totals.evalTotal,\n ),\n ],\n ];\n\n if (gate?.passRate !== undefined && gate.passRate !== null) {\n rows.push([\"Pass Rate\", formatPercent(gate.passRate)]);\n } else if (report.totals.evalTotal > 0) {\n rows.push([\n \"Pass Rate\",\n formatPercent(report.totals.evalPassed / report.totals.evalTotal),\n ]);\n }\n\n if (report.score) {\n rows.push([\"Score\", formatScoreSummary(report.score)]);\n }\n\n if (gate?.enforced) {\n rows.push([\"Gate\", gate.message]);\n }\n\n if (nonEvalFailures > 0) {\n rows.push([\n \"Other Failures\",\n `${formatNumber(nonEvalFailures)} non-eval test failure${\n nonEvalFailures === 1 ? \"\" : \"s\"\n }`,\n ]);\n }\n\n rows.push([\"Duration\", formatDuration(report.durationMs)]);\n\n return [\n \"| Metric | Value |\",\n \"| --- | --- |\",\n ...rows.map(\n ([metric, value]) =>\n `| ${escapeTableCell(metric)} | ${escapeTableCell(value)} |`,\n ),\n ];\n}\n\nfunction formatScoreSummary(score: NonNullable<EvalReport[\"score\"]>) {\n return `avg ${formatScore(score.average)}${\n score.minimum === undefined ? \"\" : `, min ${formatScore(score.minimum)}`\n }`;\n}\n\nfunction escapeTableCell(value: string) {\n return value\n .replace(/\\r?\\n/g, \" \")\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/\\|/g, \"\\\\|\");\n}\n\nfunction renderScoreDistribution(report: EvalReport) {\n const scores = report.cases\n .map((testCase) => testCase.eval?.avgScore)\n .filter(\n (score): score is number =>\n typeof score === \"number\" && Number.isFinite(score),\n );\n if (scores.length === 0) {\n return [];\n }\n\n const counts = SCORE_DISTRIBUTION_BUCKETS.map(() => 0);\n for (const score of scores) {\n const bucket = Math.min(\n SCORE_DISTRIBUTION_BUCKETS.length - 1,\n Math.max(0, Math.floor(score * SCORE_DISTRIBUTION_BUCKETS.length)),\n );\n counts[bucket] = (counts[bucket] ?? 0) + 1;\n }\n\n const maxCount = Math.max(...counts);\n return [\n \"## Scores\",\n \"\",\n \"```text\",\n ...SCORE_DISTRIBUTION_BUCKETS.map((label, index) =>\n formatScoreDistributionBucket(label, counts[index] ?? 0, maxCount),\n ),\n \"```\",\n \"\",\n ];\n}\n\nfunction formatScoreDistributionBucket(\n label: string,\n count: number,\n maxCount: number,\n) {\n const barLength =\n count === 0\n ? 0\n : Math.max(\n 1,\n Math.round((count / maxCount) * SCORE_DISTRIBUTION_BAR_WIDTH),\n );\n const bar = \"#\".repeat(barLength).padEnd(SCORE_DISTRIBUTION_BAR_WIDTH, \" \");\n return `${label.padEnd(7)} | ${bar} ${formatNumber(count)}`;\n}\n\nfunction renderFailureDetails(\n testCase: EvalCase,\n number: number,\n options: SummaryOptions,\n) {\n const failure = testCase.primaryFailure;\n const maxReasonChars = options.maxReasonChars ?? DEFAULT_MAX_REASON_CHARS;\n const maxOutputChars = options.maxOutputChars ?? DEFAULT_MAX_OUTPUT_CHARS;\n const maxToolCalls = options.maxToolCalls ?? DEFAULT_MAX_TOOL_CALLS;\n const usage = formatCaseUsage(testCase);\n const finalOutput = testCase.eval?.output ?? testCase.harness?.output;\n const summary = `${number}. ${testCase.displayName} - ${\n failure?.judgeName ?? \"failure\"\n } - ${formatScore(failure?.score ?? testCase.eval?.avgScore)}`;\n const lines = [\n \"<details>\",\n `<summary>${escapeHtml(summary)}</summary>`,\n \"\",\n \"```text\",\n ...renderFailureBlock(testCase, {\n finalOutput,\n maxOutputChars,\n maxReasonChars,\n maxToolCalls,\n number,\n usage,\n }).map(escapeFence),\n \"```\",\n \"\",\n \"</details>\",\n ];\n return lines;\n}\n\nfunction renderFailureBlock(\n testCase: EvalCase,\n {\n finalOutput,\n maxOutputChars,\n maxReasonChars,\n maxToolCalls,\n number,\n usage,\n }: {\n finalOutput: unknown;\n maxOutputChars: number;\n maxReasonChars: number;\n maxToolCalls: number;\n number: number;\n usage: string;\n },\n) {\n const failure = testCase.primaryFailure;\n const overviewRows: Array<[string, string]> = [\n [\"Case\", `${number}. ${testCase.displayName}`],\n [\"Status\", testCase.status],\n [\"Location\", formatLocation(testCase.displayFile, testCase.location)],\n [\"Harness\", testCase.harness?.name ?? \"n/a\"],\n [\"Score\", formatScore(failure?.score ?? testCase.eval?.avgScore)],\n [\"Judge\", failure?.judgeName ?? \"n/a\"],\n ];\n if (usage) {\n overviewRows.push([\"Usage\", usage]);\n }\n if (testCase.durationMs !== undefined) {\n overviewRows.push([\"Duration\", formatDuration(testCase.durationMs)]);\n }\n\n const lines = [\n ...renderAsciiSection(\"Result\", renderKeyValues(overviewRows)),\n \"\",\n ];\n\n if (failure?.reason) {\n lines.push(\n ...renderAsciiSection(\n \"Reason\",\n truncate(failure.reason, maxReasonChars).split(/\\r?\\n/),\n ),\n \"\",\n );\n }\n\n if (testCase.eval?.scores.length) {\n lines.push(\n ...renderAsciiTable(\n [\"Judge\", \"Score\"],\n testCase.eval.scores.map((score) => [\n score.name ?? \"Unknown\",\n formatScore(score.score),\n ]),\n ),\n \"\",\n );\n }\n\n if (finalOutput !== undefined) {\n lines.push(\n ...renderAsciiSection(\n \"Final Output\",\n stringifyValue(finalOutput, maxOutputChars).split(/\\r?\\n/),\n ),\n \"\",\n );\n }\n\n if (testCase.toolCalls.length) {\n const toolCalls = testCase.toolCalls.slice(0, maxToolCalls);\n lines.push(\n ...renderAsciiTable(\n [\"Tool\", \"Status\", \"Duration\"],\n toolCalls.map((toolCall) => [\n toolCall.name,\n formatToolCallStatus(toolCall),\n toolCall.durationMs === undefined\n ? \"n/a\"\n : formatDuration(toolCall.durationMs),\n ]),\n ),\n );\n if (testCase.toolCalls.length > maxToolCalls) {\n lines.push(\n `${testCase.toolCalls.length - maxToolCalls} more tool calls omitted`,\n );\n }\n lines.push(\"\");\n }\n\n if (testCase.harness?.errors.length) {\n lines.push(\n ...renderAsciiSection(\n \"Harness Errors\",\n stringifyValue(testCase.harness.errors, maxReasonChars).split(/\\r?\\n/),\n ),\n \"\",\n );\n }\n\n while (lines[lines.length - 1] === \"\") {\n lines.pop();\n }\n return lines;\n}\n\nfunction formatToolCallStatus(toolCall: ToolCallSummary) {\n if (toolCall.status === \"pending\") {\n return \"pending\";\n }\n\n if (toolCall.status === \"error\") {\n return `error: ${compactLine(toolCall.error ?? \"unknown error\", 120)}`;\n }\n\n return \"ok\";\n}\n\nfunction renderAsciiSection(title: string, content: string[]) {\n return [title, \"-\".repeat(title.length), ...content];\n}\n\nfunction renderKeyValues(rows: Array<[string, string]>) {\n const labelWidth = Math.max(...rows.map(([label]) => label.length));\n return rows.map(\n ([label, value]) =>\n `${label.padEnd(labelWidth)} ${compactLine(value, 500)}`,\n );\n}\n\nfunction renderAsciiTable(headers: string[], rows: string[][]) {\n const widths = headers.map((header, index) =>\n Math.max(header.length, ...rows.map((row) => row[index]?.length ?? 0)),\n );\n const renderRow = (row: string[]) =>\n row\n .map((cell, index) => cell.padEnd(widths[index] ?? cell.length))\n .join(\" \")\n .trimEnd();\n\n return [\n renderRow(headers),\n widths.map((width) => \"-\".repeat(width)).join(\" \"),\n ...rows.map(renderRow),\n ];\n}\n\nfunction formatCaseUsage(testCase: EvalCase) {\n const usage = testCase.harness?.usage;\n const parts: string[] = [];\n const totalTokens =\n usage?.totalTokens ??\n (usage?.inputTokens ?? 0) +\n (usage?.outputTokens ?? 0) +\n (usage?.reasoningTokens ?? 0);\n const toolCalls =\n usage?.toolCalls !== undefined\n ? Math.max(usage.toolCalls, testCase.toolCalls.length)\n : testCase.toolCalls.length;\n\n if (totalTokens > 0) {\n parts.push(`${formatNumber(totalTokens)} tokens`);\n }\n if (toolCalls > 0) {\n parts.push(`${formatNumber(toolCalls)} tool${toolCalls === 1 ? \"\" : \"s\"}`);\n }\n if (testCase.harness?.timingMs !== undefined) {\n parts.push(formatDuration(testCase.harness.timingMs));\n }\n\n return parts.join(\", \");\n}\n","import { buildCheckAnnotations } from \"./annotations\";\nimport { type EvalGateResult, evaluateEvalGate } from \"./gate\";\nimport { type SummaryOptions, renderJobSummary } from \"./summary\";\nimport type { EvalReport } from \"./types\";\n\n/** Options for creating or updating a GitHub Check Run. */\nexport type PublishCheckRunOptions = SummaryOptions & {\n token?: string;\n repository?: string;\n sha?: string;\n name?: string;\n apiUrl?: string;\n checkRunId?: number;\n maxAnnotations?: number;\n /**\n * Suite gate decision. When omitted, the report is evaluated with the\n * default advisory policy so title/conclusion stay consistent.\n */\n gate?: EvalGateResult;\n};\n\n/** Result of attempting to publish a GitHub Check Run. */\nexport type PublishCheckRunResult =\n | {\n status: \"skipped\";\n reason: string;\n }\n | {\n status: \"created\" | \"updated\";\n id?: number;\n htmlUrl?: string;\n };\n\nconst DEFAULT_CHECK_NAME = \"vitest-evals\";\nconst MAX_CHECK_SUMMARY_LENGTH = 64_000;\nconst CHECK_SUMMARY_TRUNCATION_SUFFIX =\n \"\\n\\n[truncated for GitHub Check Run]\\n\";\n\n/** Publishes the eval report to a GitHub Check Run when configuration allows it. */\nexport async function publishCheckRun(\n report: EvalReport,\n options: PublishCheckRunOptions = {},\n): Promise<PublishCheckRunResult> {\n const token = options.token ?? process.env.GITHUB_TOKEN;\n const repository = options.repository ?? process.env.GITHUB_REPOSITORY;\n const sha = options.sha ?? process.env.GITHUB_SHA;\n\n if (!token) {\n return { status: \"skipped\", reason: \"missing GITHUB_TOKEN\" };\n }\n if (!repository) {\n return { status: \"skipped\", reason: \"missing GITHUB_REPOSITORY\" };\n }\n if (!sha && options.checkRunId === undefined) {\n return { status: \"skipped\", reason: \"missing GITHUB_SHA\" };\n }\n\n const [owner, repo] = repository.split(\"/\");\n if (!owner || !repo) {\n return {\n status: \"skipped\",\n reason: `invalid GitHub repository: ${repository}`,\n };\n }\n\n const payload = buildCheckRunPayload(report, options);\n const apiUrl =\n options.apiUrl ?? process.env.GITHUB_API_URL ?? \"https://api.github.com\";\n const requestUrl =\n options.checkRunId === undefined\n ? `${apiUrl}/repos/${owner}/${repo}/check-runs`\n : `${apiUrl}/repos/${owner}/${repo}/check-runs/${options.checkRunId}`;\n const response = await fetch(requestUrl, {\n method: options.checkRunId === undefined ? \"POST\" : \"PATCH\",\n headers: {\n accept: \"application/vnd.github+json\",\n authorization: `Bearer ${token}`,\n \"content-type\": \"application/json\",\n \"x-github-api-version\": \"2022-11-28\",\n },\n body: JSON.stringify(\n options.checkRunId === undefined\n ? {\n name: options.name ?? DEFAULT_CHECK_NAME,\n head_sha: sha,\n ...payload,\n }\n : payload,\n ),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(\n `GitHub Check Run request failed: ${response.status} ${response.statusText} ${text}`.trim(),\n );\n }\n\n const data = (await response.json()) as {\n id?: number;\n html_url?: string;\n };\n\n return {\n status: options.checkRunId === undefined ? \"created\" : \"updated\",\n id: data.id,\n htmlUrl: data.html_url,\n };\n}\n\nfunction buildCheckRunPayload(\n report: EvalReport,\n options: PublishCheckRunOptions,\n) {\n const gate = options.gate ?? evaluateEvalGate(report);\n const annotations = buildCheckAnnotations(report, {\n maxAnnotations: options.maxAnnotations,\n gate,\n });\n\n return {\n status: \"completed\",\n conclusion: gate.ok ? \"success\" : \"failure\",\n completed_at: new Date().toISOString(),\n output: {\n title: gate.title,\n summary: truncateCheckSummary(\n renderJobSummary(report, {\n ...options,\n maxFailures: options.maxFailures ?? 5,\n maxReasonChars: options.maxReasonChars ?? 4000,\n maxOutputChars: options.maxOutputChars ?? 2000,\n maxToolCalls: options.maxToolCalls ?? 10,\n gate,\n }),\n ),\n annotations,\n },\n };\n}\n\nfunction truncateCheckSummary(summary: string) {\n if (summary.length <= MAX_CHECK_SUMMARY_LENGTH) {\n return summary;\n }\n\n return `${summary\n .slice(0, MAX_CHECK_SUMMARY_LENGTH - CHECK_SUMMARY_TRUNCATION_SUFFIX.length)\n .trimEnd()}${CHECK_SUMMARY_TRUNCATION_SUFFIX}`;\n}\n","import type { EvalReport, UsageSummary } from \"./types\";\n\n/** Merges multiple collected eval reports into one combined report. */\nexport function mergeEvalReports(reports: EvalReport[]): EvalReport {\n const cases = reports.flatMap((report) => report.cases);\n const failures = reports.flatMap((report) => report.failures);\n const scoredCases = cases\n .map((testCase) => testCase.eval?.avgScore)\n .filter(\n (score): score is number =>\n typeof score === \"number\" && Number.isFinite(score),\n );\n const startedAtValues = reports\n .map((report) => report.startedAt)\n .filter(\n (startedAt): startedAt is number =>\n typeof startedAt === \"number\" && Number.isFinite(startedAt),\n );\n const startedAt =\n startedAtValues.length > 0 ? Math.min(...startedAtValues) : undefined;\n\n return {\n status: reports.some((report) => report.status === \"failed\")\n ? \"failed\"\n : \"passed\",\n startedAt,\n durationMs: mergeDuration(reports),\n totals: {\n total: sum(reports, (report) => report.totals.total),\n passed: sum(reports, (report) => report.totals.passed),\n failed: sum(reports, (report) => report.totals.failed),\n skipped: sum(reports, (report) => report.totals.skipped),\n evalTotal: sum(reports, (report) => report.totals.evalTotal),\n evalPassed: sum(reports, (report) => report.totals.evalPassed),\n evalFailed: sum(reports, (report) => report.totals.evalFailed),\n },\n score:\n scoredCases.length > 0\n ? {\n average:\n scoredCases.reduce((total, score) => total + score, 0) /\n scoredCases.length,\n minimum: Math.min(...scoredCases),\n }\n : undefined,\n usage: mergeUsage(reports.map((report) => report.usage)),\n cases,\n failures,\n };\n}\n\nfunction mergeUsage(usages: Array<Required<UsageSummary>>) {\n return {\n inputTokens: sum(usages, (usage) => usage.inputTokens),\n outputTokens: sum(usages, (usage) => usage.outputTokens),\n reasoningTokens: sum(usages, (usage) => usage.reasoningTokens),\n totalTokens: sum(usages, (usage) => usage.totalTokens),\n toolCalls: sum(usages, (usage) => usage.toolCalls),\n };\n}\n\nfunction mergeDuration(reports: EvalReport[]) {\n const durations = reports\n .map((report) => report.durationMs)\n .filter(\n (durationMs): durationMs is number =>\n typeof durationMs === \"number\" && Number.isFinite(durationMs),\n );\n const intervals = reports\n .map((report) => {\n if (\n typeof report.startedAt !== \"number\" ||\n !Number.isFinite(report.startedAt) ||\n typeof report.durationMs !== \"number\" ||\n !Number.isFinite(report.durationMs)\n ) {\n return undefined;\n }\n\n return {\n start: report.startedAt,\n end: report.startedAt + report.durationMs,\n };\n })\n .filter((interval): interval is { start: number; end: number } =>\n Boolean(interval),\n );\n\n if (intervals.length > 0 && intervals.length === durations.length) {\n return (\n Math.max(...intervals.map((interval) => interval.end)) -\n Math.min(...intervals.map((interval) => interval.start))\n );\n }\n\n return durations.length > 0\n ? durations.reduce((total, durationMs) => total + durationMs, 0)\n : undefined;\n}\n\nfunction sum<T>(items: T[], select: (item: T) => number) {\n return items.reduce((total, item) => total + select(item), 0);\n}\n","#!/usr/bin/env node\nimport { parseCliArgs } from \"./cli-options\";\nimport { publishEvalReport } from \"./report\";\nimport { escapeCommandData } from \"./utils\";\n\nmain().catch((error) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exitCode = 1;\n});\n\nasync function main() {\n const options = parseCliArgs(process.argv.slice(2));\n if (options.help) {\n console.log(usage());\n return;\n }\n\n const result = await publishEvalReport({\n resultPatterns: options.resultPatterns,\n cwd: options.workspace ?? process.env.GITHUB_WORKSPACE ?? process.cwd(),\n workspace:\n options.workspace ?? process.env.GITHUB_WORKSPACE ?? process.cwd(),\n summaryEnabled: options.summaryEnabled,\n summaryPath: options.summaryPath,\n annotations: options.annotations,\n checkRun: options.checkRun,\n checkRunId: options.checkRunId,\n checkName: options.checkName,\n failOnCheckError: options.failOnCheckError,\n failOnFailures: options.failOnFailures,\n minPassRate: options.minPassRate,\n minScoreAverage: options.minScoreAverage,\n maxAnnotations: options.maxAnnotations,\n maxFailures: options.maxFailures,\n repository: options.repository,\n sha: options.sha,\n token: options.token,\n warn,\n });\n\n if (result.shouldFail) {\n console.error(result.gate.message);\n process.exitCode = 1;\n }\n}\n\nfunction warn(message: string) {\n if (process.env.GITHUB_ACTIONS === \"true\") {\n console.log(`::warning::${escapeCommandData(message)}`);\n return;\n }\n console.error(`Warning: ${message}`);\n}\n\nfunction usage() {\n return [\n \"Usage: vitest-evals-github-report [vitest-results.json ...] [--json <path>]\",\n \"\",\n \"Options:\",\n \" --json <path> Read a Vitest JSON report from this path or glob\",\n \" --summary <path> Write job summary markdown to this path\",\n \" --no-summary Disable summary output\",\n \" --annotations Emit GitHub workflow-command annotations\",\n \" --no-annotations Disable workflow-command annotations\",\n \" --check-run Publish a GitHub Check Run when configured\",\n \" --fail-on-failures Exit non-zero when any eval case failed\",\n \" --min-pass-rate <0-1> Exit non-zero when eval pass rate is below this floor\",\n \" --min-score-average <0-1> Exit non-zero when average score is below this floor\",\n \" --fail-on-check-error Fail when Check Run publishing fails\",\n \" --check-run-id <id> Update an existing Check Run\",\n \" --check-name <name> Check Run name (default: vitest-evals)\",\n \" --token <token> GitHub token (default: GITHUB_TOKEN)\",\n \" --repo <owner/repo> GitHub repository (default: GITHUB_REPOSITORY)\",\n \" --sha <sha> Git commit SHA (default: GITHUB_SHA)\",\n \" --workspace <path> Workspace path for relative annotation files\",\n \" --max-annotations <n> Maximum annotations to emit\",\n \" --max-failures <n> Maximum failures to include in details\",\n ].join(\"\\n\");\n}\n"],"mappings":"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","names":["usage","score","usage","formatToolCallStatus","startedAt","usage"]}
1
+ {"version":3,"sources":["../src/cli-options.ts","../src/report.ts","../src/utils.ts","../src/annotations.ts","../src/collect.ts","../src/gate.ts","../src/github.ts","../src/summary.ts","../src/merge.ts","../src/cli.ts"],"sourcesContent":["export type CliOptions = {\n resultPatterns: string[];\n summaryPath?: string;\n summaryEnabled: boolean;\n annotations: boolean;\n checkRun: boolean;\n failOnFailures: boolean;\n failOnCheckError: boolean;\n softFail?: boolean;\n minPassRate?: number;\n minScoreAverage?: number;\n maxAnnotations?: number;\n maxFailures?: number;\n checkRunId?: number;\n checkName?: string;\n token?: string;\n repository?: string;\n sha?: string;\n workspace?: string;\n help: boolean;\n};\n\ntype MutableCliOptions = Omit<CliOptions, \"resultPatterns\"> & {\n resultPatterns: string[];\n};\n\n/** Parses GitHub reporter CLI arguments, with explicit arguments taking precedence over environment defaults. */\nexport function parseCliArgs(\n args: string[],\n env: NodeJS.ProcessEnv = process.env,\n): CliOptions {\n const options: MutableCliOptions = {\n summaryPath: env.GITHUB_STEP_SUMMARY,\n summaryEnabled: true,\n annotations: env.GITHUB_ACTIONS === \"true\",\n checkRun: false,\n failOnFailures: false,\n failOnCheckError: false,\n resultPatterns: [],\n help: false,\n };\n\n for (let index = 0; index < args.length; index += 1) {\n const arg = args[index];\n switch (arg) {\n case \"--json\":\n options.resultPatterns.push(readValue(args, ++index, arg));\n break;\n case \"--summary\":\n options.summaryPath = readValue(args, ++index, arg);\n options.summaryEnabled = true;\n break;\n case \"--no-summary\":\n options.summaryEnabled = false;\n break;\n case \"--annotations\":\n options.annotations = true;\n break;\n case \"--no-annotations\":\n options.annotations = false;\n break;\n case \"--check-run\":\n options.checkRun = true;\n break;\n case \"--fail-on-failures\":\n options.failOnFailures = true;\n break;\n case \"--fail-on-check-error\":\n options.failOnCheckError = true;\n break;\n case \"--soft-fail\":\n options.softFail = true;\n break;\n case \"--no-soft-fail\":\n options.softFail = false;\n break;\n case \"--min-pass-rate\":\n options.minPassRate = readRatio(args, ++index, arg);\n break;\n case \"--min-score-average\":\n options.minScoreAverage = readRatio(args, ++index, arg);\n break;\n case \"--max-annotations\":\n options.maxAnnotations = readInteger(args, ++index, arg);\n break;\n case \"--max-failures\":\n options.maxFailures = readInteger(args, ++index, arg);\n break;\n case \"--check-run-id\":\n options.checkRunId = readInteger(args, ++index, arg);\n options.checkRun = true;\n break;\n case \"--check-name\":\n options.checkName = readValue(args, ++index, arg);\n break;\n case \"--token\":\n options.token = readValue(args, ++index, arg);\n break;\n case \"--repo\":\n options.repository = readValue(args, ++index, arg);\n break;\n case \"--sha\":\n options.sha = readValue(args, ++index, arg);\n break;\n case \"--workspace\":\n options.workspace = readValue(args, ++index, arg);\n break;\n case \"--help\":\n case \"-h\":\n options.help = true;\n return withDefaultJsonPath(options, env);\n default:\n if (!arg.startsWith(\"-\")) {\n options.resultPatterns.push(arg);\n break;\n }\n throw new Error(`Unknown argument: ${arg}`);\n }\n }\n\n return withDefaultJsonPath(options, env);\n}\n\nfunction withDefaultJsonPath(\n options: MutableCliOptions,\n env: NodeJS.ProcessEnv,\n): CliOptions {\n return {\n ...options,\n resultPatterns:\n options.resultPatterns.length > 0\n ? options.resultPatterns\n : [env.VITEST_EVALS_JSON_REPORT || \"vitest-results.json\"],\n };\n}\n\nfunction readValue(args: string[], index: number, flag: string) {\n const value = args[index];\n if (!value) {\n throw new Error(`Missing value for ${flag}`);\n }\n return value;\n}\n\nfunction readInteger(args: string[], index: number, flag: string) {\n const rawValue = readValue(args, index, flag);\n if (!/^\\d+$/.test(rawValue)) {\n throw new Error(`Invalid integer for ${flag}`);\n }\n return Number(rawValue);\n}\n\nfunction readRatio(args: string[], index: number, flag: string) {\n const rawValue = readValue(args, index, flag);\n const parsed = Number(rawValue);\n if (!Number.isFinite(parsed) || parsed < 0 || parsed > 1) {\n throw new Error(`Invalid ratio for ${flag}`);\n }\n return parsed;\n}\n","import { appendFile } from \"node:fs/promises\";\nimport {\n readVitestJsonReportFile,\n resolveResultFiles,\n} from \"@vitest-evals/core/node\";\nimport { renderWorkflowCommands } from \"./annotations\";\nimport { collectEvalReport } from \"./collect\";\nimport {\n type EvalGatePolicy,\n type EvalGateResult,\n evaluateEvalGate,\n renderGateWorkflowCommand,\n} from \"./gate\";\nimport { type PublishCheckRunResult, publishCheckRun } from \"./github\";\nimport { mergeEvalReports } from \"./merge\";\nimport { type SummaryOptions, renderJobSummary } from \"./summary\";\nimport type { EvalReport } from \"./types\";\n\n/** Options for reading eval JSON files and publishing GitHub report surfaces. */\nexport type PublishEvalReportOptions = SummaryOptions &\n EvalGatePolicy & {\n resultPatterns: string[];\n cwd?: string;\n workspace?: string;\n summaryEnabled?: boolean;\n summaryPath?: string;\n annotations?: boolean;\n checkRun?: boolean;\n failOnCheckError?: boolean;\n /**\n * When true, keep the workflow step green on a failed gate so the Check\n * Run owns PR status instead of a canned job failure line. Defaults to\n * true only when a Check Run is actually published; if publishing is\n * skipped/fails, the step still exits non-zero on a failed gate.\n */\n softFail?: boolean;\n maxAnnotations?: number;\n checkRunId?: number;\n checkName?: string;\n token?: string;\n repository?: string;\n sha?: string;\n detailsUrl?: string;\n externalId?: string;\n warn?: (message: string) => void;\n };\n\n/** Result from publishing eval reports, including merged report data. */\nexport type PublishEvalReportResult = {\n report: EvalReport;\n resultFiles: string[];\n gate: EvalGateResult;\n /**\n * True when an enforced gate rejects the report and soft-fail did not keep\n * the step green. Advisory (ungated) runs never fail the step, matching\n * `fail-on-failures: false` defaults.\n */\n shouldFail: boolean;\n checkRun?: PublishCheckRunResult;\n};\n\n/** Reads, merges, and publishes eval reports to GitHub Actions surfaces. */\nexport async function publishEvalReport(\n options: PublishEvalReportOptions,\n): Promise<PublishEvalReportResult> {\n const resultFiles = await resolveResultFiles(options.resultPatterns, {\n cwd: options.cwd,\n });\n if (resultFiles.length === 0) {\n throw new Error(\n `No eval result files matched: ${options.resultPatterns.join(\", \")}`,\n );\n }\n\n const reports = await Promise.all(\n resultFiles.map(async (resultFile) => {\n const json = await readVitestJsonReportFile(resultFile);\n return collectEvalReport(json, {\n workspace: options.workspace,\n });\n }),\n );\n const report = mergeEvalReports(reports);\n const gate = evaluateEvalGate(report, {\n failOnFailures: options.failOnFailures,\n minPassRate: options.minPassRate,\n minScoreAverage: options.minScoreAverage,\n });\n const summary = renderJobSummary(report, {\n maxFailures: options.maxFailures,\n maxOutputChars: options.maxOutputChars,\n maxReasonChars: options.maxReasonChars,\n maxToolCalls: options.maxToolCalls,\n gate,\n });\n\n if (options.summaryEnabled !== false) {\n if (options.summaryPath) {\n await appendFile(options.summaryPath, `${summary}\\n`);\n } else {\n console.log(summary);\n }\n }\n\n if (options.annotations) {\n const gateCommand = renderGateWorkflowCommand(gate);\n if (gateCommand) {\n console.log(gateCommand);\n }\n for (const command of renderWorkflowCommands(report, {\n maxAnnotations: options.maxAnnotations,\n gate,\n })) {\n console.log(command);\n }\n }\n\n let checkRun: PublishCheckRunResult | undefined;\n if (options.checkRun) {\n try {\n checkRun = await publishCheckRun(report, {\n checkRunId: options.checkRunId,\n maxAnnotations: options.maxAnnotations,\n maxFailures: options.maxFailures,\n maxOutputChars: options.maxOutputChars,\n maxReasonChars: options.maxReasonChars,\n maxToolCalls: options.maxToolCalls,\n name: options.checkName,\n repository: options.repository,\n sha: options.sha,\n detailsUrl: options.detailsUrl,\n externalId: options.externalId,\n token: options.token,\n gate,\n });\n\n if (checkRun.status === \"skipped\") {\n options.warn?.(`GitHub Check Run skipped: ${checkRun.reason}`);\n } else if (checkRun.htmlUrl) {\n console.log(`published check run: ${checkRun.htmlUrl}`);\n } else if (checkRun.id !== undefined) {\n console.log(`published check run id: ${checkRun.id}`);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (options.failOnCheckError) {\n throw error;\n }\n options.warn?.(message);\n }\n }\n\n const gateFailed = gate.enforced && !gate.ok;\n // Soft-fail only when a Check Run actually published. Explicit soft-fail:true\n // still requires a published check so a failed gate cannot go silent.\n const wantsSoftFail = options.softFail ?? options.checkRun === true;\n const softFail = wantsSoftFail && checkRunPublished(checkRun);\n const shouldFail = gateFailed && !softFail;\n\n return {\n report,\n resultFiles,\n gate,\n shouldFail,\n checkRun,\n };\n}\n\nfunction checkRunPublished(checkRun: PublishCheckRunResult | undefined) {\n return checkRun?.status === \"created\" || checkRun?.status === \"updated\";\n}\n","import { posix } from \"node:path\";\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function compactLine(value: string, maxLength: number) {\n const line = value\n .split(/\\r?\\n/)\n .map((part) => part.trim())\n .find((part) => part.length > 0);\n if (!line) {\n return \"\";\n }\n return truncate(line, maxLength);\n}\n\nexport function truncate(value: string, maxLength: number) {\n if (maxLength <= 0) {\n return \"\";\n }\n if (value.length <= maxLength) {\n return value;\n }\n return `${value.slice(0, Math.max(0, maxLength - 15)).trimEnd()}... [truncated]`;\n}\n\nexport function stringifyValue(value: unknown, maxLength: number) {\n if (value === undefined) {\n return \"\";\n }\n if (typeof value === \"string\") {\n return truncate(value, maxLength);\n }\n try {\n return truncate(JSON.stringify(value, null, 2), maxLength);\n } catch {\n return truncate(String(value), maxLength);\n }\n}\n\nexport function formatNumber(value: number) {\n return new Intl.NumberFormat(\"en-US\", {\n maximumFractionDigits: 0,\n }).format(value);\n}\n\nexport function formatScore(value: number | null | undefined) {\n if (value == null || !Number.isFinite(value)) {\n return \"n/a\";\n }\n return value.toFixed(2);\n}\n\nexport function formatDuration(ms: number | undefined) {\n if (ms === undefined || !Number.isFinite(ms)) {\n return \"n/a\";\n }\n if (ms < 1000) {\n return `${Math.round(ms)}ms`;\n }\n const seconds = ms / 1000;\n if (seconds < 60) {\n return `${seconds.toFixed(seconds < 10 ? 1 : 0)}s`;\n }\n const totalSeconds = Math.round(seconds);\n const minutes = Math.floor(totalSeconds / 60);\n const remainingSeconds = totalSeconds % 60;\n return `${minutes}m ${remainingSeconds}s`;\n}\n\nexport function formatLocation(\n file: string,\n location?: { line: number; column: number },\n) {\n if (!location) {\n return file;\n }\n return `${file}:${location.line}`;\n}\n\nexport function normalizePathForGitHub(path: string, workspace?: string) {\n const normalized = path.replace(/\\\\/g, \"/\");\n if (!workspace) {\n return normalized;\n }\n\n const workspacePath = workspace.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n if (\n normalized !== workspacePath &&\n !normalized.startsWith(`${workspacePath}/`)\n ) {\n return normalized;\n }\n\n return posix.relative(workspacePath, normalized);\n}\n\nexport function escapeFence(value: string) {\n return value.replace(/```/g, \"'''\");\n}\n\nexport function escapeHtml(value: string) {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\n}\n\nexport function escapeCommandData(value: string) {\n return value.replace(/%/g, \"%25\").replace(/\\r/g, \"%0D\").replace(/\\n/g, \"%0A\");\n}\n\nexport function escapeCommandProperty(value: string) {\n return escapeCommandData(value).replace(/:/g, \"%3A\").replace(/,/g, \"%2C\");\n}\n","import type { EvalGateResult } from \"./gate\";\nimport type { EvalCase, EvalReport, ToolCallSummary } from \"./types\";\nimport {\n compactLine,\n escapeCommandData,\n escapeCommandProperty,\n formatScore,\n stringifyValue,\n truncate,\n} from \"./utils\";\n\n/** Options for limiting rendered GitHub annotations. */\nexport type AnnotationOptions = {\n maxAnnotations?: number;\n /**\n * Suite gate decision. When the gate passed, quality misses are demoted to\n * warnings so a green score-gated check is not flooded with red failures.\n */\n gate?: EvalGateResult;\n};\n\n/** GitHub Check Run annotation payload. */\nexport type CheckAnnotation = {\n path: string;\n start_line: number;\n end_line: number;\n annotation_level: \"failure\" | \"warning\" | \"notice\";\n message: string;\n title?: string;\n raw_details?: string;\n};\n\nconst DEFAULT_MAX_WORKFLOW_ANNOTATIONS = 10;\nconst DEFAULT_MAX_CHECK_ANNOTATIONS = 50;\nconst MAX_CHECK_FIELD_LENGTH = 64_000;\n\ntype AnnotatedEvalCase = EvalCase & {\n location: { line: number; column: number };\n};\n\n/** Renders GitHub workflow-command annotations for failed eval cases. */\nexport function renderWorkflowCommands(\n report: EvalReport,\n options: AnnotationOptions = {},\n) {\n const maxAnnotations =\n options.maxAnnotations ?? DEFAULT_MAX_WORKFLOW_ANNOTATIONS;\n const command = caseAnnotationCommand(options.gate);\n\n return report.failures\n .filter(hasAnnotationLocation)\n .slice(0, maxAnnotations)\n .map((testCase) =>\n formatWorkflowCommand({\n command,\n properties: {\n file: testCase.displayFile,\n line: String(testCase.location.line),\n col: String(testCase.location.column),\n title: \"vitest-evals\",\n },\n message: formatWorkflowMessage(testCase),\n }),\n );\n}\n\n/** Builds Check Run annotations for failed eval cases. */\nexport function buildCheckAnnotations(\n report: EvalReport,\n options: AnnotationOptions = {},\n): CheckAnnotation[] {\n const maxAnnotations = Math.min(\n options.maxAnnotations ?? DEFAULT_MAX_CHECK_ANNOTATIONS,\n DEFAULT_MAX_CHECK_ANNOTATIONS,\n );\n const annotationLevel = caseAnnotationLevel(options.gate);\n\n return report.failures\n .filter(hasAnnotationLocation)\n .slice(0, maxAnnotations)\n .map((testCase) => ({\n path: testCase.displayFile,\n start_line: testCase.location.line,\n end_line: testCase.location.line,\n annotation_level: annotationLevel,\n title: truncate(\n `${testCase.primaryFailure?.judgeName ?? \"vitest-evals\"} - ${testCase.displayName}`,\n 255,\n ),\n message: truncate(\n formatWorkflowMessage(testCase),\n MAX_CHECK_FIELD_LENGTH,\n ),\n raw_details: truncate(formatRawDetails(testCase), MAX_CHECK_FIELD_LENGTH),\n }));\n}\n\nfunction caseAnnotationCommand(\n gate: EvalGateResult | undefined,\n): \"error\" | \"warning\" {\n return gate?.ok ? \"warning\" : \"error\";\n}\n\nfunction caseAnnotationLevel(\n gate: EvalGateResult | undefined,\n): \"failure\" | \"warning\" {\n return gate?.ok ? \"warning\" : \"failure\";\n}\n\nfunction hasAnnotationLocation(\n testCase: EvalCase,\n): testCase is AnnotatedEvalCase {\n return Boolean(testCase.location);\n}\n\nfunction formatWorkflowMessage(testCase: EvalCase) {\n const failure = testCase.primaryFailure;\n const parts = [\n testCase.displayName,\n `score ${formatScore(failure?.score ?? testCase.eval?.avgScore)}`,\n ];\n\n if (failure?.judgeName) {\n parts.push(failure.judgeName);\n }\n\n const reason = compactLine(failure?.reason ?? \"\", 320);\n if (reason) {\n parts.push(reason);\n }\n\n return parts.join(\" - \");\n}\n\nfunction formatRawDetails(testCase: AnnotatedEvalCase) {\n const lines = [\n `Test: ${testCase.displayName}`,\n `Location: ${testCase.displayFile}:${testCase.location.line}`,\n `Harness: ${testCase.harness?.name ?? \"n/a\"}`,\n `Score: ${formatScore(testCase.primaryFailure?.score ?? testCase.eval?.avgScore)}`,\n `Judge: ${testCase.primaryFailure?.judgeName ?? \"n/a\"}`,\n \"\",\n \"Reason:\",\n testCase.primaryFailure?.reason ?? \"n/a\",\n ];\n\n const finalOutput = testCase.eval?.output ?? testCase.harness?.output;\n if (finalOutput !== undefined) {\n lines.push(\"\", \"Final:\", stringifyValue(finalOutput, 8000));\n }\n\n if (testCase.toolCalls.length) {\n lines.push(\"\", \"Tools:\");\n for (const toolCall of testCase.toolCalls) {\n lines.push(`- ${toolCall.name}: ${formatToolCallStatus(toolCall)}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction formatToolCallStatus(toolCall: ToolCallSummary) {\n if (toolCall.status === \"pending\") {\n return \"pending\";\n }\n\n if (toolCall.status === \"error\") {\n return `error: ${toolCall.error ?? \"unknown error\"}`;\n }\n\n return \"ok\";\n}\n\nfunction formatWorkflowCommand({\n command,\n properties,\n message,\n}: {\n command: \"error\" | \"warning\" | \"notice\";\n properties: Record<string, string>;\n message: string;\n}) {\n const renderedProperties = Object.entries(properties)\n .map(([key, value]) => `${key}=${escapeCommandProperty(value)}`)\n .join(\",\");\n return `::${command} ${renderedProperties}::${escapeCommandData(message)}`;\n}\n","import {\n type HarnessRun,\n type ReportCase,\n type ToolCall,\n type TranscriptToolCallEvent,\n type TranscriptToolResultEvent,\n collectReportWorkspace,\n} from \"@vitest-evals/core\";\nimport type {\n CollectOptions,\n EvalCase,\n EvalFailure,\n EvalReport,\n EvalScore,\n ToolCallSummary,\n UsageSummary,\n VitestJsonReport,\n} from \"./types\";\nimport { compactLine, stringifyValue } from \"./utils\";\n\n/** Converts a Vitest JSON report into the compact eval report model. */\nexport function collectEvalReport(\n input: VitestJsonReport,\n options: CollectOptions = {},\n): EvalReport {\n const workspace = collectReportWorkspace(\n {\n report: input,\n },\n {\n workspace: options.workspace,\n },\n );\n const cases = workspace.cases.map(collectEvalCase);\n const failures = cases.filter((testCase) => testCase.status === \"failed\");\n const evalScores = cases\n .map((testCase) => testCase.eval?.avgScore)\n .filter((score): score is number => isFiniteNumber(score));\n const usage = sumUsage(cases);\n const durationMs = workspace.runs[0]?.durationMs;\n\n return {\n status: input.success && failures.length === 0 ? \"passed\" : \"failed\",\n startedAt: input.startTime,\n durationMs,\n totals: {\n total: input.numTotalTests,\n passed: input.numPassedTests,\n failed: input.numFailedTests,\n skipped: input.numPendingTests + input.numTodoTests,\n evalTotal: cases.length,\n evalPassed: cases.filter((testCase) => testCase.status === \"passed\")\n .length,\n evalFailed: failures.length,\n },\n score:\n evalScores.length > 0\n ? {\n average:\n evalScores.reduce((total, score) => total + score, 0) /\n evalScores.length,\n minimum: Math.min(...evalScores),\n }\n : undefined,\n usage,\n cases,\n failures,\n };\n}\n\nfunction collectEvalCase(reportCase: ReportCase): EvalCase {\n const scores = (reportCase.eval?.scores ?? []).map(normalizeScore);\n const harnessRun = reportCase.harness?.run;\n const toolCalls = collectToolCalls(reportCase);\n const evalCase: EvalCase = {\n id: reportCase.id,\n file: reportCase.file,\n displayFile: reportCase.displayFile,\n title: reportCase.title,\n displayName: reportCase.displayName,\n status: reportCase.status,\n durationMs: numberField(reportCase.durationMs),\n location: reportCase.location,\n failureMessages: reportCase.failureMessages,\n toolCalls,\n eval: reportCase.eval\n ? {\n avgScore: numberField(reportCase.eval.avgScore),\n thresholdFailed: reportCase.eval.thresholdFailed,\n output: reportCase.eval.output,\n scores,\n }\n : undefined,\n harness: reportCase.harness\n ? {\n name: reportCase.harness.name,\n output: harnessRun?.output,\n usage: harnessRun?.usage,\n timingMs: harnessRun?.timings?.totalMs,\n toolCalls,\n errors: harnessRun?.errors ?? [],\n }\n : undefined,\n };\n\n evalCase.primaryFailure = getPrimaryFailure(evalCase);\n return evalCase;\n}\n\nfunction normalizeScore(score: EvalScore): EvalScore {\n return {\n ...score,\n score: numberField(score.score) ?? null,\n };\n}\n\nfunction numberField(value: unknown) {\n return isFiniteNumber(value) ? value : undefined;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction collectToolCalls(reportCase: ReportCase) {\n const harnessCalls = collectSessionToolCalls(\n reportCase.harness?.run?.session,\n );\n return harnessCalls.length > 0\n ? harnessCalls\n : (reportCase.eval?.toolCalls ?? []).map(toToolCallSummary);\n}\n\nfunction collectSessionToolCalls(session: HarnessRun[\"session\"] | undefined) {\n if (!session) {\n return [];\n }\n\n const resultsById = new Map<string, TranscriptToolResultEvent>();\n for (const event of session.events) {\n if (event.type === \"tool_result\" && !resultsById.has(event.toolCallId)) {\n resultsById.set(event.toolCallId, event);\n }\n }\n\n return session.events.flatMap((event) =>\n event.type === \"tool_call\"\n ? [toSessionToolCallSummary(event, resultsById.get(event.id))]\n : [],\n );\n}\n\nfunction toToolCallSummary(call: ToolCall): ToolCallSummary {\n return {\n name: call.name,\n status: call.status,\n error: call.status === \"error\" ? getToolCallError(call.error) : undefined,\n };\n}\n\nfunction toSessionToolCallSummary(\n call: TranscriptToolCallEvent,\n result: TranscriptToolResultEvent | undefined,\n): ToolCallSummary {\n if (!result) {\n return {\n name: call.name,\n status: \"pending\",\n ...(call.durationMs !== undefined ? { durationMs: call.durationMs } : {}),\n };\n }\n\n const durationMs = result.durationMs ?? call.durationMs;\n return {\n name: call.name,\n status: result.error ? \"error\" : \"ok\",\n ...(durationMs !== undefined ? { durationMs } : {}),\n ...(result.error ? { error: getToolCallError(result.error) } : {}),\n };\n}\n\nfunction getToolCallError(value: unknown) {\n const error = value as { message?: unknown };\n if (\n value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n typeof error.message === \"string\"\n ) {\n return error.message;\n }\n if (value !== undefined) {\n return stringifyValue(value, 240);\n }\n return undefined;\n}\n\nfunction getPrimaryFailure(testCase: EvalCase): EvalFailure | undefined {\n const failingScores = [...(testCase.eval?.scores ?? [])]\n .filter(\n (score) =>\n (score.score ?? 0) < 1 ||\n score.metadata?.rationale !== undefined ||\n score.metadata?.output !== undefined,\n )\n .sort((left, right) => (left.score ?? 0) - (right.score ?? 0));\n const primary = failingScores[0];\n const score =\n typeof primary?.score === \"number\"\n ? primary.score\n : testCase.eval?.avgScore;\n const reason =\n stringifyReason(primary?.metadata?.rationale) ??\n compactLine(testCase.failureMessages.join(\"\\n\"), 500);\n\n if (!primary && !reason && score === undefined) {\n return undefined;\n }\n\n return {\n judgeName: primary?.name,\n score,\n reason: reason || undefined,\n };\n}\n\nfunction stringifyReason(value: unknown) {\n if (value === undefined) {\n return undefined;\n }\n return typeof value === \"string\" ? value : stringifyValue(value, 4000);\n}\n\nfunction sumUsage(cases: EvalCase[]) {\n const usage: Required<UsageSummary> = {\n inputTokens: 0,\n outputTokens: 0,\n reasoningTokens: 0,\n totalTokens: 0,\n toolCalls: 0,\n };\n\n for (const testCase of cases) {\n const caseUsage = testCase.harness?.usage;\n usage.inputTokens += caseUsage?.inputTokens ?? 0;\n usage.outputTokens += caseUsage?.outputTokens ?? 0;\n usage.reasoningTokens += caseUsage?.reasoningTokens ?? 0;\n usage.totalTokens +=\n caseUsage?.totalTokens ??\n (caseUsage?.inputTokens ?? 0) +\n (caseUsage?.outputTokens ?? 0) +\n (caseUsage?.reasoningTokens ?? 0);\n usage.toolCalls += toolCallCount(testCase);\n }\n\n return usage;\n}\n\nfunction toolCallCount(testCase: EvalCase) {\n const usageToolCalls = testCase.harness?.usage?.toolCalls;\n if (usageToolCalls !== undefined) {\n return Math.max(usageToolCalls, testCase.toolCalls.length);\n }\n\n return testCase.toolCalls.length;\n}\n","import type { EvalReport } from \"./types\";\nimport {\n escapeCommandData,\n escapeCommandProperty,\n formatNumber,\n formatScore,\n} from \"./utils\";\n\n/** Optional floors and legacy fail-on-any-failure policy for a combined report. */\nexport type EvalGatePolicy = {\n /**\n * Minimum fraction of eval cases that must pass, in the range `[0, 1]`.\n * Example: `0.8` requires at least 80% of eval cases to pass.\n */\n minPassRate?: number;\n /**\n * Minimum average eval score across scored cases, in the range `[0, 1]`.\n */\n minScoreAverage?: number;\n /**\n * When true, require every eval case to pass. Equivalent to setting\n * `minPassRate` to `1`, and combined with an explicit floor by taking the\n * stricter value.\n */\n failOnFailures?: boolean;\n};\n\n/** Result of applying a gate policy to a combined eval report. */\nexport type EvalGateResult = {\n /** Whether the configured policy accepts this report. */\n ok: boolean;\n /** Compact status used by action outputs and summaries. */\n status: \"passed\" | \"failed\";\n /** True when any gate input was configured. */\n enforced: boolean;\n /** Eval pass rate when the report includes at least one eval case. */\n passRate: number | null;\n /** Short title for Check Runs and workflow annotations. */\n title: string;\n /** Longer explanation used in logs, summaries, and annotations. */\n message: string;\n};\n\n/**\n * Decide whether a combined eval report meets the configured CI gate.\n *\n * With no policy inputs, the result mirrors the report status and is not\n * treated as an enforced gate. With floors or `failOnFailures`, non-eval\n * failures and empty eval reports fail closed, and qualitative misses only\n * fail when they break the configured floors.\n */\nexport function evaluateEvalGate(\n report: EvalReport,\n policy: EvalGatePolicy = {},\n): EvalGateResult {\n const minPassRate = resolveMinPassRate(policy);\n const minScoreAverage = policy.minScoreAverage;\n const enforced =\n minPassRate !== undefined ||\n minScoreAverage !== undefined ||\n policy.failOnFailures === true;\n\n const passRate = computePassRate(report);\n const counts = formatEvalCounts(report, passRate);\n\n if (!enforced) {\n const ok = report.status === \"passed\";\n return {\n ok,\n status: ok ? \"passed\" : \"failed\",\n enforced: false,\n passRate,\n title: defaultCheckTitle(report),\n message: ok\n ? `eval report passed: ${counts}`\n : `eval report failed: ${counts}`,\n };\n }\n\n const nonEvalFailures = Math.max(\n 0,\n report.totals.failed - report.totals.evalFailed,\n );\n if (nonEvalFailures > 0) {\n return {\n ok: false,\n status: \"failed\",\n enforced: true,\n passRate,\n title: \"Eval report hard failure\",\n message: `${formatNumber(nonEvalFailures)} non-eval test failure${\n nonEvalFailures === 1 ? \"\" : \"s\"\n }; ${counts}`,\n };\n }\n\n if (report.totals.evalTotal === 0) {\n return {\n ok: false,\n status: \"failed\",\n enforced: true,\n passRate: null,\n title: \"Eval report hard failure\",\n message: \"no eval cases were reported\",\n };\n }\n\n // Preserve Vitest-level hard failures that did not produce counted test\n // failures (for example success:false with empty assertion results).\n if (\n report.status === \"failed\" &&\n report.totals.failed === 0 &&\n report.failures.length === 0\n ) {\n return {\n ok: false,\n status: \"failed\",\n enforced: true,\n passRate,\n title: \"Eval report hard failure\",\n message: `vitest run failed without counted test failures; ${counts}`,\n };\n }\n\n if (\n minPassRate !== undefined &&\n (passRate === null || passRate + Number.EPSILON < minPassRate)\n ) {\n return {\n ok: false,\n status: \"failed\",\n enforced: true,\n passRate,\n title: `Eval pass rate ${formatPercent(passRate)} — required ${formatPercent(minPassRate)}`,\n message: `eval pass rate below floor: ${counts}; required >= ${formatPercent(minPassRate)}`,\n };\n }\n\n if (minScoreAverage !== undefined) {\n const average = report.score?.average;\n if (average === undefined || !Number.isFinite(average)) {\n return {\n ok: false,\n status: \"failed\",\n enforced: true,\n passRate,\n title: \"Eval score gate failed\",\n message: `no score average available; required avg score >= ${formatScore(minScoreAverage)}`,\n };\n }\n if (average + Number.EPSILON < minScoreAverage) {\n return {\n ok: false,\n status: \"failed\",\n enforced: true,\n passRate,\n title: `Avg score ${formatScore(average)} — required ${formatScore(minScoreAverage)}`,\n message: `avg score below floor: ${counts}; required avg score >= ${formatScore(minScoreAverage)}`,\n };\n }\n }\n\n return {\n ok: true,\n status: \"passed\",\n enforced: true,\n passRate,\n title: enforcedPassTitle(report, passRate, minPassRate, minScoreAverage),\n message: `eval gate passed: ${counts}${formatFloorSuffix(minPassRate, minScoreAverage)}`,\n };\n}\n\n/** Compute the eval pass rate for a report, or null when there are no evals. */\nexport function computePassRate(report: EvalReport): number | null {\n if (report.totals.evalTotal <= 0) {\n return null;\n }\n return report.totals.evalPassed / report.totals.evalTotal;\n}\n\n/** Format a 0-1 ratio as a percentage with one decimal place. */\nexport function formatPercent(value: number | null | undefined) {\n if (value == null || !Number.isFinite(value)) {\n return \"n/a\";\n }\n return `${(value * 100).toFixed(1)}%`;\n}\n\n/** Build a suite-level workflow annotation for a failed enforced gate. */\nexport function renderGateWorkflowCommand(gate: EvalGateResult) {\n if (gate.ok || !gate.enforced) {\n return undefined;\n }\n return `::error title=${escapeCommandProperty(gate.title)}::${escapeCommandData(gate.message)}`;\n}\n\nfunction resolveMinPassRate(policy: EvalGatePolicy) {\n const configured = policy.minPassRate;\n if (policy.failOnFailures) {\n if (configured === undefined) {\n return 1;\n }\n return Math.max(configured, 1);\n }\n return configured;\n}\n\nfunction defaultCheckTitle(report: EvalReport) {\n if (report.failures.length === 0 && report.status === \"passed\") {\n return \"No eval failures\";\n }\n if (report.failures.length === 0) {\n return \"Vitest run failed\";\n }\n return `${report.failures.length} eval failure${\n report.failures.length === 1 ? \"\" : \"s\"\n }`;\n}\n\nfunction enforcedPassTitle(\n report: EvalReport,\n passRate: number | null,\n minPassRate: number | undefined,\n minScoreAverage: number | undefined,\n) {\n if (minPassRate !== undefined) {\n return `Eval pass rate ${formatPercent(passRate)} — floor ${formatPercent(minPassRate)}`;\n }\n if (minScoreAverage !== undefined) {\n return `Avg score ${formatScore(report.score?.average)} — floor ${formatScore(minScoreAverage)}`;\n }\n return defaultCheckTitle(report);\n}\n\nfunction formatEvalCounts(report: EvalReport, passRate: number | null) {\n const scoreText =\n report.score?.average === undefined\n ? \"n/a\"\n : formatScore(report.score.average);\n const passRateText = passRate === null ? \"n/a\" : formatPercent(passRate);\n return `${formatNumber(report.totals.evalPassed)}/${formatNumber(\n report.totals.evalTotal,\n )} passed (${passRateText}), avg score ${scoreText}`;\n}\n\nfunction formatFloorSuffix(\n minPassRate: number | undefined,\n minScoreAverage: number | undefined,\n) {\n const parts: string[] = [];\n if (minPassRate !== undefined) {\n parts.push(`pass rate floor ${formatPercent(minPassRate)}`);\n }\n if (minScoreAverage !== undefined) {\n parts.push(`avg score floor ${formatScore(minScoreAverage)}`);\n }\n return parts.length === 0 ? \"\" : `; ${parts.join(\", \")}`;\n}\n","import { readFileSync } from \"node:fs\";\nimport { buildCheckAnnotations } from \"./annotations\";\nimport { type EvalGateResult, evaluateEvalGate } from \"./gate\";\nimport { type SummaryOptions, renderJobSummary } from \"./summary\";\nimport type { EvalReport } from \"./types\";\n\n/** Options for creating or updating a GitHub Check Run. */\nexport type PublishCheckRunOptions = SummaryOptions & {\n token?: string;\n repository?: string;\n sha?: string;\n name?: string;\n apiUrl?: string;\n detailsUrl?: string;\n externalId?: string;\n checkRunId?: number;\n maxAnnotations?: number;\n /**\n * Suite gate decision. When omitted, the report is evaluated with the\n * default advisory policy so title/conclusion stay consistent.\n */\n gate?: EvalGateResult;\n};\n\n/** Result of attempting to publish a GitHub Check Run. */\nexport type PublishCheckRunResult =\n | {\n status: \"skipped\";\n reason: string;\n }\n | {\n status: \"created\" | \"updated\";\n id?: number;\n htmlUrl?: string;\n sha?: string;\n };\n\nconst DEFAULT_CHECK_NAME = \"vitest-evals\";\nconst MAX_CHECK_SUMMARY_LENGTH = 64_000;\nconst CHECK_SUMMARY_TRUNCATION_SUFFIX =\n \"\\n\\n[truncated for GitHub Check Run]\\n\";\n\n/**\n * Resolve the commit SHA a Check Run should attach to.\n *\n * On `pull_request`, `GITHUB_SHA` is the temporary merge commit. PR status and\n * required checks attach to the head commit, so prefer an explicit head SHA\n * (option/env or `pull_request.head.sha` from the event payload) first.\n */\nexport function resolveCheckSha(\n env: NodeJS.ProcessEnv = process.env,\n options: { sha?: string; eventPath?: string } = {},\n): string | undefined {\n const explicit = options.sha?.trim() || env.GITHUB_PR_HEAD_SHA?.trim();\n if (explicit) {\n return explicit;\n }\n\n const eventPath = options.eventPath?.trim() || env.GITHUB_EVENT_PATH?.trim();\n if (eventPath) {\n try {\n const event = JSON.parse(readFileSync(eventPath, \"utf8\")) as {\n pull_request?: { head?: { sha?: unknown } };\n };\n const headSha = event.pull_request?.head?.sha;\n if (typeof headSha === \"string\" && headSha.trim()) {\n return headSha.trim();\n }\n } catch {\n // Fall through to GITHUB_SHA when the event payload is unavailable.\n }\n }\n\n return env.GITHUB_SHA?.trim() || undefined;\n}\n\n/**\n * Build a Check Run details URL that points back at the current workflow job\n * (or run) when GitHub Actions env is present.\n */\nexport function resolveCheckDetailsUrl(\n env: NodeJS.ProcessEnv = process.env,\n options: { detailsUrl?: string } = {},\n): string | undefined {\n const explicit = options.detailsUrl?.trim();\n if (explicit) {\n return explicit;\n }\n\n const server = env.GITHUB_SERVER_URL?.replace(/\\/$/, \"\");\n const repository = env.GITHUB_REPOSITORY?.trim();\n const runId = env.GITHUB_RUN_ID?.trim();\n if (!server || !repository || !runId) {\n return undefined;\n }\n\n // GITHUB_JOB is the job id/key, not the numeric job database id, so link the\n // run page. Consumers can override with an explicit details URL when needed.\n return `${server}/${repository}/actions/runs/${runId}`;\n}\n\n/** Publishes the eval report to a GitHub Check Run when configuration allows it. */\nexport async function publishCheckRun(\n report: EvalReport,\n options: PublishCheckRunOptions = {},\n): Promise<PublishCheckRunResult> {\n const token = options.token ?? process.env.GITHUB_TOKEN;\n const repository = options.repository ?? process.env.GITHUB_REPOSITORY;\n const sha = resolveCheckSha(process.env, { sha: options.sha });\n const detailsUrl = resolveCheckDetailsUrl(process.env, {\n detailsUrl: options.detailsUrl,\n });\n\n if (!token) {\n return { status: \"skipped\", reason: \"missing GITHUB_TOKEN\" };\n }\n if (!repository) {\n return { status: \"skipped\", reason: \"missing GITHUB_REPOSITORY\" };\n }\n if (!sha && options.checkRunId === undefined) {\n return {\n status: \"skipped\",\n reason:\n \"missing commit SHA (set --sha / options.sha, GITHUB_PR_HEAD_SHA, pull_request.head.sha, or GITHUB_SHA)\",\n };\n }\n\n const [owner, repo] = repository.split(\"/\");\n if (!owner || !repo) {\n return {\n status: \"skipped\",\n reason: `invalid GitHub repository: ${repository}`,\n };\n }\n\n const payload = buildCheckRunPayload(report, options, detailsUrl);\n const apiUrl =\n options.apiUrl ?? process.env.GITHUB_API_URL ?? \"https://api.github.com\";\n const requestUrl =\n options.checkRunId === undefined\n ? `${apiUrl}/repos/${owner}/${repo}/check-runs`\n : `${apiUrl}/repos/${owner}/${repo}/check-runs/${options.checkRunId}`;\n const response = await fetch(requestUrl, {\n method: options.checkRunId === undefined ? \"POST\" : \"PATCH\",\n headers: {\n accept: \"application/vnd.github+json\",\n authorization: `Bearer ${token}`,\n \"content-type\": \"application/json\",\n \"x-github-api-version\": \"2022-11-28\",\n },\n body: JSON.stringify(\n options.checkRunId === undefined\n ? {\n name: options.name ?? DEFAULT_CHECK_NAME,\n head_sha: sha,\n ...(options.externalId ? { external_id: options.externalId } : {}),\n ...payload,\n }\n : payload,\n ),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(\n `GitHub Check Run request failed: ${response.status} ${response.statusText} ${text}`.trim(),\n );\n }\n\n const data = (await response.json()) as {\n id?: number;\n html_url?: string;\n };\n\n return {\n status: options.checkRunId === undefined ? \"created\" : \"updated\",\n id: data.id,\n htmlUrl: data.html_url,\n sha,\n };\n}\n\nfunction buildCheckRunPayload(\n report: EvalReport,\n options: PublishCheckRunOptions,\n detailsUrl?: string,\n) {\n const gate = options.gate ?? evaluateEvalGate(report);\n const annotations = buildCheckAnnotations(report, {\n maxAnnotations: options.maxAnnotations,\n gate,\n });\n\n return {\n status: \"completed\",\n conclusion: gate.ok ? \"success\" : \"failure\",\n completed_at: new Date().toISOString(),\n ...(detailsUrl ? { details_url: detailsUrl } : {}),\n output: {\n title: gate.title,\n summary: truncateCheckSummary(\n renderJobSummary(report, {\n ...options,\n maxFailures: options.maxFailures ?? 5,\n maxReasonChars: options.maxReasonChars ?? 4000,\n maxOutputChars: options.maxOutputChars ?? 2000,\n maxToolCalls: options.maxToolCalls ?? 10,\n gate,\n }),\n ),\n annotations,\n },\n };\n}\n\nfunction truncateCheckSummary(summary: string) {\n if (summary.length <= MAX_CHECK_SUMMARY_LENGTH) {\n return summary;\n }\n\n return `${summary\n .slice(0, MAX_CHECK_SUMMARY_LENGTH - CHECK_SUMMARY_TRUNCATION_SUFFIX.length)\n .trimEnd()}${CHECK_SUMMARY_TRUNCATION_SUFFIX}`;\n}\n","import type { EvalGateResult } from \"./gate\";\nimport { formatPercent } from \"./gate\";\nimport type { EvalCase, EvalReport, ToolCallSummary } from \"./types\";\nimport {\n compactLine,\n escapeFence,\n escapeHtml,\n formatDuration,\n formatLocation,\n formatNumber,\n formatScore,\n stringifyValue,\n truncate,\n} from \"./utils\";\n\n/** Options for rendering GitHub Actions summary markdown. */\nexport type SummaryOptions = {\n maxFailures?: number;\n maxReasonChars?: number;\n maxOutputChars?: number;\n maxToolCalls?: number;\n gate?: EvalGateResult;\n};\n\nconst DEFAULT_MAX_FAILURES = 20;\nconst DEFAULT_MAX_REASON_CHARS = 8000;\nconst DEFAULT_MAX_OUTPUT_CHARS = 4000;\nconst DEFAULT_MAX_TOOL_CALLS = 20;\nconst SCORE_DISTRIBUTION_BUCKETS = [\n \"0-19%\",\n \"20-39%\",\n \"40-59%\",\n \"60-79%\",\n \"80-100%\",\n] as const;\nconst SCORE_DISTRIBUTION_BAR_WIDTH = 20;\n\n/** Renders the GitHub Actions job summary markdown for an eval report. */\nexport function renderJobSummary(\n report: EvalReport,\n options: SummaryOptions = {},\n) {\n const maxFailures = options.maxFailures ?? DEFAULT_MAX_FAILURES;\n const failures = report.failures.slice(0, maxFailures);\n const nonEvalFailures = report.totals.failed - report.totals.evalFailed;\n const lines: string[] = [\n \"# vitest-evals\",\n \"\",\n ...renderSummaryTable(report, nonEvalFailures, options.gate),\n \"\",\n ...renderScoreDistribution(report),\n \"## Results\",\n \"\",\n ];\n\n if (report.failures.length > 0) {\n const failureHeading =\n options.gate?.ok === true ? \"### Quality Misses\" : \"### Failures\";\n lines.push(failureHeading, \"\");\n failures.forEach((testCase, index) => {\n lines.push(...renderFailureDetails(testCase, index + 1, options), \"\");\n });\n\n if (report.failures.length > failures.length) {\n const omittedLabel =\n options.gate?.ok === true ? \"quality misses\" : \"failures\";\n lines.push(\n `${report.failures.length - failures.length} more ${omittedLabel} omitted from this summary.`,\n \"\",\n );\n }\n } else if (report.totals.evalTotal > 0) {\n lines.push(\"### Failures\", \"\", \"No eval failures.\", \"\");\n }\n\n if (report.totals.evalTotal === 0) {\n lines.push(\"No eval metadata was found in the Vitest JSON report.\", \"\");\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction formatCountLine(passed: number, failed: number, total: number) {\n return `${formatNumber(passed)} passed, ${formatNumber(failed)} failed, ${formatNumber(total)} total`;\n}\n\nfunction renderSummaryTable(\n report: EvalReport,\n nonEvalFailures: number,\n gate?: EvalGateResult,\n) {\n const rows: Array<[string, string]> = [\n [\"Status\", gate?.status ?? report.status],\n [\n \"Evals\",\n formatCountLine(\n report.totals.evalPassed,\n report.totals.evalFailed,\n report.totals.evalTotal,\n ),\n ],\n ];\n\n if (gate?.passRate !== undefined && gate.passRate !== null) {\n rows.push([\"Pass Rate\", formatPercent(gate.passRate)]);\n } else if (report.totals.evalTotal > 0) {\n rows.push([\n \"Pass Rate\",\n formatPercent(report.totals.evalPassed / report.totals.evalTotal),\n ]);\n }\n\n if (report.score) {\n rows.push([\"Score\", formatScoreSummary(report.score)]);\n }\n\n if (gate?.enforced) {\n rows.push([\"Gate\", gate.message]);\n }\n\n if (nonEvalFailures > 0) {\n rows.push([\n \"Other Failures\",\n `${formatNumber(nonEvalFailures)} non-eval test failure${\n nonEvalFailures === 1 ? \"\" : \"s\"\n }`,\n ]);\n }\n\n rows.push([\"Duration\", formatDuration(report.durationMs)]);\n\n return [\n \"| Metric | Value |\",\n \"| --- | --- |\",\n ...rows.map(\n ([metric, value]) =>\n `| ${escapeTableCell(metric)} | ${escapeTableCell(value)} |`,\n ),\n ];\n}\n\nfunction formatScoreSummary(score: NonNullable<EvalReport[\"score\"]>) {\n return `avg ${formatScore(score.average)}${\n score.minimum === undefined ? \"\" : `, min ${formatScore(score.minimum)}`\n }`;\n}\n\nfunction escapeTableCell(value: string) {\n return value\n .replace(/\\r?\\n/g, \" \")\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/\\|/g, \"\\\\|\");\n}\n\nfunction renderScoreDistribution(report: EvalReport) {\n const scores = report.cases\n .map((testCase) => testCase.eval?.avgScore)\n .filter(\n (score): score is number =>\n typeof score === \"number\" && Number.isFinite(score),\n );\n if (scores.length === 0) {\n return [];\n }\n\n const counts = SCORE_DISTRIBUTION_BUCKETS.map(() => 0);\n for (const score of scores) {\n const bucket = Math.min(\n SCORE_DISTRIBUTION_BUCKETS.length - 1,\n Math.max(0, Math.floor(score * SCORE_DISTRIBUTION_BUCKETS.length)),\n );\n counts[bucket] = (counts[bucket] ?? 0) + 1;\n }\n\n const maxCount = Math.max(...counts);\n return [\n \"## Scores\",\n \"\",\n \"```text\",\n ...SCORE_DISTRIBUTION_BUCKETS.map((label, index) =>\n formatScoreDistributionBucket(label, counts[index] ?? 0, maxCount),\n ),\n \"```\",\n \"\",\n ];\n}\n\nfunction formatScoreDistributionBucket(\n label: string,\n count: number,\n maxCount: number,\n) {\n const barLength =\n count === 0\n ? 0\n : Math.max(\n 1,\n Math.round((count / maxCount) * SCORE_DISTRIBUTION_BAR_WIDTH),\n );\n const bar = \"#\".repeat(barLength).padEnd(SCORE_DISTRIBUTION_BAR_WIDTH, \" \");\n return `${label.padEnd(7)} | ${bar} ${formatNumber(count)}`;\n}\n\nfunction renderFailureDetails(\n testCase: EvalCase,\n number: number,\n options: SummaryOptions,\n) {\n const failure = testCase.primaryFailure;\n const maxReasonChars = options.maxReasonChars ?? DEFAULT_MAX_REASON_CHARS;\n const maxOutputChars = options.maxOutputChars ?? DEFAULT_MAX_OUTPUT_CHARS;\n const maxToolCalls = options.maxToolCalls ?? DEFAULT_MAX_TOOL_CALLS;\n const usage = formatCaseUsage(testCase);\n const finalOutput = testCase.eval?.output ?? testCase.harness?.output;\n const summary = `${number}. ${testCase.displayName} - ${\n failure?.judgeName ?? \"failure\"\n } - ${formatScore(failure?.score ?? testCase.eval?.avgScore)}`;\n const lines = [\n \"<details>\",\n `<summary>${escapeHtml(summary)}</summary>`,\n \"\",\n \"```text\",\n ...renderFailureBlock(testCase, {\n finalOutput,\n maxOutputChars,\n maxReasonChars,\n maxToolCalls,\n number,\n usage,\n }).map(escapeFence),\n \"```\",\n \"\",\n \"</details>\",\n ];\n return lines;\n}\n\nfunction renderFailureBlock(\n testCase: EvalCase,\n {\n finalOutput,\n maxOutputChars,\n maxReasonChars,\n maxToolCalls,\n number,\n usage,\n }: {\n finalOutput: unknown;\n maxOutputChars: number;\n maxReasonChars: number;\n maxToolCalls: number;\n number: number;\n usage: string;\n },\n) {\n const failure = testCase.primaryFailure;\n const overviewRows: Array<[string, string]> = [\n [\"Case\", `${number}. ${testCase.displayName}`],\n [\"Status\", testCase.status],\n [\"Location\", formatLocation(testCase.displayFile, testCase.location)],\n [\"Harness\", testCase.harness?.name ?? \"n/a\"],\n [\"Score\", formatScore(failure?.score ?? testCase.eval?.avgScore)],\n [\"Judge\", failure?.judgeName ?? \"n/a\"],\n ];\n if (usage) {\n overviewRows.push([\"Usage\", usage]);\n }\n if (testCase.durationMs !== undefined) {\n overviewRows.push([\"Duration\", formatDuration(testCase.durationMs)]);\n }\n\n const lines = [\n ...renderAsciiSection(\"Result\", renderKeyValues(overviewRows)),\n \"\",\n ];\n\n if (failure?.reason) {\n lines.push(\n ...renderAsciiSection(\n \"Reason\",\n truncate(failure.reason, maxReasonChars).split(/\\r?\\n/),\n ),\n \"\",\n );\n }\n\n if (testCase.eval?.scores.length) {\n lines.push(\n ...renderAsciiTable(\n [\"Judge\", \"Score\"],\n testCase.eval.scores.map((score) => [\n score.name ?? \"Unknown\",\n formatScore(score.score),\n ]),\n ),\n \"\",\n );\n }\n\n if (finalOutput !== undefined) {\n lines.push(\n ...renderAsciiSection(\n \"Final Output\",\n stringifyValue(finalOutput, maxOutputChars).split(/\\r?\\n/),\n ),\n \"\",\n );\n }\n\n if (testCase.toolCalls.length) {\n const toolCalls = testCase.toolCalls.slice(0, maxToolCalls);\n lines.push(\n ...renderAsciiTable(\n [\"Tool\", \"Status\", \"Duration\"],\n toolCalls.map((toolCall) => [\n toolCall.name,\n formatToolCallStatus(toolCall),\n toolCall.durationMs === undefined\n ? \"n/a\"\n : formatDuration(toolCall.durationMs),\n ]),\n ),\n );\n if (testCase.toolCalls.length > maxToolCalls) {\n lines.push(\n `${testCase.toolCalls.length - maxToolCalls} more tool calls omitted`,\n );\n }\n lines.push(\"\");\n }\n\n if (testCase.harness?.errors.length) {\n lines.push(\n ...renderAsciiSection(\n \"Harness Errors\",\n stringifyValue(testCase.harness.errors, maxReasonChars).split(/\\r?\\n/),\n ),\n \"\",\n );\n }\n\n while (lines[lines.length - 1] === \"\") {\n lines.pop();\n }\n return lines;\n}\n\nfunction formatToolCallStatus(toolCall: ToolCallSummary) {\n if (toolCall.status === \"pending\") {\n return \"pending\";\n }\n\n if (toolCall.status === \"error\") {\n return `error: ${compactLine(toolCall.error ?? \"unknown error\", 120)}`;\n }\n\n return \"ok\";\n}\n\nfunction renderAsciiSection(title: string, content: string[]) {\n return [title, \"-\".repeat(title.length), ...content];\n}\n\nfunction renderKeyValues(rows: Array<[string, string]>) {\n const labelWidth = Math.max(...rows.map(([label]) => label.length));\n return rows.map(\n ([label, value]) =>\n `${label.padEnd(labelWidth)} ${compactLine(value, 500)}`,\n );\n}\n\nfunction renderAsciiTable(headers: string[], rows: string[][]) {\n const widths = headers.map((header, index) =>\n Math.max(header.length, ...rows.map((row) => row[index]?.length ?? 0)),\n );\n const renderRow = (row: string[]) =>\n row\n .map((cell, index) => cell.padEnd(widths[index] ?? cell.length))\n .join(\" \")\n .trimEnd();\n\n return [\n renderRow(headers),\n widths.map((width) => \"-\".repeat(width)).join(\" \"),\n ...rows.map(renderRow),\n ];\n}\n\nfunction formatCaseUsage(testCase: EvalCase) {\n const usage = testCase.harness?.usage;\n const parts: string[] = [];\n const totalTokens =\n usage?.totalTokens ??\n (usage?.inputTokens ?? 0) +\n (usage?.outputTokens ?? 0) +\n (usage?.reasoningTokens ?? 0);\n const toolCalls =\n usage?.toolCalls !== undefined\n ? Math.max(usage.toolCalls, testCase.toolCalls.length)\n : testCase.toolCalls.length;\n\n if (totalTokens > 0) {\n parts.push(`${formatNumber(totalTokens)} tokens`);\n }\n if (toolCalls > 0) {\n parts.push(`${formatNumber(toolCalls)} tool${toolCalls === 1 ? \"\" : \"s\"}`);\n }\n if (testCase.harness?.timingMs !== undefined) {\n parts.push(formatDuration(testCase.harness.timingMs));\n }\n\n return parts.join(\", \");\n}\n","import type { EvalReport, UsageSummary } from \"./types\";\n\n/** Merges multiple collected eval reports into one combined report. */\nexport function mergeEvalReports(reports: EvalReport[]): EvalReport {\n const cases = reports.flatMap((report) => report.cases);\n const failures = reports.flatMap((report) => report.failures);\n const scoredCases = cases\n .map((testCase) => testCase.eval?.avgScore)\n .filter(\n (score): score is number =>\n typeof score === \"number\" && Number.isFinite(score),\n );\n const startedAtValues = reports\n .map((report) => report.startedAt)\n .filter(\n (startedAt): startedAt is number =>\n typeof startedAt === \"number\" && Number.isFinite(startedAt),\n );\n const startedAt =\n startedAtValues.length > 0 ? Math.min(...startedAtValues) : undefined;\n\n return {\n status: reports.some((report) => report.status === \"failed\")\n ? \"failed\"\n : \"passed\",\n startedAt,\n durationMs: mergeDuration(reports),\n totals: {\n total: sum(reports, (report) => report.totals.total),\n passed: sum(reports, (report) => report.totals.passed),\n failed: sum(reports, (report) => report.totals.failed),\n skipped: sum(reports, (report) => report.totals.skipped),\n evalTotal: sum(reports, (report) => report.totals.evalTotal),\n evalPassed: sum(reports, (report) => report.totals.evalPassed),\n evalFailed: sum(reports, (report) => report.totals.evalFailed),\n },\n score:\n scoredCases.length > 0\n ? {\n average:\n scoredCases.reduce((total, score) => total + score, 0) /\n scoredCases.length,\n minimum: Math.min(...scoredCases),\n }\n : undefined,\n usage: mergeUsage(reports.map((report) => report.usage)),\n cases,\n failures,\n };\n}\n\nfunction mergeUsage(usages: Array<Required<UsageSummary>>) {\n return {\n inputTokens: sum(usages, (usage) => usage.inputTokens),\n outputTokens: sum(usages, (usage) => usage.outputTokens),\n reasoningTokens: sum(usages, (usage) => usage.reasoningTokens),\n totalTokens: sum(usages, (usage) => usage.totalTokens),\n toolCalls: sum(usages, (usage) => usage.toolCalls),\n };\n}\n\nfunction mergeDuration(reports: EvalReport[]) {\n const durations = reports\n .map((report) => report.durationMs)\n .filter(\n (durationMs): durationMs is number =>\n typeof durationMs === \"number\" && Number.isFinite(durationMs),\n );\n const intervals = reports\n .map((report) => {\n if (\n typeof report.startedAt !== \"number\" ||\n !Number.isFinite(report.startedAt) ||\n typeof report.durationMs !== \"number\" ||\n !Number.isFinite(report.durationMs)\n ) {\n return undefined;\n }\n\n return {\n start: report.startedAt,\n end: report.startedAt + report.durationMs,\n };\n })\n .filter((interval): interval is { start: number; end: number } =>\n Boolean(interval),\n );\n\n if (intervals.length > 0 && intervals.length === durations.length) {\n return (\n Math.max(...intervals.map((interval) => interval.end)) -\n Math.min(...intervals.map((interval) => interval.start))\n );\n }\n\n return durations.length > 0\n ? durations.reduce((total, durationMs) => total + durationMs, 0)\n : undefined;\n}\n\nfunction sum<T>(items: T[], select: (item: T) => number) {\n return items.reduce((total, item) => total + select(item), 0);\n}\n","#!/usr/bin/env node\nimport { parseCliArgs } from \"./cli-options\";\nimport { publishEvalReport } from \"./report\";\nimport { escapeCommandData } from \"./utils\";\n\nmain().catch((error) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exitCode = 1;\n});\n\nasync function main() {\n const options = parseCliArgs(process.argv.slice(2));\n if (options.help) {\n console.log(usage());\n return;\n }\n\n const result = await publishEvalReport({\n resultPatterns: options.resultPatterns,\n cwd: options.workspace ?? process.env.GITHUB_WORKSPACE ?? process.cwd(),\n workspace:\n options.workspace ?? process.env.GITHUB_WORKSPACE ?? process.cwd(),\n summaryEnabled: options.summaryEnabled,\n summaryPath: options.summaryPath,\n annotations: options.annotations,\n checkRun: options.checkRun,\n checkRunId: options.checkRunId,\n checkName: options.checkName,\n failOnCheckError: options.failOnCheckError,\n failOnFailures: options.failOnFailures,\n softFail: options.softFail,\n minPassRate: options.minPassRate,\n minScoreAverage: options.minScoreAverage,\n maxAnnotations: options.maxAnnotations,\n maxFailures: options.maxFailures,\n repository: options.repository,\n sha: options.sha,\n token: options.token,\n warn,\n });\n\n if (result.shouldFail) {\n console.error(result.gate.message);\n process.exitCode = 1;\n }\n}\n\nfunction warn(message: string) {\n if (process.env.GITHUB_ACTIONS === \"true\") {\n console.log(`::warning::${escapeCommandData(message)}`);\n return;\n }\n console.error(`Warning: ${message}`);\n}\n\nfunction usage() {\n return [\n \"Usage: vitest-evals-github-report [vitest-results.json ...] [--json <path>]\",\n \"\",\n \"Options:\",\n \" --json <path> Read a Vitest JSON report from this path or glob\",\n \" --summary <path> Write job summary markdown to this path\",\n \" --no-summary Disable summary output\",\n \" --annotations Emit GitHub workflow-command annotations\",\n \" --no-annotations Disable workflow-command annotations\",\n \" --check-run Publish a GitHub Check Run when configured\",\n \" --fail-on-failures Exit non-zero when any eval case failed\",\n \" --min-pass-rate <0-1> Exit non-zero when eval pass rate is below this floor\",\n \" --min-score-average <0-1> Exit non-zero when average score is below this floor\",\n \" --soft-fail Keep exit 0 when a published Check Run owns gate status\",\n \" --no-soft-fail Always exit non-zero when an enforced gate fails\",\n \" --fail-on-check-error Fail when Check Run publishing fails\",\n \" --check-run-id <id> Update an existing Check Run\",\n \" --check-name <name> Check Run name (default: vitest-evals)\",\n \" --token <token> GitHub token (default: GITHUB_TOKEN)\",\n \" --repo <owner/repo> GitHub repository (default: GITHUB_REPOSITORY)\",\n \" --sha <sha> Git commit SHA (default: PR head, then GITHUB_SHA)\",\n \" --workspace <path> Workspace path for relative annotation files\",\n \" --max-annotations <n> Maximum annotations to emit\",\n \" --max-failures <n> Maximum failures to include in details\",\n ].join(\"\\n\");\n}\n"],"mappings":"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","names":["usage","score","usage","formatToolCallStatus","startedAt","usage"]}
package/dist/cli.mjs CHANGED
@@ -40,6 +40,12 @@ function parseCliArgs(args, env = process.env) {
40
40
  case "--fail-on-check-error":
41
41
  options.failOnCheckError = true;
42
42
  break;
43
+ case "--soft-fail":
44
+ options.softFail = true;
45
+ break;
46
+ case "--no-soft-fail":
47
+ options.softFail = false;
48
+ break;
43
49
  case "--min-pass-rate":
44
50
  options.minPassRate = readRatio(args, ++index, arg);
45
51
  break;
@@ -649,6 +655,9 @@ function formatFloorSuffix(minPassRate, minScoreAverage) {
649
655
  return parts.length === 0 ? "" : `; ${parts.join(", ")}`;
650
656
  }
651
657
 
658
+ // src/github.ts
659
+ import { readFileSync } from "fs";
660
+
652
661
  // src/summary.ts
653
662
  var DEFAULT_MAX_FAILURES = 20;
654
663
  var DEFAULT_MAX_REASON_CHARS = 8e3;
@@ -949,10 +958,44 @@ function formatCaseUsage(testCase) {
949
958
  var DEFAULT_CHECK_NAME = "vitest-evals";
950
959
  var MAX_CHECK_SUMMARY_LENGTH = 64e3;
951
960
  var CHECK_SUMMARY_TRUNCATION_SUFFIX = "\n\n[truncated for GitHub Check Run]\n";
961
+ function resolveCheckSha(env = process.env, options = {}) {
962
+ const explicit = options.sha?.trim() || env.GITHUB_PR_HEAD_SHA?.trim();
963
+ if (explicit) {
964
+ return explicit;
965
+ }
966
+ const eventPath = options.eventPath?.trim() || env.GITHUB_EVENT_PATH?.trim();
967
+ if (eventPath) {
968
+ try {
969
+ const event = JSON.parse(readFileSync(eventPath, "utf8"));
970
+ const headSha = event.pull_request?.head?.sha;
971
+ if (typeof headSha === "string" && headSha.trim()) {
972
+ return headSha.trim();
973
+ }
974
+ } catch {
975
+ }
976
+ }
977
+ return env.GITHUB_SHA?.trim() || void 0;
978
+ }
979
+ function resolveCheckDetailsUrl(env = process.env, options = {}) {
980
+ const explicit = options.detailsUrl?.trim();
981
+ if (explicit) {
982
+ return explicit;
983
+ }
984
+ const server = env.GITHUB_SERVER_URL?.replace(/\/$/, "");
985
+ const repository = env.GITHUB_REPOSITORY?.trim();
986
+ const runId = env.GITHUB_RUN_ID?.trim();
987
+ if (!server || !repository || !runId) {
988
+ return void 0;
989
+ }
990
+ return `${server}/${repository}/actions/runs/${runId}`;
991
+ }
952
992
  async function publishCheckRun(report, options = {}) {
953
993
  const token = options.token ?? process.env.GITHUB_TOKEN;
954
994
  const repository = options.repository ?? process.env.GITHUB_REPOSITORY;
955
- const sha = options.sha ?? process.env.GITHUB_SHA;
995
+ const sha = resolveCheckSha(process.env, { sha: options.sha });
996
+ const detailsUrl = resolveCheckDetailsUrl(process.env, {
997
+ detailsUrl: options.detailsUrl
998
+ });
956
999
  if (!token) {
957
1000
  return { status: "skipped", reason: "missing GITHUB_TOKEN" };
958
1001
  }
@@ -960,7 +1003,10 @@ async function publishCheckRun(report, options = {}) {
960
1003
  return { status: "skipped", reason: "missing GITHUB_REPOSITORY" };
961
1004
  }
962
1005
  if (!sha && options.checkRunId === void 0) {
963
- return { status: "skipped", reason: "missing GITHUB_SHA" };
1006
+ return {
1007
+ status: "skipped",
1008
+ reason: "missing commit SHA (set --sha / options.sha, GITHUB_PR_HEAD_SHA, pull_request.head.sha, or GITHUB_SHA)"
1009
+ };
964
1010
  }
965
1011
  const [owner, repo] = repository.split("/");
966
1012
  if (!owner || !repo) {
@@ -969,7 +1015,7 @@ async function publishCheckRun(report, options = {}) {
969
1015
  reason: `invalid GitHub repository: ${repository}`
970
1016
  };
971
1017
  }
972
- const payload = buildCheckRunPayload(report, options);
1018
+ const payload = buildCheckRunPayload(report, options, detailsUrl);
973
1019
  const apiUrl = options.apiUrl ?? process.env.GITHUB_API_URL ?? "https://api.github.com";
974
1020
  const requestUrl = options.checkRunId === void 0 ? `${apiUrl}/repos/${owner}/${repo}/check-runs` : `${apiUrl}/repos/${owner}/${repo}/check-runs/${options.checkRunId}`;
975
1021
  const response = await fetch(requestUrl, {
@@ -984,6 +1030,7 @@ async function publishCheckRun(report, options = {}) {
984
1030
  options.checkRunId === void 0 ? {
985
1031
  name: options.name ?? DEFAULT_CHECK_NAME,
986
1032
  head_sha: sha,
1033
+ ...options.externalId ? { external_id: options.externalId } : {},
987
1034
  ...payload
988
1035
  } : payload
989
1036
  )
@@ -998,10 +1045,11 @@ async function publishCheckRun(report, options = {}) {
998
1045
  return {
999
1046
  status: options.checkRunId === void 0 ? "created" : "updated",
1000
1047
  id: data.id,
1001
- htmlUrl: data.html_url
1048
+ htmlUrl: data.html_url,
1049
+ sha
1002
1050
  };
1003
1051
  }
1004
- function buildCheckRunPayload(report, options) {
1052
+ function buildCheckRunPayload(report, options, detailsUrl) {
1005
1053
  const gate = options.gate ?? evaluateEvalGate(report);
1006
1054
  const annotations = buildCheckAnnotations(report, {
1007
1055
  maxAnnotations: options.maxAnnotations,
@@ -1011,6 +1059,7 @@ function buildCheckRunPayload(report, options) {
1011
1059
  status: "completed",
1012
1060
  conclusion: gate.ok ? "success" : "failure",
1013
1061
  completed_at: (/* @__PURE__ */ new Date()).toISOString(),
1062
+ ...detailsUrl ? { details_url: detailsUrl } : {},
1014
1063
  output: {
1015
1064
  title: gate.title,
1016
1065
  summary: truncateCheckSummary(
@@ -1164,11 +1213,17 @@ async function publishEvalReport(options) {
1164
1213
  name: options.checkName,
1165
1214
  repository: options.repository,
1166
1215
  sha: options.sha,
1216
+ detailsUrl: options.detailsUrl,
1217
+ externalId: options.externalId,
1167
1218
  token: options.token,
1168
1219
  gate
1169
1220
  });
1170
1221
  if (checkRun.status === "skipped") {
1171
1222
  options.warn?.(`GitHub Check Run skipped: ${checkRun.reason}`);
1223
+ } else if (checkRun.htmlUrl) {
1224
+ console.log(`published check run: ${checkRun.htmlUrl}`);
1225
+ } else if (checkRun.id !== void 0) {
1226
+ console.log(`published check run id: ${checkRun.id}`);
1172
1227
  }
1173
1228
  } catch (error) {
1174
1229
  const message = error instanceof Error ? error.message : String(error);
@@ -1178,14 +1233,21 @@ async function publishEvalReport(options) {
1178
1233
  options.warn?.(message);
1179
1234
  }
1180
1235
  }
1236
+ const gateFailed = gate.enforced && !gate.ok;
1237
+ const wantsSoftFail = options.softFail ?? options.checkRun === true;
1238
+ const softFail = wantsSoftFail && checkRunPublished(checkRun);
1239
+ const shouldFail = gateFailed && !softFail;
1181
1240
  return {
1182
1241
  report,
1183
1242
  resultFiles,
1184
1243
  gate,
1185
- shouldFail: gate.enforced && !gate.ok,
1244
+ shouldFail,
1186
1245
  checkRun
1187
1246
  };
1188
1247
  }
1248
+ function checkRunPublished(checkRun) {
1249
+ return checkRun?.status === "created" || checkRun?.status === "updated";
1250
+ }
1189
1251
 
1190
1252
  // src/cli.ts
1191
1253
  main().catch((error) => {
@@ -1210,6 +1272,7 @@ async function main() {
1210
1272
  checkName: options.checkName,
1211
1273
  failOnCheckError: options.failOnCheckError,
1212
1274
  failOnFailures: options.failOnFailures,
1275
+ softFail: options.softFail,
1213
1276
  minPassRate: options.minPassRate,
1214
1277
  minScoreAverage: options.minScoreAverage,
1215
1278
  maxAnnotations: options.maxAnnotations,
@@ -1245,12 +1308,14 @@ function usage() {
1245
1308
  " --fail-on-failures Exit non-zero when any eval case failed",
1246
1309
  " --min-pass-rate <0-1> Exit non-zero when eval pass rate is below this floor",
1247
1310
  " --min-score-average <0-1> Exit non-zero when average score is below this floor",
1311
+ " --soft-fail Keep exit 0 when a published Check Run owns gate status",
1312
+ " --no-soft-fail Always exit non-zero when an enforced gate fails",
1248
1313
  " --fail-on-check-error Fail when Check Run publishing fails",
1249
1314
  " --check-run-id <id> Update an existing Check Run",
1250
1315
  " --check-name <name> Check Run name (default: vitest-evals)",
1251
1316
  " --token <token> GitHub token (default: GITHUB_TOKEN)",
1252
1317
  " --repo <owner/repo> GitHub repository (default: GITHUB_REPOSITORY)",
1253
- " --sha <sha> Git commit SHA (default: GITHUB_SHA)",
1318
+ " --sha <sha> Git commit SHA (default: PR head, then GITHUB_SHA)",
1254
1319
  " --workspace <path> Workspace path for relative annotation files",
1255
1320
  " --max-annotations <n> Maximum annotations to emit",
1256
1321
  " --max-failures <n> Maximum failures to include in details"