@dungle-scrubs/skillval 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/config.ts","../src/config-contract.ts","../src/executors/codex.ts","../src/utils.ts","../src/executors/index.ts","../src/discovery.ts","../src/case-file.ts","../src/case-contract.ts","../src/graders.ts","../src/fixture.ts","../src/runner.ts","../src/cache.ts","../src/grade.ts","../src/vote.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/** Defines the command-line transport and renders runner and discovery results. */\nimport { Command } from \"commander\";\nimport { loadConfig, resolveConfigPath } from \"./config.js\";\nimport type { DiscoveredSkill } from \"./discovery.js\";\nimport { discoverSkills, discoveryReport } from \"./discovery.js\";\nimport { runEvaluation } from \"./runner.js\";\n\ninterface GlobalOptions {\n readonly config?: string;\n}\n\ninterface ListOptions {\n readonly json?: boolean;\n}\n\ninterface RunCommandOptions {\n readonly cache: boolean;\n readonly case?: string;\n readonly json?: boolean;\n readonly skipBaseline?: boolean;\n}\n\nconst program = new Command();\n\nprogram\n .name(\"skillval\")\n .description(\"Evaluate agent skills with deterministic graders\")\n .configureHelp({ showGlobalOptions: true })\n .version(\"0.1.0\") // x-release-please-version\n .option(\"--config <path>\", \"read configuration from this path\");\n\nprogram\n .command(\"run\")\n .description(\n \"Run selected cases and return a report whose exit status fails when any skill arm fails\",\n )\n .argument(\"[skill...]\", \"skill names; omit to run every skill with skillval.yml\")\n .option(\"--case <id>\", \"run only the case with this id\")\n .option(\"--no-cache\", \"ignore cached arm results\")\n .option(\"--skip-baseline\", \"do not run baseline arms\")\n .option(\"--json\", \"return the complete report as JSON\")\n .action((skills: string[], options: RunCommandOptions, command: Command): void => {\n const globalOptions = command.optsWithGlobals() as GlobalOptions & RunCommandOptions;\n const configPath = resolveConfigPath({ cliPath: globalOptions.config });\n const config = loadConfig(configPath);\n const outcome = runEvaluation(\n config,\n {\n caseFilter: options.case,\n requestedSkills: skills,\n skipBaseline: options.skipBaseline === true,\n useCache: options.cache,\n },\n options.json === true ? () => undefined : (message) => console.log(message),\n );\n\n if (options.json === true) {\n console.log(JSON.stringify(outcome.report, null, 2));\n } else {\n console.log(`report: ${outcome.reportPath}`);\n if (outcome.noops > 0) {\n console.log(`no-op alert: ${outcome.noops} case(s) pass at baseline - prune candidates`);\n }\n console.log(\n outcome.failures === 0 ? \"all cases passed\" : `${outcome.failures} case(s) FAILED`,\n );\n }\n process.exitCode = outcome.failures > 0 ? 1 : 0;\n });\n\nprogram\n .command(\"list\")\n .description(\n \"Return discovered skills, evaluation metadata, and configured roots that are missing\",\n )\n .option(\"--json\", \"return the complete discovery result as JSON\")\n .action((options: ListOptions, command: Command): void => {\n const globalOptions = command.optsWithGlobals() as GlobalOptions & ListOptions;\n const configPath = resolveConfigPath({ cliPath: globalOptions.config });\n const config = loadConfig(configPath);\n const discovery = discoverSkills(config.roots);\n if (options.json === true) {\n console.log(JSON.stringify(discoveryReport(discovery), null, 2));\n return;\n }\n\n printSkillTable(discovery.skills);\n for (const skill of discovery.skills) {\n if (skill.status === \"invalid\") console.log(`invalid skill: ${skill.validationError}`);\n }\n for (const root of discovery.missingRoots) console.log(`missing root: ${root}`);\n });\n\nexport async function main(): Promise<void> {\n try {\n await program.parseAsync(process.argv);\n } catch (error) {\n console.error(`error: ${error instanceof Error ? error.message : String(error)}`);\n process.exitCode = 1;\n }\n}\n\nfunction printSkillTable(skills: readonly DiscoveredSkill[]): void {\n const rows = [\n [\"NAME\", \"ROOT\", \"CLASS\", \"CASES\", \"HAS-SKILLVAL.YML\"],\n ...skills.map((skill) => [\n skill.name,\n skill.root,\n skill.class ?? \"-\",\n String(skill.caseCount),\n skill.hasSkillval ? \"true\" : \"false\",\n ]),\n ];\n const widths = rows[0]?.map((_, column) =>\n Math.max(...rows.map((row) => row[column]?.length ?? 0)),\n );\n for (const row of rows) {\n console.log(\n row\n .map((cell, column) => cell.padEnd(widths?.[column] ?? cell.length))\n .join(\" \")\n .trimEnd(),\n );\n }\n}\n\nawait main();\n","/** Resolves configuration and state paths, then loads validated configuration values. */\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { resolve } from \"node:path\";\nimport { Check as checkSchema, Errors as schemaErrors } from \"typebox/value\";\nimport { parse as parseYaml } from \"yaml\";\nimport type { ConfigFile } from \"./config-contract.js\";\nimport { configFileSchema } from \"./config-contract.js\";\n\nexport type SkillvalConfig = ConfigFile;\n\nexport interface ConfigPathOptions {\n readonly cliPath?: string;\n readonly environment?: NodeJS.ProcessEnv;\n readonly home?: string;\n}\n\nexport class ConfigError extends Error {\n public readonly code: string;\n\n public constructor(message: string, code = \"CONFIG_ERROR\") {\n super(message);\n this.code = code;\n this.name = \"ConfigError\";\n }\n}\n\nexport function resolveConfigPath(options: ConfigPathOptions = {}): string {\n const environment = options.environment ?? process.env;\n const home = options.home ?? homedir();\n const selected =\n options.cliPath ??\n environment.SKILLVAL_CONFIG ??\n (environment.XDG_CONFIG_HOME\n ? resolve(environment.XDG_CONFIG_HOME, \"skillval/config.yml\")\n : resolve(home, \".config/skillval/config.yml\"));\n return resolve(expandHome(selected, home));\n}\n\nexport function expandRoot(root: string, home = homedir()): string {\n return resolve(expandHome(root, home));\n}\n\nexport function loadConfig(path: string, home = homedir()): SkillvalConfig {\n if (!existsSync(path)) {\n throw new ConfigError(`config file not found: ${path}`, \"CONFIG_NOT_FOUND\");\n }\n\n let parsed: unknown;\n try {\n parsed = parseYaml(readFileSync(path, \"utf8\"));\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n throw new ConfigError(`invalid YAML in ${path}: ${detail}`, \"CONFIG_YAML_INVALID\");\n }\n\n if (!checkSchema(configFileSchema, parsed)) {\n const [firstError] = schemaErrors(configFileSchema, parsed);\n const location = firstError?.instancePath.replaceAll(\"/\", \".\").replace(/^\\./, \"\");\n const subject = location === undefined || location === \"\" ? path : `${path} ${location}`;\n throw new ConfigError(`${subject} ${firstError?.message ?? \"is invalid\"}`);\n }\n\n return {\n executor: parsed.executor,\n roots: parsed.roots.map((root) => expandRoot(root, home)),\n };\n}\n\nexport function resolveStateDirectory(\n environment: NodeJS.ProcessEnv = process.env,\n home = homedir(),\n): string {\n return environment.XDG_STATE_HOME\n ? resolve(environment.XDG_STATE_HOME, \"skillval\")\n : resolve(home, \".local/state/skillval\");\n}\n\nfunction expandHome(value: string, home: string): string {\n const withTilde =\n value === \"~\" ? home : value.startsWith(\"~/\") ? `${home}${value.slice(1)}` : value;\n return withTilde.replaceAll(String.raw`\\${HOME}`, home).replaceAll(\"$HOME\", home);\n}\n","/** Defines the configuration contract shared by runtime validation and generated JSON Schema. */\nimport type { Static } from \"typebox\";\nimport Type from \"typebox\";\nimport { EXECUTOR_NAMES } from \"./executors/index.js\";\n\nexport const configFileSchema = Type.ReadonlyObject(\n Type.Object({\n // Names come from the executor registry so configuration cannot advertise a missing adapter.\n executor: Type.Enum(EXECUTOR_NAMES, {\n description: \"Trial executor.\",\n }),\n roots: Type.Readonly(\n Type.Array(Type.String({ minLength: 1, pattern: String.raw`\\S` }), {\n description: \"Directories whose immediate children are agent skill directories.\",\n }),\n ),\n }),\n {\n $id: \"https://raw.githubusercontent.com/dungle-scrubs/skillval/main/schemas/config.schema.json\",\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n additionalProperties: false,\n title: \"skillval configuration\",\n },\n);\n\nexport type ConfigFile = Static<typeof configFileSchema>;\n","/** Implements Codex-specific skill seeding, process isolation, invocation, and trace parsing. */\nimport { spawnSync } from \"node:child_process\";\nimport { mkdirSync, readFileSync, symlinkSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Trace } from \"../types.js\";\nimport { isRecord } from \"../utils.js\";\nimport type { Executor, ExecutorMetadata, TrialRequest } from \"./types.js\";\n\nconst TRIAL_TIMEOUT_MS = 15 * 60 * 1000;\n\nexport class CodexExecutor implements Executor {\n public readonly metadata: ExecutorMetadata;\n readonly #realHome: string;\n\n public constructor(realHome = homedir()) {\n this.#realHome = realHome;\n this.metadata = detectCodex(realHome);\n }\n\n public runTrial(request: TrialRequest): Trace {\n if (request.arm === \"skill\") seedSkill(request);\n const sandbox = request.evalCase.mode === \"generation\" ? \"workspace-write\" : \"read-only\";\n // Baselines need the real Codex configuration for authentication and model selection, but an\n // empty HOME prevents globally installed skills from influencing the comparison arm.\n const environment =\n request.arm === \"baseline\"\n ? {\n ...process.env,\n CODEX_HOME: join(this.#realHome, \".codex\"),\n HOME: request.home,\n }\n : { ...process.env };\n const result = spawnSync(\n \"codex\",\n [\n \"exec\",\n \"--json\",\n \"--skip-git-repo-check\",\n \"--ephemeral\",\n \"-s\",\n sandbox,\n \"-C\",\n request.workspace,\n request.evalCase.prompt,\n ],\n {\n encoding: \"utf8\",\n env: environment,\n maxBuffer: 64 * 1024 * 1024,\n timeout: TRIAL_TIMEOUT_MS,\n },\n );\n if (result.status !== 0) {\n throw new Error(`codex exec exited ${result.status}: ${result.stderr?.slice(-500)}`);\n }\n\n return parseCodexTrace(result.stdout, request.skillName);\n }\n}\n\nfunction seedSkill(request: TrialRequest): void {\n // Skill installation paths are provider knowledge and intentionally stay inside this adapter.\n const skillsRoot = join(request.workspace, \".agents/skills\");\n mkdirSync(skillsRoot, { recursive: true });\n symlinkSync(request.skillDirectory, join(skillsRoot, request.skillName));\n}\n\nexport function detectCodex(realHome = homedir()): ExecutorMetadata {\n const version = spawnSync(\"codex\", [\"--version\"], { encoding: \"utf8\" }).stdout?.trim() ?? \"\";\n if (version === \"\") throw new Error(\"codex CLI not found on PATH\");\n const model =\n readFileSync(join(realHome, \".codex/config.toml\"), \"utf8\").match(\n /^model\\s*=\\s*\"([^\"]+)\"/m,\n )?.[1] ?? \"default\";\n return { model, name: \"codex\", version };\n}\n\nexport function parseCodexTrace(stdout: string, skillName: string): Trace {\n let completed = false;\n let invoked = false;\n const texts: string[] = [];\n let usage: unknown;\n\n for (const line of stdout.split(\"\\n\")) {\n if (line.trim() === \"\") continue;\n let event: unknown;\n try {\n event = JSON.parse(line);\n } catch {\n continue;\n }\n if (!isRecord(event)) continue;\n const item = isRecord(event.item) ? event.item : undefined;\n if (\n item?.type === \"command_execution\" &&\n typeof item.command === \"string\" &&\n item.command.includes(`${skillName}/SKILL.md`)\n ) {\n invoked = true;\n }\n if (\n event.type === \"item.completed\" &&\n item?.type === \"agent_message\" &&\n typeof item.text === \"string\"\n ) {\n texts.push(item.text);\n }\n if (event.type === \"turn.completed\") {\n completed = true;\n usage = event.usage;\n }\n }\n\n return { agentText: texts.join(\"\\n\"), completed, invoked, usage };\n}\n","import { createHash } from \"node:crypto\";\nimport { readdirSync, readFileSync } from \"node:fs\";\nimport { join, relative } from \"node:path\";\n\nexport function sha256(input: string): string {\n return createHash(\"sha256\").update(input).digest(\"hex\");\n}\n\n// Directories that never contribute to content identity or workspace materialization.\nexport const SKIPPED_DIRECTORIES: ReadonlySet<string> = new Set([\".git\", \"node_modules\"]);\n\nexport function walkFiles(root: string): string[] {\n const files: string[] = [];\n\n function visit(directory: string): void {\n for (const entry of readdirSync(directory, { withFileTypes: true })) {\n if (SKIPPED_DIRECTORIES.has(entry.name)) continue;\n const path = join(directory, entry.name);\n if (entry.isDirectory()) visit(path);\n else if (entry.isFile()) files.push(path);\n }\n }\n\n visit(root);\n return files.sort();\n}\n\nexport function skillContentHash(skillDirectory: string): string {\n const parts = walkFiles(skillDirectory).map(\n (file) => `${relative(skillDirectory, file)}\\n${readFileSync(file, \"utf8\")}`,\n );\n return sha256(parts.join(\"\\0\"));\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","/** Registers executor adapters and creates them from validated configuration names. */\nimport { CodexExecutor } from \"./codex.js\";\nimport type { Executor } from \"./types.js\";\n\nconst executorFactories = {\n codex: (): Executor => new CodexExecutor(),\n};\n\n// Both the configuration schema and factory derive from this registry.\nexport type ExecutorName = keyof typeof executorFactories;\nexport const EXECUTOR_NAMES = Object.keys(executorFactories) as ExecutorName[];\n\nexport function createExecutor(name: ExecutorName): Executor {\n return executorFactories[name]();\n}\n","/** Discovers skills and carries validated case suites into evaluation without reparsing them. */\nimport { existsSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { readCaseFile } from \"./case-file.js\";\nimport type { SkillEvals } from \"./types.js\";\n\ninterface SkillLocation {\n readonly name: string;\n readonly root: string;\n readonly skillDirectory: string;\n}\n\nexport interface MissingDiscoveredSkill extends SkillLocation {\n readonly caseCount: 0;\n readonly class: undefined;\n readonly hasSkillval: false;\n readonly status: \"missing\";\n readonly validationError: undefined;\n}\n\nexport interface InvalidDiscoveredSkill extends SkillLocation {\n readonly caseCount: 0;\n readonly class: \"invalid\";\n readonly hasSkillval: true;\n readonly status: \"invalid\";\n readonly validationError: string;\n}\n\nexport interface ReadyDiscoveredSkill extends SkillLocation {\n readonly caseCount: number;\n readonly class: \"capability\" | \"preference\";\n readonly evals: SkillEvals;\n readonly hasSkillval: true;\n readonly status: \"ready\";\n readonly validationError: undefined;\n}\n\nexport type DiscoveredSkill =\n | InvalidDiscoveredSkill\n | MissingDiscoveredSkill\n | ReadyDiscoveredSkill;\n\nexport interface DiscoveryResult {\n readonly missingRoots: readonly string[];\n readonly skills: readonly DiscoveredSkill[];\n}\n\nexport interface DiscoveryReport {\n readonly missingRoots: readonly string[];\n readonly skills: readonly DiscoverySkillSummary[];\n}\n\nexport type DiscoverySkillSummary =\n | Omit<ReadyDiscoveredSkill, \"evals\">\n | Exclude<DiscoveredSkill, ReadyDiscoveredSkill>;\n\nexport function discoverSkills(roots: readonly string[]): DiscoveryResult {\n const missingRoots: string[] = [];\n const skills: DiscoveredSkill[] = [];\n\n for (const root of roots) {\n if (!existsSync(root)) {\n missingRoots.push(root);\n continue;\n }\n\n const entries = readdirSync(root, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .sort((left, right) => left.name.localeCompare(right.name));\n for (const entry of entries) {\n const skillDirectory = join(root, entry.name);\n if (!existsSync(join(skillDirectory, \"SKILL.md\"))) continue;\n skills.push(describeSkill(entry.name, root, skillDirectory));\n }\n }\n\n return { missingRoots, skills };\n}\n\nexport function discoveryReport(discovery: DiscoveryResult): DiscoveryReport {\n return {\n missingRoots: discovery.missingRoots,\n skills: discovery.skills.map((skill) => {\n if (skill.status !== \"ready\") return skill;\n // Parsed prompts are execution input, not listing metadata. Keep list --json compact and\n // avoid exposing prompt contents when callers only asked what skills are available.\n return {\n caseCount: skill.caseCount,\n class: skill.class,\n hasSkillval: skill.hasSkillval,\n name: skill.name,\n root: skill.root,\n skillDirectory: skill.skillDirectory,\n status: skill.status,\n validationError: skill.validationError,\n };\n }),\n };\n}\n\nexport function selectSkills(\n discovery: DiscoveryResult,\n requestedNames: readonly string[],\n): readonly ReadyDiscoveredSkill[] {\n const byName = new Map<string, DiscoveredSkill>();\n for (const skill of discovery.skills) {\n if (!byName.has(skill.name)) byName.set(skill.name, skill);\n }\n\n if (requestedNames.length === 0) {\n return [...byName.values()].filter(\n (skill): skill is ReadyDiscoveredSkill => skill.status === \"ready\",\n );\n }\n\n return requestedNames.map((name) => {\n const skill = byName.get(name);\n if (skill === undefined) {\n throw new Error(`skill \"${name}\" not found under configured roots`);\n }\n if (skill.status === \"missing\") {\n throw new Error(`skill \"${name}\" has no skillval.yml`);\n }\n if (skill.status === \"invalid\") {\n throw new Error(skill.validationError);\n }\n return skill;\n });\n}\n\nfunction describeSkill(name: string, root: string, skillDirectory: string): DiscoveredSkill {\n const caseFilePath = join(skillDirectory, \"skillval.yml\");\n if (!existsSync(caseFilePath)) {\n return {\n caseCount: 0,\n class: undefined,\n hasSkillval: false,\n name,\n root,\n skillDirectory,\n status: \"missing\",\n validationError: undefined,\n };\n }\n\n let evals: SkillEvals;\n try {\n evals = readCaseFile(caseFilePath, name);\n } catch (error) {\n return {\n caseCount: 0,\n class: \"invalid\",\n hasSkillval: true,\n name,\n root,\n skillDirectory,\n status: \"invalid\",\n validationError: error instanceof Error ? error.message : String(error),\n };\n }\n\n return {\n caseCount: evals.cases.length,\n class: evals.class,\n evals,\n hasSkillval: true,\n name,\n root,\n skillDirectory,\n status: \"ready\",\n validationError: undefined,\n };\n}\n","/** Adapts YAML case files into values validated by the executable case contract. */\nimport { readFileSync, statSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport { CaseContractError, parseCaseValue } from \"./case-contract.js\";\nimport { walkFixtureEntries } from \"./fixture.js\";\nimport type { Fixture, SkillEvals } from \"./types.js\";\n\nexport class CaseFileError extends CaseContractError {\n public constructor(message: string, code = \"CASE_FILE_INVALID\") {\n super(message, code);\n this.name = \"CaseFileError\";\n }\n}\n\nexport function readCaseFile(path: string, expectedSkill?: string): SkillEvals {\n const evals = parseCaseFile(readFileSync(path, \"utf8\"), path, expectedSkill);\n // Fixture directories are validated here, not in the pure contract, because only the reader\n // knows where the case file actually lives on disk.\n const baseDirectory = dirname(path);\n assertFixtureDirectory(evals.fixture, `${path} suite fixture`, baseDirectory);\n for (const evalCase of evals.cases) {\n assertFixtureDirectory(\n evalCase.fixture,\n `${path} case \"${evalCase.id}\" fixture`,\n baseDirectory,\n );\n }\n return evals;\n}\n\nfunction assertFixtureDirectory(\n fixture: Fixture | undefined,\n subject: string,\n baseDirectory: string,\n): void {\n if (fixture?.path === undefined) return;\n const directory = join(baseDirectory, fixture.path);\n const stats = statSync(directory, { throwIfNoEntry: false });\n if (stats === undefined) {\n throw new CaseFileError(\n `${subject} path \"${fixture.path}\" does not exist`,\n \"CASE_FIXTURE_INVALID\",\n );\n }\n if (!stats.isDirectory()) {\n throw new CaseFileError(\n `${subject} path \"${fixture.path}\" is not a directory`,\n \"CASE_FIXTURE_INVALID\",\n );\n }\n try {\n walkFixtureEntries(directory);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n throw new CaseFileError(`${subject} path \"${fixture.path}\" ${detail}`, \"CASE_FIXTURE_INVALID\");\n }\n}\n\nexport function parseCaseFile(\n source: string,\n path = \"skillval.yml\",\n expectedSkill?: string,\n): SkillEvals {\n let parsed: unknown;\n try {\n parsed = parseYaml(source);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n throw new CaseFileError(`${path} YAML is invalid: ${detail}`, \"CASE_FILE_YAML_INVALID\");\n }\n\n try {\n return parseCaseValue(parsed, path, expectedSkill);\n } catch (error) {\n if (error instanceof CaseContractError) {\n throw new CaseFileError(error.message, error.code);\n }\n throw error;\n }\n}\n","/** Defines the case-file contract used for static types, runtime validation, and JSON Schema. */\nimport type { Static } from \"typebox\";\nimport Type from \"typebox\";\nimport { Check as checkSchema, Errors as schemaErrors } from \"typebox/value\";\nimport { GRADER_NAMES, graderSupportsMode } from \"./graders.js\";\n\nconst classificationSchema = Type.Enum([\"capability\", \"preference\"]);\nconst nonEmptyStringSchema = Type.String({ minLength: 1, pattern: String.raw`\\S` });\nconst stringArraySchema = Type.Readonly(Type.Array(Type.String()));\nexport const armSchema = Type.Enum([\"baseline\", \"skill\"]);\n\n// These schemas are executable at runtime and are also serialized into schemas/ for editor tooling.\nexport const fixtureSchema = Type.ReadonlyObject(\n Type.Object({\n path: Type.Optional(\n Type.String({\n description: \"Directory relative to skillval.yml, copied into the workspace.\",\n minLength: 1,\n pattern: String.raw`\\S`,\n }),\n ),\n setup: Type.Optional(\n Type.Readonly(\n Type.Array(nonEmptyStringSchema, {\n description: \"Shell commands run sequentially inside the workspace after the copy.\",\n }),\n ),\n ),\n }),\n { additionalProperties: false, minProperties: 1 },\n);\n\nexport const caseAssertSchema = Type.ReadonlyObject(\n Type.Object({\n graders: Type.Optional(\n Type.Readonly(Type.Array(Type.Enum(GRADER_NAMES), { uniqueItems: true })),\n ),\n must_match: Type.Optional(stringArraySchema),\n must_not_match: Type.Optional(stringArraySchema),\n }),\n { additionalProperties: false },\n);\n\nexport const evalCaseSchema = Type.ReadonlyObject(\n Type.Object({\n arms: Type.Optional(\n Type.Readonly(\n Type.Array(armSchema, {\n uniqueItems: true,\n }),\n ),\n ),\n assert: Type.Optional(caseAssertSchema),\n fixture: Type.Optional(fixtureSchema),\n id: nonEmptyStringSchema,\n mode: Type.Enum([\"generation\", \"trigger\"]),\n prompt: nonEmptyStringSchema,\n rule: Type.Optional(Type.String()),\n should_trigger: Type.Optional(Type.Boolean()),\n trials: Type.Optional(Type.Integer({ maximum: 5, minimum: 1 })),\n type: Type.Optional(classificationSchema),\n }),\n { additionalProperties: false },\n);\n\nexport const skillEvalsSchema = Type.ReadonlyObject(\n Type.Object({\n cases: Type.Readonly(Type.Array(evalCaseSchema)),\n class: classificationSchema,\n fixture: Type.Optional(fixtureSchema),\n skill: nonEmptyStringSchema,\n }),\n {\n $id: \"https://raw.githubusercontent.com/dungle-scrubs/skillval/main/schemas/skillval.schema.json\",\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n additionalProperties: false,\n title: \"skillval case file\",\n },\n);\n\nexport type Arm = Static<typeof armSchema>;\nexport type CaseAssert = Static<typeof caseAssertSchema>;\nexport type EvalCase = Static<typeof evalCaseSchema>;\nexport type Fixture = Static<typeof fixtureSchema>;\nexport type SkillEvals = Static<typeof skillEvalsSchema>;\n\nexport class CaseContractError extends Error {\n public readonly code: string;\n\n public constructor(message: string, code = \"CASE_FILE_INVALID\") {\n super(message);\n this.code = code;\n this.name = \"CaseContractError\";\n }\n}\n\nexport function parseCaseValue(value: unknown, path: string, expectedSkill?: string): SkillEvals {\n if (!checkSchema(skillEvalsSchema, value)) {\n const [firstError] = schemaErrors(skillEvalsSchema, value);\n const location = firstError?.instancePath.replaceAll(\"/\", \".\").replace(/^\\./, \"\");\n if (location?.endsWith(\".trials\")) {\n const match = /cases\\.(\\d+)\\.trials$/.exec(location);\n const caseIndex = match?.[1] ?? \"unknown\";\n throw new CaseContractError(\n `${path} case at index ${caseIndex} trials must be an integer from 1 through 5`,\n );\n }\n const subject = location === undefined || location === \"\" ? path : `${path} ${location}`;\n throw new CaseContractError(`${subject} ${firstError?.message ?? \"is invalid\"}`);\n }\n\n if (expectedSkill !== undefined && value.skill !== expectedSkill) {\n throw new CaseContractError(\n `${path} declares skill \"${value.skill}\", expected \"${expectedSkill}\"`,\n );\n }\n\n const ids = new Set<string>();\n for (const evalCase of value.cases) {\n // Semantic rules that depend on sibling cases, JavaScript regex compilation, or runtime\n // registries remain here. Keeping them beside the structural schema preserves one owner.\n if (ids.has(evalCase.id)) {\n throw new CaseContractError(`${path} case id \"${evalCase.id}\" is duplicated`);\n }\n ids.add(evalCase.id);\n validatePatterns(evalCase, path);\n validateGraders(evalCase, path);\n }\n return value;\n}\n\nfunction validateGraders(evalCase: EvalCase, path: string): void {\n for (const grader of evalCase.assert?.graders ?? []) {\n if (!graderSupportsMode(grader, evalCase.mode)) {\n throw new CaseContractError(\n `${path} case \"${evalCase.id}\" grader \"${grader}\" does not support ${evalCase.mode} mode`,\n );\n }\n }\n}\n\nfunction validatePatterns(evalCase: EvalCase, path: string): void {\n const fields = [\"must_match\", \"must_not_match\"] as const;\n for (const field of fields) {\n for (const pattern of evalCase.assert?.[field] ?? []) {\n try {\n new RegExp(pattern, \"m\");\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n throw new CaseContractError(\n `${path} case \"${evalCase.id}\" has invalid ${field} regex \"${pattern}\": ${detail}`,\n );\n }\n }\n }\n}\n","/** Owns the deterministic grader catalog, mode support, and grader implementations. */\nimport { spawnSync } from \"node:child_process\";\nimport { existsSync, writeFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join } from \"node:path\";\n\ntype CaseMode = \"generation\" | \"trigger\";\n\ninterface GradableCase {\n readonly assert?: {\n readonly graders?: readonly GraderName[];\n };\n}\n\ninterface GraderCheck {\n readonly detail: string;\n readonly name: string;\n readonly pass: boolean;\n}\n\ninterface Grader {\n readonly modes: readonly CaseMode[];\n run(workspace: string): GraderCheck;\n}\n\nconst packageRequire = createRequire(import.meta.url);\n// This registry is the sole source of grader names, supported modes, and implementations.\nconst graders = {\n tsc: {\n modes: [\"generation\"],\n run: gradeTsc,\n },\n} satisfies Readonly<Record<string, Grader>>;\n\nexport type GraderName = keyof typeof graders;\n// The case contract derives its allowed grader values from the registry keys.\nexport const GRADER_NAMES = Object.keys(graders) as GraderName[];\n\nexport function graderSupportsMode(name: GraderName, mode: CaseMode): boolean {\n const modes: readonly CaseMode[] = graders[name].modes;\n return modes.includes(mode);\n}\n\nexport function runGraders(evalCase: GradableCase, workspace: string): readonly GraderCheck[] {\n return (evalCase.assert?.graders ?? []).map((name) => graders[name].run(workspace));\n}\n\nfunction gradeTsc(workspace: string): GraderCheck {\n if (!existsSync(join(workspace, \"package.json\"))) {\n writeFileSync(join(workspace, \"package.json\"), '{ \"type\": \"module\" }\\n');\n }\n const nodeTypesDirectory = dirname(packageRequire.resolve(\"@types/node/package.json\"));\n writeFileSync(\n join(workspace, \"tsconfig.json\"),\n JSON.stringify({\n compilerOptions: {\n lib: [\"es2023\"],\n module: \"esnext\",\n moduleResolution: \"bundler\",\n noEmit: true,\n noUncheckedIndexedAccess: true,\n strict: true,\n target: \"es2023\",\n typeRoots: [dirname(nodeTypesDirectory)],\n types: [\"node\"],\n },\n }),\n );\n const typescriptBinary = packageRequire.resolve(\"typescript/bin/tsc\");\n const result = spawnSync(typescriptBinary, [\"-p\", workspace], {\n encoding: \"utf8\",\n timeout: 120_000,\n });\n return {\n detail: result.status === 0 ? \"compiles strict\" : (result.stdout ?? \"\").slice(0, 500),\n name: \"tsc\",\n pass: result.status === 0,\n };\n}\n","/** Prepares trial workspaces from case fixtures: content copy, setup commands, identity hashing. */\nimport { spawnSync } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { cpSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport type { Fixture } from \"./case-contract.js\";\nimport type { FixtureCommandResult } from \"./types.js\";\nimport { SKIPPED_DIRECTORIES } from \"./utils.js\";\n\n// Setup commands are workspace staging (git init, file moves), not agent work; a minute is ample.\nconst SETUP_COMMAND_TIMEOUT_MS = 60_000;\n\nexport interface ResolvedFixture {\n readonly directory: string | undefined;\n readonly hash: string;\n readonly setup: readonly string[];\n}\n\nexport class FixtureSetupError extends Error {\n public readonly results: readonly FixtureCommandResult[];\n\n public constructor(message: string, results: readonly FixtureCommandResult[]) {\n super(message);\n this.name = \"FixtureSetupError\";\n this.results = results;\n }\n}\n\nexport function selectFixture(\n caseFixture: Fixture | undefined,\n suiteFixture: Fixture | undefined,\n): Fixture | undefined {\n // A per-case fixture replaces the suite default entirely; path and setup never merge.\n return caseFixture ?? suiteFixture;\n}\n\nexport function resolveFixture(\n fixture: Fixture | undefined,\n baseDirectory: string,\n): ResolvedFixture | undefined {\n if (fixture === undefined) return undefined;\n const directory = fixture.path === undefined ? undefined : join(baseDirectory, fixture.path);\n const setup = fixture.setup ?? [];\n return { directory, hash: fixtureIdentityHash(directory, setup), setup };\n}\n\ninterface FixtureEntry {\n readonly absolutePath: string;\n readonly executable: boolean;\n readonly path: string;\n readonly type: \"directory\" | \"file\";\n}\n\n/**\n * Walks a fixture directory into a deterministic manifest, rejecting symlinks and special files.\n * Symlinks are refused because a copied link can resolve back into the source fixture and let\n * setup commands mutate it; links belong in setup commands instead.\n */\nexport function walkFixtureEntries(directory: string): FixtureEntry[] {\n const entries: FixtureEntry[] = [];\n\n function visit(current: string, prefix: string): void {\n const dirents = [...readdirSync(current, { withFileTypes: true })].sort((left, right) =>\n left.name.localeCompare(right.name),\n );\n for (const dirent of dirents) {\n if (SKIPPED_DIRECTORIES.has(dirent.name)) continue;\n const absolutePath = join(current, dirent.name);\n const path = prefix === \"\" ? dirent.name : `${prefix}/${dirent.name}`;\n if (dirent.isSymbolicLink()) {\n throw new Error(\n `contains unsupported symlink \"${path}\"; create links with setup commands instead`,\n );\n }\n if (dirent.isDirectory()) {\n entries.push({ absolutePath, executable: false, path, type: \"directory\" });\n visit(absolutePath, path);\n } else if (dirent.isFile()) {\n const executable = (statSync(absolutePath).mode & 0o111) !== 0;\n entries.push({ absolutePath, executable, path, type: \"file\" });\n } else {\n throw new Error(`contains unsupported special file \"${path}\"`);\n }\n }\n }\n\n visit(directory, \"\");\n return entries;\n}\n\nexport function fixtureIdentityHash(\n directory: string | undefined,\n setup: readonly string[],\n): string {\n // Each entry is framed with its type, path, mode, and byte length so file bytes can never\n // masquerade as entry boundaries, and raw bytes are hashed so binary files cannot collide\n // through lossy text decoding.\n const hash = createHash(\"sha256\");\n if (directory !== undefined) {\n for (const entry of walkFixtureEntries(directory)) {\n if (entry.type === \"directory\") {\n hash.update(`D\\0${entry.path}\\0`);\n continue;\n }\n const content = readFileSync(entry.absolutePath);\n hash.update(`F\\0${entry.path}\\0${entry.executable ? \"x\" : \"-\"}\\0${content.byteLength}\\0`);\n hash.update(content);\n }\n }\n hash.update(`S\\0${JSON.stringify(setup)}`);\n return hash.digest(\"hex\");\n}\n\nexport function applyFixture(\n fixture: ResolvedFixture,\n workspace: string,\n home: string,\n): readonly FixtureCommandResult[] {\n if (fixture.directory !== undefined) {\n // verbatimSymlinks guards the window between hashing (which rejects symlinks) and copying:\n // a link that appears mid-run is copied inert instead of resolving into the source fixture.\n cpSync(fixture.directory, workspace, {\n filter: (source) => !SKIPPED_DIRECTORIES.has(basename(source)),\n recursive: true,\n verbatimSymlinks: true,\n });\n }\n\n const results: FixtureCommandResult[] = [];\n for (const command of fixture.setup) {\n // Minimal environment: PATH for tool lookup plus the throwaway trial home, nothing inherited.\n // SIGKILL on timeout because SIGTERM is trappable and would let a hung command run forever.\n const outcome = spawnSync(command, {\n cwd: workspace,\n encoding: \"utf8\",\n env: { HOME: home, PATH: process.env.PATH ?? \"\" },\n killSignal: \"SIGKILL\",\n shell: true,\n timeout: SETUP_COMMAND_TIMEOUT_MS,\n });\n results.push({\n command,\n exitCode: outcome.status,\n signal: outcome.signal ?? null,\n stderr: outcome.stderr ?? \"\",\n stdout: outcome.stdout ?? \"\",\n });\n if (outcome.error !== undefined || outcome.status !== 0) {\n const timedOut = (outcome.error as NodeJS.ErrnoException | undefined)?.code === \"ETIMEDOUT\";\n const reason = timedOut\n ? `timed out after ${SETUP_COMMAND_TIMEOUT_MS / 1000}s`\n : (outcome.error?.message ??\n (outcome.signal !== null\n ? `terminated by ${outcome.signal}`\n : `exit code ${outcome.status}`));\n throw new FixtureSetupError(`fixture setup failed: \"${command}\" (${reason})`, results);\n }\n }\n return results;\n}\n","/** Orchestrates discovery, trial arms, voting, caching, cleanup, and report persistence. */\nimport { mkdirSync, mkdtempSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { ArmCache } from \"./cache.js\";\nimport type { SkillvalConfig } from \"./config.js\";\nimport { resolveStateDirectory } from \"./config.js\";\nimport type { ReadyDiscoveredSkill } from \"./discovery.js\";\nimport { discoverSkills, selectSkills } from \"./discovery.js\";\nimport { createExecutor } from \"./executors/index.js\";\nimport type { Executor, ExecutorMetadata } from \"./executors/types.js\";\nimport type { ResolvedFixture } from \"./fixture.js\";\nimport { applyFixture, FixtureSetupError, resolveFixture, selectFixture } from \"./fixture.js\";\nimport { gradeTrial } from \"./grade.js\";\nimport type { Arm, ArmResult, CaseResult, EvalCase, TrialResult } from \"./types.js\";\nimport { sha256, skillContentHash } from \"./utils.js\";\nimport { clampedTrialCount, hasMajority, shouldEscalate } from \"./vote.js\";\n\nexport interface RunOptions {\n readonly caseFilter: string | undefined;\n readonly requestedSkills: readonly string[];\n readonly skipBaseline: boolean;\n readonly useCache: boolean;\n}\n\nexport interface SkillReport {\n readonly cases: readonly CaseResult[];\n readonly class: \"capability\" | \"preference\";\n readonly contentHash: string;\n}\n\nexport interface RunReport {\n readonly executor: ExecutorMetadata;\n readonly runHash: string;\n readonly skills: Readonly<Record<string, SkillReport>>;\n}\n\nexport interface RunOutcome {\n readonly failures: number;\n readonly noops: number;\n readonly report: RunReport;\n readonly reportPath: string;\n}\n\ninterface ArmContext {\n readonly cache: ArmCache;\n readonly evalCase: EvalCase;\n readonly executor: Executor;\n readonly fixture: ResolvedFixture | undefined;\n readonly skill: ReadyDiscoveredSkill;\n readonly skillHash: string;\n readonly useCache: boolean;\n}\n\ninterface CaseContext {\n readonly cache: ArmCache;\n readonly executor: Executor;\n readonly skill: ReadyDiscoveredSkill;\n readonly skillHash: string;\n readonly skipBaseline: boolean;\n readonly useCache: boolean;\n}\n\nexport function runEvaluation(\n config: SkillvalConfig,\n options: RunOptions,\n log: (message: string) => void,\n): RunOutcome {\n const discovery = discoverSkills(config.roots);\n const selectedSkills = selectSkills(discovery, options.requestedSkills);\n const executor = createExecutor(config.executor);\n const stateDirectory = resolveStateDirectory();\n const cache = new ArmCache(stateDirectory);\n const skillInputs = selectedSkills.map((skill) => ({\n contentHash: skillContentHash(skill.skillDirectory),\n skill,\n }));\n const runHash = participatingSkillsHash(\n skillInputs.map(({ contentHash, skill }) => ({ contentHash, name: skill.name })),\n );\n const skillReports: Record<string, SkillReport> = {};\n let failures = 0;\n let noops = 0;\n\n for (const { contentHash, skill } of skillInputs) {\n const evals = skill.evals;\n log(`${skill.name} (${evals.class}, ${contentHash.slice(0, 12)}):`);\n const cases = evals.cases\n .filter((evalCase) => options.caseFilter === undefined || evalCase.id === options.caseFilter)\n .map((evalCase) =>\n runCase(\n {\n cache,\n executor,\n skill,\n skillHash: contentHash,\n skipBaseline: options.skipBaseline,\n useCache: options.useCache,\n },\n evalCase,\n log,\n ),\n );\n skillReports[skill.name] = { cases, class: evals.class, contentHash };\n failures += cases.filter((result) => !result.pass).length;\n noops += cases.filter((result) => result.noop).length;\n }\n\n const report: RunReport = {\n executor: executor.metadata,\n runHash,\n skills: skillReports,\n };\n const reportDirectory = join(stateDirectory, \"reports\");\n const reportPath = join(reportDirectory, `${runHash}.json`);\n mkdirSync(reportDirectory, { recursive: true });\n writeFileSync(reportPath, JSON.stringify(report, null, 2));\n return { failures, noops, report, reportPath };\n}\n\nexport function participatingSkillsHash(\n skills: readonly { readonly contentHash: string; readonly name: string }[],\n): string {\n return sha256(\n [...skills]\n .sort((left, right) => left.name.localeCompare(right.name))\n .map(({ contentHash, name }) => `${name}\\0${contentHash}`)\n .join(\"\\0\"),\n );\n}\n\nfunction runCase(\n context: CaseContext,\n evalCase: EvalCase,\n log: (message: string) => void,\n): CaseResult {\n const arms = (evalCase.arms ?? [\"skill\"]).filter(\n (arm) => arm === \"skill\" || !context.skipBaseline,\n );\n // Fixture paths are relative to skillval.yml, which sits in the skill directory.\n const fixture = resolveFixture(\n selectFixture(evalCase.fixture, context.skill.evals.fixture),\n context.skill.skillDirectory,\n );\n const results = arms.map((arm) => {\n log(` ${evalCase.id} [${arm}] ...`);\n const result = runArm(\n {\n cache: context.cache,\n evalCase,\n executor: context.executor,\n fixture,\n skill: context.skill,\n skillHash: context.skillHash,\n useCache: context.useCache,\n },\n arm,\n );\n log(\n ` ${evalCase.id} [${arm}] ${result.pass ? \"pass\" : \"FAIL\"}${\n result.cached ? \" (cached)\" : \"\"\n }`,\n );\n return result;\n });\n return {\n arms: results,\n id: evalCase.id,\n noop: results.find((result) => result.arm === \"baseline\")?.pass === true,\n pass: results.find((result) => result.arm === \"skill\")?.pass === true,\n rule: evalCase.rule,\n };\n}\n\nfunction runArm(context: ArmContext, arm: Arm): ArmResult {\n const identity = {\n arm,\n evalCase: context.evalCase,\n executor: context.executor.metadata,\n fixtureHash: context.fixture?.hash,\n skillHash: context.skillHash,\n };\n if (context.useCache) {\n const hit = context.cache.lookup(identity);\n if (hit !== undefined) return hit;\n }\n\n const trials: TrialResult[] = [];\n const wanted = clampedTrialCount(context.evalCase.trials);\n for (let index = 0; index < wanted; index += 1) {\n trials.push(runTrial(context, arm));\n }\n // A disagreement makes the configured sample inconclusive, so collect the full five trials.\n while (shouldEscalate(trials)) trials.push(runTrial(context, arm));\n\n const result: ArmResult = {\n arm,\n cached: false,\n pass: hasMajority(trials),\n trials,\n };\n context.cache.store(identity, result);\n return result;\n}\n\nfunction runTrial(context: ArmContext, arm: Arm): TrialResult {\n // The runner owns generic resource lifecycle; adapters own provider-specific setup inside it.\n const workspace = mkdtempSync(join(tmpdir(), `skillval-${context.evalCase.id}-`));\n const trialHome = mkdtempSync(join(tmpdir(), \"skillval-home-\"));\n\n try {\n const fixtureSetup =\n context.fixture === undefined\n ? undefined\n : applyFixture(context.fixture, workspace, trialHome);\n const trace = context.executor.runTrial({\n arm,\n evalCase: context.evalCase,\n home: trialHome,\n skillDirectory: context.skill.skillDirectory,\n skillName: context.skill.name,\n workspace,\n });\n const checks = gradeTrial(context.evalCase, arm, trace, workspace);\n return {\n checks,\n fixtureSetup,\n pass: checks.every((check) => check.pass),\n usage: trace.usage,\n };\n } catch (error) {\n if (error instanceof FixtureSetupError) {\n // Workspace staging failed before the agent ran; this is infrastructure, not grading.\n return {\n checks: [{ detail: error.message, name: \"fixture-setup\", pass: false }],\n fixtureSetup: error.results,\n pass: false,\n usage: undefined,\n };\n }\n const detail = error instanceof Error ? error.message : String(error);\n return {\n checks: [{ detail, name: \"run\", pass: false }],\n pass: false,\n usage: undefined,\n };\n } finally {\n // Trials may contain generated source or credentials-related environment state. Always clean\n // both directories, including executor and grader failure paths.\n rmSync(workspace, { force: true, recursive: true });\n rmSync(trialHome, { force: true, recursive: true });\n }\n}\n","/** Owns arm-result persistence and keeps cache-key construction private from the runner. */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { resolveStateDirectory } from \"./config.js\";\nimport type { ExecutorMetadata } from \"./executors/types.js\";\nimport type { Arm, ArmResult, EvalCase } from \"./types.js\";\nimport { sha256 } from \"./utils.js\";\n\n// Bump this whenever execution or grading semantics change so old results cannot be reused.\nexport const RUNNER_VERSION = 6;\n\nexport interface ArmCacheIdentity {\n readonly arm: Arm;\n readonly evalCase: EvalCase;\n readonly executor: ExecutorMetadata;\n readonly fixtureHash?: string;\n readonly skillHash: string;\n}\n\nexport class ArmCache {\n readonly #stateDirectory: string;\n\n public constructor(stateDirectory = resolveStateDirectory()) {\n this.#stateDirectory = stateDirectory;\n }\n\n public lookup(identity: ArmCacheIdentity): ArmResult | undefined {\n const path = this.#path(identity);\n if (!existsSync(path)) return undefined;\n return { ...(JSON.parse(readFileSync(path, \"utf8\")) as ArmResult), cached: true };\n }\n\n public store(identity: ArmCacheIdentity, result: ArmResult): void {\n const path = this.#path(identity);\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, JSON.stringify(result));\n }\n\n #path(identity: ArmCacheIdentity): string {\n // Every input that can change an arm result belongs in this identity.\n const parts = [\n String(RUNNER_VERSION),\n identity.skillHash,\n JSON.stringify(identity.evalCase),\n identity.arm,\n identity.executor.name,\n identity.executor.version,\n identity.executor.model,\n ];\n // Appended conditionally so fixture-free identities keep their historical keys.\n if (identity.fixtureHash !== undefined) parts.push(identity.fixtureHash);\n const key = sha256(parts.join(\"\\0\"));\n return join(this.#stateDirectory, \"cache\", `${key}.json`);\n }\n}\n","/** Composes trace, trigger, regex, and registered deterministic checks for one trial. */\nimport { readFileSync } from \"node:fs\";\nimport { relative } from \"node:path\";\nimport { runGraders } from \"./graders.js\";\nimport type { Arm, Check, EvalCase, Trace } from \"./types.js\";\nimport { walkFiles } from \"./utils.js\";\n\nconst INJECTED_FILES = new Set([\"package.json\", \"tsconfig.json\"]);\nexport function gradeTrial(evalCase: EvalCase, arm: Arm, trace: Trace, workspace: string): Check[] {\n const checks: Check[] = [];\n\n checks.push({\n detail: trace.completed ? \"turn.completed seen\" : \"no turn.completed in trace\",\n name: \"trace\",\n pass: trace.completed,\n });\n\n if (evalCase.should_trigger !== undefined && arm === \"skill\") {\n checks.push({\n detail: `invoked=${trace.invoked}, expected=${evalCase.should_trigger}`,\n name: \"trigger\",\n pass: trace.invoked === evalCase.should_trigger,\n });\n }\n\n const gradedText =\n evalCase.mode === \"generation\"\n ? walkFiles(workspace)\n .filter((file) => !INJECTED_FILES.has(relative(workspace, file)))\n .map((file) => `=== ${relative(workspace, file)} ===\\n${readFileSync(file, \"utf8\")}`)\n .join(\"\\n\")\n : trace.agentText;\n\n for (const pattern of evalCase.assert?.must_match ?? []) {\n const pass = new RegExp(pattern, \"m\").test(gradedText);\n checks.push({\n detail: pass ? pattern : `${pattern} | got: ${gradedText.slice(0, 400)}`,\n name: \"must_match\",\n pass,\n });\n }\n for (const pattern of evalCase.assert?.must_not_match ?? []) {\n checks.push({\n detail: pattern,\n name: \"must_not_match\",\n pass: !new RegExp(pattern, \"m\").test(gradedText),\n });\n }\n\n checks.push(...runGraders(evalCase, workspace));\n return checks;\n}\n","import type { TrialResult } from \"./types.js\";\n\nexport function clampedTrialCount(configured: number | undefined): number {\n return Math.min(5, Math.max(1, configured ?? 1));\n}\n\nexport function hasMajority(trials: readonly Pick<TrialResult, \"pass\">[]): boolean {\n const passes = trials.filter((trial) => trial.pass).length;\n return passes * 2 > trials.length;\n}\n\nexport function shouldEscalate(trials: readonly Pick<TrialResult, \"pass\">[]): boolean {\n return new Set(trials.map((trial) => trial.pass)).size > 1 && trials.length < 5;\n}\n"],"mappings":"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","names":["readFileSync","homedir","readFileSync","join","join","readFileSync","homedir","readFileSync","existsSync","readdirSync","join","readFileSync","statSync","dirname","join","parseYaml","Type","checkSchema","schemaErrors","spawnSync","existsSync","join","Type","checkSchema","schemaErrors","spawnSync","createHash","readdirSync","readFileSync","join","join","readdirSync","createHash","readFileSync","spawnSync","readFileSync","dirname","join","statSync","parseYaml","existsSync","readdirSync","join","mkdirSync","writeFileSync","join","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","existsSync","readFileSync","mkdirSync","dirname","writeFileSync","join","readFileSync","relative","relative","readFileSync","join","mkdirSync","writeFileSync"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/config.ts","../src/config-contract.ts","../src/executors/claude.ts","../src/utils.ts","../src/executors/types.ts","../src/executors/codex.ts","../src/executors/pi.ts","../src/executors/index.ts","../src/discovery.ts","../src/case-file.ts","../src/case-contract.ts","../src/graders.ts","../src/fixture.ts","../src/runner.ts","../src/cache.ts","../src/grade.ts","../src/vote.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/** Defines the command-line transport and renders runner and discovery results. */\nimport { Command } from \"commander\";\nimport { loadConfig, resolveConfigPath } from \"./config.js\";\nimport type { DiscoveredSkill } from \"./discovery.js\";\nimport { discoverSkills, discoveryReport } from \"./discovery.js\";\nimport { runEvaluation } from \"./runner.js\";\n\ninterface GlobalOptions {\n readonly config?: string;\n}\n\ninterface ListOptions {\n readonly json?: boolean;\n}\n\ninterface RunCommandOptions {\n readonly allowUnsandboxedPi?: boolean;\n readonly cache: boolean;\n readonly case?: string;\n readonly effort?: string;\n readonly json?: boolean;\n readonly model?: string;\n readonly skipBaseline?: boolean;\n}\n\nconst program = new Command();\n\nprogram\n .name(\"skillval\")\n .description(\"Evaluate agent skills with deterministic graders\")\n .configureHelp({ showGlobalOptions: true })\n .version(\"0.3.0\") // x-release-please-version\n .option(\"--config <path>\", \"read configuration from this path\");\n\nprogram\n .command(\"run\")\n .description(\n \"Run selected cases and return a report whose exit status fails when any skill arm fails\",\n )\n .argument(\"[skill...]\", \"skill names; omit to run every skill with skillval.yml\")\n .option(\"--case <id>\", \"run only the case with this id\")\n .option(\"--model <model>\", \"model for the executor to use this run\")\n .option(\"--effort <level>\", \"effort/thinking level for the executor to use this run\")\n .option(\"--no-cache\", \"ignore cached arm results\")\n .option(\"--skip-baseline\", \"do not run baseline arms\")\n .option(\n \"--allow-unsandboxed-pi\",\n \"acknowledge that pi generation trials run without an OS sandbox\",\n )\n .option(\"--json\", \"return the complete report as JSON\")\n .action((skills: string[], options: RunCommandOptions, command: Command): void => {\n const globalOptions = command.optsWithGlobals() as GlobalOptions & RunCommandOptions;\n const configPath = resolveConfigPath({ cliPath: globalOptions.config });\n const config = loadConfig(configPath);\n const outcome = runEvaluation(\n config,\n {\n allowUnsandboxedPi: options.allowUnsandboxedPi === true,\n caseFilter: options.case,\n effort: options.effort,\n model: options.model,\n requestedSkills: skills,\n skipBaseline: options.skipBaseline === true,\n useCache: options.cache,\n },\n options.json === true ? () => undefined : (message) => console.log(message),\n );\n\n if (options.json === true) {\n console.log(JSON.stringify(outcome.report, null, 2));\n } else {\n console.log(`report: ${outcome.reportPath}`);\n if (outcome.noops > 0) {\n console.log(`no-op alert: ${outcome.noops} case(s) pass at baseline - prune candidates`);\n }\n console.log(\n outcome.failures === 0 ? \"all cases passed\" : `${outcome.failures} case(s) FAILED`,\n );\n }\n process.exitCode = outcome.failures > 0 ? 1 : 0;\n });\n\nprogram\n .command(\"list\")\n .description(\n \"Return discovered skills, evaluation metadata, and configured roots that are missing\",\n )\n .option(\"--json\", \"return the complete discovery result as JSON\")\n .action((options: ListOptions, command: Command): void => {\n const globalOptions = command.optsWithGlobals() as GlobalOptions & ListOptions;\n const configPath = resolveConfigPath({ cliPath: globalOptions.config });\n const config = loadConfig(configPath);\n const discovery = discoverSkills(config.roots);\n if (options.json === true) {\n console.log(JSON.stringify(discoveryReport(discovery), null, 2));\n return;\n }\n\n printSkillTable(discovery.skills);\n for (const skill of discovery.skills) {\n if (skill.status === \"invalid\") console.log(`invalid skill: ${skill.validationError}`);\n }\n for (const root of discovery.missingRoots) console.log(`missing root: ${root}`);\n });\n\nexport async function main(): Promise<void> {\n try {\n await program.parseAsync(process.argv);\n } catch (error) {\n console.error(`error: ${error instanceof Error ? error.message : String(error)}`);\n process.exitCode = 1;\n }\n}\n\nfunction printSkillTable(skills: readonly DiscoveredSkill[]): void {\n const rows = [\n [\"NAME\", \"ROOT\", \"CLASS\", \"CASES\", \"HAS-SKILLVAL.YML\"],\n ...skills.map((skill) => [\n skill.name,\n skill.root,\n skill.class ?? \"-\",\n String(skill.caseCount),\n skill.hasSkillval ? \"true\" : \"false\",\n ]),\n ];\n const widths = rows[0]?.map((_, column) =>\n Math.max(...rows.map((row) => row[column]?.length ?? 0)),\n );\n for (const row of rows) {\n console.log(\n row\n .map((cell, column) => cell.padEnd(widths?.[column] ?? cell.length))\n .join(\" \")\n .trimEnd(),\n );\n }\n}\n\nawait main();\n","/** Resolves configuration and state paths, then loads validated configuration values. */\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { resolve } from \"node:path\";\nimport { Check as checkSchema, Errors as schemaErrors } from \"typebox/value\";\nimport { parse as parseYaml } from \"yaml\";\nimport type { ConfigFile } from \"./config-contract.js\";\nimport { configFileSchema } from \"./config-contract.js\";\n\nexport type SkillvalConfig = ConfigFile;\n\nexport interface ConfigPathOptions {\n readonly cliPath?: string;\n readonly environment?: NodeJS.ProcessEnv;\n readonly home?: string;\n}\n\nexport class ConfigError extends Error {\n public readonly code: string;\n\n public constructor(message: string, code = \"CONFIG_ERROR\") {\n super(message);\n this.code = code;\n this.name = \"ConfigError\";\n }\n}\n\nexport function resolveConfigPath(options: ConfigPathOptions = {}): string {\n const environment = options.environment ?? process.env;\n const home = options.home ?? homedir();\n const selected =\n options.cliPath ??\n environment.SKILLVAL_CONFIG ??\n (environment.XDG_CONFIG_HOME\n ? resolve(environment.XDG_CONFIG_HOME, \"skillval/config.yml\")\n : resolve(home, \".config/skillval/config.yml\"));\n return resolve(expandHome(selected, home));\n}\n\nexport function expandRoot(root: string, home = homedir()): string {\n return resolve(expandHome(root, home));\n}\n\nexport function loadConfig(path: string, home = homedir()): SkillvalConfig {\n if (!existsSync(path)) {\n throw new ConfigError(`config file not found: ${path}`, \"CONFIG_NOT_FOUND\");\n }\n\n let parsed: unknown;\n try {\n parsed = parseYaml(readFileSync(path, \"utf8\"));\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n throw new ConfigError(`invalid YAML in ${path}: ${detail}`, \"CONFIG_YAML_INVALID\");\n }\n\n if (!checkSchema(configFileSchema, parsed)) {\n const [firstError] = schemaErrors(configFileSchema, parsed);\n const location = firstError?.instancePath.replaceAll(\"/\", \".\").replace(/^\\./, \"\");\n const subject = location === undefined || location === \"\" ? path : `${path} ${location}`;\n throw new ConfigError(`${subject} ${firstError?.message ?? \"is invalid\"}`);\n }\n\n return {\n executor: parsed.executor,\n roots: parsed.roots.map((root) => expandRoot(root, home)),\n };\n}\n\nexport function resolveStateDirectory(\n environment: NodeJS.ProcessEnv = process.env,\n home = homedir(),\n): string {\n return environment.XDG_STATE_HOME\n ? resolve(environment.XDG_STATE_HOME, \"skillval\")\n : resolve(home, \".local/state/skillval\");\n}\n\nfunction expandHome(value: string, home: string): string {\n const withTilde =\n value === \"~\" ? home : value.startsWith(\"~/\") ? `${home}${value.slice(1)}` : value;\n return withTilde.replaceAll(String.raw`\\${HOME}`, home).replaceAll(\"$HOME\", home);\n}\n","/** Defines the configuration contract shared by runtime validation and generated JSON Schema. */\nimport type { Static } from \"typebox\";\nimport Type from \"typebox\";\nimport { EXECUTOR_NAMES } from \"./executors/index.js\";\n\nexport const configFileSchema = Type.ReadonlyObject(\n Type.Object({\n // Names come from the executor registry so configuration cannot advertise a missing adapter.\n executor: Type.Enum(EXECUTOR_NAMES, {\n description: \"Trial executor.\",\n }),\n roots: Type.Readonly(\n Type.Array(Type.String({ minLength: 1, pattern: String.raw`\\S` }), {\n description: \"Directories whose immediate children are agent skill directories.\",\n }),\n ),\n }),\n {\n $id: \"https://raw.githubusercontent.com/dungle-scrubs/skillval/main/schemas/config.schema.json\",\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n additionalProperties: false,\n title: \"skillval configuration\",\n },\n);\n\nexport type ConfigFile = Static<typeof configFileSchema>;\n","/** Implements Claude Code-specific skill seeding, config isolation, invocation, and parsing. */\nimport { spawnSync } from \"node:child_process\";\nimport { copyFileSync, existsSync, mkdirSync, readFileSync, symlinkSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Trace } from \"../types.js\";\nimport { isRecord } from \"../utils.js\";\nimport {\n assertEffortSupported,\n type Executor,\n type ExecutorMetadata,\n type ExecutorOverrides,\n type TrialRequest,\n} from \"./types.js\";\n\nconst TRIAL_TIMEOUT_MS = 15 * 60 * 1000;\n\n// Claude Code effort levels, from `claude --effort`.\nexport const CLAUDE_EFFORT_LEVELS: readonly string[] = [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"];\nexport const CLAUDE_INVOCATION_DETECTION: ExecutorMetadata[\"invocationDetection\"] = \"structured\";\n\nexport class ClaudeExecutor implements Executor {\n public readonly metadata: ExecutorMetadata;\n readonly #overrides: ExecutorOverrides;\n readonly #realConfigDirectory: string;\n\n public constructor(\n overrides: ExecutorOverrides = {},\n realConfigDirectory = defaultConfigDirectory(),\n ) {\n assertEffortSupported(\"claude\", overrides.effort, CLAUDE_EFFORT_LEVELS);\n this.#overrides = overrides;\n this.#realConfigDirectory = realConfigDirectory;\n const detected = detectClaude(realConfigDirectory);\n this.metadata = {\n ...detected,\n model: overrides.model ?? detected.model,\n thinking: overrides.effort ?? detected.thinking,\n };\n }\n\n public runTrial(request: TrialRequest): Trace {\n if (request.arm === \"skill\") seedSkill(request);\n // claude warns and falls back to the default on an unknown --effort, so skillval validates the\n // level at construction; here the requested model and effort pass straight through.\n const selection: string[] = [];\n if (this.#overrides.model !== undefined) selection.push(\"--model\", this.#overrides.model);\n if (this.#overrides.effort !== undefined) selection.push(\"--effort\", this.#overrides.effort);\n // Trigger cases stay read-only but must allow the Skill tool itself, or invocation is blocked\n // before it can be observed. Generation cases auto-approve edits inside the workspace.\n const permissions =\n request.evalCase.mode === \"generation\"\n ? [\"--permission-mode\", \"acceptEdits\"]\n : [\"--permission-mode\", \"dontAsk\", \"--allowedTools\", \"Read,Glob,Grep,Skill\"];\n // Baselines keep authentication but must not see user-level skills: an empty config\n // directory hides them (macOS credentials live in the Keychain; elsewhere the credentials\n // file is copied across so authentication survives the redirect).\n const environment =\n request.arm === \"baseline\"\n ? {\n ...process.env,\n CLAUDE_CONFIG_DIR: prepareBaselineConfig(request.home, this.#realConfigDirectory),\n }\n : { ...process.env };\n const result = spawnSync(\n \"claude\",\n [\n \"-p\",\n request.evalCase.prompt,\n \"--output-format\",\n \"stream-json\",\n \"--verbose\",\n \"--no-session-persistence\",\n ...selection,\n ...permissions,\n ],\n {\n cwd: request.workspace,\n encoding: \"utf8\",\n env: environment,\n maxBuffer: 64 * 1024 * 1024,\n timeout: TRIAL_TIMEOUT_MS,\n },\n );\n if (result.status !== 0) {\n throw new Error(`claude -p exited ${result.status}: ${result.stderr?.slice(-500)}`);\n }\n\n return parseClaudeTrace(result.stdout, request.skillName);\n }\n}\n\nfunction defaultConfigDirectory(): string {\n return process.env.CLAUDE_CONFIG_DIR ?? join(homedir(), \".claude\");\n}\n\nfunction seedSkill(request: TrialRequest): void {\n // Skill installation paths are provider knowledge and intentionally stay inside this adapter.\n const skillsRoot = join(request.workspace, \".claude/skills\");\n mkdirSync(skillsRoot, { recursive: true });\n symlinkSync(request.skillDirectory, join(skillsRoot, request.skillName));\n}\n\nfunction prepareBaselineConfig(home: string, realConfigDirectory: string): string {\n const configDirectory = join(home, \"claude-config\");\n mkdirSync(configDirectory, { recursive: true });\n const credentials = join(realConfigDirectory, \".credentials.json\");\n if (existsSync(credentials)) {\n copyFileSync(credentials, join(configDirectory, \".credentials.json\"));\n }\n return configDirectory;\n}\n\nexport function detectClaude(realConfigDirectory = defaultConfigDirectory()): ExecutorMetadata {\n const version = spawnSync(\"claude\", [\"--version\"], { encoding: \"utf8\" }).stdout?.trim() ?? \"\";\n if (version === \"\") throw new Error(\"claude CLI not found on PATH\");\n let model = \"default\";\n let thinking = \"default\";\n try {\n const settings: unknown = JSON.parse(\n readFileSync(join(realConfigDirectory, \"settings.json\"), \"utf8\"),\n );\n if (isRecord(settings)) {\n if (typeof settings.model === \"string\") model = settings.model;\n if (typeof settings.effort === \"string\") thinking = settings.effort;\n }\n } catch {\n // No readable settings file; the account default model applies.\n }\n return {\n invocationDetection: CLAUDE_INVOCATION_DETECTION,\n model,\n name: \"claude\",\n thinking,\n version,\n };\n}\n\nexport function parseClaudeTrace(stdout: string, skillName: string): Trace {\n let completed = false;\n let invoked = false;\n let invocationEvidence: string | null = null;\n let resultText = \"\";\n const texts: string[] = [];\n let usage: unknown;\n\n for (const line of stdout.split(\"\\n\")) {\n if (line.trim() === \"\") continue;\n let event: unknown;\n try {\n event = JSON.parse(line);\n } catch {\n continue;\n }\n if (!isRecord(event)) continue;\n if (\n event.type === \"assistant\" &&\n isRecord(event.message) &&\n Array.isArray(event.message.content)\n ) {\n for (const block of event.message.content) {\n if (!isRecord(block)) continue;\n if (block.type === \"text\" && typeof block.text === \"string\") texts.push(block.text);\n if (\n block.type === \"tool_use\" &&\n block.name === \"Skill\" &&\n JSON.stringify(block.input ?? \"\").includes(skillName)\n ) {\n invoked = true;\n invocationEvidence ??= `Skill tool_use: ${JSON.stringify(block.input ?? null)}`;\n }\n }\n }\n if (event.type === \"result\") {\n completed = event.is_error === false;\n usage = event.usage;\n if (typeof event.result === \"string\") resultText = event.result;\n }\n }\n\n return {\n agentText: texts.length > 0 ? texts.join(\"\\n\") : resultText,\n completed,\n invocationEvidence,\n invoked,\n usage,\n };\n}\n","import { createHash } from \"node:crypto\";\nimport { readdirSync, readFileSync } from \"node:fs\";\nimport { join, relative } from \"node:path\";\n\nexport function sha256(input: string): string {\n return createHash(\"sha256\").update(input).digest(\"hex\");\n}\n\n// Directories that never contribute to content identity or workspace materialization.\nexport const SKIPPED_DIRECTORIES: ReadonlySet<string> = new Set([\".git\", \"node_modules\"]);\n\nexport function walkFiles(root: string): string[] {\n const files: string[] = [];\n\n function visit(directory: string): void {\n for (const entry of readdirSync(directory, { withFileTypes: true })) {\n if (SKIPPED_DIRECTORIES.has(entry.name)) continue;\n const path = join(directory, entry.name);\n if (entry.isDirectory()) visit(path);\n else if (entry.isFile()) files.push(path);\n }\n }\n\n visit(root);\n return files.sort();\n}\n\nexport function skillContentHash(skillDirectory: string): string {\n const parts = walkFiles(skillDirectory).map(\n (file) => `${relative(skillDirectory, file)}\\n${readFileSync(file, \"utf8\")}`,\n );\n return sha256(parts.join(\"\\0\"));\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","/** Defines the provider-neutral seam between trial orchestration and executor adapters. */\nimport type { Arm, EvalCase, Trace } from \"../types.js\";\n\nexport interface ExecutorMetadata {\n // Records how the adapter decides the invoked trigger signal: \"structured\" means a dedicated\n // tool-use event names the skill; \"heuristic\" means command or argument text is string-matched\n // for <skill>/SKILL.md, so trigger rates are not directly comparable across executors.\n readonly invocationDetection: \"structured\" | \"heuristic\";\n readonly model: string;\n readonly name: string;\n // The thinking/effort level in effect for this run, or \"default\" when neither an override nor the\n // provider configuration sets one. When --effort is passed it holds the requested level; otherwise\n // it records what the harness would do. Either way it is tied to results and cache identity.\n readonly thinking: string;\n readonly version: string;\n}\n\n// Per-run model and effort selection. skillval passes these through to the harness verbatim; each\n// adapter validates the effort against its own vocabulary and applies both to the invocation.\nexport interface ExecutorOverrides {\n readonly effort?: string;\n readonly model?: string;\n}\n\n// Fail fast, before any trial spawns, when a requested effort is not in an adapter's vocabulary.\n// Model support for a given effort is finer-grained and version-specific, so the harness validates\n// the (model, effort) pair itself; skillval owns only the stable per-adapter effort vocabulary.\nexport function assertEffortSupported(\n executor: string,\n effort: string | undefined,\n allowed: readonly string[],\n): void {\n if (effort !== undefined && !allowed.includes(effort)) {\n throw new Error(\n `${executor} does not support effort \"${effort}\"; valid levels: ${allowed.join(\", \")}`,\n );\n }\n}\n\nexport interface TrialRequest {\n readonly arm: Arm;\n readonly evalCase: EvalCase;\n readonly home: string;\n readonly skillDirectory: string;\n readonly skillName: string;\n readonly workspace: string;\n}\n\nexport interface Executor {\n readonly metadata: ExecutorMetadata;\n runTrial(request: TrialRequest): Trace;\n}\n","/** Implements Codex-specific skill seeding, process isolation, invocation, and trace parsing. */\nimport { spawnSync } from \"node:child_process\";\nimport { mkdirSync, readFileSync, symlinkSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Trace } from \"../types.js\";\nimport { isRecord } from \"../utils.js\";\nimport {\n assertEffortSupported,\n type Executor,\n type ExecutorMetadata,\n type ExecutorOverrides,\n type TrialRequest,\n} from \"./types.js\";\n\nconst TRIAL_TIMEOUT_MS = 15 * 60 * 1000;\n\n// codex forwards model_reasoning_effort straight to the Responses API without local validation, so\n// these are the API's supported reasoning.effort values. Per-model support is a subset the API\n// enforces itself. Verified against codex 0.145.0 (the API reports this exact set).\nexport const CODEX_EFFORT_LEVELS: readonly string[] = [\n \"none\",\n \"minimal\",\n \"low\",\n \"medium\",\n \"high\",\n \"xhigh\",\n \"max\",\n];\nexport const CODEX_INVOCATION_DETECTION: ExecutorMetadata[\"invocationDetection\"] = \"heuristic\";\n\nexport class CodexExecutor implements Executor {\n public readonly metadata: ExecutorMetadata;\n readonly #overrides: ExecutorOverrides;\n readonly #realHome: string;\n\n public constructor(overrides: ExecutorOverrides = {}, realHome = homedir()) {\n assertEffortSupported(\"codex\", overrides.effort, CODEX_EFFORT_LEVELS);\n this.#overrides = overrides;\n this.#realHome = realHome;\n const detected = detectCodex(realHome);\n this.metadata = {\n ...detected,\n model: overrides.model ?? detected.model,\n thinking: overrides.effort ?? detected.thinking,\n };\n }\n\n public runTrial(request: TrialRequest): Trace {\n if (request.arm === \"skill\") seedSkill(request);\n const sandbox = request.evalCase.mode === \"generation\" ? \"workspace-write\" : \"read-only\";\n // Config overrides take precedence over config.toml, so the chosen model/effort apply to both\n // arms. The value portion is parsed as TOML, so a JSON-quoted string is a valid TOML string.\n const selection: string[] = [];\n if (this.#overrides.model !== undefined) {\n selection.push(\"-c\", `model=${JSON.stringify(this.#overrides.model)}`);\n }\n if (this.#overrides.effort !== undefined) {\n selection.push(\"-c\", `model_reasoning_effort=${JSON.stringify(this.#overrides.effort)}`);\n }\n // Baselines need the real Codex configuration for authentication and model selection, but an\n // empty HOME prevents globally installed skills from influencing the comparison arm.\n const environment =\n request.arm === \"baseline\"\n ? {\n ...process.env,\n CODEX_HOME: join(this.#realHome, \".codex\"),\n HOME: request.home,\n }\n : { ...process.env };\n const result = spawnSync(\n \"codex\",\n [\n \"exec\",\n \"--json\",\n \"--skip-git-repo-check\",\n \"--ephemeral\",\n ...selection,\n \"-s\",\n sandbox,\n \"-C\",\n request.workspace,\n request.evalCase.prompt,\n ],\n {\n encoding: \"utf8\",\n env: environment,\n maxBuffer: 64 * 1024 * 1024,\n timeout: TRIAL_TIMEOUT_MS,\n },\n );\n if (result.status !== 0) {\n throw new Error(`codex exec exited ${result.status}: ${result.stderr?.slice(-500)}`);\n }\n\n return parseCodexTrace(result.stdout, request.skillName);\n }\n}\n\nfunction seedSkill(request: TrialRequest): void {\n // Skill installation paths are provider knowledge and intentionally stay inside this adapter.\n const skillsRoot = join(request.workspace, \".agents/skills\");\n mkdirSync(skillsRoot, { recursive: true });\n symlinkSync(request.skillDirectory, join(skillsRoot, request.skillName));\n}\n\nexport function detectCodex(realHome = homedir()): ExecutorMetadata {\n const version = spawnSync(\"codex\", [\"--version\"], { encoding: \"utf8\" }).stdout?.trim() ?? \"\";\n if (version === \"\") throw new Error(\"codex CLI not found on PATH\");\n const configuration = readFileSync(join(realHome, \".codex/config.toml\"), \"utf8\");\n const model = configuration.match(/^model\\s*=\\s*\"([^\"]+)\"/m)?.[1] ?? \"default\";\n const thinking =\n configuration.match(/^model_reasoning_effort\\s*=\\s*\"([^\"]+)\"/m)?.[1] ?? \"default\";\n return {\n invocationDetection: CODEX_INVOCATION_DETECTION,\n model,\n name: \"codex\",\n thinking,\n version,\n };\n}\n\nexport function parseCodexTrace(stdout: string, skillName: string): Trace {\n let completed = false;\n let invoked = false;\n let invocationEvidence: string | null = null;\n const texts: string[] = [];\n let usage: unknown;\n\n for (const line of stdout.split(\"\\n\")) {\n if (line.trim() === \"\") continue;\n let event: unknown;\n try {\n event = JSON.parse(line);\n } catch {\n continue;\n }\n if (!isRecord(event)) continue;\n const item = isRecord(event.item) ? event.item : undefined;\n if (\n item?.type === \"command_execution\" &&\n typeof item.command === \"string\" &&\n item.command.includes(`${skillName}/SKILL.md`)\n ) {\n invoked = true;\n invocationEvidence ??= `command_execution: ${item.command}`;\n }\n if (\n event.type === \"item.completed\" &&\n item?.type === \"agent_message\" &&\n typeof item.text === \"string\"\n ) {\n texts.push(item.text);\n }\n if (event.type === \"turn.completed\") {\n completed = true;\n usage = event.usage;\n }\n }\n\n return { agentText: texts.join(\"\\n\"), completed, invocationEvidence, invoked, usage };\n}\n","/** Implements pi-specific skill loading, arm isolation, invocation, and trace parsing. */\nimport { spawnSync } from \"node:child_process\";\nimport { readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Trace } from \"../types.js\";\nimport { isRecord } from \"../utils.js\";\nimport {\n assertEffortSupported,\n type Executor,\n type ExecutorMetadata,\n type ExecutorOverrides,\n type TrialRequest,\n} from \"./types.js\";\n\nconst TRIAL_TIMEOUT_MS = 15 * 60 * 1000;\n\n// pi normalizes thinking across every model via pi-ai, from `pi --thinking`.\nexport const PI_EFFORT_LEVELS: readonly string[] = [\n \"off\",\n \"minimal\",\n \"low\",\n \"medium\",\n \"high\",\n \"xhigh\",\n];\nexport const PI_INVOCATION_DETECTION: ExecutorMetadata[\"invocationDetection\"] = \"heuristic\";\n\nexport class PiExecutor implements Executor {\n public readonly metadata: ExecutorMetadata;\n readonly #overrides: ExecutorOverrides;\n\n public constructor(\n overrides: ExecutorOverrides = {},\n settingsDirectory = join(homedir(), \".pi\"),\n ) {\n assertEffortSupported(\"pi\", overrides.effort, PI_EFFORT_LEVELS);\n this.#overrides = overrides;\n const detected = detectPi(settingsDirectory);\n this.metadata = {\n ...detected,\n model: overrides.model ?? detected.model,\n thinking: overrides.effort ?? detected.thinking,\n };\n }\n\n public runTrial(request: TrialRequest): Trace {\n // pi has first-class arm switches: --skill makes the evaluated skill discoverable alongside\n // the user's normal library (mirroring the other adapters), --no-skills hides every skill\n // from the baseline. No HOME or config redirection is needed.\n const arm = request.arm === \"skill\" ? [\"--skill\", request.skillDirectory] : [\"--no-skills\"];\n // pi expresses effort as a thinking level; the requested model and thinking pass through here.\n const selection: string[] = [];\n if (this.#overrides.model !== undefined) selection.push(\"--model\", this.#overrides.model);\n if (this.#overrides.effort !== undefined) selection.push(\"--thinking\", this.#overrides.effort);\n // Trigger cases are read-only via the tool allowlist; read also loads SKILL.md, so skill\n // invocation stays observable. Generation cases keep pi's default tool set - note pi has no\n // OS sandbox, so setup writes are only conventionally scoped to the workspace.\n const tools = request.evalCase.mode === \"generation\" ? [] : [\"-t\", \"read\"];\n const result = spawnSync(\n \"pi\",\n [\n \"-p\",\n \"--mode\",\n \"json\",\n \"--no-session\",\n ...selection,\n ...arm,\n ...tools,\n request.evalCase.prompt,\n ],\n {\n cwd: request.workspace,\n encoding: \"utf8\",\n env: { ...process.env },\n maxBuffer: 64 * 1024 * 1024,\n timeout: TRIAL_TIMEOUT_MS,\n },\n );\n if (result.status !== 0) {\n throw new Error(`pi -p exited ${result.status}: ${result.stderr?.slice(-500)}`);\n }\n\n const trace = parsePiTrace(result.stdout, request.skillName);\n if (!trace.completed && /no api key/i.test(result.stdout)) {\n throw new Error(\n \"pi found no API key for its configured provider; export the provider key \" +\n \"(e.g. ZAI_API_KEY) in the environment running skillval\",\n );\n }\n return trace;\n }\n}\n\nexport function detectPi(settingsDirectory = join(homedir(), \".pi\")): ExecutorMetadata {\n const version = spawnSync(\"pi\", [\"--version\"], { encoding: \"utf8\" }).stdout?.trim() ?? \"\";\n if (version === \"\") throw new Error(\"pi CLI not found on PATH\");\n let model = \"default\";\n let thinking = \"default\";\n try {\n const settings: unknown = JSON.parse(\n readFileSync(join(settingsDirectory, \"settings.json\"), \"utf8\"),\n );\n if (isRecord(settings)) {\n if (typeof settings.defaultModel === \"string\") {\n model =\n typeof settings.defaultProvider === \"string\"\n ? `${settings.defaultProvider}/${settings.defaultModel}`\n : settings.defaultModel;\n }\n if (typeof settings.defaultThinkingLevel === \"string\") {\n thinking = settings.defaultThinkingLevel;\n }\n }\n } catch {\n // No readable settings file; pi's own default model applies.\n }\n return {\n invocationDetection: PI_INVOCATION_DETECTION,\n model,\n name: \"pi\",\n thinking,\n version,\n };\n}\n\nexport function parsePiTrace(stdout: string, skillName: string): Trace {\n let completed = false;\n let invoked = false;\n let invocationEvidence: string | null = null;\n const texts: string[] = [];\n let usage: unknown;\n\n for (const line of stdout.split(\"\\n\")) {\n if (line.trim() === \"\") continue;\n let event: unknown;\n try {\n event = JSON.parse(line);\n } catch {\n continue;\n }\n if (!isRecord(event)) continue;\n // agent_end carries the complete transcript, so it is the single authoritative source.\n if (event.type !== \"agent_end\" || !Array.isArray(event.messages)) continue;\n completed = true;\n for (const message of event.messages) {\n if (!isRecord(message) || message.role !== \"assistant\") continue;\n if (!Array.isArray(message.content)) continue;\n for (const block of message.content) {\n if (!isRecord(block)) continue;\n if (block.type === \"text\" && typeof block.text === \"string\") texts.push(block.text);\n if (\n block.type === \"toolCall\" &&\n JSON.stringify(block.arguments ?? \"\").includes(`${skillName}/SKILL.md`)\n ) {\n invoked = true;\n const name = typeof block.name === \"string\" ? block.name : \"toolCall\";\n invocationEvidence ??= `${name} toolCall: ${JSON.stringify(block.arguments ?? null)}`;\n }\n }\n usage = message.usage ?? usage;\n }\n }\n\n return { agentText: texts.join(\"\\n\"), completed, invocationEvidence, invoked, usage };\n}\n","/** Registers executor adapters and creates them from validated configuration names. */\nimport { ClaudeExecutor } from \"./claude.js\";\nimport { CodexExecutor } from \"./codex.js\";\nimport { PiExecutor } from \"./pi.js\";\nimport type { Executor, ExecutorOverrides } from \"./types.js\";\n\nconst executorFactories = {\n claude: (overrides: ExecutorOverrides): Executor => new ClaudeExecutor(overrides),\n codex: (overrides: ExecutorOverrides): Executor => new CodexExecutor(overrides),\n pi: (overrides: ExecutorOverrides): Executor => new PiExecutor(overrides),\n};\n\n// Both the configuration schema and factory derive from this registry.\nexport type ExecutorName = keyof typeof executorFactories;\nexport const EXECUTOR_NAMES = Object.keys(executorFactories) as ExecutorName[];\n\nexport function createExecutor(name: ExecutorName, overrides: ExecutorOverrides = {}): Executor {\n return executorFactories[name](overrides);\n}\n","/** Discovers skills and carries validated case suites into evaluation without reparsing them. */\nimport { existsSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { readCaseFile } from \"./case-file.js\";\nimport type { SkillEvals } from \"./types.js\";\n\ninterface SkillLocation {\n readonly name: string;\n readonly root: string;\n readonly skillDirectory: string;\n}\n\nexport interface MissingDiscoveredSkill extends SkillLocation {\n readonly caseCount: 0;\n readonly class: undefined;\n readonly hasSkillval: false;\n readonly status: \"missing\";\n readonly validationError: undefined;\n}\n\nexport interface InvalidDiscoveredSkill extends SkillLocation {\n readonly caseCount: 0;\n readonly class: \"invalid\";\n readonly hasSkillval: true;\n readonly status: \"invalid\";\n readonly validationError: string;\n}\n\nexport interface ReadyDiscoveredSkill extends SkillLocation {\n readonly caseCount: number;\n readonly class: \"capability\" | \"preference\";\n readonly evals: SkillEvals;\n readonly hasSkillval: true;\n readonly status: \"ready\";\n readonly validationError: undefined;\n}\n\nexport type DiscoveredSkill =\n | InvalidDiscoveredSkill\n | MissingDiscoveredSkill\n | ReadyDiscoveredSkill;\n\nexport interface DiscoveryResult {\n readonly missingRoots: readonly string[];\n readonly skills: readonly DiscoveredSkill[];\n}\n\nexport interface DiscoveryReport {\n readonly missingRoots: readonly string[];\n readonly skills: readonly DiscoverySkillSummary[];\n}\n\nexport type DiscoverySkillSummary =\n | Omit<ReadyDiscoveredSkill, \"evals\">\n | Exclude<DiscoveredSkill, ReadyDiscoveredSkill>;\n\nexport function discoverSkills(roots: readonly string[]): DiscoveryResult {\n const missingRoots: string[] = [];\n const skills: DiscoveredSkill[] = [];\n\n for (const root of roots) {\n if (!existsSync(root)) {\n missingRoots.push(root);\n continue;\n }\n\n const entries = readdirSync(root, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .sort((left, right) => left.name.localeCompare(right.name));\n for (const entry of entries) {\n const skillDirectory = join(root, entry.name);\n if (!existsSync(join(skillDirectory, \"SKILL.md\"))) continue;\n skills.push(describeSkill(entry.name, root, skillDirectory));\n }\n }\n\n return { missingRoots, skills };\n}\n\nexport function discoveryReport(discovery: DiscoveryResult): DiscoveryReport {\n return {\n missingRoots: discovery.missingRoots,\n skills: discovery.skills.map((skill) => {\n if (skill.status !== \"ready\") return skill;\n // Parsed prompts are execution input, not listing metadata. Keep list --json compact and\n // avoid exposing prompt contents when callers only asked what skills are available.\n return {\n caseCount: skill.caseCount,\n class: skill.class,\n hasSkillval: skill.hasSkillval,\n name: skill.name,\n root: skill.root,\n skillDirectory: skill.skillDirectory,\n status: skill.status,\n validationError: skill.validationError,\n };\n }),\n };\n}\n\nexport function selectSkills(\n discovery: DiscoveryResult,\n requestedNames: readonly string[],\n): readonly ReadyDiscoveredSkill[] {\n const byName = new Map<string, DiscoveredSkill>();\n for (const skill of discovery.skills) {\n if (!byName.has(skill.name)) byName.set(skill.name, skill);\n }\n\n if (requestedNames.length === 0) {\n return [...byName.values()].filter(\n (skill): skill is ReadyDiscoveredSkill => skill.status === \"ready\",\n );\n }\n\n return requestedNames.map((name) => {\n const skill = byName.get(name);\n if (skill === undefined) {\n throw new Error(`skill \"${name}\" not found under configured roots`);\n }\n if (skill.status === \"missing\") {\n throw new Error(`skill \"${name}\" has no skillval.yml`);\n }\n if (skill.status === \"invalid\") {\n throw new Error(skill.validationError);\n }\n return skill;\n });\n}\n\nfunction describeSkill(name: string, root: string, skillDirectory: string): DiscoveredSkill {\n const caseFilePath = join(skillDirectory, \"skillval.yml\");\n if (!existsSync(caseFilePath)) {\n return {\n caseCount: 0,\n class: undefined,\n hasSkillval: false,\n name,\n root,\n skillDirectory,\n status: \"missing\",\n validationError: undefined,\n };\n }\n\n let evals: SkillEvals;\n try {\n evals = readCaseFile(caseFilePath, name);\n } catch (error) {\n return {\n caseCount: 0,\n class: \"invalid\",\n hasSkillval: true,\n name,\n root,\n skillDirectory,\n status: \"invalid\",\n validationError: error instanceof Error ? error.message : String(error),\n };\n }\n\n return {\n caseCount: evals.cases.length,\n class: evals.class,\n evals,\n hasSkillval: true,\n name,\n root,\n skillDirectory,\n status: \"ready\",\n validationError: undefined,\n };\n}\n","/** Adapts YAML case files into values validated by the executable case contract. */\nimport { readFileSync, statSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport { CaseContractError, parseCaseValue } from \"./case-contract.js\";\nimport { walkFixtureEntries } from \"./fixture.js\";\nimport type { Fixture, SkillEvals } from \"./types.js\";\n\nexport class CaseFileError extends CaseContractError {\n public constructor(message: string, code = \"CASE_FILE_INVALID\") {\n super(message, code);\n this.name = \"CaseFileError\";\n }\n}\n\nexport function readCaseFile(path: string, expectedSkill?: string): SkillEvals {\n const evals = parseCaseFile(readFileSync(path, \"utf8\"), path, expectedSkill);\n // Fixture directories are validated here, not in the pure contract, because only the reader\n // knows where the case file actually lives on disk.\n const baseDirectory = dirname(path);\n assertFixtureDirectory(evals.fixture, `${path} suite fixture`, baseDirectory);\n for (const evalCase of evals.cases) {\n assertFixtureDirectory(\n evalCase.fixture,\n `${path} case \"${evalCase.id}\" fixture`,\n baseDirectory,\n );\n }\n return evals;\n}\n\nfunction assertFixtureDirectory(\n fixture: Fixture | undefined,\n subject: string,\n baseDirectory: string,\n): void {\n if (fixture?.path === undefined) return;\n const directory = join(baseDirectory, fixture.path);\n const stats = statSync(directory, { throwIfNoEntry: false });\n if (stats === undefined) {\n throw new CaseFileError(\n `${subject} path \"${fixture.path}\" does not exist`,\n \"CASE_FIXTURE_INVALID\",\n );\n }\n if (!stats.isDirectory()) {\n throw new CaseFileError(\n `${subject} path \"${fixture.path}\" is not a directory`,\n \"CASE_FIXTURE_INVALID\",\n );\n }\n try {\n walkFixtureEntries(directory);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n throw new CaseFileError(`${subject} path \"${fixture.path}\" ${detail}`, \"CASE_FIXTURE_INVALID\");\n }\n}\n\nexport function parseCaseFile(\n source: string,\n path = \"skillval.yml\",\n expectedSkill?: string,\n): SkillEvals {\n let parsed: unknown;\n try {\n parsed = parseYaml(source);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n throw new CaseFileError(`${path} YAML is invalid: ${detail}`, \"CASE_FILE_YAML_INVALID\");\n }\n\n try {\n return parseCaseValue(parsed, path, expectedSkill);\n } catch (error) {\n if (error instanceof CaseContractError) {\n throw new CaseFileError(error.message, error.code);\n }\n throw error;\n }\n}\n","/** Defines the case-file contract used for static types, runtime validation, and JSON Schema. */\n\nimport { isAbsolute, normalize } from \"node:path\";\nimport type { Static } from \"typebox\";\nimport Type from \"typebox\";\nimport { Check as checkSchema, Errors as schemaErrors } from \"typebox/value\";\nimport {\n COMMAND_EXIT_GRADER_MODES,\n commandExitGraderSchema,\n GRADER_NAMES,\n graderSupportsMode,\n JSON_SCHEMA_GRADER_MODES,\n jsonSchemaCompileError,\n jsonSchemaGraderSchema,\n} from \"./graders.js\";\n\nconst classificationSchema = Type.Enum([\"capability\", \"preference\"]);\nconst nonEmptyStringSchema = Type.String({ minLength: 1, pattern: String.raw`\\S` });\nconst stringArraySchema = Type.Readonly(Type.Array(Type.String()));\nexport const armSchema = Type.Enum([\"baseline\", \"skill\"]);\n\n// These schemas are executable at runtime and are also serialized into schemas/ for editor tooling.\nexport const fixtureSchema = Type.ReadonlyObject(\n Type.Object({\n path: Type.Optional(\n Type.String({\n description: \"Directory relative to skillval.yml, copied into the workspace.\",\n minLength: 1,\n pattern: String.raw`\\S`,\n }),\n ),\n setup: Type.Optional(\n Type.Readonly(\n Type.Array(nonEmptyStringSchema, {\n description:\n \"Shell commands run sequentially inside the workspace after the copy. Trusted case input: arbitrary shell executed on the grading machine (see the README's Trust model section).\",\n }),\n ),\n ),\n }),\n { additionalProperties: false, minProperties: 1 },\n);\n\nexport const caseAssertSchema = Type.ReadonlyObject(\n Type.Object({\n command_exit: Type.Optional(commandExitGraderSchema),\n graders: Type.Optional(\n Type.Readonly(Type.Array(Type.Enum(GRADER_NAMES), { uniqueItems: true })),\n ),\n json_schema: Type.Optional(jsonSchemaGraderSchema),\n must_match: Type.Optional(stringArraySchema),\n must_not_match: Type.Optional(stringArraySchema),\n }),\n { additionalProperties: false },\n);\n\nexport const evalCaseSchema = Type.ReadonlyObject(\n Type.Object({\n arms: Type.Optional(\n Type.Readonly(\n Type.Array(armSchema, {\n uniqueItems: true,\n }),\n ),\n ),\n assert: Type.Optional(caseAssertSchema),\n fixture: Type.Optional(fixtureSchema),\n id: nonEmptyStringSchema,\n mode: Type.Enum([\"generation\", \"trigger\"]),\n prompt: nonEmptyStringSchema,\n rule: Type.Optional(Type.String()),\n should_trigger: Type.Optional(Type.Boolean()),\n trials: Type.Optional(Type.Integer({ maximum: 5, minimum: 1 })),\n type: Type.Optional(classificationSchema),\n }),\n { additionalProperties: false },\n);\n\nexport const skillEvalsSchema = Type.ReadonlyObject(\n Type.Object({\n cases: Type.Readonly(Type.Array(evalCaseSchema)),\n class: classificationSchema,\n fixture: Type.Optional(fixtureSchema),\n skill: nonEmptyStringSchema,\n }),\n {\n $id: \"https://raw.githubusercontent.com/dungle-scrubs/skillval/main/schemas/skillval.schema.json\",\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n additionalProperties: false,\n title: \"skillval case file\",\n },\n);\n\nexport type Arm = Static<typeof armSchema>;\nexport type CaseAssert = Static<typeof caseAssertSchema>;\nexport type EvalCase = Static<typeof evalCaseSchema>;\nexport type Fixture = Static<typeof fixtureSchema>;\nexport type SkillEvals = Static<typeof skillEvalsSchema>;\n\nexport class CaseContractError extends Error {\n public readonly code: string;\n\n public constructor(message: string, code = \"CASE_FILE_INVALID\") {\n super(message);\n this.code = code;\n this.name = \"CaseContractError\";\n }\n}\n\nexport function parseCaseValue(value: unknown, path: string, expectedSkill?: string): SkillEvals {\n if (!checkSchema(skillEvalsSchema, value)) {\n const [firstError] = schemaErrors(skillEvalsSchema, value);\n const location = firstError?.instancePath.replaceAll(\"/\", \".\").replace(/^\\./, \"\");\n if (location?.endsWith(\".trials\")) {\n const match = /cases\\.(\\d+)\\.trials$/.exec(location);\n const caseIndex = match?.[1] ?? \"unknown\";\n throw new CaseContractError(\n `${path} case at index ${caseIndex} trials must be an integer from 1 through 5`,\n );\n }\n const subject = location === undefined || location === \"\" ? path : `${path} ${location}`;\n throw new CaseContractError(`${subject} ${firstError?.message ?? \"is invalid\"}`);\n }\n\n if (expectedSkill !== undefined && value.skill !== expectedSkill) {\n throw new CaseContractError(\n `${path} declares skill \"${value.skill}\", expected \"${expectedSkill}\"`,\n );\n }\n\n const ids = new Set<string>();\n for (const evalCase of value.cases) {\n // Semantic rules that depend on sibling cases, JavaScript regex compilation, or runtime\n // registries remain here. Keeping them beside the structural schema preserves one owner.\n if (ids.has(evalCase.id)) {\n throw new CaseContractError(`${path} case id \"${evalCase.id}\" is duplicated`);\n }\n ids.add(evalCase.id);\n validatePatterns(evalCase, path);\n validateGraders(evalCase, path);\n validateJsonSchemaGrader(evalCase, path);\n validateCommandExitGrader(evalCase, path);\n }\n return value;\n}\n\nfunction validateCommandExitGrader(evalCase: EvalCase, path: string): void {\n if (evalCase.assert?.command_exit === undefined) return;\n if (!COMMAND_EXIT_GRADER_MODES.includes(evalCase.mode)) {\n throw new CaseContractError(\n `${path} case \"${evalCase.id}\" grader \"command_exit\" does not support ${evalCase.mode} mode`,\n );\n }\n}\n\nfunction validateJsonSchemaGrader(evalCase: EvalCase, path: string): void {\n const config = evalCase.assert?.json_schema;\n if (config === undefined) return;\n if (!JSON_SCHEMA_GRADER_MODES.includes(evalCase.mode)) {\n throw new CaseContractError(\n `${path} case \"${evalCase.id}\" grader \"json_schema\" does not support ${evalCase.mode} mode`,\n );\n }\n // Reject parent traversal by path segment, not string prefix, so a legitimate filename such as\n // \"..config.json\" is allowed while \"../x\" is not.\n const segments = normalize(config.file).split(/[/\\\\]/);\n if (isAbsolute(config.file) || segments.includes(\"..\")) {\n throw new CaseContractError(\n `${path} case \"${evalCase.id}\" json_schema file \"${config.file}\" must be a path inside the workspace`,\n );\n }\n const schemaError = jsonSchemaCompileError(config.schema);\n if (schemaError !== null) {\n throw new CaseContractError(\n `${path} case \"${evalCase.id}\" has an invalid json_schema: ${schemaError}`,\n );\n }\n}\n\nfunction validateGraders(evalCase: EvalCase, path: string): void {\n for (const grader of evalCase.assert?.graders ?? []) {\n if (!graderSupportsMode(grader, evalCase.mode)) {\n throw new CaseContractError(\n `${path} case \"${evalCase.id}\" grader \"${grader}\" does not support ${evalCase.mode} mode`,\n );\n }\n }\n}\n\nfunction validatePatterns(evalCase: EvalCase, path: string): void {\n const fields = [\"must_match\", \"must_not_match\"] as const;\n for (const field of fields) {\n for (const pattern of evalCase.assert?.[field] ?? []) {\n try {\n new RegExp(pattern, \"m\");\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n throw new CaseContractError(\n `${path} case \"${evalCase.id}\" has invalid ${field} regex \"${pattern}\": ${detail}`,\n );\n }\n }\n }\n}\n","/** Owns the deterministic grader catalog, mode support, and grader implementations. */\nimport { spawnSync } from \"node:child_process\";\nimport {\n existsSync,\n lstatSync,\n readFileSync,\n realpathSync,\n type Stats,\n writeFileSync,\n} from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join, resolve, sep } from \"node:path\";\nimport type { AnySchema, ValidateFunction } from \"ajv/dist/2020.js\";\nimport { Ajv2020 } from \"ajv/dist/2020.js\";\nimport type { Static } from \"typebox\";\nimport Type from \"typebox\";\n\ntype CaseMode = \"generation\" | \"trigger\";\n\n// The json_schema grader is parameterized, so its config schema lives here beside the grader and\n// is imported by the case contract, keeping graders.ts the single owner of grader behavior.\nexport const jsonSchemaGraderSchema = Type.ReadonlyObject(\n Type.Object({\n file: Type.String({\n description: \"Produced file, relative to the workspace, parsed as JSON and validated.\",\n minLength: 1,\n pattern: String.raw`\\S`,\n }),\n schema: Type.Union([Type.Record(Type.String(), Type.Unknown()), Type.Boolean()], {\n description:\n \"JSON Schema (draft 2020-12) the produced file must satisfy; an object or a boolean schema. Omit $schema, or set it to 2020-12; other declared dialects are rejected.\",\n }),\n }),\n { additionalProperties: false },\n);\n\nexport type JsonSchemaGraderConfig = Static<typeof jsonSchemaGraderSchema>;\n\n// The json_schema grader supports only generation cases, mirroring the produced-file graders.\nexport const JSON_SCHEMA_GRADER_MODES: readonly CaseMode[] = [\"generation\"];\n\n// The command_exit grader runs a case-authored command in the workspace and grades on exit code.\n// The command comes from the case file, the same trust level as fixture setup commands.\nexport const commandExitGraderSchema = Type.ReadonlyObject(\n Type.Object({\n command: Type.String({\n description:\n \"Shell command run in the workspace; the grader passes when it exits as expected. Trusted case input: this is arbitrary shell executed on the grading machine (see the README's Trust model section).\",\n minLength: 1,\n pattern: String.raw`\\S`,\n }),\n expect: Type.Optional(\n Type.Integer({\n description: \"Exit code the command must produce to pass. Defaults to 0.\",\n maximum: 255,\n minimum: 0,\n }),\n ),\n }),\n { additionalProperties: false },\n);\n\nexport type CommandExitGraderConfig = Static<typeof commandExitGraderSchema>;\n\n// The command_exit grader supports only generation cases, mirroring the produced-file graders.\nexport const COMMAND_EXIT_GRADER_MODES: readonly CaseMode[] = [\"generation\"];\n\ninterface GradableCase {\n readonly assert?: {\n readonly command_exit?: CommandExitGraderConfig;\n readonly graders?: readonly GraderName[];\n readonly json_schema?: JsonSchemaGraderConfig;\n };\n}\n\ninterface GraderCheck {\n readonly detail: string;\n readonly name: string;\n readonly pass: boolean;\n}\n\ninterface Grader {\n readonly modes: readonly CaseMode[];\n run(workspace: string): GraderCheck;\n}\n\nconst packageRequire = createRequire(import.meta.url);\n// This registry is the sole source of grader names, supported modes, and implementations.\nconst graders = {\n tsc: {\n modes: [\"generation\"],\n run: gradeTsc,\n },\n} satisfies Readonly<Record<string, Grader>>;\n\nexport type GraderName = keyof typeof graders;\n// The case contract derives its allowed grader values from the registry keys.\nexport const GRADER_NAMES = Object.keys(graders) as GraderName[];\n\nexport function graderSupportsMode(name: GraderName, mode: CaseMode): boolean {\n const modes: readonly CaseMode[] = graders[name].modes;\n return modes.includes(mode);\n}\n\nexport function runGraders(evalCase: GradableCase, workspace: string): readonly GraderCheck[] {\n const checks: GraderCheck[] = [];\n // Graders run least-mutating first: json_schema only reads, command_exit may write, and gradeTsc\n // injects package.json/tsconfig.json. Reading produced files before any grader can rewrite them\n // keeps a combined case deterministic.\n if (evalCase.assert?.json_schema !== undefined) {\n checks.push(gradeJsonSchema(workspace, evalCase.assert.json_schema));\n }\n if (evalCase.assert?.command_exit !== undefined) {\n checks.push(gradeCommandExit(workspace, evalCase.assert.command_exit));\n }\n for (const name of evalCase.assert?.graders ?? []) {\n checks.push(graders[name].run(workspace));\n }\n return checks;\n}\n\nconst COMMAND_EXIT_TIMEOUT_MS = 120_000;\n\nfunction gradeCommandExit(workspace: string, config: CommandExitGraderConfig): GraderCheck {\n const expected = config.expect ?? 0;\n // Minimal environment and SIGKILL on timeout mirror fixture setup: nothing inherited beyond PATH,\n // a throwaway HOME, and a hard kill because SIGTERM is trappable and would let a hang run forever.\n // A large maxBuffer keeps a verbose compiler or test runner from being killed with ENOBUFS, which\n // would fail the check regardless of exit code. Like fixture setup, a timed-out command that\n // spawned background descendants may leave them running; grading commands are trusted case input.\n const outcome = spawnSync(config.command, {\n cwd: workspace,\n encoding: \"utf8\",\n env: { HOME: workspace, PATH: process.env.PATH ?? \"\" },\n killSignal: \"SIGKILL\",\n maxBuffer: 64 * 1024 * 1024,\n shell: true,\n timeout: COMMAND_EXIT_TIMEOUT_MS,\n });\n if (outcome.error !== undefined) {\n const timedOut = (outcome.error as NodeJS.ErrnoException).code === \"ETIMEDOUT\";\n const reason = timedOut\n ? `timed out after ${COMMAND_EXIT_TIMEOUT_MS / 1000}s`\n : outcome.error.message;\n return {\n detail: `command \"${config.command}\" failed to run: ${reason}`,\n name: \"command_exit\",\n pass: false,\n };\n }\n if (outcome.signal !== null) {\n return {\n detail: `command \"${config.command}\" terminated by ${outcome.signal}`,\n name: \"command_exit\",\n pass: false,\n };\n }\n if (outcome.status === expected) {\n return {\n detail: `command \"${config.command}\" exited ${expected}`,\n name: \"command_exit\",\n pass: true,\n };\n }\n const stderr = outcome.stderr === \"\" ? \"\" : `: ${outcome.stderr.slice(0, 300)}`;\n return {\n detail: `command \"${config.command}\" exited ${outcome.status}, expected ${expected}${stderr}`,\n name: \"command_exit\",\n pass: false,\n };\n}\n\ntype CompileResult = { ok: true; validate: ValidateFunction } | { message: string; ok: false };\n\n// A fresh instance per call keeps grading deterministic and avoids $id collisions across cases.\n// Ajv2020 validates draft 2020-12 schemas (a superset of the older keywords authors commonly use).\nfunction compileSchema(schema: unknown): CompileResult {\n try {\n const ajv = new Ajv2020({ allErrors: false, strict: false });\n return { ok: true, validate: ajv.compile(schema as AnySchema) };\n } catch (error) {\n return { message: error instanceof Error ? error.message : String(error), ok: false };\n }\n}\n\n// Case parsing calls this so an unusable schema is a case-authoring error, not a paid trial failure.\nexport function jsonSchemaCompileError(schema: unknown): string | null {\n const result = compileSchema(schema);\n return result.ok ? null : result.message;\n}\n\nfunction safeRealpath(target: string): string | null {\n try {\n return realpathSync(target);\n } catch {\n return null;\n }\n}\n\nfunction safeLstat(target: string): Stats | null {\n try {\n return lstatSync(target);\n } catch {\n return null;\n }\n}\n\nfunction gradeJsonSchema(workspace: string, config: JsonSchemaGraderConfig): GraderCheck {\n const workspaceRoot = safeRealpath(resolve(workspace));\n if (workspaceRoot === null) {\n return { detail: \"workspace not found\", name: \"json_schema\", pass: false };\n }\n // realpath resolves every symlink in the path, so a symlinked target or a symlinked parent\n // directory pointing outside the workspace is caught by the containment check below rather than\n // silently followed. safeRealpath returns null for a missing path or a broken symlink.\n const target = safeRealpath(resolve(workspaceRoot, config.file));\n if (target === null) {\n return { detail: `file not found: ${config.file}`, name: \"json_schema\", pass: false };\n }\n if (target !== workspaceRoot && !target.startsWith(workspaceRoot + sep)) {\n return { detail: `file escapes workspace: ${config.file}`, name: \"json_schema\", pass: false };\n }\n // The real path has no remaining symlinks; reject anything that is not a regular file (a FIFO or\n // device would otherwise block readFileSync indefinitely).\n const stats = safeLstat(target);\n if (stats === null || !stats.isFile()) {\n return { detail: `not a regular file: ${config.file}`, name: \"json_schema\", pass: false };\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(target, \"utf8\"));\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n detail: `invalid JSON in ${config.file}: ${message}`,\n name: \"json_schema\",\n pass: false,\n };\n }\n const compiled = compileSchema(config.schema);\n if (!compiled.ok) {\n return { detail: `invalid json_schema: ${compiled.message}`, name: \"json_schema\", pass: false };\n }\n if (compiled.validate(parsed)) {\n return { detail: `${config.file} matches schema`, name: \"json_schema\", pass: true };\n }\n const first = compiled.validate.errors?.[0];\n const location =\n first?.instancePath === undefined || first.instancePath === \"\" ? \"(root)\" : first.instancePath;\n return {\n detail: `${config.file} ${location} ${first?.message ?? \"does not match schema\"}`,\n name: \"json_schema\",\n pass: false,\n };\n}\n\nfunction gradeTsc(workspace: string): GraderCheck {\n if (!existsSync(join(workspace, \"package.json\"))) {\n writeFileSync(join(workspace, \"package.json\"), '{ \"type\": \"module\" }\\n');\n }\n const nodeTypesDirectory = dirname(packageRequire.resolve(\"@types/node/package.json\"));\n writeFileSync(\n join(workspace, \"tsconfig.json\"),\n JSON.stringify({\n compilerOptions: {\n lib: [\"es2023\"],\n module: \"esnext\",\n moduleResolution: \"bundler\",\n noEmit: true,\n noUncheckedIndexedAccess: true,\n strict: true,\n target: \"es2023\",\n typeRoots: [dirname(nodeTypesDirectory)],\n types: [\"node\"],\n },\n }),\n );\n // TypeScript 7 stopped exporting ./bin/tsc, so resolve the package root and join to the bin.\n const typescriptBinary = join(\n dirname(packageRequire.resolve(\"typescript/package.json\")),\n \"bin\",\n \"tsc\",\n );\n const result = spawnSync(typescriptBinary, [\"-p\", workspace], {\n encoding: \"utf8\",\n timeout: 120_000,\n });\n return {\n detail: result.status === 0 ? \"compiles strict\" : (result.stdout ?? \"\").slice(0, 500),\n name: \"tsc\",\n pass: result.status === 0,\n };\n}\n","/** Prepares trial workspaces from case fixtures: content copy, setup commands, identity hashing. */\nimport { spawnSync } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { cpSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport type { Fixture } from \"./case-contract.js\";\nimport type { FixtureCommandResult } from \"./types.js\";\nimport { SKIPPED_DIRECTORIES } from \"./utils.js\";\n\n// Setup commands are workspace staging (git init, file moves), not agent work; a minute is ample.\nconst SETUP_COMMAND_TIMEOUT_MS = 60_000;\n\nexport interface ResolvedFixture {\n readonly directory: string | undefined;\n readonly hash: string;\n readonly setup: readonly string[];\n}\n\nexport class FixtureSetupError extends Error {\n public readonly results: readonly FixtureCommandResult[];\n\n public constructor(message: string, results: readonly FixtureCommandResult[]) {\n super(message);\n this.name = \"FixtureSetupError\";\n this.results = results;\n }\n}\n\nexport function selectFixture(\n caseFixture: Fixture | undefined,\n suiteFixture: Fixture | undefined,\n): Fixture | undefined {\n // A per-case fixture replaces the suite default entirely; path and setup never merge.\n return caseFixture ?? suiteFixture;\n}\n\nexport function resolveFixture(\n fixture: Fixture | undefined,\n baseDirectory: string,\n): ResolvedFixture | undefined {\n if (fixture === undefined) return undefined;\n const directory = fixture.path === undefined ? undefined : join(baseDirectory, fixture.path);\n const setup = fixture.setup ?? [];\n return { directory, hash: fixtureIdentityHash(directory, setup), setup };\n}\n\ninterface FixtureEntry {\n readonly absolutePath: string;\n readonly executable: boolean;\n readonly path: string;\n readonly type: \"directory\" | \"file\";\n}\n\n/**\n * Walks a fixture directory into a deterministic manifest, rejecting symlinks and special files.\n * Symlinks are refused because a copied link can resolve back into the source fixture and let\n * setup commands mutate it; links belong in setup commands instead.\n */\nexport function walkFixtureEntries(directory: string): FixtureEntry[] {\n const entries: FixtureEntry[] = [];\n\n function visit(current: string, prefix: string): void {\n const dirents = [...readdirSync(current, { withFileTypes: true })].sort((left, right) =>\n left.name.localeCompare(right.name),\n );\n for (const dirent of dirents) {\n if (SKIPPED_DIRECTORIES.has(dirent.name)) continue;\n const absolutePath = join(current, dirent.name);\n const path = prefix === \"\" ? dirent.name : `${prefix}/${dirent.name}`;\n if (dirent.isSymbolicLink()) {\n throw new Error(\n `contains unsupported symlink \"${path}\"; create links with setup commands instead`,\n );\n }\n if (dirent.isDirectory()) {\n entries.push({ absolutePath, executable: false, path, type: \"directory\" });\n visit(absolutePath, path);\n } else if (dirent.isFile()) {\n const executable = (statSync(absolutePath).mode & 0o111) !== 0;\n entries.push({ absolutePath, executable, path, type: \"file\" });\n } else {\n throw new Error(`contains unsupported special file \"${path}\"`);\n }\n }\n }\n\n visit(directory, \"\");\n return entries;\n}\n\nexport function fixtureIdentityHash(\n directory: string | undefined,\n setup: readonly string[],\n): string {\n // Each entry is framed with its type, path, mode, and byte length so file bytes can never\n // masquerade as entry boundaries, and raw bytes are hashed so binary files cannot collide\n // through lossy text decoding.\n const hash = createHash(\"sha256\");\n if (directory !== undefined) {\n for (const entry of walkFixtureEntries(directory)) {\n if (entry.type === \"directory\") {\n hash.update(`D\\0${entry.path}\\0`);\n continue;\n }\n const content = readFileSync(entry.absolutePath);\n hash.update(`F\\0${entry.path}\\0${entry.executable ? \"x\" : \"-\"}\\0${content.byteLength}\\0`);\n hash.update(content);\n }\n }\n hash.update(`S\\0${JSON.stringify(setup)}`);\n return hash.digest(\"hex\");\n}\n\nexport function applyFixture(\n fixture: ResolvedFixture,\n workspace: string,\n home: string,\n): readonly FixtureCommandResult[] {\n if (fixture.directory !== undefined) {\n // verbatimSymlinks guards the window between hashing (which rejects symlinks) and copying:\n // a link that appears mid-run is copied inert instead of resolving into the source fixture.\n cpSync(fixture.directory, workspace, {\n filter: (source) => !SKIPPED_DIRECTORIES.has(basename(source)),\n recursive: true,\n verbatimSymlinks: true,\n });\n }\n\n const results: FixtureCommandResult[] = [];\n for (const command of fixture.setup) {\n // Minimal environment: PATH for tool lookup plus the throwaway trial home, nothing inherited.\n // SIGKILL on timeout because SIGTERM is trappable and would let a hung command run forever.\n const outcome = spawnSync(command, {\n cwd: workspace,\n encoding: \"utf8\",\n env: { HOME: home, PATH: process.env.PATH ?? \"\" },\n killSignal: \"SIGKILL\",\n shell: true,\n timeout: SETUP_COMMAND_TIMEOUT_MS,\n });\n results.push({\n command,\n exitCode: outcome.status,\n signal: outcome.signal ?? null,\n stderr: outcome.stderr ?? \"\",\n stdout: outcome.stdout ?? \"\",\n });\n if (outcome.error !== undefined || outcome.status !== 0) {\n const timedOut = (outcome.error as NodeJS.ErrnoException | undefined)?.code === \"ETIMEDOUT\";\n const reason = timedOut\n ? `timed out after ${SETUP_COMMAND_TIMEOUT_MS / 1000}s`\n : (outcome.error?.message ??\n (outcome.signal !== null\n ? `terminated by ${outcome.signal}`\n : `exit code ${outcome.status}`));\n throw new FixtureSetupError(`fixture setup failed: \"${command}\" (${reason})`, results);\n }\n }\n return results;\n}\n","/** Orchestrates discovery, trial arms, voting, caching, cleanup, and report persistence. */\nimport { mkdirSync, mkdtempSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { ArmCache } from \"./cache.js\";\nimport type { SkillvalConfig } from \"./config.js\";\nimport { resolveStateDirectory } from \"./config.js\";\nimport type { ReadyDiscoveredSkill } from \"./discovery.js\";\nimport { discoverSkills, selectSkills } from \"./discovery.js\";\nimport { createExecutor } from \"./executors/index.js\";\nimport type { Executor, ExecutorMetadata } from \"./executors/types.js\";\nimport type { ResolvedFixture } from \"./fixture.js\";\nimport { applyFixture, FixtureSetupError, resolveFixture, selectFixture } from \"./fixture.js\";\nimport { gradeTrial } from \"./grade.js\";\nimport type { Arm, ArmResult, CaseResult, EvalCase, TrialResult } from \"./types.js\";\nimport { sha256, skillContentHash } from \"./utils.js\";\nimport { clampedTrialCount, hasMajority, shouldEscalate } from \"./vote.js\";\n\nexport interface RunOptions {\n readonly allowUnsandboxedPi: boolean;\n readonly caseFilter: string | undefined;\n readonly effort?: string;\n readonly model?: string;\n readonly requestedSkills: readonly string[];\n readonly skipBaseline: boolean;\n readonly useCache: boolean;\n}\n\nexport interface SkillReport {\n readonly cases: readonly CaseResult[];\n readonly class: \"capability\" | \"preference\";\n readonly contentHash: string;\n}\n\nexport interface RunReport {\n readonly executor: ExecutorMetadata;\n readonly runHash: string;\n readonly skills: Readonly<Record<string, SkillReport>>;\n}\n\nexport interface RunOutcome {\n readonly failures: number;\n readonly noops: number;\n readonly report: RunReport;\n readonly reportPath: string;\n}\n\ninterface ArmContext {\n readonly cache: ArmCache;\n readonly evalCase: EvalCase;\n readonly executor: Executor;\n readonly fixture: ResolvedFixture | undefined;\n readonly skill: ReadyDiscoveredSkill;\n readonly skillHash: string;\n readonly useCache: boolean;\n}\n\ninterface CaseContext {\n readonly cache: ArmCache;\n readonly executor: Executor;\n readonly skill: ReadyDiscoveredSkill;\n readonly skillHash: string;\n readonly skipBaseline: boolean;\n readonly useCache: boolean;\n}\n\nexport function runEvaluation(\n config: SkillvalConfig,\n options: RunOptions,\n log: (message: string) => void,\n): RunOutcome {\n const discovery = discoverSkills(config.roots);\n const selectedSkills = selectSkills(discovery, options.requestedSkills);\n assertPiGenerationAcknowledged(\n config.executor,\n selectedSkills,\n options.caseFilter,\n options.allowUnsandboxedPi,\n );\n const executor = createExecutor(config.executor, {\n effort: options.effort,\n model: options.model,\n });\n log(\n `executor: ${executor.metadata.name} ${executor.metadata.version} ` +\n `(model ${executor.metadata.model}, thinking ${executor.metadata.thinking}, ` +\n `invocation detection ${executor.metadata.invocationDetection})`,\n );\n const stateDirectory = resolveStateDirectory();\n const cache = new ArmCache(stateDirectory);\n const skillInputs = selectedSkills.map((skill) => ({\n contentHash: skillContentHash(skill.skillDirectory),\n skill,\n }));\n const runHash = participatingSkillsHash(\n skillInputs.map(({ contentHash, skill }) => ({ contentHash, name: skill.name })),\n );\n const skillReports: Record<string, SkillReport> = {};\n let failures = 0;\n let noops = 0;\n\n for (const { contentHash, skill } of skillInputs) {\n const evals = skill.evals;\n log(`${skill.name} (${evals.class}, ${contentHash.slice(0, 12)}):`);\n const cases = evals.cases\n .filter((evalCase) => options.caseFilter === undefined || evalCase.id === options.caseFilter)\n .map((evalCase) =>\n runCase(\n {\n cache,\n executor,\n skill,\n skillHash: contentHash,\n skipBaseline: options.skipBaseline,\n useCache: options.useCache,\n },\n evalCase,\n log,\n ),\n );\n skillReports[skill.name] = { cases, class: evals.class, contentHash };\n failures += cases.filter((result) => !result.pass).length;\n noops += cases.filter((result) => result.noop).length;\n }\n\n const report: RunReport = {\n executor: executor.metadata,\n runHash,\n skills: skillReports,\n };\n const reportDirectory = join(stateDirectory, \"reports\");\n const reportPath = join(reportDirectory, `${runHash}.json`);\n mkdirSync(reportDirectory, { recursive: true });\n writeFileSync(reportPath, JSON.stringify(report, null, 2));\n return { failures, noops, report, reportPath };\n}\n\n// pi has no OS sandbox, so generation trials run agent writes with no enforced isolation. Refuse\n// them unless the run explicitly acknowledges the gap, failing before any trial spawns.\nexport function assertPiGenerationAcknowledged(\n executorName: string,\n skills: readonly ReadyDiscoveredSkill[],\n caseFilter: string | undefined,\n allow: boolean,\n): void {\n if (executorName !== \"pi\" || allow) return;\n for (const skill of skills) {\n for (const evalCase of skill.evals.cases) {\n if (caseFilter !== undefined && evalCase.id !== caseFilter) continue;\n if (evalCase.mode === \"generation\") {\n throw new Error(\n `pi has no OS sandbox, so generation case \"${evalCase.id}\" (skill \"${skill.name}\") would ` +\n \"run agent writes without enforced isolation. Re-run with --allow-unsandboxed-pi to \" +\n \"acknowledge, or use codex or claude for generation cases.\",\n );\n }\n }\n }\n}\n\nexport function participatingSkillsHash(\n skills: readonly { readonly contentHash: string; readonly name: string }[],\n): string {\n return sha256(\n [...skills]\n .sort((left, right) => left.name.localeCompare(right.name))\n .map(({ contentHash, name }) => `${name}\\0${contentHash}`)\n .join(\"\\0\"),\n );\n}\n\nfunction runCase(\n context: CaseContext,\n evalCase: EvalCase,\n log: (message: string) => void,\n): CaseResult {\n const arms = (evalCase.arms ?? [\"skill\"]).filter(\n (arm) => arm === \"skill\" || !context.skipBaseline,\n );\n // Fixture paths are relative to skillval.yml, which sits in the skill directory.\n const fixture = resolveFixture(\n selectFixture(evalCase.fixture, context.skill.evals.fixture),\n context.skill.skillDirectory,\n );\n const results = arms.map((arm) => {\n log(` ${evalCase.id} [${arm}] ...`);\n const result = runArm(\n {\n cache: context.cache,\n evalCase,\n executor: context.executor,\n fixture,\n skill: context.skill,\n skillHash: context.skillHash,\n useCache: context.useCache,\n },\n arm,\n );\n log(\n ` ${evalCase.id} [${arm}] ${result.pass ? \"pass\" : \"FAIL\"}${\n result.cached ? \" (cached)\" : \"\"\n }`,\n );\n return result;\n });\n return {\n arms: results,\n id: evalCase.id,\n noop: results.find((result) => result.arm === \"baseline\")?.pass === true,\n pass: results.find((result) => result.arm === \"skill\")?.pass === true,\n rule: evalCase.rule,\n };\n}\n\nfunction runArm(context: ArmContext, arm: Arm): ArmResult {\n const identity = {\n arm,\n evalCase: context.evalCase,\n executor: context.executor.metadata,\n fixtureHash: context.fixture?.hash,\n skillHash: context.skillHash,\n };\n if (context.useCache) {\n const hit = context.cache.lookup(identity);\n if (hit !== undefined) return hit;\n }\n\n const trials: TrialResult[] = [];\n const wanted = clampedTrialCount(context.evalCase.trials);\n for (let index = 0; index < wanted; index += 1) {\n trials.push(runTrial(context, arm));\n }\n // A disagreement makes the configured sample inconclusive, so collect the full five trials.\n while (shouldEscalate(trials)) trials.push(runTrial(context, arm));\n\n const result: ArmResult = {\n arm,\n cached: false,\n pass: hasMajority(trials),\n trials,\n };\n context.cache.store(identity, result);\n return result;\n}\n\nfunction runTrial(context: ArmContext, arm: Arm): TrialResult {\n // The runner owns generic resource lifecycle; adapters own provider-specific setup inside it.\n const workspace = mkdtempSync(join(tmpdir(), `skillval-${context.evalCase.id}-`));\n const trialHome = mkdtempSync(join(tmpdir(), \"skillval-home-\"));\n\n try {\n const fixtureSetup =\n context.fixture === undefined\n ? undefined\n : applyFixture(context.fixture, workspace, trialHome);\n const trace = context.executor.runTrial({\n arm,\n evalCase: context.evalCase,\n home: trialHome,\n skillDirectory: context.skill.skillDirectory,\n skillName: context.skill.name,\n workspace,\n });\n const checks = gradeTrial(context.evalCase, arm, trace, workspace);\n return {\n checks,\n fixtureSetup,\n pass: checks.every((check) => check.pass),\n usage: trace.usage,\n };\n } catch (error) {\n if (error instanceof FixtureSetupError) {\n // Workspace staging failed before the agent ran; this is infrastructure, not grading.\n return {\n checks: [{ detail: error.message, name: \"fixture-setup\", pass: false }],\n fixtureSetup: error.results,\n pass: false,\n usage: undefined,\n };\n }\n const detail = error instanceof Error ? error.message : String(error);\n return {\n checks: [{ detail, name: \"run\", pass: false }],\n pass: false,\n usage: undefined,\n };\n } finally {\n // Trials may contain generated source or credentials-related environment state. Always clean\n // both directories, including executor and grader failure paths.\n rmSync(workspace, { force: true, recursive: true });\n rmSync(trialHome, { force: true, recursive: true });\n }\n}\n","/** Owns arm-result persistence and keeps cache-key construction private from the runner. */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { resolveStateDirectory } from \"./config.js\";\nimport type { ExecutorMetadata } from \"./executors/types.js\";\nimport type { Arm, ArmResult, EvalCase } from \"./types.js\";\nimport { sha256 } from \"./utils.js\";\n\n// Bump this whenever execution or grading semantics change so old results cannot be reused.\nexport const RUNNER_VERSION = 9;\n\nexport interface ArmCacheIdentity {\n readonly arm: Arm;\n readonly evalCase: EvalCase;\n readonly executor: ExecutorMetadata;\n readonly fixtureHash?: string;\n readonly skillHash: string;\n}\n\nexport class ArmCache {\n readonly #stateDirectory: string;\n\n public constructor(stateDirectory = resolveStateDirectory()) {\n this.#stateDirectory = stateDirectory;\n }\n\n public lookup(identity: ArmCacheIdentity): ArmResult | undefined {\n const path = this.#path(identity);\n if (!existsSync(path)) return undefined;\n return { ...(JSON.parse(readFileSync(path, \"utf8\")) as ArmResult), cached: true };\n }\n\n public store(identity: ArmCacheIdentity, result: ArmResult): void {\n const path = this.#path(identity);\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, JSON.stringify(result));\n }\n\n #path(identity: ArmCacheIdentity): string {\n // Every input that can change an arm result belongs in this identity. The baseline arm never\n // installs the skill, so its result cannot depend on skill content; excluding the skill hash\n // from the baseline key lets a baseline result survive skill edits, roughly halving recompute\n // on the iterate-a-skill-and-re-run loop.\n const skillComponent = identity.arm === \"skill\" ? identity.skillHash : \"\";\n const parts = [\n String(RUNNER_VERSION),\n skillComponent,\n JSON.stringify(identity.evalCase),\n identity.arm,\n identity.executor.name,\n identity.executor.version,\n identity.executor.model,\n identity.executor.thinking,\n ];\n // Appended conditionally so fixture-free identities keep their historical keys.\n if (identity.fixtureHash !== undefined) parts.push(identity.fixtureHash);\n const key = sha256(parts.join(\"\\0\"));\n return join(this.#stateDirectory, \"cache\", `${key}.json`);\n }\n}\n","/** Composes trace, trigger, regex, and registered deterministic checks for one trial. */\nimport { readFileSync } from \"node:fs\";\nimport { relative } from \"node:path\";\nimport { runGraders } from \"./graders.js\";\nimport type { Arm, Check, EvalCase, Trace } from \"./types.js\";\nimport { walkFiles } from \"./utils.js\";\n\nconst INJECTED_FILES = new Set([\"package.json\", \"tsconfig.json\"]);\nexport function gradeTrial(evalCase: EvalCase, arm: Arm, trace: Trace, workspace: string): Check[] {\n const checks: Check[] = [];\n\n checks.push({\n detail: trace.completed ? \"turn.completed seen\" : \"no turn.completed in trace\",\n name: \"trace\",\n pass: trace.completed,\n });\n\n if (evalCase.should_trigger !== undefined && arm === \"skill\") {\n const evidence = trace.invocationEvidence === null ? \"none\" : trace.invocationEvidence;\n checks.push({\n detail: `invoked=${trace.invoked}, expected=${evalCase.should_trigger}, evidence=${evidence}`,\n name: \"trigger\",\n pass: trace.invoked === evalCase.should_trigger,\n });\n }\n\n const gradedText =\n evalCase.mode === \"generation\"\n ? walkFiles(workspace)\n .filter((file) => !INJECTED_FILES.has(relative(workspace, file)))\n .map((file) => `=== ${relative(workspace, file)} ===\\n${readFileSync(file, \"utf8\")}`)\n .join(\"\\n\")\n : trace.agentText;\n\n for (const pattern of evalCase.assert?.must_match ?? []) {\n const pass = new RegExp(pattern, \"m\").test(gradedText);\n checks.push({\n detail: pass ? pattern : `${pattern} | got: ${gradedText.slice(0, 400)}`,\n name: \"must_match\",\n pass,\n });\n }\n for (const pattern of evalCase.assert?.must_not_match ?? []) {\n checks.push({\n detail: pattern,\n name: \"must_not_match\",\n pass: !new RegExp(pattern, \"m\").test(gradedText),\n });\n }\n\n checks.push(...runGraders(evalCase, workspace));\n return checks;\n}\n","import type { TrialResult } from \"./types.js\";\n\nexport function clampedTrialCount(configured: number | undefined): number {\n return Math.min(5, Math.max(1, configured ?? 1));\n}\n\nexport function hasMajority(trials: readonly Pick<TrialResult, \"pass\">[]): boolean {\n const passes = trials.filter((trial) => trial.pass).length;\n return passes * 2 > trials.length;\n}\n\nexport function shouldEscalate(trials: readonly Pick<TrialResult, \"pass\">[]): boolean {\n return new Set(trials.map((trial) => trial.pass)).size > 1 && trials.length < 5;\n}\n"],"mappings":"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","names":["existsSync","readFileSync","homedir","readFileSync","join","join","readFileSync","spawnSync","mkdirSync","readFileSync","symlinkSync","homedir","join","TRIAL_TIMEOUT_MS","homedir","seedSkill","join","spawnSync","mkdirSync","symlinkSync","readFileSync","spawnSync","readFileSync","homedir","join","TRIAL_TIMEOUT_MS","join","homedir","spawnSync","readFileSync","homedir","existsSync","readFileSync","existsSync","readdirSync","join","readFileSync","statSync","dirname","join","parseYaml","Type","checkSchema","schemaErrors","spawnSync","existsSync","readFileSync","join","resolve","Type","Type","checkSchema","schemaErrors","spawnSync","createHash","readdirSync","readFileSync","join","join","readdirSync","createHash","readFileSync","spawnSync","readFileSync","dirname","join","statSync","parseYaml","existsSync","readdirSync","join","mkdirSync","writeFileSync","join","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","existsSync","readFileSync","mkdirSync","dirname","writeFileSync","join","readFileSync","relative","relative","readFileSync","join","mkdirSync","writeFileSync"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dungle-scrubs/skillval",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Deterministic evaluation for agent skills",
5
5
  "keywords": [
6
6
  "agent-skills",
@@ -49,10 +49,11 @@
49
49
  },
50
50
  "packageManager": "pnpm@10.28.2",
51
51
  "dependencies": {
52
- "@types/node": "^26.0.1",
52
+ "@types/node": "^22.0.0",
53
+ "ajv": "^8.20.0",
53
54
  "commander": "^15.0.0",
54
55
  "typebox": "^1.3.6",
55
- "typescript": "^6.0.3",
56
+ "typescript": "^7.0.2",
56
57
  "yaml": "^2.9.0"
57
58
  },
58
59
  "devDependencies": {
@@ -3,7 +3,7 @@
3
3
  "required": ["executor", "roots"],
4
4
  "properties": {
5
5
  "executor": {
6
- "enum": ["codex"],
6
+ "enum": ["claude", "codex", "pi"],
7
7
  "description": "Trial executor."
8
8
  },
9
9
  "roots": {
@@ -18,6 +18,25 @@
18
18
  "assert": {
19
19
  "type": "object",
20
20
  "properties": {
21
+ "command_exit": {
22
+ "type": "object",
23
+ "required": ["command"],
24
+ "properties": {
25
+ "command": {
26
+ "type": "string",
27
+ "description": "Shell command run in the workspace; the grader passes when it exits as expected. Trusted case input: this is arbitrary shell executed on the grading machine (see the README's Trust model section).",
28
+ "minLength": 1,
29
+ "pattern": "\\S"
30
+ },
31
+ "expect": {
32
+ "type": "integer",
33
+ "description": "Exit code the command must produce to pass. Defaults to 0.",
34
+ "maximum": 255,
35
+ "minimum": 0
36
+ }
37
+ },
38
+ "additionalProperties": false
39
+ },
21
40
  "graders": {
22
41
  "type": "array",
23
42
  "items": {
@@ -25,6 +44,33 @@
25
44
  },
26
45
  "uniqueItems": true
27
46
  },
47
+ "json_schema": {
48
+ "type": "object",
49
+ "required": ["file", "schema"],
50
+ "properties": {
51
+ "file": {
52
+ "type": "string",
53
+ "description": "Produced file, relative to the workspace, parsed as JSON and validated.",
54
+ "minLength": 1,
55
+ "pattern": "\\S"
56
+ },
57
+ "schema": {
58
+ "anyOf": [
59
+ {
60
+ "type": "object",
61
+ "patternProperties": {
62
+ "^.*$": {}
63
+ }
64
+ },
65
+ {
66
+ "type": "boolean"
67
+ }
68
+ ],
69
+ "description": "JSON Schema (draft 2020-12) the produced file must satisfy; an object or a boolean schema. Omit $schema, or set it to 2020-12; other declared dialects are rejected."
70
+ }
71
+ },
72
+ "additionalProperties": false
73
+ },
28
74
  "must_match": {
29
75
  "type": "array",
30
76
  "items": {
@@ -56,7 +102,7 @@
56
102
  "minLength": 1,
57
103
  "pattern": "\\S"
58
104
  },
59
- "description": "Shell commands run sequentially inside the workspace after the copy."
105
+ "description": "Shell commands run sequentially inside the workspace after the copy. Trusted case input: arbitrary shell executed on the grading machine (see the README's Trust model section)."
60
106
  }
61
107
  },
62
108
  "additionalProperties": false,
@@ -112,7 +158,7 @@
112
158
  "minLength": 1,
113
159
  "pattern": "\\S"
114
160
  },
115
- "description": "Shell commands run sequentially inside the workspace after the copy."
161
+ "description": "Shell commands run sequentially inside the workspace after the copy. Trusted case input: arbitrary shell executed on the grading machine (see the README's Trust model section)."
116
162
  }
117
163
  },
118
164
  "additionalProperties": false,