Lines 43-83javascript
43 * the cache is INDEPENDENT of any install's `node_modules`: it survives that tree being deleted
44 * (worktree cleanup) or absent (`--omit=optional`), the two scenarios it exists for. Best-effort and
45 * fail-quiet; subsequent runs — in this or any sibling worktree — find it before re-probing (or
46 * re-installing) a per-worktree copy (bead kestrel-2e2e).
47 * 4. The bundled `bun` optionalDependency — its postinstall-materialized `bun/bin/bun.exe` FIRST,
48 * then the `@oven/bun-*` packages filtered by platform+arch+libc (non-baseline before baseline),
49 * because npm installs every wrong-libc/baseline variant and bun's postinstall MOVES the correct
51 * A candidate that fails the probe (or the exec) is SKIPPED and the next tried. `KESTREL_NO_BUNDLED_BUN=1`
52 * excludes the bundled PACKAGE entirely — by REALPATH, so its `.bin/bun` symlink (which npx puts first
53 * on PATH) cannot smuggle it back in. The flag targets that per-worktree package; the shared cache is a
54 * separate per-USER tier holding INDEPENDENT bytes (a hardlink/copy, not a symlink into the package), so
55 * a bun materialized there is its own artifact, no longer the bundled package the flag excludes.
57 * Only when EVERY candidate fails does the launcher fall through in-process: the heavy verb then faults
58 * through `loadHeavy` into the existing loud exit-4 RUNTIME_UNAVAILABLE refusal, rendered in the
59 * caller's mode — never a raw stack.
64const { spawnSync } = require("node:child_process");
65const fs = require("node:fs");
MediumDynamic Require
Package source references dynamic require/import behavior.
bin/kestrel.cjsView on unpkg · L63 66const os = require("node:os");
67const path = require("node:path");
68const { pathToFileURL } = require("node:url");
70const CLI = path.join(__dirname, "..", "dist", "cli.js");
72/** The floor `package.json#engines.bun` promises. An older bun ships an older `bun:sqlite`. */
73const BUN_FLOOR = [1, 1, 0];
75// `sim` is LIGHT by construction (kestrel-585): it drives the hosted funnel over fetch only
76// (no bun:sqlite/chdb), so the site's hero snippet runs under plain node via npx.
77// `prove`/`replay`/`verify` (kestrel-markets-n04e.1) are LIGHT like `sim`: they drive the hosted
78// funnel over fetch only (verify adds node:crypto — still a node built-in), so the zero-credential
79// front door runs under plain node via npx with no bun anywhere.
80// `certify` (kestrel-8kvs, gate G10) is LIGHT too: it fetches the evidence bundle over fetch and
81// re-projects the Blotter with pure `project`/`serialize` + a node:crypto-free sha256 — no bun/chdb,
82// no engine drive — so open recomputation runs under plain node via npx.
83// `whoami`/`refresh` (kestrel-p7th) are LIGHT: `whoami` is a pure-local credential read (node