@whittlelabs/trivet 0.1.10 → 0.2.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.
Files changed (4) hide show
  1. package/README.md +1 -1
  2. package/bin.js +461 -76
  3. package/bin.js.map +4 -4
  4. package/package.json +2 -2
package/bin.js CHANGED
@@ -3023,15 +3023,55 @@ var require_commander = __commonJS({
3023
3023
  var require_apply = __commonJS({
3024
3024
  "../../packages/shuttle/dist/branding/apply.js"(exports2) {
3025
3025
  "use strict";
3026
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
3027
+ if (k2 === void 0) k2 = k;
3028
+ var desc = Object.getOwnPropertyDescriptor(m, k);
3029
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
3030
+ desc = { enumerable: true, get: function() {
3031
+ return m[k];
3032
+ } };
3033
+ }
3034
+ Object.defineProperty(o, k2, desc);
3035
+ }) : (function(o, m, k, k2) {
3036
+ if (k2 === void 0) k2 = k;
3037
+ o[k2] = m[k];
3038
+ }));
3039
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
3040
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
3041
+ }) : function(o, v) {
3042
+ o["default"] = v;
3043
+ });
3044
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
3045
+ var ownKeys = function(o) {
3046
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
3047
+ var ar = [];
3048
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
3049
+ return ar;
3050
+ };
3051
+ return ownKeys(o);
3052
+ };
3053
+ return function(mod) {
3054
+ if (mod && mod.__esModule) return mod;
3055
+ var result = {};
3056
+ if (mod != null) {
3057
+ for (var k = ownKeys(mod), i2 = 0; i2 < k.length; i2++) if (k[i2] !== "default") __createBinding(result, mod, k[i2]);
3058
+ }
3059
+ __setModuleDefault(result, mod);
3060
+ return result;
3061
+ };
3062
+ })();
3026
3063
  Object.defineProperty(exports2, "__esModule", { value: true });
3027
3064
  exports2.PROFILE_NAME = exports2.DEFAULT_PROFILE = void 0;
3028
3065
  exports2.expandHome = expandHome;
3066
+ exports2.windowsLocalAppData = windowsLocalAppData;
3067
+ exports2.brandConfigDir = brandConfigDir;
3068
+ exports2.resolveBrandPath = resolveBrandPath;
3029
3069
  exports2.resolveProfile = resolveProfile;
3030
3070
  exports2.resolvePaths = resolvePaths;
3031
3071
  exports2.runConfigSearchPaths = runConfigSearchPaths;
3032
3072
  exports2.renderTemplate = renderTemplate;
3033
3073
  var os_1 = require("os");
