@brainervirus/workit-cli 8.43.2 → 8.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +1015 -603
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -97,7 +97,7 @@ import os from "node:os";
97
97
  import path from "node:path";
98
98
  var diagnosticLogger, setDiagnosticLogger = (logger) => {
99
99
  diagnosticLogger = logger;
100
- }, getDiagnosticLogger = () => diagnosticLogger, PRESETS, mergePreset = (preset, input = {}, current = {
100
+ }, getDiagnosticLogger = () => diagnosticLogger, UPDATES_MODES, isUpdatesMode = (value) => UPDATES_MODES.includes(value), PRESETS, mergePreset = (preset, input = {}, current = {
101
101
  branchPolicy: { preset, allowed: [], protected: [] }
102
102
  }) => {
103
103
  const defs = PRESETS[preset];
@@ -137,7 +137,11 @@ var diagnosticLogger, setDiagnosticLogger = (logger) => {
137
137
  copyFileSync(src, dest);
138
138
  } catch (err) {
139
139
  migrationFailed = true;
140
- diagnosticLogger?.warn(EVENT.migration, { from: src, ok: false, ...errorDetail(err) });
140
+ diagnosticLogger?.warn(EVENT.migration, {
141
+ from: src,
142
+ ok: false,
143
+ ...errorDetail(err)
144
+ });
141
145
  console.warn(`[workit] config migration: a file could not be copied to ${dir}; it will be retried on the next run`);
142
146
  }
143
147
  }
@@ -157,10 +161,18 @@ var diagnosticLogger, setDiagnosticLogger = (logger) => {
157
161
  try {
158
162
  parsed = JSON.parse(raw);
159
163
  } catch {
160
- return { status: "malformed", path: file, error: `${file} is not valid JSON` };
164
+ return {
165
+ status: "malformed",
166
+ path: file,
167
+ error: `${file} is not valid JSON`
168
+ };
161
169
  }
162
170
  if (!isConfigObject(parsed)) {
163
- return { status: "malformed", path: file, error: `${file} is not a JSON object` };
171
+ return {
172
+ status: "malformed",
173
+ path: file,
174
+ error: `${file} is not a JSON object`
175
+ };
164
176
  }
165
177
  const input = parsed;
166
178
  const locale = LOCALE_RE.test(String(input.locale ?? "")) ? input.locale : DEFAULTS.locale;
@@ -176,7 +188,8 @@ var diagnosticLogger, setDiagnosticLogger = (logger) => {
176
188
  commitPolicy: {
177
189
  preset: commitPreset,
178
190
  ...typeof input.commitPolicy?.pattern === "string" ? { pattern: input.commitPolicy.pattern } : {}
179
- }
191
+ },
192
+ ...isUpdatesMode(input.updates) ? { updates: input.updates } : {}
180
193
  };
181
194
  if (!Object.hasOwn(PRESETS, input.branchPolicy?.preset))
182
195
  unchosenBranchPolicy.add(config);
@@ -224,6 +237,7 @@ var diagnosticLogger, setDiagnosticLogger = (logger) => {
224
237
  };
225
238
  var init_config = __esm(() => {
226
239
  init_boundary();
240
+ UPDATES_MODES = ["prompt", "auto", "off"];
227
241
  PRESETS = {
228
242
  gitflow: {
229
243
  allowed: ["feature/*", "bugfix/*", "hotfix/*", "release/*"],
@@ -9417,7 +9431,7 @@ var package_default;
9417
9431
  var init_package = __esm(() => {
9418
9432
  package_default = {
9419
9433
  name: "@brainervirus/workit-cli",
9420
- version: "8.43.2",
9434
+ version: "8.44.0",
9421
9435
  private: false,
9422
9436
  description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
9423
9437
  keywords: [
@@ -9455,13 +9469,13 @@ var init_package = __esm(() => {
9455
9469
  },
9456
9470
  dependencies: {
9457
9471
  "@babel/parser": "7.29.9",
9458
- "@brainervirus/workit-cursor": "^8.43.2",
9472
+ "@brainervirus/workit-cursor": "^8.44.0",
9459
9473
  "@inkjs/ui": "2.0.0",
9460
9474
  ink: "7.1.1",
9461
9475
  react: "19.2.8"
9462
9476
  },
9463
9477
  devDependencies: {
9464
- "@brainervirus/workit-core": "^8.43.2"
9478
+ "@brainervirus/workit-core": "^8.44.0"
9465
9479
  },
9466
9480
  engines: {
9467
9481
  node: ">=24"
@@ -67459,6 +67473,60 @@ var init_hook_runs = __esm(() => {
67459
67473
  init_heavy_words();
67460
67474
  });
67461
67475
 
67476
+ // packages/workit-cli/src/update-settings.ts
67477
+ import { mkdirSync as mkdirSync7, readFileSync as readFileSync17, renameSync as renameSync4, writeFileSync as writeFileSync9 } from "node:fs";
67478
+ import os11 from "node:os";
67479
+ import path38 from "node:path";
67480
+ var workitConfigDir = (env) => env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path38.join(env.XDG_CONFIG_HOME || path38.join(env.HOME ?? os11.homedir(), ".config"), "workit"), cacheFile = (env, dir = stateDir(env)) => path38.join(dir, "update-check.json"), readUpdateCache = (env, dir) => {
67481
+ try {
67482
+ const data = JSON.parse(readFileSync17(cacheFile(env, dir), "utf8"));
67483
+ return isConfigObject(data) ? data : {};
67484
+ } catch {
67485
+ return {};
67486
+ }
67487
+ }, writeUpdateCache = (env, cache) => {
67488
+ try {
67489
+ const file = cacheFile(env);
67490
+ mkdirSync7(path38.dirname(file), { recursive: true });
67491
+ const temp = `${file}.${process.pid}.tmp`;
67492
+ writeFileSync9(temp, JSON.stringify(cache) + `
67493
+ `, "utf8");
67494
+ renameSync4(temp, file);
67495
+ } catch {}
67496
+ }, configFile = (env, dir = workitConfigDir(env)) => path38.join(dir, "config.json"), readUpdatesMode = (env, dir) => {
67497
+ try {
67498
+ const data = JSON.parse(readFileSync17(configFile(env, dir), "utf8"));
67499
+ return isConfigObject(data) && isUpdatesMode(data.updates) ? data.updates : "prompt";
67500
+ } catch {
67501
+ return "prompt";
67502
+ }
67503
+ }, writeUpdatesMode = (env, mode) => {
67504
+ const file = configFile(env);
67505
+ let data = {};
67506
+ try {
67507
+ const raw = readFileSync17(file, "utf8");
67508
+ const parsed = JSON.parse(raw);
67509
+ if (!isConfigObject(parsed))
67510
+ return `${file} is not a JSON object`;
67511
+ data = parsed;
67512
+ } catch (error) {
67513
+ if (error.code !== "ENOENT")
67514
+ return `${file} is not valid JSON`;
67515
+ }
67516
+ try {
67517
+ mkdirSync7(path38.dirname(file), { recursive: true });
67518
+ writeFileSync9(file, JSON.stringify({ ...data, updates: mode }, null, 2) + `
67519
+ `, "utf8");
67520
+ return null;
67521
+ } catch (error) {
67522
+ return error instanceof Error ? error.message : `cannot write ${file}`;
67523
+ }
67524
+ };
67525
+ var init_update_settings = __esm(() => {
67526
+ init_heavy_words();
67527
+ init_config();
67528
+ });
67529
+
67462
67530
  // packages/workit-core/src/hooks/delivery-verbs.ts
67463
67531
  var WORKIT_ALLOWED_VERBS, ALLOWED;
67464
67532
  var init_delivery_verbs = __esm(() => {
@@ -67488,14 +67556,14 @@ import {
67488
67556
  copyFileSync as copyFileSync4,
67489
67557
  existsSync as existsSync16,
67490
67558
  readdirSync as readdirSync9,
67491
- mkdirSync as mkdirSync7,
67492
- readFileSync as readFileSync17,
67559
+ mkdirSync as mkdirSync8,
67560
+ readFileSync as readFileSync18,
67493
67561
  realpathSync as realpathSync8,
67494
67562
  rmSync as rmSync3,
67495
67563
  statSync as statSync5
67496
67564
  } from "node:fs";
67497
- import os11 from "node:os";
67498
- import path38 from "node:path";
67565
+ import os12 from "node:os";
67566
+ import path39 from "node:path";
67499
67567
  function mergeClaudeSettings(settings, shell, skip = {}) {
67500
67568
  const config = clone4(settings);
67501
67569
  const owned = emptyOwned();
@@ -67615,7 +67683,7 @@ function planHostPermissions(options) {
67615
67683
  plan.blocked.push(`${target.file} is not a JSON object; left untouched`);
67616
67684
  continue;
67617
67685
  }
67618
- const shellWanted = host === "claude-code" && options.shell !== false && path38.basename(paths.env.SHELL ?? "") === "zsh";
67686
+ const shellWanted = host === "claude-code" && options.shell !== false && path39.basename(paths.env.SHELL ?? "") === "zsh";
67619
67687
  const bash = shellWanted ? options.bash === undefined ? findBash(paths.env) : options.bash : null;
67620
67688
  const merged = host === "claude-code" ? mergeClaudeSettings(parsed, bash, skip) : mergeCursorCliConfig(parsed, skip);
67621
67689
  if (merged.error) {
@@ -67715,11 +67783,11 @@ function applyHostPermissions(plan, options = {}) {
67715
67783
  try {
67716
67784
  const target = change.before === null ? change.file : realpathSync8(change.file);
67717
67785
  if (change.before !== null) {
67718
- const backups = path38.join(paths.stateDir, "host-permissions-backup");
67719
- mkdirSync7(backups, { recursive: true, mode: 448 });
67720
- copyFileSync4(target, path38.join(backups, `${new Date().toISOString().replaceAll(":", "-")}-${change.host}-${path38.basename(change.file)}`));
67786
+ const backups = path39.join(paths.stateDir, "host-permissions-backup");
67787
+ mkdirSync8(backups, { recursive: true, mode: 448 });
67788
+ copyFileSync4(target, path39.join(backups, `${new Date().toISOString().replaceAll(":", "-")}-${change.host}-${path39.basename(change.file)}`));
67721
67789
  }
67722
- mkdirSync7(path38.dirname(target), { recursive: true });
67790
+ mkdirSync8(path39.dirname(target), { recursive: true });
67723
67791
  writeFileAtomic(target, change.after);
67724
67792
  const previous = record.hosts[change.host];
67725
67793
  record.hosts[change.host] = {
@@ -67782,19 +67850,19 @@ function permissionCoverage(host, commands, options = {}) {
67782
67850
  const cwd = options.cwd ?? process.cwd();
67783
67851
  let missing;
67784
67852
  if (host === "codex") {
67785
- const patterns = codexAllowPatterns(path38.dirname(target.file));
67853
+ const patterns = codexAllowPatterns(path39.dirname(target.file));
67786
67854
  missing = commands.filter((command) => {
67787
67855
  const words = command.split(" ");
67788
67856
  return !patterns.some((p) => p.every((word, i) => words[i] === word));
67789
67857
  });
67790
67858
  } else if (host === "cursor") {
67791
- const rules = [target.file, path38.join(cwd, ".cursor", "cli.json")].flatMap((file) => stringList(valueFrom(readRecord(file), "permissions", "allow")));
67859
+ const rules = [target.file, path39.join(cwd, ".cursor", "cli.json")].flatMap((file) => stringList(valueFrom(readRecord(file), "permissions", "allow")));
67792
67860
  missing = commands.filter((command) => !rules.some((rule) => cursorRuleMatches(rule, command)));
67793
67861
  } else {
67794
67862
  const files = [
67795
67863
  target.file,
67796
- path38.join(cwd, ".claude", "settings.json"),
67797
- path38.join(cwd, ".claude", "settings.local.json")
67864
+ path39.join(cwd, ".claude", "settings.json"),
67865
+ path39.join(cwd, ".claude", "settings.local.json")
67798
67866
  ].map(readRecord);
67799
67867
  const rules = files.flatMap((file) => stringList(valueFrom(file, "permissions", "allow")));
67800
67868
  missing = commands.filter((command) => !rules.some((rule) => claudeRuleMatches(rule, command)));
@@ -67896,7 +67964,7 @@ ${[...rules, ...lease, grant].join(`
67896
67964
  };
67897
67965
  }, resolvePaths = (options) => {
67898
67966
  const env = options.env ?? process.env;
67899
- const home = options.home ?? env.HOME ?? os11.homedir();
67967
+ const home = options.home ?? env.HOME ?? os12.homedir();
67900
67968
  return {
67901
67969
  home,
67902
67970
  env,
@@ -67906,25 +67974,25 @@ ${[...rules, ...lease, grant].join(`
67906
67974
  const { home, env } = resolvePaths(options);
67907
67975
  if (host === "claude-code") {
67908
67976
  const dir = claudeConfigDir(home, env);
67909
- return { file: path38.join(dir, "settings.json"), hostDir: dir };
67977
+ return { file: path39.join(dir, "settings.json"), hostDir: dir };
67910
67978
  }
67911
67979
  if (host === "codex") {
67912
- const dir = env.CODEX_HOME || path38.join(home, ".codex");
67913
- return { file: path38.join(dir, "rules", "workit.rules"), hostDir: dir };
67980
+ const dir = env.CODEX_HOME || path39.join(home, ".codex");
67981
+ return { file: path39.join(dir, "rules", "workit.rules"), hostDir: dir };
67914
67982
  }
67915
- const dir = path38.join(home, ".cursor");
67916
- return { file: path38.join(dir, "cli-config.json"), hostDir: dir };
67983
+ const dir = path39.join(home, ".cursor");
67984
+ return { file: path39.join(dir, "cli-config.json"), hostDir: dir };
67917
67985
  }, AGENT_SESSION_VARS, agentSessionVar = (env) => AGENT_SESSION_VARS.find((name) => (env[name] ?? "") !== "") ?? null, RECORD_FILE = "host-permissions.json", readOwnership = (options = {}) => {
67918
67986
  const { stateDir } = resolvePaths(options);
67919
67987
  try {
67920
- const value = JSON.parse(readFileSync17(path38.join(stateDir, RECORD_FILE), "utf8"));
67988
+ const value = JSON.parse(readFileSync18(path39.join(stateDir, RECORD_FILE), "utf8"));
67921
67989
  if (isRecord5(value) && isRecord5(value.hosts))
67922
67990
  return { version: 1, hosts: value.hosts };
67923
67991
  } catch {}
67924
67992
  return { version: 1, hosts: {} };
67925
67993
  }, writeOwnership = (record, stateDir) => {
67926
- mkdirSync7(stateDir, { recursive: true });
67927
- writeFileAtomic(path38.join(stateDir, RECORD_FILE), JSON.stringify(record, null, 2) + `
67994
+ mkdirSync8(stateDir, { recursive: true });
67995
+ writeFileAtomic(path39.join(stateDir, RECORD_FILE), JSON.stringify(record, null, 2) + `
67928
67996
  `, 384);
67929
67997
  }, unionLists = (a, b) => {
67930
67998
  const lists = { ...a };
@@ -67946,14 +68014,14 @@ ${[...rules, ...lease, grant].join(`
67946
68014
  writeOwnership(record, paths.stateDir);
67947
68015
  }, readText4 = (file) => {
67948
68016
  try {
67949
- return readFileSync17(file, "utf8");
68017
+ return readFileSync18(file, "utf8");
67950
68018
  } catch {
67951
68019
  return null;
67952
68020
  }
67953
68021
  }, findBash = (env) => {
67954
- const dirs = ["/usr/bin", "/bin", ...(env.PATH ?? "").split(path38.delimiter).filter(Boolean)];
68022
+ const dirs = ["/usr/bin", "/bin", ...(env.PATH ?? "").split(path39.delimiter).filter(Boolean)];
67955
68023
  for (const dir of dirs) {
67956
- const candidate = path38.join(dir, "bash");
68024
+ const candidate = path39.join(dir, "bash");
67957
68025
  try {
67958
68026
  if (statSync5(candidate).isFile())
67959
68027
  return candidate;
@@ -67962,7 +68030,7 @@ ${[...rules, ...lease, grant].join(`
67962
68030
  return null;
67963
68031
  }, setupCommand = (hosts) => `workit setup --hosts=${hosts.join(",")}`, removeCodexRules = (file, options = {}) => {
67964
68032
  const expected = permissionTarget("codex", options).file;
67965
- if (path38.resolve(file) !== path38.resolve(expected) || !existsSync16(expected))
68033
+ if (path39.resolve(file) !== path39.resolve(expected) || !existsSync16(expected))
67966
68034
  return false;
67967
68035
  rmSync3(expected);
67968
68036
  return true;
@@ -68004,7 +68072,7 @@ ${[...rules, ...lease, grant].join(`
68004
68072
  return patterns;
68005
68073
  }
68006
68074
  for (const name of names)
68007
- for (const m of (readText4(path38.join(dir, name)) ?? "").matchAll(/pattern\s*=\s*(\[[^\]]*\])\s*,\s*decision\s*=\s*"allow"/gu))
68075
+ for (const m of (readText4(path39.join(dir, name)) ?? "").matchAll(/pattern\s*=\s*(\[[^\]]*\])\s*,\s*decision\s*=\s*"allow"/gu))
68008
68076
  try {
68009
68077
  const words = JSON.parse(m[1]);
68010
68078
  if (Array.isArray(words))
@@ -68105,25 +68173,25 @@ import { createHash as createHash14 } from "node:crypto";
68105
68173
  import {
68106
68174
  existsSync as existsSync17,
68107
68175
  lstatSync as lstatSync6,
68108
- mkdirSync as mkdirSync8,
68176
+ mkdirSync as mkdirSync9,
68109
68177
  mkdtempSync,
68110
68178
  readdirSync as readdirSync10,
68111
- readFileSync as readFileSync18,
68179
+ readFileSync as readFileSync19,
68112
68180
  readlinkSync as readlinkSync2,
68113
- renameSync as renameSync4,
68181
+ renameSync as renameSync5,
68114
68182
  rmSync as rmSync4,
68115
68183
  statSync as statSync6,
68116
68184
  unlinkSync as unlinkSync3,
68117
- writeFileSync as writeFileSync9
68185
+ writeFileSync as writeFileSync10
68118
68186
  } from "node:fs";
68119
- import os12 from "node:os";
68120
- import path39 from "node:path";
68187
+ import os13 from "node:os";
68188
+ import path40 from "node:path";
68121
68189
  var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68122
- let dir = path39.resolve(cwd);
68190
+ let dir = path40.resolve(cwd);
68123
68191
  while (true) {
68124
- if (existsSync17(path39.join(dir, "packages", "workit-core", "package.json")))
68192
+ if (existsSync17(path40.join(dir, "packages", "workit-core", "package.json")))
68125
68193
  return dir;
68126
- const parent = path39.dirname(dir);
68194
+ const parent = path40.dirname(dir);
68127
68195
  if (parent === dir)
68128
68196
  return null;
68129
68197
  dir = parent;
@@ -68148,12 +68216,13 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68148
68216
  return found;
68149
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) => {
68150
68218
  const env = options.env ?? process.env;
68151
- const home = options.home ?? env.HOME ?? os12.homedir();
68152
- const configDir = options.configDir ?? env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path39.join(home, ".config", "workit");
68153
- const stateDir = options.stateDir ?? env.WORKFLOW_TOOLKIT_STATE ?? path39.join(home, ".local", "state", "workit");
68219
+ const home = options.home ?? env.HOME ?? os13.homedir();
68220
+ const configDir = options.configDir ?? env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path40.join(home, ".config", "workit");
68221
+ const stateDir = options.stateDir ?? env.WORKFLOW_TOOLKIT_STATE ?? path40.join(home, ".local", "state", "workit");
68154
68222
  const cwd = options.cwd ?? process.cwd();
68155
68223
  const dev = options.dev?.trim() || env.WORKFLOW_TOOLKIT_DEV?.trim() || findDevFromCwd(cwd);
68156
68224
  return {
68225
+ explicitDirs: { config: options.configDir, state: options.stateDir },
68157
68226
  host: options.host ?? "cli",
68158
68227
  home,
68159
68228
  configDir,
@@ -68161,11 +68230,11 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68161
68230
  cwd,
68162
68231
  workspaceRoot: options.workspaceRoot ?? env.WORKFLOW_WORKSPACE_ROOT ?? cwd,
68163
68232
  dev,
68164
- opencodeConfig: options.opencodeConfig ?? path39.join(home, ".config", "opencode", "opencode.json"),
68233
+ opencodeConfig: options.opencodeConfig ?? path40.join(home, ".config", "opencode", "opencode.json"),
68165
68234
  opencodePackageCacheDir: options.opencodePackageCacheDir ?? null,
68166
- cursorSettings: options.cursorSettings ?? path39.join(home, ".cursor", "settings.json"),
68167
- cursorMcp: options.cursorMcp ?? path39.join(home, ".cursor", "mcp.json"),
68168
- cursorPluginDir: options.cursorPluginDir ?? path39.join(home, ".cursor", "plugins", "local", "workit"),
68235
+ cursorSettings: options.cursorSettings ?? path40.join(home, ".cursor", "settings.json"),
68236
+ cursorMcp: options.cursorMcp ?? path40.join(home, ".cursor", "mcp.json"),
68237
+ cursorPluginDir: options.cursorPluginDir ?? path40.join(home, ".cursor", "plugins", "local", "workit"),
68169
68238
  cursorHeartbeatDir: options.stateDir ?? (env.WORKFLOW_TOOLKIT_STATE || resolveStateDir()),
68170
68239
  hookStateDir: options.stateDir ?? (env.WORKFLOW_TOOLKIT_STATE || resolveStateDir()),
68171
68240
  codexHome: options.codexHome,
@@ -68179,14 +68248,14 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68179
68248
  };
68180
68249
  }, readJson = (p) => {
68181
68250
  try {
68182
- const parsed = JSON.parse(readFileSync18(p, "utf8"));
68251
+ const parsed = JSON.parse(readFileSync19(p, "utf8"));
68183
68252
  return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
68184
68253
  } catch {
68185
68254
  return null;
68186
68255
  }
68187
68256
  }, parsesAsConfigObject = (p) => {
68188
68257
  try {
68189
- return isConfigObject(JSON.parse(readFileSync18(p, "utf8")));
68258
+ return isConfigObject(JSON.parse(readFileSync19(p, "utf8")));
68190
68259
  } catch {
68191
68260
  return false;
68192
68261
  }
@@ -68196,12 +68265,12 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68196
68265
  ...new Set(entries.filter((entry) => typeof entry === "string" && isWorkitPlugin(entry)))
68197
68266
  ];
68198
68267
  }, commandOnPath = (name, env) => findOnPath(process.platform === "win32" ? [name, `${name}.exe`] : [name], env) !== null, pathextNames = (name, env) => process.platform === "win32" ? (env.PATHEXT ?? process.env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean).map((ext) => `${name}${ext.toLowerCase()}`) : [name], findOnPath = (names, env) => {
68199
- const dirs = (env.PATH ?? process.env.PATH ?? "").split(path39.delimiter);
68268
+ const dirs = (env.PATH ?? process.env.PATH ?? "").split(path40.delimiter);
68200
68269
  for (const dir of dirs) {
68201
68270
  if (!dir)
68202
68271
  continue;
68203
68272
  for (const candidateName of names) {
68204
- const candidate = path39.join(dir, candidateName);
68273
+ const candidate = path40.join(dir, candidateName);
68205
68274
  try {
68206
68275
  const st = statSync6(candidate);
68207
68276
  if (process.platform !== "win32" && (st.mode & 73) === 0)
@@ -68230,7 +68299,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68230
68299
  if (env.BUN && existsSync17(env.BUN))
68231
68300
  return env.BUN;
68232
68301
  for (const candidate of [
68233
- path39.join(env.HOME || os12.homedir(), ".bun/bin/bun"),
68302
+ path40.join(env.HOME || os13.homedir(), ".bun/bin/bun"),
68234
68303
  "/usr/local/bin/bun",
68235
68304
  "/usr/bin/bun"
68236
68305
  ]) {
@@ -68285,7 +68354,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68285
68354
  detail: "installed package, not a dev checkout — version parity applies to checkouts only"
68286
68355
  };
68287
68356
  }
68288
- const corePkg = readJson(path39.join(res.dev, "packages/workit-core/package.json"));
68357
+ const corePkg = readJson(path40.join(res.dev, "packages/workit-core/package.json"));
68289
68358
  if (!corePkg) {
68290
68359
  return {
68291
68360
  id: "versions",
@@ -68295,7 +68364,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68295
68364
  }
68296
68365
  const refs = new Set;
68297
68366
  for (const name of ["workit-opencode", "workit-cursor", "workit-cli"]) {
68298
- const pkg = readJson(path39.join(res.dev, "packages", name, "package.json"));
68367
+ const pkg = readJson(path40.join(res.dev, "packages", name, "package.json"));
68299
68368
  const dep = pkg?.dependencies?.["@brainervirus/workit-core"] ?? pkg?.devDependencies?.["@brainervirus/workit-core"];
68300
68369
  if (typeof dep === "string")
68301
68370
  refs.add(dep);
@@ -68311,7 +68380,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68311
68380
  if (refs.size > 1) {
68312
68381
  problems.push(`adapters pin different core versions: ${[...refs].join(", ")}`);
68313
68382
  }
68314
- const opencodePkg = readJson(path39.join(res.dev, "packages/workit-opencode/package.json"));
68383
+ const opencodePkg = readJson(path40.join(res.dev, "packages/workit-opencode/package.json"));
68315
68384
  const sdk = opencodePkg?.dependencies?.["@opencode/plugin"] ?? opencodePkg?.devDependencies?.["@opencode/plugin"];
68316
68385
  const sdkVersion = typeof sdk === "string" ? (sdk.match(/^\d+(?:\.\d+){0,2}/) ?? [])[0] : null;
68317
68386
  if (sdkVersion && !semverAtLeast(sdkVersion, SUPPORT_MATRIX.opencode.minimum)) {
@@ -68338,14 +68407,14 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68338
68407
  status: "pass",
68339
68408
  detail: "opencode CLI not on PATH — skipping version check"
68340
68409
  };
68341
- const scratch = mkdtempSync(path39.join(os12.tmpdir(), "workit-doctor-opencode-"));
68410
+ const scratch = mkdtempSync(path40.join(os13.tmpdir(), "workit-doctor-opencode-"));
68342
68411
  let raw;
68343
68412
  try {
68344
68413
  raw = versionOf("opencode", {
68345
68414
  ...res.env,
68346
- XDG_DATA_HOME: path39.join(scratch, "data"),
68347
- XDG_STATE_HOME: path39.join(scratch, "state"),
68348
- XDG_CACHE_HOME: path39.join(scratch, "cache")
68415
+ XDG_DATA_HOME: path40.join(scratch, "data"),
68416
+ XDG_STATE_HOME: path40.join(scratch, "state"),
68417
+ XDG_CACHE_HOME: path40.join(scratch, "cache")
68349
68418
  }, 5000);
68350
68419
  } finally {
68351
68420
  rmSync4(scratch, { recursive: true, force: true });
@@ -68409,7 +68478,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68409
68478
  const tables = new Map;
68410
68479
  let text;
68411
68480
  try {
68412
- text = readFileSync18(file, "utf8");
68481
+ text = readFileSync19(file, "utf8");
68413
68482
  } catch {
68414
68483
  return tables;
68415
68484
  }
@@ -68447,19 +68516,19 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68447
68516
  current[unquote(pair[1])] = value === "true" ? true : value === "false" ? false : unquote(value);
68448
68517
  }
68449
68518
  return tables;
68450
- }, codexHomeOf = (res) => res.codexHome ?? (res.env.CODEX_HOME || path39.join(res.home, ".codex")), codexWorkitInstalls = (res) => {
68519
+ }, codexHomeOf = (res) => res.codexHome ?? (res.env.CODEX_HOME || path40.join(res.home, ".codex")), codexWorkitInstalls = (res) => {
68451
68520
  const codexHome = codexHomeOf(res);
68452
- const configFile = path39.join(codexHome, "config.toml");
68521
+ const configFile = path40.join(codexHome, "config.toml");
68453
68522
  const installs = [];
68454
68523
  for (const [key, table] of readTomlTables(configFile)) {
68455
68524
  const [kind, id, ...rest] = key.split("\x00");
68456
68525
  if (kind !== "plugins" || rest.length > 0 || !id?.startsWith("workit@") || table.enabled === false)
68457
68526
  continue;
68458
68527
  const marketplace = id.slice("workit@".length);
68459
- const dir = path39.join(codexHome, "plugins", "cache", marketplace, "workit");
68528
+ const dir = path40.join(codexHome, "plugins", "cache", marketplace, "workit");
68460
68529
  let versions = [];
68461
68530
  try {
68462
- versions = readdirSync10(dir).filter((v) => existsSync17(path39.join(dir, v, ".codex-plugin")));
68531
+ versions = readdirSync10(dir).filter((v) => existsSync17(path40.join(dir, v, ".codex-plugin")));
68463
68532
  } catch {
68464
68533
  versions = [];
68465
68534
  }
@@ -68467,7 +68536,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68467
68536
  installs.push({
68468
68537
  id,
68469
68538
  marketplace,
68470
- root: version ? path39.join(dir, version) : null,
68539
+ root: version ? path40.join(dir, version) : null,
68471
68540
  version,
68472
68541
  configFile
68473
68542
  });
@@ -68489,7 +68558,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68489
68558
  };
68490
68559
  return `sha256:${createHash14("sha256").update(JSON.stringify(body)).digest("hex")}`;
68491
68560
  }, codexHookTrust = (install, tables) => {
68492
- const hooks = install.root ? readJson(path39.join(install.root, "hooks", "hooks.json"))?.hooks : null;
68561
+ const hooks = install.root ? readJson(path40.join(install.root, "hooks", "hooks.json"))?.hooks : null;
68493
68562
  if (!hooks || typeof hooks !== "object")
68494
68563
  return null;
68495
68564
  const result = [];
@@ -68562,25 +68631,25 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68562
68631
  status: "pass",
68563
68632
  detail: "no Workit Codex plugin enabled — skipping"
68564
68633
  };
68565
- const agentsDir = path39.join(codexHomeOf(res), "agents");
68634
+ const agentsDir = path40.join(codexHomeOf(res), "agents");
68566
68635
  const problems = [];
68567
68636
  const fixes = [];
68568
68637
  const installed = [];
68569
68638
  for (const install of installs) {
68570
- const source = install.root ? path39.join(install.root, "agents") : null;
68639
+ const source = install.root ? path40.join(install.root, "agents") : null;
68571
68640
  const files = source && existsSync17(source) ? readdirSync10(source).filter((f) => f.endsWith(".toml")).toSorted() : [];
68572
68641
  if (files.length === 0) {
68573
68642
  problems.push(`${install.id} ${install.version ?? "?"} bundles no agents`);
68574
68643
  fixes.push(`codex plugin remove ${install.id} && codex plugin add ${install.id}`);
68575
68644
  continue;
68576
68645
  }
68577
- const install_fix = `node ${JSON.stringify(path39.join(install.root, "dist", "launch-mcp.js"))} --install-agents, then start a new Codex session`;
68578
- const pluginVersion = readJson(path39.join(install.root, "package.json"))?.version;
68646
+ const install_fix = `node ${JSON.stringify(path40.join(install.root, "dist", "launch-mcp.js"))} --install-agents, then start a new Codex session`;
68647
+ const pluginVersion = readJson(path40.join(install.root, "package.json"))?.version;
68579
68648
  const version = typeof pluginVersion === "string" ? pluginVersion.match(SEMVER)?.[0] ?? null : null;
68580
68649
  let stale = false;
68581
68650
  for (const file of files) {
68582
- const dest = path39.join(agentsDir, file);
68583
- const want = stampCodexAgent(readFileSync18(path39.join(source, file), "utf8"), version);
68651
+ const dest = path40.join(agentsDir, file);
68652
+ const want = stampCodexAgent(readFileSync19(path40.join(source, file), "utf8"), version);
68584
68653
  let link = false;
68585
68654
  try {
68586
68655
  link = lstatSync6(dest).isSymbolicLink();
@@ -68594,7 +68663,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68594
68663
  }
68595
68664
  let have = null;
68596
68665
  try {
68597
- have = readFileSync18(dest, "utf8");
68666
+ have = readFileSync19(dest, "utf8");
68598
68667
  } catch {
68599
68668
  have = null;
68600
68669
  }
@@ -68633,7 +68702,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68633
68702
  const env = res.env.PI_CODING_AGENT_DIR;
68634
68703
  if (env)
68635
68704
  return env === "~" ? res.home : env.replace(/^~(?=\/|\\)/, res.home);
68636
- return path39.join(res.home, ".pi", "agent");
68705
+ return path40.join(res.home, ".pi", "agent");
68637
68706
  }, npmSpecName = (spec) => {
68638
68707
  const at = spec.indexOf("@", spec.startsWith("@") ? 1 : 0);
68639
68708
  return at > 0 ? { name: spec.slice(0, at), pinned: true } : { name: spec, pinned: false };
@@ -68641,12 +68710,12 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68641
68710
  const scopes = [
68642
68711
  {
68643
68712
  scope: "project",
68644
- settingsFile: path39.join(res.cwd, ".pi", "settings.json"),
68645
- base: path39.join(res.cwd, ".pi")
68713
+ settingsFile: path40.join(res.cwd, ".pi", "settings.json"),
68714
+ base: path40.join(res.cwd, ".pi")
68646
68715
  },
68647
68716
  {
68648
68717
  scope: "user",
68649
- settingsFile: path39.join(agentDir, "settings.json"),
68718
+ settingsFile: path40.join(agentDir, "settings.json"),
68650
68719
  base: agentDir
68651
68720
  }
68652
68721
  ];
@@ -68663,7 +68732,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68663
68732
  const spec = npmSpecName(source.slice(4).trim());
68664
68733
  if (spec.name !== PI_PACKAGE)
68665
68734
  continue;
68666
- const root = path39.join(base, "npm", "node_modules", ...PI_PACKAGE.split("/"));
68735
+ const root = path40.join(base, "npm", "node_modules", ...PI_PACKAGE.split("/"));
68667
68736
  return {
68668
68737
  scope,
68669
68738
  settingsFile,
@@ -68675,8 +68744,8 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68675
68744
  }
68676
68745
  if (/^(git:|https?:|ssh:|git@)/.test(source))
68677
68746
  continue;
68678
- const local = path39.resolve(base, source.replace(/^~(?=\/|\\)/, res.home));
68679
- if (readJson(path39.join(local, "package.json"))?.name === PI_PACKAGE)
68747
+ const local = path40.resolve(base, source.replace(/^~(?=\/|\\)/, res.home));
68748
+ if (readJson(path40.join(local, "package.json"))?.name === PI_PACKAGE)
68680
68749
  return { scope, settingsFile, source, filter, root: local, npm: null };
68681
68750
  }
68682
68751
  }
@@ -68687,7 +68756,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68687
68756
  const list = patterns.filter((p) => typeof p === "string");
68688
68757
  if (list.length === 0)
68689
68758
  return false;
68690
- const name = path39.posix.basename(file);
68759
+ const name = path40.posix.basename(file);
68691
68760
  const matches = (p) => {
68692
68761
  const re = globToRegExp3(p);
68693
68762
  return re.test(file) || re.test(name);
@@ -68716,12 +68785,12 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68716
68785
  return {
68717
68786
  id: "pi_extension",
68718
68787
  status: "warn",
68719
- detail: `Workit Pi extension missing: no ${PI_PACKAGE} entry in ${path39.join(agentDir, "settings.json")} or ${path39.join(res.cwd, ".pi", "settings.json")}`,
68788
+ detail: `Workit Pi extension missing: no ${PI_PACKAGE} entry in ${path40.join(agentDir, "settings.json")} or ${path40.join(res.cwd, ".pi", "settings.json")}`,
68720
68789
  fix: installCmd("user")
68721
68790
  };
68722
68791
  const where = `${entry.source} (${entry.scope}, ${entry.settingsFile})`;
68723
68792
  const rebuild = `cd ${JSON.stringify(entry.root)} && bun run build`;
68724
- const pkg = readJson(path39.join(entry.root, "package.json"));
68793
+ const pkg = readJson(path40.join(entry.root, "package.json"));
68725
68794
  if (!pkg)
68726
68795
  return {
68727
68796
  id: "pi_extension",
@@ -68730,7 +68799,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68730
68799
  fix: entry.npm ? installCmd(entry.scope, entry.source) : `restore ${entry.root}, then ${rebuild}`
68731
68800
  };
68732
68801
  const declared = Array.isArray(pkg.pi?.extensions) ? pkg.pi.extensions.some((e) => typeof e === "string" && e.replace(/^\.\//, "") === PI_EXTENSION) : false;
68733
- if (!declared || !existsSync17(path39.join(entry.root, PI_EXTENSION)))
68802
+ if (!declared || !existsSync17(path40.join(entry.root, PI_EXTENSION)))
68734
68803
  return {
68735
68804
  id: "pi_extension",
68736
68805
  status: "warn",
@@ -68783,21 +68852,21 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68783
68852
  detail: `Workit Pi extension ${version ?? "?"} from ${where} loads ${PI_EXTENSION}`
68784
68853
  };
68785
68854
  }, assetPathsFor = (host, dev) => {
68786
- const pkg = path39.join(dev, "packages", `workit-${host}`);
68855
+ const pkg = path40.join(dev, "packages", `workit-${host}`);
68787
68856
  switch (host) {
68788
68857
  case "opencode": {
68789
- const packaged = path39.join(pkg, "assets", "skills");
68790
- const root = existsSync17(packaged) ? packaged : path39.join(dev, "packages", "workit-core", "skills");
68791
- return WORKIT_METHOD_SKILLS.map((skill) => path39.join(root, skill, "SKILL.md"));
68858
+ const packaged = path40.join(pkg, "assets", "skills");
68859
+ const root = existsSync17(packaged) ? packaged : path40.join(dev, "packages", "workit-core", "skills");
68860
+ return WORKIT_METHOD_SKILLS.map((skill) => path40.join(root, skill, "SKILL.md"));
68792
68861
  }
68793
68862
  case "cursor":
68794
68863
  return [
68795
- path39.join(pkg, "assets", "templates", "workit-contract.md"),
68796
- path39.join(pkg, "mcp.json"),
68797
- path39.join(pkg, ".cursor-plugin")
68864
+ path40.join(pkg, "assets", "templates", "workit-contract.md"),
68865
+ path40.join(pkg, "mcp.json"),
68866
+ path40.join(pkg, ".cursor-plugin")
68798
68867
  ];
68799
68868
  case "cli":
68800
- return [path39.join(pkg, "assets", "templates", "spec-template.md")];
68869
+ return [path40.join(pkg, "assets", "templates", "spec-template.md")];
68801
68870
  }
68802
68871
  }, hostsFor = (host) => host === "cli" ? ["opencode", "cursor", "cli"] : [host], checkAssets = (res) => {
68803
68872
  const dev = res.dev;
@@ -68828,22 +68897,22 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68828
68897
  fix: "Reinstall or rebuild the workit package (missing assets under packages/workit-<host>)"
68829
68898
  };
68830
68899
  }, launcherSlotsFor = (host, dev) => {
68831
- const pkg = path39.join(dev, "packages", `workit-${host}`);
68900
+ const pkg = path40.join(dev, "packages", `workit-${host}`);
68832
68901
  switch (host) {
68833
68902
  case "opencode":
68834
- return [[path39.join(pkg, "src", "plugin.ts"), path39.join(pkg, "dist", "plugin.js")]];
68903
+ return [[path40.join(pkg, "src", "plugin.ts"), path40.join(pkg, "dist", "plugin.js")]];
68835
68904
  case "cursor":
68836
68905
  return [
68837
- [path39.join(pkg, "dist", "mcp-server.js")],
68838
- [path39.join(pkg, "dist", "cursor-session-start.js")]
68906
+ [path40.join(pkg, "dist", "mcp-server.js")],
68907
+ [path40.join(pkg, "dist", "cursor-session-start.js")]
68839
68908
  ];
68840
68909
  case "cli":
68841
- return [[path39.join(pkg, "src", "index.tsx"), path39.join(pkg, "dist", "index.js")]];
68910
+ return [[path40.join(pkg, "src", "index.tsx"), path40.join(pkg, "dist", "index.js")]];
68842
68911
  }
68843
68912
  }, validNodeEntry = (entry, runtime, env) => {
68844
68913
  try {
68845
68914
  const stat = statSync6(entry);
68846
- if (!stat.isFile() || stat.size === 0 || !readFileSync18(entry, "utf8").startsWith(`#!/usr/bin/env node
68915
+ if (!stat.isFile() || stat.size === 0 || !readFileSync19(entry, "utf8").startsWith(`#!/usr/bin/env node
68847
68916
  `)) {
68848
68917
  return false;
68849
68918
  }
@@ -68865,7 +68934,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68865
68934
  if (typeof command !== "string" || !Array.isArray(args) || typeof args[0] !== "string") {
68866
68935
  return "invalid";
68867
68936
  }
68868
- const executable = path39.basename(command).toLowerCase();
68937
+ const executable = path40.basename(command).toLowerCase();
68869
68938
  const canonical = cursorMcpServerEntry("").args;
68870
68939
  if (executable === "npx" || executable === "npx.exe" || executable === "npx.cmd") {
68871
68940
  if (args.length !== canonical.length || args.some((a, i) => a !== canonical[i]))
@@ -68877,10 +68946,10 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68877
68946
  return {
68878
68947
  kind: "node",
68879
68948
  runtime: command,
68880
- entry: path39.isAbsolute(args[0]) ? args[0] : path39.resolve(path39.dirname(res.cursorMcp), args[0])
68949
+ entry: path40.isAbsolute(args[0]) ? args[0] : path40.resolve(path40.dirname(res.cursorMcp), args[0])
68881
68950
  };
68882
68951
  }, canonicalCursorHook, isCanonicalCursorHook = (command, res) => command === canonicalCursorHook || command === cursorHooksEntry(res.cursorPluginDir).command, registeredCursorHook = (res) => {
68883
- const hooksFile = path39.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
68952
+ const hooksFile = path40.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
68884
68953
  if (!existsSync17(hooksFile))
68885
68954
  return "invalid";
68886
68955
  const config = readJson(hooksFile);
@@ -68898,9 +68967,9 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68898
68967
  if (!m)
68899
68968
  return false;
68900
68969
  const entry = m[1].trim();
68901
- if (!path39.isAbsolute(entry))
68970
+ if (!path40.isAbsolute(entry))
68902
68971
  return false;
68903
- if (path39.resolve(entry) !== path39.resolve(path39.join(res.cursorPluginDir, "dist", "cursor-session-start.js"))) {
68972
+ if (path40.resolve(entry) !== path40.resolve(path40.join(res.cursorPluginDir, "dist", "cursor-session-start.js"))) {
68904
68973
  return false;
68905
68974
  }
68906
68975
  return validNodeEntry(entry, "node", res.env);
@@ -68909,7 +68978,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68909
68978
  const hosts = hostsFor(res.host);
68910
68979
  const registered = hosts.includes("cursor") ? registeredCursorLauncher(res) : null;
68911
68980
  const runtime = registered && registered !== "invalid" && registered.kind === "node" ? registered.runtime : "node";
68912
- const missing = hosts.includes("cursor") ? ["dist/mcp-server.js", "dist/cursor-session-start.js"].map((rel) => path39.join(res.cursorPluginDir, rel)).filter((p) => !validNodeEntry(p, runtime, res.env)).map((p) => `cursor: ${p}`) : [];
68981
+ const missing = hosts.includes("cursor") ? ["dist/mcp-server.js", "dist/cursor-session-start.js"].map((rel) => path40.join(res.cursorPluginDir, rel)).filter((p) => !validNodeEntry(p, runtime, res.env)).map((p) => `cursor: ${p}`) : [];
68913
68982
  if (hosts.includes("cursor")) {
68914
68983
  if (registered === "invalid") {
68915
68984
  missing.push(`cursor: canonical workit MCP launcher in ${res.cursorMcp}`);
@@ -68918,9 +68987,9 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68918
68987
  }
68919
68988
  const hook = registeredCursorHook(res);
68920
68989
  if (hook === "invalid") {
68921
- missing.push(`cursor: canonical session-start hook in ${path39.join(res.cursorPluginDir, "hooks", "hooks-cursor.json")}`);
68990
+ missing.push(`cursor: canonical session-start hook in ${path40.join(res.cursorPluginDir, "hooks", "hooks-cursor.json")}`);
68922
68991
  } else if (hook !== null && !isCanonicalCursorHook(hook, res) && !validLocalDistHook(hook, res)) {
68923
- missing.push(`cursor: canonical session-start hook in ${path39.join(res.cursorPluginDir, "hooks", "hooks-cursor.json")} (registered ${hook})`);
68992
+ missing.push(`cursor: canonical session-start hook in ${path40.join(res.cursorPluginDir, "hooks", "hooks-cursor.json")} (registered ${hook})`);
68924
68993
  }
68925
68994
  }
68926
68995
  if (dev) {
@@ -68956,7 +69025,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68956
69025
  const normal = entry.replaceAll("\\", "/").replace(/\/+$/, "");
68957
69026
  if (!normal.endsWith("local/workit") && !normal.endsWith("local/workflow-toolkit"))
68958
69027
  continue;
68959
- const dir = entry.startsWith("~") ? path39.join(res.home, entry.slice(1)) : entry;
69028
+ const dir = entry.startsWith("~") ? path40.join(res.home, entry.slice(1)) : entry;
68960
69029
  let state = null;
68961
69030
  try {
68962
69031
  state = readdirSync10(dir).length === 0 ? "empty" : null;
@@ -69000,7 +69069,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69000
69069
  status: "pass",
69001
69070
  detail: "no Cursor plugin install — hook launcher not inspected"
69002
69071
  };
69003
- const launcher = path39.join(res.cursorPluginDir, "hooks", "launch.mjs");
69072
+ const launcher = path40.join(res.cursorPluginDir, "hooks", "launch.mjs");
69004
69073
  if (!existsSync17(launcher))
69005
69074
  return {
69006
69075
  id: "cursor_hook",
@@ -69008,7 +69077,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69008
69077
  detail: `cursor hook launcher mode: missing — ${launcher} is absent (an install from before the pinned launcher)`,
69009
69078
  fix: CURSOR_HOOK_FIX
69010
69079
  };
69011
- const hooksFile = path39.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
69080
+ const hooksFile = path40.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
69012
69081
  const registered = readJson(hooksFile);
69013
69082
  const sessionCommand = registered?.hooks?.sessionStart?.[0]?.command;
69014
69083
  const offLauncher = [
@@ -69079,10 +69148,10 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69079
69148
  return null;
69080
69149
  }
69081
69150
  }, silentCursorHooks = (res) => {
69082
- const session = mtimeMs(path39.join(res.cursorHeartbeatDir, "cursor-session-last-start"));
69151
+ const session = mtimeMs(path40.join(res.cursorHeartbeatDir, "cursor-session-last-start"));
69083
69152
  if (session === null || Date.now() - session < SILENT_HOOK_GRACE_MS)
69084
69153
  return null;
69085
- const hook = mtimeMs(path39.join(res.cursorHeartbeatDir, "cursor-hook-last-run"));
69154
+ const hook = mtimeMs(path40.join(res.cursorHeartbeatDir, "cursor-hook-last-run"));
69086
69155
  if (hook !== null && hook >= session)
69087
69156
  return null;
69088
69157
  return `Cursor started the Workit MCP server at ${new Date(session).toISOString()} but no Workit hook has run since${hook === null ? " (none ever)" : ""} — if the agent ran in that window, Cursor is not running the plugin hooks and Workit enforcement is off`;
@@ -69186,7 +69255,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69186
69255
  }
69187
69256
  return { id: "stale_pin", status: "pass", detail: "opencode pin resolves" };
69188
69257
  }, pluginMcpSelectors = (res) => {
69189
- const p = path39.join(res.cursorPluginDir, "mcp.json");
69258
+ const p = path40.join(res.cursorPluginDir, "mcp.json");
69190
69259
  if (!existsSync17(p))
69191
69260
  return null;
69192
69261
  const cfg = readJson(p);
@@ -69220,19 +69289,19 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69220
69289
  return null;
69221
69290
  }
69222
69291
  }, installedPluginVersion = (res) => {
69223
- const pkg = readJson(path39.join(res.cursorPluginDir, "package.json"));
69292
+ const pkg = readJson(path40.join(res.cursorPluginDir, "package.json"));
69224
69293
  return typeof pkg?.version === "string" && pkg.version ? pkg.version : null;
69225
69294
  }, installedOpenCodeCache = (res) => {
69226
69295
  if (res.opencodePackageCacheDir !== null) {
69227
- const pkg = readJson(path39.join(res.opencodePackageCacheDir, "node_modules", "@brainervirus", "workit-opencode", "package.json"));
69296
+ const pkg = readJson(path40.join(res.opencodePackageCacheDir, "node_modules", "@brainervirus", "workit-opencode", "package.json"));
69228
69297
  return typeof pkg?.version === "string" && pkg.version ? { version: pkg.version, dir: res.opencodePackageCacheDir } : null;
69229
69298
  }
69230
69299
  const found = openCodeInstalledPlugin(res.home, res.env);
69231
69300
  if (!found)
69232
69301
  return null;
69233
- let dir = path39.dirname(path39.dirname(path39.dirname(found.root)));
69234
- if (path39.basename(dir) !== "workit-opencode@latest")
69235
- dir = path39.dirname(dir);
69302
+ let dir = path40.dirname(path40.dirname(path40.dirname(found.root)));
69303
+ if (path40.basename(dir) !== "workit-opencode@latest")
69304
+ dir = path40.dirname(dir);
69236
69305
  return { version: found.version, dir };
69237
69306
  }, checkOpenCodePackageCache = (res) => {
69238
69307
  if (!existsSync17(res.opencodeConfig)) {
@@ -69336,7 +69405,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69336
69405
  fix: "Re-run install-cursor-plugin.sh — it rewrites the workit MCP entry to the canonical @latest selector"
69337
69406
  };
69338
69407
  }
69339
- const hooksFile = path39.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
69408
+ const hooksFile = path40.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
69340
69409
  const hookCmd = readJson(hooksFile)?.hooks?.sessionStart?.[0]?.command ?? null;
69341
69410
  const canonicalHook = canonicalCursorHook;
69342
69411
  const staleHook = hookCmd !== null && !isCanonicalCursorHook(hookCmd, res) && !hookCmd.startsWith("node ") && hookCmd.includes("@brainervirus/workit-cursor@");
@@ -69358,7 +69427,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69358
69427
  };
69359
69428
  }
69360
69429
  const installed = installedPluginVersion(res);
69361
- const source = res.dev ? readJson(path39.join(res.dev, "packages/workit-cursor/package.json"))?.version ?? null : readJson(path39.join(packageRoot(), "package.json"))?.version ?? null;
69430
+ const source = res.dev ? readJson(path40.join(res.dev, "packages/workit-cursor/package.json"))?.version ?? null : readJson(path40.join(packageRoot(), "package.json"))?.version ?? null;
69362
69431
  const localDist = mcpSelectors === null && hookCmd !== null && !isCanonicalCursorHook(hookCmd, res) && hookCmd.startsWith("node ");
69363
69432
  if (localDist && installed !== null && source !== null && !semverAtLeast(installed, source)) {
69364
69433
  return {
@@ -69370,7 +69439,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69370
69439
  }
69371
69440
  if (localDist && installed !== null && source !== null && res.dev) {
69372
69441
  const entry = /^node\s+(.+)$/.exec((hookCmd ?? "").trim())?.[1]?.trim() ?? "";
69373
- const sourceBundle = entry && path39.isAbsolute(entry) ? path39.join(res.dev, "packages", "workit-cursor", "dist", path39.basename(entry)) : "";
69442
+ const sourceBundle = entry && path40.isAbsolute(entry) ? path40.join(res.dev, "packages", "workit-cursor", "dist", path40.basename(entry)) : "";
69374
69443
  if (entry && sourceBundle) {
69375
69444
  const installedHash = bundleHashOfFile(entry);
69376
69445
  const sourceHash = bundleHashOfFile(sourceBundle);
@@ -69378,7 +69447,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69378
69447
  return {
69379
69448
  id: "stale_install",
69380
69449
  status: "fail",
69381
- detail: `stale_install: installed workit-cursor ${installed} runs different bytes than the current runtime build (${path39.basename(entry)} hash mismatch)`,
69450
+ detail: `stale_install: installed workit-cursor ${installed} runs different bytes than the current runtime build (${path40.basename(entry)} hash mismatch)`,
69382
69451
  fix: "Re-run install-cursor-plugin.sh — it refreshes the plugin directory with the current build"
69383
69452
  };
69384
69453
  }
@@ -69478,7 +69547,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69478
69547
  }, checkMalformedConfig = (res) => {
69479
69548
  const files = [];
69480
69549
  for (const name of ["config.json", "youtrack.json", "vcs.json", "workspaces.json"]) {
69481
- const p = path39.join(res.configDir, name);
69550
+ const p = path40.join(res.configDir, name);
69482
69551
  if (existsSync17(p))
69483
69552
  files.push(p);
69484
69553
  }
@@ -69699,17 +69768,17 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69699
69768
  return { ...installSessionHook(res.cwd, res.env), workspace: workspace.name };
69700
69769
  }, isPlaceholder = (p) => {
69701
69770
  try {
69702
- return readFileSync18(p, "utf8").trim() === TOKEN_PLACEHOLDER2;
69771
+ return readFileSync19(p, "utf8").trim() === TOKEN_PLACEHOLDER2;
69703
69772
  } catch {
69704
69773
  return false;
69705
69774
  }
69706
69775
  }, checkCredentialMetadata = (res) => {
69707
69776
  const tokenPaths = [];
69708
- const youtrackJson = readJson(path39.join(res.configDir, "youtrack.json"));
69777
+ const youtrackJson = readJson(path40.join(res.configDir, "youtrack.json"));
69709
69778
  if (youtrackJson) {
69710
- tokenPaths.push(typeof youtrackJson.tokenFile === "string" ? youtrackJson.tokenFile : path39.join(res.configDir, "youtrack.token"));
69711
- } else if (existsSync17(path39.join(res.configDir, "youtrack.token"))) {
69712
- tokenPaths.push(path39.join(res.configDir, "youtrack.token"));
69779
+ tokenPaths.push(typeof youtrackJson.tokenFile === "string" ? youtrackJson.tokenFile : path40.join(res.configDir, "youtrack.token"));
69780
+ } else if (existsSync17(path40.join(res.configDir, "youtrack.token"))) {
69781
+ tokenPaths.push(path40.join(res.configDir, "youtrack.token"));
69713
69782
  }
69714
69783
  if (tokenPaths.length === 0) {
69715
69784
  return {
@@ -69720,7 +69789,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69720
69789
  }
69721
69790
  const problems = [];
69722
69791
  for (const raw of tokenPaths) {
69723
- const p = path39.isAbsolute(raw) ? raw : path39.resolve(res.configDir, raw);
69792
+ const p = path40.isAbsolute(raw) ? raw : path40.resolve(res.configDir, raw);
69724
69793
  if (!existsSync17(p)) {
69725
69794
  problems.push(`${p} is missing`);
69726
69795
  continue;
@@ -69843,7 +69912,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69843
69912
  status: "pass",
69844
69913
  detail: "no GitHub remote configured"
69845
69914
  };
69846
- const vcsJson = readJson(res.env.WORKFLOW_VCS_CONFIG ?? path39.join(res.configDir, "vcs.json"));
69915
+ const vcsJson = readJson(res.env.WORKFLOW_VCS_CONFIG ?? path40.join(res.configDir, "vcs.json"));
69847
69916
  const workspace = workspaceProviderForIdentity(res.cwd, res.configDir, res.env);
69848
69917
  if (workspace.error)
69849
69918
  return {
@@ -69879,7 +69948,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69879
69948
  status: "pass",
69880
69949
  detail: "no GitLab remote configured"
69881
69950
  };
69882
- const vcsJson = readJson(res.env.WORKFLOW_VCS_CONFIG ?? path39.join(res.configDir, "vcs.json"));
69951
+ const vcsJson = readJson(res.env.WORKFLOW_VCS_CONFIG ?? path40.join(res.configDir, "vcs.json"));
69883
69952
  const workspace = workspaceProviderForIdentity(res.cwd, res.configDir, res.env);
69884
69953
  if (workspace.error)
69885
69954
  return {
@@ -69909,11 +69978,11 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69909
69978
  { surface: "SSH", login: probes.sshLogin(remoteHost) }
69910
69979
  ]);
69911
69980
  }, checkLogWritable = (res) => {
69912
- const logsDir = path39.join(res.stateDir, "logs");
69913
- const probe = path39.join(logsDir, "doctor-probe.tmp");
69981
+ const logsDir = path40.join(res.stateDir, "logs");
69982
+ const probe = path40.join(logsDir, "doctor-probe.tmp");
69914
69983
  try {
69915
- mkdirSync8(logsDir, { recursive: true, mode: 448 });
69916
- writeFileSync9(probe, `{"probe":true}
69984
+ mkdirSync9(logsDir, { recursive: true, mode: 448 });
69985
+ writeFileSync10(probe, `{"probe":true}
69917
69986
  `, { mode: 384 });
69918
69987
  return {
69919
69988
  id: "log_writable",
@@ -69992,7 +70061,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69992
70061
  const counts = { skip: 0, late: 0 };
69993
70062
  let text = "";
69994
70063
  try {
69995
- text = readFileSync18(path39.join(stateDir, HOOK_SKIPS_FILE), "utf8");
70064
+ text = readFileSync19(path40.join(stateDir, HOOK_SKIPS_FILE), "utf8");
69996
70065
  } catch {
69997
70066
  return counts;
69998
70067
  }
@@ -70010,7 +70079,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
70010
70079
  }
70011
70080
  return counts;
70012
70081
  }, checkHookDeadline = (res) => {
70013
- const file = path39.join(res.hookStateDir, HOOK_SKIPS_FILE);
70082
+ const file = path40.join(res.hookStateDir, HOOK_SKIPS_FILE);
70014
70083
  const { skip, late } = countHookSkips(res.hookStateDir, Date.now() - DAY_MS);
70015
70084
  const lateText = late > 0 ? `; ${late} answered past it in full` : "";
70016
70085
  if (skip > 0)
@@ -70048,8 +70117,8 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
70048
70117
  };
70049
70118
  }, checkChecksConfig = (res) => {
70050
70119
  const root = checkRoot(res.cwd);
70051
- const current = existsSync17(path39.join(root, CHECKS_FILE));
70052
- const legacy = existsSync17(path39.join(root, LEGACY_CHECKS_FILE));
70120
+ const current = existsSync17(path40.join(root, CHECKS_FILE));
70121
+ const legacy = existsSync17(path40.join(root, LEGACY_CHECKS_FILE));
70053
70122
  if (!legacy)
70054
70123
  return {
70055
70124
  id: "checks_config",
@@ -70064,8 +70133,8 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
70064
70133
  };
70065
70134
  }, fixChecksConfig = (options = {}) => {
70066
70135
  const root = checkRoot(resolve(options).cwd);
70067
- const from = path39.join(root, LEGACY_CHECKS_FILE);
70068
- const to = path39.join(root, CHECKS_FILE);
70136
+ const from = path40.join(root, LEGACY_CHECKS_FILE);
70137
+ const to = path40.join(root, CHECKS_FILE);
70069
70138
  if (!existsSync17(from))
70070
70139
  return { action: "none", detail: `no ${LEGACY_CHECKS_FILE} at ${root}` };
70071
70140
  if (existsSync17(to))
@@ -70074,7 +70143,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
70074
70143
  detail: `${CHECKS_FILE} already exists; ${LEGACY_CHECKS_FILE} left in place`
70075
70144
  };
70076
70145
  ensureWorkitDir(root);
70077
- renameSync4(from, to);
70146
+ renameSync5(from, to);
70078
70147
  return { action: "moved", detail: `${LEGACY_CHECKS_FILE} -> ${CHECKS_FILE}` };
70079
70148
  }, CLAUDE_PLUGIN_PACKAGE = "@brainervirus/workit-claude-code", versionBehind = (version, latest) => version !== latest && semverAtLeast(latest, version), checkClaudePlugin = (res) => {
70080
70149
  const installs = claudeWorkitInstalls(res.home, res.env, res.cwd);
@@ -70125,7 +70194,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
70125
70194
  status: "info",
70126
70195
  detail: "no Workit Claude Code plugin install recorded — skipping"
70127
70196
  };
70128
- const registry = readJson(path39.join(claudeConfigDir(res.home, res.env), "plugins", "installed_plugins.json"));
70197
+ const registry = readJson(path40.join(claudeConfigDir(res.home, res.env), "plugins", "installed_plugins.json"));
70129
70198
  const recorded = (install) => {
70130
70199
  const entries = registry?.plugins?.[install.id];
70131
70200
  const entry = Array.isArray(entries) ? entries.find((e) => e?.installPath === install.installPath) : null;
@@ -70218,7 +70287,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
70218
70287
  }, HOOK_ISSUED_MARKER = "workit-issued-sessions/3", hookRecordsIssued = (root) => {
70219
70288
  let files;
70220
70289
  try {
70221
- files = readdirSync10(path39.join(root, "dist")).filter((f) => f.endsWith(".js"));
70290
+ files = readdirSync10(path40.join(root, "dist")).filter((f) => f.endsWith(".js"));
70222
70291
  } catch {
70223
70292
  return null;
70224
70293
  }
@@ -70226,7 +70295,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
70226
70295
  return null;
70227
70296
  return files.some((file) => {
70228
70297
  try {
70229
- return readFileSync18(path39.join(root, "dist", file), "utf8").includes(HOOK_ISSUED_MARKER);
70298
+ return readFileSync19(path40.join(root, "dist", file), "utf8").includes(HOOK_ISSUED_MARKER);
70230
70299
  } catch {
70231
70300
  return false;
70232
70301
  }
@@ -70408,6 +70477,16 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
70408
70477
  detail: `${host} rules in ${coverage.file} do not cover ${shown}${coverage.missing.length > 4 ? ", …" : ""}${existsSync17(coverage.file) ? "" : ` (${coverage.file} does not exist yet; \`workit setup\` writes it)`}: agents get a prompt (or an auto-mode denial) on verbs the workspace grants`,
70409
70478
  fix: `workit setup --hosts=${host}`
70410
70479
  };
70480
+ }, checkUpdates = (res) => {
70481
+ const mode = readUpdatesMode(res.env, res.explicitDirs.config);
70482
+ const cache = readUpdateCache(res.env, res.explicitDirs.state);
70483
+ const checked = cache.checkedAt === undefined ? "" : ` (checked ${ago(Math.max(0, Date.now() - cache.checkedAt))})`;
70484
+ const latest = cache.latest ? `latest CLI ${cache.latest}${checked}` : "no latest CLI version cached yet";
70485
+ return {
70486
+ id: "updates",
70487
+ status: "info",
70488
+ detail: `updates: ${mode}; ${latest}${cache.skipped ? `; ${cache.skipped} skipped` : ""}`
70489
+ };
70411
70490
  }, ago = (ms) => {
70412
70491
  const minutes = Math.max(0, Math.round(ms / 60000));
70413
70492
  if (minutes < 1)
@@ -70487,6 +70566,7 @@ var init_doctor = __esm(() => {
70487
70566
  init_skill_manifests();
70488
70567
  init_session_hook();
70489
70568
  init_hook_runs();
70569
+ init_update_settings();
70490
70570
  init_host_permissions();
70491
70571
  OPENCODE_V1_FIX = `OpenCode < ${SUPPORT_MATRIX.opencode.minimum} cannot load Workit (V2 plugin API only): upgrade OpenCode to ${SUPPORT_MATRIX.opencode.minimum}+`;
70492
70572
  AGENT_MARKER_VERSION = /^# Generated by Workit (\d+\.\d+\.\d+)\b/;
@@ -70530,6 +70610,7 @@ var init_doctor = __esm(() => {
70530
70610
  checkGrantEndpoint,
70531
70611
  checkHookRuns,
70532
70612
  checkChecksConfig,
70613
+ checkUpdates,
70533
70614
  checkHostPermissions("claude-code", "claude_permissions"),
70534
70615
  checkHostPermissions("codex", "codex_permissions"),
70535
70616
  checkHostPermissions("cursor", "cursor_permissions"),
@@ -70569,19 +70650,19 @@ import {
70569
70650
  cpSync as cpSync4,
70570
70651
  existsSync as existsSync18,
70571
70652
  lstatSync as lstatSync7,
70572
- mkdirSync as mkdirSync9,
70653
+ mkdirSync as mkdirSync10,
70573
70654
  mkdtempSync as mkdtempSync2,
70574
- readFileSync as readFileSync19,
70655
+ readFileSync as readFileSync20,
70575
70656
  readdirSync as readdirSync11,
70576
70657
  realpathSync as realpathSync9,
70577
- renameSync as renameSync5,
70658
+ renameSync as renameSync6,
70578
70659
  rmSync as rmSync5,
70579
70660
  statSync as statSync7,
70580
- writeFileSync as writeFileSync10
70661
+ writeFileSync as writeFileSync11
70581
70662
  } from "node:fs";
70582
70663
  import { createRequire as createRequire2 } from "node:module";
70583
- import os13 from "node:os";
70584
- import path40 from "node:path";
70664
+ import os14 from "node:os";
70665
+ import path41 from "node:path";
70585
70666
  import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
70586
70667
  function parseList(raw) {
70587
70668
  return raw.split(",").map((s) => s.trim()).filter(Boolean);
@@ -70626,7 +70707,7 @@ function buildSetupPreview(values, opts = {}) {
70626
70707
  const current = readConfigFromDir(state.configDir);
70627
70708
  mutations.push({
70628
70709
  type: "merge-json",
70629
- path: path40.join(state.configDir, "config.json"),
70710
+ path: path41.join(state.configDir, "config.json"),
70630
70711
  value: {
70631
70712
  locale: values.locale,
70632
70713
  localeOptions: current.localeOptions,
@@ -70652,17 +70733,17 @@ function buildSetupPreview(values, opts = {}) {
70652
70733
  if (blocked.length === 0) {
70653
70734
  mutations.push({
70654
70735
  type: "update-workspaces",
70655
- path: path40.join(state.configDir, "workspaces.json"),
70736
+ path: path41.join(state.configDir, "workspaces.json"),
70656
70737
  entries: values.workspaces,
70657
70738
  expectedRevision: diskWorkspaceResult.revision
70658
70739
  });
70659
70740
  }
70660
70741
  }
70661
70742
  if (values.baseUrl.trim()) {
70662
- const ytPath = path40.join(state.configDir, "youtrack.json");
70743
+ const ytPath = path41.join(state.configDir, "youtrack.json");
70663
70744
  const ytExisting = readConfigRecord(ytPath);
70664
70745
  const ytConfigured = configuredTokenPath(ytExisting, "tokenFile");
70665
- const tokenPath = resolveTokenPath(ytConfigured, path40.join(state.configDir, "youtrack.token"), values.tokenPaths?.youtrack);
70746
+ const tokenPath = resolveTokenPath(ytConfigured, path41.join(state.configDir, "youtrack.token"), values.tokenPaths?.youtrack);
70666
70747
  const draft = youtrackDraft(values, tokenPath);
70667
70748
  if (ytConfigured !== null && tokenPath !== ytConfigured) {
70668
70749
  delete draft.tokenFile;
@@ -70690,7 +70771,7 @@ function buildSetupPreview(values, opts = {}) {
70690
70771
  });
70691
70772
  }
70692
70773
  if (values.vcsProvider !== "skip") {
70693
- const vcsPath = path40.join(state.configDir, "vcs.json");
70774
+ const vcsPath = path41.join(state.configDir, "vcs.json");
70694
70775
  mutations.push({
70695
70776
  type: "merge-json",
70696
70777
  path: vcsPath,
@@ -70719,7 +70800,7 @@ function buildSetupPreview(values, opts = {}) {
70719
70800
  mutations.push({
70720
70801
  type: "install-host",
70721
70802
  platform: "cursor",
70722
- path: path40.join(paths.home, ".cursor", "plugins", "local", ".workit-package-bootstrap"),
70803
+ path: path41.join(paths.home, ".cursor", "plugins", "local", ".workit-package-bootstrap"),
70723
70804
  commands
70724
70805
  });
70725
70806
  }
@@ -70732,7 +70813,7 @@ function buildSetupPreview(values, opts = {}) {
70732
70813
  mutations.push({
70733
70814
  type: "install-host",
70734
70815
  platform,
70735
- path: platform === "claude-code" ? claudeInstallRecord(paths.home, env) : platform === "codex" ? path40.join(env.CODEX_HOME ?? path40.join(paths.home, ".codex"), "plugins", "cache", "workflow-toolkit", "workit") : path40.join(env.PI_CODING_AGENT_DIR ?? path40.join(paths.home, ".pi", "agent"), "settings.json"),
70816
+ path: platform === "claude-code" ? claudeInstallRecord(paths.home, env) : platform === "codex" ? path41.join(env.CODEX_HOME ?? path41.join(paths.home, ".codex"), "plugins", "cache", "workflow-toolkit", "workit") : path41.join(env.PI_CODING_AGENT_DIR ?? path41.join(paths.home, ".pi", "agent"), "settings.json"),
70736
70817
  commands
70737
70818
  });
70738
70819
  }
@@ -70744,8 +70825,8 @@ function buildSetupPreview(values, opts = {}) {
70744
70825
  projectRefused = target.refused;
70745
70826
  if (target?.ok) {
70746
70827
  const root = target.root;
70747
- const gitignorePath = path40.join(root, ".gitignore");
70748
- const existing = existsSync18(gitignorePath) ? readFileSync19(gitignorePath, "utf8") : "";
70828
+ const gitignorePath = path41.join(root, ".gitignore");
70829
+ const existing = existsSync18(gitignorePath) ? readFileSync20(gitignorePath, "utf8") : "";
70749
70830
  const existingLines = new Set(existing.split(`
70750
70831
  `).map((l) => l.trim()).filter(Boolean));
70751
70832
  const entries = GITIGNORE_ENTRIES.filter((e) => e.trim() !== "" && !existingLines.has(e.trim()));
@@ -70782,10 +70863,10 @@ function deepMerge(base, patch) {
70782
70863
  return out;
70783
70864
  }
70784
70865
  function applyMutation(m) {
70785
- const dir = path40.dirname(m.path);
70866
+ const dir = path41.dirname(m.path);
70786
70867
  switch (m.type) {
70787
70868
  case "create-file": {
70788
- mkdirSync9(dir, { recursive: true });
70869
+ mkdirSync10(dir, { recursive: true });
70789
70870
  const res = writeFileExclusive(m.path, m.content, m.mode);
70790
70871
  return res === "created" ? { platform: "core", file: m.path, status: "Installed" } : {
70791
70872
  platform: "core",
@@ -70808,8 +70889,8 @@ function applyMutation(m) {
70808
70889
  if (existing.kind === "record" && JSON.stringify(existing.value) === JSON.stringify(merged)) {
70809
70890
  return { platform: "core", file: m.path, status: "Skipped", detail: "already configured" };
70810
70891
  }
70811
- mkdirSync9(dir, { recursive: true });
70812
- writeFileSync10(m.path, JSON.stringify(merged, null, 2) + `
70892
+ mkdirSync10(dir, { recursive: true });
70893
+ writeFileSync11(m.path, JSON.stringify(merged, null, 2) + `
70813
70894
  `, "utf8");
70814
70895
  return existing.kind === "record" ? { platform: "core", file: m.path, status: "Configured" } : { platform: "core", file: m.path, status: "Installed" };
70815
70896
  }
@@ -70850,10 +70931,10 @@ function applyMutation(m) {
70850
70931
  `;
70851
70932
  if (prev === next)
70852
70933
  return { platform: "core", file: m.path, status: "Skipped", detail: "already configured" };
70853
- mkdirSync9(dir, { recursive: true });
70934
+ mkdirSync10(dir, { recursive: true });
70854
70935
  const tmp = `${m.path}.${process.pid}.tmp`;
70855
70936
  try {
70856
- writeFileSync10(tmp, next, "utf8");
70937
+ writeFileSync11(tmp, next, "utf8");
70857
70938
  if (workspacesRevision(readFileSafe(m.path)) !== m.expectedRevision) {
70858
70939
  rmSync5(tmp, { force: true });
70859
70940
  return {
@@ -70863,7 +70944,7 @@ function applyMutation(m) {
70863
70944
  detail: "workspace config changed while applying the preview; rebuild and review it"
70864
70945
  };
70865
70946
  }
70866
- renameSync5(tmp, m.path);
70947
+ renameSync6(tmp, m.path);
70867
70948
  } catch (error) {
70868
70949
  rmSync5(tmp, { force: true });
70869
70950
  return {
@@ -70888,11 +70969,11 @@ function applyMutation(m) {
70888
70969
  detail: "all entries already present"
70889
70970
  };
70890
70971
  }
70891
- mkdirSync9(dir, { recursive: true });
70972
+ mkdirSync10(dir, { recursive: true });
70892
70973
  const separator = existing && !existing.endsWith(`
70893
70974
  `) ? `
70894
70975
  ` : "";
70895
- writeFileSync10(m.path, existing + separator + (existing ? `
70976
+ writeFileSync11(m.path, existing + separator + (existing ? `
70896
70977
  ` : "") + add.join(`
70897
70978
  `) + `
70898
70979
  `, "utf8");
@@ -70931,8 +71012,8 @@ function applyMutation(m) {
70931
71012
  detail: "already configured"
70932
71013
  };
70933
71014
  }
70934
- mkdirSync9(path40.dirname(m.path), { recursive: true });
70935
- writeFileSync10(m.path, JSON.stringify(merged, null, 2) + `
71015
+ mkdirSync10(path41.dirname(m.path), { recursive: true });
71016
+ writeFileSync11(m.path, JSON.stringify(merged, null, 2) + `
70936
71017
  `, "utf8");
70937
71018
  return existing.kind === "record" ? { platform: "core", file: m.path, status: "Configured" } : { platform: "core", file: m.path, status: "Installed" };
70938
71019
  }
@@ -70940,11 +71021,11 @@ function applyMutation(m) {
70940
71021
  }
70941
71022
  function adapterRoot(platform, res, preferInstalledAdapter = false) {
70942
71023
  const candidates = [];
70943
- const stagedCursor = path40.join(res.home, ".cursor", "plugins", "local", ".workit-package-bootstrap", "node_modules", "@brainervirus", "workit-cursor");
71024
+ const stagedCursor = path41.join(res.home, ".cursor", "plugins", "local", ".workit-package-bootstrap", "node_modules", "@brainervirus", "workit-cursor");
70944
71025
  if (platform === "cursor" && preferInstalledAdapter)
70945
71026
  candidates.push(stagedCursor);
70946
71027
  if (res.dev) {
70947
- candidates.push(path40.join(res.dev, "packages", `workit-${platform}`));
71028
+ candidates.push(path41.join(res.dev, "packages", `workit-${platform}`));
70948
71029
  } else {
70949
71030
  candidates.push(...nodeResolvedAdapters(platform));
70950
71031
  if (platform === "cursor")
@@ -70954,10 +71035,10 @@ function adapterRoot(platform, res, preferInstalledAdapter = false) {
70954
71035
  if (cached)
70955
71036
  candidates.push(cached.root);
70956
71037
  }
70957
- let dir = path40.resolve(res.cwd);
71038
+ let dir = path41.resolve(res.cwd);
70958
71039
  while (true) {
70959
- candidates.push(path40.join(dir, "packages", `workit-${platform}`));
70960
- const parent = path40.dirname(dir);
71040
+ candidates.push(path41.join(dir, "packages", `workit-${platform}`));
71041
+ const parent = path41.dirname(dir);
70961
71042
  if (parent === dir)
70962
71043
  break;
70963
71044
  dir = parent;
@@ -70979,7 +71060,7 @@ function applyOpenCode(root, res) {
70979
71060
  detail: "workit-opencode package has no loadable plugin entry (src/plugin.ts or dist/plugin.js)"
70980
71061
  };
70981
71062
  }
70982
- mkdirSync9(path40.dirname(res.opencodeConfig), { recursive: true });
71063
+ mkdirSync10(path41.dirname(res.opencodeConfig), { recursive: true });
70983
71064
  const existing = readExisting(res.opencodeConfig);
70984
71065
  if (existing.kind === "malformed") {
70985
71066
  return {
@@ -71004,7 +71085,7 @@ function applyOpenCode(root, res) {
71004
71085
  detail: "already registered"
71005
71086
  };
71006
71087
  }
71007
- writeFileSync10(res.opencodeConfig, JSON.stringify(merged.config, null, 2) + `
71088
+ writeFileSync11(res.opencodeConfig, JSON.stringify(merged.config, null, 2) + `
71008
71089
  `, "utf8");
71009
71090
  return existing.kind === "record" ? {
71010
71091
  platform: "opencode",
@@ -71020,31 +71101,31 @@ function applyOpenCode(root, res) {
71020
71101
  }
71021
71102
  function copyPluginDir(src, dest) {
71022
71103
  const realSrc = realpathSync9(src);
71023
- const marker = path40.join(dest, ".workit-root");
71104
+ const marker = path41.join(dest, ".workit-root");
71024
71105
  const destIsLink = existsSync18(dest) && lstatSync7(dest).isSymbolicLink();
71025
71106
  const synced = !destIsLink && readFileSafe(marker)?.trim() === realSrc && samePluginContent(realSrc, dest, dest);
71026
71107
  if (synced)
71027
71108
  return "Skipped";
71028
71109
  const hadDir = existsSync18(dest);
71029
71110
  const rules = preservedCursorRules(realSrc, dest);
71030
- const parent = path40.dirname(dest);
71031
- mkdirSync9(parent, { recursive: true });
71032
- const swap = mkdtempSync2(path40.join(parent, `.${path40.basename(dest)}.swap-`));
71033
- const stage = path40.join(swap, "stage");
71034
- const backup = path40.join(swap, "backup");
71111
+ const parent = path41.dirname(dest);
71112
+ mkdirSync10(parent, { recursive: true });
71113
+ const swap = mkdtempSync2(path41.join(parent, `.${path41.basename(dest)}.swap-`));
71114
+ const stage = path41.join(swap, "stage");
71115
+ const backup = path41.join(swap, "backup");
71035
71116
  try {
71036
71117
  cpSync4(realSrc, stage, {
71037
71118
  recursive: true,
71038
- filter: (entry) => !path40.relative(realSrc, entry).split(path40.sep).includes("node_modules")
71119
+ filter: (entry) => !path41.relative(realSrc, entry).split(path41.sep).includes("node_modules")
71039
71120
  });
71040
- const stagedHooks = path40.join(stage, CURSOR_HOOKS_FILE);
71121
+ const stagedHooks = path41.join(stage, CURSOR_HOOKS_FILE);
71041
71122
  if (existsSync18(stagedHooks))
71042
- writeFileSync10(stagedHooks, localizedCursorHooks(readFileSync19(stagedHooks), dest));
71123
+ writeFileSync11(stagedHooks, localizedCursorHooks(readFileSync20(stagedHooks), dest));
71043
71124
  for (const [name, content] of rules) {
71044
- mkdirSync9(path40.join(stage, "rules"), { recursive: true });
71045
- writeFileSync10(path40.join(stage, "rules", name), content);
71125
+ mkdirSync10(path41.join(stage, "rules"), { recursive: true });
71126
+ writeFileSync11(path41.join(stage, "rules", name), content);
71046
71127
  }
71047
- writeFileSync10(path40.join(stage, ".workit-root"), realSrc + `
71128
+ writeFileSync11(path41.join(stage, ".workit-root"), realSrc + `
71048
71129
  `, "utf8");
71049
71130
  if (!samePluginContent(realSrc, stage, dest))
71050
71131
  throw new Error("staged adapter content is incomplete");
@@ -71052,12 +71133,12 @@ function copyPluginDir(src, dest) {
71052
71133
  throw new Error("staged adapter resolved to a symlink — refusing fragile cache install");
71053
71134
  }
71054
71135
  if (hadDir)
71055
- renameSync5(dest, backup);
71136
+ renameSync6(dest, backup);
71056
71137
  try {
71057
- renameSync5(stage, dest);
71138
+ renameSync6(stage, dest);
71058
71139
  } catch (error) {
71059
71140
  if (hadDir && !existsSync18(dest))
71060
- renameSync5(backup, dest);
71141
+ renameSync6(backup, dest);
71061
71142
  throw error;
71062
71143
  }
71063
71144
  rmSync5(backup, { recursive: true, force: true });
@@ -71067,7 +71148,7 @@ function copyPluginDir(src, dest) {
71067
71148
  return hadDir ? "Configured" : "Installed";
71068
71149
  }
71069
71150
  function applyCursorSettings(root, res) {
71070
- mkdirSync9(path40.dirname(res.cursorSettings), { recursive: true });
71151
+ mkdirSync10(path41.dirname(res.cursorSettings), { recursive: true });
71071
71152
  const settingsExisting = readExisting(res.cursorSettings);
71072
71153
  if (settingsExisting.kind === "malformed") {
71073
71154
  return {
@@ -71086,7 +71167,7 @@ function applyCursorSettings(root, res) {
71086
71167
  detail: "already registered"
71087
71168
  };
71088
71169
  }
71089
- writeFileSync10(res.cursorSettings, JSON.stringify(settings.config, null, 2) + `
71170
+ writeFileSync11(res.cursorSettings, JSON.stringify(settings.config, null, 2) + `
71090
71171
  `, "utf8");
71091
71172
  return {
71092
71173
  platform: "cursor",
@@ -71095,7 +71176,7 @@ function applyCursorSettings(root, res) {
71095
71176
  };
71096
71177
  }
71097
71178
  function applyCursorMcp(root, res) {
71098
- mkdirSync9(path40.dirname(res.cursorMcp), { recursive: true });
71179
+ mkdirSync10(path41.dirname(res.cursorMcp), { recursive: true });
71099
71180
  const mcpExisting = readExisting(res.cursorMcp);
71100
71181
  if (mcpExisting.kind === "malformed") {
71101
71182
  return {
@@ -71125,7 +71206,7 @@ function applyCursorMcp(root, res) {
71125
71206
  detail: "already registered"
71126
71207
  };
71127
71208
  }
71128
- writeFileSync10(res.cursorMcp, JSON.stringify(mcp.config, null, 2) + `
71209
+ writeFileSync11(res.cursorMcp, JSON.stringify(mcp.config, null, 2) + `
71129
71210
  `, "utf8");
71130
71211
  return {
71131
71212
  platform: "cursor",
@@ -71201,7 +71282,7 @@ function applySetupPreview(preview, options = {}) {
71201
71282
  let cursorCopyOk = false;
71202
71283
  for (const mutation of preview.mutations) {
71203
71284
  if (mutation.type === "install-host") {
71204
- const expectedPath = mutation.platform === "cursor" ? path40.join(res.home, ".cursor", "plugins", "local", ".workit-package-bootstrap") : mutation.platform === "codex" ? path40.join(res.env.CODEX_HOME ?? path40.join(res.home, ".codex"), "plugins", "cache", "workflow-toolkit", "workit") : mutation.platform === "pi" ? path40.join(res.env.PI_CODING_AGENT_DIR ?? path40.join(res.home, ".pi", "agent"), "settings.json") : mutation.platform === "claude-code" ? claudeInstallRecord(res.home, res.env) : "";
71285
+ const expectedPath = mutation.platform === "cursor" ? path41.join(res.home, ".cursor", "plugins", "local", ".workit-package-bootstrap") : mutation.platform === "codex" ? path41.join(res.env.CODEX_HOME ?? path41.join(res.home, ".codex"), "plugins", "cache", "workflow-toolkit", "workit") : mutation.platform === "pi" ? path41.join(res.env.PI_CODING_AGENT_DIR ?? path41.join(res.home, ".pi", "agent"), "settings.json") : mutation.platform === "claude-code" ? claudeInstallRecord(res.home, res.env) : "";
71205
71286
  if (mutation.path !== expectedPath) {
71206
71287
  entries.push({
71207
71288
  platform: mutation.platform,
@@ -71313,7 +71394,7 @@ function applySetupPreview(preview, options = {}) {
71313
71394
  if (preview.projectRefused) {
71314
71395
  entries.push({
71315
71396
  platform: "core",
71316
- file: path40.resolve(res.cwd),
71397
+ file: path41.resolve(res.cwd),
71317
71398
  status: "Skipped",
71318
71399
  detail: preview.projectRefused
71319
71400
  });
@@ -71394,28 +71475,28 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
71394
71475
  return configured ?? fallback;
71395
71476
  }, readConfigRecord = (file) => {
71396
71477
  try {
71397
- const value = JSON.parse(readFileSync19(file, "utf8"));
71478
+ const value = JSON.parse(readFileSync20(file, "utf8"));
71398
71479
  return isRecord6(value) ? value : null;
71399
71480
  } catch {
71400
71481
  return null;
71401
71482
  }
71402
- }, claudeInstallRecord = (home, env) => path40.join(claudeConfigDir(home, env), "plugins", "installed_plugins.json"), resolveSetupPaths = (options, resolvedConfigDir) => {
71483
+ }, claudeInstallRecord = (home, env) => path41.join(claudeConfigDir(home, env), "plugins", "installed_plugins.json"), resolveSetupPaths = (options, resolvedConfigDir) => {
71403
71484
  const env = options.env ?? process.env;
71404
- const home = options.home ?? env.HOME ?? os13.homedir();
71485
+ const home = options.home ?? env.HOME ?? os14.homedir();
71405
71486
  return {
71406
71487
  home,
71407
71488
  configDir: resolvedConfigDir,
71408
71489
  cwd: options.cwd ?? process.cwd(),
71409
71490
  env,
71410
- opencodeConfig: options.opencodeConfig ?? path40.join(home, ".config", "opencode", "opencode.json"),
71411
- cursorSettings: options.cursorSettings ?? path40.join(home, ".cursor", "settings.json"),
71412
- cursorMcp: options.cursorMcp ?? path40.join(home, ".cursor", "mcp.json"),
71413
- cursorPluginDir: options.cursorPluginDir ?? path40.join(home, ".cursor", "plugins", "local", "workit")
71491
+ opencodeConfig: options.opencodeConfig ?? path41.join(home, ".config", "opencode", "opencode.json"),
71492
+ cursorSettings: options.cursorSettings ?? path41.join(home, ".cursor", "settings.json"),
71493
+ cursorMcp: options.cursorMcp ?? path41.join(home, ".cursor", "mcp.json"),
71494
+ cursorPluginDir: options.cursorPluginDir ?? path41.join(home, ".cursor", "plugins", "local", "workit")
71414
71495
  };
71415
71496
  }, isRecord6 = (v) => v !== null && typeof v === "object" && !Array.isArray(v), readExisting = (p) => {
71416
71497
  let raw;
71417
71498
  try {
71418
- raw = readFileSync19(p, "utf8");
71499
+ raw = readFileSync20(p, "utf8");
71419
71500
  } catch {
71420
71501
  if (existsSync18(p))
71421
71502
  return { kind: "malformed", error: `${p} is not readable` };
@@ -71432,7 +71513,7 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
71432
71513
  return { kind: "malformed", error: `${p} is not a JSON object` };
71433
71514
  }, readFileSafe = (p) => {
71434
71515
  try {
71435
- return readFileSync19(p, "utf8");
71516
+ return readFileSync20(p, "utf8");
71436
71517
  } catch {
71437
71518
  return null;
71438
71519
  }
@@ -71447,15 +71528,15 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
71447
71528
  }
71448
71529
  }, isAdapter = (root, platform) => {
71449
71530
  try {
71450
- const pkg = JSON.parse(readFileSync19(path40.join(root, "package.json"), "utf8"));
71531
+ const pkg = JSON.parse(readFileSync20(path41.join(root, "package.json"), "utf8"));
71451
71532
  return pkg.name === `@brainervirus/workit-${platform}`;
71452
71533
  } catch {
71453
71534
  return false;
71454
71535
  }
71455
71536
  }, nodeResolvedAdapters = (platform) => {
71456
71537
  const name = `@brainervirus/workit-${platform}`;
71457
- const require2 = createRequire2(path40.join(packageRoot(), "package.json"));
71458
- return (require2.resolve.paths(name) ?? []).map((dir) => path40.join(dir, name));
71538
+ const require2 = createRequire2(path41.join(packageRoot(), "package.json"));
71539
+ return (require2.resolve.paths(name) ?? []).map((dir) => path41.join(dir, name));
71459
71540
  }, realRoot = (root) => {
71460
71541
  try {
71461
71542
  return realpathSync9(root);
@@ -71471,7 +71552,7 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
71471
71552
  if (!isDevOpenCodeAdapterRoot(root, opts.dev))
71472
71553
  return OPENCODE_NPM_PIN;
71473
71554
  for (const rel of ["src/plugin.ts", "dist/plugin.js"]) {
71474
- const entry = path40.join(root, rel);
71555
+ const entry = path41.join(root, rel);
71475
71556
  if (existsSync18(entry))
71476
71557
  return `file://${entry}`;
71477
71558
  }
@@ -71489,22 +71570,22 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
71489
71570
  for (const entry of readdirSync11(src, { withFileTypes: true })) {
71490
71571
  if (entry.name === "node_modules")
71491
71572
  continue;
71492
- const source = path40.join(src, entry.name);
71493
- const installed = path40.join(dest, entry.name);
71494
- const rel = path40.join(relative, entry.name);
71573
+ const source = path41.join(src, entry.name);
71574
+ const installed = path41.join(dest, entry.name);
71575
+ const rel = path41.join(relative, entry.name);
71495
71576
  if (entry.isDirectory()) {
71496
71577
  if (!statSync7(installed).isDirectory() || !samePluginContent(source, installed, pluginDir, rel))
71497
71578
  return false;
71498
71579
  } else {
71499
- const expected = rel === CURSOR_HOOKS_FILE ? localizedCursorHooks(readFileSync19(source), pluginDir) : readFileSync19(source);
71500
- if (!expected.equals(readFileSync19(installed)))
71580
+ const expected = rel === CURSOR_HOOKS_FILE ? localizedCursorHooks(readFileSync20(source), pluginDir) : readFileSync20(source);
71581
+ if (!expected.equals(readFileSync20(installed)))
71501
71582
  return false;
71502
71583
  }
71503
71584
  }
71504
71585
  for (const entry of readdirSync11(dest, { withFileTypes: true })) {
71505
- if (existsSync18(path40.join(src, entry.name)))
71586
+ if (existsSync18(path41.join(src, entry.name)))
71506
71587
  continue;
71507
- const rel = path40.join(relative, entry.name);
71588
+ const rel = path41.join(relative, entry.name);
71508
71589
  if (rel === ".workit-root")
71509
71590
  continue;
71510
71591
  if (relative === "rules" && entry.isFile() && entry.name.endsWith(".mdc"))
@@ -71517,32 +71598,32 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
71517
71598
  }
71518
71599
  }, preservedCursorRules = (src, dest) => {
71519
71600
  const preserved = new Map;
71520
- const sourceRules = path40.join(src, "rules");
71521
- const installedRules = path40.join(dest, "rules");
71601
+ const sourceRules = path41.join(src, "rules");
71602
+ const installedRules = path41.join(dest, "rules");
71522
71603
  try {
71523
71604
  for (const entry of readdirSync11(installedRules, { withFileTypes: true })) {
71524
71605
  if (!entry.isFile() || !entry.name.endsWith(".mdc"))
71525
71606
  continue;
71526
- if (existsSync18(path40.join(sourceRules, entry.name)))
71607
+ if (existsSync18(path41.join(sourceRules, entry.name)))
71527
71608
  continue;
71528
- preserved.set(entry.name, readFileSync19(path40.join(installedRules, entry.name)));
71609
+ preserved.set(entry.name, readFileSync20(path41.join(installedRules, entry.name)));
71529
71610
  }
71530
71611
  } catch {}
71531
71612
  return preserved;
71532
71613
  }, removeLegacyCursorDir = (res) => {
71533
- const legacy = path40.join(res.home, ".cursor", "plugins", "local", "workflow-toolkit");
71614
+ const legacy = path41.join(res.home, ".cursor", "plugins", "local", "workflow-toolkit");
71534
71615
  if (legacy === res.cursorPluginDir || !existsSync18(legacy))
71535
71616
  return;
71536
- const legacyRules = path40.join(legacy, "rules");
71617
+ const legacyRules = path41.join(legacy, "rules");
71537
71618
  if (existsSync18(legacyRules)) {
71538
71619
  try {
71539
- mkdirSync9(path40.join(res.cursorPluginDir, "rules"), { recursive: true });
71620
+ mkdirSync10(path41.join(res.cursorPluginDir, "rules"), { recursive: true });
71540
71621
  for (const entry of readdirSync11(legacyRules, { withFileTypes: true })) {
71541
71622
  if (!entry.isFile() || !entry.name.endsWith(".mdc"))
71542
71623
  continue;
71543
- const target = path40.join(res.cursorPluginDir, "rules", entry.name);
71624
+ const target = path41.join(res.cursorPluginDir, "rules", entry.name);
71544
71625
  if (!existsSync18(target))
71545
- copyFileSync5(path40.join(legacyRules, entry.name), target);
71626
+ copyFileSync5(path41.join(legacyRules, entry.name), target);
71546
71627
  }
71547
71628
  } catch {}
71548
71629
  }
@@ -71576,16 +71657,16 @@ var init_setup = __esm(() => {
71576
71657
  { envKey: "WORKFLOW_GITHUB_HOST", affects: "vcs.json github.host" }
71577
71658
  ];
71578
71659
  SETUP_OVERRIDES = [...YT_OVERRIDES, ...VCS_OVERRIDES];
71579
- CURSOR_HOOKS_FILE = path40.join("hooks", "hooks-cursor.json");
71660
+ CURSOR_HOOKS_FILE = path41.join("hooks", "hooks-cursor.json");
71580
71661
  });
71581
71662
 
71582
71663
  // packages/workit-core/src/core/workspace-branch-policy.ts
71583
- import { mkdirSync as mkdirSync10, readFileSync as readFileSync20, renameSync as renameSync6, rmSync as rmSync6, writeFileSync as writeFileSync11 } from "node:fs";
71584
- import path41 from "node:path";
71664
+ import { mkdirSync as mkdirSync11, readFileSync as readFileSync21, renameSync as renameSync7, rmSync as rmSync6, writeFileSync as writeFileSync12 } from "node:fs";
71665
+ import path42 from "node:path";
71585
71666
  import { isDeepStrictEqual as isDeepStrictEqual3 } from "node:util";
71586
71667
  function applyWorkspaceBranchPolicy(opts) {
71587
71668
  const { workspace_root, env = process.env } = opts;
71588
- const dir = path41.join(env.WORKFLOW_TOOLKIT_CONFIG ?? configDir());
71669
+ const dir = path42.join(env.WORKFLOW_TOOLKIT_CONFIG ?? configDir());
71589
71670
  const {
71590
71671
  status,
71591
71672
  path: wsPath,
@@ -71597,7 +71678,7 @@ function applyWorkspaceBranchPolicy(opts) {
71597
71678
  if (status === "malformed" || status === "invalid")
71598
71679
  return { ok: false, error: workspacesError ?? `invalid workspaces.json: ${wsPath}` };
71599
71680
  const detection = detectBranchPolicy(workspace_root);
71600
- const name = String(env.WORKFLOW_BP_NAME ?? path41.basename(workspace_root));
71681
+ const name = String(env.WORKFLOW_BP_NAME ?? path42.basename(workspace_root));
71601
71682
  const integration = env.WORKFLOW_BP_INTEGRATION ?? detection.integration;
71602
71683
  const policy = {
71603
71684
  preset: detection.preset,
@@ -71646,10 +71727,10 @@ function applyWorkspaceBranchPolicy(opts) {
71646
71727
  ok: false,
71647
71728
  error: `workspaces.json changed while applying the branch policy: ${wsPath}`
71648
71729
  };
71649
- mkdirSync10(path41.dirname(wsPath), { recursive: true });
71730
+ mkdirSync11(path42.dirname(wsPath), { recursive: true });
71650
71731
  const tmp = `${wsPath}.${process.pid}.tmp`;
71651
71732
  try {
71652
- writeFileSync11(tmp, JSON.stringify({ ...document2, workspaces: next }, null, 2) + `
71733
+ writeFileSync12(tmp, JSON.stringify({ ...document2, workspaces: next }, null, 2) + `
71653
71734
  `, "utf8");
71654
71735
  if (workspacesRevision(readFileSafe2(wsPath)) !== revision) {
71655
71736
  rmSync6(tmp, { force: true });
@@ -71658,7 +71739,7 @@ function applyWorkspaceBranchPolicy(opts) {
71658
71739
  error: `workspaces.json changed while applying the branch policy: ${wsPath}`
71659
71740
  };
71660
71741
  }
71661
- renameSync6(tmp, wsPath);
71742
+ renameSync7(tmp, wsPath);
71662
71743
  } catch (error) {
71663
71744
  try {
71664
71745
  rmSync6(tmp, { force: true });
@@ -71678,7 +71759,7 @@ function applyWorkspaceBranchPolicy(opts) {
71678
71759
  }
71679
71760
  var readFileSafe2 = (p) => {
71680
71761
  try {
71681
- return readFileSync20(p, "utf8");
71762
+ return readFileSync21(p, "utf8");
71682
71763
  } catch {
71683
71764
  return null;
71684
71765
  }
@@ -71931,7 +72012,7 @@ var init_logic = __esm(() => {
71931
72012
 
71932
72013
  // packages/workit-cli/src/wizard-state.ts
71933
72014
  import { existsSync as existsSync19, statSync as statSync8 } from "node:fs";
71934
- import path42 from "node:path";
72015
+ import path43 from "node:path";
71935
72016
  import { isDeepStrictEqual as isDeepStrictEqual4 } from "node:util";
71936
72017
  function resolveBasePath(values, env = process.env) {
71937
72018
  return env.WORKFLOW_WORKSPACE_ROOT?.trim() || values.basePath.trim();
@@ -72458,8 +72539,8 @@ var NEXT, PREV, skipsCustomBranch = (screen, preset) => (screen === "branchAllow
72458
72539
  const p = value.trim();
72459
72540
  if (!p)
72460
72541
  return "workspace root path is required";
72461
- return !path42.isAbsolute(p) || !isDirectory(p) ? `invalid workspace root "${p}" — enter an existing absolute directory` : null;
72462
- }, skipsBranchPolicy = (screen, basePath) => (screen === "branchPolicy" || screen === "branchPolicyDevelop") && !existsSync19(path42.join(basePath, ".git")), decodeBranchPreset = (value, fallback) => value === "gitflow" || value === "github-flow" || value === "trunk-based" || value === "custom" ? value : fallback, decodeVcsProvider = (value, fallback) => value === "gitlab" || value === "github" || value === "skip" ? value : fallback, decodeIssueTracker = (value, fallback) => value === "youtrack" || value === "github" || value === "gitlab" || value === "none" ? value : fallback, GITHUB_ISSUES, withGithubIssues = (draft, tracker) => tracker === "github" ? { ...draft, issues: { ...GITHUB_ISSUES } } : draft;
72542
+ return !path43.isAbsolute(p) || !isDirectory(p) ? `invalid workspace root "${p}" — enter an existing absolute directory` : null;
72543
+ }, skipsBranchPolicy = (screen, basePath) => (screen === "branchPolicy" || screen === "branchPolicyDevelop") && !existsSync19(path43.join(basePath, ".git")), decodeBranchPreset = (value, fallback) => value === "gitflow" || value === "github-flow" || value === "trunk-based" || value === "custom" ? value : fallback, decodeVcsProvider = (value, fallback) => value === "gitlab" || value === "github" || value === "skip" ? value : fallback, decodeIssueTracker = (value, fallback) => value === "youtrack" || value === "github" || value === "gitlab" || value === "none" ? value : fallback, GITHUB_ISSUES, withGithubIssues = (draft, tracker) => tracker === "github" ? { ...draft, issues: { ...GITHUB_ISSUES } } : draft;
72463
72544
  var init_wizard_state = __esm(() => {
72464
72545
  init_config();
72465
72546
  init_workspaces();
@@ -72518,9 +72599,9 @@ var init_wizard_state = __esm(() => {
72518
72599
  });
72519
72600
 
72520
72601
  // packages/workit-cli/src/admin/uninstall.ts
72521
- import { existsSync as existsSync20, readFileSync as readFileSync21, realpathSync as realpathSync10, rmSync as rmSync7, writeFileSync as writeFileSync12 } from "node:fs";
72522
- import os14 from "node:os";
72523
- import path43 from "node:path";
72602
+ import { existsSync as existsSync20, readFileSync as readFileSync22, realpathSync as realpathSync10, rmSync as rmSync7, writeFileSync as writeFileSync13 } from "node:fs";
72603
+ import os15 from "node:os";
72604
+ import path44 from "node:path";
72524
72605
  function cleanCursorSettings(settings, pluginDir) {
72525
72606
  const next = { ...settings };
72526
72607
  let changed = false;
@@ -72667,7 +72748,7 @@ function planUninstall(paths = {}) {
72667
72748
  }
72668
72749
  ] : []
72669
72750
  };
72670
- const home = paths.home ?? paths.env?.HOME ?? os14.homedir();
72751
+ const home = paths.home ?? paths.env?.HOME ?? os15.homedir();
72671
72752
  const claudeInstalls = claudeWorkitInstalls(home, paths.env ?? process.env, paths.cwd ?? process.cwd());
72672
72753
  const claude = {
72673
72754
  host: "claude-code",
@@ -72693,7 +72774,7 @@ function planUninstall(paths = {}) {
72693
72774
  plan.actions.push({
72694
72775
  kind: "edit-json-remove",
72695
72776
  path: file,
72696
- detail: `remove Workit's permission block from ${path43.basename(file)}`
72777
+ detail: `remove Workit's permission block from ${path44.basename(file)}`
72697
72778
  });
72698
72779
  }
72699
72780
  if (existsSync20(res.codexRules))
@@ -72727,8 +72808,8 @@ function applyUninstall(plan, paths = {}) {
72727
72808
  status = outcome.status;
72728
72809
  detail = outcome.detail;
72729
72810
  } else if (action.kind === "remove-dir") {
72730
- const resolved = path43.resolve(action.path);
72731
- const allowed = canonicalRemoveDirAllowed(resolved, res) || resolved === path43.resolve(res.codexPluginDir) && path43.basename(resolved) === "workit" && path43.basename(path43.dirname(resolved)) === "plugins";
72811
+ const resolved = path44.resolve(action.path);
72812
+ const allowed = canonicalRemoveDirAllowed(resolved, res) || resolved === path44.resolve(res.codexPluginDir) && path44.basename(resolved) === "workit" && path44.basename(path44.dirname(resolved)) === "plugins";
72732
72813
  if (!allowed) {
72733
72814
  status = "failed";
72734
72815
  detail = `refusing to remove non-canonical plugin directory: ${resolved}`;
@@ -72764,23 +72845,23 @@ function applyUninstall(plan, paths = {}) {
72764
72845
  return { ok: entries.every((e) => e.status !== "failed"), entries };
72765
72846
  }
72766
72847
  var resolveUninstallPaths = (options = {}) => {
72767
- const home = options.home ?? options.env?.HOME ?? os14.homedir();
72848
+ const home = options.home ?? options.env?.HOME ?? os15.homedir();
72768
72849
  const permissionPaths = { home, env: options.env ?? process.env };
72769
72850
  return {
72770
72851
  claudeSettings: permissionTarget("claude-code", permissionPaths).file,
72771
72852
  cursorCliConfig: permissionTarget("cursor", permissionPaths).file,
72772
72853
  codexRules: permissionTarget("codex", permissionPaths).file,
72773
- opencodeConfig: options.opencodeConfig ?? path43.join(home, ".config", "opencode", "opencode.json"),
72774
- cursorSettings: options.cursorSettings ?? path43.join(home, ".cursor", "settings.json"),
72775
- cursorMcp: options.cursorMcp ?? path43.join(home, ".cursor", "mcp.json"),
72776
- cursorPluginDir: options.cursorPluginDir ?? path43.join(home, ".cursor", "plugins", "local", "workit"),
72777
- codexPluginDir: path43.join(home, ".codex", "plugins", "workit"),
72778
- piConfig: path43.join(home, ".pi", "config.json")
72854
+ opencodeConfig: options.opencodeConfig ?? path44.join(home, ".config", "opencode", "opencode.json"),
72855
+ cursorSettings: options.cursorSettings ?? path44.join(home, ".cursor", "settings.json"),
72856
+ cursorMcp: options.cursorMcp ?? path44.join(home, ".cursor", "mcp.json"),
72857
+ cursorPluginDir: options.cursorPluginDir ?? path44.join(home, ".cursor", "plugins", "local", "workit"),
72858
+ codexPluginDir: path44.join(home, ".codex", "plugins", "workit"),
72859
+ piConfig: path44.join(home, ".pi", "config.json")
72779
72860
  };
72780
72861
  }, isRecord7 = (v) => v !== null && typeof v === "object" && !Array.isArray(v), readJsonRecord = (file) => {
72781
72862
  let raw;
72782
72863
  try {
72783
- raw = readFileSync21(file, "utf8");
72864
+ raw = readFileSync22(file, "utf8");
72784
72865
  } catch {
72785
72866
  if (existsSync20(file))
72786
72867
  return { kind: "malformed", error: `${file} is not readable` };
@@ -72793,12 +72874,12 @@ var resolveUninstallPaths = (options = {}) => {
72793
72874
  return { kind: "malformed", error: `${file} is not valid JSON` };
72794
72875
  }
72795
72876
  }, stripTrailingSep = (p) => {
72796
- const j = path43.join(p);
72797
- return path43.dirname(j) === j ? j : j.replace(/[\\/]+$/, "");
72877
+ const j = path44.join(p);
72878
+ return path44.dirname(j) === j ? j : j.replace(/[\\/]+$/, "");
72798
72879
  }, CURSOR_LEGACY_IDENTITIES, permissionPathsOf = (paths) => {
72799
72880
  const env = paths.env ?? process.env;
72800
72881
  return {
72801
- home: paths.home ?? env.HOME ?? os14.homedir(),
72882
+ home: paths.home ?? env.HOME ?? os15.homedir(),
72802
72883
  env,
72803
72884
  ...paths.stateDir ? { stateDir: paths.stateDir } : {}
72804
72885
  };
@@ -72821,8 +72902,8 @@ var resolveUninstallPaths = (options = {}) => {
72821
72902
  return cleanPiConfig;
72822
72903
  return null;
72823
72904
  }, canonicalRemoveDirAllowed = (actionPath, res) => {
72824
- const expected = path43.resolve(res.cursorPluginDir);
72825
- if (!(actionPath === expected && path43.basename(expected) === "workit" && path43.basename(path43.dirname(expected)) === "local" && path43.basename(path43.dirname(path43.dirname(expected))) === "plugins")) {
72905
+ const expected = path44.resolve(res.cursorPluginDir);
72906
+ if (!(actionPath === expected && path44.basename(expected) === "workit" && path44.basename(path44.dirname(expected)) === "local" && path44.basename(path44.dirname(path44.dirname(expected))) === "plugins")) {
72826
72907
  return false;
72827
72908
  }
72828
72909
  try {
@@ -72845,7 +72926,7 @@ var resolveUninstallPaths = (options = {}) => {
72845
72926
  `;
72846
72927
  let current;
72847
72928
  try {
72848
- current = readFileSync21(target, "utf8");
72929
+ current = readFileSync22(target, "utf8");
72849
72930
  } catch (error) {
72850
72931
  return {
72851
72932
  status: "failed",
@@ -72856,7 +72937,7 @@ var resolveUninstallPaths = (options = {}) => {
72856
72937
  return { status: "skipped", detail: "already clean" };
72857
72938
  }
72858
72939
  try {
72859
- writeFileSync12(target, serialized, "utf8");
72940
+ writeFileSync13(target, serialized, "utf8");
72860
72941
  } catch (error) {
72861
72942
  return {
72862
72943
  status: "failed",
@@ -72872,9 +72953,9 @@ var resolveUninstallPaths = (options = {}) => {
72872
72953
  status: "failed",
72873
72954
  detail: `refusing unreviewed host command: ${action.args.join(" ")}`
72874
72955
  };
72875
- const home = paths.home ?? paths.env?.HOME ?? os14.homedir();
72956
+ const home = paths.home ?? paths.env?.HOME ?? os15.homedir();
72876
72957
  const env = paths.env ?? process.env;
72877
- const recorded = claudeWorkitInstalls(home, env, action.cwd).some((install) => install.id === id && install.scope === scope && (install.projectPath === null ? action.cwd === null : path43.resolve(install.projectPath) === path43.resolve(action.cwd ?? "")));
72958
+ const recorded = claudeWorkitInstalls(home, env, action.cwd).some((install) => install.id === id && install.scope === scope && (install.projectPath === null ? action.cwd === null : path44.resolve(install.projectPath) === path44.resolve(action.cwd ?? "")));
72878
72959
  if (!recorded)
72879
72960
  return { status: "skipped", detail: `${id} (${scope} scope) is no longer installed` };
72880
72961
  const executable = findHostExecutable("claude", { home, env });
@@ -72898,7 +72979,7 @@ var init_uninstall = __esm(() => {
72898
72979
  });
72899
72980
 
72900
72981
  // packages/workit-cli/src/admin/detect-hosts.ts
72901
- import os15 from "node:os";
72982
+ import os16 from "node:os";
72902
72983
  function preselectedPlatforms(detection) {
72903
72984
  return WIZARD_HOSTS.filter((host) => detection[host].detected);
72904
72985
  }
@@ -72913,7 +72994,7 @@ function emptyDetection() {
72913
72994
  }
72914
72995
  function detectHosts(options = {}) {
72915
72996
  const env = options.env ?? process.env;
72916
- const home = options.home ?? env.HOME ?? os15.homedir();
72997
+ const home = options.home ?? env.HOME ?? os16.homedir();
72917
72998
  const plan = planUninstall({ ...options, home, env });
72918
72999
  const configuredByHost = new Map(plan.hosts.map((h) => [h.host, h.installed]));
72919
73000
  const found = emptyDetection();
@@ -75113,7 +75194,7 @@ var init_diagnostics = __esm(() => {
75113
75194
 
75114
75195
  // packages/workit-cli/src/progress.ts
75115
75196
  import { spawn } from "node:child_process";
75116
- import path44 from "node:path";
75197
+ import path45 from "node:path";
75117
75198
  function createProgress(options = {}) {
75118
75199
  const env = options.env ?? process.env;
75119
75200
  const mode = terminalMode({ ...options, env });
@@ -75226,7 +75307,7 @@ function createProgress(options = {}) {
75226
75307
  var FRAMES, FRAME_MS, CLEAR = "\r\x1B[2K", TICKER_SOURCE, defaultTicker = (label, began, stream) => {
75227
75308
  if (stream !== process.stderr)
75228
75309
  return;
75229
- if (!/^(?:node|nodejs|bun)(?:\.exe)?$/i.test(path44.basename(process.execPath)))
75310
+ if (!/^(?:node|nodejs|bun)(?:\.exe)?$/i.test(path45.basename(process.execPath)))
75230
75311
  return;
75231
75312
  try {
75232
75313
  const child = spawn(process.execPath, ["-e", TICKER_SOURCE], {
@@ -75531,6 +75612,13 @@ var init_init = __esm(() => {
75531
75612
  });
75532
75613
 
75533
75614
  // packages/workit-cli/src/prompt.ts
75615
+ var exports_prompt = {};
75616
+ __export(exports_prompt, {
75617
+ askLine: () => askLine,
75618
+ askOrCancel: () => askOrCancel,
75619
+ cancelled: () => cancelled,
75620
+ isPromptAbort: () => isPromptAbort
75621
+ });
75534
75622
  import { createInterface } from "node:readline/promises";
75535
75623
  async function askLine(question, output = process.stdout) {
75536
75624
  const prompt = createInterface({ input: process.stdin, output });
@@ -75674,9 +75762,9 @@ var init_setup2 = __esm(() => {
75674
75762
 
75675
75763
  // packages/workit-cli/src/upgrade/shared.ts
75676
75764
  import { spawn as spawn2 } from "node:child_process";
75677
- import { existsSync as existsSync21, readFileSync as readFileSync22 } from "node:fs";
75678
- import path45 from "node:path";
75679
- import os16 from "node:os";
75765
+ import { existsSync as existsSync21, readFileSync as readFileSync23 } from "node:fs";
75766
+ import path46 from "node:path";
75767
+ import os17 from "node:os";
75680
75768
  import { createHash as createHash15 } from "node:crypto";
75681
75769
  function errorText(error) {
75682
75770
  return error instanceof Error ? error.message : "installed source could not be read";
@@ -75685,39 +75773,39 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
75685
75773
  const tail = stderrTail(result.stderr);
75686
75774
  return `\`${command.command} ${command.args.join(" ")}\` failed${tail ? `: ${tail}` : ""}`;
75687
75775
  }, 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) => {
75688
- const home = deps.home ?? deps.env?.HOME ?? os16.homedir();
75776
+ const home = deps.home ?? deps.env?.HOME ?? os17.homedir();
75689
75777
  const env = {
75690
75778
  ...process.env,
75691
75779
  ...deps.home || deps.env?.HOME ? {
75692
75780
  HOME: home,
75693
- CODEX_HOME: path45.join(home, ".codex"),
75694
- CLAUDE_CONFIG_DIR: path45.join(home, ".claude"),
75695
- PI_CODING_AGENT_DIR: path45.join(home, ".pi/agent"),
75696
- XDG_CONFIG_HOME: path45.join(home, ".config"),
75781
+ CODEX_HOME: path46.join(home, ".codex"),
75782
+ CLAUDE_CONFIG_DIR: path46.join(home, ".claude"),
75783
+ PI_CODING_AGENT_DIR: path46.join(home, ".pi/agent"),
75784
+ XDG_CONFIG_HOME: path46.join(home, ".config"),
75697
75785
  WORKFLOW_TOOLKIT_CONFIG: undefined,
75698
75786
  WORKFLOW_TOOLKIT_CONFIG_DIR: undefined
75699
75787
  } : {},
75700
75788
  ...deps.env,
75701
75789
  HOME: home
75702
75790
  };
75703
- const xdg = env.XDG_CONFIG_HOME || path45.join(home, ".config");
75704
- const codexHome = env.CODEX_HOME ?? path45.join(home, ".codex");
75791
+ const xdg = env.XDG_CONFIG_HOME || path46.join(home, ".config");
75792
+ const codexHome = env.CODEX_HOME ?? path46.join(home, ".codex");
75705
75793
  return {
75706
75794
  home,
75707
75795
  env,
75708
- configDir: env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path45.join(xdg, "workit"),
75709
- opencodeConfig: path45.join(xdg, "opencode/opencode.json"),
75710
- piSettings: path45.join(env.PI_CODING_AGENT_DIR ?? path45.join(home, ".pi/agent"), "settings.json"),
75796
+ configDir: workitConfigDir(env),
75797
+ opencodeConfig: path46.join(xdg, "opencode/opencode.json"),
75798
+ piSettings: path46.join(env.PI_CODING_AGENT_DIR ?? path46.join(home, ".pi/agent"), "settings.json"),
75711
75799
  codexHome,
75712
- codexConfig: path45.join(codexHome, "config.toml"),
75713
- cursorRoot: path45.join(home, ".cursor/plugins/local/workit")
75800
+ codexConfig: path46.join(codexHome, "config.toml"),
75801
+ cursorRoot: path46.join(home, ".cursor/plugins/local/workit")
75714
75802
  };
75715
75803
  }, object2 = (file) => {
75716
75804
  if (!existsSync21(file))
75717
75805
  return null;
75718
75806
  let data;
75719
75807
  try {
75720
- data = JSON.parse(readFileSync22(file, "utf8"));
75808
+ data = JSON.parse(readFileSync23(file, "utf8"));
75721
75809
  } catch {
75722
75810
  throw new Error(`${file} is not valid JSON; use the native host to inspect JSONC settings`);
75723
75811
  }
@@ -75730,7 +75818,7 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
75730
75818
  } catch {
75731
75819
  return null;
75732
75820
  }
75733
- }, digest2 = (file) => existsSync21(file) ? createHash15("sha256").update(readFileSync22(file)).digest("hex") : "missing", runner = (deps) => deps.run ?? ((command, args) => {
75821
+ }, digest2 = (file) => existsSync21(file) ? createHash15("sha256").update(readFileSync23(file)).digest("hex") : "missing", runner = (deps) => deps.run ?? ((command, args) => {
75734
75822
  const { home, env } = upgradePaths(deps);
75735
75823
  let step;
75736
75824
  try {
@@ -75761,10 +75849,10 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
75761
75849
  stderr: `Cannot safely execute batch shim ${step.command}`
75762
75850
  });
75763
75851
  const childEnv = { ...process.env, ...env, HOME: home };
75764
- childEnv.CODEX_HOME = env.CODEX_HOME ?? path45.join(home, ".codex");
75765
- childEnv.PI_CODING_AGENT_DIR = env.PI_CODING_AGENT_DIR ?? path45.join(home, ".pi", "agent");
75766
- childEnv.CLAUDE_CONFIG_DIR = env.CLAUDE_CONFIG_DIR ?? path45.join(home, ".claude");
75767
- childEnv.XDG_CONFIG_HOME = env.XDG_CONFIG_HOME ?? path45.join(home, ".config");
75852
+ childEnv.CODEX_HOME = env.CODEX_HOME ?? path46.join(home, ".codex");
75853
+ childEnv.PI_CODING_AGENT_DIR = env.PI_CODING_AGENT_DIR ?? path46.join(home, ".pi", "agent");
75854
+ childEnv.CLAUDE_CONFIG_DIR = env.CLAUDE_CONFIG_DIR ?? path46.join(home, ".claude");
75855
+ childEnv.XDG_CONFIG_HOME = env.XDG_CONFIG_HOME ?? path46.join(home, ".config");
75768
75856
  return new Promise((resolve) => {
75769
75857
  let stdout = "";
75770
75858
  let stderr = "";
@@ -75807,9 +75895,9 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
75807
75895
  }, piInstalledVersion = (listing, selector) => {
75808
75896
  const lines = listing.split(/\r?\n/).map((line) => line.trim());
75809
75897
  const index = lines.indexOf(selector);
75810
- if (index < 0 || !lines[index + 1] || !path45.isAbsolute(lines[index + 1]))
75898
+ if (index < 0 || !lines[index + 1] || !path46.isAbsolute(lines[index + 1]))
75811
75899
  return;
75812
- const found = objectOrNull(path45.join(lines[index + 1], "package.json"));
75900
+ const found = objectOrNull(path46.join(lines[index + 1], "package.json"));
75813
75901
  return found?.name === "@brainervirus/workit-pi" ? found.version : undefined;
75814
75902
  }, versionAtLeast = (installed, latest) => {
75815
75903
  if (!/^\d+\.\d+\.\d+$/.test(installed))
@@ -75828,6 +75916,7 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
75828
75916
  };
75829
75917
  var init_shared = __esm(() => {
75830
75918
  init_host_install();
75919
+ init_update_settings();
75831
75920
  LAUNCH_HOSTS = ["opencode", "cursor", "codex", "pi"];
75832
75921
  HOSTS2 = [...LAUNCH_HOSTS, "claude-code"];
75833
75922
  LIVE_HOSTS = new Set(["opencode", "claude-code"]);
@@ -75835,12 +75924,12 @@ var init_shared = __esm(() => {
75835
75924
  });
75836
75925
 
75837
75926
  // packages/workit-cli/src/upgrade/processes.ts
75838
- import path46 from "node:path";
75927
+ import path47 from "node:path";
75839
75928
  var PROCESS_HOSTS, SCRIPT_RUNTIMES, classifyProcess = (proc) => {
75840
75929
  if (proc.state.startsWith("Z") || proc.args.includes("<defunct>"))
75841
75930
  return null;
75842
75931
  const argv0 = proc.args.trim().split(/\s+/)[0] ?? "";
75843
- const baseName = (value) => path46.basename(value.replaceAll("\\", "/")).replace(/^\[|\]$/g, "").replace(/\.exe$/i, "").toLowerCase();
75932
+ const baseName = (value) => path47.basename(value.replaceAll("\\", "/")).replace(/^\[|\]$/g, "").replace(/\.exe$/i, "").toLowerCase();
75844
75933
  let host = PROCESS_HOSTS[baseName(argv0)];
75845
75934
  if (!host && SCRIPT_RUNTIMES.has(baseName(argv0))) {
75846
75935
  const script = proc.args.trim().split(/\s+/).slice(1).find((arg) => !arg.startsWith("-"));
@@ -75890,8 +75979,8 @@ var init_processes = __esm(() => {
75890
75979
  });
75891
75980
 
75892
75981
  // packages/workit-cli/src/upgrade/apply.ts
75893
- import { existsSync as existsSync22, readdirSync as readdirSync12, mkdirSync as mkdirSync11, copyFileSync as copyFileSync6, chmodSync as chmodSync2, cpSync as cpSync5 } from "node:fs";
75894
- import path47 from "node:path";
75982
+ import { existsSync as existsSync22, readdirSync as readdirSync12, mkdirSync as mkdirSync12, copyFileSync as copyFileSync6, chmodSync as chmodSync2, cpSync as cpSync5 } from "node:fs";
75983
+ import path48 from "node:path";
75895
75984
  import { createHash as createHash16 } from "node:crypto";
75896
75985
  async function applyUpgrade(plan, deps = {}) {
75897
75986
  const hosts = [...plan.failed];
@@ -75926,11 +76015,11 @@ async function applyUpgrade(plan, deps = {}) {
75926
76015
  };
75927
76016
  const paths = upgradePaths(deps);
75928
76017
  const { home, configDir } = paths;
75929
- const backup = path47.join(home, ".local/state/workit/upgrades", new Date().toISOString().replaceAll(":", "-"));
75930
- mkdirSync11(backup, { recursive: true, mode: 448 });
76018
+ const backup = path48.join(home, ".local/state/workit/upgrades", new Date().toISOString().replaceAll(":", "-"));
76019
+ mkdirSync12(backup, { recursive: true, mode: 448 });
75931
76020
  for (const file of Object.keys(plan.configDigests))
75932
76021
  if (existsSync22(file)) {
75933
- const target = path47.join(backup, createHash16("sha256").update(file).digest("hex").slice(0, 12) + "-" + path47.basename(file));
76022
+ const target = path48.join(backup, createHash16("sha256").update(file).digest("hex").slice(0, 12) + "-" + path48.basename(file));
75934
76023
  copyFileSync6(file, target);
75935
76024
  chmodSync2(target, 384);
75936
76025
  }
@@ -75953,7 +76042,7 @@ async function applyUpgrade(plan, deps = {}) {
75953
76042
  let cursorBackupError = null;
75954
76043
  if (plan.entries.some((entry) => entry.host === "cursor") && existsSync22(paths.cursorRoot))
75955
76044
  try {
75956
- cpSync5(paths.cursorRoot, path47.join(backup, "cursor-package"), {
76045
+ cpSync5(paths.cursorRoot, path48.join(backup, "cursor-package"), {
75957
76046
  recursive: true
75958
76047
  });
75959
76048
  } catch (error) {
@@ -76101,7 +76190,7 @@ var briefDetail = (detail) => {
76101
76190
  const lines = detail.split(/\r?\n/).filter((line) => line.trim());
76102
76191
  return (lines.length > 6 ? [lines[0], ...lines.slice(-5)] : lines).join(" | ");
76103
76192
  }, codexPluginRoot = (codexHome) => {
76104
- const dir = path47.join(codexHome, "plugins", "cache", CODEX_MARKETPLACE, "workit");
76193
+ const dir = path48.join(codexHome, "plugins", "cache", CODEX_MARKETPLACE, "workit");
76105
76194
  let versions = [];
76106
76195
  try {
76107
76196
  versions = readdirSync12(dir).filter((version) => /^\d+\.\d+\.\d+$/.test(version));
@@ -76109,7 +76198,7 @@ var briefDetail = (detail) => {
76109
76198
  return null;
76110
76199
  }
76111
76200
  const newest = versions.reduce((best, version) => best && versionAtLeast(best, version) ? best : version, null);
76112
- return newest ? path47.join(dir, newest) : null;
76201
+ return newest ? path48.join(dir, newest) : null;
76113
76202
  }, opencodeVersion = async (run) => {
76114
76203
  const listing = await run("opencode", ["plugin", "list"]);
76115
76204
  if (listing.status !== 0)
@@ -76156,8 +76245,8 @@ ${result.stderr}`;
76156
76245
  if (result.exitCode !== 0)
76157
76246
  break;
76158
76247
  }
76159
- const cursorSettings = path47.join(home, ".cursor", "settings.json");
76160
- const cursorMcp = path47.join(home, ".cursor", "mcp.json");
76248
+ const cursorSettings = path48.join(home, ".cursor", "settings.json");
76249
+ const cursorMcp = path48.join(home, ".cursor", "mcp.json");
76161
76250
  const preview = {
76162
76251
  ok: true,
76163
76252
  blocked: [],
@@ -76169,7 +76258,7 @@ ${result.stderr}`;
76169
76258
  {
76170
76259
  type: "install-host",
76171
76260
  platform: "cursor",
76172
- path: path47.join(home, ".cursor/plugins/local/.workit-package-bootstrap"),
76261
+ path: path48.join(home, ".cursor/plugins/local/.workit-package-bootstrap"),
76173
76262
  commands
76174
76263
  },
76175
76264
  { type: "install-adapter", platform: "cursor", path: paths.cursorRoot },
@@ -76188,7 +76277,7 @@ ${result.stderr}`;
76188
76277
  stderr: "command did not run"
76189
76278
  }
76190
76279
  });
76191
- const installed = objectOrNull(path47.join(paths.cursorRoot, "package.json"));
76280
+ const installed = objectOrNull(path48.join(paths.cursorRoot, "package.json"));
76192
76281
  const problems = result.entries.filter((one) => one.status === "Failed").map((one) => one.detail ?? `${one.file} failed`);
76193
76282
  if (problems.length)
76194
76283
  return fail(`Cursor install failed: ${problems.map(briefDetail).join("; ")}`);
@@ -76258,7 +76347,7 @@ ${result.stderr}`;
76258
76347
  };
76259
76348
  }, refreshCodexAgents = async (run, codexHome) => {
76260
76349
  const root = codexPluginRoot(codexHome);
76261
- const launcher = root && path47.join(root, "dist", "launch-mcp.js");
76350
+ const launcher = root && path48.join(root, "dist", "launch-mcp.js");
76262
76351
  if (!launcher || !existsSync22(launcher))
76263
76352
  return { ok: true, note: "" };
76264
76353
  const fix = `node ${JSON.stringify(launcher)} --install-agents`;
@@ -76278,8 +76367,8 @@ ${result.stderr}`;
76278
76367
  const currentRoot = await run("npm", ["root", "--global"]);
76279
76368
  if (currentRoot.status !== 0 || currentRoot.stdout.trim() !== cli.root)
76280
76369
  return fail("Global npm location changed; preview again");
76281
- const cliBackup = path47.join(backup, "cli-package");
76282
- cpSync5(path47.join(cli.root, "@brainervirus/workit-cli"), cliBackup, {
76370
+ const cliBackup = path48.join(backup, "cli-package");
76371
+ cpSync5(path48.join(cli.root, "@brainervirus/workit-cli"), cliBackup, {
76283
76372
  recursive: true
76284
76373
  });
76285
76374
  const install = await run("npm", [
@@ -76288,8 +76377,8 @@ ${result.stderr}`;
76288
76377
  `@brainervirus/workit-cli@${cli.latest}`
76289
76378
  ]);
76290
76379
  if (install.status !== 0)
76291
- return fail(`CLI update failed${stderrTail(install.stderr) ? ` (${stderrTail(install.stderr)})` : ""}; preserved package at ${cliBackup}; use npm to repair or run node ${path47.join(cliBackup, "dist/index.js")}`);
76292
- const installed = objectOrNull(path47.join(cli.root, "@brainervirus/workit-cli/package.json"));
76380
+ return fail(`CLI update failed${stderrTail(install.stderr) ? ` (${stderrTail(install.stderr)})` : ""}; preserved package at ${cliBackup}; use npm to repair or run node ${path48.join(cliBackup, "dist/index.js")}`);
76381
+ const installed = objectOrNull(path48.join(cli.root, "@brainervirus/workit-cli/package.json"));
76293
76382
  if (installed?.name !== "@brainervirus/workit-cli" || installed.version !== cli.latest)
76294
76383
  return fail(`CLI update did not verify the requested version; preserved package at ${cliBackup}`);
76295
76384
  return {
@@ -76308,10 +76397,171 @@ var init_apply = __esm(() => {
76308
76397
  init_shared();
76309
76398
  });
76310
76399
 
76400
+ // packages/workit-cli/src/update-check.ts
76401
+ var exports_update_check = {};
76402
+ __export(exports_update_check, {
76403
+ CLI_PACKAGE: () => CLI_PACKAGE2,
76404
+ launchUpdateCheck: () => launchUpdateCheck,
76405
+ readUpdateCache: () => readUpdateCache,
76406
+ readUpdatesMode: () => readUpdatesMode,
76407
+ refreshUpdateCache: () => refreshUpdateCache,
76408
+ writeUpdateCache: () => writeUpdateCache,
76409
+ writeUpdatesMode: () => writeUpdatesMode
76410
+ });
76411
+ import { spawn as spawn3, spawnSync as spawnSync17 } from "node:child_process";
76412
+ import { readFileSync as readFileSync24 } from "node:fs";
76413
+ import path49 from "node:path";
76414
+ async function launchUpdateCheck(context, deps) {
76415
+ if (!interactiveLaunch(context, deps))
76416
+ return;
76417
+ const mode = readUpdatesMode(deps.env);
76418
+ if (mode === "off")
76419
+ return;
76420
+ const now = (deps.now ?? Date.now)();
76421
+ const cache = readUpdateCache(deps.env);
76422
+ if (cache.checkedAt === undefined || now - cache.checkedAt >= UPDATE_TTL_MS) {
76423
+ writeUpdateCache(deps.env, { ...cache, checkedAt: now });
76424
+ (deps.refresh ?? (() => startRefresh(deps.env)))();
76425
+ }
76426
+ const installed = deps.installed ?? package_default.version;
76427
+ const latest = cache.latest;
76428
+ if (!latest || versionAtLeast(installed, latest))
76429
+ return;
76430
+ if (cache.snoozedAt !== undefined && now - cache.snoozedAt < UPDATE_TTL_MS)
76431
+ return;
76432
+ const style = createStyle({ stream: deps.stderr, env: deps.env });
76433
+ if (mode === "prompt") {
76434
+ if (cache.skipped === latest)
76435
+ return;
76436
+ let answer;
76437
+ try {
76438
+ answer = await (deps.ask ?? defaultAsk)(`${style.bold("Workit update available:")} ${installed} -> ${style.ok(latest)} ${style.command("[u]")}pgrade now / ${style.command("[s]")}kip for now / ${style.command("[n]")}ever for this version: `);
76439
+ } catch (error) {
76440
+ if (!isPromptAbort(error))
76441
+ return;
76442
+ deps.write(`
76443
+ Cancelled.
76444
+ `);
76445
+ return CANCELLED_EXIT2;
76446
+ }
76447
+ const choice = answer.trim().toLowerCase();
76448
+ if (choice === "n" || choice === "never") {
76449
+ writeUpdateCache(deps.env, {
76450
+ ...readUpdateCache(deps.env),
76451
+ skipped: latest
76452
+ });
76453
+ return;
76454
+ }
76455
+ if (choice !== "u" && choice !== "upgrade") {
76456
+ writeUpdateCache(deps.env, {
76457
+ ...readUpdateCache(deps.env),
76458
+ snoozedAt: now
76459
+ });
76460
+ return;
76461
+ }
76462
+ } else {
76463
+ deps.write(`${style.bold("Workit update:")} upgrading ${installed} -> ${latest} (CLI and host plugins; updates=auto)
76464
+ `);
76465
+ }
76466
+ writeUpdateCache(deps.env, { ...readUpdateCache(deps.env), snoozedAt: now });
76467
+ const outcome = await (deps.upgrade ?? defaultUpgrade)();
76468
+ if (outcome.code !== 0 && outcome.failed.length)
76469
+ deps.write(`${style.warn("Upgrade incomplete:")} ${outcome.failed.map((row) => `${row.host} failed${row.fix ? ` (fix: ${row.fix})` : ""}`).join("; ")}
76470
+ `);
76471
+ const onDisk = (deps.cliOnDisk ?? defaultCliOnDisk)();
76472
+ if (!onDisk || onDisk === installed) {
76473
+ if (outcome.code !== 0)
76474
+ deps.write(`${style.warn("Upgrade did not finish;")} running your command with ${installed}.
76475
+ `);
76476
+ return;
76477
+ }
76478
+ return (deps.reexec ?? defaultReexec)(context.argv);
76479
+ }
76480
+ var CLI_PACKAGE2 = "@brainervirus/workit-cli", UPDATE_TTL_MS, QUIET_ENV = "WORKIT_UPDATE_CHECK", REFRESH_ENV = "WORKIT_UPDATE_REFRESH", AGENT_VARIABLES, AGENT_PREFIXES, PROFILE_VARIABLES, agentHostMarker = (env) => Object.keys(env).find((key) => env[key] !== undefined && !PROFILE_VARIABLES.has(key) && (AGENT_VARIABLES.has(key) || AGENT_PREFIXES.some((prefix) => key.startsWith(prefix)))), SILENT_COMMANDS, interactiveLaunch = (context, deps) => !SILENT_COMMANDS.has(context.command) && deps.env[QUIET_ENV] !== "0" && deps.stdin.isTTY === true && deps.stdout.isTTY === true && deps.stderr.isTTY === true && terminalMode({ stream: deps.stderr, env: deps.env, json: context.json }) !== "off" && agentHostMarker(deps.env) === undefined, CANCELLED_EXIT2 = 130, defaultCliOnDisk = () => {
76481
+ const script = process.argv[1];
76482
+ if (!script)
76483
+ return;
76484
+ let dir = path49.dirname(script);
76485
+ for (let depth = 0;depth < 4; depth += 1, dir = path49.dirname(dir)) {
76486
+ try {
76487
+ const found = JSON.parse(readFileSync24(path49.join(dir, "package.json"), "utf8"));
76488
+ if (found.name === CLI_PACKAGE2 && typeof found.version === "string")
76489
+ return found.version;
76490
+ } catch {}
76491
+ }
76492
+ return;
76493
+ }, defaultAsk = async (question) => (await Promise.resolve().then(() => (init_prompt(), exports_prompt))).askLine(question, process.stderr), defaultUpgrade = async () => {
76494
+ const failed = [];
76495
+ const code = await (await Promise.resolve().then(() => (init_upgrade(), exports_upgrade))).runUpgradeCommand(["--yes"], {
76496
+ out: process.stderr,
76497
+ onResult: (hosts) => {
76498
+ for (const row of hosts)
76499
+ if (row.status === "failed")
76500
+ failed.push({ host: row.host, fix: row.fix });
76501
+ }
76502
+ });
76503
+ return { code, failed };
76504
+ }, defaultReexec = (argv) => {
76505
+ const script = process.argv[1];
76506
+ if (!script)
76507
+ return;
76508
+ const result = spawnSync17(process.execPath, [script, ...argv], {
76509
+ stdio: "inherit",
76510
+ env: { ...process.env, [QUIET_ENV]: "0" }
76511
+ });
76512
+ return result.error ? undefined : result.status ?? 1;
76513
+ }, startRefresh = (env) => {
76514
+ const script = process.argv[1];
76515
+ if (!script)
76516
+ return;
76517
+ try {
76518
+ spawn3(process.execPath, [script], {
76519
+ detached: true,
76520
+ stdio: "ignore",
76521
+ windowsHide: true,
76522
+ env: { ...env, [REFRESH_ENV]: "1", [QUIET_ENV]: "0" }
76523
+ }).unref();
76524
+ } catch {}
76525
+ }, refreshUpdateCache = (env, options = {}) => {
76526
+ let latest;
76527
+ try {
76528
+ latest = registryVersion(options.run ?? runner({ env }), CLI_PACKAGE2);
76529
+ } catch {
76530
+ latest = undefined;
76531
+ }
76532
+ const cache = readUpdateCache(env);
76533
+ writeUpdateCache(env, {
76534
+ ...cache,
76535
+ checkedAt: (options.now ?? Date.now)(),
76536
+ ...latest ? { latest } : {}
76537
+ });
76538
+ };
76539
+ var init_update_check = __esm(() => {
76540
+ init_package();
76541
+ init_prompt();
76542
+ init_style();
76543
+ init_shared();
76544
+ init_update_settings();
76545
+ UPDATE_TTL_MS = 24 * 60 * 60 * 1000;
76546
+ AGENT_VARIABLES = new Set(["CLAUDECODE", "CLAUDE_CODE_ENTRYPOINT"]);
76547
+ AGENT_PREFIXES = ["CODEX_", "OPENCODE", "CURSOR_", "PI_"];
76548
+ PROFILE_VARIABLES = new Set(["CODEX_HOME", "PI_CODING_AGENT_DIR"]);
76549
+ SILENT_COMMANDS = new Set([
76550
+ undefined,
76551
+ "upgrade",
76552
+ "help",
76553
+ "--help",
76554
+ "-h",
76555
+ "version",
76556
+ "--version",
76557
+ "-v"
76558
+ ]);
76559
+ });
76560
+
76311
76561
  // packages/workit-cli/src/upgrade/plan.ts
76312
- import { existsSync as existsSync23, mkdtempSync as mkdtempSync3, rmSync as rmSync8, lstatSync as lstatSync8, readFileSync as readFileSync23 } from "node:fs";
76313
- import path48 from "node:path";
76314
- import os17 from "node:os";
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";
76564
+ import os18 from "node:os";
76315
76565
  function previewUpgrade(hosts = HOSTS2, deps = {}) {
76316
76566
  const paths = upgradePaths(deps);
76317
76567
  const { home, configDir } = paths;
@@ -76334,9 +76584,9 @@ function previewUpgrade(hosts = HOSTS2, deps = {}) {
76334
76584
  for (const file of [
76335
76585
  paths.opencodeConfig,
76336
76586
  paths.opencodeConfig + "c",
76337
- path48.join(home, ".cursor/settings.json"),
76338
- path48.join(home, ".cursor/mcp.json"),
76339
- path48.join(paths.cursorRoot, "package.json"),
76587
+ path50.join(home, ".cursor/settings.json"),
76588
+ path50.join(home, ".cursor/mcp.json"),
76589
+ path50.join(paths.cursorRoot, "package.json"),
76340
76590
  paths.codexConfig,
76341
76591
  paths.piSettings
76342
76592
  ])
@@ -76463,7 +76713,7 @@ function previewUpgrade(hosts = HOSTS2, deps = {}) {
76463
76713
  var codexRegistered = (configFile) => {
76464
76714
  let text;
76465
76715
  try {
76466
- text = readFileSync23(configFile, "utf8");
76716
+ text = readFileSync25(configFile, "utf8");
76467
76717
  } catch {
76468
76718
  return false;
76469
76719
  }
@@ -76506,8 +76756,8 @@ var codexRegistered = (configFile) => {
76506
76756
  result.push(classify("opencode", pin));
76507
76757
  });
76508
76758
  guard("cursor", () => {
76509
- const cursor = objectOrNull(path48.join(paths.cursorRoot, "package.json"));
76510
- const mcp = objectOrNull(path48.join(home, ".cursor/mcp.json"));
76759
+ const cursor = objectOrNull(path50.join(paths.cursorRoot, "package.json"));
76760
+ const mcp = objectOrNull(path50.join(home, ".cursor/mcp.json"));
76511
76761
  const args = mcp?.mcpServers?.workit?.args ?? [];
76512
76762
  const arg = args.find((value) => typeof value === "string" && value.startsWith("--package="));
76513
76763
  const selector = typeof arg === "string" ? arg.slice(10) : "local";
@@ -76518,7 +76768,7 @@ var codexRegistered = (configFile) => {
76518
76768
  });
76519
76769
  return;
76520
76770
  }
76521
- const settings = objectOrNull(path48.join(home, ".cursor/settings.json"));
76771
+ const settings = objectOrNull(path50.join(home, ".cursor/settings.json"));
76522
76772
  const dirs = Array.isArray(settings?.plugin_dirs) ? settings.plugin_dirs : [];
76523
76773
  const registered = mcp?.mcpServers?.workit !== undefined || dirs.some((dir) => String(dir).replaceAll("\\", "/").replace(/\/+$/, "").endsWith("local/workit"));
76524
76774
  if (registered)
@@ -76533,7 +76783,7 @@ var codexRegistered = (configFile) => {
76533
76783
  if (typeof source !== "string")
76534
76784
  continue;
76535
76785
  const npm = /^(?:npm:)?@brainervirus\/workit-pi(?:@[^/]+)?$/.test(source);
76536
- const local = path48.isAbsolute(source) && source.replaceAll("\\", "/").endsWith("/packages/workit-pi") && object2(path48.join(source, "package.json"))?.name === "@brainervirus/workit-pi";
76786
+ const local = path50.isAbsolute(source) && source.replaceAll("\\", "/").endsWith("/packages/workit-pi") && object2(path50.join(source, "package.json"))?.name === "@brainervirus/workit-pi";
76537
76787
  if (!npm && !local)
76538
76788
  continue;
76539
76789
  const found = classify("pi", source);
@@ -76593,15 +76843,15 @@ var codexRegistered = (configFile) => {
76593
76843
  });
76594
76844
  return result;
76595
76845
  }, opencodeProbe = (deps, args) => {
76596
- const scratch = mkdtempSync3(path48.join(os17.tmpdir(), "workit-upgrade-opencode-"));
76846
+ const scratch = mkdtempSync3(path50.join(os18.tmpdir(), "workit-upgrade-opencode-"));
76597
76847
  try {
76598
76848
  return runner({
76599
76849
  ...deps,
76600
76850
  env: {
76601
76851
  ...deps.env,
76602
- XDG_DATA_HOME: path48.join(scratch, "data"),
76603
- XDG_STATE_HOME: path48.join(scratch, "state"),
76604
- XDG_CACHE_HOME: path48.join(scratch, "cache")
76852
+ XDG_DATA_HOME: path50.join(scratch, "data"),
76853
+ XDG_STATE_HOME: path50.join(scratch, "state"),
76854
+ XDG_CACHE_HOME: path50.join(scratch, "cache")
76605
76855
  }
76606
76856
  })("opencode", args);
76607
76857
  } finally {
@@ -76609,7 +76859,7 @@ var codexRegistered = (configFile) => {
76609
76859
  }
76610
76860
  }, planCli = (plan, run) => {
76611
76861
  const root = run("npm", ["root", "--global"]);
76612
- if (root.status !== 0 || !path48.isAbsolute(root.stdout.trim())) {
76862
+ if (root.status !== 0 || !path50.isAbsolute(root.stdout.trim())) {
76613
76863
  plan.skipped.push({
76614
76864
  host: "cli",
76615
76865
  reason: "global npm location could not be verified",
@@ -76617,9 +76867,9 @@ var codexRegistered = (configFile) => {
76617
76867
  });
76618
76868
  return;
76619
76869
  }
76620
- const packageFile = path48.join(root.stdout.trim(), "@brainervirus/workit-cli/package.json");
76870
+ const packageFile = path50.join(root.stdout.trim(), "@brainervirus/workit-cli/package.json");
76621
76871
  const installed = objectOrNull(packageFile);
76622
- if (installed?.name !== "@brainervirus/workit-cli" || lstatSync8(path48.dirname(packageFile)).isSymbolicLink()) {
76872
+ if (installed?.name !== "@brainervirus/workit-cli" || lstatSync8(path50.dirname(packageFile)).isSymbolicLink()) {
76623
76873
  plan.skipped.push({
76624
76874
  host: "cli",
76625
76875
  reason: "no managed global CLI install (local links preserved); use npx @brainervirus/workit-cli@latest"
@@ -76656,6 +76906,132 @@ var init_plan = __esm(() => {
76656
76906
  init_shared();
76657
76907
  });
76658
76908
 
76909
+ // packages/workit-cli/src/upgrade/check.ts
76910
+ import path51 from "node:path";
76911
+ function runUpdateCheck(json, deps) {
76912
+ const out = deps.out ?? process.stdout;
76913
+ const paths = upgradePaths(deps);
76914
+ const run = runner(deps);
76915
+ const latest = (name) => registryVersion(run, name);
76916
+ const cliLatest = latest(CLI_PACKAGE2);
76917
+ if (cliLatest)
76918
+ writeUpdateCache(paths.env, {
76919
+ ...readUpdateCache(paths.env),
76920
+ checkedAt: Date.now(),
76921
+ latest: cliLatest
76922
+ });
76923
+ const components = [
76924
+ {
76925
+ component: "cli",
76926
+ package: CLI_PACKAGE2,
76927
+ installed: package_default.version,
76928
+ latest: cliLatest ?? null,
76929
+ status: statusOf(package_default.version, cliLatest)
76930
+ }
76931
+ ];
76932
+ const failed = [];
76933
+ const installed = sources(paths, run, HOSTS2, failed);
76934
+ const unreadableBy = new Map(failed.map((entry) => [entry.host, entry]));
76935
+ const versionBy = new Map;
76936
+ for (const source of installed)
76937
+ if (!versionBy.has(source.host) || source.installedVersion)
76938
+ versionBy.set(source.host, versionBy.get(source.host) ?? source.installedVersion);
76939
+ for (const host of HOSTS2) {
76940
+ const name = `@brainervirus/workit-${host}`;
76941
+ const unreadable = unreadableBy.get(host);
76942
+ if (unreadable) {
76943
+ components.push({
76944
+ component: host,
76945
+ package: name,
76946
+ installed: null,
76947
+ latest: null,
76948
+ status: "unreadable",
76949
+ reason: unreadable.reason
76950
+ });
76951
+ continue;
76952
+ }
76953
+ if (!versionBy.has(host))
76954
+ continue;
76955
+ const version = versionBy.get(host);
76956
+ const newest = latest(name);
76957
+ components.push({
76958
+ component: host,
76959
+ package: name,
76960
+ installed: version ?? null,
76961
+ latest: newest ?? null,
76962
+ status: statusOf(version, newest)
76963
+ });
76964
+ }
76965
+ const pending = components.some((entry) => entry.status === "update" || entry.status === "unknown");
76966
+ const updates = readUpdatesMode(paths.env);
76967
+ if (json) {
76968
+ out.write(JSON.stringify({ updates, components, apply: pending ? APPLY : null }, null, 2) + `
76969
+ `);
76970
+ return 0;
76971
+ }
76972
+ const style = createStyle({
76973
+ stream: out === process.stdout ? process.stdout : undefined,
76974
+ env: paths.env
76975
+ });
76976
+ const width = Math.max(...components.map((entry) => entry.component.length));
76977
+ const rows = components.map((entry) => {
76978
+ const label = LABEL[entry.status];
76979
+ const paint = entry.status === "current" ? style.ok : entry.status === "update" ? style.warn : style.dim;
76980
+ return ` ${entry.component.padEnd(width)} ${entry.installed ?? "-"} -> ${entry.latest ?? "?"} ${paint(label)}${entry.reason ? ` (${entry.reason})` : ""}
76981
+ `;
76982
+ });
76983
+ out.write(`${style.bold("Workit versions")} (updates: ${updates}; change with ${style.command(`workit upgrade --set-updates=${UPDATES_MODES.join("|")}`)})
76984
+ ${rows.join("")}`);
76985
+ const unchecked = components.filter((entry) => entry.status === "unavailable");
76986
+ if (unchecked.length)
76987
+ out.write(`${style.warn("Could not check: registry unavailable")} for ${unchecked.map((entry) => entry.component).join(", ")}
76988
+ `);
76989
+ if (pending)
76990
+ out.write(`Apply with: ${style.command(APPLY)} (upgrades the CLI and every host plugin together)
76991
+ `);
76992
+ else if (!unchecked.length)
76993
+ out.write(`${style.ok("Everything is current.")}
76994
+ `);
76995
+ out.write(`${style.dim("check only; nothing changed.")}
76996
+ `);
76997
+ return 0;
76998
+ }
76999
+ function runSetUpdates(value, deps) {
77000
+ const out = deps.out ?? process.stdout;
77001
+ if (!isUpdatesMode(value)) {
77002
+ out.write(SET_USAGE);
77003
+ return 2;
77004
+ }
77005
+ const { env, configDir } = upgradePaths(deps);
77006
+ const error = writeUpdatesMode(env, value);
77007
+ if (error) {
77008
+ out.write(`updates not changed: ${error}
77009
+ `);
77010
+ return 1;
77011
+ }
77012
+ out.write(`updates: ${value} (saved in ${path51.join(configDir, "config.json")})
77013
+ `);
77014
+ return 0;
77015
+ }
77016
+ var APPLY = "workit upgrade --yes", SET_USAGE, statusOf = (installed, latest) => !latest ? "unavailable" : !installed ? "unknown" : versionAtLeast(installed, latest) ? "current" : "update", LABEL;
77017
+ var init_check = __esm(() => {
77018
+ init_config();
77019
+ init_package();
77020
+ init_style();
77021
+ init_update_check();
77022
+ init_plan();
77023
+ init_shared();
77024
+ SET_USAGE = `Usage: workit upgrade --set-updates=${UPDATES_MODES.join("|")}
77025
+ `;
77026
+ LABEL = {
77027
+ current: "current",
77028
+ update: "update available",
77029
+ unknown: "installed version unknown",
77030
+ unavailable: "registry unavailable",
77031
+ unreadable: "could not be read"
77032
+ };
77033
+ });
77034
+
76659
77035
  // packages/workit-cli/src/upgrade/report.ts
76660
77036
  var pad2 = (text) => text.padEnd(12), PLAIN, summary = (plan, permissions, style = PLAIN) => {
76661
77037
  const host = (name) => ` ${style.bold(pad2(name))}`;
@@ -76683,8 +77059,8 @@ var pad2 = (text) => text.padEnd(12), PLAIN, summary = (plan, permissions, style
76683
77059
  return lines.join(`
76684
77060
  `) + `
76685
77061
  `;
76686
- }, LABEL, reasonFor = (entry) => {
76687
- const label = LABEL[entry.status];
77062
+ }, LABEL2, reasonFor = (entry) => {
77063
+ const label = LABEL2[entry.status];
76688
77064
  const head = entry.reason.slice(0, label.length);
76689
77065
  return entry.status !== "failed" && head.toLowerCase() === label.toLowerCase() && !/^[a-z]/i.test(entry.reason[label.length] ?? "") ? entry.reason.slice(label.length).replace(/^[\s:;,-]+/, "") : entry.reason;
76690
77066
  }, PAINT, table = (hosts, style = PLAIN) => [
@@ -76692,7 +77068,7 @@ var pad2 = (text) => text.padEnd(12), PLAIN, summary = (plan, permissions, style
76692
77068
  ...hosts.map((entry) => {
76693
77069
  const paint = style[PAINT[entry.status]];
76694
77070
  const reason = reasonFor(entry);
76695
- return ` ${style.bold(pad2(entry.host))}${paint(LABEL[entry.status])}${" ".repeat(16 - LABEL[entry.status].length)}${entry.status === "current" ? style.dim(reason) : reason}${entry.fix && entry.status !== "updated" && entry.status !== "current" ? `
77071
+ return ` ${style.bold(pad2(entry.host))}${paint(LABEL2[entry.status])}${" ".repeat(16 - LABEL2[entry.status].length)}${entry.status === "current" ? style.dim(reason) : reason}${entry.fix && entry.status !== "updated" && entry.status !== "current" ? `
76696
77072
  ${pad2("")}${"".padEnd(16)}fix: ${style.command(entry.fix)}` : ""}`;
76697
77073
  })
76698
77074
  ].join(`
@@ -76709,7 +77085,7 @@ var pad2 = (text) => text.padEnd(12), PLAIN, summary = (plan, permissions, style
76709
77085
  var init_report = __esm(() => {
76710
77086
  init_style();
76711
77087
  PLAIN = createStyle({ json: true });
76712
- LABEL = {
77088
+ LABEL2 = {
76713
77089
  updated: "updated",
76714
77090
  current: "already current",
76715
77091
  skipped: "skipped",
@@ -76724,9 +77100,23 @@ var init_report = __esm(() => {
76724
77100
  });
76725
77101
 
76726
77102
  // packages/workit-cli/src/upgrade.ts
76727
- import { spawnSync as spawnSync17 } from "node:child_process";
77103
+ var exports_upgrade = {};
77104
+ __export(exports_upgrade, {
77105
+ runLaunchCommand: () => runLaunchCommand,
77106
+ runUpgradeCommand: () => runUpgradeCommand
77107
+ });
77108
+ import { spawnSync as spawnSync18 } from "node:child_process";
76728
77109
  async function runUpgradeCommand(argv, deps = {}) {
76729
77110
  const out = deps.out ?? process.stdout;
77111
+ const setting = argv.find((arg) => arg.startsWith("--set-updates="));
77112
+ if (argv.includes("--check") || setting) {
77113
+ const extra = argv.filter((arg) => arg !== "--check" && arg !== "--json" && arg !== setting);
77114
+ if (extra.length || setting && argv.length > 1) {
77115
+ out.write(USAGE3);
77116
+ return 2;
77117
+ }
77118
+ return setting ? runSetUpdates(setting.slice("--set-updates=".length), deps) : runUpdateCheck(argv.includes("--json"), deps);
77119
+ }
76730
77120
  const flags = new Set(argv);
76731
77121
  const unknown = argv.filter((arg) => !["--apply", "--confirm", "--json", "--cli", "--preview", "--yes"].includes(arg) && !arg.startsWith("--hosts="));
76732
77122
  const hostFlag = argv.find((arg) => arg.startsWith("--hosts="))?.slice(8);
@@ -76753,7 +77143,7 @@ async function runUpgradeCommand(argv, deps = {}) {
76753
77143
  plan.ok = plan.blocked.length === 0 && plan.failed.length === 0;
76754
77144
  const { home, env } = upgradePaths(deps);
76755
77145
  const style = createStyle({
76756
- stream: out === process.stdout ? process.stdout : undefined,
77146
+ stream: out === process.stdout ? process.stdout : out === process.stderr ? process.stderr : undefined,
76757
77147
  env,
76758
77148
  json
76759
77149
  });
@@ -76819,6 +77209,7 @@ Nothing changed.
76819
77209
  ...entry.status === "written" ? {} : { fix: `workit setup --hosts=${entry.host}` }
76820
77210
  });
76821
77211
  }
77212
+ deps.onResult?.(result.hosts);
76822
77213
  const failed = !result.ok || !permissionsOk;
76823
77214
  const cliVersion = result.hosts.some((h) => h.host === "cli" && h.status === "updated") ? plan.cli.latest : package_default.version;
76824
77215
  const report = progress.runSync("Checking the result with workit doctor", () => (deps.doctor ?? ((version) => runDoctor({ home, env, cliVersion: version, only: "upgrade" })))(cliVersion));
@@ -76896,12 +77287,14 @@ async function runLaunchCommand(argv, deps = {}) {
76896
77287
  }
76897
77288
  if (deps.run)
76898
77289
  return deps.run(host, hostArgs).status ?? 1;
76899
- return spawnSync17(launch.command, launch.args, {
77290
+ return spawnSync18(launch.command, launch.args, {
76900
77291
  stdio: "inherit",
76901
77292
  env
76902
77293
  }).status ?? 1;
76903
77294
  }
76904
77295
  var USAGE3 = `Usage: workit upgrade [--hosts=opencode,cursor,codex,pi,claude-code|none] [--cli] [--preview | --yes | --apply --confirm] [--json]
77296
+ workit upgrade --check [--json]
77297
+ workit upgrade --set-updates=prompt|auto|off
76905
77298
  `;
76906
77299
  var init_upgrade = __esm(() => {
76907
77300
  init_package();
@@ -76911,6 +77304,7 @@ var init_upgrade = __esm(() => {
76911
77304
  init_progress();
76912
77305
  init_style();
76913
77306
  init_apply();
77307
+ init_check();
76914
77308
  init_plan();
76915
77309
  init_report();
76916
77310
  init_shared();
@@ -76920,8 +77314,8 @@ var init_upgrade = __esm(() => {
76920
77314
  });
76921
77315
 
76922
77316
  // packages/workit-cli/src/verbs/upgrade.ts
76923
- var exports_upgrade = {};
76924
- __export(exports_upgrade, {
77317
+ var exports_upgrade2 = {};
77318
+ __export(exports_upgrade2, {
76925
77319
  run: () => run5
76926
77320
  });
76927
77321
  var run5 = (argv) => runUpgradeCommand(argv);
@@ -76940,9 +77334,9 @@ var init_launch = __esm(() => {
76940
77334
  });
76941
77335
 
76942
77336
  // packages/workit-core/src/knowledge.ts
76943
- import { spawnSync as spawnSync18 } from "node:child_process";
77337
+ import { spawnSync as spawnSync19 } from "node:child_process";
76944
77338
  import fs20 from "node:fs";
76945
- import path49 from "node:path";
77339
+ import path52 from "node:path";
76946
77340
  function lintKnowledge(root) {
76947
77341
  const seen = new Set;
76948
77342
  const unreadable = [];
@@ -77046,7 +77440,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
77046
77440
  const end = lines.indexOf("---", 1);
77047
77441
  return end === -1 ? lines : [...lines.slice(0, end + 1).map(() => ""), ...lines.slice(end + 1)];
77048
77442
  }, read = (root, file) => {
77049
- const full = path49.join(root, file);
77443
+ const full = path52.join(root, file);
77050
77444
  try {
77051
77445
  fs20.lstatSync(full);
77052
77446
  } catch {
@@ -77061,7 +77455,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
77061
77455
  return "unreadable";
77062
77456
  }
77063
77457
  }, trackedTopLevel = (root) => {
77064
- const run = spawnSync18("git", ["ls-files", "-z", "--cached"], {
77458
+ const run = spawnSync19("git", ["ls-files", "-z", "--cached"], {
77065
77459
  cwd: root,
77066
77460
  encoding: "utf8",
77067
77461
  maxBuffer: 256 * 1024 * 1024,
@@ -77087,7 +77481,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
77087
77481
  }
77088
77482
  }, brokenLinks = (root, doc, tracked) => {
77089
77483
  const findings = [];
77090
- const base = path49.dirname(path49.join(root, doc.file));
77484
+ const base = path52.dirname(path52.join(root, doc.file));
77091
77485
  const missing = (target, line, how) => findings.push({
77092
77486
  rule: "broken-link",
77093
77487
  file: doc.file,
@@ -77106,7 +77500,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
77106
77500
  const local = localTarget(target);
77107
77501
  if (!local)
77108
77502
  continue;
77109
- const resolved = local.startsWith("/") ? path49.join(root, local) : path49.resolve(base, local);
77503
+ const resolved = local.startsWith("/") ? path52.join(root, local) : path52.resolve(base, local);
77110
77504
  if (!exists2(resolved))
77111
77505
  missing(target, index + 1, "link");
77112
77506
  }
@@ -77116,9 +77510,9 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
77116
77510
  continue;
77117
77511
  const relative = /^\.\.?\//.test(candidate);
77118
77512
  const first = candidate.split("/")[0];
77119
- if (!relative && !(tracked ? tracked.has(first) : exists2(path49.join(root, first))))
77513
+ if (!relative && !(tracked ? tracked.has(first) : exists2(path52.join(root, first))))
77120
77514
  continue;
77121
- const resolved = relative ? path49.resolve(base, candidate) : path49.join(root, candidate);
77515
+ const resolved = relative ? path52.resolve(base, candidate) : path52.join(root, candidate);
77122
77516
  if (!exists2(resolved))
77123
77517
  missing(span, index + 1, "pointer");
77124
77518
  }
@@ -77484,11 +77878,11 @@ var init_redact = __esm(() => {
77484
77878
  });
77485
77879
 
77486
77880
  // packages/workit-core/src/checks.ts
77487
- import { spawn as spawn3, spawnSync as spawnSync19 } from "node:child_process";
77881
+ import { spawn as spawn4, spawnSync as spawnSync20 } from "node:child_process";
77488
77882
  import { createHash as createHash17 } from "node:crypto";
77489
77883
  import fs21 from "node:fs";
77490
- import os18 from "node:os";
77491
- import path50 from "node:path";
77884
+ import os19 from "node:os";
77885
+ import path53 from "node:path";
77492
77886
  import { StringDecoder } from "node:string_decoder";
77493
77887
  function tailLines(text, lines = TAIL_LINES) {
77494
77888
  const all = text.replace(/\r\n?/gu, `
@@ -77608,7 +78002,7 @@ function planSpawn(argv, options) {
77608
78002
  return { file: argv[0], args: [], verbatim: false, shell: true };
77609
78003
  if (options.platform !== "win32")
77610
78004
  return { file: argv[0], args: argv.slice(1), verbatim: false, shell: false };
77611
- const win = path50.win32;
78005
+ const win = path53.win32;
77612
78006
  const isFile = options.isFile ?? ((file) => {
77613
78007
  try {
77614
78008
  return fs21.statSync(file).isFile();
@@ -77666,7 +78060,7 @@ function runCheckCommand(argv, options) {
77666
78060
  if (!child?.pid)
77667
78061
  return;
77668
78062
  if (windows)
77669
- spawnSync19("taskkill", ["/pid", String(child.pid), "/T", "/F"], {
78063
+ spawnSync20("taskkill", ["/pid", String(child.pid), "/T", "/F"], {
77670
78064
  stdio: "ignore",
77671
78065
  windowsHide: true
77672
78066
  });
@@ -77693,7 +78087,7 @@ function runCheckCommand(argv, options) {
77693
78087
  `);
77694
78088
  redactor.end();
77695
78089
  resolve({
77696
- exitCode: spawnError ? 127 : code !== null ? code : 128 + (signal ? os18.constants.signals[signal] ?? 1 : 1),
78090
+ exitCode: spawnError ? 127 : code !== null ? code : 128 + (signal ? os19.constants.signals[signal] ?? 1 : 1),
77697
78091
  signal: signal ?? null,
77698
78092
  timedOut,
77699
78093
  durationMs: Date.now() - started,
@@ -77713,7 +78107,7 @@ function runCheckCommand(argv, options) {
77713
78107
  shell: plan.shell
77714
78108
  };
77715
78109
  try {
77716
- child = spawn3(plan.file, plan.args, spawnOptions);
78110
+ child = spawn4(plan.file, plan.args, spawnOptions);
77717
78111
  } catch (error) {
77718
78112
  finish(null, null, error.code ?? error.message);
77719
78113
  return;
@@ -77770,10 +78164,10 @@ function runCheckCommand(argv, options) {
77770
78164
  function storeLog(storeRoot, log) {
77771
78165
  const digest = logDigest(log);
77772
78166
  const ref = `blobs/logs/${digest.slice("sha256:".length)}.log`;
77773
- const file = path50.join(storeRoot, ref);
78167
+ const file = path53.join(storeRoot, ref);
77774
78168
  try {
77775
78169
  if (!fs21.existsSync(file)) {
77776
- fs21.mkdirSync(path50.dirname(file), { recursive: true });
78170
+ fs21.mkdirSync(path53.dirname(file), { recursive: true });
77777
78171
  const temp = `${file}.${process.pid}.${Date.now()}.tmp`;
77778
78172
  fs21.writeFileSync(temp, log, { mode: 384 });
77779
78173
  fs21.renameSync(temp, file);
@@ -77786,7 +78180,7 @@ function storeLog(storeRoot, log) {
77786
78180
  function pruneCheckLogs(storeRoot, options = {}) {
77787
78181
  const limits = { ...LOG_RETENTION, ...options.retention };
77788
78182
  const now = options.now ?? Date.now();
77789
- const dir = path50.join(storeRoot, "blobs", "logs");
78183
+ const dir = path53.join(storeRoot, "blobs", "logs");
77790
78184
  const report = { removed: 0, removedBytes: 0, kept: 0 };
77791
78185
  let names;
77792
78186
  try {
@@ -77796,7 +78190,7 @@ function pruneCheckLogs(storeRoot, options = {}) {
77796
78190
  }
77797
78191
  const files = names.flatMap((name) => {
77798
78192
  try {
77799
- const stat = fs21.statSync(path50.join(dir, name));
78193
+ const stat = fs21.statSync(path53.join(dir, name));
77800
78194
  return stat.isFile() ? [{ name, size: stat.size, mtimeMs: stat.mtimeMs }] : [];
77801
78195
  } catch {
77802
78196
  return [];
@@ -77815,7 +78209,7 @@ function pruneCheckLogs(storeRoot, options = {}) {
77815
78209
  continue;
77816
78210
  if (!options.dryRun)
77817
78211
  try {
77818
- fs21.rmSync(path50.join(dir, file.name), { force: true });
78212
+ fs21.rmSync(path53.join(dir, file.name), { force: true });
77819
78213
  } catch {
77820
78214
  continue;
77821
78215
  }
@@ -78468,12 +78862,12 @@ var init_workspace = __esm(() => {
78468
78862
 
78469
78863
  // packages/workit-core/src/core/heavy-rules.ts
78470
78864
  import fs22 from "node:fs";
78471
- import path51 from "node:path";
78865
+ import path54 from "node:path";
78472
78866
  function gitTop(cwd) {
78473
- for (let dir = path51.resolve(cwd);; dir = path51.dirname(dir)) {
78474
- if (fs22.existsSync(path51.join(dir, ".git")))
78867
+ for (let dir = path54.resolve(cwd);; dir = path54.dirname(dir)) {
78868
+ if (fs22.existsSync(path54.join(dir, ".git")))
78475
78869
  return dir;
78476
- if (path51.dirname(dir) === dir)
78870
+ if (path54.dirname(dir) === dir)
78477
78871
  return null;
78478
78872
  }
78479
78873
  }
@@ -78514,19 +78908,19 @@ var init_heavy_rules = () => {};
78514
78908
 
78515
78909
  // packages/workit-core/src/core/heavy.ts
78516
78910
  import fs23 from "node:fs";
78517
- import os19 from "node:os";
78518
- import path52 from "node:path";
78911
+ import os20 from "node:os";
78912
+ import path55 from "node:path";
78519
78913
  function stateDir2(env, platform = process.platform) {
78520
78914
  if (env.WORKFLOW_TOOLKIT_STATE)
78521
78915
  return env.WORKFLOW_TOOLKIT_STATE;
78522
78916
  if (env.XDG_STATE_HOME)
78523
- return path52.join(env.XDG_STATE_HOME, "workit");
78524
- const home = env.HOME || os19.homedir();
78917
+ return path55.join(env.XDG_STATE_HOME, "workit");
78918
+ const home = env.HOME || os20.homedir();
78525
78919
  if (platform === "darwin")
78526
- return path52.join(home, "Library", "Application Support", "workit");
78920
+ return path55.join(home, "Library", "Application Support", "workit");
78527
78921
  if (platform === "win32")
78528
- return path52.join(env.LOCALAPPDATA ?? path52.join(home, "AppData", "Local"), "workit");
78529
- return path52.join(home, ".local", "state", "workit");
78922
+ return path55.join(env.LOCALAPPDATA ?? path55.join(home, "AppData", "Local"), "workit");
78923
+ return path55.join(home, ".local", "state", "workit");
78530
78924
  }
78531
78925
  function positional(words, from, values = PM_VALUES) {
78532
78926
  let index = from;
@@ -78666,7 +79060,7 @@ function machinePatterns(env) {
78666
79060
  return isRecord8(value) ? stringList2(value.patterns) : [];
78667
79061
  }
78668
79062
  function repoPatterns(cwd) {
78669
- return repoHeavyCommands(gitTop(cwd) ?? path52.resolve(cwd));
79063
+ return repoHeavyCommands(gitTop(cwd) ?? path55.resolve(cwd));
78670
79064
  }
78671
79065
  function heavyLines(lines, options) {
78672
79066
  const found = [];
@@ -78745,7 +79139,7 @@ function leaseRewrite(command) {
78745
79139
  return null;
78746
79140
  return `${prefix}workit check --heavy -- ${rest}`;
78747
79141
  }
78748
- var HEAVY_COMMANDS_FILE = "heavy-commands.json", heavyCommandsFile = (env) => path52.join(stateDir2(env), HEAVY_COMMANDS_FILE), HEAVY_SCRIPT, INFO_FLAGS, WATCH_FLAG, WATCH_SCRIPT, sub = (...names) => new Set(names), TOOLS, PM_VALUES, baseName2 = (word) => (word?.split(/[\\/]/u).at(-1) ?? "").toLowerCase().replace(/\.(?:exe|cmd|bat|ps1)$/u, ""), WORKIT, PYTHONS, NPM_INSTALL, NPM_RUN, NPM_TEST, EXEC, globWord = (word) => new RegExp(`^${word.replace(/[.+?^${}()|[\]\\]/gu, "\\$&").replaceAll("*", ".*")}$`, "u"), matches2 = (matchers, words) => matchers.length <= words.length && matchers.every((matcher, index) => index === 0 ? matcher.test(words[0]) || matcher.test(baseName2(words[0])) : matcher.test(words[index])), readJson2 = (file) => {
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) => {
78749
79143
  try {
78750
79144
  return JSON.parse(fs23.readFileSync(file, "utf8"));
78751
79145
  } catch {
@@ -78891,8 +79285,8 @@ var init_heavy = __esm(() => {
78891
79285
  // packages/workit-core/src/core/resources.ts
78892
79286
  import { randomUUID as randomUUID5 } from "node:crypto";
78893
79287
  import fs24 from "node:fs";
78894
- import os20 from "node:os";
78895
- import path53 from "node:path";
79288
+ import os21 from "node:os";
79289
+ import path56 from "node:path";
78896
79290
  function memoryValue(value, host) {
78897
79291
  const text = typeof value === "number" ? String(value) : typeof value === "string" ? value : "";
78898
79292
  const percent = PERCENT.exec(text.trim());
@@ -79088,7 +79482,7 @@ function tryOnce(options, record, reclaimed) {
79088
79482
  const text = `${JSON.stringify(record)}
79089
79483
  `;
79090
79484
  for (let slot = 0;slot < options.slots; slot += 1) {
79091
- const file = path53.join(options.dir, `slot-${slot}.json`);
79485
+ const file = path56.join(options.dir, `slot-${slot}.json`);
79092
79486
  for (let attempt = 0;attempt < 2; attempt += 1) {
79093
79487
  try {
79094
79488
  const fd = fs24.openSync(file, "wx", 384);
@@ -79133,7 +79527,7 @@ function leaseQueue(dir, probe = {}) {
79133
79527
  }
79134
79528
  const entries = [];
79135
79529
  for (const name of names.filter((item) => item.endsWith(".json")).toSorted()) {
79136
- const file = path53.join(queueDir(dir), name);
79530
+ const file = path56.join(queueDir(dir), name);
79137
79531
  const record = parseLease(readText5(file));
79138
79532
  if (!record)
79139
79533
  continue;
@@ -79149,9 +79543,9 @@ function leaseQueue(dir, probe = {}) {
79149
79543
  function waitersAhead(options, own) {
79150
79544
  let ahead = 0;
79151
79545
  for (const entry of leaseQueue(options.dir, options.probe)) {
79152
- if (path53.basename(entry.file) >= own)
79546
+ if (path56.basename(entry.file) >= own)
79153
79547
  break;
79154
- if (!TICKET.test(path53.basename(entry.file)))
79548
+ if (!TICKET.test(path56.basename(entry.file)))
79155
79549
  continue;
79156
79550
  if (entry.stale && reclaim(entry.file, (current) => !current || staleReason(current, options.probe) !== null))
79157
79551
  continue;
@@ -79163,7 +79557,7 @@ function liveHolders(options) {
79163
79557
  return leaseSlots(options.dir, options.slots, options.probe).filter((slot) => slot.holder && !slot.stale).map((slot) => slot.holder);
79164
79558
  }
79165
79559
  function writeTicket(file, record) {
79166
- fs24.mkdirSync(path53.dirname(file), { recursive: true, mode: 448 });
79560
+ fs24.mkdirSync(path56.dirname(file), { recursive: true, mode: 448 });
79167
79561
  fs24.writeFileSync(file, `${JSON.stringify(record)}
79168
79562
  `, { mode: 384 });
79169
79563
  }
@@ -79208,7 +79602,7 @@ async function acquireLease(options) {
79208
79602
  const reclaimed = [];
79209
79603
  let waitedOn = [];
79210
79604
  const name = ticketName(started, record.id);
79211
- const ticket = path53.join(queueDir(options.dir), name);
79605
+ const ticket = path56.join(queueDir(options.dir), name);
79212
79606
  const ticketRecord = {
79213
79607
  ...record,
79214
79608
  maxAgeMs: options.waitMs + 60000
@@ -79329,7 +79723,7 @@ function heldLease(dir, id, options = {}) {
79329
79723
  for (const name of names) {
79330
79724
  if (!/^slot-\d+\.json$/u.test(name))
79331
79725
  continue;
79332
- const lease = parseLease(readText5(path53.join(dir, name)));
79726
+ const lease = parseLease(readText5(path56.join(dir, name)));
79333
79727
  if (lease?.id === id && !staleReason(lease, options.probe) && (options.ancestor ?? isAncestor)(lease.pid))
79334
79728
  return lease;
79335
79729
  }
@@ -79384,10 +79778,10 @@ async function runScoped(run, wrapper, sinks) {
79384
79778
  }
79385
79779
  function firstNotice(env, session, key, now = Date.now()) {
79386
79780
  const id = (session ?? `ppid-${process.ppid}`).replace(/[^A-Za-z0-9_.-]/gu, "_").slice(0, 120);
79387
- const dir = path53.join(stateDir2(env), "notices");
79781
+ const dir = path56.join(stateDir2(env), "notices");
79388
79782
  try {
79389
79783
  fs24.mkdirSync(dir, { recursive: true, mode: 448 });
79390
- fs24.writeFileSync(path53.join(dir, `${key}-${id}`), `${new Date(now).toISOString()}
79784
+ fs24.writeFileSync(path56.join(dir, `${key}-${id}`), `${new Date(now).toISOString()}
79391
79785
  `, {
79392
79786
  flag: "wx",
79393
79787
  mode: 384
@@ -79397,7 +79791,7 @@ function firstNotice(env, session, key, now = Date.now()) {
79397
79791
  }
79398
79792
  try {
79399
79793
  for (const name of fs24.readdirSync(dir)) {
79400
- const file = path53.join(dir, name);
79794
+ const file = path56.join(dir, name);
79401
79795
  if (now - fs24.statSync(file).mtimeMs > NOTICE_TTL_MS)
79402
79796
  fs24.rmSync(file, { force: true });
79403
79797
  }
@@ -79407,7 +79801,7 @@ function firstNotice(env, session, key, now = Date.now()) {
79407
79801
  function leaseSlots(dir, slots, probe = {}) {
79408
79802
  const states = [];
79409
79803
  for (let slot = 0;slot < slots; slot += 1) {
79410
- const lease = parseLease(readText5(path53.join(dir, `slot-${slot}.json`)));
79804
+ const lease = parseLease(readText5(path56.join(dir, `slot-${slot}.json`)));
79411
79805
  states.push({
79412
79806
  slot,
79413
79807
  holder: lease ? holderOf(lease) : null,
@@ -79417,15 +79811,15 @@ function leaseSlots(dir, slots, probe = {}) {
79417
79811
  return states;
79418
79812
  }
79419
79813
  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 = () => ({
79420
- totalMemBytes: os20.totalmem(),
79421
- cpus: Math.max(1, os20.availableParallelism?.() ?? os20.cpus().length)
79422
- }), isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), SIZE, PERCENT, UNITS, leaseDir = (env) => path53.join(stateDir2(env), "leases"), readText5 = (file) => {
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) => {
79423
79817
  try {
79424
79818
  return fs24.readFileSync(file, "utf8");
79425
79819
  } catch {
79426
79820
  return null;
79427
79821
  }
79428
- }, bootId = () => readText5("/proc/sys/kernel/random/boot_id")?.trim() || null, bootTime = () => Math.round((Date.now() - os20.uptime() * 1000) / 1000) * 1000, BOOT_SLACK_MS = 120000, statFields = (pid) => {
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) => {
79429
79823
  const stat = readText5(`/proc/${pid}/stat`);
79430
79824
  return stat ? stat.slice(stat.lastIndexOf(")") + 2).split(" ") : null;
79431
79825
  }, processStart = (pid) => statFields(pid)?.[19] ?? null, pidAlive2 = (pid) => {
@@ -79450,7 +79844,7 @@ var DEFAULT_HEAVY_CHECKS, DEFAULT_LIGHT_CHECKS, DEFAULT_SLOTS = 1, DEFAULT_WAIT_
79450
79844
  cwd: lease.cwd,
79451
79845
  session: lease.session,
79452
79846
  startedAt: lease.startedAt
79453
- }), realClock, queueDir = (dir) => path53.join(dir, "queue"), TICKET, ticketName = (now, id) => `${String(now).padStart(15, "0")}-${String(process.hrtime.bigint() % 10n ** 16n).padStart(16, "0")}-${id}.json`, SCOPE_START_FAILURE, NOTICE_TTL_MS;
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;
79454
79848
  var init_resources = __esm(() => {
79455
79849
  init_checks3();
79456
79850
  init_heavy();
@@ -79479,8 +79873,8 @@ __export(exports_check, {
79479
79873
  run: () => run12,
79480
79874
  workspaceResources: () => workspaceResources
79481
79875
  });
79482
- import os21 from "node:os";
79483
- import path54 from "node:path";
79876
+ import os22 from "node:os";
79877
+ import path57 from "node:path";
79484
79878
  function parse6(argv) {
79485
79879
  const split = argv.indexOf("--");
79486
79880
  const head = split >= 0 ? argv.slice(0, split) : [...argv];
@@ -79711,7 +80105,7 @@ ${footer}`;
79711
80105
  }
79712
80106
  async function workspaceResources(io) {
79713
80107
  const env = io.env;
79714
- const dir = env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path54.join(env.XDG_CONFIG_HOME || path54.join(env.HOME || os21.homedir(), ".config"), "workit");
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");
79715
80109
  try {
79716
80110
  await Promise.resolve().then(() => init_workspaces());
79717
80111
  const workspace = resolveWorkspaceFrom(io.cwd, dir, env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined);
@@ -79853,7 +80247,7 @@ async function run12(argv, io) {
79853
80247
  if (options.shell && command.length !== 1)
79854
80248
  return emit(io, fail2("invalid_input", '--shell takes the command as one string: workit check --shell -- "<cmd>"'));
79855
80249
  }
79856
- const relCwd = posix(path54.relative(top, runCwd));
80250
+ const relCwd = posix(path57.relative(top, runCwd));
79857
80251
  const configured = !options.shell && matchesNamedCheck(config, name, command, relCwd);
79858
80252
  const shadowed = !configured && name !== null ? config.checks.find((item) => item.name === name) : undefined;
79859
80253
  if (shadowed)
@@ -79918,7 +80312,7 @@ async function run12(argv, io) {
79918
80312
  const modifiedWorktree = key.tree !== null && treeAfter !== key.tree;
79919
80313
  const store = storeRoot(io.cwd);
79920
80314
  const blob = store.ok ? storeLog(store.value.root, result.log) : null;
79921
- const logPath = store.ok && blob ? path54.join(store.value.root, blob.ref) : null;
80315
+ const logPath = store.ok && blob ? path57.join(store.value.root, blob.ref) : null;
79922
80316
  const tail = tailLines(result.log, TAIL_LINES);
79923
80317
  const passed = result.exitCode === 0 && !result.timedOut;
79924
80318
  const bounded = boundedArgv(command);
@@ -80033,8 +80427,8 @@ async function run12(argv, io) {
80033
80427
  return recordError.code === "busy" ? 4 : recordError.code === "invalid_input" ? 2 : 5;
80034
80428
  return 0;
80035
80429
  }
80036
- var USAGE6 = 'workit check <name> [--full] [--wait <dur> | --no-wait] [--no-lease --reason "<why>"] | workit check [--name <n>] [--shell] [--heavy] [--full] [--wait <dur> | --no-wait] [--timeout <s>] [--task <id>] [--json] -- <cmd…>', OUTPUT_LINES = 60, MAX_UNVERIFIED_RUN_MS, RECORD_TAIL_LINES = 20, RECORD_TAIL_CHARS = 200, posix = (value) => value.split(path54.sep).join("/") || ".", ENGINE_CODES2, FINGERPRINT_VARS, ANSI_COLOR, WARNING_LINE, NO_WARNINGS, STDERR_TAIL_LINES = 10, STDERR_KEEP_CHARS = 65536, FAILURE_LINE, MAX_FAILURE_LINES = 15;
80037
- var init_check = __esm(() => {
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;
80431
+ var init_check2 = __esm(() => {
80038
80432
  init_check_config();
80039
80433
  init_checks3();
80040
80434
  init_rev();
@@ -80064,7 +80458,7 @@ __export(exports_lock, {
80064
80458
  run: () => run13
80065
80459
  });
80066
80460
  import fs25 from "node:fs";
80067
- import path55 from "node:path";
80461
+ import path58 from "node:path";
80068
80462
  async function settingsFor(io) {
80069
80463
  const workspace = await workspaceResources(io);
80070
80464
  const config = loadCheckConfig(io.cwd);
@@ -80141,7 +80535,7 @@ async function runHeavy(args, io) {
80141
80535
  return emit(io, fail2("invalid_input", unknown ? `unexpected ${unknown}` : "no command after --", {
80142
80536
  unblock: "workit lock run [--shell] [--wait <dur> | --no-wait] [--timeout <s>] -- <cmd…>"
80143
80537
  }));
80144
- const check = await Promise.resolve().then(() => (init_check(), {}));
80538
+ const check = await Promise.resolve().then(() => (init_check2(), {}));
80145
80539
  return run12([`--heavy`, ...head, ...args.slice(split)], io);
80146
80540
  }
80147
80541
  function readPatterns(file) {
@@ -80156,7 +80550,7 @@ function readPatterns(file) {
80156
80550
  return { patterns: [] };
80157
80551
  }
80158
80552
  function writePatterns(file, value) {
80159
- fs25.mkdirSync(path55.dirname(file), { recursive: true, mode: 448 });
80553
+ fs25.mkdirSync(path58.dirname(file), { recursive: true, mode: 448 });
80160
80554
  const temp = `${file}.${process.pid}.tmp`;
80161
80555
  fs25.writeFileSync(temp, `${JSON.stringify(value, null, 2)}
80162
80556
  `, { mode: 384 });
@@ -80234,7 +80628,7 @@ var init_lock = __esm(() => {
80234
80628
  init_heavy();
80235
80629
  init_resources();
80236
80630
  init_output();
80237
- init_check();
80631
+ init_check2();
80238
80632
  });
80239
80633
 
80240
80634
  // packages/workit-cli/src/verbs/models.ts
@@ -80242,9 +80636,9 @@ var exports_models = {};
80242
80636
  __export(exports_models, {
80243
80637
  run: () => run14
80244
80638
  });
80245
- import { existsSync as existsSync25, readdirSync as readdirSync13, readFileSync as readFileSync24, statSync as statSync9 } from "node:fs";
80246
- import os22 from "node:os";
80247
- import path56 from "node:path";
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";
80248
80642
  async function run14(argv, io) {
80249
80643
  const [sub, ...args] = argv.filter((arg) => arg !== "--json");
80250
80644
  if (sub !== "show")
@@ -80305,7 +80699,7 @@ var USAGE8 = "workit models show [--role <role>] [--tier <tier>] [--host <host>]
80305
80699
  const found = new Set;
80306
80700
  let text = "";
80307
80701
  try {
80308
- text = readFileSync24(file, "utf8");
80702
+ text = readFileSync26(file, "utf8");
80309
80703
  } catch {
80310
80704
  return found;
80311
80705
  }
@@ -80319,24 +80713,24 @@ var USAGE8 = "workit models show [--role <role>] [--tier <tier>] [--host <host>]
80319
80713
  } catch {}
80320
80714
  return found;
80321
80715
  }, matches3 = (ran, configured) => ran.toLowerCase().includes(configured.toLowerCase()), usageReport = (cwd, env, days) => {
80322
- const projects = path56.join(env.CLAUDE_CONFIG_DIR || path56.join(env.HOME || os22.homedir(), ".claude"), "projects");
80716
+ const projects = path59.join(env.CLAUDE_CONFIG_DIR || path59.join(env.HOME || os23.homedir(), ".claude"), "projects");
80323
80717
  const since = Date.now() - days * 86400000;
80324
80718
  const types = {};
80325
80719
  let agents = 0;
80326
80720
  const dirs = (dir) => {
80327
80721
  try {
80328
- return readdirSync13(dir).map((name) => path56.join(dir, name));
80722
+ return readdirSync13(dir).map((name) => path59.join(dir, name));
80329
80723
  } catch {
80330
80724
  return [];
80331
80725
  }
80332
80726
  };
80333
80727
  for (const project of dirs(projects))
80334
80728
  for (const session of dirs(project))
80335
- for (const meta of dirs(path56.join(session, "subagents")).filter((f) => f.endsWith(".meta.json"))) {
80729
+ for (const meta of dirs(path59.join(session, "subagents")).filter((f) => f.endsWith(".meta.json"))) {
80336
80730
  try {
80337
80731
  if (statSync9(meta).mtimeMs < since)
80338
80732
  continue;
80339
- const agentType = JSON.parse(readFileSync24(meta, "utf8")).agentType;
80733
+ const agentType = JSON.parse(readFileSync26(meta, "utf8")).agentType;
80340
80734
  const transcript = meta.replace(/\.meta\.json$/, ".jsonl");
80341
80735
  if (typeof agentType !== "string" || !existsSync25(transcript))
80342
80736
  continue;
@@ -80476,9 +80870,9 @@ var init_youtrack_writes = __esm(() => {
80476
80870
  var success2 = (data) => ({ ok: true, data }), failure3 = (code, error, unblock) => ({ ok: false, code, error, ...unblock ? { unblock } : {} });
80477
80871
 
80478
80872
  // packages/workit-core/src/git/ops.ts
80479
- import { spawnSync as spawnSync20 } from "node:child_process";
80480
- import { existsSync as existsSync26, readFileSync as readFileSync25 } from "node:fs";
80481
- import path57 from "node:path";
80873
+ 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";
80482
80876
  function operationInProgress(cwd) {
80483
80877
  const markers = [
80484
80878
  ["rebase-merge", "rebase"],
@@ -80491,18 +80885,18 @@ function operationInProgress(cwd) {
80491
80885
  if (!run.ok)
80492
80886
  return null;
80493
80887
  const found = run.stdout.split(`
80494
- `).map((line) => path57.resolve(cwd, line.trim()));
80888
+ `).map((line) => path60.resolve(cwd, line.trim()));
80495
80889
  const conflicted = () => git5(cwd, ["ls-files", "-u"]).stdout.trim() !== "";
80496
80890
  for (const [index, [, operation]] of markers.entries()) {
80497
80891
  const marker = found[index];
80498
80892
  if (!marker || !existsSync26(marker))
80499
80893
  continue;
80500
- if (index === 1 && existsSync26(path57.join(marker, "applying")))
80894
+ if (index === 1 && existsSync26(path60.join(marker, "applying")))
80501
80895
  return { operation: "am", commitAllowed: false, branch: null };
80502
- if (index === 0 && existsSync26(path57.join(marker, "amend")) && !conflicted()) {
80896
+ if (index === 0 && existsSync26(path60.join(marker, "amend")) && !conflicted()) {
80503
80897
  let headName = "";
80504
80898
  try {
80505
- headName = readFileSync25(path57.join(marker, "head-name"), "utf8").trim();
80899
+ headName = readFileSync27(path60.join(marker, "head-name"), "utf8").trim();
80506
80900
  } catch {}
80507
80901
  const branch = headName.startsWith("refs/heads/") ? headName.slice("refs/heads/".length) : null;
80508
80902
  return { operation, commitAllowed: branch !== null, branch };
@@ -80837,7 +81231,7 @@ function gitCommit(cwd, input) {
80837
81231
  if (paths.some((value) => value.startsWith("-") || !value.trim()))
80838
81232
  return failure3("invalid_input", "paths must not be empty or start with -");
80839
81233
  const tracked = new Set(nulList(git5(cwd, ["ls-files", "-z", "--", ...paths]).stdout));
80840
- const addable = paths.filter((value) => existsSync26(path57.resolve(cwd, value)) || [...tracked].some((file) => file === value || file.startsWith(`${value}/`)));
81234
+ const addable = paths.filter((value) => existsSync26(path60.resolve(cwd, value)) || [...tracked].some((file) => file === value || file.startsWith(`${value}/`)));
80841
81235
  if (addable.length) {
80842
81236
  const added = git5(cwd, ["add", "-A", "--", ...addable]);
80843
81237
  if (!added.ok)
@@ -81310,7 +81704,7 @@ ${run.stdout}`;
81310
81704
  } : { ok: false, lease: false, error: gitError(run) };
81311
81705
  }
81312
81706
  var COMMIT_TIMEOUT_MS, PUSH_TIMEOUT_MS = 120000, git5 = (cwd, args, options = {}) => {
81313
- const result = spawnSync20("git", args, {
81707
+ const result = spawnSync21("git", args, {
81314
81708
  cwd,
81315
81709
  encoding: "utf8",
81316
81710
  env: { ...options.env ?? process.env, GIT_TERMINAL_PROMPT: "0" },
@@ -81378,12 +81772,12 @@ var init_ops = __esm(() => {
81378
81772
 
81379
81773
  // packages/workit-core/src/verdict-cover.ts
81380
81774
  import fs26 from "node:fs";
81381
- import path58 from "node:path";
81775
+ import path61 from "node:path";
81382
81776
  function chainsAbove(cwd, branch) {
81383
81777
  const root = storeRoot(cwd);
81384
81778
  if (!root.ok)
81385
81779
  return [];
81386
- const dir = path58.join(root.value.root, "stacks");
81780
+ const dir = path61.join(root.value.root, "stacks");
81387
81781
  let names = [];
81388
81782
  try {
81389
81783
  names = fs26.readdirSync(dir).filter((name) => name.endsWith(".json"));
@@ -81394,7 +81788,7 @@ function chainsAbove(cwd, branch) {
81394
81788
  for (const name of names.toSorted()) {
81395
81789
  let parsed;
81396
81790
  try {
81397
- parsed = JSON.parse(fs26.readFileSync(path58.join(dir, name), "utf8"));
81791
+ parsed = JSON.parse(fs26.readFileSync(path61.join(dir, name), "utf8"));
81398
81792
  } catch {
81399
81793
  continue;
81400
81794
  }
@@ -81550,10 +81944,10 @@ var init_check_evidence = __esm(() => {
81550
81944
 
81551
81945
  // packages/workit-core/src/forge/reruns.ts
81552
81946
  import fs27 from "node:fs";
81553
- import path59 from "node:path";
81947
+ import path62 from "node:path";
81554
81948
  function rerunLogPath(cwd) {
81555
81949
  const common = gitCommonDir(cwd);
81556
- return common ? path59.join(common, "workit", "ci-reruns.jsonl") : null;
81950
+ return common ? path62.join(common, "workit", "ci-reruns.jsonl") : null;
81557
81951
  }
81558
81952
  function rerunCounts(cwd, key) {
81559
81953
  const counts = new Map;
@@ -81588,7 +81982,7 @@ function recordReruns(cwd, rows) {
81588
81982
  if (!file)
81589
81983
  return false;
81590
81984
  try {
81591
- fs27.mkdirSync(path59.dirname(file), { recursive: true });
81985
+ fs27.mkdirSync(path62.dirname(file), { recursive: true });
81592
81986
  fs27.appendFileSync(file, rows.map((row) => `${JSON.stringify(row)}
81593
81987
  `).join(""));
81594
81988
  return true;
@@ -81601,7 +81995,7 @@ function withRerunLock(cwd, fn) {
81601
81995
  if (!file)
81602
81996
  return fn();
81603
81997
  const lock = `${file.slice(0, -".jsonl".length)}.lock`;
81604
- fs27.mkdirSync(path59.dirname(lock), { recursive: true });
81998
+ fs27.mkdirSync(path62.dirname(lock), { recursive: true });
81605
81999
  const until = Date.now() + LOCK_WAIT_MS2;
81606
82000
  for (;; ) {
81607
82001
  try {
@@ -82042,7 +82436,7 @@ var init_report2 = __esm(() => {
82042
82436
  });
82043
82437
 
82044
82438
  // packages/workit-core/src/forge/pr-ops.ts
82045
- import { spawnSync as spawnSync21 } from "node:child_process";
82439
+ import { spawnSync as spawnSync22 } from "node:child_process";
82046
82440
  function fillFromCommits(cwd, resolved, base) {
82047
82441
  const tracking = `refs/remotes/${resolved.baseRemote}/${base}`;
82048
82442
  if (!base.startsWith("-"))
@@ -82050,7 +82444,7 @@ function fillFromCommits(cwd, resolved, base) {
82050
82444
  const from = resolveRef(cwd, tracking) ?? resolveRef(cwd, `refs/heads/${base}`);
82051
82445
  if (!from)
82052
82446
  return failure3("not_found", `base ${base} is not available locally`, `git fetch ${resolved.baseRemote} ${base}`);
82053
- const log = spawnSync21("git", ["log", "--reverse", "--no-merges", "--format=%s%x1f%b%x1e", `${from}..HEAD`], {
82447
+ const log = spawnSync22("git", ["log", "--reverse", "--no-merges", "--format=%s%x1f%b%x1e", `${from}..HEAD`], {
82054
82448
  cwd,
82055
82449
  encoding: "utf8",
82056
82450
  timeout: GIT_TIMEOUTS.local,
@@ -82247,7 +82641,7 @@ function squashCommitList(cwd, resolved, base, head) {
82247
82641
  const from = resolveRef(cwd, `refs/remotes/${resolved.baseRemote}/${base}`) ?? resolveRef(cwd, `refs/heads/${base}`);
82248
82642
  if (!from)
82249
82643
  return "";
82250
- const log = spawnSync21("git", ["log", "--reverse", "--no-merges", "--format=%B%x1e", `${from}..${head}`], {
82644
+ const log = spawnSync22("git", ["log", "--reverse", "--no-merges", "--format=%B%x1e", `${from}..${head}`], {
82251
82645
  cwd,
82252
82646
  encoding: "utf8",
82253
82647
  timeout: GIT_TIMEOUTS.local,
@@ -82594,10 +82988,10 @@ var init_pr_ops = __esm(() => {
82594
82988
  });
82595
82989
 
82596
82990
  // packages/workit-core/src/stack.ts
82597
- import { spawnSync as spawnSync22 } from "node:child_process";
82991
+ import { spawnSync as spawnSync23 } from "node:child_process";
82598
82992
  import { createHash as createHash18, randomBytes as randomBytes4 } from "node:crypto";
82599
82993
  import fs28 from "node:fs";
82600
- import path60 from "node:path";
82994
+ import path63 from "node:path";
82601
82995
  function worktreeOf(cwd, branch) {
82602
82996
  const list = gitRun3(cwd, ["worktree", "list", "--porcelain"]);
82603
82997
  if (!list.ok)
@@ -82646,7 +83040,7 @@ function gitRestack(cwd, input) {
82646
83040
  error: "no store root"
82647
83041
  };
82648
83042
  fs28.mkdirSync(scratch, { recursive: true });
82649
- dir = path60.join(scratch, `${input.branch.replace(/[^A-Za-z0-9._-]+/gu, "_").slice(0, 40)}-${randomBytes4(4).toString("hex")}`);
83043
+ dir = path63.join(scratch, `${input.branch.replace(/[^A-Za-z0-9._-]+/gu, "_").slice(0, 40)}-${randomBytes4(4).toString("hex")}`);
82650
83044
  const added = gitRun3(cwd, ["worktree", "add", "-q", dir, input.branch], GIT_TIMEOUTS.worktree);
82651
83045
  if (!added.ok)
82652
83046
  return {
@@ -82702,7 +83096,7 @@ function pruneScratch(cwd) {
82702
83096
  if (!scratch || !fs28.existsSync(scratch))
82703
83097
  return;
82704
83098
  for (const name of fs28.readdirSync(scratch)) {
82705
- const dir = path60.join(scratch, name);
83099
+ const dir = path63.join(scratch, name);
82706
83100
  if (!rebaseInProgress(dir) && !trackedDirt(dir))
82707
83101
  gitRun3(cwd, ["worktree", "remove", "--force", dir]);
82708
83102
  }
@@ -82712,7 +83106,7 @@ function stacksDir(cwd) {
82712
83106
  const root = storeRoot(cwd);
82713
83107
  if (!root.ok)
82714
83108
  return stackFail(root.code, root.error, root.unblock);
82715
- return { ok: true, data: path60.join(root.value.root, "stacks") };
83109
+ return { ok: true, data: path63.join(root.value.root, "stacks") };
82716
83110
  }
82717
83111
  function parseStack(raw) {
82718
83112
  if (!isRecord12(raw) || !Array.isArray(raw.branches))
@@ -82764,7 +83158,7 @@ function readStack(cwd, name) {
82764
83158
  const dir = stacksDir(cwd);
82765
83159
  if (!dir.ok)
82766
83160
  return dir;
82767
- const file = path60.join(dir.data, fileFor(name));
83161
+ const file = path63.join(dir.data, fileFor(name));
82768
83162
  let text;
82769
83163
  try {
82770
83164
  text = fs28.readFileSync(file, "utf8");
@@ -82785,7 +83179,7 @@ function writeStack(cwd, stack, now = new Date) {
82785
83179
  const dir = stacksDir(cwd);
82786
83180
  if (!dir.ok)
82787
83181
  return dir;
82788
- const file = path60.join(dir.data, fileFor(stack.name));
83182
+ const file = path63.join(dir.data, fileFor(stack.name));
82789
83183
  const temp = `${file}.${process.pid}.tmp`;
82790
83184
  try {
82791
83185
  fs28.mkdirSync(dir.data, { recursive: true });
@@ -82813,7 +83207,7 @@ function listStacks(cwd) {
82813
83207
  for (const name of names) {
82814
83208
  let parsed = null;
82815
83209
  try {
82816
- parsed = parseStack(JSON.parse(fs28.readFileSync(path60.join(dir.data, name), "utf8")));
83210
+ parsed = parseStack(JSON.parse(fs28.readFileSync(path63.join(dir.data, name), "utf8")));
82817
83211
  } catch {
82818
83212
  parsed = null;
82819
83213
  }
@@ -82875,7 +83269,7 @@ function takeLock(lock) {
82875
83269
  host: localLockHost(),
82876
83270
  nonce: randomBytes4(8).toString("hex")
82877
83271
  };
82878
- fs28.writeFileSync(path60.join(lock, OWNER), JSON.stringify(owner));
83272
+ fs28.writeFileSync(path63.join(lock, OWNER), JSON.stringify(owner));
82879
83273
  return owner;
82880
83274
  }
82881
83275
  function reapLock(lock, observed) {
@@ -82912,7 +83306,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
82912
83306
  return dir;
82913
83307
  if (!validName(name))
82914
83308
  return stackFail("invalid_input", "a stack name must be 1-200 printable characters");
82915
- const lock = path60.join(dir.data, `${fileFor(name)}.lock`);
83309
+ const lock = path63.join(dir.data, `${fileFor(name)}.lock`);
82916
83310
  try {
82917
83311
  fs28.mkdirSync(dir.data, { recursive: true });
82918
83312
  } catch (error) {
@@ -82942,7 +83336,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
82942
83336
  const touch = () => {
82943
83337
  try {
82944
83338
  const now = new Date;
82945
- fs28.utimesSync(path60.join(lock, OWNER), now, now);
83339
+ fs28.utimesSync(path63.join(lock, OWNER), now, now);
82946
83340
  } catch {}
82947
83341
  };
82948
83342
  const beat = setInterval(touch, HEARTBEAT_MS);
@@ -83130,7 +83524,7 @@ function commitKeys(cwd, range) {
83130
83524
  const patches = new Map;
83131
83525
  const diff = gitRun3(cwd, ["log", "--no-merges", "-p", "--format=commit %H", range]);
83132
83526
  if (diff.ok && diff.stdout.trim()) {
83133
- const ids = spawnSync22("git", ["patch-id", "--stable"], {
83527
+ const ids = spawnSync23("git", ["patch-id", "--stable"], {
83134
83528
  cwd,
83135
83529
  input: diff.stdout,
83136
83530
  encoding: "utf8",
@@ -83883,7 +84277,7 @@ var STACK_VERSION = 1, stackFail = (code, error, unblock, data) => ({
83883
84277
  ...unblock ? { unblock } : {},
83884
84278
  ...data ? { data } : {}
83885
84279
  }), fromForge = (result) => stackFail(result.code, result.error, result.unblock), stackDeps, gitRun3 = (cwd, args, timeoutMs = GIT_TIMEOUTS.local) => {
83886
- const run = spawnSync22("git", args, {
84280
+ const run = spawnSync23("git", args, {
83887
84281
  cwd,
83888
84282
  encoding: "utf8",
83889
84283
  timeout: timeoutMs,
@@ -83911,7 +84305,7 @@ var STACK_VERSION = 1, stackFail = (code, error, unblock, data) => ({
83911
84305
  return !status.ok || status.stdout.trim() !== "";
83912
84306
  }, scratchDir = (cwd) => {
83913
84307
  const dir = stacksDir(cwd);
83914
- return dir.ok ? path60.join(dir.data, "worktrees") : null;
84308
+ return dir.ok ? path63.join(dir.data, "worktrees") : null;
83915
84309
  }, firstLine = (run) => (`${run.stderr}
83916
84310
  ${run.stdout}`.split(`
83917
84311
  `).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) => {
@@ -83926,12 +84320,12 @@ ${run.stdout}`.split(`
83926
84320
  }, 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) => {
83927
84321
  let raw = null;
83928
84322
  try {
83929
- raw = fs28.readFileSync(path60.join(lock, OWNER), "utf8");
84323
+ raw = fs28.readFileSync(path63.join(lock, OWNER), "utf8");
83930
84324
  } catch {
83931
84325
  raw = null;
83932
84326
  }
83933
84327
  let age = null;
83934
- for (const target of [path60.join(lock, OWNER), lock])
84328
+ for (const target of [path63.join(lock, OWNER), lock])
83935
84329
  try {
83936
84330
  age = Date.now() - fs28.statSync(target).mtimeMs;
83937
84331
  break;
@@ -83972,10 +84366,10 @@ var init_stack = __esm(() => {
83972
84366
  });
83973
84367
 
83974
84368
  // packages/workit-core/src/fanout.ts
83975
- import { spawnSync as spawnSync23 } from "node:child_process";
84369
+ import { spawnSync as spawnSync24 } from "node:child_process";
83976
84370
  import { createHash as createHash19 } from "node:crypto";
83977
84371
  import fs29 from "node:fs";
83978
- import path61 from "node:path";
84372
+ import path64 from "node:path";
83979
84373
  function expandBraces2(pattern, limit = 64) {
83980
84374
  for (let index = 0;index < pattern.length; index += 1) {
83981
84375
  if (pattern[index] === "\\") {
@@ -84221,7 +84615,7 @@ function parsePlan(raw, defaults, name) {
84221
84615
  id,
84222
84616
  branch,
84223
84617
  base: optional("base") ?? "",
84224
- worktree: path61.resolve(defaults.root, optional("worktree") ?? path61.join(defaults.worktreeRoot, id)),
84618
+ worktree: path64.resolve(defaults.root, optional("worktree") ?? path64.join(defaults.worktreeRoot, id)),
84225
84619
  tier,
84226
84620
  reason,
84227
84621
  dependsOn: [...new Set(dependsOn ?? [])],
@@ -84350,12 +84744,12 @@ function regeneratedFiles(root, tracked) {
84350
84744
  const found = new Map;
84351
84745
  let scripts;
84352
84746
  try {
84353
- const manifest = JSON.parse(fs29.readFileSync(path61.join(root, "package.json"), "utf8"));
84747
+ const manifest = JSON.parse(fs29.readFileSync(path64.join(root, "package.json"), "utf8"));
84354
84748
  scripts = manifest.scripts ?? {};
84355
84749
  } catch {
84356
84750
  return found;
84357
84751
  }
84358
- const runner = fs29.existsSync(path61.join(root, "bun.lock")) ? "bun run" : fs29.existsSync(path61.join(root, "pnpm-lock.yaml")) ? "pnpm run" : fs29.existsSync(path61.join(root, "yarn.lock")) ? "yarn run" : "npm run";
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";
84359
84753
  const outputs = tracked.filter((file) => !CODE.test(file));
84360
84754
  for (const [name, command] of Object.entries(scripts)) {
84361
84755
  if (!name.startsWith("write:") || typeof command !== "string")
@@ -84363,7 +84757,7 @@ function regeneratedFiles(root, tracked) {
84363
84757
  for (const file of command.match(/[\w./-]+\.[cm]?[jt]s\b/gu) ?? []) {
84364
84758
  let source;
84365
84759
  try {
84366
- source = fs29.readFileSync(path61.join(root, file), "utf8");
84760
+ source = fs29.readFileSync(path64.join(root, file), "utf8");
84367
84761
  } catch {
84368
84762
  continue;
84369
84763
  }
@@ -84485,11 +84879,11 @@ function defaultTrunk(cwd) {
84485
84879
  }
84486
84880
  function mainCheckout(cwd) {
84487
84881
  const common = gitCommonDir(cwd);
84488
- return common && path61.basename(common) === ".git" ? path61.dirname(common) : path61.resolve(cwd);
84882
+ return common && path64.basename(common) === ".git" ? path64.dirname(common) : path64.resolve(cwd);
84489
84883
  }
84490
84884
  function worktreeRoot(cwd) {
84491
84885
  const main = mainCheckout(cwd);
84492
- return path61.join(path61.dirname(main), `${path61.basename(main)}-wt`);
84886
+ return path64.join(path64.dirname(main), `${path64.basename(main)}-wt`);
84493
84887
  }
84494
84888
  function sliceHash(slice) {
84495
84889
  const {
@@ -84509,7 +84903,7 @@ function fanoutsDir(cwd) {
84509
84903
  const root = storeRoot(cwd);
84510
84904
  if (!root.ok)
84511
84905
  return fanoutFail(root.code, root.error, root.unblock);
84512
- return { ok: true, data: path61.join(root.value.root, "fanouts") };
84906
+ return { ok: true, data: path64.join(root.value.root, "fanouts") };
84513
84907
  }
84514
84908
  function parseStored(raw) {
84515
84909
  if (!isRecord13(raw) || typeof raw.name !== "string" || typeof raw.trunk !== "string")
@@ -84577,7 +84971,7 @@ function readFanout(cwd, name) {
84577
84971
  const dir = fanoutsDir(cwd);
84578
84972
  if (!dir.ok)
84579
84973
  return dir;
84580
- const file = path61.join(dir.data, stackFileName(name));
84974
+ const file = path64.join(dir.data, stackFileName(name));
84581
84975
  let parsed = null;
84582
84976
  try {
84583
84977
  parsed = parseStored(JSON.parse(fs29.readFileSync(file, "utf8")));
@@ -84602,7 +84996,7 @@ function listFanouts(cwd) {
84602
84996
  for (const entry of names) {
84603
84997
  let parsed = null;
84604
84998
  try {
84605
- parsed = parseStored(JSON.parse(fs29.readFileSync(path61.join(dir.data, entry), "utf8")));
84999
+ parsed = parseStored(JSON.parse(fs29.readFileSync(path64.join(dir.data, entry), "utf8")));
84606
85000
  } catch {
84607
85001
  parsed = null;
84608
85002
  }
@@ -84641,7 +85035,7 @@ function writeFanout(cwd, plan) {
84641
85035
  const dir = fanoutsDir(cwd);
84642
85036
  if (!dir.ok)
84643
85037
  return dir;
84644
- const file = path61.join(dir.data, stackFileName(plan.name));
85038
+ const file = path64.join(dir.data, stackFileName(plan.name));
84645
85039
  const temp = `${file}.${process.pid}.tmp`;
84646
85040
  try {
84647
85041
  fs29.mkdirSync(dir.data, { recursive: true });
@@ -84809,7 +85203,7 @@ var FANOUT_VERSION = 1, TIERS, REASONS, FAN_IN_MODES, fanoutFail = (code, error,
84809
85203
  text: edges.map((edge) => `add "${edge.dependsOn}" to "dependsOn" of slice ${edge.slice}`).join("; ")
84810
85204
  };
84811
85205
  }, gitRun4 = (cwd, args, timeoutMs = GIT_TIMEOUTS.local) => {
84812
- const run = spawnSync23("git", args, {
85206
+ const run = spawnSync24("git", args, {
84813
85207
  cwd,
84814
85208
  encoding: "utf8",
84815
85209
  timeout: timeoutMs,
@@ -84850,15 +85244,15 @@ var init_fanout = __esm(() => {
84850
85244
  });
84851
85245
 
84852
85246
  // packages/workit-core/src/forge/exec.ts
84853
- import { spawnSync as spawnSync24 } from "node:child_process";
85247
+ import { spawnSync as spawnSync25 } from "node:child_process";
84854
85248
  import fs30 from "node:fs";
84855
- import path62 from "node:path";
85249
+ import path65 from "node:path";
84856
85250
  function findExecutable(bin, env) {
84857
- const dirs = (env.PATH ?? env.Path ?? "").split(path62.delimiter).filter(Boolean);
85251
+ const dirs = (env.PATH ?? env.Path ?? "").split(path65.delimiter).filter(Boolean);
84858
85252
  const exts = process.platform === "win32" ? [".exe"] : [""];
84859
85253
  for (const dir of dirs)
84860
85254
  for (const ext of exts) {
84861
- const candidate = path62.join(dir, `${bin}${ext}`);
85255
+ const candidate = path65.join(dir, `${bin}${ext}`);
84862
85256
  try {
84863
85257
  const stat = fs30.statSync(candidate);
84864
85258
  if (stat.isFile())
@@ -84885,7 +85279,7 @@ function systemRunner(kind, apiHost, env = process.env) {
84885
85279
  if (!exe)
84886
85280
  return { status: null, stdout: "", stderr: "", timedOut: false, missing: true };
84887
85281
  const token = options.token ? kind === "github" ? { GH_TOKEN: options.token, GH_ENTERPRISE_TOKEN: options.token } : { GITLAB_TOKEN: options.token } : {};
84888
- const result = spawnSync24(exe, [...args], {
85282
+ const result = spawnSync25(exe, [...args], {
84889
85283
  encoding: "utf8",
84890
85284
  env: { ...childEnv, ...token },
84891
85285
  maxBuffer: MAX_BUFFER2,
@@ -86220,7 +86614,7 @@ var init_issue_link = __esm(() => {
86220
86614
  });
86221
86615
 
86222
86616
  // packages/workit-core/src/forge/pr-edit.ts
86223
- import { spawnSync as spawnSync25 } from "node:child_process";
86617
+ import { spawnSync as spawnSync26 } from "node:child_process";
86224
86618
  function openPr(cwd, resolved, pr) {
86225
86619
  const grant = requireGrant(cwd, "pr");
86226
86620
  if (!grant.allowed)
@@ -86385,7 +86779,7 @@ function replyToThread(cwd, resolved, input) {
86385
86779
  });
86386
86780
  }
86387
86781
  var label2 = (resolved, number) => `${resolved.forge.kind === "github" ? "PR #" : "MR !"}${number}`, git6 = (cwd, args) => {
86388
- const run = spawnSync25("git", args, {
86782
+ const run = spawnSync26("git", args, {
86389
86783
  cwd,
86390
86784
  encoding: "utf8",
86391
86785
  timeout: GIT_TIMEOUTS.local,
@@ -86405,7 +86799,7 @@ var init_pr_edit = __esm(() => {
86405
86799
  });
86406
86800
 
86407
86801
  // packages/workit-core/src/fanout-landed.ts
86408
- import { spawnSync as spawnSync26 } from "node:child_process";
86802
+ import { spawnSync as spawnSync27 } from "node:child_process";
86409
86803
  function forgeBreaker(resolved) {
86410
86804
  if (!resolved)
86411
86805
  return { forge: null, down: () => null };
@@ -86510,7 +86904,7 @@ function trunkPatchIds(ctx, fork) {
86510
86904
  "--"
86511
86905
  ]);
86512
86906
  if (log.ok && log.stdout.trim()) {
86513
- const run = spawnSync26("git", ["patch-id", "--stable"], {
86907
+ const run = spawnSync27("git", ["patch-id", "--stable"], {
86514
86908
  cwd: ctx.cwd,
86515
86909
  input: log.stdout,
86516
86910
  encoding: "utf8",
@@ -86632,7 +87026,7 @@ var init_fanout_landed = __esm(() => {
86632
87026
  });
86633
87027
 
86634
87028
  // packages/workit-core/src/core/live-session.ts
86635
- import { spawnSync as spawnSync27 } from "node:child_process";
87029
+ import { spawnSync as spawnSync28 } from "node:child_process";
86636
87030
  var LIVE_SESSION_TTL_MS, liveProbe, PIDS;
86637
87031
  var init_live_session = __esm(() => {
86638
87032
  init_paths();
@@ -86641,14 +87035,14 @@ var init_live_session = __esm(() => {
86641
87035
  LIVE_SESSION_TTL_MS = 15 * 60000;
86642
87036
  liveProbe = {
86643
87037
  platform: process.platform,
86644
- run: (args) => spawnSync27("ps", args, { encoding: "utf8", timeout: 2000 }).stdout ?? "",
87038
+ run: (args) => spawnSync28("ps", args, { encoding: "utf8", timeout: 2000 }).stdout ?? "",
86645
87039
  start: (pid) => processStartOf(pid)
86646
87040
  };
86647
87041
  PIDS = new Map;
86648
87042
  });
86649
87043
 
86650
87044
  // packages/workit-core/src/hooks/write-gate.ts
86651
- import path63 from "node:path";
87045
+ import path66 from "node:path";
86652
87046
  var CASE_INSENSITIVE, PREFIXES2, SCRIPT_SHELLS, cache3, MUTATING_GIT, DRY_N, MUTATING_WORKIT_GIT, CD2, PUSHD2, POPD2, UNKNOWN_DIR;
86653
87047
  var init_write_gate = __esm(() => {
86654
87048
  init_task_store();
@@ -86688,7 +87082,7 @@ var init_write_gate = __esm(() => {
86688
87082
  CD2 = new Set(["cd", "chdir", "set-location", "sl"]);
86689
87083
  PUSHD2 = new Set(["pushd", "push-location"]);
86690
87084
  POPD2 = new Set(["popd", "pop-location"]);
86691
- UNKNOWN_DIR = path63.resolve(path63.parse(process.cwd()).root, ".workit-unknown-dir");
87085
+ UNKNOWN_DIR = path66.resolve(path66.parse(process.cwd()).root, ".workit-unknown-dir");
86692
87086
  });
86693
87087
 
86694
87088
  // packages/workit-core/src/hooks/worktree-confine.ts
@@ -86713,20 +87107,20 @@ var init_worktree_confine = __esm(() => {
86713
87107
 
86714
87108
  // packages/workit-core/src/worktree-deps.ts
86715
87109
  import fs31 from "node:fs";
86716
- import path64 from "node:path";
87110
+ import path67 from "node:path";
86717
87111
  function moduleDirs(main) {
86718
87112
  const out = [];
86719
87113
  const walk = (relative, depth) => {
86720
87114
  let entries;
86721
87115
  try {
86722
- entries = fs31.readdirSync(path64.join(main, relative), { withFileTypes: true });
87116
+ entries = fs31.readdirSync(path67.join(main, relative), { withFileTypes: true });
86723
87117
  } catch {
86724
87118
  return;
86725
87119
  }
86726
87120
  for (const entry of entries) {
86727
87121
  if (!entry.isDirectory())
86728
87122
  continue;
86729
- const child = path64.join(relative, entry.name);
87123
+ const child = path67.join(relative, entry.name);
86730
87124
  if (entry.name === MODULES)
86731
87125
  out.push(child);
86732
87126
  else if (depth < MAX_DEPTH2 && !entry.name.startsWith("."))
@@ -86740,8 +87134,8 @@ function linkEntry(main, worktree, source, target) {
86740
87134
  const stat = fs31.lstatSync(source);
86741
87135
  if (stat.isSymbolicLink()) {
86742
87136
  const link = fs31.readlinkSync(source);
86743
- const outside = path64.isAbsolute(link) && within(link, main) && !path64.relative(main, link).split(path64.sep).includes(MODULES);
86744
- const to = outside ? path64.join(worktree, path64.relative(main, link)) : link;
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;
86745
87139
  fs31.symlinkSync(to, target, process.platform === "win32" ? "junction" : undefined);
86746
87140
  return;
86747
87141
  }
@@ -86751,8 +87145,8 @@ function mirror(main, worktree, source, target, top) {
86751
87145
  fs31.mkdirSync(target);
86752
87146
  let count = 0;
86753
87147
  for (const entry of fs31.readdirSync(source, { withFileTypes: true })) {
86754
- const from = path64.join(source, entry.name);
86755
- const to = path64.join(target, entry.name);
87148
+ const from = path67.join(source, entry.name);
87149
+ const to = path67.join(target, entry.name);
86756
87150
  if (top && entry.isDirectory() && (entry.name.startsWith("@") || entry.name === ".bin"))
86757
87151
  count += mirror(main, worktree, from, to, false);
86758
87152
  else {
@@ -86768,16 +87162,16 @@ function linkWorktreeDependencies(main, worktree) {
86768
87162
  const dirs = [];
86769
87163
  let entries = 0;
86770
87164
  for (const relative of moduleDirs(main)) {
86771
- const target = path64.join(worktree, relative);
86772
- if (!fs31.existsSync(path64.dirname(target)) || fs31.existsSync(target))
87165
+ const target = path67.join(worktree, relative);
87166
+ if (!fs31.existsSync(path67.dirname(target)) || fs31.existsSync(target))
86773
87167
  continue;
86774
- if (!gitRun4(worktree, ["check-ignore", "-q", `${relative.split(path64.sep).join("/")}/`]).ok) {
86775
- notes.push(`${relative.split(path64.sep).join("/")} is not ignored by git, so it was not linked from ${main}; install dependencies in the worktree yourself`);
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`);
86776
87170
  continue;
86777
87171
  }
86778
87172
  try {
86779
- entries += mirror(main, worktree, path64.join(main, relative), target, true);
86780
- dirs.push(relative.split(path64.sep).join("/"));
87173
+ entries += mirror(main, worktree, path67.join(main, relative), target, true);
87174
+ dirs.push(relative.split(path67.sep).join("/"));
86781
87175
  } catch (error) {
86782
87176
  fs31.rmSync(target, { recursive: true, force: true });
86783
87177
  notes.push(`could not link ${relative} from ${main} (${error.message}); install dependencies in the worktree yourself`);
@@ -86790,8 +87184,8 @@ function linkWorktreeDependencies(main, worktree) {
86790
87184
  return { linked: { from: main, dirs, entries, ms }, notes };
86791
87185
  }
86792
87186
  var MODULES = "node_modules", MAX_DEPTH2 = 2, within = (child, parent) => {
86793
- const relative = path64.relative(parent, child);
86794
- return relative === "" || !relative.startsWith("..") && !path64.isAbsolute(relative);
87187
+ const relative = path67.relative(parent, child);
87188
+ return relative === "" || !relative.startsWith("..") && !path67.isAbsolute(relative);
86795
87189
  };
86796
87190
  var init_worktree_deps = __esm(() => {
86797
87191
  init_fanout();
@@ -86800,7 +87194,7 @@ var init_worktree_deps = __esm(() => {
86800
87194
  // packages/workit-core/src/fanout-worktree.ts
86801
87195
  import { randomBytes as randomBytes5 } from "node:crypto";
86802
87196
  import fs32 from "node:fs";
86803
- import path65 from "node:path";
87197
+ import path68 from "node:path";
86804
87198
  function rowSample(lines) {
86805
87199
  const out = [];
86806
87200
  let bytes = 0;
@@ -86860,7 +87254,7 @@ function adminDir(worktree) {
86860
87254
  const file = dir.stdout.trim();
86861
87255
  let token = null;
86862
87256
  try {
86863
- token = fs32.readFileSync(path65.join(file, FANOUT_TOKEN_FILE), "utf8").trim() || null;
87257
+ token = fs32.readFileSync(path68.join(file, FANOUT_TOKEN_FILE), "utf8").trim() || null;
86864
87258
  } catch {
86865
87259
  token = null;
86866
87260
  }
@@ -86868,7 +87262,7 @@ function adminDir(worktree) {
86868
87262
  const stat = worktreeDeps.stat(file);
86869
87263
  return {
86870
87264
  path: file,
86871
- id: path65.basename(file),
87265
+ id: path68.basename(file),
86872
87266
  ino: stat.ino.toString(),
86873
87267
  token,
86874
87268
  birthMs: stat.birthtimeNs > 0n ? Number(stat.birthtimeMs) : null,
@@ -86884,7 +87278,7 @@ function markAdminDir(worktree) {
86884
87278
  return null;
86885
87279
  const token = randomBytes5(16).toString("hex");
86886
87280
  try {
86887
- fs32.writeFileSync(path65.join(admin.path, FANOUT_TOKEN_FILE), `${token}
87281
+ fs32.writeFileSync(path68.join(admin.path, FANOUT_TOKEN_FILE), `${token}
86888
87282
  `);
86889
87283
  } catch {
86890
87284
  return null;
@@ -86899,7 +87293,7 @@ function excludeScratch(cwd) {
86899
87293
  const common = gitCommonDir(cwd);
86900
87294
  if (!common)
86901
87295
  return;
86902
- const file = path65.join(common, "info", "exclude");
87296
+ const file = path68.join(common, "info", "exclude");
86903
87297
  let text = "";
86904
87298
  try {
86905
87299
  text = fs32.readFileSync(file, "utf8");
@@ -86908,7 +87302,7 @@ function excludeScratch(cwd) {
86908
87302
  }
86909
87303
  if (text.split(/\r?\n/u).includes(EXCLUDE_LINE))
86910
87304
  return;
86911
- fs32.mkdirSync(path65.dirname(file), { recursive: true });
87305
+ fs32.mkdirSync(path68.dirname(file), { recursive: true });
86912
87306
  fs32.appendFileSync(file, `${text && !text.endsWith(`
86913
87307
  `) ? `
86914
87308
  ` : ""}# workit fanout: per-worker scratch dirs
@@ -86917,13 +87311,13 @@ ${EXCLUDE_LINE}
86917
87311
  }
86918
87312
  function worktreeDependencies(main, worktree) {
86919
87313
  for (const [name, install] of LOCKFILES2) {
86920
- const ours = readBytes(path65.join(main, name));
86921
- const theirs = readBytes(path65.join(worktree, name));
87314
+ const ours = readBytes(path68.join(main, name));
87315
+ const theirs = readBytes(path68.join(worktree, name));
86922
87316
  if (ours === null && theirs === null)
86923
87317
  continue;
86924
87318
  if (ours !== null && theirs !== null && ours.equals(theirs))
86925
87319
  continue;
86926
- if (fs32.existsSync(path65.join(worktree, "node_modules")))
87320
+ if (fs32.existsSync(path68.join(worktree, "node_modules")))
86927
87321
  break;
86928
87322
  const command = install(worktree);
86929
87323
  return {
@@ -86935,7 +87329,7 @@ function worktreeDependencies(main, worktree) {
86935
87329
  };
86936
87330
  }
86937
87331
  const stale = staleBunInstall(main);
86938
- if (stale && !fs32.existsSync(path65.join(worktree, "node_modules"))) {
87332
+ if (stale && !fs32.existsSync(path68.join(worktree, "node_modules"))) {
86939
87333
  const command = `bun install --frozen-lockfile --cwd ${worktree}`;
86940
87334
  return {
86941
87335
  linked: null,
@@ -86948,9 +87342,9 @@ function worktreeDependencies(main, worktree) {
86948
87342
  return { ...linkWorktreeDependencies(main, worktree), install: null };
86949
87343
  }
86950
87344
  function staleBunInstall(main) {
86951
- if (!fs32.existsSync(path65.join(main, "node_modules")))
87345
+ if (!fs32.existsSync(path68.join(main, "node_modules")))
86952
87346
  return null;
86953
- const text = readBytes(path65.join(main, "bun.lock"))?.toString("utf8");
87347
+ const text = readBytes(path68.join(main, "bun.lock"))?.toString("utf8");
86954
87348
  if (!text)
86955
87349
  return null;
86956
87350
  let packages;
@@ -86977,7 +87371,7 @@ function staleBunInstall(main) {
86977
87371
  const version = spec.slice(at + 1);
86978
87372
  if (name !== key || version.includes(":"))
86979
87373
  continue;
86980
- const manifest = readBytes(path65.join(main, "node_modules", key, "package.json"));
87374
+ const manifest = readBytes(path68.join(main, "node_modules", key, "package.json"));
86981
87375
  if (!manifest) {
86982
87376
  problems.push(`${key} missing`);
86983
87377
  continue;
@@ -86994,7 +87388,7 @@ function staleBunInstall(main) {
86994
87388
  return problems.length ? problems.join("; ") : null;
86995
87389
  }
86996
87390
  function ensureScratch(worktree) {
86997
- const scratch = path65.join(worktree, SCRATCH_DIR);
87391
+ const scratch = path68.join(worktree, SCRATCH_DIR);
86998
87392
  fs32.mkdirSync(scratch, { recursive: true });
86999
87393
  return scratch;
87000
87394
  }
@@ -87268,7 +87662,7 @@ function unpushedCount(cwd, branch) {
87268
87662
  return count.ok ? Number(count.stdout.trim()) : null;
87269
87663
  }
87270
87664
  function removeScratch(worktree) {
87271
- const scratch = path65.join(worktree, SCRATCH_DIR);
87665
+ const scratch = path68.join(worktree, SCRATCH_DIR);
87272
87666
  let stat;
87273
87667
  try {
87274
87668
  stat = fs32.lstatSync(scratch);
@@ -87284,16 +87678,16 @@ var SLOW, SCRATCH_DIR = ".workit-scratch", EXCLUDE_LINE, DIRTY_ROW_BYTES = 2000,
87284
87678
  try {
87285
87679
  return fs32.realpathSync.native(target);
87286
87680
  } catch {
87287
- return path65.resolve(target);
87681
+ return path68.resolve(target);
87288
87682
  }
87289
87683
  }, samePath = (a, b) => {
87290
87684
  const left = canonical2(a);
87291
87685
  const right = canonical2(b);
87292
87686
  return process.platform === "win32" || process.platform === "darwin" ? left.toLowerCase() === right.toLowerCase() : left === right;
87293
87687
  }, inside3 = (child, parent) => {
87294
- const relative = path65.relative(canonical2(parent), canonical2(child));
87295
- return relative === "" || !relative.startsWith("..") && !path65.isAbsolute(relative);
87296
- }, slicePath = (cwd, slice) => path65.isAbsolute(slice.worktree) ? slice.worktree : path65.resolve(mainCheckout(cwd), slice.worktree), CLOCK_SLACK_MS = 2000, worktreeDeps, LOCKFILES2, readBytes = (file) => {
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) => {
87297
87691
  try {
87298
87692
  return fs32.readFileSync(file);
87299
87693
  } catch {
@@ -87325,7 +87719,7 @@ var init_fanout_worktree = __esm(() => {
87325
87719
 
87326
87720
  // packages/workit-core/src/forge/merge-cleanup.ts
87327
87721
  import fs33 from "node:fs";
87328
- import path66 from "node:path";
87722
+ import path69 from "node:path";
87329
87723
  function cleanupMergedBranch(cwd, branch, mergedHead) {
87330
87724
  const out = { branchDeleted: false, worktreeRemoved: null, notes: [] };
87331
87725
  if (!branch || branch.startsWith("-"))
@@ -87385,13 +87779,13 @@ var SLOW2, isFanoutWorktree = (worktree) => {
87385
87779
  if (!dir.ok)
87386
87780
  return false;
87387
87781
  try {
87388
- return fs33.readFileSync(path66.join(dir.stdout.trim(), FANOUT_TOKEN_FILE), "utf8").trim() !== "";
87782
+ return fs33.readFileSync(path69.join(dir.stdout.trim(), FANOUT_TOKEN_FILE), "utf8").trim() !== "";
87389
87783
  } catch {
87390
87784
  return false;
87391
87785
  }
87392
87786
  }, inside4 = (child, parent) => {
87393
- const relative = path66.relative(fs33.realpathSync.native(parent), fs33.realpathSync.native(child));
87394
- return relative === "" || !relative.startsWith("..") && !path66.isAbsolute(relative);
87787
+ const relative = path69.relative(fs33.realpathSync.native(parent), fs33.realpathSync.native(child));
87788
+ return relative === "" || !relative.startsWith("..") && !path69.isAbsolute(relative);
87395
87789
  };
87396
87790
  var init_merge_cleanup = __esm(() => {
87397
87791
  init_fanout();
@@ -87672,7 +88066,7 @@ var init_duration = __esm(() => {
87672
88066
  });
87673
88067
 
87674
88068
  // packages/workit-cli/src/verbs/forge-common.ts
87675
- import { readFileSync as readFileSync26 } from "node:fs";
88069
+ import { readFileSync as readFileSync28 } from "node:fs";
87676
88070
  function parseFlags(argv, spec) {
87677
88071
  const parsed = { values: {}, booleans: new Set, lists: {}, positionals: [] };
87678
88072
  for (let index = 0;index < argv.length; index += 1) {
@@ -87830,7 +88224,7 @@ var init_forge_common = __esm(() => {
87830
88224
  forgeDeps = {
87831
88225
  runner: undefined,
87832
88226
  npm: undefined,
87833
- readStdin: () => readFileSync26(0, "utf8"),
88227
+ readStdin: () => readFileSync28(0, "utf8"),
87834
88228
  sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
87835
88229
  now: () => Date.now()
87836
88230
  };
@@ -87842,8 +88236,8 @@ __export(exports_pr, {
87842
88236
  checkPrTitle: () => checkPrTitle,
87843
88237
  run: () => run15
87844
88238
  });
87845
- import { existsSync as existsSync27, readFileSync as readFileSync27 } from "node:fs";
87846
- import path67 from "node:path";
88239
+ import { existsSync as existsSync27, readFileSync as readFileSync29 } from "node:fs";
88240
+ import path70 from "node:path";
87847
88241
  function titleRules(cwd) {
87848
88242
  let root;
87849
88243
  try {
@@ -87854,16 +88248,16 @@ function titleRules(cwd) {
87854
88248
  let text = null;
87855
88249
  let name = "";
87856
88250
  for (const candidate of COMMITLINT_FILES) {
87857
- const full = path67.join(root, candidate);
88251
+ const full = path70.join(root, candidate);
87858
88252
  if (!existsSync27(full))
87859
88253
  continue;
87860
- text = readFileSync27(full, "utf8");
88254
+ text = readFileSync29(full, "utf8");
87861
88255
  name = candidate;
87862
88256
  break;
87863
88257
  }
87864
88258
  if (text === null) {
87865
88259
  try {
87866
- const pkg = JSON.parse(readFileSync27(path67.join(root, "package.json"), "utf8"));
88260
+ const pkg = JSON.parse(readFileSync29(path70.join(root, "package.json"), "utf8"));
87867
88261
  if (pkg.commitlint === undefined)
87868
88262
  return { rules: null, note: null };
87869
88263
  text = JSON.stringify(pkg.commitlint);
@@ -87960,7 +88354,7 @@ function refuseTitle(io, title, line) {
87960
88354
  function readBodyFile(io, file) {
87961
88355
  try {
87962
88356
  return {
87963
- body: file === "-" ? forgeDeps.readStdin() : readFileSync27(path67.resolve(io.cwd, file), "utf8")
88357
+ body: file === "-" ? forgeDeps.readStdin() : readFileSync29(path70.resolve(io.cwd, file), "utf8")
87964
88358
  };
87965
88359
  } catch {
87966
88360
  return `cannot read --body-file ${file}`;
@@ -88849,8 +89243,8 @@ var exports_git = {};
88849
89243
  __export(exports_git, {
88850
89244
  run: () => run17
88851
89245
  });
88852
- import { readFileSync as readFileSync28 } from "node:fs";
88853
- import path68 from "node:path";
89246
+ import { readFileSync as readFileSync30 } from "node:fs";
89247
+ import path71 from "node:path";
88854
89248
  function kindHint(cwd, kind) {
88855
89249
  let kinds = [...BRANCH_KINDS];
88856
89250
  try {
@@ -88954,7 +89348,7 @@ function commitMessage(parsed, io) {
88954
89348
 
88955
89349
  `);
88956
89350
  try {
88957
- return file === "-" ? readFileSync28(0, "utf8") : readFileSync28(path68.resolve(io.cwd, file), "utf8");
89351
+ return file === "-" ? readFileSync30(0, "utf8") : readFileSync30(path71.resolve(io.cwd, file), "utf8");
88958
89352
  } catch (error) {
88959
89353
  return {
88960
89354
  error: `cannot read -F ${file}: ${error instanceof Error ? error.message : String(error)}`
@@ -89140,7 +89534,7 @@ var init_git2 = __esm(() => {
89140
89534
  });
89141
89535
 
89142
89536
  // packages/workit-core/src/forge/verify.ts
89143
- import { spawnSync as spawnSync28 } from "node:child_process";
89537
+ import { spawnSync as spawnSync29 } from "node:child_process";
89144
89538
  function finish(cwd, report, actor) {
89145
89539
  const delivered = report.observations.length > 0 && report.observations.every((entry) => entry.ok);
89146
89540
  const out = { ...report, delivered };
@@ -89353,7 +89747,7 @@ var NPM_NAME, SEMVER2, SAFE_ARG, systemNpm = (args) => {
89353
89747
  };
89354
89748
  const found = process.platform === "win32" ? findExecutable("npm.cmd", process.env) : null;
89355
89749
  const npmCmd = found && !/["%!^]/u.test(found) ? `"${found}"` : "npm.cmd";
89356
- const result = process.platform === "win32" ? spawnSync28(`${npmCmd} ${args.join(" ")}`, { ...options, shell: true }) : spawnSync28("npm", [...args], options);
89750
+ const result = process.platform === "win32" ? spawnSync29(`${npmCmd} ${args.join(" ")}`, { ...options, shell: true }) : spawnSync29("npm", [...args], options);
89357
89751
  return { status: result.status, stdout: result.stdout ?? "", stderr: result.stderr ?? "" };
89358
89752
  }, short3 = (sha) => sha ? sha.slice(0, 12) : "(absent)", npmView = (stdout) => {
89359
89753
  try {
@@ -90418,7 +90812,7 @@ var init_stack2 = __esm(() => {
90418
90812
  // packages/workit-core/src/fanout-brief.ts
90419
90813
  import { createHash as createHash20 } from "node:crypto";
90420
90814
  import fs35 from "node:fs";
90421
- import path69 from "node:path";
90815
+ import path72 from "node:path";
90422
90816
  function workerSession(lead, slice, attempt) {
90423
90817
  const tail = attempt === null ? "" : `+try${attempt}`;
90424
90818
  const full = `${lead}-w-${slice}${tail}`;
@@ -90501,7 +90895,7 @@ function renderBrief(cwd, plan, input) {
90501
90895
  "STANDING:",
90502
90896
  ...standing.length ? standing.map((order) => ` - ${order.what}`) : [" - none recorded beyond this brief"],
90503
90897
  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)`,
90504
- ...exists && typeof made?.install === "string" && !fs35.existsSync(path69.join(planned, "node_modules")) ? [`INSTALL: \`${made.install}\` first: the main checkout's node_modules was not linked here`] : [],
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`] : [],
90505
90899
  ...identityLines(identity, minted),
90506
90900
  ...rules(mode, branch, sliceBase, exists ? planned : null)
90507
90901
  ];
@@ -91043,7 +91437,7 @@ __export(exports_fanout, {
91043
91437
  run: () => run21
91044
91438
  });
91045
91439
  import fs36 from "node:fs";
91046
- import path70 from "node:path";
91440
+ import path73 from "node:path";
91047
91441
  function forgeFor(io, offline) {
91048
91442
  if (offline)
91049
91443
  return { forge: null, error: "--offline" };
@@ -91104,7 +91498,7 @@ function plan2(argv, io) {
91104
91498
  return usage4(io, "pass --trunk or --track, not both (--track picks the trunk)", PLAN_USAGE2);
91105
91499
  if (flags.positionals.length !== 1)
91106
91500
  return usage4(io, flags.positionals.length ? `unexpected argument ${flags.positionals[1]}` : "missing <plan.json>", PLAN_USAGE2);
91107
- const file = path70.resolve(io.cwd, flags.positionals[0]);
91501
+ const file = path73.resolve(io.cwd, flags.positionals[0]);
91108
91502
  let raw;
91109
91503
  try {
91110
91504
  raw = JSON.parse(fs36.readFileSync(file, "utf8"));
@@ -106680,7 +107074,7 @@ var init_ast = __esm(() => {
106680
107074
 
106681
107075
  // packages/workit-cli/src/test-audit/rules.ts
106682
107076
  import { builtinModules } from "node:module";
106683
- import path71 from "node:path";
107077
+ import path74 from "node:path";
106684
107078
  function testCallee(call) {
106685
107079
  let callee = call.callee;
106686
107080
  if (callee.type === "CallExpression")
@@ -107173,12 +107567,12 @@ function checkConstantsOnly(ctx, emit) {
107173
107567
  }
107174
107568
  function checkOverMocking(ctx, emit) {
107175
107569
  const { program } = ctx.parsed;
107176
- const unit = path71.basename(ctx.file).replace(/\.(?:[cm]?[jt]sx?)$/, "").replace(/\.(?:test|spec)$/, "");
107570
+ const unit = path74.basename(ctx.file).replace(/\.(?:[cm]?[jt]sx?)$/, "").replace(/\.(?:test|spec)$/, "");
107177
107571
  const mocked = find2(program, (node) => node.type === "CallExpression" && MODULE_MOCK.test(calleeName(node.callee) ?? "") && node.arguments[0]?.type === "StringLiteral");
107178
107572
  const internal = mocked.filter((call) => /^(?:\.|@\/|~\/)/.test(call.arguments[0].value));
107179
107573
  for (const call of mocked) {
107180
107574
  const spec = call.arguments[0].value;
107181
- const base = path71.basename(spec.replace(/\/index(?:\.[cm]?[jt]sx?)?$/, "")).replace(/\.(?:[cm]?[jt]sx?)$/, "");
107575
+ const base = path74.basename(spec.replace(/\/index(?:\.[cm]?[jt]sx?)?$/, "")).replace(/\.(?:[cm]?[jt]sx?)$/, "");
107182
107576
  if (base === unit)
107183
107577
  emit({
107184
107578
  rule: "over-mocking",
@@ -107566,11 +107960,11 @@ var init_rules = __esm(() => {
107566
107960
  });
107567
107961
 
107568
107962
  // packages/workit-cli/src/test-audit/audit.ts
107569
- import { spawnSync as spawnSync29 } from "node:child_process";
107570
- import { existsSync as existsSync28, readdirSync as readdirSync14, readFileSync as readFileSync29, statSync as statSync10 } from "node:fs";
107571
- import path72 from "node:path";
107963
+ 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";
107572
107966
  function git7(cwd, args) {
107573
- const run = spawnSync29("git", ["-c", "core.quotepath=off", ...args], {
107967
+ const run = spawnSync30("git", ["-c", "core.quotepath=off", ...args], {
107574
107968
  cwd,
107575
107969
  encoding: "utf8",
107576
107970
  maxBuffer: 64 * 1024 * 1024
@@ -107581,7 +107975,7 @@ function walkTests(dir, out) {
107581
107975
  for (const entry of readdirSync14(dir, { withFileTypes: true })) {
107582
107976
  if (entry.name.startsWith(".") && entry.name !== "." && entry.isDirectory())
107583
107977
  continue;
107584
- const full = path72.join(dir, entry.name);
107978
+ const full = path75.join(dir, entry.name);
107585
107979
  if (entry.isDirectory()) {
107586
107980
  if (!SKIP_DIRS.has(entry.name))
107587
107981
  walkTests(full, out);
@@ -107593,7 +107987,7 @@ function expandPaths(cwd, inputs) {
107593
107987
  const files = [];
107594
107988
  const missing = [];
107595
107989
  for (const input of inputs.length > 0 ? inputs : ["."]) {
107596
- const full = path72.resolve(cwd, input);
107990
+ const full = path75.resolve(cwd, input);
107597
107991
  if (!existsSync28(full))
107598
107992
  missing.push(input);
107599
107993
  else if (statSync10(full).isDirectory())
@@ -107630,11 +108024,11 @@ function changedLines(cwd, base) {
107630
108024
  for (let offset = 0;offset < count; offset += 1)
107631
108025
  lines.add(start + offset);
107632
108026
  }
107633
- changed.set(path72.join(root, file), lines);
108027
+ changed.set(path75.join(root, file), lines);
107634
108028
  }
107635
108029
  const untracked = git7(root, ["ls-files", "--others", "--exclude-standard", "-z"]);
107636
108030
  for (const file of untracked.stdout.split("\x00").filter(Boolean))
107637
- changed.set(path72.join(root, file), "all");
108031
+ changed.set(path75.join(root, file), "all");
107638
108032
  return changed;
107639
108033
  }
107640
108034
  function auditFiles(files, display) {
@@ -107647,7 +108041,7 @@ function auditFiles(files, display) {
107647
108041
  const shown = display(file);
107648
108042
  let parsed;
107649
108043
  try {
107650
- parsed = parseSource(readFileSync29(file, "utf8"), file);
108044
+ parsed = parseSource(readFileSync31(file, "utf8"), file);
107651
108045
  } catch (error) {
107652
108046
  parseErrors.push({
107653
108047
  file: shown,
@@ -107696,7 +108090,7 @@ function auditFiles(files, display) {
107696
108090
  durationMs: Math.round(performance.now() - started)
107697
108091
  };
107698
108092
  }
107699
- var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(path72.sep).join("/"), SEVERITY_ORDER, ruleIds;
108093
+ var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(path75.sep).join("/"), SEVERITY_ORDER, ruleIds;
107700
108094
  var init_audit = __esm(() => {
107701
108095
  init_ast();
107702
108096
  init_rules();
@@ -107708,25 +108102,25 @@ var init_audit = __esm(() => {
107708
108102
  });
107709
108103
 
107710
108104
  // packages/workit-cli/src/test-audit/mutate.ts
107711
- import { spawn as spawn4 } from "node:child_process";
108105
+ import { spawn as spawn5 } from "node:child_process";
107712
108106
  import {
107713
108107
  existsSync as existsSync29,
107714
108108
  lstatSync as lstatSync9,
107715
- mkdirSync as mkdirSync12,
108109
+ mkdirSync as mkdirSync13,
107716
108110
  mkdtempSync as mkdtempSync4,
107717
108111
  readdirSync as readdirSync15,
107718
- readFileSync as readFileSync30,
108112
+ readFileSync as readFileSync32,
107719
108113
  readlinkSync as readlinkSync3,
107720
108114
  realpathSync as realpathSync11,
107721
- renameSync as renameSync7,
108115
+ renameSync as renameSync8,
107722
108116
  rmSync as rmSync9,
107723
108117
  statSync as statSync11,
107724
108118
  symlinkSync,
107725
- writeFileSync as writeFileSync13,
108119
+ writeFileSync as writeFileSync14,
107726
108120
  copyFileSync as copyFileSync8
107727
108121
  } from "node:fs";
107728
- import os23 from "node:os";
107729
- import path73 from "node:path";
108122
+ import os24 from "node:os";
108123
+ import path76 from "node:path";
107730
108124
  function mutantsFor(source, file, lines) {
107731
108125
  const parsed = parseSource(source, file);
107732
108126
  const out = [];
@@ -107799,7 +108193,7 @@ function relatedTests(source, testFiles) {
107799
108193
  for (const match of text.matchAll(SPECIFIER)) {
107800
108194
  const spec = match[1];
107801
108195
  if (spec.startsWith(".")) {
107802
- if (stripExt(path73.posix.join(path73.posix.dirname(file), spec)) === target)
108196
+ if (stripExt(path76.posix.join(path76.posix.dirname(file), spec)) === target)
107803
108197
  return true;
107804
108198
  } else if (spec.includes("/") && stripExt(spec).split("/").slice(-2).join("/") === tail)
107805
108199
  return true;
@@ -107807,7 +108201,7 @@ function relatedTests(source, testFiles) {
107807
108201
  return false;
107808
108202
  }).map((entry) => entry.file);
107809
108203
  }
107810
- function removeStaleCopies(tmp = os23.tmpdir()) {
108204
+ function removeStaleCopies(tmp = os24.tmpdir()) {
107811
108205
  let removed = 0;
107812
108206
  let names = [];
107813
108207
  try {
@@ -107819,12 +108213,12 @@ function removeStaleCopies(tmp = os23.tmpdir()) {
107819
108213
  for (const name of names) {
107820
108214
  if (!name.startsWith(TEMP_PREFIX))
107821
108215
  continue;
107822
- const dir = path73.join(tmp, name);
108216
+ const dir = path76.join(tmp, name);
107823
108217
  try {
107824
108218
  const stat = lstatSync9(dir);
107825
108219
  if (!stat.isDirectory() || uid !== undefined && stat.uid !== uid)
107826
108220
  continue;
107827
- const pid = Number(readFileSync30(path73.join(dir, PID_FILE), "utf8"));
108221
+ const pid = Number(readFileSync32(path76.join(dir, PID_FILE), "utf8"));
107828
108222
  if (Number.isInteger(pid) && pid > 0 && alive(pid))
107829
108223
  continue;
107830
108224
  } catch (error) {
@@ -107839,16 +108233,16 @@ function removeStaleCopies(tmp = os23.tmpdir()) {
107839
108233
  return removed;
107840
108234
  }
107841
108235
  function linkNodeModules(origin, target, repo, copy) {
107842
- mkdirSync12(target, { recursive: true });
108236
+ mkdirSync13(target, { recursive: true });
107843
108237
  for (const entry of readdirSync15(origin, { withFileTypes: true })) {
107844
- const from = path73.join(origin, entry.name);
107845
- const to = path73.join(target, entry.name);
108238
+ const from = path76.join(origin, entry.name);
108239
+ const to = path76.join(target, entry.name);
107846
108240
  if (entry.name.startsWith("@") && entry.isDirectory()) {
107847
108241
  linkNodeModules(from, to, repo, copy);
107848
108242
  continue;
107849
108243
  }
107850
108244
  if (entry.name.startsWith(".") && entry.name !== ".bin" && entry.isDirectory()) {
107851
- mkdirSync12(to, { recursive: true });
108245
+ mkdirSync13(to, { recursive: true });
107852
108246
  continue;
107853
108247
  }
107854
108248
  if (entry.isSymbolicLink()) {
@@ -107858,9 +108252,9 @@ function linkNodeModules(origin, target, repo, copy) {
107858
108252
  } catch {
107859
108253
  continue;
107860
108254
  }
107861
- const relative = path73.relative(repo, real);
107862
- if (!relative.startsWith("..") && !path73.isAbsolute(relative) && !relative.split(path73.sep).includes("node_modules")) {
107863
- symlinkSync(path73.join(copy, relative), to, "junction");
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");
107864
108258
  continue;
107865
108259
  }
107866
108260
  }
@@ -107876,7 +108270,7 @@ function copySymlink(repo, tree, from, to) {
107876
108270
  }
107877
108271
  const realRepo = realpathSync11(repo);
107878
108272
  if (real && inside5(realRepo, real)) {
107879
- symlinkSync(path73.relative(path73.dirname(to), path73.join(tree, path73.relative(realRepo, real))), to);
108273
+ symlinkSync(path76.relative(path76.dirname(to), path76.join(tree, path76.relative(realRepo, real))), to);
107880
108274
  return;
107881
108275
  }
107882
108276
  if (real && statSync11(real).isFile())
@@ -107885,23 +108279,23 @@ function copySymlink(repo, tree, from, to) {
107885
108279
  symlinkSync(readlinkSync3(from), to);
107886
108280
  }
107887
108281
  function writeInside(copy, file, content) {
107888
- const target = path73.join(copy, file);
108282
+ const target = path76.join(copy, file);
107889
108283
  try {
107890
108284
  const stat = lstatSync9(target);
107891
- if (!stat.isFile() || !inside5(realpathSync11(copy), realpathSync11(path73.dirname(target))))
108285
+ if (!stat.isFile() || !inside5(realpathSync11(copy), realpathSync11(path76.dirname(target))))
107892
108286
  return false;
107893
108287
  } catch {
107894
108288
  return false;
107895
108289
  }
107896
108290
  const temp = `${target}.workit-mutant-${process.pid}`;
107897
- writeFileSync13(temp, content);
107898
- renameSync7(temp, target);
108291
+ writeFileSync14(temp, content);
108292
+ renameSync8(temp, target);
107899
108293
  return true;
107900
108294
  }
107901
108295
  function copyWorkingTree(repo) {
107902
- const dir = mkdtempSync4(path73.join(os23.tmpdir(), TEMP_PREFIX));
107903
- writeFileSync13(path73.join(dir, PID_FILE), String(process.pid));
107904
- const tree = path73.join(dir, "tree");
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");
107905
108299
  const head = git7(repo, ["rev-parse", "--verify", "--quiet", "HEAD"]).stdout.trim();
107906
108300
  if (head && git7(dir, ["clone", "-q", "--shared", "--no-checkout", repo, tree]).ok) {
107907
108301
  const branch = git7(repo, ["symbolic-ref", "--quiet", "--short", "HEAD"]).stdout.trim();
@@ -107912,42 +108306,42 @@ function copyWorkingTree(repo) {
107912
108306
  git7(tree, ["update-ref", "--no-deref", "HEAD", head]);
107913
108307
  git7(tree, ["reset", "-q"]);
107914
108308
  } else
107915
- mkdirSync12(tree, { recursive: true });
108309
+ mkdirSync13(tree, { recursive: true });
107916
108310
  const listed = git7(repo, ["ls-files", "-co", "--exclude-standard", "-z"]).stdout.split("\x00");
107917
108311
  const dirs = new Set([""]);
107918
108312
  for (const relative of listed) {
107919
108313
  if (!relative)
107920
108314
  continue;
107921
- const from = path73.join(repo, relative);
108315
+ const from = path76.join(repo, relative);
107922
108316
  let stat;
107923
108317
  try {
107924
108318
  stat = lstatSync9(from);
107925
108319
  } catch {
107926
108320
  continue;
107927
108321
  }
107928
- const to = path73.join(tree, relative);
107929
- mkdirSync12(path73.dirname(to), { recursive: true });
108322
+ const to = path76.join(tree, relative);
108323
+ mkdirSync13(path76.dirname(to), { recursive: true });
107930
108324
  if (stat.isSymbolicLink())
107931
108325
  copySymlink(repo, tree, from, to);
107932
108326
  else if (stat.isFile())
107933
108327
  copyFileSync8(from, to);
107934
- let parent = path73.dirname(relative);
108328
+ let parent = path76.dirname(relative);
107935
108329
  while (parent !== "." && !dirs.has(parent)) {
107936
108330
  dirs.add(parent);
107937
- parent = path73.dirname(parent);
108331
+ parent = path76.dirname(parent);
107938
108332
  }
107939
108333
  }
107940
108334
  for (const parent of dirs) {
107941
- const modules = path73.join(repo, parent, "node_modules");
107942
- if (existsSync29(modules) && !existsSync29(path73.join(tree, parent, "node_modules")))
107943
- linkNodeModules(modules, path73.join(tree, parent, "node_modules"), repo, tree);
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);
107944
108338
  }
107945
108339
  return { dir, tree };
107946
108340
  }
107947
108341
  function runCommand(command, cwd, timeoutMs, env) {
107948
108342
  const started = performance.now();
107949
108343
  return new Promise((resolve) => {
107950
- const child = spawn4(command, {
108344
+ const child = spawn5(command, {
107951
108345
  cwd,
107952
108346
  env,
107953
108347
  shell: true,
@@ -107979,20 +108373,20 @@ async function runMutation(options) {
107979
108373
  const tracked = git7(repo, ["ls-files", "-co", "--exclude-standard", "-z"]).stdout.split("\x00").filter(Boolean);
107980
108374
  const testFiles = tracked.filter((file) => TEST_FILE.test(file)).map((file) => {
107981
108375
  try {
107982
- return { file, text: readFileSync30(path73.join(repo, file), "utf8") };
108376
+ return { file, text: readFileSync32(path76.join(repo, file), "utf8") };
107983
108377
  } catch {
107984
108378
  return { file, text: "" };
107985
108379
  }
107986
108380
  });
107987
108381
  const candidates = [];
107988
108382
  for (const [absolute, lines] of [...options.changed].toSorted(([a], [b]) => a.localeCompare(b))) {
107989
- const relative = toPosix(path73.relative(repo, absolute));
108383
+ const relative = toPosix(path76.relative(repo, absolute));
107990
108384
  if (!CODE_FILE.test(relative) || TEST_FILE.test(relative) || relative.endsWith(".d.ts"))
107991
108385
  continue;
107992
108386
  if (NOT_SOURCE.test(relative) || !existsSync29(absolute))
107993
108387
  continue;
107994
108388
  try {
107995
- candidates.push(...mutantsFor(readFileSync30(absolute, "utf8"), relative, lines));
108389
+ candidates.push(...mutantsFor(readFileSync32(absolute, "utf8"), relative, lines));
107996
108390
  } catch {}
107997
108391
  }
107998
108392
  const mutants = candidates.map((mutant, index) => ({ ...mutant, id: index + 1 }));
@@ -108000,9 +108394,9 @@ async function runMutation(options) {
108000
108394
  for (const mutant of mutants)
108001
108395
  if (!related.has(mutant.file))
108002
108396
  related.set(mutant.file, relatedTests(mutant.file, testFiles));
108003
- const cwdRelative = path73.relative(repo, options.cwd);
108397
+ const cwdRelative = path76.relative(repo, options.cwd);
108004
108398
  const asArg = (file) => {
108005
- const relative = toPosix(path73.relative(cwdRelative, file));
108399
+ const relative = toPosix(path76.relative(cwdRelative, file));
108006
108400
  return shellQuote(relative.startsWith(".") ? relative : `./${relative}`);
108007
108401
  };
108008
108402
  const commandFor = (tests) => options.command.replaceAll("{files}", () => tests.map(asArg).join(" "));
@@ -108038,7 +108432,7 @@ async function runMutation(options) {
108038
108432
  return finish3(options, 0, results, counts, started);
108039
108433
  removeStaleCopies();
108040
108434
  const { dir: copyDir, tree: copy } = copyWorkingTree(repo);
108041
- const copyCwd = path73.join(copy, cwdRelative);
108435
+ const copyCwd = path76.join(copy, cwdRelative);
108042
108436
  let current = null;
108043
108437
  const restore = () => {
108044
108438
  if (current)
@@ -108073,7 +108467,7 @@ async function runMutation(options) {
108073
108467
  record({ ...mutant, status: "skipped", durationMs: 0, tests, reason: "budget" });
108074
108468
  continue;
108075
108469
  }
108076
- const original = readFileSync30(path73.join(copy, mutant.file), "utf8");
108470
+ const original = readFileSync32(path76.join(copy, mutant.file), "utf8");
108077
108471
  const mutated = original.slice(0, mutant.start) + mutant.replacement + original.slice(mutant.end);
108078
108472
  current = { file: mutant.file, original };
108079
108473
  if (!writeInside(copy, mutant.file, mutated)) {
@@ -108130,8 +108524,8 @@ var NOT_SOURCE, FLIPS, isStringy = (node) => node.type === "StringLiteral" || no
108130
108524
  return error.code === "EPERM";
108131
108525
  }
108132
108526
  }, inside5 = (root, file) => {
108133
- const relative = path73.relative(root, file);
108134
- return relative === "" || !relative.startsWith("..") && !path73.isAbsolute(relative);
108527
+ const relative = path76.relative(root, file);
108528
+ return relative === "" || !relative.startsWith("..") && !path76.isAbsolute(relative);
108135
108529
  }, active, killTree = (child) => {
108136
108530
  try {
108137
108531
  if (child.pid && process.platform !== "win32")
@@ -108180,7 +108574,7 @@ __export(exports_test_audit, {
108180
108574
  run: () => run23
108181
108575
  });
108182
108576
  import { existsSync as existsSync30 } from "node:fs";
108183
- import path74 from "node:path";
108577
+ import path77 from "node:path";
108184
108578
  function parse8(argv) {
108185
108579
  const options = {
108186
108580
  paths: [],
@@ -108285,8 +108679,8 @@ async function run23(argv, io) {
108285
108679
  return emit(io, fail2("invalid_input", `${options}
108286
108680
  usage: ${USAGE16}`));
108287
108681
  const top = git7(io.cwd, ["rev-parse", "--show-toplevel"]);
108288
- const repo = top.ok ? path74.resolve(top.stdout.trim()) : null;
108289
- const display = (file) => toPosix(path74.relative(io.cwd, file) || file);
108682
+ const repo = top.ok ? path77.resolve(top.stdout.trim()) : null;
108683
+ const display = (file) => toPosix(path77.relative(io.cwd, file) || file);
108290
108684
  let base = null;
108291
108685
  let changed = null;
108292
108686
  if (options.diff || options.mutate) {
@@ -108424,8 +108818,8 @@ var exports_youtrack = {};
108424
108818
  __export(exports_youtrack, {
108425
108819
  run: () => run25
108426
108820
  });
108427
- import { readFileSync as readFileSync31 } from "node:fs";
108428
- import path75 from "node:path";
108821
+ import { readFileSync as readFileSync33 } from "node:fs";
108822
+ import path78 from "node:path";
108429
108823
  async function run25(argv, io) {
108430
108824
  const [sub, ...rest] = argv;
108431
108825
  if (sub !== "note" && sub !== "time" && sub !== "meeting")
@@ -108471,7 +108865,7 @@ async function run25(argv, io) {
108471
108865
  let markdown = flags.values.markdown ?? "";
108472
108866
  if (flags.values.file)
108473
108867
  try {
108474
- markdown = readFileSync31(path75.resolve(io.cwd, flags.values.file), "utf8");
108868
+ markdown = readFileSync33(path78.resolve(io.cwd, flags.values.file), "utf8");
108475
108869
  } catch (error) {
108476
108870
  return usage4(io, `cannot read ${flags.values.file}: ${String(error)}`, USAGE18);
108477
108871
  }
@@ -108542,8 +108936,8 @@ var exports_changelog = {};
108542
108936
  __export(exports_changelog, {
108543
108937
  run: () => run26
108544
108938
  });
108545
- import { readFileSync as readFileSync32 } from "node:fs";
108546
- import path76 from "node:path";
108939
+ import { readFileSync as readFileSync34 } from "node:fs";
108940
+ import path79 from "node:path";
108547
108941
  async function run26(argv, io) {
108548
108942
  const [sub, ...rest] = argv;
108549
108943
  if (sub !== "apply")
@@ -108589,7 +108983,7 @@ async function run26(argv, io) {
108589
108983
  ]);
108590
108984
  }
108591
108985
  var USAGE19 = "workit changelog apply (--entries <JSON|@file|-> | --normalize-only) [--path CHANGELOG.md] [--preview]", readEntries = (raw, cwd) => {
108592
- const text = raw === "-" ? readFileSync32(0, "utf8") : raw.startsWith("@") ? readFileSync32(path76.resolve(cwd, raw.slice(1)), "utf8") : raw;
108986
+ const text = raw === "-" ? readFileSync34(0, "utf8") : raw.startsWith("@") ? readFileSync34(path79.resolve(cwd, raw.slice(1)), "utf8") : raw;
108593
108987
  return JSON.parse(text);
108594
108988
  };
108595
108989
  var init_changelog2 = __esm(() => {
@@ -108605,7 +108999,7 @@ __export(exports_handoff, {
108605
108999
  run: () => run27
108606
109000
  });
108607
109001
  import fs37 from "node:fs";
108608
- import path77 from "node:path";
109002
+ import path80 from "node:path";
108609
109003
  import { parseArgs as parseArgs2 } from "node:util";
108610
109004
  function render3(brief) {
108611
109005
  const lines = [
@@ -108645,9 +109039,9 @@ function bounded(brief, cwd) {
108645
109039
  let file = null;
108646
109040
  if (store.ok)
108647
109041
  try {
108648
- const dir = path77.join(store.value.root, "handoff");
109042
+ const dir = path80.join(store.value.root, "handoff");
108649
109043
  fs37.mkdirSync(dir, { recursive: true });
108650
- file = path77.join(dir, `${(brief.branch ?? "detached").replaceAll(/[^\w.-]+/gu, "-")}.txt`);
109044
+ file = path80.join(dir, `${(brief.branch ?? "detached").replaceAll(/[^\w.-]+/gu, "-")}.txt`);
108651
109045
  fs37.writeFileSync(file, `${[...body, ...tail].join(`
108652
109046
  `)}
108653
109047
  `, {
@@ -108722,7 +109116,7 @@ var init_handoff = __esm(() => {
108722
109116
  });
108723
109117
 
108724
109118
  // packages/workit-cli/src/main.ts
108725
- import path78 from "node:path";
109119
+ import path81 from "node:path";
108726
109120
 
108727
109121
  // packages/workit-core/src/git/env-redirect.ts
108728
109122
  var GIT_REDIRECT_ENV = [
@@ -108881,9 +109275,9 @@ var VERBS = [
108881
109275
  {
108882
109276
  name: "upgrade",
108883
109277
  group: "setup",
108884
- usage: "workit upgrade [--hosts=a,b|none] [--cli] [--preview | --yes | --apply --confirm] [--json]",
108885
- summary: "Upgrade the CLI and every host after one confirmation, then verify with doctor",
108886
- load: () => Promise.resolve().then(() => (init_upgrade2(), exports_upgrade))
109278
+ usage: "workit upgrade [--hosts=a,b|none] [--cli] [--preview | --yes | --apply --confirm | --check] [--set-updates=prompt|auto|off] [--json]",
109279
+ summary: "Upgrade the CLI and every host after one confirmation, then verify with doctor; --check compares installed and latest versions",
109280
+ load: () => Promise.resolve().then(() => (init_upgrade2(), exports_upgrade2))
108887
109281
  },
108888
109282
  {
108889
109283
  name: "launch",
@@ -108993,7 +109387,7 @@ var VERBS = [
108993
109387
  'workit check test --no-lease --reason "machine is idle, debugging a hang"'
108994
109388
  ],
108995
109389
  notes: LEASE_NOTES,
108996
- load: () => Promise.resolve().then(() => (init_check(), exports_check))
109390
+ load: () => Promise.resolve().then(() => (init_check2(), exports_check))
108997
109391
  },
108998
109392
  withSubcommands({
108999
109393
  name: "lock",
@@ -109671,7 +110065,7 @@ var defaultIo = (json) => ({
109671
110065
  });
109672
110066
  async function main(argv, overrides = {}, options = {}) {
109673
110067
  const parsed = parseGlobals(argv);
109674
- const cwd = path78.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
110068
+ const cwd = path81.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
109675
110069
  const io = {
109676
110070
  ...defaultIo(parsed.json),
109677
110071
  terminals: {
@@ -109717,6 +110111,18 @@ async function main(argv, overrides = {}, options = {}) {
109717
110111
  const entry = findVerb(command);
109718
110112
  if (!entry)
109719
110113
  return unknown2(io, command);
110114
+ if (!io.json && overrides.stdout === undefined && overrides.stderr === undefined && process.stdin.isTTY && process.stdout.isTTY && process.stderr.isTTY) {
110115
+ await Promise.resolve().then(() => init_update_check());
110116
+ const reexecuted = await launchUpdateCheck({ argv, command, json: parsed.json }, {
110117
+ env: io.env,
110118
+ stdin: process.stdin,
110119
+ stdout: process.stdout,
110120
+ stderr: process.stderr,
110121
+ write: (text) => void process.stderr.write(text)
110122
+ });
110123
+ if (reexecuted !== undefined)
110124
+ return reexecuted;
110125
+ }
109720
110126
  const route = async (routed) => {
109721
110127
  if (wantsHelp(verbArgs)) {
109722
110128
  const word = firstWord(verbArgs);
@@ -109887,8 +110293,14 @@ var describe4 = (entry) => ({
109887
110293
  summary: entry.summary,
109888
110294
  ...entry.planned ? { planned: entry.planned } : {}
109889
110295
  });
109890
- var unknown2 = (io, command) => emit(io, fail2("invalid_input", `unknown command "${command}"`, { unblock: commandUnblock(command) }));
110296
+ var unknown2 = (io, command) => emit(io, fail2("invalid_input", `unknown command "${command}"`, {
110297
+ unblock: commandUnblock(command)
110298
+ }));
109891
110299
  if (__require.main == __require.module) {
110300
+ if (process.env.WORKIT_UPDATE_REFRESH === "1") {
110301
+ (await Promise.resolve().then(() => (init_update_check(), exports_update_check))).refreshUpdateCache(process.env);
110302
+ process.exit(0);
110303
+ }
109892
110304
  const code = await main(process.argv.slice(2), {}, { diagnostics: true });
109893
110305
  await flushStreams();
109894
110306
  process.exit(code);