@brainervirus/workit-claude-code 8.44.0 → 8.44.2

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
@@ -9431,7 +9431,7 @@ var package_default;
9431
9431
  var init_package = __esm(() => {
9432
9432
  package_default = {
9433
9433
  name: "@brainervirus/workit-cli",
9434
- version: "8.44.0",
9434
+ version: "8.44.2",
9435
9435
  private: false,
9436
9436
  description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
9437
9437
  keywords: [
@@ -9469,13 +9469,13 @@ var init_package = __esm(() => {
9469
9469
  },
9470
9470
  dependencies: {
9471
9471
  "@babel/parser": "7.29.9",
9472
- "@brainervirus/workit-cursor": "^8.44.0",
9472
+ "@brainervirus/workit-cursor": "^8.44.2",
9473
9473
  "@inkjs/ui": "2.0.0",
9474
9474
  ink: "7.1.1",
9475
9475
  react: "19.2.8"
9476
9476
  },
9477
9477
  devDependencies: {
9478
- "@brainervirus/workit-core": "^8.44.0"
9478
+ "@brainervirus/workit-core": "^8.44.2"
9479
9479
  },
9480
9480
  engines: {
9481
9481
  node: ">=24"
@@ -68214,7 +68214,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68214
68214
  found.push({ pid: Number(m[1]), startedMs, args: m[3] });
68215
68215
  }
68216
68216
  return found;
68217
- }, 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) => {
68217
+ }, PS_START_SLACK_MS = 2000, startedBefore = (proc, installedMs) => proc.startedMs + PS_START_SLACK_MS < installedMs, 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) => {
68218
68218
  const env = options.env ?? process.env;
68219
68219
  const home = options.home ?? env.HOME ?? os13.homedir();
68220
68220
  const configDir = options.configDir ?? env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path40.join(home, ".config", "workit");
@@ -68230,7 +68230,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68230
68230
  cwd,
68231
68231
  workspaceRoot: options.workspaceRoot ?? env.WORKFLOW_WORKSPACE_ROOT ?? cwd,
68232
68232
  dev,
68233
- opencodeConfig: options.opencodeConfig ?? path40.join(home, ".config", "opencode", "opencode.json"),
68233
+ opencodeConfig: options.opencodeConfig ?? path40.join(env.XDG_CONFIG_HOME || path40.join(home, ".config"), "opencode", "opencode.json"),
68234
68234
  opencodePackageCacheDir: options.opencodePackageCacheDir ?? null,
68235
68235
  cursorSettings: options.cursorSettings ?? path40.join(home, ".cursor", "settings.json"),
68236
68236
  cursorMcp: options.cursorMcp ?? path40.join(home, ".cursor", "mcp.json"),
@@ -69369,9 +69369,25 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69369
69369
  detail: `OpenCode @latest cache workit-opencode ${installed} matches published ${expected}`
69370
69370
  };
69371
69371
  }, checkStaleInstall = (res) => {
69372
- if (res.host === "opencode") {
69372
+ if (res.host === "opencode")
69373
69373
  return checkOpenCodePackageCache(res);
69374
- }
69374
+ const cursor = checkCursorStaleInstall(res);
69375
+ if (res.host !== "cli")
69376
+ return cursor;
69377
+ const oc = checkOpenCodePackageCache(res);
69378
+ if (oc.status === "pass")
69379
+ return cursor;
69380
+ if (cursor.status === "pass")
69381
+ return oc;
69382
+ if (oc.id !== "stale_install")
69383
+ return cursor;
69384
+ return {
69385
+ ...cursor,
69386
+ registryProbed: Boolean(cursor.registryProbed || oc.registryProbed),
69387
+ detail: `${cursor.detail}; ${oc.detail}`,
69388
+ fix: [cursor.fix, oc.fix].filter(Boolean).join("; ")
69389
+ };
69390
+ }, checkCursorStaleInstall = (res) => {
69375
69391
  if (res.host !== "cursor" && res.host !== "cli") {
69376
69392
  return {
69377
69393
  id: "stale_install",
@@ -69479,11 +69495,6 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69479
69495
  registryProbed: true,
69480
69496
  detail: `installed local-dist workit-cursor ${installed} matches the published runtime ${expected}`
69481
69497
  };
69482
- if (res.host === "cli") {
69483
- const oc = checkOpenCodePackageCache(res);
69484
- if (oc.status !== "pass")
69485
- return oc;
69486
- }
69487
69498
  return cursorOk;
69488
69499
  }
69489
69500
  const cursorOk = {
@@ -69491,11 +69502,6 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69491
69502
  status: "pass",
69492
69503
  detail: installed === null ? "installed workit-cursor selectors are canonical" : `installed workit-cursor ${installed} on canonical selectors (hooks run this version through the pinned launcher; MCP resolves @latest at launch)`
69493
69504
  };
69494
- if (res.host === "cli") {
69495
- const oc = checkOpenCodePackageCache(res);
69496
- if (oc.status !== "pass")
69497
- return oc;
69498
- }
69499
69505
  return cursorOk;
69500
69506
  }, checkDuplicateRegistration = (res) => {
69501
69507
  const problems = [];
@@ -70223,7 +70229,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
70223
70229
  status: "info",
70224
70230
  detail: "could not list running claude processes (ps) — skipping"
70225
70231
  };
70226
- const stale = running.filter((proc) => proc.startedMs < latest.at);
70232
+ const stale = running.filter((proc) => startedBefore(proc, latest.at));
70227
70233
  if (stale.length === 0)
70228
70234
  return {
70229
70235
  id,
@@ -70271,7 +70277,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
70271
70277
  status: "info",
70272
70278
  detail: "could not list running codex processes (ps) — skipping"
70273
70279
  };
70274
- const stale = running.filter((proc) => proc.startedMs < latest.at);
70280
+ const stale = running.filter((proc) => startedBefore(proc, latest.at));
70275
70281
  if (stale.length === 0)
70276
70282
  return {
70277
70283
  id,
@@ -75769,9 +75775,13 @@ import { createHash as createHash15 } from "node:crypto";
75769
75775
  function errorText(error) {
75770
75776
  return error instanceof Error ? error.message : "installed source could not be read";
75771
75777
  }
75772
- 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) => {
75778
+ 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(" | "), errorLine = (result) => `${result.stdout}
75779
+ ${result.stderr ?? ""}`.split(/\r?\n/).map((line) => line.trim()).find((line) => /\bError:/.test(line)), failureReason = (command, result) => {
75773
75780
  const tail = stderrTail(result.stderr);
75774
- return `\`${command.command} ${command.args.join(" ")}\` failed${tail ? `: ${tail}` : ""}`;
75781
+ const message = errorLine(result);
75782
+ const detail = message && !tail.includes(message) ? [message, tail].filter(Boolean) : [tail];
75783
+ const text = detail.filter(Boolean).join(" | ");
75784
+ return `\`${command.command} ${command.args.join(" ")}\` failed${text ? `: ${text}` : ""}`;
75775
75785
  }, 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) => {
75776
75786
  const home = deps.home ?? deps.env?.HOME ?? os17.homedir();
75777
75787
  const env = {
@@ -75818,27 +75828,27 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
75818
75828
  } catch {
75819
75829
  return null;
75820
75830
  }
75821
- }, digest2 = (file) => existsSync21(file) ? createHash15("sha256").update(readFileSync23(file)).digest("hex") : "missing", runner = (deps) => deps.run ?? ((command, args) => {
75831
+ }, digest2 = (file) => existsSync21(file) ? createHash15("sha256").update(readFileSync23(file)).digest("hex") : "missing", runner = (deps) => deps.run ?? ((command, args, options) => {
75822
75832
  const { home, env } = upgradePaths(deps);
75823
75833
  let step;
75824
75834
  try {
75825
- step = hostCommand(command, args, { home, env });
75835
+ step = hostCommand(command, args, { home, env, cwd: options?.cwd });
75826
75836
  } catch (error) {
75827
75837
  return { status: 1, stdout: "", stderr: errorText(error) };
75828
75838
  }
75829
75839
  const result = runHostCommand(step, { home, env });
75830
75840
  return { status: result.exitCode, stdout: result.stdout, stderr: result.stderr };
75831
- }), COMMAND_TIMEOUT_MS = 60000, asyncRunner = (deps) => {
75841
+ }), COMMAND_TIMEOUT_MS = 60000, asyncRunner = (deps, timeoutMs = COMMAND_TIMEOUT_MS) => {
75832
75842
  if (deps.runAsync)
75833
75843
  return deps.runAsync;
75834
75844
  const injected = deps.run;
75835
75845
  if (injected)
75836
- return async (command, args) => injected(command, args);
75837
- return (command, args) => {
75846
+ return async (command, args, options) => injected(command, args, options);
75847
+ return (command, args, options) => {
75838
75848
  const { home, env } = upgradePaths(deps);
75839
75849
  let step;
75840
75850
  try {
75841
- step = hostCommand(command, args, { home, env });
75851
+ step = hostCommand(command, args, { home, env, cwd: options?.cwd });
75842
75852
  } catch (error) {
75843
75853
  return Promise.resolve({ status: 1, stdout: "", stderr: errorText(error) });
75844
75854
  }
@@ -75880,7 +75890,7 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
75880
75890
  const timer = setTimeout(() => {
75881
75891
  child.kill("SIGKILL");
75882
75892
  finish(1);
75883
- }, COMMAND_TIMEOUT_MS);
75893
+ }, timeoutMs);
75884
75894
  child.stdout?.setEncoding("utf8");
75885
75895
  child.stdout?.on("data", (chunk) => stdout += chunk);
75886
75896
  child.stderr?.setEncoding("utf8");
@@ -75978,11 +75988,95 @@ var init_processes = __esm(() => {
75978
75988
  SCRIPT_RUNTIMES = new Set(["node", "nodejs", "bun"]);
75979
75989
  });
75980
75990
 
75991
+ // packages/workit-cli/src/upgrade/opencode.ts
75992
+ var pluginApiArgs = (home) => [
75993
+ "api",
75994
+ "plugin.list",
75995
+ "-H",
75996
+ `x-opencode-directory:${home}`
75997
+ ], PLUGIN_LIST, OPENCODE_READY_TIMEOUT_MS = 20000, READY_INTERVAL_MS = 500, OPENCODE_NOT_READY, isWorkitTarget = (target) => typeof target === "string" && /^(?:npm:)?@brainervirus\/workit-opencode(?:@[^/\s]+)?$/.test(target), lacksApi = (result) => result.status !== 0 && !result.timedOut && /\b(?:unknown|unrecognized|unsupported) (?:command|operation|argument)|\bno such (?:command|operation)/i.test(`${result.stdout}
75998
+ ${result.stderr ?? ""}`), parsePluginApi = (result) => {
75999
+ if (result.status !== 0)
76000
+ return null;
76001
+ let parsed;
76002
+ try {
76003
+ parsed = JSON.parse(result.stdout);
76004
+ } catch {
76005
+ return null;
76006
+ }
76007
+ const data = parsed?.data;
76008
+ if (!Array.isArray(data))
76009
+ return null;
76010
+ const entry = data.find((item) => isWorkitTarget(item?.source?.target));
76011
+ if (!entry)
76012
+ return { via: "api", listed: false };
76013
+ const version = entry.source?.version;
76014
+ return {
76015
+ via: "api",
76016
+ listed: true,
76017
+ ...typeof version === "string" && /^\d+\.\d+\.\d+$/.test(version) ? { version } : {},
76018
+ ...typeof entry.source?.outdated === "boolean" ? { outdated: entry.source.outdated } : {},
76019
+ ...typeof entry.state?.status === "string" ? { status: entry.state.status } : {}
76020
+ };
76021
+ }, parsePluginList = (result) => {
76022
+ if (result.status === 0)
76023
+ for (const line of result.stdout.split(/\r?\n/)) {
76024
+ const fields = line.trim().split(/\s+/);
76025
+ if (fields.length < 3)
76026
+ continue;
76027
+ const source = fields[fields.length - 1].replace(/^file:\/\//, "");
76028
+ const version = fields[fields.length - 2];
76029
+ if (isWorkitTarget(source) && /^\d+\.\d+\.\d+$/.test(version))
76030
+ return { via: "list", listed: true, version };
76031
+ }
76032
+ return { via: "list", listed: false };
76033
+ }, readOpencodePlugin = async (run, home) => parsePluginApi(await run("opencode", pluginApiArgs(home), { cwd: home })) ?? parsePluginList(await run("opencode", PLUGIN_LIST, { cwd: home })), waitForOpencodePlugin = async (run, home, options = {}) => {
76034
+ const timeoutMs = options.timeoutMs ?? OPENCODE_READY_TIMEOUT_MS;
76035
+ const intervalMs = options.intervalMs ?? READY_INTERVAL_MS;
76036
+ const now = options.now ?? Date.now;
76037
+ const sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
76038
+ const deadline = now() + timeoutMs;
76039
+ const [versionResult, firstApi] = await Promise.all([
76040
+ run("opencode", ["--version"], { cwd: home }),
76041
+ run("opencode", pluginApiArgs(home), { cwd: home })
76042
+ ]);
76043
+ const installed = versionResult.stdout.match(/\d+\.\d+\.\d+/)?.[0];
76044
+ if (installed && !versionAtLeast(installed, SUPPORT_MATRIX.opencode.minimum)) {
76045
+ const text = parsePluginList(await run("opencode", PLUGIN_LIST, { cwd: home }));
76046
+ return text.listed ? text : { via: "list", listed: true };
76047
+ }
76048
+ let pending = firstApi;
76049
+ let textOnly = false;
76050
+ for (;; ) {
76051
+ let api = null;
76052
+ if (!textOnly) {
76053
+ const result = pending ?? await run("opencode", pluginApiArgs(home), { cwd: home });
76054
+ pending = undefined;
76055
+ api = parsePluginApi(result);
76056
+ textOnly = !api && lacksApi(result);
76057
+ }
76058
+ if (textOnly || api?.listed) {
76059
+ const text = parsePluginList(await run("opencode", PLUGIN_LIST, { cwd: home }));
76060
+ if (text.listed)
76061
+ return api?.listed ? { ...api, version: api.version ?? text.version } : text;
76062
+ }
76063
+ if (now() >= deadline)
76064
+ return null;
76065
+ await sleep(Math.min(intervalMs, Math.max(0, deadline - now())));
76066
+ }
76067
+ };
76068
+ var init_opencode = __esm(() => {
76069
+ init_support_matrix();
76070
+ init_shared();
76071
+ PLUGIN_LIST = ["plugin", "list"];
76072
+ OPENCODE_NOT_READY = `OpenCode did not finish loading its plugins (opencode api plugin.list never listed ${OPENCODE_PACKAGE})`;
76073
+ });
76074
+
75981
76075
  // packages/workit-cli/src/upgrade/apply.ts
75982
76076
  import { existsSync as existsSync22, readdirSync as readdirSync12, mkdirSync as mkdirSync12, copyFileSync as copyFileSync6, chmodSync as chmodSync2, cpSync as cpSync5 } from "node:fs";
75983
76077
  import path48 from "node:path";
75984
76078
  import { createHash as createHash16 } from "node:crypto";
75985
- async function applyUpgrade(plan, deps = {}) {
76079
+ async function applyUpgrade(plan, deps = {}, options = {}) {
75986
76080
  const hosts = [...plan.failed];
75987
76081
  const done = (backup) => {
75988
76082
  const failures = hosts.filter((entry) => entry.status === "failed");
@@ -76039,6 +76133,26 @@ async function applyUpgrade(plan, deps = {}) {
76039
76133
  const runAsync = asyncRunner(deps);
76040
76134
  const progress = deps.progress ?? createProgress({ json: true });
76041
76135
  const statusOf = (outcome) => outcome?.status === "failed" ? "failed" : outcome?.status === "updated" ? "done" : "skipped";
76136
+ if (plan.cli) {
76137
+ let cli;
76138
+ try {
76139
+ cli = await progress.run("Updating the CLI", () => applyCli(plan.cli, runAsync, backup), statusOf, { signals: true });
76140
+ } catch (error) {
76141
+ cli = { host: "cli", status: "failed", reason: errorText(error), fix: CLI_FIX };
76142
+ }
76143
+ if (cli.status === "updated" && options.handoff) {
76144
+ const code = await options.handoff(cli);
76145
+ if (code !== undefined)
76146
+ return { ...done(backup), hosts: [...hosts, cli], handedOff: code };
76147
+ if (plan.entries.length)
76148
+ cli = {
76149
+ ...cli,
76150
+ reason: `${cli.reason}; the new CLI could not be started, hosts upgraded with workit ${package_default.version}`
76151
+ };
76152
+ } else if (cli.status === "failed" && plan.entries.length)
76153
+ cli = { ...cli, reason: `${cli.reason}; hosts upgraded with workit ${package_default.version}` };
76154
+ hosts.push(cli);
76155
+ }
76042
76156
  let cursorBackupError = null;
76043
76157
  if (plan.entries.some((entry) => entry.host === "cursor") && existsSync22(paths.cursorRoot))
76044
76158
  try {
@@ -76098,7 +76212,12 @@ async function applyUpgrade(plan, deps = {}) {
76098
76212
  }
76099
76213
  let outcome;
76100
76214
  try {
76101
- outcome = await applyEntry(entry, { runAsync, paths, configDir });
76215
+ outcome = await applyEntry(entry, {
76216
+ runAsync,
76217
+ paths,
76218
+ configDir,
76219
+ opencodeReady: deps.opencodeReady
76220
+ });
76102
76221
  if (entry.host === "codex" && outcome.status === "updated") {
76103
76222
  const agents = await refreshCodexAgents(runAsync, paths.codexHome);
76104
76223
  if (!agents.ok)
@@ -76173,17 +76292,6 @@ async function applyUpgrade(plan, deps = {}) {
76173
76292
  reason: `${hosts[index].reason}; ${agents.note}`
76174
76293
  };
76175
76294
  }
76176
- if (plan.cli)
76177
- try {
76178
- hosts.push(await progress.run("Updating the CLI", () => applyCli(plan.cli, runAsync, backup), statusOf, { signals: true }));
76179
- } catch (error) {
76180
- hosts.push({
76181
- host: "cli",
76182
- status: "failed",
76183
- reason: errorText(error),
76184
- fix: CLI_FIX
76185
- });
76186
- }
76187
76295
  return done(backup);
76188
76296
  }
76189
76297
  var briefDetail = (detail) => {
@@ -76199,20 +76307,31 @@ var briefDetail = (detail) => {
76199
76307
  }
76200
76308
  const newest = versions.reduce((best, version) => best && versionAtLeast(best, version) ? best : version, null);
76201
76309
  return newest ? path48.join(dir, newest) : null;
76202
- }, opencodeVersion = async (run) => {
76203
- const listing = await run("opencode", ["plugin", "list"]);
76204
- if (listing.status !== 0)
76205
- return;
76206
- for (const line of listing.stdout.split(/\r?\n/)) {
76207
- const fields = line.trim().split(/\s+/);
76208
- if (fields.length < 3)
76209
- continue;
76210
- const source = fields[fields.length - 1].replace(/^file:\/\//, "");
76211
- const version = fields[fields.length - 2];
76212
- if (/^(?:npm:)?@brainervirus\/workit-opencode(?:@[^/\s]+)?$/.test(source) && /^\d+\.\d+\.\d+$/.test(version))
76213
- return version;
76214
- }
76215
- return;
76310
+ }, opencodeVersion = async (run, home) => (await readOpencodePlugin(run, home)).version, opencodeOutcome = async (before, target, runAsync, home) => {
76311
+ const below = (version) => target !== undefined && (version === undefined || !versionAtLeast(version, target));
76312
+ let after = await opencodeVersion(runAsync, home);
76313
+ if (below(after))
76314
+ after = await opencodeVersion(runAsync, home) ?? after;
76315
+ const live = "OpenCode V2 loads it live";
76316
+ if (before && target && versionAtLeast(before, target))
76317
+ return { host: "opencode", status: "current", reason: `already current (${before})` };
76318
+ if (after && below(after))
76319
+ return {
76320
+ host: "opencode",
76321
+ status: "updated",
76322
+ reason: `update ran, but OpenCode still lists ${after} (published ${target}); the doctor below checks its package cache`
76323
+ };
76324
+ if (before && after && after !== before)
76325
+ return { host: "opencode", status: "updated", reason: `${before} -> ${after}; ${live}` };
76326
+ if (before && after)
76327
+ return {
76328
+ host: "opencode",
76329
+ status: "current",
76330
+ reason: `unchanged (${after}); the published version could not be read`
76331
+ };
76332
+ if (after)
76333
+ return { host: "opencode", status: "updated", reason: `now ${after}; ${live}` };
76334
+ return { host: "opencode", status: "updated", reason: `scoped update ran; ${live}` };
76216
76335
  }, applyEntry = async (entry, context) => {
76217
76336
  const { runAsync, paths, configDir } = context;
76218
76337
  const { home, env } = paths;
@@ -76289,32 +76408,23 @@ ${result.stderr}`;
76289
76408
  reason: entry.repair ? `reinstalled missing plugin files (${entry.latest})` : `${entry.installedVersion ?? "?"} -> ${entry.latest}`
76290
76409
  };
76291
76410
  }
76292
- const before = entry.host === "opencode" ? await opencodeVersion(runAsync) : undefined;
76411
+ let before;
76412
+ if (entry.host === "opencode") {
76413
+ const ready = await waitForOpencodePlugin(runAsync, home, context.opencodeReady);
76414
+ if (!ready)
76415
+ return fail(OPENCODE_NOT_READY);
76416
+ before = ready.version;
76417
+ }
76293
76418
  for (const command of entry.commands) {
76294
- let result = await runAsync(command.command, command.args);
76419
+ const where = command.cwd ? { cwd: command.cwd } : undefined;
76420
+ let result = await runAsync(command.command, command.args, where);
76295
76421
  if (result.status !== 0 && entry.host === "opencode")
76296
- result = await runAsync(command.command, command.args);
76422
+ result = await runAsync(command.command, command.args, where);
76297
76423
  if (result.status !== 0)
76298
76424
  return fail(failureReason(command, result));
76299
76425
  }
76300
- if (entry.host === "opencode") {
76301
- const after = await opencodeVersion(runAsync);
76302
- if (before && after)
76303
- return after === before ? {
76304
- host: "opencode",
76305
- status: "current",
76306
- reason: `already current (${after})`
76307
- } : {
76308
- host: "opencode",
76309
- status: "updated",
76310
- reason: `${before} -> ${after}; OpenCode V2 loads it live`
76311
- };
76312
- return {
76313
- host: "opencode",
76314
- status: "updated",
76315
- reason: "scoped update ran; OpenCode V2 loads it live"
76316
- };
76317
- }
76426
+ if (entry.host === "opencode")
76427
+ return opencodeOutcome(before, entry.published, runAsync, home);
76318
76428
  if (entry.host === "claude-code") {
76319
76429
  const after = claudeWorkitInstalls(home, env, null).find((install) => install.id === entry.selector)?.version;
76320
76430
  return after && after === entry.installedVersion ? {
@@ -76388,12 +76498,14 @@ ${result.stderr}`;
76388
76498
  };
76389
76499
  };
76390
76500
  var init_apply = __esm(() => {
76501
+ init_package();
76391
76502
  init_host_install();
76392
76503
  init_setup_state();
76393
76504
  init_setup();
76394
76505
  init_safe_write();
76395
76506
  init_progress();
76396
76507
  init_processes();
76508
+ init_opencode();
76397
76509
  init_shared();
76398
76510
  });
76399
76511
 
@@ -76558,14 +76670,107 @@ var init_update_check = __esm(() => {
76558
76670
  ]);
76559
76671
  });
76560
76672
 
76561
- // packages/workit-cli/src/upgrade/plan.ts
76562
- import { existsSync as existsSync23, mkdtempSync as mkdtempSync3, rmSync as rmSync8, lstatSync as lstatSync8, readFileSync as readFileSync25 } from "node:fs";
76563
- import path50 from "node:path";
76673
+ // packages/workit-cli/src/upgrade/probes.ts
76674
+ import { existsSync as existsSync23, mkdtempSync as mkdtempSync3, rmSync as rmSync8 } from "node:fs";
76564
76675
  import os18 from "node:os";
76565
- function previewUpgrade(hosts = HOSTS2, deps = {}) {
76676
+ import path50 from "node:path";
76677
+ var PROBE_TIMEOUT_MS = 20000, probeKey = (command, args) => [command, ...args].join(" "), opencodeScratchEnv = (deps, scratch) => ({
76678
+ ...deps.env,
76679
+ XDG_DATA_HOME: path50.join(scratch, "data"),
76680
+ XDG_STATE_HOME: path50.join(scratch, "state"),
76681
+ XDG_CACHE_HOME: path50.join(scratch, "cache")
76682
+ }), registry2 = (name) => ["npm", ["view", name, "version"]], OPENCODE_READY_KEY = "opencode-ready", opencodeReading = (probes) => {
76683
+ const result = probes?.get(OPENCODE_READY_KEY);
76684
+ if (!result)
76685
+ return;
76686
+ return result.status === 0 ? JSON.parse(result.stdout) : null;
76687
+ }, opencodeRegistersWorkit = (file) => {
76688
+ const config = objectOrNull(file);
76689
+ return [config?.plugins, config?.plugin].flatMap((value) => Array.isArray(value) ? value : []).some((pin) => typeof pin === "string" && /^(?:npm:)?@brainervirus\/workit-opencode(?:@[^/\s]+)?$/.test(pin));
76690
+ }, runProbes = async (hosts, cli, deps, options = {}) => {
76691
+ const paths = upgradePaths(deps);
76692
+ const timeoutMs = deps.probeTimeoutMs ?? PROBE_TIMEOUT_MS;
76693
+ const run = asyncRunner(deps, timeoutMs);
76694
+ const probes = [];
76695
+ const add = (command, args, runner = run) => probes.push([command, args, runner]);
76696
+ const scratch = mkdtempSync3(path50.join(os18.tmpdir(), "workit-upgrade-opencode-"));
76697
+ try {
76698
+ if (hosts.includes("opencode") && existsSync23(paths.opencodeConfig)) {
76699
+ if (!options.check) {
76700
+ const opencode = asyncRunner({ ...deps, env: opencodeScratchEnv(deps, scratch) }, timeoutMs);
76701
+ add("opencode", ["--version"], opencode);
76702
+ add("opencode", ["plugin", "--help"], opencode);
76703
+ }
76704
+ add(...registry2(OPENCODE_PACKAGE));
76705
+ }
76706
+ for (const name of options.registries ?? [])
76707
+ add(...registry2(name));
76708
+ if (hosts.includes("cursor"))
76709
+ add(...registry2("@brainervirus/workit-cursor"));
76710
+ if (hosts.includes("codex")) {
76711
+ add("codex", ["plugin", "list", "--json"]);
76712
+ add(...registry2("@brainervirus/workit-codex"));
76713
+ }
76714
+ if (hosts.includes("pi")) {
76715
+ if (existsSync23(paths.piSettings))
76716
+ add("pi", ["list"]);
76717
+ add(...registry2("@brainervirus/workit-pi"));
76718
+ }
76719
+ if (cli) {
76720
+ add("npm", ["root", "--global"]);
76721
+ add(...registry2(CLI_PACKAGE2));
76722
+ }
76723
+ const ready = hosts.includes("opencode") && opencodeRegistersWorkit(paths.opencodeConfig) ? waitForOpencodePlugin((command, args, where) => run(command, args, where).catch((error) => ({
76724
+ status: 1,
76725
+ stdout: "",
76726
+ stderr: error instanceof Error ? error.message : String(error)
76727
+ })), paths.home, deps.opencodeReady).then((reading) => [
76728
+ OPENCODE_READY_KEY,
76729
+ reading ? { status: 0, stdout: JSON.stringify(reading) } : { status: 1, stdout: "", stderr: OPENCODE_NOT_READY }
76730
+ ]) : undefined;
76731
+ const results = await Promise.all(probes.map(async ([command, args, runner]) => {
76732
+ let timer;
76733
+ const timedOut = new Promise((resolve) => {
76734
+ timer = setTimeout(() => resolve({
76735
+ status: null,
76736
+ stdout: "",
76737
+ stderr: `\`${probeKey(command, args)}\` timed out after ${Math.round(timeoutMs / 1000)} s`,
76738
+ timedOut: true
76739
+ }), timeoutMs);
76740
+ });
76741
+ try {
76742
+ const result = await Promise.race([
76743
+ runner(command, args).catch((error) => ({
76744
+ status: 1,
76745
+ stdout: "",
76746
+ stderr: error instanceof Error ? error.message : String(error)
76747
+ })),
76748
+ timedOut
76749
+ ]);
76750
+ return [probeKey(command, args), result];
76751
+ } finally {
76752
+ clearTimeout(timer);
76753
+ }
76754
+ }));
76755
+ return new Map([...results, ...ready ? [await ready] : []]);
76756
+ } finally {
76757
+ rmSync8(scratch, { recursive: true, force: true });
76758
+ }
76759
+ };
76760
+ var init_probes = __esm(() => {
76761
+ init_update_check();
76762
+ init_opencode();
76763
+ init_shared();
76764
+ });
76765
+
76766
+ // packages/workit-cli/src/upgrade/plan.ts
76767
+ import { existsSync as existsSync24, mkdtempSync as mkdtempSync4, rmSync as rmSync9, lstatSync as lstatSync8, readFileSync as readFileSync25 } from "node:fs";
76768
+ import path51 from "node:path";
76769
+ import os19 from "node:os";
76770
+ function previewUpgrade(hosts = HOSTS2, deps = {}, probes) {
76566
76771
  const paths = upgradePaths(deps);
76567
76772
  const { home, configDir } = paths;
76568
- const run = runner(deps);
76773
+ const run = probedRunner(deps, probes);
76569
76774
  const state = readSetupState(configDir);
76570
76775
  const plan = {
76571
76776
  ok: true,
@@ -76584,9 +76789,9 @@ function previewUpgrade(hosts = HOSTS2, deps = {}) {
76584
76789
  for (const file of [
76585
76790
  paths.opencodeConfig,
76586
76791
  paths.opencodeConfig + "c",
76587
- path50.join(home, ".cursor/settings.json"),
76588
- path50.join(home, ".cursor/mcp.json"),
76589
- path50.join(paths.cursorRoot, "package.json"),
76792
+ path51.join(home, ".cursor/settings.json"),
76793
+ path51.join(home, ".cursor/mcp.json"),
76794
+ path51.join(paths.cursorRoot, "package.json"),
76590
76795
  paths.codexConfig,
76591
76796
  paths.piSettings
76592
76797
  ])
@@ -76605,7 +76810,7 @@ function previewUpgrade(hosts = HOSTS2, deps = {}) {
76605
76810
  const installedSources = sources(paths, run, hosts, plan.failed);
76606
76811
  let opencodeHelp;
76607
76812
  if (installedSources.some((source) => source.host === "opencode")) {
76608
- const probe = opencodeProbe(deps, ["--version"]);
76813
+ const probe = opencodeProbe(deps, ["--version"], probes);
76609
76814
  const installed = probe.status === 0 ? probe.stdout.match(/\d+\.\d+\.\d+/)?.[0] : undefined;
76610
76815
  if (installed && !versionAtLeast(installed, SUPPORT_MATRIX.opencode.minimum))
76611
76816
  (plan.warnings ??= []).push(`opencode ${installed}: ${OPENCODE_V1_FIX}`);
@@ -76646,7 +76851,17 @@ function previewUpgrade(hosts = HOSTS2, deps = {}) {
76646
76851
  continue;
76647
76852
  }
76648
76853
  if (source.host === "opencode") {
76649
- opencodeHelp ??= opencodeProbe(deps, ["plugin", "--help"]).stdout;
76854
+ const help = opencodeProbe(deps, ["plugin", "--help"], probes);
76855
+ if (help.timedOut) {
76856
+ plan.failed.push({
76857
+ host: "opencode",
76858
+ status: "failed",
76859
+ reason: `could not check: ${help.stderr}`,
76860
+ fix: OPENCODE_UPDATE
76861
+ });
76862
+ continue;
76863
+ }
76864
+ opencodeHelp ??= help.stdout;
76650
76865
  if (!/^\s*(?:opencode\s+plugin\s+)?update\b/m.test(opencodeHelp)) {
76651
76866
  plan.skipped.push({
76652
76867
  host: "opencode",
@@ -76655,11 +76870,26 @@ function previewUpgrade(hosts = HOSTS2, deps = {}) {
76655
76870
  });
76656
76871
  continue;
76657
76872
  }
76873
+ const reading = opencodeReading(probes);
76874
+ if (reading === null) {
76875
+ plan.failed.push({
76876
+ host: "opencode",
76877
+ status: "failed",
76878
+ reason: OPENCODE_NOT_READY,
76879
+ fix: OPENCODE_UPDATE
76880
+ });
76881
+ continue;
76882
+ }
76883
+ const published = registryVersion(run, OPENCODE_PACKAGE);
76658
76884
  plan.entries.push({
76659
76885
  host: "opencode",
76660
76886
  selector: source.selector,
76661
76887
  latest: "",
76662
- commands: [{ command: "opencode", args: ["plugin", "update", OPENCODE_PACKAGE] }],
76888
+ ...published ? { published } : {},
76889
+ ...reading?.version ? { installedVersion: reading.version } : {},
76890
+ commands: [
76891
+ { command: "opencode", args: ["plugin", "update", OPENCODE_PACKAGE], cwd: home }
76892
+ ],
76663
76893
  fix: OPENCODE_UPDATE
76664
76894
  });
76665
76895
  continue;
@@ -76746,7 +76976,7 @@ var codexRegistered = (configFile) => {
76746
76976
  }
76747
76977
  };
76748
76978
  guard("opencode", () => {
76749
- if (existsSync23(paths.opencodeConfig + "c"))
76979
+ if (existsSync24(paths.opencodeConfig + "c"))
76750
76980
  throw new Error("OpenCode JSONC config is present; inspect effective native configuration before updating");
76751
76981
  const oc = object2(paths.opencodeConfig);
76752
76982
  if (oc && [oc.plugins, oc.plugin].some((value) => value !== undefined && !Array.isArray(value)))
@@ -76756,8 +76986,8 @@ var codexRegistered = (configFile) => {
76756
76986
  result.push(classify("opencode", pin));
76757
76987
  });
76758
76988
  guard("cursor", () => {
76759
- const cursor = objectOrNull(path50.join(paths.cursorRoot, "package.json"));
76760
- const mcp = objectOrNull(path50.join(home, ".cursor/mcp.json"));
76989
+ const cursor = objectOrNull(path51.join(paths.cursorRoot, "package.json"));
76990
+ const mcp = objectOrNull(path51.join(home, ".cursor/mcp.json"));
76761
76991
  const args = mcp?.mcpServers?.workit?.args ?? [];
76762
76992
  const arg = args.find((value) => typeof value === "string" && value.startsWith("--package="));
76763
76993
  const selector = typeof arg === "string" ? arg.slice(10) : "local";
@@ -76768,7 +76998,7 @@ var codexRegistered = (configFile) => {
76768
76998
  });
76769
76999
  return;
76770
77000
  }
76771
- const settings = objectOrNull(path50.join(home, ".cursor/settings.json"));
77001
+ const settings = objectOrNull(path51.join(home, ".cursor/settings.json"));
76772
77002
  const dirs = Array.isArray(settings?.plugin_dirs) ? settings.plugin_dirs : [];
76773
77003
  const registered = mcp?.mcpServers?.workit !== undefined || dirs.some((dir) => String(dir).replaceAll("\\", "/").replace(/\/+$/, "").endsWith("local/workit"));
76774
77004
  if (registered)
@@ -76783,12 +77013,14 @@ var codexRegistered = (configFile) => {
76783
77013
  if (typeof source !== "string")
76784
77014
  continue;
76785
77015
  const npm = /^(?:npm:)?@brainervirus\/workit-pi(?:@[^/]+)?$/.test(source);
76786
- const local = path50.isAbsolute(source) && source.replaceAll("\\", "/").endsWith("/packages/workit-pi") && object2(path50.join(source, "package.json"))?.name === "@brainervirus/workit-pi";
77016
+ const local = path51.isAbsolute(source) && source.replaceAll("\\", "/").endsWith("/packages/workit-pi") && object2(path51.join(source, "package.json"))?.name === "@brainervirus/workit-pi";
76787
77017
  if (!npm && !local)
76788
77018
  continue;
76789
77019
  const found = classify("pi", source);
76790
77020
  if (found.kind === "floating") {
76791
77021
  const inventory = run("pi", ["list"]);
77022
+ if (inventory.timedOut)
77023
+ throw new Error(`could not check: ${inventory.stderr}`);
76792
77024
  if (inventory.status === 0)
76793
77025
  found.installedVersion = piInstalledVersion(inventory.stdout, source);
76794
77026
  }
@@ -76797,13 +77029,15 @@ var codexRegistered = (configFile) => {
76797
77029
  });
76798
77030
  guard("codex", () => {
76799
77031
  const listing = run("codex", ["plugin", "list", "--json"]);
77032
+ if (listing.timedOut)
77033
+ throw new Error(`could not check: ${listing.stderr}`);
76800
77034
  if (listing.status !== 0) {
76801
77035
  let available = false;
76802
77036
  try {
76803
77037
  hostCommand("codex", [], { home, env: paths.env });
76804
77038
  available = true;
76805
77039
  } catch {}
76806
- if (available || existsSync23(paths.codexConfig))
77040
+ if (available || existsSync24(paths.codexConfig))
76807
77041
  throw new Error("Codex plugin inventory failed; inspect the native host before upgrading");
76808
77042
  return;
76809
77043
  }
@@ -76842,24 +77076,22 @@ var codexRegistered = (configFile) => {
76842
77076
  });
76843
77077
  });
76844
77078
  return result;
76845
- }, opencodeProbe = (deps, args) => {
76846
- const scratch = mkdtempSync3(path50.join(os18.tmpdir(), "workit-upgrade-opencode-"));
77079
+ }, opencodeProbe = (deps, args, probes) => {
77080
+ const cached = probes?.get(probeKey("opencode", args));
77081
+ if (cached)
77082
+ return cached;
77083
+ const scratch = mkdtempSync4(path51.join(os19.tmpdir(), "workit-upgrade-opencode-"));
76847
77084
  try {
76848
- return runner({
76849
- ...deps,
76850
- env: {
76851
- ...deps.env,
76852
- XDG_DATA_HOME: path50.join(scratch, "data"),
76853
- XDG_STATE_HOME: path50.join(scratch, "state"),
76854
- XDG_CACHE_HOME: path50.join(scratch, "cache")
76855
- }
76856
- })("opencode", args);
77085
+ return runner({ ...deps, env: opencodeScratchEnv(deps, scratch) })("opencode", args);
76857
77086
  } finally {
76858
- rmSync8(scratch, { recursive: true, force: true });
77087
+ rmSync9(scratch, { recursive: true, force: true });
76859
77088
  }
77089
+ }, probedRunner = (deps, probes) => {
77090
+ const run = runner(deps);
77091
+ return probes ? (command, args) => probes.get(probeKey(command, args)) ?? run(command, args) : run;
76860
77092
  }, planCli = (plan, run) => {
76861
77093
  const root = run("npm", ["root", "--global"]);
76862
- if (root.status !== 0 || !path50.isAbsolute(root.stdout.trim())) {
77094
+ if (root.status !== 0 || !path51.isAbsolute(root.stdout.trim())) {
76863
77095
  plan.skipped.push({
76864
77096
  host: "cli",
76865
77097
  reason: "global npm location could not be verified",
@@ -76867,9 +77099,9 @@ var codexRegistered = (configFile) => {
76867
77099
  });
76868
77100
  return;
76869
77101
  }
76870
- const packageFile = path50.join(root.stdout.trim(), "@brainervirus/workit-cli/package.json");
77102
+ const packageFile = path51.join(root.stdout.trim(), "@brainervirus/workit-cli/package.json");
76871
77103
  const installed = objectOrNull(packageFile);
76872
- if (installed?.name !== "@brainervirus/workit-cli" || lstatSync8(path50.dirname(packageFile)).isSymbolicLink()) {
77104
+ if (installed?.name !== "@brainervirus/workit-cli" || lstatSync8(path51.dirname(packageFile)).isSymbolicLink()) {
76873
77105
  plan.skipped.push({
76874
77106
  host: "cli",
76875
77107
  reason: "no managed global CLI install (local links preserved); use npx @brainervirus/workit-cli@latest"
@@ -76898,6 +77130,8 @@ var codexRegistered = (configFile) => {
76898
77130
  });
76899
77131
  };
76900
77132
  var init_plan = __esm(() => {
77133
+ init_probes();
77134
+ init_opencode();
76901
77135
  init_registration();
76902
77136
  init_setup_state();
76903
77137
  init_host_install();
@@ -76907,11 +77141,17 @@ var init_plan = __esm(() => {
76907
77141
  });
76908
77142
 
76909
77143
  // packages/workit-cli/src/upgrade/check.ts
76910
- import path51 from "node:path";
76911
- function runUpdateCheck(json, deps) {
77144
+ import path52 from "node:path";
77145
+ async function runUpdateCheck(json, deps) {
76912
77146
  const out = deps.out ?? process.stdout;
76913
77147
  const paths = upgradePaths(deps);
76914
- const run = runner(deps);
77148
+ const progress = deps.progress ?? createProgress({ stream: process.stderr, json });
77149
+ const checking = HOSTS2.length + 1;
77150
+ const probes = await progress.run(`Checking ${checking} hosts`, () => runProbes(HOSTS2, true, deps, {
77151
+ check: true,
77152
+ registries: ["@brainervirus/workit-claude-code"]
77153
+ }));
77154
+ const run = probedRunner(deps, probes);
76915
77155
  const latest = (name) => registryVersion(run, name);
76916
77156
  const cliLatest = latest(CLI_PACKAGE2);
76917
77157
  if (cliLatest)
@@ -76952,14 +77192,27 @@ function runUpdateCheck(json, deps) {
76952
77192
  }
76953
77193
  if (!versionBy.has(host))
76954
77194
  continue;
76955
- const version = versionBy.get(host);
77195
+ const reading = host === "opencode" ? opencodeReading(probes) : undefined;
77196
+ if (reading === null) {
77197
+ components.push({
77198
+ component: host,
77199
+ package: name,
77200
+ installed: null,
77201
+ latest: null,
77202
+ status: "unreadable",
77203
+ reason: OPENCODE_NOT_READY
77204
+ });
77205
+ continue;
77206
+ }
77207
+ const version = versionBy.get(host) ?? reading?.version;
76956
77208
  const newest = latest(name);
77209
+ const status = statusOf(version, newest);
76957
77210
  components.push({
76958
77211
  component: host,
76959
77212
  package: name,
76960
77213
  installed: version ?? null,
76961
77214
  latest: newest ?? null,
76962
- status: statusOf(version, newest)
77215
+ status: reading?.outdated && status === "current" ? "update" : status
76963
77216
  });
76964
77217
  }
76965
77218
  const pending = components.some((entry) => entry.status === "update" || entry.status === "unknown");
@@ -77009,7 +77262,7 @@ function runSetUpdates(value, deps) {
77009
77262
  `);
77010
77263
  return 1;
77011
77264
  }
77012
- out.write(`updates: ${value} (saved in ${path51.join(configDir, "config.json")})
77265
+ out.write(`updates: ${value} (saved in ${path52.join(configDir, "config.json")})
77013
77266
  `);
77014
77267
  return 0;
77015
77268
  }
@@ -77019,7 +77272,10 @@ var init_check = __esm(() => {
77019
77272
  init_package();
77020
77273
  init_style();
77021
77274
  init_update_check();
77275
+ init_progress();
77276
+ init_opencode();
77022
77277
  init_plan();
77278
+ init_probes();
77023
77279
  init_shared();
77024
77280
  SET_USAGE = `Usage: workit upgrade --set-updates=${UPDATES_MODES.join("|")}
77025
77281
  `;
@@ -77106,7 +77362,24 @@ __export(exports_upgrade, {
77106
77362
  runUpgradeCommand: () => runUpgradeCommand
77107
77363
  });
77108
77364
  import { spawnSync as spawnSync18 } from "node:child_process";
77365
+ import { mkdtempSync as mkdtempSync5, readFileSync as readFileSync26, rmSync as rmSync10, writeFileSync as writeFileSync14 } from "node:fs";
77366
+ import os20 from "node:os";
77367
+ import path53 from "node:path";
77109
77368
  async function runUpgradeCommand(argv, deps = {}) {
77369
+ const { env } = upgradePaths(deps);
77370
+ const handBack = env[CONTINUE_ENV] !== undefined ? env[ROWS_ENV] : undefined;
77371
+ const handed = {};
77372
+ const code = await upgradeOnce(argv, deps, handed);
77373
+ if (!handBack)
77374
+ return code;
77375
+ try {
77376
+ writeFileSync14(handBack, JSON.stringify({ code, rows: handed.rows ?? [] }));
77377
+ return 0;
77378
+ } catch {
77379
+ return code;
77380
+ }
77381
+ }
77382
+ async function upgradeOnce(argv, deps, handed) {
77110
77383
  const out = deps.out ?? process.stdout;
77111
77384
  const setting = argv.find((arg) => arg.startsWith("--set-updates="));
77112
77385
  if (argv.includes("--check") || setting) {
@@ -77115,7 +77388,7 @@ async function runUpgradeCommand(argv, deps = {}) {
77115
77388
  out.write(USAGE3);
77116
77389
  return 2;
77117
77390
  }
77118
- return setting ? runSetUpdates(setting.slice("--set-updates=".length), deps) : runUpdateCheck(argv.includes("--json"), deps);
77391
+ return setting ? runSetUpdates(setting.slice("--set-updates=".length), deps) : await runUpdateCheck(argv.includes("--json"), deps);
77119
77392
  }
77120
77393
  const flags = new Set(argv);
77121
77394
  const unknown = argv.filter((arg) => !["--apply", "--confirm", "--json", "--cli", "--preview", "--yes"].includes(arg) && !arg.startsWith("--hosts="));
@@ -77132,16 +77405,19 @@ async function runUpgradeCommand(argv, deps = {}) {
77132
77405
  }
77133
77406
  const legacy = flags.has("--apply");
77134
77407
  const json = flags.has("--json") || legacy;
77135
- const run = runner(deps);
77408
+ const { home, env } = upgradePaths(deps);
77409
+ const continued = env[CONTINUE_ENV] !== undefined ? priorRows(env[CONTINUE_ENV]) : undefined;
77136
77410
  const progress = deps.progress ?? createProgress({ stream: process.stderr, json });
77137
- const plan = progress.runSync("Planning the upgrade", () => {
77138
- const planned = previewUpgrade(raw, deps);
77139
- if (hostFlag === undefined || flags.has("--cli"))
77140
- planCli(planned, run);
77411
+ const withCli = !continued && (hostFlag === undefined || flags.has("--cli"));
77412
+ const checking = raw.length + (withCli ? 1 : 0);
77413
+ const plan = await progress.run(`Checking ${checking} ${checking === 1 ? "host" : "hosts"}`, async () => {
77414
+ const probes = await runProbes(raw, withCli, deps);
77415
+ const planned = previewUpgrade(raw, deps, probes);
77416
+ if (withCli)
77417
+ planCli(planned, probedRunner(deps, probes));
77141
77418
  return planned;
77142
77419
  });
77143
77420
  plan.ok = plan.blocked.length === 0 && plan.failed.length === 0;
77144
- const { home, env } = upgradePaths(deps);
77145
77421
  const style = createStyle({
77146
77422
  stream: out === process.stdout ? process.stdout : out === process.stderr ? process.stderr : undefined,
77147
77423
  env,
@@ -77172,7 +77448,8 @@ async function runUpgradeCommand(argv, deps = {}) {
77172
77448
  return plan.blocked.length ? 1 : 0;
77173
77449
  }
77174
77450
  if (!json)
77175
- out.write(summary(plan, permissions.changes, style));
77451
+ out.write(continued ? `Continuing the upgrade with the new CLI (workit ${package_default.version}).
77452
+ ` : summary(plan, permissions.changes, style));
77176
77453
  if (flags.has("--preview")) {
77177
77454
  out.write(nothingChanged);
77178
77455
  return plan.blocked.length ? 1 : 0;
@@ -77195,7 +77472,44 @@ Nothing changed.
77195
77472
  for (const warning of plan.warnings ?? [])
77196
77473
  out.write(`warning: ${warning}
77197
77474
  `);
77198
- const result = await applyUpgrade(plan, { ...deps, progress });
77475
+ const reexec = deps.reexec ?? (deps.run && !deps.cliEntry ? undefined : spawnUpgrade({
77476
+ entry: deps.cliEntry ?? process.argv[1],
77477
+ out,
77478
+ toStderr: out === process.stderr,
77479
+ json
77480
+ }));
77481
+ const handoff = async (cli) => {
77482
+ if (!reexec || (deps.cliOnDisk ?? runningCliVersion)() !== plan.cli?.latest)
77483
+ return;
77484
+ const scratch = mkdtempSync5(path53.join(os20.tmpdir(), "workit-upgrade-"));
77485
+ const rowsFile = path53.join(scratch, "rows.json");
77486
+ try {
77487
+ const code = await reexec([
77488
+ ...legacy ? ["--apply", "--confirm"] : ["--yes"],
77489
+ ...flags.has("--json") ? ["--json"] : [],
77490
+ `--hosts=${raw.length ? raw.join(",") : "none"}`
77491
+ ], {
77492
+ [CONTINUE_ENV]: JSON.stringify([cli]),
77493
+ [ROWS_ENV]: rowsFile,
77494
+ WORKIT_UPDATE_CHECK: "0"
77495
+ });
77496
+ if (code === undefined)
77497
+ return;
77498
+ const back = handedBack(readText5(rowsFile));
77499
+ deps.onResult?.(back?.rows.length ? back.rows : [cli]);
77500
+ return back?.code ?? code;
77501
+ } finally {
77502
+ rmSync10(scratch, { recursive: true, force: true });
77503
+ }
77504
+ };
77505
+ const result = await applyUpgrade(plan, { ...deps, progress }, continued || !reexec ? {} : { handoff });
77506
+ if (result.handedOff !== undefined)
77507
+ return result.handedOff;
77508
+ if (continued?.length) {
77509
+ result.hosts.unshift(...continued);
77510
+ if (continued.some((row) => row.status === "failed"))
77511
+ result.ok = false;
77512
+ }
77199
77513
  let permissionsOk = true;
77200
77514
  let written;
77201
77515
  if (permissions.changes.length && !permissions.refused && !result.error?.startsWith("configuration changed")) {
@@ -77210,8 +77524,9 @@ Nothing changed.
77210
77524
  });
77211
77525
  }
77212
77526
  deps.onResult?.(result.hosts);
77527
+ handed.rows = result.hosts;
77213
77528
  const failed = !result.ok || !permissionsOk;
77214
- const cliVersion = result.hosts.some((h) => h.host === "cli" && h.status === "updated") ? plan.cli.latest : package_default.version;
77529
+ const cliVersion = plan.cli && result.hosts.some((h) => h.host === "cli" && h.status === "updated") ? plan.cli.latest : package_default.version;
77215
77530
  const report = progress.runSync("Checking the result with workit doctor", () => (deps.doctor ?? ((version) => runDoctor({ home, env, cliVersion: version, only: "upgrade" })))(cliVersion));
77216
77531
  const left = report.checks.filter((check) => check.status === "warn" || check.status === "fail");
77217
77532
  if (json) {
@@ -77234,7 +77549,7 @@ Nothing changed.
77234
77549
  if (result.backup)
77235
77550
  out.write(`Backup: ${style.path(result.backup)}
77236
77551
  `);
77237
- out.write(left.length === 0 ? `${style.ok("Verified:")} workit doctor is clean for versions, assets, agents and permissions.
77552
+ out.write(left.length === 0 ? `${style.ok("Verified:")} workit doctor is clean for versions, assets, agents, stale installs and permissions.
77238
77553
  ` : `${style.warn("Left after upgrade (workit doctor):")}
77239
77554
  ${left.map((check) => ` ${style.bold(check.id)}: ${check.detail}${check.fix ? `
77240
77555
  fix: ${style.command(check.fix)}` : ""}`).join(`
@@ -77295,7 +77610,68 @@ async function runLaunchCommand(argv, deps = {}) {
77295
77610
  var USAGE3 = `Usage: workit upgrade [--hosts=opencode,cursor,codex,pi,claude-code|none] [--cli] [--preview | --yes | --apply --confirm] [--json]
77296
77611
  workit upgrade --check [--json]
77297
77612
  workit upgrade --set-updates=prompt|auto|off
77298
- `;
77613
+ `, CONTINUE_ENV = "WORKIT_UPGRADE_CONTINUE", ROWS_ENV = "WORKIT_UPGRADE_ROWS", readText5 = (file) => {
77614
+ try {
77615
+ return readFileSync26(file, "utf8");
77616
+ } catch {
77617
+ return;
77618
+ }
77619
+ }, priorRows = (text) => {
77620
+ if (text === undefined)
77621
+ return;
77622
+ try {
77623
+ const rows = JSON.parse(text);
77624
+ return Array.isArray(rows) ? rows.filter((row) => typeof row?.host === "string" && typeof row?.status === "string" && typeof row?.reason === "string") : [];
77625
+ } catch {
77626
+ return [];
77627
+ }
77628
+ }, handedBack = (text) => {
77629
+ if (text === undefined)
77630
+ return;
77631
+ try {
77632
+ const value = JSON.parse(text);
77633
+ return {
77634
+ code: typeof value.code === "number" ? value.code : undefined,
77635
+ rows: priorRows(JSON.stringify(value.rows ?? [])) ?? []
77636
+ };
77637
+ } catch {
77638
+ return;
77639
+ }
77640
+ }, runningCliVersion = () => {
77641
+ const script = process.argv[1];
77642
+ if (!script)
77643
+ return;
77644
+ let dir = path53.dirname(script);
77645
+ for (let depth = 0;depth < 4; depth += 1, dir = path53.dirname(dir)) {
77646
+ const found = cliPackageVersion(readText5(path53.join(dir, "package.json")));
77647
+ if (found)
77648
+ return found;
77649
+ }
77650
+ return;
77651
+ }, cliPackageVersion = (text) => {
77652
+ if (text === undefined)
77653
+ return;
77654
+ try {
77655
+ const found = JSON.parse(text);
77656
+ return found.name === package_default.name && typeof found.version === "string" ? found.version : undefined;
77657
+ } catch {
77658
+ return;
77659
+ }
77660
+ }, spawnUpgrade = (options) => (argv, extra) => {
77661
+ if (!options.entry)
77662
+ return;
77663
+ const result = spawnSync18(process.execPath, [options.entry, "upgrade", ...argv], {
77664
+ stdio: ["inherit", options.json ? "pipe" : options.toStderr ? 2 : "inherit", "inherit"],
77665
+ encoding: "utf8",
77666
+ maxBuffer: 64 * 1024 * 1024,
77667
+ env: { ...process.env, ...extra }
77668
+ });
77669
+ if (result.error)
77670
+ return;
77671
+ if (options.json && result.stdout)
77672
+ options.out.write(result.stdout);
77673
+ return result.status ?? 1;
77674
+ };
77299
77675
  var init_upgrade = __esm(() => {
77300
77676
  init_package();
77301
77677
  init_host_install();
@@ -77306,6 +77682,7 @@ var init_upgrade = __esm(() => {
77306
77682
  init_apply();
77307
77683
  init_check();
77308
77684
  init_plan();
77685
+ init_probes();
77309
77686
  init_report();
77310
77687
  init_shared();
77311
77688
  init_apply();
@@ -77336,7 +77713,7 @@ var init_launch = __esm(() => {
77336
77713
  // packages/workit-core/src/knowledge.ts
77337
77714
  import { spawnSync as spawnSync19 } from "node:child_process";
77338
77715
  import fs20 from "node:fs";
77339
- import path52 from "node:path";
77716
+ import path54 from "node:path";
77340
77717
  function lintKnowledge(root) {
77341
77718
  const seen = new Set;
77342
77719
  const unreadable = [];
@@ -77440,7 +77817,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
77440
77817
  const end = lines.indexOf("---", 1);
77441
77818
  return end === -1 ? lines : [...lines.slice(0, end + 1).map(() => ""), ...lines.slice(end + 1)];
77442
77819
  }, read = (root, file) => {
77443
- const full = path52.join(root, file);
77820
+ const full = path54.join(root, file);
77444
77821
  try {
77445
77822
  fs20.lstatSync(full);
77446
77823
  } catch {
@@ -77481,7 +77858,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
77481
77858
  }
77482
77859
  }, brokenLinks = (root, doc, tracked) => {
77483
77860
  const findings = [];
77484
- const base = path52.dirname(path52.join(root, doc.file));
77861
+ const base = path54.dirname(path54.join(root, doc.file));
77485
77862
  const missing = (target, line, how) => findings.push({
77486
77863
  rule: "broken-link",
77487
77864
  file: doc.file,
@@ -77500,7 +77877,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
77500
77877
  const local = localTarget(target);
77501
77878
  if (!local)
77502
77879
  continue;
77503
- const resolved = local.startsWith("/") ? path52.join(root, local) : path52.resolve(base, local);
77880
+ const resolved = local.startsWith("/") ? path54.join(root, local) : path54.resolve(base, local);
77504
77881
  if (!exists2(resolved))
77505
77882
  missing(target, index + 1, "link");
77506
77883
  }
@@ -77510,9 +77887,9 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
77510
77887
  continue;
77511
77888
  const relative = /^\.\.?\//.test(candidate);
77512
77889
  const first = candidate.split("/")[0];
77513
- if (!relative && !(tracked ? tracked.has(first) : exists2(path52.join(root, first))))
77890
+ if (!relative && !(tracked ? tracked.has(first) : exists2(path54.join(root, first))))
77514
77891
  continue;
77515
- const resolved = relative ? path52.resolve(base, candidate) : path52.join(root, candidate);
77892
+ const resolved = relative ? path54.resolve(base, candidate) : path54.join(root, candidate);
77516
77893
  if (!exists2(resolved))
77517
77894
  missing(span, index + 1, "pointer");
77518
77895
  }
@@ -77881,8 +78258,8 @@ var init_redact = __esm(() => {
77881
78258
  import { spawn as spawn4, spawnSync as spawnSync20 } from "node:child_process";
77882
78259
  import { createHash as createHash17 } from "node:crypto";
77883
78260
  import fs21 from "node:fs";
77884
- import os19 from "node:os";
77885
- import path53 from "node:path";
78261
+ import os21 from "node:os";
78262
+ import path55 from "node:path";
77886
78263
  import { StringDecoder } from "node:string_decoder";
77887
78264
  function tailLines(text, lines = TAIL_LINES) {
77888
78265
  const all = text.replace(/\r\n?/gu, `
@@ -78002,7 +78379,7 @@ function planSpawn(argv, options) {
78002
78379
  return { file: argv[0], args: [], verbatim: false, shell: true };
78003
78380
  if (options.platform !== "win32")
78004
78381
  return { file: argv[0], args: argv.slice(1), verbatim: false, shell: false };
78005
- const win = path53.win32;
78382
+ const win = path55.win32;
78006
78383
  const isFile = options.isFile ?? ((file) => {
78007
78384
  try {
78008
78385
  return fs21.statSync(file).isFile();
@@ -78087,7 +78464,7 @@ function runCheckCommand(argv, options) {
78087
78464
  `);
78088
78465
  redactor.end();
78089
78466
  resolve({
78090
- exitCode: spawnError ? 127 : code !== null ? code : 128 + (signal ? os19.constants.signals[signal] ?? 1 : 1),
78467
+ exitCode: spawnError ? 127 : code !== null ? code : 128 + (signal ? os21.constants.signals[signal] ?? 1 : 1),
78091
78468
  signal: signal ?? null,
78092
78469
  timedOut,
78093
78470
  durationMs: Date.now() - started,
@@ -78164,10 +78541,10 @@ function runCheckCommand(argv, options) {
78164
78541
  function storeLog(storeRoot, log) {
78165
78542
  const digest = logDigest(log);
78166
78543
  const ref = `blobs/logs/${digest.slice("sha256:".length)}.log`;
78167
- const file = path53.join(storeRoot, ref);
78544
+ const file = path55.join(storeRoot, ref);
78168
78545
  try {
78169
78546
  if (!fs21.existsSync(file)) {
78170
- fs21.mkdirSync(path53.dirname(file), { recursive: true });
78547
+ fs21.mkdirSync(path55.dirname(file), { recursive: true });
78171
78548
  const temp = `${file}.${process.pid}.${Date.now()}.tmp`;
78172
78549
  fs21.writeFileSync(temp, log, { mode: 384 });
78173
78550
  fs21.renameSync(temp, file);
@@ -78180,7 +78557,7 @@ function storeLog(storeRoot, log) {
78180
78557
  function pruneCheckLogs(storeRoot, options = {}) {
78181
78558
  const limits = { ...LOG_RETENTION, ...options.retention };
78182
78559
  const now = options.now ?? Date.now();
78183
- const dir = path53.join(storeRoot, "blobs", "logs");
78560
+ const dir = path55.join(storeRoot, "blobs", "logs");
78184
78561
  const report = { removed: 0, removedBytes: 0, kept: 0 };
78185
78562
  let names;
78186
78563
  try {
@@ -78190,7 +78567,7 @@ function pruneCheckLogs(storeRoot, options = {}) {
78190
78567
  }
78191
78568
  const files = names.flatMap((name) => {
78192
78569
  try {
78193
- const stat = fs21.statSync(path53.join(dir, name));
78570
+ const stat = fs21.statSync(path55.join(dir, name));
78194
78571
  return stat.isFile() ? [{ name, size: stat.size, mtimeMs: stat.mtimeMs }] : [];
78195
78572
  } catch {
78196
78573
  return [];
@@ -78209,7 +78586,7 @@ function pruneCheckLogs(storeRoot, options = {}) {
78209
78586
  continue;
78210
78587
  if (!options.dryRun)
78211
78588
  try {
78212
- fs21.rmSync(path53.join(dir, file.name), { force: true });
78589
+ fs21.rmSync(path55.join(dir, file.name), { force: true });
78213
78590
  } catch {
78214
78591
  continue;
78215
78592
  }
@@ -78479,7 +78856,7 @@ __export(exports_workspace, {
78479
78856
  run: () => run11,
78480
78857
  runWorkspace: () => runWorkspace
78481
78858
  });
78482
- import { copyFileSync as copyFileSync7, existsSync as existsSync24 } from "node:fs";
78859
+ import { copyFileSync as copyFileSync7, existsSync as existsSync25 } from "node:fs";
78483
78860
  function list2(argv, io) {
78484
78861
  if (argv.length)
78485
78862
  return usage3(io, `unexpected argument ${argv[0]}`);
@@ -78788,7 +79165,7 @@ usage: ${USAGE5}`)), load = (io) => {
78788
79165
  return { ok: false, error: `${current.path} changed; retry` };
78789
79166
  let backup = null;
78790
79167
  try {
78791
- if (existsSync24(current.path)) {
79168
+ if (existsSync25(current.path)) {
78792
79169
  backup = `${current.path}.bak`;
78793
79170
  copyFileSync7(current.path, backup);
78794
79171
  }
@@ -78862,12 +79239,12 @@ var init_workspace = __esm(() => {
78862
79239
 
78863
79240
  // packages/workit-core/src/core/heavy-rules.ts
78864
79241
  import fs22 from "node:fs";
78865
- import path54 from "node:path";
79242
+ import path56 from "node:path";
78866
79243
  function gitTop(cwd) {
78867
- for (let dir = path54.resolve(cwd);; dir = path54.dirname(dir)) {
78868
- if (fs22.existsSync(path54.join(dir, ".git")))
79244
+ for (let dir = path56.resolve(cwd);; dir = path56.dirname(dir)) {
79245
+ if (fs22.existsSync(path56.join(dir, ".git")))
78869
79246
  return dir;
78870
- if (path54.dirname(dir) === dir)
79247
+ if (path56.dirname(dir) === dir)
78871
79248
  return null;
78872
79249
  }
78873
79250
  }
@@ -78908,19 +79285,19 @@ var init_heavy_rules = () => {};
78908
79285
 
78909
79286
  // packages/workit-core/src/core/heavy.ts
78910
79287
  import fs23 from "node:fs";
78911
- import os20 from "node:os";
78912
- import path55 from "node:path";
79288
+ import os22 from "node:os";
79289
+ import path57 from "node:path";
78913
79290
  function stateDir2(env, platform = process.platform) {
78914
79291
  if (env.WORKFLOW_TOOLKIT_STATE)
78915
79292
  return env.WORKFLOW_TOOLKIT_STATE;
78916
79293
  if (env.XDG_STATE_HOME)
78917
- return path55.join(env.XDG_STATE_HOME, "workit");
78918
- const home = env.HOME || os20.homedir();
79294
+ return path57.join(env.XDG_STATE_HOME, "workit");
79295
+ const home = env.HOME || os22.homedir();
78919
79296
  if (platform === "darwin")
78920
- return path55.join(home, "Library", "Application Support", "workit");
79297
+ return path57.join(home, "Library", "Application Support", "workit");
78921
79298
  if (platform === "win32")
78922
- return path55.join(env.LOCALAPPDATA ?? path55.join(home, "AppData", "Local"), "workit");
78923
- return path55.join(home, ".local", "state", "workit");
79299
+ return path57.join(env.LOCALAPPDATA ?? path57.join(home, "AppData", "Local"), "workit");
79300
+ return path57.join(home, ".local", "state", "workit");
78924
79301
  }
78925
79302
  function positional(words, from, values = PM_VALUES) {
78926
79303
  let index = from;
@@ -79060,7 +79437,7 @@ function machinePatterns(env) {
79060
79437
  return isRecord8(value) ? stringList2(value.patterns) : [];
79061
79438
  }
79062
79439
  function repoPatterns(cwd) {
79063
- return repoHeavyCommands(gitTop(cwd) ?? path55.resolve(cwd));
79440
+ return repoHeavyCommands(gitTop(cwd) ?? path57.resolve(cwd));
79064
79441
  }
79065
79442
  function heavyLines(lines, options) {
79066
79443
  const found = [];
@@ -79139,7 +79516,7 @@ function leaseRewrite(command) {
79139
79516
  return null;
79140
79517
  return `${prefix}workit check --heavy -- ${rest}`;
79141
79518
  }
79142
- var HEAVY_COMMANDS_FILE = "heavy-commands.json", heavyCommandsFile = (env) => path55.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) => {
79519
+ var HEAVY_COMMANDS_FILE = "heavy-commands.json", heavyCommandsFile = (env) => path57.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) => {
79143
79520
  try {
79144
79521
  return JSON.parse(fs23.readFileSync(file, "utf8"));
79145
79522
  } catch {
@@ -79285,8 +79662,8 @@ var init_heavy = __esm(() => {
79285
79662
  // packages/workit-core/src/core/resources.ts
79286
79663
  import { randomUUID as randomUUID5 } from "node:crypto";
79287
79664
  import fs24 from "node:fs";
79288
- import os21 from "node:os";
79289
- import path56 from "node:path";
79665
+ import os23 from "node:os";
79666
+ import path58 from "node:path";
79290
79667
  function memoryValue(value, host) {
79291
79668
  const text = typeof value === "number" ? String(value) : typeof value === "string" ? value : "";
79292
79669
  const percent = PERCENT.exec(text.trim());
@@ -79412,7 +79789,7 @@ function scopeBusy(unit) {
79412
79789
  return false;
79413
79790
  const uid = process.getuid?.() ?? 0;
79414
79791
  const manager = `/sys/fs/cgroup/user.slice/user-${uid}.slice/user@${uid}.service`;
79415
- return [`${manager}/app.slice/${unit}`, `${manager}/${unit}`].some((dir) => (readText5(`${dir}/cgroup.procs`) ?? "").trim() !== "");
79792
+ return [`${manager}/app.slice/${unit}`, `${manager}/${unit}`].some((dir) => (readText6(`${dir}/cgroup.procs`) ?? "").trim() !== "");
79416
79793
  }
79417
79794
  function isAncestor(pid) {
79418
79795
  if (process.platform !== "linux")
@@ -79469,7 +79846,7 @@ function reclaim(file, stale) {
79469
79846
  } catch {
79470
79847
  return true;
79471
79848
  }
79472
- if (!stale(parseLease(readText5(file)), ageMs))
79849
+ if (!stale(parseLease(readText6(file)), ageMs))
79473
79850
  return false;
79474
79851
  fs24.rmSync(file, { force: true });
79475
79852
  return true;
@@ -79482,7 +79859,7 @@ function tryOnce(options, record, reclaimed) {
79482
79859
  const text = `${JSON.stringify(record)}
79483
79860
  `;
79484
79861
  for (let slot = 0;slot < options.slots; slot += 1) {
79485
- const file = path56.join(options.dir, `slot-${slot}.json`);
79862
+ const file = path58.join(options.dir, `slot-${slot}.json`);
79486
79863
  for (let attempt = 0;attempt < 2; attempt += 1) {
79487
79864
  try {
79488
79865
  const fd = fs24.openSync(file, "wx", 384);
@@ -79496,7 +79873,7 @@ function tryOnce(options, record, reclaimed) {
79496
79873
  if (error.code !== "EEXIST")
79497
79874
  throw error;
79498
79875
  }
79499
- const lease = parseLease(readText5(file));
79876
+ const lease = parseLease(readText6(file));
79500
79877
  let reason = null;
79501
79878
  const removed = reclaim(file, (current, ageMs) => {
79502
79879
  reason = current ? staleReason(current, options.probe) : ageMs > UNREADABLE_TTL_MS ? "unreadable" : null;
@@ -79515,7 +79892,7 @@ function tryOnce(options, record, reclaimed) {
79515
79892
  return { holders };
79516
79893
  }
79517
79894
  function removeOwn(file, id) {
79518
- if (parseLease(readText5(file))?.id === id)
79895
+ if (parseLease(readText6(file))?.id === id)
79519
79896
  fs24.rmSync(file, { force: true });
79520
79897
  }
79521
79898
  function leaseQueue(dir, probe = {}) {
@@ -79527,8 +79904,8 @@ function leaseQueue(dir, probe = {}) {
79527
79904
  }
79528
79905
  const entries = [];
79529
79906
  for (const name of names.filter((item) => item.endsWith(".json")).toSorted()) {
79530
- const file = path56.join(queueDir(dir), name);
79531
- const record = parseLease(readText5(file));
79907
+ const file = path58.join(queueDir(dir), name);
79908
+ const record = parseLease(readText6(file));
79532
79909
  if (!record)
79533
79910
  continue;
79534
79911
  entries.push({
@@ -79543,9 +79920,9 @@ function leaseQueue(dir, probe = {}) {
79543
79920
  function waitersAhead(options, own) {
79544
79921
  let ahead = 0;
79545
79922
  for (const entry of leaseQueue(options.dir, options.probe)) {
79546
- if (path56.basename(entry.file) >= own)
79923
+ if (path58.basename(entry.file) >= own)
79547
79924
  break;
79548
- if (!TICKET.test(path56.basename(entry.file)))
79925
+ if (!TICKET.test(path58.basename(entry.file)))
79549
79926
  continue;
79550
79927
  if (entry.stale && reclaim(entry.file, (current) => !current || staleReason(current, options.probe) !== null))
79551
79928
  continue;
@@ -79557,7 +79934,7 @@ function liveHolders(options) {
79557
79934
  return leaseSlots(options.dir, options.slots, options.probe).filter((slot) => slot.holder && !slot.stale).map((slot) => slot.holder);
79558
79935
  }
79559
79936
  function writeTicket(file, record) {
79560
- fs24.mkdirSync(path56.dirname(file), { recursive: true, mode: 448 });
79937
+ fs24.mkdirSync(path58.dirname(file), { recursive: true, mode: 448 });
79561
79938
  fs24.writeFileSync(file, `${JSON.stringify(record)}
79562
79939
  `, { mode: 384 });
79563
79940
  }
@@ -79602,7 +79979,7 @@ async function acquireLease(options) {
79602
79979
  const reclaimed = [];
79603
79980
  let waitedOn = [];
79604
79981
  const name = ticketName(started, record.id);
79605
- const ticket = path56.join(queueDir(options.dir), name);
79982
+ const ticket = path58.join(queueDir(options.dir), name);
79606
79983
  const ticketRecord = {
79607
79984
  ...record,
79608
79985
  maxAgeMs: options.waitMs + 60000
@@ -79703,7 +80080,7 @@ async function acquireLease(options) {
79703
80080
  function updateLease(lease, patch) {
79704
80081
  Object.assign(lease.record, patch);
79705
80082
  try {
79706
- if (parseLease(readText5(lease.file))?.id !== lease.record.id)
80083
+ if (parseLease(readText6(lease.file))?.id !== lease.record.id)
79707
80084
  return;
79708
80085
  const temp = `${lease.file}.${process.pid}.tmp`;
79709
80086
  fs24.writeFileSync(temp, `${JSON.stringify(lease.record)}
@@ -79723,7 +80100,7 @@ function heldLease(dir, id, options = {}) {
79723
80100
  for (const name of names) {
79724
80101
  if (!/^slot-\d+\.json$/u.test(name))
79725
80102
  continue;
79726
- const lease = parseLease(readText5(path56.join(dir, name)));
80103
+ const lease = parseLease(readText6(path58.join(dir, name)));
79727
80104
  if (lease?.id === id && !staleReason(lease, options.probe) && (options.ancestor ?? isAncestor)(lease.pid))
79728
80105
  return lease;
79729
80106
  }
@@ -79778,10 +80155,10 @@ async function runScoped(run, wrapper, sinks) {
79778
80155
  }
79779
80156
  function firstNotice(env, session, key, now = Date.now()) {
79780
80157
  const id = (session ?? `ppid-${process.ppid}`).replace(/[^A-Za-z0-9_.-]/gu, "_").slice(0, 120);
79781
- const dir = path56.join(stateDir2(env), "notices");
80158
+ const dir = path58.join(stateDir2(env), "notices");
79782
80159
  try {
79783
80160
  fs24.mkdirSync(dir, { recursive: true, mode: 448 });
79784
- fs24.writeFileSync(path56.join(dir, `${key}-${id}`), `${new Date(now).toISOString()}
80161
+ fs24.writeFileSync(path58.join(dir, `${key}-${id}`), `${new Date(now).toISOString()}
79785
80162
  `, {
79786
80163
  flag: "wx",
79787
80164
  mode: 384
@@ -79791,7 +80168,7 @@ function firstNotice(env, session, key, now = Date.now()) {
79791
80168
  }
79792
80169
  try {
79793
80170
  for (const name of fs24.readdirSync(dir)) {
79794
- const file = path56.join(dir, name);
80171
+ const file = path58.join(dir, name);
79795
80172
  if (now - fs24.statSync(file).mtimeMs > NOTICE_TTL_MS)
79796
80173
  fs24.rmSync(file, { force: true });
79797
80174
  }
@@ -79801,7 +80178,7 @@ function firstNotice(env, session, key, now = Date.now()) {
79801
80178
  function leaseSlots(dir, slots, probe = {}) {
79802
80179
  const states = [];
79803
80180
  for (let slot = 0;slot < slots; slot += 1) {
79804
- const lease = parseLease(readText5(path56.join(dir, `slot-${slot}.json`)));
80181
+ const lease = parseLease(readText6(path58.join(dir, `slot-${slot}.json`)));
79805
80182
  states.push({
79806
80183
  slot,
79807
80184
  holder: lease ? holderOf(lease) : null,
@@ -79811,16 +80188,16 @@ function leaseSlots(dir, slots, probe = {}) {
79811
80188
  return states;
79812
80189
  }
79813
80190
  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 = () => ({
79814
- totalMemBytes: os21.totalmem(),
79815
- cpus: Math.max(1, os21.availableParallelism?.() ?? os21.cpus().length)
79816
- }), isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), SIZE, PERCENT, UNITS, leaseDir = (env) => path56.join(stateDir2(env), "leases"), readText5 = (file) => {
80191
+ totalMemBytes: os23.totalmem(),
80192
+ cpus: Math.max(1, os23.availableParallelism?.() ?? os23.cpus().length)
80193
+ }), isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), SIZE, PERCENT, UNITS, leaseDir = (env) => path58.join(stateDir2(env), "leases"), readText6 = (file) => {
79817
80194
  try {
79818
80195
  return fs24.readFileSync(file, "utf8");
79819
80196
  } catch {
79820
80197
  return null;
79821
80198
  }
79822
- }, bootId = () => readText5("/proc/sys/kernel/random/boot_id")?.trim() || null, bootTime = () => Math.round((Date.now() - os21.uptime() * 1000) / 1000) * 1000, BOOT_SLACK_MS = 120000, statFields = (pid) => {
79823
- const stat = readText5(`/proc/${pid}/stat`);
80199
+ }, bootId = () => readText6("/proc/sys/kernel/random/boot_id")?.trim() || null, bootTime = () => Math.round((Date.now() - os23.uptime() * 1000) / 1000) * 1000, BOOT_SLACK_MS = 120000, statFields = (pid) => {
80200
+ const stat = readText6(`/proc/${pid}/stat`);
79824
80201
  return stat ? stat.slice(stat.lastIndexOf(")") + 2).split(" ") : null;
79825
80202
  }, processStart = (pid) => statFields(pid)?.[19] ?? null, pidAlive2 = (pid) => {
79826
80203
  try {
@@ -79844,7 +80221,7 @@ var DEFAULT_HEAVY_CHECKS, DEFAULT_LIGHT_CHECKS, DEFAULT_SLOTS = 1, DEFAULT_WAIT_
79844
80221
  cwd: lease.cwd,
79845
80222
  session: lease.session,
79846
80223
  startedAt: lease.startedAt
79847
- }), realClock, queueDir = (dir) => path56.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;
80224
+ }), realClock, queueDir = (dir) => path58.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;
79848
80225
  var init_resources = __esm(() => {
79849
80226
  init_checks3();
79850
80227
  init_heavy();
@@ -79873,8 +80250,8 @@ __export(exports_check, {
79873
80250
  run: () => run12,
79874
80251
  workspaceResources: () => workspaceResources
79875
80252
  });
79876
- import os22 from "node:os";
79877
- import path57 from "node:path";
80253
+ import os24 from "node:os";
80254
+ import path59 from "node:path";
79878
80255
  function parse6(argv) {
79879
80256
  const split = argv.indexOf("--");
79880
80257
  const head = split >= 0 ? argv.slice(0, split) : [...argv];
@@ -80105,7 +80482,7 @@ ${footer}`;
80105
80482
  }
80106
80483
  async function workspaceResources(io) {
80107
80484
  const env = io.env;
80108
- const dir = env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path57.join(env.XDG_CONFIG_HOME || path57.join(env.HOME || os22.homedir(), ".config"), "workit");
80485
+ const dir = env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path59.join(env.XDG_CONFIG_HOME || path59.join(env.HOME || os24.homedir(), ".config"), "workit");
80109
80486
  try {
80110
80487
  await Promise.resolve().then(() => init_workspaces());
80111
80488
  const workspace = resolveWorkspaceFrom(io.cwd, dir, env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined);
@@ -80247,7 +80624,7 @@ async function run12(argv, io) {
80247
80624
  if (options.shell && command.length !== 1)
80248
80625
  return emit(io, fail2("invalid_input", '--shell takes the command as one string: workit check --shell -- "<cmd>"'));
80249
80626
  }
80250
- const relCwd = posix(path57.relative(top, runCwd));
80627
+ const relCwd = posix(path59.relative(top, runCwd));
80251
80628
  const configured = !options.shell && matchesNamedCheck(config, name, command, relCwd);
80252
80629
  const shadowed = !configured && name !== null ? config.checks.find((item) => item.name === name) : undefined;
80253
80630
  if (shadowed)
@@ -80312,7 +80689,7 @@ async function run12(argv, io) {
80312
80689
  const modifiedWorktree = key.tree !== null && treeAfter !== key.tree;
80313
80690
  const store = storeRoot(io.cwd);
80314
80691
  const blob = store.ok ? storeLog(store.value.root, result.log) : null;
80315
- const logPath = store.ok && blob ? path57.join(store.value.root, blob.ref) : null;
80692
+ const logPath = store.ok && blob ? path59.join(store.value.root, blob.ref) : null;
80316
80693
  const tail = tailLines(result.log, TAIL_LINES);
80317
80694
  const passed = result.exitCode === 0 && !result.timedOut;
80318
80695
  const bounded = boundedArgv(command);
@@ -80427,7 +80804,7 @@ async function run12(argv, io) {
80427
80804
  return recordError.code === "busy" ? 4 : recordError.code === "invalid_input" ? 2 : 5;
80428
80805
  return 0;
80429
80806
  }
80430
- 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(path57.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;
80807
+ 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(path59.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;
80431
80808
  var init_check2 = __esm(() => {
80432
80809
  init_check_config();
80433
80810
  init_checks3();
@@ -80458,7 +80835,7 @@ __export(exports_lock, {
80458
80835
  run: () => run13
80459
80836
  });
80460
80837
  import fs25 from "node:fs";
80461
- import path58 from "node:path";
80838
+ import path60 from "node:path";
80462
80839
  async function settingsFor(io) {
80463
80840
  const workspace = await workspaceResources(io);
80464
80841
  const config = loadCheckConfig(io.cwd);
@@ -80550,7 +80927,7 @@ function readPatterns(file) {
80550
80927
  return { patterns: [] };
80551
80928
  }
80552
80929
  function writePatterns(file, value) {
80553
- fs25.mkdirSync(path58.dirname(file), { recursive: true, mode: 448 });
80930
+ fs25.mkdirSync(path60.dirname(file), { recursive: true, mode: 448 });
80554
80931
  const temp = `${file}.${process.pid}.tmp`;
80555
80932
  fs25.writeFileSync(temp, `${JSON.stringify(value, null, 2)}
80556
80933
  `, { mode: 384 });
@@ -80636,9 +81013,9 @@ var exports_models = {};
80636
81013
  __export(exports_models, {
80637
81014
  run: () => run14
80638
81015
  });
80639
- import { existsSync as existsSync25, readdirSync as readdirSync13, readFileSync as readFileSync26, statSync as statSync9 } from "node:fs";
80640
- import os23 from "node:os";
80641
- import path59 from "node:path";
81016
+ import { existsSync as existsSync26, readdirSync as readdirSync13, readFileSync as readFileSync27, statSync as statSync9 } from "node:fs";
81017
+ import os25 from "node:os";
81018
+ import path61 from "node:path";
80642
81019
  async function run14(argv, io) {
80643
81020
  const [sub, ...args] = argv.filter((arg) => arg !== "--json");
80644
81021
  if (sub !== "show")
@@ -80699,7 +81076,7 @@ var USAGE8 = "workit models show [--role <role>] [--tier <tier>] [--host <host>]
80699
81076
  const found = new Set;
80700
81077
  let text = "";
80701
81078
  try {
80702
- text = readFileSync26(file, "utf8");
81079
+ text = readFileSync27(file, "utf8");
80703
81080
  } catch {
80704
81081
  return found;
80705
81082
  }
@@ -80713,26 +81090,26 @@ var USAGE8 = "workit models show [--role <role>] [--tier <tier>] [--host <host>]
80713
81090
  } catch {}
80714
81091
  return found;
80715
81092
  }, matches3 = (ran, configured) => ran.toLowerCase().includes(configured.toLowerCase()), usageReport = (cwd, env, days) => {
80716
- const projects = path59.join(env.CLAUDE_CONFIG_DIR || path59.join(env.HOME || os23.homedir(), ".claude"), "projects");
81093
+ const projects = path61.join(env.CLAUDE_CONFIG_DIR || path61.join(env.HOME || os25.homedir(), ".claude"), "projects");
80717
81094
  const since = Date.now() - days * 86400000;
80718
81095
  const types = {};
80719
81096
  let agents = 0;
80720
81097
  const dirs = (dir) => {
80721
81098
  try {
80722
- return readdirSync13(dir).map((name) => path59.join(dir, name));
81099
+ return readdirSync13(dir).map((name) => path61.join(dir, name));
80723
81100
  } catch {
80724
81101
  return [];
80725
81102
  }
80726
81103
  };
80727
81104
  for (const project of dirs(projects))
80728
81105
  for (const session of dirs(project))
80729
- for (const meta of dirs(path59.join(session, "subagents")).filter((f) => f.endsWith(".meta.json"))) {
81106
+ for (const meta of dirs(path61.join(session, "subagents")).filter((f) => f.endsWith(".meta.json"))) {
80730
81107
  try {
80731
81108
  if (statSync9(meta).mtimeMs < since)
80732
81109
  continue;
80733
- const agentType = JSON.parse(readFileSync26(meta, "utf8")).agentType;
81110
+ const agentType = JSON.parse(readFileSync27(meta, "utf8")).agentType;
80734
81111
  const transcript = meta.replace(/\.meta\.json$/, ".jsonl");
80735
- if (typeof agentType !== "string" || !existsSync25(transcript))
81112
+ if (typeof agentType !== "string" || !existsSync26(transcript))
80736
81113
  continue;
80737
81114
  const ran = modelsOf(transcript);
80738
81115
  if (!ran.size)
@@ -80871,8 +81248,8 @@ var success2 = (data) => ({ ok: true, data }), failure3 = (code, error, unblock)
80871
81248
 
80872
81249
  // packages/workit-core/src/git/ops.ts
80873
81250
  import { spawnSync as spawnSync21 } from "node:child_process";
80874
- import { existsSync as existsSync26, readFileSync as readFileSync27 } from "node:fs";
80875
- import path60 from "node:path";
81251
+ import { existsSync as existsSync27, readFileSync as readFileSync28 } from "node:fs";
81252
+ import path62 from "node:path";
80876
81253
  function operationInProgress(cwd) {
80877
81254
  const markers = [
80878
81255
  ["rebase-merge", "rebase"],
@@ -80885,18 +81262,18 @@ function operationInProgress(cwd) {
80885
81262
  if (!run.ok)
80886
81263
  return null;
80887
81264
  const found = run.stdout.split(`
80888
- `).map((line) => path60.resolve(cwd, line.trim()));
81265
+ `).map((line) => path62.resolve(cwd, line.trim()));
80889
81266
  const conflicted = () => git5(cwd, ["ls-files", "-u"]).stdout.trim() !== "";
80890
81267
  for (const [index, [, operation]] of markers.entries()) {
80891
81268
  const marker = found[index];
80892
- if (!marker || !existsSync26(marker))
81269
+ if (!marker || !existsSync27(marker))
80893
81270
  continue;
80894
- if (index === 1 && existsSync26(path60.join(marker, "applying")))
81271
+ if (index === 1 && existsSync27(path62.join(marker, "applying")))
80895
81272
  return { operation: "am", commitAllowed: false, branch: null };
80896
- if (index === 0 && existsSync26(path60.join(marker, "amend")) && !conflicted()) {
81273
+ if (index === 0 && existsSync27(path62.join(marker, "amend")) && !conflicted()) {
80897
81274
  let headName = "";
80898
81275
  try {
80899
- headName = readFileSync27(path60.join(marker, "head-name"), "utf8").trim();
81276
+ headName = readFileSync28(path62.join(marker, "head-name"), "utf8").trim();
80900
81277
  } catch {}
80901
81278
  const branch = headName.startsWith("refs/heads/") ? headName.slice("refs/heads/".length) : null;
80902
81279
  return { operation, commitAllowed: branch !== null, branch };
@@ -81231,7 +81608,7 @@ function gitCommit(cwd, input) {
81231
81608
  if (paths.some((value) => value.startsWith("-") || !value.trim()))
81232
81609
  return failure3("invalid_input", "paths must not be empty or start with -");
81233
81610
  const tracked = new Set(nulList(git5(cwd, ["ls-files", "-z", "--", ...paths]).stdout));
81234
- const addable = paths.filter((value) => existsSync26(path60.resolve(cwd, value)) || [...tracked].some((file) => file === value || file.startsWith(`${value}/`)));
81611
+ const addable = paths.filter((value) => existsSync27(path62.resolve(cwd, value)) || [...tracked].some((file) => file === value || file.startsWith(`${value}/`)));
81235
81612
  if (addable.length) {
81236
81613
  const added = git5(cwd, ["add", "-A", "--", ...addable]);
81237
81614
  if (!added.ok)
@@ -81772,12 +82149,12 @@ var init_ops = __esm(() => {
81772
82149
 
81773
82150
  // packages/workit-core/src/verdict-cover.ts
81774
82151
  import fs26 from "node:fs";
81775
- import path61 from "node:path";
82152
+ import path63 from "node:path";
81776
82153
  function chainsAbove(cwd, branch) {
81777
82154
  const root = storeRoot(cwd);
81778
82155
  if (!root.ok)
81779
82156
  return [];
81780
- const dir = path61.join(root.value.root, "stacks");
82157
+ const dir = path63.join(root.value.root, "stacks");
81781
82158
  let names = [];
81782
82159
  try {
81783
82160
  names = fs26.readdirSync(dir).filter((name) => name.endsWith(".json"));
@@ -81788,7 +82165,7 @@ function chainsAbove(cwd, branch) {
81788
82165
  for (const name of names.toSorted()) {
81789
82166
  let parsed;
81790
82167
  try {
81791
- parsed = JSON.parse(fs26.readFileSync(path61.join(dir, name), "utf8"));
82168
+ parsed = JSON.parse(fs26.readFileSync(path63.join(dir, name), "utf8"));
81792
82169
  } catch {
81793
82170
  continue;
81794
82171
  }
@@ -81944,10 +82321,10 @@ var init_check_evidence = __esm(() => {
81944
82321
 
81945
82322
  // packages/workit-core/src/forge/reruns.ts
81946
82323
  import fs27 from "node:fs";
81947
- import path62 from "node:path";
82324
+ import path64 from "node:path";
81948
82325
  function rerunLogPath(cwd) {
81949
82326
  const common = gitCommonDir(cwd);
81950
- return common ? path62.join(common, "workit", "ci-reruns.jsonl") : null;
82327
+ return common ? path64.join(common, "workit", "ci-reruns.jsonl") : null;
81951
82328
  }
81952
82329
  function rerunCounts(cwd, key) {
81953
82330
  const counts = new Map;
@@ -81982,7 +82359,7 @@ function recordReruns(cwd, rows) {
81982
82359
  if (!file)
81983
82360
  return false;
81984
82361
  try {
81985
- fs27.mkdirSync(path62.dirname(file), { recursive: true });
82362
+ fs27.mkdirSync(path64.dirname(file), { recursive: true });
81986
82363
  fs27.appendFileSync(file, rows.map((row) => `${JSON.stringify(row)}
81987
82364
  `).join(""));
81988
82365
  return true;
@@ -81995,7 +82372,7 @@ function withRerunLock(cwd, fn) {
81995
82372
  if (!file)
81996
82373
  return fn();
81997
82374
  const lock = `${file.slice(0, -".jsonl".length)}.lock`;
81998
- fs27.mkdirSync(path62.dirname(lock), { recursive: true });
82375
+ fs27.mkdirSync(path64.dirname(lock), { recursive: true });
81999
82376
  const until = Date.now() + LOCK_WAIT_MS2;
82000
82377
  for (;; ) {
82001
82378
  try {
@@ -82991,7 +83368,7 @@ var init_pr_ops = __esm(() => {
82991
83368
  import { spawnSync as spawnSync23 } from "node:child_process";
82992
83369
  import { createHash as createHash18, randomBytes as randomBytes4 } from "node:crypto";
82993
83370
  import fs28 from "node:fs";
82994
- import path63 from "node:path";
83371
+ import path65 from "node:path";
82995
83372
  function worktreeOf(cwd, branch) {
82996
83373
  const list = gitRun3(cwd, ["worktree", "list", "--porcelain"]);
82997
83374
  if (!list.ok)
@@ -83040,7 +83417,7 @@ function gitRestack(cwd, input) {
83040
83417
  error: "no store root"
83041
83418
  };
83042
83419
  fs28.mkdirSync(scratch, { recursive: true });
83043
- dir = path63.join(scratch, `${input.branch.replace(/[^A-Za-z0-9._-]+/gu, "_").slice(0, 40)}-${randomBytes4(4).toString("hex")}`);
83420
+ dir = path65.join(scratch, `${input.branch.replace(/[^A-Za-z0-9._-]+/gu, "_").slice(0, 40)}-${randomBytes4(4).toString("hex")}`);
83044
83421
  const added = gitRun3(cwd, ["worktree", "add", "-q", dir, input.branch], GIT_TIMEOUTS.worktree);
83045
83422
  if (!added.ok)
83046
83423
  return {
@@ -83096,7 +83473,7 @@ function pruneScratch(cwd) {
83096
83473
  if (!scratch || !fs28.existsSync(scratch))
83097
83474
  return;
83098
83475
  for (const name of fs28.readdirSync(scratch)) {
83099
- const dir = path63.join(scratch, name);
83476
+ const dir = path65.join(scratch, name);
83100
83477
  if (!rebaseInProgress(dir) && !trackedDirt(dir))
83101
83478
  gitRun3(cwd, ["worktree", "remove", "--force", dir]);
83102
83479
  }
@@ -83106,7 +83483,7 @@ function stacksDir(cwd) {
83106
83483
  const root = storeRoot(cwd);
83107
83484
  if (!root.ok)
83108
83485
  return stackFail(root.code, root.error, root.unblock);
83109
- return { ok: true, data: path63.join(root.value.root, "stacks") };
83486
+ return { ok: true, data: path65.join(root.value.root, "stacks") };
83110
83487
  }
83111
83488
  function parseStack(raw) {
83112
83489
  if (!isRecord12(raw) || !Array.isArray(raw.branches))
@@ -83158,7 +83535,7 @@ function readStack(cwd, name) {
83158
83535
  const dir = stacksDir(cwd);
83159
83536
  if (!dir.ok)
83160
83537
  return dir;
83161
- const file = path63.join(dir.data, fileFor(name));
83538
+ const file = path65.join(dir.data, fileFor(name));
83162
83539
  let text;
83163
83540
  try {
83164
83541
  text = fs28.readFileSync(file, "utf8");
@@ -83179,7 +83556,7 @@ function writeStack(cwd, stack, now = new Date) {
83179
83556
  const dir = stacksDir(cwd);
83180
83557
  if (!dir.ok)
83181
83558
  return dir;
83182
- const file = path63.join(dir.data, fileFor(stack.name));
83559
+ const file = path65.join(dir.data, fileFor(stack.name));
83183
83560
  const temp = `${file}.${process.pid}.tmp`;
83184
83561
  try {
83185
83562
  fs28.mkdirSync(dir.data, { recursive: true });
@@ -83207,7 +83584,7 @@ function listStacks(cwd) {
83207
83584
  for (const name of names) {
83208
83585
  let parsed = null;
83209
83586
  try {
83210
- parsed = parseStack(JSON.parse(fs28.readFileSync(path63.join(dir.data, name), "utf8")));
83587
+ parsed = parseStack(JSON.parse(fs28.readFileSync(path65.join(dir.data, name), "utf8")));
83211
83588
  } catch {
83212
83589
  parsed = null;
83213
83590
  }
@@ -83269,7 +83646,7 @@ function takeLock(lock) {
83269
83646
  host: localLockHost(),
83270
83647
  nonce: randomBytes4(8).toString("hex")
83271
83648
  };
83272
- fs28.writeFileSync(path63.join(lock, OWNER), JSON.stringify(owner));
83649
+ fs28.writeFileSync(path65.join(lock, OWNER), JSON.stringify(owner));
83273
83650
  return owner;
83274
83651
  }
83275
83652
  function reapLock(lock, observed) {
@@ -83306,7 +83683,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
83306
83683
  return dir;
83307
83684
  if (!validName(name))
83308
83685
  return stackFail("invalid_input", "a stack name must be 1-200 printable characters");
83309
- const lock = path63.join(dir.data, `${fileFor(name)}.lock`);
83686
+ const lock = path65.join(dir.data, `${fileFor(name)}.lock`);
83310
83687
  try {
83311
83688
  fs28.mkdirSync(dir.data, { recursive: true });
83312
83689
  } catch (error) {
@@ -83336,7 +83713,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
83336
83713
  const touch = () => {
83337
83714
  try {
83338
83715
  const now = new Date;
83339
- fs28.utimesSync(path63.join(lock, OWNER), now, now);
83716
+ fs28.utimesSync(path65.join(lock, OWNER), now, now);
83340
83717
  } catch {}
83341
83718
  };
83342
83719
  const beat = setInterval(touch, HEARTBEAT_MS);
@@ -84305,7 +84682,7 @@ var STACK_VERSION = 1, stackFail = (code, error, unblock, data) => ({
84305
84682
  return !status.ok || status.stdout.trim() !== "";
84306
84683
  }, scratchDir = (cwd) => {
84307
84684
  const dir = stacksDir(cwd);
84308
- return dir.ok ? path63.join(dir.data, "worktrees") : null;
84685
+ return dir.ok ? path65.join(dir.data, "worktrees") : null;
84309
84686
  }, firstLine = (run) => (`${run.stderr}
84310
84687
  ${run.stdout}`.split(`
84311
84688
  `).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) => {
@@ -84320,12 +84697,12 @@ ${run.stdout}`.split(`
84320
84697
  }, 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) => {
84321
84698
  let raw = null;
84322
84699
  try {
84323
- raw = fs28.readFileSync(path63.join(lock, OWNER), "utf8");
84700
+ raw = fs28.readFileSync(path65.join(lock, OWNER), "utf8");
84324
84701
  } catch {
84325
84702
  raw = null;
84326
84703
  }
84327
84704
  let age = null;
84328
- for (const target of [path63.join(lock, OWNER), lock])
84705
+ for (const target of [path65.join(lock, OWNER), lock])
84329
84706
  try {
84330
84707
  age = Date.now() - fs28.statSync(target).mtimeMs;
84331
84708
  break;
@@ -84369,7 +84746,7 @@ var init_stack = __esm(() => {
84369
84746
  import { spawnSync as spawnSync24 } from "node:child_process";
84370
84747
  import { createHash as createHash19 } from "node:crypto";
84371
84748
  import fs29 from "node:fs";
84372
- import path64 from "node:path";
84749
+ import path66 from "node:path";
84373
84750
  function expandBraces2(pattern, limit = 64) {
84374
84751
  for (let index = 0;index < pattern.length; index += 1) {
84375
84752
  if (pattern[index] === "\\") {
@@ -84615,7 +84992,7 @@ function parsePlan(raw, defaults, name) {
84615
84992
  id,
84616
84993
  branch,
84617
84994
  base: optional("base") ?? "",
84618
- worktree: path64.resolve(defaults.root, optional("worktree") ?? path64.join(defaults.worktreeRoot, id)),
84995
+ worktree: path66.resolve(defaults.root, optional("worktree") ?? path66.join(defaults.worktreeRoot, id)),
84619
84996
  tier,
84620
84997
  reason,
84621
84998
  dependsOn: [...new Set(dependsOn ?? [])],
@@ -84744,12 +85121,12 @@ function regeneratedFiles(root, tracked) {
84744
85121
  const found = new Map;
84745
85122
  let scripts;
84746
85123
  try {
84747
- const manifest = JSON.parse(fs29.readFileSync(path64.join(root, "package.json"), "utf8"));
85124
+ const manifest = JSON.parse(fs29.readFileSync(path66.join(root, "package.json"), "utf8"));
84748
85125
  scripts = manifest.scripts ?? {};
84749
85126
  } catch {
84750
85127
  return found;
84751
85128
  }
84752
- const runner = fs29.existsSync(path64.join(root, "bun.lock")) ? "bun run" : fs29.existsSync(path64.join(root, "pnpm-lock.yaml")) ? "pnpm run" : fs29.existsSync(path64.join(root, "yarn.lock")) ? "yarn run" : "npm run";
85129
+ const runner = fs29.existsSync(path66.join(root, "bun.lock")) ? "bun run" : fs29.existsSync(path66.join(root, "pnpm-lock.yaml")) ? "pnpm run" : fs29.existsSync(path66.join(root, "yarn.lock")) ? "yarn run" : "npm run";
84753
85130
  const outputs = tracked.filter((file) => !CODE.test(file));
84754
85131
  for (const [name, command] of Object.entries(scripts)) {
84755
85132
  if (!name.startsWith("write:") || typeof command !== "string")
@@ -84757,7 +85134,7 @@ function regeneratedFiles(root, tracked) {
84757
85134
  for (const file of command.match(/[\w./-]+\.[cm]?[jt]s\b/gu) ?? []) {
84758
85135
  let source;
84759
85136
  try {
84760
- source = fs29.readFileSync(path64.join(root, file), "utf8");
85137
+ source = fs29.readFileSync(path66.join(root, file), "utf8");
84761
85138
  } catch {
84762
85139
  continue;
84763
85140
  }
@@ -84879,11 +85256,11 @@ function defaultTrunk(cwd) {
84879
85256
  }
84880
85257
  function mainCheckout(cwd) {
84881
85258
  const common = gitCommonDir(cwd);
84882
- return common && path64.basename(common) === ".git" ? path64.dirname(common) : path64.resolve(cwd);
85259
+ return common && path66.basename(common) === ".git" ? path66.dirname(common) : path66.resolve(cwd);
84883
85260
  }
84884
85261
  function worktreeRoot(cwd) {
84885
85262
  const main = mainCheckout(cwd);
84886
- return path64.join(path64.dirname(main), `${path64.basename(main)}-wt`);
85263
+ return path66.join(path66.dirname(main), `${path66.basename(main)}-wt`);
84887
85264
  }
84888
85265
  function sliceHash(slice) {
84889
85266
  const {
@@ -84903,7 +85280,7 @@ function fanoutsDir(cwd) {
84903
85280
  const root = storeRoot(cwd);
84904
85281
  if (!root.ok)
84905
85282
  return fanoutFail(root.code, root.error, root.unblock);
84906
- return { ok: true, data: path64.join(root.value.root, "fanouts") };
85283
+ return { ok: true, data: path66.join(root.value.root, "fanouts") };
84907
85284
  }
84908
85285
  function parseStored(raw) {
84909
85286
  if (!isRecord13(raw) || typeof raw.name !== "string" || typeof raw.trunk !== "string")
@@ -84971,7 +85348,7 @@ function readFanout(cwd, name) {
84971
85348
  const dir = fanoutsDir(cwd);
84972
85349
  if (!dir.ok)
84973
85350
  return dir;
84974
- const file = path64.join(dir.data, stackFileName(name));
85351
+ const file = path66.join(dir.data, stackFileName(name));
84975
85352
  let parsed = null;
84976
85353
  try {
84977
85354
  parsed = parseStored(JSON.parse(fs29.readFileSync(file, "utf8")));
@@ -84996,7 +85373,7 @@ function listFanouts(cwd) {
84996
85373
  for (const entry of names) {
84997
85374
  let parsed = null;
84998
85375
  try {
84999
- parsed = parseStored(JSON.parse(fs29.readFileSync(path64.join(dir.data, entry), "utf8")));
85376
+ parsed = parseStored(JSON.parse(fs29.readFileSync(path66.join(dir.data, entry), "utf8")));
85000
85377
  } catch {
85001
85378
  parsed = null;
85002
85379
  }
@@ -85035,7 +85412,7 @@ function writeFanout(cwd, plan) {
85035
85412
  const dir = fanoutsDir(cwd);
85036
85413
  if (!dir.ok)
85037
85414
  return dir;
85038
- const file = path64.join(dir.data, stackFileName(plan.name));
85415
+ const file = path66.join(dir.data, stackFileName(plan.name));
85039
85416
  const temp = `${file}.${process.pid}.tmp`;
85040
85417
  try {
85041
85418
  fs29.mkdirSync(dir.data, { recursive: true });
@@ -85246,13 +85623,13 @@ var init_fanout = __esm(() => {
85246
85623
  // packages/workit-core/src/forge/exec.ts
85247
85624
  import { spawnSync as spawnSync25 } from "node:child_process";
85248
85625
  import fs30 from "node:fs";
85249
- import path65 from "node:path";
85626
+ import path67 from "node:path";
85250
85627
  function findExecutable(bin, env) {
85251
- const dirs = (env.PATH ?? env.Path ?? "").split(path65.delimiter).filter(Boolean);
85628
+ const dirs = (env.PATH ?? env.Path ?? "").split(path67.delimiter).filter(Boolean);
85252
85629
  const exts = process.platform === "win32" ? [".exe"] : [""];
85253
85630
  for (const dir of dirs)
85254
85631
  for (const ext of exts) {
85255
- const candidate = path65.join(dir, `${bin}${ext}`);
85632
+ const candidate = path67.join(dir, `${bin}${ext}`);
85256
85633
  try {
85257
85634
  const stat = fs30.statSync(candidate);
85258
85635
  if (stat.isFile())
@@ -87042,7 +87419,7 @@ var init_live_session = __esm(() => {
87042
87419
  });
87043
87420
 
87044
87421
  // packages/workit-core/src/hooks/write-gate.ts
87045
- import path66 from "node:path";
87422
+ import path68 from "node:path";
87046
87423
  var CASE_INSENSITIVE, PREFIXES2, SCRIPT_SHELLS, cache3, MUTATING_GIT, DRY_N, MUTATING_WORKIT_GIT, CD2, PUSHD2, POPD2, UNKNOWN_DIR;
87047
87424
  var init_write_gate = __esm(() => {
87048
87425
  init_task_store();
@@ -87082,7 +87459,7 @@ var init_write_gate = __esm(() => {
87082
87459
  CD2 = new Set(["cd", "chdir", "set-location", "sl"]);
87083
87460
  PUSHD2 = new Set(["pushd", "push-location"]);
87084
87461
  POPD2 = new Set(["popd", "pop-location"]);
87085
- UNKNOWN_DIR = path66.resolve(path66.parse(process.cwd()).root, ".workit-unknown-dir");
87462
+ UNKNOWN_DIR = path68.resolve(path68.parse(process.cwd()).root, ".workit-unknown-dir");
87086
87463
  });
87087
87464
 
87088
87465
  // packages/workit-core/src/hooks/worktree-confine.ts
@@ -87107,20 +87484,20 @@ var init_worktree_confine = __esm(() => {
87107
87484
 
87108
87485
  // packages/workit-core/src/worktree-deps.ts
87109
87486
  import fs31 from "node:fs";
87110
- import path67 from "node:path";
87487
+ import path69 from "node:path";
87111
87488
  function moduleDirs(main) {
87112
87489
  const out = [];
87113
87490
  const walk = (relative, depth) => {
87114
87491
  let entries;
87115
87492
  try {
87116
- entries = fs31.readdirSync(path67.join(main, relative), { withFileTypes: true });
87493
+ entries = fs31.readdirSync(path69.join(main, relative), { withFileTypes: true });
87117
87494
  } catch {
87118
87495
  return;
87119
87496
  }
87120
87497
  for (const entry of entries) {
87121
87498
  if (!entry.isDirectory())
87122
87499
  continue;
87123
- const child = path67.join(relative, entry.name);
87500
+ const child = path69.join(relative, entry.name);
87124
87501
  if (entry.name === MODULES)
87125
87502
  out.push(child);
87126
87503
  else if (depth < MAX_DEPTH2 && !entry.name.startsWith("."))
@@ -87134,8 +87511,8 @@ function linkEntry(main, worktree, source, target) {
87134
87511
  const stat = fs31.lstatSync(source);
87135
87512
  if (stat.isSymbolicLink()) {
87136
87513
  const link = fs31.readlinkSync(source);
87137
- const outside = path67.isAbsolute(link) && within(link, main) && !path67.relative(main, link).split(path67.sep).includes(MODULES);
87138
- const to = outside ? path67.join(worktree, path67.relative(main, link)) : link;
87514
+ const outside = path69.isAbsolute(link) && within(link, main) && !path69.relative(main, link).split(path69.sep).includes(MODULES);
87515
+ const to = outside ? path69.join(worktree, path69.relative(main, link)) : link;
87139
87516
  fs31.symlinkSync(to, target, process.platform === "win32" ? "junction" : undefined);
87140
87517
  return;
87141
87518
  }
@@ -87145,8 +87522,8 @@ function mirror(main, worktree, source, target, top) {
87145
87522
  fs31.mkdirSync(target);
87146
87523
  let count = 0;
87147
87524
  for (const entry of fs31.readdirSync(source, { withFileTypes: true })) {
87148
- const from = path67.join(source, entry.name);
87149
- const to = path67.join(target, entry.name);
87525
+ const from = path69.join(source, entry.name);
87526
+ const to = path69.join(target, entry.name);
87150
87527
  if (top && entry.isDirectory() && (entry.name.startsWith("@") || entry.name === ".bin"))
87151
87528
  count += mirror(main, worktree, from, to, false);
87152
87529
  else {
@@ -87162,16 +87539,16 @@ function linkWorktreeDependencies(main, worktree) {
87162
87539
  const dirs = [];
87163
87540
  let entries = 0;
87164
87541
  for (const relative of moduleDirs(main)) {
87165
- const target = path67.join(worktree, relative);
87166
- if (!fs31.existsSync(path67.dirname(target)) || fs31.existsSync(target))
87542
+ const target = path69.join(worktree, relative);
87543
+ if (!fs31.existsSync(path69.dirname(target)) || fs31.existsSync(target))
87167
87544
  continue;
87168
- if (!gitRun4(worktree, ["check-ignore", "-q", `${relative.split(path67.sep).join("/")}/`]).ok) {
87169
- notes.push(`${relative.split(path67.sep).join("/")} is not ignored by git, so it was not linked from ${main}; install dependencies in the worktree yourself`);
87545
+ if (!gitRun4(worktree, ["check-ignore", "-q", `${relative.split(path69.sep).join("/")}/`]).ok) {
87546
+ notes.push(`${relative.split(path69.sep).join("/")} is not ignored by git, so it was not linked from ${main}; install dependencies in the worktree yourself`);
87170
87547
  continue;
87171
87548
  }
87172
87549
  try {
87173
- entries += mirror(main, worktree, path67.join(main, relative), target, true);
87174
- dirs.push(relative.split(path67.sep).join("/"));
87550
+ entries += mirror(main, worktree, path69.join(main, relative), target, true);
87551
+ dirs.push(relative.split(path69.sep).join("/"));
87175
87552
  } catch (error) {
87176
87553
  fs31.rmSync(target, { recursive: true, force: true });
87177
87554
  notes.push(`could not link ${relative} from ${main} (${error.message}); install dependencies in the worktree yourself`);
@@ -87184,8 +87561,8 @@ function linkWorktreeDependencies(main, worktree) {
87184
87561
  return { linked: { from: main, dirs, entries, ms }, notes };
87185
87562
  }
87186
87563
  var MODULES = "node_modules", MAX_DEPTH2 = 2, within = (child, parent) => {
87187
- const relative = path67.relative(parent, child);
87188
- return relative === "" || !relative.startsWith("..") && !path67.isAbsolute(relative);
87564
+ const relative = path69.relative(parent, child);
87565
+ return relative === "" || !relative.startsWith("..") && !path69.isAbsolute(relative);
87189
87566
  };
87190
87567
  var init_worktree_deps = __esm(() => {
87191
87568
  init_fanout();
@@ -87194,7 +87571,7 @@ var init_worktree_deps = __esm(() => {
87194
87571
  // packages/workit-core/src/fanout-worktree.ts
87195
87572
  import { randomBytes as randomBytes5 } from "node:crypto";
87196
87573
  import fs32 from "node:fs";
87197
- import path68 from "node:path";
87574
+ import path70 from "node:path";
87198
87575
  function rowSample(lines) {
87199
87576
  const out = [];
87200
87577
  let bytes = 0;
@@ -87254,7 +87631,7 @@ function adminDir(worktree) {
87254
87631
  const file = dir.stdout.trim();
87255
87632
  let token = null;
87256
87633
  try {
87257
- token = fs32.readFileSync(path68.join(file, FANOUT_TOKEN_FILE), "utf8").trim() || null;
87634
+ token = fs32.readFileSync(path70.join(file, FANOUT_TOKEN_FILE), "utf8").trim() || null;
87258
87635
  } catch {
87259
87636
  token = null;
87260
87637
  }
@@ -87262,7 +87639,7 @@ function adminDir(worktree) {
87262
87639
  const stat = worktreeDeps.stat(file);
87263
87640
  return {
87264
87641
  path: file,
87265
- id: path68.basename(file),
87642
+ id: path70.basename(file),
87266
87643
  ino: stat.ino.toString(),
87267
87644
  token,
87268
87645
  birthMs: stat.birthtimeNs > 0n ? Number(stat.birthtimeMs) : null,
@@ -87278,7 +87655,7 @@ function markAdminDir(worktree) {
87278
87655
  return null;
87279
87656
  const token = randomBytes5(16).toString("hex");
87280
87657
  try {
87281
- fs32.writeFileSync(path68.join(admin.path, FANOUT_TOKEN_FILE), `${token}
87658
+ fs32.writeFileSync(path70.join(admin.path, FANOUT_TOKEN_FILE), `${token}
87282
87659
  `);
87283
87660
  } catch {
87284
87661
  return null;
@@ -87293,7 +87670,7 @@ function excludeScratch(cwd) {
87293
87670
  const common = gitCommonDir(cwd);
87294
87671
  if (!common)
87295
87672
  return;
87296
- const file = path68.join(common, "info", "exclude");
87673
+ const file = path70.join(common, "info", "exclude");
87297
87674
  let text = "";
87298
87675
  try {
87299
87676
  text = fs32.readFileSync(file, "utf8");
@@ -87302,7 +87679,7 @@ function excludeScratch(cwd) {
87302
87679
  }
87303
87680
  if (text.split(/\r?\n/u).includes(EXCLUDE_LINE))
87304
87681
  return;
87305
- fs32.mkdirSync(path68.dirname(file), { recursive: true });
87682
+ fs32.mkdirSync(path70.dirname(file), { recursive: true });
87306
87683
  fs32.appendFileSync(file, `${text && !text.endsWith(`
87307
87684
  `) ? `
87308
87685
  ` : ""}# workit fanout: per-worker scratch dirs
@@ -87311,13 +87688,13 @@ ${EXCLUDE_LINE}
87311
87688
  }
87312
87689
  function worktreeDependencies(main, worktree) {
87313
87690
  for (const [name, install] of LOCKFILES2) {
87314
- const ours = readBytes(path68.join(main, name));
87315
- const theirs = readBytes(path68.join(worktree, name));
87691
+ const ours = readBytes(path70.join(main, name));
87692
+ const theirs = readBytes(path70.join(worktree, name));
87316
87693
  if (ours === null && theirs === null)
87317
87694
  continue;
87318
87695
  if (ours !== null && theirs !== null && ours.equals(theirs))
87319
87696
  continue;
87320
- if (fs32.existsSync(path68.join(worktree, "node_modules")))
87697
+ if (fs32.existsSync(path70.join(worktree, "node_modules")))
87321
87698
  break;
87322
87699
  const command = install(worktree);
87323
87700
  return {
@@ -87329,7 +87706,7 @@ function worktreeDependencies(main, worktree) {
87329
87706
  };
87330
87707
  }
87331
87708
  const stale = staleBunInstall(main);
87332
- if (stale && !fs32.existsSync(path68.join(worktree, "node_modules"))) {
87709
+ if (stale && !fs32.existsSync(path70.join(worktree, "node_modules"))) {
87333
87710
  const command = `bun install --frozen-lockfile --cwd ${worktree}`;
87334
87711
  return {
87335
87712
  linked: null,
@@ -87342,9 +87719,9 @@ function worktreeDependencies(main, worktree) {
87342
87719
  return { ...linkWorktreeDependencies(main, worktree), install: null };
87343
87720
  }
87344
87721
  function staleBunInstall(main) {
87345
- if (!fs32.existsSync(path68.join(main, "node_modules")))
87722
+ if (!fs32.existsSync(path70.join(main, "node_modules")))
87346
87723
  return null;
87347
- const text = readBytes(path68.join(main, "bun.lock"))?.toString("utf8");
87724
+ const text = readBytes(path70.join(main, "bun.lock"))?.toString("utf8");
87348
87725
  if (!text)
87349
87726
  return null;
87350
87727
  let packages;
@@ -87371,7 +87748,7 @@ function staleBunInstall(main) {
87371
87748
  const version = spec.slice(at + 1);
87372
87749
  if (name !== key || version.includes(":"))
87373
87750
  continue;
87374
- const manifest = readBytes(path68.join(main, "node_modules", key, "package.json"));
87751
+ const manifest = readBytes(path70.join(main, "node_modules", key, "package.json"));
87375
87752
  if (!manifest) {
87376
87753
  problems.push(`${key} missing`);
87377
87754
  continue;
@@ -87388,7 +87765,7 @@ function staleBunInstall(main) {
87388
87765
  return problems.length ? problems.join("; ") : null;
87389
87766
  }
87390
87767
  function ensureScratch(worktree) {
87391
- const scratch = path68.join(worktree, SCRATCH_DIR);
87768
+ const scratch = path70.join(worktree, SCRATCH_DIR);
87392
87769
  fs32.mkdirSync(scratch, { recursive: true });
87393
87770
  return scratch;
87394
87771
  }
@@ -87662,7 +88039,7 @@ function unpushedCount(cwd, branch) {
87662
88039
  return count.ok ? Number(count.stdout.trim()) : null;
87663
88040
  }
87664
88041
  function removeScratch(worktree) {
87665
- const scratch = path68.join(worktree, SCRATCH_DIR);
88042
+ const scratch = path70.join(worktree, SCRATCH_DIR);
87666
88043
  let stat;
87667
88044
  try {
87668
88045
  stat = fs32.lstatSync(scratch);
@@ -87678,16 +88055,16 @@ var SLOW, SCRATCH_DIR = ".workit-scratch", EXCLUDE_LINE, DIRTY_ROW_BYTES = 2000,
87678
88055
  try {
87679
88056
  return fs32.realpathSync.native(target);
87680
88057
  } catch {
87681
- return path68.resolve(target);
88058
+ return path70.resolve(target);
87682
88059
  }
87683
88060
  }, samePath = (a, b) => {
87684
88061
  const left = canonical2(a);
87685
88062
  const right = canonical2(b);
87686
88063
  return process.platform === "win32" || process.platform === "darwin" ? left.toLowerCase() === right.toLowerCase() : left === right;
87687
88064
  }, inside3 = (child, parent) => {
87688
- const relative = path68.relative(canonical2(parent), canonical2(child));
87689
- return relative === "" || !relative.startsWith("..") && !path68.isAbsolute(relative);
87690
- }, slicePath = (cwd, slice) => path68.isAbsolute(slice.worktree) ? slice.worktree : path68.resolve(mainCheckout(cwd), slice.worktree), CLOCK_SLACK_MS = 2000, worktreeDeps, LOCKFILES2, readBytes = (file) => {
88065
+ const relative = path70.relative(canonical2(parent), canonical2(child));
88066
+ return relative === "" || !relative.startsWith("..") && !path70.isAbsolute(relative);
88067
+ }, slicePath = (cwd, slice) => path70.isAbsolute(slice.worktree) ? slice.worktree : path70.resolve(mainCheckout(cwd), slice.worktree), CLOCK_SLACK_MS = 2000, worktreeDeps, LOCKFILES2, readBytes = (file) => {
87691
88068
  try {
87692
88069
  return fs32.readFileSync(file);
87693
88070
  } catch {
@@ -87719,7 +88096,7 @@ var init_fanout_worktree = __esm(() => {
87719
88096
 
87720
88097
  // packages/workit-core/src/forge/merge-cleanup.ts
87721
88098
  import fs33 from "node:fs";
87722
- import path69 from "node:path";
88099
+ import path71 from "node:path";
87723
88100
  function cleanupMergedBranch(cwd, branch, mergedHead) {
87724
88101
  const out = { branchDeleted: false, worktreeRemoved: null, notes: [] };
87725
88102
  if (!branch || branch.startsWith("-"))
@@ -87779,13 +88156,13 @@ var SLOW2, isFanoutWorktree = (worktree) => {
87779
88156
  if (!dir.ok)
87780
88157
  return false;
87781
88158
  try {
87782
- return fs33.readFileSync(path69.join(dir.stdout.trim(), FANOUT_TOKEN_FILE), "utf8").trim() !== "";
88159
+ return fs33.readFileSync(path71.join(dir.stdout.trim(), FANOUT_TOKEN_FILE), "utf8").trim() !== "";
87783
88160
  } catch {
87784
88161
  return false;
87785
88162
  }
87786
88163
  }, inside4 = (child, parent) => {
87787
- const relative = path69.relative(fs33.realpathSync.native(parent), fs33.realpathSync.native(child));
87788
- return relative === "" || !relative.startsWith("..") && !path69.isAbsolute(relative);
88164
+ const relative = path71.relative(fs33.realpathSync.native(parent), fs33.realpathSync.native(child));
88165
+ return relative === "" || !relative.startsWith("..") && !path71.isAbsolute(relative);
87789
88166
  };
87790
88167
  var init_merge_cleanup = __esm(() => {
87791
88168
  init_fanout();
@@ -88066,7 +88443,7 @@ var init_duration = __esm(() => {
88066
88443
  });
88067
88444
 
88068
88445
  // packages/workit-cli/src/verbs/forge-common.ts
88069
- import { readFileSync as readFileSync28 } from "node:fs";
88446
+ import { readFileSync as readFileSync29 } from "node:fs";
88070
88447
  function parseFlags(argv, spec) {
88071
88448
  const parsed = { values: {}, booleans: new Set, lists: {}, positionals: [] };
88072
88449
  for (let index = 0;index < argv.length; index += 1) {
@@ -88224,7 +88601,7 @@ var init_forge_common = __esm(() => {
88224
88601
  forgeDeps = {
88225
88602
  runner: undefined,
88226
88603
  npm: undefined,
88227
- readStdin: () => readFileSync28(0, "utf8"),
88604
+ readStdin: () => readFileSync29(0, "utf8"),
88228
88605
  sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
88229
88606
  now: () => Date.now()
88230
88607
  };
@@ -88236,8 +88613,8 @@ __export(exports_pr, {
88236
88613
  checkPrTitle: () => checkPrTitle,
88237
88614
  run: () => run15
88238
88615
  });
88239
- import { existsSync as existsSync27, readFileSync as readFileSync29 } from "node:fs";
88240
- import path70 from "node:path";
88616
+ import { existsSync as existsSync28, readFileSync as readFileSync30 } from "node:fs";
88617
+ import path72 from "node:path";
88241
88618
  function titleRules(cwd) {
88242
88619
  let root;
88243
88620
  try {
@@ -88248,16 +88625,16 @@ function titleRules(cwd) {
88248
88625
  let text = null;
88249
88626
  let name = "";
88250
88627
  for (const candidate of COMMITLINT_FILES) {
88251
- const full = path70.join(root, candidate);
88252
- if (!existsSync27(full))
88628
+ const full = path72.join(root, candidate);
88629
+ if (!existsSync28(full))
88253
88630
  continue;
88254
- text = readFileSync29(full, "utf8");
88631
+ text = readFileSync30(full, "utf8");
88255
88632
  name = candidate;
88256
88633
  break;
88257
88634
  }
88258
88635
  if (text === null) {
88259
88636
  try {
88260
- const pkg = JSON.parse(readFileSync29(path70.join(root, "package.json"), "utf8"));
88637
+ const pkg = JSON.parse(readFileSync30(path72.join(root, "package.json"), "utf8"));
88261
88638
  if (pkg.commitlint === undefined)
88262
88639
  return { rules: null, note: null };
88263
88640
  text = JSON.stringify(pkg.commitlint);
@@ -88354,7 +88731,7 @@ function refuseTitle(io, title, line) {
88354
88731
  function readBodyFile(io, file) {
88355
88732
  try {
88356
88733
  return {
88357
- body: file === "-" ? forgeDeps.readStdin() : readFileSync29(path70.resolve(io.cwd, file), "utf8")
88734
+ body: file === "-" ? forgeDeps.readStdin() : readFileSync30(path72.resolve(io.cwd, file), "utf8")
88358
88735
  };
88359
88736
  } catch {
88360
88737
  return `cannot read --body-file ${file}`;
@@ -89243,8 +89620,8 @@ var exports_git = {};
89243
89620
  __export(exports_git, {
89244
89621
  run: () => run17
89245
89622
  });
89246
- import { readFileSync as readFileSync30 } from "node:fs";
89247
- import path71 from "node:path";
89623
+ import { readFileSync as readFileSync31 } from "node:fs";
89624
+ import path73 from "node:path";
89248
89625
  function kindHint(cwd, kind) {
89249
89626
  let kinds = [...BRANCH_KINDS];
89250
89627
  try {
@@ -89348,7 +89725,7 @@ function commitMessage(parsed, io) {
89348
89725
 
89349
89726
  `);
89350
89727
  try {
89351
- return file === "-" ? readFileSync30(0, "utf8") : readFileSync30(path71.resolve(io.cwd, file), "utf8");
89728
+ return file === "-" ? readFileSync31(0, "utf8") : readFileSync31(path73.resolve(io.cwd, file), "utf8");
89352
89729
  } catch (error) {
89353
89730
  return {
89354
89731
  error: `cannot read -F ${file}: ${error instanceof Error ? error.message : String(error)}`
@@ -90812,7 +91189,7 @@ var init_stack2 = __esm(() => {
90812
91189
  // packages/workit-core/src/fanout-brief.ts
90813
91190
  import { createHash as createHash20 } from "node:crypto";
90814
91191
  import fs35 from "node:fs";
90815
- import path72 from "node:path";
91192
+ import path74 from "node:path";
90816
91193
  function workerSession(lead, slice, attempt) {
90817
91194
  const tail = attempt === null ? "" : `+try${attempt}`;
90818
91195
  const full = `${lead}-w-${slice}${tail}`;
@@ -90895,7 +91272,7 @@ function renderBrief(cwd, plan, input) {
90895
91272
  "STANDING:",
90896
91273
  ...standing.length ? standing.map((order) => ` - ${order.what}`) : [" - none recorded beyond this brief"],
90897
91274
  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)`,
90898
- ...exists && typeof made?.install === "string" && !fs35.existsSync(path72.join(planned, "node_modules")) ? [`INSTALL: \`${made.install}\` first: the main checkout's node_modules was not linked here`] : [],
91275
+ ...exists && typeof made?.install === "string" && !fs35.existsSync(path74.join(planned, "node_modules")) ? [`INSTALL: \`${made.install}\` first: the main checkout's node_modules was not linked here`] : [],
90899
91276
  ...identityLines(identity, minted),
90900
91277
  ...rules(mode, branch, sliceBase, exists ? planned : null)
90901
91278
  ];
@@ -91437,7 +91814,7 @@ __export(exports_fanout, {
91437
91814
  run: () => run21
91438
91815
  });
91439
91816
  import fs36 from "node:fs";
91440
- import path73 from "node:path";
91817
+ import path75 from "node:path";
91441
91818
  function forgeFor(io, offline) {
91442
91819
  if (offline)
91443
91820
  return { forge: null, error: "--offline" };
@@ -91498,7 +91875,7 @@ function plan2(argv, io) {
91498
91875
  return usage4(io, "pass --trunk or --track, not both (--track picks the trunk)", PLAN_USAGE2);
91499
91876
  if (flags.positionals.length !== 1)
91500
91877
  return usage4(io, flags.positionals.length ? `unexpected argument ${flags.positionals[1]}` : "missing <plan.json>", PLAN_USAGE2);
91501
- const file = path73.resolve(io.cwd, flags.positionals[0]);
91878
+ const file = path75.resolve(io.cwd, flags.positionals[0]);
91502
91879
  let raw;
91503
91880
  try {
91504
91881
  raw = JSON.parse(fs36.readFileSync(file, "utf8"));
@@ -107074,7 +107451,7 @@ var init_ast = __esm(() => {
107074
107451
 
107075
107452
  // packages/workit-cli/src/test-audit/rules.ts
107076
107453
  import { builtinModules } from "node:module";
107077
- import path74 from "node:path";
107454
+ import path76 from "node:path";
107078
107455
  function testCallee(call) {
107079
107456
  let callee = call.callee;
107080
107457
  if (callee.type === "CallExpression")
@@ -107567,12 +107944,12 @@ function checkConstantsOnly(ctx, emit) {
107567
107944
  }
107568
107945
  function checkOverMocking(ctx, emit) {
107569
107946
  const { program } = ctx.parsed;
107570
- const unit = path74.basename(ctx.file).replace(/\.(?:[cm]?[jt]sx?)$/, "").replace(/\.(?:test|spec)$/, "");
107947
+ const unit = path76.basename(ctx.file).replace(/\.(?:[cm]?[jt]sx?)$/, "").replace(/\.(?:test|spec)$/, "");
107571
107948
  const mocked = find2(program, (node) => node.type === "CallExpression" && MODULE_MOCK.test(calleeName(node.callee) ?? "") && node.arguments[0]?.type === "StringLiteral");
107572
107949
  const internal = mocked.filter((call) => /^(?:\.|@\/|~\/)/.test(call.arguments[0].value));
107573
107950
  for (const call of mocked) {
107574
107951
  const spec = call.arguments[0].value;
107575
- const base = path74.basename(spec.replace(/\/index(?:\.[cm]?[jt]sx?)?$/, "")).replace(/\.(?:[cm]?[jt]sx?)$/, "");
107952
+ const base = path76.basename(spec.replace(/\/index(?:\.[cm]?[jt]sx?)?$/, "")).replace(/\.(?:[cm]?[jt]sx?)$/, "");
107576
107953
  if (base === unit)
107577
107954
  emit({
107578
107955
  rule: "over-mocking",
@@ -107961,8 +108338,8 @@ var init_rules = __esm(() => {
107961
108338
 
107962
108339
  // packages/workit-cli/src/test-audit/audit.ts
107963
108340
  import { spawnSync as spawnSync30 } from "node:child_process";
107964
- import { existsSync as existsSync28, readdirSync as readdirSync14, readFileSync as readFileSync31, statSync as statSync10 } from "node:fs";
107965
- import path75 from "node:path";
108341
+ import { existsSync as existsSync29, readdirSync as readdirSync14, readFileSync as readFileSync32, statSync as statSync10 } from "node:fs";
108342
+ import path77 from "node:path";
107966
108343
  function git7(cwd, args) {
107967
108344
  const run = spawnSync30("git", ["-c", "core.quotepath=off", ...args], {
107968
108345
  cwd,
@@ -107975,7 +108352,7 @@ function walkTests(dir, out) {
107975
108352
  for (const entry of readdirSync14(dir, { withFileTypes: true })) {
107976
108353
  if (entry.name.startsWith(".") && entry.name !== "." && entry.isDirectory())
107977
108354
  continue;
107978
- const full = path75.join(dir, entry.name);
108355
+ const full = path77.join(dir, entry.name);
107979
108356
  if (entry.isDirectory()) {
107980
108357
  if (!SKIP_DIRS.has(entry.name))
107981
108358
  walkTests(full, out);
@@ -107987,8 +108364,8 @@ function expandPaths(cwd, inputs) {
107987
108364
  const files = [];
107988
108365
  const missing = [];
107989
108366
  for (const input of inputs.length > 0 ? inputs : ["."]) {
107990
- const full = path75.resolve(cwd, input);
107991
- if (!existsSync28(full))
108367
+ const full = path77.resolve(cwd, input);
108368
+ if (!existsSync29(full))
107992
108369
  missing.push(input);
107993
108370
  else if (statSync10(full).isDirectory())
107994
108371
  walkTests(full, files);
@@ -108024,11 +108401,11 @@ function changedLines(cwd, base) {
108024
108401
  for (let offset = 0;offset < count; offset += 1)
108025
108402
  lines.add(start + offset);
108026
108403
  }
108027
- changed.set(path75.join(root, file), lines);
108404
+ changed.set(path77.join(root, file), lines);
108028
108405
  }
108029
108406
  const untracked = git7(root, ["ls-files", "--others", "--exclude-standard", "-z"]);
108030
108407
  for (const file of untracked.stdout.split("\x00").filter(Boolean))
108031
- changed.set(path75.join(root, file), "all");
108408
+ changed.set(path77.join(root, file), "all");
108032
108409
  return changed;
108033
108410
  }
108034
108411
  function auditFiles(files, display) {
@@ -108041,7 +108418,7 @@ function auditFiles(files, display) {
108041
108418
  const shown = display(file);
108042
108419
  let parsed;
108043
108420
  try {
108044
- parsed = parseSource(readFileSync31(file, "utf8"), file);
108421
+ parsed = parseSource(readFileSync32(file, "utf8"), file);
108045
108422
  } catch (error) {
108046
108423
  parseErrors.push({
108047
108424
  file: shown,
@@ -108090,7 +108467,7 @@ function auditFiles(files, display) {
108090
108467
  durationMs: Math.round(performance.now() - started)
108091
108468
  };
108092
108469
  }
108093
- var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(path75.sep).join("/"), SEVERITY_ORDER, ruleIds;
108470
+ var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(path77.sep).join("/"), SEVERITY_ORDER, ruleIds;
108094
108471
  var init_audit = __esm(() => {
108095
108472
  init_ast();
108096
108473
  init_rules();
@@ -108104,23 +108481,23 @@ var init_audit = __esm(() => {
108104
108481
  // packages/workit-cli/src/test-audit/mutate.ts
108105
108482
  import { spawn as spawn5 } from "node:child_process";
108106
108483
  import {
108107
- existsSync as existsSync29,
108484
+ existsSync as existsSync30,
108108
108485
  lstatSync as lstatSync9,
108109
108486
  mkdirSync as mkdirSync13,
108110
- mkdtempSync as mkdtempSync4,
108487
+ mkdtempSync as mkdtempSync6,
108111
108488
  readdirSync as readdirSync15,
108112
- readFileSync as readFileSync32,
108489
+ readFileSync as readFileSync33,
108113
108490
  readlinkSync as readlinkSync3,
108114
108491
  realpathSync as realpathSync11,
108115
108492
  renameSync as renameSync8,
108116
- rmSync as rmSync9,
108493
+ rmSync as rmSync11,
108117
108494
  statSync as statSync11,
108118
108495
  symlinkSync,
108119
- writeFileSync as writeFileSync14,
108496
+ writeFileSync as writeFileSync15,
108120
108497
  copyFileSync as copyFileSync8
108121
108498
  } from "node:fs";
108122
- import os24 from "node:os";
108123
- import path76 from "node:path";
108499
+ import os26 from "node:os";
108500
+ import path78 from "node:path";
108124
108501
  function mutantsFor(source, file, lines) {
108125
108502
  const parsed = parseSource(source, file);
108126
108503
  const out = [];
@@ -108193,7 +108570,7 @@ function relatedTests(source, testFiles) {
108193
108570
  for (const match of text.matchAll(SPECIFIER)) {
108194
108571
  const spec = match[1];
108195
108572
  if (spec.startsWith(".")) {
108196
- if (stripExt(path76.posix.join(path76.posix.dirname(file), spec)) === target)
108573
+ if (stripExt(path78.posix.join(path78.posix.dirname(file), spec)) === target)
108197
108574
  return true;
108198
108575
  } else if (spec.includes("/") && stripExt(spec).split("/").slice(-2).join("/") === tail)
108199
108576
  return true;
@@ -108201,7 +108578,7 @@ function relatedTests(source, testFiles) {
108201
108578
  return false;
108202
108579
  }).map((entry) => entry.file);
108203
108580
  }
108204
- function removeStaleCopies(tmp = os24.tmpdir()) {
108581
+ function removeStaleCopies(tmp = os26.tmpdir()) {
108205
108582
  let removed = 0;
108206
108583
  let names = [];
108207
108584
  try {
@@ -108213,12 +108590,12 @@ function removeStaleCopies(tmp = os24.tmpdir()) {
108213
108590
  for (const name of names) {
108214
108591
  if (!name.startsWith(TEMP_PREFIX))
108215
108592
  continue;
108216
- const dir = path76.join(tmp, name);
108593
+ const dir = path78.join(tmp, name);
108217
108594
  try {
108218
108595
  const stat = lstatSync9(dir);
108219
108596
  if (!stat.isDirectory() || uid !== undefined && stat.uid !== uid)
108220
108597
  continue;
108221
- const pid = Number(readFileSync32(path76.join(dir, PID_FILE), "utf8"));
108598
+ const pid = Number(readFileSync33(path78.join(dir, PID_FILE), "utf8"));
108222
108599
  if (Number.isInteger(pid) && pid > 0 && alive(pid))
108223
108600
  continue;
108224
108601
  } catch (error) {
@@ -108226,7 +108603,7 @@ function removeStaleCopies(tmp = os24.tmpdir()) {
108226
108603
  continue;
108227
108604
  }
108228
108605
  try {
108229
- rmSync9(dir, { recursive: true, force: true });
108606
+ rmSync11(dir, { recursive: true, force: true });
108230
108607
  removed += 1;
108231
108608
  } catch {}
108232
108609
  }
@@ -108235,8 +108612,8 @@ function removeStaleCopies(tmp = os24.tmpdir()) {
108235
108612
  function linkNodeModules(origin, target, repo, copy) {
108236
108613
  mkdirSync13(target, { recursive: true });
108237
108614
  for (const entry of readdirSync15(origin, { withFileTypes: true })) {
108238
- const from = path76.join(origin, entry.name);
108239
- const to = path76.join(target, entry.name);
108615
+ const from = path78.join(origin, entry.name);
108616
+ const to = path78.join(target, entry.name);
108240
108617
  if (entry.name.startsWith("@") && entry.isDirectory()) {
108241
108618
  linkNodeModules(from, to, repo, copy);
108242
108619
  continue;
@@ -108252,9 +108629,9 @@ function linkNodeModules(origin, target, repo, copy) {
108252
108629
  } catch {
108253
108630
  continue;
108254
108631
  }
108255
- const relative = path76.relative(repo, real);
108256
- if (!relative.startsWith("..") && !path76.isAbsolute(relative) && !relative.split(path76.sep).includes("node_modules")) {
108257
- symlinkSync(path76.join(copy, relative), to, "junction");
108632
+ const relative = path78.relative(repo, real);
108633
+ if (!relative.startsWith("..") && !path78.isAbsolute(relative) && !relative.split(path78.sep).includes("node_modules")) {
108634
+ symlinkSync(path78.join(copy, relative), to, "junction");
108258
108635
  continue;
108259
108636
  }
108260
108637
  }
@@ -108270,7 +108647,7 @@ function copySymlink(repo, tree, from, to) {
108270
108647
  }
108271
108648
  const realRepo = realpathSync11(repo);
108272
108649
  if (real && inside5(realRepo, real)) {
108273
- symlinkSync(path76.relative(path76.dirname(to), path76.join(tree, path76.relative(realRepo, real))), to);
108650
+ symlinkSync(path78.relative(path78.dirname(to), path78.join(tree, path78.relative(realRepo, real))), to);
108274
108651
  return;
108275
108652
  }
108276
108653
  if (real && statSync11(real).isFile())
@@ -108279,23 +108656,23 @@ function copySymlink(repo, tree, from, to) {
108279
108656
  symlinkSync(readlinkSync3(from), to);
108280
108657
  }
108281
108658
  function writeInside(copy, file, content) {
108282
- const target = path76.join(copy, file);
108659
+ const target = path78.join(copy, file);
108283
108660
  try {
108284
108661
  const stat = lstatSync9(target);
108285
- if (!stat.isFile() || !inside5(realpathSync11(copy), realpathSync11(path76.dirname(target))))
108662
+ if (!stat.isFile() || !inside5(realpathSync11(copy), realpathSync11(path78.dirname(target))))
108286
108663
  return false;
108287
108664
  } catch {
108288
108665
  return false;
108289
108666
  }
108290
108667
  const temp = `${target}.workit-mutant-${process.pid}`;
108291
- writeFileSync14(temp, content);
108668
+ writeFileSync15(temp, content);
108292
108669
  renameSync8(temp, target);
108293
108670
  return true;
108294
108671
  }
108295
108672
  function copyWorkingTree(repo) {
108296
- const dir = mkdtempSync4(path76.join(os24.tmpdir(), TEMP_PREFIX));
108297
- writeFileSync14(path76.join(dir, PID_FILE), String(process.pid));
108298
- const tree = path76.join(dir, "tree");
108673
+ const dir = mkdtempSync6(path78.join(os26.tmpdir(), TEMP_PREFIX));
108674
+ writeFileSync15(path78.join(dir, PID_FILE), String(process.pid));
108675
+ const tree = path78.join(dir, "tree");
108299
108676
  const head = git7(repo, ["rev-parse", "--verify", "--quiet", "HEAD"]).stdout.trim();
108300
108677
  if (head && git7(dir, ["clone", "-q", "--shared", "--no-checkout", repo, tree]).ok) {
108301
108678
  const branch = git7(repo, ["symbolic-ref", "--quiet", "--short", "HEAD"]).stdout.trim();
@@ -108312,29 +108689,29 @@ function copyWorkingTree(repo) {
108312
108689
  for (const relative of listed) {
108313
108690
  if (!relative)
108314
108691
  continue;
108315
- const from = path76.join(repo, relative);
108692
+ const from = path78.join(repo, relative);
108316
108693
  let stat;
108317
108694
  try {
108318
108695
  stat = lstatSync9(from);
108319
108696
  } catch {
108320
108697
  continue;
108321
108698
  }
108322
- const to = path76.join(tree, relative);
108323
- mkdirSync13(path76.dirname(to), { recursive: true });
108699
+ const to = path78.join(tree, relative);
108700
+ mkdirSync13(path78.dirname(to), { recursive: true });
108324
108701
  if (stat.isSymbolicLink())
108325
108702
  copySymlink(repo, tree, from, to);
108326
108703
  else if (stat.isFile())
108327
108704
  copyFileSync8(from, to);
108328
- let parent = path76.dirname(relative);
108705
+ let parent = path78.dirname(relative);
108329
108706
  while (parent !== "." && !dirs.has(parent)) {
108330
108707
  dirs.add(parent);
108331
- parent = path76.dirname(parent);
108708
+ parent = path78.dirname(parent);
108332
108709
  }
108333
108710
  }
108334
108711
  for (const parent of dirs) {
108335
- const modules = path76.join(repo, parent, "node_modules");
108336
- if (existsSync29(modules) && !existsSync29(path76.join(tree, parent, "node_modules")))
108337
- linkNodeModules(modules, path76.join(tree, parent, "node_modules"), repo, tree);
108712
+ const modules = path78.join(repo, parent, "node_modules");
108713
+ if (existsSync30(modules) && !existsSync30(path78.join(tree, parent, "node_modules")))
108714
+ linkNodeModules(modules, path78.join(tree, parent, "node_modules"), repo, tree);
108338
108715
  }
108339
108716
  return { dir, tree };
108340
108717
  }
@@ -108373,20 +108750,20 @@ async function runMutation(options) {
108373
108750
  const tracked = git7(repo, ["ls-files", "-co", "--exclude-standard", "-z"]).stdout.split("\x00").filter(Boolean);
108374
108751
  const testFiles = tracked.filter((file) => TEST_FILE.test(file)).map((file) => {
108375
108752
  try {
108376
- return { file, text: readFileSync32(path76.join(repo, file), "utf8") };
108753
+ return { file, text: readFileSync33(path78.join(repo, file), "utf8") };
108377
108754
  } catch {
108378
108755
  return { file, text: "" };
108379
108756
  }
108380
108757
  });
108381
108758
  const candidates = [];
108382
108759
  for (const [absolute, lines] of [...options.changed].toSorted(([a], [b]) => a.localeCompare(b))) {
108383
- const relative = toPosix(path76.relative(repo, absolute));
108760
+ const relative = toPosix(path78.relative(repo, absolute));
108384
108761
  if (!CODE_FILE.test(relative) || TEST_FILE.test(relative) || relative.endsWith(".d.ts"))
108385
108762
  continue;
108386
- if (NOT_SOURCE.test(relative) || !existsSync29(absolute))
108763
+ if (NOT_SOURCE.test(relative) || !existsSync30(absolute))
108387
108764
  continue;
108388
108765
  try {
108389
- candidates.push(...mutantsFor(readFileSync32(absolute, "utf8"), relative, lines));
108766
+ candidates.push(...mutantsFor(readFileSync33(absolute, "utf8"), relative, lines));
108390
108767
  } catch {}
108391
108768
  }
108392
108769
  const mutants = candidates.map((mutant, index) => ({ ...mutant, id: index + 1 }));
@@ -108394,9 +108771,9 @@ async function runMutation(options) {
108394
108771
  for (const mutant of mutants)
108395
108772
  if (!related.has(mutant.file))
108396
108773
  related.set(mutant.file, relatedTests(mutant.file, testFiles));
108397
- const cwdRelative = path76.relative(repo, options.cwd);
108774
+ const cwdRelative = path78.relative(repo, options.cwd);
108398
108775
  const asArg = (file) => {
108399
- const relative = toPosix(path76.relative(cwdRelative, file));
108776
+ const relative = toPosix(path78.relative(cwdRelative, file));
108400
108777
  return shellQuote(relative.startsWith(".") ? relative : `./${relative}`);
108401
108778
  };
108402
108779
  const commandFor = (tests) => options.command.replaceAll("{files}", () => tests.map(asArg).join(" "));
@@ -108432,7 +108809,7 @@ async function runMutation(options) {
108432
108809
  return finish3(options, 0, results, counts, started);
108433
108810
  removeStaleCopies();
108434
108811
  const { dir: copyDir, tree: copy } = copyWorkingTree(repo);
108435
- const copyCwd = path76.join(copy, cwdRelative);
108812
+ const copyCwd = path78.join(copy, cwdRelative);
108436
108813
  let current = null;
108437
108814
  const restore = () => {
108438
108815
  if (current)
@@ -108443,7 +108820,7 @@ async function runMutation(options) {
108443
108820
  for (const child of active)
108444
108821
  killTree(child);
108445
108822
  restore();
108446
- rmSync9(copyDir, { recursive: true, force: true });
108823
+ rmSync11(copyDir, { recursive: true, force: true });
108447
108824
  };
108448
108825
  const onSignal = (signal) => {
108449
108826
  cleanup();
@@ -108467,7 +108844,7 @@ async function runMutation(options) {
108467
108844
  record({ ...mutant, status: "skipped", durationMs: 0, tests, reason: "budget" });
108468
108845
  continue;
108469
108846
  }
108470
- const original = readFileSync32(path76.join(copy, mutant.file), "utf8");
108847
+ const original = readFileSync33(path78.join(copy, mutant.file), "utf8");
108471
108848
  const mutated = original.slice(0, mutant.start) + mutant.replacement + original.slice(mutant.end);
108472
108849
  current = { file: mutant.file, original };
108473
108850
  if (!writeInside(copy, mutant.file, mutated)) {
@@ -108524,8 +108901,8 @@ var NOT_SOURCE, FLIPS, isStringy = (node) => node.type === "StringLiteral" || no
108524
108901
  return error.code === "EPERM";
108525
108902
  }
108526
108903
  }, inside5 = (root, file) => {
108527
- const relative = path76.relative(root, file);
108528
- return relative === "" || !relative.startsWith("..") && !path76.isAbsolute(relative);
108904
+ const relative = path78.relative(root, file);
108905
+ return relative === "" || !relative.startsWith("..") && !path78.isAbsolute(relative);
108529
108906
  }, active, killTree = (child) => {
108530
108907
  try {
108531
108908
  if (child.pid && process.platform !== "win32")
@@ -108573,8 +108950,8 @@ var exports_test_audit = {};
108573
108950
  __export(exports_test_audit, {
108574
108951
  run: () => run23
108575
108952
  });
108576
- import { existsSync as existsSync30 } from "node:fs";
108577
- import path77 from "node:path";
108953
+ import { existsSync as existsSync31 } from "node:fs";
108954
+ import path79 from "node:path";
108578
108955
  function parse8(argv) {
108579
108956
  const options = {
108580
108957
  paths: [],
@@ -108679,8 +109056,8 @@ async function run23(argv, io) {
108679
109056
  return emit(io, fail2("invalid_input", `${options}
108680
109057
  usage: ${USAGE16}`));
108681
109058
  const top = git7(io.cwd, ["rev-parse", "--show-toplevel"]);
108682
- const repo = top.ok ? path77.resolve(top.stdout.trim()) : null;
108683
- const display = (file) => toPosix(path77.relative(io.cwd, file) || file);
109059
+ const repo = top.ok ? path79.resolve(top.stdout.trim()) : null;
109060
+ const display = (file) => toPosix(path79.relative(io.cwd, file) || file);
108684
109061
  let base = null;
108685
109062
  let changed = null;
108686
109063
  if (options.diff || options.mutate) {
@@ -108697,7 +109074,7 @@ usage: ${USAGE16}`));
108697
109074
  }
108698
109075
  let files;
108699
109076
  if (options.diff && changed)
108700
- files = [...changed.keys()].filter((file) => TEST_FILE.test(toPosix(file)) && existsSync30(file)).toSorted();
109077
+ files = [...changed.keys()].filter((file) => TEST_FILE.test(toPosix(file)) && existsSync31(file)).toSorted();
108701
109078
  else {
108702
109079
  const expanded = expandPaths(io.cwd, options.paths);
108703
109080
  if (expanded.missing.length > 0)
@@ -108818,8 +109195,8 @@ var exports_youtrack = {};
108818
109195
  __export(exports_youtrack, {
108819
109196
  run: () => run25
108820
109197
  });
108821
- import { readFileSync as readFileSync33 } from "node:fs";
108822
- import path78 from "node:path";
109198
+ import { readFileSync as readFileSync34 } from "node:fs";
109199
+ import path80 from "node:path";
108823
109200
  async function run25(argv, io) {
108824
109201
  const [sub, ...rest] = argv;
108825
109202
  if (sub !== "note" && sub !== "time" && sub !== "meeting")
@@ -108865,7 +109242,7 @@ async function run25(argv, io) {
108865
109242
  let markdown = flags.values.markdown ?? "";
108866
109243
  if (flags.values.file)
108867
109244
  try {
108868
- markdown = readFileSync33(path78.resolve(io.cwd, flags.values.file), "utf8");
109245
+ markdown = readFileSync34(path80.resolve(io.cwd, flags.values.file), "utf8");
108869
109246
  } catch (error) {
108870
109247
  return usage4(io, `cannot read ${flags.values.file}: ${String(error)}`, USAGE18);
108871
109248
  }
@@ -108936,8 +109313,8 @@ var exports_changelog = {};
108936
109313
  __export(exports_changelog, {
108937
109314
  run: () => run26
108938
109315
  });
108939
- import { readFileSync as readFileSync34 } from "node:fs";
108940
- import path79 from "node:path";
109316
+ import { readFileSync as readFileSync35 } from "node:fs";
109317
+ import path81 from "node:path";
108941
109318
  async function run26(argv, io) {
108942
109319
  const [sub, ...rest] = argv;
108943
109320
  if (sub !== "apply")
@@ -108983,7 +109360,7 @@ async function run26(argv, io) {
108983
109360
  ]);
108984
109361
  }
108985
109362
  var USAGE19 = "workit changelog apply (--entries <JSON|@file|-> | --normalize-only) [--path CHANGELOG.md] [--preview]", readEntries = (raw, cwd) => {
108986
- const text = raw === "-" ? readFileSync34(0, "utf8") : raw.startsWith("@") ? readFileSync34(path79.resolve(cwd, raw.slice(1)), "utf8") : raw;
109363
+ const text = raw === "-" ? readFileSync35(0, "utf8") : raw.startsWith("@") ? readFileSync35(path81.resolve(cwd, raw.slice(1)), "utf8") : raw;
108987
109364
  return JSON.parse(text);
108988
109365
  };
108989
109366
  var init_changelog2 = __esm(() => {
@@ -108999,7 +109376,7 @@ __export(exports_handoff, {
108999
109376
  run: () => run27
109000
109377
  });
109001
109378
  import fs37 from "node:fs";
109002
- import path80 from "node:path";
109379
+ import path82 from "node:path";
109003
109380
  import { parseArgs as parseArgs2 } from "node:util";
109004
109381
  function render3(brief) {
109005
109382
  const lines = [
@@ -109039,9 +109416,9 @@ function bounded(brief, cwd) {
109039
109416
  let file = null;
109040
109417
  if (store.ok)
109041
109418
  try {
109042
- const dir = path80.join(store.value.root, "handoff");
109419
+ const dir = path82.join(store.value.root, "handoff");
109043
109420
  fs37.mkdirSync(dir, { recursive: true });
109044
- file = path80.join(dir, `${(brief.branch ?? "detached").replaceAll(/[^\w.-]+/gu, "-")}.txt`);
109421
+ file = path82.join(dir, `${(brief.branch ?? "detached").replaceAll(/[^\w.-]+/gu, "-")}.txt`);
109045
109422
  fs37.writeFileSync(file, `${[...body, ...tail].join(`
109046
109423
  `)}
109047
109424
  `, {
@@ -109116,7 +109493,7 @@ var init_handoff = __esm(() => {
109116
109493
  });
109117
109494
 
109118
109495
  // packages/workit-cli/src/main.ts
109119
- import path81 from "node:path";
109496
+ import path83 from "node:path";
109120
109497
 
109121
109498
  // packages/workit-core/src/git/env-redirect.ts
109122
109499
  var GIT_REDIRECT_ENV = [
@@ -110065,7 +110442,7 @@ var defaultIo = (json) => ({
110065
110442
  });
110066
110443
  async function main(argv, overrides = {}, options = {}) {
110067
110444
  const parsed = parseGlobals(argv);
110068
- const cwd = path81.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
110445
+ const cwd = path83.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
110069
110446
  const io = {
110070
110447
  ...defaultIo(parsed.json),
110071
110448
  terminals: {