@sverka/arena 0.2.25 → 0.2.26

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pack-DoL1QL1y.mjs","names":["comboLabel","comboLabel","formatTokens"],"sources":["../src/acp.ts","../src/adapters/devin.ts","../src/judge.ts","../src/runner.ts","../src/config.ts","../src/report.ts","../src/aggregate-report.ts","../src/internal/git.ts","../src/registry.ts","../src/publish.ts","../src/board.ts","../src/pack.ts"],"sourcesContent":["/**\n * Shared ACP (Agent Client Protocol) utilities — extracted from the Devin\n * adapter so they can be reused by other adapters and the benchmark runner.\n *\n * This module contains:\n * - {@link sanitizeEnv}: strip host-contaminating env vars before spawning an agent.\n * - {@link createPermissionHandler}: auto-approve permission requests.\n * - {@link runAcpSession}: drive a full ACP connect/initialize/prompt/collect loop.\n */\n\nimport { Writable, Readable } from \"node:stream\";\nimport type { ChildProcess } from \"node:child_process\";\n\nimport * as acp from \"@agentclientprotocol/sdk\";\nimport type {\n PromptResponse,\n RequestPermissionResponse,\n SessionUpdate,\n} from \"@agentclientprotocol/sdk\";\n\nimport type { AgentSpawnConfig } from \"./types.js\";\n\n// ─── Types ───────────────────────────────────────────────────────────\n\n/** A `session/update` notification whose `sessionUpdate` is `\"tool_call\"`. */\nexport type ToolCallMessage = Extract<\n SessionUpdate,\n { sessionUpdate: \"tool_call\" }\n>;\n\n/** A `session/update` notification whose `sessionUpdate` is `\"tool_call_update\"`. */\nexport type ToolCallUpdateMessage = Extract<\n SessionUpdate,\n { sessionUpdate: \"tool_call_update\" }\n>;\n\n// ─── Environment sanitization ────────────────────────────────────────\n\n/** Env-var prefixes to strip from the spawned process environment. */\nconst SANITIZE_PREFIXES = [\n \"GC_\",\n \"BEADS_\",\n \"BD_\",\n \"MCP_\",\n \"CLAUDECODE\",\n \"CLAUDE_CODE_\",\n \"CODEX_\",\n];\n\n/** Exact env-var names to strip from the spawned process environment. */\nconst SANITIZE_EXACT = new Set([\n \"DEVIN_PERMISSION_MODE\",\n \"DEVIN_MODEL\",\n \"AGENTS_MD\",\n \"CLAUDE_PROJECT_MD\",\n]);\n\n/** Check if an env var name should be stripped from the agent environment. */\nfunction shouldSanitize(key: string): boolean {\n if (SANITIZE_EXACT.has(key)) return true;\n return SANITIZE_PREFIXES.some((p) => key.startsWith(p));\n}\n\n/** Copy process.env into a clean record, dropping sanitized entries. */\nfunction copyCleanEnv(): Record<string, string> {\n const env: Record<string, string> = {};\n for (const [key, value] of Object.entries(process.env)) {\n if (value === undefined) continue;\n if (shouldSanitize(key)) continue;\n env[key] = value;\n }\n return env;\n}\n\n/** Apply model and permission settings to the env record. */\nfunction applyModelEnv(\n env: Record<string, string>,\n config: AgentSpawnConfig,\n): void {\n const model = config.model;\n env.DEVIN_PERMISSION_MODE = config.permissionMode ?? \"dangerous\";\n env.DEVIN_MODEL = model.envVar ? (env[model.envVar] ?? model.id) : model.id;\n if (model.envVar) {\n env[model.envVar] = env[model.envVar] ?? model.id;\n }\n}\n\n/** Merge explicit env overrides from config (these win). */\nfunction mergeEnvOverrides(\n env: Record<string, string>,\n overrides?: Record<string, string>,\n): void {\n if (!overrides) return;\n for (const [key, value] of Object.entries(overrides)) {\n env[key] = value;\n }\n}\n\n/**\n * Build a sanitized environment for an agent subprocess.\n *\n * Strips out host contamination: Gas City, Beads, MCP servers, project\n * skills, and other variables that would leak the host's configuration\n * into the benchmark. The agent must only see what we explicitly install.\n *\n * Sets `DEVIN_PERMISSION_MODE` and `DEVIN_MODEL` from the spawn config,\n * then merges any explicit `config.env` overrides (which win).\n */\nexport function sanitizeEnv(config: AgentSpawnConfig): Record<string, string> {\n const env = copyCleanEnv();\n applyModelEnv(env, config);\n mergeEnvOverrides(env, config.env);\n return env;\n}\n\n// ─── Permission handling ──────────────────────────────────────────────\n\n/**\n * Create a permission-request handler that auto-approves tool calls.\n *\n * Selects the first `allow_once` or `allow_always` option, falling back to\n * the first available option. This is the same handler used by both the\n * Devin adapter and the benchmark runner.\n */\nexport function createPermissionHandler(): acp.ClientRequestHandler<\n acp.RequestPermissionRequest,\n acp.RequestPermissionResponse\n> {\n return (ctx): RequestPermissionResponse => {\n const options = ctx.params.options;\n const allow = options.find(\n (o) => o.kind === \"allow_once\" || o.kind === \"allow_always\",\n );\n return {\n outcome: {\n outcome: \"selected\",\n optionId: allow?.optionId ?? options[0]?.optionId ?? \"\",\n },\n };\n };\n}\n\n// ─── Session loop ────────────────────────────────────────────────────\n\n/**\n * Process a single {@link acp.ActiveSessionMessage} from the session update\n * stream. Returns the final {@link PromptResponse} when the session reports\n * a stop, otherwise invokes the appropriate callback and returns `undefined`\n * so the caller can continue collecting.\n */\nfunction handleSessionUpdate(\n message: acp.ActiveSessionMessage,\n onToolCall?: (update: ToolCallMessage, receivedAt: number) => void,\n onToolUpdate?: (update: ToolCallUpdateMessage, receivedAt: number) => void,\n): PromptResponse | undefined {\n if (message.kind === \"stop\") return message.response;\n const receivedAt = Date.now();\n const update = message.update;\n if (update.sessionUpdate === \"tool_call\") {\n onToolCall?.(update, receivedAt);\n } else if (update.sessionUpdate === \"tool_call_update\") {\n onToolUpdate?.(update, receivedAt);\n }\n return undefined;\n}\n\n/**\n * Drive a single ACP session: send the prompt, race the collect loop\n * against a timeout, and return the final {@link PromptResponse}.\n */\nasync function runSessionLoop(\n session: acp.ActiveSession,\n prompt: string,\n timeoutMs: number,\n onToolCall?: (update: ToolCallMessage, receivedAt: number) => void,\n onToolUpdate?: (update: ToolCallUpdateMessage, receivedAt: number) => void,\n onSession?: (sessionId: string) => void,\n): Promise<PromptResponse> {\n onSession?.(session.sessionId);\n const promptPromise = session.prompt(prompt);\n const timeoutPromise = new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(`Agent timed out after ${timeoutMs}ms`)),\n timeoutMs,\n ),\n );\n\n const collectPromise = (async (): Promise<PromptResponse> => {\n for (;;) {\n const message = await session.nextUpdate();\n const result = handleSessionUpdate(message, onToolCall, onToolUpdate);\n if (result) return result;\n }\n })();\n\n return Promise.race([promptPromise, collectPromise, timeoutPromise]);\n}\n\n/**\n * Run a full ACP session against a spawned agent subprocess.\n *\n * Connects to the agent, initializes the protocol, creates a session in\n * `workspace`, sends `prompt`, and collects update events until the session\n * stops or `timeoutMs` elapses.\n *\n * The `onToolCall` and `onToolUpdate` callbacks let callers collect tool\n * calls and observations without duplicating the session loop logic. The\n * optional `onSession` callback reports the session ID once created. All\n * callbacks are optional.\n *\n * @returns The final {@link PromptResponse} from the agent.\n */\nexport async function runAcpSession(\n proc: ChildProcess,\n workspace: string,\n prompt: string,\n timeoutMs: number,\n onToolCall?: (update: ToolCallMessage, receivedAt: number) => void,\n onToolUpdate?: (update: ToolCallUpdateMessage, receivedAt: number) => void,\n onSession?: (sessionId: string) => void,\n): Promise<PromptResponse> {\n if (!proc.stdin || !proc.stdout) {\n throw new Error(\"Agent process missing stdin/stdout\");\n }\n\n const input = Writable.toWeb(proc.stdin);\n const output = Readable.toWeb(proc.stdout);\n const stream = acp.ndJsonStream(input, output);\n\n return acp\n .client({ name: \"sverka-arena\" })\n .onRequest(\n acp.methods.client.session.requestPermission,\n createPermissionHandler(),\n )\n .connectWith(stream, async (ctx) => {\n await ctx.request(acp.methods.agent.initialize, {\n protocolVersion: acp.PROTOCOL_VERSION,\n clientCapabilities: {},\n });\n return ctx\n .buildSession(workspace)\n .withSession((session) =>\n runSessionLoop(\n session,\n prompt,\n timeoutMs,\n onToolCall,\n onToolUpdate,\n onSession,\n ),\n );\n });\n}\n","/**\n * Devin ACP adapter — spawns `devin acp` as a subprocess and drives an\n * Agent Client Protocol session to collect trace data + metrics.\n *\n * The adapter is abstract over models and plugins: it accepts any\n * {@link ModelConfig} and any set of {@link PluginConfig}s, installs the\n * enabled plugins into the workspace, and runs the prompt against the\n * spawned agent. After the session completes it reads the Devin CLI\n * transcript file to build full {@link TraceData}.\n */\n\nimport { spawn, execSync, type ChildProcess } from \"node:child_process\";\nimport { mkdir, cp, rm, readFile, writeFile } from \"node:fs/promises\";\nimport { existsSync, mkdtempSync, mkdirSync, cpSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { DatabaseSync } from \"node:sqlite\";\n\nimport type {\n PromptResponse,\n Usage,\n ToolCallContent,\n} from \"@agentclientprotocol/sdk\";\n\nimport type {\n AgentAdapter,\n AgentSpawnConfig,\n AgentProcess,\n RunResult,\n RunMetrics,\n TraceData,\n TraceStep,\n ToolCall,\n Observation,\n PluginConfig,\n ModelConfig,\n} from \"../types.js\";\nimport { sanitizeEnv, runAcpSession } from \"../acp.js\";\nimport type { ToolCallMessage, ToolCallUpdateMessage } from \"../acp.js\";\n\n// ─── Transcript source types (raw JSON from Devin CLI) ───────────────\n\n/** A single step in the raw Devin CLI transcript. */\ninterface TranscriptStep {\n step_id: number;\n source: \"system\" | \"agent\" | \"user\";\n message: string;\n timestamp: string;\n extra?: {\n generation_model?: string | null;\n telemetry?: {\n source?: string;\n operation?: string;\n } | null;\n } | null;\n}\n\n/** Final metrics block in a Devin CLI transcript. */\ninterface TranscriptMetrics {\n total_prompt_tokens: number;\n total_completion_tokens: number;\n total_cached_tokens: number;\n total_steps: number;\n}\n\n/** Full raw transcript written by the Devin CLI. */\ninterface Transcript {\n session_id: string;\n schema_version: string;\n agent: {\n name: string;\n version: string;\n model_name: string;\n };\n final_metrics: TranscriptMetrics;\n steps: TranscriptStep[];\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────\n\n/** Default transcript directory: ~/.local/share/devin/cli/transcripts */\nexport function transcriptDir(): string {\n return join(homedir(), \".local\", \"share\", \"devin\", \"cli\", \"transcripts\");\n}\n\n/**\n * Devin CLI session DB. It lives on the host at a fixed path — it does\n * NOT follow XDG_DATA_HOME, so isolated runs still write here.\n */\nexport function sessionDbPath(): string {\n return join(homedir(), \".local\", \"share\", \"devin\", \"cli\", \"sessions.db\");\n}\n\n/** Read a transcript JSON file by session ID. Throws if not found. */\nasync function readTranscript(\n sessionId: string,\n dir?: string,\n): Promise<Transcript> {\n const path = join(dir ?? transcriptDir(), `${sessionId}.json`);\n const content = await readFile(path, \"utf-8\");\n return JSON.parse(content) as Transcript;\n}\n\n/** A message_nodes row: chat_message is a JSON-encoded chat message. */\ninterface SessionNodeRow {\n node_id: number;\n created_at: number;\n chat_message: string;\n}\n\n/** Parsed fields of a session-DB chat message we care about. */\ninterface SessionNodeMessage {\n role: string;\n content?: string;\n thinking?: { thinking?: string } | null;\n tool_calls?: { id?: string; name?: string }[] | null;\n metadata?: {\n metrics?: {\n input_tokens?: number | null;\n output_tokens?: number | null;\n cache_read_tokens?: number | null;\n } | null;\n } | null;\n}\n\n/** One parsed session-DB node: a trace step plus its token metrics (inference calls only). */\ninterface ParsedNode {\n step: TranscriptStep;\n tokens: { prompt: number; completion: number; cached: number } | null;\n}\n\n/**\n * Map a message_nodes row to a {@link ParsedNode}. Returns `undefined`\n * for non-step roles (e.g. `tool` results — their content arrives via\n * ACP-collected observations; as steps they'd mislabel tool output as\n * agent output).\n */\nfunction parseNode(row: SessionNodeRow): ParsedNode | undefined {\n const node = JSON.parse(row.chat_message) as SessionNodeMessage;\n if (\n node.role !== \"system\" &&\n node.role !== \"user\" &&\n node.role !== \"assistant\"\n ) {\n return undefined;\n }\n const isInference = node.role === \"assistant\";\n const toolNames = (node.tool_calls ?? [])\n .map((t) => t.name)\n .filter(Boolean)\n .join(\", \");\n const message = (\n node.content?.trim() ||\n node.thinking?.thinking?.trim() ||\n toolNames\n ).slice(0, 4000);\n const m = node.metadata?.metrics;\n return {\n step: {\n step_id: row.node_id,\n // message_nodes.created_at is epoch SECONDS (the CLI batch-writes\n // nodes at session end, so per-step timing is identical anyway);\n // tolerate a future switch to ms.\n timestamp: new Date(\n row.created_at < 1e12 ? row.created_at * 1000 : row.created_at,\n ).toISOString(),\n source: isInference ? \"agent\" : (node.role as \"system\" | \"user\"),\n message,\n extra: isInference\n ? { telemetry: { source: \"assistant\", operation: \"inference\" } }\n : null,\n },\n tokens: isInference\n ? {\n prompt: m?.input_tokens ?? 0,\n completion: m?.output_tokens ?? 0,\n cached: m?.cache_read_tokens ?? 0,\n }\n : null,\n };\n}\n\n/** Accumulate one inference call's token counts into transcript totals. */\nfunction addTokens(\n metrics: TranscriptMetrics,\n tokens: NonNullable<ParsedNode[\"tokens\"]>,\n): void {\n metrics.total_prompt_tokens += tokens.prompt;\n metrics.total_completion_tokens += tokens.completion;\n metrics.total_cached_tokens += tokens.cached;\n metrics.total_steps += 1;\n}\n\n/**\n * Build a {@link Transcript} from the Devin session DB. `devin acp` never\n * writes transcript JSON files, but every message (incl. per-call token\n * metrics) lands in `message_nodes` — each `assistant` node is one LLM\n * inference call. Returns `undefined` when the session has no rows yet.\n */\nexport function readSessionTranscript(\n sessionId: string,\n dbPath?: string,\n): Transcript | undefined {\n const path = dbPath ?? sessionDbPath();\n if (!existsSync(path)) return undefined;\n\n const db = new DatabaseSync(path, { readOnly: true });\n try {\n const rows = db\n .prepare(\n \"SELECT node_id, created_at, chat_message FROM message_nodes WHERE session_id = ? ORDER BY node_id\",\n )\n .all(sessionId) as unknown as SessionNodeRow[];\n if (rows.length === 0) return undefined;\n\n const sessionRow = db\n .prepare(\"SELECT model FROM sessions WHERE id = ?\")\n .get(sessionId) as { model?: string } | undefined;\n\n const steps: TranscriptStep[] = [];\n const metrics: TranscriptMetrics = {\n total_prompt_tokens: 0,\n total_completion_tokens: 0,\n total_cached_tokens: 0,\n total_steps: 0,\n };\n for (const row of rows) {\n const parsed = parseNode(row);\n if (!parsed) continue;\n steps.push(parsed.step);\n if (parsed.tokens) addTokens(metrics, parsed.tokens);\n }\n\n return {\n session_id: sessionId,\n schema_version: \"session-db\",\n agent: {\n name: \"devin\",\n version: \"\",\n model_name: sessionRow?.model ?? \"\",\n },\n final_metrics: metrics,\n steps,\n };\n } finally {\n db.close();\n }\n}\n\n/**\n * Load a transcript for the session — session DB first (that's where\n * `devin acp` actually writes), then the transcript file as a fallback.\n * The DB write can lag `session/prompt` completion, so retry once.\n *\n * The session DB lives at `~/.local/share/devin/cli/` — it does NOT\n * follow XDG_DATA_HOME — so it lands under the child's resolved HOME\n * (`childHome`, which already accounts for any caller override). The\n * host-home path stays a last-resort fallback.\n */\nasync function loadTranscript(\n sessionId: string,\n childHome: string,\n): Promise<Transcript | undefined> {\n const childDataDir = join(childHome, \".local\", \"share\", \"devin\", \"cli\");\n const tryDb = (): Transcript | undefined => {\n try {\n return (\n readSessionTranscript(sessionId, join(childDataDir, \"sessions.db\")) ??\n readSessionTranscript(sessionId)\n );\n } catch {\n return undefined;\n }\n };\n const fromDb =\n tryDb() ??\n (await new Promise<Transcript | undefined>((resolve) =>\n setTimeout(() => resolve(tryDb()), 400),\n ));\n if (fromDb) return fromDb;\n try {\n return await readTranscript(sessionId, join(childDataDir, \"transcripts\"));\n } catch {\n return undefined;\n }\n}\n\n/** Count LLM inference calls in a transcript (agent steps with telemetry.operation === \"inference\"). */\nexport function countLlmCalls(transcript: Transcript): number {\n return transcript.steps.filter(\n (s) =>\n s.source === \"agent\" && s.extra?.telemetry?.operation === \"inference\",\n ).length;\n}\n\n/** Build a {@link TraceStep} from a raw transcript step. */\nfunction buildTraceStep(step: TranscriptStep): TraceStep {\n const isLlmCall =\n step.source === \"agent\" && step.extra?.telemetry?.operation === \"inference\";\n return {\n stepId: step.step_id,\n timestamp: step.timestamp,\n source: step.source,\n message: step.message,\n isLlmCall,\n };\n}\n\n/** Extract text content from a ToolCallContent array (best-effort). */\nfunction extractTextContent(\n contents: ReadonlyArray<ToolCallContent> | undefined,\n): string {\n if (!contents) return \"\";\n const parts: string[] = [];\n for (const c of contents) {\n if (c.type === \"content\" && c.content.type === \"text\") {\n parts.push(c.content.text);\n }\n }\n return parts.join(\"\\n\");\n}\n\n/** Extract token counts from a Usage object, defaulting to 0. */\nexport function extractUsageTokens(usage: Usage | null | undefined): {\n inputTokens: number;\n outputTokens: number;\n thoughtTokens: number;\n totalTokens: number;\n} {\n return {\n inputTokens: usage?.inputTokens ?? 0,\n outputTokens: usage?.outputTokens ?? 0,\n thoughtTokens: usage?.thoughtTokens ?? 0,\n totalTokens: usage?.totalTokens ?? 0,\n };\n}\n\n/** Build {@link RunMetrics} from a PromptResponse + collected counts + timing. */\nfunction buildMetrics(\n promptResult: { stopReason: string; usage?: Usage | null },\n toolCallCount: number,\n llmCallCount: number,\n startTime: number,\n): RunMetrics {\n return {\n ...extractUsageTokens(promptResult.usage),\n toolCallCount,\n llmCallCount,\n executionTimeMs: Date.now() - startTime,\n stopReason: promptResult.stopReason,\n };\n}\n\n/**\n * Extract the agent's final text output from the prompt response or trace.\n *\n * Prefers the text content from the ACP `PromptResponse`, falling back to\n * the last agent message in the trace.\n */\nfunction extractAgentOutput(\n promptResult: PromptResponse,\n trace: TraceData,\n): string {\n // PromptResponse in ACP v1 doesn't have a content field directly.\n // Fall back to the last agent message in the trace.\n for (let i = trace.steps.length - 1; i >= 0; i--) {\n const step = trace.steps[i];\n if (step?.source === \"agent\" && step.message.length > 0) {\n return step.message;\n }\n }\n return \"\";\n}\n\n// ─── Plugin installation ─────────────────────────────────────────────\n\n/**\n * Install enabled plugins and remove disabled ones from the workspace.\n *\n * CRITICAL: This function first removes the entire `.agents/skills/`\n * directory to ensure no inherited skills from the host contaminate the\n * benchmark. Only explicitly enabled plugins are installed.\n *\n * Each enabled plugin's `path` is copied to `workspace/.agents/skills/<id>/`.\n */\nexport async function installPlugins(\n workspace: string,\n plugins: PluginConfig[],\n): Promise<void> {\n const skillsDir = join(workspace, \".agents\", \"skills\");\n\n // Forbid every installed plugin at the repo level. Devin resolves plugin\n // authority enterprise > org > repo > user, and a repo-level wildcard\n // forbid blocks all user/managed installs (higher-authority \"required\"\n // plugins still load — they're a constant baseline across cells).\n // .agents/skills copies below are workspace content, not plugins, so\n // plugin-on cells are unaffected.\n await writeForbidManifest(workspace);\n\n // Nuke any existing skills directory — we start from a clean slate.\n // This prevents host skill contamination.\n await rm(skillsDir, { recursive: true, force: true });\n\n // Only create the directory if we have enabled plugins to install.\n const enabledPlugins = plugins.filter((p) => p.enabled);\n if (enabledPlugins.length === 0) return;\n\n await mkdir(skillsDir, { recursive: true });\n for (const plugin of enabledPlugins) {\n // Reject path-like plugin ids to prevent directory traversal\n if (\n plugin.id.includes(\"/\") ||\n plugin.id.includes(\"\\\\\") ||\n plugin.id.includes(\"..\")\n ) {\n throw new Error(`Invalid plugin id: ${plugin.id}`);\n }\n const dest = join(skillsDir, plugin.id);\n await mkdir(dest, { recursive: true });\n await cp(plugin.path, dest, { recursive: true });\n }\n}\n\n/**\n * Write (or merge into) `<workspace>/.devin/config.json` with\n * `forbiddenPlugins: [\"*\"]`. Preserves other keys the fixture may ship,\n * including `requiredPlugins` (same-manifest requireds are exempt from\n * its own forbids, so plugin fixtures still work).\n */\nasync function writeForbidManifest(workspace: string): Promise<void> {\n const devinDir = join(workspace, \".devin\");\n const manifestPath = join(devinDir, \"config.json\");\n let manifest: Record<string, unknown> = {};\n try {\n const parsed: unknown = JSON.parse(await readFile(manifestPath, \"utf8\"));\n if (typeof parsed === \"object\" && parsed !== null) {\n manifest = parsed as Record<string, unknown>;\n }\n } catch {\n // No existing manifest (or unreadable) — start fresh.\n }\n manifest.forbiddenPlugins = [\"*\"];\n await mkdir(devinDir, { recursive: true });\n await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`); // codeql[js/insecure-temporary-file] — inside a private mkdtemp (0700) workspace, not a predictable shared temp file\n}\n\n/**\n * Create a fresh XDG home for the spawned agent and point `env` at it:\n * - `HOME` — drops host user-level skills (`~/.agents/skills`), which are\n * resolved via `homedir()` and would otherwise leak into every cell.\n * - `XDG_CONFIG_HOME` — drops global user skills, hooks, MCP config, and\n * user-level `AGENTS.md` so all cells share the builtin baseline.\n * - `XDG_DATA_HOME` — fresh plugin/session store; seeded with the host's\n * `devin/credentials.toml` so the agent stays authenticated without\n * writing session state into the user's real Devin data dir.\n *\n * Returns the env-home path — the caller must delete it after the run.\n *\n * An explicit `config.env.HOME` override wins over the redirect (the\n * caller then owns whatever leaks from that home).\n */\nfunction isolateAgentEnv(\n env: Record<string, string>,\n overrides?: Record<string, string>,\n): string {\n const envHome = mkdtempSync(join(tmpdir(), \"arena-env-\"));\n try {\n const configDir = join(envHome, \"config\");\n const dataDir = join(envHome, \"data\");\n const homeDir = join(envHome, \"home\");\n mkdirSync(join(dataDir, \"devin\"), { recursive: true });\n mkdirSync(configDir, { recursive: true });\n mkdirSync(homeDir, { recursive: true });\n\n const hostDataHome =\n process.env.XDG_DATA_HOME ?? join(homedir(), \".local\", \"share\");\n const creds = join(hostDataHome, \"devin\", \"credentials.toml\");\n if (existsSync(creds)) {\n cpSync(creds, join(dataDir, \"devin\", \"credentials.toml\"));\n }\n\n if (overrides?.[\"HOME\"] === undefined) env.HOME = homeDir;\n // Windows resolves the profile dir via USERPROFILE, not HOME.\n if (overrides?.[\"USERPROFILE\"] === undefined) env.USERPROFILE = homeDir;\n env.XDG_CONFIG_HOME = configDir;\n env.XDG_DATA_HOME = dataDir;\n return envHome;\n } catch (error) {\n rmSync(envHome, { recursive: true, force: true });\n throw error;\n }\n}\n\n// ─── Adapter ─────────────────────────────────────────────────────────\n\n/**\n * Devin ACP adapter — spawns `devin acp` as a subprocess.\n *\n * Usage:\n * ```ts\n * const adapter = new DevinAdapter();\n * const proc = adapter.spawn({ model, workspace, plugins });\n * const result = await proc.run(\"Fix the bug\", 120_000);\n * proc.kill();\n * ```\n */\nexport class DevinAdapter implements AgentAdapter {\n readonly id = \"devin\";\n\n spawn(config: AgentSpawnConfig): AgentProcess {\n const { proc, envHome, childHome } = spawnDevin(config);\n let killed = false;\n let cleaned = false;\n const cleanup = (): void => {\n if (cleaned) return;\n cleaned = true;\n rm(envHome, { recursive: true, force: true }).catch((err: unknown) => {\n console.warn(\n `[arena] failed to remove isolated env ${envHome}: ${String(err)}`,\n );\n });\n };\n\n // SIGTERM, wait for exit (SIGKILL fallback), then remove envHome —\n // the child may still be writing session data/transcripts into it.\n const terminate = (): void => {\n if (proc.exitCode != null || proc.signalCode != null) {\n cleanup();\n return;\n }\n proc.once(\"exit\", cleanup);\n const force = setTimeout(() => {\n proc.kill(\"SIGKILL\");\n cleanup();\n }, 5_000);\n force.unref();\n proc.kill(\"SIGTERM\");\n };\n\n return {\n run: async (prompt: string, timeoutMs: number): Promise<RunResult> => {\n try {\n return await runDevinSession(\n proc,\n config,\n prompt,\n timeoutMs,\n childHome,\n );\n } finally {\n terminate();\n }\n },\n kill: (): void => {\n if (killed) return;\n killed = true;\n terminate();\n },\n };\n }\n}\n\n/** Resolve the full path to the devin binary to avoid PATH-based lookup. */\nfunction resolveDevinBinary(): string {\n try {\n const opts = { encoding: \"utf-8\", stdio: \"pipe\" } as const;\n // NOSONAR suppresses only issues on the marker's own line — it must\n // trail the execSync call, not sit inside the options literal.\n return execSync(\"which devin\", opts).trim(); // NOSONAR — PATH needed to locate devin binary\n } catch {\n return \"devin\";\n }\n}\n\n/**\n * Spawn `devin acp --model <model.id>` as a subprocess in the workspace,\n * in an isolated XDG env (see {@link isolateAgentEnv}). Returns the child\n * process and the env-home path the caller must clean up.\n */\nfunction spawnDevin(config: AgentSpawnConfig): {\n proc: ChildProcess;\n envHome: string;\n childHome: string;\n} {\n const env = sanitizeEnv(config);\n const envHome = isolateAgentEnv(env, config.env);\n const devinBin = resolveDevinBinary();\n try {\n const proc = spawn(devinBin, [\"acp\", \"--model\", config.model.id], {\n cwd: config.workspace,\n stdio: [\"pipe\", \"pipe\", \"inherit\"],\n env,\n });\n // The session DB lives under the child's resolved HOME (it does NOT\n // follow XDG_DATA_HOME) — keep it for transcript loading.\n const childHome = env[\"HOME\"] ?? envHome;\n return { proc, envHome, childHome };\n } catch (error) {\n rm(envHome, { recursive: true, force: true }).catch(() => {});\n throw error;\n }\n}\n\n/** Mutable collection state + callbacks for gathering ACP tool calls and observations. */\ninterface ToolCollector {\n collectedToolCalls: ToolCall[];\n observationsByCallId: Map<string, Observation>;\n toolCallCount: number;\n onToolCall: (update: ToolCallMessage, receivedAt: number) => void;\n onToolUpdate: (update: ToolCallUpdateMessage, receivedAt: number) => void;\n}\n\n/** Create a {@link ToolCollector} with callbacks that populate shared state. */\nfunction createToolCollector(): ToolCollector {\n const collectedToolCalls: ToolCall[] = [];\n const observationsByCallId = new Map<string, Observation>();\n let toolCallCount = 0;\n\n const onToolCall = (update: ToolCallMessage, receivedAt: number): void => {\n toolCallCount++;\n const name = update.name ?? update.title ?? \"unknown\";\n const args = (update.rawInput as Record<string, unknown> | null) ?? {};\n collectedToolCalls.push({\n functionName: name,\n arguments: args,\n toolCallId: update.toolCallId,\n collectedAt: new Date(receivedAt).toISOString(),\n });\n };\n\n const onToolUpdate = (\n update: ToolCallUpdateMessage,\n _receivedAt: number,\n ): void => {\n const text = extractTextContent(update.content ?? undefined);\n if (text) {\n observationsByCallId.set(update.toolCallId, {\n sourceCallId: update.toolCallId,\n content: text,\n });\n }\n };\n\n return {\n collectedToolCalls,\n observationsByCallId,\n get toolCallCount() {\n return toolCallCount;\n },\n onToolCall,\n onToolUpdate,\n };\n}\n\n/** Build a {@link RunResult} for a failed session (best-effort trace from collected data). */\nfunction buildErrorResult(\n model: ModelConfig,\n pluginIds: string[],\n toolCallCount: number,\n sessionId: string,\n startTime: number,\n error: unknown,\n): RunResult {\n const metrics = buildMetrics(\n { stopReason: \"cancelled\", usage: null },\n toolCallCount,\n 0,\n startTime,\n );\n const trace: TraceData = {\n sessionId,\n model: model.id,\n steps: [],\n finalMetrics: {\n totalPromptTokens: 0,\n totalCompletionTokens: 0,\n totalCachedTokens: 0,\n totalSteps: 0,\n },\n };\n return {\n taskId: \"\",\n modelId: model.id,\n pluginIds,\n metrics,\n trace,\n output: \"\",\n checkResults: [],\n verdicts: [],\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n}\n\n/** Run a full ACP session: initialize, create session, prompt, collect events, read transcript. */\nasync function runDevinSession(\n proc: ChildProcess,\n config: AgentSpawnConfig,\n prompt: string,\n timeoutMs: number,\n childHome: string,\n): Promise<RunResult> {\n const startTime = Date.now();\n const model = config.model;\n const pluginIds = config.plugins.filter((p) => p.enabled).map((p) => p.id);\n const collector = createToolCollector();\n let sessionId = \"\";\n\n try {\n const promptResult = await runAcpSession(\n proc,\n config.workspace,\n prompt,\n timeoutMs,\n collector.onToolCall,\n collector.onToolUpdate,\n (id) => {\n sessionId = id;\n },\n );\n\n const trace = await buildTrace(\n sessionId,\n model,\n collector.collectedToolCalls,\n collector.observationsByCallId,\n childHome,\n );\n const llmCallCount = trace.steps.filter((s) => s.isLlmCall).length;\n const metrics = buildMetrics(\n promptResult,\n collector.toolCallCount,\n llmCallCount,\n startTime,\n );\n const agentOutput = extractAgentOutput(promptResult, trace);\n\n return {\n taskId: \"\",\n modelId: model.id,\n pluginIds,\n metrics,\n trace,\n output: agentOutput,\n checkResults: [],\n verdicts: [],\n success: metrics.stopReason === \"end_turn\",\n };\n } catch (error) {\n return buildErrorResult(\n model,\n pluginIds,\n collector.toolCallCount,\n sessionId,\n startTime,\n error,\n );\n }\n}\n\n/**\n * Build {@link TraceData} from the Devin transcript, enriched with\n * ACP-collected tool calls. Returns `undefined` when no transcript is\n * available so the caller can fall back to {@link buildTraceFallback}.\n */\nasync function buildTraceFromTranscript(\n sessionId: string,\n collectedToolCalls: ToolCall[],\n observationsByCallId: Map<string, Observation>,\n childHome: string,\n): Promise<TraceData | undefined> {\n if (!sessionId) return undefined;\n try {\n const transcript = await loadTranscript(sessionId, childHome);\n if (!transcript) return undefined;\n const steps = transcript.steps.map(buildTraceStep);\n attachToolCallsToSteps(steps, collectedToolCalls, observationsByCallId);\n return {\n sessionId: transcript.session_id,\n model: transcript.agent.model_name,\n steps,\n finalMetrics: {\n totalPromptTokens: transcript.final_metrics.total_prompt_tokens,\n totalCompletionTokens: transcript.final_metrics.total_completion_tokens,\n totalCachedTokens: transcript.final_metrics.total_cached_tokens,\n totalSteps: transcript.final_metrics.total_steps,\n },\n };\n } catch {\n // Transcript not available — fall through to ACP-only trace.\n return undefined;\n }\n}\n\n/** Attach the next tool call + observation to an agent step. Returns true if attached. */\nfunction attachNextToolCall(\n step: TraceStep,\n collectedToolCalls: ToolCall[],\n observationsByCallId: Map<string, Observation>,\n toolIdx: number,\n): { attached: boolean; nextIdx: number } {\n if (toolIdx >= collectedToolCalls.length)\n return { attached: false, nextIdx: toolIdx };\n const tc = collectedToolCalls[toolIdx];\n if (!tc) return { attached: false, nextIdx: toolIdx };\n const calls: ToolCall[] = [tc];\n const obs = observationsByCallId.get(tc.toolCallId);\n const observations: Observation[] = obs ? [obs] : [];\n step.toolCalls = calls;\n // Real arrival time beats the DB's identical session-end stamps.\n if (tc.collectedAt) step.timestamp = tc.collectedAt;\n if (observations.length > 0) step.observations = observations;\n return { attached: true, nextIdx: toolIdx + 1 };\n}\n\n/** Attach ACP-collected tool calls/observations to agent steps in order. */\nfunction attachToolCallsToSteps(\n steps: TraceStep[],\n collectedToolCalls: ToolCall[],\n observationsByCallId: Map<string, Observation>,\n): void {\n let toolIdx = 0;\n for (const step of steps) {\n if (step.source !== \"agent\") continue;\n const result = attachNextToolCall(\n step,\n collectedToolCalls,\n observationsByCallId,\n toolIdx,\n );\n if (result.attached) toolIdx = result.nextIdx;\n }\n}\n\n/** Build a minimal {@link TraceData} from ACP-collected data only. */\nfunction buildTraceFallback(\n sessionId: string,\n model: ModelConfig,\n collectedToolCalls: ToolCall[],\n observationsByCallId: Map<string, Observation>,\n): TraceData {\n const steps: TraceStep[] = collectedToolCalls.map((tc, i): TraceStep => {\n const obs = observationsByCallId.get(tc.toolCallId);\n const step: TraceStep = {\n stepId: i,\n timestamp: tc.collectedAt ?? new Date().toISOString(),\n source: \"agent\",\n message: tc.functionName,\n toolCalls: [tc],\n isLlmCall: false,\n };\n if (obs) {\n step.observations = [obs];\n }\n return step;\n });\n\n return {\n sessionId,\n model: model.id,\n steps,\n finalMetrics: {\n totalPromptTokens: 0,\n totalCompletionTokens: 0,\n totalCachedTokens: 0,\n totalSteps: steps.length,\n },\n };\n}\n\n/** Build {@link TraceData} from the Devin transcript, falling back to ACP-only data. */\nasync function buildTrace(\n sessionId: string,\n model: ModelConfig,\n collectedToolCalls: ToolCall[],\n observationsByCallId: Map<string, Observation>,\n childHome: string,\n): Promise<TraceData> {\n return (\n (await buildTraceFromTranscript(\n sessionId,\n collectedToolCalls,\n observationsByCallId,\n childHome,\n )) ??\n buildTraceFallback(\n sessionId,\n model,\n collectedToolCalls,\n observationsByCallId,\n )\n );\n}\n","/**\n * Judge module — blind LLM evaluation of run outputs.\n *\n * The judge receives the task prompt + the agent's output and scores it\n * against the success criteria. It does NOT know which plugins were active\n * (blind evaluation) unless {@link JudgeConfig.revealPlugins} is set.\n *\n * The judge itself is driven through the same {@link AgentAdapter}\n * interface as the agent under test: it is spawned, sent a prompt, and\n * killed after the response is collected.\n */\n\nimport type {\n JudgeConfig,\n JudgeVerdict,\n RunResult,\n Task,\n ComboComparison,\n} from \"./types.js\";\n\n/** Default system prompt for the judge. */\nexport const DEFAULT_JUDGE_PROMPT =\n \"You are a blind evaluator. You will receive a task prompt and an agent's \" +\n \"response. Score the response 0-100 based on how well it completes the \" +\n \"task. Be strict but fair. Output JSON: \" +\n '{\"score\": number, \"passed\": boolean, \"reasoning\": string, \"issues\": string[]}. ' +\n \"A score of 70+ is passing.\";\n\n/** Default timeout for a single judge run (ms). */\nconst DEFAULT_JUDGE_TIMEOUT_MS = 120_000;\n\n/**\n * Build the judge prompt for a single run.\n *\n * Includes the task prompt, success criteria, and the agent's output. Does\n * NOT include which plugins were active unless `config.revealPlugins` is\n * true. Asks the judge for a JSON response with score, passed, reasoning,\n * and issues.\n */\nexport function buildJudgePrompt(\n task: Task,\n runOutput: string,\n config: JudgeConfig,\n pluginIds: string[] = [],\n): string {\n const systemPrompt = config.systemPrompt ?? DEFAULT_JUDGE_PROMPT;\n const lines: string[] = [systemPrompt, \"\", \"## Task Prompt\", task.prompt, \"\"];\n\n if (task.successCriteria) {\n lines.push(\"## Success Criteria\", task.successCriteria, \"\");\n }\n\n if (config.revealPlugins && task.id) {\n // Only reveal plugin info when explicitly requested.\n lines.push(\"## Plugins Active During Run\");\n if (pluginIds.length > 0) {\n lines.push(pluginIds.join(\", \"));\n } else {\n lines.push(\"(no plugins)\");\n }\n lines.push(\"\");\n }\n\n lines.push(\"## Agent Response\");\n lines.push(runOutput || \"(no output)\");\n lines.push(\"\");\n\n lines.push(\n \"## Instructions\\n\" +\n \"Evaluate the agent's response against the task prompt and success \" +\n 'criteria. Respond with ONLY a JSON object: {\"score\": number, \"passed\": ' +\n 'boolean, \"reasoning\": string, \"issues\": string[]}. A score of 70 or ' +\n \"above is passing. Do not include any text outside the JSON.\",\n );\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Parse a judge response into a {@link JudgeVerdict}.\n *\n * Extracts JSON from the response, handling markdown code fences\n * (` ```json ... ``` `). Falls back to `score=0, passed=false` when the\n * response cannot be parsed.\n */\nexport function parseJudgeResponse(\n response: string,\n runIndex: number,\n run: RunResult,\n): JudgeVerdict {\n const jsonText = extractJson(response);\n const fallback: JudgeVerdict = {\n runIndex,\n score: 0,\n passed: false,\n reasoning: response.trim() || \"Failed to parse judge response\",\n issues: [],\n taskId: run.taskId,\n modelId: run.modelId,\n pluginIds: run.pluginIds,\n };\n\n if (jsonText === null) {\n return fallback;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(jsonText);\n } catch {\n return fallback;\n }\n\n if (typeof parsed !== \"object\" || parsed === null) {\n return fallback;\n }\n\n const obj = parsed as Record<string, unknown>;\n const score = typeof obj.score === \"number\" ? obj.score : 0;\n const passed = typeof obj.passed === \"boolean\" ? obj.passed : score >= 70;\n const reasoning = typeof obj.reasoning === \"string\" ? obj.reasoning : \"\";\n const issues = Array.isArray(obj.issues)\n ? obj.issues.filter((i): i is string => typeof i === \"string\")\n : [];\n\n return {\n runIndex,\n score,\n passed,\n reasoning,\n issues,\n taskId: run.taskId,\n modelId: run.modelId,\n pluginIds: run.pluginIds,\n };\n}\n\n/**\n * Judge a single run — spawn the judge agent, send the prompt, collect the\n * response, parse it into a {@link JudgeVerdict}, and kill the agent.\n */\nexport async function judgeRun(\n run: RunResult,\n task: Task,\n config: JudgeConfig,\n runIndex: number,\n): Promise<JudgeVerdict> {\n const prompt = buildJudgePrompt(task, run.output, config, run.pluginIds);\n\n const proc = config.agent.spawn({\n model: config.model,\n workspace: process.cwd(),\n plugins: [],\n permissionMode: \"dangerous\",\n });\n\n try {\n const result = await proc.run(prompt, DEFAULT_JUDGE_TIMEOUT_MS);\n return parseJudgeResponse(result.output, runIndex, run);\n } catch (error) {\n return {\n runIndex,\n score: 0,\n passed: false,\n reasoning: error instanceof Error ? error.message : String(error),\n issues: [],\n taskId: run.taskId,\n modelId: run.modelId,\n pluginIds: run.pluginIds,\n };\n } finally {\n proc.kill();\n }\n}\n\n/**\n * Judge all runs in a list, pairing each run with its matching task.\n *\n * Supports `config.repetitions` — the judge is run N times per run for\n * confidence. All verdicts are returned (one per repetition).\n */\nexport async function judgeAllRuns(\n results: RunResult[],\n tasks: Task[],\n config: JudgeConfig,\n): Promise<JudgeVerdict[]> {\n const taskById = new Map<string, Task>();\n for (const task of tasks) {\n taskById.set(task.id, task);\n }\n\n const repetitions = config.repetitions ?? 1;\n const verdicts: JudgeVerdict[] = [];\n\n for (let i = 0; i < results.length; i++) {\n const run = results[i];\n if (!run) continue;\n const task = taskById.get(run.taskId);\n if (!task) continue;\n\n for (let rep = 0; rep < repetitions; rep++) {\n // eslint-disable-next-line no-await-in-loop\n const verdict = await judgeRun(run, task, config, i);\n verdicts.push(verdict);\n }\n }\n\n return verdicts;\n}\n\n/**\n * Compare two plugin combos for a task (for {@link ComboComparison}).\n *\n * Computes deltas as `candidate - baseline`. Determines whether the\n * candidate is better:\n * - Lower tokens / toolCalls / llmCalls / time = better\n * - Higher judgeScore = better\n *\n * The judge score for each run is the average of its verdicts' scores\n * (0 when there are no verdicts).\n */\nexport function compareCombos(\n baseline: RunResult,\n candidate: RunResult,\n): ComboComparison {\n const baselineScore = avgJudgeScore(baseline);\n const candidateScore = avgJudgeScore(candidate);\n\n const deltaTokens =\n candidate.metrics.totalTokens - baseline.metrics.totalTokens;\n const deltaToolCalls =\n candidate.metrics.toolCallCount - baseline.metrics.toolCallCount;\n const deltaLlmCalls =\n candidate.metrics.llmCallCount - baseline.metrics.llmCallCount;\n const deltaTimeMs =\n candidate.metrics.executionTimeMs - baseline.metrics.executionTimeMs;\n const deltaJudgeScore = candidateScore - baselineScore;\n\n // Candidate is better when it uses fewer resources OR scores higher.\n // A strictly better on score, or equal score with fewer resources.\n const fewerResources =\n deltaTokens <= 0 &&\n deltaToolCalls <= 0 &&\n deltaLlmCalls <= 0 &&\n deltaTimeMs <= 0;\n\n const candidateBetter =\n deltaJudgeScore > 0 ||\n (deltaJudgeScore === 0 &&\n fewerResources &&\n (deltaTokens < 0 ||\n deltaToolCalls < 0 ||\n deltaLlmCalls < 0 ||\n deltaTimeMs < 0));\n\n return {\n baseline: comboLabel(baseline),\n candidate: comboLabel(candidate),\n deltaTokens,\n deltaToolCalls,\n deltaLlmCalls,\n deltaTimeMs,\n deltaJudgeScore,\n candidateBetter,\n };\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────\n\n/**\n * Extract the first JSON object from a response string.\n *\n * Handles raw JSON and JSON wrapped in markdown code fences\n * (` ```json ... ``` ` or ` ``` ... ``` `). Returns `null` when no JSON\n * object can be located.\n */\nfunction extractJson(response: string): string | null {\n const trimmed = response.trim();\n if (trimmed === \"\") return null;\n\n const fenced = extractFromFence(trimmed);\n if (fenced !== null) return fenced;\n\n const braced = extractFromBraces(trimmed);\n if (braced !== null) return braced;\n\n return null;\n}\n\n/** Extract JSON from inside a markdown code fence (```...```). */\nfunction extractFromFence(text: string): string | null {\n // Use string search instead of regex to avoid ReDoS on pathological input.\n const fenceStart = text.indexOf(\"```\");\n if (fenceStart === -1) return null;\n\n const afterFence = text.slice(fenceStart + 3);\n // Skip optional \"json\" label\n let contentStart = 0;\n if (afterFence.startsWith(\"json\")) {\n contentStart = 4;\n }\n // Skip whitespace after label\n while (\n contentStart < afterFence.length &&\n /\\s/.test(afterFence[contentStart]!)\n ) {\n contentStart++;\n }\n const fenceEnd = afterFence.indexOf(\"```\", contentStart);\n if (fenceEnd === -1) return null;\n\n const inner = afterFence.slice(contentStart, fenceEnd).trim();\n if (!looksLikeJson(inner)) return null;\n\n return inner;\n}\n\n/** Extract JSON by finding the first `{` and last `}` in the text. */\nfunction extractFromBraces(text: string): string | null {\n const start = text.indexOf(\"{\");\n const end = text.lastIndexOf(\"}\");\n if (start === -1 || end === -1 || end <= start) return null;\n\n return text.slice(start, end + 1);\n}\n\n/** Quick check that a string starts with `{` (a JSON object). */\nfunction looksLikeJson(text: string): boolean {\n return text.trim().startsWith(\"{\");\n}\n\n/** Average judge score across a run's verdicts (0 when no verdicts). */\nfunction avgJudgeScore(run: RunResult): number {\n if (run.verdicts.length === 0) return 0;\n const sum = run.verdicts.reduce((a, v) => a + v.score, 0);\n return sum / run.verdicts.length;\n}\n\n/** Build a human-readable combo label for a run's plugin set. */\nfunction comboLabel(run: RunResult): string {\n if (run.pluginIds.length === 0) return \"no-plugins\";\n return run.pluginIds.join(\",\");\n}\n","/**\n * Matrix runner — executes the full arena matrix:\n *\n * task × model × plugin combination × repetition\n *\n * For each cell it spawns the agent, runs the prompt, collects the result,\n * and kills the agent. Results are aggregated into {@link ArenaResult}.\n */\n\nimport { writeFile, mkdir, cp, rm, realpath } from \"node:fs/promises\";\nimport { existsSync, mkdtempSync, realpathSync, rmSync } from \"node:fs\";\nimport { isAbsolute, join, resolve, sep } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport { spawn, spawnSync, type SpawnOptions } from \"node:child_process\";\nimport { fileURLToPath } from \"node:url\";\n\nimport type {\n ArenaConfig,\n ArenaResult,\n RunResult,\n AggregateMetrics,\n PluginConfig,\n ModelConfig,\n Task,\n CaseAnalysis,\n ComboComparison,\n CheckResult,\n} from \"./types.js\";\nimport { judgeAllRuns, compareCombos } from \"./judge.js\";\nimport { installPlugins } from \"./adapters/devin.js\";\n\n/** Resolve the arena package root (for fixture paths). */\nconst PKG_ROOT = resolve(\n typeof __dirname !== \"undefined\"\n ? __dirname\n : fileURLToPath(new URL(\".\", import.meta.url)),\n \"..\",\n);\n\n/**\n * Generate all plugin on/off combinations.\n *\n * For N plugins this produces 2^N combinations, each a full copy of the\n * plugins array with `enabled` set appropriately.\n *\n * - 0 plugins → `[[]]` (one empty combination)\n * - 1 plugin → `[[off], [on]]`\n * - 2 plugins → `[[off,off], [on,off], [off,on], [on,on]]`\n */\nexport function pluginCombinations(plugins: PluginConfig[]): PluginConfig[][] {\n if (plugins.length === 0) return [[]];\n\n const combos: PluginConfig[][] = [[]];\n for (const plugin of plugins) {\n const next: PluginConfig[][] = [];\n for (const combo of combos) {\n // Disabled variant\n next.push([...combo, { ...plugin, enabled: false }]);\n // Enabled variant\n next.push([...combo, { ...plugin, enabled: true }]);\n }\n combos.length = 0;\n combos.push(...next);\n }\n return combos;\n}\n\n/**\n * Run the full arena matrix: task × model × plugin combo × repetitions.\n *\n * Each cell spawns the configured agent adapter, installs the plugin\n * combination, runs the prompt, collects trace + metrics, and kills the\n * agent. Results are written to `config.outputDir/results.json` and the\n * full {@link ArenaResult} is returned.\n */\nexport async function runArena(config: ArenaConfig): Promise<ArenaResult> {\n const repetitions = config.repetitions ?? 1;\n const combos = pluginCombinations(config.plugins);\n const results = await runMatrix(config, combos);\n\n // Run the judge on all results if configured.\n if (config.judge) {\n const verdicts = await judgeAllRuns(results, config.tasks, config.judge);\n for (const verdict of verdicts) {\n const run = results[verdict.runIndex];\n if (run) run.verdicts.push(verdict);\n }\n }\n\n // Build aggregates AFTER judging so judge metrics are included.\n const aggregates = buildAggregates(results, config.models, combos);\n const analysis = computeAnalysis(results, config.tasks);\n const arenaResult: ArenaResult = {\n timestamp: new Date().toISOString(),\n config: {\n models: config.models.map((m) => m.id),\n plugins: config.plugins.map((p) => p.id),\n tasks: config.tasks.map((t) => t.id),\n repetitions,\n ...(config.judge ? { judgeModel: config.judge.model.id } : {}),\n },\n results,\n aggregates,\n analysis,\n };\n\n await mkdir(config.outputDir, { recursive: true });\n await writeFile(\n join(config.outputDir, \"results.json\"),\n JSON.stringify(arenaResult, null, 2),\n \"utf-8\",\n );\n return arenaResult;\n}\n\n/**\n * Run every cell of the task × model × combo × repetition matrix, collecting\n * results and logging per-cell progress to stderr.\n */\nasync function runMatrix(\n config: ArenaConfig,\n combos: PluginConfig[][],\n): Promise<RunResult[]> {\n const repetitions = config.repetitions ?? 1;\n const results: RunResult[] = [];\n for (const task of config.tasks) {\n for (const model of config.models) {\n for (const combo of combos) {\n for (let rep = 0; rep < repetitions; rep++) {\n const cellLabel = formatCell(task.id, model.id, combo, rep);\n process.stderr.write(`[arena] ${cellLabel} running...\\n`);\n const result = await runCell(\n config.agent,\n task,\n model,\n combo,\n rep,\n config.workspace,\n config.unshareNet,\n );\n results.push(result);\n process.stderr.write(\n `[arena] ${cellLabel} ${result.success ? \"PASS\" : \"FAIL\"} — ` +\n `${result.metrics.totalTokens} tokens, ${result.metrics.toolCallCount} tools, ` +\n `${result.metrics.llmCallCount} llm calls, ${result.metrics.executionTimeMs}ms\\n`,\n );\n }\n }\n }\n }\n return results;\n}\n\n/**\n * Aggregate metrics per (model × plugin combo) cell.\n */\nfunction buildAggregates(\n results: RunResult[],\n models: ModelConfig[],\n combos: PluginConfig[][],\n): AggregateMetrics[] {\n const aggregates: AggregateMetrics[] = [];\n for (const model of models) {\n for (const combo of combos) {\n const pluginIds = combo.filter((p) => p.enabled).map((p) => p.id);\n const label = formatAggregateLabel(model.id, pluginIds);\n aggregates.push(\n aggregateResults(\n results,\n (r) =>\n r.modelId === model.id && samePluginIds(r.pluginIds, pluginIds),\n label,\n ),\n );\n }\n }\n return aggregates;\n}\n\n/** Run a single matrix cell in an ISOLATED temp workspace. */\nasync function runCell(\n agent: ArenaConfig[\"agent\"],\n task: ArenaConfig[\"tasks\"][number],\n model: ArenaConfig[\"models\"][number],\n combo: PluginConfig[],\n rep: number,\n workspaceBase?: string,\n unshareNet = false,\n): Promise<RunResult> {\n const tempWorkspace = await createTempWorkspace(\n task,\n model,\n combo,\n rep,\n workspaceBase,\n );\n await installPlugins(tempWorkspace, combo);\n const result = await executeRun(\n agent,\n task,\n model,\n combo,\n tempWorkspace,\n unshareNet,\n );\n await rm(tempWorkspace, { recursive: true, force: true });\n return result;\n}\n\n/**\n * Create an isolated temp workspace with a fresh copy of the fixture (if any).\n * Each run gets its own copy to prevent skill contamination from the host repo.\n */\nasync function createTempWorkspace(\n task: ArenaConfig[\"tasks\"][number],\n model: ArenaConfig[\"models\"][number],\n combo: PluginConfig[],\n rep: number,\n base?: string,\n): Promise<string> {\n const tempWorkspace = join(\n base ?? tmpdir(),\n `arena-${task.id}-${model.id}-${combo.map((p) => p.id + (p.enabled ? \"on\" : \"off\")).join(\",\")}-r${rep}-${Date.now()}`,\n );\n await mkdir(tempWorkspace, { recursive: true });\n if (task.fixture) {\n const fixturePath = resolve(PKG_ROOT, task.fixture);\n // Prevent path traversal: relative fixtures must stay under PKG_ROOT.\n // Absolute paths (e.g. anchored to the config file by loadArenaConfig)\n // are trusted as intentional. realpath() catches a fixture dir that is\n // itself a symlink escaping the root.\n if (!isAbsolute(task.fixture)) {\n const real = await realpath(fixturePath);\n const realRoot = await realpath(PKG_ROOT);\n if (!real.startsWith(realRoot + sep) && real !== realRoot) {\n throw new Error(`Fixture path escapes package root: ${task.fixture}`);\n }\n }\n await cp(fixturePath, tempWorkspace, { recursive: true });\n }\n return tempWorkspace;\n}\n\n/**\n * Spawn the agent, run the prompt, run deterministic checks, and return the\n * result. On error returns a zeroed {@link RunResult} via {@link errorResult}.\n */\nasync function executeRun(\n agent: ArenaConfig[\"agent\"],\n task: ArenaConfig[\"tasks\"][number],\n model: ArenaConfig[\"models\"][number],\n combo: PluginConfig[],\n tempWorkspace: string,\n unshareNet = false,\n): Promise<RunResult> {\n const setupError = await runSetup(tempWorkspace, task.setup);\n if (setupError) return errorResult(task, model, combo, setupError);\n const proc = agent.spawn({\n model,\n workspace: tempWorkspace,\n plugins: combo,\n permissionMode: \"dangerous\",\n });\n try {\n const result = await proc.run(task.prompt, task.timeoutMs ?? 120_000);\n result.taskId = task.id;\n if (!result.verdicts) result.verdicts = [];\n if (!result.checkResults) result.checkResults = [];\n if (task.checks && task.checks.length > 0) {\n result.checkResults = await runChecks(\n tempWorkspace,\n task.checks,\n unshareNet,\n );\n result.success =\n result.success && result.checkResults.every((c) => c.passed);\n }\n return result;\n } catch (error) {\n return errorResult(task, model, combo, error);\n } finally {\n proc.kill();\n }\n}\n\n/** Run a task's setup commands; returns the failure, or null on success. */\nasync function runSetup(\n workspace: string,\n setup: string[] | undefined,\n): Promise<Error | null> {\n for (const command of setup ?? []) {\n try {\n const { output, exitCode } = await execShell(workspace, command);\n if (exitCode !== 0) {\n return new Error(\n `setup command failed (exit ${exitCode}): ${command}\\n${output.trim()}`,\n );\n }\n } catch (error) {\n return error instanceof Error ? error : new Error(String(error));\n }\n }\n return null;\n}\n\n/** Build a zeroed {@link RunResult} for a failed run. */\nfunction errorResult(\n task: ArenaConfig[\"tasks\"][number],\n model: ArenaConfig[\"models\"][number],\n combo: PluginConfig[],\n error: unknown,\n): RunResult {\n return {\n taskId: task.id,\n modelId: model.id,\n pluginIds: combo.filter((p) => p.enabled).map((p) => p.id),\n metrics: {\n inputTokens: 0,\n outputTokens: 0,\n thoughtTokens: 0,\n totalTokens: 0,\n toolCallCount: 0,\n llmCallCount: 0,\n executionTimeMs: 0,\n stopReason: \"cancelled\",\n },\n trace: {\n sessionId: \"\",\n model: model.id,\n steps: [],\n finalMetrics: {\n totalPromptTokens: 0,\n totalCompletionTokens: 0,\n totalCachedTokens: 0,\n totalSteps: 0,\n },\n },\n output: \"\",\n checkResults: [],\n verdicts: [],\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n}\n\n/**\n * Env for check subprocesses. Checks run agent-written scripts (e.g.\n * `bun run verify` executes whatever the agent left in package.json), so\n * the runner's secrets must not leak in. Allowlist toolchain basics only.\n */\nexport function buildCheckEnv(\n env: Record<string, string | undefined> = process.env,\n home?: string,\n): Record<string, string> {\n // NODE_OPTIONS is deliberately excluded — host preload flags would inject\n // host modules into Node-based checks.\n const SAFE =\n /^(PATH|HOME|USERPROFILE|HOMEDRIVE|HOMEPATH|SYSTEMROOT|SystemRoot|WINDIR|COMSPEC|PATHEXT|TEMP|TMP|TMPDIR|SHELL|TERM|COLORTERM|FORCE_COLOR|NO_COLOR|LANG|LC_[A-Z_]+|USER|LOGNAME|XDG_CACHE_HOME|XDG_CONFIG_HOME|XDG_DATA_HOME|TZ|NODE_ENV|BUN_INSTALL|VIRTUAL_ENV|OSTYPE|MACHTYPE|HOSTTYPE)$/;\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(env)) {\n if (typeof value === \"string\" && SAFE.test(key)) out[key] = value;\n }\n // Redirect the credential-bearing home dirs at a fresh empty home.\n if (home) {\n out[\"HOME\"] = home;\n out[\"USERPROFILE\"] = home;\n out[\"XDG_CACHE_HOME\"] = join(home, \".cache\");\n out[\"XDG_CONFIG_HOME\"] = join(home, \".config\");\n out[\"XDG_DATA_HOME\"] = join(home, \".local\", \"share\");\n // Keep package-manager caches warm: setup ran with the host HOME and\n // populated them, and caches carry no credentials. Without this every\n // check that installs or resolves deps re-downloads the world.\n const hostHome = env[\"HOME\"];\n if (hostHome) {\n out[\"BUN_INSTALL_CACHE_DIR\"] =\n env[\"BUN_INSTALL_CACHE_DIR\"] ??\n join(hostHome, \".bun\", \"install\", \"cache\");\n out[\"npm_config_cache\"] =\n env[\"npm_config_cache\"] ?? join(hostHome, \".npm\");\n }\n }\n out[\"CI\"] = \"true\"; // forced — checks always see CI mode\n return out;\n}\n\n/**\n * Host dirs bound read-only into the check sandbox — the toolchain (bun,\n * node, bash, git) plus /etc. Host $HOME is deliberately absent: that is\n * what makes credentials unreachable by absolute path, not just by env.\n */\nconst SANDBOX_RO_DIRS = [\"/usr\", \"/bin\", \"/sbin\", \"/lib\", \"/lib64\", \"/etc\"];\n\n/**\n * Toolchain prefixes outside the system dirs bound read-only — never a\n * wholesale parent like /opt or /home/linuxbrew, which would expose\n * arbitrary host files.\n */\nconst SANDBOX_RO_TOOL_DIRS = [\n \"/opt/hostedtoolcache\",\n \"/home/linuxbrew/.linuxbrew\",\n];\n\n/**\n * Toolchain subdirs under the host HOME bound read-only — binaries and\n * version managers only, never credential-bearing dirs. `~/.bun` and\n * `~/.local/bin` stay on PATH inside the sandbox without exposing\n * ~/.config, ~/.ssh or ~/.npmrc.\n */\nconst SANDBOX_HOME_TOOL_DIRS = [\n \".bun\",\n \".local/bin\",\n \".local/share/mise\",\n \".local/share/pnpm\",\n \".local/share/pipx\",\n \".local/share/uv\",\n \".cargo/bin\",\n \".rustup\",\n \".nvm\",\n \".volta\",\n \".asdf\",\n \".deno\",\n \".pyenv\",\n \".poetry\",\n \".rbenv\",\n \".sdkman\",\n];\n\n/**\n * Read-only bind args shared by the availability probe and the real\n * sandbox — both must mount the same view or the probe lies. A dir that\n * is inside, or equal to, the host HOME is never bound wholesale;\n * toolchain subtrees under HOME are re-exposed explicitly by\n * SANDBOX_HOME_TOOL_DIRS.\n */\nfunction sandboxRoBinds(hostHome: string | undefined): string[] {\n const argv: string[] = [];\n for (const dir of [...SANDBOX_RO_DIRS, ...SANDBOX_RO_TOOL_DIRS]) {\n if (hostHome && (dir === hostHome || dir.startsWith(hostHome + sep)))\n continue;\n if (existsSync(dir)) argv.push(\"--ro-bind\", dir, dir);\n }\n const resolv = resolvConfTarget(hostHome);\n if (resolv) argv.push(\"--ro-bind\", resolv, resolv);\n return argv;\n}\n\n/**\n * Resolved /etc/resolv.conf target worth binding, or undefined. The file\n * is often a symlink (/run/systemd/resolve/* on systemd-resolved,\n * /mnt/wsl/resolv.conf on WSL) whose target lives outside the /etc bind —\n * bind the target alone so sandboxed checks keep DNS without exposing\n * the whole parent dir. A target inside host HOME is skipped like any\n * other HOME path; a plain file stays covered by the /etc bind.\n */\nfunction resolvConfTarget(hostHome: string | undefined): string | undefined {\n try {\n const resolv = realpathSync(\"/etc/resolv.conf\");\n if (resolv === \"/etc/resolv.conf\") return undefined;\n const insideHome =\n hostHome !== undefined &&\n (resolv === hostHome || resolv.startsWith(hostHome + sep));\n return insideHome ? undefined : resolv;\n } catch {\n // No usable resolv.conf target — DNS is absent inside, like /run.\n return undefined;\n }\n}\n\n/**\n * Args masking the host HOME inside the sandbox and re-exposing only the\n * allowlisted toolchain subdirs. HOME may be a symlink into a bound dir\n * — a textual containment check would miss that /usr/runner is readable\n * through /usr — so containment is tested on the resolved path while\n * tool dirs bind back at the textual HOME so PATH entries keep working.\n */\nfunction sandboxHomeBinds(hostHome: string, roDirs: string[]): string[] {\n const resolvedHome = existsSync(hostHome) ? realpathSync(hostHome) : hostHome;\n const underBoundDir = (p: string) =>\n roDirs.some((d) => p.startsWith(d + sep));\n const argv: string[] = [];\n if (underBoundDir(resolvedHome)) argv.push(\"--tmpfs\", resolvedHome);\n if (hostHome !== resolvedHome && underBoundDir(hostHome)) {\n argv.push(\"--tmpfs\", hostHome);\n }\n for (const sub of SANDBOX_HOME_TOOL_DIRS) {\n const src = join(resolvedHome, sub);\n if (existsSync(src)) argv.push(\"--ro-bind\", src, join(hostHome, sub));\n }\n return argv;\n}\n\nconst bwrapDetected = new Map<boolean, boolean>();\nfunction hasBwrap(unshareNet = false): boolean {\n // Probe a real namespace launch — `bwrap --version` says nothing about\n // whether unprivileged user namespaces are enabled on this kernel. Run\n // the full argv (tmpfs + ro/rw binds, plus --unshare-net when the config\n // asks for it) against throwaway dirs so a mount/namespace-type failure\n // surfaces here, not on the first check.\n const cached = bwrapDetected.get(unshareNet);\n if (cached !== undefined) return cached;\n if (process.platform !== \"linux\") {\n bwrapDetected.set(unshareNet, false);\n return false;\n }\n const probeWs = mkdtempSync(join(tmpdir(), \"arena-probe-\"));\n const probeHome = mkdtempSync(join(tmpdir(), \"arena-probe-home-\"));\n let detected: boolean;\n try {\n detected =\n spawnSync(\n \"bwrap\", // NOSONAR — host PATH is trusted runner config\n [...buildSandboxArgv(probeWs, probeHome, unshareNet), \"true\"],\n { stdio: \"ignore\" },\n ).status === 0;\n } finally {\n rmSync(probeWs, { recursive: true, force: true });\n rmSync(probeHome, { recursive: true, force: true });\n }\n bwrapDetected.set(unshareNet, detected);\n return detected;\n}\n\n/**\n * bubblewrap argv wrapping a check command: fresh user+pid namespaces,\n * only the workspace and check HOME writable, toolchain dirs read-only.\n * Anything not bound (host $HOME, ~/.ssh, ~/.config) simply does not\n * exist inside — a real filesystem boundary, unlike env scrubbing.\n */\nexport function buildSandboxArgv(\n workspace: string,\n checkHome: string,\n unshareNet = false,\n): string[] {\n const argv = [\n \"--die-with-parent\",\n \"--unshare-user\",\n \"--uid\",\n \"0\",\n \"--gid\",\n \"0\",\n \"--unshare-pid\",\n // Opt-in: a fresh network namespace has no interfaces but loopback —\n // checks that must not reach the network get full isolation. Off by\n // default because checks legitimately install packages.\n ...(unshareNet ? [\"--unshare-net\"] : []),\n \"--new-session\",\n \"--dev\",\n \"/dev\",\n \"--proc\",\n \"/proc\",\n \"--tmpfs\",\n \"/tmp\",\n ];\n const hostHome = process.env[\"HOME\"];\n const roDirs = [...SANDBOX_RO_DIRS, ...SANDBOX_RO_TOOL_DIRS];\n argv.push(...sandboxRoBinds(hostHome));\n if (hostHome) argv.push(...sandboxHomeBinds(hostHome, roDirs));\n argv.push(\n \"--bind\",\n checkHome,\n checkHome,\n \"--bind\",\n workspace,\n workspace,\n \"--chdir\",\n workspace,\n \"--\",\n \"bash\",\n \"-c\",\n );\n return argv;\n}\n\n/** Run a shell command in the workspace, capturing combined output. */\nfunction execShell(\n workspace: string,\n command: string,\n env?: Record<string, string>,\n checkHome?: string,\n unshareNet = false,\n): Promise<{ output: string; exitCode: number }> {\n const opts: SpawnOptions = {\n cwd: workspace,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env: env ?? { ...process.env, CI: \"true\" },\n };\n const run = (\n sandboxed: boolean,\n ): Promise<{ output: string; exitCode: number }> =>\n new Promise((resolve, reject) => {\n const proc = sandboxed\n ? spawn(\n \"bwrap\", // NOSONAR — host PATH is trusted runner config\n [\n ...buildSandboxArgv(workspace, checkHome ?? \"\", unshareNet),\n command,\n ],\n opts,\n )\n : spawn(\"bash\", [\"-c\", command], opts); // NOSONAR — config-author shell commands\n // Cap captured output — a noisy command must not grow memory\n // without bound. 256 KiB keeps tail diagnostics while bounding the\n // worst case.\n const MAX_OUTPUT = 256 * 1024;\n let stdout = \"\";\n const append = (d: Buffer): void => {\n if (stdout.length < MAX_OUTPUT) stdout += d.toString();\n };\n proc.stdout?.on(\"data\", append);\n proc.stderr?.on(\"data\", append);\n proc.on(\"close\", (code: number | null) => {\n // null = killed by signal; treat as failure, not a crash source.\n resolve({ output: stdout, exitCode: code ?? -1 });\n });\n proc.on(\"error\", reject);\n });\n if (checkHome === undefined || !hasBwrap(unshareNet)) return run(false);\n // No retry on sandboxed failure: the check output is child-controlled,\n // so a nonzero result can never prove the sandbox itself failed —\n // treating any marker as \"retry outside\" would hand agent-authored\n // commands an un-sandboxed second run. Coverage lives in hasBwrap(),\n // which probes the full argv before the first check runs.\n return run(true);\n}\n\n/**\n * Run deterministic checks in the workspace. Checks execute agent-written\n * scripts, so they get a scrubbed env (see {@link buildCheckEnv}) plus a\n * fresh empty HOME. On Linux with bubblewrap available the command also\n * runs in a mount/user/pid namespace ({@link buildSandboxArgv}) — host\n * $HOME and credentials are unreachable even via absolute paths. Without\n * bwrap the env scrub stands alone: hygiene, not a sandbox.\n */\nasync function runChecks(\n workspace: string,\n checks: Task[\"checks\"],\n unshareNet = false,\n): Promise<CheckResult[]> {\n if (!checks) return [];\n const checkHome = mkdtempSync(join(tmpdir(), \"arena-check-home-\"));\n const env = buildCheckEnv(process.env, checkHome);\n if (unshareNet && !hasBwrap(true)) {\n // Requested network isolation is unavailable on this host — say so\n // loudly instead of silently running checks with host network.\n process.stderr.write(\n \"[arena] warning: unshareNet requested but the bwrap sandbox is \" +\n \"unavailable — checks run with host network\\n\",\n );\n }\n if (hasBwrap(unshareNet)) {\n // Host cache paths aren't bound inside the sandbox — point them at\n // writable dirs under the fresh check HOME instead.\n env[\"BUN_INSTALL_CACHE_DIR\"] = join(checkHome, \".bun\", \"install\", \"cache\");\n env[\"npm_config_cache\"] = join(checkHome, \".npm\");\n }\n const results: CheckResult[] = [];\n try {\n for (const check of checks) {\n try {\n const { output, exitCode } = await execShell(\n workspace,\n check.command,\n env,\n checkHome,\n unshareNet,\n );\n results.push({\n checkId: check.id,\n passed: exitCode === 0,\n output: output.trim(),\n exitCode,\n });\n } catch (error) {\n results.push({\n checkId: check.id,\n passed: false,\n output: error instanceof Error ? error.message : String(error),\n exitCode: -1,\n });\n }\n }\n return results;\n } finally {\n await rm(checkHome, { recursive: true, force: true }).catch(() => {});\n }\n}\n\n/**\n * Aggregate metrics for a group of runs selected by `filter`.\n *\n * Computes averages across all matching runs. Returns zeroed metrics when\n * no runs match. Includes judge-related fields (`avgJudgeScore`,\n * `judgePassCount`) and a `label` identifying the aggregate group.\n */\nexport function aggregateResults(\n results: RunResult[],\n filter: (r: RunResult) => boolean,\n label = \"\",\n): AggregateMetrics {\n const filtered = results.filter(filter);\n const n = filtered.length;\n if (n === 0) {\n return {\n totalRuns: 0,\n successCount: 0,\n avgInputTokens: 0,\n avgOutputTokens: 0,\n avgTotalTokens: 0,\n avgToolCalls: 0,\n avgLlmCalls: 0,\n avgExecutionTimeMs: 0,\n avgJudgeScore: 0,\n judgePassCount: 0,\n label,\n };\n }\n const sum = (f: (r: RunResult) => number) =>\n filtered.reduce((a, r) => a + f(r), 0);\n const round = (v: number) => Math.round(v);\n const round2 = (v: number) => Math.round(v * 100) / 100;\n\n // Judge scores: use verdicts[0].score (first judge verdict per run).\n const judgedRuns = filtered.filter((r) => r.verdicts.length > 0);\n const avgJudgeScore =\n judgedRuns.length === 0\n ? 0\n : round2(\n judgedRuns.reduce((a, r) => a + (r.verdicts[0]?.score ?? 0), 0) /\n judgedRuns.length,\n );\n const judgePassCount = filtered.filter(\n (r) => r.verdicts[0]?.passed === true,\n ).length;\n\n return {\n totalRuns: n,\n successCount: filtered.filter((r) => r.success).length,\n avgInputTokens: round(sum((r) => r.metrics.inputTokens) / n),\n avgOutputTokens: round(sum((r) => r.metrics.outputTokens) / n),\n avgTotalTokens: round(sum((r) => r.metrics.totalTokens) / n),\n avgToolCalls: round2(sum((r) => r.metrics.toolCallCount) / n),\n avgLlmCalls: round2(sum((r) => r.metrics.llmCallCount) / n),\n avgExecutionTimeMs: round(sum((r) => r.metrics.executionTimeMs) / n),\n avgJudgeScore,\n judgePassCount,\n label,\n };\n}\n\n/** Compare two plugin-id arrays for equality (order-insensitive). */\nfunction samePluginIds(a: string[], b: string[]): boolean {\n if (a.length !== b.length) return false;\n const set = new Set(a);\n for (const id of b) {\n if (!set.has(id)) return false;\n }\n return true;\n}\n\n/** Format a human-readable cell label for logging. */\nfunction formatCell(\n taskId: string,\n modelId: string,\n combo: PluginConfig[],\n rep: number,\n): string {\n const plugins = combo\n .map((p) => `${p.id}=${p.enabled ? \"on\" : \"off\"}`)\n .join(\",\");\n return `${taskId}/${modelId}/{${plugins}}#${rep}`;\n}\n\n/** Format an aggregate group label: \"model-id/plugins=on,off\" or \"model-id/no-plugins\". */\nfunction formatAggregateLabel(modelId: string, pluginIds: string[]): string {\n if (pluginIds.length === 0) return `${modelId}/no-plugins`;\n return `${modelId}/plugins=${pluginIds.join(\",\")}`;\n}\n\n/** Format a plugin combo label for comparisons: \"no-plugins\" or comma-joined ids. */\nfunction comboLabel(pluginIds: string[]): string {\n if (pluginIds.length === 0) return \"no-plugins\";\n return pluginIds.join(\",\");\n}\n\n// ─── Case analysis ───────────────────────────────────────────────────\n\n/**\n * Create a synthetic \"average\" {@link RunResult} representing a group of\n * runs with the same plugin combo. Used to feed {@link compareCombos} which\n * operates on single runs.\n */\nfunction averageRun(runs: RunResult[]): RunResult | null {\n if (runs.length === 0) return null;\n const n = runs.length;\n const avg = (f: (r: RunResult) => number): number =>\n Math.round(runs.reduce((a, r) => a + f(r), 0) / n);\n const avg2 = (f: (r: RunResult) => number): number =>\n Math.round((runs.reduce((a, r) => a + f(r), 0) / n) * 100) / 100;\n const first = runs[0]!;\n return {\n taskId: first.taskId,\n modelId: first.modelId,\n pluginIds: first.pluginIds,\n metrics: {\n inputTokens: avg((r) => r.metrics.inputTokens),\n outputTokens: avg((r) => r.metrics.outputTokens),\n thoughtTokens: avg((r) => r.metrics.thoughtTokens),\n totalTokens: avg((r) => r.metrics.totalTokens),\n toolCallCount: avg2((r) => r.metrics.toolCallCount),\n llmCallCount: avg2((r) => r.metrics.llmCallCount),\n executionTimeMs: avg((r) => r.metrics.executionTimeMs),\n stopReason: first.metrics.stopReason,\n },\n trace: first.trace,\n output: first.output,\n checkResults: first.checkResults ?? [],\n verdicts: first.verdicts,\n success: runs.every((r) => r.success),\n };\n}\n\n/**\n * Compute per-task analysis comparing baseline (no plugins) vs each\n * candidate plugin combo.\n *\n * For each task, groups runs by plugin combo, creates an averaged\n * representative run per group, then compares the baseline (empty\n * `pluginIds`) against every non-empty candidate combo using\n * {@link compareCombos} from `judge.ts`.\n */\nexport function computeAnalysis(\n results: RunResult[],\n tasks: Task[],\n): CaseAnalysis[] {\n const analyses: CaseAnalysis[] = [];\n\n for (const task of tasks) {\n const taskRuns = results.filter((r) => r.taskId === task.id);\n\n // Group runs by plugin combo (order-insensitive).\n const comboGroups = new Map<string, RunResult[]>();\n for (const run of taskRuns) {\n const key = comboLabel(run.pluginIds);\n const group = comboGroups.get(key);\n if (group) {\n group.push(run);\n } else {\n comboGroups.set(key, [run]);\n }\n }\n\n const baselineRuns = comboGroups.get(\"no-plugins\") ?? [];\n const baseline = averageRun(baselineRuns);\n const comparisons: ComboComparison[] = [];\n\n if (baseline) {\n for (const [key, candidateRuns] of comboGroups) {\n if (key === \"no-plugins\") continue;\n const candidate = averageRun(candidateRuns);\n if (candidate) {\n comparisons.push(compareCombos(baseline, candidate));\n }\n }\n }\n\n analyses.push({\n taskId: task.id,\n taskName: task.name,\n prompt: task.prompt,\n comparisons,\n });\n }\n\n return analyses;\n}\n","/**\n * Arena config file support — `arena.config.ts` exports declarative data;\n * the CLI resolves the agent adapter by name and validates the shape with\n * zod. See specs/49-arena-cli.\n */\n\nimport { z } from \"zod\";\nimport { pathToFileURL } from \"node:url\";\nimport { dirname, isAbsolute, resolve } from \"node:path\";\n\nimport type { AgentAdapter, ArenaConfig, ModelConfig } from \"./types.js\";\nimport { DevinAdapter } from \"./adapters/devin.js\";\n\nexport type ArenaErrorCode =\n | \"CONFIG_INVALID\"\n | \"CONFIG_NOT_FOUND\"\n | \"UNKNOWN_AGENT\"\n | \"SCHEMA_INVALID\"\n | \"PUBLISH_CONFLICT\"\n | \"REGISTRY_UNAVAILABLE\"\n | \"PACK_NOT_FOUND\"\n | \"PACK_INVALID\";\n\nexport class ArenaError extends Error {\n override readonly cause: unknown;\n\n constructor(\n message: string,\n readonly code: ArenaErrorCode,\n cause?: unknown,\n ) {\n super(message);\n this.name = \"ArenaError\";\n if (cause !== undefined) {\n this.cause = cause;\n }\n }\n}\n\n// ─── Adapter registry ────────────────────────────────────────────────\n\nconst ADAPTERS: Readonly<Record<string, () => AgentAdapter>> = {\n devin: () => new DevinAdapter(),\n};\n\nexport function resolveAdapter(name: string): AgentAdapter {\n if (!Object.hasOwn(ADAPTERS, name)) {\n throw new ArenaError(\n `unknown agent '${name}' — registered adapters: ${Object.keys(ADAPTERS).join(\", \")}`,\n \"UNKNOWN_AGENT\",\n );\n }\n return ADAPTERS[name]!();\n}\n\n// ─── Schema ──────────────────────────────────────────────────────────\n\nconst modelSchema = z.object({\n id: z.string(),\n name: z.string(),\n envVar: z.string().optional(),\n});\n\nconst pluginSchema = z.object({\n id: z.string(),\n name: z.string(),\n path: z.string(),\n enabled: z.boolean().optional(),\n installPath: z.string().optional(),\n});\n\nconst checkSchema = z.object({\n id: z.string(),\n command: z.string(),\n description: z.string(),\n});\n\nconst taskSchema = z.object({\n id: z.string(),\n name: z.string(),\n prompt: z.string(),\n timeoutMs: z.number().optional(),\n successCriteria: z.string().optional(),\n expectedOutput: z.string().optional(),\n fixture: z.string().optional(),\n setup: z.array(z.string()).optional(),\n checks: z.array(checkSchema).optional(),\n});\n\nconst configFileSchema = z.object({\n agent: z.string(),\n models: z.array(modelSchema).min(1),\n plugins: z.array(pluginSchema).optional(),\n tasks: z.array(taskSchema).min(1),\n workspace: z.string().optional(),\n repetitions: z.number().int().positive().optional(),\n unshareNet: z.boolean().optional(),\n outputDir: z.string(),\n judge: z\n .object({\n model: modelSchema,\n agent: z.string().optional(),\n repetitions: z.number().int().positive().optional(),\n revealPlugins: z.boolean().optional(),\n systemPrompt: z.string().optional(),\n })\n .optional(),\n});\n\n/** Declarative config shape authored in `arena.config.ts`. */\nexport type ArenaConfigFile = z.input<typeof configFileSchema>;\n\n/** Type-only identity helper — gives configs full typechecking. */\nexport function defineConfig(config: ArenaConfigFile): ArenaConfigFile {\n return config;\n}\n\n// ─── Loader ──────────────────────────────────────────────────────────\n\n/**\n * Load and validate an arena config file, resolving the named agent\n * (and judge agent, defaulting to the same adapter) to live adapters.\n */\nexport async function loadArenaConfig(\n configPath: string,\n): Promise<ArenaConfig> {\n const absPath = isAbsolute(configPath)\n ? configPath\n : resolve(process.cwd(), configPath);\n\n let mod: Record<string, unknown>;\n try {\n mod = (await import(pathToFileURL(absPath).href)) as Record<\n string,\n unknown\n >;\n } catch (err) {\n throw new ArenaError(\n `cannot load arena config '${absPath}': ${err instanceof Error ? err.message : String(err)}`,\n \"CONFIG_NOT_FOUND\",\n );\n }\n\n if (typeof mod.default !== \"object\" || mod.default === null) {\n throw new ArenaError(\n `arena config '${absPath}' must export a default config object`,\n \"CONFIG_INVALID\",\n );\n }\n\n const parsed = configFileSchema.safeParse(mod.default);\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((i) => ` ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\");\n throw new ArenaError(\n `invalid arena config '${absPath}':\\n${issues}`,\n \"CONFIG_INVALID\",\n );\n }\n\n const file = parsed.data;\n const agent = resolveAdapter(file.agent);\n\n // Paths in the config file resolve relative to the config file's\n // directory, so `sverka-arena` can be invoked from anywhere.\n const dir = dirname(absPath);\n const rel = (p: string): string => (isAbsolute(p) ? p : resolve(dir, p));\n\n return {\n agent,\n models: file.models as ModelConfig[],\n plugins: (file.plugins ?? []).map((p) => ({\n ...p,\n path: rel(p.path),\n })) as ArenaConfig[\"plugins\"],\n tasks: file.tasks.map((t) => ({\n ...t,\n ...(t.fixture !== undefined ? { fixture: rel(t.fixture) } : {}),\n })) as ArenaConfig[\"tasks\"],\n outputDir: rel(file.outputDir),\n ...optionalFields({\n workspace: file.workspace === undefined ? undefined : rel(file.workspace),\n repetitions: file.repetitions,\n unshareNet: file.unshareNet,\n }),\n ...(file.judge ? { judge: mapJudge(file.agent, file.judge) } : {}),\n };\n}\n\n/** Spreadable optional fields — drops keys whose value is undefined. */\nfunction optionalFields<T extends Record<string, unknown>>(\n fields: T,\n): { [K in keyof T]?: Exclude<T[K], undefined> } {\n return Object.fromEntries(\n Object.entries(fields).filter(([, v]) => v !== undefined),\n ) as { [K in keyof T]?: Exclude<T[K], undefined> };\n}\n\nfunction mapJudge(\n agentName: string,\n j: NonNullable<z.infer<typeof configFileSchema>[\"judge\"]>,\n): NonNullable<ArenaConfig[\"judge\"]> {\n return {\n model: j.model as ModelConfig,\n agent: resolveAdapter(j.agent ?? agentName),\n ...optionalFields({\n repetitions: j.repetitions,\n revealPlugins: j.revealPlugins,\n systemPrompt: j.systemPrompt,\n }),\n };\n}\n","/**\n * Text rendering for arena results — aggregate table + per-task analysis.\n * Used by `sverka-arena run` (post-run summary) and `sverka-arena report`.\n */\n\nimport type { AggregateMetrics, ArenaResult } from \"./types.js\";\n\nfunction fmtNum(n: number): string {\n return Number.isInteger(n) ? String(n) : n.toFixed(1);\n}\n\nfunction row(\n cells: readonly (string | number)[],\n widths: readonly number[],\n): string {\n return cells\n .map((c, i) => String(c).padEnd(widths[i] ?? 10))\n .join(\"\")\n .trimEnd();\n}\n\nfunction aggregateTable(aggregates: readonly AggregateMetrics[]): string {\n const header = [\n \"label\",\n \"runs\",\n \"pass\",\n \"tokens\",\n \"tools\",\n \"llm\",\n \"ms\",\n \"judge\",\n ];\n const data = aggregates.map((a) => [\n a.label,\n a.totalRuns,\n a.successCount,\n fmtNum(a.avgTotalTokens),\n fmtNum(a.avgToolCalls),\n fmtNum(a.avgLlmCalls),\n fmtNum(a.avgExecutionTimeMs),\n a.judgePassCount > 0 || a.avgJudgeScore > 0 ? fmtNum(a.avgJudgeScore) : \"-\",\n ]);\n const widths = header.map((h, i) =>\n Math.max(h.length + 2, ...data.map((r) => String(r[i] ?? \"\").length + 2)),\n );\n const lines = [row(header, widths)];\n for (const r of data) lines.push(row(r, widths));\n return lines.join(\"\\n\");\n}\n\n/** Render an ArenaResult as human-readable text. */\nexport function renderReport(result: ArenaResult): string {\n const parts: string[] = [];\n\n parts.push(\"Aggregates\", aggregateTable(result.aggregates));\n\n if (result.analysis.length > 0) {\n parts.push(\"\", \"Analysis\");\n for (const task of result.analysis) {\n parts.push(` ${task.taskName} (${task.taskId})`);\n for (const cmp of task.comparisons) {\n const verdict = cmp.candidateBetter ? \"better\" : \"worse\";\n parts.push(\n ` ${cmp.baseline} → ${cmp.candidate}: ` +\n `tokens ${cmp.deltaTokens}, tools ${cmp.deltaToolCalls}, ` +\n `llm ${cmp.deltaLlmCalls}, ms ${cmp.deltaTimeMs}, ` +\n `judge ${cmp.deltaJudgeScore} — ${verdict}`,\n );\n }\n if (task.summary !== undefined) {\n parts.push(` ${task.summary}`);\n }\n }\n }\n\n return parts.join(\"\\n\");\n}\n","/**\n * ArenaResult → one sverka report for the whole run matrix.\n *\n * The per-run trace report ({@link ./trace-report.js}) renders a single\n * agent run; this renders the benchmark itself as a pipeline: each task\n * is a pipeline, each run (task × model × plugin combo × repetition) is\n * a step. Durations are the real `executionTimeMs`, so the Gantt view is\n * an honest wall-clock comparison and the DAG shows the run matrix.\n */\nimport type { RunEvent } from \"@sverka/runtime\";\nimport type { DefinitionGraph } from \"@sverka/workflow\";\nimport type { ReportContext } from \"@sverka/reporter\";\nimport { createHtmlRenderer } from \"@sverka/reporter\";\nimport type { ArenaResult, RunResult } from \"./types.js\";\n\nfunction comboLabel(result: RunResult): string {\n return result.pluginIds.length ? result.pluginIds.join(\"+\") : \"no-plugins\";\n}\n\n/** Stable per-run step id — readable in the DAG, Gantt and step list. */\nexport function runStepId(result: RunResult, rep: number): string {\n return `${result.taskId}/${result.modelId}/${comboLabel(result)}/r${rep}`;\n}\n\n/**\n * Repetition number within (task, model, combo) — the global matrix\n * index would label task B's first run \"r13\" in a wide matrix.\n */\nfunction repNumbers(results: readonly RunResult[]): Map<RunResult, number> {\n const counts = new Map<string, number>();\n const reps = new Map<RunResult, number>();\n for (const r of results) {\n const key = `${r.taskId} ${r.modelId} ${comboLabel(r)}`;\n const rep = (counts.get(key) ?? 0) + 1;\n counts.set(key, rep);\n reps.set(r, rep);\n }\n return reps;\n}\n\nconst SENSITIVE_KEY = /TOKEN|KEY|SECRET|PASSWORD|PASSWD|CREDENTIAL/i;\n\n/**\n * Best-effort secret scrub before run output lands in a public HTML.\n * Word-wise, no content regexes — a scanner-auditable shape.\n */\nfunction redact(text: string): string {\n const words = text.split(\" \");\n for (let i = 0; i < words.length; i++) {\n const w = words[i]!;\n const eqIdx = w.indexOf(\"=\");\n const colonIdx = w.indexOf(\":\");\n const sepIdx = Math.min(\n eqIdx === -1 ? w.length : eqIdx,\n colonIdx === -1 ? w.length : colonIdx,\n );\n if (sepIdx === w.length || sepIdx === 0) continue;\n const key = w.slice(0, sepIdx);\n if (!SENSITIVE_KEY.test(key)) continue;\n if (sepIdx === w.length - 1 && i + 1 < words.length) {\n // \"KEY=\" or \"KEY:\" alone — the value is the next word.\n words[i + 1] = \"[REDACTED]\";\n } else {\n words[i] = `${key}=[REDACTED]`;\n }\n }\n return words.join(\" \").replace(/Bearer\\s+\\S+/gi, \"Bearer [REDACTED]\");\n}\n\nfunction formatTokens(n: number): string {\n return n >= 1000 ? `${(n / 1000).toFixed(1)}k` : String(n);\n}\n\nfunction metricsLine(result: RunResult): string {\n const m = result.metrics;\n if (m === undefined) return \"no metrics recorded\";\n const judge = result.verdicts?.length\n ? `, judge ${Math.round(\n result.verdicts.reduce((a, v) => a + v.score, 0) /\n result.verdicts.length,\n )}`\n : \"\";\n return `${formatTokens(m.totalTokens)} tokens, ${m.toolCallCount} tool calls, ${m.llmCallCount} llm calls${judge}`;\n}\n\nfunction failureReason(result: RunResult): string {\n const failed = (result.checkResults ?? []).filter((c) => !c.passed);\n if (failed.length > 0) {\n return redact(\n failed\n .map((c) => `${c.checkId}: ${c.output || \"exit \" + c.exitCode}`)\n .join(\"; \"),\n );\n }\n return redact(result.error ?? \"run reported success=false\");\n}\n\n/**\n * One pipeline per task, one step per run — no edges, so the DAG renders\n * the matrix as a fan-out per task.\n */\nexport function arenaResultGraph(result: ArenaResult): DefinitionGraph {\n const byTask = new Map<string, { id: string; dependencies: never[] }[]>();\n const reps = repNumbers(result.results);\n for (const r of result.results) {\n const steps = byTask.get(r.taskId) ?? [];\n steps.push({ id: runStepId(r, reps.get(r)!), dependencies: [] });\n byTask.set(r.taskId, steps);\n }\n return {\n project: {\n id: \"arena\",\n pipelines: [...byTask].map(([taskId, steps]) => ({\n id: taskId,\n inputs: {},\n entries: [],\n steps,\n outputs: [],\n })),\n },\n } as unknown as DefinitionGraph;\n}\n\n/**\n * Convert the whole matrix into a RunEvent stream. Runs are laid out\n * serially — each starts when the previous ended — because arena\n * executes the matrix sequentially; the Gantt then reads as the real\n * wall-clock timeline and `run-completed` carries the honest total.\n */\nexport function arenaResultToEvents(result: ArenaResult): RunEvent[] {\n const events: RunEvent[] = [\n { type: \"run-started\", runId: \"arena\", planId: \"arena\", at: 0 },\n ];\n let t = 0;\n const reps = repNumbers(result.results);\n for (const r of result.results) {\n const stepId = runStepId(r, reps.get(r)!);\n const dur = Math.max(r.metrics?.executionTimeMs ?? 0, 0);\n const end = t + dur;\n events.push({ type: \"step-started\", stepId, at: t });\n events.push(...outcomeEvents(r, stepId, dur, end));\n events.push(...verdictEvents(r, stepId, end));\n t = end;\n }\n const anyFail = result.results.some((r) => !r.success);\n events.push({\n type: \"run-completed\",\n runId: \"arena\",\n status: anyFail ? \"failure\" : \"success\",\n durationMs: t,\n at: t,\n });\n return events;\n}\n\nfunction outcomeEvents(\n r: RunResult,\n stepId: string,\n dur: number,\n end: number,\n): RunEvent[] {\n const events: RunEvent[] = [];\n if (r.metrics?.executionTimeMs === undefined || dur === 0) {\n events.push({\n type: \"diagnostic\",\n stepId,\n severity: \"info\",\n message: \"no duration recorded — run failed before/without timing\",\n at: end,\n });\n }\n if (r.success) {\n events.push({\n type: \"step-succeeded\",\n stepId,\n durationMs: dur,\n stdout: metricsLine(r),\n at: end,\n });\n } else {\n events.push({\n type: \"step-failed\",\n stepId,\n error: failureReason(r),\n durationMs: dur,\n stdout: metricsLine(r),\n at: end,\n });\n }\n return events;\n}\n\nfunction verdictEvents(r: RunResult, stepId: string, end: number): RunEvent[] {\n return (r.verdicts ?? []).map((v) => ({\n type: \"diagnostic\" as const,\n stepId,\n severity: (v.passed ? \"info\" : \"warn\") as \"info\" | \"warn\",\n message: redact(\n `judge score ${v.score}${v.passed ? \"\" : \" (failed)\"}: ${v.reasoning}`,\n ),\n at: end,\n }));\n}\n\n/** Render the whole arena matrix as a standalone sverka HTML report. */\nexport function writeAggregateReport(\n result: ArenaResult,\n outputPath: string,\n context?: ReportContext,\n): void {\n const meta = [\n { label: \"models\", value: result.config.models.join(\", \") },\n { label: \"plugins\", value: result.config.plugins.join(\", \") },\n { label: \"tasks\", value: result.config.tasks.join(\", \") },\n { label: \"repetitions\", value: String(result.config.repetitions) },\n { label: \"runs\", value: String(result.results.length) },\n ...(result.config.judgeModel\n ? [{ label: \"judge\", value: result.config.judgeModel }]\n : []),\n ...(context?.meta ?? []),\n ];\n const renderer = createHtmlRenderer({\n outputPath,\n graph: arenaResultGraph(result),\n context: {\n title: \"arena aggregate\",\n generatedAt: result.timestamp ?? new Date().toISOString(),\n command: \"sverka-arena report --format html\",\n ...context,\n meta,\n },\n });\n for (const e of arenaResultToEvents(result)) renderer.onEvent(e);\n renderer.flush();\n}\n","/**\n * Internal git seam — the only place the arena spawns `git`. Tests mock\n * this module (vi.mock) to script push conflicts deterministically; it is\n * deliberately not exported from the package index.\n */\nimport { execFile } from \"node:child_process\";\n\nexport interface GitResult {\n readonly code: number;\n readonly stdout: string;\n readonly stderr: string;\n}\n\nconst MAX_BUFFER = 8 * 1024 * 1024;\n\n/** Run `git <args>`; resolves with the exit code, never rejects on non-zero. */\nexport function git(\n args: readonly string[],\n opts: { cwd?: string; env?: Record<string, string> } = {},\n): Promise<GitResult> {\n return new Promise((resolve, reject) => {\n execFile(\n \"git\", // NOSONAR — fixed binary, args never interpolated into a shell\n [...args],\n {\n cwd: opts.cwd,\n env: { ...process.env, ...opts.env },\n maxBuffer: MAX_BUFFER,\n },\n (error, stdout, stderr) => {\n // Spawn failures (ENOENT), aborts, and signal kills report a\n // non-numeric error.code — the process never exited, so reject.\n if (error !== null && typeof error.code !== \"number\") {\n reject(error);\n return;\n }\n resolve({\n code: typeof error?.code === \"number\" ? error.code : 0,\n stdout: String(stdout),\n stderr: String(stderr),\n });\n },\n );\n });\n}\n\n/** Args carrying credentials must never reach an error message (CWE-209). */\nfunction redactArgs(args: readonly string[]): string {\n return args\n .map((a) =>\n /authorization|bearer|credential|token=/i.test(a) ? \"<redacted>\" : a,\n )\n .join(\" \");\n}\n\n/** Run `git <args>`; throws a plain Error with stderr context on non-zero. */\nexport async function gitOrThrow(\n args: readonly string[],\n opts: { cwd?: string; env?: Record<string, string> } = {},\n): Promise<GitResult> {\n const res = await git(args, opts);\n if (res.code !== 0) {\n throw new Error(\n `git ${redactArgs(args)} failed (exit ${res.code}): ${res.stderr.trim()}`,\n );\n }\n return res;\n}\n","/**\n * Arena results registry — `arena.result/v1` documents committed to an\n * append-only store, plus the `ArenaRegistry` read/write contract.\n * Spec: specs/56-arena-eval-service.\n *\n * Registry tree layout:\n *\n * results/<pack>/<agent>/<YYYY-MM-DD>/<runId>.json\n * traces/<runId>/<task>.<run-index>.trace.jsonl\n * packs/<name>/pack.json + tasks/*.json\n * index.json — denormalized pack → runs; readers\n * never scan the results/ tree\n *\n * Backends: file (local dir — a git checkout or plain tree), git\n * (clone → write → commit → push), s3 (put-object via an injectable\n * client — no AWS SDK dependency in tests).\n */\nimport { createHash } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { chmod, mkdir, readFile, readdir, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { basename, join, resolve } from \"node:path\";\nimport { z } from \"zod\";\n\nimport { ArenaError } from \"./config.js\";\nimport { git, gitOrThrow } from \"./internal/git.js\";\n\n// ─── arena.result/v1 ─────────────────────────────────────────────────\n\nexport interface TaskResult {\n readonly task: string;\n /** sha256 of the task prompt — a prompt edit breaks comparability. */\n readonly promptHash: string;\n readonly score: { readonly passed: boolean; readonly findings: number };\n readonly metrics: {\n readonly tokens?: number;\n readonly toolCalls?: number;\n readonly durationMs: number;\n readonly stopReason?: string;\n };\n readonly traceRef?: string;\n}\n\nexport interface ArenaResultV1 {\n readonly schema: \"arena.result/v1\";\n readonly runId: string;\n readonly pack: string;\n readonly agent: string;\n readonly model: string;\n readonly plugins: readonly string[];\n readonly sverkaVersion: string;\n readonly startedAt: string;\n readonly tasks: readonly TaskResult[];\n}\n\nconst taskResultSchema = z.object({\n task: z.string().min(1),\n promptHash: z.string().regex(/^[0-9a-f]{64}$/),\n score: z.object({\n passed: z.boolean(),\n findings: z.number().int().nonnegative(),\n }),\n metrics: z.object({\n tokens: z.number().optional(),\n toolCalls: z.number().optional(),\n durationMs: z.number(),\n stopReason: z.string().optional(),\n }),\n traceRef: z.string().optional(),\n});\n\nexport const arenaResultV1Schema = z.object({\n schema: z.literal(\"arena.result/v1\"),\n runId: z.string().min(1),\n pack: z.string().min(1),\n agent: z.string().min(1),\n model: z.string().min(1),\n plugins: z.array(z.string()),\n sverkaVersion: z.string().min(1),\n startedAt: z.iso.datetime(),\n tasks: z.array(taskResultSchema),\n});\n\n/** Validate a parsed value as arena.result/v1 — names failing fields. */\nexport function parseArenaResultV1(doc: unknown): ArenaResultV1 {\n const parsed = arenaResultV1Schema.safeParse(doc);\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((i) => ` ${i.path.join(\".\") || \"(root)\"}: ${i.message}`)\n .join(\"\\n\");\n throw new ArenaError(\n `invalid arena.result/v1 document:\\n${issues}`,\n \"SCHEMA_INVALID\",\n );\n }\n return parsed.data as ArenaResultV1;\n}\n\n/** Registry path segments must not escape or nest the layout. */\nfunction checkSegment(value: string, field: string): void {\n if (\n !/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(value) ||\n value === \".\" ||\n value === \"..\"\n ) {\n throw new ArenaError(\n `invalid ${field} '${value}' — registry path segments must match [a-zA-Z0-9._-]+ and not start with a dot`,\n \"SCHEMA_INVALID\",\n );\n }\n}\n\n/** Canonical result path: results/<pack>/<agent>/<YYYY-MM-DD>/<runId>.json */\nexport function resultPath(doc: ArenaResultV1, date?: string): string {\n checkSegment(doc.pack, \"pack\");\n checkSegment(doc.agent, \"agent\");\n checkSegment(doc.runId, \"runId\");\n const day = date ?? doc.startedAt.slice(0, 10);\n // The partition lands inside a filesystem path — a date override must\n // be a strict YYYY-MM-DD, never a traversal like \"../../tmp/out\".\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(day)) {\n throw new ArenaError(\n `invalid date partition '${day}' — expected YYYY-MM-DD`,\n \"SCHEMA_INVALID\",\n );\n }\n return `results/${doc.pack}/${doc.agent}/${day}/${doc.runId}.json`;\n}\n\n/** sha256 of a task prompt — the comparability cohort key. */\nexport function promptHash(prompt: string): string {\n return createHash(\"sha256\").update(prompt, \"utf8\").digest(\"hex\");\n}\n\n// ─── ArenaRegistry ───────────────────────────────────────────────────\n\n/** A trace payload: a filesystem path to copy, or inline data. */\nexport type TraceInput = string | { name: string; data: unknown };\n\nexport interface PublishOptions {\n /** Trace files/payloads — written under traces/<runId>/<name>. */\n traces?: readonly TraceInput[];\n /** Override the YYYY-MM-DD partition (default: startedAt day). */\n date?: string;\n}\n\nexport interface ListQuery {\n pack?: string;\n agent?: string;\n /** ISO date/datetime lower bound on startedAt (inclusive). */\n since?: string;\n}\n\nexport interface ArenaRegistry {\n publish(result: ArenaResultV1, opts?: PublishOptions): Promise<string>;\n list(query?: ListQuery): Promise<ArenaResultV1[]>;\n}\n\n// ─── Tree backends (internal) ────────────────────────────────────────\n\n/** Uniform read/write view over the registry tree per backend. */\ninterface TreeStore {\n readFile(rel: string): Promise<string | null>;\n writeFile(rel: string, data: string): Promise<void>;\n /** Relative posix paths under relPrefix, recursive. */\n listFiles(relPrefix: string): Promise<string[]>;\n /**\n * Re-sync remote state before a read operation — the git backend\n * re-pulls (its clone is memoized, so without this a long-lived\n * registry never sees pushes that landed after first access).\n * File/s3 backends don't implement it.\n */\n refresh?(): Promise<void>;\n /** Commit/publish pending writes — git commits + pushes; others no-op. */\n finalize(message: string): Promise<void>;\n}\n\nconst registries = new WeakMap<ArenaRegistry, TreeStore>();\n\nfunction createFileTree(dir: string): TreeStore {\n const unavailable = (what: string, cause: unknown): ArenaError =>\n new ArenaError(\n `registry unavailable — ${what} under ${dir}`,\n \"REGISTRY_UNAVAILABLE\",\n cause,\n );\n return {\n async readFile(rel) {\n try {\n return await readFile(join(dir, rel), \"utf8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw unavailable(`cannot read ${rel}`, err);\n }\n },\n async writeFile(rel, data) {\n const target = join(dir, rel);\n try {\n await mkdir(join(target, \"..\"), { recursive: true });\n // 0o600 — registry roots may live under tmpdir(); keep the\n // created file owner-only (CodeQL js/insecure-temporary-file).\n await writeFile(target, data, { encoding: \"utf8\", mode: 0o600 });\n } catch (err) {\n throw unavailable(`cannot write ${rel}`, err);\n }\n },\n async listFiles(relPrefix) {\n const out: string[] = [];\n const walk = async (rel: string): Promise<void> => {\n let entries;\n try {\n entries = await readdir(join(dir, rel), { withFileTypes: true });\n } catch (err) {\n // Only ENOENT means \"empty subtree\" — permission or I/O\n // failures must surface (a silent empty list would let\n // `reindex` overwrite index.json with nothing).\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return;\n throw unavailable(`cannot list ${rel}`, err);\n }\n for (const e of entries) {\n const child = rel === \"\" ? e.name : `${rel}/${e.name}`;\n if (e.isDirectory()) await walk(child);\n else if (e.isFile()) out.push(child);\n }\n };\n await walk(relPrefix);\n return out;\n },\n async finalize() {},\n };\n}\n\n// ─── Git backend ─────────────────────────────────────────────────────\n\nexport interface GitRegistryConfig {\n /** Clone URL — https or git@. */\n url: string;\n /** Branch to publish on (default: \"main\"). */\n branch?: string;\n /** Local checkout dir (default: a tmp cache keyed by URL). */\n dir?: string;\n /** Bearer token for https remotes (header-scoped, never persisted). */\n token?: string;\n}\n\nfunction gitRegistryDir(cfg: GitRegistryConfig): string {\n return (\n cfg.dir ??\n join(\n tmpdir(),\n `arena-registry-${createHash(\"sha256\").update(cfg.url).digest(\"hex\").slice(0, 12)}`,\n )\n );\n}\n\n/**\n * Auth is injected through GIT_CONFIG_* env vars, never argv — a\n * `-c http.extraHeader=...` argument would expose the bearer token to\n * other users on the host via the process list (CWE-214).\n */\nfunction gitAuthEnv(cfg: GitRegistryConfig): Record<string, string> {\n return cfg.token !== undefined && /^https?:\\/\\//.test(cfg.url)\n ? {\n GIT_CONFIG_COUNT: \"1\",\n GIT_CONFIG_KEY_0: \"http.extraHeader\",\n GIT_CONFIG_VALUE_0: `AUTHORIZATION: bearer ${cfg.token}`,\n }\n : {};\n}\n\nconst gitUnavailable =\n (cfg: GitRegistryConfig, dir: string) =>\n (what: string, cause: unknown): ArenaError =>\n new ArenaError(\n `registry unavailable — ${what} (${cfg.url} → ${dir})`,\n \"REGISTRY_UNAVAILABLE\",\n cause,\n );\n\nconst checkouts = new Map<string, Promise<void>>();\n\n/**\n * Clone-or-refresh a git registry checkout (memoized per dir). Soft on\n * refresh when a checkout exists — a stale local view stays readable;\n * publish does its own pull --rebase anyway.\n */\nfunction ensureGitCheckout(cfg: GitRegistryConfig): Promise<void> {\n const dir = gitRegistryDir(cfg);\n const branch = cfg.branch ?? \"main\";\n const auth = gitAuthEnv(cfg);\n const unavailable = gitUnavailable(cfg, dir);\n let p = checkouts.get(dir);\n if (p === undefined) {\n p = (async () => {\n if (cfg.dir === undefined) {\n // The auto-derived tmpdir path is predictable — keep it\n // owner-only so results/credentials stay private (CWE-377).\n await mkdir(dir, { recursive: true, mode: 0o700 });\n await chmod(dir, 0o700);\n }\n if (existsSync(join(dir, \".git\"))) {\n // A checkout left mid-rebase (a killed publish, or a version\n // before abort-on-failure) poisons every later git op here.\n if (\n existsSync(join(dir, \".git\", \"rebase-merge\")) ||\n existsSync(join(dir, \".git\", \"rebase-apply\"))\n ) {\n await git([\"-C\", dir, \"rebase\", \"--abort\"], { env: auth });\n }\n // fetch alone only moves origin/<branch>; the worktree stays at\n // the clone-time commit and list/board read stale results\n // forever. pull --ff-only refreshes it — a checkout holding\n // unpublished commits (a failed publish) can't ff and stays\n // as-is; publish's own pull --rebase reconciles it. Only when\n // HEAD is the registry branch: ff-ing some other checked-out\n // branch would silently move it.\n const head = await git(\n [\"-C\", dir, \"symbolic-ref\", \"-q\", \"--short\", \"HEAD\"],\n { env: auth },\n );\n if (head.code === 0 && head.stdout.trim() === branch) {\n await git([\"-C\", dir, \"pull\", \"--ff-only\", \"origin\", branch], {\n env: auth,\n });\n }\n return;\n }\n try {\n await gitOrThrow(\n [\n \"clone\",\n ...(cfg.branch !== undefined ? [\"--branch\", cfg.branch] : []),\n cfg.url,\n dir,\n ],\n { env: auth },\n );\n } catch (err) {\n throw unavailable(`git clone failed`, err);\n }\n })();\n checkouts.set(dir, p);\n // A failed clone must not poison the memo — retry next call. The\n // identity check keeps a concurrent fresh entry from being removed.\n p.catch(() => {\n if (checkouts.get(dir) === p) checkouts.delete(dir);\n });\n }\n return p;\n}\n\nconst GIT_IDENTITY = [\n \"-c\",\n \"user.name=sverka-arena\",\n \"-c\",\n \"user.email=arena@sverka.dev\",\n];\n\nconst gitOps = new Map<string, Promise<unknown>>();\n\n/**\n * Serialize git-mutating operations per checkout dir — a refresh pull\n * racing publish's add/commit would fail on index.lock, and a stopped\n * rebase observed under the lock is dead (a live one holds the queue\n * through finalize), so the holder may safely abort it.\n */\nfunction serializedGitOp<T>(dir: string, fn: () => Promise<T>): Promise<T> {\n const run = (gitOps.get(dir) ?? Promise.resolve()).then(fn);\n gitOps.set(\n dir,\n run.then(\n () => undefined,\n () => undefined,\n ),\n );\n return run;\n}\n\nfunction createGitTree(cfg: GitRegistryConfig): TreeStore & { dir: string } {\n const dir = gitRegistryDir(cfg);\n const branch = cfg.branch ?? \"main\";\n const auth = gitAuthEnv(cfg);\n const inner = createFileTree(dir);\n const unavailable = gitUnavailable(cfg, dir);\n const ensure = (): Promise<void> => ensureGitCheckout(cfg);\n\n const rebaseInProgress = (): boolean =>\n existsSync(join(dir, \".git\", \"rebase-merge\")) ||\n existsSync(join(dir, \".git\", \"rebase-apply\"));\n\n /**\n * Best-effort re-sync before a read — one `pull --ff-only` per call,\n * serialized against publish's git ops on this checkout. Every step\n * is soft: a stopped rebase found here is dead (a live publish holds\n * the queue) so it's aborted; a non-ff/dirty/offline pull just leaves\n * the stale view, which stays readable — publish reconciles through\n * its own pull --rebase.\n */\n async function refresh(): Promise<void> {\n await serializedGitOp(dir, async () => {\n await ensure(); // a failed clone is real unavailability — throws\n if (rebaseInProgress()) {\n await git([\"-C\", dir, \"rebase\", \"--abort\"], { env: auth });\n }\n const head = await git(\n [\"-C\", dir, \"symbolic-ref\", \"-q\", \"--short\", \"HEAD\"],\n { env: auth },\n );\n if (head.code === 0 && head.stdout.trim() === branch) {\n await git([\"-C\", dir, \"pull\", \"--ff-only\", \"origin\", branch], {\n env: auth,\n });\n }\n });\n }\n\n /**\n * Recover a stopped rebase. Two publishers racing always collide on\n * index.json — each commit rewrites it — while result/trace paths are\n * per-run and never conflict. index.json is a pure function of the\n * results/ tree (reindex semantics), so a conflicted rebase whose only\n * unmerged path is index.json is resolved by regenerating it and\n * continuing. Anything else is a real conflict: give up and let the\n * caller abort.\n */\n async function resolveRebaseConflicts(): Promise<boolean> {\n // Each round resolves exactly one stopped commit — the only\n // tolerated conflict is index.json, regenerated from the merged\n // results/ tree — so the loop is bounded by the number of commits\n // the rebase replays. No fixed cap: a checkout holding many\n // unpublished commits (repeated PUBLISH_CONFLICTs) is still\n // resolvable.\n while (rebaseInProgress()) {\n const unmerged = await git(\n [\"-C\", dir, \"diff\", \"--name-only\", \"--diff-filter=U\"],\n { env: auth },\n );\n if (unmerged.code !== 0) return false;\n const paths = unmerged.stdout.split(\"\\n\").filter((l) => l !== \"\");\n if (paths.length === 0 || paths.some((p) => p !== INDEX_PATH)) {\n return false;\n }\n const { index } = await buildIndex(inner);\n await writeIndex(inner, index);\n const add = await git([\"-C\", dir, \"add\", \"--\", INDEX_PATH], {\n env: auth,\n });\n if (add.code !== 0) return false;\n // --continue either finishes the rebase or stops at the next\n // conflicted commit — the loop re-checks unmerged paths.\n await git([\"-C\", dir, ...GIT_IDENTITY, \"rebase\", \"--continue\"], {\n env: { ...auth, GIT_EDITOR: \"true\" },\n });\n }\n return !rebaseInProgress();\n }\n\n async function pullRebase(): Promise<void> {\n // Rebase replays our commit — it needs a committer identity too, and\n // hosts without a global gitconfig (CI) have none.\n const res = await git(\n [\"-C\", dir, ...GIT_IDENTITY, \"pull\", \"--rebase\", \"origin\", branch],\n { env: auth },\n );\n if (res.code === 0) return;\n if (!rebaseInProgress()) {\n // The pull failed before any rebase started (fetch/auth/network).\n throw unavailable(`git pull --rebase failed`, res.stderr.trim());\n }\n const resolved = await resolveRebaseConflicts().catch(() => false);\n if (!resolved) {\n // A failed rebase must never be left in place — a mid-rebase\n // checkout poisons every later git op in this dir.\n await git([\"-C\", dir, \"rebase\", \"--abort\"], { env: auth });\n throw unavailable(`git pull --rebase failed`, res.stderr.trim());\n }\n }\n\n async function push(): Promise<ReturnType<typeof git>> {\n return git([\"-C\", dir, \"push\", \"origin\", `HEAD:${branch}`], {\n env: auth,\n });\n }\n\n return {\n dir,\n async readFile(rel) {\n await ensure();\n return inner.readFile(rel);\n },\n async writeFile(rel, data) {\n await ensure();\n return inner.writeFile(rel, data);\n },\n async listFiles(relPrefix) {\n await ensure();\n return inner.listFiles(relPrefix);\n },\n refresh,\n async finalize(message) {\n // Serialized with refresh — a pull must never interleave with\n // add/commit/rebase on this checkout.\n await serializedGitOp(dir, async () => {\n await ensure();\n try {\n await gitOrThrow([\"-C\", dir, \"add\", \"-A\"]);\n } catch (err) {\n throw unavailable(`git add failed`, err);\n }\n const staged = await git([\"-C\", dir, \"diff\", \"--cached\", \"--quiet\"]);\n if (staged.code === 0) return; // nothing to commit\n try {\n await gitOrThrow([\n \"-C\",\n dir,\n ...GIT_IDENTITY,\n \"commit\",\n \"-m\",\n message,\n ]);\n } catch (err) {\n throw unavailable(`git commit failed`, err);\n }\n let res = await push();\n if (res.code !== 0) {\n // Non-fast-forward (or auth failure indistinguishable from it):\n // one rebase retry — results are append-only, never force-pushed.\n await pullRebase();\n res = await push();\n if (res.code !== 0) {\n throw new ArenaError(\n `publish rejected — git push to '${cfg.url}' failed after rebase retry; ` +\n `results are preserved in the local checkout at ${dir}`,\n \"PUBLISH_CONFLICT\",\n res.stderr.trim(),\n );\n }\n }\n });\n },\n };\n}\n\nexport function createGitRegistry(cfg: GitRegistryConfig): ArenaRegistry {\n const tree = createGitTree(cfg);\n const registry = createRegistry(tree);\n registries.set(registry, tree);\n return registry;\n}\n\n// ─── S3 backend ──────────────────────────────────────────────────────\n\n/** Minimal structural subset of the AWS SDK S3 client we depend on. */\nexport interface S3ClientLike {\n putObject(input: {\n Bucket: string;\n Key: string;\n Body: string | Uint8Array;\n }): Promise<unknown>;\n getObject?(input: { Bucket: string; Key: string }): Promise<{\n Body?: unknown;\n }>;\n listObjectsV2?(input: {\n Bucket: string;\n Prefix?: string;\n ContinuationToken?: string;\n }): Promise<{\n Contents?: { Key?: string }[];\n IsTruncated?: boolean;\n NextContinuationToken?: string;\n }>;\n}\n\nexport interface S3RegistryConfig {\n bucket: string;\n /** Key prefix for the whole registry tree (default: \"\"). */\n prefix?: string;\n /** Client — injectable so tests need no AWS SDK. When omitted, the\n * optional `@aws-sdk/client-s3` peer is imported lazily. */\n client?: S3ClientLike;\n}\n\ntype AwsS3Ctor = new (cfg: Record<string, never>) => S3ClientLike;\n\n/** Computed specifier — keeps the optional AWS peer out of the dep graph. */\nconst S3_SDK_MODULE = \"@aws-sdk/client-s3\";\n\nasync function defaultS3Client(): Promise<S3ClientLike> {\n try {\n const mod = (await import(S3_SDK_MODULE)) as {\n S3Client: AwsS3Ctor;\n };\n return new mod.S3Client({});\n } catch (err) {\n throw new ArenaError(\n `s3 registry requires a client — install @aws-sdk/client-s3 or pass { client }`,\n \"REGISTRY_UNAVAILABLE\",\n err,\n );\n }\n}\n\nasync function s3BodyToString(body: unknown): Promise<string> {\n if (body === undefined || body === null) return \"\";\n if (typeof body === \"string\") return body;\n if (body instanceof Uint8Array) return new TextDecoder().decode(body);\n if (\n typeof (body as { transformToString?: unknown }).transformToString ===\n \"function\"\n ) {\n return (\n body as { transformToString(): Promise<string> }\n ).transformToString();\n }\n if (\n typeof (body as AsyncIterable<Uint8Array>)[Symbol.asyncIterator] ===\n \"function\"\n ) {\n const chunks: Uint8Array[] = [];\n for await (const c of body as AsyncIterable<Uint8Array>) chunks.push(c);\n return new TextDecoder().decode(\n chunks.reduce((a, c) => {\n const n = new Uint8Array(a.length + c.length);\n n.set(a);\n n.set(c, a.length);\n return n;\n }, new Uint8Array(0)),\n );\n }\n throw new ArenaError(\n \"s3 registry: unsupported getObject Body type\",\n \"REGISTRY_UNAVAILABLE\",\n );\n}\n\n/** Strip trailing '/' without a regex — a `\\/+$` match on a hostile\n * prefix (many trailing slashes + a non-slash tail) backtracks\n * quadratically (CodeQL js/polynomial-redos). */\nfunction stripTrailingSlashes(s: string): string {\n let end = s.length;\n while (end > 0 && s.codePointAt(end - 1) === 47) end--;\n return s.slice(0, end);\n}\n\nfunction createS3Tree(cfg: S3RegistryConfig): TreeStore {\n const stripped =\n cfg.prefix === undefined ? \"\" : stripTrailingSlashes(cfg.prefix);\n const prefix = stripped === \"\" ? \"\" : `${stripped}/`;\n let clientP: Promise<S3ClientLike> | undefined;\n const client = (): Promise<S3ClientLike> => {\n clientP ??=\n cfg.client !== undefined\n ? Promise.resolve(cfg.client)\n : defaultS3Client();\n return clientP;\n };\n const unavailable = (what: string, cause: unknown): ArenaError =>\n new ArenaError(\n `s3 registry unavailable — ${what}`,\n \"REGISTRY_UNAVAILABLE\",\n cause,\n );\n\n return {\n async readFile(rel) {\n const c = await client();\n if (c.getObject === undefined) {\n throw unavailable(`client has no getObject`, undefined);\n }\n try {\n const res = await c.getObject({\n Bucket: cfg.bucket,\n Key: prefix + rel,\n });\n return await s3BodyToString(res?.Body);\n } catch (err) {\n const name = (err as { name?: string }).name ?? \"\";\n if (name === \"NoSuchKey\" || name === \"NotFound\") return null;\n if (err instanceof ArenaError) throw err;\n throw unavailable(`getObject ${rel} failed`, err);\n }\n },\n async writeFile(rel, data) {\n const c = await client();\n try {\n await c.putObject({\n Bucket: cfg.bucket,\n Key: prefix + rel,\n Body: data,\n });\n } catch (err) {\n throw unavailable(`putObject ${rel} failed`, err);\n }\n },\n async listFiles(relPrefix) {\n const c = await client();\n if (c.listObjectsV2 === undefined) {\n throw unavailable(`client has no listObjectsV2`, undefined);\n }\n const out: string[] = [];\n let token: string | undefined;\n try {\n do {\n const page = await c.listObjectsV2({\n Bucket: cfg.bucket,\n Prefix: prefix + relPrefix,\n ...(token !== undefined ? { ContinuationToken: token } : {}),\n });\n for (const obj of page.Contents ?? []) {\n if (obj.Key !== undefined) out.push(obj.Key.slice(prefix.length));\n }\n token =\n page.IsTruncated === true ? page.NextContinuationToken : undefined;\n } while (token !== undefined);\n } catch (err) {\n throw unavailable(`listObjectsV2 failed`, err);\n }\n return out;\n },\n async finalize() {},\n };\n}\n\nexport function createS3Registry(cfg: S3RegistryConfig): ArenaRegistry {\n const tree = createS3Tree(cfg);\n const registry = createRegistry(tree);\n registries.set(registry, tree);\n return registry;\n}\n\n// ─── File backend ────────────────────────────────────────────────────\n\n/** Registry over a local directory — a git checkout or a plain tree. */\nexport function createFileRegistry(dir: string): ArenaRegistry {\n const tree = createFileTree(resolve(dir));\n const registry = createRegistry(tree);\n registries.set(registry, tree);\n return registry;\n}\n\n// ─── Generic registry over a tree ────────────────────────────────────\n\ninterface IndexRun {\n runId: string;\n agent: string;\n date: string;\n path: string;\n}\n\ninterface RegistryIndex {\n schema: \"arena.index/v1\";\n updatedAt: string;\n packs: Record<string, { runs: IndexRun[] }>;\n}\n\nconst INDEX_PATH = \"index.json\";\n\nasync function readIndex(tree: TreeStore): Promise<RegistryIndex> {\n const raw = await tree.readFile(INDEX_PATH);\n if (raw === null) {\n return { schema: \"arena.index/v1\", updatedAt: \"\", packs: {} };\n }\n try {\n const parsed = JSON.parse(raw) as RegistryIndex;\n if (\n parsed.schema !== \"arena.index/v1\" ||\n typeof parsed.packs !== \"object\" ||\n parsed.packs === null\n ) {\n return { schema: \"arena.index/v1\", updatedAt: \"\", packs: {} };\n }\n return parsed;\n } catch {\n return { schema: \"arena.index/v1\", updatedAt: \"\", packs: {} };\n }\n}\n\nasync function writeIndex(\n tree: TreeStore,\n index: RegistryIndex,\n): Promise<void> {\n index.updatedAt = new Date().toISOString();\n await tree.writeFile(INDEX_PATH, JSON.stringify(index, null, 2) + \"\\n\");\n}\n\n/** Own-property lookup — \"constructor\" is a valid pack name. */\nfunction indexPack(\n index: RegistryIndex,\n name: string,\n): { runs: IndexRun[] } | undefined {\n return Object.hasOwn(index.packs, name) ? index.packs[name] : undefined;\n}\n\nfunction compareIndexRuns(a: IndexRun, b: IndexRun): number {\n if (a.date !== b.date) return a.date < b.date ? -1 : 1;\n if (a.runId !== b.runId) return a.runId < b.runId ? -1 : 1;\n return 0;\n}\n\nasync function updateIndex(\n tree: TreeStore,\n doc: ArenaResultV1,\n relPath: string,\n): Promise<void> {\n const index = await readIndex(tree);\n const date = relPath.split(\"/\")[3] ?? doc.startedAt.slice(0, 10);\n const pack = indexPack(index, doc.pack) ?? { runs: [] };\n pack.runs = [\n ...pack.runs.filter((r) => r.runId !== doc.runId),\n { runId: doc.runId, agent: doc.agent, date, path: relPath },\n ];\n pack.runs.sort(compareIndexRuns);\n index.packs[doc.pack] = pack;\n await writeIndex(tree, index);\n}\n\nfunction matchesQuery(doc: ArenaResultV1, query: ListQuery): boolean {\n if (query.pack !== undefined && doc.pack !== query.pack) return false;\n if (query.agent !== undefined && doc.agent !== query.agent) return false;\n // Compare instants, not strings — \"01:00+02:00\" sorts after \"00:00Z\"\n // lexically but is the earlier instant. Unparsable input falls back\n // to including the row (NaN comparisons are false).\n if (\n query.since !== undefined &&\n Date.parse(doc.startedAt) < Date.parse(query.since)\n ) {\n return false;\n }\n return true;\n}\n\nfunction tryParseResult(raw: string | null): ArenaResultV1 | null {\n if (raw === null) return null;\n try {\n const doc = JSON.parse(raw) as { schema?: string };\n if (doc?.schema !== \"arena.result/v1\") return null;\n return parseArenaResultV1(doc);\n } catch {\n return null; // a stray bad file must not break readers\n }\n}\n\nasync function writeResult(\n tree: TreeStore,\n doc: ArenaResultV1,\n opts: PublishOptions,\n): Promise<string> {\n const valid = parseArenaResultV1(doc);\n const rel = resultPath(valid, opts.date);\n await tree.writeFile(rel, JSON.stringify(valid, null, 2) + \"\\n\");\n for (const trace of opts.traces ?? []) {\n const name =\n typeof trace === \"string\" ? basename(trace) : basename(trace.name);\n checkSegment(name.replace(/\\.[^.]+$/, \"\"), \"trace name\");\n const data =\n typeof trace === \"string\"\n ? await readFile(trace, \"utf8\")\n : JSON.stringify(trace.data) + \"\\n\"; // single-line — .trace.jsonl stays valid JSONL\n await tree.writeFile(`traces/${valid.runId}/${name}`, data);\n }\n await updateIndex(tree, valid, rel);\n return rel;\n}\n\n/**\n * Publish several documents under ONE finalize — a matrix explosion\n * produces one commit+push, not N. Internal: package code only.\n */\nexport async function publishBatch(\n registry: ArenaRegistry,\n docs: readonly { doc: ArenaResultV1; opts?: PublishOptions }[],\n message: string,\n): Promise<string[]> {\n const tree = registries.get(registry);\n if (tree === undefined) {\n // Foreign registry — fall back to per-doc publish.\n const paths: string[] = [];\n for (const { doc, opts } of docs)\n paths.push(await registry.publish(doc, opts));\n return paths;\n }\n const paths: string[] = [];\n for (const { doc, opts } of docs) {\n paths.push(await writeResult(tree, doc, opts ?? {}));\n }\n await tree.finalize(message);\n return paths;\n}\n\nfunction createRegistry(tree: TreeStore): ArenaRegistry {\n return {\n async publish(result, opts = {}) {\n // No refresh here: publishing off a stale checkout surfaces\n // same-path rewrites as a rebase conflict (REGISTRY_UNAVAILABLE)\n // rather than silently last-writer-wins.\n const rel = await writeResult(tree, result, opts);\n await tree.finalize(\n `arena: publish ${result.pack}/${result.agent}/${result.runId}`,\n );\n return rel;\n },\n async list(query = {}) {\n await tree.refresh?.();\n const out: ArenaResultV1[] = [];\n const index = await readIndex(tree);\n const packEntries =\n query.pack !== undefined\n ? ([[query.pack, indexPack(index, query.pack)]] as const)\n : Object.entries(index.packs);\n if (packEntries.some(([, v]) => v !== undefined)) {\n for (const [pack, entry] of packEntries) {\n if (entry === undefined) continue;\n for (const run of entry.runs) {\n const doc = tryParseResult(await tree.readFile(run.path));\n if (doc !== null && doc.pack === pack && matchesQuery(doc, query)) {\n out.push(doc);\n }\n }\n }\n } else {\n // No index — scan the results/ tree (fixture registries).\n for (const rel of await tree.listFiles(\"results/\")) {\n if (!rel.endsWith(\".json\")) continue;\n const doc = tryParseResult(await tree.readFile(rel));\n if (doc !== null && matchesQuery(doc, query)) out.push(doc);\n }\n }\n out.sort((a, b) => (a.startedAt < b.startedAt ? -1 : 1));\n return out;\n },\n };\n}\n\n/**\n * Build index.json by scanning the results/ tree — the shared\n * denormalization pass behind `reindex` and the git backend's\n * index-conflict resolution.\n */\nasync function buildIndex(\n tree: TreeStore,\n): Promise<{ index: RegistryIndex; runs: number }> {\n const index: RegistryIndex = {\n schema: \"arena.index/v1\",\n updatedAt: \"\",\n packs: {},\n };\n let runs = 0;\n for (const rel of await tree.listFiles(\"results/\")) {\n if (!rel.endsWith(\".json\")) continue;\n const doc = tryParseResult(await tree.readFile(rel));\n if (doc === null) continue;\n const parts = rel.split(\"/\");\n const pack = indexPack(index, doc.pack) ?? { runs: [] };\n pack.runs.push({\n runId: doc.runId,\n agent: doc.agent,\n date: parts[3] ?? doc.startedAt.slice(0, 10),\n path: rel,\n });\n index.packs[doc.pack] = pack;\n runs++;\n }\n for (const pack of Object.values(index.packs)) {\n pack.runs.sort(compareIndexRuns);\n }\n return { index, runs };\n}\n\n/**\n * Rebuild index.json by scanning the results/ tree — the CI job that\n * denormalizes after publish pushes (`arena reindex`).\n */\nexport async function reindexRegistry(\n registry: ArenaRegistry,\n): Promise<{ runs: number }> {\n const tree = registries.get(registry);\n if (tree === undefined) {\n throw new ArenaError(\n \"reindex: registry was not created by @sverka/arena\",\n \"REGISTRY_UNAVAILABLE\",\n );\n }\n // Re-sync first — a memoized checkout would index a stale tree.\n await tree.refresh?.();\n const { index, runs } = await buildIndex(tree);\n await writeIndex(tree, index);\n await tree.finalize(\"arena: reindex\");\n return { runs };\n}\n\n/**\n * Resolve a registry reference to an ArenaRegistry:\n * s3://bucket[/prefix] → s3 backend\n * file:///abs/path | ./dir → file backend\n * git::<url> | <git-url> → git backend\n */\nexport function openRegistry(\n ref: string,\n opts: { token?: string; dir?: string; client?: S3ClientLike } = {},\n): ArenaRegistry {\n if (ref.startsWith(\"s3://\")) {\n const rest = ref.slice(\"s3://\".length);\n const slash = rest.indexOf(\"/\");\n const bucket = slash === -1 ? rest : rest.slice(0, slash);\n const prefix = slash === -1 ? undefined : rest.slice(slash + 1);\n return createS3Registry({\n bucket,\n ...(prefix !== undefined && prefix !== \"\" ? { prefix } : {}),\n ...(opts.client !== undefined ? { client: opts.client } : {}),\n });\n }\n const gitRef = ref.startsWith(\"git::\") ? ref.slice(5) : ref;\n if (\n /^https?:\\/\\//.test(gitRef) ||\n gitRef.startsWith(\"git@\") ||\n /^(?:ssh|git):\\/\\//.test(gitRef) ||\n gitRef.endsWith(\".git\")\n ) {\n return createGitRegistry({\n url: gitRef,\n ...(opts.token !== undefined ? { token: opts.token } : {}),\n ...(opts.dir !== undefined ? { dir: opts.dir } : {}),\n });\n }\n const path = ref.startsWith(\"file://\") ? ref.slice(7) : ref;\n return createFileRegistry(path);\n}\n\n/**\n * Resolve a registry ref to a local directory — file refs return their\n * path, git refs return the (cloned) checkout dir. s3 registries have no\n * local dir — callers that need one must error themselves.\n */\nexport async function resolveRegistryDir(\n ref: string,\n opts: { token?: string; dir?: string } = {},\n): Promise<string> {\n if (ref.startsWith(\"s3://\")) {\n throw new ArenaError(\n `s3 registry '${ref}' has no local directory`,\n \"REGISTRY_UNAVAILABLE\",\n );\n }\n const gitRef = ref.startsWith(\"git::\") ? ref.slice(5) : ref;\n if (\n /^https?:\\/\\//.test(gitRef) ||\n gitRef.startsWith(\"git@\") ||\n /^(?:ssh|git):\\/\\//.test(gitRef) ||\n gitRef.endsWith(\".git\")\n ) {\n const cfg: GitRegistryConfig = {\n url: gitRef,\n ...(opts.token !== undefined ? { token: opts.token } : {}),\n ...(opts.dir !== undefined ? { dir: opts.dir } : {}),\n };\n await ensureGitCheckout(cfg);\n return gitRegistryDir(cfg);\n }\n const path = ref.startsWith(\"file://\") ? ref.slice(7) : ref;\n return resolve(path);\n}\n","/**\n * Publish matrix `ArenaResult`s to a registry — explodes one matrix\n * results.json into one `arena.result/v1` document per\n * (model, plugin-set) cell, then writes result + trace files via the\n * registry backend. Spec: specs/56-arena-eval-service.\n */\nimport { randomBytes } from \"node:crypto\";\nimport { readFile } from \"node:fs/promises\";\n\nimport { ArenaError } from \"./config.js\";\nimport type { ArenaResult, RunResult } from \"./types.js\";\nimport type {\n ArenaRegistry,\n ArenaResultV1,\n TaskResult,\n TraceInput,\n} from \"./registry.js\";\nimport { parseArenaResultV1, promptHash, publishBatch } from \"./registry.js\";\n\nexport interface PublishContext {\n /** Task-pack name — the leaderboard's first-level grouping. */\n pack: string;\n /** The run's AgentAdapter.id (matrix results carry no agent field). */\n agent: string;\n /** sverka version stamp — part of the comparability cohort. */\n sverkaVersion: string;\n /** startedAt override (default: result.timestamp). */\n startedAt?: string;\n /** taskId → prompt supplement — used when the file's analysis section\n * does not carry the prompt (e.g. hand-shaped results). */\n prompts?: Record<string, string>;\n /** Trace file paths attached to v1-document publishes (--trace). */\n traces?: readonly string[];\n /** Deterministic runId generator for tests: called per cell. */\n runId?: (cell: { model: string; plugins: string[] }, index: number) => string;\n}\n\n/** Unique per-document run id — readable, sortable, collision-free. */\nexport function newRunId(): string {\n return `run-${Date.now().toString(36)}-${randomBytes(3).toString(\"hex\")}`;\n}\n\n/** Registry-safe file stem for a task id. */\nfunction taskStem(taskId: string): string {\n return taskId.replace(/[^a-zA-Z0-9._-]+/g, \"-\");\n}\n\n/**\n * Trace file name for one run — the run's index inside its cell keeps\n * repetitions of the same task apart and disambiguates task ids whose\n * stems collide (`a/b` and `a-b` both stem to `a-b`).\n */\nfunction traceName(runIndex: number, taskId: string): string {\n return `${taskStem(taskId)}.${runIndex}.trace.jsonl`;\n}\n\ninterface Cell {\n model: string;\n plugins: string[];\n runs: RunResult[];\n}\n\nfunction cellsOf(result: ArenaResult): Cell[] {\n const seen = new Map<string, Cell>();\n const cells: Cell[] = [];\n for (const run of result.results) {\n // JSON tuple key — string concat collides (model \"m\"+plugin \"ab\"\n // vs model \"ma\"+plugin \"b\" both produced \"mab\"). localeCompare —\n // default sort order is code-unit order, locale dependent per S2871.\n const plugins = [...run.pluginIds].sort((a, b) => a.localeCompare(b));\n const key = JSON.stringify([run.modelId, plugins]);\n let cell = seen.get(key);\n if (cell === undefined) {\n cell = {\n model: run.modelId,\n plugins,\n runs: [],\n };\n seen.set(key, cell);\n cells.push(cell);\n }\n cell.runs.push(run);\n }\n return cells;\n}\n\nfunction promptFor(\n result: ArenaResult,\n ctx: PublishContext,\n taskId: string,\n): string {\n // `analysis` is required on ArenaResult but publishFile accepts\n // unchecked JSON — a hand-shaped matrix file may omit it. The saved\n // prompt wins over the supplied map: a `run --pack` publish retry can\n // load config prompts that differ from the tasks that actually ran.\n const analysis = result.analysis;\n if (analysis !== undefined && !Array.isArray(analysis)) {\n throw new ArenaError(\n \"results.analysis must be an array when present\",\n \"SCHEMA_INVALID\",\n );\n }\n const prompt =\n analysis?.find((a) => a.taskId === taskId)?.prompt ?? ctx.prompts?.[taskId];\n if (prompt === undefined) {\n throw new ArenaError(\n `cannot compute promptHash for task '${taskId}' — the prompt is not in ` +\n `results.analysis and no prompts map was supplied`,\n \"SCHEMA_INVALID\",\n );\n }\n return prompt;\n}\n\nfunction toTaskResult(\n run: RunResult,\n result: ArenaResult,\n ctx: PublishContext,\n runId: string,\n runIndex: number,\n): TaskResult {\n const failedChecks = (run.checkResults ?? []).filter((c) => !c.passed);\n const hasTrace = (run.trace?.steps?.length ?? 0) > 0;\n return {\n task: run.taskId,\n promptHash: promptHash(promptFor(result, ctx, run.taskId)),\n score: { passed: run.success, findings: failedChecks.length },\n metrics: {\n tokens: run.metrics.totalTokens,\n toolCalls: run.metrics.toolCallCount,\n durationMs: run.metrics.executionTimeMs,\n ...(run.metrics.stopReason !== undefined\n ? { stopReason: run.metrics.stopReason }\n : {}),\n },\n ...(hasTrace\n ? { traceRef: `traces/${runId}/${traceName(runIndex, run.taskId)}` }\n : {}),\n };\n}\n\n/**\n * Explode a matrix {@link ArenaResult} into one `arena.result/v1`\n * document per (model, plugin-set) cell.\n */\nexport function explodeResult(\n result: ArenaResult,\n ctx: PublishContext,\n): ArenaResultV1[] {\n return cellsOf(result).map((cell, i) => {\n const runId =\n ctx.runId?.({ model: cell.model, plugins: cell.plugins }, i) ??\n newRunId();\n return {\n schema: \"arena.result/v1\",\n runId,\n pack: ctx.pack,\n agent: ctx.agent,\n model: cell.model,\n plugins: cell.plugins,\n sverkaVersion: ctx.sverkaVersion,\n startedAt: ctx.startedAt ?? result.timestamp,\n tasks: cell.runs.map((r, k) => toTaskResult(r, result, ctx, runId, k)),\n };\n });\n}\n\n/**\n * Trace payloads for one cell — `runs[i]` produced `doc.tasks[i]`, so the\n * run index keeps each repetition's trace under its own file (a\n * taskId-keyed Map would collapse repeats to the last run's trace).\n */\nfunction tracePayloads(runs: readonly RunResult[]): TraceInput[] {\n const out: TraceInput[] = [];\n runs.forEach((run, i) => {\n if ((run.trace?.steps?.length ?? 0) > 0) {\n out.push({ name: traceName(i, run.taskId), data: run.trace });\n }\n });\n return out;\n}\n\n/**\n * Explode a matrix result and publish every cell document (with its\n * traces) to the registry. Returns the registry-relative result paths.\n */\nexport async function publishResult(\n result: ArenaResult,\n registry: ArenaRegistry,\n ctx: PublishContext,\n): Promise<string[]> {\n const docs = explodeResult(result, ctx);\n const cells = cellsOf(result);\n return publishBatch(\n registry,\n docs.map((doc, i) => ({\n doc,\n opts: { traces: tracePayloads(cells[i]!.runs) },\n })),\n `arena: publish ${ctx.pack}/${ctx.agent} (${docs.length} run${docs.length === 1 ? \"\" : \"s\"})`,\n );\n}\n\n/**\n * Publish a results file — accepts either an `arena.result/v1` document\n * (or an array of them, published as-is) or a matrix `results.json`\n * (exploded per cell). Returns the registry-relative result paths.\n */\nexport async function publishFile(\n file: string,\n registry: ArenaRegistry,\n ctx: PublishContext,\n): Promise<string[]> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(await readFile(file, \"utf8\"));\n } catch (err) {\n throw new ArenaError(\n `cannot parse '${file}': ${err instanceof Error ? err.message : String(err)}`,\n \"SCHEMA_INVALID\",\n err,\n );\n }\n\n const docs: ArenaResultV1[] = [];\n if (Array.isArray(parsed)) {\n for (const doc of parsed) docs.push(parseArenaResultV1(doc));\n } else if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n (parsed as { schema?: string }).schema === \"arena.result/v1\"\n ) {\n docs.push(parseArenaResultV1(parsed));\n } else if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n Array.isArray((parsed as { results?: unknown }).results)\n ) {\n return publishResult(parsed as ArenaResult, registry, ctx);\n } else {\n throw new ArenaError(\n `'${file}' is neither an arena.result/v1 document nor a matrix results.json`,\n \"SCHEMA_INVALID\",\n );\n }\n\n const paths: string[] = [];\n for (const doc of docs) {\n paths.push(\n await registry.publish(doc, {\n ...(ctx.traces !== undefined ? { traces: ctx.traces } : {}),\n }),\n );\n }\n return paths;\n}\n","/**\n * Leaderboard aggregation — groups published `arena.result/v1` documents\n * into cohorts keyed (pack, task, sverkaVersion, promptHash) and renders\n * one row per (agent, model). Results from different tasks, sverka\n * versions, or prompts never merge into one score.\n * Spec: specs/56-arena-eval-service.\n */\nimport type { ArenaResultV1 } from \"./registry.js\";\n\nexport interface BoardRow {\n readonly agent: string;\n readonly model: string;\n /** passed runs / total runs, 0..1 */\n readonly successRate: number;\n readonly medianTokens?: number;\n readonly medianDurationMs: number;\n readonly runs: number;\n /** Success rate per day for the last `days` days — NaN on days with no runs. */\n readonly trend: readonly number[];\n}\n\nexport interface BoardCohort {\n readonly pack: string;\n readonly task: string;\n readonly sverkaVersion: string;\n readonly promptHash: string;\n readonly rows: readonly BoardRow[];\n}\n\ninterface Sample {\n readonly day: string;\n readonly passed: boolean;\n readonly tokens?: number;\n readonly durationMs: number;\n}\n\nfunction median(xs: readonly number[]): number | undefined {\n if (xs.length === 0) return undefined;\n const s = [...xs].sort((a, b) => a - b);\n const m = s.length >> 1;\n return s.length % 2 === 1 ? s[m]! : (s[m - 1]! + s[m]!) / 2;\n}\n\nfunction isoDay(d: Date): string {\n return d.toISOString().slice(0, 10);\n}\n\nconst TREND_DAYS = 30;\n\nexport interface BuildBoardOptions {\n /** Trend window length in days (default: 30). */\n days?: number;\n /** Anchor date for the trend window (default: the cohort's latest sample). */\n now?: Date;\n}\n\n/**\n * Aggregate published results into board cohorts. The cohort key is\n * (pack, task, sverkaVersion, promptHash) — a board row is only ever a\n * comparison inside one prompt+toolchain generation.\n */\nexport function buildBoard(\n results: readonly ArenaResultV1[],\n opts: BuildBoardOptions = {},\n): BoardCohort[] {\n const days = opts.days ?? TREND_DAYS;\n const cohorts = new Map<\n string,\n {\n key: Omit<BoardCohort, \"rows\">;\n rows: Map<string, { agent: string; model: string; samples: Sample[] }>;\n }\n >();\n\n for (const doc of results) {\n const day = doc.startedAt.slice(0, 10);\n for (const t of doc.tasks) {\n const ck = JSON.stringify([\n doc.pack,\n t.task,\n doc.sverkaVersion,\n t.promptHash,\n ]);\n let cohort = cohorts.get(ck);\n if (cohort === undefined) {\n cohort = {\n key: {\n pack: doc.pack,\n task: t.task,\n sverkaVersion: doc.sverkaVersion,\n promptHash: t.promptHash,\n },\n rows: new Map(),\n };\n cohorts.set(ck, cohort);\n }\n const rk = JSON.stringify([doc.agent, doc.model]);\n let row = cohort.rows.get(rk);\n if (row === undefined) {\n row = { agent: doc.agent, model: doc.model, samples: [] };\n cohort.rows.set(rk, row);\n }\n row.samples.push({\n day,\n passed: t.score.passed,\n ...(t.metrics.tokens !== undefined ? { tokens: t.metrics.tokens } : {}),\n durationMs: t.metrics.durationMs,\n });\n }\n }\n\n const out: BoardCohort[] = [];\n for (const { key, rows } of cohorts.values()) {\n // One trend window per cohort — every row anchors to the same date so\n // all trend columns under one heading cover the same period.\n const anchor =\n opts.now !== undefined\n ? isoDay(opts.now)\n : [...rows.values()].reduce(\n (max, r) =>\n r.samples.reduce((m, s) => (s.day > m ? s.day : m), max),\n \"0000-00-00\",\n );\n const boardRows: BoardRow[] = [...rows.values()].map((r) => {\n const n = r.samples.length;\n const passes = r.samples.filter((s) => s.passed).length;\n const byDay = new Map<string, { pass: number; n: number }>();\n for (const s of r.samples) {\n const d = byDay.get(s.day) ?? { pass: 0, n: 0 };\n d.n++;\n if (s.passed) d.pass++;\n byDay.set(s.day, d);\n }\n const trend: number[] = [];\n const anchorDate = new Date(`${anchor}T00:00:00.000Z`);\n for (let i = days - 1; i >= 0; i--) {\n const d = new Date(anchorDate.getTime() - i * 86_400_000);\n const stat = byDay.get(isoDay(d));\n trend.push(stat === undefined ? Number.NaN : stat.pass / stat.n);\n }\n const tokens = median(\n r.samples.flatMap((s) => (s.tokens !== undefined ? [s.tokens] : [])),\n );\n return {\n agent: r.agent,\n model: r.model,\n successRate: n === 0 ? 0 : passes / n,\n ...(tokens !== undefined ? { medianTokens: tokens } : {}),\n medianDurationMs: median(r.samples.map((s) => s.durationMs)) ?? 0,\n runs: n,\n trend,\n };\n });\n boardRows.sort(\n (a, b) =>\n b.successRate - a.successRate ||\n (a.medianTokens ?? Infinity) - (b.medianTokens ?? Infinity) ||\n a.agent.localeCompare(b.agent) ||\n a.model.localeCompare(b.model),\n );\n out.push({ ...key, rows: boardRows });\n }\n out.sort(\n (a, b) =>\n a.pack.localeCompare(b.pack) ||\n a.task.localeCompare(b.task) ||\n a.sverkaVersion.localeCompare(b.sverkaVersion) ||\n a.promptHash.localeCompare(b.promptHash),\n );\n return out;\n}\n\n// ─── Text render ─────────────────────────────────────────────────────\n\nconst SPARK = \"▁▂▃▄▅▆▇█\";\n\n/** Sparkline over the trend array — NaN days render as a gap dot. */\nexport function sparkline(trend: readonly number[]): string {\n return trend\n .map((v) =>\n Number.isNaN(v)\n ? \"·\"\n : SPARK[\n Math.min(\n SPARK.length - 1,\n Math.max(0, Math.round(v * (SPARK.length - 1))),\n )\n ],\n )\n .join(\"\");\n}\n\nfunction formatTokens(n: number | undefined): string {\n if (n === undefined) return \"—\";\n return n >= 1000 ? `${(n / 1000).toFixed(1)}k` : String(Math.round(n));\n}\n\nfunction formatDuration(ms: number): string {\n return ms >= 1000 ? `${(ms / 1000).toFixed(1)}s` : `${Math.round(ms)}ms`;\n}\n\nfunction cohortTitle(c: BoardCohort): string {\n return `${c.pack} · ${c.task} · sverka ${c.sverkaVersion} · prompt ${c.promptHash.slice(0, 12)}`;\n}\n\n/** Render the leaderboard as a text table — `sverka-arena board`. */\nexport function renderBoard(cohorts: readonly BoardCohort[]): string {\n if (cohorts.length === 0) {\n return \"no arena results — nothing published to this registry yet\";\n }\n const out: string[] = [];\n for (const c of cohorts) {\n out.push(cohortTitle(c));\n const header = [\n \"AGENT\",\n \"MODEL\",\n \"SUCCESS\",\n \"MED-TOK\",\n \"MED-DUR\",\n \"RUNS\",\n \"TREND\",\n ];\n const lines = c.rows.map((r) => [\n r.agent,\n r.model,\n `${(r.successRate * 100).toFixed(1)}%`,\n formatTokens(r.medianTokens),\n formatDuration(r.medianDurationMs),\n String(r.runs),\n sparkline(r.trend),\n ]);\n const widths = header.map((h, i) =>\n Math.max(h.length, ...lines.map((l) => l[i]!.length)),\n );\n const fmt = (cells: readonly string[]): string =>\n cells\n .map((cell, i) => cell.padEnd(widths[i]!))\n .join(\" \")\n .trimEnd();\n out.push(` ${fmt(header)}`);\n for (const l of lines) out.push(` ${fmt(l)}`);\n out.push(\"\");\n }\n return out.join(\"\\n\").trimEnd();\n}\n\n// ─── HTML render ─────────────────────────────────────────────────────\n\nfunction rateClass(successRate: number): string {\n if (successRate >= 0.99) return \"ok\";\n if (successRate >= 0.5) return \"mid\";\n return \"bad\";\n}\n\nfunction esc(s: string): string {\n return s\n .replaceAll(/&/g, \"&amp;\")\n .replaceAll(/</g, \"&lt;\")\n .replaceAll(/>/g, \"&gt;\")\n .replaceAll(/\"/g, \"&quot;\");\n}\n\n/**\n * Render the leaderboard as a self-contained static HTML page — no JS,\n * no server. Used by `sverka-arena board --format html` and the website\n * arena page (generated at build time from the registry).\n */\nexport function renderBoardHtml(\n cohorts: readonly BoardCohort[],\n opts: { title?: string; generatedAt?: string } = {},\n): string {\n const title = opts.title ?? \"Sverka Arena — Leaderboard\";\n const generatedAt = opts.generatedAt ?? new Date().toISOString();\n const sections = cohorts\n .map((c) => {\n const rows = c.rows\n .map((r) => {\n const spark = esc(sparkline(r.trend));\n return ` <tr>\n <td>${esc(r.agent)}</td>\n <td>${esc(r.model)}</td>\n <td class=\"num ${rateClass(r.successRate)}\">${(r.successRate * 100).toFixed(1)}%</td>\n <td class=\"num\">${formatTokens(r.medianTokens)}</td>\n <td class=\"num\">${formatDuration(r.medianDurationMs)}</td>\n <td class=\"num\">${r.runs}</td>\n <td class=\"spark\" title=\"daily success rate, last ${r.trend.length} days\">${spark}</td>\n </tr>`;\n })\n .join(\"\\n\");\n return ` <section class=\"cohort\">\n <h2>${esc(cohortTitle(c))}</h2>\n <table>\n <thead><tr><th>agent</th><th>model</th><th class=\"num\">success</th><th class=\"num\">med&nbsp;tokens</th><th class=\"num\">med&nbsp;duration</th><th class=\"num\">runs</th><th>trend</th></tr></thead>\n <tbody>\n${rows}\n </tbody>\n </table>\n </section>`;\n })\n .join(\"\\n\");\n const body =\n cohorts.length === 0\n ? ` <p class=\"empty\">no arena results — nothing published to this registry yet</p>`\n : sections;\n return `<!doctype html>\n<html lang=\"en\" data-theme=\"dark\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<title>${esc(title)}</title>\n<style>\n:root {\n --bg: #0d1117; --surface: #161b22; --border: #30363d;\n --text: #e6edf3; --text-muted: #8b949e;\n --green: #3fb950; --yellow: #d29922; --red: #f85149; --accent: #58a6ff;\n}\n* { margin: 0; padding: 0; box-sizing: border-box; }\nbody {\n background: var(--bg); color: var(--text);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif;\n line-height: 1.6; padding: 2rem; max-width: 1100px; margin: 0 auto;\n}\nh1 { font-size: 1.4rem; }\n.subtitle { color: var(--text-muted); font-size: 0.85rem; margin: 0.25rem 0 1.5rem; }\n.cohort {\n background: var(--surface); border: 1px solid var(--border);\n border-radius: 8px; padding: 1rem 1.25rem; margin-bottom: 1.25rem;\n}\n.cohort h2 {\n font-size: 0.95rem; font-family: ui-monospace, \"SF Mono\", monospace;\n color: var(--accent); margin-bottom: 0.75rem; font-weight: 600;\n}\ntable { width: 100%; border-collapse: collapse; font-size: 0.85rem; }\nth {\n text-align: left; color: var(--text-muted); font-weight: 600;\n font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.05em;\n padding: 0.3rem 0.6rem; border-bottom: 1px solid var(--border);\n}\ntd { padding: 0.4rem 0.6rem; border-bottom: 1px solid var(--border); }\ntr:last-child td { border-bottom: none; }\n.num { text-align: right; font-variant-numeric: tabular-nums; }\nth.num { text-align: right; }\n.ok { color: var(--green); } .mid { color: var(--yellow); } .bad { color: var(--red); }\n.spark { font-family: ui-monospace, \"SF Mono\", monospace; letter-spacing: 0.05em; color: var(--green); }\n.empty { color: var(--text-muted); padding: 3rem 0; text-align: center; }\nfooter { color: var(--text-muted); font-size: 0.75rem; margin-top: 2rem; }\n</style>\n</head>\n<body>\n <h1>${esc(title)}</h1>\n <p class=\"subtitle\">verification-grounded agent evals — cohorts are (pack · task · sverka version · prompt hash); rows compare agent×model inside one cohort only</p>\n${body}\n <footer>generated ${esc(generatedAt)} — deterministic checks as ground truth, no LLM judge</footer>\n</body>\n</html>\n`;\n}\n","/**\n * Task packs — shareable benchmark suites. A pack is a directory:\n *\n * <pack>/\n * pack.json # { name, version, description, defaults }\n * tasks/<id>.json # { id, prompt, repo|fixture, checks, timeout? }\n *\n * `sverka-arena run --pack <ref>` resolves a local dir, a git URL, or a\n * pack name inside a registry (`packs/<name>/`). Community contribution\n * is a git PR adding a pack — no registry write API needed.\n * Spec: specs/56-arena-eval-service.\n */\nimport { createHash } from \"node:crypto\";\nimport { existsSync, statSync } from \"node:fs\";\nimport { chmod, mkdir, readdir, readFile, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { basename, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { z } from \"zod\";\n\nimport { ArenaError } from \"./config.js\";\nimport { git, gitOrThrow } from \"./internal/git.js\";\nimport { resolveRegistryDir } from \"./registry.js\";\nimport type { DeterministicCheck, Task } from \"./types.js\";\n\n// ─── Schemas ─────────────────────────────────────────────────────────\n\nconst packCheckSchema = z.object({\n id: z.string().min(1),\n command: z.string().min(1),\n description: z.string().optional(),\n});\n\nconst packTaskSchema = z.object({\n id: z.string().min(1).optional(),\n name: z.string().optional(),\n prompt: z.string().min(1),\n timeoutMs: z.number().positive().optional(),\n /** Git URL cloned as the task's workspace seed. */\n repo: z.string().min(1).optional(),\n /** Directory inside the pack copied into the workspace. */\n fixture: z.string().min(1).optional(),\n setup: z.array(z.string()).optional(),\n checks: z.array(packCheckSchema).optional(),\n successCriteria: z.string().optional(),\n expectedOutput: z.string().optional(),\n});\n\nconst packJsonSchema = z.object({\n name: z.string().min(1),\n version: z.string().optional(),\n description: z.string().optional(),\n defaults: z\n .object({\n timeoutMs: z.number().positive().optional(),\n repetitions: z.number().int().positive().optional(),\n outputDir: z.string().min(1).optional(),\n })\n .optional(),\n});\n\nexport interface PackDefaults {\n readonly timeoutMs?: number;\n readonly repetitions?: number;\n readonly outputDir?: string;\n}\n\nexport interface TaskPack {\n readonly name: string;\n readonly version?: string;\n readonly description?: string;\n /** Local directory the pack was loaded from. */\n readonly dir: string;\n readonly tasks: readonly Task[];\n readonly defaults: PackDefaults;\n}\n\nexport interface PackLint {\n readonly errors: readonly string[];\n readonly warnings: readonly string[];\n}\n\n// ─── Loading ─────────────────────────────────────────────────────────\n\ninterface LoadOptions {\n /** Where `repo:` fixtures are cloned (default: tmp cache). */\n cacheDir?: string;\n}\n\nasync function taskFromFile(\n file: string,\n dir: string,\n defaults: PackDefaults,\n opts: LoadOptions,\n): Promise<Task> {\n let raw: unknown;\n try {\n raw = JSON.parse(await readFile(file, \"utf8\"));\n } catch (err) {\n throw new ArenaError(\n `pack task '${file}' is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n \"PACK_INVALID\",\n err,\n );\n }\n const parsed = packTaskSchema.safeParse(raw);\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((i) => ` ${i.path.join(\".\") || \"(root)\"}: ${i.message}`)\n .join(\"\\n\");\n throw new ArenaError(\n `pack task '${file}' is invalid:\\n${issues}`,\n \"PACK_INVALID\",\n );\n }\n const t = parsed.data;\n const id = t.id ?? basename(file, \".json\");\n if (t.fixture !== undefined && t.repo !== undefined) {\n throw new ArenaError(\n `pack task '${id}': cannot specify both 'fixture' and 'repo' — choose one`,\n \"PACK_INVALID\",\n );\n }\n let fixture: string | undefined;\n if (t.fixture !== undefined) {\n fixture = resolve(dir, t.fixture);\n // Community packs arrive via git clone — a fixture must resolve\n // inside the pack dir (no ../ escapes) and be a directory.\n const rel = relative(dir, fixture);\n if (rel.startsWith(\"..\") || isAbsolute(rel)) {\n throw new ArenaError(\n `pack task '${id}': fixture '${t.fixture}' escapes the pack dir`,\n \"PACK_INVALID\",\n );\n }\n if (!existsSync(fixture) || !statSync(fixture).isDirectory()) {\n throw new ArenaError(\n `pack task '${id}': fixture dir '${t.fixture}' does not exist in ${dir}`,\n \"PACK_INVALID\",\n );\n }\n }\n if (t.repo !== undefined) {\n fixture = await cloneRepo(t.repo, opts);\n }\n const checks: DeterministicCheck[] | undefined = t.checks?.map((c) => ({\n id: c.id,\n command: c.command,\n description: c.description ?? c.command,\n }));\n return {\n id,\n name: t.name ?? id,\n prompt: t.prompt,\n ...(t.timeoutMs !== undefined || defaults.timeoutMs !== undefined\n ? { timeoutMs: t.timeoutMs ?? defaults.timeoutMs! }\n : {}),\n ...(fixture !== undefined ? { fixture } : {}),\n ...(t.setup !== undefined ? { setup: t.setup } : {}),\n ...(checks !== undefined ? { checks } : {}),\n ...(t.successCriteria !== undefined\n ? { successCriteria: t.successCriteria }\n : {}),\n ...(t.expectedOutput !== undefined\n ? { expectedOutput: t.expectedOutput }\n : {}),\n };\n}\n\n/** Load a pack directory into a {@link TaskPack}. */\nexport async function loadPack(\n dir: string,\n opts: LoadOptions = {},\n): Promise<TaskPack> {\n const packJsonPath = join(dir, \"pack.json\");\n if (!existsSync(packJsonPath)) {\n throw new ArenaError(\n `no pack.json in '${dir}' — not a task pack`,\n \"PACK_NOT_FOUND\",\n );\n }\n let raw: unknown;\n try {\n raw = JSON.parse(await readFile(packJsonPath, \"utf8\"));\n } catch (err) {\n throw new ArenaError(\n `pack.json in '${dir}' is not valid JSON`,\n \"PACK_INVALID\",\n err,\n );\n }\n const parsed = packJsonSchema.safeParse(raw);\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((i) => ` ${i.path.join(\".\") || \"(root)\"}: ${i.message}`)\n .join(\"\\n\");\n throw new ArenaError(\n `pack.json in '${dir}' is invalid:\\n${issues}`,\n \"PACK_INVALID\",\n );\n }\n const meta = parsed.data;\n // exactOptionalPropertyTypes — drop keys whose value is undefined.\n const defaults: PackDefaults = {\n ...(meta.defaults?.timeoutMs !== undefined\n ? { timeoutMs: meta.defaults.timeoutMs }\n : {}),\n ...(meta.defaults?.repetitions !== undefined\n ? { repetitions: meta.defaults.repetitions }\n : {}),\n ...(meta.defaults?.outputDir !== undefined\n ? { outputDir: meta.defaults.outputDir }\n : {}),\n };\n const tasksDir = join(dir, \"tasks\");\n const files = existsSync(tasksDir)\n ? (await readdir(tasksDir)).filter((f) => f.endsWith(\".json\")).sort()\n : [];\n const tasks: Task[] = [];\n const ids = new Set<string>();\n for (const f of files) {\n const task = await taskFromFile(join(tasksDir, f), dir, defaults, opts);\n if (ids.has(task.id)) {\n throw new ArenaError(\n `duplicate task id '${task.id}' in pack '${meta.name}'`,\n \"PACK_INVALID\",\n );\n }\n ids.add(task.id);\n tasks.push(task);\n }\n if (tasks.length === 0) {\n throw new ArenaError(\n `pack '${meta.name}' has no tasks — add tasks/<id>.json`,\n \"PACK_INVALID\",\n );\n }\n return {\n name: meta.name,\n ...(meta.version !== undefined ? { version: meta.version } : {}),\n ...(meta.description !== undefined\n ? { description: meta.description }\n : {}),\n dir,\n tasks,\n defaults,\n };\n}\n\n// ─── Lint ────────────────────────────────────────────────────────────\n\n/**\n * Validate a pack directory without loading it into a run — collects\n * errors AND warnings instead of throwing on the first problem.\n */\nexport async function lintPack(dir: string): Promise<PackLint> {\n const errors: string[] = [];\n const warnings: string[] = [];\n const packJsonPath = join(dir, \"pack.json\");\n if (!existsSync(packJsonPath)) {\n return { errors: [`no pack.json in '${dir}'`], warnings };\n }\n try {\n const parsed = packJsonSchema.safeParse(\n JSON.parse(await readFile(packJsonPath, \"utf8\")),\n );\n if (!parsed.success) {\n for (const i of parsed.error.issues) {\n errors.push(`pack.json ${i.path.join(\".\") || \"(root)\"}: ${i.message}`);\n }\n return { errors, warnings };\n }\n if (parsed.data.name !== basename(dir)) {\n warnings.push(\n `pack name '${parsed.data.name}' does not match directory '${basename(dir)}'`,\n );\n }\n } catch (err) {\n return {\n errors: [\n `pack.json is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n ],\n warnings,\n };\n }\n\n const tasksDir = join(dir, \"tasks\");\n if (!existsSync(tasksDir)) {\n errors.push(`no tasks/ directory in '${dir}'`);\n return { errors, warnings };\n }\n const files = (await readdir(tasksDir)).filter((f) => f.endsWith(\".json\"));\n if (files.length === 0) errors.push(`no tasks/*.json files in '${dir}'`);\n const ids = new Set<string>();\n for (const f of files.sort()) {\n const file = join(tasksDir, f);\n let raw: unknown;\n try {\n raw = JSON.parse(await readFile(file, \"utf8\"));\n } catch (err) {\n errors.push(\n `tasks/${f}: not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n );\n continue;\n }\n const parsed = packTaskSchema.safeParse(raw);\n if (!parsed.success) {\n for (const i of parsed.error.issues) {\n errors.push(`tasks/${f} ${i.path.join(\".\") || \"(root)\"}: ${i.message}`);\n }\n continue;\n }\n const t = parsed.data;\n const id = t.id ?? basename(f, \".json\");\n if (ids.has(id)) errors.push(`duplicate task id '${id}'`);\n ids.add(id);\n if (t.checks === undefined || t.checks.length === 0) {\n warnings.push(\n `task '${id}' has no checks — it scores on agent exit status only, not verification`,\n );\n }\n if (t.fixture !== undefined && t.repo !== undefined) {\n errors.push(\n `task '${id}': cannot specify both 'fixture' and 'repo' — choose one`,\n );\n } else if (t.fixture !== undefined) {\n const fx = resolve(dir, t.fixture);\n const rel = relative(dir, fx);\n if (rel.startsWith(\"..\") || isAbsolute(rel)) {\n errors.push(\n `task '${id}': fixture '${t.fixture}' escapes the pack dir`,\n );\n } else if (!existsSync(fx) || !statSync(fx).isDirectory()) {\n errors.push(`task '${id}': fixture dir '${t.fixture}' does not exist`);\n }\n }\n }\n return { errors, warnings };\n}\n\n// ─── Init scaffold ───────────────────────────────────────────────────\n\n/** Scaffold a new pack at `<dir>` — `sverka-arena pack init <name>`. */\nexport async function initPack(dir: string, name: string): Promise<void> {\n if (existsSync(dir) && (await readdir(dir)).length > 0) {\n throw new ArenaError(\n `'${dir}' exists and is not empty — pick a fresh pack directory`,\n \"PACK_INVALID\",\n );\n }\n await mkdir(join(dir, \"tasks\"), { recursive: true });\n await writeFile(\n join(dir, \"pack.json\"),\n JSON.stringify(\n {\n name,\n version: \"0.1.0\",\n description: `${name} — sverka arena task pack`,\n defaults: { timeoutMs: 120_000, repetitions: 1, outputDir: \".arena\" },\n },\n null,\n 2,\n ) + \"\\n\",\n \"utf8\",\n );\n await writeFile(\n join(dir, \"tasks\", \"example-task.json\"),\n JSON.stringify(\n {\n id: \"example-task\",\n name: \"Example task\",\n prompt:\n \"Describe the task for the agent here. The score comes from the \" +\n \"checks below — deterministic verification, not an LLM judge.\",\n checks: [\n {\n id: \"example-check\",\n command: \"true\",\n description:\n \"replace with a real verification (e.g. npm test, sverka run)\",\n },\n ],\n },\n null,\n 2,\n ) + \"\\n\",\n \"utf8\",\n );\n}\n\n// ─── Resolution ──────────────────────────────────────────────────────\n\nfunction isGitUrl(ref: string): boolean {\n return (\n /^https?:\\/\\//.test(ref) ||\n ref.startsWith(\"git@\") ||\n /^(?:ssh|git):\\/\\//.test(ref) ||\n ref.endsWith(\".git\")\n );\n}\n\n/** Predictable tmpdir clone destinations stay owner-only (CWE-377). */\nasync function privateDir(dir: string): Promise<void> {\n await mkdir(dir, { recursive: true, mode: 0o700 });\n await chmod(dir, 0o700);\n}\n\nasync function cloneRepo(url: string, opts: LoadOptions): Promise<string> {\n const dest = join(\n opts.cacheDir ?? tmpdir(),\n `arena-pack-repo-${createHash(\"sha256\").update(url).digest(\"hex\").slice(0, 12)}`,\n );\n if (existsSync(join(dest, \".git\"))) {\n await git([\"-C\", dest, \"pull\", \"--ff-only\"]); // best-effort refresh\n return dest;\n }\n try {\n await privateDir(dest);\n await gitOrThrow([\"clone\", \"--depth\", \"1\", url, dest]);\n } catch (err) {\n throw new ArenaError(\n `cannot clone task repo '${url}': ${err instanceof Error ? err.message : String(err)}`,\n \"PACK_NOT_FOUND\",\n err,\n );\n }\n return dest;\n}\n\nasync function clonePack(url: string, opts: LoadOptions): Promise<string> {\n const dest = join(\n opts.cacheDir ?? tmpdir(),\n `arena-pack-${createHash(\"sha256\").update(url).digest(\"hex\").slice(0, 12)}`,\n );\n if (existsSync(join(dest, \".git\"))) {\n const res = await git([\"-C\", dest, \"pull\", \"--ff-only\"]);\n if (res.code !== 0) {\n throw new ArenaError(\n `cannot update pack clone '${url}': ${res.stderr.trim()}`,\n \"PACK_NOT_FOUND\",\n );\n }\n return dest;\n }\n try {\n await privateDir(dest);\n await gitOrThrow([\"clone\", url, dest]);\n } catch (err) {\n throw new ArenaError(\n `cannot clone pack '${url}': ${err instanceof Error ? err.message : String(err)}`,\n \"PACK_NOT_FOUND\",\n err,\n );\n }\n return dest;\n}\n\nexport interface ResolvePackOptions extends LoadOptions {\n /** Registry ref for bare pack names (`packs/<name>/` inside it). */\n registry?: string;\n /** Bearer token for https git registries. */\n token?: string;\n}\n\n/**\n * Resolve a pack reference to a loaded {@link TaskPack}:\n * <dir> — a local pack directory\n * <git-url> — cloned into a tmp cache, then loaded\n * <bare-name> — packs/<name>/ inside --registry (file or git)\n */\nexport async function resolvePack(\n ref: string,\n opts: ResolvePackOptions = {},\n): Promise<TaskPack> {\n // Local directory.\n if (existsSync(ref) && existsSync(join(ref, \"pack.json\"))) {\n return loadPack(resolve(ref), opts);\n }\n // Git URL.\n if (isGitUrl(ref) || ref.startsWith(\"git::\")) {\n const url = ref.startsWith(\"git::\") ? ref.slice(5) : ref;\n return loadPack(await clonePack(url, opts), opts);\n }\n // Bare name → packs/<name>/ inside the registry.\n if (/^[a-zA-Z0-9._-]+$/.test(ref)) {\n if (opts.registry === undefined) {\n throw new ArenaError(\n `cannot resolve pack '${ref}' — no --registry given (packs live at packs/<name>/ inside a registry)`,\n \"PACK_NOT_FOUND\",\n );\n }\n const regDir = await resolveRegistryDir(opts.registry, {\n ...(opts.token !== undefined ? { token: opts.token } : {}),\n });\n const packDir = join(regDir, \"packs\", ref);\n if (!existsSync(join(packDir, \"pack.json\"))) {\n throw new ArenaError(\n `pack '${ref}' not found at ${packDir}`,\n \"PACK_NOT_FOUND\",\n );\n }\n return loadPack(packDir, opts);\n }\n throw new ArenaError(`pack '${ref}' not found`, \"PACK_NOT_FOUND\");\n}\n"],"mappings":"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"}