/** * Locate the impeccable engine binary for tests that drive verbs end to end. * * Order: $IMPECCABLE_BIN, then skill/scripts/bin/-/impeccable[.exe] * (what `bun run fetch:engine` writes). Returns null when neither exists so a * suite can skip cleanly instead of failing on a machine without the engine. */ import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..'); export function engineTarget() { const platform = { darwin: 'darwin', linux: 'linux', win32: 'windows' }[os.platform()] || 'unknown'; const arch = { arm64: 'arm64', x64: 'x64' }[os.arch()] || 'unknown'; return `${platform}-${arch}`; } export function findEngineBinary() { const fromEnv = process.env.IMPECCABLE_BIN; if (fromEnv && fs.existsSync(fromEnv)) return path.resolve(fromEnv); const target = engineTarget(); const local = path.join(REPO_ROOT, 'skill', 'scripts', 'bin', target, target.startsWith('windows-') ? 'impeccable.exe' : 'impeccable'); return fs.existsSync(local) ? local : null; } export const ENGINE_MISSING_MESSAGE = 'engine binary not found: run `bun run fetch:engine` or set IMPECCABLE_BIN'; /** Environment the launcher would export for the binary when run from this repo's skill dir. */ export function engineEnv(bin, extra = {}) { return { ...process.env, IMPECCABLE_SKILL_DIR: path.join(REPO_ROOT, 'skill'), IMPECCABLE_SELF: bin, ...extra, }; }