@brainervirus/workit-claude-code 8.41.0 → 8.41.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/workit.js CHANGED
@@ -9417,7 +9417,7 @@ var package_default;
9417
9417
  var init_package = __esm(() => {
9418
9418
  package_default = {
9419
9419
  name: "@brainervirus/workit-cli",
9420
- version: "8.41.0",
9420
+ version: "8.41.1",
9421
9421
  private: false,
9422
9422
  description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
9423
9423
  keywords: [
@@ -9455,13 +9455,13 @@ var init_package = __esm(() => {
9455
9455
  },
9456
9456
  dependencies: {
9457
9457
  "@babel/parser": "7.29.9",
9458
- "@brainervirus/workit-cursor": "^8.41.0",
9458
+ "@brainervirus/workit-cursor": "^8.41.1",
9459
9459
  "@inkjs/ui": "2.0.0",
9460
9460
  ink: "7.1.1",
9461
9461
  react: "19.2.8"
9462
9462
  },
9463
9463
  devDependencies: {
9464
- "@brainervirus/workit-core": "^8.41.0"
9464
+ "@brainervirus/workit-core": "^8.41.1"
9465
9465
  },
9466
9466
  engines: {
9467
9467
  node: ">=24"
@@ -66193,7 +66193,7 @@ import path33 from "node:path";
66193
66193
  function hostCommand(name, args, options = {}) {
66194
66194
  const executable = findHostExecutable(name, options);
66195
66195
  if (!executable)
66196
- throw new Error(`${name} executable was not found on PATH or supported user bin directories`);
66196
+ throw new Error(path33.isAbsolute(name) || name.includes("/") || name.includes("\\") ? `${name} does not exist or is not executable` : `${name} executable was not found on PATH or supported user bin directories`);
66197
66197
  if (process.platform === "win32" && /\.(?:cmd|bat)$/i.test(executable)) {
66198
66198
  const node = findHostExecutable("node", options);
66199
66199
  if (!node)
@@ -66217,6 +66217,17 @@ function resolveWindowsShimEntry(contents, shim, exists = existsSync13) {
66217
66217
  return null;
66218
66218
  }
66219
66219
  function findHostExecutable(name, options = {}) {
66220
+ if (path33.isAbsolute(name) || name.includes("/") || name.includes("\\")) {
66221
+ try {
66222
+ if (!statSync2(name).isFile())
66223
+ return null;
66224
+ if (process.platform !== "win32")
66225
+ accessSync(name, constants2.X_OK);
66226
+ return name;
66227
+ } catch {
66228
+ return null;
66229
+ }
66230
+ }
66220
66231
  const env = options.env ?? process.env;
66221
66232
  const home = options.home ?? env.HOME ?? os9.homedir();
66222
66233
  const suffixes = process.platform === "win32" ? ["", ".exe", ".cmd", ".bat"] : [""];
@@ -67761,7 +67772,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67761
67772
  return null;
67762
67773
  dir = parent;
67763
67774
  }
67764
- }, listClaudeProcesses = () => {
67775
+ }, listProcessesMatching = (match) => {
67765
67776
  const r = spawnSync16("ps", ["-eo", "pid=,lstart=,args="], {
67766
67777
  encoding: "utf8",
67767
67778
  timeout: 5000
@@ -67772,14 +67783,14 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67772
67783
  for (const row of r.stdout.split(`
67773
67784
  `)) {
67774
67785
  const m = /^\s*(\d+)\s+(\w{3}\s+\w{3}\s+\d+\s+[\d:]+\s+\d{4})\s+(.*)$/.exec(row);
67775
- if (!m || !/^(\S*\/)?claude(\s|$)/.test(m[3]))
67786
+ if (!m || !match(m[3]))
67776
67787
  continue;
67777
67788
  const startedMs = Date.parse(m[2]);
67778
67789
  if (Number.isFinite(startedMs))
67779
67790
  found.push({ pid: Number(m[1]), startedMs, args: m[3] });
67780
67791
  }
67781
67792
  return found;
67782
- }, resolve = (options) => {
67793
+ }, listClaudeProcesses = () => listProcessesMatching((args) => /^(\S*\/)?claude(\s|$)/.test(args)), listCodexProcesses = () => listProcessesMatching((args) => /^(\S*\/)?codex(\.js)?(\s|$)|^(\S*\/)?node(js)?\s+(\S+\s+)*?\S*\/codex(\.js)?(\s|$)/.test(args) && !/\bdaemon\s+pid-update-loop\b/.test(args)), resolve = (options) => {
67783
67794
  const env = options.env ?? process.env;
67784
67795
  const home = options.home ?? env.HOME ?? os12.homedir();
67785
67796
  const configDir = options.configDir ?? env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path39.join(home, ".config", "workit");
@@ -67807,7 +67818,8 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67807
67818
  installer: options.installer ?? false,
67808
67819
  cliVersion: options.cliVersion ?? null,
67809
67820
  scopeProbe: options.scopeProbe ?? probeScope,
67810
- claudeProcesses: options.claudeProcesses ?? listClaudeProcesses
67821
+ claudeProcesses: options.claudeProcesses ?? listClaudeProcesses,
67822
+ codexProcesses: options.codexProcesses ?? listCodexProcesses
67811
67823
  };
67812
67824
  }, readJson = (p) => {
67813
67825
  try {
@@ -68563,7 +68575,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68563
68575
  id: "launcher",
68564
68576
  status: "fail",
68565
68577
  detail: `missing or invalid launcher entry: ${missing.join("; ")}`,
68566
- fix: `Rebuild and reinstall the workit package (bun run build) — dist entries must be non-empty Node launchers`
68578
+ fix: dev ? `Rebuild and reinstall the workit package (bun run build) — dist entries must be non-empty Node launchers` : "workit upgrade --hosts=cursor — it reinstalls the plugin files and re-registers the MCP launcher"
68567
68579
  };
68568
68580
  }
68569
68581
  if (!dev && res.host !== "cursor") {
@@ -69804,6 +69816,49 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69804
69816
  status: "warn",
69805
69817
  detail: `started before Workit ${latest.install.version} was installed: ${rows.join("; ")}; quit and start \`claude --resume ${first ?? "<session id>"}\` to load it (\`/resume\` keeps the old plugin)`
69806
69818
  };
69819
+ }, checkCodexSessionPlugin = (res) => {
69820
+ const id = "codex_session_plugin";
69821
+ if (process.platform === "win32")
69822
+ return {
69823
+ id,
69824
+ status: "info",
69825
+ detail: "running Codex processes are not checked on Windows"
69826
+ };
69827
+ const installs = codexWorkitInstalls(res).filter((install) => install.root && install.version);
69828
+ const stamped = installs.flatMap((install) => {
69829
+ try {
69830
+ return [{ install, at: statSync6(install.root).mtimeMs }];
69831
+ } catch {
69832
+ return [];
69833
+ }
69834
+ });
69835
+ const latest = stamped.toSorted((a, b) => b.at - a.at)[0];
69836
+ if (!latest)
69837
+ return {
69838
+ id,
69839
+ status: "info",
69840
+ detail: "no Workit Codex plugin install recorded — skipping"
69841
+ };
69842
+ const running = res.codexProcesses();
69843
+ if (running === null)
69844
+ return {
69845
+ id,
69846
+ status: "info",
69847
+ detail: "could not list running codex processes (ps) — skipping"
69848
+ };
69849
+ const stale = running.filter((proc) => proc.startedMs < latest.at);
69850
+ if (stale.length === 0)
69851
+ return {
69852
+ id,
69853
+ status: "info",
69854
+ detail: `${running.length} running codex process(es), none started before Workit ${latest.install.version} was installed`
69855
+ };
69856
+ const rows = stale.map((proc) => `pid ${proc.pid} started ${new Date(proc.startedMs).toISOString()} (${proc.args.slice(0, 60)})`);
69857
+ return {
69858
+ id,
69859
+ status: "warn",
69860
+ detail: `started before Workit ${latest.install.version} was installed: ${rows.join("; ")}; they keep the old plugin until restarted, new Codex sessions load it`
69861
+ };
69807
69862
  }, HOOK_ISSUED_MARKER = "workit-issued-sessions/3", hookRecordsIssued = (root) => {
69808
69863
  let files;
69809
69864
  try {
@@ -70095,6 +70150,7 @@ var init_doctor = __esm(() => {
70095
70150
  checkOpencodeVersion,
70096
70151
  checkClaudePlugin,
70097
70152
  checkClaudeSessionPlugin,
70153
+ checkCodexSessionPlugin,
70098
70154
  checkHookIssuedSessions,
70099
70155
  checkWorkitOnPath,
70100
70156
  checkAssets,
@@ -75219,6 +75275,8 @@ var init_setup2 = __esm(() => {
75219
75275
  });
75220
75276
 
75221
75277
  // packages/workit-cli/src/progress.ts
75278
+ import { spawn } from "node:child_process";
75279
+ import path44 from "node:path";
75222
75280
  function createProgress(options = {}) {
75223
75281
  const env = options.env ?? process.env;
75224
75282
  const mode = modeFor(options, env);
@@ -75311,18 +75369,43 @@ function createProgress(options = {}) {
75311
75369
  },
75312
75370
  runSync(label, fn, classify) {
75313
75371
  const step = start(label);
75372
+ const ticker = mode === "spinner" && stream ? (options.spawnTicker ?? ((text, began) => defaultTicker(text, began, stream)))(label, now()) : undefined;
75314
75373
  try {
75315
75374
  const value = fn();
75375
+ ticker?.stop();
75316
75376
  step.end(classify ? classify(value) : "done");
75317
75377
  return value;
75318
75378
  } catch (error) {
75379
+ ticker?.stop();
75319
75380
  step.end("failed");
75320
75381
  throw error;
75321
75382
  }
75322
75383
  }
75323
75384
  };
75324
75385
  }
75325
- var FRAMES, FRAME_MS = 120, CLEAR = "\r\x1B[2K", truthy = (value) => value !== undefined && value !== "" && value !== "0" && value.toLowerCase() !== "false", modeFor = (options, env) => {
75386
+ var FRAMES, FRAME_MS = 120, CLEAR = "\r\x1B[2K", TICKER_SOURCE, defaultTicker = (label, began, stream) => {
75387
+ if (stream !== process.stderr)
75388
+ return;
75389
+ if (!/^(?:node|nodejs|bun)(?:\.exe)?$/i.test(path44.basename(process.execPath)))
75390
+ return;
75391
+ try {
75392
+ const child = spawn(process.execPath, ["-e", TICKER_SOURCE], {
75393
+ env: {
75394
+ ...process.env,
75395
+ WORKIT_TICK_LABEL: label,
75396
+ WORKIT_TICK_BEGAN: String(began),
75397
+ WORKIT_TICK_COLS: String(stream.columns ?? 0)
75398
+ },
75399
+ stdio: ["ignore", "ignore", "inherit"],
75400
+ windowsHide: true
75401
+ });
75402
+ child.on("error", () => {});
75403
+ child.unref();
75404
+ return { stop: () => void child.kill("SIGKILL") };
75405
+ } catch {
75406
+ return;
75407
+ }
75408
+ }, truthy = (value) => value !== undefined && value !== "" && value !== "0" && value.toLowerCase() !== "false", modeFor = (options, env) => {
75326
75409
  if (options.json || !options.stream?.isTTY || truthy(env.CI))
75327
75410
  return "off";
75328
75411
  if (truthy(env.NO_COLOR) || env.TERM === "dumb")
@@ -75331,42 +75414,64 @@ var FRAMES, FRAME_MS = 120, CLEAR = "\r\x1B[2K", truthy = (value) => value !== u
75331
75414
  }, NOOP_STEP;
75332
75415
  var init_progress = __esm(() => {
75333
75416
  FRAMES = ["·", "✢", "✳", "∗", "✻", "✽"];
75417
+ TICKER_SOURCE = `
75418
+ const frames = ${JSON.stringify(FRAMES)};
75419
+ const { WORKIT_TICK_LABEL: label, WORKIT_TICK_BEGAN: began, WORKIT_TICK_COLS: cols } = process.env;
75420
+ const parent = process.ppid;
75421
+ let frame = 0;
75422
+ const timer = setInterval(() => {
75423
+ let alive = process.ppid === parent;
75424
+ if (alive) try { process.kill(parent, 0); } catch { alive = false; }
75425
+ if (!alive || Date.now() - Number(began) > 600000) process.exit(0);
75426
+ frame += 1;
75427
+ const seconds = Math.floor((Date.now() - Number(began)) / 1000);
75428
+ let line = frames[frame % frames.length] + " " + label + " (" + seconds + "s)";
75429
+ if (Number(cols) && line.length >= Number(cols)) line = line.slice(0, Math.max(1, Number(cols) - 2)) + "…";
75430
+ process.stderr.write(${JSON.stringify(CLEAR)} + line);
75431
+ }, ${FRAME_MS});
75432
+ `;
75334
75433
  NOOP_STEP = { label: () => {}, end: () => {} };
75335
75434
  });
75336
75435
 
75337
75436
  // packages/workit-cli/src/upgrade/shared.ts
75338
- import { spawn } from "node:child_process";
75437
+ import { spawn as spawn2 } from "node:child_process";
75339
75438
  import { existsSync as existsSync21, readFileSync as readFileSync22 } from "node:fs";
75340
- import path44 from "node:path";
75439
+ import path45 from "node:path";
75341
75440
  import os16 from "node:os";
75342
75441
  import { createHash as createHash15 } from "node:crypto";
75343
- var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-opencode", OPENCODE_UPDATE, CODEX_MARKETPLACE = "workflow-toolkit", CLI_FIX = "npm install --global @brainervirus/workit-cli@latest", fixFor = (host, selector = "") => host === "pi" ? `pi update --extension ${selector || "npm:@brainervirus/workit-pi"}` : host === "codex" ? `codex plugin marketplace upgrade ${CODEX_MARKETPLACE} && codex plugin add workit@${CODEX_MARKETPLACE}` : host === "claude-code" ? "claude plugin marketplace update workit && claude plugin update workit@workit" : host === "opencode" ? OPENCODE_UPDATE : host === "cursor" ? "workit upgrade --hosts=cursor" : CLI_FIX, upgradePaths = (deps) => {
75442
+ function errorText(error) {
75443
+ return error instanceof Error ? error.message : "installed source could not be read";
75444
+ }
75445
+ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-opencode", OPENCODE_UPDATE, CODEX_MARKETPLACE = "workflow-toolkit", CLI_FIX = "npm install --global @brainervirus/workit-cli@latest", stderrTail = (text, lines = 5) => (text ?? "").split(/\r?\n/).map((line) => line.trim()).filter(Boolean).slice(-lines).join(" | "), failureReason = (command, result) => {
75446
+ const tail = stderrTail(result.stderr);
75447
+ return `\`${command.command} ${command.args.join(" ")}\` failed${tail ? `: ${tail}` : ""}`;
75448
+ }, fixFor = (host, selector = "") => host === "pi" ? `pi update --extension ${selector || "npm:@brainervirus/workit-pi"}` : host === "codex" ? `codex plugin marketplace upgrade ${CODEX_MARKETPLACE} && codex plugin add workit@${CODEX_MARKETPLACE}` : host === "claude-code" ? "claude plugin marketplace update workit && claude plugin update workit@workit" : host === "opencode" ? OPENCODE_UPDATE : host === "cursor" ? "workit upgrade --hosts=cursor" : CLI_FIX, upgradePaths = (deps) => {
75344
75449
  const home = deps.home ?? deps.env?.HOME ?? os16.homedir();
75345
75450
  const env = {
75346
75451
  ...process.env,
75347
75452
  ...deps.home || deps.env?.HOME ? {
75348
75453
  HOME: home,
75349
- CODEX_HOME: path44.join(home, ".codex"),
75350
- CLAUDE_CONFIG_DIR: path44.join(home, ".claude"),
75351
- PI_CODING_AGENT_DIR: path44.join(home, ".pi/agent"),
75352
- XDG_CONFIG_HOME: path44.join(home, ".config"),
75454
+ CODEX_HOME: path45.join(home, ".codex"),
75455
+ CLAUDE_CONFIG_DIR: path45.join(home, ".claude"),
75456
+ PI_CODING_AGENT_DIR: path45.join(home, ".pi/agent"),
75457
+ XDG_CONFIG_HOME: path45.join(home, ".config"),
75353
75458
  WORKFLOW_TOOLKIT_CONFIG: undefined,
75354
75459
  WORKFLOW_TOOLKIT_CONFIG_DIR: undefined
75355
75460
  } : {},
75356
75461
  ...deps.env,
75357
75462
  HOME: home
75358
75463
  };
75359
- const xdg = env.XDG_CONFIG_HOME || path44.join(home, ".config");
75360
- const codexHome = env.CODEX_HOME ?? path44.join(home, ".codex");
75464
+ const xdg = env.XDG_CONFIG_HOME || path45.join(home, ".config");
75465
+ const codexHome = env.CODEX_HOME ?? path45.join(home, ".codex");
75361
75466
  return {
75362
75467
  home,
75363
75468
  env,
75364
- configDir: env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path44.join(xdg, "workit"),
75365
- opencodeConfig: path44.join(xdg, "opencode/opencode.json"),
75366
- piSettings: path44.join(env.PI_CODING_AGENT_DIR ?? path44.join(home, ".pi/agent"), "settings.json"),
75469
+ configDir: env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path45.join(xdg, "workit"),
75470
+ opencodeConfig: path45.join(xdg, "opencode/opencode.json"),
75471
+ piSettings: path45.join(env.PI_CODING_AGENT_DIR ?? path45.join(home, ".pi/agent"), "settings.json"),
75367
75472
  codexHome,
75368
- codexConfig: path44.join(codexHome, "config.toml"),
75369
- cursorRoot: path44.join(home, ".cursor/plugins/local/workit")
75473
+ codexConfig: path45.join(codexHome, "config.toml"),
75474
+ cursorRoot: path45.join(home, ".cursor/plugins/local/workit")
75370
75475
  };
75371
75476
  }, object2 = (file) => {
75372
75477
  if (!existsSync21(file))
@@ -75391,11 +75496,11 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
75391
75496
  let step;
75392
75497
  try {
75393
75498
  step = hostCommand(command, args, { home, env });
75394
- } catch {
75395
- return { status: 1, stdout: "" };
75499
+ } catch (error) {
75500
+ return { status: 1, stdout: "", stderr: errorText(error) };
75396
75501
  }
75397
75502
  const result = runHostCommand(step, { home, env });
75398
- return { status: result.exitCode, stdout: result.stdout };
75503
+ return { status: result.exitCode, stdout: result.stdout, stderr: result.stderr };
75399
75504
  }), COMMAND_TIMEOUT_MS = 60000, asyncRunner = (deps) => {
75400
75505
  if (deps.runAsync)
75401
75506
  return deps.runAsync;
@@ -75407,37 +75512,42 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
75407
75512
  let step;
75408
75513
  try {
75409
75514
  step = hostCommand(command, args, { home, env });
75410
- } catch {
75411
- return Promise.resolve({ status: 1, stdout: "" });
75515
+ } catch (error) {
75516
+ return Promise.resolve({ status: 1, stdout: "", stderr: errorText(error) });
75412
75517
  }
75413
75518
  if (process.platform === "win32" && /\.(?:cmd|bat)$/i.test(step.command))
75414
- return Promise.resolve({ status: 1, stdout: "" });
75519
+ return Promise.resolve({
75520
+ status: 1,
75521
+ stdout: "",
75522
+ stderr: `Cannot safely execute batch shim ${step.command}`
75523
+ });
75415
75524
  const childEnv = { ...process.env, ...env, HOME: home };
75416
- childEnv.CODEX_HOME = env.CODEX_HOME ?? path44.join(home, ".codex");
75417
- childEnv.PI_CODING_AGENT_DIR = env.PI_CODING_AGENT_DIR ?? path44.join(home, ".pi", "agent");
75418
- childEnv.CLAUDE_CONFIG_DIR = env.CLAUDE_CONFIG_DIR ?? path44.join(home, ".claude");
75419
- childEnv.XDG_CONFIG_HOME = env.XDG_CONFIG_HOME ?? path44.join(home, ".config");
75525
+ childEnv.CODEX_HOME = env.CODEX_HOME ?? path45.join(home, ".codex");
75526
+ childEnv.PI_CODING_AGENT_DIR = env.PI_CODING_AGENT_DIR ?? path45.join(home, ".pi", "agent");
75527
+ childEnv.CLAUDE_CONFIG_DIR = env.CLAUDE_CONFIG_DIR ?? path45.join(home, ".claude");
75528
+ childEnv.XDG_CONFIG_HOME = env.XDG_CONFIG_HOME ?? path45.join(home, ".config");
75420
75529
  return new Promise((resolve) => {
75421
75530
  let stdout = "";
75531
+ let stderr = "";
75422
75532
  let settled = false;
75423
75533
  const finish = (status) => {
75424
75534
  if (settled)
75425
75535
  return;
75426
75536
  settled = true;
75427
75537
  clearTimeout(timer);
75428
- resolve({ status, stdout });
75538
+ resolve({ status, stdout, stderr });
75429
75539
  };
75430
75540
  let child;
75431
75541
  try {
75432
- child = spawn(step.command, step.args, {
75542
+ child = spawn2(step.command, step.args, {
75433
75543
  cwd: step.cwd,
75434
75544
  env: childEnv,
75435
- stdio: ["ignore", "pipe", "ignore"],
75545
+ stdio: ["ignore", "pipe", "pipe"],
75436
75546
  windowsHide: true,
75437
75547
  shell: false
75438
75548
  });
75439
- } catch {
75440
- resolve({ status: 1, stdout: "" });
75549
+ } catch (error) {
75550
+ resolve({ status: 1, stdout: "", stderr: errorText(error) });
75441
75551
  return;
75442
75552
  }
75443
75553
  const timer = setTimeout(() => {
@@ -75446,16 +75556,21 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
75446
75556
  }, COMMAND_TIMEOUT_MS);
75447
75557
  child.stdout?.setEncoding("utf8");
75448
75558
  child.stdout?.on("data", (chunk) => stdout += chunk);
75449
- child.on("error", () => finish(1));
75559
+ child.stderr?.setEncoding("utf8");
75560
+ child.stderr?.on("data", (chunk) => stderr = (stderr + chunk).slice(-4000));
75561
+ child.on("error", (error) => {
75562
+ stderr += error.message;
75563
+ finish(1);
75564
+ });
75450
75565
  child.on("close", (code) => finish(code ?? 1));
75451
75566
  });
75452
75567
  };
75453
- }, errorText = (error) => error instanceof Error ? error.message : "installed source could not be read", piInstalledVersion = (listing, selector) => {
75568
+ }, piInstalledVersion = (listing, selector) => {
75454
75569
  const lines = listing.split(/\r?\n/).map((line) => line.trim());
75455
75570
  const index = lines.indexOf(selector);
75456
- if (index < 0 || !lines[index + 1] || !path44.isAbsolute(lines[index + 1]))
75571
+ if (index < 0 || !lines[index + 1] || !path45.isAbsolute(lines[index + 1]))
75457
75572
  return;
75458
- const found = objectOrNull(path44.join(lines[index + 1], "package.json"));
75573
+ const found = objectOrNull(path45.join(lines[index + 1], "package.json"));
75459
75574
  return found?.name === "@brainervirus/workit-pi" ? found.version : undefined;
75460
75575
  }, versionAtLeast = (installed, latest) => {
75461
75576
  if (!/^\d+\.\d+\.\d+$/.test(installed))
@@ -75481,12 +75596,12 @@ var init_shared = __esm(() => {
75481
75596
  });
75482
75597
 
75483
75598
  // packages/workit-cli/src/upgrade/processes.ts
75484
- import path45 from "node:path";
75599
+ import path46 from "node:path";
75485
75600
  var PROCESS_HOSTS, SCRIPT_RUNTIMES, classifyProcess = (proc) => {
75486
75601
  if (proc.state.startsWith("Z") || proc.args.includes("<defunct>"))
75487
75602
  return null;
75488
75603
  const argv0 = proc.args.trim().split(/\s+/)[0] ?? "";
75489
- const baseName = (value) => path45.basename(value.replaceAll("\\", "/")).replace(/^\[|\]$/g, "").replace(/\.exe$/i, "").toLowerCase();
75604
+ const baseName = (value) => path46.basename(value.replaceAll("\\", "/")).replace(/^\[|\]$/g, "").replace(/\.exe$/i, "").toLowerCase();
75490
75605
  let host = PROCESS_HOSTS[baseName(argv0)];
75491
75606
  if (!host && SCRIPT_RUNTIMES.has(baseName(argv0))) {
75492
75607
  const script = proc.args.trim().split(/\s+/).slice(1).find((arg) => !arg.startsWith("-"));
@@ -75537,7 +75652,7 @@ var init_processes = __esm(() => {
75537
75652
 
75538
75653
  // packages/workit-cli/src/upgrade/apply.ts
75539
75654
  import { existsSync as existsSync22, readdirSync as readdirSync12, mkdirSync as mkdirSync11, copyFileSync as copyFileSync6, chmodSync as chmodSync2, cpSync as cpSync5 } from "node:fs";
75540
- import path46 from "node:path";
75655
+ import path47 from "node:path";
75541
75656
  import { createHash as createHash16 } from "node:crypto";
75542
75657
  async function applyUpgrade(plan, deps = {}) {
75543
75658
  const hosts = [...plan.failed];
@@ -75572,11 +75687,11 @@ async function applyUpgrade(plan, deps = {}) {
75572
75687
  };
75573
75688
  const paths = upgradePaths(deps);
75574
75689
  const { home, configDir } = paths;
75575
- const backup = path46.join(home, ".local/state/workit/upgrades", new Date().toISOString().replaceAll(":", "-"));
75690
+ const backup = path47.join(home, ".local/state/workit/upgrades", new Date().toISOString().replaceAll(":", "-"));
75576
75691
  mkdirSync11(backup, { recursive: true, mode: 448 });
75577
75692
  for (const file of Object.keys(plan.configDigests))
75578
75693
  if (existsSync22(file)) {
75579
- const target = path46.join(backup, createHash16("sha256").update(file).digest("hex").slice(0, 12) + "-" + path46.basename(file));
75694
+ const target = path47.join(backup, createHash16("sha256").update(file).digest("hex").slice(0, 12) + "-" + path47.basename(file));
75580
75695
  copyFileSync6(file, target);
75581
75696
  chmodSync2(target, 384);
75582
75697
  }
@@ -75593,14 +75708,13 @@ async function applyUpgrade(plan, deps = {}) {
75593
75708
  writeFileAtomic(migration.file, JSON.stringify(value, null, 2) + `
75594
75709
  `, 384);
75595
75710
  }
75596
- const run = runner(deps);
75597
75711
  const runAsync = asyncRunner(deps);
75598
75712
  const progress = deps.progress ?? createProgress({ json: true });
75599
75713
  const statusOf = (outcome) => outcome?.status === "failed" ? "failed" : outcome?.status === "updated" ? "done" : "skipped";
75600
75714
  let cursorBackupError = null;
75601
75715
  if (plan.entries.some((entry) => entry.host === "cursor") && existsSync22(paths.cursorRoot))
75602
75716
  try {
75603
- cpSync5(paths.cursorRoot, path46.join(backup, "cursor-package"), {
75717
+ cpSync5(paths.cursorRoot, path47.join(backup, "cursor-package"), {
75604
75718
  recursive: true
75605
75719
  });
75606
75720
  } catch (error) {
@@ -75649,14 +75763,14 @@ async function applyUpgrade(plan, deps = {}) {
75649
75763
  hosts.push({
75650
75764
  host: "codex",
75651
75765
  status: "failed",
75652
- reason: `could not stop the Codex app-server daemon (${daemons.map(describe2).join("; ")})`,
75766
+ reason: `could not stop the Codex app-server daemon (${daemons.map(describe2).join("; ")})${stderrTail(stopped.stderr) ? `: ${stderrTail(stopped.stderr)}` : ""}`,
75653
75767
  fix: "codex app-server daemon stop && workit upgrade --hosts=codex"
75654
75768
  });
75655
75769
  continue;
75656
75770
  }
75657
75771
  let outcome;
75658
75772
  try {
75659
- outcome = await applyEntry(entry, { run, runAsync, paths, configDir });
75773
+ outcome = await applyEntry(entry, { runAsync, paths, configDir });
75660
75774
  if (entry.host === "codex" && outcome.status === "updated") {
75661
75775
  const agents = await refreshCodexAgents(runAsync, paths.codexHome);
75662
75776
  if (!agents.ok)
@@ -75667,7 +75781,10 @@ async function applyUpgrade(plan, deps = {}) {
75667
75781
  fix: agents.fix
75668
75782
  };
75669
75783
  else if (agents.note)
75670
- outcome = { ...outcome, reason: `${outcome.reason}; ${agents.note}` };
75784
+ outcome = {
75785
+ ...outcome,
75786
+ reason: `${outcome.reason}; ${agents.note}`
75787
+ };
75671
75788
  }
75672
75789
  } catch (error) {
75673
75790
  outcome = {
@@ -75741,8 +75858,11 @@ async function applyUpgrade(plan, deps = {}) {
75741
75858
  }
75742
75859
  return done(backup);
75743
75860
  }
75744
- var codexPluginRoot = (codexHome) => {
75745
- const dir = path46.join(codexHome, "plugins", "cache", CODEX_MARKETPLACE, "workit");
75861
+ var briefDetail = (detail) => {
75862
+ const lines = detail.split(/\r?\n/).filter((line) => line.trim());
75863
+ return (lines.length > 6 ? [lines[0], ...lines.slice(-5)] : lines).join(" | ");
75864
+ }, codexPluginRoot = (codexHome) => {
75865
+ const dir = path47.join(codexHome, "plugins", "cache", CODEX_MARKETPLACE, "workit");
75746
75866
  let versions = [];
75747
75867
  try {
75748
75868
  versions = readdirSync12(dir).filter((version) => /^\d+\.\d+\.\d+$/.test(version));
@@ -75750,7 +75870,7 @@ var codexPluginRoot = (codexHome) => {
75750
75870
  return null;
75751
75871
  }
75752
75872
  const newest = versions.reduce((best, version) => best && versionAtLeast(best, version) ? best : version, null);
75753
- return newest ? path46.join(dir, newest) : null;
75873
+ return newest ? path47.join(dir, newest) : null;
75754
75874
  }, opencodeVersion = async (run) => {
75755
75875
  const listing = await run("opencode", ["plugin", "list"]);
75756
75876
  if (listing.status !== 0)
@@ -75766,7 +75886,7 @@ var codexPluginRoot = (codexHome) => {
75766
75886
  }
75767
75887
  return;
75768
75888
  }, applyEntry = async (entry, context) => {
75769
- const { run, runAsync, paths, configDir } = context;
75889
+ const { runAsync, paths, configDir } = context;
75770
75890
  const { home, env } = paths;
75771
75891
  const fail = (reason) => ({
75772
75892
  host: entry.host,
@@ -75775,6 +75895,30 @@ var codexPluginRoot = (codexHome) => {
75775
75895
  fix: entry.fix
75776
75896
  });
75777
75897
  if (entry.host === "cursor") {
75898
+ const commands = entry.commands.map((command) => ({
75899
+ ...command,
75900
+ purpose: command.purpose ?? "Upgrade Cursor"
75901
+ }));
75902
+ const recorded = new Map;
75903
+ let history = "";
75904
+ for (const command of commands) {
75905
+ if (command.skipWhenOutputIncludes && history.includes(command.skipWhenOutputIncludes))
75906
+ continue;
75907
+ const outcome = await runAsync(command.command, command.args);
75908
+ const result = {
75909
+ exitCode: outcome.status ?? 1,
75910
+ stdout: outcome.stdout,
75911
+ stderr: outcome.stderr ?? ""
75912
+ };
75913
+ recorded.set(command, result);
75914
+ history += `
75915
+ ${result.stdout}
75916
+ ${result.stderr}`;
75917
+ if (result.exitCode !== 0)
75918
+ break;
75919
+ }
75920
+ const cursorSettings = path47.join(home, ".cursor", "settings.json");
75921
+ const cursorMcp = path47.join(home, ".cursor", "mcp.json");
75778
75922
  const preview = {
75779
75923
  ok: true,
75780
75924
  blocked: [],
@@ -75786,13 +75930,12 @@ var codexPluginRoot = (codexHome) => {
75786
75930
  {
75787
75931
  type: "install-host",
75788
75932
  platform: "cursor",
75789
- path: path46.join(home, ".cursor/plugins/local/.workit-package-bootstrap"),
75790
- commands: entry.commands.map((command) => ({
75791
- ...command,
75792
- purpose: command.purpose ?? "Upgrade Cursor"
75793
- }))
75933
+ path: path47.join(home, ".cursor/plugins/local/.workit-package-bootstrap"),
75934
+ commands
75794
75935
  },
75795
- { type: "install-adapter", platform: "cursor", path: paths.cursorRoot }
75936
+ { type: "install-adapter", platform: "cursor", path: paths.cursorRoot },
75937
+ { type: "register-platform", platform: "cursor", path: cursorSettings },
75938
+ { type: "register-platform", platform: "cursor", path: cursorMcp }
75796
75939
  ]
75797
75940
  };
75798
75941
  const result = applySetupPreview(preview, {
@@ -75800,16 +75943,16 @@ var codexPluginRoot = (codexHome) => {
75800
75943
  env,
75801
75944
  cwd: home,
75802
75945
  preferInstalledAdapter: true,
75803
- runHostCommand: (command) => {
75804
- const outcome = run(command.command, command.args);
75805
- return {
75806
- exitCode: outcome.status ?? 1,
75807
- stdout: outcome.stdout,
75808
- stderr: ""
75809
- };
75946
+ runHostCommand: (command) => recorded.get(command) ?? {
75947
+ exitCode: 1,
75948
+ stdout: "",
75949
+ stderr: "command did not run"
75810
75950
  }
75811
75951
  });
75812
- const installed = objectOrNull(path46.join(paths.cursorRoot, "package.json"));
75952
+ const installed = objectOrNull(path47.join(paths.cursorRoot, "package.json"));
75953
+ const problems = result.entries.filter((one) => one.status === "Failed").map((one) => one.detail ?? `${one.file} failed`);
75954
+ if (problems.length)
75955
+ return fail(`Cursor install failed: ${problems.map(briefDetail).join("; ")}`);
75813
75956
  if (!result.ok || installed?.version !== entry.latest)
75814
75957
  return fail("Cursor install did not verify the requested package version; inspect the installer before retrying");
75815
75958
  return {
@@ -75819,9 +75962,13 @@ var codexPluginRoot = (codexHome) => {
75819
75962
  };
75820
75963
  }
75821
75964
  const before = entry.host === "opencode" ? await opencodeVersion(runAsync) : undefined;
75822
- for (const command of entry.commands)
75823
- if ((await runAsync(command.command, command.args)).status !== 0)
75824
- return fail(`\`${command.command} ${command.args.join(" ")}\` failed`);
75965
+ for (const command of entry.commands) {
75966
+ let result = await runAsync(command.command, command.args);
75967
+ if (result.status !== 0 && entry.host === "opencode")
75968
+ result = await runAsync(command.command, command.args);
75969
+ if (result.status !== 0)
75970
+ return fail(failureReason(command, result));
75971
+ }
75825
75972
  if (entry.host === "opencode") {
75826
75973
  const after = await opencodeVersion(runAsync);
75827
75974
  if (before && after)
@@ -75854,7 +76001,7 @@ var codexPluginRoot = (codexHome) => {
75854
76001
  }
75855
76002
  const verify = entry.host === "codex" ? await runAsync("codex", ["plugin", "list", "--json"]) : await runAsync("pi", ["list"]);
75856
76003
  if (verify.status !== 0)
75857
- return fail("update verification failed");
76004
+ return fail(`update verification failed${stderrTail(verify.stderr) ? `: ${stderrTail(verify.stderr)}` : ""}`);
75858
76005
  if (entry.host === "codex") {
75859
76006
  let installed = [];
75860
76007
  try {
@@ -75872,11 +76019,16 @@ var codexPluginRoot = (codexHome) => {
75872
76019
  };
75873
76020
  }, refreshCodexAgents = async (run, codexHome) => {
75874
76021
  const root = codexPluginRoot(codexHome);
75875
- const launcher = root && path46.join(root, "dist", "launch-mcp.js");
76022
+ const launcher = root && path47.join(root, "dist", "launch-mcp.js");
75876
76023
  if (!launcher || !existsSync22(launcher))
75877
76024
  return { ok: true, note: "" };
75878
76025
  const fix = `node ${JSON.stringify(launcher)} --install-agents`;
75879
- return (await run("node", [launcher, "--install-agents"])).status === 0 ? { ok: true, note: "agents refreshed" } : { ok: false, note: "agent refresh failed", fix };
76026
+ const refreshed = await run("node", [launcher, "--install-agents"]);
76027
+ return refreshed.status === 0 ? { ok: true, note: "agents refreshed" } : {
76028
+ ok: false,
76029
+ note: `agent refresh failed${stderrTail(refreshed.stderr) ? `: ${stderrTail(refreshed.stderr)}` : ""}`,
76030
+ fix
76031
+ };
75880
76032
  }, applyCli = async (cli, run, backup) => {
75881
76033
  const fail = (reason) => ({
75882
76034
  host: "cli",
@@ -75887,13 +76039,18 @@ var codexPluginRoot = (codexHome) => {
75887
76039
  const currentRoot = await run("npm", ["root", "--global"]);
75888
76040
  if (currentRoot.status !== 0 || currentRoot.stdout.trim() !== cli.root)
75889
76041
  return fail("Global npm location changed; preview again");
75890
- const cliBackup = path46.join(backup, "cli-package");
75891
- cpSync5(path46.join(cli.root, "@brainervirus/workit-cli"), cliBackup, {
76042
+ const cliBackup = path47.join(backup, "cli-package");
76043
+ cpSync5(path47.join(cli.root, "@brainervirus/workit-cli"), cliBackup, {
75892
76044
  recursive: true
75893
76045
  });
75894
- if ((await run("npm", ["install", "--global", `@brainervirus/workit-cli@${cli.latest}`])).status !== 0)
75895
- return fail(`CLI update failed; preserved package at ${cliBackup}; use npm to repair or run node ${path46.join(cliBackup, "dist/index.js")}`);
75896
- const installed = objectOrNull(path46.join(cli.root, "@brainervirus/workit-cli/package.json"));
76046
+ const install = await run("npm", [
76047
+ "install",
76048
+ "--global",
76049
+ `@brainervirus/workit-cli@${cli.latest}`
76050
+ ]);
76051
+ if (install.status !== 0)
76052
+ return fail(`CLI update failed${stderrTail(install.stderr) ? ` (${stderrTail(install.stderr)})` : ""}; preserved package at ${cliBackup}; use npm to repair or run node ${path47.join(cliBackup, "dist/index.js")}`);
76053
+ const installed = objectOrNull(path47.join(cli.root, "@brainervirus/workit-cli/package.json"));
75897
76054
  if (installed?.name !== "@brainervirus/workit-cli" || installed.version !== cli.latest)
75898
76055
  return fail(`CLI update did not verify the requested version; preserved package at ${cliBackup}`);
75899
76056
  return {
@@ -75914,7 +76071,7 @@ var init_apply = __esm(() => {
75914
76071
 
75915
76072
  // packages/workit-cli/src/upgrade/plan.ts
75916
76073
  import { existsSync as existsSync23, mkdtempSync as mkdtempSync3, rmSync as rmSync8, lstatSync as lstatSync8, readFileSync as readFileSync23 } from "node:fs";
75917
- import path47 from "node:path";
76074
+ import path48 from "node:path";
75918
76075
  import os17 from "node:os";
75919
76076
  function previewUpgrade(hosts = HOSTS2, deps = {}) {
75920
76077
  const paths = upgradePaths(deps);
@@ -75938,9 +76095,9 @@ function previewUpgrade(hosts = HOSTS2, deps = {}) {
75938
76095
  for (const file of [
75939
76096
  paths.opencodeConfig,
75940
76097
  paths.opencodeConfig + "c",
75941
- path47.join(home, ".cursor/settings.json"),
75942
- path47.join(home, ".cursor/mcp.json"),
75943
- path47.join(paths.cursorRoot, "package.json"),
76098
+ path48.join(home, ".cursor/settings.json"),
76099
+ path48.join(home, ".cursor/mcp.json"),
76100
+ path48.join(paths.cursorRoot, "package.json"),
75944
76101
  paths.codexConfig,
75945
76102
  paths.piSettings
75946
76103
  ])
@@ -76110,8 +76267,8 @@ var codexRegistered = (configFile) => {
76110
76267
  result.push(classify("opencode", pin));
76111
76268
  });
76112
76269
  guard("cursor", () => {
76113
- const cursor = objectOrNull(path47.join(paths.cursorRoot, "package.json"));
76114
- const mcp = objectOrNull(path47.join(home, ".cursor/mcp.json"));
76270
+ const cursor = objectOrNull(path48.join(paths.cursorRoot, "package.json"));
76271
+ const mcp = objectOrNull(path48.join(home, ".cursor/mcp.json"));
76115
76272
  const args = mcp?.mcpServers?.workit?.args ?? [];
76116
76273
  const arg = args.find((value) => typeof value === "string" && value.startsWith("--package="));
76117
76274
  const selector = typeof arg === "string" ? arg.slice(10) : "local";
@@ -76122,7 +76279,7 @@ var codexRegistered = (configFile) => {
76122
76279
  });
76123
76280
  return;
76124
76281
  }
76125
- const settings = objectOrNull(path47.join(home, ".cursor/settings.json"));
76282
+ const settings = objectOrNull(path48.join(home, ".cursor/settings.json"));
76126
76283
  const dirs = Array.isArray(settings?.plugin_dirs) ? settings.plugin_dirs : [];
76127
76284
  const registered = mcp?.mcpServers?.workit !== undefined || dirs.some((dir) => String(dir).replaceAll("\\", "/").replace(/\/+$/, "").endsWith("local/workit"));
76128
76285
  if (registered)
@@ -76137,7 +76294,7 @@ var codexRegistered = (configFile) => {
76137
76294
  if (typeof source !== "string")
76138
76295
  continue;
76139
76296
  const npm = /^(?:npm:)?@brainervirus\/workit-pi(?:@[^/]+)?$/.test(source);
76140
- const local = path47.isAbsolute(source) && source.replaceAll("\\", "/").endsWith("/packages/workit-pi") && object2(path47.join(source, "package.json"))?.name === "@brainervirus/workit-pi";
76297
+ const local = path48.isAbsolute(source) && source.replaceAll("\\", "/").endsWith("/packages/workit-pi") && object2(path48.join(source, "package.json"))?.name === "@brainervirus/workit-pi";
76141
76298
  if (!npm && !local)
76142
76299
  continue;
76143
76300
  const found = classify("pi", source);
@@ -76197,15 +76354,15 @@ var codexRegistered = (configFile) => {
76197
76354
  });
76198
76355
  return result;
76199
76356
  }, opencodeProbe = (deps, args) => {
76200
- const scratch = mkdtempSync3(path47.join(os17.tmpdir(), "workit-upgrade-opencode-"));
76357
+ const scratch = mkdtempSync3(path48.join(os17.tmpdir(), "workit-upgrade-opencode-"));
76201
76358
  try {
76202
76359
  return runner({
76203
76360
  ...deps,
76204
76361
  env: {
76205
76362
  ...deps.env,
76206
- XDG_DATA_HOME: path47.join(scratch, "data"),
76207
- XDG_STATE_HOME: path47.join(scratch, "state"),
76208
- XDG_CACHE_HOME: path47.join(scratch, "cache")
76363
+ XDG_DATA_HOME: path48.join(scratch, "data"),
76364
+ XDG_STATE_HOME: path48.join(scratch, "state"),
76365
+ XDG_CACHE_HOME: path48.join(scratch, "cache")
76209
76366
  }
76210
76367
  })("opencode", args);
76211
76368
  } finally {
@@ -76213,7 +76370,7 @@ var codexRegistered = (configFile) => {
76213
76370
  }
76214
76371
  }, planCli = (plan, run) => {
76215
76372
  const root = run("npm", ["root", "--global"]);
76216
- if (root.status !== 0 || !path47.isAbsolute(root.stdout.trim())) {
76373
+ if (root.status !== 0 || !path48.isAbsolute(root.stdout.trim())) {
76217
76374
  plan.skipped.push({
76218
76375
  host: "cli",
76219
76376
  reason: "global npm location could not be verified",
@@ -76221,9 +76378,9 @@ var codexRegistered = (configFile) => {
76221
76378
  });
76222
76379
  return;
76223
76380
  }
76224
- const packageFile = path47.join(root.stdout.trim(), "@brainervirus/workit-cli/package.json");
76381
+ const packageFile = path48.join(root.stdout.trim(), "@brainervirus/workit-cli/package.json");
76225
76382
  const installed = objectOrNull(packageFile);
76226
- if (installed?.name !== "@brainervirus/workit-cli" || lstatSync8(path47.dirname(packageFile)).isSymbolicLink()) {
76383
+ if (installed?.name !== "@brainervirus/workit-cli" || lstatSync8(path48.dirname(packageFile)).isSymbolicLink()) {
76227
76384
  plan.skipped.push({
76228
76385
  host: "cli",
76229
76386
  reason: "no managed global CLI install (local links preserved); use npx @brainervirus/workit-cli@latest"
@@ -76284,9 +76441,13 @@ var pad2 = (text) => text.padEnd(12), summary = (plan, permissions) => {
76284
76441
  return lines.join(`
76285
76442
  `) + `
76286
76443
  `;
76287
- }, LABEL, table = (hosts) => [
76444
+ }, LABEL, reasonFor = (entry) => {
76445
+ const label = LABEL[entry.status];
76446
+ const head = entry.reason.slice(0, label.length);
76447
+ return entry.status !== "failed" && head.toLowerCase() === label.toLowerCase() && !/^[a-z]/i.test(entry.reason[label.length] ?? "") ? entry.reason.slice(label.length).replace(/^[\s:;,-]+/, "") : entry.reason;
76448
+ }, table = (hosts) => [
76288
76449
  "Result:",
76289
- ...hosts.map((entry) => ` ${pad2(entry.host)}${LABEL[entry.status].padEnd(16)}${entry.reason}${entry.fix && entry.status !== "updated" && entry.status !== "current" ? `
76450
+ ...hosts.map((entry) => ` ${pad2(entry.host)}${LABEL[entry.status].padEnd(16)}${reasonFor(entry)}${entry.fix && entry.status !== "updated" && entry.status !== "current" ? `
76290
76451
  ${pad2("")}${"".padEnd(16)}fix: ${entry.fix}` : ""}`)
76291
76452
  ].join(`
76292
76453
  `) + `
@@ -76393,9 +76554,9 @@ Nothing changed.
76393
76554
  permissionsOk = written.every((entry) => entry.status === "written");
76394
76555
  for (const entry of written)
76395
76556
  result.hosts.push({
76396
- host: entry.host,
76557
+ host: "permissions",
76397
76558
  status: entry.status === "written" ? "updated" : "failed",
76398
- reason: `permission block ${entry.status === "written" ? "refreshed" : entry.status} in ${entry.file}`,
76559
+ reason: `${entry.host} block ${entry.status === "written" ? "refreshed" : entry.status} in ${entry.file}`,
76399
76560
  ...entry.status === "written" ? {} : { fix: `workit setup --hosts=${entry.host}` }
76400
76561
  });
76401
76562
  }
@@ -76521,7 +76682,7 @@ var init_launch = __esm(() => {
76521
76682
  // packages/workit-core/src/knowledge.ts
76522
76683
  import { spawnSync as spawnSync18 } from "node:child_process";
76523
76684
  import fs20 from "node:fs";
76524
- import path48 from "node:path";
76685
+ import path49 from "node:path";
76525
76686
  function lintKnowledge(root) {
76526
76687
  const seen = new Set;
76527
76688
  const unreadable = [];
@@ -76625,7 +76786,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
76625
76786
  const end = lines.indexOf("---", 1);
76626
76787
  return end === -1 ? lines : [...lines.slice(0, end + 1).map(() => ""), ...lines.slice(end + 1)];
76627
76788
  }, read = (root, file) => {
76628
- const full = path48.join(root, file);
76789
+ const full = path49.join(root, file);
76629
76790
  try {
76630
76791
  fs20.lstatSync(full);
76631
76792
  } catch {
@@ -76666,7 +76827,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
76666
76827
  }
76667
76828
  }, brokenLinks = (root, doc, tracked) => {
76668
76829
  const findings = [];
76669
- const base = path48.dirname(path48.join(root, doc.file));
76830
+ const base = path49.dirname(path49.join(root, doc.file));
76670
76831
  const missing = (target, line, how) => findings.push({
76671
76832
  rule: "broken-link",
76672
76833
  file: doc.file,
@@ -76685,7 +76846,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
76685
76846
  const local = localTarget(target);
76686
76847
  if (!local)
76687
76848
  continue;
76688
- const resolved = local.startsWith("/") ? path48.join(root, local) : path48.resolve(base, local);
76849
+ const resolved = local.startsWith("/") ? path49.join(root, local) : path49.resolve(base, local);
76689
76850
  if (!exists2(resolved))
76690
76851
  missing(target, index + 1, "link");
76691
76852
  }
@@ -76695,9 +76856,9 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
76695
76856
  continue;
76696
76857
  const relative = /^\.\.?\//.test(candidate);
76697
76858
  const first = candidate.split("/")[0];
76698
- if (!relative && !(tracked ? tracked.has(first) : exists2(path48.join(root, first))))
76859
+ if (!relative && !(tracked ? tracked.has(first) : exists2(path49.join(root, first))))
76699
76860
  continue;
76700
- const resolved = relative ? path48.resolve(base, candidate) : path48.join(root, candidate);
76861
+ const resolved = relative ? path49.resolve(base, candidate) : path49.join(root, candidate);
76701
76862
  if (!exists2(resolved))
76702
76863
  missing(span, index + 1, "pointer");
76703
76864
  }
@@ -76849,12 +77010,12 @@ async function run7(argv, io) {
76849
77010
  };
76850
77011
  }
76851
77012
  }
76852
- const report = runDoctor({
77013
+ const report = createProgress({ stream: process.stderr, json: io.json }).runSync("Checking Workit (workit doctor)", () => runDoctor({
76853
77014
  host: "cli",
76854
77015
  cwd: io.cwd,
76855
77016
  workspaceRoot: root,
76856
77017
  cliVersion: package_default.version
76857
- });
77018
+ }), (done) => done.ok ? "done" : "failed");
76858
77019
  let knowledge = null;
76859
77020
  try {
76860
77021
  knowledge = lintKnowledge(root);
@@ -76910,6 +77071,7 @@ var init_doctor2 = __esm(() => {
76910
77071
  init_knowledge();
76911
77072
  init_store_lock();
76912
77073
  init_output();
77074
+ init_progress();
76913
77075
  init_prompt();
76914
77076
  init_task();
76915
77077
  });
@@ -77019,11 +77181,11 @@ var init_redact = __esm(() => {
77019
77181
  });
77020
77182
 
77021
77183
  // packages/workit-core/src/checks.ts
77022
- import { spawn as spawn2, spawnSync as spawnSync19 } from "node:child_process";
77184
+ import { spawn as spawn3, spawnSync as spawnSync19 } from "node:child_process";
77023
77185
  import { createHash as createHash17 } from "node:crypto";
77024
77186
  import fs21 from "node:fs";
77025
77187
  import os18 from "node:os";
77026
- import path49 from "node:path";
77188
+ import path50 from "node:path";
77027
77189
  import { StringDecoder } from "node:string_decoder";
77028
77190
  function tailLines(text, lines = TAIL_LINES) {
77029
77191
  const all = text.replace(/\r\n?/gu, `
@@ -77143,7 +77305,7 @@ function planSpawn(argv, options) {
77143
77305
  return { file: argv[0], args: [], verbatim: false, shell: true };
77144
77306
  if (options.platform !== "win32")
77145
77307
  return { file: argv[0], args: argv.slice(1), verbatim: false, shell: false };
77146
- const win = path49.win32;
77308
+ const win = path50.win32;
77147
77309
  const isFile = options.isFile ?? ((file) => {
77148
77310
  try {
77149
77311
  return fs21.statSync(file).isFile();
@@ -77248,7 +77410,7 @@ function runCheckCommand(argv, options) {
77248
77410
  shell: plan.shell
77249
77411
  };
77250
77412
  try {
77251
- child = spawn2(plan.file, plan.args, spawnOptions);
77413
+ child = spawn3(plan.file, plan.args, spawnOptions);
77252
77414
  } catch (error) {
77253
77415
  finish(null, null, error.code ?? error.message);
77254
77416
  return;
@@ -77305,10 +77467,10 @@ function runCheckCommand(argv, options) {
77305
77467
  function storeLog(storeRoot, log) {
77306
77468
  const digest = logDigest(log);
77307
77469
  const ref = `blobs/logs/${digest.slice("sha256:".length)}.log`;
77308
- const file = path49.join(storeRoot, ref);
77470
+ const file = path50.join(storeRoot, ref);
77309
77471
  try {
77310
77472
  if (!fs21.existsSync(file)) {
77311
- fs21.mkdirSync(path49.dirname(file), { recursive: true });
77473
+ fs21.mkdirSync(path50.dirname(file), { recursive: true });
77312
77474
  const temp = `${file}.${process.pid}.${Date.now()}.tmp`;
77313
77475
  fs21.writeFileSync(temp, log, { mode: 384 });
77314
77476
  fs21.renameSync(temp, file);
@@ -77321,7 +77483,7 @@ function storeLog(storeRoot, log) {
77321
77483
  function pruneCheckLogs(storeRoot, options = {}) {
77322
77484
  const limits = { ...LOG_RETENTION, ...options.retention };
77323
77485
  const now = options.now ?? Date.now();
77324
- const dir = path49.join(storeRoot, "blobs", "logs");
77486
+ const dir = path50.join(storeRoot, "blobs", "logs");
77325
77487
  const report = { removed: 0, removedBytes: 0, kept: 0 };
77326
77488
  let names;
77327
77489
  try {
@@ -77331,7 +77493,7 @@ function pruneCheckLogs(storeRoot, options = {}) {
77331
77493
  }
77332
77494
  const files = names.flatMap((name) => {
77333
77495
  try {
77334
- const stat = fs21.statSync(path49.join(dir, name));
77496
+ const stat = fs21.statSync(path50.join(dir, name));
77335
77497
  return stat.isFile() ? [{ name, size: stat.size, mtimeMs: stat.mtimeMs }] : [];
77336
77498
  } catch {
77337
77499
  return [];
@@ -77350,7 +77512,7 @@ function pruneCheckLogs(storeRoot, options = {}) {
77350
77512
  continue;
77351
77513
  if (!options.dryRun)
77352
77514
  try {
77353
- fs21.rmSync(path49.join(dir, file.name), { force: true });
77515
+ fs21.rmSync(path50.join(dir, file.name), { force: true });
77354
77516
  } catch {
77355
77517
  continue;
77356
77518
  }
@@ -78002,12 +78164,12 @@ var init_workspace = __esm(() => {
78002
78164
 
78003
78165
  // packages/workit-core/src/core/heavy-rules.ts
78004
78166
  import fs22 from "node:fs";
78005
- import path50 from "node:path";
78167
+ import path51 from "node:path";
78006
78168
  function gitTop(cwd) {
78007
- for (let dir = path50.resolve(cwd);; dir = path50.dirname(dir)) {
78008
- if (fs22.existsSync(path50.join(dir, ".git")))
78169
+ for (let dir = path51.resolve(cwd);; dir = path51.dirname(dir)) {
78170
+ if (fs22.existsSync(path51.join(dir, ".git")))
78009
78171
  return dir;
78010
- if (path50.dirname(dir) === dir)
78172
+ if (path51.dirname(dir) === dir)
78011
78173
  return null;
78012
78174
  }
78013
78175
  }
@@ -78049,18 +78211,18 @@ var init_heavy_rules = () => {};
78049
78211
  // packages/workit-core/src/core/heavy.ts
78050
78212
  import fs23 from "node:fs";
78051
78213
  import os19 from "node:os";
78052
- import path51 from "node:path";
78214
+ import path52 from "node:path";
78053
78215
  function stateDir2(env, platform = process.platform) {
78054
78216
  if (env.WORKFLOW_TOOLKIT_STATE)
78055
78217
  return env.WORKFLOW_TOOLKIT_STATE;
78056
78218
  if (env.XDG_STATE_HOME)
78057
- return path51.join(env.XDG_STATE_HOME, "workit");
78219
+ return path52.join(env.XDG_STATE_HOME, "workit");
78058
78220
  const home = env.HOME || os19.homedir();
78059
78221
  if (platform === "darwin")
78060
- return path51.join(home, "Library", "Application Support", "workit");
78222
+ return path52.join(home, "Library", "Application Support", "workit");
78061
78223
  if (platform === "win32")
78062
- return path51.join(env.LOCALAPPDATA ?? path51.join(home, "AppData", "Local"), "workit");
78063
- return path51.join(home, ".local", "state", "workit");
78224
+ return path52.join(env.LOCALAPPDATA ?? path52.join(home, "AppData", "Local"), "workit");
78225
+ return path52.join(home, ".local", "state", "workit");
78064
78226
  }
78065
78227
  function positional(words, from, values = PM_VALUES) {
78066
78228
  let index = from;
@@ -78200,7 +78362,7 @@ function machinePatterns(env) {
78200
78362
  return isRecord8(value) ? stringList2(value.patterns) : [];
78201
78363
  }
78202
78364
  function repoPatterns(cwd) {
78203
- return repoHeavyCommands(gitTop(cwd) ?? path51.resolve(cwd));
78365
+ return repoHeavyCommands(gitTop(cwd) ?? path52.resolve(cwd));
78204
78366
  }
78205
78367
  function heavyLines(lines, options) {
78206
78368
  const found = [];
@@ -78279,7 +78441,7 @@ function leaseRewrite(command) {
78279
78441
  return null;
78280
78442
  return `${prefix}workit check --heavy -- ${rest}`;
78281
78443
  }
78282
- var HEAVY_COMMANDS_FILE = "heavy-commands.json", heavyCommandsFile = (env) => path51.join(stateDir2(env), HEAVY_COMMANDS_FILE), HEAVY_SCRIPT, INFO_FLAGS, WATCH_FLAG, WATCH_SCRIPT, sub = (...names) => new Set(names), TOOLS, PM_VALUES, baseName2 = (word) => (word?.split(/[\\/]/u).at(-1) ?? "").toLowerCase().replace(/\.(?:exe|cmd|bat|ps1)$/u, ""), WORKIT, PYTHONS, NPM_INSTALL, NPM_RUN, NPM_TEST, EXEC, globWord = (word) => new RegExp(`^${word.replace(/[.+?^${}()|[\]\\]/gu, "\\$&").replaceAll("*", ".*")}$`, "u"), matches2 = (matchers, words) => matchers.length <= words.length && matchers.every((matcher, index) => index === 0 ? matcher.test(words[0]) || matcher.test(baseName2(words[0])) : matcher.test(words[index])), readJson2 = (file) => {
78444
+ var HEAVY_COMMANDS_FILE = "heavy-commands.json", heavyCommandsFile = (env) => path52.join(stateDir2(env), HEAVY_COMMANDS_FILE), HEAVY_SCRIPT, INFO_FLAGS, WATCH_FLAG, WATCH_SCRIPT, sub = (...names) => new Set(names), TOOLS, PM_VALUES, baseName2 = (word) => (word?.split(/[\\/]/u).at(-1) ?? "").toLowerCase().replace(/\.(?:exe|cmd|bat|ps1)$/u, ""), WORKIT, PYTHONS, NPM_INSTALL, NPM_RUN, NPM_TEST, EXEC, globWord = (word) => new RegExp(`^${word.replace(/[.+?^${}()|[\]\\]/gu, "\\$&").replaceAll("*", ".*")}$`, "u"), matches2 = (matchers, words) => matchers.length <= words.length && matchers.every((matcher, index) => index === 0 ? matcher.test(words[0]) || matcher.test(baseName2(words[0])) : matcher.test(words[index])), readJson2 = (file) => {
78283
78445
  try {
78284
78446
  return JSON.parse(fs23.readFileSync(file, "utf8"));
78285
78447
  } catch {
@@ -78426,7 +78588,7 @@ var init_heavy = __esm(() => {
78426
78588
  import { randomUUID as randomUUID5 } from "node:crypto";
78427
78589
  import fs24 from "node:fs";
78428
78590
  import os20 from "node:os";
78429
- import path52 from "node:path";
78591
+ import path53 from "node:path";
78430
78592
  function memoryValue(value, host) {
78431
78593
  const text = typeof value === "number" ? String(value) : typeof value === "string" ? value : "";
78432
78594
  const percent = PERCENT.exec(text.trim());
@@ -78622,7 +78784,7 @@ function tryOnce(options, record, reclaimed) {
78622
78784
  const text = `${JSON.stringify(record)}
78623
78785
  `;
78624
78786
  for (let slot = 0;slot < options.slots; slot += 1) {
78625
- const file = path52.join(options.dir, `slot-${slot}.json`);
78787
+ const file = path53.join(options.dir, `slot-${slot}.json`);
78626
78788
  for (let attempt = 0;attempt < 2; attempt += 1) {
78627
78789
  try {
78628
78790
  const fd = fs24.openSync(file, "wx", 384);
@@ -78667,7 +78829,7 @@ function leaseQueue(dir, probe = {}) {
78667
78829
  }
78668
78830
  const entries = [];
78669
78831
  for (const name of names.filter((item) => item.endsWith(".json")).toSorted()) {
78670
- const file = path52.join(queueDir(dir), name);
78832
+ const file = path53.join(queueDir(dir), name);
78671
78833
  const record = parseLease(readText5(file));
78672
78834
  if (!record)
78673
78835
  continue;
@@ -78683,9 +78845,9 @@ function leaseQueue(dir, probe = {}) {
78683
78845
  function waitersAhead(options, own) {
78684
78846
  let ahead = 0;
78685
78847
  for (const entry of leaseQueue(options.dir, options.probe)) {
78686
- if (path52.basename(entry.file) >= own)
78848
+ if (path53.basename(entry.file) >= own)
78687
78849
  break;
78688
- if (!TICKET.test(path52.basename(entry.file)))
78850
+ if (!TICKET.test(path53.basename(entry.file)))
78689
78851
  continue;
78690
78852
  if (entry.stale && reclaim(entry.file, (current) => !current || staleReason(current, options.probe) !== null))
78691
78853
  continue;
@@ -78697,7 +78859,7 @@ function liveHolders(options) {
78697
78859
  return leaseSlots(options.dir, options.slots, options.probe).filter((slot) => slot.holder && !slot.stale).map((slot) => slot.holder);
78698
78860
  }
78699
78861
  function writeTicket(file, record) {
78700
- fs24.mkdirSync(path52.dirname(file), { recursive: true, mode: 448 });
78862
+ fs24.mkdirSync(path53.dirname(file), { recursive: true, mode: 448 });
78701
78863
  fs24.writeFileSync(file, `${JSON.stringify(record)}
78702
78864
  `, { mode: 384 });
78703
78865
  }
@@ -78742,7 +78904,7 @@ async function acquireLease(options) {
78742
78904
  const reclaimed = [];
78743
78905
  let waitedOn = [];
78744
78906
  const name = ticketName(started, record.id);
78745
- const ticket = path52.join(queueDir(options.dir), name);
78907
+ const ticket = path53.join(queueDir(options.dir), name);
78746
78908
  const ticketRecord = {
78747
78909
  ...record,
78748
78910
  maxAgeMs: options.waitMs + 60000
@@ -78863,7 +79025,7 @@ function heldLease(dir, id, options = {}) {
78863
79025
  for (const name of names) {
78864
79026
  if (!/^slot-\d+\.json$/u.test(name))
78865
79027
  continue;
78866
- const lease = parseLease(readText5(path52.join(dir, name)));
79028
+ const lease = parseLease(readText5(path53.join(dir, name)));
78867
79029
  if (lease?.id === id && !staleReason(lease, options.probe) && (options.ancestor ?? isAncestor)(lease.pid))
78868
79030
  return lease;
78869
79031
  }
@@ -78918,10 +79080,10 @@ async function runScoped(run, wrapper, sinks) {
78918
79080
  }
78919
79081
  function firstNotice(env, session, key, now = Date.now()) {
78920
79082
  const id = (session ?? `ppid-${process.ppid}`).replace(/[^A-Za-z0-9_.-]/gu, "_").slice(0, 120);
78921
- const dir = path52.join(stateDir2(env), "notices");
79083
+ const dir = path53.join(stateDir2(env), "notices");
78922
79084
  try {
78923
79085
  fs24.mkdirSync(dir, { recursive: true, mode: 448 });
78924
- fs24.writeFileSync(path52.join(dir, `${key}-${id}`), `${new Date(now).toISOString()}
79086
+ fs24.writeFileSync(path53.join(dir, `${key}-${id}`), `${new Date(now).toISOString()}
78925
79087
  `, {
78926
79088
  flag: "wx",
78927
79089
  mode: 384
@@ -78931,7 +79093,7 @@ function firstNotice(env, session, key, now = Date.now()) {
78931
79093
  }
78932
79094
  try {
78933
79095
  for (const name of fs24.readdirSync(dir)) {
78934
- const file = path52.join(dir, name);
79096
+ const file = path53.join(dir, name);
78935
79097
  if (now - fs24.statSync(file).mtimeMs > NOTICE_TTL_MS)
78936
79098
  fs24.rmSync(file, { force: true });
78937
79099
  }
@@ -78941,7 +79103,7 @@ function firstNotice(env, session, key, now = Date.now()) {
78941
79103
  function leaseSlots(dir, slots, probe = {}) {
78942
79104
  const states = [];
78943
79105
  for (let slot = 0;slot < slots; slot += 1) {
78944
- const lease = parseLease(readText5(path52.join(dir, `slot-${slot}.json`)));
79106
+ const lease = parseLease(readText5(path53.join(dir, `slot-${slot}.json`)));
78945
79107
  states.push({
78946
79108
  slot,
78947
79109
  holder: lease ? holderOf(lease) : null,
@@ -78953,7 +79115,7 @@ function leaseSlots(dir, slots, probe = {}) {
78953
79115
  var DEFAULT_HEAVY_CHECKS, DEFAULT_LIGHT_CHECKS, DEFAULT_SLOTS = 1, DEFAULT_WAIT_S = 1800, DEFAULT_MEMORY_SHARE = 0.4, DEFAULT_CPU_SHARE = 0.7, MAX_SLOTS = 64, UNREADABLE_TTL_MS = 30000, GUARD_TTL_MS = 30000, hostShape = () => ({
78954
79116
  totalMemBytes: os20.totalmem(),
78955
79117
  cpus: Math.max(1, os20.availableParallelism?.() ?? os20.cpus().length)
78956
- }), isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), SIZE, PERCENT, UNITS, leaseDir = (env) => path52.join(stateDir2(env), "leases"), readText5 = (file) => {
79118
+ }), isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), SIZE, PERCENT, UNITS, leaseDir = (env) => path53.join(stateDir2(env), "leases"), readText5 = (file) => {
78957
79119
  try {
78958
79120
  return fs24.readFileSync(file, "utf8");
78959
79121
  } catch {
@@ -78984,7 +79146,7 @@ var DEFAULT_HEAVY_CHECKS, DEFAULT_LIGHT_CHECKS, DEFAULT_SLOTS = 1, DEFAULT_WAIT_
78984
79146
  cwd: lease.cwd,
78985
79147
  session: lease.session,
78986
79148
  startedAt: lease.startedAt
78987
- }), realClock, queueDir = (dir) => path52.join(dir, "queue"), TICKET, ticketName = (now, id) => `${String(now).padStart(15, "0")}-${String(process.hrtime.bigint() % 10n ** 16n).padStart(16, "0")}-${id}.json`, SCOPE_START_FAILURE, NOTICE_TTL_MS;
79149
+ }), realClock, queueDir = (dir) => path53.join(dir, "queue"), TICKET, ticketName = (now, id) => `${String(now).padStart(15, "0")}-${String(process.hrtime.bigint() % 10n ** 16n).padStart(16, "0")}-${id}.json`, SCOPE_START_FAILURE, NOTICE_TTL_MS;
78988
79150
  var init_resources = __esm(() => {
78989
79151
  init_checks3();
78990
79152
  init_heavy();
@@ -79014,7 +79176,7 @@ __export(exports_check, {
79014
79176
  workspaceResources: () => workspaceResources
79015
79177
  });
79016
79178
  import os21 from "node:os";
79017
- import path53 from "node:path";
79179
+ import path54 from "node:path";
79018
79180
  function parse6(argv) {
79019
79181
  const split = argv.indexOf("--");
79020
79182
  const head = split >= 0 ? argv.slice(0, split) : [...argv];
@@ -79245,7 +79407,7 @@ ${footer}`;
79245
79407
  }
79246
79408
  async function workspaceResources(io) {
79247
79409
  const env = io.env;
79248
- const dir = env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path53.join(env.XDG_CONFIG_HOME || path53.join(env.HOME || os21.homedir(), ".config"), "workit");
79410
+ const dir = env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path54.join(env.XDG_CONFIG_HOME || path54.join(env.HOME || os21.homedir(), ".config"), "workit");
79249
79411
  try {
79250
79412
  await Promise.resolve().then(() => init_workspaces());
79251
79413
  const workspace = resolveWorkspaceFrom(io.cwd, dir, env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined);
@@ -79387,7 +79549,7 @@ async function run12(argv, io) {
79387
79549
  if (options.shell && command.length !== 1)
79388
79550
  return emit(io, fail2("invalid_input", '--shell takes the command as one string: workit check --shell -- "<cmd>"'));
79389
79551
  }
79390
- const relCwd = posix(path53.relative(top, runCwd));
79552
+ const relCwd = posix(path54.relative(top, runCwd));
79391
79553
  const configured = !options.shell && matchesNamedCheck(config, name, command, relCwd);
79392
79554
  const shadowed = !configured && name !== null ? config.checks.find((item) => item.name === name) : undefined;
79393
79555
  if (shadowed)
@@ -79452,7 +79614,7 @@ async function run12(argv, io) {
79452
79614
  const modifiedWorktree = key.tree !== null && treeAfter !== key.tree;
79453
79615
  const store = storeRoot(io.cwd);
79454
79616
  const blob = store.ok ? storeLog(store.value.root, result.log) : null;
79455
- const logPath = store.ok && blob ? path53.join(store.value.root, blob.ref) : null;
79617
+ const logPath = store.ok && blob ? path54.join(store.value.root, blob.ref) : null;
79456
79618
  const tail = tailLines(result.log, TAIL_LINES);
79457
79619
  const passed = result.exitCode === 0 && !result.timedOut;
79458
79620
  const bounded = boundedArgv(command);
@@ -79567,7 +79729,7 @@ async function run12(argv, io) {
79567
79729
  return recordError.code === "busy" ? 4 : recordError.code === "invalid_input" ? 2 : 5;
79568
79730
  return 0;
79569
79731
  }
79570
- var USAGE6 = 'workit check <name> [--full] [--wait <dur> | --no-wait] [--no-lease --reason "<why>"] | workit check [--name <n>] [--shell] [--heavy] [--full] [--wait <dur> | --no-wait] [--timeout <s>] [--task <id>] [--json] -- <cmd…>', OUTPUT_LINES = 60, MAX_UNVERIFIED_RUN_MS, RECORD_TAIL_LINES = 20, RECORD_TAIL_CHARS = 200, posix = (value) => value.split(path53.sep).join("/") || ".", ENGINE_CODES2, FINGERPRINT_VARS, ANSI_COLOR, WARNING_LINE, NO_WARNINGS, STDERR_TAIL_LINES = 10, STDERR_KEEP_CHARS = 65536, FAILURE_LINE, MAX_FAILURE_LINES = 15;
79732
+ var USAGE6 = 'workit check <name> [--full] [--wait <dur> | --no-wait] [--no-lease --reason "<why>"] | workit check [--name <n>] [--shell] [--heavy] [--full] [--wait <dur> | --no-wait] [--timeout <s>] [--task <id>] [--json] -- <cmd…>', OUTPUT_LINES = 60, MAX_UNVERIFIED_RUN_MS, RECORD_TAIL_LINES = 20, RECORD_TAIL_CHARS = 200, posix = (value) => value.split(path54.sep).join("/") || ".", ENGINE_CODES2, FINGERPRINT_VARS, ANSI_COLOR, WARNING_LINE, NO_WARNINGS, STDERR_TAIL_LINES = 10, STDERR_KEEP_CHARS = 65536, FAILURE_LINE, MAX_FAILURE_LINES = 15;
79571
79733
  var init_check = __esm(() => {
79572
79734
  init_check_config();
79573
79735
  init_checks3();
@@ -79598,7 +79760,7 @@ __export(exports_lock, {
79598
79760
  run: () => run13
79599
79761
  });
79600
79762
  import fs25 from "node:fs";
79601
- import path54 from "node:path";
79763
+ import path55 from "node:path";
79602
79764
  async function settingsFor(io) {
79603
79765
  const workspace = await workspaceResources(io);
79604
79766
  const config = loadCheckConfig(io.cwd);
@@ -79690,7 +79852,7 @@ function readPatterns(file) {
79690
79852
  return { patterns: [] };
79691
79853
  }
79692
79854
  function writePatterns(file, value) {
79693
- fs25.mkdirSync(path54.dirname(file), { recursive: true, mode: 448 });
79855
+ fs25.mkdirSync(path55.dirname(file), { recursive: true, mode: 448 });
79694
79856
  const temp = `${file}.${process.pid}.tmp`;
79695
79857
  fs25.writeFileSync(temp, `${JSON.stringify(value, null, 2)}
79696
79858
  `, { mode: 384 });
@@ -79778,7 +79940,7 @@ __export(exports_models, {
79778
79940
  });
79779
79941
  import { existsSync as existsSync25, readdirSync as readdirSync13, readFileSync as readFileSync24, statSync as statSync9 } from "node:fs";
79780
79942
  import os22 from "node:os";
79781
- import path55 from "node:path";
79943
+ import path56 from "node:path";
79782
79944
  async function run14(argv, io) {
79783
79945
  const [sub, ...args] = argv.filter((arg) => arg !== "--json");
79784
79946
  if (sub !== "show")
@@ -79853,20 +80015,20 @@ var USAGE8 = "workit models show [--role <role>] [--tier <tier>] [--host <host>]
79853
80015
  } catch {}
79854
80016
  return found;
79855
80017
  }, matches3 = (ran, configured) => ran.toLowerCase().includes(configured.toLowerCase()), usageReport = (cwd, env, days) => {
79856
- const projects = path55.join(env.CLAUDE_CONFIG_DIR || path55.join(env.HOME || os22.homedir(), ".claude"), "projects");
80018
+ const projects = path56.join(env.CLAUDE_CONFIG_DIR || path56.join(env.HOME || os22.homedir(), ".claude"), "projects");
79857
80019
  const since = Date.now() - days * 86400000;
79858
80020
  const types = {};
79859
80021
  let agents = 0;
79860
80022
  const dirs = (dir) => {
79861
80023
  try {
79862
- return readdirSync13(dir).map((name) => path55.join(dir, name));
80024
+ return readdirSync13(dir).map((name) => path56.join(dir, name));
79863
80025
  } catch {
79864
80026
  return [];
79865
80027
  }
79866
80028
  };
79867
80029
  for (const project of dirs(projects))
79868
80030
  for (const session of dirs(project))
79869
- for (const meta of dirs(path55.join(session, "subagents")).filter((f) => f.endsWith(".meta.json"))) {
80031
+ for (const meta of dirs(path56.join(session, "subagents")).filter((f) => f.endsWith(".meta.json"))) {
79870
80032
  try {
79871
80033
  if (statSync9(meta).mtimeMs < since)
79872
80034
  continue;
@@ -80012,7 +80174,7 @@ var success2 = (data) => ({ ok: true, data }), failure3 = (code, error, unblock)
80012
80174
  // packages/workit-core/src/git/ops.ts
80013
80175
  import { spawnSync as spawnSync20 } from "node:child_process";
80014
80176
  import { existsSync as existsSync26, readFileSync as readFileSync25 } from "node:fs";
80015
- import path56 from "node:path";
80177
+ import path57 from "node:path";
80016
80178
  function operationInProgress(cwd) {
80017
80179
  const markers = [
80018
80180
  ["rebase-merge", "rebase"],
@@ -80025,18 +80187,18 @@ function operationInProgress(cwd) {
80025
80187
  if (!run.ok)
80026
80188
  return null;
80027
80189
  const found = run.stdout.split(`
80028
- `).map((line) => path56.resolve(cwd, line.trim()));
80190
+ `).map((line) => path57.resolve(cwd, line.trim()));
80029
80191
  const conflicted = () => git5(cwd, ["ls-files", "-u"]).stdout.trim() !== "";
80030
80192
  for (const [index, [, operation]] of markers.entries()) {
80031
80193
  const marker = found[index];
80032
80194
  if (!marker || !existsSync26(marker))
80033
80195
  continue;
80034
- if (index === 1 && existsSync26(path56.join(marker, "applying")))
80196
+ if (index === 1 && existsSync26(path57.join(marker, "applying")))
80035
80197
  return { operation: "am", commitAllowed: false, branch: null };
80036
- if (index === 0 && existsSync26(path56.join(marker, "amend")) && !conflicted()) {
80198
+ if (index === 0 && existsSync26(path57.join(marker, "amend")) && !conflicted()) {
80037
80199
  let headName = "";
80038
80200
  try {
80039
- headName = readFileSync25(path56.join(marker, "head-name"), "utf8").trim();
80201
+ headName = readFileSync25(path57.join(marker, "head-name"), "utf8").trim();
80040
80202
  } catch {}
80041
80203
  const branch = headName.startsWith("refs/heads/") ? headName.slice("refs/heads/".length) : null;
80042
80204
  return { operation, commitAllowed: branch !== null, branch };
@@ -80364,7 +80526,7 @@ function gitCommit(cwd, input) {
80364
80526
  if (paths.some((value) => value.startsWith("-") || !value.trim()))
80365
80527
  return failure3("invalid_input", "paths must not be empty or start with -");
80366
80528
  const tracked = new Set(nulList(git5(cwd, ["ls-files", "-z", "--", ...paths]).stdout));
80367
- const addable = paths.filter((value) => existsSync26(path56.resolve(cwd, value)) || [...tracked].some((file) => file === value || file.startsWith(`${value}/`)));
80529
+ const addable = paths.filter((value) => existsSync26(path57.resolve(cwd, value)) || [...tracked].some((file) => file === value || file.startsWith(`${value}/`)));
80368
80530
  if (addable.length) {
80369
80531
  const added = git5(cwd, ["add", "-A", "--", ...addable]);
80370
80532
  if (!added.ok)
@@ -80903,12 +81065,12 @@ var init_ops = __esm(() => {
80903
81065
 
80904
81066
  // packages/workit-core/src/verdict-cover.ts
80905
81067
  import fs26 from "node:fs";
80906
- import path57 from "node:path";
81068
+ import path58 from "node:path";
80907
81069
  function chainsAbove(cwd, branch) {
80908
81070
  const root = storeRoot(cwd);
80909
81071
  if (!root.ok)
80910
81072
  return [];
80911
- const dir = path57.join(root.value.root, "stacks");
81073
+ const dir = path58.join(root.value.root, "stacks");
80912
81074
  let names = [];
80913
81075
  try {
80914
81076
  names = fs26.readdirSync(dir).filter((name) => name.endsWith(".json"));
@@ -80919,7 +81081,7 @@ function chainsAbove(cwd, branch) {
80919
81081
  for (const name of names.toSorted()) {
80920
81082
  let parsed;
80921
81083
  try {
80922
- parsed = JSON.parse(fs26.readFileSync(path57.join(dir, name), "utf8"));
81084
+ parsed = JSON.parse(fs26.readFileSync(path58.join(dir, name), "utf8"));
80923
81085
  } catch {
80924
81086
  continue;
80925
81087
  }
@@ -81075,10 +81237,10 @@ var init_check_evidence = __esm(() => {
81075
81237
 
81076
81238
  // packages/workit-core/src/forge/reruns.ts
81077
81239
  import fs27 from "node:fs";
81078
- import path58 from "node:path";
81240
+ import path59 from "node:path";
81079
81241
  function rerunLogPath(cwd) {
81080
81242
  const common = gitCommonDir(cwd);
81081
- return common ? path58.join(common, "workit", "ci-reruns.jsonl") : null;
81243
+ return common ? path59.join(common, "workit", "ci-reruns.jsonl") : null;
81082
81244
  }
81083
81245
  function rerunCounts(cwd, key) {
81084
81246
  const counts = new Map;
@@ -81113,7 +81275,7 @@ function recordReruns(cwd, rows) {
81113
81275
  if (!file)
81114
81276
  return false;
81115
81277
  try {
81116
- fs27.mkdirSync(path58.dirname(file), { recursive: true });
81278
+ fs27.mkdirSync(path59.dirname(file), { recursive: true });
81117
81279
  fs27.appendFileSync(file, rows.map((row) => `${JSON.stringify(row)}
81118
81280
  `).join(""));
81119
81281
  return true;
@@ -81126,7 +81288,7 @@ function withRerunLock(cwd, fn) {
81126
81288
  if (!file)
81127
81289
  return fn();
81128
81290
  const lock = `${file.slice(0, -".jsonl".length)}.lock`;
81129
- fs27.mkdirSync(path58.dirname(lock), { recursive: true });
81291
+ fs27.mkdirSync(path59.dirname(lock), { recursive: true });
81130
81292
  const until = Date.now() + LOCK_WAIT_MS2;
81131
81293
  for (;; ) {
81132
81294
  try {
@@ -82122,7 +82284,7 @@ var init_pr_ops = __esm(() => {
82122
82284
  import { spawnSync as spawnSync22 } from "node:child_process";
82123
82285
  import { createHash as createHash18, randomBytes as randomBytes4 } from "node:crypto";
82124
82286
  import fs28 from "node:fs";
82125
- import path59 from "node:path";
82287
+ import path60 from "node:path";
82126
82288
  function worktreeOf(cwd, branch) {
82127
82289
  const list = gitRun3(cwd, ["worktree", "list", "--porcelain"]);
82128
82290
  if (!list.ok)
@@ -82171,7 +82333,7 @@ function gitRestack(cwd, input) {
82171
82333
  error: "no store root"
82172
82334
  };
82173
82335
  fs28.mkdirSync(scratch, { recursive: true });
82174
- dir = path59.join(scratch, `${input.branch.replace(/[^A-Za-z0-9._-]+/gu, "_").slice(0, 40)}-${randomBytes4(4).toString("hex")}`);
82336
+ dir = path60.join(scratch, `${input.branch.replace(/[^A-Za-z0-9._-]+/gu, "_").slice(0, 40)}-${randomBytes4(4).toString("hex")}`);
82175
82337
  const added = gitRun3(cwd, ["worktree", "add", "-q", dir, input.branch], GIT_TIMEOUTS.worktree);
82176
82338
  if (!added.ok)
82177
82339
  return {
@@ -82227,7 +82389,7 @@ function pruneScratch(cwd) {
82227
82389
  if (!scratch || !fs28.existsSync(scratch))
82228
82390
  return;
82229
82391
  for (const name of fs28.readdirSync(scratch)) {
82230
- const dir = path59.join(scratch, name);
82392
+ const dir = path60.join(scratch, name);
82231
82393
  if (!rebaseInProgress(dir) && !trackedDirt(dir))
82232
82394
  gitRun3(cwd, ["worktree", "remove", "--force", dir]);
82233
82395
  }
@@ -82237,7 +82399,7 @@ function stacksDir(cwd) {
82237
82399
  const root = storeRoot(cwd);
82238
82400
  if (!root.ok)
82239
82401
  return stackFail(root.code, root.error, root.unblock);
82240
- return { ok: true, data: path59.join(root.value.root, "stacks") };
82402
+ return { ok: true, data: path60.join(root.value.root, "stacks") };
82241
82403
  }
82242
82404
  function parseStack(raw) {
82243
82405
  if (!isRecord12(raw) || !Array.isArray(raw.branches))
@@ -82289,7 +82451,7 @@ function readStack(cwd, name) {
82289
82451
  const dir = stacksDir(cwd);
82290
82452
  if (!dir.ok)
82291
82453
  return dir;
82292
- const file = path59.join(dir.data, fileFor(name));
82454
+ const file = path60.join(dir.data, fileFor(name));
82293
82455
  let text;
82294
82456
  try {
82295
82457
  text = fs28.readFileSync(file, "utf8");
@@ -82310,7 +82472,7 @@ function writeStack(cwd, stack, now = new Date) {
82310
82472
  const dir = stacksDir(cwd);
82311
82473
  if (!dir.ok)
82312
82474
  return dir;
82313
- const file = path59.join(dir.data, fileFor(stack.name));
82475
+ const file = path60.join(dir.data, fileFor(stack.name));
82314
82476
  const temp = `${file}.${process.pid}.tmp`;
82315
82477
  try {
82316
82478
  fs28.mkdirSync(dir.data, { recursive: true });
@@ -82338,7 +82500,7 @@ function listStacks(cwd) {
82338
82500
  for (const name of names) {
82339
82501
  let parsed = null;
82340
82502
  try {
82341
- parsed = parseStack(JSON.parse(fs28.readFileSync(path59.join(dir.data, name), "utf8")));
82503
+ parsed = parseStack(JSON.parse(fs28.readFileSync(path60.join(dir.data, name), "utf8")));
82342
82504
  } catch {
82343
82505
  parsed = null;
82344
82506
  }
@@ -82400,7 +82562,7 @@ function takeLock(lock) {
82400
82562
  host: localLockHost(),
82401
82563
  nonce: randomBytes4(8).toString("hex")
82402
82564
  };
82403
- fs28.writeFileSync(path59.join(lock, OWNER), JSON.stringify(owner));
82565
+ fs28.writeFileSync(path60.join(lock, OWNER), JSON.stringify(owner));
82404
82566
  return owner;
82405
82567
  }
82406
82568
  function reapLock(lock, observed) {
@@ -82437,7 +82599,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
82437
82599
  return dir;
82438
82600
  if (!validName(name))
82439
82601
  return stackFail("invalid_input", "a stack name must be 1-200 printable characters");
82440
- const lock = path59.join(dir.data, `${fileFor(name)}.lock`);
82602
+ const lock = path60.join(dir.data, `${fileFor(name)}.lock`);
82441
82603
  try {
82442
82604
  fs28.mkdirSync(dir.data, { recursive: true });
82443
82605
  } catch (error) {
@@ -82467,7 +82629,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
82467
82629
  const touch = () => {
82468
82630
  try {
82469
82631
  const now = new Date;
82470
- fs28.utimesSync(path59.join(lock, OWNER), now, now);
82632
+ fs28.utimesSync(path60.join(lock, OWNER), now, now);
82471
82633
  } catch {}
82472
82634
  };
82473
82635
  const beat = setInterval(touch, HEARTBEAT_MS);
@@ -83436,7 +83598,7 @@ var STACK_VERSION = 1, stackFail = (code, error, unblock, data) => ({
83436
83598
  return !status.ok || status.stdout.trim() !== "";
83437
83599
  }, scratchDir = (cwd) => {
83438
83600
  const dir = stacksDir(cwd);
83439
- return dir.ok ? path59.join(dir.data, "worktrees") : null;
83601
+ return dir.ok ? path60.join(dir.data, "worktrees") : null;
83440
83602
  }, firstLine = (run) => (`${run.stderr}
83441
83603
  ${run.stdout}`.split(`
83442
83604
  `).find((line) => line.trim()) ?? "git failed").trim().slice(0, 300), stackFileName = (name) => `${name.replace(/[^A-Za-z0-9._-]+/gu, "_").replace(/^[._]+/u, "").slice(0, 48).toLowerCase()}-${createHash18("sha256").update(name).digest("hex").slice(0, 12)}.json`, fileFor, validName = (name) => {
@@ -83451,12 +83613,12 @@ ${run.stdout}`.split(`
83451
83613
  }, isRecord12 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), str3 = (value) => typeof value === "string" && value ? value : null, LOCK_WAIT_MS3 = 2000, HEARTBEAT_MS = 20000, HEARTBEAT_STALE_MS, OWNERLESS_STALE_MS = 30000, OWNER = "owner", readOwner = (lock) => {
83452
83614
  let raw = null;
83453
83615
  try {
83454
- raw = fs28.readFileSync(path59.join(lock, OWNER), "utf8");
83616
+ raw = fs28.readFileSync(path60.join(lock, OWNER), "utf8");
83455
83617
  } catch {
83456
83618
  raw = null;
83457
83619
  }
83458
83620
  let age = null;
83459
- for (const target of [path59.join(lock, OWNER), lock])
83621
+ for (const target of [path60.join(lock, OWNER), lock])
83460
83622
  try {
83461
83623
  age = Date.now() - fs28.statSync(target).mtimeMs;
83462
83624
  break;
@@ -83500,7 +83662,7 @@ var init_stack = __esm(() => {
83500
83662
  import { spawnSync as spawnSync23 } from "node:child_process";
83501
83663
  import { createHash as createHash19 } from "node:crypto";
83502
83664
  import fs29 from "node:fs";
83503
- import path60 from "node:path";
83665
+ import path61 from "node:path";
83504
83666
  function expandBraces2(pattern, limit = 64) {
83505
83667
  for (let index = 0;index < pattern.length; index += 1) {
83506
83668
  if (pattern[index] === "\\") {
@@ -83746,7 +83908,7 @@ function parsePlan(raw, defaults, name) {
83746
83908
  id,
83747
83909
  branch,
83748
83910
  base: optional("base") ?? "",
83749
- worktree: path60.resolve(defaults.root, optional("worktree") ?? path60.join(defaults.worktreeRoot, id)),
83911
+ worktree: path61.resolve(defaults.root, optional("worktree") ?? path61.join(defaults.worktreeRoot, id)),
83750
83912
  tier,
83751
83913
  reason,
83752
83914
  dependsOn: [...new Set(dependsOn ?? [])],
@@ -83875,12 +84037,12 @@ function regeneratedFiles(root, tracked) {
83875
84037
  const found = new Map;
83876
84038
  let scripts;
83877
84039
  try {
83878
- const manifest = JSON.parse(fs29.readFileSync(path60.join(root, "package.json"), "utf8"));
84040
+ const manifest = JSON.parse(fs29.readFileSync(path61.join(root, "package.json"), "utf8"));
83879
84041
  scripts = manifest.scripts ?? {};
83880
84042
  } catch {
83881
84043
  return found;
83882
84044
  }
83883
- const runner = fs29.existsSync(path60.join(root, "bun.lock")) ? "bun run" : fs29.existsSync(path60.join(root, "pnpm-lock.yaml")) ? "pnpm run" : fs29.existsSync(path60.join(root, "yarn.lock")) ? "yarn run" : "npm run";
84045
+ const runner = fs29.existsSync(path61.join(root, "bun.lock")) ? "bun run" : fs29.existsSync(path61.join(root, "pnpm-lock.yaml")) ? "pnpm run" : fs29.existsSync(path61.join(root, "yarn.lock")) ? "yarn run" : "npm run";
83884
84046
  const outputs = tracked.filter((file) => !CODE.test(file));
83885
84047
  for (const [name, command] of Object.entries(scripts)) {
83886
84048
  if (!name.startsWith("write:") || typeof command !== "string")
@@ -83888,7 +84050,7 @@ function regeneratedFiles(root, tracked) {
83888
84050
  for (const file of command.match(/[\w./-]+\.[cm]?[jt]s\b/gu) ?? []) {
83889
84051
  let source;
83890
84052
  try {
83891
- source = fs29.readFileSync(path60.join(root, file), "utf8");
84053
+ source = fs29.readFileSync(path61.join(root, file), "utf8");
83892
84054
  } catch {
83893
84055
  continue;
83894
84056
  }
@@ -84010,11 +84172,11 @@ function defaultTrunk(cwd) {
84010
84172
  }
84011
84173
  function mainCheckout(cwd) {
84012
84174
  const common = gitCommonDir(cwd);
84013
- return common && path60.basename(common) === ".git" ? path60.dirname(common) : path60.resolve(cwd);
84175
+ return common && path61.basename(common) === ".git" ? path61.dirname(common) : path61.resolve(cwd);
84014
84176
  }
84015
84177
  function worktreeRoot(cwd) {
84016
84178
  const main = mainCheckout(cwd);
84017
- return path60.join(path60.dirname(main), `${path60.basename(main)}-wt`);
84179
+ return path61.join(path61.dirname(main), `${path61.basename(main)}-wt`);
84018
84180
  }
84019
84181
  function sliceHash(slice) {
84020
84182
  const {
@@ -84034,7 +84196,7 @@ function fanoutsDir(cwd) {
84034
84196
  const root = storeRoot(cwd);
84035
84197
  if (!root.ok)
84036
84198
  return fanoutFail(root.code, root.error, root.unblock);
84037
- return { ok: true, data: path60.join(root.value.root, "fanouts") };
84199
+ return { ok: true, data: path61.join(root.value.root, "fanouts") };
84038
84200
  }
84039
84201
  function parseStored(raw) {
84040
84202
  if (!isRecord13(raw) || typeof raw.name !== "string" || typeof raw.trunk !== "string")
@@ -84102,7 +84264,7 @@ function readFanout(cwd, name) {
84102
84264
  const dir = fanoutsDir(cwd);
84103
84265
  if (!dir.ok)
84104
84266
  return dir;
84105
- const file = path60.join(dir.data, stackFileName(name));
84267
+ const file = path61.join(dir.data, stackFileName(name));
84106
84268
  let parsed = null;
84107
84269
  try {
84108
84270
  parsed = parseStored(JSON.parse(fs29.readFileSync(file, "utf8")));
@@ -84127,7 +84289,7 @@ function listFanouts(cwd) {
84127
84289
  for (const entry of names) {
84128
84290
  let parsed = null;
84129
84291
  try {
84130
- parsed = parseStored(JSON.parse(fs29.readFileSync(path60.join(dir.data, entry), "utf8")));
84292
+ parsed = parseStored(JSON.parse(fs29.readFileSync(path61.join(dir.data, entry), "utf8")));
84131
84293
  } catch {
84132
84294
  parsed = null;
84133
84295
  }
@@ -84166,7 +84328,7 @@ function writeFanout(cwd, plan) {
84166
84328
  const dir = fanoutsDir(cwd);
84167
84329
  if (!dir.ok)
84168
84330
  return dir;
84169
- const file = path60.join(dir.data, stackFileName(plan.name));
84331
+ const file = path61.join(dir.data, stackFileName(plan.name));
84170
84332
  const temp = `${file}.${process.pid}.tmp`;
84171
84333
  try {
84172
84334
  fs29.mkdirSync(dir.data, { recursive: true });
@@ -84377,13 +84539,13 @@ var init_fanout = __esm(() => {
84377
84539
  // packages/workit-core/src/forge/exec.ts
84378
84540
  import { spawnSync as spawnSync24 } from "node:child_process";
84379
84541
  import fs30 from "node:fs";
84380
- import path61 from "node:path";
84542
+ import path62 from "node:path";
84381
84543
  function findExecutable(bin, env) {
84382
- const dirs = (env.PATH ?? env.Path ?? "").split(path61.delimiter).filter(Boolean);
84544
+ const dirs = (env.PATH ?? env.Path ?? "").split(path62.delimiter).filter(Boolean);
84383
84545
  const exts = process.platform === "win32" ? [".exe"] : [""];
84384
84546
  for (const dir of dirs)
84385
84547
  for (const ext of exts) {
84386
- const candidate = path61.join(dir, `${bin}${ext}`);
84548
+ const candidate = path62.join(dir, `${bin}${ext}`);
84387
84549
  try {
84388
84550
  const stat = fs30.statSync(candidate);
84389
84551
  if (stat.isFile())
@@ -86173,7 +86335,7 @@ var init_live_session = __esm(() => {
86173
86335
  });
86174
86336
 
86175
86337
  // packages/workit-core/src/hooks/write-gate.ts
86176
- import path62 from "node:path";
86338
+ import path63 from "node:path";
86177
86339
  var CASE_INSENSITIVE, PREFIXES2, SCRIPT_SHELLS, cache3, MUTATING_GIT, DRY_N, MUTATING_WORKIT_GIT, CD2, PUSHD2, POPD2, UNKNOWN_DIR;
86178
86340
  var init_write_gate = __esm(() => {
86179
86341
  init_task_store();
@@ -86213,7 +86375,7 @@ var init_write_gate = __esm(() => {
86213
86375
  CD2 = new Set(["cd", "chdir", "set-location", "sl"]);
86214
86376
  PUSHD2 = new Set(["pushd", "push-location"]);
86215
86377
  POPD2 = new Set(["popd", "pop-location"]);
86216
- UNKNOWN_DIR = path62.resolve(path62.parse(process.cwd()).root, ".workit-unknown-dir");
86378
+ UNKNOWN_DIR = path63.resolve(path63.parse(process.cwd()).root, ".workit-unknown-dir");
86217
86379
  });
86218
86380
 
86219
86381
  // packages/workit-core/src/hooks/worktree-confine.ts
@@ -86238,20 +86400,20 @@ var init_worktree_confine = __esm(() => {
86238
86400
 
86239
86401
  // packages/workit-core/src/worktree-deps.ts
86240
86402
  import fs31 from "node:fs";
86241
- import path63 from "node:path";
86403
+ import path64 from "node:path";
86242
86404
  function moduleDirs(main) {
86243
86405
  const out = [];
86244
86406
  const walk = (relative, depth) => {
86245
86407
  let entries;
86246
86408
  try {
86247
- entries = fs31.readdirSync(path63.join(main, relative), { withFileTypes: true });
86409
+ entries = fs31.readdirSync(path64.join(main, relative), { withFileTypes: true });
86248
86410
  } catch {
86249
86411
  return;
86250
86412
  }
86251
86413
  for (const entry of entries) {
86252
86414
  if (!entry.isDirectory())
86253
86415
  continue;
86254
- const child = path63.join(relative, entry.name);
86416
+ const child = path64.join(relative, entry.name);
86255
86417
  if (entry.name === MODULES)
86256
86418
  out.push(child);
86257
86419
  else if (depth < MAX_DEPTH2 && !entry.name.startsWith("."))
@@ -86265,8 +86427,8 @@ function linkEntry(main, worktree, source, target) {
86265
86427
  const stat = fs31.lstatSync(source);
86266
86428
  if (stat.isSymbolicLink()) {
86267
86429
  const link = fs31.readlinkSync(source);
86268
- const outside = path63.isAbsolute(link) && within(link, main) && !path63.relative(main, link).split(path63.sep).includes(MODULES);
86269
- const to = outside ? path63.join(worktree, path63.relative(main, link)) : link;
86430
+ const outside = path64.isAbsolute(link) && within(link, main) && !path64.relative(main, link).split(path64.sep).includes(MODULES);
86431
+ const to = outside ? path64.join(worktree, path64.relative(main, link)) : link;
86270
86432
  fs31.symlinkSync(to, target, process.platform === "win32" ? "junction" : undefined);
86271
86433
  return;
86272
86434
  }
@@ -86276,8 +86438,8 @@ function mirror(main, worktree, source, target, top) {
86276
86438
  fs31.mkdirSync(target);
86277
86439
  let count = 0;
86278
86440
  for (const entry of fs31.readdirSync(source, { withFileTypes: true })) {
86279
- const from = path63.join(source, entry.name);
86280
- const to = path63.join(target, entry.name);
86441
+ const from = path64.join(source, entry.name);
86442
+ const to = path64.join(target, entry.name);
86281
86443
  if (top && entry.isDirectory() && (entry.name.startsWith("@") || entry.name === ".bin"))
86282
86444
  count += mirror(main, worktree, from, to, false);
86283
86445
  else {
@@ -86293,16 +86455,16 @@ function linkWorktreeDependencies(main, worktree) {
86293
86455
  const dirs = [];
86294
86456
  let entries = 0;
86295
86457
  for (const relative of moduleDirs(main)) {
86296
- const target = path63.join(worktree, relative);
86297
- if (!fs31.existsSync(path63.dirname(target)) || fs31.existsSync(target))
86458
+ const target = path64.join(worktree, relative);
86459
+ if (!fs31.existsSync(path64.dirname(target)) || fs31.existsSync(target))
86298
86460
  continue;
86299
- if (!gitRun4(worktree, ["check-ignore", "-q", `${relative.split(path63.sep).join("/")}/`]).ok) {
86300
- notes.push(`${relative.split(path63.sep).join("/")} is not ignored by git, so it was not linked from ${main}; install dependencies in the worktree yourself`);
86461
+ if (!gitRun4(worktree, ["check-ignore", "-q", `${relative.split(path64.sep).join("/")}/`]).ok) {
86462
+ notes.push(`${relative.split(path64.sep).join("/")} is not ignored by git, so it was not linked from ${main}; install dependencies in the worktree yourself`);
86301
86463
  continue;
86302
86464
  }
86303
86465
  try {
86304
- entries += mirror(main, worktree, path63.join(main, relative), target, true);
86305
- dirs.push(relative.split(path63.sep).join("/"));
86466
+ entries += mirror(main, worktree, path64.join(main, relative), target, true);
86467
+ dirs.push(relative.split(path64.sep).join("/"));
86306
86468
  } catch (error) {
86307
86469
  fs31.rmSync(target, { recursive: true, force: true });
86308
86470
  notes.push(`could not link ${relative} from ${main} (${error.message}); install dependencies in the worktree yourself`);
@@ -86315,8 +86477,8 @@ function linkWorktreeDependencies(main, worktree) {
86315
86477
  return { linked: { from: main, dirs, entries, ms }, notes };
86316
86478
  }
86317
86479
  var MODULES = "node_modules", MAX_DEPTH2 = 2, within = (child, parent) => {
86318
- const relative = path63.relative(parent, child);
86319
- return relative === "" || !relative.startsWith("..") && !path63.isAbsolute(relative);
86480
+ const relative = path64.relative(parent, child);
86481
+ return relative === "" || !relative.startsWith("..") && !path64.isAbsolute(relative);
86320
86482
  };
86321
86483
  var init_worktree_deps = __esm(() => {
86322
86484
  init_fanout();
@@ -86325,7 +86487,7 @@ var init_worktree_deps = __esm(() => {
86325
86487
  // packages/workit-core/src/fanout-worktree.ts
86326
86488
  import { randomBytes as randomBytes5 } from "node:crypto";
86327
86489
  import fs32 from "node:fs";
86328
- import path64 from "node:path";
86490
+ import path65 from "node:path";
86329
86491
  function rowSample(lines) {
86330
86492
  const out = [];
86331
86493
  let bytes = 0;
@@ -86385,7 +86547,7 @@ function adminDir(worktree) {
86385
86547
  const file = dir.stdout.trim();
86386
86548
  let token = null;
86387
86549
  try {
86388
- token = fs32.readFileSync(path64.join(file, FANOUT_TOKEN_FILE), "utf8").trim() || null;
86550
+ token = fs32.readFileSync(path65.join(file, FANOUT_TOKEN_FILE), "utf8").trim() || null;
86389
86551
  } catch {
86390
86552
  token = null;
86391
86553
  }
@@ -86393,7 +86555,7 @@ function adminDir(worktree) {
86393
86555
  const stat = worktreeDeps.stat(file);
86394
86556
  return {
86395
86557
  path: file,
86396
- id: path64.basename(file),
86558
+ id: path65.basename(file),
86397
86559
  ino: stat.ino.toString(),
86398
86560
  token,
86399
86561
  birthMs: stat.birthtimeNs > 0n ? Number(stat.birthtimeMs) : null,
@@ -86409,7 +86571,7 @@ function markAdminDir(worktree) {
86409
86571
  return null;
86410
86572
  const token = randomBytes5(16).toString("hex");
86411
86573
  try {
86412
- fs32.writeFileSync(path64.join(admin.path, FANOUT_TOKEN_FILE), `${token}
86574
+ fs32.writeFileSync(path65.join(admin.path, FANOUT_TOKEN_FILE), `${token}
86413
86575
  `);
86414
86576
  } catch {
86415
86577
  return null;
@@ -86424,7 +86586,7 @@ function excludeScratch(cwd) {
86424
86586
  const common = gitCommonDir(cwd);
86425
86587
  if (!common)
86426
86588
  return;
86427
- const file = path64.join(common, "info", "exclude");
86589
+ const file = path65.join(common, "info", "exclude");
86428
86590
  let text = "";
86429
86591
  try {
86430
86592
  text = fs32.readFileSync(file, "utf8");
@@ -86433,7 +86595,7 @@ function excludeScratch(cwd) {
86433
86595
  }
86434
86596
  if (text.split(/\r?\n/u).includes(EXCLUDE_LINE))
86435
86597
  return;
86436
- fs32.mkdirSync(path64.dirname(file), { recursive: true });
86598
+ fs32.mkdirSync(path65.dirname(file), { recursive: true });
86437
86599
  fs32.appendFileSync(file, `${text && !text.endsWith(`
86438
86600
  `) ? `
86439
86601
  ` : ""}# workit fanout: per-worker scratch dirs
@@ -86442,13 +86604,13 @@ ${EXCLUDE_LINE}
86442
86604
  }
86443
86605
  function worktreeDependencies(main, worktree) {
86444
86606
  for (const [name, install] of LOCKFILES2) {
86445
- const ours = readBytes(path64.join(main, name));
86446
- const theirs = readBytes(path64.join(worktree, name));
86607
+ const ours = readBytes(path65.join(main, name));
86608
+ const theirs = readBytes(path65.join(worktree, name));
86447
86609
  if (ours === null && theirs === null)
86448
86610
  continue;
86449
86611
  if (ours !== null && theirs !== null && ours.equals(theirs))
86450
86612
  continue;
86451
- if (fs32.existsSync(path64.join(worktree, "node_modules")))
86613
+ if (fs32.existsSync(path65.join(worktree, "node_modules")))
86452
86614
  break;
86453
86615
  const command = install(worktree);
86454
86616
  return {
@@ -86460,7 +86622,7 @@ function worktreeDependencies(main, worktree) {
86460
86622
  };
86461
86623
  }
86462
86624
  const stale = staleBunInstall(main);
86463
- if (stale && !fs32.existsSync(path64.join(worktree, "node_modules"))) {
86625
+ if (stale && !fs32.existsSync(path65.join(worktree, "node_modules"))) {
86464
86626
  const command = `bun install --frozen-lockfile --cwd ${worktree}`;
86465
86627
  return {
86466
86628
  linked: null,
@@ -86473,9 +86635,9 @@ function worktreeDependencies(main, worktree) {
86473
86635
  return { ...linkWorktreeDependencies(main, worktree), install: null };
86474
86636
  }
86475
86637
  function staleBunInstall(main) {
86476
- if (!fs32.existsSync(path64.join(main, "node_modules")))
86638
+ if (!fs32.existsSync(path65.join(main, "node_modules")))
86477
86639
  return null;
86478
- const text = readBytes(path64.join(main, "bun.lock"))?.toString("utf8");
86640
+ const text = readBytes(path65.join(main, "bun.lock"))?.toString("utf8");
86479
86641
  if (!text)
86480
86642
  return null;
86481
86643
  let packages;
@@ -86502,7 +86664,7 @@ function staleBunInstall(main) {
86502
86664
  const version = spec.slice(at + 1);
86503
86665
  if (name !== key || version.includes(":"))
86504
86666
  continue;
86505
- const manifest = readBytes(path64.join(main, "node_modules", key, "package.json"));
86667
+ const manifest = readBytes(path65.join(main, "node_modules", key, "package.json"));
86506
86668
  if (!manifest) {
86507
86669
  problems.push(`${key} missing`);
86508
86670
  continue;
@@ -86519,7 +86681,7 @@ function staleBunInstall(main) {
86519
86681
  return problems.length ? problems.join("; ") : null;
86520
86682
  }
86521
86683
  function ensureScratch(worktree) {
86522
- const scratch = path64.join(worktree, SCRATCH_DIR);
86684
+ const scratch = path65.join(worktree, SCRATCH_DIR);
86523
86685
  fs32.mkdirSync(scratch, { recursive: true });
86524
86686
  return scratch;
86525
86687
  }
@@ -86793,7 +86955,7 @@ function unpushedCount(cwd, branch) {
86793
86955
  return count.ok ? Number(count.stdout.trim()) : null;
86794
86956
  }
86795
86957
  function removeScratch(worktree) {
86796
- const scratch = path64.join(worktree, SCRATCH_DIR);
86958
+ const scratch = path65.join(worktree, SCRATCH_DIR);
86797
86959
  let stat;
86798
86960
  try {
86799
86961
  stat = fs32.lstatSync(scratch);
@@ -86809,16 +86971,16 @@ var SLOW, SCRATCH_DIR = ".workit-scratch", EXCLUDE_LINE, DIRTY_ROW_BYTES = 2000,
86809
86971
  try {
86810
86972
  return fs32.realpathSync.native(target);
86811
86973
  } catch {
86812
- return path64.resolve(target);
86974
+ return path65.resolve(target);
86813
86975
  }
86814
86976
  }, samePath = (a, b) => {
86815
86977
  const left = canonical2(a);
86816
86978
  const right = canonical2(b);
86817
86979
  return process.platform === "win32" || process.platform === "darwin" ? left.toLowerCase() === right.toLowerCase() : left === right;
86818
86980
  }, inside3 = (child, parent) => {
86819
- const relative = path64.relative(canonical2(parent), canonical2(child));
86820
- return relative === "" || !relative.startsWith("..") && !path64.isAbsolute(relative);
86821
- }, slicePath = (cwd, slice) => path64.isAbsolute(slice.worktree) ? slice.worktree : path64.resolve(mainCheckout(cwd), slice.worktree), CLOCK_SLACK_MS = 2000, worktreeDeps, LOCKFILES2, readBytes = (file) => {
86981
+ const relative = path65.relative(canonical2(parent), canonical2(child));
86982
+ return relative === "" || !relative.startsWith("..") && !path65.isAbsolute(relative);
86983
+ }, slicePath = (cwd, slice) => path65.isAbsolute(slice.worktree) ? slice.worktree : path65.resolve(mainCheckout(cwd), slice.worktree), CLOCK_SLACK_MS = 2000, worktreeDeps, LOCKFILES2, readBytes = (file) => {
86822
86984
  try {
86823
86985
  return fs32.readFileSync(file);
86824
86986
  } catch {
@@ -86850,7 +87012,7 @@ var init_fanout_worktree = __esm(() => {
86850
87012
 
86851
87013
  // packages/workit-core/src/forge/merge-cleanup.ts
86852
87014
  import fs33 from "node:fs";
86853
- import path65 from "node:path";
87015
+ import path66 from "node:path";
86854
87016
  function cleanupMergedBranch(cwd, branch, mergedHead) {
86855
87017
  const out = { branchDeleted: false, worktreeRemoved: null, notes: [] };
86856
87018
  if (!branch || branch.startsWith("-"))
@@ -86910,13 +87072,13 @@ var SLOW2, isFanoutWorktree = (worktree) => {
86910
87072
  if (!dir.ok)
86911
87073
  return false;
86912
87074
  try {
86913
- return fs33.readFileSync(path65.join(dir.stdout.trim(), FANOUT_TOKEN_FILE), "utf8").trim() !== "";
87075
+ return fs33.readFileSync(path66.join(dir.stdout.trim(), FANOUT_TOKEN_FILE), "utf8").trim() !== "";
86914
87076
  } catch {
86915
87077
  return false;
86916
87078
  }
86917
87079
  }, inside4 = (child, parent) => {
86918
- const relative = path65.relative(fs33.realpathSync.native(parent), fs33.realpathSync.native(child));
86919
- return relative === "" || !relative.startsWith("..") && !path65.isAbsolute(relative);
87080
+ const relative = path66.relative(fs33.realpathSync.native(parent), fs33.realpathSync.native(child));
87081
+ return relative === "" || !relative.startsWith("..") && !path66.isAbsolute(relative);
86920
87082
  };
86921
87083
  var init_merge_cleanup = __esm(() => {
86922
87084
  init_fanout();
@@ -87368,7 +87530,7 @@ __export(exports_pr, {
87368
87530
  run: () => run15
87369
87531
  });
87370
87532
  import { existsSync as existsSync27, readFileSync as readFileSync27 } from "node:fs";
87371
- import path66 from "node:path";
87533
+ import path67 from "node:path";
87372
87534
  function titleRules(cwd) {
87373
87535
  let root;
87374
87536
  try {
@@ -87379,7 +87541,7 @@ function titleRules(cwd) {
87379
87541
  let text = null;
87380
87542
  let name = "";
87381
87543
  for (const candidate of COMMITLINT_FILES) {
87382
- const full = path66.join(root, candidate);
87544
+ const full = path67.join(root, candidate);
87383
87545
  if (!existsSync27(full))
87384
87546
  continue;
87385
87547
  text = readFileSync27(full, "utf8");
@@ -87388,7 +87550,7 @@ function titleRules(cwd) {
87388
87550
  }
87389
87551
  if (text === null) {
87390
87552
  try {
87391
- const pkg = JSON.parse(readFileSync27(path66.join(root, "package.json"), "utf8"));
87553
+ const pkg = JSON.parse(readFileSync27(path67.join(root, "package.json"), "utf8"));
87392
87554
  if (pkg.commitlint === undefined)
87393
87555
  return { rules: null, note: null };
87394
87556
  text = JSON.stringify(pkg.commitlint);
@@ -87485,7 +87647,7 @@ function refuseTitle(io, title, line) {
87485
87647
  function readBodyFile(io, file) {
87486
87648
  try {
87487
87649
  return {
87488
- body: file === "-" ? forgeDeps.readStdin() : readFileSync27(path66.resolve(io.cwd, file), "utf8")
87650
+ body: file === "-" ? forgeDeps.readStdin() : readFileSync27(path67.resolve(io.cwd, file), "utf8")
87489
87651
  };
87490
87652
  } catch {
87491
87653
  return `cannot read --body-file ${file}`;
@@ -88374,7 +88536,7 @@ __export(exports_git, {
88374
88536
  run: () => run17
88375
88537
  });
88376
88538
  import { readFileSync as readFileSync28 } from "node:fs";
88377
- import path67 from "node:path";
88539
+ import path68 from "node:path";
88378
88540
  function kindHint(cwd, kind) {
88379
88541
  let kinds = [...BRANCH_KINDS];
88380
88542
  try {
@@ -88478,7 +88640,7 @@ function commitMessage(parsed, io) {
88478
88640
 
88479
88641
  `);
88480
88642
  try {
88481
- return file === "-" ? readFileSync28(0, "utf8") : readFileSync28(path67.resolve(io.cwd, file), "utf8");
88643
+ return file === "-" ? readFileSync28(0, "utf8") : readFileSync28(path68.resolve(io.cwd, file), "utf8");
88482
88644
  } catch (error) {
88483
88645
  return {
88484
88646
  error: `cannot read -F ${file}: ${error instanceof Error ? error.message : String(error)}`
@@ -89936,7 +90098,7 @@ var init_stack2 = __esm(() => {
89936
90098
  // packages/workit-core/src/fanout-brief.ts
89937
90099
  import { createHash as createHash20 } from "node:crypto";
89938
90100
  import fs35 from "node:fs";
89939
- import path68 from "node:path";
90101
+ import path69 from "node:path";
89940
90102
  function workerSession(lead, slice, attempt) {
89941
90103
  const tail = attempt === null ? "" : `+try${attempt}`;
89942
90104
  const full = `${lead}-w-${slice}${tail}`;
@@ -90019,7 +90181,7 @@ function renderBrief(cwd, plan, input) {
90019
90181
  "STANDING:",
90020
90182
  ...standing.length ? standing.map((order) => ` - ${order.what}`) : [" - none recorded beyond this brief"],
90021
90183
  exists ? `WORKTREE: ${planned} (made by \`workit fanout worktree create ${slice.id}\`; yours alone)` : `WORKTREE: ${planned} (not made yet: the lead runs \`workit fanout worktree create ${slice.id}\` before spawning, then renders this brief again)`,
90022
- ...exists && typeof made?.install === "string" && !fs35.existsSync(path68.join(planned, "node_modules")) ? [`INSTALL: \`${made.install}\` first: the main checkout's node_modules was not linked here`] : [],
90184
+ ...exists && typeof made?.install === "string" && !fs35.existsSync(path69.join(planned, "node_modules")) ? [`INSTALL: \`${made.install}\` first: the main checkout's node_modules was not linked here`] : [],
90023
90185
  ...identityLines(identity, minted),
90024
90186
  ...rules(mode, branch, sliceBase, exists ? planned : null)
90025
90187
  ];
@@ -90561,7 +90723,7 @@ __export(exports_fanout, {
90561
90723
  run: () => run21
90562
90724
  });
90563
90725
  import fs36 from "node:fs";
90564
- import path69 from "node:path";
90726
+ import path70 from "node:path";
90565
90727
  function forgeFor(io, offline) {
90566
90728
  if (offline)
90567
90729
  return { forge: null, error: "--offline" };
@@ -90622,7 +90784,7 @@ function plan2(argv, io) {
90622
90784
  return usage4(io, "pass --trunk or --track, not both (--track picks the trunk)", PLAN_USAGE2);
90623
90785
  if (flags.positionals.length !== 1)
90624
90786
  return usage4(io, flags.positionals.length ? `unexpected argument ${flags.positionals[1]}` : "missing <plan.json>", PLAN_USAGE2);
90625
- const file = path69.resolve(io.cwd, flags.positionals[0]);
90787
+ const file = path70.resolve(io.cwd, flags.positionals[0]);
90626
90788
  let raw;
90627
90789
  try {
90628
90790
  raw = JSON.parse(fs36.readFileSync(file, "utf8"));
@@ -106197,7 +106359,7 @@ var init_ast = __esm(() => {
106197
106359
 
106198
106360
  // packages/workit-cli/src/test-audit/rules.ts
106199
106361
  import { builtinModules } from "node:module";
106200
- import path70 from "node:path";
106362
+ import path71 from "node:path";
106201
106363
  function testCallee(call) {
106202
106364
  let callee = call.callee;
106203
106365
  if (callee.type === "CallExpression")
@@ -106690,12 +106852,12 @@ function checkConstantsOnly(ctx, emit) {
106690
106852
  }
106691
106853
  function checkOverMocking(ctx, emit) {
106692
106854
  const { program } = ctx.parsed;
106693
- const unit = path70.basename(ctx.file).replace(/\.(?:[cm]?[jt]sx?)$/, "").replace(/\.(?:test|spec)$/, "");
106855
+ const unit = path71.basename(ctx.file).replace(/\.(?:[cm]?[jt]sx?)$/, "").replace(/\.(?:test|spec)$/, "");
106694
106856
  const mocked = find2(program, (node) => node.type === "CallExpression" && MODULE_MOCK.test(calleeName(node.callee) ?? "") && node.arguments[0]?.type === "StringLiteral");
106695
106857
  const internal = mocked.filter((call) => /^(?:\.|@\/|~\/)/.test(call.arguments[0].value));
106696
106858
  for (const call of mocked) {
106697
106859
  const spec = call.arguments[0].value;
106698
- const base = path70.basename(spec.replace(/\/index(?:\.[cm]?[jt]sx?)?$/, "")).replace(/\.(?:[cm]?[jt]sx?)$/, "");
106860
+ const base = path71.basename(spec.replace(/\/index(?:\.[cm]?[jt]sx?)?$/, "")).replace(/\.(?:[cm]?[jt]sx?)$/, "");
106699
106861
  if (base === unit)
106700
106862
  emit({
106701
106863
  rule: "over-mocking",
@@ -107085,7 +107247,7 @@ var init_rules = __esm(() => {
107085
107247
  // packages/workit-cli/src/test-audit/audit.ts
107086
107248
  import { spawnSync as spawnSync29 } from "node:child_process";
107087
107249
  import { existsSync as existsSync28, readdirSync as readdirSync14, readFileSync as readFileSync29, statSync as statSync10 } from "node:fs";
107088
- import path71 from "node:path";
107250
+ import path72 from "node:path";
107089
107251
  function git7(cwd, args) {
107090
107252
  const run = spawnSync29("git", ["-c", "core.quotepath=off", ...args], {
107091
107253
  cwd,
@@ -107098,7 +107260,7 @@ function walkTests(dir, out) {
107098
107260
  for (const entry of readdirSync14(dir, { withFileTypes: true })) {
107099
107261
  if (entry.name.startsWith(".") && entry.name !== "." && entry.isDirectory())
107100
107262
  continue;
107101
- const full = path71.join(dir, entry.name);
107263
+ const full = path72.join(dir, entry.name);
107102
107264
  if (entry.isDirectory()) {
107103
107265
  if (!SKIP_DIRS.has(entry.name))
107104
107266
  walkTests(full, out);
@@ -107110,7 +107272,7 @@ function expandPaths(cwd, inputs) {
107110
107272
  const files = [];
107111
107273
  const missing = [];
107112
107274
  for (const input of inputs.length > 0 ? inputs : ["."]) {
107113
- const full = path71.resolve(cwd, input);
107275
+ const full = path72.resolve(cwd, input);
107114
107276
  if (!existsSync28(full))
107115
107277
  missing.push(input);
107116
107278
  else if (statSync10(full).isDirectory())
@@ -107147,11 +107309,11 @@ function changedLines(cwd, base) {
107147
107309
  for (let offset = 0;offset < count; offset += 1)
107148
107310
  lines.add(start + offset);
107149
107311
  }
107150
- changed.set(path71.join(root, file), lines);
107312
+ changed.set(path72.join(root, file), lines);
107151
107313
  }
107152
107314
  const untracked = git7(root, ["ls-files", "--others", "--exclude-standard", "-z"]);
107153
107315
  for (const file of untracked.stdout.split("\x00").filter(Boolean))
107154
- changed.set(path71.join(root, file), "all");
107316
+ changed.set(path72.join(root, file), "all");
107155
107317
  return changed;
107156
107318
  }
107157
107319
  function auditFiles(files, display) {
@@ -107213,7 +107375,7 @@ function auditFiles(files, display) {
107213
107375
  durationMs: Math.round(performance.now() - started)
107214
107376
  };
107215
107377
  }
107216
- var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(path71.sep).join("/"), SEVERITY_ORDER, ruleIds;
107378
+ var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(path72.sep).join("/"), SEVERITY_ORDER, ruleIds;
107217
107379
  var init_audit = __esm(() => {
107218
107380
  init_ast();
107219
107381
  init_rules();
@@ -107225,7 +107387,7 @@ var init_audit = __esm(() => {
107225
107387
  });
107226
107388
 
107227
107389
  // packages/workit-cli/src/test-audit/mutate.ts
107228
- import { spawn as spawn3 } from "node:child_process";
107390
+ import { spawn as spawn4 } from "node:child_process";
107229
107391
  import {
107230
107392
  existsSync as existsSync29,
107231
107393
  lstatSync as lstatSync9,
@@ -107243,7 +107405,7 @@ import {
107243
107405
  copyFileSync as copyFileSync8
107244
107406
  } from "node:fs";
107245
107407
  import os23 from "node:os";
107246
- import path72 from "node:path";
107408
+ import path73 from "node:path";
107247
107409
  function mutantsFor(source, file, lines) {
107248
107410
  const parsed = parseSource(source, file);
107249
107411
  const out = [];
@@ -107316,7 +107478,7 @@ function relatedTests(source, testFiles) {
107316
107478
  for (const match of text.matchAll(SPECIFIER)) {
107317
107479
  const spec = match[1];
107318
107480
  if (spec.startsWith(".")) {
107319
- if (stripExt(path72.posix.join(path72.posix.dirname(file), spec)) === target)
107481
+ if (stripExt(path73.posix.join(path73.posix.dirname(file), spec)) === target)
107320
107482
  return true;
107321
107483
  } else if (spec.includes("/") && stripExt(spec).split("/").slice(-2).join("/") === tail)
107322
107484
  return true;
@@ -107336,12 +107498,12 @@ function removeStaleCopies(tmp = os23.tmpdir()) {
107336
107498
  for (const name of names) {
107337
107499
  if (!name.startsWith(TEMP_PREFIX))
107338
107500
  continue;
107339
- const dir = path72.join(tmp, name);
107501
+ const dir = path73.join(tmp, name);
107340
107502
  try {
107341
107503
  const stat = lstatSync9(dir);
107342
107504
  if (!stat.isDirectory() || uid !== undefined && stat.uid !== uid)
107343
107505
  continue;
107344
- const pid = Number(readFileSync30(path72.join(dir, PID_FILE), "utf8"));
107506
+ const pid = Number(readFileSync30(path73.join(dir, PID_FILE), "utf8"));
107345
107507
  if (Number.isInteger(pid) && pid > 0 && alive(pid))
107346
107508
  continue;
107347
107509
  } catch (error) {
@@ -107358,8 +107520,8 @@ function removeStaleCopies(tmp = os23.tmpdir()) {
107358
107520
  function linkNodeModules(origin, target, repo, copy) {
107359
107521
  mkdirSync12(target, { recursive: true });
107360
107522
  for (const entry of readdirSync15(origin, { withFileTypes: true })) {
107361
- const from = path72.join(origin, entry.name);
107362
- const to = path72.join(target, entry.name);
107523
+ const from = path73.join(origin, entry.name);
107524
+ const to = path73.join(target, entry.name);
107363
107525
  if (entry.name.startsWith("@") && entry.isDirectory()) {
107364
107526
  linkNodeModules(from, to, repo, copy);
107365
107527
  continue;
@@ -107375,9 +107537,9 @@ function linkNodeModules(origin, target, repo, copy) {
107375
107537
  } catch {
107376
107538
  continue;
107377
107539
  }
107378
- const relative = path72.relative(repo, real);
107379
- if (!relative.startsWith("..") && !path72.isAbsolute(relative) && !relative.split(path72.sep).includes("node_modules")) {
107380
- symlinkSync(path72.join(copy, relative), to, "junction");
107540
+ const relative = path73.relative(repo, real);
107541
+ if (!relative.startsWith("..") && !path73.isAbsolute(relative) && !relative.split(path73.sep).includes("node_modules")) {
107542
+ symlinkSync(path73.join(copy, relative), to, "junction");
107381
107543
  continue;
107382
107544
  }
107383
107545
  }
@@ -107393,7 +107555,7 @@ function copySymlink(repo, tree, from, to) {
107393
107555
  }
107394
107556
  const realRepo = realpathSync11(repo);
107395
107557
  if (real && inside5(realRepo, real)) {
107396
- symlinkSync(path72.relative(path72.dirname(to), path72.join(tree, path72.relative(realRepo, real))), to);
107558
+ symlinkSync(path73.relative(path73.dirname(to), path73.join(tree, path73.relative(realRepo, real))), to);
107397
107559
  return;
107398
107560
  }
107399
107561
  if (real && statSync11(real).isFile())
@@ -107402,10 +107564,10 @@ function copySymlink(repo, tree, from, to) {
107402
107564
  symlinkSync(readlinkSync3(from), to);
107403
107565
  }
107404
107566
  function writeInside(copy, file, content) {
107405
- const target = path72.join(copy, file);
107567
+ const target = path73.join(copy, file);
107406
107568
  try {
107407
107569
  const stat = lstatSync9(target);
107408
- if (!stat.isFile() || !inside5(realpathSync11(copy), realpathSync11(path72.dirname(target))))
107570
+ if (!stat.isFile() || !inside5(realpathSync11(copy), realpathSync11(path73.dirname(target))))
107409
107571
  return false;
107410
107572
  } catch {
107411
107573
  return false;
@@ -107416,9 +107578,9 @@ function writeInside(copy, file, content) {
107416
107578
  return true;
107417
107579
  }
107418
107580
  function copyWorkingTree(repo) {
107419
- const dir = mkdtempSync4(path72.join(os23.tmpdir(), TEMP_PREFIX));
107420
- writeFileSync13(path72.join(dir, PID_FILE), String(process.pid));
107421
- const tree = path72.join(dir, "tree");
107581
+ const dir = mkdtempSync4(path73.join(os23.tmpdir(), TEMP_PREFIX));
107582
+ writeFileSync13(path73.join(dir, PID_FILE), String(process.pid));
107583
+ const tree = path73.join(dir, "tree");
107422
107584
  const head = git7(repo, ["rev-parse", "--verify", "--quiet", "HEAD"]).stdout.trim();
107423
107585
  if (head && git7(dir, ["clone", "-q", "--shared", "--no-checkout", repo, tree]).ok) {
107424
107586
  const branch = git7(repo, ["symbolic-ref", "--quiet", "--short", "HEAD"]).stdout.trim();
@@ -107435,36 +107597,36 @@ function copyWorkingTree(repo) {
107435
107597
  for (const relative of listed) {
107436
107598
  if (!relative)
107437
107599
  continue;
107438
- const from = path72.join(repo, relative);
107600
+ const from = path73.join(repo, relative);
107439
107601
  let stat;
107440
107602
  try {
107441
107603
  stat = lstatSync9(from);
107442
107604
  } catch {
107443
107605
  continue;
107444
107606
  }
107445
- const to = path72.join(tree, relative);
107446
- mkdirSync12(path72.dirname(to), { recursive: true });
107607
+ const to = path73.join(tree, relative);
107608
+ mkdirSync12(path73.dirname(to), { recursive: true });
107447
107609
  if (stat.isSymbolicLink())
107448
107610
  copySymlink(repo, tree, from, to);
107449
107611
  else if (stat.isFile())
107450
107612
  copyFileSync8(from, to);
107451
- let parent = path72.dirname(relative);
107613
+ let parent = path73.dirname(relative);
107452
107614
  while (parent !== "." && !dirs.has(parent)) {
107453
107615
  dirs.add(parent);
107454
- parent = path72.dirname(parent);
107616
+ parent = path73.dirname(parent);
107455
107617
  }
107456
107618
  }
107457
107619
  for (const parent of dirs) {
107458
- const modules = path72.join(repo, parent, "node_modules");
107459
- if (existsSync29(modules) && !existsSync29(path72.join(tree, parent, "node_modules")))
107460
- linkNodeModules(modules, path72.join(tree, parent, "node_modules"), repo, tree);
107620
+ const modules = path73.join(repo, parent, "node_modules");
107621
+ if (existsSync29(modules) && !existsSync29(path73.join(tree, parent, "node_modules")))
107622
+ linkNodeModules(modules, path73.join(tree, parent, "node_modules"), repo, tree);
107461
107623
  }
107462
107624
  return { dir, tree };
107463
107625
  }
107464
107626
  function runCommand(command, cwd, timeoutMs, env) {
107465
107627
  const started = performance.now();
107466
107628
  return new Promise((resolve) => {
107467
- const child = spawn3(command, {
107629
+ const child = spawn4(command, {
107468
107630
  cwd,
107469
107631
  env,
107470
107632
  shell: true,
@@ -107496,14 +107658,14 @@ async function runMutation(options) {
107496
107658
  const tracked = git7(repo, ["ls-files", "-co", "--exclude-standard", "-z"]).stdout.split("\x00").filter(Boolean);
107497
107659
  const testFiles = tracked.filter((file) => TEST_FILE.test(file)).map((file) => {
107498
107660
  try {
107499
- return { file, text: readFileSync30(path72.join(repo, file), "utf8") };
107661
+ return { file, text: readFileSync30(path73.join(repo, file), "utf8") };
107500
107662
  } catch {
107501
107663
  return { file, text: "" };
107502
107664
  }
107503
107665
  });
107504
107666
  const candidates = [];
107505
107667
  for (const [absolute, lines] of [...options.changed].toSorted(([a], [b]) => a.localeCompare(b))) {
107506
- const relative = toPosix(path72.relative(repo, absolute));
107668
+ const relative = toPosix(path73.relative(repo, absolute));
107507
107669
  if (!CODE_FILE.test(relative) || TEST_FILE.test(relative) || relative.endsWith(".d.ts"))
107508
107670
  continue;
107509
107671
  if (NOT_SOURCE.test(relative) || !existsSync29(absolute))
@@ -107517,9 +107679,9 @@ async function runMutation(options) {
107517
107679
  for (const mutant of mutants)
107518
107680
  if (!related.has(mutant.file))
107519
107681
  related.set(mutant.file, relatedTests(mutant.file, testFiles));
107520
- const cwdRelative = path72.relative(repo, options.cwd);
107682
+ const cwdRelative = path73.relative(repo, options.cwd);
107521
107683
  const asArg = (file) => {
107522
- const relative = toPosix(path72.relative(cwdRelative, file));
107684
+ const relative = toPosix(path73.relative(cwdRelative, file));
107523
107685
  return shellQuote(relative.startsWith(".") ? relative : `./${relative}`);
107524
107686
  };
107525
107687
  const commandFor = (tests) => options.command.replaceAll("{files}", () => tests.map(asArg).join(" "));
@@ -107555,7 +107717,7 @@ async function runMutation(options) {
107555
107717
  return finish3(options, 0, results, counts, started);
107556
107718
  removeStaleCopies();
107557
107719
  const { dir: copyDir, tree: copy } = copyWorkingTree(repo);
107558
- const copyCwd = path72.join(copy, cwdRelative);
107720
+ const copyCwd = path73.join(copy, cwdRelative);
107559
107721
  let current = null;
107560
107722
  const restore = () => {
107561
107723
  if (current)
@@ -107590,7 +107752,7 @@ async function runMutation(options) {
107590
107752
  record({ ...mutant, status: "skipped", durationMs: 0, tests, reason: "budget" });
107591
107753
  continue;
107592
107754
  }
107593
- const original = readFileSync30(path72.join(copy, mutant.file), "utf8");
107755
+ const original = readFileSync30(path73.join(copy, mutant.file), "utf8");
107594
107756
  const mutated = original.slice(0, mutant.start) + mutant.replacement + original.slice(mutant.end);
107595
107757
  current = { file: mutant.file, original };
107596
107758
  if (!writeInside(copy, mutant.file, mutated)) {
@@ -107647,8 +107809,8 @@ var NOT_SOURCE, FLIPS, isStringy = (node) => node.type === "StringLiteral" || no
107647
107809
  return error.code === "EPERM";
107648
107810
  }
107649
107811
  }, inside5 = (root, file) => {
107650
- const relative = path72.relative(root, file);
107651
- return relative === "" || !relative.startsWith("..") && !path72.isAbsolute(relative);
107812
+ const relative = path73.relative(root, file);
107813
+ return relative === "" || !relative.startsWith("..") && !path73.isAbsolute(relative);
107652
107814
  }, active, killTree = (child) => {
107653
107815
  try {
107654
107816
  if (child.pid && process.platform !== "win32")
@@ -107697,7 +107859,7 @@ __export(exports_test_audit, {
107697
107859
  run: () => run23
107698
107860
  });
107699
107861
  import { existsSync as existsSync30 } from "node:fs";
107700
- import path73 from "node:path";
107862
+ import path74 from "node:path";
107701
107863
  function parse8(argv) {
107702
107864
  const options = {
107703
107865
  paths: [],
@@ -107802,8 +107964,8 @@ async function run23(argv, io) {
107802
107964
  return emit(io, fail2("invalid_input", `${options}
107803
107965
  usage: ${USAGE16}`));
107804
107966
  const top = git7(io.cwd, ["rev-parse", "--show-toplevel"]);
107805
- const repo = top.ok ? path73.resolve(top.stdout.trim()) : null;
107806
- const display = (file) => toPosix(path73.relative(io.cwd, file) || file);
107967
+ const repo = top.ok ? path74.resolve(top.stdout.trim()) : null;
107968
+ const display = (file) => toPosix(path74.relative(io.cwd, file) || file);
107807
107969
  let base = null;
107808
107970
  let changed = null;
107809
107971
  if (options.diff || options.mutate) {
@@ -107942,7 +108104,7 @@ __export(exports_youtrack, {
107942
108104
  run: () => run25
107943
108105
  });
107944
108106
  import { readFileSync as readFileSync31 } from "node:fs";
107945
- import path74 from "node:path";
108107
+ import path75 from "node:path";
107946
108108
  async function run25(argv, io) {
107947
108109
  const [sub, ...rest] = argv;
107948
108110
  if (sub !== "note" && sub !== "time" && sub !== "meeting")
@@ -107988,7 +108150,7 @@ async function run25(argv, io) {
107988
108150
  let markdown = flags.values.markdown ?? "";
107989
108151
  if (flags.values.file)
107990
108152
  try {
107991
- markdown = readFileSync31(path74.resolve(io.cwd, flags.values.file), "utf8");
108153
+ markdown = readFileSync31(path75.resolve(io.cwd, flags.values.file), "utf8");
107992
108154
  } catch (error) {
107993
108155
  return usage4(io, `cannot read ${flags.values.file}: ${String(error)}`, USAGE18);
107994
108156
  }
@@ -108057,7 +108219,7 @@ __export(exports_changelog, {
108057
108219
  run: () => run26
108058
108220
  });
108059
108221
  import { readFileSync as readFileSync32 } from "node:fs";
108060
- import path75 from "node:path";
108222
+ import path76 from "node:path";
108061
108223
  async function run26(argv, io) {
108062
108224
  const [sub, ...rest] = argv;
108063
108225
  if (sub !== "apply")
@@ -108103,7 +108265,7 @@ async function run26(argv, io) {
108103
108265
  ]);
108104
108266
  }
108105
108267
  var USAGE19 = "workit changelog apply (--entries <JSON|@file|-> | --normalize-only) [--path CHANGELOG.md] [--preview]", readEntries = (raw, cwd) => {
108106
- const text = raw === "-" ? readFileSync32(0, "utf8") : raw.startsWith("@") ? readFileSync32(path75.resolve(cwd, raw.slice(1)), "utf8") : raw;
108268
+ const text = raw === "-" ? readFileSync32(0, "utf8") : raw.startsWith("@") ? readFileSync32(path76.resolve(cwd, raw.slice(1)), "utf8") : raw;
108107
108269
  return JSON.parse(text);
108108
108270
  };
108109
108271
  var init_changelog2 = __esm(() => {
@@ -108119,7 +108281,7 @@ __export(exports_handoff, {
108119
108281
  run: () => run27
108120
108282
  });
108121
108283
  import fs37 from "node:fs";
108122
- import path76 from "node:path";
108284
+ import path77 from "node:path";
108123
108285
  import { parseArgs as parseArgs2 } from "node:util";
108124
108286
  function render3(brief) {
108125
108287
  const lines = [
@@ -108159,9 +108321,9 @@ function bounded(brief, cwd) {
108159
108321
  let file = null;
108160
108322
  if (store.ok)
108161
108323
  try {
108162
- const dir = path76.join(store.value.root, "handoff");
108324
+ const dir = path77.join(store.value.root, "handoff");
108163
108325
  fs37.mkdirSync(dir, { recursive: true });
108164
- file = path76.join(dir, `${(brief.branch ?? "detached").replaceAll(/[^\w.-]+/gu, "-")}.txt`);
108326
+ file = path77.join(dir, `${(brief.branch ?? "detached").replaceAll(/[^\w.-]+/gu, "-")}.txt`);
108165
108327
  fs37.writeFileSync(file, `${[...body, ...tail].join(`
108166
108328
  `)}
108167
108329
  `, {
@@ -108236,7 +108398,7 @@ var init_handoff = __esm(() => {
108236
108398
  });
108237
108399
 
108238
108400
  // packages/workit-cli/src/main.ts
108239
- import path77 from "node:path";
108401
+ import path78 from "node:path";
108240
108402
 
108241
108403
  // packages/workit-core/src/git/env-redirect.ts
108242
108404
  var GIT_REDIRECT_ENV = [
@@ -109185,7 +109347,7 @@ var defaultIo = (json) => ({
109185
109347
  });
109186
109348
  async function main(argv, overrides = {}, options = {}) {
109187
109349
  const parsed = parseGlobals(argv);
109188
- const cwd = path77.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
109350
+ const cwd = path78.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
109189
109351
  const io = { ...defaultIo(parsed.json), ...overrides, json: parsed.json, cwd };
109190
109352
  if (parsed.error)
109191
109353
  return emit(io, fail2("invalid_input", parsed.error));