3034
- var path_1 = require("path");
3074
+ var path_1 = __importStar(require("path"));
3035
3075
  function expandHome(p) {
3036
3076
  if (p === "~")
3037
3077
  return (0, os_1.homedir)();
@@ -3039,6 +3079,26 @@ var require_apply = __commonJS({
3039
3079
  return (0, path_1.join)((0, os_1.homedir)(), p.slice(2));
3040
3080
  return p;
3041
3081
  }
3082
+ function windowsLocalAppData(env = process.env) {
3083
+ return env.LOCALAPPDATA ?? path_1.default.win32.join((0, os_1.homedir)(), "AppData", "Local");
3084
+ }
3085
+ function brandConfigDir(brand, platform = process.platform, env = process.env) {
3086
+ const declared = brand.paths.configDir;
3087
+ if (platform === "win32" && (declared === "~" || declared.startsWith("~/"))) {
3088
+ return path_1.default.win32.join(windowsLocalAppData(env), brand.product.cliBinary);
3089
+ }
3090
+ return expandHome(declared);
3091
+ }
3092
+ function resolveBrandPath(brand, declaredPath, platform = process.platform, env = process.env) {
3093
+ const declaredDir = brand.paths.configDir;
3094
+ if (declaredPath === declaredDir)
3095
+ return brandConfigDir(brand, platform, env);
3096
+ if (declaredPath.startsWith(`${declaredDir}/`)) {
3097
+ const p = platform === "win32" ? path_1.default.win32 : path_1.default;
3098
+ return p.join(brandConfigDir(brand, platform, env), ...declaredPath.slice(declaredDir.length + 1).split("/"));
3099
+ }
3100
+ return expandHome(declaredPath);
3101
+ }
3042
3102
  exports2.DEFAULT_PROFILE = "default";
3043
3103
  exports2.PROFILE_NAME = /^[a-z0-9][a-z0-9-]*$/;
3044
3104
  function resolveProfile(brand, explicit) {
@@ -3050,9 +3110,9 @@ var require_apply = __commonJS({
3050
3110
  return candidate;
3051
3111
  }
3052
3112
  function resolvePaths(brand, profile = exports2.DEFAULT_PROFILE) {
3053
- const base = expandHome(brand.paths.configDir);
3113
+ const base = brandConfigDir(brand);
3054
3114
  const configDir = profile === exports2.DEFAULT_PROFILE ? base : (0, path_1.join)(base, profile);
3055
- const auditFile = brand.audit?.path ? expandHome(brand.audit.path) : (0, path_1.join)(configDir, "audit.jsonl");
3115
+ const auditFile = brand.audit?.path ? resolveBrandPath(brand, brand.audit.path) : (0, path_1.join)(configDir, "audit.jsonl");
3056
3116
  return {
3057
3117
  profile,
3058
3118
  configDir,
@@ -3063,7 +3123,7 @@ var require_apply = __commonJS({
3063
3123
  }
3064
3124
  function runConfigSearchPaths(brand, profile) {
3065
3125
  if (profile === exports2.DEFAULT_PROFILE) {
3066
- return brand.paths.configSearchPaths ? [...brand.paths.configSearchPaths] : [];
3126
+ return brand.paths.configSearchPaths ? brand.paths.configSearchPaths.map((p) => resolveBrandPath(brand, p)) : [];
3067
3127
  }
3068
3128
  return [(0, path_1.join)(resolvePaths(brand, profile).configDir, `${brand.product.id}.yaml`)];
3069
3129
  }
@@ -10375,6 +10435,148 @@ var require_progress = __commonJS({
10375
10435
  }
10376
10436
  });
10377
10437
 
10438
+ // ../../packages/shuttle/dist/platform/launch.js
10439
+ var require_launch = __commonJS({
10440
+ "../../packages/shuttle/dist/platform/launch.js"(exports2) {
10441
+ "use strict";
10442
+ var __importDefault = exports2 && exports2.__importDefault || function(mod) {
10443
+ return mod && mod.__esModule ? mod : { "default": mod };
10444
+ };
10445
+ Object.defineProperty(exports2, "__esModule", { value: true });
10446
+ exports2.UnlaunchableError = void 0;
10447
+ exports2.findOnPath = findOnPath;
10448
+ exports2.pathExtensions = pathExtensions;
10449
+ exports2.resolveLaunch = resolveLaunch;
10450
+ exports2.npmShimTarget = npmShimTarget;
10451
+ var fs_1 = require("fs");
10452
+ var path_1 = __importDefault(require("path"));
10453
+ var UnlaunchableError = class extends Error {
10454
+ code = "EUNLAUNCHABLE";
10455
+ constructor(message) {
10456
+ super(message);
10457
+ this.name = "UnlaunchableError";
10458
+ }
10459
+ };
10460
+ exports2.UnlaunchableError = UnlaunchableError;
10461
+ var DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD";
10462
+ function findOnPath(bin, host = {}) {
10463
+ const platform = host.platform ?? process.platform;
10464
+ const env = host.env ?? process.env;
10465
+ const delimiter = platform === "win32" ? ";" : ":";
10466
+ const dirs = (env.PATH ?? env.Path ?? "").split(delimiter).filter(Boolean);
10467
+ const names = platform === "win32" ? [...path_1.default.extname(bin) ? [bin] : [], ...pathExtensions(env).map((ext) => `${bin}${ext}`)] : [bin];
10468
+ if (path_1.default.isAbsolute(bin))
10469
+ return names.find((name2) => isLaunchableFile(name2, platform)) ?? null;
10470
+ for (const dir of dirs) {
10471
+ for (const name2 of names) {
10472
+ const candidate = path_1.default.join(dir, name2);
10473
+ if (isLaunchableFile(candidate, platform))
10474
+ return candidate;
10475
+ }
10476
+ }
10477
+ return null;
10478
+ }
10479
+ function pathExtensions(env = process.env) {
10480
+ return (env.PATHEXT ?? DEFAULT_PATHEXT).split(";").map((ext) => ext.trim().toLowerCase()).filter((ext) => ext.startsWith("."));
10481
+ }
10482
+ function isLaunchableFile(candidate, platform) {
10483
+ try {
10484
+ if (!(0, fs_1.statSync)(candidate).isFile())
10485
+ return false;
10486
+ if (platform !== "win32")
10487
+ (0, fs_1.accessSync)(candidate, fs_1.constants.X_OK);
10488
+ return true;
10489
+ } catch {
10490
+ return false;
10491
+ }
10492
+ }
10493
+ function resolveLaunch(bin, args2, host = {}) {
10494
+ const platform = host.platform ?? process.platform;
10495
+ if (platform !== "win32")
10496
+ return { command: bin, args: args2 };
10497
+ const found = findOnPath(bin, host);
10498
+ if (found === null)
10499
+ return { command: bin, args: args2 };
10500
+ const ext = path_1.default.extname(found).toLowerCase();
10501
+ if (ext === ".exe" || ext === ".com")
10502
+ return { command: found, args: args2 };
10503
+ if (ext === ".cmd" || ext === ".bat") {
10504
+ const unwrapped = unwrapNpmShim(found, host);
10505
+ if (unwrapped !== null)
10506
+ return { command: unwrapped.command, args: [...unwrapped.args, ...args2] };
10507
+ throw new UnlaunchableError(`${found} is a batch file that is not an npm shim; it would have to run through cmd.exe, which a review's arguments must never reach. Install ${bin} as an .exe or with npm`);
10508
+ }
10509
+ throw new UnlaunchableError(`${found} is not a program Windows starts directly (${ext || "no extension"})`);
10510
+ }
10511
+ function unwrapNpmShim(shim, host) {
10512
+ let text;
10513
+ try {
10514
+ text = (0, fs_1.readFileSync)(shim, "utf8");
10515
+ } catch {
10516
+ return null;
10517
+ }
10518
+ const dir = path_1.default.dirname(shim);
10519
+ const target = npmShimTarget(text);
10520
+ let resolved = null;
10521
+ if (target !== null) {
10522
+ resolved = path_1.default.join(dir, ...target.split(/[\\/]/));
10523
+ } else if (/NPM_CLI_JS/.test(text)) {
10524
+ resolved = path_1.default.join(dir, "node_modules", "npm", "bin", "npm-cli.js");
10525
+ }
10526
+ if (resolved === null || !(0, fs_1.existsSync)(resolved))
10527
+ return null;
10528
+ const ext = path_1.default.extname(resolved).toLowerCase();
10529
+ if (ext === ".exe" || ext === ".com")
10530
+ return { command: resolved, args: [] };
10531
+ if (ext !== ".js" && ext !== ".cjs" && ext !== ".mjs" && ext !== "")
10532
+ return null;
10533
+ const besideShim = path_1.default.join(dir, "node.exe");
10534
+ const node = (0, fs_1.existsSync)(besideShim) ? besideShim : host.nodePath ?? process.execPath;
10535
+ return { command: node, args: [resolved] };
10536
+ }
10537
+ function npmShimTarget(cmdText) {
10538
+ const match = /"%~?dp0%?\\([^"]+)"\s+%\*/.exec(cmdText);
10539
+ if (!match)
10540
+ return null;
10541
+ const target = match[1];
10542
+ if (/[%!^&|<>]/.test(target))
10543
+ return null;
10544
+ return target;
10545
+ }
10546
+ }
10547
+ });
10548
+
10549
+ // ../../packages/shuttle/dist/platform/terminate.js
10550
+ var require_terminate = __commonJS({
10551
+ "../../packages/shuttle/dist/platform/terminate.js"(exports2) {
10552
+ "use strict";
10553
+ var __importDefault = exports2 && exports2.__importDefault || function(mod) {
10554
+ return mod && mod.__esModule ? mod : { "default": mod };
10555
+ };
10556
+ Object.defineProperty(exports2, "__esModule", { value: true });
10557
+ exports2.terminate = terminate;
10558
+ exports2.taskkillPath = taskkillPath;
10559
+ var child_process_1 = require("child_process");
10560
+ var path_1 = __importDefault(require("path"));
10561
+ function terminate(child, signal = "SIGTERM", platform = process.platform) {
10562
+ if (platform !== "win32") {
10563
+ child.kill(signal);
10564
+ return;
10565
+ }
10566
+ if (child.pid === void 0 || child.exitCode !== null)
10567
+ return;
10568
+ const killer = (0, child_process_1.spawn)(taskkillPath(), ["/pid", String(child.pid), "/T", "/F"], {
10569
+ stdio: "ignore",
10570
+ windowsHide: true
10571
+ });
10572
+ killer.on("error", () => child.kill());
10573
+ }
10574
+ function taskkillPath(env = process.env) {
10575
+ return path_1.default.win32.join(env.SystemRoot ?? env.SYSTEMROOT ?? "C:\\Windows", "System32", "taskkill.exe");
10576
+ }
10577
+ }
10578
+ });
10579
+
10378
10580
  // ../../packages/shuttle/dist/executors/agent-process.js
10379
10581
  var require_agent_process = __commonJS({
10380
10582
  "../../packages/shuttle/dist/executors/agent-process.js"(exports2) {
@@ -10395,12 +10597,15 @@ var require_agent_process = __commonJS({
10395
10597
  var fs_1 = require("fs");
10396
10598
  var path_1 = __importDefault(require("path"));
10397
10599
  var string_decoder_1 = require("string_decoder");
10600
+ var launch_1 = require_launch();
10601
+ var terminate_1 = require_terminate();
10398
10602
  exports2.STDERR_LIMIT = 4e3;
10399
10603
  function runAgentProcess(opts) {
10400
10604
  return new Promise((resolve, reject) => {
10401
10605
  let child;
10402
10606
  try {
10403
- child = (0, child_process_1.spawn)(opts.bin, opts.args, {
10607
+ const launch = (0, launch_1.resolveLaunch)(opts.bin, opts.args, opts.env ? { env: opts.env } : {});
10608
+ child = (0, child_process_1.spawn)(launch.command, launch.args, {
10404
10609
  cwd: opts.cwd,
10405
10610
  stdio: ["pipe", "pipe", "pipe"],
10406
10611
  ...opts.env ? { env: opts.env } : {}
@@ -10425,11 +10630,11 @@ var require_agent_process = __commonJS({
10425
10630
  fn();
10426
10631
  };
10427
10632
  function onAbort() {
10428
- child.kill("SIGTERM");
10633
+ (0, terminate_1.terminate)(child);
10429
10634
  finish(() => reject(new Error("Dispatch aborted")));
10430
10635
  }
10431
10636
  if (opts.signal.aborted) {
10432
- child.kill("SIGTERM");
10637
+ (0, terminate_1.terminate)(child);
10433
10638
  finish(() => reject(new Error("Dispatch aborted")));
10434
10639
  return;
10435
10640
  }
@@ -10440,7 +10645,7 @@ var require_agent_process = __commonJS({
10440
10645
  if (timer)
10441
10646
  clearTimeout(timer);
10442
10647
  timer = setTimeout(() => {
10443
- child.kill("SIGTERM");
10648
+ (0, terminate_1.terminate)(child);
10444
10649
  finish(() => reject(new Error(`${opts.toolName} produced no output for ${opts.idleTimeoutMs}ms; killed as hung`)));
10445
10650
  }, opts.idleTimeoutMs);
10446
10651
  };
@@ -10494,7 +10699,7 @@ var require_agent_process = __commonJS({
10494
10699
  }
10495
10700
  }
10496
10701
  function classifyAgentFault(failure, vocab) {
10497
- if (failure.spawnErrorCode === "ENOENT")
10702
+ if (failure.spawnErrorCode === "ENOENT" || failure.spawnErrorCode === "EUNLAUNCHABLE")
10498
10703
  return vocab.installRemedy;
10499
10704
  const text = failure.text ?? "";
10500
10705
  if (failure.apiErrorStatus === 401 || vocab.signedOut.test(text))
@@ -10695,6 +10900,18 @@ var require_workspace_telemetry = __commonJS({
10695
10900
  }
10696
10901
  return roots;
10697
10902
  }
10903
+ function insideRoot(resolved, root) {
10904
+ const fold = (s) => process.platform === "win32" ? s.toLowerCase() : s;
10905
+ if (!fold(resolved).startsWith(fold(root + path_1.default.sep)))
10906
+ return null;
10907
+ return resolved.slice(root.length + 1).split(path_1.default.sep).join("/");
10908
+ }
10909
+ function stripRoots(input, roots) {
10910
+ if (process.platform !== "win32")
10911
+ return roots.reduce((s, r) => s.split(`${r}/`).join(""), input);
10912
+ const slashed = input.replaceAll("\\\\", "/");
10913
+ return roots.reduce((s, r) => s.replace(new RegExp(`${escapeRegExp(r.split(path_1.default.sep).join("/"))}/`, "gi"), ""), slashed);
10914
+ }
10698
10915
  function relativeWorkspaceReads(readPaths, cwd) {
10699
10916
  const roots = workspaceRoots(cwd);
10700
10917
  const root = roots[0];
@@ -10702,11 +10919,10 @@ var require_workspace_telemetry = __commonJS({
10702
10919
  for (const p of readPaths) {
10703
10920
  const resolved = path_1.default.resolve(root, p);
10704
10921
  for (const r of roots) {
10705
- if (resolved === r)
10706
- break;
10707
- if (!resolved.startsWith(r + path_1.default.sep))
10922
+ const rel = insideRoot(resolved, r);
10923
+ if (rel === null)
10708
10924
  continue;
10709
- out2.add(resolved.slice(r.length + 1));
10925
+ out2.add(rel);
10710
10926
  break;
10711
10927
  }
10712
10928
  if (out2.size >= MAX_REPORTED_READS)
@@ -10770,10 +10986,10 @@ var require_workspace_telemetry = __commonJS({
10770
10986
  const dirAlt = [...dirs].map(escapeRegExp).join("|");
10771
10987
  const wordRe = dirs.size > 0 ? new RegExp(`(?:${dirAlt})[^\\s"'\`;|&<>()\\\\]*`, "g") : null;
10772
10988
  const findRe = dirs.size > 0 ? new RegExp(`\\bfind\\s+(?:\\./)?(${[...dirs].map((d) => escapeRegExp(d.slice(0, -1))).join("|")})/?(?=\\s|$)`, "g") : null;
10773
- const readerRe = new RegExp(`(?:^|[\\s"])(?:-exec|-execdir|xargs)\\b[^;|&]*\\b${READERS}\\b`);
10989
+ const readerRe = new RegExp(`(?:^|[\\s"])(?:-exec|-execdir|xargs)\\b[^;|&]*\\b${READERS}\\b`, READER_FLAGS);
10774
10990
  const credited = /* @__PURE__ */ new Set();
10775
10991
  for (const raw of toolInputs) {
10776
- const input = roots.reduce((s, r) => s.split(`${r}/`).join(""), raw);
10992
+ const input = stripRoots(raw, roots);
10777
10993
  for (const rel of writtenPaths) {
10778
10994
  if (input.includes(rel))
10779
10995
  credited.add(rel);
@@ -10816,8 +11032,9 @@ var require_workspace_telemetry = __commonJS({
10816
11032
  }
10817
11033
  return [...credited].sort();
10818
11034
  }
10819
- var READERS = "(?:cat|head|tail|sed|awk|less|more|bat)";
10820
- var PLAIN_READER_RE = new RegExp(`(?:^|[\\s"'\`;|&(])${READERS}\\b`);
11035
+ var READERS = process.platform === "win32" ? "(?:cat|head|tail|sed|awk|less|more|bat|Get-Content|gc|type)" : "(?:cat|head|tail|sed|awk|less|more|bat)";
11036
+ var READER_FLAGS = process.platform === "win32" ? "i" : "";
11037
+ var PLAIN_READER_RE = new RegExp(`(?:^|[\\s"'\`;|&(])${READERS}\\b`, READER_FLAGS);
10821
11038
  var CD_RE = /(?:^|[\s"'`;|&(])cd\s+(?:--\s+)?["']?([^\s"'`;|&<>()\\]+)/g;
10822
11039
  function namesBareWord(input, word) {
10823
11040
  const edge = String.raw`[\s"'\`;|&<>(),\\]`;
@@ -10833,8 +11050,8 @@ var require_workspace_telemetry = __commonJS({
10833
11050
  const word = raw.replace(/^\.\//, "");
10834
11051
  if (word.length === 0 || word.startsWith("-") || GLOB_CHARS.test(word))
10835
11052
  continue;
10836
- const abs = path_1.default.resolve(roots[0], roots.reduce((w, r) => w.startsWith(`${r}/`) ? w.slice(r.length + 1) : w, word));
10837
- if (!roots.some((r) => abs.startsWith(r + path_1.default.sep)))
11053
+ const abs = path_1.default.resolve(roots[0], roots.reduce((w, r) => w.startsWith(`${r}/`) || w.startsWith(`${r}${path_1.default.sep}`) ? w.slice(r.length + 1) : w, word));
11054
+ if (!roots.some((r) => insideRoot(abs, r) !== null))
10838
11055
  continue;
10839
11056
  try {
10840
11057
  if ((0, fs_1.statSync)(abs).isFile())
@@ -10877,11 +11094,13 @@ var require_cli_version = __commonJS({
10877
11094
  Object.defineProperty(exports2, "__esModule", { value: true });
10878
11095
  exports2.cliVersion = cliVersion;
10879
11096
  var child_process_1 = require("child_process");
11097
+ var launch_1 = require_launch();
10880
11098
  var VERSION_TIMEOUT_MS = 5e3;
10881
11099
  function cliVersion(bin, env) {
10882
11100
  return new Promise((resolve) => {
10883
11101
  try {
10884
- (0, child_process_1.execFile)(bin, ["--version"], { timeout: VERSION_TIMEOUT_MS, ...env ? { env } : {} }, (err2, stdout) => {
11102
+ const launch = (0, launch_1.resolveLaunch)(bin, ["--version"], env ? { env } : {});
11103
+ (0, child_process_1.execFile)(launch.command, launch.args, { timeout: VERSION_TIMEOUT_MS, ...env ? { env } : {} }, (err2, stdout) => {
10885
11104
  resolve(err2 ? null : String(stdout).match(/\d+\.\d+\.\d+/)?.[0] ?? null);
10886
11105
  });
10887
11106
  } catch {
@@ -56610,6 +56829,78 @@ data:
56610
56829
  }
56611
56830
  });
56612
56831
 
56832
+ // ../../packages/shuttle/dist/platform/private-file.js
56833
+ var require_private_file = __commonJS({
56834
+ "../../packages/shuttle/dist/platform/private-file.js"(exports2) {
56835
+ "use strict";
56836
+ var __importDefault = exports2 && exports2.__importDefault || function(mod) {
56837
+ return mod && mod.__esModule ? mod : { "default": mod };
56838
+ };
56839
+ Object.defineProperty(exports2, "__esModule", { value: true });
56840
+ exports2.restrictToOwner = restrictToOwner;
56841
+ exports2.othersWithAccess = othersWithAccess;
56842
+ var child_process_1 = require("child_process");
56843
+ var fs_1 = require("fs");
56844
+ var path_1 = __importDefault(require("path"));
56845
+ var SYSTEM_SID = "S-1-5-18";
56846
+ var ADMINISTRATORS_SID = "S-1-5-32-544";
56847
+ async function restrictToOwner(target, platform = process.platform) {
56848
+ const isDirectory = (await fs_1.promises.stat(target)).isDirectory();
56849
+ if (platform !== "win32") {
56850
+ await fs_1.promises.chmod(target, isDirectory ? 448 : 384);
56851
+ return;
56852
+ }
56853
+ const user = await currentUserSid();
56854
+ const inherit = isDirectory ? "(OI)(CI)" : "";
56855
+ await run2(system32("icacls.exe"), [
56856
+ target,
56857
+ "/inheritance:r",
56858
+ "/grant:r",
56859
+ `*${user}:${inherit}F`,
56860
+ `*${SYSTEM_SID}:${inherit}F`
56861
+ ]);
56862
+ }
56863
+ async function othersWithAccess(file) {
56864
+ try {
56865
+ const user = await currentUserSid();
56866
+ const env = Object.fromEntries(Object.entries(process.env).filter(([key]) => key.toUpperCase() !== "PSMODULEPATH"));
56867
+ const stdout = await run2(system32("WindowsPowerShell", "v1.0", "powershell.exe"), [
56868
+ "-NoProfile",
56869
+ "-NonInteractive",
56870
+ "-Command",
56871
+ "(Get-Acl -LiteralPath $env:SHUTTLE_ACL_TARGET).Access | ForEach-Object { $_.IdentityReference.Translate([Security.Principal.SecurityIdentifier]).Value }"
56872
+ ], { ...env, SHUTTLE_ACL_TARGET: file });
56873
+ const allowed = /* @__PURE__ */ new Set([user, SYSTEM_SID, ADMINISTRATORS_SID]);
56874
+ return {
56875
+ others: [...new Set(stdout.split(/\r?\n/).map((l) => l.trim()).filter((sid) => sid.length > 0 && !allowed.has(sid)))]
56876
+ };
56877
+ } catch (err2) {
56878
+ return { unreadable: err2 instanceof Error ? err2.message : String(err2) };
56879
+ }
56880
+ }
56881
+ async function currentUserSid() {
56882
+ const stdout = await run2(system32("whoami.exe"), ["/user", "/fo", "csv", "/nh"]);
56883
+ const sid = /"(S-1-[0-9-]+)"/.exec(stdout)?.[1];
56884
+ if (!sid)
56885
+ throw new Error(`whoami did not report this user's SID: ${stdout.trim().slice(0, 200)}`);
56886
+ return sid;
56887
+ }
56888
+ function system32(...parts2) {
56889
+ return path_1.default.win32.join(process.env.SystemRoot ?? process.env.SYSTEMROOT ?? "C:\\Windows", "System32", ...parts2);
56890
+ }
56891
+ function run2(file, args2, env) {
56892
+ return new Promise((resolve, reject) => {
56893
+ (0, child_process_1.execFile)(file, args2, { windowsHide: true, timeout: 15e3, ...env ? { env } : {} }, (err2, stdout, stderr) => {
56894
+ if (err2)
56895
+ reject(new Error(`${path_1.default.win32.basename(file)} failed: ${String(stderr).trim() || err2.message}`));
56896
+ else
56897
+ resolve(String(stdout));
56898
+ });
56899
+ });
56900
+ }
56901
+ }
56902
+ });
56903
+
56613
56904
  // ../../packages/shuttle/dist/toolsets/server.js
56614
56905
  var require_server = __commonJS({
56615
56906
  "../../packages/shuttle/dist/toolsets/server.js"(exports2) {
@@ -56628,6 +56919,7 @@ var require_server = __commonJS({
56628
56919
  var node_path_1 = __importDefault(require("node:path"));
56629
56920
  var node_stream_1 = require("node:stream");
56630
56921
  var server_1 = require_dist3();
56922
+ var private_file_1 = require_private_file();
56631
56923
  async function serveToolSet(name2, toolNames, build) {
56632
56924
  const handler = (0, server_1.createMcpHandler)(build, { legacy: "stateless" });
56633
56925
  const token = node_crypto_1.default.randomBytes(32).toString("base64url");
@@ -56667,6 +56959,7 @@ var require_server = __commonJS({
56667
56959
  let configDir = null;
56668
56960
  try {
56669
56961
  configDir = await node_fs_1.promises.mkdtemp(node_path_1.default.join(node_os_1.default.tmpdir(), "shuttle-mcp-"));
56962
+ await (0, private_file_1.restrictToOwner)(configDir);
56670
56963
  const mcpConfigPath = node_path_1.default.join(configDir, "mcp.json");
56671
56964
  const mcpServers = Object.fromEntries(sets.map((s) => [s.name, { type: "http", url: s.url, headers: { Authorization: `Bearer ${s.token}` } }]));
56672
56965
  await node_fs_1.promises.writeFile(mcpConfigPath, JSON.stringify({ mcpServers }), { mode: 384, flag: "wx" });
@@ -56805,6 +57098,27 @@ ${items.map(render).join("\n")}`;
56805
57098
  }
56806
57099
  });
56807
57100
 
57101
+ // ../../packages/shuttle/dist/platform/no-follow.js
57102
+ var require_no_follow = __commonJS({
57103
+ "../../packages/shuttle/dist/platform/no-follow.js"(exports2) {
57104
+ "use strict";
57105
+ Object.defineProperty(exports2, "__esModule", { value: true });
57106
+ exports2.writeFileNoFollow = writeFileNoFollow;
57107
+ var fs_1 = require("fs");
57108
+ async function writeFileNoFollow(file, content) {
57109
+ if (fs_1.constants.O_NOFOLLOW === void 0 && (await fs_1.promises.lstat(file).catch(() => null))?.isSymbolicLink()) {
57110
+ throw new Error(`${file} is a symlink; refusing to write through it`);
57111
+ }
57112
+ const handle2 = await fs_1.promises.open(file, fs_1.constants.O_WRONLY | fs_1.constants.O_CREAT | fs_1.constants.O_TRUNC | (fs_1.constants.O_NOFOLLOW ?? 0), 420);
57113
+ try {
57114
+ await handle2.writeFile(content);
57115
+ } finally {
57116
+ await handle2.close();
57117
+ }
57118
+ }
57119
+ }
57120
+ });
57121
+
56808
57122
  // ../../packages/shuttle/dist/workspace/overlay.js
56809
57123
  var require_overlay = __commonJS({
56810
57124
  "../../packages/shuttle/dist/workspace/overlay.js"(exports2) {
@@ -56819,6 +57133,7 @@ var require_overlay = __commonJS({
56819
57133
  exports2.fetchCapped = fetchCapped;
56820
57134
  var fs_1 = require("fs");
56821
57135
  var path_1 = __importDefault(require("path"));
57136
+ var no_follow_1 = require_no_follow();
56822
57137
  var DEFAULT_TIMEOUT_MS = 3e4;
56823
57138
  var DEFAULT_MAX_BYTES = 5 * 1024 * 1024;
56824
57139
  exports2.overlayModifier = {
@@ -56868,12 +57183,7 @@ var require_overlay = __commonJS({
56868
57183
  skip("destination parent escapes the workspace root");
56869
57184
  continue;
56870
57185
  }
56871
- const handle2 = await fs_1.promises.open(dest, fs_1.constants.O_WRONLY | fs_1.constants.O_CREAT | fs_1.constants.O_TRUNC | fs_1.constants.O_NOFOLLOW, 420);
56872
- try {
56873
- await handle2.writeFile(content);
56874
- } finally {
56875
- await handle2.close();
56876
- }
57186
+ await (0, no_follow_1.writeFileNoFollow)(dest, content);
56877
57187
  result.written += 1;
56878
57188
  result.writtenPaths.push(file.path);
56879
57189
  } catch (err2) {
@@ -57967,6 +58277,7 @@ var require_codex = __commonJS({
57967
58277
  var strict_schema_1 = require_strict_schema();
57968
58278
  var workspace_telemetry_1 = require_workspace_telemetry();
57969
58279
  var apply_1 = require_apply();
58280
+ var launch_1 = require_launch();
57970
58281
  var CODEX_PROFILE = "sift-review";
57971
58282
  function reviewProfile(installDir, platform = process.platform, outputDir) {
57972
58283
  const rules = ['":root"="deny"', '":minimal"="read"', '":workspace_roots"="read"', `${JSON.stringify(installDir)}="read"`];
@@ -57982,7 +58293,9 @@ var require_codex = __commonJS({
57982
58293
  function codexHome() {
57983
58294
  return process.env.CODEX_HOME ?? path_1.default.join(os_1.default.homedir(), ".codex");
57984
58295
  }
57985
- function resolveCodex(pathEnv = process.env.PATH ?? "") {
58296
+ function resolveCodex(pathEnv = process.env.PATH ?? "", platform = process.platform) {
58297
+ if (platform === "win32")
58298
+ return resolveCodexOnWindows(pathEnv);
57986
58299
  for (const dir of pathEnv.split(path_1.default.delimiter)) {
57987
58300
  if (!dir)
57988
58301
  continue;
@@ -58000,6 +58313,20 @@ var require_codex = __commonJS({
58000
58313
  }
58001
58314
  return null;
58002
58315
  }
58316
+ function resolveCodexOnWindows(pathEnv) {
58317
+ let launch;
58318
+ try {
58319
+ launch = (0, launch_1.resolveLaunch)("codex", [], { platform: "win32", env: { ...process.env, PATH: pathEnv } });
58320
+ } catch {
58321
+ return null;
58322
+ }
58323
+ const script = launch.args[0];
58324
+ if (script !== void 0)
58325
+ return { bin: "codex", installDir: path_1.default.dirname(path_1.default.dirname(script)) };
58326
+ if (!path_1.default.isAbsolute(launch.command))
58327
+ return null;
58328
+ return { bin: launch.command, installDir: path_1.default.dirname(launch.command) };
58329
+ }
58003
58330
  var DISABLED_FEATURES = [
58004
58331
  "hooks",
58005
58332
  "apps",
@@ -58032,6 +58359,7 @@ var require_codex = __commonJS({
58032
58359
  reviewProfile(installDir, platform, outputDir),
58033
58360
  "-c",
58034
58361
  `default_permissions="${CODEX_PROFILE}"`,
58362
+ ...platform === "win32" ? ["-c", 'windows.sandbox="unelevated"'] : [],
58035
58363
  "-c",
58036
58364
  'approval_policy="never"',
58037
58365
  "-c",
@@ -58437,6 +58765,7 @@ var require_copilot = __commonJS({
58437
58765
  Object.defineProperty(exports2, "__esModule", { value: true });
58438
58766
  exports2.copilotReviewArgs = copilotReviewArgs;
58439
58767
  exports2.withSchema = withSchema;
58768
+ exports2.withoutRealGh = withoutRealGh;
58440
58769
  exports2.usageOf = usageOf;
58441
58770
  exports2.parseCopilotEvents = parseCopilotEvents;
58442
58771
  exports2.parseCopilotModels = parseCopilotModels;
@@ -58457,6 +58786,7 @@ var require_copilot = __commonJS({
58457
58786
  var cli_version_1 = require_cli_version();
58458
58787
  var version_check_1 = require_version_check();
58459
58788
  var apply_1 = require_apply();
58789
+ var private_file_1 = require_private_file();
58460
58790
  var REVIEW_TOOLS = ["view", "grep", "glob"];
58461
58791
  var DENIED_TOOLS = ["shell", "write"];
58462
58792
  function copilotReviewArgs(version, outputDir) {
@@ -58765,13 +59095,17 @@ ${JSON.stringify(spec.outputSchema)}
58765
59095
  async function makeRunHome(scratch) {
58766
59096
  const home = path_1.default.join(scratch, "copilot-home");
58767
59097
  await fs_1.promises.mkdir(home, { mode: 448 });
59098
+ if (process.platform === "win32")
59099
+ await (0, private_file_1.restrictToOwner)(home);
58768
59100
  await fs_1.promises.writeFile(path_1.default.join(home, "settings.json"), JSON.stringify(RUN_SETTINGS));
58769
59101
  const bin = path_1.default.join(scratch, "bin");
58770
59102
  await fs_1.promises.mkdir(bin, { recursive: true });
58771
59103
  await fs_1.promises.writeFile(path_1.default.join(bin, "gh"), REFUSING_GH, { mode: 493 });
59104
+ await fs_1.promises.writeFile(path_1.default.join(bin, "gh.cmd"), REFUSING_GH_CMD);
58772
59105
  return home;
58773
59106
  }
58774
59107
  var REFUSING_GH = '#!/bin/sh\necho "gh is not available to a Sifter review" >&2\nexit 1\n';
59108
+ var REFUSING_GH_CMD = "@echo gh is not available to a Sifter review 1>&2\r\n@exit /b 1\r\n";
58775
59109
  var LOGIN_POINTER_KEYS = ["lastLoggedInUser", "loggedInUsers"];
58776
59110
  var LOGIN_TOKEN_KEYS = ["authTokens"];
58777
59111
  async function withOperatorLogin(home, fn) {
@@ -58819,12 +59153,20 @@ ${JSON.stringify(spec.outputSchema)}
58819
59153
  }
58820
59154
  function runEnv(home) {
58821
59155
  const bin = path_1.default.join(path_1.default.dirname(home), "bin");
58822
- return {
59156
+ const ambient = process.env.PATH ?? process.env.Path ?? "";
59157
+ const searched = process.platform === "win32" ? withoutRealGh(ambient) : ambient;
59158
+ const env = {
58823
59159
  ...process.env,
58824
- PATH: `${bin}${path_1.default.delimiter}${process.env.PATH ?? ""}`,
59160
+ PATH: `${bin}${path_1.default.delimiter}${searched}`,
58825
59161
  COPILOT_HOME: home,
58826
59162
  COPILOT_AUTO_UPDATE: "false"
58827
59163
  };
59164
+ if (process.platform === "win32" && "Path" in env)
59165
+ delete env.Path;
59166
+ return env;
59167
+ }
59168
+ function withoutRealGh(pathValue) {
59169
+ return pathValue.split(path_1.default.win32.delimiter).filter((dir) => dir.length > 0 && !["gh.exe", "gh.com"].some((name2) => (0, fs_1.existsSync)(path_1.default.join(dir, name2)))).join(path_1.default.win32.delimiter);
58828
59170
  }
58829
59171
  async function readUsage(file) {
58830
59172
  try {
@@ -59427,7 +59769,10 @@ var require_exchange = __commonJS({
59427
59769
  transport: async (url, init2) => {
59428
59770
  let response;
59429
59771
  try {
59430
- response = await fetch(url, init2);
59772
+ const headers = new Headers(init2?.headers);
59773
+ if (request.apiVersion)
59774
+ headers.set("Whittle-Version", request.apiVersion);
59775
+ response = await fetch(url, { ...init2, headers });
59431
59776
  } catch (err2) {
59432
59777
  return raise(new KeepUnavailableError(`[${manager}] could not reach Keep at ${host}: ${describeTransportError(err2)}`, {
59433
59778
  host,
@@ -59772,12 +60117,14 @@ var require_agent_token = __commonJS({
59772
60117
  clientId;
59773
60118
  clientSecret;
59774
60119
  enabled;
60120
+ apiVersion;
59775
60121
  onResponse;
59776
60122
  constructor(config) {
59777
60123
  this.keepApiUrl = config.keepApiUrl.replace(/\/$/, "");
59778
60124
  this.clientId = config.clientId;
59779
60125
  this.clientSecret = config.clientSecret;
59780
60126
  this.enabled = !!(config.clientId && config.clientSecret && config.keepApiUrl);
60127
+ this.apiVersion = config.apiVersion;
59781
60128
  this.onResponse = config.onResponse;
59782
60129
  }
59783
60130
  async getToken(forceRefresh = false) {
@@ -59803,6 +60150,7 @@ var require_agent_token = __commonJS({
59803
60150
  keepApiUrl: this.keepApiUrl,
59804
60151
  send: (api) => api.post("/api/agent-tokens", { body: { clientId: this.clientId, clientSecret: this.clientSecret } }),
59805
60152
  rateLimit: this.rateLimit,
60153
+ apiVersion: this.apiVersion,
59806
60154
  onResponse: this.onResponse,
59807
60155
  exchangeName: "Agent token exchange",
59808
60156
  refused: () => new AgentCredentialRevokedError2(`[AgentTokenManager] Keep refused this agent's credentials (401): the pairing was revoked or the secret rotated. Re-pair to continue.`)
@@ -60282,6 +60630,7 @@ var require_custom_script = __commonJS({
60282
60630
  var child_process_1 = require("child_process");
60283
60631
  var loom_1 = require_dist();
60284
60632
  var validate_output_1 = require_validate_output();
60633
+ var terminate_1 = require_terminate();
60285
60634
  var DEFAULT_TIMEOUT = 3e4;
60286
60635
  var CustomScriptExecutor = class {
60287
60636
  capability;
@@ -60331,16 +60680,16 @@ var require_custom_script = __commonJS({
60331
60680
  child.stdin.write(JSON.stringify(request));
60332
60681
  child.stdin.end();
60333
60682
  const timer = setTimeout(() => {
60334
- child.kill("SIGTERM");
60683
+ (0, terminate_1.terminate)(child);
60335
60684
  settle(() => reject(new Error(`Custom script timed out after ${this.config.timeout}ms`)));
60336
60685
  }, this.config.timeout);
60337
60686
  function onAbort() {
60338
- child.kill("SIGTERM");
60687
+ (0, terminate_1.terminate)(child);
60339
60688
  settle(() => reject(new Error("Dispatch aborted")));
60340
60689
  }
60341
60690
  if (signal.aborted) {
60342
60691
  clearTimeout(timer);
60343
- child.kill("SIGTERM");
60692
+ (0, terminate_1.terminate)(child);
60344
60693
  settle(() => reject(new Error("Dispatch aborted")));
60345
60694
  return;
60346
60695
  }
@@ -67909,6 +68258,7 @@ var require_store = __commonJS({
67909
68258
  var fs2 = __importStar(require("fs"));
67910
68259
  var fsp = __importStar(require("fs/promises"));
67911
68260
  var path_1 = require("path");
68261
+ var private_file_1 = require_private_file();
67912
68262
  var PairingConfigStore = class {
67913
68263
  path;
67914
68264
  constructor(path) {
@@ -67933,13 +68283,14 @@ var require_store = __commonJS({
67933
68283
  const tmp = `${this.path}.tmp`;
67934
68284
  const fd = await fsp.open(tmp, "w", 384);
67935
68285
  try {
68286
+ await (0, private_file_1.restrictToOwner)(tmp);
67936
68287
  await fd.write(JSON.stringify(config, null, 2));
67937
68288
  await fd.sync();
67938
68289
  } finally {
67939
68290
  await fd.close();
67940
68291
  }
67941
68292
  await fsp.rename(tmp, this.path);
67942
- await fsp.chmod(this.path, 384);
68293
+ await (0, private_file_1.restrictToOwner)(this.path);
67943
68294
  }
67944
68295
  /** Forget the pairing: `revoke` of this machine, whose credential is dead. */
67945
68296
  async remove() {
@@ -68043,7 +68394,7 @@ var require_checks3 = __commonJS({
68043
68394
  var apply_1 = require_apply();
68044
68395
  var environment_1 = require_environment();
68045
68396
  var scaffold_1 = require_scaffold();
68046
- var NODE_FLOOR = "20.0.0";
68397
+ var NODE_FLOOR = "22.0.0";
68047
68398
  var DISK_FLOOR_BYTES = 1024 * 1024 * 1024;
68048
68399
  var AGENTS = [
68049
68400
  { executor: "claude-code", bin: "claude", install: "install Claude Code (npm install -g @anthropic-ai/claude-code)" },
@@ -68163,16 +68514,12 @@ var require_checks3 = __commonJS({
68163
68514
  var platformSupported = {
68164
68515
  name: "platform-supported",
68165
68516
  phases: ["init", "run", "doctor"],
68166
- prerequisite: true,
68167
- async run(probes, subject) {
68517
+ async run(probes) {
68168
68518
  const platform = probes.platform();
68169
- if (platform === "win32") {
68170
- return fail("platform-supported", "native Windows is not supported", `install WSL (https://learn.microsoft.com/windows/wsl/install), then install and run ${subject.brand.product.cliBinary} inside it`);
68171
- }
68172
68519
  return pass("platform-supported", PLATFORM_NAMES[platform] ?? platform);
68173
68520
  }
68174
68521
  };
68175
- var PLATFORM_NAMES = { darwin: "macOS", linux: "Linux" };
68522
+ var PLATFORM_NAMES = { darwin: "macOS", linux: "Linux", win32: "Windows" };
68176
68523
  var nodeVersion = {
68177
68524
  name: "node-version",
68178
68525
  phases: ["init", "run", "doctor"],
@@ -68195,6 +68542,16 @@ var require_checks3 = __commonJS({
68195
68542
  if (result.value === null) {
68196
68543
  return fail("pairing-present", `no pairing at ${subject.paths.configFile}`, pairElsewhereRemedy(probes, subject) ?? `run \`${subject.brand.product.cliBinary} init\` to pair`);
68197
68544
  }
68545
+ if (probes.platform() === "win32") {
68546
+ const acl = await probes.othersWithAccess(subject.paths.configFile);
68547
+ if ("unreadable" in acl) {
68548
+ return warn("pairing-present", `paired, but who else can read ${subject.paths.configFile} could not be determined (${acl.unreadable}), and it holds a bearer secret`, `in PowerShell: icacls "${subject.paths.configFile}" /inheritance:r /grant:r "$env:USERNAME:F"`);
68549
+ }
68550
+ if (acl.others.length > 0) {
68551
+ return warn("pairing-present", `paired, but ${subject.paths.configFile} holds a bearer secret and its ACL also grants ${acl.others.join(", ")}`, `in PowerShell: icacls "${subject.paths.configFile}" /inheritance:r /grant:r "$env:USERNAME:F"`);
68552
+ }
68553
+ return pass("pairing-present", `paired as ${result.value.serviceIdentity.displayName}`);
68554
+ }
68198
68555
  const mode = await probes.stat(subject.paths.configFile);
68199
68556
  if (mode !== null && (mode.mode & 63) !== 0) {
68200
68557
  return warn("pairing-present", `paired, but ${subject.paths.configFile} is mode ${mode.mode.toString(8).padStart(4, "0")} and holds a bearer secret`, `chmod 600 ${subject.paths.configFile}`);
@@ -68790,12 +69147,14 @@ var require_client3 = __commonJS({
68790
69147
  apiKey;
68791
69148
  accessToken;
68792
69149
  getAccessToken;
69150
+ apiVersion;
68793
69151
  onResponse;
68794
69152
  constructor(config) {
68795
69153
  this.baseUrl = config.baseUrl.replace(/\/$/, "");
68796
69154
  this.apiKey = config.apiKey;
68797
69155
  this.accessToken = config.accessToken;
68798
69156
  this.getAccessToken = config.getAccessToken;
69157
+ this.apiVersion = config.apiVersion;
68799
69158
  this.onResponse = config.onResponse;
68800
69159
  }
68801
69160
  /**
@@ -68806,6 +69165,8 @@ var require_client3 = __commonJS({
68806
69165
  */
68807
69166
  async buildHeaders(forceRefresh = false) {
68808
69167
  const headers = { "Content-Type": "application/json" };
69168
+ if (this.apiVersion)
69169
+ headers["Whittle-Version"] = this.apiVersion;
68809
69170
  if (this.apiKey) {
68810
69171
  headers["X-API-Key"] = this.apiKey;
68811
69172
  } else if (this.getAccessToken) {
@@ -70128,12 +70489,8 @@ var require_loader = __commonJS({
70128
70489
  }
70129
70490
  }
70130
70491
  function defaultSearchPaths(productId) {
70131
- return [
70132
- (0, path_1.resolve)("shuttle.yaml"),
70133
- (0, path_1.resolve)(`${productId}.yaml`),
70134
- (0, path_1.join)((0, os_1.homedir)(), ".config", "whittle-labs", `${productId}.yaml`),
70135
- (0, path_1.join)((0, os_1.homedir)(), ".config", "whittle-labs", "shuttle.yaml")
70136
- ];
70492
+ const shared = process.platform === "win32" ? (0, path_1.join)((0, apply_1.windowsLocalAppData)(), "whittle-labs") : (0, path_1.join)((0, os_1.homedir)(), ".config", "whittle-labs");
70493
+ return [(0, path_1.resolve)("shuttle.yaml"), (0, path_1.resolve)(`${productId}.yaml`), (0, path_1.join)(shared, `${productId}.yaml`), (0, path_1.join)(shared, "shuttle.yaml")];
70137
70494
  }
70138
70495
  function resolveConfigPath(opts) {
70139
70496
  if (opts.explicitPath) {
@@ -70233,6 +70590,9 @@ var require_probes = __commonJS({
70233
70590
  var codex_1 = require_codex();
70234
70591
  var copilot_1 = require_copilot();
70235
70592
  var store_1 = require_store();
70593
+ var launch_1 = require_launch();
70594
+ var private_file_1 = require_private_file();
70595
+ var terminate_1 = require_terminate();
70236
70596
  var version_check_1 = require_version_check();
70237
70597
  var PROBE_TIMEOUT_MS = 1e4;
70238
70598
  var VERSION_TIMEOUT_MS = 1e4;
@@ -70263,6 +70623,7 @@ var require_probes = __commonJS({
70263
70623
  keepApiUrl: pairing.keepApiUrl,
70264
70624
  clientId: pairing.credentials.clientId,
70265
70625
  clientSecret: pairing.credentials.clientSecret,
70626
+ apiVersion: options.brand.apiVersion,
70266
70627
  onResponse: enforceFloor
70267
70628
  });
70268
70629
  managers.set(key, tokens);
@@ -70278,16 +70639,7 @@ var require_probes = __commonJS({
70278
70639
  platform: () => process.platform,
70279
70640
  osTmpDir: () => os_1.default.tmpdir(),
70280
70641
  async which(bin) {
70281
- const dirs = (process.env.PATH ?? "").split(path_1.default.delimiter).filter(Boolean);
70282
- for (const dir of dirs) {
70283
- const candidate = path_1.default.join(dir, bin);
70284
- try {
70285
- await fs_1.promises.access(candidate, fs_1.constants.X_OK);
70286
- return candidate;
70287
- } catch {
70288
- }
70289
- }
70290
- return null;
70642
+ return (0, launch_1.findOnPath)(bin);
70291
70643
  },
70292
70644
  async versionOf(bin) {
70293
70645
  const known = versions.get(bin);
@@ -70329,6 +70681,7 @@ var require_probes = __commonJS({
70329
70681
  return null;
70330
70682
  }
70331
70683
  },
70684
+ othersWithAccess: (target) => (0, private_file_1.othersWithAccess)(target),
70332
70685
  async mkdtemp(dir) {
70333
70686
  let created;
70334
70687
  try {
@@ -70430,6 +70783,7 @@ var require_probes = __commonJS({
70430
70783
  baseUrl: config.auth.jobsApiUrl,
70431
70784
  ...config.auth.apiKey ? { apiKey: config.auth.apiKey } : {},
70432
70785
  getAccessToken: (opts) => tokens.getToken(opts?.forceRefresh),
70786
+ apiVersion: options.brand.apiVersion,
70433
70787
  onResponse: enforceFloor
70434
70788
  });
70435
70789
  const poolIds = config.pools.map((pool) => pool.id).filter((id) => typeof id === "string");
@@ -70523,7 +70877,8 @@ ${outcome.stderr}`.split("\n").map((l) => l.trim()).find((l) => l.length > 0);
70523
70877
  return new Promise((resolve) => {
70524
70878
  let child;
70525
70879
  try {
70526
- child = (0, child_process_1.spawn)(bin, args2, { stdio: ["ignore", "pipe", "pipe"] });
70880
+ const launch = (0, launch_1.resolveLaunch)(bin, args2);
70881
+ child = (0, child_process_1.spawn)(launch.command, launch.args, { stdio: ["ignore", "pipe", "pipe"] });
70527
70882
  } catch (err2) {
70528
70883
  resolve({ ok: false, reason: describe(err2), exited: false });
70529
70884
  return;
@@ -70538,7 +70893,7 @@ ${outcome.stderr}`.split("\n").map((l) => l.trim()).find((l) => l.length > 0);
70538
70893
  resolve(value);
70539
70894
  };
70540
70895
  const timer = setTimeout(() => {
70541
- child.kill("SIGKILL");
70896
+ (0, terminate_1.terminate)(child, "SIGKILL");
70542
70897
  settle({ ok: false, reason: `did not finish within ${Math.round(timeoutMs / 1e3)}s`, exited: false });
70543
70898
  }, timeoutMs);
70544
70899
  child.stdout?.on("data", (chunk) => {
@@ -70657,19 +71012,11 @@ var require_preflight = __commonJS({
70657
71012
  var typed_exit_1 = require_typed_exit();
70658
71013
  async function runPreflight(probes, subject) {
70659
71014
  const verdicts = [];
70660
- let blockedBy;
70661
71015
  for (const check of checks_1.CHECKS) {
70662
71016
  if (!check.phases.includes(subject.phase))
70663
71017
  continue;
70664
- if (blockedBy !== void 0) {
70665
- verdicts.push({ name: check.name, status: "SKIP", detail: `not checked; see ${blockedBy}` });
70666
- continue;
70667
- }
70668
71018
  try {
70669
- const verdict = await check.run(probes, subject);
70670
- verdicts.push(verdict);
70671
- if (check.prerequisite === true && verdict.status === "FAIL")
70672
- blockedBy = check.name;
71019
+ verdicts.push(await check.run(probes, subject));
70673
71020
  } catch (err2) {
70674
71021
  if ((0, typed_exit_1.isTypedExit)(err2))
70675
71022
  throw err2;
@@ -70752,6 +71099,24 @@ var require_doctor = __commonJS({
70752
71099
  }
70753
71100
  });
70754
71101
 
71102
+ // ../../packages/shuttle/dist/api-version.js
71103
+ var require_api_version = __commonJS({
71104
+ "../../packages/shuttle/dist/api-version.js"(exports2) {
71105
+ "use strict";
71106
+ Object.defineProperty(exports2, "__esModule", { value: true });
71107
+ exports2.VERSION_HEADER = void 0;
71108
+ exports2.withApiVersion = withApiVersion;
71109
+ exports2.VERSION_HEADER = "Whittle-Version";
71110
+ function withApiVersion(fetcher, version) {
71111
+ return (input, init2) => {
71112
+ const headers = new Headers(init2?.headers);
71113
+ headers.set(exports2.VERSION_HEADER, version);
71114
+ return fetcher(input, { ...init2, headers });
71115
+ };
71116
+ }
71117
+ }
71118
+ });
71119
+
70755
71120
  // ../../node_modules/.pnpm/qrcode-generator@2.0.4/node_modules/qrcode-generator/dist/qrcode.js
70756
71121
  var require_qrcode = __commonJS({
70757
71122
  "../../node_modules/.pnpm/qrcode-generator@2.0.4/node_modules/qrcode-generator/dist/qrcode.js"(exports2, module2) {
@@ -72515,12 +72880,13 @@ var require_device_code = __commonJS({
72515
72880
  var os_1 = require("os");
72516
72881
  var jobs_1 = require_jobs();
72517
72882
  var keep_1 = require_keep();
72883
+ var api_version_1 = require_api_version();
72518
72884
  var apply_1 = require_apply();
72519
72885
  var version_check_1 = require_version_check();
72520
72886
  var typed_exit_1 = require_typed_exit();
72521
72887
  var terminal_1 = require_terminal();
72522
72888
  async function pair(opts) {
72523
- const fetcher = opts.fetcher ?? globalThis.fetch;
72889
+ const fetcher = (0, api_version_1.withApiVersion)(opts.fetcher ?? globalThis.fetch, opts.brand.apiVersion);
72524
72890
  const log = opts.log ?? ((line) => console.log(line));
72525
72891
  const reg = opts.brand.keepRegistration;
72526
72892
  const displayName = (0, apply_1.renderTemplate)(reg.serviceIdentityDisplayName, {
@@ -72643,7 +73009,7 @@ var require_device_code = __commonJS({
72643
73009
  return [
72644
73010
  reason,
72645
73011
  "",
72646
- restored ? "Nothing was saved on this machine, so it is as it was before init." : `Some of what init wrote could not be put back; check ${brand.paths.configDir} before pairing again.`,
73012
+ restored ? "Nothing was saved on this machine, so it is as it was before init." : `Some of what init wrote could not be put back; check ${(0, apply_1.brandConfigDir)(brand)} before pairing again.`,
72647
73013
  `Keep has already issued "${identity}", which this machine will not use: open`,
72648
73014
  `${webPairingPlace(brand)}, remove "${identity}", then pair again from there.`
72649
73015
  ].join("\n");
@@ -73156,6 +73522,7 @@ var require_self_update = __commonJS({
73156
73522
  exports2.updateForFloor = updateForFloor;
73157
73523
  var child_process_1 = require("child_process");
73158
73524
  var version_check_1 = require_version_check();
73525
+ var launch_1 = require_launch();
73159
73526
  function readUpgradeDirective(directives, currentVersion, attemptedVersions) {
73160
73527
  const raw = directives.upgrade;
73161
73528
  if (!raw || typeof raw !== "object")
@@ -73223,7 +73590,8 @@ var require_self_update = __commonJS({
73223
73590
  }
73224
73591
  function defaultInstall(packageSpec) {
73225
73592
  return new Promise((resolve, reject) => {
73226
- const child = (0, child_process_1.spawn)("npm", ["install", "-g", packageSpec], {
73593
+ const launch = (0, launch_1.resolveLaunch)("npm", ["install", "-g", packageSpec]);
73594
+ const child = (0, child_process_1.spawn)(launch.command, launch.args, {
73227
73595
  stdio: ["ignore", "pipe", "pipe"]
73228
73596
  });
73229
73597
  let output = "";
@@ -73240,7 +73608,7 @@ var require_self_update = __commonJS({
73240
73608
  }
73241
73609
  function defaultRespawn() {
73242
73610
  const child = (0, child_process_1.spawn)(process.execPath, process.argv.slice(1), {
73243
- detached: true,
73611
+ detached: process.platform !== "win32",
73244
73612
  stdio: "inherit"
73245
73613
  });
73246
73614
  child.unref();
@@ -73516,6 +73884,8 @@ var require_git = __commonJS({
73516
73884
  var child_process_1 = require("child_process");
73517
73885
  var fs_1 = require("fs");
73518
73886
  var path_1 = __importDefault(require("path"));
73887
+ var launch_1 = require_launch();
73888
+ var terminate_1 = require_terminate();
73519
73889
  var DEFAULT_GIT_TIMEOUT_MS = 12e4;
73520
73890
  exports2.DEFAULT_GIT_PROTOCOLS = "https:ssh:git";
73521
73891
  var DEFAULT_MAX_CONTEXT_REPOS = 5;
@@ -73779,9 +74149,11 @@ var require_git = __commonJS({
73779
74149
  used.add(name2);
73780
74150
  return name2;
73781
74151
  }
74152
+ var CHECKOUT_CONFIG = ["-c", "core.autocrlf=false", "-c", "core.longpaths=true"];
73782
74153
  function runGit(args2, cwd, opts) {
73783
74154
  return new Promise((resolve) => {
73784
- const child = (0, child_process_1.spawn)("git", args2, {
74155
+ const launch = (0, launch_1.resolveLaunch)("git", [...CHECKOUT_CONFIG, ...args2]);
74156
+ const child = (0, child_process_1.spawn)(launch.command, launch.args, {
73785
74157
  cwd,
73786
74158
  stdio: [opts.stdin !== void 0 ? "pipe" : "ignore", "pipe", "pipe"],
73787
74159
  env: {
@@ -73805,7 +74177,9 @@ var require_git = __commonJS({
73805
74177
  resolve(result);
73806
74178
  };
73807
74179
  const killChild = () => {
73808
- child.kill("SIGTERM");
74180
+ (0, terminate_1.terminate)(child);
74181
+ if (process.platform === "win32")
74182
+ return;
73809
74183
  const escalate = setTimeout(() => child.kill("SIGKILL"), 5e3);
73810
74184
  escalate.unref();
73811
74185
  child.once("close", () => clearTimeout(escalate));
@@ -74668,6 +75042,8 @@ var require_defaults2 = __commonJS({
74668
75042
  },
74669
75043
  // Dev distribution allows every executor.
74670
75044
  executorAllowlist: ["*"],
75045
+ // The baseline (ADR 0161): the dev distribution speaks the wire it was cut from.
75046
+ apiVersion: "2026-11-03",
74671
75047
  keepRegistration: {
74672
75048
  keepApiUrl: "http://localhost:3007",
74673
75049
  jobsApiUrl: "http://localhost:3005",
@@ -75063,6 +75439,7 @@ var require_shuttle = __commonJS({
75063
75439
  baseUrl: this.config.auth.jobsApiUrl,
75064
75440
  apiKey: auth.kind === "apiKey" ? auth.apiKey : void 0,
75065
75441
  getAccessToken: auth.kind === "tokenProvider" ? auth.getToken : void 0,
75442
+ apiVersion: this.brand.apiVersion,
75066
75443
  onResponse: onBackendResponse
75067
75444
  });
75068
75445
  const registry = new registry_1.ExecutorRegistry(this.brand.executorAllowlist);
@@ -75426,6 +75803,7 @@ var require_shuttle = __commonJS({
75426
75803
  keepApiUrl: pairing.keepApiUrl,
75427
75804
  clientId: pairing.credentials.clientId,
75428
75805
  clientSecret: pairing.credentials.clientSecret,
75806
+ apiVersion: brand.apiVersion,
75429
75807
  onResponse
75430
75808
  });
75431
75809
  const token = await mintWaitingOutKeep(() => tokens.getToken(), brand, options);
@@ -75501,6 +75879,8 @@ var require_shutdown = __commonJS({
75501
75879
  process.on("SIGINT", () => handler("SIGINT"));
75502
75880
  process.on("SIGTERM", () => handler("SIGTERM"));
75503
75881
  process.on("SIGHUP", () => handler("SIGHUP"));
75882
+ if (process.platform === "win32")
75883
+ process.on("SIGBREAK", () => handler("SIGBREAK"));
75504
75884
  }
75505
75885
  function createShutdownHandler(onShutdown, options = {}) {
75506
75886
  const deadlineMs = options.deadlineMs ?? exports2.SHUTDOWN_DEADLINE_MS;
@@ -75767,6 +76147,7 @@ var require_pairings = __commonJS({
75767
76147
  exports2.revokePairing = revokePairing;
75768
76148
  var keep_1 = require_keep();
75769
76149
  var keep_2 = require_dist4();
76150
+ var api_version_1 = require_api_version();
75770
76151
  var version_check_1 = require_version_check();
75771
76152
  var PAGE_LIMIT = 100;
75772
76153
  async function listPairings(opts) {
@@ -75788,7 +76169,7 @@ var require_pairings = __commonJS({
75788
76169
  }));
75789
76170
  }
75790
76171
  async function ask(opts, send) {
75791
- const fetcher = opts.fetcher ?? globalThis.fetch;
76172
+ const fetcher = (0, api_version_1.withApiVersion)(opts.fetcher ?? globalThis.fetch, opts.brand.apiVersion);
75792
76173
  let belowFloor;
75793
76174
  const transport = async (url, init2) => {
75794
76175
  const response = await fetcher(url, init2);
@@ -76452,7 +76833,7 @@ var import_shuttle2 = __toESM(require_dist8());
76452
76833
 
76453
76834
  // src/brand.ts
76454
76835
  var import_shuttle = __toESM(require_dist8());
76455
- var buildVersion = true ? "0.1.10" : pkg.version;
76836
+ var buildVersion = true ? "0.2.1" : pkg.version;
76456
76837
  var EXECUTORS = ["claude-code"];
76457
76838
  var trivetBrand = {
76458
76839
  product: {
@@ -76471,6 +76852,10 @@ var trivetBrand = {
76471
76852
  configSearchPaths: ["~/.trivet/trivet.yaml"]
76472
76853
  },
76473
76854
  executorAllowlist: EXECUTORS,
76855
+ // The Whittle API version this code speaks (ADR 0156): a literal, never the
76856
+ // calendar's newest, so it moves only in the PR that adapts the runner to a
76857
+ // newer shape. The baseline (ADR 0161).
76858
+ apiVersion: "2026-11-03",
76474
76859
  defaultExecutor: "claude-code",
76475
76860
  executorBlock: (executor, options) => ({
76476
76861
  type: executor,