@attest-ai/core 1.0.0 → 1.1.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +1869 -887
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +413 -124
- package/dist/cjs/proto/index.cjs +8 -1
- package/dist/cjs/proto/index.cjs.map +1 -1
- package/dist/cjs/proto/index.d.cts +17 -1
- package/dist/esm/cli.d.ts +3 -1
- package/dist/esm/cli.js +219 -80
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/index.d.ts +413 -124
- package/dist/esm/index.js +1861 -891
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/proto/index.d.ts +17 -1
- package/dist/esm/proto/index.js +6 -1
- package/dist/esm/proto/index.js.map +1 -1
- package/engine-checksums.json +10 -0
- package/package.json +4 -2
package/dist/esm/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli.ts","../../src/version.ts","../../src/engine-manager.ts","../../src/engine-downloader.ts","../../src/scaffold.ts","../../src/capture.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * The `attest` command line (`npx attest`).\n *\n * `attest init` runs in the SDK. Every other command (`doctor`, `baseline`, `policy`,\n * `cache`, `calibrate`, `version` and any command a later engine adds) runs in\n * `attest-engine`: the CLI resolves a version-checked engine with `resolveEngine`, checks\n * that the engine's `help` lists the command, and forwards the arguments, stdio and exit\n * code unchanged. A missing, mismatched or too-old engine exits 1 before anything runs, so\n * a gate such as `attest policy evaluate` never exits 0 without evaluating.\n *\n * `attest capture` is forwarded the same way; when the engine writes a fixture, the CLI\n * then drafts its Vitest file (`emitVitest`).\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { ENGINE_VERSION, VERSION } from \"./version.js\";\nimport { resolveEngine } from \"./engine-manager.js\";\nimport { scaffoldProject } from \"./scaffold.js\";\nimport { emitVitest, testPathFor } from \"./capture.js\";\n\nconst HELP_FLAGS = new Set([\"-h\", \"--help\"]);\n\nconst SDK_USAGE =\n \"usage: attest <command> [args]\\n\" +\n \"\\n\" +\n \"SDK commands:\\n\" +\n \" init [--ci github] [--skills] [--mcp] [--json]\\n\" +\n \" scaffold a sample test and merge policy here\\n\" +\n \" (--ci github also writes .github/workflows/attest.yml;\\n\" +\n \" --skills installs the agent skills with attest-engine;\\n\" +\n \" --mcp writes the MCP client configs (.mcp.json, .cursor/mcp.json,\\n\" +\n \" .codex/config.toml) with attest-engine;\\n\" +\n \" --json prints {created, updated, skipped} paths as JSON)\\n\" +\n \"\\n\" +\n \"`attest capture` (engine) also drafts tests/attest/<name>.test.ts from a verified\\n\" +\n \"fixture, unless that file exists.\\n\" +\n \"\\n\" +\n \"options:\\n\" +\n \" --version print the SDK version and the engine version it requires\\n\" +\n \" --help print this help\\n\";\n\nconst HELP_PROBE_TIMEOUT_MS = 10_000;\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/**\n * `{command: summary}` from `<engine> help`, or null if it lists none.\n *\n * stdin is closed and the probe times out after 10 s, so an engine that predates the\n * command registry (and starts the JSON-RPC server for `help`) cannot hang the CLI.\n */\nexport function engineCommands(\n engine: string,\n timeoutMs: number = HELP_PROBE_TIMEOUT_MS,\n): Map<string, string> | null {\n const proc = spawnSync(engine, [\"help\"], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n encoding: \"utf-8\",\n timeout: timeoutMs,\n });\n if (proc.error || proc.status !== 0) return null;\n const lines = proc.stdout.split(\"\\n\");\n const start = lines.indexOf(\"commands:\");\n if (start === -1) return null;\n const commands = new Map<string, string>();\n for (const line of lines.slice(start + 1)) {\n const match = /^\\s*(\\S+)\\s*(.*)$/.exec(line);\n if (match?.[1]) commands.set(match[1], (match[2] ?? \"\").trim());\n }\n return commands;\n}\n\n/** Print SDK commands, plus engine commands when an engine is available without download. */\nasync function printHelp(): Promise<number> {\n process.stdout.write(`${SDK_USAGE}\\n`);\n let engine: string;\n try {\n engine = await resolveEngine(undefined, { allowDownload: false });\n } catch (err) {\n const firstLine = (errorMessage(err).split(\"\\n\")[0] ?? \"\").replace(/\\.$/, \"\");\n process.stdout.write(\n `engine commands: not available (${firstLine}). Run \\`attest doctor\\` to download ` +\n `attest-engine ${ENGINE_VERSION}, or set ATTEST_ENGINE_PATH.\\n`,\n );\n return 0;\n }\n const commands = engineCommands(engine);\n if (commands === null) {\n process.stdout.write(\n `engine commands: not available (attest-engine at ${engine} lists no commands; ` +\n \"it predates the command registry).\\n\",\n );\n return 0;\n }\n const width = Math.max(0, ...[...commands.keys()].map((name) => name.length));\n process.stdout.write(`engine commands (attest-engine ${ENGINE_VERSION}, ${engine}):\\n`);\n for (const [name, summary] of commands) {\n process.stdout.write(` ${name.padEnd(width)} ${summary}\\n`);\n }\n return 0;\n}\n\n/** Map a child's exit to a shell exit status (signal N → 128 + N). */\nexport function exitStatus(status: number | null, signal: NodeJS.Signals | null): number {\n if (status !== null) return status;\n if (signal !== null) return 128 + (os.constants.signals[signal] ?? 0);\n return 1;\n}\n\n/**\n * Resolve a version-checked engine whose `help` lists `command`; print the reason to\n * stderr and resolve to null when there is none.\n */\nasync function engineProviding(command: string): Promise<string | null> {\n let engine: string;\n try {\n engine = await resolveEngine();\n } catch (err) {\n process.stderr.write(`attest: ${errorMessage(err)}\\n`);\n return null;\n }\n const commands = engineCommands(engine);\n if (commands === null || (command !== \"help\" && !commands.has(command))) {\n process.stderr.write(\n `attest: attest-engine at ${engine} (version ${ENGINE_VERSION}) predates ` +\n `\\`attest ${command}\\`: its help does not list that command. Set ATTEST_ENGINE_PATH ` +\n \"to an engine built from this release (make engine), or install a release whose \" +\n \"engine provides it.\\n\",\n );\n return null;\n }\n return engine;\n}\n\nconst INIT_HELP_ENTRY = {\n name: \"init\",\n summary: \"scaffold a sample test and policy; --ci github, --skills, --mcp, --json\",\n schema: \"cli/init.schema.json\",\n exit_codes: [\n { code: 0, meaning: \"success\" },\n {\n code: 1,\n meaning: \"--skills or --mcp could not install: the engine is missing, too old or failed\",\n },\n { code: 2, meaning: \"usage error\" },\n ],\n};\n\n/** Print the engine's `help --json` document with the SDK's `init` command added. */\nexport function helpJson(engine: string): number {\n const proc = spawnSync(engine, [\"help\", \"--json\"], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n encoding: \"utf-8\",\n });\n if (proc.error) throw proc.error;\n if (proc.status !== 0) {\n process.stderr.write(proc.stderr);\n return exitStatus(proc.status, proc.signal);\n }\n let doc: { commands: { name: string }[] };\n try {\n doc = JSON.parse(proc.stdout) as { commands: { name: string }[] };\n if (!Array.isArray(doc.commands)) throw new Error(\"no commands array\");\n } catch (err) {\n process.stderr.write(`attest: \\`${engine} help --json\\` printed an unexpected document: ${errorMessage(err)}\\n`);\n return 1;\n }\n doc.commands = [...doc.commands, INIT_HELP_ENTRY].sort((a, b) =>\n a.name < b.name ? -1 : a.name > b.name ? 1 : 0,\n );\n process.stdout.write(`${JSON.stringify(doc, null, 2)}\\n`);\n return 0;\n}\n\nasync function forward(args: string[]): Promise<number> {\n const command = args[0] ?? \"\";\n const engine = await engineProviding(command);\n if (engine === null) return 1;\n if (args.length === 2 && command === \"help\" && args[1] === \"--json\") return helpJson(engine);\n if (command === \"capture\" && captureWritesFixture(args.slice(1))) {\n return captureAndEmit(engine, args.slice(1));\n }\n const proc = spawnSync(engine, args, { stdio: \"inherit\" });\n if (proc.error) throw proc.error;\n return exitStatus(proc.status, proc.signal);\n}\n\n// Engine capture modes the CLI drafts no test for: help, --check-redaction (writes no\n// fixture) and --serve (used by record(), which drafts its own). Go flags accept one or\n// two dashes.\nconst CAPTURE_NO_TEST = new Set([\"check-redaction\", \"serve\", \"h\", \"help\"]);\n\nfunction flagName(arg: string): string | null {\n if (!arg.startsWith(\"-\") || arg === \"-\" || arg === \"--\") return null;\n return arg.replace(/^-+/, \"\").split(\"=\", 1)[0] ?? null;\n}\n\n/** True when `attest capture` args select a mode whose fixture the CLI drafts a test for. */\nexport function captureWritesFixture(args: string[]): boolean {\n for (const a of args) {\n if (a === \"--\") break;\n const name = flagName(a);\n if (name !== null && CAPTURE_NO_TEST.has(name)) return false;\n }\n return true;\n}\n\nfunction userResultFile(args: string[]): boolean {\n for (const a of args) {\n if (a === \"--\") break;\n if (flagName(a) === \"result-file\") return true;\n }\n return false;\n}\n\n/** Run `attest-engine capture` and draft the Vitest file for the fixture it wrote. */\nfunction captureAndEmit(engine: string, args: string[]): number {\n if (userResultFile(args)) {\n process.stderr.write(\n \"attest: capture --result-file is set by the attest CLI; run attest-engine capture directly to choose it\\n\",\n );\n return 2;\n }\n const tmp = fs.mkdtempSync(path.join(os.tmpdir(), \"attest-capture-\"));\n const resultFile = path.join(tmp, \"result.json\");\n let result: { fixture: string; verified: boolean; outcome: string };\n let code: number;\n try {\n const proc = spawnSync(engine, [\"capture\", \"--result-file\", resultFile, ...args], { stdio: \"inherit\" });\n if (proc.error) throw proc.error;\n code = exitStatus(proc.status, proc.signal);\n if (!fs.existsSync(resultFile)) return code;\n result = JSON.parse(fs.readFileSync(resultFile, \"utf8\")) as { fixture: string; verified: boolean; outcome: string };\n } finally {\n fs.rmSync(tmp, { recursive: true, force: true });\n }\n const fixture = result.fixture;\n if (!result.verified) {\n const reason = result.outcome === \"nothing_to_verify\" ? \"with nothing to verify\" : \"for unverified\";\n process.stderr.write(` test: none drafted ${reason} ${fixture}\\n`);\n return code;\n }\n const written = emitVitest(fixture);\n process.stderr.write(\n written === null\n ? ` test: ${testPathFor(fixture)} exists; left unchanged\\n`\n : ` test: drafted ${written}\\n`,\n );\n return code;\n}\n\nconst INIT_USAGE =\n \"usage: attest init [--ci github] [--skills] [--mcp] [--json] (scaffolds into the current directory)\";\n\nconst INIT_KINDS = [\"created\", \"updated\", \"skipped\"] as const;\n// `--mcp` adds a fourth kind: configs that already hold a different `attest` entry.\nconst INIT_KINDS_WITH_CONFLICT = [...INIT_KINDS, \"conflict\"] as const;\ntype InitKind = (typeof INIT_KINDS_WITH_CONFLICT)[number];\ntype InitResult = Record<InitKind, string[]>;\n\n// `attest-engine skills install --json` key -> `attest init --json` key.\nconst SKILLS_KINDS = [\n [\"created\", \"created\"],\n [\"updated\", \"updated\"],\n [\"unchanged\", \"skipped\"],\n] as const;\n\n// `attest-engine mcp install --json` key -> `attest init --json` key.\nconst MCP_KINDS = [\n [\"created\", \"created\"],\n [\"updated\", \"updated\"],\n [\"unchanged\", \"skipped\"],\n [\"conflict\", \"conflict\"],\n] as const;\n\ninterface InitArgs {\n ci: boolean;\n skills: boolean;\n mcp: boolean;\n json: boolean;\n}\n\n/** Parse `attest init` args; null on a usage error. */\nfunction parseInitArgs(args: string[]): InitArgs | null {\n const parsed: InitArgs = { ci: false, skills: false, mcp: false, json: false };\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === \"--ci\" && args[i + 1] === \"github\" && !parsed.ci) {\n parsed.ci = true;\n i++;\n } else if (arg === \"--ci=github\" && !parsed.ci) {\n parsed.ci = true;\n } else if (arg === \"--skills\" && !parsed.skills) {\n parsed.skills = true;\n } else if (arg === \"--mcp\" && !parsed.mcp) {\n parsed.mcp = true;\n } else if (arg === \"--json\" && !parsed.json) {\n parsed.json = true;\n } else {\n return null;\n }\n }\n return parsed;\n}\n\nfunction emptyInitResult(): InitResult {\n return { created: [], updated: [], skipped: [], conflict: [] };\n}\n\n/**\n * Run `<engine> <subcommand> --json` and map its path lists to init kinds.\n * Throws when the engine fails or prints an unexpected document.\n */\nfunction runEngineInstall(\n engine: string,\n subcommand: string[],\n kinds: readonly (readonly [string, InitKind])[],\n what: string,\n): InitResult {\n const argv = [...subcommand, \"--json\"];\n const shown = [engine, ...argv].join(\" \");\n const proc = spawnSync(engine, argv, {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n encoding: \"utf-8\",\n });\n if (proc.error) throw proc.error;\n if (proc.status !== 0) {\n const detail = proc.stderr.trim();\n throw new Error(\n `${what} failed (\\`${shown}\\` exited ${String(exitStatus(proc.status, proc.signal))})` +\n (detail === \"\" ? \"\" : `: ${detail}`),\n );\n }\n process.stderr.write(proc.stderr);\n let doc: unknown;\n try {\n doc = JSON.parse(proc.stdout);\n } catch (err) {\n throw new Error(`\\`${shown}\\` printed invalid JSON: ${errorMessage(err)}`);\n }\n if (typeof doc !== \"object\" || doc === null || Array.isArray(doc)) {\n throw new Error(`\\`${shown}\\` printed ${JSON.stringify(doc)}, not an object`);\n }\n const record = doc as Record<string, unknown>;\n const result = emptyInitResult();\n for (const [engineKind, initKind] of kinds) {\n const paths = record[engineKind];\n if (!Array.isArray(paths) || !paths.every((p): p is string => typeof p === \"string\")) {\n throw new Error(`\\`${shown}\\` printed no \\`${engineKind}\\` list of paths: ${proc.stdout}`);\n }\n result[initKind].push(...paths);\n }\n return result;\n}\n\n/** Run `<engine> skills install --dir <root> --json` and map its paths to init kinds. */\nfunction installSkills(engine: string, root: string): InitResult {\n return runEngineInstall(engine, [\"skills\", \"install\", \"--dir\", root], SKILLS_KINDS, \"skills install\");\n}\n\n/**\n * The command an MCP client runs to start the server: `pnpm exec attest mcp` in a pnpm\n * project (`pnpm-lock.yaml` in `root`), else `npx --no attest mcp`. `--no` makes a missing\n * local install fail instead of letting npx fetch the unscoped `attest` package.\n */\nfunction mcpLaunchCommand(root: string): string[] {\n return fs.existsSync(path.join(root, \"pnpm-lock.yaml\"))\n ? [\"pnpm\", \"exec\", \"attest\", \"mcp\"]\n : [\"npx\", \"--no\", \"attest\", \"mcp\"];\n}\n\n/** Run `<engine> mcp install --dir <root> --command <launch> --json`. */\nfunction installMcp(engine: string, root: string): InitResult {\n return runEngineInstall(\n engine,\n [\"mcp\", \"install\", \"--dir\", root, \"--command\", JSON.stringify(mcpLaunchCommand(root))],\n MCP_KINDS,\n \"mcp install\",\n );\n}\n\nfunction printSkills(root: string, skills: InitResult): void {\n const abs = (rel: string) => path.join(root, ...rel.split(\"/\"));\n for (const rel of skills.created) process.stdout.write(`Created: ${abs(rel)}\\n`);\n for (const rel of skills.updated) process.stdout.write(`Updated: ${abs(rel)}\\n`);\n for (const rel of skills.skipped) process.stderr.write(`Skipped (unchanged): ${abs(rel)}\\n`);\n for (const rel of skills.conflict) {\n process.stderr.write(\n `Conflict (a different attest entry, left as it is; ` +\n `\\`attest-engine mcp install --force\\` replaces it): ${abs(rel)}\\n`,\n );\n }\n}\n\nasync function runInit(parsed: InitArgs, root: string): Promise<InitResult | null> {\n const result = emptyInitResult();\n const installs: [boolean, string, (engine: string, root: string) => InitResult][] = [\n [parsed.skills, \"skills\", installSkills],\n [parsed.mcp, \"mcp\", installMcp],\n ];\n for (const [wanted, command, install] of installs) {\n if (!wanted) continue;\n const engine = await engineProviding(command);\n if (engine === null) return null;\n let installed: InitResult;\n try {\n installed = install(engine, root);\n } catch (err) {\n process.stderr.write(`attest: ${errorMessage(err)}\\n`);\n return null;\n }\n if (!parsed.json) printSkills(root, installed);\n for (const kind of INIT_KINDS_WITH_CONFLICT) result[kind].push(...installed[kind]);\n }\n const scaffolded = scaffoldProject(root, {\n ...(parsed.ci ? { ci: \"github\" as const } : {}),\n quiet: parsed.json,\n });\n result.created.push(...scaffolded.created);\n result.skipped.push(...scaffolded.skipped);\n return result;\n}\n\n/**\n * Run `attest init [--ci github] [--skills] [--mcp] [--json]` in the current directory.\n *\n * `--skills` installs the agent skills with `attest-engine skills install` before\n * scaffolding; a missing or failing engine exits 1 with nothing scaffolded. `--json`\n * prints one `{created, updated, skipped}` document (plus `conflict` with `--mcp`) (paths relative to the current\n * directory, sorted) as the only stdout; everything else goes to stderr.\n */\nasync function cmdInit(args: string[]): Promise<number> {\n if (args.some((a) => HELP_FLAGS.has(a))) {\n process.stdout.write(`${INIT_USAGE}\\n`);\n return 0;\n }\n const parsed = parseInitArgs(args);\n if (parsed === null) {\n process.stderr.write(`${INIT_USAGE}\\n`);\n return 2;\n }\n const root = process.cwd();\n if (!parsed.json) return (await runInit(parsed, root)) === null ? 1 : 0;\n // Under --json, stdout carries the document only: anything else written goes to stderr.\n const stdoutWrite = process.stdout.write;\n process.stdout.write = process.stderr.write.bind(process.stderr) as typeof process.stdout.write;\n let result: InitResult | null;\n try {\n result = await runInit(parsed, root);\n } finally {\n process.stdout.write = stdoutWrite;\n }\n if (result === null) return 1;\n const done = result;\n const kinds = parsed.mcp ? INIT_KINDS_WITH_CONFLICT : INIT_KINDS;\n const sorted = Object.fromEntries(kinds.map((k) => [k, [...done[k]].sort()]));\n process.stdout.write(`${JSON.stringify(sorted)}\\n`);\n return 0;\n}\n\n/** Dispatch `attest` arguments and resolve to the process exit code. */\nexport async function main(argv: string[] = process.argv.slice(2)): Promise<number> {\n const [command] = argv;\n if (command === undefined || HELP_FLAGS.has(command) || (command === \"help\" && argv.length === 1)) {\n return printHelp();\n }\n if (command === \"--version\") {\n process.stdout.write(`attest ${VERSION} (requires attest-engine ${ENGINE_VERSION})\\n`);\n return 0;\n }\n if (command === \"init\") {\n return cmdInit(argv.slice(1));\n }\n if (command.startsWith(\"-\")) {\n process.stderr.write(`attest: unknown option ${command}\\n\\n${SDK_USAGE}`);\n return 2;\n }\n return forward(argv);\n}\n\n// Run when executed directly, including through the node_modules/.bin/attest symlink.\nfunction isDirectExecution(): boolean {\n const script = process.argv[1];\n if (script === undefined || !fs.existsSync(script)) return false;\n return fs.realpathSync(script) === fs.realpathSync(fileURLToPath(import.meta.url));\n}\n\nif (isDirectExecution()) {\n main().then(\n (code) => process.exit(code),\n (err: unknown) => {\n process.stderr.write(`attest: ${errorMessage(err)}\\n`);\n process.exit(1);\n },\n );\n}\n","export const VERSION = \"1.0.0\";\nexport const ENGINE_VERSION = \"1.0.0\";\n","import { spawn, spawnSync, type ChildProcess } from \"node:child_process\";\nimport { createInterface, type Interface as ReadlineInterface } from \"node:readline\";\nimport { existsSync, accessSync, statSync, constants as fsConstants } from \"node:fs\";\nimport { delimiter, join } from \"node:path\";\nimport type { InitializeResult } from \"./proto/types.js\";\nimport { decodeResponse, encodeRequest, extractResult } from \"./proto/codec.js\";\nimport { ENGINE_VERSION, VERSION } from \"./version.js\";\nimport { binaryFilename, cachedEnginePath, downloadEngine } from \"./engine-downloader.js\";\n\nconst ENGINE_BINARY_NAME = \"attest-engine\";\nconst VERSION_PROBE_TIMEOUT_MS = 10_000;\n\n/** A discovered engine does not report the version this SDK requires. */\nexport class EngineVersionMismatchError extends Error {\n readonly enginePath: string;\n readonly source: string;\n readonly found: string | null;\n readonly required: string;\n\n constructor(enginePath: string, source: string, found: string | null, required: string) {\n const reported = found === null ? \"reports no version\" : `reports version ${found}`;\n super(\n `attest-engine at ${enginePath} (from ${source}) ${reported}; ` +\n `this SDK requires attest-engine ${required}. ` +\n \"Point ATTEST_ENGINE_PATH at a matching engine, or remove the mismatched one \" +\n `from PATH so the SDK can download ${required} into ~/.attest/bin/${required}/.`,\n );\n this.name = \"EngineVersionMismatchError\";\n this.enginePath = enginePath;\n this.source = source;\n this.found = found;\n this.required = required;\n }\n}\n\n/**\n * The version `<path> version` reports, or null if it reports none.\n *\n * Every engine since 0.4 answers `version` with `attest-engine <version>`. stdin is\n * closed so a binary that starts the JSON-RPC server instead reads EOF and exits.\n */\nexport function engineVersion(enginePath: string): string | null {\n const proc = spawnSync(enginePath, [\"version\"], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n encoding: \"utf-8\",\n timeout: VERSION_PROBE_TIMEOUT_MS,\n });\n if (proc.error) throw proc.error;\n const out = proc.stdout.trim();\n const prefix = `${ENGINE_BINARY_NAME} `;\n if (proc.status !== 0 || !out.startsWith(prefix)) return null;\n return out.slice(prefix.length).trim();\n}\n\nfunction onPath(): string | null {\n for (const dir of (process.env[\"PATH\"] ?? \"\").split(delimiter)) {\n if (!dir) continue;\n const candidate = join(dir, binaryFilename());\n try {\n accessSync(candidate, fsConstants.X_OK);\n } catch {\n continue;\n }\n if (statSync(candidate).isFile()) return candidate;\n }\n return null;\n}\n\nfunction requireFile(enginePath: string, label: string): void {\n if (!existsSync(enginePath) || !statSync(enginePath).isFile()) {\n throw new Error(`${label}=${enginePath} does not exist or is not a file.`);\n }\n}\n\nasync function locateEngine(\n explicitPath: string | undefined,\n allowDownload: boolean,\n): Promise<[string, string]> {\n if (explicitPath) {\n requireFile(explicitPath, \"Engine path\");\n return [explicitPath, \"explicit engine path\"];\n }\n const envPath = process.env[\"ATTEST_ENGINE_PATH\"];\n if (envPath) {\n requireFile(envPath, \"ATTEST_ENGINE_PATH\");\n return [envPath, \"ATTEST_ENGINE_PATH\"];\n }\n const found = onPath();\n if (found) return [found, \"PATH\"];\n const cached = cachedEnginePath();\n if (cached) return [cached, \"engine cache\"];\n\n if (!allowDownload) {\n throw new Error(\n `No '${ENGINE_BINARY_NAME}' ${ENGINE_VERSION} in ATTEST_ENGINE_PATH, PATH or ` +\n `~/.attest/bin/${ENGINE_VERSION}/.`,\n );\n }\n\n const noDownload = process.env[\"ATTEST_ENGINE_NO_DOWNLOAD\"]?.toLowerCase();\n if (noDownload === \"1\" || noDownload === \"true\" || noDownload === \"yes\") {\n throw new Error(\n `Cannot find '${ENGINE_BINARY_NAME}' ${ENGINE_VERSION} and ATTEST_ENGINE_NO_DOWNLOAD is set.\\n` +\n \"Install options:\\n\" +\n \" 1. Build from source: make engine, then set ATTEST_ENGINE_PATH\\n\" +\n ` 2. Download release v${ENGINE_VERSION}: https://github.com/attest-framework/attest/releases\\n` +\n \" 3. Allow auto-download by unsetting ATTEST_ENGINE_NO_DOWNLOAD\",\n );\n }\n return [await downloadEngine(), \"download\"];\n}\n\n/**\n * Find an engine whose version matches this SDK and return its path.\n *\n * The single discovery function behind `EngineManager` and the `attest` CLI. Order:\n * explicit path → `ATTEST_ENGINE_PATH` → `attest-engine` on `PATH` →\n * `~/.attest/bin/<ENGINE_VERSION>/` → download (unless `ATTEST_ENGINE_NO_DOWNLOAD` is set or\n * `allowDownload` is false).\n * The first engine found must report exactly `ENGINE_VERSION`; a mismatched engine is\n * never skipped in favor of the next location.\n */\nexport async function resolveEngine(\n explicitPath?: string,\n options: { allowDownload?: boolean } = {},\n): Promise<string> {\n const [enginePath, source] = await locateEngine(explicitPath, options.allowDownload ?? true);\n const found = engineVersion(enginePath);\n if (found !== ENGINE_VERSION) {\n throw new EngineVersionMismatchError(enginePath, source, found, ENGINE_VERSION);\n }\n return enginePath;\n}\n\nexport class EngineManager {\n private enginePath: string;\n private readonly logLevel: string;\n private process: ChildProcess | null = null;\n private reader: ReadlineInterface | null = null;\n private initialized = false;\n private requestId = 0;\n private initResult: InitializeResult | null = null;\n\n constructor(options?: { enginePath?: string; logLevel?: string }) {\n this.enginePath = options?.enginePath ?? \"\";\n this.logLevel = options?.logLevel ?? \"warn\";\n }\n\n async start(): Promise<InitializeResult> {\n this.enginePath = await resolveEngine(this.enginePath || undefined);\n\n this.process = spawn(this.enginePath, [`--log-level=${this.logLevel}`], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n\n this.reader = createInterface({ input: this.process.stdout! });\n\n try {\n this.initResult = await this.initialize();\n } catch (err) {\n await this.stop();\n throw err;\n }\n this.initialized = true;\n return this.initResult;\n }\n\n /** Send initialize and check the engine's version and capabilities. */\n private async initialize(): Promise<InitializeResult> {\n const init = (await this.sendRequestInternal(\"initialize\", {\n sdk_name: \"attest-typescript\",\n sdk_version: VERSION,\n protocol_version: 1,\n required_capabilities: [\"layers_1_4\"],\n preferred_encoding: \"json\",\n })) as InitializeResult;\n if (init.engine_version !== ENGINE_VERSION) {\n throw new EngineVersionMismatchError(\n this.enginePath,\n \"initialize\",\n init.engine_version,\n ENGINE_VERSION,\n );\n }\n if (!init.compatible) {\n throw new Error(`Engine incompatible. Missing capabilities: ${JSON.stringify(init.missing)}`);\n }\n return init;\n }\n\n async stop(): Promise<void> {\n if (this.process === null) return;\n\n if (this.initialized) {\n try {\n await this.sendRequestInternal(\"shutdown\", {});\n } catch {\n // shutdown failed, will kill\n }\n }\n\n if (this.reader) {\n this.reader.close();\n this.reader = null;\n }\n\n if (this.process.exitCode === null) {\n this.process.kill(\"SIGTERM\");\n await new Promise<void>((res) => {\n const timer = setTimeout(() => {\n this.process?.kill(\"SIGKILL\");\n }, 5000);\n this.process!.on(\"exit\", () => {\n clearTimeout(timer);\n res();\n });\n });\n }\n\n this.initialized = false;\n this.process = null;\n }\n\n async sendRequest(method: string, params: Record<string, unknown>): Promise<unknown> {\n if (!this.initialized && method !== \"initialize\") {\n throw new Error(\"Engine not initialized. Call start() first.\");\n }\n return this.sendRequestInternal(method, params);\n }\n\n private async sendRequestInternal(method: string, params: Record<string, unknown>): Promise<unknown> {\n if (this.process === null || this.process.stdin === null || this.reader === null) {\n throw new Error(\"Engine process not started.\");\n }\n\n this.requestId += 1;\n const requestStr = encodeRequest(this.requestId, method, params);\n\n return new Promise<unknown>((resolve, reject) => {\n const onLine = (line: string): void => {\n try {\n const response = decodeResponse(line);\n resolve(extractResult(response));\n } catch (err) {\n reject(err);\n }\n };\n\n this.reader!.once(\"line\", onLine);\n\n const ok = this.process!.stdin!.write(requestStr, (err: Error | null | undefined) => {\n if (err) {\n this.reader!.removeListener(\"line\", onLine);\n reject(err);\n }\n });\n\n if (!ok) {\n this.process!.stdin!.once(\"drain\", () => {\n // write will proceed after drain\n });\n }\n });\n }\n\n get isRunning(): boolean {\n return this.process !== null && this.process.exitCode === null;\n }\n\n /** Expose process for AttestClient reader loop access */\n get childProcess(): ChildProcess | null {\n return this.process;\n }\n\n /** Expose readline interface for AttestClient reader loop */\n get readlineInterface(): ReadlineInterface | null {\n return this.reader;\n }\n}\n","import * as https from \"node:https\";\nimport * as http from \"node:http\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport * as crypto from \"node:crypto\";\nimport { ENGINE_VERSION } from \"./version.js\";\n\nconst RELEASE_BASE = `https://github.com/attest-framework/attest/releases/download/v${ENGINE_VERSION}`;\nconst CHECKSUMS_URL = `${RELEASE_BASE}/checksums-sha256.txt`;\nconst MAX_REDIRECTS = 5;\n\n/**\n * Cache directory for this SDK's engine: `~/.attest/bin/<ENGINE_VERSION>/`.\n *\n * The directory name is the canonical engine version (for example `1.0.0`). The legacy\n * unversioned `~/.attest/bin/attest-engine` is neither read nor modified.\n */\nexport function versionedBinDir(): string {\n return path.join(os.homedir(), \".attest\", \"bin\", ENGINE_VERSION);\n}\n\nexport function platformKey(): string {\n const platform = os.platform();\n const arch = os.arch();\n\n const mapping: Record<string, Record<string, string>> = {\n darwin: { arm64: \"darwin-arm64\", x64: \"darwin-amd64\" },\n linux: { arm64: \"linux-arm64\", x64: \"linux-amd64\" },\n win32: { x64: \"windows-amd64\", arm64: \"windows-arm64\" }\n };\n\n const osMap = mapping[platform];\n if (!osMap) {\n throw new Error(\n `Unsupported platform: ${platform}. Supported: darwin, linux, win32.`\n );\n }\n\n const key = osMap[arch];\n if (!key) {\n throw new Error(\n `Unsupported architecture '${arch}' on platform '${platform}'. ` +\n `Supported architectures: ${Object.keys(osMap).join(\", \")}.`\n );\n }\n\n return key;\n}\n\nexport function binaryFilename(): string {\n return os.platform() === \"win32\" ? \"attest-engine.exe\" : \"attest-engine\";\n}\n\n/** The engine binary in the versioned cache, or null if it is absent. */\nexport function cachedEnginePath(): string | null {\n const binPath = path.join(versionedBinDir(), binaryFilename());\n return fs.statSync(binPath, { throwIfNoEntry: false })?.isFile() ? binPath : null;\n}\n\nexport function parseChecksums(text: string): Map<string, string> {\n const checksums = new Map<string, string>();\n for (const line of text.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n // Format: \"{hash} {filename}\" (two spaces between hash and filename)\n const match = trimmed.match(/^([a-f0-9]{64})\\s+(.+)$/);\n if (match) {\n checksums.set(match[2], match[1]);\n }\n }\n return checksums;\n}\n\nfunction httpsGet(url: string, redirectCount = 0): Promise<Buffer> {\n if (redirectCount > MAX_REDIRECTS) {\n return Promise.reject(\n new Error(`Too many redirects (>${MAX_REDIRECTS}) following ${url}`)\n );\n }\n\n return new Promise<Buffer>((resolve, reject) => {\n const client = url.startsWith(\"https:\") ? https : http;\n client.get(url, (res) => {\n const status = res.statusCode ?? 0;\n\n if (status === 301 || status === 302) {\n const location = res.headers.location;\n if (!location) {\n reject(new Error(`Redirect ${status} without Location header from ${url}`));\n return;\n }\n res.resume();\n resolve(httpsGet(location, redirectCount + 1));\n return;\n }\n\n if (status < 200 || status >= 300) {\n res.resume();\n reject(new Error(`HTTP ${status} fetching ${url}`));\n return;\n }\n\n const chunks: Buffer[] = [];\n res.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n res.on(\"end\", () => resolve(Buffer.concat(chunks)));\n res.on(\"error\", reject);\n }).on(\"error\", reject);\n });\n}\n\nexport async function downloadEngine(): Promise<string> {\n const key = platformKey();\n const filename = `attest-engine-${key}${os.platform() === \"win32\" ? \".exe\" : \"\"}`;\n const binaryUrl = `${RELEASE_BASE}/${filename}`;\n\n process.stderr.write(`[attest] Downloading engine v${ENGINE_VERSION} for ${key}...\\n`);\n\n // Fetch checksums\n process.stderr.write(`[attest] Fetching checksums...\\n`);\n const checksumsText = (await httpsGet(CHECKSUMS_URL)).toString(\"utf-8\");\n const checksums = parseChecksums(checksumsText);\n const expectedHash = checksums.get(filename);\n if (!expectedHash) {\n throw new Error(\n `No checksum found for '${filename}' in checksums-sha256.txt. ` +\n `Available files: ${[...checksums.keys()].join(\", \")}`\n );\n }\n\n // Download binary\n process.stderr.write(`[attest] Downloading ${binaryUrl}...\\n`);\n const data = await httpsGet(binaryUrl);\n\n // Verify SHA256\n const actualHash = crypto.createHash(\"sha256\").update(data).digest(\"hex\");\n if (actualHash !== expectedHash) {\n throw new Error(\n `SHA256 mismatch for ${filename}. ` +\n `Expected: ${expectedHash}, got: ${actualHash}. ` +\n `The download may be corrupted. Retry or download manually.`\n );\n }\n process.stderr.write(`[attest] Checksum verified.\\n`);\n\n // Atomic write: temp file + rename\n const dir = versionedBinDir();\n fs.mkdirSync(dir, { recursive: true });\n const destPath = path.join(dir, binaryFilename());\n const suffix = `${String(process.pid)}.${crypto.randomBytes(8).toString(\"hex\")}`;\n const tmpPath = path.join(dir, `.${binaryFilename()}.tmp.${suffix}`);\n try {\n fs.writeFileSync(tmpPath, data, { flag: \"wx\", mode: 0o755 });\n fs.chmodSync(tmpPath, 0o755);\n fs.renameSync(tmpPath, destPath);\n } catch (err) {\n // EEXIST means the temp name belongs to someone else; leave it alone.\n if ((err as NodeJS.ErrnoException).code !== \"EEXIST\") fs.rmSync(tmpPath, { force: true });\n throw err;\n }\n\n process.stderr.write(`[attest] Engine installed at ${destPath}\\n`);\n return destPath;\n}\n","/**\n * Scaffolding for `attest init`.\n *\n * `attest init` writes a sample Vitest test that runs with no model, API key or\n * network: the agent run is a trace built by hand with `TraceBuilder` and every\n * assertion is deterministic (layers 1-4). `attest init --ci github` also writes a\n * GitHub Actions workflow that gates merges on the test run, the report and the\n * policy.\n */\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { VERSION } from \"./version.js\";\n\n/** Marks the line a new user edits to see a failure. */\nexport const DEMO_MARKER = \"ATTEST-DEMO\";\n\nexport const CI_PROVIDERS = [\"github\"] as const;\nexport type CiProvider = (typeof CI_PROVIDERS)[number];\n\nexport const SAMPLE_TEST_TEMPLATE = `// Sample Attest test written by \\`attest init\\`. Run it with \\`npx vitest run\\`.\nimport { it } from \"vitest\";\nimport { attestExpect, TraceBuilder, type Trace } from \"@attest-ai/core\";\nimport { evaluate } from \"@attest-ai/vitest\";\n\n// The trace of one agent run, built by hand so the sample needs no model, API key\n// or network. Replace it with a trace from your agent: wrap the agent with\n// \\`new Agent(...)\\` or record it with an adapter such as OpenAIAdapter.\nfunction myAgentResult(): Trace {\n return new TraceBuilder(\"refund-agent\")\n .setInput({ user_message: \"Please refund order ORD-1001.\" })\n .addToolCall(\"lookup_order\", {\n args: { order_id: \"ORD-1001\" },\n result: { status: \"delivered\", amount: 42.0 },\n })\n .addToolCall(\"issue_refund\", {\n args: { order_id: \"ORD-1001\", amount: 42.0 },\n result: { refund_id: \"RF-1001\" },\n })\n .setOutput({\n message: \"Your refund of $42.00 has been issued.\",\n structured: { refund_id: \"RF-1001\", amount: 42.0 },\n })\n .setMetadata({ total_tokens: 180, cost_usd: 0.002, latency_ms: 900 })\n .build();\n}\n\nit(\"my agent issues the refund\", async (context) => {\n const chain = attestExpect(myAgentResult())\n .outputMatchesSchema({ type: \"object\", required: [\"refund_id\"] }) // layer 1: schema\n .costUnder(0.01) // layer 2: constraint\n .toolsCalledInOrder([\"lookup_order\", \"issue_refund\"]) // layer 3: trace\n .outputContains(\"refund\"); // ${DEMO_MARKER}: change \"refund\" to \"store credit\"\n await evaluate(chain, { context });\n});\n`;\n\n/** Vitest arguments that add AttestReporter and write the report-v2 file. */\nexport const REPORT_ARGS =\n \"--reporter=default --reporter=@attest-ai/vitest/reporter --outputFile.attest=attest-report.json\";\n\nexport const POLICY_TEMPLATE = `# Merge policy for \\`attest policy evaluate --report <report> --policy attest.policy.yaml\\`.\n# Exit 0: pass. Exit 1: a blocking rule failed. Exit 2: warnings only.\nlayers:\n 0: # layer 0 caps every layer together\n max_hard_fails: 0\n# Assertions that could not run (no judge configured, simulation) warn instead of block.\nnot_evaluated: warn\n`;\n\nexport const GITHUB_WORKFLOW_TEMPLATE = `# Written by \\`attest init --ci github\\`.\n# The test step records its outcome and continues so the report is always uploaded,\n# the JUnit file written, the policy evaluated and the pull request summarised; the last\n# step fails the job when the tests failed. A policy warning (exit 2) does not fail the job.\nname: attest\n\non:\n pull_request:\n push:\n branches: [main]\n\npermissions:\n contents: read\n\njobs:\n attest:\n runs-on: ubuntu-latest\n permissions:\n contents: read\n pull-requests: write\n steps:\n - uses: actions/checkout@v6\n with:\n persist-credentials: false\n - uses: actions/setup-node@v6\n with:\n node-version: 22\n - name: Install dependencies\n run: npm ci\n - name: Run tests\n id: tests\n continue-on-error: true\n # Traces (prompts, outputs, tool args; not redacted) travel in the artifact; on a public\n # repository any signed-in GitHub user can download it. Enable on private repositories only:\n # env:\n # ATTEST_REPORT_TRACES: \"1\"\n run: npx vitest run ${REPORT_ARGS}\n - name: Write the JUnit report\n if: always()\n run: npx attest report junit --report attest-report.json --out attest-junit.xml\n - name: Write the failure viewer\n if: always()\n run: npx attest view attest-report.json --no-open --out attest-report.html\n - name: Upload the Attest report\n if: always()\n uses: actions/upload-artifact@v7\n with:\n name: attest-report\n path: |\n attest-report.json\n attest-junit.xml\n attest-report.html\n if-no-files-found: error\n - name: Evaluate the merge policy\n if: always()\n run: |\n set +e\n npx attest policy evaluate --report attest-report.json --policy attest.policy.yaml\n code=$?\n if [ \"$code\" -eq 2 ]; then\n echo \"::warning::attest policy: warnings only (exit 2)\"\n exit 0\n fi\n exit \"$code\"\n - name: Annotate the pull request\n # Posts one summary comment (updated on every run) and annotates failures at their\n # file and line. Fork pull requests get a read-only token that cannot comment; the\n # last step still fails the job when tests failed.\n if: >-\n always() && github.event_name == 'pull_request' &&\n github.event.pull_request.head.repo.full_name == github.repository\n uses: attest-framework/attest/.github/actions/pr-annotate@v${VERSION}\n with:\n report: attest-report.json\n - name: Fail the job when tests failed\n if: always() && steps.tests.outcome == 'failure'\n run: |\n echo \"::error::vitest failed; see the Run tests step\"\n exit 1\n`;\n\n/**\n * Files `scaffoldProject` wrote (`created`) and left alone because they existed\n * (`skipped`), as forward-slash paths relative to the target directory.\n */\nexport interface ScaffoldResult {\n created: string[];\n skipped: string[];\n}\n\nfunction write(\n targetDir: string,\n rel: string,\n content: string,\n result: ScaffoldResult,\n quiet: boolean,\n): void {\n const file = path.join(targetDir, ...rel.split(\"/\"));\n if (fs.existsSync(file)) {\n result.skipped.push(rel);\n if (!quiet) process.stderr.write(`Skipped (exists): ${file}\\n`);\n return;\n }\n fs.mkdirSync(path.dirname(file), { recursive: true });\n fs.writeFileSync(file, content);\n result.created.push(rel);\n if (!quiet) process.stdout.write(`Created: ${file}\\n`);\n}\n\n/**\n * Write the sample test and the merge policy into `targetDir`; `ci: \"github\"` also\n * writes `.github/workflows/attest.yml`. Existing files are never overwritten. No\n * Vitest config is written: the workflow adds AttestReporter on the command line\n * (`REPORT_ARGS`), so an existing config keeps working unchanged. `quiet` suppresses the\n * per-file lines and the next-step hint. Returns what was written.\n */\nexport function scaffoldProject(\n targetDir: string,\n options: { ci?: CiProvider; quiet?: boolean } = {},\n): ScaffoldResult {\n const quiet = options.quiet ?? false;\n const result: ScaffoldResult = { created: [], skipped: [] };\n write(targetDir, \"tests/my-agent.test.ts\", SAMPLE_TEST_TEMPLATE, result, quiet);\n write(targetDir, \"attest.policy.yaml\", POLICY_TEMPLATE, result, quiet);\n if (options.ci === \"github\") {\n write(targetDir, \".github/workflows/attest.yml\", GITHUB_WORKFLOW_TEMPLATE, result, quiet);\n }\n if (!quiet) {\n process.stdout.write(\n `\\nNext: run \\`npx vitest run\\`. Then change the line marked ${DEMO_MARKER} in ` +\n \"tests/my-agent.test.ts and run it again to see a failure.\\n\",\n );\n }\n return result;\n}\n","/**\n * Capture: turn a run into a verified fixture, and fixtures into tests.\n *\n * `attest capture --name <name> -- <command>` (the engine) records a run's trace and model\n * exchanges into `tests/attest/fixtures/<name>.attest.json`. This module is the TypeScript\n * side:\n *\n * - `record()` captures the code in a callback in this process.\n * - `loadFixture()` reads a fixture (`proto/attest/v1/fixture-v1.schema.json`).\n * - `emitVitest()` writes the fixture's drafted contracts as a Vitest file, using the\n * `attestExpect()` DSL. `attest capture` and `record()` call it.\n */\n\nimport { spawn } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { resolveEngine } from \"./engine-manager.js\";\nimport type { Trace } from \"./proto/types.js\";\n\nexport const FIXTURE_VERSION = 1;\nexport const DEFAULT_FIXTURE_DIR = path.join(\"tests\", \"attest\", \"fixtures\");\n\n/** A capture did not produce a fixture, or produced one that is not verified. */\nexport class CaptureError extends Error {\n /** The fixture written, when the engine wrote one. */\n readonly fixture: string | null;\n\n constructor(message: string, fixture: string | null = null) {\n super(message);\n this.name = \"CaptureError\";\n this.fixture = fixture;\n }\n}\n\n/** A drafted contract: an engine assertion spec plus its id and description. */\nexport interface Contract {\n id: string;\n kind: string;\n description: string;\n type: string;\n spec: Record<string, unknown>;\n}\n\n/** A contract's status on the captured trace. */\nexport interface ContractResult {\n contract: string;\n status: string;\n explanation: string;\n}\n\n/** A capture fixture (fixture-v1). */\nexport interface Fixture {\n name: string;\n source: { kind: string; replay_capable: boolean; command?: string[]; exit_code?: number };\n trace: Trace;\n exchanges: Record<string, unknown>[];\n contracts: Contract[];\n verification: {\n verified: boolean;\n expect_fail: boolean;\n trace_check: { ok: boolean; errors: number; warnings: number };\n results: ContractResult[];\n expected_failures: string[];\n };\n world: Record<string, unknown> | null;\n}\n\nfunction toPath(p: string | URL): string {\n return p instanceof URL ? fileURLToPath(p) : p;\n}\n\n/** Read a capture fixture written by `attest capture` or `record()`. */\nexport function loadFixture(file: string | URL): Fixture {\n const p = toPath(file);\n const doc = JSON.parse(fs.readFileSync(p, \"utf8\")) as unknown;\n if (!isObject(doc) || doc[\"fixture_version\"] !== FIXTURE_VERSION) {\n throw new CaptureError(`${p}: not a fixture_version ${FIXTURE_VERSION} capture fixture`);\n }\n validate(p, doc);\n return doc as unknown as Fixture;\n}\n\n/** Fixture names, as the engine accepts them (they become file names). */\nexport const NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;\n\ntype Kind = \"string\" | \"boolean\" | \"object\" | \"array\";\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\nfunction kindOf(v: unknown): Kind | \"other\" {\n if (Array.isArray(v)) return \"array\";\n if (isObject(v)) return \"object\";\n if (typeof v === \"string\" || typeof v === \"boolean\") return typeof v as Kind;\n return \"other\";\n}\n\n/** Check the fixture-v1 fields this module reads before using any of them. */\nfunction validate(p: string, doc: Record<string, unknown>): void {\n const need = (where: string, obj: unknown, fields: Record<string, Kind>): Record<string, unknown> => {\n if (!isObject(obj)) throw new CaptureError(`${p}: ${where} is not an object`);\n for (const [key, kind] of Object.entries(fields)) {\n if (kindOf(obj[key]) !== kind) throw new CaptureError(`${p}: ${where}.${key} is missing or not a ${kind}`);\n }\n return obj;\n };\n need(\"fixture\", doc, { name: \"string\", source: \"object\", trace: \"object\", exchanges: \"array\", contracts: \"array\", verification: \"object\" });\n if (!(\"world\" in doc)) throw new CaptureError(`${p}: fixture.world is missing`);\n if (!NAME_PATTERN.test(doc[\"name\"] as string)) {\n throw new CaptureError(`${p}: fixture name ${JSON.stringify(doc[\"name\"])} is not a valid fixture name`);\n }\n const v = need(\"fixture.verification\", doc[\"verification\"], {\n verified: \"boolean\",\n expect_fail: \"boolean\",\n results: \"array\",\n expected_failures: \"array\",\n });\n (doc[\"contracts\"] as unknown[]).forEach((c, i) =>\n need(`fixture.contracts[${i}]`, c, { id: \"string\", kind: \"string\", description: \"string\", type: \"string\", spec: \"object\" }),\n );\n (v[\"results\"] as unknown[]).forEach((r, i) =>\n need(`fixture.verification.results[${i}]`, r, { contract: \"string\", status: \"string\", explanation: \"string\" }),\n );\n}\n\n// ---------------------------------------------------------------------------- emitter\n\n/**\n * An object-literal key for `k`. `__proto__` must be a computed key: written plain or\n * quoted it sets the object's prototype instead of a property.\n */\nfunction objectKey(k: string): string {\n if (k === \"__proto__\") return `[${JSON.stringify(k)}]`;\n return /^[A-Za-z_$][\\w$]*$/.test(k) ? k : JSON.stringify(k);\n}\n\n/** Make captured text safe inside a `//` comment: one line, no control characters. */\nfunction comment(text: string): string {\n return text.replace(/[\\p{Cc}\\p{Zl}\\p{Zp}]/gu, \" \");\n}\n\n/** Render a JSON value as a TypeScript literal. */\nfunction ts(value: unknown): string {\n if (value === null || typeof value === \"boolean\" || typeof value === \"number\") {\n return JSON.stringify(value);\n }\n if (typeof value === \"string\") return JSON.stringify(value);\n if (Array.isArray(value)) return `[${value.map(ts).join(\", \")}]`;\n if (typeof value === \"object\") {\n const entries = Object.entries(value as Record<string, unknown>).map(\n ([k, v]) => `${objectKey(k)}: ${ts(v)}`,\n );\n return entries.length === 0 ? \"{}\" : `{ ${entries.join(\", \")} }`;\n }\n throw new Error(`value ${String(value)} has no literal`);\n}\n\nfunction str(spec: Record<string, unknown>, key: string): string {\n const v = spec[key];\n if (typeof v !== \"string\") throw new Error(`missing ${key}`);\n return v;\n}\n\nfunction options(entries: Array<[string, unknown]>): string {\n const set = entries.filter(([, v]) => v !== undefined && v !== null && v !== false);\n return set.length === 0 ? \"\" : `{ ${set.map(([k, v]) => `${k}: ${ts(v)}`).join(\", \")} }`;\n}\n\nfunction call(method: string, args: string[], opts: string): string {\n return `.${method}(${[...args, ...(opts ? [opts] : [])].join(\", \")})`;\n}\n\n/** The `ExpectChain` method call that emits `contract`'s spec; throws when there is none. */\nexport function dslCall(contract: Contract): string {\n const s = contract.spec;\n const soft = s[\"soft\"] === true ? true : undefined;\n try {\n if (contract.type === \"trace\") {\n const check = s[\"check\"];\n if (check === \"trajectory\" && s[\"mode\"] !== \"partial_order\") {\n const mode = s[\"mode\"] === \"strict\" || s[\"mode\"] === undefined ? undefined : s[\"mode\"];\n if (!Array.isArray(s[\"tools\"])) throw new Error(\"missing tools\");\n return call(\"trajectory\", [ts(s[\"tools\"])], options([[\"mode\", mode], [\"soft\", soft]]));\n }\n if (check === \"tool_order\") {\n return call(\"toolCalledBefore\", [ts(str(s, \"before\")), ts(str(s, \"after\"))], options([[\"soft\", soft]]));\n }\n if (check === \"tool_cardinality\") {\n return call(\n \"toolCardinality\",\n [ts(str(s, \"tool\"))],\n options([\n [\"per\", s[\"per\"]],\n [\"atLeast\", s[\"min\"]],\n [\"atMost\", s[\"max\"]],\n [\"soft\", soft],\n ]),\n );\n }\n }\n if (contract.type === \"schema\" && s[\"target\"] === \"output.structured\") {\n if (typeof s[\"schema\"] !== \"object\" || s[\"schema\"] === null) throw new Error(\"missing schema\");\n return call(\"outputMatchesSchema\", [ts(s[\"schema\"])], \"\");\n }\n if (contract.type === \"constraint\" && s[\"field\"] === \"metadata.cost_usd\" && s[\"operator\"] === \"lte\") {\n if (typeof s[\"value\"] !== \"number\") throw new Error(\"missing value\");\n return call(\"costUnder\", [ts(s[\"value\"])], options([[\"soft\", soft]]));\n }\n } catch (err) {\n throw new Error(`contract ${contract.id}: malformed spec (${(err as Error).message})`);\n }\n throw new Error(`contract ${contract.id}: no TypeScript DSL call for ${contract.type} spec`);\n}\n\n/**\n * Where the drafted test for a fixture goes: `tests/attest/<name>.test.ts` for\n * `tests/attest/fixtures/<name>.attest.json`.\n */\nexport function testPathFor(fixturePath: string): string {\n const name = path.basename(fixturePath).replace(/\\.attest\\.json$/, \"\");\n return path.join(path.dirname(path.dirname(fixturePath)), `${name}.test.ts`);\n}\n\n/**\n * Render a fixture's drafted contracts as a Vitest module.\n *\n * A verified fixture becomes a test that enforces every contract with `evaluate`. An\n * incident reproduction (`expect_fail`) becomes a test that checks, with `inspect`, that\n * the expected failures still fail and the other contracts still pass; it stays green\n * while it reproduces the incident.\n */\nexport function renderVitest(fixture: Fixture, fixturePath: string, testPath: string): string {\n const calls: Array<[Contract, string]> = [];\n const skipped: string[] = [];\n for (const c of fixture.contracts) {\n try {\n calls.push([c, dslCall(c)]);\n } catch (err) {\n skipped.push((err as Error).message);\n }\n }\n const rel = path.relative(path.dirname(testPath), fixturePath).split(path.sep).join(\"/\");\n const status = new Map(fixture.verification.results.map((r) => [r.contract, r.status]));\n const expectFail = fixture.verification.expect_fail;\n\n const lines = [\n `// Contracts drafted by \\`attest capture\\` from fixture ${comment(ts(fixture.name))}.`,\n \"//\",\n \"// Review and edit before committing: they check the captured trace without running\",\n \"// the agent. Re-capturing does not overwrite this file.\",\n `import { attestExpect, loadFixture, type ExpectChain } from \"@attest-ai/core\";`,\n `import { ${expectFail ? \"inspect\" : \"evaluate\"} } from \"@attest-ai/vitest\";`,\n `import { describe, ${expectFail ? \"expect, \" : \"\"}it } from \"vitest\";`,\n \"\",\n `const FIXTURE = loadFixture(new URL(${ts(rel.startsWith(\".\") ? rel : `./${rel}`)}, import.meta.url));`,\n ];\n if (skipped.length > 0) {\n lines.push(\"\", \"// Drafted contracts without a TypeScript DSL call (left out):\");\n for (const s of skipped) lines.push(`// - ${comment(s)}`);\n }\n lines.push(\"\", \"function contracts(): ExpectChain {\", \" return attestExpect(FIXTURE.trace)\");\n for (const [c, dsl] of calls) {\n lines.push(` // ${comment(`${c.id}: ${c.description}`)}`, ` ${dsl}`);\n }\n lines[lines.length - 1] += \";\";\n lines.push(\"}\");\n if (expectFail) {\n lines.push(\"\", \"// Status of each contract on the captured incident, in contracts() order.\");\n lines.push(\"const EXPECTED: Array<[string, string]> = [\");\n for (const [c] of calls) lines.push(` [${ts(c.id)}, ${ts(status.get(c.id) ?? \"pass\")}],`);\n lines.push(\n \"];\",\n \"\",\n `describe(${ts(fixture.name)}, () => {`,\n ` it(\"reproduces the incident\", async () => {`,\n \" const result = await inspect(contracts());\",\n \"\",\n \" expect(result.assertionResults.map((row) => row.status)).toEqual(EXPECTED.map(([, s]) => s));\",\n \" });\",\n \"});\",\n );\n } else {\n lines.push(\n \"\",\n `describe(${ts(fixture.name)}, () => {`,\n ` it(\"keeps its drafted contracts\", async () => {`,\n \" await evaluate(contracts());\",\n \" });\",\n \"});\",\n );\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\n/**\n * Write the drafted Vitest file for a fixture unless it already exists. Returns the path\n * written, or null when a test file is already there (re-capturing never overwrites an\n * edited test).\n */\nexport function emitVitest(fixturePath: string): string | null {\n const testPath = testPathFor(fixturePath);\n const existing = fs.lstatSync(testPath, { throwIfNoEntry: false });\n if (existing?.isSymbolicLink()) {\n throw new CaptureError(`${testPath} is a symbolic link; refusing to draft a test through it`);\n }\n if (existing !== undefined) return null;\n const source = renderVitest(loadFixture(fixturePath), fixturePath, testPath);\n fs.mkdirSync(path.dirname(testPath), { recursive: true });\n // Create exclusively: \"wx\" fails on any existing path, a link planted after\n // the check included, and never writes through it.\n try {\n fs.writeFileSync(testPath, source, { encoding: \"utf8\", flag: \"wx\" });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"EEXIST\") {\n throw new CaptureError(`${testPath} appeared while drafting; left unchanged`);\n }\n throw err;\n }\n return testPath;\n}\n\n// ---------------------------------------------------------------------------- record()\n\n/** A running in-process capture. */\nexport interface Capture {\n name: string;\n /** The variables `record()` set in `process.env` for the callback. */\n env: Record<string, string>;\n}\n\nexport interface RecordOptions {\n /** Fixture directory (default `tests/attest/fixtures`). */\n outDir?: string;\n /** Save an incident reproduction: verified when drafted contracts fail. */\n expectFail?: boolean;\n /** Trace `agent_id` (default: the first turn's agent name). */\n agentId?: string;\n /** Write the drafted Vitest file (default true). */\n emitTest?: boolean;\n /** Engine binary (default: the SDK's engine discovery). */\n enginePath?: string;\n /**\n * A `world.yaml` to host for the callback (the engine's `--world`): its base URL variable\n * (`PAYMENTS_BASE_URL`) is set for the callback and the world's final state is saved in\n * the fixture's `world` section.\n */\n world?: string;\n /**\n * Called after the callback returns and before the fixture is built; pass the tracer\n * provider's `forceFlush` so batched spans reach the receiver.\n */\n flush?: () => unknown;\n}\n\nexport interface RecordResult<T> {\n value: T;\n fixture: string;\n verified: boolean;\n /**\n * `verified`, `not_verified` or `nothing_to_verify`: a healthy run with no tool call,\n * structured output or cost to draft a contract from. `record` throws for\n * `not_verified`; `nothing_to_verify` returns `verified: false` and no test file.\n */\n outcome: \"verified\" | \"nothing_to_verify\";\n testFile: string | null;\n}\n\ninterface ServeExit {\n code: number | null;\n signal: NodeJS.Signals | null;\n stdout: string;\n stderr: string;\n}\n\ninterface ServeProcess {\n ready: Promise<string | null>;\n finish(finalize: boolean): Promise<ServeExit>;\n}\n\nfunction serve(engine: string, args: string[]): ServeProcess {\n const child = spawn(engine, args, { stdio: [\"pipe\", \"pipe\", \"pipe\"] });\n let stdout = \"\";\n let stderr = \"\";\n let resolveReady: (line: string | null) => void = () => undefined;\n const ready = new Promise<string | null>((resolve) => {\n resolveReady = resolve;\n });\n const exited = new Promise<{ code: number | null; signal: NodeJS.Signals | null }>((resolve) => {\n child.on(\"close\", (code, signal) => {\n resolveReady(null);\n resolve({ code, signal });\n });\n child.on(\"error\", (err) => {\n stderr += err.message;\n resolveReady(null);\n resolve({ code: null, signal: null });\n });\n });\n child.stdout.setEncoding(\"utf8\").on(\"data\", (chunk: string) => {\n stdout += chunk;\n const nl = stdout.indexOf(\"\\n\");\n if (nl >= 0) resolveReady(stdout.slice(0, nl));\n });\n child.stderr.setEncoding(\"utf8\").on(\"data\", (chunk: string) => {\n stderr += chunk;\n });\n // An engine that already exited cannot take \"finalize\"; its exit still says why.\n child.stdin.on(\"error\", () => undefined);\n return {\n ready,\n async finish(finalize) {\n // The environment as it is now: secrets the callback loaded (a dotenv\n // file, for example) are redacted too.\n if (finalize) {\n const environ = Object.entries(process.env).flatMap(([k, v]) => (v === undefined ? [] : [`${k}=${v}`]));\n child.stdin.write(`${JSON.stringify({ finalize: true, environ })}\\n`);\n }\n child.stdin.end();\n const { code, signal } = await exited;\n return { code, signal, stdout, stderr };\n },\n };\n}\n\nfunction readyEnv(line: string | null): Record<string, string> | null {\n if (line === null) return null;\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n return null;\n }\n const env = (parsed as { env?: unknown } | null)?.env;\n if (typeof env !== \"object\" || env === null) return null;\n const entries = Object.entries(env);\n if (!entries.every(([, v]) => typeof v === \"string\")) return null;\n return Object.fromEntries(entries) as Record<string, string>;\n}\n\nfunction exitDetail(exit: ServeExit): string {\n const how = exit.signal !== null ? `killed by ${exit.signal}` : `exit ${String(exit.code)}`;\n const err = exit.stderr.trim();\n return err ? `${how}: ${err}` : how;\n}\n\nfunction restore(saved: Map<string, string | undefined>): void {\n for (const [k, v] of saved) {\n if (v === undefined) delete process.env[k];\n else process.env[k] = v;\n }\n}\n\n// record() sets process-wide environment variables, so a second concurrent capture\n// would save and later restore the first one's values.\nlet recording = false;\n\n/**\n * Capture `fn` as fixture `<outDir>/<name>.attest.json`.\n *\n * Starts `attest-engine capture --serve`, which hosts the recording proxy and the\n * OTLP/HTTP receiver on 127.0.0.1, and sets `OPENAI_BASE_URL`, `ANTHROPIC_BASE_URL` and\n * `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` while `fn` runs. Model clients and the\n * OpenTelemetry exporter read these when they are constructed, so construct them inside\n * `fn`, and pass the tracer provider's `forceFlush` as `flush`. Afterwards the variables\n * are restored and the engine writes the fixture; for a verified fixture with `emitTest`\n * the drafted Vitest file is written unless one exists. If `fn` throws, the capture is\n * abandoned and no fixture is written. Captures cannot overlap.\n *\n * @throws CaptureError when another capture is running, the engine writes no fixture,\n * or the fixture is not verified (a drafted contract did not hold, the trace check\n * failed or no model call was recorded; the fixture is still written and no test is\n * drafted). A healthy run with nothing to draft a contract from does not throw: the\n * result has `outcome: \"nothing_to_verify\"`, `verified: false` and no test file.\n */\nexport async function record<T>(\n name: string,\n fn: (capture: Capture) => T | Promise<T>,\n opts: RecordOptions = {},\n): Promise<RecordResult<T>> {\n if (recording) throw new CaptureError(\"record() is already running; captures cannot overlap\");\n recording = true;\n try {\n return await recordExclusive(name, fn, opts);\n } finally {\n recording = false;\n }\n}\n\nasync function recordExclusive<T>(\n name: string,\n fn: (capture: Capture) => T | Promise<T>,\n opts: RecordOptions,\n): Promise<RecordResult<T>> {\n const engine = await resolveEngine(opts.enginePath);\n const args = [\"capture\", \"--serve\", \"--name\", name, \"--out-dir\", opts.outDir ?? DEFAULT_FIXTURE_DIR];\n if (opts.expectFail) args.push(\"--expect-fail\");\n if (opts.agentId !== undefined) args.push(\"--agent-id\", opts.agentId);\n if (opts.world !== undefined) args.push(\"--world\", path.resolve(opts.world));\n const proc = serve(engine, args);\n const env = readyEnv(await proc.ready);\n if (env === null) {\n const exit = await proc.finish(false);\n throw new CaptureError(`attest-engine capture --serve did not start (${exitDetail(exit)})`);\n }\n const saved = new Map(Object.keys(env).map((k) => [k, process.env[k]]));\n Object.assign(process.env, env);\n let value: T;\n try {\n value = await fn({ name, env });\n if (opts.flush) await opts.flush();\n } catch (err) {\n restore(saved);\n await proc.finish(false);\n throw err;\n }\n restore(saved);\n const exit = await proc.finish(true);\n process.stderr.write(exit.stderr);\n const lines = exit.stdout.trim().split(\"\\n\");\n if (lines.length < 2) {\n throw new CaptureError(`capture ${name} wrote no fixture (${exitDetail(exit)})`);\n }\n const outcome = JSON.parse(lines[lines.length - 1] ?? \"\") as {\n fixture: string;\n verified: boolean;\n outcome: \"verified\" | \"not_verified\" | \"nothing_to_verify\";\n };\n if (exit.code !== 0 || outcome.outcome === \"not_verified\") {\n throw new CaptureError(`capture ${name}: fixture ${outcome.fixture} is not verified; no test drafted`, outcome.fixture);\n }\n if (outcome.outcome === \"nothing_to_verify\") {\n return { value, fixture: outcome.fixture, verified: false, outcome: \"nothing_to_verify\", testFile: null };\n }\n const testFile = opts.emitTest === false ? null : emitVitest(outcome.fixture);\n return { value, fixture: outcome.fixture, verified: true, outcome: \"verified\", testFile };\n}\n"],"mappings":"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","names":["spawnSync","fs","os","path","fileURLToPath","statSync","join","platform","arch","resolve","join","statSync","options","fs","path","options","spawn","fs","path","spawnSync","fileURLToPath"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli.ts","../../src/version.ts","../../src/engine-manager.ts","../../src/engine-downloader.ts","../../src/scaffold.ts","../../src/capture.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * The `attest` command line (`npx attest`).\n *\n * `attest init` runs in the SDK. Every other command (`doctor`, `baseline`, `policy`,\n * `cache`, `calibrate`, `version` and any command a later engine adds) runs in\n * `attest-engine`: the CLI resolves a version-checked engine with `resolveEngine`, checks\n * that the engine's `help` lists the command, and forwards the arguments, stdio and exit\n * code unchanged. A missing, mismatched or too-old engine exits 1 before anything runs, so\n * a gate such as `attest policy evaluate` never exits 0 without evaluating.\n *\n * `attest capture` is forwarded the same way; when the engine writes a fixture, the CLI\n * then drafts its Vitest file (`emitVitest`).\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { ENGINE_VERSION, VERSION } from \"./version.js\";\nimport { resolveEngine } from \"./engine-manager.js\";\nimport { scaffoldProject } from \"./scaffold.js\";\nimport { emitVitest, testPathFor } from \"./capture.js\";\n\nconst HELP_FLAGS = new Set([\"-h\", \"--help\"]);\n\nconst SDK_USAGE =\n \"usage: attest <command> [args]\\n\" +\n \"\\n\" +\n \"SDK commands:\\n\" +\n \" init [--ci github] [--skills] [--mcp] [--json]\\n\" +\n \" scaffold a sample test and merge policy here\\n\" +\n \" (--ci github also writes .github/workflows/attest.yml;\\n\" +\n \" --skills installs the agent skills with attest-engine;\\n\" +\n \" --mcp writes the MCP client configs (.mcp.json, .cursor/mcp.json,\\n\" +\n \" .codex/config.toml) with attest-engine;\\n\" +\n \" --json prints {created, updated, skipped} paths as JSON)\\n\" +\n \"\\n\" +\n \"`attest capture` (engine) also drafts tests/attest/<name>.test.ts from a fixture that\\n\" +\n \"is consistent with the recording, unless that file exists. For a command capture the\\n\" +\n \"test re-runs the command written in it under strict replay (OpenAI- and Anthropic-\\n\" +\n \"compatible calls are served from the recording; other providers are not blocked) and\\n\" +\n \"evaluates the contracts on the new run.\\n\" +\n \"\\n\" +\n \"options:\\n\" +\n \" --version print the SDK version and the engine version it requires\\n\" +\n \" --help print this help\\n\";\n\nconst HELP_PROBE_TIMEOUT_MS = 10_000;\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/**\n * `{command: summary}` from `<engine> help`, or null if it lists none.\n *\n * stdin is closed and the probe times out after 10 s, so an engine that predates the\n * command registry (and starts the JSON-RPC server for `help`) cannot hang the CLI.\n */\nexport function engineCommands(\n engine: string,\n timeoutMs: number = HELP_PROBE_TIMEOUT_MS,\n): Map<string, string> | null {\n const proc = spawnSync(engine, [\"help\"], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n encoding: \"utf-8\",\n timeout: timeoutMs,\n });\n if (proc.error || proc.status !== 0) return null;\n const lines = proc.stdout.split(\"\\n\");\n const start = lines.indexOf(\"commands:\");\n if (start === -1) return null;\n const commands = new Map<string, string>();\n for (const line of lines.slice(start + 1)) {\n const match = /^\\s*(\\S+)\\s*(.*)$/.exec(line);\n if (match?.[1]) commands.set(match[1], (match[2] ?? \"\").trim());\n }\n return commands;\n}\n\n/** Print SDK commands, plus engine commands when an engine is available without download. */\nasync function printHelp(): Promise<number> {\n process.stdout.write(`${SDK_USAGE}\\n`);\n let engine: string;\n try {\n engine = await resolveEngine(undefined, { allowDownload: false });\n } catch (err) {\n const firstLine = (errorMessage(err).split(\"\\n\")[0] ?? \"\").replace(/\\.$/, \"\");\n process.stdout.write(\n `engine commands: not available (${firstLine}). Run \\`attest doctor\\` to download ` +\n `attest-engine ${ENGINE_VERSION}, or set ATTEST_ENGINE_PATH.\\n`,\n );\n return 0;\n }\n const commands = engineCommands(engine);\n if (commands === null) {\n process.stdout.write(\n `engine commands: not available (attest-engine at ${engine} lists no commands; ` +\n \"it predates the command registry).\\n\",\n );\n return 0;\n }\n const width = Math.max(0, ...[...commands.keys()].map((name) => name.length));\n process.stdout.write(`engine commands (attest-engine ${ENGINE_VERSION}, ${engine}):\\n`);\n for (const [name, summary] of commands) {\n process.stdout.write(` ${name.padEnd(width)} ${summary}\\n`);\n }\n return 0;\n}\n\n/** Map a child's exit to a shell exit status (signal N → 128 + N). */\nexport function exitStatus(status: number | null, signal: NodeJS.Signals | null): number {\n if (status !== null) return status;\n if (signal !== null) return 128 + (os.constants.signals[signal] ?? 0);\n return 1;\n}\n\n/**\n * Resolve a version-checked engine whose `help` lists `command`; print the reason to\n * stderr and resolve to null when there is none.\n */\nasync function engineProviding(command: string): Promise<string | null> {\n let engine: string;\n try {\n engine = await resolveEngine();\n } catch (err) {\n process.stderr.write(`attest: ${errorMessage(err)}\\n`);\n return null;\n }\n const commands = engineCommands(engine);\n if (commands === null || (command !== \"help\" && !commands.has(command))) {\n process.stderr.write(\n `attest: attest-engine at ${engine} (version ${ENGINE_VERSION}) predates ` +\n `\\`attest ${command}\\`: its help does not list that command. Set ATTEST_ENGINE_PATH ` +\n \"to an engine built from this release (make engine), or install a release whose \" +\n \"engine provides it.\\n\",\n );\n return null;\n }\n return engine;\n}\n\nconst INIT_HELP_ENTRY = {\n name: \"init\",\n summary: \"scaffold a sample test and policy; --ci github, --skills, --mcp, --json\",\n schema: \"cli/init.schema.json\",\n exit_codes: [\n { code: 0, meaning: \"success\" },\n {\n code: 1,\n meaning: \"--skills or --mcp could not install: the engine is missing, too old or failed\",\n },\n { code: 2, meaning: \"usage error\" },\n ],\n};\n\n/** Print the engine's `help --json` document with the SDK's `init` command added. */\nexport function helpJson(engine: string): number {\n const proc = spawnSync(engine, [\"help\", \"--json\"], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n encoding: \"utf-8\",\n });\n if (proc.error) throw proc.error;\n if (proc.status !== 0) {\n process.stderr.write(proc.stderr);\n return exitStatus(proc.status, proc.signal);\n }\n let doc: { commands: { name: string }[] };\n try {\n doc = JSON.parse(proc.stdout) as { commands: { name: string }[] };\n if (!Array.isArray(doc.commands)) throw new Error(\"no commands array\");\n } catch (err) {\n process.stderr.write(`attest: \\`${engine} help --json\\` printed an unexpected document: ${errorMessage(err)}\\n`);\n return 1;\n }\n doc.commands = [...doc.commands, INIT_HELP_ENTRY].sort((a, b) =>\n a.name < b.name ? -1 : a.name > b.name ? 1 : 0,\n );\n process.stdout.write(`${JSON.stringify(doc, null, 2)}\\n`);\n return 0;\n}\n\nasync function forward(args: string[]): Promise<number> {\n const command = args[0] ?? \"\";\n const engine = await engineProviding(command);\n if (engine === null) return 1;\n if (args.length === 2 && command === \"help\" && args[1] === \"--json\") return helpJson(engine);\n if (command === \"capture\" && captureWritesFixture(args.slice(1))) {\n return captureAndEmit(engine, args.slice(1));\n }\n const proc = spawnSync(engine, args, { stdio: \"inherit\" });\n if (proc.error) throw proc.error;\n return exitStatus(proc.status, proc.signal);\n}\n\n// Engine capture modes the CLI drafts no test for: help, --check-redaction (writes no\n// fixture) and --serve (used by record(), which drafts its own). Go flags accept one or\n// two dashes.\nconst CAPTURE_NO_TEST = new Set([\"check-redaction\", \"serve\", \"h\", \"help\"]);\n\nfunction flagName(arg: string): string | null {\n if (!arg.startsWith(\"-\") || arg === \"-\" || arg === \"--\") return null;\n return arg.replace(/^-+/, \"\").split(\"=\", 1)[0] ?? null;\n}\n\n/** True when `attest capture` args select a mode whose fixture the CLI drafts a test for. */\nexport function captureWritesFixture(args: string[]): boolean {\n for (const a of args) {\n if (a === \"--\") break;\n const name = flagName(a);\n if (name !== null && CAPTURE_NO_TEST.has(name)) return false;\n }\n return true;\n}\n\n/** The `--world` file of `attest capture` args (before the `--` command), resolved against cwd. */\nexport function captureWorldPath(args: string[]): string | undefined {\n for (let i = 0; i < args.length; i++) {\n const a = args[i] as string;\n if (a === \"--\") return undefined;\n const [name, ...rest] = a.split(\"=\");\n if (name === \"--world\" || name === \"-world\") {\n const value = rest.length > 0 ? rest.join(\"=\") : args[i + 1];\n return value === undefined ? undefined : path.resolve(value);\n }\n }\n return undefined;\n}\n\nfunction userResultFile(args: string[]): boolean {\n for (const a of args) {\n if (a === \"--\") break;\n if (flagName(a) === \"result-file\") return true;\n }\n return false;\n}\n\n/** Run `attest-engine capture` and draft the Vitest file for the fixture it wrote. */\nfunction captureAndEmit(engine: string, args: string[]): number {\n if (userResultFile(args)) {\n process.stderr.write(\n \"attest: capture --result-file is set by the attest CLI; run attest-engine capture directly to choose it\\n\",\n );\n return 2;\n }\n const tmp = fs.mkdtempSync(path.join(os.tmpdir(), \"attest-capture-\"));\n const resultFile = path.join(tmp, \"result.json\");\n let result: { fixture: string; verified: boolean; outcome: string };\n let code: number;\n try {\n const proc = spawnSync(engine, [\"capture\", \"--result-file\", resultFile, ...args], { stdio: \"inherit\" });\n if (proc.error) throw proc.error;\n code = exitStatus(proc.status, proc.signal);\n if (!fs.existsSync(resultFile)) return code;\n result = JSON.parse(fs.readFileSync(resultFile, \"utf8\")) as { fixture: string; verified: boolean; outcome: string };\n } finally {\n fs.rmSync(tmp, { recursive: true, force: true });\n }\n const fixture = result.fixture;\n if (!result.verified) {\n const reason = result.outcome === \"nothing_to_verify\" ? \"with nothing to verify\" : \"for unverified\";\n process.stderr.write(` test: none drafted ${reason} ${fixture}\\n`);\n return code;\n }\n const written = emitVitest(fixture, { cwd: process.cwd(), world: captureWorldPath(args) });\n process.stderr.write(\n written === null\n ? ` test: ${testPathFor(fixture)} exists; left unchanged\\n`\n : ` test: drafted ${written}; for a command capture it re-runs the command under strict replay (other providers are not blocked: run it without their credentials) and evaluates the contracts on the new run\\n`,\n );\n return code;\n}\n\nconst INIT_USAGE =\n \"usage: attest init [--ci github] [--skills] [--mcp] [--json] (scaffolds into the current directory)\";\n\nconst INIT_KINDS = [\"created\", \"updated\", \"skipped\"] as const;\n// `--mcp` adds a fourth kind: configs that already hold a different `attest` entry.\nconst INIT_KINDS_WITH_CONFLICT = [...INIT_KINDS, \"conflict\"] as const;\ntype InitKind = (typeof INIT_KINDS_WITH_CONFLICT)[number];\ntype InitResult = Record<InitKind, string[]>;\n\n// `attest-engine skills install --json` key -> `attest init --json` key.\nconst SKILLS_KINDS = [\n [\"created\", \"created\"],\n [\"updated\", \"updated\"],\n [\"unchanged\", \"skipped\"],\n] as const;\n\n// `attest-engine mcp install --json` key -> `attest init --json` key.\nconst MCP_KINDS = [\n [\"created\", \"created\"],\n [\"updated\", \"updated\"],\n [\"unchanged\", \"skipped\"],\n [\"conflict\", \"conflict\"],\n] as const;\n\ninterface InitArgs {\n ci: boolean;\n skills: boolean;\n mcp: boolean;\n json: boolean;\n}\n\n/** Parse `attest init` args; null on a usage error. */\nfunction parseInitArgs(args: string[]): InitArgs | null {\n const parsed: InitArgs = { ci: false, skills: false, mcp: false, json: false };\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === \"--ci\" && args[i + 1] === \"github\" && !parsed.ci) {\n parsed.ci = true;\n i++;\n } else if (arg === \"--ci=github\" && !parsed.ci) {\n parsed.ci = true;\n } else if (arg === \"--skills\" && !parsed.skills) {\n parsed.skills = true;\n } else if (arg === \"--mcp\" && !parsed.mcp) {\n parsed.mcp = true;\n } else if (arg === \"--json\" && !parsed.json) {\n parsed.json = true;\n } else {\n return null;\n }\n }\n return parsed;\n}\n\nfunction emptyInitResult(): InitResult {\n return { created: [], updated: [], skipped: [], conflict: [] };\n}\n\n/**\n * Run `<engine> <subcommand> --json` and map its path lists to init kinds.\n * Throws when the engine fails or prints an unexpected document.\n */\nfunction runEngineInstall(\n engine: string,\n subcommand: string[],\n kinds: readonly (readonly [string, InitKind])[],\n what: string,\n): InitResult {\n const argv = [...subcommand, \"--json\"];\n const shown = [engine, ...argv].join(\" \");\n const proc = spawnSync(engine, argv, {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n encoding: \"utf-8\",\n });\n if (proc.error) throw proc.error;\n if (proc.status !== 0) {\n const detail = proc.stderr.trim();\n throw new Error(\n `${what} failed (\\`${shown}\\` exited ${String(exitStatus(proc.status, proc.signal))})` +\n (detail === \"\" ? \"\" : `: ${detail}`),\n );\n }\n process.stderr.write(proc.stderr);\n let doc: unknown;\n try {\n doc = JSON.parse(proc.stdout);\n } catch (err) {\n throw new Error(`\\`${shown}\\` printed invalid JSON: ${errorMessage(err)}`);\n }\n if (typeof doc !== \"object\" || doc === null || Array.isArray(doc)) {\n throw new Error(`\\`${shown}\\` printed ${JSON.stringify(doc)}, not an object`);\n }\n const record = doc as Record<string, unknown>;\n const result = emptyInitResult();\n for (const [engineKind, initKind] of kinds) {\n const paths = record[engineKind];\n if (!Array.isArray(paths) || !paths.every((p): p is string => typeof p === \"string\")) {\n throw new Error(`\\`${shown}\\` printed no \\`${engineKind}\\` list of paths: ${proc.stdout}`);\n }\n result[initKind].push(...paths);\n }\n return result;\n}\n\n/** Run `<engine> skills install --dir <root> --json` and map its paths to init kinds. */\nfunction installSkills(engine: string, root: string): InitResult {\n return runEngineInstall(engine, [\"skills\", \"install\", \"--dir\", root], SKILLS_KINDS, \"skills install\");\n}\n\n/**\n * The command an MCP client runs to start the server: `pnpm exec attest mcp` in a pnpm\n * project (`pnpm-lock.yaml` in `root`), else `npx --no attest mcp`. `--no` makes a missing\n * local install fail instead of letting npx fetch the unscoped `attest` package.\n */\nfunction mcpLaunchCommand(root: string): string[] {\n return fs.existsSync(path.join(root, \"pnpm-lock.yaml\"))\n ? [\"pnpm\", \"exec\", \"attest\", \"mcp\"]\n : [\"npx\", \"--no\", \"attest\", \"mcp\"];\n}\n\n/** Run `<engine> mcp install --dir <root> --command <launch> --json`. */\nfunction installMcp(engine: string, root: string): InitResult {\n return runEngineInstall(\n engine,\n [\"mcp\", \"install\", \"--dir\", root, \"--command\", JSON.stringify(mcpLaunchCommand(root))],\n MCP_KINDS,\n \"mcp install\",\n );\n}\n\nfunction printSkills(root: string, skills: InitResult): void {\n const abs = (rel: string) => path.join(root, ...rel.split(\"/\"));\n for (const rel of skills.created) process.stdout.write(`Created: ${abs(rel)}\\n`);\n for (const rel of skills.updated) process.stdout.write(`Updated: ${abs(rel)}\\n`);\n for (const rel of skills.skipped) process.stderr.write(`Skipped (unchanged): ${abs(rel)}\\n`);\n for (const rel of skills.conflict) {\n process.stderr.write(\n `Conflict (a different attest entry, left as it is; ` +\n `\\`attest-engine mcp install --force\\` replaces it): ${abs(rel)}\\n`,\n );\n }\n}\n\nasync function runInit(parsed: InitArgs, root: string): Promise<InitResult | null> {\n const result = emptyInitResult();\n const installs: [boolean, string, (engine: string, root: string) => InitResult][] = [\n [parsed.skills, \"skills\", installSkills],\n [parsed.mcp, \"mcp\", installMcp],\n ];\n for (const [wanted, command, install] of installs) {\n if (!wanted) continue;\n const engine = await engineProviding(command);\n if (engine === null) return null;\n let installed: InitResult;\n try {\n installed = install(engine, root);\n } catch (err) {\n process.stderr.write(`attest: ${errorMessage(err)}\\n`);\n return null;\n }\n if (!parsed.json) printSkills(root, installed);\n for (const kind of INIT_KINDS_WITH_CONFLICT) result[kind].push(...installed[kind]);\n }\n const scaffolded = scaffoldProject(root, {\n ...(parsed.ci ? { ci: \"github\" as const } : {}),\n quiet: parsed.json,\n });\n result.created.push(...scaffolded.created);\n result.skipped.push(...scaffolded.skipped);\n return result;\n}\n\n/**\n * Run `attest init [--ci github] [--skills] [--mcp] [--json]` in the current directory.\n *\n * `--skills` installs the agent skills with `attest-engine skills install` before\n * scaffolding; a missing or failing engine exits 1 with nothing scaffolded. `--json`\n * prints one `{created, updated, skipped}` document (plus `conflict` with `--mcp`) (paths relative to the current\n * directory, sorted) as the only stdout; everything else goes to stderr.\n */\nasync function cmdInit(args: string[]): Promise<number> {\n if (args.some((a) => HELP_FLAGS.has(a))) {\n process.stdout.write(`${INIT_USAGE}\\n`);\n return 0;\n }\n const parsed = parseInitArgs(args);\n if (parsed === null) {\n process.stderr.write(`${INIT_USAGE}\\n`);\n return 2;\n }\n const root = process.cwd();\n if (!parsed.json) return (await runInit(parsed, root)) === null ? 1 : 0;\n // Under --json, stdout carries the document only: anything else written goes to stderr.\n const stdoutWrite = process.stdout.write;\n process.stdout.write = process.stderr.write.bind(process.stderr) as typeof process.stdout.write;\n let result: InitResult | null;\n try {\n result = await runInit(parsed, root);\n } finally {\n process.stdout.write = stdoutWrite;\n }\n if (result === null) return 1;\n const done = result;\n const kinds = parsed.mcp ? INIT_KINDS_WITH_CONFLICT : INIT_KINDS;\n const sorted = Object.fromEntries(kinds.map((k) => [k, [...done[k]].sort()]));\n process.stdout.write(`${JSON.stringify(sorted)}\\n`);\n return 0;\n}\n\n/** Dispatch `attest` arguments and resolve to the process exit code. */\nexport async function main(argv: string[] = process.argv.slice(2)): Promise<number> {\n const [command] = argv;\n if (command === undefined || HELP_FLAGS.has(command) || (command === \"help\" && argv.length === 1)) {\n return printHelp();\n }\n if (command === \"--version\") {\n process.stdout.write(`attest ${VERSION} (requires attest-engine ${ENGINE_VERSION})\\n`);\n return 0;\n }\n if (command === \"init\") {\n return cmdInit(argv.slice(1));\n }\n if (command.startsWith(\"-\")) {\n process.stderr.write(`attest: unknown option ${command}\\n\\n${SDK_USAGE}`);\n return 2;\n }\n return forward(argv);\n}\n\n// Run when executed directly, including through the node_modules/.bin/attest symlink.\nfunction isDirectExecution(): boolean {\n const script = process.argv[1];\n if (script === undefined || !fs.existsSync(script)) return false;\n return fs.realpathSync(script) === fs.realpathSync(fileURLToPath(import.meta.url));\n}\n\nif (isDirectExecution()) {\n main().then(\n (code) => process.exit(code),\n (err: unknown) => {\n process.stderr.write(`attest: ${errorMessage(err)}\\n`);\n process.exit(1);\n },\n );\n}\n","export const VERSION = \"1.1.0-rc.1\";\nexport const ENGINE_VERSION = \"1.1.0-rc.1\";\n","import { spawn, spawnSync, type ChildProcess } from \"node:child_process\";\nimport { createInterface, type Interface as ReadlineInterface } from \"node:readline\";\nimport { existsSync, accessSync, statSync, constants as fsConstants } from \"node:fs\";\nimport { delimiter, join } from \"node:path\";\nimport { AttestClient, type BudgetReservation } from \"./client.js\";\nimport type { InitializeResult, Usage } from \"./proto/types.js\";\nimport { ENGINE_VERSION, VERSION } from \"./version.js\";\nimport { binaryFilename, cachedEnginePath, downloadEngine } from \"./engine-downloader.js\";\n\nconst ENGINE_BINARY_NAME = \"attest-engine\";\nconst VERSION_PROBE_TIMEOUT_MS = 10_000;\nconst DEFAULT_INITIALIZE_TIMEOUT_MS = 30_000;\nconst SHUTDOWN_TIMEOUT_MS = 5_000;\nconst STDERR_TAIL_BYTES = 4_096;\n/** How long a failed pipe write waits for the exiting engine's own report (exit status and stderr). */\nconst EXIT_REPORT_GRACE_MS = 1_000;\nconst PIPE_WRITE_ERROR_CODES = new Set([\"EPIPE\", \"ECONNRESET\", \"ERR_STREAM_DESTROYED\"]);\n\nfunction isPipeWriteError(err: unknown): boolean {\n for (let e: unknown = err; e instanceof Error; e = e.cause) {\n const code = (e as NodeJS.ErrnoException).code;\n if (code !== undefined && PIPE_WRITE_ERROR_CODES.has(code)) return true;\n }\n return false;\n}\n\n/** A discovered engine does not report the version this SDK requires. */\nexport class EngineVersionMismatchError extends Error {\n readonly enginePath: string;\n readonly source: string;\n readonly found: string | null;\n readonly required: string;\n\n constructor(enginePath: string, source: string, found: string | null, required: string) {\n const reported = found === null ? \"reports no version\" : `reports version ${found}`;\n super(\n `attest-engine at ${enginePath} (from ${source}) ${reported}; ` +\n `this SDK requires attest-engine ${required}. ` +\n \"Point ATTEST_ENGINE_PATH at a matching engine, or remove the mismatched one \" +\n `from PATH so the SDK can download ${required} into ~/.attest/bin/${required}/.`,\n );\n this.name = \"EngineVersionMismatchError\";\n this.enginePath = enginePath;\n this.source = source;\n this.found = found;\n this.required = required;\n }\n}\n\n/**\n * The version `<path> version` reports, or null if it reports none.\n *\n * Every engine since 0.4 answers `version` with `attest-engine <version>`. stdin is\n * closed so a binary that starts the JSON-RPC server instead reads EOF and exits.\n */\nexport function engineVersion(enginePath: string): string | null {\n const proc = spawnSync(enginePath, [\"version\"], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n encoding: \"utf-8\",\n timeout: VERSION_PROBE_TIMEOUT_MS,\n });\n if (proc.error) throw proc.error;\n const out = proc.stdout.trim();\n const prefix = `${ENGINE_BINARY_NAME} `;\n if (proc.status !== 0 || !out.startsWith(prefix)) return null;\n return out.slice(prefix.length).trim();\n}\n\nfunction onPath(): string | null {\n for (const dir of (process.env[\"PATH\"] ?? \"\").split(delimiter)) {\n if (!dir) continue;\n const candidate = join(dir, binaryFilename());\n try {\n accessSync(candidate, fsConstants.X_OK);\n } catch {\n continue;\n }\n if (statSync(candidate).isFile()) return candidate;\n }\n return null;\n}\n\nfunction requireFile(enginePath: string, label: string): void {\n if (!existsSync(enginePath) || !statSync(enginePath).isFile()) {\n throw new Error(`${label}=${enginePath} does not exist or is not a file.`);\n }\n}\n\nasync function locateEngine(\n explicitPath: string | undefined,\n allowDownload: boolean,\n): Promise<[string, string]> {\n if (explicitPath) {\n requireFile(explicitPath, \"Engine path\");\n return [explicitPath, \"explicit engine path\"];\n }\n const envPath = process.env[\"ATTEST_ENGINE_PATH\"];\n if (envPath) {\n requireFile(envPath, \"ATTEST_ENGINE_PATH\");\n return [envPath, \"ATTEST_ENGINE_PATH\"];\n }\n const found = onPath();\n if (found) return [found, \"PATH\"];\n const cached = cachedEnginePath();\n if (cached) return [cached, \"engine cache\"];\n\n if (!allowDownload) {\n throw new Error(\n `No '${ENGINE_BINARY_NAME}' ${ENGINE_VERSION} in ATTEST_ENGINE_PATH, PATH or ` +\n `~/.attest/bin/${ENGINE_VERSION}/.`,\n );\n }\n\n const noDownload = process.env[\"ATTEST_ENGINE_NO_DOWNLOAD\"]?.toLowerCase();\n if (noDownload === \"1\" || noDownload === \"true\" || noDownload === \"yes\") {\n throw new Error(\n `Cannot find '${ENGINE_BINARY_NAME}' ${ENGINE_VERSION} and ATTEST_ENGINE_NO_DOWNLOAD is set.\\n` +\n \"Install options:\\n\" +\n \" 1. Build from source: make engine, then set ATTEST_ENGINE_PATH\\n\" +\n ` 2. Download release v${ENGINE_VERSION}: https://github.com/attest-framework/attest/releases\\n` +\n \" 3. Allow auto-download by unsetting ATTEST_ENGINE_NO_DOWNLOAD\",\n );\n }\n return [await downloadEngine(), \"download\"];\n}\n\n/**\n * Find an engine whose version matches this SDK and return its path.\n *\n * The single discovery function behind `EngineManager` and the `attest` CLI. Order:\n * explicit path → `ATTEST_ENGINE_PATH` → `attest-engine` on `PATH` →\n * `~/.attest/bin/<ENGINE_VERSION>/` → download (unless `ATTEST_ENGINE_NO_DOWNLOAD` is set or\n * `allowDownload` is false).\n * The first engine found must report exactly `ENGINE_VERSION`; a mismatched engine is\n * never skipped in favor of the next location.\n */\nexport async function resolveEngine(\n explicitPath?: string,\n options: { allowDownload?: boolean } = {},\n): Promise<string> {\n const [enginePath, source] = await locateEngine(explicitPath, options.allowDownload ?? true);\n const found = engineVersion(enginePath);\n if (found !== ENGINE_VERSION) {\n throw new EngineVersionMismatchError(enginePath, source, found, ENGINE_VERSION);\n }\n return enginePath;\n}\n\n/** Session budget limits read from the environment; null means unlimited. */\ninterface SessionBudget {\n readonly judgeCalls: number | null;\n readonly usd: number | null;\n}\n\nfunction envNumber(name: string): number | null {\n const raw = process.env[name];\n if (raw === undefined || raw === \"\") return null;\n const parsed = Number(raw);\n // A malformed value is the engine's startup error to report, not ours.\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : null;\n}\n\n/**\n * Rethrow the engine's exit report (status and stderr tail) when it arrives within `graceMs`.\n * A pipe write fails before the child's 'close' fires; a grandchild holding stderr open can\n * delay 'close' indefinitely, hence the bound.\n */\nasync function reportExit(exited: Promise<never>, graceMs: number): Promise<void> {\n let timer: NodeJS.Timeout | undefined;\n const grace = new Promise<void>((done) => {\n timer = setTimeout(done, graceMs);\n });\n try {\n await Promise.race([exited, grace]);\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport class EngineManager {\n private enginePath: string;\n private readonly logLevel: string;\n private readonly initializeTimeoutMs: number;\n private process: ChildProcess | null = null;\n private reader: ReadlineInterface | null = null;\n private initialized = false;\n private initResult: InitializeResult | null = null;\n private routedClient: AttestClient | undefined;\n /** The running engine's stderr tail; each launch owns a fresh one so a killed engine cannot write into it. */\n private stderr: { text: string } = { text: \"\" };\n private restarting: Promise<void> | null = null;\n\n private configuredBudget: SessionBudget = { judgeCalls: null, usd: null };\n private usedJudgeCalls = 0;\n private usedUsd = 0;\n private heldJudgeCalls = 0;\n private heldUsd = 0;\n /** Spend the SDK cannot observe may have happened; a restart then leaves no budget. */\n private unknownSpend = false;\n\n constructor(options?: { enginePath?: string; logLevel?: string; initializeTimeoutMs?: number }) {\n this.enginePath = options?.enginePath ?? \"\";\n this.logLevel = options?.logLevel ?? \"warn\";\n this.initializeTimeoutMs = options?.initializeTimeoutMs ?? DEFAULT_INITIALIZE_TIMEOUT_MS;\n }\n\n /**\n * Start the engine and complete the `initialize` handshake. Rejects when the engine exits,\n * closes its pipes or fails to answer within the initialize timeout; the error carries the\n * tail of the engine's stderr.\n */\n async start(): Promise<InitializeResult> {\n this.enginePath = await resolveEngine(this.enginePath || undefined);\n this.configuredBudget = {\n judgeCalls: envNumber(\"ATTEST_MAX_JUDGE_CALLS\"),\n usd: envNumber(\"ATTEST_BUDGET_USD\"),\n };\n this.usedJudgeCalls = this.usedUsd = this.heldJudgeCalls = this.heldUsd = 0;\n this.unknownSpend = false;\n\n this.initResult = await this.launch(undefined);\n this.initialized = true;\n return this.initResult;\n }\n\n /** Spawn the engine and run `initialize` on it; the engine is stopped when that fails. */\n private async launch(envOverrides: Record<string, string> | undefined): Promise<InitializeResult> {\n const stderr = { text: \"\" };\n this.stderr = stderr;\n const child = spawn(this.enginePath, [`--log-level=${this.logLevel}`], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env: { ...process.env, ...envOverrides },\n });\n this.process = child;\n child.stderr.setEncoding(\"utf8\");\n child.stderr.on(\"data\", (chunk: string) => {\n stderr.text = (stderr.text + chunk).slice(-STDERR_TAIL_BYTES);\n });\n // A write to a dead engine fails through the write callback (launch() then waits for the\n // exit report below); the stream's own 'error' event would only duplicate that as an\n // uncaught exception.\n child.stdin.on(\"error\", () => undefined);\n\n this.reader = createInterface({ input: child.stdout });\n const client = new AttestClient(this);\n this.routedClient = client;\n client.startReader();\n\n const exited = new Promise<never>((_, reject) => {\n child.once(\"error\", (err) => reject(new Error(`attest-engine failed to start: ${err.message}`)));\n child.once(\"close\", (code, signal) => {\n const how = signal !== null ? `signal ${signal}` : `exit code ${String(code)}`;\n reject(\n new Error(\n `attest-engine exited before it was ready (${how}).` +\n (stderr.text === \"\" ? \"\" : ` stderr:\\n${stderr.text.trimEnd()}`),\n ),\n );\n });\n });\n // After a successful start this rejection is just the engine stopping.\n exited.catch(() => undefined);\n\n try {\n return await Promise.race([this.initialize(client), exited]);\n } catch (err) {\n await this.terminate();\n if (isPipeWriteError(err)) await reportExit(exited, EXIT_REPORT_GRACE_MS);\n throw err;\n }\n }\n\n /** Send initialize and check the engine's version and capabilities. */\n private async initialize(client: AttestClient): Promise<InitializeResult> {\n const init = (await client.sendWithoutRestart(\n \"initialize\",\n {\n sdk_name: \"attest-typescript\",\n sdk_version: VERSION,\n protocol_version: 1,\n required_capabilities: [\"layers_1_4\"],\n preferred_encoding: \"json\",\n },\n this.initializeTimeoutMs,\n )) as InitializeResult;\n if (init.engine_version !== ENGINE_VERSION) {\n throw new EngineVersionMismatchError(\n this.enginePath,\n \"initialize\",\n init.engine_version,\n ENGINE_VERSION,\n );\n }\n if (!init.compatible) {\n throw new Error(`Engine incompatible. Missing capabilities: ${JSON.stringify(init.missing)}`);\n }\n return init;\n }\n\n async stop(): Promise<void> {\n if (this.restarting !== null) await this.restarting.catch(() => undefined);\n if (this.process === null) return;\n\n if (this.initialized && this.routedClient !== undefined && this.isRunning) {\n try {\n await this.routedClient.sendWithoutRestart(\"shutdown\", {}, SHUTDOWN_TIMEOUT_MS);\n } catch {\n // shutdown failed, will kill\n }\n }\n await this.terminate();\n this.initialized = false;\n }\n\n /** Close the pipes, reject pending requests and stop the engine process (SIGKILL when `force`). */\n private async terminate(force = false): Promise<void> {\n const child = this.process;\n this.routedClient?.stopReader();\n this.routedClient?.rejectPending(new Error(\"Engine stopped.\"));\n this.reader?.close();\n this.reader = null;\n this.process = null;\n if (child === null) return;\n\n if (child.exitCode === null && child.signalCode === null) {\n await new Promise<void>((res) => {\n const timer = force ? undefined : setTimeout(() => child.kill(\"SIGKILL\"), 5000);\n child.once(\"exit\", () => {\n clearTimeout(timer);\n res();\n });\n child.kill(force ? \"SIGKILL\" : \"SIGTERM\");\n });\n }\n }\n\n /**\n * Replace the engine after a request timed out: its late response can no longer be told\n * apart from a new one. The new engine gets the remaining session budget: the configured\n * limit minus the usage already returned, minus what the abandoned requests may still have\n * reserved. A restart that leaves no budget makes later model calls\n * `not_evaluated(budget_exhausted)`.\n */\n restartAfterTimeout(abandoned: readonly BudgetReservation[]): Promise<void> {\n for (const r of abandoned) {\n this.heldJudgeCalls += r.judgeCalls ?? Number.POSITIVE_INFINITY;\n this.heldUsd += r.usd ?? Number.POSITIVE_INFINITY;\n }\n this.restarting ??= this.restart().finally(() => {\n this.restarting = null;\n });\n return this.restarting;\n }\n\n /** An engine reply the SDK cannot account for (no usage, an RPC error, a dropped reply) may have spent budget. */\n markUnknownSpend(): void {\n this.unknownSpend = true;\n }\n\n private async restart(): Promise<void> {\n // The abandoned engine may sit in a slow model call; nothing it says is wanted any more.\n await this.terminate(true);\n const overrides: Record<string, string> = {};\n const { judgeCalls, usd } = this.configuredBudget;\n const unknown = this.unknownSpend ? Number.POSITIVE_INFINITY : 0;\n if (judgeCalls !== null) {\n overrides[\"ATTEST_MAX_JUDGE_CALLS\"] = String(\n Math.max(0, Math.floor(judgeCalls - this.usedJudgeCalls - this.heldJudgeCalls - unknown)),\n );\n }\n if (usd !== null) {\n overrides[\"ATTEST_BUDGET_USD\"] = String(Math.max(0, usd - this.usedUsd - this.heldUsd - unknown));\n }\n this.initResult = await this.launch(overrides);\n }\n\n /** Count the usage an evaluate_batch result reported against the session budget. */\n recordUsage(usage: Usage): void {\n this.usedJudgeCalls += usage.judge_calls;\n this.usedUsd += usage.cost_usd;\n }\n\n /** Resolves once an engine restart in progress has finished. */\n async whenReady(): Promise<void> {\n if (this.restarting !== null) await this.restarting;\n }\n\n /** Tail of the engine's stderr: the reason an engine died. */\n get stderrTail(): string {\n return this.stderr.text.trimEnd();\n }\n\n /** The client that routes this engine's responses by id; replaced when the engine restarts. */\n get client(): AttestClient | undefined {\n return this.routedClient;\n }\n\n async sendRequest(method: string, params: Record<string, unknown>): Promise<unknown> {\n if (!this.initialized && method !== \"initialize\") {\n throw new Error(\"Engine not initialized. Call start() first.\");\n }\n if (this.routedClient === undefined) throw new Error(\"Engine process not started.\");\n return this.routedClient.sendRequest(method, params);\n }\n\n get isRunning(): boolean {\n return this.process !== null && this.process.exitCode === null && this.process.signalCode === null;\n }\n\n /** Expose process for AttestClient reader loop access */\n get childProcess(): ChildProcess | null {\n return this.process;\n }\n\n /** Expose readline interface for AttestClient reader loop */\n get readlineInterface(): ReadlineInterface | null {\n return this.reader;\n }\n}\n","import * as https from \"node:https\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport * as crypto from \"node:crypto\";\nimport { fileURLToPath } from \"node:url\";\nimport { ENGINE_VERSION, VERSION } from \"./version.js\";\n\nconst RELEASE_BASE = `https://github.com/attest-framework/attest/releases/download/v${ENGINE_VERSION}`;\nconst TABLE_NAME = \"engine-checksums.json\";\nconst MAX_REDIRECTS = 5;\nconst REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);\nconst DEFAULT_CONNECT_TIMEOUT_MS = 10_000;\nconst DEFAULT_TOTAL_TIMEOUT_MS = 120_000;\nconst SHA256_HEX = /^[0-9a-f]{64}$/;\n\n/**\n * Seams for tests. Production calls `downloadEngine()` with none of them. Every option keeps\n * https-only and certificate verification on; `ca` swaps the trusted roots, it never disables checks.\n */\nexport interface DownloadOptions {\n /** Release asset base URL (default: GitHub Releases for `ENGINE_VERSION`). */\n releaseBase?: string;\n /** Path of the embedded hash table (default: the one shipped in this package). */\n tablePath?: string;\n /** Trusted root certificates (PEM). Node's `ca` replaces the default CA list rather than extending it. */\n ca?: string | Buffer;\n /** Connect timeout, and the longest silence tolerated mid-transfer. */\n connectTimeoutMs?: number;\n /** Deadline for one whole fetch including redirects and body. */\n totalTimeoutMs?: number;\n}\n\n/**\n * Cache directory for this SDK's engine: `~/.attest/bin/<ENGINE_VERSION>/`.\n *\n * The directory name is the canonical engine version (for example `1.0.0`). The legacy\n * unversioned `~/.attest/bin/attest-engine` is neither read nor modified.\n */\nexport function versionedBinDir(): string {\n return path.join(os.homedir(), \".attest\", \"bin\", ENGINE_VERSION);\n}\n\nexport function platformKey(): string {\n const platform = os.platform();\n const arch = os.arch();\n\n const mapping: Record<string, Record<string, string>> = {\n darwin: { arm64: \"darwin-arm64\", x64: \"darwin-amd64\" },\n linux: { arm64: \"linux-arm64\", x64: \"linux-amd64\" },\n win32: { x64: \"windows-amd64\", arm64: \"windows-arm64\" }\n };\n\n const osMap = mapping[platform];\n if (!osMap) {\n throw new Error(\n `Unsupported platform: ${platform}. Supported: darwin, linux, win32.`\n );\n }\n\n const key = osMap[arch];\n if (!key) {\n throw new Error(\n `Unsupported architecture '${arch}' on platform '${platform}'. ` +\n `Supported architectures: ${Object.keys(osMap).join(\", \")}.`\n );\n }\n\n return key;\n}\n\nexport function binaryFilename(): string {\n return os.platform() === \"win32\" ? \"attest-engine.exe\" : \"attest-engine\";\n}\n\n/** The engine binary in the versioned cache, or null if it is absent. */\nexport function cachedEnginePath(): string | null {\n const binPath = path.join(versionedBinDir(), binaryFilename());\n return fs.statSync(binPath, { throwIfNoEntry: false })?.isFile() ? binPath : null;\n}\n\nfunction packageRoot(): string {\n // __dirname exists in the CJS build; deriving it from a file: URL there would cut the path at\n // a '#' or '?' in the install directory.\n let dir = typeof __dirname === \"string\" ? __dirname : path.dirname(fileURLToPath(import.meta.url));\n while (!fs.existsSync(path.join(dir, \"package.json\"))) {\n const parent = path.dirname(dir);\n if (parent === dir) return dir;\n dir = parent;\n }\n return dir;\n}\n\nfunction embeddedHash(key: string, tablePath: string): string {\n if (!fs.existsSync(tablePath)) {\n throw new Error(\n `This @attest-ai/core install has no embedded engine hash table (${TABLE_NAME}), which is ` +\n `how a source or workspace install looks, so it never downloads an engine. ` +\n `Point ATTEST_ENGINE_PATH at an engine binary, or build one with \\`make engine\\` ` +\n `and set ATTEST_ENGINE_PATH=./bin/attest-engine.`\n );\n }\n let hash: unknown;\n try {\n const table = JSON.parse(fs.readFileSync(tablePath, \"utf-8\")) as Record<string, Record<string, unknown>>;\n hash = table[ENGINE_VERSION]?.[key];\n } catch (err) {\n throw new Error(\n `@attest-ai/core ${VERSION} ships an unreadable engine hash table at ${tablePath}: ${String(err)}`\n );\n }\n if (typeof hash !== \"string\" || !SHA256_HEX.test(hash)) {\n throw new Error(\n `@attest-ai/core ${VERSION} ships no valid engine hash for v${ENGINE_VERSION} on ${key} ` +\n `in ${tablePath}.`\n );\n }\n return hash;\n}\n\nfunction httpsGet(url: string, o: Required<Pick<DownloadOptions, \"connectTimeoutMs\" | \"totalTimeoutMs\">> & Pick<DownloadOptions, \"ca\">): Promise<Buffer> {\n return new Promise<Buffer>((resolve, reject) => {\n let current: import(\"node:http\").ClientRequest | undefined;\n let done = false;\n const finish = (err: Error | null, data?: Buffer): void => {\n if (done) return;\n done = true;\n clearTimeout(deadline);\n if (err) {\n current?.destroy();\n reject(err);\n } else {\n resolve(data as Buffer);\n }\n };\n const deadline = setTimeout(\n () => finish(new Error(`Timed out after ${o.totalTimeoutMs}ms fetching ${url}`)),\n o.totalTimeoutMs,\n );\n\n const hop = (target: string, redirects: number): void => {\n if (redirects > MAX_REDIRECTS) {\n finish(new Error(`Too many redirects (>${MAX_REDIRECTS}) following ${url}`));\n return;\n }\n let parsed: URL;\n try {\n parsed = new URL(target);\n } catch {\n finish(new Error(`Invalid URL: ${target}`));\n return;\n }\n if (parsed.protocol !== \"https:\") {\n finish(new Error(`Refusing to download over a non-https URL: ${target}`));\n return;\n }\n current = https.get(parsed, { ca: o.ca, timeout: o.connectTimeoutMs }, (res) => {\n const status = res.statusCode ?? 0;\n if (REDIRECT_STATUSES.has(status)) {\n res.resume();\n const location = res.headers.location;\n if (!location) {\n finish(new Error(`Redirect ${status} without Location header from ${target}`));\n return;\n }\n let next: string;\n try {\n next = new URL(location, parsed).toString();\n } catch {\n finish(new Error(`Invalid redirect Location ${JSON.stringify(location)} from ${target}`));\n return;\n }\n hop(next, redirects + 1);\n return;\n }\n if (status !== 200) {\n res.resume();\n finish(new Error(`HTTP ${status} fetching ${target}`));\n return;\n }\n const chunks: Buffer[] = [];\n res.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n res.on(\"end\", () => finish(null, Buffer.concat(chunks)));\n res.on(\"error\", (err) => finish(err));\n });\n current.on(\"timeout\", () =>\n finish(new Error(`No response within ${o.connectTimeoutMs}ms from ${target}`)),\n );\n current.on(\"error\", (err) => finish(err));\n };\n hop(url, 0);\n });\n}\n\nexport async function downloadEngine(options: DownloadOptions = {}): Promise<string> {\n const key = platformKey();\n const filename = `attest-engine-${key}${os.platform() === \"win32\" ? \".exe\" : \"\"}`;\n const expectedHash = embeddedHash(key, options.tablePath ?? path.join(packageRoot(), TABLE_NAME));\n const binaryUrl = `${options.releaseBase ?? RELEASE_BASE}/${filename}`;\n\n process.stderr.write(`[attest] Downloading engine v${ENGINE_VERSION} for ${key}...\\n`);\n let data: Buffer;\n try {\n data = await httpsGet(binaryUrl, {\n ca: options.ca,\n connectTimeoutMs: options.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS,\n totalTimeoutMs: options.totalTimeoutMs ?? DEFAULT_TOTAL_TIMEOUT_MS,\n });\n } catch (err) {\n throw new Error(`Failed to download engine from ${binaryUrl}: ${(err as Error).message}`);\n }\n\n const actualHash = crypto.createHash(\"sha256\").update(data).digest(\"hex\");\n if (actualHash !== expectedHash) {\n throw new Error(\n `${filename} does not match the hash shipped in @attest-ai/core ${VERSION}: ` +\n `expected ${expectedHash}, got ${actualHash}. ` +\n `Refusing to install it. Retry, or set ATTEST_ENGINE_PATH to a binary you trust.`\n );\n }\n process.stderr.write(`[attest] Checksum verified.\\n`);\n\n // Atomic write: temp file + rename\n const dir = versionedBinDir();\n fs.mkdirSync(dir, { recursive: true });\n const destPath = path.join(dir, binaryFilename());\n const suffix = `${String(process.pid)}.${crypto.randomBytes(8).toString(\"hex\")}`;\n const tmpPath = path.join(dir, `.${binaryFilename()}.tmp.${suffix}`);\n try {\n fs.writeFileSync(tmpPath, data, { flag: \"wx\", mode: 0o755 });\n fs.chmodSync(tmpPath, 0o755);\n fs.renameSync(tmpPath, destPath);\n } catch (err) {\n // EEXIST means the temp name belongs to someone else; leave it alone.\n if ((err as NodeJS.ErrnoException).code !== \"EEXIST\") fs.rmSync(tmpPath, { force: true });\n throw err;\n }\n\n process.stderr.write(`[attest] Engine installed at ${destPath}\\n`);\n return destPath;\n}\n","/**\n * Scaffolding for `attest init`.\n *\n * `attest init` writes a sample Vitest test that runs with no model, API key or\n * network: the agent run is a trace built by hand with `TraceBuilder` and every\n * assertion is deterministic (layers 1-4). `attest init --ci github` also writes a\n * GitHub Actions workflow that gates merges on the test run, the report and the\n * policy.\n */\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { VERSION } from \"./version.js\";\n\n/** Marks the line a new user edits to see a failure. */\nexport const DEMO_MARKER = \"ATTEST-DEMO\";\n\nexport const CI_PROVIDERS = [\"github\"] as const;\nexport type CiProvider = (typeof CI_PROVIDERS)[number];\n\nexport const SAMPLE_TEST_TEMPLATE = `// Sample Attest test written by \\`attest init\\`. Run it with \\`npx vitest run\\`.\nimport { it } from \"vitest\";\nimport { attestExpect, TraceBuilder, type Trace } from \"@attest-ai/core\";\nimport { evaluate } from \"@attest-ai/vitest\";\n\n// The trace of one agent run, built by hand so the sample needs no model, API key\n// or network. Replace it with a trace from your agent: wrap the agent with\n// \\`new Agent(...)\\` or record it with an adapter such as OpenAIAdapter.\nfunction myAgentResult(): Trace {\n return new TraceBuilder(\"refund-agent\")\n .setInput({ user_message: \"Please refund order ORD-1001.\" })\n .addToolCall(\"lookup_order\", {\n args: { order_id: \"ORD-1001\" },\n result: { status: \"delivered\", amount: 42.0 },\n })\n .addToolCall(\"issue_refund\", {\n args: { order_id: \"ORD-1001\", amount: 42.0 },\n result: { refund_id: \"RF-1001\" },\n })\n .setOutput({\n message: \"Your refund of $42.00 has been issued.\",\n structured: { refund_id: \"RF-1001\", amount: 42.0 },\n })\n .setMetadata({ total_tokens: 180, cost_usd: 0.002, latency_ms: 900 })\n .build();\n}\n\nit(\"my agent issues the refund\", async (context) => {\n const chain = attestExpect(myAgentResult())\n .outputMatchesSchema({ type: \"object\", required: [\"refund_id\"] }) // layer 1: schema\n .costUnder(0.01) // layer 2: constraint\n .toolsCalledInOrder([\"lookup_order\", \"issue_refund\"]) // layer 3: trace\n .outputContains(\"refund\"); // ${DEMO_MARKER}: change \"refund\" to \"store credit\"\n await evaluate(chain, { context });\n});\n`;\n\n/** Vitest arguments that add AttestReporter and write the report-v2 file. */\nexport const REPORT_ARGS =\n \"--reporter=default --reporter=@attest-ai/vitest/reporter --outputFile.attest=attest-report.json\";\n\nexport const POLICY_TEMPLATE = `# Merge policy for \\`attest policy evaluate --report <report> --policy attest.policy.yaml\\`.\n# Exit 0: pass. Exit 1: a blocking rule failed. Exit 2: warnings only.\nlayers:\n 0: # layer 0 caps every layer together\n max_hard_fails: 0\n# Assertions that could not run (no judge configured, simulation) warn instead of block.\nnot_evaluated: warn\n`;\n\nexport const GITHUB_WORKFLOW_TEMPLATE = `# Written by \\`attest init --ci github\\`.\n# The test step records its outcome and continues so the report is always uploaded,\n# the JUnit file written, the policy evaluated and the pull request summarised; the last\n# step fails the job when the tests failed. A policy warning (exit 2) does not fail the job.\nname: attest\n\non:\n pull_request:\n push:\n branches: [main]\n\npermissions:\n contents: read\n\njobs:\n attest:\n runs-on: ubuntu-latest\n permissions:\n contents: read\n pull-requests: write\n steps:\n - uses: actions/checkout@v6\n with:\n persist-credentials: false\n - uses: actions/setup-node@v6\n with:\n node-version: 22\n - name: Install dependencies\n run: npm ci\n - name: Run tests\n id: tests\n continue-on-error: true\n # Traces (prompts, outputs, tool args; not redacted) travel in the artifact; on a public\n # repository any signed-in GitHub user can download it. Enable on private repositories only:\n # env:\n # ATTEST_REPORT_TRACES: \"1\"\n run: npx vitest run ${REPORT_ARGS}\n - name: Write the JUnit report\n if: always()\n run: npx attest report junit --report attest-report.json --out attest-junit.xml\n - name: Write the failure viewer\n if: always()\n run: npx attest view attest-report.json --no-open --out attest-report.html\n - name: Upload the Attest report\n if: always()\n uses: actions/upload-artifact@v7\n with:\n name: attest-report\n path: |\n attest-report.json\n attest-junit.xml\n attest-report.html\n if-no-files-found: error\n - name: Evaluate the merge policy\n if: always()\n run: |\n set +e\n npx attest policy evaluate --report attest-report.json --policy attest.policy.yaml\n code=$?\n if [ \"$code\" -eq 2 ]; then\n echo \"::warning::attest policy: warnings only (exit 2)\"\n exit 0\n fi\n exit \"$code\"\n - name: Annotate the pull request\n # Posts one summary comment (updated on every run) and annotates failures at their\n # file and line. Fork pull requests get a read-only token that cannot comment; the\n # last step still fails the job when tests failed.\n if: >-\n always() && github.event_name == 'pull_request' &&\n github.event.pull_request.head.repo.full_name == github.repository\n uses: attest-framework/attest/.github/actions/pr-annotate@v${VERSION}\n with:\n report: attest-report.json\n - name: Fail the job when tests failed\n if: always() && steps.tests.outcome == 'failure'\n run: |\n echo \"::error::vitest failed; see the Run tests step\"\n exit 1\n`;\n\n/**\n * Files `scaffoldProject` wrote (`created`) and left alone because they existed\n * (`skipped`), as forward-slash paths relative to the target directory.\n */\nexport interface ScaffoldResult {\n created: string[];\n skipped: string[];\n}\n\nfunction write(\n targetDir: string,\n rel: string,\n content: string,\n result: ScaffoldResult,\n quiet: boolean,\n): void {\n const file = path.join(targetDir, ...rel.split(\"/\"));\n if (fs.existsSync(file)) {\n result.skipped.push(rel);\n if (!quiet) process.stderr.write(`Skipped (exists): ${file}\\n`);\n return;\n }\n fs.mkdirSync(path.dirname(file), { recursive: true });\n fs.writeFileSync(file, content);\n result.created.push(rel);\n if (!quiet) process.stdout.write(`Created: ${file}\\n`);\n}\n\n/**\n * Write the sample test and the merge policy into `targetDir`; `ci: \"github\"` also\n * writes `.github/workflows/attest.yml`. Existing files are never overwritten. No\n * Vitest config is written: the workflow adds AttestReporter on the command line\n * (`REPORT_ARGS`), so an existing config keeps working unchanged. `quiet` suppresses the\n * per-file lines and the next-step hint. Returns what was written.\n */\nexport function scaffoldProject(\n targetDir: string,\n options: { ci?: CiProvider; quiet?: boolean } = {},\n): ScaffoldResult {\n const quiet = options.quiet ?? false;\n const result: ScaffoldResult = { created: [], skipped: [] };\n write(targetDir, \"tests/my-agent.test.ts\", SAMPLE_TEST_TEMPLATE, result, quiet);\n write(targetDir, \"attest.policy.yaml\", POLICY_TEMPLATE, result, quiet);\n if (options.ci === \"github\") {\n write(targetDir, \".github/workflows/attest.yml\", GITHUB_WORKFLOW_TEMPLATE, result, quiet);\n }\n if (!quiet) {\n process.stdout.write(\n `\\nNext: run \\`npx vitest run\\`. Then change the line marked ${DEMO_MARKER} in ` +\n \"tests/my-agent.test.ts and run it again to see a failure.\\n\",\n );\n }\n return result;\n}\n","/**\n * Capture: turn a run into a verified fixture, and fixtures into tests.\n *\n * `attest capture --name <name> -- <command>` (the engine) records a run's trace and model\n * exchanges into `tests/attest/fixtures/<name>.attest.json`. This module is the TypeScript\n * side:\n *\n * - `record()` captures the code in a callback in this process.\n * - `loadFixture()` reads a fixture (`proto/attest/v1/fixture-v1.schema.json`).\n * - `emitVitest()` writes the fixture's drafted contracts as a Vitest file, using the\n * `attestExpect()` DSL. `attest capture` and `record()` call it. For a fixture captured\n * from a command, the test re-runs that command under strict replay (`replayRun()`) and\n * evaluates the contracts on the new run's trace.\n */\n\nimport { spawn } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { resolveEngine } from \"./engine-manager.js\";\nimport type { Trace } from \"./proto/types.js\";\n\nexport const FIXTURE_VERSION = 1;\nexport const DEFAULT_FIXTURE_DIR = path.join(\"tests\", \"attest\", \"fixtures\");\n\n/** A capture did not produce a fixture, or produced one that is not verified. */\nexport class CaptureError extends Error {\n /** The fixture written, when the engine wrote one. */\n readonly fixture: string | null;\n\n constructor(message: string, fixture: string | null = null) {\n super(message);\n this.name = \"CaptureError\";\n this.fixture = fixture;\n }\n}\n\n/** A drafted contract: an engine assertion spec plus its id and description. */\nexport interface Contract {\n id: string;\n kind: string;\n description: string;\n type: string;\n spec: Record<string, unknown>;\n}\n\n/** A contract's status on the captured trace. */\nexport interface ContractResult {\n contract: string;\n status: string;\n explanation: string;\n}\n\n/** A capture fixture (fixture-v1). */\nexport interface Fixture {\n name: string;\n source: { kind: string; replay_capable: boolean; command?: string[]; exit_code?: number };\n trace: Trace;\n exchanges: Record<string, unknown>[];\n contracts: Contract[];\n verification: {\n verified: boolean;\n expect_fail: boolean;\n trace_check: { ok: boolean; errors: number; warnings: number };\n results: ContractResult[];\n expected_failures: string[];\n };\n world: Record<string, unknown> | null;\n}\n\nfunction toPath(p: string | URL): string {\n return p instanceof URL ? fileURLToPath(p) : p;\n}\n\n/** Read a capture fixture written by `attest capture` or `record()`. */\nexport function loadFixture(file: string | URL): Fixture {\n const p = toPath(file);\n const doc = JSON.parse(fs.readFileSync(p, \"utf8\")) as unknown;\n if (!isObject(doc) || doc[\"fixture_version\"] !== FIXTURE_VERSION) {\n throw new CaptureError(`${p}: not a fixture_version ${FIXTURE_VERSION} capture fixture`);\n }\n validate(p, doc);\n return doc as unknown as Fixture;\n}\n\n/** Fixture names, as the engine accepts them (they become file names). */\nexport const NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;\n\ntype Kind = \"string\" | \"boolean\" | \"object\" | \"array\";\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\nfunction kindOf(v: unknown): Kind | \"other\" {\n if (Array.isArray(v)) return \"array\";\n if (isObject(v)) return \"object\";\n if (typeof v === \"string\" || typeof v === \"boolean\") return typeof v as Kind;\n return \"other\";\n}\n\n/** Check the fixture-v1 fields this module reads before using any of them. */\nfunction validate(p: string, doc: Record<string, unknown>): void {\n const need = (where: string, obj: unknown, fields: Record<string, Kind>): Record<string, unknown> => {\n if (!isObject(obj)) throw new CaptureError(`${p}: ${where} is not an object`);\n for (const [key, kind] of Object.entries(fields)) {\n if (kindOf(obj[key]) !== kind) throw new CaptureError(`${p}: ${where}.${key} is missing or not a ${kind}`);\n }\n return obj;\n };\n need(\"fixture\", doc, { name: \"string\", source: \"object\", trace: \"object\", exchanges: \"array\", contracts: \"array\", verification: \"object\" });\n if (!(\"world\" in doc)) throw new CaptureError(`${p}: fixture.world is missing`);\n if (!NAME_PATTERN.test(doc[\"name\"] as string)) {\n throw new CaptureError(`${p}: fixture name ${JSON.stringify(doc[\"name\"])} is not a valid fixture name`);\n }\n const v = need(\"fixture.verification\", doc[\"verification\"], {\n verified: \"boolean\",\n expect_fail: \"boolean\",\n results: \"array\",\n expected_failures: \"array\",\n });\n (doc[\"contracts\"] as unknown[]).forEach((c, i) =>\n need(`fixture.contracts[${i}]`, c, { id: \"string\", kind: \"string\", description: \"string\", type: \"string\", spec: \"object\" }),\n );\n (v[\"results\"] as unknown[]).forEach((r, i) =>\n need(`fixture.verification.results[${i}]`, r, { contract: \"string\", status: \"string\", explanation: \"string\" }),\n );\n}\n\n// ---------------------------------------------------------------------------- emitter\n\n/**\n * An object-literal key for `k`. `__proto__` must be a computed key: written plain or\n * quoted it sets the object's prototype instead of a property.\n */\nfunction objectKey(k: string): string {\n if (k === \"__proto__\") return `[${JSON.stringify(k)}]`;\n return /^[A-Za-z_$][\\w$]*$/.test(k) ? k : JSON.stringify(k);\n}\n\n/** Make captured text safe inside a `//` comment: one line, no control characters. */\nfunction comment(text: string): string {\n return text.replace(/[\\p{Cc}\\p{Zl}\\p{Zp}]/gu, \" \");\n}\n\n/** Render a JSON value as a TypeScript literal. */\nfunction ts(value: unknown): string {\n if (value === null || typeof value === \"boolean\" || typeof value === \"number\") {\n return JSON.stringify(value);\n }\n if (typeof value === \"string\") return JSON.stringify(value);\n if (Array.isArray(value)) return `[${value.map(ts).join(\", \")}]`;\n if (typeof value === \"object\") {\n const entries = Object.entries(value as Record<string, unknown>).map(\n ([k, v]) => `${objectKey(k)}: ${ts(v)}`,\n );\n return entries.length === 0 ? \"{}\" : `{ ${entries.join(\", \")} }`;\n }\n throw new Error(`value ${String(value)} has no literal`);\n}\n\nfunction str(spec: Record<string, unknown>, key: string): string {\n const v = spec[key];\n if (typeof v !== \"string\") throw new Error(`missing ${key}`);\n return v;\n}\n\nfunction options(entries: Array<[string, unknown]>): string {\n const set = entries.filter(([, v]) => v !== undefined && v !== null && v !== false);\n return set.length === 0 ? \"\" : `{ ${set.map(([k, v]) => `${k}: ${ts(v)}`).join(\", \")} }`;\n}\n\nfunction call(method: string, args: string[], opts: string): string {\n return `.${method}(${[...args, ...(opts ? [opts] : [])].join(\", \")})`;\n}\n\n/** The `ExpectChain` method call that emits `contract`'s spec; throws when there is none. */\nexport function dslCall(contract: Contract): string {\n const s = contract.spec;\n const soft = s[\"soft\"] === true ? true : undefined;\n try {\n if (contract.type === \"trace\") {\n const check = s[\"check\"];\n if (check === \"trajectory\" && s[\"mode\"] !== \"partial_order\") {\n const mode = s[\"mode\"] === \"strict\" || s[\"mode\"] === undefined ? undefined : s[\"mode\"];\n if (!Array.isArray(s[\"tools\"])) throw new Error(\"missing tools\");\n return call(\"trajectory\", [ts(s[\"tools\"])], options([[\"mode\", mode], [\"soft\", soft]]));\n }\n if (check === \"tool_order\") {\n return call(\"toolCalledBefore\", [ts(str(s, \"before\")), ts(str(s, \"after\"))], options([[\"soft\", soft]]));\n }\n if (check === \"tool_cardinality\") {\n return call(\n \"toolCardinality\",\n [ts(str(s, \"tool\"))],\n options([\n [\"per\", s[\"per\"]],\n [\"atLeast\", s[\"min\"]],\n [\"atMost\", s[\"max\"]],\n [\"soft\", soft],\n ]),\n );\n }\n }\n if (contract.type === \"schema\" && s[\"target\"] === \"output.structured\") {\n if (typeof s[\"schema\"] !== \"object\" || s[\"schema\"] === null) throw new Error(\"missing schema\");\n return call(\"outputMatchesSchema\", [ts(s[\"schema\"])], \"\");\n }\n if (contract.type === \"constraint\" && s[\"field\"] === \"metadata.cost_usd\" && s[\"operator\"] === \"lte\") {\n if (typeof s[\"value\"] !== \"number\") throw new Error(\"missing value\");\n return call(\"costUnder\", [ts(s[\"value\"])], options([[\"soft\", soft]]));\n }\n } catch (err) {\n throw new Error(`contract ${contract.id}: malformed spec (${(err as Error).message})`);\n }\n throw new Error(`contract ${contract.id}: no TypeScript DSL call for ${contract.type} spec`);\n}\n\n/**\n * Where a drafted replay test re-runs the fixture's source command: `cwd` is the directory\n * the capture ran in (the command's relative paths resolve there), `world` the world file\n * the capture hosted, if any.\n */\nexport interface Rerun {\n cwd: string;\n world?: string;\n}\n\n/**\n * Where the drafted test for a fixture goes: `tests/attest/<name>.test.ts` for\n * `tests/attest/fixtures/<name>.attest.json`.\n */\nexport function testPathFor(fixturePath: string): string {\n const name = path.basename(fixturePath).replace(/\\.attest\\.json$/, \"\");\n return path.join(path.dirname(path.dirname(fixturePath)), `${name}.test.ts`);\n}\n\nfunction relUrl(target: string, testPath: string): string {\n const rel = path.relative(path.dirname(testPath), target).split(path.sep).join(\"/\");\n const url = rel === \"\" ? \".\" : rel;\n return `new URL(${ts(url.startsWith(\".\") ? url : `./${url}`)}, import.meta.url)`;\n}\n\nfunction chainLines(calls: Array<[Contract, string]>, subject: string, param: string): string[] {\n const lines = [`function contracts(${param}): ExpectChain {`, ` return attestExpect(${subject})`];\n for (const [c, dsl] of calls) {\n lines.push(` // ${comment(`${c.id}: ${c.description}`)}`, ` ${dsl}`);\n }\n lines[lines.length - 1] += \";\";\n lines.push(\"}\");\n return lines;\n}\n\nfunction skippedLines(skipped: string[]): string[] {\n if (skipped.length === 0) return [];\n return [\"\", \"// Drafted contracts without a TypeScript DSL call (left out):\", ...skipped.map((s) => `// - ${comment(s)}`)];\n}\n\nfunction renderReplay(\n fixture: Fixture,\n calls: Array<[Contract, string]>,\n skipped: string[],\n fixturePath: string,\n testPath: string,\n rerun: Rerun,\n): string {\n const meaning = fixture.verification.expect_fail\n ? [\n \"// The recording is an incident: these contracts failed on it. The test passes once\",\n \"// the new run satisfies them, so it fails again if the agent regresses.\",\n ]\n : [\"// The test fails when the agent's behavior stops satisfying them.\"];\n const world = rerun.world === undefined ? \"undefined\" : relUrl(rerun.world, testPath);\n const lines = [\n `// Replay test drafted by \\`attest capture\\` from fixture ${comment(ts(fixture.name))}.`,\n \"//\",\n \"// Re-runs COMMAND, the source command of the fixture, under strict replay (the engine's\",\n \"// `replay --mode strict --no-live`): OpenAI- and Anthropic-compatible calls are served\",\n \"// from the recording, and one that matches no recording fails the test. Other providers\",\n \"// are not blocked: run this test without their credentials. The drafted contracts are\",\n \"// evaluated on the NEW run's trace, not on the recording.\",\n \"//\",\n \"// COMMAND is what this test runs and is reviewed with the test: if the fixture's\",\n \"// source.command stops matching it, the test fails instead of running the fixture's.\",\n ...meaning,\n \"//\",\n \"// A pass means the new run is consistent with the recording and satisfies the drafted\",\n \"// contracts; it does not prove the agent correct. Identities are compared by role\",\n \"// (relative identity): a run that swaps who plays which role misses, while the absolute\",\n \"// identity is not checked. Review and edit before committing. Re-capturing does not\",\n \"// overwrite this file.\",\n `import { attestExpect, replayRun, type ExpectChain } from \"@attest-ai/core\";`,\n `import type { Trace } from \"@attest-ai/core/proto\";`,\n `import { evaluate } from \"@attest-ai/vitest\";`,\n `import { describe, it } from \"vitest\";`,\n \"\",\n `const FIXTURE = ${relUrl(fixturePath, testPath)};`,\n \"// The directory `attest capture` ran in: the source command's relative paths start here.\",\n `const RUN_DIR = ${relUrl(rerun.cwd, testPath)};`,\n `const WORLD = ${world};`,\n \"// Reviewed argv: the only command this test runs.\",\n `const COMMAND = ${ts(fixture.source.command ?? [])};`,\n ...skippedLines(skipped),\n \"\",\n ...chainLines(calls, \"trace\", \"trace: Trace\"),\n \"\",\n `describe(${ts(fixture.name)}, () => {`,\n ` it(\"new run is consistent with the recording\", async () => {`,\n \" const trace = await replayRun(FIXTURE, { command: COMMAND, cwd: RUN_DIR, world: WORLD });\",\n \"\",\n \" await evaluate(contracts(trace));\",\n \" });\",\n \"});\",\n ];\n return `${lines.join(\"\\n\")}\\n`;\n}\n\n/**\n * Render a fixture's drafted contracts as a Vitest module.\n *\n * With `rerun` and a fixture captured from a command, the test re-runs that command under\n * strict replay and evaluates every contract on the new run's trace (an incident\n * reproduction included: it passes once the agent no longer reproduces the incident).\n * Otherwise a verified fixture becomes a test that enforces every contract on the recorded\n * trace with `evaluate`, and an incident reproduction (`expect_fail`) a test that checks,\n * with `inspect`, that the expected failures still fail and the other contracts still\n * pass; it stays green while it reproduces the incident.\n */\nexport function renderVitest(\n fixture: Fixture,\n fixturePath: string,\n testPath: string,\n rerun?: Rerun,\n): string {\n const calls: Array<[Contract, string]> = [];\n const skipped: string[] = [];\n for (const c of fixture.contracts) {\n try {\n calls.push([c, dslCall(c)]);\n } catch (err) {\n skipped.push((err as Error).message);\n }\n }\n if (rerun !== undefined && fixture.source.kind === \"command\" && fixture.source.replay_capable) {\n return renderReplay(fixture, calls, skipped, fixturePath, testPath, rerun);\n }\n const status = new Map(fixture.verification.results.map((r) => [r.contract, r.status]));\n const expectFail = fixture.verification.expect_fail;\n\n const lines = [\n `// Contracts drafted by \\`attest capture\\` from fixture ${comment(ts(fixture.name))}.`,\n \"//\",\n \"// Review and edit before committing: they check the captured trace without running\",\n \"// the agent. Re-capturing does not overwrite this file.\",\n `import { attestExpect, loadFixture, type ExpectChain } from \"@attest-ai/core\";`,\n `import { ${expectFail ? \"inspect\" : \"evaluate\"} } from \"@attest-ai/vitest\";`,\n `import { describe, ${expectFail ? \"expect, \" : \"\"}it } from \"vitest\";`,\n \"\",\n `const FIXTURE = loadFixture(${relUrl(fixturePath, testPath)});`,\n ...skippedLines(skipped),\n \"\",\n ...chainLines(calls, \"FIXTURE.trace\", \"\"),\n ];\n if (expectFail) {\n lines.push(\"\", \"// Status of each contract on the captured incident, in contracts() order.\");\n lines.push(\"const EXPECTED: Array<[string, string]> = [\");\n for (const [c] of calls) lines.push(` [${ts(c.id)}, ${ts(status.get(c.id) ?? \"pass\")}],`);\n lines.push(\n \"];\",\n \"\",\n `describe(${ts(fixture.name)}, () => {`,\n ` it(\"reproduces the incident\", async () => {`,\n \" const result = await inspect(contracts());\",\n \"\",\n \" expect(result.assertionResults.map((row) => row.status)).toEqual(EXPECTED.map(([, s]) => s));\",\n \" });\",\n \"});\",\n );\n } else {\n lines.push(\n \"\",\n `describe(${ts(fixture.name)}, () => {`,\n ` it(\"keeps its drafted contracts\", async () => {`,\n \" await evaluate(contracts());\",\n \" });\",\n \"});\",\n );\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\n/**\n * Write the drafted Vitest file for a fixture unless it already exists. Returns the path\n * written, or null when a test file is already there (re-capturing never overwrites an\n * edited test). `rerun` makes the test of a command fixture re-run the command under strict\n * replay (see `renderVitest`).\n */\nexport function emitVitest(fixturePath: string, rerun?: Rerun): string | null {\n const testPath = testPathFor(fixturePath);\n const existing = fs.lstatSync(testPath, { throwIfNoEntry: false });\n if (existing?.isSymbolicLink()) {\n throw new CaptureError(`${testPath} is a symbolic link; refusing to draft a test through it`);\n }\n if (existing !== undefined) return null;\n const source = renderVitest(loadFixture(fixturePath), fixturePath, testPath, rerun);\n fs.mkdirSync(path.dirname(testPath), { recursive: true });\n // Create exclusively: \"wx\" fails on any existing path, a link planted after\n // the check included, and never writes through it.\n try {\n fs.writeFileSync(testPath, source, { encoding: \"utf8\", flag: \"wx\" });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"EEXIST\") {\n throw new CaptureError(`${testPath} appeared while drafting; left unchanged`);\n }\n throw err;\n }\n return testPath;\n}\n\n// ------------------------------------------------------------------------ replayRun()\n\nconst OTHER_PROVIDER_KEYS = [\"ANTHROPIC_API_KEY\", \"GOOGLE_API_KEY\", \"GEMINI_API_KEY\"];\nconst REPLAY_TIMEOUT_MS = 300_000;\nconst REDACTED_MARKER = \"[redacted]\"; // engine/internal/redact: Marker\nconst PLACEHOLDER = /\\{\\{(?:id|email|timestamp)_\\d+\\}\\}/; // capture.HasPlaceholder\nconst STDERR_TAIL = 4000;\n\nexport interface ReplayRunOptions {\n /** The argv to run, written in the reviewed test; must equal the fixture's `source.command`. */\n command: readonly string[];\n /** Directory to run the command in (the one the capture ran in). */\n cwd?: string | URL;\n /** World file the capture hosted, when the fixture has a `world` section. */\n world?: string | URL;\n /** Engine binary; default is the SDK's discovery order. */\n enginePath?: string;\n /** Milliseconds before the run is abandoned (default 300000). */\n timeoutMs?: number;\n}\n\n/**\n * Re-run a fixture's source command under strict replay and return the new run's trace.\n *\n * Runs `attest-engine replay --mode strict --no-live --trace-out ... -- <command>`: the\n * OpenAI- and Anthropic-compatible calls the command makes are answered from the fixture's\n * recorded exchanges, and a call that matches no recording fails. Other providers are not\n * blocked: the replay proxy redirects only `OPENAI_BASE_URL` and `ANTHROPIC_BASE_URL`, and\n * `ATTEST_EGRESS=block` only affects processes that install attest's guard.\n * `ANTHROPIC_API_KEY`, `GOOGLE_API_KEY` and `GEMINI_API_KEY` are removed from the\n * environment and `OPENAI_API_KEY` is a placeholder; run without other providers'\n * credentials. The new run's trace is written unredacted to a private temporary directory\n * removed afterwards.\n *\n * The fixture file can be changed by a pull request, so its `source.command` is never run:\n * `options.command` is, and the call rejects when the fixture's differs, or when it has\n * redacted or templated (`{{id_N}}`) arguments.\n *\n * Rejects with `CaptureError` when the fixture has no replayable source command, a request\n * matched no recording, the command exited differently than when recorded, or no trace came\n * out.\n */\nexport async function replayRun(fixture: string | URL, options: ReplayRunOptions): Promise<Trace> {\n const fp = path.resolve(toPath(fixture));\n const doc = loadFixture(fp);\n const recorded = doc.source.command;\n if (doc.source.kind !== \"command\" || !doc.source.replay_capable || !recorded || recorded.length === 0) {\n throw new CaptureError(`${fp}: not a command capture with recorded exchanges; cannot replay`);\n }\n const command = [...options.command];\n if (command.length !== recorded.length || command.some((a, i) => a !== recorded[i])) {\n throw new CaptureError(\n `${fp}: refusing to run: the fixture's source.command ${JSON.stringify(recorded)} differs from the test's COMMAND ${JSON.stringify(command)}; review the change, then update the test`,\n );\n }\n if (command.some((a) => a.includes(REDACTED_MARKER) || PLACEHOLDER.test(a))) {\n throw new CaptureError(\n `${fp}: refusing to run: the recorded command has redacted or templated arguments; re-run \\`attest capture\\` with the real command`,\n );\n }\n if (doc.world !== null && options.world === undefined) {\n throw new CaptureError(`${fp}: captured with a world; pass the world file the capture ran with`);\n }\n const env: NodeJS.ProcessEnv = { ...process.env, OPENAI_API_KEY: \"replay-needs-no-key\", ATTEST_EGRESS: \"block\" };\n for (const key of OTHER_PROVIDER_KEYS) delete env[key];\n const engine = await resolveEngine(options.enginePath);\n const tmp = fs.mkdtempSync(path.join(os.tmpdir(), \"attest-replay-\"));\n try {\n const traceFile = path.join(tmp, \"trace.json\");\n const argv = [\"replay\", \"--fixture\", fp, \"--mode\", \"strict\", \"--no-live\", \"--trace-out\", traceFile, \"--json\"];\n if (options.world !== undefined) argv.push(\"--world\", path.resolve(toPath(options.world)));\n argv.push(\"--\", ...command);\n const timeoutMs = options.timeoutMs ?? REPLAY_TIMEOUT_MS;\n const run = await runEngine(engine, argv, {\n cwd: options.cwd === undefined ? undefined : toPath(options.cwd),\n env,\n timeoutMs,\n });\n if (run.error !== null) throw new CaptureError(`${fp}: ${run.error}`);\n if (run.timedOut) throw new CaptureError(`${fp}: replay run exceeded ${timeoutMs}ms`);\n checkReplay(fp, doc, run);\n if (!fs.existsSync(traceFile)) {\n throw new CaptureError(`${fp}: the replay run exported no trace\\n${tail(run.stderr)}`);\n }\n return JSON.parse(fs.readFileSync(traceFile, \"utf8\")) as Trace;\n } finally {\n fs.rmSync(tmp, { recursive: true, force: true });\n }\n}\n\ninterface EngineRun {\n code: number | null;\n signal: NodeJS.Signals | null;\n stdout: string;\n stderr: string;\n timedOut: boolean;\n error: string | null;\n}\n\nfunction tail(stderr: string): string {\n return stderr.slice(-STDERR_TAIL);\n}\n\n/**\n * Fail unless every request was served and the command exited as it did when recorded. The\n * engine exits 1 for a miss and for a failing command alike, so the verdict comes from its\n * `--json` result. An incident recording exits non-zero; its replay must too.\n */\nfunction checkReplay(fp: string, fixture: Fixture, run: EngineRun): void {\n let misses: number;\n let exitCode: number;\n try {\n const result = JSON.parse(run.stdout) as { exit_code: unknown; summary: { misses: unknown } };\n misses = Number(result.summary.misses);\n exitCode = Number(result.exit_code);\n if (!Number.isInteger(misses) || !Number.isInteger(exitCode)) throw new TypeError(\"not integers\");\n } catch {\n throw new CaptureError(`${fp}: replay run exited ${run.code ?? run.signal}\\n${tail(run.stderr)}`);\n }\n if (misses > 0) throw new CaptureError(`${fp}: ${misses} request(s) matched no recording\\n${tail(run.stderr)}`);\n const recorded = fixture.source.exit_code ?? 0;\n if (exitCode !== recorded) {\n throw new CaptureError(`${fp}: the command exited ${exitCode}; the recording exited ${recorded}\\n${tail(run.stderr)}`);\n }\n}\n\nfunction runEngine(\n engine: string,\n argv: string[],\n opts: { cwd: string | undefined; env: NodeJS.ProcessEnv; timeoutMs: number },\n): Promise<EngineRun> {\n return new Promise((resolve) => {\n const child = spawn(engine, argv, { cwd: opts.cwd, env: opts.env, stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n let stdout = \"\";\n let stderr = \"\";\n let timedOut = false;\n child.stdout.setEncoding(\"utf8\").on(\"data\", (chunk: string) => {\n stdout += chunk;\n });\n child.stderr.setEncoding(\"utf8\").on(\"data\", (chunk: string) => {\n stderr += chunk;\n });\n const timer = setTimeout(() => {\n timedOut = true;\n child.kill(\"SIGKILL\");\n }, opts.timeoutMs);\n child.on(\"error\", (err) => {\n clearTimeout(timer);\n resolve({ code: null, signal: null, stdout, stderr, timedOut, error: `could not start the replay run: ${err.message}` });\n });\n child.on(\"close\", (code, signal) => {\n clearTimeout(timer);\n resolve({ code, signal, stdout, stderr, timedOut, error: null });\n });\n });\n}\n\n// ---------------------------------------------------------------------------- record()\n\n/** A running in-process capture. */\nexport interface Capture {\n name: string;\n /** The variables `record()` set in `process.env` for the callback. */\n env: Record<string, string>;\n}\n\nexport interface RecordOptions {\n /** Fixture directory (default `tests/attest/fixtures`). */\n outDir?: string;\n /** Save an incident reproduction: verified when drafted contracts fail. */\n expectFail?: boolean;\n /** Trace `agent_id` (default: the first turn's agent name). */\n agentId?: string;\n /** Write the drafted Vitest file (default true). */\n emitTest?: boolean;\n /** Engine binary (default: the SDK's engine discovery). */\n enginePath?: string;\n /**\n * A `world.yaml` to host for the callback (the engine's `--world`): its base URL variable\n * (`PAYMENTS_BASE_URL`) is set for the callback and the world's final state is saved in\n * the fixture's `world` section.\n */\n world?: string;\n /**\n * Called after the callback returns and before the fixture is built; pass the tracer\n * provider's `forceFlush` so batched spans reach the receiver.\n */\n flush?: () => unknown;\n}\n\nexport interface RecordResult<T> {\n value: T;\n fixture: string;\n verified: boolean;\n /**\n * `verified`, `not_verified` or `nothing_to_verify`: a healthy run with no tool call,\n * structured output or cost to draft a contract from. `record` throws for\n * `not_verified`; `nothing_to_verify` returns `verified: false` and no test file.\n */\n outcome: \"verified\" | \"nothing_to_verify\";\n testFile: string | null;\n}\n\ninterface ServeExit {\n code: number | null;\n signal: NodeJS.Signals | null;\n stdout: string;\n stderr: string;\n}\n\ninterface ServeProcess {\n ready: Promise<string | null>;\n finish(finalize: boolean): Promise<ServeExit>;\n}\n\nfunction serve(engine: string, args: string[]): ServeProcess {\n const child = spawn(engine, args, { stdio: [\"pipe\", \"pipe\", \"pipe\"] });\n let stdout = \"\";\n let stderr = \"\";\n let resolveReady: (line: string | null) => void = () => undefined;\n const ready = new Promise<string | null>((resolve) => {\n resolveReady = resolve;\n });\n const exited = new Promise<{ code: number | null; signal: NodeJS.Signals | null }>((resolve) => {\n child.on(\"close\", (code, signal) => {\n resolveReady(null);\n resolve({ code, signal });\n });\n child.on(\"error\", (err) => {\n stderr += err.message;\n resolveReady(null);\n resolve({ code: null, signal: null });\n });\n });\n child.stdout.setEncoding(\"utf8\").on(\"data\", (chunk: string) => {\n stdout += chunk;\n const nl = stdout.indexOf(\"\\n\");\n if (nl >= 0) resolveReady(stdout.slice(0, nl));\n });\n child.stderr.setEncoding(\"utf8\").on(\"data\", (chunk: string) => {\n stderr += chunk;\n });\n // An engine that already exited cannot take \"finalize\"; its exit still says why.\n child.stdin.on(\"error\", () => undefined);\n return {\n ready,\n async finish(finalize) {\n // The environment as it is now: secrets the callback loaded (a dotenv\n // file, for example) are redacted too.\n if (finalize) {\n const environ = Object.entries(process.env).flatMap(([k, v]) => (v === undefined ? [] : [`${k}=${v}`]));\n child.stdin.write(`${JSON.stringify({ finalize: true, environ })}\\n`);\n }\n child.stdin.end();\n const { code, signal } = await exited;\n return { code, signal, stdout, stderr };\n },\n };\n}\n\nfunction readyEnv(line: string | null): Record<string, string> | null {\n if (line === null) return null;\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n return null;\n }\n const env = (parsed as { env?: unknown } | null)?.env;\n if (typeof env !== \"object\" || env === null) return null;\n const entries = Object.entries(env);\n if (!entries.every(([, v]) => typeof v === \"string\")) return null;\n return Object.fromEntries(entries) as Record<string, string>;\n}\n\nfunction exitDetail(exit: ServeExit): string {\n const how = exit.signal !== null ? `killed by ${exit.signal}` : `exit ${String(exit.code)}`;\n const err = exit.stderr.trim();\n return err ? `${how}: ${err}` : how;\n}\n\nfunction restore(saved: Map<string, string | undefined>): void {\n for (const [k, v] of saved) {\n if (v === undefined) delete process.env[k];\n else process.env[k] = v;\n }\n}\n\n// record() sets process-wide environment variables, so a second concurrent capture\n// would save and later restore the first one's values.\nlet recording = false;\n\n/**\n * Capture `fn` as fixture `<outDir>/<name>.attest.json`.\n *\n * Starts `attest-engine capture --serve`, which hosts the recording proxy and the\n * OTLP/HTTP receiver on 127.0.0.1, and sets `OPENAI_BASE_URL`, `ANTHROPIC_BASE_URL` and\n * `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` while `fn` runs. Model clients and the\n * OpenTelemetry exporter read these when they are constructed, so construct them inside\n * `fn`, and pass the tracer provider's `forceFlush` as `flush`. Afterwards the variables\n * are restored and the engine writes the fixture; for a verified fixture with `emitTest`\n * the drafted Vitest file is written unless one exists. If `fn` throws, the capture is\n * abandoned and no fixture is written. Captures cannot overlap.\n *\n * @throws CaptureError when another capture is running, the engine writes no fixture,\n * or the fixture is not verified (a drafted contract did not hold, the trace check\n * failed or no model call was recorded; the fixture is still written and no test is\n * drafted). A healthy run with nothing to draft a contract from does not throw: the\n * result has `outcome: \"nothing_to_verify\"`, `verified: false` and no test file.\n */\nexport async function record<T>(\n name: string,\n fn: (capture: Capture) => T | Promise<T>,\n opts: RecordOptions = {},\n): Promise<RecordResult<T>> {\n if (recording) throw new CaptureError(\"record() is already running; captures cannot overlap\");\n recording = true;\n try {\n return await recordExclusive(name, fn, opts);\n } finally {\n recording = false;\n }\n}\n\nasync function recordExclusive<T>(\n name: string,\n fn: (capture: Capture) => T | Promise<T>,\n opts: RecordOptions,\n): Promise<RecordResult<T>> {\n const engine = await resolveEngine(opts.enginePath);\n const args = [\"capture\", \"--serve\", \"--name\", name, \"--out-dir\", opts.outDir ?? DEFAULT_FIXTURE_DIR];\n if (opts.expectFail) args.push(\"--expect-fail\");\n if (opts.agentId !== undefined) args.push(\"--agent-id\", opts.agentId);\n if (opts.world !== undefined) args.push(\"--world\", path.resolve(opts.world));\n const proc = serve(engine, args);\n const env = readyEnv(await proc.ready);\n if (env === null) {\n const exit = await proc.finish(false);\n throw new CaptureError(`attest-engine capture --serve did not start (${exitDetail(exit)})`);\n }\n const saved = new Map(Object.keys(env).map((k) => [k, process.env[k]]));\n Object.assign(process.env, env);\n let value: T;\n try {\n value = await fn({ name, env });\n if (opts.flush) await opts.flush();\n } catch (err) {\n restore(saved);\n await proc.finish(false);\n throw err;\n }\n restore(saved);\n const exit = await proc.finish(true);\n process.stderr.write(exit.stderr);\n const lines = exit.stdout.trim().split(\"\\n\");\n if (lines.length < 2) {\n throw new CaptureError(`capture ${name} wrote no fixture (${exitDetail(exit)})`);\n }\n const outcome = JSON.parse(lines[lines.length - 1] ?? \"\") as {\n fixture: string;\n verified: boolean;\n outcome: \"verified\" | \"not_verified\" | \"nothing_to_verify\";\n };\n if (exit.code !== 0 || outcome.outcome === \"not_verified\") {\n throw new CaptureError(`capture ${name}: fixture ${outcome.fixture} is not verified; no test drafted`, outcome.fixture);\n }\n if (outcome.outcome === \"nothing_to_verify\") {\n return { value, fixture: outcome.fixture, verified: false, outcome: \"nothing_to_verify\", testFile: null };\n }\n const testFile = opts.emitTest === false ? null : emitVitest(outcome.fixture);\n return { value, fixture: outcome.fixture, verified: true, outcome: \"verified\", testFile };\n}\n"],"mappings":"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","names":["spawnSync","fs","os","path","fileURLToPath","existsSync","statSync","join","platform","arch","resolve","options","join","statSync","existsSync","options","fs","path","options","spawn","fs","os","path","fileURLToPath","fileURLToPath","spawnSync","fileURLToPath"]}
|