@alis-build/harness-eval 0.1.2 → 0.1.4
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/README.md +187 -30
- package/dist/adapters/claude-code/index.d.ts +2 -2
- package/dist/adapters/claude-code/index.js +2 -1
- package/dist/adapters/codex/index.d.ts +68 -0
- package/dist/adapters/codex/index.js +3 -0
- package/dist/{claude-code-DZ4Vkgp6.js → claude-code-C_7hxC8z.js} +3 -245
- package/dist/claude-code-C_7hxC8z.js.map +1 -0
- package/dist/cli/bin.js +131 -151
- package/dist/cli/bin.js.map +1 -1
- package/dist/codex-0cHO2te9.js +496 -0
- package/dist/codex-0cHO2te9.js.map +1 -0
- package/dist/config/loader.d.ts +2 -2
- package/dist/config/loader.js +2 -2
- package/dist/{index-V22PrR0p.d.ts → index-C56AEDUr.d.ts} +2 -2
- package/dist/index.d.ts +134 -6
- package/dist/index.js +6 -5
- package/dist/index.js.map +1 -1
- package/dist/{loader-DcI0KfRX.js → loader-CiBm4Kf6.js} +491 -209
- package/dist/loader-CiBm4Kf6.js.map +1 -0
- package/dist/loader-CrmzNwkq.d.ts +107 -0
- package/dist/{projections-BcX7w-f6.js → reporter-BKCJZRYr.js} +1475 -729
- package/dist/reporter-BKCJZRYr.js.map +1 -0
- package/dist/runner/suite.d.ts +1 -1
- package/dist/runner/suite.js +1 -1
- package/dist/{suite-Dlzl-HI0.js → suite-C3-8EjUW.js} +558 -4
- package/dist/suite-C3-8EjUW.js.map +1 -0
- package/dist/{suite-DPJMIEbu.d.ts → suite-qyOGre2g.d.ts} +2 -2
- package/dist/types-Bac8_Ixb.js +246 -0
- package/dist/types-Bac8_Ixb.js.map +1 -0
- package/dist/{types-CD3TwOtZ.d.ts → types-CLt4Yygc.d.ts} +2 -2
- package/dist/{types-B9H4IZtA.d.ts → types-D0HR2WnP.d.ts} +9 -2
- package/dist/types-DFMpv_HJ.d.ts +77 -0
- package/package.json +11 -2
- package/schemas/eval-run-envelope.schema.json +193 -183
- package/dist/claude-code-DZ4Vkgp6.js.map +0 -1
- package/dist/loader-C9yQHUPC.d.ts +0 -50
- package/dist/loader-DcI0KfRX.js.map +0 -1
- package/dist/projections-BcX7w-f6.js.map +0 -1
- package/dist/suite-Dlzl-HI0.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"projections-BcX7w-f6.js","names":["parseYaml","formatJson","RESET","GREEN","RED","formatRate"],"sources":["../src/types/eval-record.ts","../src/otel/attributes.ts","../src/otel/messages.ts","../src/otel/types.ts","../src/otel/emitter.ts","../src/grader/prompt.ts","../src/grader/parse.ts","../src/grader/claude-grader.ts","../src/grader/expectations.ts","../src/grader/transcript.ts","../src/grader/grade-report.ts","../src/grader/resolve-grade-options.ts","../src/grader/format-console.ts","../src/reporter/format-console.ts","../src/reporter/format-json.ts","../src/reporter/format-markdown.ts","../src/reporter/renderable.ts","../src/reporter/index.ts","../src/eval-interchange/normalize.ts","../src/eval-interchange/protojson/trajectory-instances.ts","../src/eval-interchange/protojson/evaluation-instance.ts","../src/metrics/trajectory.ts","../src/eval-interchange/protojson/harness-metrics.ts","../src/eval-interchange/enrich.ts","../src/eval-record/build.ts","../src/eval-interchange/projections.ts"],"sourcesContent":["/**\n * Cross-harness eval record contract for storage, CI/CD, and external judges.\n */\n\nimport type { AdapterDiagnostics } from \"../adapters/types\";\nimport type { GradedExpectation, GradingSummary } from \"../grader/types\";\nimport type {\n EvaluationInstanceJson,\n HarnessMetrics,\n ProtojsonTrajectory,\n TrajectoryInstancesJson,\n} from \"./eval-interchange\";\nimport type { AssertionResult } from \"./assertions\";\nimport type { TrajectoryView } from \"./trajectory\";\n\n/** Schema version for {@link EvalRunEnvelope} JSON documents. */\nexport const EVAL_RUN_SCHEMA_VERSION = \"1.0\";\n\n/** Schema version embedded in each {@link TrajectoryView} at export time. */\nexport const TRAJECTORY_SCHEMA_VERSION = \"1.0\";\n\n/** Link to the suite spec that produced a run. */\nexport interface SuiteReference {\n uri?: string;\n id?: string;\n contentHash?: string;\n}\n\n/** Harness that executed the run. */\nexport interface HarnessInfo {\n adapter: string;\n frameworkVersion?: string;\n harnessVersion?: string;\n}\n\n/** CI, git, or runtime provenance for correlation in the DB. */\nexport interface EvalProvenance {\n runId?: string;\n ci?: {\n provider?: string;\n jobId?: string;\n pipelineId?: string;\n url?: string;\n };\n git?: {\n commit?: string;\n branch?: string;\n repository?: string;\n };\n pluginVersion?: string;\n triggeredBy?: string;\n [key: string]: unknown;\n}\n\n/** Aggregate behavioral summary for the run. */\nexport interface EvalRunSummary {\n cellsTotal: number;\n cellsPassed: number;\n behavioralPass: boolean;\n outcomePass?: boolean;\n}\n\n/** Identity of the judge that produced outcome grades. */\nexport interface JudgeInfo {\n id: string;\n model?: string;\n version?: string;\n}\n\n/** Outcome grades for one repetition (built-in or external judge). */\nexport interface OutcomeGrades {\n judge: JudgeInfo;\n expectations: GradedExpectation[];\n summary: GradingSummary;\n evalFeedback?: {\n suggestions: Array<{ assertion?: string; reason: string }>;\n overall: string;\n };\n error?: string;\n}\n\n/** Score from an external eval framework (LangSmith, Braintrust, custom). */\nexport interface ExternalScore {\n source: string;\n metric: string;\n value: number | boolean | string;\n metadata?: Record<string, unknown>;\n}\n\n/** Optional large or vendor-specific blobs (store by reference in DB when possible). */\nexport interface EvalArtifacts {\n rawStreamEvents?: unknown[];\n otlpTraceUri?: string;\n transcript?: string;\n}\n\n/** One harness invocation — the unit external judges and trajectory queries use. */\nexport interface EvalRepetition {\n repetitionIndex: number;\n durationMs: number;\n trajectory?: TrajectoryView & { schemaVersion: string };\n diagnostics?: Partial<AdapterDiagnostics>;\n assertionResults: AssertionResult[];\n outcomeGrades?: OutcomeGrades;\n externalScores?: ExternalScore[];\n artifacts?: EvalArtifacts;\n\n /** Vertex EvaluationInstance protojson wire object. */\n evaluationInstance?: EvaluationInstanceJson;\n\n /** Vertex Trajectory*Instance protojson wire objects keyed by metric. */\n trajectoryInstances?: TrajectoryInstancesJson;\n\n /** Harness-precomputed trajectory metric scores (camelCase). */\n harnessMetrics?: HarnessMetrics;\n\n latencySeconds?: number;\n failure?: 0 | 1;\n\n error?: {\n message: string;\n diagnostics?: Partial<AdapterDiagnostics>;\n };\n}\n\n/** Behavioral stats for one assertion across repetitions in a cell. */\nexport interface EvalAssertionStat {\n description: string;\n threshold: number;\n passedCount: number;\n evaluatedCount: number;\n passRate: number;\n meetsThreshold: boolean;\n}\n\n/** One (test case × matrix cell) result. */\nexport interface EvalCellResult {\n caseId: string;\n category?: string;\n notes?: string;\n prompt?: string;\n expectations?: string[];\n cellLabel: string;\n axes?: Record<string, string>;\n /** Reference trajectory in Vertex protojson wire format. */\n referenceTrajectory?: ProtojsonTrajectory;\n humanRatings?: Record<string, number>;\n assertionStats: EvalAssertionStat[];\n adapterErrors: number;\n behavioralPass: boolean;\n outcomePass?: boolean;\n repetitions: EvalRepetition[];\n}\n\n/** Top-level document for CI/CD pipelines, APIs, and databases. */\nexport interface EvalRunEnvelope {\n schemaVersion: typeof EVAL_RUN_SCHEMA_VERSION;\n runId: string;\n startedAt: string;\n durationMs: number;\n suite?: SuiteReference;\n harness: HarnessInfo;\n provenance?: EvalProvenance;\n summary: EvalRunSummary;\n cells: EvalCellResult[];\n}\n\nexport interface BuildEvalRunEnvelopeOptions {\n /** Override envelope runId; defaults to a random UUID. */\n runId?: string;\n /** Link to the suite YAML that produced the run. */\n suite?: SuiteReference;\n /** Harness adapter metadata; adapter defaults to `\"claude-code\"`. */\n harness?: Partial<HarnessInfo>;\n /** CI, git, and runtime provenance for correlation. */\n provenance?: EvalProvenance;\n /** Outcome grades to merge from a grader run. */\n grading?: {\n gradedAt?: string;\n sourceReport?: string;\n results: Array<{\n caseId: string;\n cellLabel: string;\n repetitionIndex: number;\n expectations: GradedExpectation[];\n summary: GradingSummary;\n evalFeedback?: OutcomeGrades[\"evalFeedback\"];\n graderError?: string;\n durationMs?: number;\n }>;\n judge?: JudgeInfo;\n };\n /** Include text transcript artifact (default true). */\n includeTranscript?: boolean;\n /** Include raw stream-json events (default false; debug only). */\n includeRawStreamEvents?: boolean;\n}\n","/**\n * Helpers for OTLP attribute values.\n *\n * OTLP JSON uses typed value objects (`stringValue`, `intValue`, etc.) rather\n * than plain JSON scalars on attributes.\n */\n\nimport type { AnyValue, KeyValue } from \"./types\";\n\n/** Build a string-typed OTLP attribute. */\nexport function strAttr(key: string, value: string): KeyValue {\n return { key, value: { stringValue: value } };\n}\n\n/** Build an integer-typed OTLP attribute (stored as decimal string). */\nexport function intAttr(key: string, value: number): KeyValue {\n return { key, value: { intValue: String(value) } };\n}\n\n/** Build a boolean-typed OTLP attribute. */\nexport function boolAttr(key: string, value: boolean): KeyValue {\n return { key, value: { boolValue: value } };\n}\n\n/** Build a JSON-serialized string attribute (common for message arrays). */\nexport function jsonAttr(key: string, value: unknown): KeyValue {\n return { key, value: { stringValue: JSON.stringify(value) } };\n}\n\n/** Coerce an arbitrary JS value into an OTLP {@link AnyValue}. */\nexport function anyValue(value: unknown): AnyValue {\n if (value === null || value === undefined) {\n return { stringValue: \"\" };\n }\n if (typeof value === \"string\") {\n return { stringValue: value };\n }\n if (typeof value === \"boolean\") {\n return { boolValue: value };\n }\n if (typeof value === \"number\") {\n if (Number.isInteger(value)) {\n return { intValue: String(value) };\n }\n return { doubleValue: value };\n }\n return { stringValue: JSON.stringify(value) };\n}\n","/**\n * Build GenAI semconv message arrays from a {@link TrajectoryView}.\n *\n * Message shapes follow OpenTelemetry GenAI semantic conventions for\n * `gen_ai.input.messages` and `gen_ai.output.messages` span attributes.\n */\n\nimport type { AssistantTurn, ToolCall, TrajectoryView } from \"../types/trajectory\";\n\n/** One message in GenAI semconv format (role + typed parts). */\nexport interface GenAiMessage {\n role: string;\n parts: GenAiPart[];\n finish_reason?: string;\n}\n\n/** Discriminated content part within a {@link GenAiMessage}. */\nexport type GenAiPart =\n | { type: \"text\"; content: string }\n | {\n type: \"tool_call\";\n id: string;\n name: string;\n arguments: unknown;\n }\n | {\n type: \"tool_call_response\";\n id: string;\n result: unknown;\n };\n\n/**\n * Map harness stop reasons to GenAI semconv finish_reason values.\n *\n * Unknown reasons pass through unchanged for forward compatibility.\n */\nexport function mapStopReason(reason: string | null): string | undefined {\n if (!reason) return undefined;\n switch (reason) {\n case \"end_turn\":\n return \"stop\";\n case \"tool_use\":\n return \"tool_calls\";\n case \"max_tokens\":\n return \"length\";\n case \"stop_sequence\":\n return \"stop\";\n default:\n return reason;\n }\n}\n\n/** Build a tool_call part from a {@link ToolCall}. */\nexport function toolCallPart(call: ToolCall): GenAiPart {\n return {\n type: \"tool_call\",\n id: call.callId,\n name: call.name,\n arguments: call.args ?? {},\n };\n}\n\n/** Build a tool_call_response part from a {@link ToolCall} result. */\nexport function toolResponsePart(call: ToolCall): GenAiPart {\n return {\n type: \"tool_call_response\",\n id: call.callId,\n result: call.result,\n };\n}\n\n/** Convert one assistant turn to a GenAI semconv assistant message. */\nexport function assistantMessageFromTurn(turn: AssistantTurn): GenAiMessage {\n const parts: GenAiPart[] = [];\n if (turn.text) {\n parts.push({ type: \"text\", content: turn.text });\n }\n for (const call of turn.toolCalls) {\n parts.push(toolCallPart(call));\n }\n const finish = mapStopReason(turn.stopReason);\n return {\n role: \"assistant\",\n parts,\n ...(finish ? { finish_reason: finish } : {}),\n };\n}\n\n/** Aggregate tool results from a turn into a single tool-role message, if any. */\nexport function toolResultsMessage(calls: ToolCall[]): GenAiMessage | null {\n const parts = calls\n .filter((c) => c.result !== null)\n .map((c) => toolResponsePart(c));\n if (parts.length === 0) return null;\n return { role: \"tool\", parts };\n}\n\n/**\n * Input history before the assistant turn at `turnIndex`.\n */\nexport function inputMessagesBeforeTurn(\n view: TrajectoryView,\n turnIndex: number,\n prompt?: string,\n): GenAiMessage[] {\n const messages: GenAiMessage[] = [];\n\n if (prompt) {\n messages.push({\n role: \"user\",\n parts: [{ type: \"text\", content: prompt }],\n });\n }\n\n for (let i = 0; i < turnIndex; i++) {\n const turn = view.turns[i];\n if (!turn) continue;\n messages.push(assistantMessageFromTurn(turn));\n const toolMsg = toolResultsMessage(turn.toolCalls);\n if (toolMsg) messages.push(toolMsg);\n }\n\n return messages;\n}\n\n/** Messages representing model output for the final turn (or synthetic final response). */\nexport function finalOutputMessages(view: TrajectoryView): GenAiMessage[] {\n if (view.turns.length === 0) {\n if (!view.finalResponse) return [];\n return [\n {\n role: \"assistant\",\n parts: [{ type: \"text\", content: view.finalResponse }],\n finish_reason: mapStopReason(view.finalStopReason),\n },\n ];\n }\n\n const last = view.turns[view.turns.length - 1];\n return [assistantMessageFromTurn(last)];\n}\n","/**\n * Minimal OTLP JSON types for trace export.\n *\n * Shapes follow OTLP/HTTP JSON Protobuf encoding (lowerCamelCase field names).\n * @see https://opentelemetry.io/docs/specs/otlp/\n */\n\n/** OTLP ExportTraceServiceRequest root — batch of resource spans. */\nexport interface ExportTraceServiceRequest {\n resourceSpans: ResourceSpans[];\n}\n\n/** Resource-attributed span group in an export batch. */\nexport interface ResourceSpans {\n resource: Resource;\n scopeSpans: ScopeSpans[];\n}\n\n/** OTLP resource descriptor (service.name, agent metadata). */\nexport interface Resource {\n attributes: KeyValue[];\n}\n\n/** Spans emitted by one instrumentation scope within a resource. */\nexport interface ScopeSpans {\n scope: InstrumentationScope;\n spans: Span[];\n}\n\n/** Instrumentation library identity (name + optional version). */\nexport interface InstrumentationScope {\n name: string;\n version?: string;\n}\n\n/** One span in OTLP JSON encoding (nanosecond timestamps as strings). */\nexport interface Span {\n traceId: string;\n spanId: string;\n parentSpanId?: string;\n name: string;\n kind: number;\n startTimeUnixNano: string;\n endTimeUnixNano: string;\n attributes: KeyValue[];\n status?: SpanStatus;\n}\n\n/** OTLP span status (OK, ERROR, or UNSET). */\nexport interface SpanStatus {\n code: number;\n message?: string;\n}\n\n/** Key-value attribute pair on a span or resource. */\nexport interface KeyValue {\n key: string;\n value: AnyValue;\n}\n\n/** Discriminated OTLP attribute value (one of the typed fields set). */\nexport interface AnyValue {\n stringValue?: string;\n boolValue?: boolean;\n intValue?: string;\n doubleValue?: number;\n bytesValue?: string;\n arrayValue?: ArrayValue;\n kvlistValue?: KeyValueList;\n}\n\nexport interface ArrayValue {\n values: AnyValue[];\n}\n\nexport interface KeyValueList {\n values: KeyValue[];\n}\n\n/** OTLP span kinds (enum integers). */\nexport const SpanKind = {\n INTERNAL: 1,\n CLIENT: 2,\n} as const;\n\n/** OTLP status codes. */\nexport const StatusCode = {\n UNSET: 0,\n OK: 1,\n ERROR: 2,\n} as const;\n\n/** Options passed to {@link trajectoryToOtlp} / {@link emitOtel}. */\nexport interface EmitOtelOptions {\n /** User prompt for the first `gen_ai.input.messages` entry. */\n prompt?: string;\n /** `gen_ai.agent.name` on the root span. Default: `claude-code`. */\n agentName?: string;\n /** `gen_ai.provider.name`. Default: `anthropic`. */\n providerName?: string;\n /** Resource `service.name`. Default: `harness-eval`. */\n serviceName?: string;\n /** Instrumentation scope name. Default: `@alis-build/harness-eval`. */\n instrumentationScope?: string;\n /**\n * Wall-clock end time for the trace (ms). Defaults to `Date.now()`.\n * Start is derived from `view.usage.durationMs`.\n */\n endTimeMs?: number;\n}\n","/**\n * TrajectoryView → OTLP JSON export using OpenTelemetry GenAI semantic conventions.\n *\n * Produces an `ExportTraceServiceRequest` suitable for OTLP/HTTP JSON ingestion.\n * Assertions continue to use {@link TrajectoryView} directly; this is export-only.\n */\n\nimport { createHash } from \"node:crypto\";\n\nimport type { TrajectoryView } from \"../types/trajectory\";\nimport { boolAttr, intAttr, jsonAttr, strAttr } from \"./attributes\";\nimport {\n assistantMessageFromTurn,\n inputMessagesBeforeTurn,\n mapStopReason,\n} from \"./messages\";\nimport type {\n EmitOtelOptions,\n ExportTraceServiceRequest,\n Span,\n SpanStatus,\n} from \"./types\";\nimport { SpanKind, StatusCode } from \"./types\";\n\nconst INSTRUMENTATION_VERSION = \"0.1.0\";\n\ninterface SpanTiming {\n startNs: string;\n endNs: string;\n}\n\n/**\n * Map a {@link TrajectoryView} to OTLP trace JSON.\n *\n * Span tree (siblings under `invoke_agent`, not nested):\n * ```\n * invoke_agent\n * ├── chat {model}\n * ├── execute_tool {name}\n * ├── chat {model}\n * └── ...\n * ```\n */\nexport function trajectoryToOtlp(\n view: TrajectoryView,\n options: EmitOtelOptions = {},\n): ExportTraceServiceRequest {\n const agentName = options.agentName ?? \"claude-code\";\n const providerName = options.providerName ?? \"anthropic\";\n const serviceName = options.serviceName ?? \"harness-eval\";\n const scopeName =\n options.instrumentationScope ?? \"@alis-build/harness-eval\";\n\n const traceId = traceIdFromSession(view.meta.sessionId);\n const rootSpanId = spanIdFromKey(traceId, \"invoke_agent\");\n\n const durationMs = Math.max(view.usage.durationMs, 1);\n const endMs = options.endTimeMs ?? Date.now();\n const startMs = endMs - durationMs;\n const rootStartNs = msToNs(startMs);\n const rootEndNs = msToNs(endMs);\n\n const spans: Span[] = [];\n const timings = buildSpanTimings(view, startMs, endMs);\n\n spans.push({\n traceId,\n spanId: rootSpanId,\n name: \"invoke_agent\",\n kind: SpanKind.INTERNAL,\n startTimeUnixNano: rootStartNs,\n endTimeUnixNano: rootEndNs,\n attributes: [\n strAttr(\"gen_ai.operation.name\", \"invoke_agent\"),\n strAttr(\"gen_ai.agent.name\", agentName),\n strAttr(\"gen_ai.provider.name\", providerName),\n strAttr(\"gen_ai.conversation.id\", view.meta.sessionId),\n strAttr(\"gen_ai.request.model\", view.meta.model),\n strAttr(\"gen_ai.response.model\", view.meta.model),\n intAttr(\"gen_ai.usage.input_tokens\", view.usage.inputTokens),\n intAttr(\"gen_ai.usage.output_tokens\", view.usage.outputTokens),\n boolAttr(\"harness_eval.success\", view.success),\n ],\n status: viewStatus(view),\n });\n\n let opIndex = 0;\n for (const turn of view.turns) {\n const chatTiming = timings[opIndex++];\n const chatSpanId = spanIdFromKey(traceId, `chat:${turn.turnIndex}`);\n const inputMessages = inputMessagesBeforeTurn(\n view,\n turn.turnIndex,\n options.prompt,\n );\n const outputMessages = [assistantMessageFromTurn(turn)];\n\n spans.push({\n traceId,\n spanId: chatSpanId,\n parentSpanId: rootSpanId,\n name: `chat ${view.meta.model}`,\n kind: SpanKind.CLIENT,\n startTimeUnixNano: chatTiming.startNs,\n endTimeUnixNano: chatTiming.endNs,\n attributes: [\n strAttr(\"gen_ai.operation.name\", \"chat\"),\n strAttr(\"gen_ai.provider.name\", providerName),\n strAttr(\"gen_ai.request.model\", view.meta.model),\n strAttr(\"gen_ai.response.model\", view.meta.model),\n ...(inputMessages.length > 0\n ? [jsonAttr(\"gen_ai.input.messages\", inputMessages)]\n : []),\n jsonAttr(\"gen_ai.output.messages\", outputMessages),\n ...(turn.stopReason\n ? [\n jsonAttr(\"gen_ai.response.finish_reasons\", [\n mapStopReason(turn.stopReason) ?? turn.stopReason,\n ]),\n ]\n : []),\n ],\n status: { code: StatusCode.OK },\n });\n\n if (turn.toolCalls.length === 0) continue;\n\n const toolTiming = timings[opIndex++];\n for (const call of turn.toolCalls) {\n const toolSpanId = spanIdFromKey(\n traceId,\n `tool:${call.callId}`,\n );\n\n spans.push({\n traceId,\n spanId: toolSpanId,\n parentSpanId: rootSpanId,\n name: `execute_tool ${call.name}`,\n kind: SpanKind.INTERNAL,\n startTimeUnixNano: toolTiming.startNs,\n endTimeUnixNano: toolTiming.endNs,\n attributes: [\n strAttr(\"gen_ai.operation.name\", \"execute_tool\"),\n strAttr(\"gen_ai.provider.name\", providerName),\n strAttr(\"gen_ai.tool.name\", call.name),\n strAttr(\"gen_ai.tool.call.id\", call.callId),\n jsonAttr(\"gen_ai.tool.call.arguments\", call.args ?? {}),\n ...(call.result !== null\n ? [jsonAttr(\"gen_ai.tool.call.result\", call.result)]\n : []),\n ...(call.namespace\n ? [strAttr(\"harness_eval.tool.namespace\", call.namespace)]\n : []),\n boolAttr(\"harness_eval.tool.is_error\", call.isError),\n ],\n status: call.isError\n ? { code: StatusCode.ERROR, message: \"tool reported error\" }\n : { code: StatusCode.OK },\n });\n }\n }\n\n return {\n resourceSpans: [\n {\n resource: {\n attributes: [\n strAttr(\"service.name\", serviceName),\n strAttr(\"gen_ai.agent.name\", agentName),\n ],\n },\n scopeSpans: [\n {\n scope: {\n name: scopeName,\n version: INSTRUMENTATION_VERSION,\n },\n spans,\n },\n ],\n },\n ],\n };\n}\n\n/** Alias for {@link trajectoryToOtlp} — matches implementation plan naming. */\nexport const emitOtel = trajectoryToOtlp;\n\n/** Map view success flag to OTLP span status on the root invoke_agent span. */\nfunction viewStatus(view: TrajectoryView): SpanStatus {\n if (view.success) {\n return { code: StatusCode.OK };\n }\n return {\n code: StatusCode.ERROR,\n message: \"harness run did not complete successfully\",\n };\n}\n\n/**\n * Assign synthetic timestamps to chat and tool spans.\n *\n * Stream-json does not carry per-turn wall times, so we divide the session\n * duration evenly across chat/tool slots for OTLP consumers that require\n * start/end times on every span.\n */\nfunction buildSpanTimings(\n view: TrajectoryView,\n startMs: number,\n endMs: number,\n): SpanTiming[] {\n const slots: Array<\"chat\" | \"tools\"> = [];\n for (const turn of view.turns) {\n slots.push(\"chat\");\n if (turn.toolCalls.length > 0) slots.push(\"tools\");\n }\n\n if (slots.length === 0) {\n return [];\n }\n\n const totalMs = Math.max(endMs - startMs, 1);\n const slotMs = totalMs / slots.length;\n const timings: SpanTiming[] = [];\n let offset = startMs;\n\n for (const slot of slots) {\n const slotStart = offset;\n const slotEnd = offset + slotMs;\n timings.push({\n startNs: msToNs(slotStart),\n endNs: msToNs(slotEnd),\n });\n offset = slotEnd;\n }\n\n return timings;\n}\n\n/**\n * Derive a deterministic 128-bit trace id from the harness session id.\n *\n * Uses SHA-256 truncation so the same session always maps to the same trace.\n */\nexport function traceIdFromSession(sessionId: string): string {\n return createHash(\"sha256\")\n .update(`harness-eval:trace:${sessionId}`)\n .digest(\"hex\")\n .slice(0, 32)\n .toUpperCase();\n}\n\n/**\n * Derive a deterministic 64-bit span id from trace id and a logical span key.\n */\nexport function spanIdFromKey(traceId: string, key: string): string {\n return createHash(\"sha256\")\n .update(`${traceId}:span:${key}`)\n .digest(\"hex\")\n .slice(0, 16)\n .toUpperCase();\n}\n\n/** Convert milliseconds since epoch to OTLP nanosecond timestamp string. */\nfunction msToNs(ms: number): string {\n return String(Math.round(ms * 1_000_000));\n}\n","/**\n * Build the grader prompt for Claude subprocess grading.\n */\n\nimport type { GraderInput } from \"./types\";\n\n/**\n * Build the full grader prompt including eval prompt, transcript, and schema.\n *\n * When `systemInstruction` is set it is prepended as a judge-specific prefix.\n */\nexport function buildGraderPrompt(input: GraderInput): string {\n const expectationList = input.expectations\n .map((e, i) => `${i + 1}. ${e}`)\n .join(\"\\n\");\n\n const prefix = input.systemInstruction\n ? `${input.systemInstruction.trim()}\\n\\n`\n : \"\";\n\n return `${prefix}You are an automated evaluation grader (not the agent under test). Your only job is to score expectations against the transcript below.\n\nYour job is to evaluate each expectation against the transcript and final response.\nPASS only when there is clear evidence in the transcript or final response.\nWhen uncertain, FAIL — burden of proof is on PASS.\n\nAlso critique the expectations themselves if any are trivially satisfied or miss important outcomes.\n\n## Eval prompt\n\n${input.prompt}\n\n## Execution transcript\n\n${input.transcript}\n\n## Expectations to grade\n\n${expectationList}\n\n## Output format\n\nRespond with ONLY a single JSON object (no markdown fences, no commentary) matching this schema:\n\n{\n \"expectations\": [\n { \"text\": \"<original expectation>\", \"passed\": true|false, \"evidence\": \"<quote or description>\" }\n ],\n \"summary\": { \"passed\": <int>, \"failed\": <int>, \"total\": <int>, \"pass_rate\": <0.0-1.0> },\n \"eval_feedback\": {\n \"suggestions\": [{ \"assertion\": \"<optional>\", \"reason\": \"<string>\" }],\n \"overall\": \"<brief assessment>\"\n }\n}\n\nInclude every expectation in the same order. summary must match the expectations array.`;\n}\n","/**\n * Parse grader JSON from Claude stdout / response text.\n */\n\nimport type {\n EvalFeedback,\n GradedExpectation,\n GradingSummary,\n GraderOutput,\n} from \"./types\";\n\n/**\n * Extract assistant text from Claude stdout.\n *\n * Handles plain text, single JSON result envelopes, stream-json arrays, and\n * assistant message objects — the judge subprocess may emit any of these\n * depending on Claude Code version and flags.\n */\nexport function extractClaudeResponseText(stdout: string): string {\n const trimmed = stdout.trim();\n if (!trimmed) return \"\";\n\n try {\n const data = JSON.parse(trimmed) as unknown;\n\n if (Array.isArray(data)) {\n return extractFromEventArray(data) ?? trimmed;\n }\n\n if (typeof data === \"object\" && data !== null) {\n const event = data as { type?: string; result?: string; message?: unknown };\n if (event.type === \"result\" && typeof event.result === \"string\") {\n return event.result;\n }\n if (event.type === \"assistant\" && event.message) {\n const text = textFromAssistantMessage(event.message);\n if (text) return text;\n }\n }\n } catch {\n // fall through to raw stdout\n }\n\n return trimmed;\n}\n\n/** Walk a stream-json event array and return the final assistant or result text. */\nfunction extractFromEventArray(events: unknown[]): string | null {\n const result = events.find(\n (e) =>\n typeof e === \"object\" &&\n e !== null &&\n (e as { type?: string }).type === \"result\",\n ) as { result?: string } | undefined;\n if (result?.result) return result.result;\n\n const assistantTexts: string[] = [];\n for (const event of events) {\n if (\n typeof event === \"object\" &&\n event !== null &&\n (event as { type?: string }).type === \"assistant\"\n ) {\n const text = textFromAssistantMessage(\n (event as { message?: unknown }).message,\n );\n if (text) assistantTexts.push(text);\n }\n }\n if (assistantTexts.length > 0) {\n return assistantTexts[assistantTexts.length - 1];\n }\n return null;\n}\n\n/** Concatenate text blocks from an Anthropic-style assistant message object. */\nfunction textFromAssistantMessage(message: unknown): string | null {\n if (!message || typeof message !== \"object\") return null;\n const content = (message as { content?: unknown }).content;\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return null;\n\n const texts: string[] = [];\n for (const block of content) {\n if (\n typeof block === \"object\" &&\n block !== null &&\n (block as { type?: string }).type === \"text\" &&\n typeof (block as { text?: string }).text === \"string\"\n ) {\n texts.push((block as { text: string }).text);\n }\n }\n return texts.length > 0 ? texts.join(\"\\n\") : null;\n}\n\n/**\n * Parse grader JSON from response text.\n *\n * Tries the raw string first, then fenced code blocks and brace-delimited\n * substrings. Returns null when no valid expectations array is found.\n */\nexport function parseGraderJson(text: string): GraderOutput | null {\n const candidates = [text.trim(), extractJsonBlock(text)];\n for (const candidate of candidates) {\n if (!candidate) continue;\n try {\n const raw = JSON.parse(candidate) as RawGraderJson;\n const normalized = normalizeGraderJson(raw);\n if (normalized.expectations.length > 0) {\n return normalized;\n }\n } catch {\n continue;\n }\n }\n return null;\n}\n\n/** Raw grader JSON shape before normalization (snake_case from prompt schema). */\ninterface RawGraderJson {\n expectations?: Array<{\n text?: string;\n passed?: boolean;\n evidence?: string;\n }>;\n summary?: {\n passed?: number;\n failed?: number;\n total?: number;\n pass_rate?: number;\n passRate?: number;\n };\n eval_feedback?: {\n suggestions?: Array<{ assertion?: string; reason?: string }>;\n overall?: string;\n };\n}\n\n/** Extract JSON from markdown fences or the outermost `{...}` substring. */\nfunction extractJsonBlock(text: string): string | null {\n const fence = text.match(/```(?:json)?\\s*([\\s\\S]*?)```/);\n if (fence?.[1]) return fence[1].trim();\n\n const start = text.indexOf(\"{\");\n const end = text.lastIndexOf(\"}\");\n if (start >= 0 && end > start) {\n return text.slice(start, end + 1);\n }\n return null;\n}\n\n/** Map raw grader JSON to runtime {@link GraderOutput} with computed summary. */\nfunction normalizeGraderJson(raw: RawGraderJson): GraderOutput {\n const expectations: GradedExpectation[] = (raw.expectations ?? []).map(\n (e) => ({\n text: e.text ?? \"\",\n passed: Boolean(e.passed),\n evidence: e.evidence ?? \"\",\n }),\n );\n\n const passed = expectations.filter((e) => e.passed).length;\n const failed = expectations.length - passed;\n const total = expectations.length;\n const passRate =\n raw.summary?.pass_rate ??\n raw.summary?.passRate ??\n (total === 0 ? 0 : passed / total);\n\n const summary: GradingSummary = {\n passed: raw.summary?.passed ?? passed,\n failed: raw.summary?.failed ?? failed,\n total: raw.summary?.total ?? total,\n passRate,\n };\n\n let evalFeedback: EvalFeedback | undefined;\n if (raw.eval_feedback) {\n evalFeedback = {\n suggestions: (raw.eval_feedback.suggestions ?? []).map((s) => ({\n assertion: s.assertion,\n reason: s.reason ?? \"\",\n })),\n overall: raw.eval_feedback.overall ?? \"\",\n };\n }\n\n return { expectations, summary, evalFeedback };\n}\n","/**\n * Grade expectations by spawning Claude as judge (skill-creator grader pattern).\n */\n\nimport { spawn } from \"node:child_process\";\n\nimport { buildJudgeArgs } from \"../adapters/claude-code/flags\";\nimport type { ClaudeCodeOptions } from \"../adapters/claude-code/types\";\nimport { buildGraderPrompt } from \"./prompt\";\nimport { extractClaudeResponseText, parseGraderJson } from \"./parse\";\nimport type { GraderFn, GraderInput, GraderOutput } from \"./types\";\n\nconst DEFAULT_TIMEOUT_MS = 300_000;\n\n/**\n * Judge subprocess defaults — grading is a single-shot JSON response, not an agent session.\n * Without these, Claude Code may load plugins/MCP and loop on tools until timeout.\n */\nexport const JUDGE_CLAUDE_DEFAULTS: ClaudeCodeOptions = {\n maxTurns: 1,\n bare: true,\n disableSlashCommands: true,\n noSessionPersistence: true,\n};\n\n/** Merge user-supplied Claude Code options over judge-safe defaults. */\nexport function mergeJudgeClaudeOptions(\n claudeCode?: ClaudeCodeOptions,\n): ClaudeCodeOptions {\n return { ...JUDGE_CLAUDE_DEFAULTS, ...claudeCode };\n}\n\n/** Options for {@link createClaudeGrader} / {@link runClaudeGrader}. */\nexport interface ClaudeGraderOptions {\n binary?: string;\n model?: string;\n timeoutMs?: number;\n env?: Record<string, string>;\n cwd?: string;\n claudeCode?: ClaudeCodeOptions;\n}\n\n/** Factory returning a {@link GraderFn} bound to subprocess options. */\nexport function createClaudeGrader(\n options: ClaudeGraderOptions = {},\n): GraderFn {\n return (input) => runClaudeGrader(input, options);\n}\n\n/**\n * Spawn Claude as judge, parse JSON response, align with input expectations.\n *\n * Unparseable output fails all expectations and sets {@link GraderOutput.error}.\n */\nexport async function runClaudeGrader(\n input: GraderInput,\n options: ClaudeGraderOptions = {},\n): Promise<GraderOutput> {\n const binary = options.binary ?? options.claudeCode?.binary ?? \"claude\";\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const prompt = buildGraderPrompt(input);\n const model = options.model ?? options.claudeCode?.model;\n\n const args = buildJudgeArgs(prompt, {\n ...mergeJudgeClaudeOptions(options.claudeCode),\n model,\n });\n\n const stdout = await spawnCollectStdout(\n binary,\n args,\n timeoutMs,\n options.env,\n options.cwd,\n );\n const responseText = extractClaudeResponseText(stdout);\n const parsed = parseGraderJson(responseText);\n\n if (!parsed) {\n return {\n expectations: input.expectations.map((text) => ({\n text,\n passed: false,\n evidence: \"Grader returned unparseable output\",\n })),\n summary: {\n passed: 0,\n failed: input.expectations.length,\n total: input.expectations.length,\n passRate: 0,\n },\n error: `failed to parse grader JSON from response: ${responseText.slice(0, 200)}`,\n };\n }\n\n // Align expectation text with input order when grader omits text field\n const expectations = input.expectations.map((text, i) => {\n const graded = parsed.expectations[i];\n return {\n text,\n passed: graded?.passed ?? false,\n evidence: graded?.evidence ?? \"No evidence returned\",\n };\n });\n\n const passed = expectations.filter((e) => e.passed).length;\n const total = expectations.length;\n\n return {\n expectations,\n summary: {\n passed,\n failed: total - passed,\n total,\n passRate: total === 0 ? 0 : passed / total,\n },\n evalFeedback: parsed.evalFeedback,\n };\n}\n\n/**\n * Spawn a child process and collect stdout until exit or timeout.\n *\n * Non-zero exit with empty stdout is treated as failure; partial stdout on\n * non-zero exit is retained (Claude sometimes exits non-zero after emitting JSON).\n */\nfunction spawnCollectStdout(\n binary: string,\n args: string[],\n timeoutMs: number,\n extraEnv?: Record<string, string>,\n cwd?: string,\n): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = spawn(binary, args, {\n env: buildChildEnv(extraEnv),\n cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n const chunks: string[] = [];\n child.stdout?.setEncoding(\"utf8\");\n child.stdout?.on(\"data\", (c: string) => chunks.push(c));\n\n const stderrChunks: string[] = [];\n child.stderr?.setEncoding(\"utf8\");\n child.stderr?.on(\"data\", (c: string) => stderrChunks.push(c));\n\n const timer = setTimeout(() => {\n child.kill(\"SIGTERM\");\n const stderrHint = stderrChunks.join(\"\").trim().slice(0, 400);\n reject(\n new Error(\n `grader timed out after ${timeoutMs}ms` +\n (stderrHint ? ` (stderr: ${stderrHint})` : \"\"),\n ),\n );\n }, timeoutMs);\n\n const finalize = (err?: Error) => {\n clearTimeout(timer);\n if (err) reject(err);\n else resolve(chunks.join(\"\"));\n };\n\n child.on(\"error\", (err) => finalize(err));\n child.on(\"close\", (code) => {\n if (code !== 0 && chunks.length === 0) {\n finalize(\n new Error(\n `grader exited ${code}: ${stderrChunks.join(\"\").slice(0, 500)}`,\n ),\n );\n } else {\n finalize();\n }\n });\n });\n}\n\n/**\n * Build subprocess env, stripping CLAUDECODE to avoid nested-session guards.\n */\nfunction buildChildEnv(extraEnv?: Record<string, string>): Record<string, string | undefined> {\n const env = { ...process.env, ...extraEnv };\n delete env.CLAUDECODE;\n return env;\n}\n","/**\n * Load expectations sidecar (YAML or JSON).\n */\n\nimport { readFile } from \"node:fs/promises\";\n\nimport { parse as parseYaml } from \"yaml\";\n\nimport type { ExpectationsMap } from \"./types\";\n\n/**\n * Load expectations sidecar (YAML or JSON).\n *\n * File format: `{ \"<caseId>\": [\"expectation 1\", ...], ... }`.\n */\nexport async function loadExpectationsMap(path: string): Promise<ExpectationsMap> {\n const text = await readFile(path, \"utf8\");\n const trimmed = path.trim().toLowerCase();\n\n let raw: unknown;\n if (trimmed.endsWith(\".json\")) {\n raw = JSON.parse(text);\n } else {\n raw = parseYaml(text);\n }\n\n if (!raw || typeof raw !== \"object\") {\n throw new Error(`expectations file must be an object mapping case ids to lists`);\n }\n\n const map: ExpectationsMap = {};\n for (const [caseId, value] of Object.entries(raw as Record<string, unknown>)) {\n if (!Array.isArray(value)) {\n throw new Error(`expectations for case \"${caseId}\" must be an array of strings`);\n }\n map[caseId] = value.map(String);\n }\n return map;\n}\n","/**\n * TrajectoryView → markdown transcript for LLM graders.\n */\n\nimport type { TrajectoryView } from \"../types/trajectory\";\n\n/** Maximum characters per tool result embedded in grader transcripts. */\nconst MAX_RESULT_CHARS = 4000;\n\n/**\n * Render a {@link TrajectoryView} as markdown for LLM graders.\n *\n * Tool results are truncated at {@link MAX_RESULT_CHARS} to keep judge\n * prompts within reasonable token limits.\n */\nexport function trajectoryToTranscript(\n view: TrajectoryView,\n prompt?: string,\n): string {\n const lines: string[] = [];\n\n if (prompt) {\n lines.push(\"## User prompt\", \"\", prompt, \"\");\n }\n\n for (const turn of view.turns) {\n lines.push(`## Assistant turn ${turn.turnIndex + 1}`, \"\");\n if (turn.text) {\n lines.push(turn.text, \"\");\n }\n for (const call of turn.toolCalls) {\n lines.push(`[Tool call] ${call.name} (id=${call.callId})`);\n lines.push(`Arguments: ${formatJson(call.args)}`);\n if (call.result !== null) {\n lines.push(`[Tool result] ${formatResult(call.result)}`);\n if (call.isError) lines.push(\"(tool reported error)\");\n } else {\n lines.push(\"[Tool result] (none observed)\");\n }\n lines.push(\"\");\n }\n if (turn.stopReason) {\n lines.push(`Stop reason: ${turn.stopReason}`, \"\");\n }\n }\n\n const finalInTurns = view.turns.some((t) => t.text === view.finalResponse);\n if (view.finalResponse && !finalInTurns) {\n lines.push(\"## Final response\", \"\", view.finalResponse, \"\");\n }\n\n lines.push(\n \"## Session metadata\",\n `session_id: ${view.meta.sessionId}`,\n `model: ${view.meta.model}`,\n `cwd: ${view.meta.cwd}`,\n `success: ${view.success}`,\n `tool_calls: ${view.toolCalls.length}`,\n `duration_ms: ${view.usage.durationMs}`,\n `input_tokens: ${view.usage.inputTokens}`,\n `output_tokens: ${view.usage.outputTokens}`,\n );\n\n return lines.join(\"\\n\").trimEnd();\n}\n\n/** Format unknown values as JSON for transcript embedding. */\nfunction formatJson(value: unknown): string {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\n/** Format a tool result, truncating long string or JSON payloads. */\nfunction formatResult(result: unknown): string {\n if (typeof result === \"string\") {\n return truncate(result);\n }\n return truncate(formatJson(result));\n}\n\n/** Truncate text with ellipsis when exceeding the transcript size budget. */\nfunction truncate(text: string): string {\n if (text.length <= MAX_RESULT_CHARS) return text;\n return `${text.slice(0, MAX_RESULT_CHARS)}… (truncated)`;\n}\n","/**\n * Grade a harness-eval SuiteReport with outcome expectations (LLM judge).\n */\n\nimport { readFile } from \"node:fs/promises\";\n\nimport { createClaudeGrader, type ClaudeGraderOptions } from \"./claude-grader\";\nimport { loadExpectationsMap } from \"./expectations\";\nimport { trajectoryToTranscript } from \"./transcript\";\nimport type {\n GradeReportOptions,\n GraderFn,\n RepGradingResult,\n SuiteGradingReport,\n} from \"./types\";\nimport { createLimit } from \"../runner/limit\";\nimport type { CellReport, SuiteReport } from \"../runner/types\";\n\n/**\n * Grade every repetition in a {@link SuiteReport} that has expectations.\n *\n * Expectations come from inline case fields or an optional sidecar YAML/JSON\n * map. Runs are concurrent under {@link GradeReportOptions.maxConcurrent}.\n */\nexport async function gradeReport(\n report: SuiteReport,\n options: GradeReportOptions = {},\n): Promise<SuiteGradingReport> {\n const expectationsMap = options.expectationsPath\n ? await loadExpectationsMap(options.expectationsPath)\n : {};\n\n const gradeFn: GraderFn =\n options.gradeFn ??\n createClaudeGrader({\n binary: options.binary,\n model: options.model,\n timeoutMs: options.timeoutMs,\n env: options.env,\n cwd: options.cwd,\n claudeCode: options.claudeCode as ClaudeGraderOptions[\"claudeCode\"],\n });\n\n const maxConcurrent = options.maxConcurrent ?? 2;\n const limit = createLimit(maxConcurrent);\n\n const tasks: Array<{\n cell: CellReport;\n rep: CellReport[\"repetitions\"][number];\n expectations: string[];\n }> = [];\n\n for (const cell of report.cells) {\n const expectations =\n cell.expectations ??\n expectationsMap[cell.caseId] ??\n [];\n\n if (expectations.length === 0) continue;\n\n for (const rep of cell.repetitions) {\n if (!rep.adapterResult) continue;\n tasks.push({ cell, rep, expectations });\n }\n }\n\n const gradeStartTs = Date.now();\n options.onProgress?.({ kind: \"grade-start\", total: tasks.length });\n\n const results: RepGradingResult[] = await Promise.all(\n tasks.map(({ cell, rep, expectations }) =>\n limit(async () => {\n const start = Date.now();\n const view = rep.adapterResult!.view;\n const prompt = cell.prompt ?? \"\";\n const transcript = trajectoryToTranscript(view, prompt);\n\n try {\n const graded = await gradeFn({\n prompt,\n transcript,\n expectations,\n systemInstruction: options.systemInstruction,\n });\n\n const result: RepGradingResult = {\n caseId: cell.caseId,\n cellLabel: cell.cell.label,\n repetitionIndex: rep.repetitionIndex,\n prompt,\n expectations: graded.expectations,\n summary: graded.summary,\n evalFeedback: graded.evalFeedback,\n graderError: graded.error,\n durationMs: Date.now() - start,\n };\n\n options.onProgress?.({\n kind: \"grade-complete\",\n caseId: result.caseId,\n cellLabel: result.cellLabel,\n repetitionIndex: result.repetitionIndex,\n passed: result.summary.passed,\n failed: result.summary.failed,\n durationMs: result.durationMs,\n graderError: result.graderError,\n });\n\n return result;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const result: RepGradingResult = {\n caseId: cell.caseId,\n cellLabel: cell.cell.label,\n repetitionIndex: rep.repetitionIndex,\n prompt,\n expectations: expectations.map((text) => ({\n text,\n passed: false,\n evidence: message,\n })),\n summary: {\n passed: 0,\n failed: expectations.length,\n total: expectations.length,\n passRate: 0,\n },\n graderError: message,\n durationMs: Date.now() - start,\n };\n\n options.onProgress?.({\n kind: \"grade-complete\",\n caseId: result.caseId,\n cellLabel: result.cellLabel,\n repetitionIndex: result.repetitionIndex,\n passed: 0,\n failed: expectations.length,\n durationMs: result.durationMs,\n graderError: message,\n });\n\n return result;\n }\n }),\n ),\n );\n\n results.sort((a, b) => {\n const keyA = `${a.caseId}::${a.cellLabel}::${a.repetitionIndex}`;\n const keyB = `${b.caseId}::${b.cellLabel}::${b.repetitionIndex}`;\n return keyA.localeCompare(keyB);\n });\n\n const totalExpectations = results.reduce((n, r) => n + r.summary.total, 0);\n const passedExpectations = results.reduce((n, r) => n + r.summary.passed, 0);\n\n options.onProgress?.({\n kind: \"grade-done\",\n durationMs: Date.now() - gradeStartTs,\n totalExpectations,\n passedExpectations,\n });\n\n return {\n gradedAt: new Date().toISOString(),\n sourceReport: options.sourceReport ?? \"\",\n gradingConfigPath: options.gradingConfigPath,\n results,\n summary: {\n passed: passedExpectations,\n failed: totalExpectations - passedExpectations,\n total: totalExpectations,\n passRate:\n totalExpectations === 0 ? 0 : passedExpectations / totalExpectations,\n },\n };\n}\n\n/** Load a suite report JSON file produced by `harness-eval run`. */\nexport async function loadSuiteReport(path: string): Promise<SuiteReport> {\n const text = await readFile(path, \"utf8\");\n return JSON.parse(text) as SuiteReport;\n}\n","/**\n * Merge grading YAML with CLI overrides for `gradeReport`.\n */\n\nimport type { ClaudeCodeOptions } from \"../adapters/claude-code/types\";\nimport type { GradingConfig } from \"../config/grading-loader\";\nimport type { GradeReportOptions } from \"./types\";\n\n/** CLI flag overrides for grading (take precedence over grading YAML). */\nexport interface GradeCliOverrides {\n model?: string;\n binary?: string;\n timeoutMs?: number;\n maxConcurrent?: number;\n expectationsPath?: string;\n sourceReport?: string;\n}\n\n/**\n * Merge standalone grading YAML with CLI flags (CLI wins).\n */\nexport function resolveGradeOptions(\n fileConfig?: GradingConfig,\n cli: GradeCliOverrides = {},\n configPath?: string,\n): GradeReportOptions {\n const judge = fileConfig?.judge;\n\n const adapter = judge?.adapter ?? \"claude-code\";\n if (adapter !== \"claude-code\") {\n throw new Error(\n `unsupported grading adapter \"${adapter}\" (only claude-code today)`,\n );\n }\n\n const claudeCode = (judge?.claudeCode ?? {}) as ClaudeCodeOptions;\n const binary = cli.binary ?? claudeCode.binary;\n const model = cli.model ?? judge?.model ?? claudeCode.model;\n\n return {\n sourceReport: cli.sourceReport,\n expectationsPath: cli.expectationsPath,\n model,\n binary,\n timeoutMs: cli.timeoutMs ?? judge?.timeoutMs,\n maxConcurrent: cli.maxConcurrent ?? judge?.maxConcurrent,\n systemInstruction: judge?.system_instruction,\n env: judge?.env,\n cwd: judge?.cwd,\n claudeCode: {\n ...claudeCode,\n binary: undefined,\n model: undefined,\n },\n gradingConfigPath: configPath,\n };\n}\n","/**\n * Console formatter for suite grading reports.\n */\n\nimport type { RepGradingResult, SuiteGradingReport } from \"./types\";\n\nconst RESET = \"\\x1b[0m\";\nconst GREEN = \"\\x1b[32m\";\nconst RED = \"\\x1b[31m\";\nconst DIM = \"\\x1b[2m\";\n\n/**\n * Format a {@link SuiteGradingReport} for terminal output.\n *\n * @param color When true, emit ANSI status colors (default for TTY console).\n */\nexport function formatGradingConsole(\n report: SuiteGradingReport,\n color = true,\n): string {\n const lines: string[] = [];\n\n if (report.results.length === 0) {\n lines.push(\n \"No repetitions graded. Add expectations to the suite YAML or pass --expectations.\",\n );\n return lines.join(\"\\n\");\n }\n\n for (const result of report.results) {\n const allPassed = result.summary.failed === 0 && !result.graderError;\n const status = allPassed\n ? color ? `${GREEN}PASS${RESET}` : \"PASS\"\n : color ? `${RED}FAIL${RESET}` : \"FAIL\";\n\n lines.push(\n `${result.caseId} @ ${result.cellLabel} rep${result.repetitionIndex} ${status}`,\n );\n\n if (result.graderError) {\n lines.push(\n color\n ? ` ${RED}grader error: ${result.graderError}${RESET}`\n : ` grader error: ${result.graderError}`,\n );\n }\n\n for (const exp of result.expectations) {\n const marker = exp.passed\n ? color ? `${GREEN}✓${RESET}` : \"✓\"\n : color ? `${RED}✗${RESET}` : \"✗\";\n lines.push(` ├─ ${exp.text} ${marker}`);\n if (!exp.passed || exp.evidence) {\n lines.push(\n color\n ? ` │ ${DIM}${exp.evidence}${RESET}`\n : ` │ ${exp.evidence}`,\n );\n }\n }\n\n const pct = (result.summary.passRate * 100).toFixed(0);\n lines.push(\n ` └─ ${result.summary.passed}/${result.summary.total} (${pct}%) expectations`,\n );\n lines.push(\"\");\n }\n\n const overallPct = (report.summary.passRate * 100).toFixed(0);\n lines.push(\n `Overall: ${report.summary.passed}/${report.summary.total} (${overallPct}%) expectations passed`,\n );\n\n return lines.join(\"\\n\").trimEnd();\n}\n\n/** True when every graded rep passed all expectations without grader errors. */\nexport function gradingReportPassed(report: SuiteGradingReport): boolean {\n return report.results.every(\n (r) => !r.graderError && r.summary.failed === 0 && r.summary.total > 0,\n );\n}\n","/**\n * Console (ANSI) report formatter.\n */\n\nimport type { RenderableRow } from \"./types\";\n\nconst RESET = \"\\x1b[0m\";\nconst GREEN = \"\\x1b[32m\";\nconst RED = \"\\x1b[31m\";\nconst YELLOW = \"\\x1b[33m\";\nconst DIM = \"\\x1b[2m\";\n\n/**\n * Render renderable rows as ANSI-colored console output.\n *\n * @param color When false, emit plain text without escape codes.\n */\nexport function formatConsole(rows: RenderableRow[], color = true): string {\n const lines: string[] = [];\n\n for (const row of rows) {\n const status = row.passed\n ? color ? `${GREEN}PASS${RESET}` : \"PASS\"\n : color ? `${RED}FAIL${RESET}` : \"FAIL\";\n\n const crashNote =\n row.adapterErrors > 0\n ? ` ${color ? YELLOW : \"\"}[${row.adapterErrors} adapter errors]${color ? RESET : \"\"}`\n : \"\";\n\n lines.push(`${row.caseId} @ ${row.cellLabel} ${status}${crashNote}`);\n if (row.category) lines.push(` category: ${row.category}`);\n\n for (const stat of row.stats) {\n const marker = stat.meetsThreshold\n ? color ? `${GREEN}✓${RESET}` : \"✓\"\n : color ? `${RED}✗${RESET}` : \"✗\";\n\n const rateStr = formatRate(stat);\n const thresholdPct = (stat.threshold * 100).toFixed(0);\n let line = ` ├─ ${stat.description}: ${rateStr} [threshold ${thresholdPct}%] ${marker}`;\n\n if (stat.delta !== undefined && stat.baselinePassRate !== undefined) {\n const arrow = stat.delta >= 0 ? \"↑\" : \"↓\";\n const basePct = (stat.baselinePassRate * 100).toFixed(0);\n const curPct = (stat.passRate * 100).toFixed(0);\n const deltaPct = (stat.delta * 100).toFixed(0);\n line += ` (${basePct}% → ${curPct}% (${arrow}${deltaPct}%))`;\n }\n\n lines.push(line);\n }\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\").trimEnd();\n}\n\n/** Format pass rate for display, noting when all reps crashed. */\nfunction formatRate(stat: RenderableRow[\"stats\"][number]): string {\n if (stat.evaluatedCount === 0) {\n return `0/${stat.totalReps} (all reps crashed)`;\n }\n const pct = (stat.passRate * 100).toFixed(0);\n return `${stat.passedCount}/${stat.evaluatedCount} (${pct}%)`;\n}\n","/**\n * JSON report formatter (passthrough).\n */\n\nimport type { SuiteReport } from \"../runner/types\";\n\n/**\n * Serialize a suite report as indented JSON (no transformation).\n *\n * Used by `--format json` and `--output` persistence.\n */\nexport function formatJson(report: SuiteReport): string {\n return JSON.stringify(report, null, 2);\n}\n","/**\n * Markdown (GFM) report formatter.\n */\n\nimport type { RenderableRow } from \"./types\";\n\n/** Render renderable rows as a GitHub-flavored markdown report. */\nexport function formatMarkdown(rows: RenderableRow[]): string {\n const lines: string[] = [\"# Harness Eval Report\", \"\"];\n\n for (const row of rows) {\n const status = row.passed ? \"PASS\" : \"FAIL\";\n const crashNote =\n row.adapterErrors > 0 ? ` (${row.adapterErrors} adapter errors)` : \"\";\n\n lines.push(`## ${row.caseId} @ ${row.cellLabel} — ${status}${crashNote}`);\n if (row.category) lines.push(`**Category:** ${row.category}`);\n if (row.notes) {\n lines.push(\"<details><summary>Notes</summary>\", row.notes, \"</details>\");\n }\n lines.push(\"\");\n lines.push(\"| Assertion | Result | Threshold | Status |\");\n lines.push(\"| --- | --- | --- | --- |\");\n\n for (const stat of row.stats) {\n const rateStr = formatRate(stat);\n const threshold = `${(stat.threshold * 100).toFixed(0)}%`;\n const statusCell = stat.meetsThreshold ? \"✓\" : \"✗\";\n let result = rateStr;\n if (stat.delta !== undefined && stat.baselinePassRate !== undefined) {\n const base = (stat.baselinePassRate * 100).toFixed(0);\n const cur = (stat.passRate * 100).toFixed(0);\n const d = (stat.delta * 100).toFixed(0);\n const sign = stat.delta >= 0 ? \"+\" : \"\";\n result += ` (${base}% → ${cur}%, ${sign}${d}%)`;\n }\n lines.push(`| ${stat.description} | ${result} | ${threshold} | ${statusCell} |`);\n }\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\").trimEnd();\n}\n\n/** Format pass rate for markdown tables, noting when all reps crashed. */\nfunction formatRate(stat: RenderableRow[\"stats\"][number]): string {\n if (stat.evaluatedCount === 0) {\n return `0/${stat.totalReps} (all reps crashed)`;\n }\n const pct = (stat.passRate * 100).toFixed(0);\n return `${stat.passedCount}/${stat.evaluatedCount} (${pct}%)`;\n}\n","/**\n * SuiteReport → RenderableRow[] intermediate model.\n */\n\nimport type { CellReport, SuiteReport } from \"../runner/types\";\nimport type { RenderableRow, RenderableStat } from \"./types\";\n\n/** Map a suite report to formatter-ready rows (one per cell). */\nexport function toRenderableRows(report: SuiteReport): RenderableRow[] {\n return report.cells.map((cell) => cellToRow(cell));\n}\n\n/**\n * Attach baseline pass-rate deltas to matching rows.\n *\n * Rows without a matching baseline cell are returned unchanged.\n */\nexport function applyBaseline(\n rows: RenderableRow[],\n baseline: SuiteReport,\n): RenderableRow[] {\n const baselineMap = new Map(\n baseline.cells.map((c) => [`${c.caseId}::${c.cell.label}`, c]),\n );\n\n return rows.map((row) => {\n const baseCell = baselineMap.get(`${row.caseId}::${row.cellLabel}`);\n if (!baseCell) return row;\n\n const stats = row.stats.map((stat, i) => {\n const baseStat = baseCell.assertionStats[i];\n if (!baseStat) return stat;\n const delta = stat.passRate - baseStat.passRate;\n return {\n ...stat,\n baselinePassRate: baseStat.passRate,\n delta,\n };\n });\n\n return { ...row, stats };\n });\n}\n\n/** Convert one {@link CellReport} to a {@link RenderableRow}. */\nfunction cellToRow(cell: CellReport): RenderableRow {\n const totalReps = cell.repetitions.length;\n\n const stats: RenderableStat[] = cell.assertionStats.map((s) => ({\n description: s.description,\n threshold: s.threshold,\n passedCount: s.passedCount,\n evaluatedCount: s.evaluatedCount,\n totalReps,\n adapterErrors: cell.adapterErrors,\n passRate: s.passRate,\n meetsThreshold: s.meetsThreshold,\n }));\n\n return {\n caseId: cell.caseId,\n category: cell.category,\n notes: cell.notes,\n cellLabel: cell.cell.label,\n passed: cell.passed,\n adapterErrors: cell.adapterErrors,\n totalReps,\n stats,\n };\n}\n","/**\n * Reporter public API.\n */\n\nimport type { SuiteReport } from \"../runner/types\";\nimport { formatConsole } from \"./format-console\";\nimport { formatJson } from \"./format-json\";\nimport { formatMarkdown } from \"./format-markdown\";\nimport { applyBaseline, toRenderableRows } from \"./renderable\";\nimport type { ReporterOptions } from \"./types\";\n\nexport type { ReporterOptions, ReportFormat, RenderableRow } from \"./types\";\n\n/**\n * Format a {@link SuiteReport} for console, markdown, or JSON output.\n *\n * JSON format bypasses the renderable intermediate model and serializes the\n * report directly. Console and markdown apply optional baseline deltas.\n */\nexport function formatReport(\n report: SuiteReport,\n options: ReporterOptions,\n): string {\n if (options.format === \"json\") {\n return formatJson(report);\n }\n\n let rows = toRenderableRows(report);\n if (options.baseline) {\n rows = applyBaseline(rows, options.baseline);\n }\n\n const useColor =\n options.color ?? (options.format === \"console\");\n\n if (options.format === \"markdown\") {\n return formatMarkdown(rows);\n }\n\n return formatConsole(rows, useColor);\n}\n","/**\n * Normalize harness and suite data into Vertex protojson wire shapes.\n *\n * Accepts both {@link ToolCall} (harness runtime) and suite YAML reference\n * step shapes, producing consistent {@link ProtojsonTrajectory} objects for\n * EvaluateInstances and envelope export.\n */\n\nimport type { ToolCall } from \"../types/trajectory\";\nimport type { ProtojsonTrajectory, ReferenceToolNameMode } from \"../types/eval-interchange\";\n\n/** Input accepted by trajectory normalizers — harness or suite reference steps. */\nexport type TrajectoryInput =\n | ToolCall[]\n | Array<{ tool_name: string; tool_input: unknown | string }>;\n\n/**\n * Serialize tool arguments to the Vertex wire string format.\n *\n * Already-string inputs pass through unchanged (e.g. pre-serialized reference\n * steps). Objects and nullish values become JSON strings; empty input becomes `{}`.\n *\n * @param args - Tool arguments from harness or suite YAML.\n * @returns JSON string suitable for {@link ProtojsonToolCall.toolInput}.\n */\nexport function serializeToolInput(args: unknown): string {\n if (typeof args === \"string\") return args;\n return JSON.stringify(args ?? {});\n}\n\n/**\n * Normalize a tool name according to suite reference configuration.\n *\n * In `\"bare\"` mode, strips the MCP namespace prefix (`mcp__api__foo` → `foo`)\n * so reference trajectories authored with bare names match harness tool names.\n *\n * @param toolName - Raw tool name from harness or suite.\n * @param mode - `\"harness\"` preserves the name; `\"bare\"` strips after last `__`.\n */\nexport function normalizeReferenceToolName(\n toolName: string,\n mode: ReferenceToolNameMode,\n): string {\n if (mode !== \"bare\") return toolName;\n\n const separator = toolName.lastIndexOf(\"__\");\n if (separator === -1) return toolName;\n return toolName.slice(separator + 2);\n}\n\n/**\n * Convert a harness or suite trajectory into Vertex protojson wire format.\n *\n * `toolNameMode` controls MCP prefix stripping for every tool name in the\n * trajectory. Suite reference steps and predicted harness tool calls use the\n * same mode so comparisons stay consistent across metrics and instances.\n *\n * @param trajectory - Tool calls in harness or YAML reference shape.\n * @param options.toolNameMode - `\"harness\"` keeps full names; `\"bare\"` strips after last `__`.\n */\nexport function toProtojsonTrajectory(\n trajectory: TrajectoryInput,\n options: { toolNameMode?: ReferenceToolNameMode } = {},\n): ProtojsonTrajectory {\n const toolNameMode = options.toolNameMode ?? \"harness\";\n\n return {\n toolCalls: trajectory.map((toolCall) => {\n const name = \"name\" in toolCall ? toolCall.name : toolCall.tool_name;\n const args = \"args\" in toolCall ? toolCall.args : toolCall.tool_input;\n\n return {\n toolName: normalizeReferenceToolName(name, toolNameMode),\n toolInput: serializeToolInput(args),\n };\n }),\n };\n}\n","/**\n * Build Vertex Trajectory*Instance protojson wire objects.\n *\n * Each trajectory metric in Vertex EvaluateInstances expects a specific\n * protobuf message. This module constructs all six instance payloads from\n * one predicted/reference pair so callers can batch-upload via JSONL.\n */\n\nimport { toProtojsonTrajectory } from \"../normalize\";\nimport type {\n ProtojsonTrajectory,\n ReferenceToolNameMode,\n TrajectoryInstancesJson,\n TrajectoryPairInstanceJson,\n TrajectorySingleToolUseInstanceJson,\n} from \"../../types/eval-interchange\";\nimport type { ToolCall } from \"../../types/trajectory\";\n\ntype ReferenceStep = { tool_name: string; tool_input: unknown };\n\n/**\n * Build a pair instance with predicted and reference trajectories.\n *\n * Both sides use the same `referenceToolNameMode` so wire payloads align with\n * {@link toHarnessMetrics} and Vertex EvaluateInstances sees comparable names.\n * In `\"bare\"` mode, MCP prefixes are stripped on predicted and reference alike.\n */\nfunction pairInstance(\n predicted: ToolCall[],\n reference: ReferenceStep[],\n referenceToolNameMode: ReferenceToolNameMode,\n): TrajectoryPairInstanceJson {\n return {\n predictedTrajectory: toProtojsonTrajectory(predicted, {\n toolNameMode: referenceToolNameMode,\n }),\n referenceTrajectory: toProtojsonTrajectory(reference, {\n toolNameMode: referenceToolNameMode,\n }),\n };\n}\n\n/**\n * Build all Trajectory*Instance payloads for one predicted/reference pair.\n *\n * Pair metrics (exact, in-order, any-order, precision, recall) share the\n * same trajectory pair; single-tool-use omits the reference trajectory\n * per Vertex API shape.\n */\nexport function toTrajectoryInstances(options: {\n predicted: ToolCall[];\n reference: ReferenceStep[];\n referenceToolNameMode?: ReferenceToolNameMode;\n}): TrajectoryInstancesJson {\n const referenceToolNameMode = options.referenceToolNameMode ?? \"harness\";\n const pair = pairInstance(\n options.predicted,\n options.reference,\n referenceToolNameMode,\n );\n\n return {\n exactMatch: pair,\n inOrderMatch: pair,\n anyOrderMatch: pair,\n precision: pair,\n recall: pair,\n singleToolUse: {\n predictedTrajectory: pair.predictedTrajectory,\n },\n };\n}\n\n/**\n * Convert suite reference steps to cell-level protojson trajectory export.\n */\nexport function toReferenceTrajectory(\n reference: ReferenceStep[],\n referenceToolNameMode: ReferenceToolNameMode = \"harness\",\n): ProtojsonTrajectory {\n return toProtojsonTrajectory(reference, { toolNameMode: referenceToolNameMode });\n}\n\n/**\n * Map a trajectory instance key to the Vertex protobuf message type name.\n *\n * Used as `messageType` in {@link InstancesJsonlRow} for EvaluateInstances batching.\n */\nexport function trajectoryInstanceMessageType(\n key: keyof TrajectoryInstancesJson,\n): string {\n switch (key) {\n case \"exactMatch\":\n return \"TrajectoryExactMatchInstance\";\n case \"inOrderMatch\":\n return \"TrajectoryInOrderMatchInstance\";\n case \"anyOrderMatch\":\n return \"TrajectoryAnyOrderMatchInstance\";\n case \"precision\":\n return \"TrajectoryPrecisionInstance\";\n case \"recall\":\n return \"TrajectoryRecallInstance\";\n case \"singleToolUse\":\n return \"TrajectorySingleToolUseInstance\";\n }\n}\n\nexport type { TrajectoryPairInstanceJson, TrajectorySingleToolUseInstanceJson };\n","/**\n * Build Vertex EvaluationInstance protojson wire objects.\n *\n * Maps harness prompt/response text into the InstanceData wrapper shape\n * expected by EvaluateInstances for text-based metrics.\n */\n\nimport type { EvaluationInstanceJson } from \"../../types/eval-interchange\";\n\n/**\n * Build an EvaluationInstance protojson object from harness strings.\n *\n * Omitted fields are excluded from the output object rather than set to\n * empty wrappers — protojson omits unset optional fields.\n *\n * @param options.prompt - Case prompt sent to the agent.\n * @param options.response - Final agent response from the trajectory.\n * @param options.reference - Optional reference answer text (rare in harness eval).\n */\nexport function toEvaluationInstance(options: {\n prompt?: string;\n response?: string;\n reference?: string;\n}): EvaluationInstanceJson {\n const instance: EvaluationInstanceJson = {};\n\n if (options.prompt !== undefined) {\n instance.prompt = { text: options.prompt };\n }\n if (options.response !== undefined) {\n instance.response = { text: options.response };\n }\n if (options.reference !== undefined) {\n instance.reference = { text: options.reference };\n }\n\n return instance;\n}\n","/**\n * Trajectory-level metrics for comparing predicted and reference tool-call sequences.\n *\n * Aligns with Vertex AI EvaluationService trajectory metrics (exact match,\n * in-order, any-order, precision, recall, single tool use). Tool calls are\n * compared by `(tool_name, serialized tool_input)` identity after normalization.\n *\n * Binary metrics return 0 or 1; precision and recall return fractions in [0, 1].\n */\n\nimport { serializeToolInput } from \"../eval-interchange/normalize\";\n\n/** Canonical wire tool call used internally for comparison. */\nexport interface WireToolCall {\n tool_name: string;\n tool_input: string;\n}\n\n/** All trajectory metric scores for one predicted/reference pair. */\nexport interface TrajectoryMetrics {\n trajectory_exact_match: number;\n trajectory_in_order_match: number;\n trajectory_any_order_match: number;\n trajectory_precision: number;\n trajectory_recall: number;\n trajectory_single_tool_use: number;\n}\n\n/** Input accepted by trajectory metrics — wire or harness/YAML shapes. */\nexport type TrajectoryInput =\n | WireToolCall[]\n | Array<{ tool_name: string; tool_input: unknown | string }>;\n\nfunction normalizeToolCall(\n toolCall: TrajectoryInput[number],\n): WireToolCall {\n if (typeof toolCall.tool_input === \"string\") {\n return {\n tool_name: toolCall.tool_name,\n tool_input: toolCall.tool_input,\n };\n }\n\n return {\n tool_name: toolCall.tool_name,\n tool_input: serializeToolInput(toolCall.tool_input),\n };\n}\n\nfunction normalizeTrajectory(trajectory: TrajectoryInput): WireToolCall[] {\n return trajectory.map(normalizeToolCall);\n}\n\n/** Stable composite key for multiset and equality checks. */\nfunction toolCallKey(toolCall: WireToolCall): string {\n return `${toolCall.tool_name}\\0${toolCall.tool_input}`;\n}\n\n/**\n * Count predicted tool calls that appear in reference (multiset intersection).\n *\n * Duplicate tool calls are matched one-for-one; order does not matter.\n */\nfunction multisetIntersectionSize(\n predicted: WireToolCall[],\n reference: WireToolCall[],\n): number {\n const refCounts = new Map<string, number>();\n for (const toolCall of reference) {\n const key = toolCallKey(toolCall);\n refCounts.set(key, (refCounts.get(key) ?? 0) + 1);\n }\n\n let matched = 0;\n for (const toolCall of predicted) {\n const key = toolCallKey(toolCall);\n const count = refCounts.get(key) ?? 0;\n if (count > 0) {\n matched += 1;\n refCounts.set(key, count - 1);\n }\n }\n\n return matched;\n}\n\n/**\n * Whether reference appears as a subsequence of predicted (order preserved).\n *\n * Extra predicted calls between reference steps are allowed (in-order match\n * semantics per Vertex).\n */\nfunction isSubsequence(\n predicted: WireToolCall[],\n reference: WireToolCall[],\n): boolean {\n let refIndex = 0;\n for (const toolCall of predicted) {\n if (refIndex >= reference.length) break;\n if (toolCallKey(toolCall) === toolCallKey(reference[refIndex]!)) {\n refIndex += 1;\n }\n }\n return refIndex === reference.length;\n}\n\nfunction arraysEqual(left: WireToolCall[], right: WireToolCall[]): boolean {\n if (left.length !== right.length) return false;\n return left.every((toolCall, index) => {\n const other = right[index]!;\n return toolCallKey(toolCall) === toolCallKey(other);\n });\n}\n\n/** Exact sequence equality after normalization. */\nexport function trajectoryExactMatch(\n predicted: TrajectoryInput,\n reference: TrajectoryInput,\n): number {\n const predictedNorm = normalizeTrajectory(predicted);\n const referenceNorm = normalizeTrajectory(reference);\n return arraysEqual(predictedNorm, referenceNorm) ? 1 : 0;\n}\n\n/** Reference is a subsequence of predicted (order preserved, extras allowed). */\nexport function trajectoryInOrderMatch(\n predicted: TrajectoryInput,\n reference: TrajectoryInput,\n): number {\n const predictedNorm = normalizeTrajectory(predicted);\n const referenceNorm = normalizeTrajectory(reference);\n return isSubsequence(predictedNorm, referenceNorm) ? 1 : 0;\n}\n\n/** Same multiset of tool calls; length must match. */\nexport function trajectoryAnyOrderMatch(\n predicted: TrajectoryInput,\n reference: TrajectoryInput,\n): number {\n const predictedNorm = normalizeTrajectory(predicted);\n const referenceNorm = normalizeTrajectory(reference);\n if (predictedNorm.length !== referenceNorm.length) return 0;\n\n const predictedKeys = predictedNorm.map(toolCallKey).sort();\n const referenceKeys = referenceNorm.map(toolCallKey).sort();\n return predictedKeys.every((key, index) => key === referenceKeys[index])\n ? 1\n : 0;\n}\n\n/**\n * Fraction of predicted tool calls that appear in reference (multiset).\n *\n * Returns 1 when both trajectories are empty.\n */\nexport function trajectoryPrecision(\n predicted: TrajectoryInput,\n reference: TrajectoryInput,\n): number {\n const predictedNorm = normalizeTrajectory(predicted);\n if (predictedNorm.length === 0) return reference.length === 0 ? 1 : 0;\n\n const referenceNorm = normalizeTrajectory(reference);\n return multisetIntersectionSize(predictedNorm, referenceNorm) /\n predictedNorm.length;\n}\n\n/**\n * Fraction of reference tool calls matched in predicted (multiset recall).\n *\n * Returns 1 when reference is empty and predicted is empty.\n */\nexport function trajectoryRecall(\n predicted: TrajectoryInput,\n reference: TrajectoryInput,\n): number {\n const referenceNorm = normalizeTrajectory(reference);\n if (referenceNorm.length === 0) return predicted.length === 0 ? 1 : 0;\n\n const predictedNorm = normalizeTrajectory(predicted);\n return multisetIntersectionSize(predictedNorm, referenceNorm) /\n referenceNorm.length;\n}\n\n/** Both trajectories have exactly one call and they match. */\nexport function trajectorySingleToolUse(\n predicted: TrajectoryInput,\n reference: TrajectoryInput,\n): number {\n const predictedNorm = normalizeTrajectory(predicted);\n const referenceNorm = normalizeTrajectory(reference);\n if (predictedNorm.length !== 1 || referenceNorm.length !== 1) return 0;\n return toolCallKey(predictedNorm[0]!) === toolCallKey(referenceNorm[0]!)\n ? 1\n : 0;\n}\n\n/** Compute all trajectory metrics in one pass. */\nexport function computeTrajectoryMetrics(\n predicted: TrajectoryInput,\n reference: TrajectoryInput,\n): TrajectoryMetrics {\n return {\n trajectory_exact_match: trajectoryExactMatch(predicted, reference),\n trajectory_in_order_match: trajectoryInOrderMatch(predicted, reference),\n trajectory_any_order_match: trajectoryAnyOrderMatch(predicted, reference),\n trajectory_precision: trajectoryPrecision(predicted, reference),\n trajectory_recall: trajectoryRecall(predicted, reference),\n trajectory_single_tool_use: trajectorySingleToolUse(predicted, reference),\n };\n}\n\n/**\n * Parse a wire tool_input string to JSON, or return the raw string on failure.\n *\n * Exported for tool-call metrics that need structured arg comparison.\n */\nfunction parseToolInput(toolInput: string): unknown {\n try {\n return JSON.parse(toolInput) as unknown;\n } catch {\n return toolInput;\n }\n}\n\nexport { parseToolInput };\n","/**\n * Harness-owned trajectory metric scores in Vertex camelCase field names.\n *\n * Wraps {@link computeTrajectoryMetrics} for envelope export. External\n * systems can compare harness-precomputed scores against Vertex EvaluateInstances\n * results without reimplementing trajectory matching logic.\n */\n\nimport { computeTrajectoryMetrics } from \"../../metrics/trajectory\";\nimport { normalizeReferenceToolName } from \"../normalize\";\nimport type { HarnessMetrics, ReferenceToolNameMode } from \"../../types/eval-interchange\";\nimport type { ToolCall } from \"../../types/trajectory\";\n\n/** Suite YAML reference step shape accepted by metric computation. */\ntype ReferenceStep = { tool_name: string; tool_input: unknown };\n\n/**\n * Compute trajectory metrics and map snake_case keys to Vertex camelCase.\n *\n * When `referenceToolNameMode` is `\"bare\"`, both predicted and reference tool\n * names are stripped to the suffix after the last `__` so suite reference steps\n * authored with bare names (e.g. `ListLandingZones`) match harness MCP names\n * (e.g. `mcp__plugin__ListLandingZones`).\n *\n * @param predicted - Tool calls from the harness trajectory view.\n * @param reference - Reference steps from suite YAML.\n * @param options.referenceToolNameMode - Name normalization mode from suite YAML.\n */\nexport function toHarnessMetrics(\n predicted: ToolCall[],\n reference: ReferenceStep[],\n options: { referenceToolNameMode?: ReferenceToolNameMode } = {},\n): HarnessMetrics {\n const referenceToolNameMode = options.referenceToolNameMode ?? \"harness\";\n\n const metrics = computeTrajectoryMetrics(\n predicted.map((toolCall) => ({\n tool_name: normalizeReferenceToolName(toolCall.name, referenceToolNameMode),\n tool_input: toolCall.args,\n })),\n reference.map((step) => ({\n tool_name: normalizeReferenceToolName(step.tool_name, referenceToolNameMode),\n tool_input: step.tool_input,\n })),\n );\n\n return {\n trajectoryExactMatch: metrics.trajectory_exact_match,\n trajectoryInOrderMatch: metrics.trajectory_in_order_match,\n trajectoryAnyOrderMatch: metrics.trajectory_any_order_match,\n trajectoryPrecision: metrics.trajectory_precision,\n trajectoryRecall: metrics.trajectory_recall,\n trajectorySingleToolUse: metrics.trajectory_single_tool_use,\n };\n}\n","/**\n * Enrich eval repetitions with Vertex protojson interchange fields.\n *\n * Called during envelope build for each successful repetition. Adds\n * `evaluationInstance`, optional `trajectoryInstances` / `harnessMetrics`\n * when a suite reference exists, and Vertex-style `latencySeconds` / `failure`\n * flags derived from trajectory success.\n */\n\nimport { toEvaluationInstance } from \"./protojson/evaluation-instance\";\nimport { toHarnessMetrics } from \"./protojson/harness-metrics\";\nimport { toTrajectoryInstances } from \"./protojson/trajectory-instances\";\nimport type { EvalRepetition } from \"../types/eval-record\";\nimport type { ReferenceTrajectoryConfig } from \"../types/eval-interchange\";\nimport type { ToolCall } from \"../types/trajectory\";\n\n/** Extract reference steps from suite config when present. */\nfunction referenceSteps(\n reference?: ReferenceTrajectoryConfig,\n): Array<{ tool_name: string; tool_input: unknown }> | undefined {\n return reference?.steps;\n}\n\n/**\n * Attach Vertex protojson interchange fields to one {@link EvalRepetition}.\n *\n * When no trajectory exists (adapter error), sets `failure: 1` and skips\n * protojson payloads. Trajectory instances and harness metrics are only\n * computed when the suite defines a non-empty reference trajectory.\n *\n * @param repetition - Base repetition from the runner (trajectory, assertions, grades).\n * @param options.prompt - Case prompt for EvaluationInstance.\n * @param options.reference - Suite reference trajectory config, if any.\n */\nexport function enrichRepetitionWithProtojson(\n repetition: EvalRepetition,\n options: {\n prompt?: string;\n reference?: ReferenceTrajectoryConfig;\n } = {},\n): EvalRepetition {\n if (!repetition.trajectory) {\n return {\n ...repetition,\n failure: 1,\n };\n }\n\n const predicted = repetition.trajectory.toolCalls;\n const referenceStepsList = referenceSteps(options.reference);\n const referenceToolNameMode = options.reference?.tool_name_mode ?? \"harness\";\n\n const enriched: EvalRepetition = {\n ...repetition,\n evaluationInstance: toEvaluationInstance({\n prompt: options.prompt,\n response: repetition.trajectory.finalResponse,\n }),\n // Vertex EvaluateInstances expects seconds; harness stores milliseconds.\n latencySeconds: repetition.trajectory.usage.durationMs / 1000,\n failure: repetition.trajectory.success ? 0 : 1,\n };\n\n if (referenceStepsList?.length) {\n enriched.trajectoryInstances = toTrajectoryInstances({\n predicted,\n reference: referenceStepsList,\n referenceToolNameMode,\n });\n enriched.harnessMetrics = toHarnessMetrics(predicted, referenceStepsList, {\n referenceToolNameMode,\n });\n }\n\n return enriched;\n}\n\n/**\n * Return predicted tool calls from a repetition, or an empty array.\n *\n * Convenience for metrics and tests that need harness-shaped tool calls\n * without null-checking trajectory.\n */\nexport function predictedToolCalls(repetition: EvalRepetition): ToolCall[] {\n return repetition.trajectory?.toolCalls ?? [];\n}\n","/**\n * Build {@link EvalRunEnvelope} from harness-eval run and grading reports.\n *\n * This is the canonical export path from in-process or on-disk {@link SuiteReport}\n * JSON into the cross-harness eval record contract. It stitches together:\n *\n * - Behavioral assertion results from the runner\n * - Optional outcome grades from the LLM grader\n * - Vertex protojson interchange fields via {@link enrichRepetitionWithProtojson}\n * - Optional artifacts (transcript, raw stream-json) controlled by build options\n *\n * Downstream consumers include CI gates, databases, and the `harness-eval envelope`\n * CLI projection commands.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport { readFile } from \"node:fs/promises\";\nimport { createHash } from \"node:crypto\";\n\nimport { trajectoryToTranscript } from \"../grader/transcript\";\nimport { toReferenceTrajectory } from \"../eval-interchange/protojson/trajectory-instances\";\nimport { enrichRepetitionWithProtojson } from \"../eval-interchange/enrich\";\nimport type { SuiteGradingReport } from \"../grader/types\";\nimport type {\n BuildEvalRunEnvelopeOptions,\n EvalCellResult,\n EvalRepetition,\n EvalRunEnvelope,\n} from \"../types/eval-record\";\nimport {\n EVAL_RUN_SCHEMA_VERSION,\n TRAJECTORY_SCHEMA_VERSION,\n} from \"../types/eval-record\";\nimport type { SuiteReport } from \"../runner/types\";\n\n/**\n * Pull raw stream-json events from an adapter result when the adapter exposes them.\n *\n * Adapters may attach `rawEvents` for debug-only envelope export; this helper\n * avoids coupling the builder to a specific adapter result type.\n */\nfunction extractRawEvents(adapterResult: unknown): unknown[] | undefined {\n if (\n adapterResult !== null &&\n typeof adapterResult === \"object\" &&\n \"rawEvents\" in adapterResult &&\n Array.isArray((adapterResult as { rawEvents: unknown }).rawEvents)\n ) {\n return (adapterResult as { rawEvents: unknown[] }).rawEvents;\n }\n return undefined;\n}\n\n/**\n * Derive cell-level outcome pass from graded repetitions.\n *\n * Returns `undefined` when no repetition was graded (outcome gate not applicable).\n * When graded, every repetition must have zero failed expectations and no grader error.\n *\n * @param _caseId - Reserved for future per-case outcome rules; unused today.\n * @param _cellLabel - Reserved for future per-cell outcome rules; unused today.\n */\nfunction outcomePassForCell(\n _caseId: string,\n _cellLabel: string,\n repetitions: EvalRepetition[],\n): boolean | undefined {\n const graded = repetitions.filter((r) => r.outcomeGrades);\n if (graded.length === 0) return undefined;\n return graded.every(\n (r) =>\n r.outcomeGrades!.error === undefined &&\n r.outcomeGrades!.summary.failed === 0,\n );\n}\n\n/**\n * Convert a {@link SuiteReport} (and optional grading) into a versioned\n * {@link EvalRunEnvelope} for storage or API handoff.\n *\n * @param report - Runner output for one suite execution.\n * @param options - Provenance, grading merge, and artifact inclusion flags.\n * @returns A fully populated envelope with protojson interchange fields on each repetition.\n */\nexport function buildEvalRunEnvelope(\n report: SuiteReport,\n options: BuildEvalRunEnvelopeOptions = {},\n): EvalRunEnvelope {\n // Transcript is on by default — judges and external tools expect it.\n const includeTranscript = options.includeTranscript !== false;\n // Raw stream-json is opt-in: large, vendor-specific, not cross-harness.\n const includeRaw = options.includeRawStreamEvents === true;\n\n const judge =\n options.grading?.judge ?? { id: \"harness-eval/claude-grader\" };\n\n const cells: EvalCellResult[] = report.cells.map((cell) => {\n const prompt = cell.prompt ?? \"\";\n const referenceTrajectoryConfig = cell.reference_trajectory;\n // Cell-level reference is exported in Vertex wire format for DB storage and\n // interchange even when individual repetitions also carry trajectoryInstances.\n const referenceTrajectory = referenceTrajectoryConfig\n ? toReferenceTrajectory(\n referenceTrajectoryConfig.steps,\n referenceTrajectoryConfig.tool_name_mode ?? \"harness\",\n )\n : undefined;\n const repetitions: EvalRepetition[] = cell.repetitions.map((rep) => {\n const base: EvalRepetition = {\n repetitionIndex: rep.repetitionIndex,\n durationMs: rep.durationMs,\n assertionResults: rep.assertionResults,\n };\n\n if (rep.error) {\n base.error = {\n message: rep.error.message,\n diagnostics: rep.error.diagnostics,\n };\n return base;\n }\n\n if (rep.adapterResult) {\n base.trajectory = {\n ...rep.adapterResult.view,\n schemaVersion: TRAJECTORY_SCHEMA_VERSION,\n };\n base.diagnostics = rep.adapterResult.diagnostics;\n\n const artifacts: EvalRepetition[\"artifacts\"] = {};\n if (includeTranscript) {\n artifacts.transcript = trajectoryToTranscript(\n rep.adapterResult.view,\n prompt,\n );\n }\n if (includeRaw) {\n const raw = extractRawEvents(rep.adapterResult);\n if (raw) artifacts.rawStreamEvents = raw;\n }\n if (Object.keys(artifacts).length > 0) {\n base.artifacts = artifacts;\n }\n }\n\n // Match grading rows by the same composite key the grader uses: case × cell × rep.\n const graded = options.grading?.results.find(\n (r) =>\n r.caseId === cell.caseId &&\n r.cellLabel === cell.cell.label &&\n r.repetitionIndex === rep.repetitionIndex,\n );\n\n if (graded) {\n base.outcomeGrades = {\n judge,\n expectations: graded.expectations,\n summary: graded.summary,\n evalFeedback: graded.evalFeedback,\n error: graded.graderError,\n };\n }\n\n // Protojson fields (evaluationInstance, trajectoryInstances, harnessMetrics)\n // are derived from trajectory + suite reference config, not from the runner report.\n return enrichRepetitionWithProtojson(base, {\n prompt,\n reference: referenceTrajectoryConfig,\n });\n });\n\n return {\n caseId: cell.caseId,\n category: cell.category,\n notes: cell.notes,\n prompt: cell.prompt,\n expectations: cell.expectations,\n referenceTrajectory,\n humanRatings: cell.human_ratings,\n cellLabel: cell.cell.label,\n axes: cell.cell.axes,\n assertionStats: cell.assertionStats,\n adapterErrors: cell.adapterErrors,\n behavioralPass: cell.passed,\n outcomePass: outcomePassForCell(\n cell.caseId,\n cell.cell.label,\n repetitions,\n ),\n repetitions,\n };\n });\n\n const cellsPassed = cells.filter((c) => c.behavioralPass).length;\n const gradedCells = cells.filter((c) => c.outcomePass !== undefined);\n // Run-level outcomePass is omitted when grading was not run for any cell.\n const outcomePass =\n gradedCells.length > 0\n ? gradedCells.every((c) => c.outcomePass === true)\n : undefined;\n\n return {\n schemaVersion: EVAL_RUN_SCHEMA_VERSION,\n runId: options.runId ?? randomUUID(),\n startedAt: report.startedAt,\n durationMs: report.durationMs,\n suite: options.suite,\n harness: {\n adapter: options.harness?.adapter ?? \"claude-code\",\n frameworkVersion: options.harness?.frameworkVersion,\n harnessVersion: options.harness?.harnessVersion,\n },\n provenance: options.provenance,\n summary: {\n cellsTotal: cells.length,\n cellsPassed,\n behavioralPass: cellsPassed === cells.length,\n outcomePass,\n },\n cells,\n };\n}\n\n/**\n * Build an envelope from on-disk runner and grader JSON artifacts.\n *\n * Reads `reportPath` as a {@link SuiteReport}. When `gradingPath` is set, merges\n * outcome grades from a {@link SuiteGradingReport}. When `suitePath` is set,\n * attaches suite URI and SHA-256 content hash for reproducibility.\n *\n * @param reportPath - Path to the suite run report JSON from `harness-eval run`.\n * @param options - Same build options as {@link buildEvalRunEnvelope}, plus file paths.\n */\nexport async function buildEvalRunEnvelopeFromFiles(\n reportPath: string,\n options: BuildEvalRunEnvelopeOptions & {\n gradingPath?: string;\n suitePath?: string;\n } = {},\n): Promise<EvalRunEnvelope> {\n const reportText = await readFile(reportPath, \"utf8\");\n const report = JSON.parse(reportText) as SuiteReport;\n\n let grading: BuildEvalRunEnvelopeOptions[\"grading\"] | undefined =\n options.grading;\n\n if (options.gradingPath) {\n const gradingText = await readFile(options.gradingPath, \"utf8\");\n const parsed = JSON.parse(gradingText) as SuiteGradingReport;\n grading = {\n gradedAt: parsed.gradedAt,\n sourceReport: parsed.sourceReport,\n results: parsed.results,\n judge: options.grading?.judge ?? { id: \"harness-eval/claude-grader\" },\n };\n }\n\n let suite = options.suite;\n if (options.suitePath) {\n const content = await readFile(options.suitePath, \"utf8\");\n suite = {\n ...suite,\n uri: options.suitePath,\n contentHash: createHash(\"sha256\").update(content).digest(\"hex\"),\n };\n }\n\n return buildEvalRunEnvelope(report, {\n ...options,\n suite,\n grading,\n });\n}\n","/**\n * Envelope projection methods for Vertex protojson interchange output.\n *\n * Flatten a nested {@link EvalRunEnvelope} into JSONL-friendly rows for:\n *\n * - `trajectory` projection — one {@link EvalDatasetRow} per repetition\n * - `instances` projection — one {@link InstancesJsonlRow} per trajectory metric\n *\n * Used by `harness-eval envelope --projection trajectory|instances`.\n */\n\nimport type {\n EvalDatasetRow,\n InstancesJsonlRow,\n TrajectoryInstanceMetricKey,\n TrajectoryInstancesJson,\n} from \"../types/eval-interchange\";\nimport type {\n EvalCellResult,\n EvalRepetition,\n EvalRunEnvelope,\n} from \"../types/eval-record\";\nimport { trajectoryInstanceMessageType } from \"./protojson/trajectory-instances\";\n\n/** Trajectory instance keys emitted in stable order for JSONL export. */\nconst TRAJECTORY_INSTANCE_KEYS: TrajectoryInstanceMetricKey[] = [\n \"exactMatch\",\n \"inOrderMatch\",\n \"anyOrderMatch\",\n \"precision\",\n \"recall\",\n \"singleToolUse\",\n];\n\n/**\n * Flatten one repetition into a trajectory dataset row.\n *\n * Pulls prompt from the cell, response from evaluationInstance, and falls\n * back to duration-based latency when enrich did not set latencySeconds.\n */\nexport function repetitionToDatasetRow(\n cell: EvalCellResult,\n repetition: EvalRepetition,\n): EvalDatasetRow {\n return {\n caseId: cell.caseId,\n repetitionIndex: repetition.repetitionIndex,\n prompt: cell.prompt,\n response: repetition.evaluationInstance?.response?.text,\n evaluationInstance: repetition.evaluationInstance,\n latencySeconds: repetition.latencySeconds ?? repetition.durationMs / 1000,\n failure: repetition.failure ?? (repetition.trajectory?.success ? 0 : 1),\n humanRatings: cell.humanRatings,\n };\n}\n\n/**\n * Expand one repetition into type-tagged instance rows for EvaluateInstances.\n *\n * Returns an empty array when the repetition has no reference trajectory\n * (and therefore no trajectoryInstances block).\n */\nexport function repetitionToInstanceRows(\n cell: EvalCellResult,\n repetition: EvalRepetition,\n): InstancesJsonlRow[] {\n if (!repetition.trajectoryInstances) return [];\n\n const rows: InstancesJsonlRow[] = [];\n for (const key of TRAJECTORY_INSTANCE_KEYS) {\n const instance = repetition.trajectoryInstances[key];\n if (!instance) continue;\n\n rows.push({\n messageType: trajectoryInstanceMessageType(key),\n caseId: cell.caseId,\n repetitionIndex: repetition.repetitionIndex,\n instance,\n });\n }\n\n return rows;\n}\n\n/**\n * Trajectory projection — all repetitions in the envelope as dataset rows.\n */\nexport function toTrajectory(envelope: EvalRunEnvelope): EvalDatasetRow[] {\n const rows: EvalDatasetRow[] = [];\n for (const cell of envelope.cells) {\n for (const repetition of cell.repetitions) {\n rows.push(repetitionToDatasetRow(cell, repetition));\n }\n }\n return rows;\n}\n\n/**\n * Instances projection — all trajectory metric instances as JSONL rows.\n */\nexport function toInstancesJsonl(envelope: EvalRunEnvelope): InstancesJsonlRow[] {\n const rows: InstancesJsonlRow[] = [];\n for (const cell of envelope.cells) {\n for (const repetition of cell.repetitions) {\n rows.push(...repetitionToInstanceRows(cell, repetition));\n }\n }\n return rows;\n}\n\n/** Return which trajectory metric keys are populated on an instances block. */\nexport function listTrajectoryInstanceKeys(\n instances: TrajectoryInstancesJson,\n): TrajectoryInstanceMetricKey[] {\n return TRAJECTORY_INSTANCE_KEYS.filter((key) => instances[key] !== undefined);\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"suite-Dlzl-HI0.js","names":["predicateMatches","_exhaustive"],"sources":["../src/assertions/patterns.ts","../src/assertions/predicates.ts","../src/assertions/tool-calls.ts","../src/assertions/behavior.ts","../src/assertions/compound.ts","../src/assertions/evaluator.ts","../src/adapters/registry.ts","../src/config/resolve-config.ts","../src/runner/case.ts","../src/runner/limit.ts","../src/runner/suite.ts"],"sourcesContent":["/**\n * Tool name pattern matching.\n *\n * Tool names follow conventions:\n * - Built-in tools: `Bash`, `Read`, `Edit`, `WebSearch`, etc.\n * - MCP tools: `mcp__<server>__<tool>`, e.g. `mcp__api__search_skills`.\n *\n * Patterns support `*` as a glob wildcard. The most useful patterns for\n * the skills-loading problem are namespace globs like `mcp__api__*` —\n * \"did any tool from the alis MCP server get called.\"\n */\n\nimport type { ToolPattern } from \"../types/assertions\";\n\n/**\n * Test whether a fully-qualified tool name matches a pattern.\n *\n * Literal patterns (no `*`) match by string equality. Glob patterns are\n * compiled to a regex on each call — fine for our scale (dozens of patterns,\n * thousands of calls per run). If this becomes a hot path, memoize.\n */\nexport function toolMatches(toolName: string, pattern: ToolPattern): boolean {\n const p = patternString(pattern);\n if (!p.includes(\"*\")) return toolName === p;\n return globToRegex(p).test(toolName);\n}\n\n/** Extract the underlying string from either pattern form. */\nexport function patternString(pattern: ToolPattern): string {\n return typeof pattern === \"string\" ? pattern : pattern.pattern;\n}\n\n/** Human-readable representation for diagnostic messages. */\nexport function describePattern(pattern: ToolPattern): string {\n return patternString(pattern);\n}\n\n/**\n * Convert a glob (with `*` wildcards only) to an anchored regex.\n * Other regex metacharacters in the input are escaped.\n */\nfunction globToRegex(glob: string): RegExp {\n const escaped = glob\n .replace(/[.+?^${}()|[\\]\\\\]/g, \"\\\\$&\") // escape regex specials\n .replace(/\\*/g, \".*\"); // * → .*\n return new RegExp(`^${escaped}$`);\n}\n","/**\n * Predicate engine for matching tool call arguments.\n *\n * Conceptually similar to MongoDB query selectors: a predicate is a tree\n * of conditions, applied recursively to a value. Examples:\n *\n * matches(\"hello world\", { contains: \"world\" }) // true\n * matches({ a: 1 }, { a: { gte: 0 } }) // true\n * matches({ a: { b: \"x\" } }, { a: { b: \"x\" } }) // true (scalar shortcut)\n * matches({ q: \"ab\" }, { any_of: [{equals:\"x\"}, {contains:\"a\"}] }) // ???\n *\n * Last example: the `any_of` applies to the value (`{q:\"ab\"}`), not to a\n * field. `equals:\"x\"` and `contains:\"a\"` are both leaf predicates that\n * apply to the whole value. `contains` requires a string, so it returns\n * false for the object. The whole thing returns false. That's deliberate.\n *\n * Disambiguation rule (single-key objects): a single-key object is interpreted as a leaf or compound predicate IF\n * the key matches a known operator name. Otherwise it falls through to\n * being treated as an object predicate (field name = key).\n *\n * This means a tool argument schema cannot have a top-level field named\n * `equals`, `contains`, `regex`, `any_of`, `all_of`, `not`, etc. — those\n * fields would be shadowed by predicate operators. For MCP tools, this\n * has never been a problem in practice; document it and move on.\n */\n\nimport type { Predicate } from \"../types/assertions\";\n\nconst LEAF_OPS = new Set([\n \"equals\",\n \"contains\",\n \"not_contains\",\n \"regex\",\n \"gte\",\n \"lte\",\n \"gt\",\n \"lt\",\n \"one_of\",\n]);\nconst COMPOUND_OPS = new Set([\"any_of\", \"all_of\", \"not\"]);\n\n/**\n * Apply a predicate to a value. Returns true if the value satisfies the\n * predicate, false otherwise.\n *\n * The `predicate` parameter is typed as `unknown` because YAML deserialization\n * produces unconstrained shapes; runtime dispatch is the validation.\n */\nexport function matches(value: unknown, predicate: unknown): boolean {\n // Scalar shortcut: anything that isn't a plain object (or is an array) is\n // treated as an equality target.\n if (!isPlainObject(predicate)) {\n return deepEquals(value, predicate);\n }\n\n const obj = predicate as Record<string, unknown>;\n const keys = Object.keys(obj);\n\n // Single-key object: check if it's a known operator.\n if (keys.length === 1) {\n const key = keys[0];\n\n if (COMPOUND_OPS.has(key)) {\n switch (key) {\n case \"any_of\":\n return (obj.any_of as Predicate[]).some((sub) => matches(value, sub));\n case \"all_of\":\n return (obj.all_of as Predicate[]).every((sub) =>\n matches(value, sub),\n );\n case \"not\":\n return !matches(value, obj.not);\n }\n }\n\n if (LEAF_OPS.has(key)) {\n return matchesLeaf(value, key, obj[key]);\n }\n\n // Single key but not a known operator → object predicate (field match).\n }\n\n // Object predicate: every key is a field on `value`, every key's value is\n // a sub-predicate that must hold for the corresponding field.\n if (!isPlainObject(value)) return false;\n const valueObj = value as Record<string, unknown>;\n\n for (const [field, subPred] of Object.entries(obj)) {\n if (!matches(valueObj[field], subPred)) return false;\n }\n return true;\n}\n\n/** Apply a single leaf operator to a value. Caller guarantees `op` is in LEAF_OPS. */\nfunction matchesLeaf(value: unknown, op: string, target: unknown): boolean {\n switch (op) {\n case \"equals\":\n return deepEquals(value, target);\n case \"contains\":\n return typeof value === \"string\" && value.includes(target as string);\n case \"not_contains\":\n return typeof value === \"string\" && !value.includes(target as string);\n case \"regex\":\n if (typeof value !== \"string\" || typeof target !== \"string\") {\n return false;\n }\n try {\n return new RegExp(target).test(value);\n } catch {\n return false;\n }\n case \"gte\":\n return typeof value === \"number\" && value >= (target as number);\n case \"lte\":\n return typeof value === \"number\" && value <= (target as number);\n case \"gt\":\n return typeof value === \"number\" && value > (target as number);\n case \"lt\":\n return typeof value === \"number\" && value < (target as number);\n case \"one_of\":\n return (target as unknown[]).some((t) => deepEquals(value, t));\n default:\n throw new Error(`unknown leaf operator: ${op}`);\n }\n}\n\n/** True for non-null, non-array objects. */\nfunction isPlainObject(x: unknown): x is Record<string, unknown> {\n return typeof x === \"object\" && x !== null && !Array.isArray(x);\n}\n\n/**\n * Structural equality for unknown values. Used by `equals` and `one_of`.\n * Strict — no coercions, no NaN-equals-NaN special case (matches `===`).\n */\nfunction deepEquals(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (typeof a !== typeof b) return false;\n if (a === null || b === null) return false;\n if (typeof a !== \"object\") return false;\n\n if (Array.isArray(a) !== Array.isArray(b)) return false;\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n return a.every((v, i) => deepEquals(v, b[i]));\n }\n\n const aObj = a as Record<string, unknown>;\n const bObj = b as Record<string, unknown>;\n const aKeys = Object.keys(aObj);\n const bKeys = Object.keys(bObj);\n if (aKeys.length !== bKeys.length) return false;\n return aKeys.every((k) => deepEquals(aObj[k], bObj[k]));\n}\n","/**\n * Tool-call assertion evaluators.\n *\n * These assertions query the `toolCalls` array on the trajectory view:\n * presence, cardinality, ordering, and argument matching.\n *\n * Ordering is done on `turnIndex`, not wall-clock time. Parallel tool calls\n * within a single assistant turn share a turnIndex, which means \"A came\n * before B\" requires A's turn to *strictly precede* B's turn — calls within\n * the same turn are considered unordered. This is the right default\n * because Claude Code dispatches parallel calls concurrently and the\n * wall-clock ordering is non-deterministic.\n */\n\nimport type { Assertion, AssertionResult } from \"../types/assertions\";\nimport type { ToolCall, TrajectoryView } from \"../types/trajectory\";\nimport { describeCardinality, parseCardinality } from \"./cardinality\";\nimport { describePattern, toolMatches } from \"./patterns\";\nimport { matches as predicateMatches } from \"./predicates\";\n\n// presence\n\n/** Assert a tool was called with optional cardinality (`times`). */\nexport function evaluateCalled(\n view: TrajectoryView,\n assertion: Extract<Assertion, { type: \"called\" }>,\n): AssertionResult {\n const matching = view.toolCalls.filter((c) =>\n toolMatches(c.name, assertion.tool),\n );\n const check = parseCardinality(assertion.times);\n const passed = check(matching.length);\n\n return {\n passed,\n description: `called(${describePattern(assertion.tool)}, ${describeCardinality(assertion.times)})`,\n details: passed\n ? `found ${matching.length} matching call(s)`\n : `found ${matching.length} call(s), expected ${describeCardinality(assertion.times)}`,\n matches: matching,\n };\n}\n\n/** Assert a tool was never called. */\nexport function evaluateNotCalled(\n view: TrajectoryView,\n assertion: Extract<Assertion, { type: \"not_called\" }>,\n): AssertionResult {\n const matching = view.toolCalls.filter((c) =>\n toolMatches(c.name, assertion.tool),\n );\n const passed = matching.length === 0;\n\n return {\n passed,\n description: `not_called(${describePattern(assertion.tool)})`,\n details: passed\n ? \"no matching calls\"\n : `found ${matching.length} forbidden call(s)`,\n matches: matching,\n };\n}\n\n/** Assert at least one of the listed tools was called. */\nexport function evaluateCalledAnyOf(\n view: TrajectoryView,\n assertion: Extract<Assertion, { type: \"called_any_of\" }>,\n): AssertionResult {\n const allMatches: ToolCall[] = [];\n for (const pattern of assertion.tools) {\n allMatches.push(\n ...view.toolCalls.filter((c) => toolMatches(c.name, pattern)),\n );\n }\n const passed = allMatches.length > 0;\n return {\n passed,\n description: `called_any_of(${assertion.tools.map(describePattern).join(\", \")})`,\n details: passed\n ? `${allMatches.length} matching call(s)`\n : \"no calls matched any pattern\",\n matches: allMatches,\n };\n}\n\n/** Assert every listed tool was called at least once. */\nexport function evaluateCalledAllOf(\n view: TrajectoryView,\n assertion: Extract<Assertion, { type: \"called_all_of\" }>,\n): AssertionResult {\n const perPattern = assertion.tools.map((p) => ({\n pattern: p,\n matches: view.toolCalls.filter((c) => toolMatches(c.name, p)),\n }));\n const missing = perPattern.filter((p) => p.matches.length === 0);\n const passed = missing.length === 0;\n\n return {\n passed,\n description: `called_all_of(${assertion.tools.map(describePattern).join(\", \")})`,\n details: passed\n ? \"all patterns matched\"\n : `missing: ${missing.map((m) => describePattern(m.pattern)).join(\", \")}`,\n matches: perPattern.flatMap((p) => p.matches),\n };\n}\n\n// ordering\n\n/** Assert `first` tool's earliest turn strictly precedes `then` tool's earliest turn. */\nexport function evaluateCalledBefore(\n view: TrajectoryView,\n assertion: Extract<Assertion, { type: \"called_before\" }>,\n): AssertionResult {\n const firsts = view.toolCalls.filter((c) =>\n toolMatches(c.name, assertion.first),\n );\n const thens = view.toolCalls.filter((c) =>\n toolMatches(c.name, assertion.then),\n );\n const desc = `called_before(${describePattern(assertion.first)} → ${describePattern(assertion.then)})`;\n\n if (firsts.length === 0) {\n return {\n passed: false,\n description: desc,\n details: `no calls matching first`,\n };\n }\n if (thens.length === 0) {\n return {\n passed: false,\n description: desc,\n details: `no calls matching then`,\n };\n }\n\n // Earliest occurrence of each side, by turn. Strictly less than = \"before\".\n const earliestFirst = Math.min(...firsts.map((c) => c.turnIndex));\n const earliestThen = Math.min(...thens.map((c) => c.turnIndex));\n const passed = earliestFirst < earliestThen;\n\n return {\n passed,\n description: desc,\n details: passed\n ? `first @ turn ${earliestFirst}, then @ turn ${earliestThen}`\n : `first @ turn ${earliestFirst}, then @ turn ${earliestThen} (not before)`,\n matches: [...firsts, ...thens],\n };\n}\n\n/**\n * Assert tools appear in order.\n *\n * Non-strict mode allows interleaved calls; strict mode requires a contiguous subsequence.\n */\nexport function evaluateSequence(\n view: TrajectoryView,\n assertion: Extract<Assertion, { type: \"sequence\" }>,\n): AssertionResult {\n const { tools, strict = false } = assertion;\n const desc = `sequence([${tools.map(describePattern).join(\" → \")}]${strict ? \", strict\" : \"\"})`;\n\n if (tools.length === 0) {\n return {\n passed: true,\n description: desc,\n details: \"empty sequence trivially matches\",\n };\n }\n\n if (strict) {\n // Strict: the tools must appear in exact order with no other tool calls\n // interleaved. We look for a contiguous subsequence of the right shape.\n if (view.toolCalls.length < tools.length) {\n return {\n passed: false,\n description: desc,\n details: \"not enough tool calls\",\n };\n }\n for (\n let start = 0;\n start <= view.toolCalls.length - tools.length;\n start++\n ) {\n let ok = true;\n for (let i = 0; i < tools.length; i++) {\n if (!toolMatches(view.toolCalls[start + i].name, tools[i])) {\n ok = false;\n break;\n }\n }\n if (ok) {\n return {\n passed: true,\n description: desc,\n details: `matched at positions ${start}..${start + tools.length - 1}`,\n matches: view.toolCalls.slice(start, start + tools.length),\n };\n }\n }\n return { passed: false, description: desc, details: \"no contiguous match\" };\n }\n\n // Non-strict: tools must appear in order, interleaved calls allowed.\n // Walk the tool call list once, advancing the sequence pointer on each match.\n let idx = 0;\n const matched: ToolCall[] = [];\n for (const call of view.toolCalls) {\n if (idx < tools.length && toolMatches(call.name, tools[idx])) {\n matched.push(call);\n idx++;\n }\n }\n const passed = idx === tools.length;\n return {\n passed,\n description: desc,\n details: passed ? \"matched in order\" : `matched ${idx}/${tools.length}`,\n matches: matched,\n };\n}\n\n// arguments\n\n/** Assert at least one call to `tool` had arguments matching the predicate. */\nexport function evaluateCalledWith(\n view: TrajectoryView,\n assertion: Extract<Assertion, { type: \"called_with\" }>,\n): AssertionResult {\n const candidates = view.toolCalls.filter((c) =>\n toolMatches(c.name, assertion.tool),\n );\n const matching = candidates.filter((c) =>\n predicateMatches(c.args, assertion.args),\n );\n const passed = matching.length > 0;\n\n let details: string;\n if (passed) {\n details = `${matching.length} call(s) with matching args`;\n } else if (candidates.length === 0) {\n details = `no calls to ${describePattern(assertion.tool)} at all`;\n } else {\n details = `${candidates.length} call(s) but none with matching args`;\n }\n\n return {\n passed,\n description: `called_with(${describePattern(assertion.tool)}, args matching predicate)`,\n details,\n matches: matching,\n };\n}\n","/**\n * Behavior and response-text assertions.\n *\n * Cover everything that isn't a tool-call query:\n * - Did the agent answer without using any tool? (the \"blind answer\" case)\n * - Did it stay within iteration / cost / time budget?\n * - What did it say its stop reason was?\n * - Does the response text contain expected substrings or match a regex?\n * - Arbitrary user-supplied predicate (escape hatch).\n */\n\nimport type { Assertion, AssertionResult } from \"../types/assertions\";\nimport type { TrajectoryView } from \"../types/trajectory\";\n\n// behavior\n\n/**\n * Was the response delivered without using any tool? This is the primary\n * failure mode detector for the skills-loading problem: when the harness\n * ignores the MCP, the trace shows zero tool calls and one terminal\n * assistant turn with finish reason `end_turn`.\n *\n * \"Without tool calls\" is defined as `toolCalls.length === 0` AND the\n * response text is non-empty (so we don't confuse \"answered blind\" with\n * \"session died before producing anything\").\n */\nexport function evaluateRespondedWithoutToolCalls(\n view: TrajectoryView,\n _assertion: Extract<Assertion, { type: \"responded_without_tool_calls\" }>,\n): AssertionResult {\n const passed = view.toolCalls.length === 0 && view.finalResponse.length > 0;\n return {\n passed,\n description: \"responded_without_tool_calls\",\n details: passed\n ? \"no tools called, response non-empty\"\n : view.toolCalls.length > 0\n ? `${view.toolCalls.length} tool call(s) made`\n : \"response was empty (session probably aborted)\",\n };\n}\n\n/** Assert the session stayed within the reported turn count. */\nexport function evaluateIterationsWithin(\n view: TrajectoryView,\n assertion: Extract<Assertion, { type: \"iterations_within\" }>,\n): AssertionResult {\n const n = view.usage.numTurns;\n const passed = n <= assertion.max;\n return {\n passed,\n description: `iterations_within(${assertion.max})`,\n details: `used ${n} turn(s)`,\n };\n}\n\n/** Assert total session cost in USD is within budget. */\nexport function evaluateCostWithinUsd(\n view: TrajectoryView,\n assertion: Extract<Assertion, { type: \"cost_within_usd\" }>,\n): AssertionResult {\n const cost = view.usage.totalCostUsd;\n const passed = cost <= assertion.max;\n return {\n passed,\n description: `cost_within_usd(${assertion.max.toFixed(4)})`,\n details: `used $${cost.toFixed(4)}`,\n };\n}\n\n/** Assert wall-clock session duration is within budget. */\nexport function evaluateDurationWithinMs(\n view: TrajectoryView,\n assertion: Extract<Assertion, { type: \"duration_within_ms\" }>,\n): AssertionResult {\n const ms = view.usage.durationMs;\n const passed = ms <= assertion.max;\n return {\n passed,\n description: `duration_within_ms(${assertion.max})`,\n details: `took ${ms}ms`,\n };\n}\n\n/** Assert the final stop reason matches one of the allowed values. */\nexport function evaluateFinishedWith(\n view: TrajectoryView,\n assertion: Extract<Assertion, { type: \"finished_with\" }>,\n): AssertionResult {\n const allowed = Array.isArray(assertion.reasons)\n ? assertion.reasons\n : [assertion.reasons];\n const actual = view.finalStopReason;\n const passed = actual !== null && allowed.includes(actual);\n return {\n passed,\n description: `finished_with(${allowed.join(\"|\")})`,\n details: `actual: ${actual ?? \"(none)\"}`,\n };\n}\n\n// response text\n\n/** Assert `finalResponse` contains the given substring. */\nexport function evaluateResponseContains(\n view: TrajectoryView,\n assertion: Extract<Assertion, { type: \"response_contains\" }>,\n): AssertionResult {\n const passed = view.finalResponse.includes(assertion.text);\n return {\n passed,\n description: `response_contains(${JSON.stringify(assertion.text)})`,\n details: passed ? \"text found\" : \"text not in response\",\n };\n}\n\n/** Assert `finalResponse` does not contain the given substring. */\nexport function evaluateResponseNotContains(\n view: TrajectoryView,\n assertion: Extract<Assertion, { type: \"response_not_contains\" }>,\n): AssertionResult {\n const passed = !view.finalResponse.includes(assertion.text);\n return {\n passed,\n description: `response_not_contains(${JSON.stringify(assertion.text)})`,\n details: passed ? \"text absent\" : \"forbidden text found\",\n };\n}\n\n/** Assert `finalResponse` matches a regular expression. */\nexport function evaluateResponseMatches(\n view: TrajectoryView,\n assertion: Extract<Assertion, { type: \"response_matches\" }>,\n): AssertionResult {\n // Construction may throw on a malformed regex; surface that as a failure\n // rather than crashing the whole eval run.\n let passed: boolean;\n let details: string;\n try {\n const re = new RegExp(assertion.pattern, assertion.flags);\n passed = re.test(view.finalResponse);\n details = passed ? \"pattern matched\" : \"pattern did not match\";\n } catch (err) {\n passed = false;\n details = `invalid regex: ${err instanceof Error ? err.message : String(err)}`;\n }\n return {\n passed,\n description: `response_matches(/${assertion.pattern}/${assertion.flags ?? \"\"})`,\n details,\n };\n}\n\n// escape hatch\n\n/**\n * Run an arbitrary user-supplied predicate against the view.\n *\n * Only available from programmatic test definition (the YAML loader cannot\n * produce functions). Catches thrown errors and reports them as failures so\n * one bad predicate doesn't take down a whole eval run.\n */\nexport function evaluatePredicate(\n view: TrajectoryView,\n assertion: Extract<Assertion, { type: \"predicate\" }>,\n): AssertionResult {\n let passed = false;\n let details: string;\n try {\n passed = assertion.fn(view);\n details = passed ? \"predicate returned true\" : \"predicate returned false\";\n } catch (err) {\n details = `predicate threw: ${err instanceof Error ? err.message : String(err)}`;\n }\n return {\n passed,\n description: assertion.description ?? \"predicate(...)\",\n details,\n };\n}\n","/**\n * Compound assertion evaluators: `any_of`, `all_of`, `not`.\n *\n * These recurse into the main evaluator. To avoid a circular import between\n * this file and `evaluator.ts`, the dispatcher is passed in as a function\n * parameter rather than imported directly. The evaluator binds itself when\n * dispatching to these.\n */\n\nimport type { Assertion, AssertionResult } from \"../types/assertions\";\nimport type { TrajectoryView } from \"../types/trajectory\";\n\n/**\n * Signature of the top-level dispatcher. Passed into compound evaluators so\n * they can recursively evaluate child assertions without a circular import.\n */\nexport type Evaluator = (\n view: TrajectoryView,\n assertion: Assertion,\n) => AssertionResult;\n\n/** Evaluate `all_of`: every child assertion must pass. */\nexport function evaluateAllOf(\n view: TrajectoryView,\n assertion: Extract<Assertion, { type: \"all_of\" }>,\n evaluate: Evaluator,\n): AssertionResult {\n const children = assertion.assertions.map((a) => evaluate(view, a));\n const passed = children.every((c) => c.passed);\n const failedCount = children.filter((c) => !c.passed).length;\n\n return {\n passed,\n description: `all_of (${children.length} child${children.length === 1 ? \"\" : \"ren\"})`,\n details: passed\n ? \"all passed\"\n : `${failedCount} of ${children.length} failed`,\n children,\n };\n}\n\n/** Evaluate `any_of`: at least one child assertion must pass. */\nexport function evaluateAnyOf(\n view: TrajectoryView,\n assertion: Extract<Assertion, { type: \"any_of\" }>,\n evaluate: Evaluator,\n): AssertionResult {\n const children = assertion.assertions.map((a) => evaluate(view, a));\n const passedCount = children.filter((c) => c.passed).length;\n const passed = passedCount > 0;\n\n return {\n passed,\n description: `any_of (${children.length} child${children.length === 1 ? \"\" : \"ren\"})`,\n details: passed ? `${passedCount} passed` : \"all failed\",\n children,\n };\n}\n\n/** Evaluate `not`: invert the inner assertion result. */\nexport function evaluateNot(\n view: TrajectoryView,\n assertion: Extract<Assertion, { type: \"not\" }>,\n evaluate: Evaluator,\n): AssertionResult {\n const child = evaluate(view, assertion.assertion);\n return {\n passed: !child.passed,\n description: `not(${child.description})`,\n details: child.passed\n ? \"inner passed (so outer fails)\"\n : \"inner failed (so outer passes)\",\n children: [child],\n };\n}\n","/**\n * Top-level assertion evaluator.\n *\n * Dispatches on the discriminant of the `Assertion` tagged union, delegating\n * to the per-kind evaluators in the sibling modules. This file deliberately\n * contains no logic of its own — keep it boring so adding a new assertion\n * type is just (a) extend the union in `types/assertions.ts`, (b) add an\n * evaluator function in the appropriate sibling, (c) add one case here.\n */\n\nimport type { Assertion, AssertionResult } from \"../types/assertions\";\nimport type { TrajectoryView } from \"../types/trajectory\";\n\nimport {\n evaluateCalled,\n evaluateCalledAllOf,\n evaluateCalledAnyOf,\n evaluateCalledBefore,\n evaluateCalledWith,\n evaluateNotCalled,\n evaluateSequence,\n} from \"./tool-calls\";\n\nimport {\n evaluateCostWithinUsd,\n evaluateDurationWithinMs,\n evaluateFinishedWith,\n evaluateIterationsWithin,\n evaluatePredicate,\n evaluateRespondedWithoutToolCalls,\n evaluateResponseContains,\n evaluateResponseMatches,\n evaluateResponseNotContains,\n} from \"./behavior\";\n\nimport { evaluateAllOf, evaluateAnyOf, evaluateNot } from \"./compound\";\n\n/**\n * Evaluate one assertion against a trajectory view.\n *\n * The switch is exhaustive — TypeScript's `never` check at the end will\n * flag any new variant added to the `Assertion` union that hasn't been\n * wired up here.\n */\nexport function evaluate(\n view: TrajectoryView,\n assertion: Assertion,\n): AssertionResult {\n switch (assertion.type) {\n // tool-call presence and ordering\n case \"called\":\n return evaluateCalled(view, assertion);\n case \"not_called\":\n return evaluateNotCalled(view, assertion);\n case \"called_any_of\":\n return evaluateCalledAnyOf(view, assertion);\n case \"called_all_of\":\n return evaluateCalledAllOf(view, assertion);\n case \"called_before\":\n return evaluateCalledBefore(view, assertion);\n case \"sequence\":\n return evaluateSequence(view, assertion);\n\n // tool-call arguments\n case \"called_with\":\n return evaluateCalledWith(view, assertion);\n\n // behavior\n case \"responded_without_tool_calls\":\n return evaluateRespondedWithoutToolCalls(view, assertion);\n case \"iterations_within\":\n return evaluateIterationsWithin(view, assertion);\n case \"cost_within_usd\":\n return evaluateCostWithinUsd(view, assertion);\n case \"duration_within_ms\":\n return evaluateDurationWithinMs(view, assertion);\n case \"finished_with\":\n return evaluateFinishedWith(view, assertion);\n\n // response text\n case \"response_contains\":\n return evaluateResponseContains(view, assertion);\n case \"response_not_contains\":\n return evaluateResponseNotContains(view, assertion);\n case \"response_matches\":\n return evaluateResponseMatches(view, assertion);\n\n // compound — pass the dispatcher in so they can recurse without\n // creating a circular import\n case \"all_of\":\n return evaluateAllOf(view, assertion, evaluate);\n case \"any_of\":\n return evaluateAnyOf(view, assertion, evaluate);\n case \"not\":\n return evaluateNot(view, assertion, evaluate);\n\n // escape hatch\n case \"predicate\":\n return evaluatePredicate(view, assertion);\n\n default: {\n // Exhaustiveness guard. If a new assertion variant is added to the\n // union and not wired into the switch above, TypeScript will fail\n // here at compile time. Don't remove this case.\n const _exhaustive: never = assertion;\n throw new Error(`unknown assertion: ${JSON.stringify(_exhaustive)}`);\n }\n }\n}\n\n/**\n * Evaluate a list of assertions independently. Used at the test-case level\n * where each top-level assertion is reported separately (and thresholded\n * separately, in the runner layer).\n */\nexport function evaluateAll(\n view: TrajectoryView,\n assertions: Assertion[],\n): AssertionResult[] {\n return assertions.map((a) => evaluate(view, a));\n}\n","/**\n * Default harness adapter registry.\n *\n * New adapters register here so the CLI and runner can resolve `adapter`\n * names from YAML without hard-coding imports at every call site.\n *\n * ## Adding a new harness adapter\n *\n * 1. **Create an adapter module** under `src/adapters/<id>/` implementing\n * {@link HarnessAdapter} from `./types`. Set `id` to match the YAML\n * `adapter` field (e.g. `\"codex\"`).\n * 2. **Nest suite config** under a camelCase key in {@link SuiteConfig}\n * (e.g. `codex: { ... }`) so each harness keeps its own options.\n * 3. **Register at startup** via {@link registerAdapter} — either in this\n * module for built-in adapters or from plugin/bootstrap code for\n * runtime extensions.\n * 4. **Reference in suite YAML** with `adapter: <id>` and the nested config\n * block; the runner calls `getAdapter(id).run(resolvedConfig)`.\n *\n * Built-in adapters are registered when this module loads. Only `claude-code`\n * ships today; future harnesses (Codex, Gemini CLI, Antigravity CLI) follow\n * the same pattern in separate tracks.\n */\n\nimport type { HarnessAdapter } from \"./types\";\nimport { claudeCodeAdapter } from \"./claude-code/index\";\n\nconst ADAPTERS: Record<string, HarnessAdapter> = {};\n\nfunction registerBuiltIn(id: string, adapter: HarnessAdapter): void {\n ADAPTERS[id] = adapter;\n}\n\nregisterBuiltIn(\"claude-code\", claudeCodeAdapter);\n\n/**\n * Register a harness adapter by id.\n *\n * Duplicate ids throw — registration is explicit so accidental overrides\n * surface immediately during startup or test setup.\n */\nexport function registerAdapter(id: string, adapter: HarnessAdapter): void {\n if (ADAPTERS[id]) {\n throw new Error(`adapter \"${id}\" is already registered`);\n }\n ADAPTERS[id] = adapter;\n}\n\n/** Return all registered adapter ids (built-in and runtime). */\nexport function listAdapters(): string[] {\n return Object.keys(ADAPTERS);\n}\n\n/** Resolve an adapter by id. Throws if unknown. */\nexport function getAdapter(id: string): HarnessAdapter {\n const adapter = ADAPTERS[id];\n if (!adapter) {\n throw new Error(\n `unknown adapter \"${id}\". Available: ${listAdapters().join(\", \")}`,\n );\n }\n return adapter;\n}\n\n/** Default adapter when YAML omits `adapter`. */\nexport const DEFAULT_ADAPTER_ID = \"claude-code\";\n\nexport function getDefaultAdapter(): HarnessAdapter {\n return getAdapter(DEFAULT_ADAPTER_ID);\n}\n","/**\n * Flatten nested suite config into harness-specific adapter config.\n *\n * Suite YAML nests adapter options under keys like `claudeCode`; adapters\n * expect a flat config object. This module merges layers and flattens per\n * adapter id.\n */\n\nimport { DEFAULT_ADAPTER_ID } from \"../adapters/registry\";\nimport type { BaseAdapterConfig } from \"../adapters/types\";\nimport type { ClaudeCodeAdapterConfig } from \"../adapters/claude-code/types\";\nimport type { SuiteConfig } from \"../adapters/types\";\n\n/** Merged config passed to {@link HarnessAdapter.run}. */\nexport type ResolvedRunConfig = BaseAdapterConfig & Record<string, unknown>;\n\n/** Merge generic suite config layers into a flat {@link ClaudeCodeAdapterConfig}. */\nexport function toClaudeCodeConfig(\n layers: SuiteConfig[],\n prompt: string,\n): ClaudeCodeAdapterConfig {\n const merged: Record<string, unknown> = {};\n for (const layer of layers) {\n const { claudeCode, ...generic } = layer;\n Object.assign(merged, generic);\n if (claudeCode && typeof claudeCode === \"object\") {\n Object.assign(merged, claudeCode);\n }\n }\n merged.prompt = prompt;\n return merged as unknown as ClaudeCodeAdapterConfig;\n}\n\n/**\n * Resolve merged suite layers into the flat config shape expected by the\n * selected harness adapter.\n */\nexport function resolveRunConfig(\n adapterId: string,\n layers: SuiteConfig[],\n prompt: string,\n): ResolvedRunConfig {\n if (adapterId === DEFAULT_ADAPTER_ID || adapterId === \"claude-code\") {\n return toClaudeCodeConfig(layers, prompt) as ResolvedRunConfig;\n }\n\n const merged: Record<string, unknown> = {};\n for (const layer of layers) {\n Object.assign(merged, layer);\n }\n merged.prompt = prompt;\n return merged as ResolvedRunConfig;\n}\n","/**\n * Case-level runner — config merge, single-repetition execution, and cell aggregation.\n *\n * The suite runner (`suite.ts`) fans out work; this module owns the per-rep\n * lifecycle: merge config layers, invoke the adapter, evaluate assertions, and\n * compute thresholded pass rates for one matrix cell.\n */\n\nimport type { AdapterDiagnostics, AdapterResult, BaseAdapterConfig } from \"../adapters/types\";\nimport { getDefaultAdapter } from \"../adapters/registry\";\nimport { resolveRunConfig } from \"../config/resolve-config\";\nimport { evaluateAll } from \"../assertions/evaluator\";\nimport type {\n AssertionStat,\n CellReport,\n MatrixCell,\n RepetitionError,\n RepetitionResult,\n TestCase,\n TestSuite,\n} from \"./types\";\n\n/** Default repetition count when `case.repetitions` is omitted. */\nexport const DEFAULT_REPETITIONS = 5;\n\n/** Default assertion pass-rate threshold when `threshold` is omitted. */\nexport const DEFAULT_THRESHOLD = 1.0;\n\n/** Injectable adapter run function (used by tests to stub harness I/O). */\nexport type AdapterRunFn = (\n config: BaseAdapterConfig & Record<string, unknown>,\n) => Promise<AdapterResult>;\n\n/**\n * Build the effective adapter config for one (suite, case, cell).\n *\n * Merge order (later wins): defaultConfig < case.config < cell.config.\n */\nexport function mergeConfig(\n suite: TestSuite,\n testCase: TestCase,\n cell: MatrixCell,\n): BaseAdapterConfig & Record<string, unknown> {\n const adapterId = suite.adapter ?? getDefaultAdapter().id;\n const layers = [\n suite.defaultConfig ?? {},\n testCase.config ?? {},\n cell.config,\n ];\n return resolveRunConfig(adapterId, layers, testCase.prompt);\n}\n\n/** Effective repetition count for a case (`case.repetitions` or default). */\nexport function getRepetitions(testCase: TestCase): number {\n return testCase.repetitions ?? DEFAULT_REPETITIONS;\n}\n\n/**\n * Run one repetition: invoke the adapter, evaluate assertions, capture errors.\n *\n * Adapter failures are returned as {@link RepetitionResult.error} rather than\n * thrown so the suite runner can continue other reps and report adapter error counts.\n */\nexport async function runRepetition(\n testCase: TestCase,\n _cell: MatrixCell,\n config: BaseAdapterConfig & Record<string, unknown>,\n repetitionIndex: number,\n run: AdapterRunFn,\n signal?: AbortSignal,\n): Promise<RepetitionResult> {\n const startTs = Date.now();\n\n try {\n const adapterResult = await run({\n ...config,\n signal: signal ?? config.signal,\n });\n\n const assertionResults = evaluateAll(\n adapterResult.view,\n testCase.assertions.map((t) => t.assertion),\n );\n\n return {\n repetitionIndex,\n adapterResult,\n error: null,\n assertionResults,\n durationMs: Date.now() - startTs,\n };\n } catch (err) {\n return {\n repetitionIndex,\n adapterResult: null,\n error: extractError(err),\n assertionResults: [],\n durationMs: Date.now() - startTs,\n };\n }\n}\n\n/**\n * Normalize thrown values into a {@link RepetitionError}.\n *\n * Preserves {@link AdapterDiagnostics} when the thrown value is an\n * {@link AdapterError} or carries a `diagnostics` property.\n */\nfunction extractError(err: unknown): RepetitionError {\n const message = err instanceof Error ? err.message : String(err);\n\n let diagnostics: Partial<AdapterDiagnostics> = {};\n if (err !== null && typeof err === \"object\" && \"diagnostics\" in err) {\n const d = (err as { diagnostics: unknown }).diagnostics;\n if (d !== null && typeof d === \"object\") {\n diagnostics = d as Partial<AdapterDiagnostics>;\n }\n }\n\n return { message, diagnostics };\n}\n\n/**\n * Roll up repetition results into a {@link CellReport}.\n *\n * Adapter errors reduce `evaluatedCount` but do not fail the cell by\n * themselves — only assertion threshold misses mark a cell as failed.\n */\nexport function aggregateCell(\n testCase: TestCase,\n cell: MatrixCell,\n repetitions: RepetitionResult[],\n): CellReport {\n const adapterErrors = repetitions.filter((r) => r.error !== null).length;\n const evaluatedReps = repetitions.filter((r) => r.error === null);\n\n const assertionStats: AssertionStat[] = testCase.assertions.map(\n (thresholded, i) => {\n const threshold = thresholded.threshold ?? DEFAULT_THRESHOLD;\n const passedCount = evaluatedReps.filter(\n (r) => r.assertionResults[i]?.passed,\n ).length;\n const evaluatedCount = evaluatedReps.length;\n const passRate = evaluatedCount === 0 ? 0 : passedCount / evaluatedCount;\n\n const description =\n evaluatedReps[0]?.assertionResults[i]?.description ??\n `(${thresholded.assertion.type})`;\n\n return {\n description,\n threshold,\n passedCount,\n evaluatedCount,\n passRate,\n meetsThreshold: evaluatedCount > 0 && passRate >= threshold,\n };\n },\n );\n\n const passed = assertionStats.every((s) => s.meetsThreshold);\n\n return {\n caseId: testCase.id,\n category: testCase.category,\n notes: testCase.notes,\n prompt: testCase.prompt,\n expectations: testCase.expectations,\n reference_trajectory: testCase.reference_trajectory,\n human_ratings: testCase.human_ratings,\n cell,\n repetitions,\n assertionStats,\n adapterErrors,\n passed,\n };\n}\n","/**\n * Promise-based concurrency limiter.\n *\n * Functionally equivalent to the `p-limit` package, inlined to avoid an\n * external dependency for ~20 lines of code.\n *\n * Usage:\n *\n * const limit = createLimit(4);\n * const results = await Promise.all(tasks.map(t => limit(() => run(t))));\n *\n * The limiter is unbounded in queue depth — it doesn't push back on the\n * caller. If you need bounded enqueue, wrap it.\n */\n\n/** A function that runs an async task under the concurrency limit. */\nexport type LimitedRunner = <T>(fn: () => Promise<T>) => Promise<T>;\n\nexport function createLimit(max: number): LimitedRunner {\n if (!Number.isInteger(max) || max < 1) {\n throw new Error(`createLimit: max must be a positive integer, got ${max}`);\n }\n\n let running = 0;\n /**\n * FIFO list of resolvers belonging to tasks waiting for a slot. When a\n * running task finishes, the next resolver is invoked to wake one waiter.\n */\n const waiters: (() => void)[] = [];\n\n return async <T>(fn: () => Promise<T>): Promise<T> => {\n // Wait for a slot. The loop guards a race where another waiter could\n // grab the slot between our `await` resolving and our increment — in\n // single-threaded JS this is theoretical, but `while` is the right shape.\n while (running >= max) {\n await new Promise<void>((resolve) => waiters.push(resolve));\n }\n running++;\n\n try {\n return await fn();\n } finally {\n running--;\n // Wake exactly one waiter per finished task. Shifting from the front\n // gives FIFO behaviour — earlier callers get slots first.\n const next = waiters.shift();\n if (next) next();\n }\n };\n}\n","/**\n * Suite-level runner — fans out (case × cell × repetition) tasks with concurrency control.\n *\n * Tasks run under a {@link createLimit} pool; results are bucketed by case and\n * cell label, sorted by repetition index, then aggregated into a\n * {@link SuiteReport}.\n */\n\nimport { getAdapter, getDefaultAdapter } from \"../adapters/registry\";\nimport {\n aggregateCell,\n getRepetitions,\n mergeConfig,\n runRepetition,\n type AdapterRunFn,\n} from \"./case\";\nimport { createLimit } from \"./limit\";\nimport type {\n CellReport,\n MatrixCell,\n RepetitionResult,\n RunSuiteOptions,\n SuiteReport,\n TestCase,\n TestSuite,\n} from \"./types\";\n\nconst DEFAULT_MAX_CONCURRENT = 4;\n\n/** One unit of concurrent work: a single repetition for a (case, cell) pair. */\ninterface Task {\n testCase: TestCase;\n cell: MatrixCell;\n repetitionIndex: number;\n}\n\n/**\n * Execute an entire test suite and return an aggregated report.\n *\n * @throws When `suite.matrix` or `suite.cases` is empty.\n */\nexport async function runSuite(\n suite: TestSuite,\n options: RunSuiteOptions = {},\n): Promise<SuiteReport> {\n if (suite.matrix.length === 0) {\n throw new Error(\"runSuite: suite.matrix must contain at least one cell\");\n }\n if (suite.cases.length === 0) {\n throw new Error(\"runSuite: suite.cases must contain at least one case\");\n }\n\n const adapter =\n options.adapter ?? getAdapter(suite.adapter ?? getDefaultAdapter().id);\n\n const run: AdapterRunFn = (config) => adapter.run(config);\n\n const maxConcurrent = options.maxConcurrent ?? DEFAULT_MAX_CONCURRENT;\n const limit = createLimit(maxConcurrent);\n const onProgress = options.onProgress;\n\n const startTs = Date.now();\n const startedAt = new Date(startTs).toISOString();\n\n const tasks: Task[] = [];\n for (const testCase of suite.cases) {\n const reps = getRepetitions(testCase);\n for (const cell of suite.matrix) {\n for (let i = 0; i < reps; i++) {\n tasks.push({ testCase, cell, repetitionIndex: i });\n }\n }\n }\n\n onProgress?.({ kind: \"suite-start\", totalReps: tasks.length });\n\n const buckets = new Map<string, RepetitionResult[]>();\n // Stable key for grouping reps belonging to the same (case, cell).\n const bucketKey = (caseId: string, cellLabel: string) =>\n `${caseId}::${cellLabel}`;\n\n for (const testCase of suite.cases) {\n for (const cell of suite.matrix) {\n buckets.set(bucketKey(testCase.id, cell.label), []);\n }\n }\n\n await Promise.all(\n tasks.map((task) =>\n limit(async () => {\n if (options.signal?.aborted) return;\n\n onProgress?.({\n kind: \"rep-start\",\n caseId: task.testCase.id,\n cellLabel: task.cell.label,\n repIndex: task.repetitionIndex,\n });\n\n const config = mergeConfig(suite, task.testCase, task.cell);\n const result = await runRepetition(\n task.testCase,\n task.cell,\n config,\n task.repetitionIndex,\n run,\n options.signal,\n );\n\n buckets.get(bucketKey(task.testCase.id, task.cell.label))!.push(result);\n\n onProgress?.({\n kind: \"rep-complete\",\n caseId: task.testCase.id,\n cellLabel: task.cell.label,\n repIndex: task.repetitionIndex,\n ok: result.error === null,\n durationMs: result.durationMs,\n toolCallCount: result.adapterResult?.view.toolCalls.length,\n assertionResults: result.assertionResults,\n errorMessage: result.error?.message,\n });\n }),\n ),\n );\n\n const cells: CellReport[] = [];\n for (const testCase of suite.cases) {\n for (const cell of suite.matrix) {\n const reps = buckets.get(bucketKey(testCase.id, cell.label)) ?? [];\n reps.sort((a, b) => a.repetitionIndex - b.repetitionIndex);\n\n const cellReport = aggregateCell(testCase, cell, reps);\n cells.push(cellReport);\n\n onProgress?.({ kind: \"cell-complete\", report: cellReport });\n }\n }\n\n const report: SuiteReport = {\n startedAt,\n durationMs: Date.now() - startTs,\n cells,\n };\n\n onProgress?.({ kind: \"suite-complete\", report });\n\n return report;\n}\n"],"mappings":"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"}
|