@alis-build/harness-eval 0.1.1 → 0.1.3
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 +104 -10
- 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-ycT0JQZF.js → claude-code-C_7hxC8z.js} +37 -250
- package/dist/claude-code-C_7hxC8z.js.map +1 -0
- package/dist/cli/bin.js +204 -127
- 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-6Z17eKZx.d.ts → index-DnvP1UBl.d.ts} +3 -2
- package/dist/index.d.ts +397 -153
- package/dist/index.js +125 -5
- package/dist/index.js.map +1 -0
- package/dist/loader-B1WmGGzf.d.ts +107 -0
- package/dist/{loader-BCnFJ8rm.js → loader-DnQ6Jt0i.js} +707 -157
- package/dist/loader-DnQ6Jt0i.js.map +1 -0
- package/dist/reporter-Biy-5-9M.js +2216 -0
- package/dist/reporter-Biy-5-9M.js.map +1 -0
- package/dist/runner/suite.d.ts +1 -1
- package/dist/runner/suite.js +1 -1
- package/dist/{suite-BoOvK_lq.d.ts → suite-BEShV0by.d.ts} +7 -2
- package/dist/{suite-chj0j22j.js → suite-BcP64nlb.js} +72 -4
- package/dist/suite-BcP64nlb.js.map +1 -0
- package/dist/{types-BQol062t.d.ts → types-0QkNVyp9.d.ts} +152 -11
- package/dist/types-Bac8_Ixb.js +246 -0
- package/dist/types-Bac8_Ixb.js.map +1 -0
- package/dist/types-Bu8uOZZN.d.ts +77 -0
- package/dist/{types-B9H4IZtA.d.ts → types-C0gBkl0-.d.ts} +3 -2
- package/package.json +7 -2
- package/schemas/eval-interchange-instances.schema.json +196 -0
- package/schemas/eval-interchange.schema.json +65 -52
- package/schemas/eval-run-envelope.schema.json +182 -425
- package/dist/build-DsVJ_UeU.js +0 -1396
- package/dist/build-DsVJ_UeU.js.map +0 -1
- package/dist/claude-code-ycT0JQZF.js.map +0 -1
- package/dist/loader-BCnFJ8rm.js.map +0 -1
- package/dist/loader-DTvoVfN0.d.ts +0 -33
- package/dist/suite-chj0j22j.js.map +0 -1
- package/schemas/eval-interchange-agent-trace.schema.json +0 -322
- package/schemas/eval-interchange-proto-instance.schema.json +0 -106
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"build-DsVJ_UeU.js","names":["parseYaml","formatJson","RESET","GREEN","RED","formatRate","normalizeToolCall"],"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/build.ts","../src/metrics/trajectory.ts","../src/metrics/tool-calls.ts","../src/eval-interchange/projections.ts","../src/eval-record/build.ts"],"sourcesContent":["/**\n * Cross-harness eval record contract for storage, CI/CD, and external judges.\n *\n * Layering:\n * - {@link TrajectoryView} — canonical harness session (adapter output)\n * - {@link EvalRunEnvelope} — full run for DB / pipelines\n * - Optional artifacts — vendor-specific raw streams, OTLP traces\n *\n * @see docs/eval-record.md\n * @see schemas/eval-run-envelope.schema.json\n */\n\nimport type { AdapterDiagnostics } from \"../adapters/types\";\nimport type { GradedExpectation, GradingSummary } from \"../grader/types\";\nimport type {\n AgentTrace,\n InterchangeToolCall,\n TabularToolCall,\n ToolCallMetrics,\n TrajectoryMetrics,\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 /** Absolute or repo-relative path to the suite YAML. */\n uri?: string;\n /** Stable suite identifier when known (e.g. case bundle name). */\n id?: string;\n /** SHA-256 or similar hash of suite file contents. */\n contentHash?: string;\n}\n\n/** Harness that executed the run. */\nexport interface HarnessInfo {\n /** Adapter id from suite YAML, e.g. `claude-code`. */\n adapter: string;\n /** harness-eval package version when envelope was built. */\n frameworkVersion?: string;\n /** Optional harness binary version (e.g. `claude -v`). */\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 /** All cells passed behavioral assertion thresholds. */\n behavioralPass: boolean;\n /** All graded expectations passed (when outcome layer present). */\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 /** Claude Code `stream-json` lines — debug only, not cross-harness. */\n rawStreamEvents?: unknown[];\n /** URI to OTLP JSON (S3, GCS, etc.). */\n otlpTraceUri?: string;\n /** Text transcript for judges (`trajectoryToTranscript`). */\n transcript?: string;\n}\n\n/**\n * One harness invocation — the unit external judges and trajectory queries use.\n */\nexport interface EvalRepetition {\n repetitionIndex: number;\n durationMs: number;\n\n /** Normalized harness session. Required when the harness completed with a view. */\n trajectory?: TrajectoryView & { schemaVersion: string };\n\n diagnostics?: Partial<AdapterDiagnostics>;\n assertionResults: AssertionResult[];\n\n outcomeGrades?: OutcomeGrades;\n externalScores?: ExternalScore[];\n\n artifacts?: EvalArtifacts;\n\n /** Interchange-format predicted tool-call trajectory. */\n predicted_trajectory?: InterchangeToolCall[];\n\n /** Full multi-turn agent trace in interchange format. */\n agent_trace?: AgentTrace;\n\n /** Session latency in seconds (interchange field). */\n latency_in_seconds?: number;\n\n /** 1 when the harness run failed, 0 on success (interchange field). */\n failure?: 0 | 1;\n\n /** Trajectory-level metrics when reference_trajectory is provided. */\n trajectoryMetrics?: TrajectoryMetrics;\n\n /** Tool-call-level metrics when reference_trajectory is provided. */\n toolCallMetrics?: ToolCallMetrics;\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 tool-call trajectory for metric computation. */\n reference_trajectory?: TabularToolCall[];\n /** Human ratings keyed by metric name for judge calibration. */\n human_ratings?: Record<string, number>;\n assertionStats: EvalAssertionStat[];\n adapterErrors: number;\n /** Passed all behavioral assertion thresholds for this cell. */\n behavioralPass: boolean;\n /** Passed all outcome expectations when graded; omitted if not graded. */\n outcomePass?: boolean;\n repetitions: EvalRepetition[];\n}\n\n/**\n * Top-level document for CI/CD pipelines, APIs, and databases.\n *\n * This is the interchange format your storage layer should target — not\n * {@link import(\"./stream\").StreamEvent} or OTLP traces.\n */\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 /** UUID for this run; generated if omitted. */\n runId?: string;\n suite?: SuiteReference;\n harness?: Partial<HarnessInfo>;\n provenance?: EvalProvenance;\n /** Merge outcome grades from `gradeReport()` or compatible structure. */\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 transcript in each repetition's artifacts. Default true. */\n includeTranscript?: boolean;\n /** Include raw stream events when adapter provides them. Default false. */\n includeRawStreamEvents?: boolean;\n}\n","/**\n * Helpers for OTLP attribute values.\n */\n\nimport type { AnyValue, KeyValue } from \"./types\";\n\nexport function strAttr(key: string, value: string): KeyValue {\n return { key, value: { stringValue: value } };\n}\n\nexport function intAttr(key: string, value: number): KeyValue {\n return { key, value: { intValue: String(value) } };\n}\n\nexport function boolAttr(key: string, value: boolean): KeyValue {\n return { key, value: { boolValue: value } };\n}\n\nexport function jsonAttr(key: string, value: unknown): KeyValue {\n return { key, value: { stringValue: JSON.stringify(value) } };\n}\n\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 TrajectoryView.\n */\n\nimport type { AssistantTurn, ToolCall, TrajectoryView } from \"../types/trajectory\";\n\nexport interface GenAiMessage {\n role: string;\n parts: GenAiPart[];\n finish_reason?: string;\n}\n\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\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\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\nexport function toolResponsePart(call: ToolCall): GenAiPart {\n return {\n type: \"tool_call_response\",\n id: call.callId,\n result: call.result,\n };\n}\n\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\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\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\nexport interface ExportTraceServiceRequest {\n resourceSpans: ResourceSpans[];\n}\n\nexport interface ResourceSpans {\n resource: Resource;\n scopeSpans: ScopeSpans[];\n}\n\nexport interface Resource {\n attributes: KeyValue[];\n}\n\nexport interface ScopeSpans {\n scope: InstrumentationScope;\n spans: Span[];\n}\n\nexport interface InstrumentationScope {\n name: string;\n version?: string;\n}\n\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\nexport interface SpanStatus {\n code: number;\n message?: string;\n}\n\nexport interface KeyValue {\n key: string;\n value: AnyValue;\n}\n\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\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 matching the implementation plan naming. */\nexport const emitOtel = trajectoryToOtlp;\n\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\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\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\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\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\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\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\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\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\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\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\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\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\nexport function mergeJudgeClaudeOptions(\n claudeCode?: ClaudeCodeOptions,\n): ClaudeCodeOptions {\n return { ...JUDGE_CLAUDE_DEFAULTS, ...claudeCode };\n}\n\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\nexport function createClaudeGrader(\n options: ClaudeGraderOptions = {},\n): GraderFn {\n return (input) => runClaudeGrader(input, options);\n}\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\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\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\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\nconst MAX_RESULT_CHARS = 4000;\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\nfunction formatJson(value: unknown): string {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction formatResult(result: unknown): string {\n if (typeof result === \"string\") {\n return truncate(result);\n }\n return truncate(formatJson(result));\n}\n\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\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\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\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\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\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\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\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\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\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\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\nexport function toRenderableRows(report: SuiteReport): RenderableRow[] {\n return report.cells.map((cell) => cellToRow(cell));\n}\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\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\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 * Build interchange output from internal {@link TrajectoryView} data.\n */\n\nimport type {\n AgentTrace,\n InterchangeToolCall,\n TabularToolCall,\n} from \"../types/eval-interchange\";\nimport type { ToolCall, TrajectoryView } from \"../types/trajectory\";\n\nconst DEFAULT_AGENT_ID = \"agent\";\n\nexport function serializeToolInput(args: unknown): string {\n return JSON.stringify(args ?? {});\n}\n\nexport function parseToolInput(toolInput: string): unknown {\n try {\n return JSON.parse(toolInput) as unknown;\n } catch {\n return toolInput;\n }\n}\n\nexport function toolCallToInterchange(toolCall: ToolCall): InterchangeToolCall {\n return {\n tool_name: toolCall.name,\n tool_input: serializeToolInput(toolCall.args),\n };\n}\n\nexport function toolCallToTabular(toolCall: ToolCall): TabularToolCall {\n return {\n tool_name: toolCall.name,\n tool_input: toolCall.args ?? {},\n };\n}\n\nexport function interchangeToTabular(\n toolCall: InterchangeToolCall,\n): TabularToolCall {\n return {\n tool_name: toolCall.tool_name,\n tool_input: parseToolInput(toolCall.tool_input),\n };\n}\n\nexport function tabularToInterchange(\n toolCall: TabularToolCall,\n): InterchangeToolCall {\n return {\n tool_name: toolCall.tool_name,\n tool_input: serializeToolInput(toolCall.tool_input),\n };\n}\n\nexport function predictedTrajectoryFromView(\n view: TrajectoryView,\n): InterchangeToolCall[] {\n return view.toolCalls.map(toolCallToInterchange);\n}\n\nexport function buildAgentTrace(\n view: TrajectoryView,\n agentId: string = DEFAULT_AGENT_ID,\n): AgentTrace {\n const agents: AgentTrace[\"agents\"] = {\n [agentId]: {\n agent_id: agentId,\n agent_type: \"assistant\",\n description: view.meta.model,\n tools: view.meta.availableTools.map((name) => ({ name })),\n },\n };\n\n const activeTools = view.meta.availableTools.map((name) => ({ name }));\n\n const turns = view.turns.map((turn) => {\n const events: AgentTrace[\"turns\"][number][\"events\"] = [];\n\n if (turn.text) {\n events.push({\n author: agentId,\n content: { parts: [{ text: turn.text }] },\n active_tools: activeTools,\n });\n }\n\n for (const toolCall of turn.toolCalls) {\n events.push({\n author: agentId,\n content: {\n parts: [\n {\n function_call: {\n name: toolCall.name,\n args: toolCall.args ?? {},\n },\n },\n ],\n },\n active_tools: activeTools,\n });\n\n if (toolCall.result !== null && toolCall.result !== undefined) {\n events.push({\n author: agentId,\n content: {\n parts: [\n {\n function_response: {\n name: toolCall.name,\n response: toolCall.result,\n },\n },\n ],\n },\n active_tools: activeTools,\n });\n }\n }\n\n return {\n turn_index: turn.turnIndex,\n events,\n };\n });\n\n return { agents, turns };\n}\n\nexport function latencyInSeconds(view: TrajectoryView): number {\n return view.usage.durationMs / 1000;\n}\n\nexport function failureFlag(view: TrajectoryView): 0 | 1 {\n return view.success ? 0 : 1;\n}\n","/**\n * Trajectory-level metrics for comparing predicted and reference tool-call sequences.\n *\n * Metric definitions align with upstream evaluation service trajectory specs.\n */\n\nimport type {\n InterchangeToolCall,\n TabularToolCall,\n TrajectoryMetrics,\n} from \"../types/eval-interchange\";\nimport { serializeToolInput } from \"../eval-interchange/build\";\n\nexport type TrajectoryInput =\n | InterchangeToolCall[]\n | TabularToolCall[]\n | Array<{ tool_name: string; tool_input: unknown }>;\n\nfunction normalizeToolCall(\n toolCall: TrajectoryInput[number],\n): InterchangeToolCall {\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): InterchangeToolCall[] {\n return trajectory.map(normalizeToolCall);\n}\n\nfunction toolCallKey(toolCall: InterchangeToolCall): string {\n return `${toolCall.tool_name}\\0${toolCall.tool_input}`;\n}\n\nfunction multisetIntersectionSize(\n predicted: InterchangeToolCall[],\n reference: InterchangeToolCall[],\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\nfunction isSubsequence(\n predicted: InterchangeToolCall[],\n reference: InterchangeToolCall[],\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(\n left: InterchangeToolCall[],\n right: InterchangeToolCall[],\n): 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\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\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\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\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\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\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\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 * Tool-call-level metrics operating on prediction/reference tool-call pairs.\n *\n * Metric definitions align with upstream evaluation service tool-call specs.\n */\n\nimport type {\n InterchangeToolCall,\n TabularToolCall,\n ToolCallMetrics,\n} from \"../types/eval-interchange\";\nimport { parseToolInput, serializeToolInput } from \"../eval-interchange/build\";\n\nexport interface ToolCallMetricOptions {\n useStrictStringMatch?: boolean;\n}\n\ntype ToolCallInput =\n | InterchangeToolCall\n | TabularToolCall\n | { tool_name: string; tool_input: unknown };\n\nfunction normalizeToolCall(toolCall: ToolCallInput): InterchangeToolCall {\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 parsedArgs(toolCall: InterchangeToolCall): Record<string, unknown> | null {\n const parsed = parseToolInput(toolCall.tool_input);\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n return null;\n }\n return parsed as Record<string, unknown>;\n}\n\nexport function toolCallValid(toolCall: ToolCallInput): number {\n const normalized = normalizeToolCall(toolCall);\n if (!normalized.tool_name.trim()) return 0;\n\n try {\n JSON.parse(normalized.tool_input);\n return 1;\n } catch {\n return 0;\n }\n}\n\nexport function toolNameMatch(\n predicted: ToolCallInput,\n reference: ToolCallInput,\n): number {\n const predictedNorm = normalizeToolCall(predicted);\n const referenceNorm = normalizeToolCall(reference);\n return predictedNorm.tool_name === referenceNorm.tool_name ? 1 : 0;\n}\n\nexport function toolParameterKeyMatch(\n predicted: ToolCallInput,\n reference: ToolCallInput,\n): number {\n if (toolNameMatch(predicted, reference) === 0) return 0;\n\n const predictedArgs = parsedArgs(normalizeToolCall(predicted));\n const referenceArgs = parsedArgs(normalizeToolCall(reference));\n if (predictedArgs === null || referenceArgs === null) return 0;\n\n const predictedKeys = Object.keys(predictedArgs).sort();\n const referenceKeys = Object.keys(referenceArgs).sort();\n if (predictedKeys.length !== referenceKeys.length) return 0;\n\n return predictedKeys.every((key, index) => key === referenceKeys[index])\n ? 1\n : 0;\n}\n\nfunction valuesEqual(\n left: unknown,\n right: unknown,\n useStrictStringMatch: boolean,\n): boolean {\n if (useStrictStringMatch) {\n return JSON.stringify(left) === JSON.stringify(right);\n }\n return JSON.stringify(left) === JSON.stringify(right);\n}\n\nexport function toolParameterKvMatch(\n predicted: ToolCallInput,\n reference: ToolCallInput,\n options: ToolCallMetricOptions = {},\n): number {\n if (toolParameterKeyMatch(predicted, reference) === 0) return 0;\n\n const predictedArgs = parsedArgs(normalizeToolCall(predicted))!;\n const referenceArgs = parsedArgs(normalizeToolCall(reference))!;\n\n for (const key of Object.keys(referenceArgs)) {\n if (\n !valuesEqual(\n predictedArgs[key],\n referenceArgs[key],\n options.useStrictStringMatch ?? false,\n )\n ) {\n return 0;\n }\n }\n\n return 1;\n}\n\nexport function computeToolCallMetrics(\n predicted: ToolCallInput[],\n reference: ToolCallInput[],\n options: ToolCallMetricOptions = {},\n): ToolCallMetrics {\n const pairCount = Math.max(predicted.length, reference.length, 1);\n let valid = 0;\n let nameMatch = 0;\n let keyMatch = 0;\n let kvMatch = 0;\n\n for (let index = 0; index < pairCount; index += 1) {\n const predictedCall = predicted[index];\n const referenceCall = reference[index];\n if (!predictedCall) continue;\n\n valid += toolCallValid(predictedCall);\n if (!referenceCall) continue;\n\n nameMatch += toolNameMatch(predictedCall, referenceCall);\n keyMatch += toolParameterKeyMatch(predictedCall, referenceCall);\n kvMatch += toolParameterKvMatch(predictedCall, referenceCall, options);\n }\n\n return {\n tool_call_valid: valid / pairCount,\n tool_name_match: nameMatch / pairCount,\n tool_parameter_key_match: keyMatch / pairCount,\n tool_parameter_kv_match: kvMatch / pairCount,\n };\n}\n","/**\n * Envelope projection methods for eval interchange output.\n */\n\nimport {\n buildAgentTrace,\n interchangeToTabular,\n latencyInSeconds,\n predictedTrajectoryFromView,\n toolCallToTabular,\n} from \"./build\";\nimport type {\n AgentTrace,\n EvalDatasetRow,\n InterchangeToolCall,\n ProtoTrajectoryInstance,\n TabularToolCall,\n TrajectoryMetrics,\n} from \"../types/eval-interchange\";\nimport type {\n EvalCellResult,\n EvalRepetition,\n EvalRunEnvelope,\n} from \"../types/eval-record\";\nimport { computeTrajectoryMetrics } from \"../metrics/trajectory\";\nimport { computeToolCallMetrics } from \"../metrics/tool-calls\";\n\nfunction repetitionInterchangeFields(\n repetition: EvalRepetition,\n): {\n predicted_trajectory: InterchangeToolCall[];\n agent_trace?: AgentTrace;\n latency_in_seconds?: number;\n failure?: 0 | 1;\n} {\n if (!repetition.trajectory) {\n return { predicted_trajectory: [] };\n }\n\n return {\n predicted_trajectory: repetition.predicted_trajectory ??\n predictedTrajectoryFromView(repetition.trajectory),\n agent_trace: repetition.agent_trace ??\n buildAgentTrace(repetition.trajectory),\n latency_in_seconds: repetition.latency_in_seconds ??\n latencyInSeconds(repetition.trajectory),\n failure: repetition.failure ?? (repetition.trajectory.success ? 0 : 1),\n };\n}\n\nfunction referenceTrajectoryForCell(\n cell: EvalCellResult,\n): TabularToolCall[] | undefined {\n return cell.reference_trajectory;\n}\n\nexport function repetitionToDatasetRow(\n cell: EvalCellResult,\n repetition: EvalRepetition,\n): EvalDatasetRow | null {\n const fields = repetitionInterchangeFields(repetition);\n if (!repetition.trajectory) {\n return {\n prompt: cell.prompt,\n response: undefined,\n predicted_trajectory: [],\n reference_trajectory: referenceTrajectoryForCell(cell),\n latency_in_seconds: repetition.durationMs / 1000,\n failure: 1,\n human_ratings: cell.human_ratings,\n };\n }\n\n return {\n prompt: cell.prompt,\n response: repetition.trajectory.finalResponse,\n predicted_trajectory: fields.predicted_trajectory.map(interchangeToTabular),\n reference_trajectory: referenceTrajectoryForCell(cell),\n latency_in_seconds: fields.latency_in_seconds ?? repetition.durationMs / 1000,\n failure: fields.failure ?? 1,\n human_ratings: cell.human_ratings,\n };\n}\n\nexport function repetitionToProtoInstance(\n cell: EvalCellResult,\n repetition: EvalRepetition,\n): ProtoTrajectoryInstance | null {\n const fields = repetitionInterchangeFields(repetition);\n if (!repetition.trajectory) return null;\n\n const reference = referenceTrajectoryForCell(cell);\n return {\n prompt: cell.prompt,\n response: repetition.trajectory.finalResponse,\n predicted_trajectory: {\n tool_calls: fields.predicted_trajectory,\n },\n reference_trajectory: reference\n ? {\n tool_calls: reference.map((toolCall) => ({\n tool_name: toolCall.tool_name,\n tool_input:\n typeof toolCall.tool_input === \"string\"\n ? toolCall.tool_input\n : JSON.stringify(toolCall.tool_input ?? {}),\n })),\n }\n : undefined,\n };\n}\n\nexport function repetitionToAgentTrace(\n repetition: EvalRepetition,\n): AgentTrace | null {\n const fields = repetitionInterchangeFields(repetition);\n return fields.agent_trace ?? null;\n}\n\nexport function computeRepetitionMetrics(\n repetition: EvalRepetition,\n referenceTrajectory?: TabularToolCall[],\n): {\n trajectoryMetrics?: TrajectoryMetrics;\n toolCallMetrics?: ReturnType<typeof computeToolCallMetrics>;\n} {\n if (!referenceTrajectory?.length) {\n return {};\n }\n\n const predicted = repetition.predicted_trajectory ??\n (repetition.trajectory\n ? predictedTrajectoryFromView(repetition.trajectory)\n : []);\n\n const predictedTabular = predicted.map(interchangeToTabular);\n\n return {\n trajectoryMetrics: computeTrajectoryMetrics(\n predictedTabular,\n referenceTrajectory,\n ),\n toolCallMetrics: computeToolCallMetrics(\n predictedTabular,\n referenceTrajectory,\n ),\n };\n}\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 const row = repetitionToDatasetRow(cell, repetition);\n if (row) rows.push(row);\n }\n }\n return rows;\n}\n\nexport function toProtoInstances(\n envelope: EvalRunEnvelope,\n): ProtoTrajectoryInstance[] {\n const instances: ProtoTrajectoryInstance[] = [];\n for (const cell of envelope.cells) {\n for (const repetition of cell.repetitions) {\n const instance = repetitionToProtoInstance(cell, repetition);\n if (instance) instances.push(instance);\n }\n }\n return instances;\n}\n\nexport function toAgentTrace(envelope: EvalRunEnvelope): AgentTrace[] {\n const traces: AgentTrace[] = [];\n for (const cell of envelope.cells) {\n for (const repetition of cell.repetitions) {\n const trace = repetitionToAgentTrace(repetition);\n if (trace) traces.push(trace);\n }\n }\n return traces;\n}\n\nexport function enrichRepetitionWithInterchange(\n repetition: EvalRepetition,\n referenceTrajectory?: TabularToolCall[],\n): EvalRepetition {\n if (!repetition.trajectory) {\n return repetition;\n }\n\n const predicted_trajectory = predictedTrajectoryFromView(repetition.trajectory);\n const agent_trace = buildAgentTrace(repetition.trajectory);\n const latency_in_seconds = latencyInSeconds(repetition.trajectory);\n const failure = repetition.trajectory.success ? 0 : 1;\n\n const metrics = computeRepetitionMetrics(\n {\n ...repetition,\n predicted_trajectory,\n agent_trace,\n latency_in_seconds,\n failure,\n },\n referenceTrajectory,\n );\n\n return {\n ...repetition,\n predicted_trajectory,\n agent_trace,\n latency_in_seconds,\n failure,\n trajectoryMetrics: metrics.trajectoryMetrics,\n toolCallMetrics: metrics.toolCallMetrics,\n };\n}\n","/**\n * Build {@link EvalRunEnvelope} from harness-eval run and grading reports.\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 { enrichRepetitionWithInterchange } from \"../eval-interchange/projections\";\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\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\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 */\nexport function buildEvalRunEnvelope(\n report: SuiteReport,\n options: BuildEvalRunEnvelopeOptions = {},\n): EvalRunEnvelope {\n const includeTranscript = options.includeTranscript !== false;\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 referenceTrajectory = cell.reference_trajectory;\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 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 return enrichRepetitionWithInterchange(base, referenceTrajectory);\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 reference_trajectory: cell.reference_trajectory,\n human_ratings: 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 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/** Build envelope from on-disk report + optional grading JSON paths. */\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"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code-ycT0JQZF.js","names":[],"sources":["../src/types/stream.ts","../src/types/trajectory.ts","../src/trajectory/builder.ts","../src/parsers/stream-json.ts","../src/adapters/types.ts","../src/adapters/claude-code/flags.ts","../src/adapters/claude-code/process.ts","../src/adapters/claude-code/index.ts"],"sourcesContent":["/**\n * Discriminated union of events emitted by Claude Code's\n * `--output-format stream-json` mode.\n *\n * The format is NDJSON (one JSON object per line on stdout). Each line has\n * a required `type` field and often a `subtype` for further disambiguation.\n *\n * Source notes: the stream-json schema is not formally documented as of mid-2026.\n * These types are derived from:\n * - https://code.claude.com/docs/en/headless\n * - https://github.com/anthropics/claude-code/issues/24612 (event-types tracking issue)\n * - https://takopi.dev/reference/runners/claude/stream-json-cheatsheet/\n * - The `@anthropic-ai/claude-agent-sdk` TypeScript declaration files,\n * which are the de-facto source of truth.\n *\n * When adding new event types, prefer extending the union here rather than\n * branching on `any` in callers. Unknown events should be tolerated silently\n * by the builder (the schema evolves and we don't want CI to break on a new\n * event type we haven't modelled yet).\n */\n\n/** Top-level discriminated union of stream-json events. */\nexport type StreamEvent =\n | SystemInitEvent\n | SystemRetryEvent\n | SystemPluginInstallEvent\n | SystemCompactBoundaryEvent\n | SystemUnknownEvent\n | AssistantMessageEvent\n | UserMessageEvent\n | ResultEvent;\n\n// system events\n\n/** Emitted once at session start. Carries the session-level metadata. */\nexport interface SystemInitEvent {\n type: \"system\";\n subtype: \"init\";\n session_id: string;\n cwd: string;\n model: string;\n permissionMode?: string;\n apiKeySource?: string;\n /** Names of tools available in the session (built-in + MCP). */\n tools: string[];\n /** MCP servers configured for this session, with connection status. */\n mcp_servers: McpServerStatus[];\n}\n\nexport interface McpServerStatus {\n name: string;\n status: \"connected\" | \"disconnected\" | \"error\" | string;\n}\n\n/** Emitted when the API rate-limits us or otherwise asks for a retry. */\nexport interface SystemRetryEvent {\n type: \"system\";\n subtype: \"api_retry\";\n session_id: string;\n /** Implementation-defined retry payload (delay, reason, etc). */\n [key: string]: unknown;\n}\n\n/** Emitted while marketplace plugins are installing pre-session. */\nexport interface SystemPluginInstallEvent {\n type: \"system\";\n subtype: \"plugin_install\";\n session_id: string;\n [key: string]: unknown;\n}\n\n/** Emitted when Claude Code compacts the context window mid-session. */\nexport interface SystemCompactBoundaryEvent {\n type: \"system\";\n subtype: \"compact_boundary\";\n session_id: string;\n [key: string]: unknown;\n}\n\n/**\n * Catch-all for `type: \"system\"` events we haven't modelled.\n *\n * Keeps the union exhaustive while tolerating schema evolution. Callers should\n * either explicitly handle a known subtype or fall through to ignore.\n */\nexport interface SystemUnknownEvent {\n type: \"system\";\n subtype: string;\n session_id?: string;\n [key: string]: unknown;\n}\n\n// conversational events\n\n/** One assistant turn. The `message` field mirrors the Anthropic Messages API shape. */\nexport interface AssistantMessageEvent {\n type: \"assistant\";\n session_id: string;\n message: AssistantMessage;\n}\n\nexport interface AssistantMessage {\n id: string;\n type: \"message\";\n role: \"assistant\";\n content: ContentBlock[];\n model?: string;\n stop_reason?: StopReason | null;\n usage?: Usage;\n}\n\n/**\n * A user-role message in the stream.\n *\n * In stream-json these are usually *synthetic* — the harness injects them to\n * feed tool results back into the conversation after dispatching a tool. The\n * very first user message (the prompt) is also emitted here for completeness.\n */\nexport interface UserMessageEvent {\n type: \"user\";\n session_id: string;\n message: UserMessage;\n}\n\nexport interface UserMessage {\n role: \"user\";\n /** String for the initial prompt, array of blocks when carrying tool results. */\n content: ContentBlock[] | string;\n}\n\n// content blocks\n\nexport type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock;\n\nexport interface TextBlock {\n type: \"text\";\n text: string;\n}\n\nexport interface ToolUseBlock {\n type: \"tool_use\";\n /** Unique id assigned by the model; used to match tool_result back to this call. */\n id: string;\n /** Tool name. MCP tools follow the convention `mcp__<server>__<tool>`. */\n name: string;\n /** Arguments the model passed. Schema is per-tool. */\n input: unknown;\n}\n\nexport interface ToolResultBlock {\n type: \"tool_result\";\n /** The id of the corresponding tool_use block. */\n tool_use_id: string;\n /** Tool output. May be plain text or further content blocks for richer tools. */\n content: string | ContentBlock[];\n is_error?: boolean;\n}\n\n// result envelope\n\n/** Emitted once at session end. Carries aggregate usage and cost. */\nexport interface ResultEvent {\n type: \"result\";\n subtype: \"success\" | \"error\";\n session_id: string;\n total_cost_usd: number;\n is_error: boolean;\n duration_ms: number;\n duration_api_ms?: number;\n num_turns: number;\n /** The final text the harness returned, if any. */\n result?: string;\n usage?: Usage;\n}\n\n// shared scalars\n\n/**\n * Reasons the model can stop a turn. Open-ended string union because new\n * stop reasons appear over time.\n */\nexport type StopReason =\n | \"end_turn\"\n | \"tool_use\"\n | \"max_tokens\"\n | \"stop_sequence\"\n | (string & {});\n\nexport interface Usage {\n input_tokens: number;\n output_tokens: number;\n cache_creation_input_tokens?: number;\n cache_read_input_tokens?: number;\n}\n\n// type guards\n\n/** Type guards. Prefer these over manual `e.type === \"...\"` checks at call sites. */\n\nexport function isSystemInit(e: StreamEvent): e is SystemInitEvent {\n return e.type === \"system\" && (e as SystemInitEvent).subtype === \"init\";\n}\n\nexport function isSystemRetry(e: StreamEvent): e is SystemRetryEvent {\n return e.type === \"system\" && (e as SystemRetryEvent).subtype === \"api_retry\";\n}\n\nexport function isAssistantMessage(e: StreamEvent): e is AssistantMessageEvent {\n return e.type === \"assistant\";\n}\n\nexport function isUserMessage(e: StreamEvent): e is UserMessageEvent {\n return e.type === \"user\";\n}\n\nexport function isResult(e: StreamEvent): e is ResultEvent {\n return e.type === \"result\";\n}\n\nexport function isTextBlock(b: ContentBlock): b is TextBlock {\n return b.type === \"text\";\n}\n\nexport function isToolUseBlock(b: ContentBlock): b is ToolUseBlock {\n return b.type === \"tool_use\";\n}\n\nexport function isToolResultBlock(b: ContentBlock): b is ToolResultBlock {\n return b.type === \"tool_result\";\n}\n","/**\n * TrajectoryView — the assertion-friendly projection of a Claude Code session.\n *\n * The view is derived from the stream of {@link StreamEvent} values produced by\n * the harness, but is optimized for the queries that the assertion DSL needs to\n * express:\n *\n * - did tool X get called? (look at `toolCalls`)\n * - did tool A come before tool B? (compare `turnIndex` / `callIndex`)\n * - was a tool called with arguments matching predicate P? (`toolCalls[i].args`)\n * - did the agent answer without using any tool? (`toolCalls.length === 0`)\n *\n * The view is reconstructable from the raw events (lossless w.r.t. assertions),\n * but operating on it directly is dramatically simpler than walking event\n * streams or OTel span trees.\n *\n * Design notes:\n * - `turnIndex` and `callIndex` are the right primitives for ordering.\n * Wall-clock timestamps from the stream are unreliable for sub-second\n * ordering and parallel tool dispatch.\n * - Parallel tool calls (multiple `tool_use` blocks in one assistant message)\n * share a `turnIndex` but have distinct `callIndex` values in emission order.\n * - `namespace` is precomputed so assertions like `called(pattern: \"mcp__api__*\")`\n * can do a cheap string check.\n */\n\nimport type { StopReason } from \"./stream\";\n\nexport interface TrajectoryView {\n /** Session metadata, captured from the `system/init` event. */\n meta: SessionMeta;\n\n /** Every tool call, in global emission order. */\n toolCalls: ToolCall[];\n\n /** Each assistant turn: text content + any tool calls emitted in that turn. */\n turns: AssistantTurn[];\n\n /** All assistant text concatenated across turns. Useful for `response_contains`. */\n finalResponse: string;\n\n /** Stop reason of the *last* assistant turn. */\n finalStopReason: StopReason | null;\n\n /** Aggregate usage and cost from the result event. */\n usage: UsageSummary;\n\n /** Retry events observed during the run (rate limits, transient errors). */\n retries: RetryRecord[];\n\n /** Whether the result envelope indicated success. */\n success: boolean;\n}\n\nexport interface SessionMeta {\n sessionId: string;\n model: string;\n cwd: string;\n permissionMode?: string;\n /** Tool names the harness reported as available at session start. */\n availableTools: string[];\n /** MCP servers configured for the session, with connection status. */\n mcpServers: { name: string; status: string }[];\n}\n\nexport interface ToolCall {\n /** Fully-qualified tool name, e.g. `\"mcp__api__search_skills\"` or `\"Bash\"`. */\n name: string;\n\n /**\n * Namespace prefix for MCP-style names (`\"mcp__api\"`), or null for built-ins.\n * Precomputed via {@link namespaceOf} for cheap pattern matching.\n */\n namespace: string | null;\n\n /** The `tool_use` block's `id`; matches a later `tool_result.tool_use_id`. */\n callId: string;\n\n /** Args the model emitted on this call. Tool-specific schema. */\n args: unknown;\n\n /** Tool result, or null if no result was observed (e.g. process killed). */\n result: unknown | null;\n\n /** Whether the tool reported an error in its result. */\n isError: boolean;\n\n /**\n * Which assistant turn produced this call. Parallel calls within a single\n * assistant message share a `turnIndex`.\n */\n turnIndex: number;\n\n /** Index in the global ordered tool-call sequence. */\n callIndex: number;\n}\n\nexport interface AssistantTurn {\n turnIndex: number;\n /** Text emitted in this turn (may be empty if turn was tool-only). */\n text: string;\n /** Tool calls emitted in this turn, in their block order. */\n toolCalls: ToolCall[];\n /** Stop reason reported by the model for this turn. */\n stopReason: StopReason | null;\n}\n\nexport interface UsageSummary {\n inputTokens: number;\n outputTokens: number;\n totalCostUsd: number;\n durationMs: number;\n numTurns: number;\n}\n\nexport interface RetryRecord {\n /** ms since session start (approximate; the stream doesn't include precise ts). */\n offsetMs: number;\n /** Raw payload from the `system/api_retry` event for diagnostics. */\n raw: unknown;\n}\n\n// helpers\n\n/**\n * Extract the MCP namespace prefix from a tool name.\n *\n * Claude Code formats MCP tool names as `mcp__<server>__<tool>`. The namespace\n * is the first two segments joined: `mcp__<server>`. Returns null for non-MCP\n * tool names (built-ins like `Bash`, `Read`, `Edit`).\n *\n * @example\n * namespaceOf(\"mcp__api__search_skills\") // \"mcp__api\"\n * namespaceOf(\"Bash\") // null\n */\nexport function namespaceOf(toolName: string): string | null {\n if (!toolName.startsWith(\"mcp__\")) return null;\n const parts = toolName.split(\"__\");\n if (parts.length < 3) return null;\n return `${parts[0]}__${parts[1]}`;\n}\n","/**\n * TrajectoryBuilder — consumes a stream of {@link StreamEvent} values and\n * produces a {@link TrajectoryView}.\n *\n * State machine: the builder is a small, tolerant state machine. Invariants:\n *\n * - Exactly one `system/init` event opens the session. The builder requires\n * it to be present before `build()`.\n * - Each `assistant` event begins a new turn. Text blocks accumulate into\n * the turn's text; `tool_use` blocks become `ToolCall` records.\n * - `user` events with `tool_result` blocks deliver tool results back. We\n * match them to pending calls by `tool_use_id`.\n * - One `result` event closes the session and carries aggregate usage.\n *\n * The builder is *tolerant of partial streams*: a process killed mid-run\n * produces a coherent (but flagged) view. Tool calls without matching results\n * keep `result: null`. The `success` flag reflects whether a successful result\n * event was actually observed.\n *\n * Why a class (not a reducer)?\n * The internal `pendingCalls` map is mutable by design — we modify ToolCall\n * objects in place when results arrive, so other parts of the view (which\n * hold references to the same objects) see the update for free. A reducer\n * would force a deep copy per result event, which is wasteful and would\n * complicate identity-based queries.\n */\n\nimport {\n isAssistantMessage,\n isResult,\n isSystemInit,\n isTextBlock,\n isToolResultBlock,\n isToolUseBlock,\n isUserMessage,\n type StreamEvent,\n type Usage,\n} from \"../types/stream\";\nimport {\n namespaceOf,\n type AssistantTurn,\n type RetryRecord,\n type SessionMeta,\n type ToolCall,\n type TrajectoryView,\n} from \"../types/trajectory\";\n\nexport class TrajectoryBuilder {\n private meta: SessionMeta | null = null;\n private sessionStartTs: number | null = null;\n\n private turns: AssistantTurn[] = [];\n private allToolCalls: ToolCall[] = [];\n\n /**\n * tool_use_id → ToolCall, for matching results back to calls.\n * Entries are removed once a result is observed.\n */\n private pendingCalls: Map<string, ToolCall> = new Map();\n\n private retries: RetryRecord[] = [];\n\n private finalUsage: Usage | null = null;\n private finalCostUsd = 0;\n private finalDurationMs = 0;\n private finalNumTurns = 0;\n private finalResultText = \"\";\n private sawResultEvent = false;\n private resultIsError = false;\n\n /**\n * Consume one event. Safe to call with events in stream order.\n *\n * Unknown event types are silently ignored — the schema evolves and we\n * don't want CI to break on a new event type we haven't modelled.\n */\n consume(event: StreamEvent): void {\n if (isSystemInit(event)) {\n this.meta = {\n sessionId: event.session_id,\n model: event.model,\n cwd: event.cwd,\n permissionMode: event.permissionMode,\n availableTools: event.tools ?? [],\n mcpServers: (event.mcp_servers ?? []).map((s) => ({\n name: s.name,\n status: s.status,\n })),\n };\n this.sessionStartTs = Date.now();\n return;\n }\n\n if (event.type === \"system\" && event.subtype === \"api_retry\") {\n this.retries.push({\n offsetMs: this.sessionStartTs ? Date.now() - this.sessionStartTs : 0,\n raw: event,\n });\n return;\n }\n\n if (isAssistantMessage(event)) {\n this.handleAssistantMessage(event);\n return;\n }\n\n if (isUserMessage(event)) {\n this.handleUserMessage(event);\n return;\n }\n\n if (isResult(event)) {\n this.sawResultEvent = true;\n this.resultIsError = event.is_error;\n this.finalUsage = event.usage ?? null;\n this.finalCostUsd = event.total_cost_usd ?? 0;\n this.finalDurationMs = event.duration_ms ?? 0;\n this.finalNumTurns = event.num_turns ?? 0;\n this.finalResultText = event.result ?? \"\";\n return;\n }\n\n // Unknown event: ignored. See class doc.\n }\n\n /**\n * Finalize the view. Call after consuming the last event from the stream.\n *\n * Throws if no `system/init` was observed — at that point we have no model,\n * no session id, and no available-tools list, which means assertions like\n * \"called any mcp__api__* tool\" can't even be evaluated meaningfully.\n */\n build(): TrajectoryView {\n if (this.meta === null) {\n throw new Error(\n \"TrajectoryBuilder.build() called before any system/init event was observed. \" +\n \"The harness may have failed to start, or the stream was truncated before init.\",\n );\n }\n\n const lastTurn = this.turns[this.turns.length - 1];\n\n // Prefer the assistant text we accumulated turn-by-turn over the\n // `result.result` field, because the latter is sometimes a summary\n // and the former is exactly what the model said.\n const accumulatedText = this.turns\n .map((t) => t.text)\n .filter((t) => t.length > 0)\n .join(\"\\n\\n\")\n .trim();\n\n return {\n meta: this.meta,\n toolCalls: this.allToolCalls,\n turns: this.turns,\n finalResponse: accumulatedText || this.finalResultText,\n finalStopReason: lastTurn?.stopReason ?? null,\n usage: {\n inputTokens: this.finalUsage?.input_tokens ?? 0,\n outputTokens: this.finalUsage?.output_tokens ?? 0,\n totalCostUsd: this.finalCostUsd,\n durationMs: this.finalDurationMs,\n // Fall back to observed turn count if the result event was missing.\n numTurns: this.finalNumTurns || this.turns.length,\n },\n retries: this.retries,\n // Successful = saw a non-error result envelope. Streams that ended without\n // a result event are reported as unsuccessful regardless of tool outcomes.\n success: this.sawResultEvent && !this.resultIsError,\n };\n }\n\n // private handlers\n\n private handleAssistantMessage(\n event: Extract<StreamEvent, { type: \"assistant\" }>,\n ): void {\n const turnIndex = this.turns.length;\n const textChunks: string[] = [];\n const toolCallsThisTurn: ToolCall[] = [];\n\n for (const block of event.message.content) {\n if (isTextBlock(block)) {\n textChunks.push(block.text);\n continue;\n }\n if (isToolUseBlock(block)) {\n const call: ToolCall = {\n name: block.name,\n namespace: namespaceOf(block.name),\n callId: block.id,\n args: block.input,\n result: null,\n isError: false,\n turnIndex,\n callIndex: this.allToolCalls.length,\n };\n this.allToolCalls.push(call);\n this.pendingCalls.set(block.id, call);\n toolCallsThisTurn.push(call);\n continue;\n }\n // tool_result blocks don't appear in assistant messages — those arrive\n // via user messages. If one does appear, ignore it; we'd rather drop\n // an unexpected block than crash the eval.\n }\n\n this.turns.push({\n turnIndex,\n text: textChunks.join(\"\").trim(),\n toolCalls: toolCallsThisTurn,\n stopReason: event.message.stop_reason ?? null,\n });\n }\n\n private handleUserMessage(\n event: Extract<StreamEvent, { type: \"user\" }>,\n ): void {\n const content = event.message.content;\n\n // The very first user message carries the prompt as a plain string. We\n // already know the prompt (the caller passed it to the adapter), so we\n // ignore this case — there's nothing assertion-relevant in it.\n if (typeof content === \"string\") return;\n\n for (const block of content) {\n if (!isToolResultBlock(block)) continue;\n\n const call = this.pendingCalls.get(block.tool_use_id);\n if (!call) {\n // Unmatched result: ignore. Can happen if events arrive out of order\n // or the corresponding tool_use was emitted in an earlier run that\n // we're resuming. Either way, dropping is safer than throwing.\n continue;\n }\n\n call.result = block.content;\n call.isError = block.is_error ?? false;\n this.pendingCalls.delete(block.tool_use_id);\n }\n }\n}\n\n/**\n * Convenience: drain an async iterable of events through a fresh builder.\n *\n * Suitable when you have the full event stream and just want the view.\n * For interactive/incremental scenarios (e.g. surfacing partial state in a UI)\n * instantiate {@link TrajectoryBuilder} directly and call `consume()` /\n * `build()` yourself.\n */\nexport async function buildTrajectory(\n events: AsyncIterable<StreamEvent>,\n): Promise<TrajectoryView> {\n const builder = new TrajectoryBuilder();\n for await (const event of events) {\n builder.consume(event);\n }\n return builder.build();\n}\n","/**\n * Line-buffered NDJSON parser for Claude Code's `--output-format stream-json`.\n *\n * Claude Code emits one JSON object per line on stdout. The parser:\n * - buffers across chunk boundaries (a single JSON line may arrive in two reads)\n * - skips empty lines (defensive — shouldn't occur, but harmless if it does)\n * - emits a discriminated `ParseResult` per line so callers can decide whether\n * a malformed line should abort the run or just be logged.\n *\n * Why a generator (and not a Transform stream)?\n * The eval adapter consumes events sequentially and synchronously updates a\n * builder. Async iteration is the simplest interface for that pattern and\n * composes cleanly with `for await` in the adapter. A Transform would force\n * the builder into event-handler style.\n */\n\nimport type { Readable } from \"node:stream\";\nimport type { StreamEvent } from \"../types/stream\";\n\n/**\n * Result of attempting to parse a single line.\n *\n * Successful parses yield `{ ok: true }` with the typed event and the raw line\n * (kept for diagnostics and OTel `events.attributes.raw`). Failed parses yield\n * `{ ok: false }` with the parse error and the raw line — callers can log,\n * skip, or fail the run as they see fit.\n */\nexport type ParseResult =\n | { ok: true; event: StreamEvent; rawLine: string }\n | { ok: false; error: Error; rawLine: string };\n\n/**\n * Parse a readable stream of NDJSON into a sequence of typed stream-json events.\n *\n * @example\n * const child = spawn(\"claude\", [\"-p\", prompt, \"--output-format\", \"stream-json\", \"--verbose\"]);\n * for await (const result of parseStreamJson(child.stdout)) {\n * if (result.ok) builder.consume(result.event);\n * else console.warn(\"malformed stream line:\", result.rawLine, result.error);\n * }\n */\nexport async function* parseStreamJson(\n stream: Readable,\n): AsyncGenerator<ParseResult, void, void> {\n let buffer = \"\";\n // The Node child_process stdout is a binary stream by default. Setting the\n // encoding here means `for await (const chunk of stream)` yields strings.\n stream.setEncoding(\"utf8\");\n\n for await (const chunk of stream) {\n buffer += chunk as string;\n\n // Drain every complete line currently in the buffer before reading more.\n // Multiple JSON objects can arrive in one chunk (e.g. when the harness\n // emits a burst of events at session start).\n let newlineIdx: number;\n while ((newlineIdx = buffer.indexOf(\"\\n\")) !== -1) {\n const line = buffer.slice(0, newlineIdx).trim();\n buffer = buffer.slice(newlineIdx + 1);\n if (line.length === 0) continue;\n yield tryParseLine(line);\n }\n }\n\n // Flush any trailing content that arrived without a final newline. Stream-json\n // typically ends with a newline-terminated `result` event, but a killed\n // process may not flush, so we still try to emit what we have.\n const trailing = buffer.trim();\n if (trailing.length > 0) {\n yield tryParseLine(trailing);\n }\n}\n\n/**\n * Parse a single line. Extracted as a helper so the generator stays readable.\n *\n * Note: we do not validate the event structure beyond `JSON.parse`. Runtime\n * validation (e.g. zod) is overkill here — the schema is stable enough at\n * runtime, and the TrajectoryBuilder is tolerant of missing fields. Adding\n * validation would be premature.\n */\nfunction tryParseLine(line: string): ParseResult {\n try {\n const event = JSON.parse(line) as StreamEvent;\n return { ok: true, event, rawLine: line };\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err : new Error(String(err)),\n rawLine: line,\n };\n }\n}\n","/**\n * Generic harness adapter contract.\n *\n * Every harness adapter produces a {@link TrajectoryView} plus process\n * diagnostics. The runner and assertion engine depend only on these types —\n * not on any specific harness implementation.\n */\n\nimport type { TrajectoryView } from \"../types/trajectory\";\n\n/** Base config every adapter must accept. */\nexport interface BaseAdapterConfig {\n prompt: string;\n model?: string;\n timeoutMs?: number;\n signal?: AbortSignal;\n env?: Record<string, string>;\n cwd?: string;\n}\n\n/** Suite-level config: generic fields plus adapter-specific nested blocks. */\nexport type SuiteConfig = Partial<BaseAdapterConfig> & {\n /** Claude Code adapter options (when `adapter` is `claude-code`). */\n claudeCode?: Record<string, unknown>;\n};\n\n/** Generic harness adapter interface. */\nexport interface HarnessAdapter<\n TConfig extends BaseAdapterConfig = BaseAdapterConfig,\n> {\n readonly id: string;\n run(config: TConfig): Promise<AdapterResult>;\n}\n\n/** Successful adapter run. */\nexport interface AdapterResult {\n view: TrajectoryView;\n diagnostics: AdapterDiagnostics;\n}\n\n/** Process-level diagnostics from any adapter. */\nexport interface AdapterDiagnostics {\n exitCode: number | null;\n signal: NodeJS.Signals | null;\n stderr: string;\n parseErrors: ParseErrorRecord[];\n timedOut: boolean;\n durationMs: number;\n}\n\nexport interface ParseErrorRecord {\n line: string;\n error: string;\n}\n\n/**\n * Thrown when the harness fails to produce a usable trajectory.\n *\n * Most commonly this means the process failed before emitting a usable\n * session init event. Inspect `diagnostics.stderr` for the cause.\n */\nexport class AdapterError extends Error {\n constructor(\n message: string,\n public readonly diagnostics: Partial<AdapterDiagnostics>,\n ) {\n super(message);\n this.name = \"AdapterError\";\n }\n}\n","/**\n * Build CLI args for Claude Code judge subprocesses (JSON output, not stream-json).\n */\n\nimport type { ClaudeCodeAdapterConfig, ClaudeCodeOptions } from \"./types\";\n\nfunction pushRepeatableFlag(args: string[], flag: string, values?: string[]): void {\n if (!values) return;\n for (const value of values) {\n args.push(flag, value);\n }\n}\n\nfunction pushOptionalFlag(\n args: string[],\n flag: string,\n value: string | number | boolean | undefined,\n): void {\n if (value === undefined) return;\n if (typeof value === \"boolean\") {\n if (value) args.push(flag);\n return;\n }\n args.push(flag, String(value));\n}\n\n/** Append Claude Code CLI flags shared by harness runs and grading judges. */\nexport function appendClaudeCodeFlags(\n args: string[],\n config: ClaudeCodeOptions & { model?: string },\n): void {\n pushRepeatableFlag(args, \"--plugin-dir\", config.pluginDirs);\n pushRepeatableFlag(args, \"--plugin-url\", config.pluginUrls);\n pushRepeatableFlag(args, \"--add-dir\", config.addDirs);\n\n pushOptionalFlag(args, \"--mcp-config\", config.mcpConfig);\n pushOptionalFlag(args, \"--model\", config.model);\n pushOptionalFlag(args, \"--permission-mode\", config.permissionMode);\n pushOptionalFlag(args, \"--effort\", config.effort);\n pushOptionalFlag(args, \"--agent\", config.agent);\n pushOptionalFlag(args, \"--fallback-model\", config.fallbackModel);\n pushOptionalFlag(args, \"--tools\", config.tools);\n pushOptionalFlag(args, \"--settings\", config.settings);\n pushOptionalFlag(args, \"--setting-sources\", config.settingSources);\n pushOptionalFlag(args, \"--max-turns\", config.maxTurns);\n pushOptionalFlag(args, \"--max-budget-usd\", config.maxBudgetUsd);\n pushOptionalFlag(args, \"--system-prompt\", config.systemPrompt);\n pushOptionalFlag(args, \"--system-prompt-file\", config.systemPromptFile);\n pushOptionalFlag(args, \"--append-system-prompt\", config.appendSystemPrompt);\n pushOptionalFlag(\n args,\n \"--append-system-prompt-file\",\n config.appendSystemPromptFile,\n );\n pushOptionalFlag(args, \"--debug\", config.debug);\n pushOptionalFlag(args, \"--debug-file\", config.debugFile);\n\n if (config.allowedTools && config.allowedTools.length > 0) {\n args.push(\"--allowedTools\", config.allowedTools.join(\",\"));\n }\n\n if (config.disallowedTools && config.disallowedTools.length > 0) {\n args.push(\"--disallowedTools\", config.disallowedTools.join(\",\"));\n }\n\n pushOptionalFlag(args, \"--strict-mcp-config\", config.strictMcpConfig);\n pushOptionalFlag(args, \"--include-hook-events\", config.includeHookEvents);\n pushOptionalFlag(args, \"--no-session-persistence\", config.noSessionPersistence);\n pushOptionalFlag(args, \"--disable-slash-commands\", config.disableSlashCommands);\n pushOptionalFlag(args, \"--bare\", config.bare);\n pushOptionalFlag(args, \"--safe-mode\", config.safeMode);\n pushOptionalFlag(\n args,\n \"--allow-dangerously-skip-permissions\",\n config.allowDangerouslySkipPermissions,\n );\n pushOptionalFlag(\n args,\n \"--dangerously-skip-permissions\",\n config.dangerouslySkipPermissions,\n );\n}\n\n/**\n * Build the argument vector for spawning `claude`.\n *\n * Order matters only for flags that take values — value flags must come\n * after their flag name. Everything else is order-independent.\n */\nexport function buildArgs(config: ClaudeCodeAdapterConfig): string[] {\n const args: string[] = [\n \"-p\",\n config.prompt,\n \"--output-format\",\n \"stream-json\",\n \"--verbose\",\n ];\n\n appendClaudeCodeFlags(args, config);\n\n return args;\n}\n\n/** Build args for an LLM judge subprocess (`--output-format json`). */\nexport function buildJudgeArgs(\n prompt: string,\n config: ClaudeCodeOptions & { model?: string } = {},\n): string[] {\n const args: string[] = [\"-p\", prompt, \"--output-format\", \"json\"];\n const permissionMode = config.permissionMode ?? \"bypassPermissions\";\n appendClaudeCodeFlags(args, {\n ...config,\n permissionMode,\n });\n return args;\n}\n","/**\n * Process management for the Claude Code adapter.\n *\n * This module owns spawning, timeout, abort signal handling, and process-tree\n * teardown. The orchestrator (`index.ts`) consumes the returned handle —\n * reading stdout and waiting for completion — but doesn't worry about how\n * the process gets killed or how its config gets isolated.\n *\n * Why a separate module? Process management is the one part of the adapter\n * with real I/O complexity (process groups, signal escalation, temp-dir\n * lifecycle, env merging). Isolating it makes the orchestrator easy to read\n * and lets us swap the spawning logic if we later need to, e.g., wrap claude\n * in a sandbox runner.\n */\n\nimport { spawn, type ChildProcess } from \"node:child_process\";\nimport { mkdtemp, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Readable } from \"node:stream\";\n\nimport { buildArgs } from \"./flags\";\nimport type { ClaudeCodeAdapterConfig } from \"./types\";\n\n/** Default hard timeout per run. Tunable via config.timeoutMs. */\nconst DEFAULT_TIMEOUT_MS = 5 * 60 * 1000;\n\n/**\n * Grace period between SIGTERM and SIGKILL. Most processes shut down cleanly\n * within a few seconds; this gives them that chance while preventing CI from\n * hanging indefinitely on a stuck child.\n */\nconst KILL_GRACE_MS = 5_000;\n\n/**\n * Handle to a spawned `claude` process. The orchestrator drives it:\n * - Read `stdout` (typically via parseStreamJson).\n * - Await `done` to learn the exit state.\n * - Await `stderrCollected` for diagnostic stderr.\n * - Check `timedOut()` after exit to distinguish kill-by-timeout from\n * normal termination.\n * - Call `cleanup()` after all of the above to remove the temp config dir.\n */\nexport interface SpawnedClaude {\n stdout: Readable;\n done: Promise<{ exitCode: number | null; signal: NodeJS.Signals | null }>;\n stderrCollected: Promise<string>;\n timedOut: () => boolean;\n cleanup: () => Promise<void>;\n}\n\n/**\n * Spawn `claude` in headless mode with isolated config and a process-group\n * lifecycle. See {@link SpawnedClaude} for how to consume the result.\n */\nexport async function spawnClaude(\n config: ClaudeCodeAdapterConfig,\n): Promise<SpawnedClaude> {\n const binary = config.binary ?? \"claude\";\n const args = buildArgs(config);\n\n const isolateConfig = config.isolateConfig !== false;\n\n // Isolated runs use a fresh temp dir so plugins/settings don't leak between\n // reps. Non-isolated runs inherit the caller's Claude login and plugins.\n const tempConfigDir = isolateConfig\n ? await mkdtemp(join(tmpdir(), \"harness-eval-\"))\n : null;\n\n const env: Record<string, string | undefined> = {\n ...process.env,\n ...config.env,\n };\n if (tempConfigDir) {\n // Override after ...env so callers can't accidentally un-isolate.\n env.CLAUDE_CONFIG_DIR = tempConfigDir;\n }\n\n const child = spawn(binary, args, {\n cwd: config.cwd ?? process.cwd(),\n env,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n // detached: true means the child becomes the leader of its own process\n // group. We exploit this to kill the entire group (including any MCP\n // server subprocesses and tool processes) on timeout/abort.\n detached: true,\n });\n\n\n let timedOut = false;\n let killEscalation: NodeJS.Timeout | null = null;\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\n const scheduleKillEscalation = () => {\n if (killEscalation) clearTimeout(killEscalation);\n killEscalation = setTimeout(\n () => killTree(child, \"SIGKILL\"),\n KILL_GRACE_MS,\n );\n };\n\n const timeoutTimer = setTimeout(() => {\n timedOut = true;\n killTree(child, \"SIGTERM\");\n scheduleKillEscalation();\n }, timeoutMs);\n\n // External cancellation uses the same kill path.\n const onAbort = () => {\n killTree(child, \"SIGTERM\");\n scheduleKillEscalation();\n };\n config.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\n // Drain stderr eagerly so the OS-level buffer never fills and stalls the\n // child (Node child processes will block on a full pipe).\n const stderrChunks: string[] = [];\n child.stderr?.setEncoding(\"utf8\");\n child.stderr?.on(\"data\", (chunk: string) => {\n stderrChunks.push(chunk);\n });\n\n const stderrCollected = new Promise<string>((resolve) => {\n const finalize = () => resolve(stderrChunks.join(\"\"));\n child.stderr?.on(\"end\", finalize);\n // Errors during stderr capture shouldn't fail the whole run; we just\n // return what we've buffered so far.\n child.stderr?.on(\"error\", finalize);\n });\n\n\n const done = new Promise<{\n exitCode: number | null;\n signal: NodeJS.Signals | null;\n }>((resolve) => {\n let settled = false;\n const finalize = (\n exitCode: number | null,\n signal: NodeJS.Signals | null,\n ) => {\n if (settled) return;\n settled = true;\n clearTimeout(timeoutTimer);\n if (killEscalation) clearTimeout(killEscalation);\n config.signal?.removeEventListener(\"abort\", onAbort);\n resolve({ exitCode, signal });\n };\n\n child.on(\"close\", (code, signal) => finalize(code, signal));\n // ENOENT and other spawn failures emit `error` — `close` may not follow.\n child.on(\"error\", () => finalize(null, null));\n });\n\n\n const cleanup = async () => {\n if (!tempConfigDir) return;\n try {\n await rm(tempConfigDir, { recursive: true, force: true });\n } catch {\n // Best-effort. A leftover temp dir is annoying but not catastrophic;\n // we don't want to fail the run for it.\n }\n };\n\n // stdout is guaranteed non-null because we passed `stdio: [..., \"pipe\", ...]`.\n // The `!` is safe; the alternative would be a redundant runtime check that\n // could never fire.\n return {\n stdout: child.stdout!,\n done,\n stderrCollected,\n timedOut: () => timedOut,\n cleanup,\n };\n}\n\n/**\n * Kill the child's process group, then fall back to the bare PID if the\n * group is already gone. This catches MCP server subprocesses and tool\n * processes spawned by claude.\n *\n * Why both? On some platforms the process group dies before we get here\n * (the child itself already cleaned up), in which case `kill(-pid)` throws\n * ESRCH. The fallback handles that edge case without leaking zombies in\n * the common case.\n */\nfunction killTree(child: ChildProcess, signal: NodeJS.Signals): void {\n if (child.pid === undefined) return;\n try {\n // Negative PID = process group. Requires the child was spawned with\n // detached=true (which we do).\n process.kill(-child.pid, signal);\n } catch {\n try {\n child.kill(signal);\n } catch {\n // Nothing left to kill.\n }\n }\n}\n","/**\n * Claude Code adapter — public API.\n */\n\nimport { parseStreamJson } from \"../../parsers/stream-json\";\nimport { TrajectoryBuilder } from \"../../trajectory/builder\";\nimport type { StreamEvent } from \"../../types/stream\";\n\nimport { AdapterError } from \"../types\";\nimport { spawnClaude } from \"./process\";\nimport type {\n AdapterDiagnostics,\n ClaudeCodeAdapterConfig,\n ClaudeCodeAdapterResult,\n ParseErrorRecord,\n} from \"./types\";\nimport type { HarnessAdapter } from \"../types\";\n\nexport { AdapterError } from \"../types\";\nexport type {\n AdapterDiagnostics,\n AdapterResult,\n ClaudeCodeAdapterConfig,\n ClaudeCodeAdapterResult,\n ClaudeCodeOptions,\n ParseErrorRecord,\n PermissionMode,\n} from \"./types\";\n\n/**\n * Run Claude Code in headless mode and return a trajectory.\n */\nexport async function runClaudeCode(\n config: ClaudeCodeAdapterConfig,\n): Promise<ClaudeCodeAdapterResult> {\n const startTs = Date.now();\n const spawned = await spawnClaude(config);\n\n const builder = new TrajectoryBuilder();\n const rawEvents: StreamEvent[] = [];\n const parseErrors: ParseErrorRecord[] = [];\n\n try {\n for await (const result of parseStreamJson(spawned.stdout)) {\n if (result.ok) {\n builder.consume(result.event);\n rawEvents.push(result.event);\n } else {\n parseErrors.push({\n line: result.rawLine,\n error: result.error.message,\n });\n }\n }\n\n const [{ exitCode, signal }, stderr] = await Promise.all([\n spawned.done,\n spawned.stderrCollected,\n ]);\n\n const diagnostics: AdapterDiagnostics = {\n exitCode,\n signal,\n stderr,\n parseErrors,\n timedOut: spawned.timedOut(),\n durationMs: Date.now() - startTs,\n };\n\n let view;\n try {\n view = builder.build();\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new AdapterError(\n `harness produced no usable trajectory: ${message}`,\n diagnostics,\n );\n }\n\n return { view, diagnostics, rawEvents };\n } finally {\n await spawned.cleanup();\n }\n}\n\nexport const claudeCodeAdapter: HarnessAdapter<ClaudeCodeAdapterConfig> = {\n id: \"claude-code\",\n run: runClaudeCode,\n};\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"loader-BCnFJ8rm.js","names":["parseYaml","formatZodError","parseYaml"],"sources":["../src/config/paths.ts","../src/config/schema.ts","../src/config/transform.ts","../src/config/grading-schema.ts","../src/config/grading-loader.ts","../src/config/loader.ts"],"sourcesContent":["/**\n * Resolve relative paths in suite config against the suite file directory.\n */\n\nimport { isAbsolute, join } from \"node:path\";\n\nimport type { SuiteConfig } from \"../adapters/types\";\n\nfunction resolvePath(value: string, suiteDir: string): string {\n if (isAbsolute(value) || value.startsWith(\"~/\")) {\n return value;\n }\n return join(suiteDir, value);\n}\n\nfunction resolveClaudeCodePaths(\n block: Record<string, unknown>,\n suiteDir: string,\n): Record<string, unknown> {\n const resolved = { ...block };\n if (typeof resolved.mcpConfig === \"string\") {\n resolved.mcpConfig = resolvePath(resolved.mcpConfig, suiteDir);\n }\n if (Array.isArray(resolved.pluginDirs)) {\n resolved.pluginDirs = resolved.pluginDirs.map((p) =>\n typeof p === \"string\" ? resolvePath(p, suiteDir) : p,\n );\n }\n if (Array.isArray(resolved.addDirs)) {\n resolved.addDirs = resolved.addDirs.map((p) =>\n typeof p === \"string\" ? resolvePath(p, suiteDir) : p,\n );\n }\n const filePathFields = [\n \"systemPromptFile\",\n \"appendSystemPromptFile\",\n \"debugFile\",\n ] as const;\n for (const field of filePathFields) {\n const value = resolved[field];\n if (typeof value === \"string\" && !value.trim().startsWith(\"{\")) {\n resolved[field] = resolvePath(value, suiteDir);\n }\n }\n if (typeof resolved.settings === \"string\" && !resolved.settings.trim().startsWith(\"{\")) {\n resolved.settings = resolvePath(resolved.settings, suiteDir);\n }\n return resolved;\n}\n\n/** Resolve relative paths in a config layer relative to `suiteDir`. */\nexport function resolveConfigPaths(\n config: SuiteConfig | undefined,\n suiteDir: string,\n): SuiteConfig | undefined {\n if (!config) return undefined;\n\n const resolved: SuiteConfig = { ...config };\n if (typeof resolved.cwd === \"string\") {\n resolved.cwd = resolvePath(resolved.cwd, suiteDir);\n }\n if (\n resolved.claudeCode &&\n typeof resolved.claudeCode === \"object\" &&\n !Array.isArray(resolved.claudeCode)\n ) {\n resolved.claudeCode = resolveClaudeCodePaths(\n resolved.claudeCode as Record<string, unknown>,\n suiteDir,\n );\n }\n return resolved;\n}\n\n/** Resolve paths on an entire suite after load. */\nexport function resolveSuitePaths(\n suite: {\n defaultConfig?: SuiteConfig;\n matrix: Array<{ config: SuiteConfig }>;\n cases: Array<{ config?: SuiteConfig }>;\n },\n suiteFilePath: string,\n): void {\n const suiteDir = configFileDir(suiteFilePath);\n\n suite.defaultConfig = resolveConfigPaths(suite.defaultConfig, suiteDir);\n for (const cell of suite.matrix) {\n cell.config = resolveConfigPaths(cell.config, suiteDir) ?? cell.config;\n }\n for (const testCase of suite.cases) {\n testCase.config = resolveConfigPaths(testCase.config, suiteDir);\n }\n}\n\nfunction configFileDir(filePath: string): string {\n return filePath.includes(\"/\") || filePath.includes(\"\\\\\")\n ? filePath.replace(/[/\\\\][^/\\\\]+$/, \"\")\n : \".\";\n}\n\nfunction resolveEnvPaths(\n env: Record<string, string>,\n baseDir: string,\n): Record<string, string> {\n const resolved: Record<string, string> = {};\n for (const [key, value] of Object.entries(env)) {\n if (\n value.startsWith(\"./\") ||\n value.startsWith(\"../\") ||\n (value.includes(\"/\") && !value.startsWith(\"http\"))\n ) {\n resolved[key] = resolvePath(value, baseDir);\n } else {\n resolved[key] = value;\n }\n }\n return resolved;\n}\n\n/** Resolve relative paths in a standalone grading config file. */\nexport function resolveGradingConfigPaths(\n config: { judge: SuiteConfig & { maxConcurrent?: number; adapter?: string } },\n configFilePath: string,\n): void {\n const baseDir = configFileDir(configFilePath);\n const { adapter, maxConcurrent, ...rest } = config.judge;\n const resolved = resolveConfigPaths(rest, baseDir) ?? rest;\n config.judge = {\n ...resolved,\n adapter,\n maxConcurrent,\n };\n if (config.judge.env) {\n config.judge.env = resolveEnvPaths(config.judge.env, baseDir);\n }\n}\n","/**\n * zod schemas for the YAML on-disk shape.\n *\n * Config uses a nested layout: generic harness fields at the top level,\n * adapter-specific options under a named key (e.g. `claudeCode`).\n */\n\nimport { z } from \"zod\";\n\n/** Claude Code adapter-specific options (nested under `claudeCode`). */\nexport const ClaudeCodeConfigSchema = z\n .object({\n binary: z.string(),\n pluginDirs: z.array(z.string()),\n mcpConfig: z.string(),\n permissionMode: z.enum([\n \"default\",\n \"acceptEdits\",\n \"plan\",\n \"auto\",\n \"dontAsk\",\n \"bypassPermissions\",\n ]),\n effort: z.enum([\"low\", \"medium\", \"high\", \"xhigh\", \"max\"]),\n pluginUrls: z.array(z.string()),\n addDirs: z.array(z.string()),\n strictMcpConfig: z.boolean(),\n agent: z.string(),\n fallbackModel: z.string(),\n tools: z.string(),\n maxBudgetUsd: z.number().positive(),\n settings: z.string(),\n settingSources: z.string(),\n systemPrompt: z.string(),\n systemPromptFile: z.string(),\n appendSystemPrompt: z.string(),\n appendSystemPromptFile: z.string(),\n debug: z.union([z.string(), z.boolean()]),\n debugFile: z.string(),\n includeHookEvents: z.boolean(),\n noSessionPersistence: z.boolean(),\n disableSlashCommands: z.boolean(),\n bare: z.boolean(),\n safeMode: z.boolean(),\n allowDangerouslySkipPermissions: z.boolean(),\n dangerouslySkipPermissions: z.boolean(),\n allowedTools: z.array(z.string()),\n disallowedTools: z.array(z.string()),\n maxTurns: z.number().int().positive(),\n isolateConfig: z.boolean(),\n })\n .partial();\n\n/** Generic + nested adapter config for one layer (defaultConfig, case, cell). */\nexport const ConfigPartialSchema = z\n .object({\n model: z.string(),\n cwd: z.string(),\n timeoutMs: z.number().int().positive(),\n env: z.record(z.string(), z.string()),\n claudeCode: ClaudeCodeConfigSchema,\n })\n .partial();\n\n/** A matrix cell — one point in the configuration matrix. */\nexport const MatrixCellSchema = z.object({\n label: z.string().min(1),\n config: ConfigPartialSchema,\n axes: z.record(z.string(), z.string()).optional(),\n});\n\n/** Reference tool call in suite YAML. */\nexport const ReferenceToolCallSchema = z.object({\n tool_name: z.string().min(1),\n tool_input: z.unknown(),\n});\n\n/** A test case. */\nexport const TestCaseSchema = z.object({\n id: z.string().min(1),\n prompt: z.string().min(1),\n category: z.string().optional(),\n notes: z.string().optional(),\n expectations: z.array(z.string().min(1)).optional(),\n reference_trajectory: z.array(ReferenceToolCallSchema).optional(),\n human_ratings: z.record(z.string(), z.number()).optional(),\n assertions: z.array(z.unknown()).min(1),\n repetitions: z.number().int().positive().optional(),\n config: ConfigPartialSchema.optional(),\n});\n\n/** Top-level suite shape. */\nexport const TestSuiteSchema = z.object({\n adapter: z.string().optional(),\n defaultConfig: ConfigPartialSchema.optional(),\n matrix: z.array(MatrixCellSchema).min(1),\n cases: z.array(TestCaseSchema).min(1),\n});\n\n/** Directory suite root (suite.yaml) — cases may live under cases/ as separate YAML files. */\nexport const SuiteDirectorySchema = z.object({\n adapter: z.string().optional(),\n defaultConfig: ConfigPartialSchema.optional(),\n matrix: z.array(MatrixCellSchema).min(1),\n cases: z.array(TestCaseSchema).optional(),\n});\n\nexport type RawTestSuite = z.infer<typeof TestSuiteSchema>;\nexport type RawSuiteDirectory = z.infer<typeof SuiteDirectorySchema>;\nexport type RawTestCase = z.infer<typeof TestCaseSchema>;\nexport type RawMatrixCell = z.infer<typeof MatrixCellSchema>;\n","/**\n * Transform YAML-shape assertions into runtime tagged-union assertions.\n *\n * Why a hand-written transformer rather than zod? The YAML shape is single-key objects (`called: \"foo\"`) and the runtime\n * shape is a tagged union (`{ type: \"called\", tool: \"foo\" }`). zod CAN\n * express this via `z.union` with one member per assertion type, but the\n * error messages devolve into \"expected one of 19 alternatives, none\n * matched\" with no indication of which one the user was trying to write.\n * Hand-written transformers per-assertion give targeted errors like\n * `at cases[2].assertions[1].called: 'tool' field missing`.\n *\n * Shortcut policy: for ergonomics, four assertions accept a bare scalar in place of an\n * object: `called`, `not_called`, `response_contains`, and\n * `responded_without_tool_calls`. Everything else requires the verbose\n * object form. This keeps the transformer small without giving up the\n * 90% of YAML readability.\n */\n\nimport type {\n Assertion,\n Predicate,\n ThresholdedAssertion,\n ToolPattern,\n} from \"../types/assertions\";\nimport { parseCardinality } from \"../assertions/cardinality\";\nimport type { MatrixCell, TestCase, TestSuite } from \"../runner/types\";\nimport type { RawMatrixCell, RawTestCase, RawTestSuite, RawSuiteDirectory } from \"./schema\";\n\n// error type\n\n/**\n * Thrown when a YAML suite fails to validate or transform. Carries a JSON-path-\n * like trail so users can find the offending node in their config quickly.\n */\nexport class ConfigError extends Error {\n constructor(\n message: string,\n public readonly path?: string,\n ) {\n super(path ? `[${path}] ${message}` : message);\n this.name = \"ConfigError\";\n }\n}\n\n// suite-level transformer\n\n/** Transform a zod-validated raw suite into the runtime `TestSuite` shape. */\nexport function transformSuite(raw: RawTestSuite): TestSuite {\n return transformSuiteParts(raw);\n}\n\n/** Transform a directory `suite.yaml` (cases optional) into runtime shape. */\nexport function transformSuiteDirectory(raw: RawSuiteDirectory): TestSuite {\n return transformSuiteParts({\n ...raw,\n cases: raw.cases ?? [],\n });\n}\n\n/** Transform parsed case files into runtime test cases. */\nexport function transformTestCases(\n raw: RawTestCase[],\n pathPrefix: string,\n): TestCase[] {\n return raw.map((c, i) => transformTestCase(c, `${pathPrefix}[${i}]`));\n}\n\nfunction transformSuiteParts(raw: RawTestSuite): TestSuite {\n return {\n adapter: raw.adapter,\n defaultConfig: raw.defaultConfig,\n matrix: raw.matrix.map(transformMatrixCell),\n cases: raw.cases.map((c, i) => transformTestCase(c, `cases[${i}]`)),\n };\n}\n\nfunction transformMatrixCell(raw: RawMatrixCell): MatrixCell {\n return {\n label: raw.label,\n config: raw.config,\n axes: raw.axes,\n };\n}\n\nfunction transformTestCase(raw: RawTestCase, path: string): TestCase {\n return {\n id: raw.id,\n prompt: raw.prompt,\n category: raw.category,\n notes: raw.notes,\n expectations: raw.expectations,\n reference_trajectory: raw.reference_trajectory,\n human_ratings: raw.human_ratings,\n repetitions: raw.repetitions,\n config: raw.config,\n assertions: raw.assertions.map((a, i) =>\n transformThresholdedAssertion(a, `${path}.assertions[${i}]`),\n ),\n };\n}\n\n// thresholded assertion\n\n/** Keys that may appear alongside an assertion-type key. Not assertion types themselves. */\nconst SIBLING_KEYS = new Set([\"threshold\"]);\n\nfunction transformThresholdedAssertion(\n raw: unknown,\n path: string,\n): ThresholdedAssertion {\n if (!isPlainObject(raw)) {\n throw new ConfigError(`expected object, got ${typeOf(raw)}`, path);\n }\n\n const threshold = raw.threshold;\n if (threshold !== undefined) {\n if (typeof threshold !== \"number\" || threshold < 0 || threshold > 1) {\n throw new ConfigError(\n `threshold must be a number in [0, 1], got ${JSON.stringify(threshold)}`,\n `${path}.threshold`,\n );\n }\n }\n\n return {\n assertion: transformAssertion(raw, path),\n threshold: typeof threshold === \"number\" ? threshold : undefined,\n };\n}\n\n// assertion transformer (the bulk)\n\n/**\n * Transform one assertion from YAML shape to runtime shape.\n *\n * Finds the single non-sibling key, dispatches to the per-type transformer.\n * Per-type transformers handle both verbose-object and shortcut-scalar input\n * shapes where applicable.\n */\nexport function transformAssertion(raw: unknown, path: string): Assertion {\n if (!isPlainObject(raw)) {\n throw new ConfigError(`expected object, got ${typeOf(raw)}`, path);\n }\n\n const typeKeys = Object.keys(raw).filter((k) => !SIBLING_KEYS.has(k));\n if (typeKeys.length === 0) {\n throw new ConfigError(\n `no assertion type key found (got only sibling keys: ${Object.keys(raw).join(\", \")})`,\n path,\n );\n }\n if (typeKeys.length > 1) {\n throw new ConfigError(\n `multiple assertion type keys; pick one: ${typeKeys.join(\", \")}`,\n path,\n );\n }\n\n const typeKey = typeKeys[0];\n const value = raw[typeKey];\n const valuePath = `${path}.${typeKey}`;\n\n switch (typeKey) {\n case \"called\":\n return transformCalled(value, valuePath);\n case \"not_called\":\n return transformNotCalled(value, valuePath);\n case \"called_any_of\":\n return transformCalledAnyOf(value, valuePath);\n case \"called_all_of\":\n return transformCalledAllOf(value, valuePath);\n\n case \"called_before\":\n return transformCalledBefore(value, valuePath);\n case \"sequence\":\n return transformSequence(value, valuePath);\n\n case \"called_with\":\n return transformCalledWith(value, valuePath);\n\n case \"responded_without_tool_calls\":\n return transformRespondedWithoutToolCalls(value, valuePath);\n case \"iterations_within\":\n return transformScalarMax(value, valuePath, \"iterations_within\");\n case \"cost_within_usd\":\n return transformScalarMax(value, valuePath, \"cost_within_usd\");\n case \"duration_within_ms\":\n return transformScalarMax(value, valuePath, \"duration_within_ms\");\n case \"finished_with\":\n return transformFinishedWith(value, valuePath);\n\n case \"response_contains\":\n return transformResponseText(value, valuePath, \"response_contains\");\n case \"response_not_contains\":\n return transformResponseText(value, valuePath, \"response_not_contains\");\n case \"response_matches\":\n return transformResponseMatches(value, valuePath);\n\n case \"all_of\":\n return transformAllOf(value, valuePath);\n case \"any_of\":\n return transformAnyOf(value, valuePath);\n case \"not\":\n return transformNot(value, valuePath);\n\n default:\n throw new ConfigError(`unknown assertion type: ${typeKey}`, path);\n }\n}\n\n// per-assertion transformers\n\nfunction transformCalled(value: unknown, path: string): Assertion {\n // Scalar shortcut: bare string is the tool name.\n if (typeof value === \"string\") {\n return { type: \"called\", tool: value };\n }\n if (!isPlainObject(value)) {\n throw new ConfigError(\n `expected string or object, got ${typeOf(value)}`,\n path,\n );\n }\n const tool = requireToolPattern(value.tool, `${path}.tool`);\n let times: string | undefined;\n if (value.times !== undefined) {\n times = requireString(value.times, `${path}.times`);\n try {\n parseCardinality(times);\n } catch (err) {\n throw new ConfigError(\n err instanceof Error ? err.message : `invalid cardinality: ${times}`,\n `${path}.times`,\n );\n }\n }\n return { type: \"called\", tool, times };\n}\n\nfunction transformNotCalled(value: unknown, path: string): Assertion {\n if (typeof value === \"string\") {\n return { type: \"not_called\", tool: value };\n }\n if (!isPlainObject(value)) {\n throw new ConfigError(\n `expected string or object, got ${typeOf(value)}`,\n path,\n );\n }\n return {\n type: \"not_called\",\n tool: requireToolPattern(value.tool, `${path}.tool`),\n };\n}\n\nfunction transformCalledAnyOf(value: unknown, path: string): Assertion {\n const tools = requireToolPatternList(value, path);\n return { type: \"called_any_of\", tools };\n}\n\nfunction transformCalledAllOf(value: unknown, path: string): Assertion {\n const tools = requireToolPatternList(value, path);\n return { type: \"called_all_of\", tools };\n}\n\nfunction transformCalledBefore(value: unknown, path: string): Assertion {\n if (!isPlainObject(value)) {\n throw new ConfigError(\n `expected object with {first, then}, got ${typeOf(value)}`,\n path,\n );\n }\n const first = requireToolPattern(value.first, `${path}.first`);\n const then = requireToolPattern(value.then, `${path}.then`);\n return { type: \"called_before\", first, then };\n}\n\nfunction transformSequence(value: unknown, path: string): Assertion {\n // Two forms: bare list of patterns, or {tools: [...], strict?: bool}.\n if (Array.isArray(value)) {\n return {\n type: \"sequence\",\n tools: value.map((v, i) => requireToolPattern(v, `${path}[${i}]`)),\n };\n }\n if (!isPlainObject(value)) {\n throw new ConfigError(\n `expected array or object, got ${typeOf(value)}`,\n path,\n );\n }\n const tools = requireToolPatternList(value.tools, `${path}.tools`);\n const strict =\n value.strict === undefined\n ? undefined\n : requireBool(value.strict, `${path}.strict`);\n return { type: \"sequence\", tools, strict };\n}\n\nfunction transformCalledWith(value: unknown, path: string): Assertion {\n if (!isPlainObject(value)) {\n throw new ConfigError(\n `expected object with {tool, args}, got ${typeOf(value)}`,\n path,\n );\n }\n const tool = requireToolPattern(value.tool, `${path}.tool`);\n if (value.args === undefined) {\n throw new ConfigError(`missing required field 'args'`, `${path}.args`);\n }\n validatePredicate(value.args, `${path}.args`);\n return { type: \"called_with\", tool, args: value.args as Predicate };\n}\n\nfunction transformRespondedWithoutToolCalls(\n value: unknown,\n path: string,\n): Assertion {\n // Accepts `true`, `{}`, or omitted (since the key being present is enough).\n if (\n value === true ||\n value === null ||\n (isPlainObject(value) && Object.keys(value).length === 0)\n ) {\n return { type: \"responded_without_tool_calls\" };\n }\n throw new ConfigError(\n `expected true or empty object, got ${JSON.stringify(value)}`,\n path,\n );\n}\n\nfunction transformScalarMax(\n value: unknown,\n path: string,\n type: \"iterations_within\" | \"cost_within_usd\" | \"duration_within_ms\",\n): Assertion {\n let max: number | undefined;\n if (typeof value === \"number\") {\n max = value;\n } else if (isPlainObject(value) && typeof value.max === \"number\") {\n max = value.max;\n } else {\n throw new ConfigError(\n `expected number or {max: number}, got ${JSON.stringify(value)}`,\n path,\n );\n }\n if (max <= 0) {\n throw new ConfigError(`max must be positive, got ${max}`, path);\n }\n return { type, max };\n}\n\nfunction transformFinishedWith(value: unknown, path: string): Assertion {\n // Three forms: bare string, bare array of strings, or {reasons: string | string[]}.\n if (typeof value === \"string\") {\n return { type: \"finished_with\", reasons: value };\n }\n if (Array.isArray(value)) {\n return {\n type: \"finished_with\",\n reasons: value.map((v, i) => requireString(v, `${path}[${i}]`)),\n };\n }\n if (isPlainObject(value)) {\n const reasons = value.reasons;\n if (typeof reasons === \"string\") return { type: \"finished_with\", reasons };\n if (Array.isArray(reasons)) {\n return {\n type: \"finished_with\",\n reasons: reasons.map((v, i) =>\n requireString(v, `${path}.reasons[${i}]`),\n ),\n };\n }\n }\n throw new ConfigError(\n `expected string, string[], or {reasons: ...}, got ${JSON.stringify(value)}`,\n path,\n );\n}\n\nfunction transformResponseText(\n value: unknown,\n path: string,\n type: \"response_contains\" | \"response_not_contains\",\n): Assertion {\n if (typeof value === \"string\") {\n return { type, text: value };\n }\n if (isPlainObject(value) && typeof value.text === \"string\") {\n return { type, text: value.text };\n }\n throw new ConfigError(\n `expected string or {text: string}, got ${JSON.stringify(value)}`,\n path,\n );\n}\n\nfunction transformResponseMatches(value: unknown, path: string): Assertion {\n if (!isPlainObject(value)) {\n throw new ConfigError(\n `expected object with {pattern, flags?}, got ${typeOf(value)}`,\n path,\n );\n }\n const pattern = requireString(value.pattern, `${path}.pattern`);\n const flags =\n value.flags === undefined\n ? undefined\n : requireString(value.flags, `${path}.flags`);\n return { type: \"response_matches\", pattern, flags };\n}\n\nfunction transformAllOf(value: unknown, path: string): Assertion {\n return { type: \"all_of\", assertions: transformCompoundList(value, path) };\n}\n\nfunction transformAnyOf(value: unknown, path: string): Assertion {\n return { type: \"any_of\", assertions: transformCompoundList(value, path) };\n}\n\nfunction transformNot(value: unknown, path: string): Assertion {\n // `not` takes a single assertion as its value (not a list). The inner\n // assertion uses the same single-key shape as top-level assertions, so\n // we recurse via the main transformer. We don't pass thresholds for\n // inner assertions — those only apply at the top level.\n return { type: \"not\", assertion: transformAssertion(value, path) };\n}\n\nfunction transformCompoundList(value: unknown, path: string): Assertion[] {\n // Two forms: bare array of assertions, or {assertions: [...]}.\n const list = Array.isArray(value)\n ? value\n : isPlainObject(value) && Array.isArray(value.assertions)\n ? value.assertions\n : null;\n\n if (list === null) {\n throw new ConfigError(\n `expected array or {assertions: [...]}, got ${JSON.stringify(value)}`,\n path,\n );\n }\n\n return list.map((a, i) => transformAssertion(a, `${path}[${i}]`));\n}\n\n// predicate validation\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 * Validate that a predicate is well-formed. The runtime engine is tolerant\n * (returns false on bad shapes), but the loader is strict — invalid\n * predicates are far more often user typos than intentional patterns.\n *\n * Permitted shapes:\n * - scalar (treated as `{equals: scalar}` at runtime)\n * - single-key object whose key is a leaf op (e.g. `{contains: \"x\"}`)\n * - single-key compound (`{any_of: [...]}`, `{all_of: [...]}`, `{not: ...}`)\n * - multi-key object (descend into fields; each value is a sub-predicate)\n */\nfunction validatePredicate(raw: unknown, path: string): void {\n // Scalars are valid (interpreted as equals at runtime).\n if (!isPlainObject(raw)) return;\n\n const keys = Object.keys(raw);\n if (keys.length === 1) {\n const key = keys[0];\n\n if (LEAF_OPS.has(key)) {\n validateLeafOperator(key, raw[key], `${path}.${key}`);\n return;\n }\n\n if (COMPOUND_OPS.has(key)) {\n if (key === \"not\") {\n validatePredicate(raw[key], `${path}.not`);\n } else {\n const arr = raw[key];\n if (!Array.isArray(arr)) {\n throw new ConfigError(\n `${key} must be an array, got ${typeOf(arr)}`,\n `${path}.${key}`,\n );\n }\n arr.forEach((sub, i) => validatePredicate(sub, `${path}.${key}[${i}]`));\n }\n return;\n }\n\n // Single key but not a known op — falls through to object predicate.\n }\n\n // Multi-key object: each field is a sub-predicate.\n for (const [field, sub] of Object.entries(raw)) {\n validatePredicate(sub, `${path}.${field}`);\n }\n}\n\nfunction validateLeafOperator(op: string, value: unknown, path: string): void {\n switch (op) {\n case \"equals\":\n return;\n case \"contains\":\n case \"not_contains\":\n if (typeof value !== \"string\") {\n throw new ConfigError(`${op} requires a string`, path);\n }\n return;\n case \"regex\":\n if (typeof value !== \"string\") {\n throw new ConfigError(\"regex requires a string\", path);\n }\n try {\n new RegExp(value);\n } catch {\n throw new ConfigError(`invalid regex: ${value}`, path);\n }\n return;\n case \"gte\":\n case \"lte\":\n case \"gt\":\n case \"lt\":\n if (typeof value !== \"number\") {\n throw new ConfigError(`${op} requires a number`, path);\n }\n return;\n case \"one_of\":\n if (!Array.isArray(value)) {\n throw new ConfigError(\"one_of requires an array\", path);\n }\n return;\n default:\n return;\n }\n}\n\n// small validation helpers\n\nfunction requireToolPattern(value: unknown, path: string): ToolPattern {\n if (typeof value === \"string\") return value;\n if (isPlainObject(value) && typeof value.pattern === \"string\") {\n return { pattern: value.pattern };\n }\n throw new ConfigError(\n `expected string or {pattern: string}, got ${JSON.stringify(value)}`,\n path,\n );\n}\n\nfunction requireToolPatternList(value: unknown, path: string): ToolPattern[] {\n // Two forms: bare array, or {tools: [...]}.\n const list = Array.isArray(value)\n ? value\n : isPlainObject(value) && Array.isArray(value.tools)\n ? value.tools\n : null;\n\n if (list === null) {\n throw new ConfigError(\n `expected array of tool patterns or {tools: [...]}, got ${JSON.stringify(value)}`,\n path,\n );\n }\n\n return list.map((v, i) => requireToolPattern(v, `${path}[${i}]`));\n}\n\nfunction requireString(value: unknown, path: string): string {\n if (typeof value === \"string\") return value;\n throw new ConfigError(`expected string, got ${typeOf(value)}`, path);\n}\n\nfunction requireBool(value: unknown, path: string): boolean {\n if (typeof value === \"boolean\") return value;\n throw new ConfigError(`expected boolean, got ${typeOf(value)}`, path);\n}\n\nfunction isPlainObject(x: unknown): x is Record<string, unknown> {\n return typeof x === \"object\" && x !== null && !Array.isArray(x);\n}\n\nfunction typeOf(x: unknown): string {\n if (x === null) return \"null\";\n if (Array.isArray(x)) return \"array\";\n return typeof x;\n}\n","/**\n * Zod schema for standalone grading YAML (`grading.yaml`).\n */\n\nimport { z } from \"zod\";\n\nimport { ConfigPartialSchema } from \"./schema\";\n\n/** Top-level `judge` block — mirrors harness config fields plus grader concurrency. */\nexport const JudgeConfigSchema = ConfigPartialSchema.extend({\n adapter: z.string().optional(),\n maxConcurrent: z.number().int().positive().optional(),\n /** Optional judge prompt prefix (maps to upstream system_instruction). */\n system_instruction: z.string().optional(),\n});\n\nexport const GradingConfigSchema = z.object({\n judge: JudgeConfigSchema,\n});\n\nexport type RawGradingConfig = z.infer<typeof GradingConfigSchema>;\nexport type RawJudgeConfig = z.infer<typeof JudgeConfigSchema>;\n","/**\n * Load standalone grading YAML for `harness-eval grade`.\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport type { z } from \"zod\";\n\nimport type { SuiteConfig } from \"../adapters/types\";\nimport { resolveGradingConfigPaths } from \"./paths\";\nimport { GradingConfigSchema, type RawGradingConfig } from \"./grading-schema\";\nimport { ConfigError } from \"./transform\";\n\nexport interface GradingConfig {\n judge: SuiteConfig & {\n adapter?: string;\n maxConcurrent?: number;\n system_instruction?: string;\n };\n}\n\nexport async function loadGradingConfig(filePath: string): Promise<GradingConfig> {\n const absolutePath = resolve(filePath);\n let content: string;\n try {\n content = await readFile(absolutePath, \"utf8\");\n } catch (err) {\n throw new ConfigError(\n `failed to read grading config: ${err instanceof Error ? err.message : String(err)}`,\n filePath,\n );\n }\n return parseGradingConfig(content, absolutePath);\n}\n\nexport function parseGradingConfig(\n yamlContent: string,\n sourcePath?: string,\n): GradingConfig {\n let raw: unknown;\n try {\n raw = parseYaml(yamlContent);\n } catch (err) {\n throw new ConfigError(\n `YAML parse error: ${err instanceof Error ? err.message : String(err)}`,\n sourcePath,\n );\n }\n\n const validated = GradingConfigSchema.safeParse(raw);\n if (!validated.success) {\n throw new ConfigError(\n `validation failed:\\n${formatZodError(validated.error, sourcePath)}`,\n sourcePath,\n );\n }\n\n const config: GradingConfig = {\n judge: { ...validated.data.judge },\n };\n\n if (sourcePath) {\n resolveGradingConfigPaths(config, sourcePath);\n }\n\n return config;\n}\n\nfunction formatZodError(err: z.ZodError, sourcePath?: string): string {\n return err.issues\n .map((issue) => {\n const path = issue.path.length > 0 ? issue.path.join(\".\") : \"(root)\";\n const prefix = sourcePath ? `${sourcePath} → ${path}` : path;\n return ` ${prefix}: ${issue.message}`;\n })\n .join(\"\\n\");\n}\n","/**\n * Load a `TestSuite` from a YAML file, directory, or string.\n */\n\nimport { readdir, readFile, stat } from \"node:fs/promises\";\nimport { join, relative, resolve } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport { z } from \"zod\";\n\nimport type { TestCase, TestSuite } from \"../runner/types\";\nimport { resolveSuitePaths } from \"./paths\";\nimport {\n SuiteDirectorySchema,\n TestCaseSchema,\n TestSuiteSchema,\n type RawTestCase,\n} from \"./schema\";\nimport {\n ConfigError,\n transformSuite,\n transformSuiteDirectory,\n transformTestCases,\n} from \"./transform\";\n\nexport { ConfigError } from \"./transform\";\nexport {\n loadGradingConfig,\n parseGradingConfig,\n type GradingConfig,\n} from \"./grading-loader\";\n\nexport async function loadSuite(filePath: string): Promise<TestSuite> {\n const absolutePath = resolve(filePath);\n let info;\n try {\n info = await stat(absolutePath);\n } catch (err) {\n throw new ConfigError(\n `failed to read suite path: ${err instanceof Error ? err.message : String(err)}`,\n filePath,\n );\n }\n\n if (info.isDirectory()) {\n return loadSuiteDirectory(absolutePath);\n }\n return loadSuiteFile(absolutePath);\n}\n\nasync function loadSuiteFile(absolutePath: string): Promise<TestSuite> {\n let content: string;\n try {\n content = await readFile(absolutePath, \"utf8\");\n } catch (err) {\n throw new ConfigError(\n `failed to read suite file: ${err instanceof Error ? err.message : String(err)}`,\n absolutePath,\n );\n }\n\n return parseSuite(content, absolutePath);\n}\n\nasync function loadSuiteDirectory(dir: string): Promise<TestSuite> {\n const suiteYamlPath = join(dir, \"suite.yaml\");\n let content: string;\n try {\n content = await readFile(suiteYamlPath, \"utf8\");\n } catch (err) {\n throw new ConfigError(\n `missing suite.yaml in suite directory: ${err instanceof Error ? err.message : String(err)}`,\n dir,\n );\n }\n\n const base = parseSuiteDirectory(content, suiteYamlPath);\n const casesDir = join(dir, \"cases\");\n const caseFiles = await collectCaseYamlFiles(casesDir);\n\n type TaggedCase = { relPath: string; index: number; testCase: TestCase };\n const tagged: TaggedCase[] = base.cases.map((testCase, index) => ({\n relPath: \"suite.yaml\",\n index,\n testCase,\n }));\n\n for (const filePath of caseFiles) {\n const fileContent = await readFile(filePath, \"utf8\");\n const cases = parseCasesFile(fileContent, filePath);\n const relPath = relative(casesDir, filePath);\n for (const [index, testCase] of cases.entries()) {\n tagged.push({ relPath, index, testCase });\n }\n }\n\n tagged.sort((a, b) => {\n const pathCmp = a.relPath.localeCompare(b.relPath);\n if (pathCmp !== 0) return pathCmp;\n return a.index - b.index;\n });\n\n const cases = tagged.map((entry) => entry.testCase);\n if (cases.length === 0) {\n throw new ConfigError(\"suite directory has no test cases\", dir);\n }\n\n const suite: TestSuite = { ...base, cases };\n resolveSuitePaths(suite, suiteYamlPath);\n return suite;\n}\n\nexport function parseSuite(\n yamlContent: string,\n sourcePath?: string,\n): TestSuite {\n let raw: unknown;\n try {\n raw = parseYaml(yamlContent);\n } catch (err) {\n throw new ConfigError(\n `YAML parse error: ${err instanceof Error ? err.message : String(err)}`,\n sourcePath,\n );\n }\n\n const validated = TestSuiteSchema.safeParse(raw);\n if (!validated.success) {\n throw new ConfigError(\n `validation failed:\\n${formatZodError(validated.error, sourcePath)}`,\n sourcePath,\n );\n }\n\n const suite = transformSuite(validated.data);\n if (sourcePath) {\n resolveSuitePaths(suite, resolve(sourcePath));\n }\n return suite;\n}\n\nfunction parseSuiteDirectory(\n yamlContent: string,\n sourcePath: string,\n): TestSuite {\n let raw: unknown;\n try {\n raw = parseYaml(yamlContent);\n } catch (err) {\n throw new ConfigError(\n `YAML parse error: ${err instanceof Error ? err.message : String(err)}`,\n sourcePath,\n );\n }\n\n const validated = SuiteDirectorySchema.safeParse(raw);\n if (!validated.success) {\n throw new ConfigError(\n `validation failed:\\n${formatZodError(validated.error, sourcePath)}`,\n sourcePath,\n );\n }\n\n return transformSuiteDirectory(validated.data);\n}\n\n/** Parse one case file: single case, array, or `{ cases: [...] }`. */\nexport function parseCasesFile(\n yamlContent: string,\n sourcePath?: string,\n): TestCase[] {\n let raw: unknown;\n try {\n raw = parseYaml(yamlContent);\n } catch (err) {\n throw new ConfigError(\n `YAML parse error: ${err instanceof Error ? err.message : String(err)}`,\n sourcePath,\n );\n }\n\n const rawCases = extractRawCases(raw, sourcePath);\n return transformTestCases(rawCases, sourcePath ?? \"cases\");\n}\n\nfunction extractRawCases(raw: unknown, sourcePath?: string): RawTestCase[] {\n if (Array.isArray(raw)) {\n return raw.map((item, index) => validateRawCase(item, sourcePath, index));\n }\n\n if (raw && typeof raw === \"object\") {\n const obj = raw as Record<string, unknown>;\n if (Array.isArray(obj.cases)) {\n return obj.cases.map((item, index) =>\n validateRawCase(item, sourcePath, index),\n );\n }\n if (\"id\" in obj && \"prompt\" in obj && \"assertions\" in obj) {\n return [validateRawCase(raw, sourcePath, 0)];\n }\n }\n\n throw new ConfigError(\n \"expected a case object, array of cases, or { cases: [...] }\",\n sourcePath,\n );\n}\n\nfunction validateRawCase(\n raw: unknown,\n sourcePath: string | undefined,\n index: number,\n): RawTestCase {\n const validated = TestCaseSchema.safeParse(raw);\n if (!validated.success) {\n throw new ConfigError(\n `validation failed:\\n${formatZodError(validated.error, sourcePath)}`,\n sourcePath,\n );\n }\n\n return validated.data;\n}\n\nasync function collectCaseYamlFiles(casesDir: string): Promise<string[]> {\n const files: string[] = [];\n\n async function walk(dir: string): Promise<void> {\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch (err) {\n if (\n err instanceof Error &&\n \"code\" in err &&\n (err as NodeJS.ErrnoException).code === \"ENOENT\"\n ) {\n return;\n }\n throw err;\n }\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n await walk(fullPath);\n } else if (\n entry.isFile() &&\n (entry.name.endsWith(\".yaml\") || entry.name.endsWith(\".yml\"))\n ) {\n files.push(fullPath);\n }\n }\n }\n\n await walk(casesDir);\n return files.sort();\n}\n\nfunction formatZodError(err: z.ZodError, sourcePath?: string): string {\n return err.issues\n .map((issue) => {\n const path = issue.path.length > 0 ? issue.path.join(\".\") : \"(root)\";\n const prefix = sourcePath ? `${sourcePath} → ${path}` : path;\n return ` ${prefix}: ${issue.message}`;\n })\n .join(\"\\n\");\n}\n"],"mappings":";;;;;;;;;AAQA,SAAS,YAAY,OAAe,UAA0B;CAC5D,IAAI,WAAW,KAAK,KAAK,MAAM,WAAW,IAAI,GAC5C,OAAO;CAET,OAAO,KAAK,UAAU,KAAK;AAC7B;AAEA,SAAS,uBACP,OACA,UACyB;CACzB,MAAM,WAAW,EAAE,GAAG,MAAM;CAC5B,IAAI,OAAO,SAAS,cAAc,UAChC,SAAS,YAAY,YAAY,SAAS,WAAW,QAAQ;CAE/D,IAAI,MAAM,QAAQ,SAAS,UAAU,GACnC,SAAS,aAAa,SAAS,WAAW,KAAK,MAC7C,OAAO,MAAM,WAAW,YAAY,GAAG,QAAQ,IAAI,CACrD;CAEF,IAAI,MAAM,QAAQ,SAAS,OAAO,GAChC,SAAS,UAAU,SAAS,QAAQ,KAAK,MACvC,OAAO,MAAM,WAAW,YAAY,GAAG,QAAQ,IAAI,CACrD;CAOF,KAAK,MAAM,SAAS;EAJlB;EACA;EACA;CAE+B,GAAG;EAClC,MAAM,QAAQ,SAAS;EACvB,IAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,CAAC,CAAC,WAAW,GAAG,GAC3D,SAAS,SAAS,YAAY,OAAO,QAAQ;CAEjD;CACA,IAAI,OAAO,SAAS,aAAa,YAAY,CAAC,SAAS,SAAS,KAAK,CAAC,CAAC,WAAW,GAAG,GACnF,SAAS,WAAW,YAAY,SAAS,UAAU,QAAQ;CAE7D,OAAO;AACT;;AAGA,SAAgB,mBACd,QACA,UACyB;CACzB,IAAI,CAAC,QAAQ,OAAO,KAAA;CAEpB,MAAM,WAAwB,EAAE,GAAG,OAAO;CAC1C,IAAI,OAAO,SAAS,QAAQ,UAC1B,SAAS,MAAM,YAAY,SAAS,KAAK,QAAQ;CAEnD,IACE,SAAS,cACT,OAAO,SAAS,eAAe,YAC/B,CAAC,MAAM,QAAQ,SAAS,UAAU,GAElC,SAAS,aAAa,uBACpB,SAAS,YACT,QACF;CAEF,OAAO;AACT;;AAGA,SAAgB,kBACd,OAKA,eACM;CACN,MAAM,WAAW,cAAc,aAAa;CAE5C,MAAM,gBAAgB,mBAAmB,MAAM,eAAe,QAAQ;CACtE,KAAK,MAAM,QAAQ,MAAM,QACvB,KAAK,SAAS,mBAAmB,KAAK,QAAQ,QAAQ,KAAK,KAAK;CAElE,KAAK,MAAM,YAAY,MAAM,OAC3B,SAAS,SAAS,mBAAmB,SAAS,QAAQ,QAAQ;AAElE;AAEA,SAAS,cAAc,UAA0B;CAC/C,OAAO,SAAS,SAAS,GAAG,KAAK,SAAS,SAAS,IAAI,IACnD,SAAS,QAAQ,iBAAiB,EAAE,IACpC;AACN;AAEA,SAAS,gBACP,KACA,SACwB;CACxB,MAAM,WAAmC,CAAC;CAC1C,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,GAAG,GAC3C,IACE,MAAM,WAAW,IAAI,KACrB,MAAM,WAAW,KAAK,KACrB,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,WAAW,MAAM,GAEhD,SAAS,OAAO,YAAY,OAAO,OAAO;MAE1C,SAAS,OAAO;CAGpB,OAAO;AACT;;AAGA,SAAgB,0BACd,QACA,gBACM;CACN,MAAM,UAAU,cAAc,cAAc;CAC5C,MAAM,EAAE,SAAS,eAAe,GAAG,SAAS,OAAO;CAEnD,OAAO,QAAQ;EACb,GAFe,mBAAmB,MAAM,OAAO,KAAK;EAGpD;EACA;CACF;CACA,IAAI,OAAO,MAAM,KACf,OAAO,MAAM,MAAM,gBAAgB,OAAO,MAAM,KAAK,OAAO;AAEhE;;;;;;;;;;AC7HA,MAAa,yBAAyB,EACnC,OAAO;CACN,QAAQ,EAAE,OAAO;CACjB,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC;CAC9B,WAAW,EAAE,OAAO;CACpB,gBAAgB,EAAE,KAAK;EACrB;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CACD,QAAQ,EAAE,KAAK;EAAC;EAAO;EAAU;EAAQ;EAAS;CAAK,CAAC;CACxD,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC;CAC9B,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC;CAC3B,iBAAiB,EAAE,QAAQ;CAC3B,OAAO,EAAE,OAAO;CAChB,eAAe,EAAE,OAAO;CACxB,OAAO,EAAE,OAAO;CAChB,cAAc,EAAE,OAAO,CAAC,CAAC,SAAS;CAClC,UAAU,EAAE,OAAO;CACnB,gBAAgB,EAAE,OAAO;CACzB,cAAc,EAAE,OAAO;CACvB,kBAAkB,EAAE,OAAO;CAC3B,oBAAoB,EAAE,OAAO;CAC7B,wBAAwB,EAAE,OAAO;CACjC,OAAO,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,CAAC;CACxC,WAAW,EAAE,OAAO;CACpB,mBAAmB,EAAE,QAAQ;CAC7B,sBAAsB,EAAE,QAAQ;CAChC,sBAAsB,EAAE,QAAQ;CAChC,MAAM,EAAE,QAAQ;CAChB,UAAU,EAAE,QAAQ;CACpB,iCAAiC,EAAE,QAAQ;CAC3C,4BAA4B,EAAE,QAAQ;CACtC,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC;CAChC,iBAAiB,EAAE,MAAM,EAAE,OAAO,CAAC;CACnC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS;CACpC,eAAe,EAAE,QAAQ;AAC3B,CAAC,CAAC,CACD,QAAQ;;AAGX,MAAa,sBAAsB,EAChC,OAAO;CACN,OAAO,EAAE,OAAO;CAChB,KAAK,EAAE,OAAO;CACd,WAAW,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS;CACrC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC;CACpC,YAAY;AACd,CAAC,CAAC,CACD,QAAQ;;AAGX,MAAa,mBAAmB,EAAE,OAAO;CACvC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CACvB,QAAQ;CACR,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS;AAClD,CAAC;;AAGD,MAAa,0BAA0B,EAAE,OAAO;CAC9C,WAAW,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CAC3B,YAAY,EAAE,QAAQ;AACxB,CAAC;;AAGD,MAAa,iBAAiB,EAAE,OAAO;CACrC,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CACpB,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CACxB,UAAU,EAAE,OAAO,CAAC,CAAC,SAAS;CAC9B,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS;CAC3B,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;CAClD,sBAAsB,EAAE,MAAM,uBAAuB,CAAC,CAAC,SAAS;CAChE,eAAe,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS;CACzD,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;CACtC,aAAa,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;CAClD,QAAQ,oBAAoB,SAAS;AACvC,CAAC;;AAGD,MAAa,kBAAkB,EAAE,OAAO;CACtC,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS;CAC7B,eAAe,oBAAoB,SAAS;CAC5C,QAAQ,EAAE,MAAM,gBAAgB,CAAC,CAAC,IAAI,CAAC;CACvC,OAAO,EAAE,MAAM,cAAc,CAAC,CAAC,IAAI,CAAC;AACtC,CAAC;;AAGD,MAAa,uBAAuB,EAAE,OAAO;CAC3C,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS;CAC7B,eAAe,oBAAoB,SAAS;CAC5C,QAAQ,EAAE,MAAM,gBAAgB,CAAC,CAAC,IAAI,CAAC;CACvC,OAAO,EAAE,MAAM,cAAc,CAAC,CAAC,SAAS;AAC1C,CAAC;;;;;;;ACvED,IAAa,cAAb,cAAiC,MAAM;CAGnB;CAFlB,YACE,SACA,MACA;EACA,MAAM,OAAO,IAAI,KAAK,IAAI,YAAY,OAAO;EAF7B,KAAA,OAAA;EAGhB,KAAK,OAAO;CACd;AACF;;AAKA,SAAgB,eAAe,KAA8B;CAC3D,OAAO,oBAAoB,GAAG;AAChC;;AAGA,SAAgB,wBAAwB,KAAmC;CACzE,OAAO,oBAAoB;EACzB,GAAG;EACH,OAAO,IAAI,SAAS,CAAC;CACvB,CAAC;AACH;;AAGA,SAAgB,mBACd,KACA,YACY;CACZ,OAAO,IAAI,KAAK,GAAG,MAAM,kBAAkB,GAAG,GAAG,WAAW,GAAG,EAAE,EAAE,CAAC;AACtE;AAEA,SAAS,oBAAoB,KAA8B;CACzD,OAAO;EACL,SAAS,IAAI;EACb,eAAe,IAAI;EACnB,QAAQ,IAAI,OAAO,IAAI,mBAAmB;EAC1C,OAAO,IAAI,MAAM,KAAK,GAAG,MAAM,kBAAkB,GAAG,SAAS,EAAE,EAAE,CAAC;CACpE;AACF;AAEA,SAAS,oBAAoB,KAAgC;CAC3D,OAAO;EACL,OAAO,IAAI;EACX,QAAQ,IAAI;EACZ,MAAM,IAAI;CACZ;AACF;AAEA,SAAS,kBAAkB,KAAkB,MAAwB;CACnE,OAAO;EACL,IAAI,IAAI;EACR,QAAQ,IAAI;EACZ,UAAU,IAAI;EACd,OAAO,IAAI;EACX,cAAc,IAAI;EAClB,sBAAsB,IAAI;EAC1B,eAAe,IAAI;EACnB,aAAa,IAAI;EACjB,QAAQ,IAAI;EACZ,YAAY,IAAI,WAAW,KAAK,GAAG,MACjC,8BAA8B,GAAG,GAAG,KAAK,cAAc,EAAE,EAAE,CAC7D;CACF;AACF;;AAKA,MAAM,+BAAe,IAAI,IAAI,CAAC,WAAW,CAAC;AAE1C,SAAS,8BACP,KACA,MACsB;CACtB,IAAI,CAAC,cAAc,GAAG,GACpB,MAAM,IAAI,YAAY,wBAAwB,OAAO,GAAG,KAAK,IAAI;CAGnE,MAAM,YAAY,IAAI;CACtB,IAAI,cAAc,KAAA;MACZ,OAAO,cAAc,YAAY,YAAY,KAAK,YAAY,GAChE,MAAM,IAAI,YACR,6CAA6C,KAAK,UAAU,SAAS,KACrE,GAAG,KAAK,WACV;CAAA;CAIJ,OAAO;EACL,WAAW,mBAAmB,KAAK,IAAI;EACvC,WAAW,OAAO,cAAc,WAAW,YAAY,KAAA;CACzD;AACF;;;;;;;;AAWA,SAAgB,mBAAmB,KAAc,MAAyB;CACxE,IAAI,CAAC,cAAc,GAAG,GACpB,MAAM,IAAI,YAAY,wBAAwB,OAAO,GAAG,KAAK,IAAI;CAGnE,MAAM,WAAW,OAAO,KAAK,GAAG,CAAC,CAAC,QAAQ,MAAM,CAAC,aAAa,IAAI,CAAC,CAAC;CACpE,IAAI,SAAS,WAAW,GACtB,MAAM,IAAI,YACR,uDAAuD,OAAO,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE,IACnF,IACF;CAEF,IAAI,SAAS,SAAS,GACpB,MAAM,IAAI,YACR,2CAA2C,SAAS,KAAK,IAAI,KAC7D,IACF;CAGF,MAAM,UAAU,SAAS;CACzB,MAAM,QAAQ,IAAI;CAClB,MAAM,YAAY,GAAG,KAAK,GAAG;CAE7B,QAAQ,SAAR;EACE,KAAK,UACH,OAAO,gBAAgB,OAAO,SAAS;EACzC,KAAK,cACH,OAAO,mBAAmB,OAAO,SAAS;EAC5C,KAAK,iBACH,OAAO,qBAAqB,OAAO,SAAS;EAC9C,KAAK,iBACH,OAAO,qBAAqB,OAAO,SAAS;EAE9C,KAAK,iBACH,OAAO,sBAAsB,OAAO,SAAS;EAC/C,KAAK,YACH,OAAO,kBAAkB,OAAO,SAAS;EAE3C,KAAK,eACH,OAAO,oBAAoB,OAAO,SAAS;EAE7C,KAAK,gCACH,OAAO,mCAAmC,OAAO,SAAS;EAC5D,KAAK,qBACH,OAAO,mBAAmB,OAAO,WAAW,mBAAmB;EACjE,KAAK,mBACH,OAAO,mBAAmB,OAAO,WAAW,iBAAiB;EAC/D,KAAK,sBACH,OAAO,mBAAmB,OAAO,WAAW,oBAAoB;EAClE,KAAK,iBACH,OAAO,sBAAsB,OAAO,SAAS;EAE/C,KAAK,qBACH,OAAO,sBAAsB,OAAO,WAAW,mBAAmB;EACpE,KAAK,yBACH,OAAO,sBAAsB,OAAO,WAAW,uBAAuB;EACxE,KAAK,oBACH,OAAO,yBAAyB,OAAO,SAAS;EAElD,KAAK,UACH,OAAO,eAAe,OAAO,SAAS;EACxC,KAAK,UACH,OAAO,eAAe,OAAO,SAAS;EACxC,KAAK,OACH,OAAO,aAAa,OAAO,SAAS;EAEtC,SACE,MAAM,IAAI,YAAY,2BAA2B,WAAW,IAAI;CACpE;AACF;AAIA,SAAS,gBAAgB,OAAgB,MAAyB;CAEhE,IAAI,OAAO,UAAU,UACnB,OAAO;EAAE,MAAM;EAAU,MAAM;CAAM;CAEvC,IAAI,CAAC,cAAc,KAAK,GACtB,MAAM,IAAI,YACR,kCAAkC,OAAO,KAAK,KAC9C,IACF;CAEF,MAAM,OAAO,mBAAmB,MAAM,MAAM,GAAG,KAAK,MAAM;CAC1D,IAAI;CACJ,IAAI,MAAM,UAAU,KAAA,GAAW;EAC7B,QAAQ,cAAc,MAAM,OAAO,GAAG,KAAK,OAAO;EAClD,IAAI;GACF,iBAAiB,KAAK;EACxB,SAAS,KAAK;GACZ,MAAM,IAAI,YACR,eAAe,QAAQ,IAAI,UAAU,wBAAwB,SAC7D,GAAG,KAAK,OACV;EACF;CACF;CACA,OAAO;EAAE,MAAM;EAAU;EAAM;CAAM;AACvC;AAEA,SAAS,mBAAmB,OAAgB,MAAyB;CACnE,IAAI,OAAO,UAAU,UACnB,OAAO;EAAE,MAAM;EAAc,MAAM;CAAM;CAE3C,IAAI,CAAC,cAAc,KAAK,GACtB,MAAM,IAAI,YACR,kCAAkC,OAAO,KAAK,KAC9C,IACF;CAEF,OAAO;EACL,MAAM;EACN,MAAM,mBAAmB,MAAM,MAAM,GAAG,KAAK,MAAM;CACrD;AACF;AAEA,SAAS,qBAAqB,OAAgB,MAAyB;CAErE,OAAO;EAAE,MAAM;EAAiB,OADlB,uBAAuB,OAAO,IACR;CAAE;AACxC;AAEA,SAAS,qBAAqB,OAAgB,MAAyB;CAErE,OAAO;EAAE,MAAM;EAAiB,OADlB,uBAAuB,OAAO,IACR;CAAE;AACxC;AAEA,SAAS,sBAAsB,OAAgB,MAAyB;CACtE,IAAI,CAAC,cAAc,KAAK,GACtB,MAAM,IAAI,YACR,2CAA2C,OAAO,KAAK,KACvD,IACF;CAIF,OAAO;EAAE,MAAM;EAAiB,OAFlB,mBAAmB,MAAM,OAAO,GAAG,KAAK,OAElB;EAAG,MAD1B,mBAAmB,MAAM,MAAM,GAAG,KAAK,MACV;CAAE;AAC9C;AAEA,SAAS,kBAAkB,OAAgB,MAAyB;CAElE,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO;EACL,MAAM;EACN,OAAO,MAAM,KAAK,GAAG,MAAM,mBAAmB,GAAG,GAAG,KAAK,GAAG,EAAE,EAAE,CAAC;CACnE;CAEF,IAAI,CAAC,cAAc,KAAK,GACtB,MAAM,IAAI,YACR,iCAAiC,OAAO,KAAK,KAC7C,IACF;CAOF,OAAO;EAAE,MAAM;EAAY,OALb,uBAAuB,MAAM,OAAO,GAAG,KAAK,OAK3B;EAAG,QAHhC,MAAM,WAAW,KAAA,IACb,KAAA,IACA,YAAY,MAAM,QAAQ,GAAG,KAAK,QAAQ;CACP;AAC3C;AAEA,SAAS,oBAAoB,OAAgB,MAAyB;CACpE,IAAI,CAAC,cAAc,KAAK,GACtB,MAAM,IAAI,YACR,0CAA0C,OAAO,KAAK,KACtD,IACF;CAEF,MAAM,OAAO,mBAAmB,MAAM,MAAM,GAAG,KAAK,MAAM;CAC1D,IAAI,MAAM,SAAS,KAAA,GACjB,MAAM,IAAI,YAAY,iCAAiC,GAAG,KAAK,MAAM;CAEvE,kBAAkB,MAAM,MAAM,GAAG,KAAK,MAAM;CAC5C,OAAO;EAAE,MAAM;EAAe;EAAM,MAAM,MAAM;CAAkB;AACpE;AAEA,SAAS,mCACP,OACA,MACW;CAEX,IACE,UAAU,QACV,UAAU,QACT,cAAc,KAAK,KAAK,OAAO,KAAK,KAAK,CAAC,CAAC,WAAW,GAEvD,OAAO,EAAE,MAAM,+BAA+B;CAEhD,MAAM,IAAI,YACR,sCAAsC,KAAK,UAAU,KAAK,KAC1D,IACF;AACF;AAEA,SAAS,mBACP,OACA,MACA,MACW;CACX,IAAI;CACJ,IAAI,OAAO,UAAU,UACnB,MAAM;MACD,IAAI,cAAc,KAAK,KAAK,OAAO,MAAM,QAAQ,UACtD,MAAM,MAAM;MAEZ,MAAM,IAAI,YACR,yCAAyC,KAAK,UAAU,KAAK,KAC7D,IACF;CAEF,IAAI,OAAO,GACT,MAAM,IAAI,YAAY,6BAA6B,OAAO,IAAI;CAEhE,OAAO;EAAE;EAAM;CAAI;AACrB;AAEA,SAAS,sBAAsB,OAAgB,MAAyB;CAEtE,IAAI,OAAO,UAAU,UACnB,OAAO;EAAE,MAAM;EAAiB,SAAS;CAAM;CAEjD,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO;EACL,MAAM;EACN,SAAS,MAAM,KAAK,GAAG,MAAM,cAAc,GAAG,GAAG,KAAK,GAAG,EAAE,EAAE,CAAC;CAChE;CAEF,IAAI,cAAc,KAAK,GAAG;EACxB,MAAM,UAAU,MAAM;EACtB,IAAI,OAAO,YAAY,UAAU,OAAO;GAAE,MAAM;GAAiB;EAAQ;EACzE,IAAI,MAAM,QAAQ,OAAO,GACvB,OAAO;GACL,MAAM;GACN,SAAS,QAAQ,KAAK,GAAG,MACvB,cAAc,GAAG,GAAG,KAAK,WAAW,EAAE,EAAE,CAC1C;EACF;CAEJ;CACA,MAAM,IAAI,YACR,qDAAqD,KAAK,UAAU,KAAK,KACzE,IACF;AACF;AAEA,SAAS,sBACP,OACA,MACA,MACW;CACX,IAAI,OAAO,UAAU,UACnB,OAAO;EAAE;EAAM,MAAM;CAAM;CAE7B,IAAI,cAAc,KAAK,KAAK,OAAO,MAAM,SAAS,UAChD,OAAO;EAAE;EAAM,MAAM,MAAM;CAAK;CAElC,MAAM,IAAI,YACR,0CAA0C,KAAK,UAAU,KAAK,KAC9D,IACF;AACF;AAEA,SAAS,yBAAyB,OAAgB,MAAyB;CACzE,IAAI,CAAC,cAAc,KAAK,GACtB,MAAM,IAAI,YACR,+CAA+C,OAAO,KAAK,KAC3D,IACF;CAOF,OAAO;EAAE,MAAM;EAAoB,SALnB,cAAc,MAAM,SAAS,GAAG,KAAK,SAKZ;EAAG,OAH1C,MAAM,UAAU,KAAA,IACZ,KAAA,IACA,cAAc,MAAM,OAAO,GAAG,KAAK,OAAO;CACE;AACpD;AAEA,SAAS,eAAe,OAAgB,MAAyB;CAC/D,OAAO;EAAE,MAAM;EAAU,YAAY,sBAAsB,OAAO,IAAI;CAAE;AAC1E;AAEA,SAAS,eAAe,OAAgB,MAAyB;CAC/D,OAAO;EAAE,MAAM;EAAU,YAAY,sBAAsB,OAAO,IAAI;CAAE;AAC1E;AAEA,SAAS,aAAa,OAAgB,MAAyB;CAK7D,OAAO;EAAE,MAAM;EAAO,WAAW,mBAAmB,OAAO,IAAI;CAAE;AACnE;AAEA,SAAS,sBAAsB,OAAgB,MAA2B;CAExE,MAAM,OAAO,MAAM,QAAQ,KAAK,IAC5B,QACA,cAAc,KAAK,KAAK,MAAM,QAAQ,MAAM,UAAU,IACpD,MAAM,aACN;CAEN,IAAI,SAAS,MACX,MAAM,IAAI,YACR,8CAA8C,KAAK,UAAU,KAAK,KAClE,IACF;CAGF,OAAO,KAAK,KAAK,GAAG,MAAM,mBAAmB,GAAG,GAAG,KAAK,GAAG,EAAE,EAAE,CAAC;AAClE;AAIA,MAAM,2BAAW,IAAI,IAAI;CACvB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AACD,MAAM,+BAAe,IAAI,IAAI;CAAC;CAAU;CAAU;AAAK,CAAC;;;;;;;;;;;;AAaxD,SAAS,kBAAkB,KAAc,MAAoB;CAE3D,IAAI,CAAC,cAAc,GAAG,GAAG;CAEzB,MAAM,OAAO,OAAO,KAAK,GAAG;CAC5B,IAAI,KAAK,WAAW,GAAG;EACrB,MAAM,MAAM,KAAK;EAEjB,IAAI,SAAS,IAAI,GAAG,GAAG;GACrB,qBAAqB,KAAK,IAAI,MAAM,GAAG,KAAK,GAAG,KAAK;GACpD;EACF;EAEA,IAAI,aAAa,IAAI,GAAG,GAAG;GACzB,IAAI,QAAQ,OACV,kBAAkB,IAAI,MAAM,GAAG,KAAK,KAAK;QACpC;IACL,MAAM,MAAM,IAAI;IAChB,IAAI,CAAC,MAAM,QAAQ,GAAG,GACpB,MAAM,IAAI,YACR,GAAG,IAAI,yBAAyB,OAAO,GAAG,KAC1C,GAAG,KAAK,GAAG,KACb;IAEF,IAAI,SAAS,KAAK,MAAM,kBAAkB,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,EAAE,EAAE,CAAC;GACxE;GACA;EACF;CAGF;CAGA,KAAK,MAAM,CAAC,OAAO,QAAQ,OAAO,QAAQ,GAAG,GAC3C,kBAAkB,KAAK,GAAG,KAAK,GAAG,OAAO;AAE7C;AAEA,SAAS,qBAAqB,IAAY,OAAgB,MAAoB;CAC5E,QAAQ,IAAR;EACE,KAAK,UACH;EACF,KAAK;EACL,KAAK;GACH,IAAI,OAAO,UAAU,UACnB,MAAM,IAAI,YAAY,GAAG,GAAG,qBAAqB,IAAI;GAEvD;EACF,KAAK;GACH,IAAI,OAAO,UAAU,UACnB,MAAM,IAAI,YAAY,2BAA2B,IAAI;GAEvD,IAAI;IACF,IAAI,OAAO,KAAK;GAClB,QAAQ;IACN,MAAM,IAAI,YAAY,kBAAkB,SAAS,IAAI;GACvD;GACA;EACF,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;GACH,IAAI,OAAO,UAAU,UACnB,MAAM,IAAI,YAAY,GAAG,GAAG,qBAAqB,IAAI;GAEvD;EACF,KAAK;GACH,IAAI,CAAC,MAAM,QAAQ,KAAK,GACtB,MAAM,IAAI,YAAY,4BAA4B,IAAI;GAExD;EACF,SACE;CACJ;AACF;AAIA,SAAS,mBAAmB,OAAgB,MAA2B;CACrE,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,IAAI,cAAc,KAAK,KAAK,OAAO,MAAM,YAAY,UACnD,OAAO,EAAE,SAAS,MAAM,QAAQ;CAElC,MAAM,IAAI,YACR,6CAA6C,KAAK,UAAU,KAAK,KACjE,IACF;AACF;AAEA,SAAS,uBAAuB,OAAgB,MAA6B;CAE3E,MAAM,OAAO,MAAM,QAAQ,KAAK,IAC5B,QACA,cAAc,KAAK,KAAK,MAAM,QAAQ,MAAM,KAAK,IAC/C,MAAM,QACN;CAEN,IAAI,SAAS,MACX,MAAM,IAAI,YACR,0DAA0D,KAAK,UAAU,KAAK,KAC9E,IACF;CAGF,OAAO,KAAK,KAAK,GAAG,MAAM,mBAAmB,GAAG,GAAG,KAAK,GAAG,EAAE,EAAE,CAAC;AAClE;AAEA,SAAS,cAAc,OAAgB,MAAsB;CAC3D,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,MAAM,IAAI,YAAY,wBAAwB,OAAO,KAAK,KAAK,IAAI;AACrE;AAEA,SAAS,YAAY,OAAgB,MAAuB;CAC1D,IAAI,OAAO,UAAU,WAAW,OAAO;CACvC,MAAM,IAAI,YAAY,yBAAyB,OAAO,KAAK,KAAK,IAAI;AACtE;AAEA,SAAS,cAAc,GAA0C;CAC/D,OAAO,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,MAAM,QAAQ,CAAC;AAChE;AAEA,SAAS,OAAO,GAAoB;CAClC,IAAI,MAAM,MAAM,OAAO;CACvB,IAAI,MAAM,QAAQ,CAAC,GAAG,OAAO;CAC7B,OAAO,OAAO;AAChB;;;;;;;AC/kBA,MAAa,oBAAoB,oBAAoB,OAAO;CAC1D,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS;CAC7B,eAAe,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;;CAEpD,oBAAoB,EAAE,OAAO,CAAC,CAAC,SAAS;AAC1C,CAAC;AAED,MAAa,sBAAsB,EAAE,OAAO,EAC1C,OAAO,kBACT,CAAC;;;;;;ACID,eAAsB,kBAAkB,UAA0C;CAChF,MAAM,eAAe,QAAQ,QAAQ;CACrC,IAAI;CACJ,IAAI;EACF,UAAU,MAAM,SAAS,cAAc,MAAM;CAC/C,SAAS,KAAK;EACZ,MAAM,IAAI,YACR,kCAAkC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,KACjF,QACF;CACF;CACA,OAAO,mBAAmB,SAAS,YAAY;AACjD;AAEA,SAAgB,mBACd,aACA,YACe;CACf,IAAI;CACJ,IAAI;EACF,MAAMA,MAAU,WAAW;CAC7B,SAAS,KAAK;EACZ,MAAM,IAAI,YACR,qBAAqB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,KACpE,UACF;CACF;CAEA,MAAM,YAAY,oBAAoB,UAAU,GAAG;CACnD,IAAI,CAAC,UAAU,SACb,MAAM,IAAI,YACR,uBAAuBC,iBAAe,UAAU,OAAO,UAAU,KACjE,UACF;CAGF,MAAM,SAAwB,EAC5B,OAAO,EAAE,GAAG,UAAU,KAAK,MAAM,EACnC;CAEA,IAAI,YACF,0BAA0B,QAAQ,UAAU;CAG9C,OAAO;AACT;AAEA,SAASA,iBAAe,KAAiB,YAA6B;CACpE,OAAO,IAAI,OACR,KAAK,UAAU;EACd,MAAM,OAAO,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,KAAK,GAAG,IAAI;EAE5D,OAAO,KADQ,aAAa,GAAG,WAAW,KAAK,SAAS,KACrC,IAAI,MAAM;CAC/B,CAAC,CAAC,CACD,KAAK,IAAI;AACd;;;;;;AC9CA,eAAsB,UAAU,UAAsC;CACpE,MAAM,eAAe,QAAQ,QAAQ;CACrC,IAAI;CACJ,IAAI;EACF,OAAO,MAAM,KAAK,YAAY;CAChC,SAAS,KAAK;EACZ,MAAM,IAAI,YACR,8BAA8B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,KAC7E,QACF;CACF;CAEA,IAAI,KAAK,YAAY,GACnB,OAAO,mBAAmB,YAAY;CAExC,OAAO,cAAc,YAAY;AACnC;AAEA,eAAe,cAAc,cAA0C;CACrE,IAAI;CACJ,IAAI;EACF,UAAU,MAAM,SAAS,cAAc,MAAM;CAC/C,SAAS,KAAK;EACZ,MAAM,IAAI,YACR,8BAA8B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,KAC7E,YACF;CACF;CAEA,OAAO,WAAW,SAAS,YAAY;AACzC;AAEA,eAAe,mBAAmB,KAAiC;CACjE,MAAM,gBAAgB,KAAK,KAAK,YAAY;CAC5C,IAAI;CACJ,IAAI;EACF,UAAU,MAAM,SAAS,eAAe,MAAM;CAChD,SAAS,KAAK;EACZ,MAAM,IAAI,YACR,0CAA0C,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,KACzF,GACF;CACF;CAEA,MAAM,OAAO,oBAAoB,SAAS,aAAa;CACvD,MAAM,WAAW,KAAK,KAAK,OAAO;CAClC,MAAM,YAAY,MAAM,qBAAqB,QAAQ;CAGrD,MAAM,SAAuB,KAAK,MAAM,KAAK,UAAU,WAAW;EAChE,SAAS;EACT;EACA;CACF,EAAE;CAEF,KAAK,MAAM,YAAY,WAAW;EAEhC,MAAM,QAAQ,eAAe,MADH,SAAS,UAAU,MAAM,GACT,QAAQ;EAClD,MAAM,UAAU,SAAS,UAAU,QAAQ;EAC3C,KAAK,MAAM,CAAC,OAAO,aAAa,MAAM,QAAQ,GAC5C,OAAO,KAAK;GAAE;GAAS;GAAO;EAAS,CAAC;CAE5C;CAEA,OAAO,MAAM,GAAG,MAAM;EACpB,MAAM,UAAU,EAAE,QAAQ,cAAc,EAAE,OAAO;EACjD,IAAI,YAAY,GAAG,OAAO;EAC1B,OAAO,EAAE,QAAQ,EAAE;CACrB,CAAC;CAED,MAAM,QAAQ,OAAO,KAAK,UAAU,MAAM,QAAQ;CAClD,IAAI,MAAM,WAAW,GACnB,MAAM,IAAI,YAAY,qCAAqC,GAAG;CAGhE,MAAM,QAAmB;EAAE,GAAG;EAAM;CAAM;CAC1C,kBAAkB,OAAO,aAAa;CACtC,OAAO;AACT;AAEA,SAAgB,WACd,aACA,YACW;CACX,IAAI;CACJ,IAAI;EACF,MAAMC,MAAU,WAAW;CAC7B,SAAS,KAAK;EACZ,MAAM,IAAI,YACR,qBAAqB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,KACpE,UACF;CACF;CAEA,MAAM,YAAY,gBAAgB,UAAU,GAAG;CAC/C,IAAI,CAAC,UAAU,SACb,MAAM,IAAI,YACR,uBAAuB,eAAe,UAAU,OAAO,UAAU,KACjE,UACF;CAGF,MAAM,QAAQ,eAAe,UAAU,IAAI;CAC3C,IAAI,YACF,kBAAkB,OAAO,QAAQ,UAAU,CAAC;CAE9C,OAAO;AACT;AAEA,SAAS,oBACP,aACA,YACW;CACX,IAAI;CACJ,IAAI;EACF,MAAMA,MAAU,WAAW;CAC7B,SAAS,KAAK;EACZ,MAAM,IAAI,YACR,qBAAqB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,KACpE,UACF;CACF;CAEA,MAAM,YAAY,qBAAqB,UAAU,GAAG;CACpD,IAAI,CAAC,UAAU,SACb,MAAM,IAAI,YACR,uBAAuB,eAAe,UAAU,OAAO,UAAU,KACjE,UACF;CAGF,OAAO,wBAAwB,UAAU,IAAI;AAC/C;;AAGA,SAAgB,eACd,aACA,YACY;CACZ,IAAI;CACJ,IAAI;EACF,MAAMA,MAAU,WAAW;CAC7B,SAAS,KAAK;EACZ,MAAM,IAAI,YACR,qBAAqB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,KACpE,UACF;CACF;CAGA,OAAO,mBADU,gBAAgB,KAAK,UACL,GAAG,cAAc,OAAO;AAC3D;AAEA,SAAS,gBAAgB,KAAc,YAAoC;CACzE,IAAI,MAAM,QAAQ,GAAG,GACnB,OAAO,IAAI,KAAK,MAAM,UAAU,gBAAgB,MAAM,YAAY,KAAK,CAAC;CAG1E,IAAI,OAAO,OAAO,QAAQ,UAAU;EAClC,MAAM,MAAM;EACZ,IAAI,MAAM,QAAQ,IAAI,KAAK,GACzB,OAAO,IAAI,MAAM,KAAK,MAAM,UAC1B,gBAAgB,MAAM,YAAY,KAAK,CACzC;EAEF,IAAI,QAAQ,OAAO,YAAY,OAAO,gBAAgB,KACpD,OAAO,CAAC,gBAAgB,KAAK,YAAY,CAAC,CAAC;CAE/C;CAEA,MAAM,IAAI,YACR,+DACA,UACF;AACF;AAEA,SAAS,gBACP,KACA,YACA,OACa;CACb,MAAM,YAAY,eAAe,UAAU,GAAG;CAC9C,IAAI,CAAC,UAAU,SACb,MAAM,IAAI,YACR,uBAAuB,eAAe,UAAU,OAAO,UAAU,KACjE,UACF;CAGF,OAAO,UAAU;AACnB;AAEA,eAAe,qBAAqB,UAAqC;CACvE,MAAM,QAAkB,CAAC;CAEzB,eAAe,KAAK,KAA4B;EAC9C,IAAI;EACJ,IAAI;GACF,UAAU,MAAM,QAAQ,KAAK,EAAE,eAAe,KAAK,CAAC;EACtD,SAAS,KAAK;GACZ,IACE,eAAe,SACf,UAAU,OACT,IAA8B,SAAS,UAExC;GAEF,MAAM;EACR;EAEA,KAAK,MAAM,SAAS,SAAS;GAC3B,MAAM,WAAW,KAAK,KAAK,MAAM,IAAI;GACrC,IAAI,MAAM,YAAY,GACpB,MAAM,KAAK,QAAQ;QACd,IACL,MAAM,OAAO,MACZ,MAAM,KAAK,SAAS,OAAO,KAAK,MAAM,KAAK,SAAS,MAAM,IAE3D,MAAM,KAAK,QAAQ;EAEvB;CACF;CAEA,MAAM,KAAK,QAAQ;CACnB,OAAO,MAAM,KAAK;AACpB;AAEA,SAAS,eAAe,KAAiB,YAA6B;CACpE,OAAO,IAAI,OACR,KAAK,UAAU;EACd,MAAM,OAAO,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,KAAK,GAAG,IAAI;EAE5D,OAAO,KADQ,aAAa,GAAG,WAAW,KAAK,SAAS,KACrC,IAAI,MAAM;CAC/B,CAAC,CAAC,CACD,KAAK,IAAI;AACd"}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { s as SuiteConfig } from "./types-B9H4IZtA.js";
|
|
2
|
-
import { d as TestSuite, u as TestCase } from "./types-BQol062t.js";
|
|
3
|
-
import { z } from "zod";
|
|
4
|
-
|
|
5
|
-
//#region src/config/transform.d.ts
|
|
6
|
-
/**
|
|
7
|
-
* Thrown when a YAML suite fails to validate or transform. Carries a JSON-path-
|
|
8
|
-
* like trail so users can find the offending node in their config quickly.
|
|
9
|
-
*/
|
|
10
|
-
declare class ConfigError extends Error {
|
|
11
|
-
readonly path?: string | undefined;
|
|
12
|
-
constructor(message: string, path?: string | undefined);
|
|
13
|
-
}
|
|
14
|
-
//#endregion
|
|
15
|
-
//#region src/config/grading-loader.d.ts
|
|
16
|
-
interface GradingConfig {
|
|
17
|
-
judge: SuiteConfig & {
|
|
18
|
-
adapter?: string;
|
|
19
|
-
maxConcurrent?: number;
|
|
20
|
-
system_instruction?: string;
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
declare function loadGradingConfig(filePath: string): Promise<GradingConfig>;
|
|
24
|
-
declare function parseGradingConfig(yamlContent: string, sourcePath?: string): GradingConfig;
|
|
25
|
-
//#endregion
|
|
26
|
-
//#region src/config/loader.d.ts
|
|
27
|
-
declare function loadSuite(filePath: string): Promise<TestSuite>;
|
|
28
|
-
declare function parseSuite(yamlContent: string, sourcePath?: string): TestSuite;
|
|
29
|
-
/** Parse one case file: single case, array, or `{ cases: [...] }`. */
|
|
30
|
-
declare function parseCasesFile(yamlContent: string, sourcePath?: string): TestCase[];
|
|
31
|
-
//#endregion
|
|
32
|
-
export { loadGradingConfig as a, GradingConfig as i, parseCasesFile as n, parseGradingConfig as o, parseSuite as r, ConfigError as s, loadSuite as t };
|
|
33
|
-
//# sourceMappingURL=loader-DTvoVfN0.d.ts.map
|