@brainervirus/workit-claude-code 8.32.0 → 8.34.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.
package/dist/workit.js CHANGED
@@ -9286,7 +9286,7 @@ var package_default;
9286
9286
  var init_package = __esm(() => {
9287
9287
  package_default = {
9288
9288
  name: "@brainervirus/workit-cli",
9289
- version: "8.32.0",
9289
+ version: "8.34.0",
9290
9290
  private: false,
9291
9291
  description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
9292
9292
  keywords: [
@@ -9324,13 +9324,13 @@ var init_package = __esm(() => {
9324
9324
  },
9325
9325
  dependencies: {
9326
9326
  "@babel/parser": "7.29.9",
9327
- "@brainervirus/workit-cursor": "^8.32.0",
9327
+ "@brainervirus/workit-cursor": "^8.34.0",
9328
9328
  "@inkjs/ui": "2.0.0",
9329
9329
  ink: "7.1.1",
9330
9330
  react: "19.2.8"
9331
9331
  },
9332
9332
  devDependencies: {
9333
- "@brainervirus/workit-core": "^8.32.0"
9333
+ "@brainervirus/workit-core": "^8.34.0"
9334
9334
  },
9335
9335
  engines: {
9336
9336
  node: ">=24"
@@ -66607,6 +66607,35 @@ var init_heavy_words = __esm(() => {
66607
66607
  HEAVY_WORDS = new Set(("npm npx pnpm pnpx yarn bun bunx deno corepack make gmake docker podman nerdctl " + "python python3 py uv poetry pdm pipenv hatch rye bundle rake nx " + "jest vitest mocha ava tap karma jasmine nyc c8 tsc vue-tsc svelte-check eslint stylelint " + "tslint webpack webpack-cli rollup parcel tsup vite next nuxt nuxi astro ng react-scripts " + "playwright cypress wdio testcafe turbo lerna sonar-scanner sonarless sonarless-mcp go " + "golangci-lint gotestsum staticcheck cargo mvn mvnw gradle gradlew ant sbt bazel bazelisk " + "buck2 dotnet msbuild pytest py.test tox nox mypy pyright pylint coverage maturin pip pip3 " + "rspec rails phpunit pest phpstan psalm composer mix swift xcodebuild flutter dart pod cmake " + "ninja meson ctest scons docker-compose buildah earthly").split(" "));
66608
66608
  });
66609
66609
 
66610
+ // packages/workit-core/src/hooks/hook-runs.ts
66611
+ import { mkdirSync as mkdirSync6, readdirSync as readdirSync8, readFileSync as readFileSync15, writeFileSync as writeFileSync7 } from "node:fs";
66612
+ import path37 from "node:path";
66613
+ var HOOK_RUNS_DIR = "hook-runs", readHookRuns = (dir) => {
66614
+ const runs = [];
66615
+ let names = [];
66616
+ try {
66617
+ names = readdirSync8(path37.join(dir, HOOK_RUNS_DIR));
66618
+ } catch {
66619
+ return runs;
66620
+ }
66621
+ for (const name of names) {
66622
+ try {
66623
+ const row = JSON.parse(readFileSync15(path37.join(dir, HOOK_RUNS_DIR, name), "utf8"));
66624
+ if (typeof row.host === "string" && typeof row.event === "string" && typeof row.at === "string" && typeof row.count === "number")
66625
+ runs.push({
66626
+ host: row.host,
66627
+ event: row.event,
66628
+ at: row.at,
66629
+ count: row.count
66630
+ });
66631
+ } catch {}
66632
+ }
66633
+ return runs;
66634
+ };
66635
+ var init_hook_runs = __esm(() => {
66636
+ init_heavy_words();
66637
+ });
66638
+
66610
66639
  // packages/workit-core/src/hooks/delivery-verbs.ts
66611
66640
  var WORKIT_ALLOWED_VERBS, ALLOWED;
66612
66641
  var init_delivery_verbs = __esm(() => {
@@ -66635,14 +66664,15 @@ var init_delivery_verbs = __esm(() => {
66635
66664
  import {
66636
66665
  copyFileSync as copyFileSync4,
66637
66666
  existsSync as existsSync15,
66638
- mkdirSync as mkdirSync6,
66639
- readFileSync as readFileSync15,
66667
+ readdirSync as readdirSync9,
66668
+ mkdirSync as mkdirSync7,
66669
+ readFileSync as readFileSync16,
66640
66670
  realpathSync as realpathSync7,
66641
66671
  rmSync as rmSync3,
66642
66672
  statSync as statSync5
66643
66673
  } from "node:fs";
66644
66674
  import os11 from "node:os";
66645
- import path37 from "node:path";
66675
+ import path38 from "node:path";
66646
66676
  function mergeClaudeSettings(settings, shell, skip = {}) {
66647
66677
  const config = clone4(settings);
66648
66678
  const owned = emptyOwned();
@@ -66652,7 +66682,11 @@ function mergeClaudeSettings(settings, shell, skip = {}) {
66652
66682
  if (shell) {
66653
66683
  const env = objectAt(config, ["env"], owned);
66654
66684
  if (!env)
66655
- return { config: settings, owned: emptyOwned(), error: "env is not an object" };
66685
+ return {
66686
+ config: settings,
66687
+ owned: emptyOwned(),
66688
+ error: "env is not an object"
66689
+ };
66656
66690
  if (env.CLAUDE_CODE_SHELL === undefined) {
66657
66691
  env.CLAUDE_CODE_SHELL = shell;
66658
66692
  owned.env.CLAUDE_CODE_SHELL = shell;
@@ -66758,7 +66792,7 @@ function planHostPermissions(options) {
66758
66792
  plan.blocked.push(`${target.file} is not a JSON object; left untouched`);
66759
66793
  continue;
66760
66794
  }
66761
- const shellWanted = host === "claude-code" && options.shell !== false && path37.basename(paths.env.SHELL ?? "") === "zsh";
66795
+ const shellWanted = host === "claude-code" && options.shell !== false && path38.basename(paths.env.SHELL ?? "") === "zsh";
66762
66796
  const bash = shellWanted ? options.bash === undefined ? findBash(paths.env) : options.bash : null;
66763
66797
  const merged = host === "claude-code" ? mergeClaudeSettings(parsed, bash, skip) : mergeCursorCliConfig(parsed, skip);
66764
66798
  if (merged.error) {
@@ -66858,11 +66892,11 @@ function applyHostPermissions(plan, options = {}) {
66858
66892
  try {
66859
66893
  const target = change.before === null ? change.file : realpathSync7(change.file);
66860
66894
  if (change.before !== null) {
66861
- const backups = path37.join(paths.stateDir, "host-permissions-backup");
66862
- mkdirSync6(backups, { recursive: true, mode: 448 });
66863
- copyFileSync4(target, path37.join(backups, `${new Date().toISOString().replaceAll(":", "-")}-${change.host}-${path37.basename(change.file)}`));
66895
+ const backups = path38.join(paths.stateDir, "host-permissions-backup");
66896
+ mkdirSync7(backups, { recursive: true, mode: 448 });
66897
+ copyFileSync4(target, path38.join(backups, `${new Date().toISOString().replaceAll(":", "-")}-${change.host}-${path38.basename(change.file)}`));
66864
66898
  }
66865
- mkdirSync6(path37.dirname(target), { recursive: true });
66899
+ mkdirSync7(path38.dirname(target), { recursive: true });
66866
66900
  writeFileAtomic(target, change.after);
66867
66901
  const previous = record.hosts[change.host];
66868
66902
  record.hosts[change.host] = {
@@ -66892,7 +66926,10 @@ function permissionHealth(host, options = {}) {
66892
66926
  if (host === "codex") {
66893
66927
  if (text === null)
66894
66928
  return { state: "absent" };
66895
- return text === codexRulesText() ? { state: "ok" } : { state: "drift", detail: `${target.file} differs from this Workit version's rules` };
66929
+ return text === codexRulesText() ? { state: "ok" } : {
66930
+ state: "drift",
66931
+ detail: `${target.file} differs from this Workit version's rules`
66932
+ };
66896
66933
  }
66897
66934
  if (text === null)
66898
66935
  return { state: "absent" };
@@ -66915,7 +66952,37 @@ function permissionHealth(host, options = {}) {
66915
66952
  detail: `${target.file} lacks ${missing.length} Workit entr${missing.length === 1 ? "y" : "ies"} (${missing[0]}${missing.length > 1 ? ", …" : ""})`
66916
66953
  };
66917
66954
  }
66918
- var PERMISSION_HOSTS, CLAUDE_ALLOW, CLAUDE_ASK, AUTO_MODE_ENVIRONMENT = "Org-specific CLIs: workit — the user's delivery CLI. Its push, pr merge, release and PR-thread verbs run only under per-workspace grants and non-author verdicts the user configured in ~/.config/workit, outside the agent's reach.", AUTO_MODE_ALLOW = "Workit-gated delivery: `workit pr merge`, `workit git push --force-with-lease` on the session's own branch, `workit release` and `workit pr reply/resolve` on the session's repo are authorized by the user's standing Workit grants; not Merge Without Review, Git Destructive or External System Writes. Does NOT cover `--unverified`, `--admin` or any bypass flag.", DEFAULTS2 = "$defaults", CHECK_NAMES, LOCK_VERBS, LEASE_PREFIXES, CURSOR_ALLOW, CODEX_HEADER, codexRulesText = () => {
66955
+ function permissionCoverage(host, commands, options = {}) {
66956
+ const target = permissionTarget(host, options);
66957
+ if (!existsSync15(target.hostDir))
66958
+ return { state: "no-host" };
66959
+ const cwd = options.cwd ?? process.cwd();
66960
+ let missing;
66961
+ if (host === "codex") {
66962
+ const patterns = codexAllowPatterns(path38.dirname(target.file));
66963
+ missing = commands.filter((command) => {
66964
+ const words = command.split(" ");
66965
+ return !patterns.some((p) => p.every((word, i) => words[i] === word));
66966
+ });
66967
+ } else if (host === "cursor") {
66968
+ const rules = [target.file, path38.join(cwd, ".cursor", "cli.json")].flatMap((file) => stringList(valueFrom(readRecord(file), "permissions", "allow")));
66969
+ missing = commands.filter((command) => !rules.some((rule) => cursorRuleMatches(rule, command)));
66970
+ } else {
66971
+ const files = [
66972
+ target.file,
66973
+ path38.join(cwd, ".claude", "settings.json"),
66974
+ path38.join(cwd, ".claude", "settings.local.json")
66975
+ ].map(readRecord);
66976
+ const rules = files.flatMap((file) => stringList(valueFrom(file, "permissions", "allow")));
66977
+ missing = commands.filter((command) => !rules.some((rule) => claudeRuleMatches(rule, command)));
66978
+ const delivery = commands.some((command) => !LEASE_COMMANDS.includes(command));
66979
+ const auto = files.flatMap((file) => stringList(valueFrom(file, "autoMode", "allow")));
66980
+ if (delivery && !auto.some((line) => /\bworkit\b/iu.test(line)))
66981
+ missing.push("autoMode.allow line naming workit");
66982
+ }
66983
+ return missing.length === 0 ? { state: "ok" } : { state: "missing", file: target.file, missing };
66984
+ }
66985
+ var PERMISSION_HOSTS, CHECK_NAMES, LOCK_VERBS, LEASE_PREFIXES, CLAUDE_ALLOW, CLAUDE_ASK, AUTO_MODE_ENVIRONMENT = "Org-specific CLIs: workit — the user's delivery CLI. Its push, pr merge, release and PR-thread verbs run only under per-workspace grants and non-author verdicts the user configured in ~/.config/workit, outside the agent's reach.", AUTO_MODE_ALLOW = "Workit-gated delivery: `workit pr merge`, `workit git push --force-with-lease` on the session's own branch, `workit release` and `workit pr reply/resolve` on the session's repo are authorized by the user's standing Workit grants; not Merge Without Review, Git Destructive or External System Writes. Does NOT cover `--unverified`, `--admin` or any bypass flag.", DEFAULTS2 = "$defaults", CURSOR_ALLOW, CODEX_HEADER, codexRulesText = () => {
66919
66986
  const rules = [...WORKIT_ALLOWED_VERBS, "--version"].map((verb) => {
66920
66987
  const examples = verb === "git" ? `
66921
66988
  match = [["workit", "git", "push", "--cwd", "/w"]],
@@ -67007,30 +67074,34 @@ ${[...rules, ...lease, grant].join(`
67007
67074
  }, resolvePaths = (options) => {
67008
67075
  const env = options.env ?? process.env;
67009
67076
  const home = options.home ?? env.HOME ?? os11.homedir();
67010
- return { home, env, stateDir: options.stateDir ?? stateDir({ ...env, HOME: home }) };
67077
+ return {
67078
+ home,
67079
+ env,
67080
+ stateDir: options.stateDir ?? stateDir({ ...env, HOME: home })
67081
+ };
67011
67082
  }, permissionTarget = (host, options = {}) => {
67012
67083
  const { home, env } = resolvePaths(options);
67013
67084
  if (host === "claude-code") {
67014
67085
  const dir = claudeConfigDir(home, env);
67015
- return { file: path37.join(dir, "settings.json"), hostDir: dir };
67086
+ return { file: path38.join(dir, "settings.json"), hostDir: dir };
67016
67087
  }
67017
67088
  if (host === "codex") {
67018
- const dir = env.CODEX_HOME || path37.join(home, ".codex");
67019
- return { file: path37.join(dir, "rules", "workit.rules"), hostDir: dir };
67089
+ const dir = env.CODEX_HOME || path38.join(home, ".codex");
67090
+ return { file: path38.join(dir, "rules", "workit.rules"), hostDir: dir };
67020
67091
  }
67021
- const dir = path37.join(home, ".cursor");
67022
- return { file: path37.join(dir, "cli-config.json"), hostDir: dir };
67092
+ const dir = path38.join(home, ".cursor");
67093
+ return { file: path38.join(dir, "cli-config.json"), hostDir: dir };
67023
67094
  }, AGENT_SESSION_VARS, agentSessionVar = (env) => AGENT_SESSION_VARS.find((name) => (env[name] ?? "") !== "") ?? null, RECORD_FILE = "host-permissions.json", readOwnership = (options = {}) => {
67024
67095
  const { stateDir } = resolvePaths(options);
67025
67096
  try {
67026
- const value = JSON.parse(readFileSync15(path37.join(stateDir, RECORD_FILE), "utf8"));
67097
+ const value = JSON.parse(readFileSync16(path38.join(stateDir, RECORD_FILE), "utf8"));
67027
67098
  if (isRecord5(value) && isRecord5(value.hosts))
67028
67099
  return { version: 1, hosts: value.hosts };
67029
67100
  } catch {}
67030
67101
  return { version: 1, hosts: {} };
67031
67102
  }, writeOwnership = (record, stateDir) => {
67032
- mkdirSync6(stateDir, { recursive: true });
67033
- writeFileAtomic(path37.join(stateDir, RECORD_FILE), JSON.stringify(record, null, 2) + `
67103
+ mkdirSync7(stateDir, { recursive: true });
67104
+ writeFileAtomic(path38.join(stateDir, RECORD_FILE), JSON.stringify(record, null, 2) + `
67034
67105
  `, 384);
67035
67106
  }, unionLists = (a, b) => {
67036
67107
  const lists = { ...a };
@@ -67052,14 +67123,14 @@ ${[...rules, ...lease, grant].join(`
67052
67123
  writeOwnership(record, paths.stateDir);
67053
67124
  }, readText4 = (file) => {
67054
67125
  try {
67055
- return readFileSync15(file, "utf8");
67126
+ return readFileSync16(file, "utf8");
67056
67127
  } catch {
67057
67128
  return null;
67058
67129
  }
67059
67130
  }, findBash = (env) => {
67060
- const dirs = ["/usr/bin", "/bin", ...(env.PATH ?? "").split(path37.delimiter).filter(Boolean)];
67131
+ const dirs = ["/usr/bin", "/bin", ...(env.PATH ?? "").split(path38.delimiter).filter(Boolean)];
67061
67132
  for (const dir of dirs) {
67062
- const candidate = path37.join(dir, "bash");
67133
+ const candidate = path38.join(dir, "bash");
67063
67134
  try {
67064
67135
  if (statSync5(candidate).isFile())
67065
67136
  return candidate;
@@ -67068,10 +67139,60 @@ ${[...rules, ...lease, grant].join(`
67068
67139
  return null;
67069
67140
  }, setupCommand = (hosts) => `workit setup --hosts=${hosts.join(",")}`, removeCodexRules = (file, options = {}) => {
67070
67141
  const expected = permissionTarget("codex", options).file;
67071
- if (path37.resolve(file) !== path37.resolve(expected) || !existsSync15(expected))
67142
+ if (path38.resolve(file) !== path38.resolve(expected) || !existsSync15(expected))
67072
67143
  return false;
67073
67144
  rmSync3(expected);
67074
67145
  return true;
67146
+ }, GRANT_COMMANDS, LEASE_COMMANDS, grantedCommands = (kinds) => [
67147
+ ...kinds.flatMap((kind) => GRANT_COMMANDS[kind] ?? []),
67148
+ ...LEASE_COMMANDS
67149
+ ], claudeRuleMatches = (rule, command) => {
67150
+ const body = /^Bash\((.*)\)$/u.exec(rule)?.[1];
67151
+ if (rule === "Bash" || body === "*" || body === "")
67152
+ return true;
67153
+ if (body === undefined)
67154
+ return false;
67155
+ if (body.endsWith(":*") && !body.slice(0, -2).includes("*")) {
67156
+ const prefix = body.slice(0, -2);
67157
+ return command === prefix || command.startsWith(`${prefix} `);
67158
+ }
67159
+ const escaped = body.split("*").map((part) => part.replace(/[.+?^${}()|[\]\\]/gu, "\\$&")).join(".*");
67160
+ const pattern = body.endsWith(" *") ? escaped.replace(/ \.\*$/u, "(?: .*)?") : escaped;
67161
+ return new RegExp(`^${pattern}$`, "u").test(command);
67162
+ }, cursorRuleMatches = (rule, command) => {
67163
+ const full = /^Shell\((.*)\)$/u.exec(rule)?.[1];
67164
+ return full !== undefined && (command === full || command.startsWith(`${full} `));
67165
+ }, stringList = (value) => Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [], readRecord = (file) => {
67166
+ const text = readText4(file);
67167
+ if (text === null)
67168
+ return null;
67169
+ try {
67170
+ const value = JSON.parse(text);
67171
+ return isRecord5(value) ? value : null;
67172
+ } catch {
67173
+ return null;
67174
+ }
67175
+ }, codexAllowPatterns = (dir) => {
67176
+ const patterns = [];
67177
+ let names = [];
67178
+ try {
67179
+ names = readdirSync9(dir).filter((name) => name.endsWith(".rules"));
67180
+ } catch {
67181
+ return patterns;
67182
+ }
67183
+ for (const name of names)
67184
+ for (const m of (readText4(path38.join(dir, name)) ?? "").matchAll(/pattern\s*=\s*(\[[^\]]*\])\s*,\s*decision\s*=\s*"allow"/gu))
67185
+ try {
67186
+ const words = JSON.parse(m[1]);
67187
+ if (Array.isArray(words))
67188
+ patterns.push(words.map(String));
67189
+ } catch {}
67190
+ return patterns;
67191
+ }, valueFrom = (root, ...keys) => {
67192
+ let node = root;
67193
+ for (const key of keys)
67194
+ node = isRecord5(node) ? node[key] : undefined;
67195
+ return node;
67075
67196
  };
67076
67197
  var init_host_permissions = __esm(() => {
67077
67198
  init_heavy_words();
@@ -67083,20 +67204,21 @@ var init_host_permissions = __esm(() => {
67083
67204
  "codex",
67084
67205
  "cursor"
67085
67206
  ]);
67207
+ CHECK_NAMES = ["test", "lint", "typecheck", "build", "format", "docs"];
67208
+ LOCK_VERBS = ["status", "wait"];
67209
+ LEASE_PREFIXES = [
67210
+ ...CHECK_NAMES.map((name) => ["check", name]),
67211
+ ...LOCK_VERBS.map((verb) => ["lock", verb])
67212
+ ];
67086
67213
  CLAUDE_ALLOW = [
67087
67214
  ...WORKIT_ALLOWED_VERBS.map((verb) => `Bash(workit ${verb} *)`),
67215
+ ...LEASE_PREFIXES.map((rest) => `Bash(workit ${rest.join(" ")} *)`),
67088
67216
  "Bash(workit --version)"
67089
67217
  ];
67090
67218
  CLAUDE_ASK = [
67091
67219
  "Bash(workit * --unverified*)",
67092
67220
  "Bash(workit * --overwrite-unintegrated*)"
67093
67221
  ];
67094
- CHECK_NAMES = ["test", "lint", "typecheck", "build", "format", "docs"];
67095
- LOCK_VERBS = ["status", "wait"];
67096
- LEASE_PREFIXES = [
67097
- ...CHECK_NAMES.map((name) => ["check", name]),
67098
- ...LOCK_VERBS.map((verb) => ["lock", verb])
67099
- ];
67100
67222
  CURSOR_ALLOW = [
67101
67223
  ...WORKIT_ALLOWED_VERBS.map((verb) => `Shell(workit ${verb})`),
67102
67224
  ...LEASE_PREFIXES.map((rest) => `Shell(workit ${rest.join(" ")})`),
@@ -67115,7 +67237,11 @@ var init_host_permissions = __esm(() => {
67115
67237
  created: [],
67116
67238
  env: {}
67117
67239
  },
67118
- cursor: { lists: { "permissions.allow": [...CURSOR_ALLOW] }, created: [], env: {} }
67240
+ cursor: {
67241
+ lists: { "permissions.allow": [...CURSOR_ALLOW] },
67242
+ created: [],
67243
+ env: {}
67244
+ }
67119
67245
  };
67120
67246
  PRIOR_ENTRIES = {
67121
67247
  "claude-code": {},
@@ -67142,6 +67268,12 @@ var init_host_permissions = __esm(() => {
67142
67268
  "PI_SESSION_ID",
67143
67269
  "CURSOR_AGENT"
67144
67270
  ];
67271
+ GRANT_COMMANDS = {
67272
+ push: ["workit git push"],
67273
+ pr: ["workit pr create"],
67274
+ merge: ["workit pr merge"]
67275
+ };
67276
+ LEASE_COMMANDS = LEASE_PREFIXES.map((rest) => `workit ${rest.join(" ")}`);
67145
67277
  });
67146
67278
 
67147
67279
  // packages/workit-cli/src/admin/doctor.ts
@@ -67150,31 +67282,34 @@ import { createHash as createHash14 } from "node:crypto";
67150
67282
  import {
67151
67283
  existsSync as existsSync16,
67152
67284
  lstatSync as lstatSync5,
67153
- mkdirSync as mkdirSync7,
67285
+ mkdirSync as mkdirSync8,
67154
67286
  mkdtempSync,
67155
- readdirSync as readdirSync8,
67156
- readFileSync as readFileSync16,
67287
+ readdirSync as readdirSync10,
67288
+ readFileSync as readFileSync17,
67157
67289
  readlinkSync as readlinkSync2,
67158
67290
  renameSync as renameSync4,
67159
67291
  rmSync as rmSync4,
67160
67292
  statSync as statSync6,
67161
67293
  unlinkSync as unlinkSync3,
67162
- writeFileSync as writeFileSync7
67294
+ writeFileSync as writeFileSync8
67163
67295
  } from "node:fs";
67164
67296
  import os12 from "node:os";
67165
- import path38 from "node:path";
67297
+ import path39 from "node:path";
67166
67298
  var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67167
- let dir = path38.resolve(cwd);
67299
+ let dir = path39.resolve(cwd);
67168
67300
  while (true) {
67169
- if (existsSync16(path38.join(dir, "packages", "workit-core", "package.json")))
67301
+ if (existsSync16(path39.join(dir, "packages", "workit-core", "package.json")))
67170
67302
  return dir;
67171
- const parent = path38.dirname(dir);
67303
+ const parent = path39.dirname(dir);
67172
67304
  if (parent === dir)
67173
67305
  return null;
67174
67306
  dir = parent;
67175
67307
  }
67176
67308
  }, listClaudeProcesses = () => {
67177
- const r = spawnSync16("ps", ["-eo", "pid=,lstart=,args="], { encoding: "utf8", timeout: 5000 });
67309
+ const r = spawnSync16("ps", ["-eo", "pid=,lstart=,args="], {
67310
+ encoding: "utf8",
67311
+ timeout: 5000
67312
+ });
67178
67313
  if (r.status !== 0 || typeof r.stdout !== "string")
67179
67314
  return null;
67180
67315
  const found = [];
@@ -67191,8 +67326,8 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67191
67326
  }, resolve = (options) => {
67192
67327
  const env = options.env ?? process.env;
67193
67328
  const home = options.home ?? env.HOME ?? os12.homedir();
67194
- const configDir = options.configDir ?? env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path38.join(home, ".config", "workit");
67195
- const stateDir = options.stateDir ?? env.WORKFLOW_TOOLKIT_STATE ?? path38.join(home, ".local", "state", "workit");
67329
+ const configDir = options.configDir ?? env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path39.join(home, ".config", "workit");
67330
+ const stateDir = options.stateDir ?? env.WORKFLOW_TOOLKIT_STATE ?? path39.join(home, ".local", "state", "workit");
67196
67331
  const cwd = options.cwd ?? process.cwd();
67197
67332
  const dev = options.dev?.trim() || env.WORKFLOW_TOOLKIT_DEV?.trim() || findDevFromCwd(cwd);
67198
67333
  return {
@@ -67203,11 +67338,11 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67203
67338
  cwd,
67204
67339
  workspaceRoot: options.workspaceRoot ?? env.WORKFLOW_WORKSPACE_ROOT ?? cwd,
67205
67340
  dev,
67206
- opencodeConfig: options.opencodeConfig ?? path38.join(home, ".config", "opencode", "opencode.json"),
67341
+ opencodeConfig: options.opencodeConfig ?? path39.join(home, ".config", "opencode", "opencode.json"),
67207
67342
  opencodePackageCacheDir: options.opencodePackageCacheDir ?? null,
67208
- cursorSettings: options.cursorSettings ?? path38.join(home, ".cursor", "settings.json"),
67209
- cursorMcp: options.cursorMcp ?? path38.join(home, ".cursor", "mcp.json"),
67210
- cursorPluginDir: options.cursorPluginDir ?? path38.join(home, ".cursor", "plugins", "local", "workit"),
67343
+ cursorSettings: options.cursorSettings ?? path39.join(home, ".cursor", "settings.json"),
67344
+ cursorMcp: options.cursorMcp ?? path39.join(home, ".cursor", "mcp.json"),
67345
+ cursorPluginDir: options.cursorPluginDir ?? path39.join(home, ".cursor", "plugins", "local", "workit"),
67211
67346
  cursorHeartbeatDir: options.stateDir ?? (env.WORKFLOW_TOOLKIT_STATE || resolveStateDir()),
67212
67347
  hookStateDir: options.stateDir ?? (env.WORKFLOW_TOOLKIT_STATE || resolveStateDir()),
67213
67348
  codexHome: options.codexHome,
@@ -67220,14 +67355,14 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67220
67355
  };
67221
67356
  }, readJson = (p) => {
67222
67357
  try {
67223
- const parsed = JSON.parse(readFileSync16(p, "utf8"));
67358
+ const parsed = JSON.parse(readFileSync17(p, "utf8"));
67224
67359
  return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
67225
67360
  } catch {
67226
67361
  return null;
67227
67362
  }
67228
67363
  }, parsesAsConfigObject = (p) => {
67229
67364
  try {
67230
- return isConfigObject(JSON.parse(readFileSync16(p, "utf8")));
67365
+ return isConfigObject(JSON.parse(readFileSync17(p, "utf8")));
67231
67366
  } catch {
67232
67367
  return false;
67233
67368
  }
@@ -67237,12 +67372,12 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67237
67372
  ...new Set(entries.filter((entry) => typeof entry === "string" && isWorkitPlugin(entry)))
67238
67373
  ];
67239
67374
  }, 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) => {
67240
- const dirs = (env.PATH ?? process.env.PATH ?? "").split(path38.delimiter);
67375
+ const dirs = (env.PATH ?? process.env.PATH ?? "").split(path39.delimiter);
67241
67376
  for (const dir of dirs) {
67242
67377
  if (!dir)
67243
67378
  continue;
67244
67379
  for (const candidateName of names) {
67245
- const candidate = path38.join(dir, candidateName);
67380
+ const candidate = path39.join(dir, candidateName);
67246
67381
  try {
67247
67382
  const st = statSync6(candidate);
67248
67383
  if (process.platform !== "win32" && (st.mode & 73) === 0)
@@ -67271,7 +67406,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67271
67406
  if (env.BUN && existsSync16(env.BUN))
67272
67407
  return env.BUN;
67273
67408
  for (const candidate of [
67274
- path38.join(env.HOME || os12.homedir(), ".bun/bin/bun"),
67409
+ path39.join(env.HOME || os12.homedir(), ".bun/bin/bun"),
67275
67410
  "/usr/local/bin/bun",
67276
67411
  "/usr/bin/bun"
67277
67412
  ]) {
@@ -67326,7 +67461,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67326
67461
  detail: "installed package, not a dev checkout — version parity applies to checkouts only"
67327
67462
  };
67328
67463
  }
67329
- const corePkg = readJson(path38.join(res.dev, "packages/workit-core/package.json"));
67464
+ const corePkg = readJson(path39.join(res.dev, "packages/workit-core/package.json"));
67330
67465
  if (!corePkg) {
67331
67466
  return {
67332
67467
  id: "versions",
@@ -67336,7 +67471,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67336
67471
  }
67337
67472
  const refs = new Set;
67338
67473
  for (const name of ["workit-opencode", "workit-cursor", "workit-cli"]) {
67339
- const pkg = readJson(path38.join(res.dev, "packages", name, "package.json"));
67474
+ const pkg = readJson(path39.join(res.dev, "packages", name, "package.json"));
67340
67475
  const dep = pkg?.dependencies?.["@brainervirus/workit-core"] ?? pkg?.devDependencies?.["@brainervirus/workit-core"];
67341
67476
  if (typeof dep === "string")
67342
67477
  refs.add(dep);
@@ -67352,7 +67487,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67352
67487
  if (refs.size > 1) {
67353
67488
  problems.push(`adapters pin different core versions: ${[...refs].join(", ")}`);
67354
67489
  }
67355
- const opencodePkg = readJson(path38.join(res.dev, "packages/workit-opencode/package.json"));
67490
+ const opencodePkg = readJson(path39.join(res.dev, "packages/workit-opencode/package.json"));
67356
67491
  const sdk = opencodePkg?.dependencies?.["@opencode/plugin"] ?? opencodePkg?.devDependencies?.["@opencode/plugin"];
67357
67492
  const sdkVersion = typeof sdk === "string" ? (sdk.match(/^\d+(?:\.\d+){0,2}/) ?? [])[0] : null;
67358
67493
  if (sdkVersion && !semverAtLeast(sdkVersion, SUPPORT_MATRIX.opencode.minimum)) {
@@ -67379,14 +67514,14 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67379
67514
  status: "pass",
67380
67515
  detail: "opencode CLI not on PATH — skipping version check"
67381
67516
  };
67382
- const scratch = mkdtempSync(path38.join(os12.tmpdir(), "workit-doctor-opencode-"));
67517
+ const scratch = mkdtempSync(path39.join(os12.tmpdir(), "workit-doctor-opencode-"));
67383
67518
  let raw;
67384
67519
  try {
67385
67520
  raw = versionOf("opencode", {
67386
67521
  ...res.env,
67387
- XDG_DATA_HOME: path38.join(scratch, "data"),
67388
- XDG_STATE_HOME: path38.join(scratch, "state"),
67389
- XDG_CACHE_HOME: path38.join(scratch, "cache")
67522
+ XDG_DATA_HOME: path39.join(scratch, "data"),
67523
+ XDG_STATE_HOME: path39.join(scratch, "state"),
67524
+ XDG_CACHE_HOME: path39.join(scratch, "cache")
67390
67525
  }, 5000);
67391
67526
  } finally {
67392
67527
  rmSync4(scratch, { recursive: true, force: true });
@@ -67450,7 +67585,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67450
67585
  const tables = new Map;
67451
67586
  let text;
67452
67587
  try {
67453
- text = readFileSync16(file, "utf8");
67588
+ text = readFileSync17(file, "utf8");
67454
67589
  } catch {
67455
67590
  return tables;
67456
67591
  }
@@ -67488,19 +67623,19 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67488
67623
  current[unquote(pair[1])] = value === "true" ? true : value === "false" ? false : unquote(value);
67489
67624
  }
67490
67625
  return tables;
67491
- }, codexHomeOf = (res) => res.codexHome ?? (res.env.CODEX_HOME || path38.join(res.home, ".codex")), codexWorkitInstalls = (res) => {
67626
+ }, codexHomeOf = (res) => res.codexHome ?? (res.env.CODEX_HOME || path39.join(res.home, ".codex")), codexWorkitInstalls = (res) => {
67492
67627
  const codexHome = codexHomeOf(res);
67493
- const configFile = path38.join(codexHome, "config.toml");
67628
+ const configFile = path39.join(codexHome, "config.toml");
67494
67629
  const installs = [];
67495
67630
  for (const [key, table] of readTomlTables(configFile)) {
67496
67631
  const [kind, id, ...rest] = key.split("\x00");
67497
67632
  if (kind !== "plugins" || rest.length > 0 || !id?.startsWith("workit@") || table.enabled === false)
67498
67633
  continue;
67499
67634
  const marketplace = id.slice("workit@".length);
67500
- const dir = path38.join(codexHome, "plugins", "cache", marketplace, "workit");
67635
+ const dir = path39.join(codexHome, "plugins", "cache", marketplace, "workit");
67501
67636
  let versions = [];
67502
67637
  try {
67503
- versions = readdirSync8(dir).filter((v) => existsSync16(path38.join(dir, v, ".codex-plugin")));
67638
+ versions = readdirSync10(dir).filter((v) => existsSync16(path39.join(dir, v, ".codex-plugin")));
67504
67639
  } catch {
67505
67640
  versions = [];
67506
67641
  }
@@ -67508,7 +67643,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67508
67643
  installs.push({
67509
67644
  id,
67510
67645
  marketplace,
67511
- root: version ? path38.join(dir, version) : null,
67646
+ root: version ? path39.join(dir, version) : null,
67512
67647
  version,
67513
67648
  configFile
67514
67649
  });
@@ -67530,7 +67665,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67530
67665
  };
67531
67666
  return `sha256:${createHash14("sha256").update(JSON.stringify(body)).digest("hex")}`;
67532
67667
  }, codexHookTrust = (install, tables) => {
67533
- const hooks = install.root ? readJson(path38.join(install.root, "hooks", "hooks.json"))?.hooks : null;
67668
+ const hooks = install.root ? readJson(path39.join(install.root, "hooks", "hooks.json"))?.hooks : null;
67534
67669
  if (!hooks || typeof hooks !== "object")
67535
67670
  return null;
67536
67671
  const result = [];
@@ -67603,25 +67738,25 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67603
67738
  status: "pass",
67604
67739
  detail: "no Workit Codex plugin enabled — skipping"
67605
67740
  };
67606
- const agentsDir = path38.join(codexHomeOf(res), "agents");
67741
+ const agentsDir = path39.join(codexHomeOf(res), "agents");
67607
67742
  const problems = [];
67608
67743
  const fixes = [];
67609
67744
  const installed = [];
67610
67745
  for (const install of installs) {
67611
- const source = install.root ? path38.join(install.root, "agents") : null;
67612
- const files = source && existsSync16(source) ? readdirSync8(source).filter((f) => f.endsWith(".toml")).toSorted() : [];
67746
+ const source = install.root ? path39.join(install.root, "agents") : null;
67747
+ const files = source && existsSync16(source) ? readdirSync10(source).filter((f) => f.endsWith(".toml")).toSorted() : [];
67613
67748
  if (files.length === 0) {
67614
67749
  problems.push(`${install.id} ${install.version ?? "?"} bundles no agents`);
67615
67750
  fixes.push(`codex plugin remove ${install.id} && codex plugin add ${install.id}`);
67616
67751
  continue;
67617
67752
  }
67618
- const install_fix = `node ${JSON.stringify(path38.join(install.root, "dist", "launch-mcp.js"))} --install-agents, then start a new Codex session`;
67619
- const pluginVersion = readJson(path38.join(install.root, "package.json"))?.version;
67753
+ const install_fix = `node ${JSON.stringify(path39.join(install.root, "dist", "launch-mcp.js"))} --install-agents, then start a new Codex session`;
67754
+ const pluginVersion = readJson(path39.join(install.root, "package.json"))?.version;
67620
67755
  const version = typeof pluginVersion === "string" ? pluginVersion.match(SEMVER)?.[0] ?? null : null;
67621
67756
  let stale = false;
67622
67757
  for (const file of files) {
67623
- const dest = path38.join(agentsDir, file);
67624
- const want = stampCodexAgent(readFileSync16(path38.join(source, file), "utf8"), version);
67758
+ const dest = path39.join(agentsDir, file);
67759
+ const want = stampCodexAgent(readFileSync17(path39.join(source, file), "utf8"), version);
67625
67760
  let link = false;
67626
67761
  try {
67627
67762
  link = lstatSync5(dest).isSymbolicLink();
@@ -67635,7 +67770,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67635
67770
  }
67636
67771
  let have = null;
67637
67772
  try {
67638
- have = readFileSync16(dest, "utf8");
67773
+ have = readFileSync17(dest, "utf8");
67639
67774
  } catch {
67640
67775
  have = null;
67641
67776
  }
@@ -67674,7 +67809,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67674
67809
  const env = res.env.PI_CODING_AGENT_DIR;
67675
67810
  if (env)
67676
67811
  return env === "~" ? res.home : env.replace(/^~(?=\/|\\)/, res.home);
67677
- return path38.join(res.home, ".pi", "agent");
67812
+ return path39.join(res.home, ".pi", "agent");
67678
67813
  }, npmSpecName = (spec) => {
67679
67814
  const at = spec.indexOf("@", spec.startsWith("@") ? 1 : 0);
67680
67815
  return at > 0 ? { name: spec.slice(0, at), pinned: true } : { name: spec, pinned: false };
@@ -67682,10 +67817,14 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67682
67817
  const scopes = [
67683
67818
  {
67684
67819
  scope: "project",
67685
- settingsFile: path38.join(res.cwd, ".pi", "settings.json"),
67686
- base: path38.join(res.cwd, ".pi")
67820
+ settingsFile: path39.join(res.cwd, ".pi", "settings.json"),
67821
+ base: path39.join(res.cwd, ".pi")
67687
67822
  },
67688
- { scope: "user", settingsFile: path38.join(agentDir, "settings.json"), base: agentDir }
67823
+ {
67824
+ scope: "user",
67825
+ settingsFile: path39.join(agentDir, "settings.json"),
67826
+ base: agentDir
67827
+ }
67689
67828
  ];
67690
67829
  for (const { scope, settingsFile, base } of scopes) {
67691
67830
  const packages = readJson(settingsFile)?.packages;
@@ -67700,13 +67839,20 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67700
67839
  const spec = npmSpecName(source.slice(4).trim());
67701
67840
  if (spec.name !== PI_PACKAGE)
67702
67841
  continue;
67703
- const root = path38.join(base, "npm", "node_modules", ...PI_PACKAGE.split("/"));
67704
- return { scope, settingsFile, source, filter, root, npm: { pinned: spec.pinned } };
67842
+ const root = path39.join(base, "npm", "node_modules", ...PI_PACKAGE.split("/"));
67843
+ return {
67844
+ scope,
67845
+ settingsFile,
67846
+ source,
67847
+ filter,
67848
+ root,
67849
+ npm: { pinned: spec.pinned }
67850
+ };
67705
67851
  }
67706
67852
  if (/^(git:|https?:|ssh:|git@)/.test(source))
67707
67853
  continue;
67708
- const local = path38.resolve(base, source.replace(/^~(?=\/|\\)/, res.home));
67709
- if (readJson(path38.join(local, "package.json"))?.name === PI_PACKAGE)
67854
+ const local = path39.resolve(base, source.replace(/^~(?=\/|\\)/, res.home));
67855
+ if (readJson(path39.join(local, "package.json"))?.name === PI_PACKAGE)
67710
67856
  return { scope, settingsFile, source, filter, root: local, npm: null };
67711
67857
  }
67712
67858
  }
@@ -67717,7 +67863,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67717
67863
  const list = patterns.filter((p) => typeof p === "string");
67718
67864
  if (list.length === 0)
67719
67865
  return false;
67720
- const name = path38.posix.basename(file);
67866
+ const name = path39.posix.basename(file);
67721
67867
  const matches = (p) => {
67722
67868
  const re = globToRegExp3(p);
67723
67869
  return re.test(file) || re.test(name);
@@ -67735,19 +67881,23 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67735
67881
  }, checkPiExtension = (res) => {
67736
67882
  const agentDir = piAgentDirOf(res);
67737
67883
  if (!existsSync16(agentDir) && !commandOnPath("pi", res.env))
67738
- return { id: "pi_extension", status: "pass", detail: "Pi not installed — skipping" };
67884
+ return {
67885
+ id: "pi_extension",
67886
+ status: "pass",
67887
+ detail: "Pi not installed — skipping"
67888
+ };
67739
67889
  const installCmd = (scope, spec = `npm:${PI_PACKAGE}`) => `pi install ${spec}${scope === "project" ? " -l" : ""}`;
67740
67890
  const entry = findPiEntry(res, agentDir);
67741
67891
  if (!entry)
67742
67892
  return {
67743
67893
  id: "pi_extension",
67744
67894
  status: "warn",
67745
- detail: `Workit Pi extension missing: no ${PI_PACKAGE} entry in ${path38.join(agentDir, "settings.json")} or ${path38.join(res.cwd, ".pi", "settings.json")}`,
67895
+ detail: `Workit Pi extension missing: no ${PI_PACKAGE} entry in ${path39.join(agentDir, "settings.json")} or ${path39.join(res.cwd, ".pi", "settings.json")}`,
67746
67896
  fix: installCmd("user")
67747
67897
  };
67748
67898
  const where = `${entry.source} (${entry.scope}, ${entry.settingsFile})`;
67749
67899
  const rebuild = `cd ${JSON.stringify(entry.root)} && bun run build`;
67750
- const pkg = readJson(path38.join(entry.root, "package.json"));
67900
+ const pkg = readJson(path39.join(entry.root, "package.json"));
67751
67901
  if (!pkg)
67752
67902
  return {
67753
67903
  id: "pi_extension",
@@ -67756,7 +67906,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67756
67906
  fix: entry.npm ? installCmd(entry.scope, entry.source) : `restore ${entry.root}, then ${rebuild}`
67757
67907
  };
67758
67908
  const declared = Array.isArray(pkg.pi?.extensions) ? pkg.pi.extensions.some((e) => typeof e === "string" && e.replace(/^\.\//, "") === PI_EXTENSION) : false;
67759
- if (!declared || !existsSync16(path38.join(entry.root, PI_EXTENSION)))
67909
+ if (!declared || !existsSync16(path39.join(entry.root, PI_EXTENSION)))
67760
67910
  return {
67761
67911
  id: "pi_extension",
67762
67912
  status: "warn",
@@ -67809,21 +67959,21 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67809
67959
  detail: `Workit Pi extension ${version ?? "?"} from ${where} loads ${PI_EXTENSION}`
67810
67960
  };
67811
67961
  }, assetPathsFor = (host, dev) => {
67812
- const pkg = path38.join(dev, "packages", `workit-${host}`);
67962
+ const pkg = path39.join(dev, "packages", `workit-${host}`);
67813
67963
  switch (host) {
67814
67964
  case "opencode": {
67815
- const packaged = path38.join(pkg, "assets", "skills");
67816
- const root = existsSync16(packaged) ? packaged : path38.join(dev, "packages", "workit-core", "skills");
67817
- return WORKIT_METHOD_SKILLS.map((skill) => path38.join(root, skill, "SKILL.md"));
67965
+ const packaged = path39.join(pkg, "assets", "skills");
67966
+ const root = existsSync16(packaged) ? packaged : path39.join(dev, "packages", "workit-core", "skills");
67967
+ return WORKIT_METHOD_SKILLS.map((skill) => path39.join(root, skill, "SKILL.md"));
67818
67968
  }
67819
67969
  case "cursor":
67820
67970
  return [
67821
- path38.join(pkg, "assets", "templates", "workit-contract.md"),
67822
- path38.join(pkg, "mcp.json"),
67823
- path38.join(pkg, ".cursor-plugin")
67971
+ path39.join(pkg, "assets", "templates", "workit-contract.md"),
67972
+ path39.join(pkg, "mcp.json"),
67973
+ path39.join(pkg, ".cursor-plugin")
67824
67974
  ];
67825
67975
  case "cli":
67826
- return [path38.join(pkg, "assets", "templates", "spec-template.md")];
67976
+ return [path39.join(pkg, "assets", "templates", "spec-template.md")];
67827
67977
  }
67828
67978
  }, hostsFor = (host) => host === "cli" ? ["opencode", "cursor", "cli"] : [host], checkAssets = (res) => {
67829
67979
  const dev = res.dev;
@@ -67854,22 +68004,22 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67854
68004
  fix: "Reinstall or rebuild the workit package (missing assets under packages/workit-<host>)"
67855
68005
  };
67856
68006
  }, launcherSlotsFor = (host, dev) => {
67857
- const pkg = path38.join(dev, "packages", `workit-${host}`);
68007
+ const pkg = path39.join(dev, "packages", `workit-${host}`);
67858
68008
  switch (host) {
67859
68009
  case "opencode":
67860
- return [[path38.join(pkg, "src", "plugin.ts"), path38.join(pkg, "dist", "plugin.js")]];
68010
+ return [[path39.join(pkg, "src", "plugin.ts"), path39.join(pkg, "dist", "plugin.js")]];
67861
68011
  case "cursor":
67862
68012
  return [
67863
- [path38.join(pkg, "dist", "mcp-server.js")],
67864
- [path38.join(pkg, "dist", "cursor-session-start.js")]
68013
+ [path39.join(pkg, "dist", "mcp-server.js")],
68014
+ [path39.join(pkg, "dist", "cursor-session-start.js")]
67865
68015
  ];
67866
68016
  case "cli":
67867
- return [[path38.join(pkg, "src", "index.tsx"), path38.join(pkg, "dist", "index.js")]];
68017
+ return [[path39.join(pkg, "src", "index.tsx"), path39.join(pkg, "dist", "index.js")]];
67868
68018
  }
67869
68019
  }, validNodeEntry = (entry, runtime, env) => {
67870
68020
  try {
67871
68021
  const stat = statSync6(entry);
67872
- if (!stat.isFile() || stat.size === 0 || !readFileSync16(entry, "utf8").startsWith(`#!/usr/bin/env node
68022
+ if (!stat.isFile() || stat.size === 0 || !readFileSync17(entry, "utf8").startsWith(`#!/usr/bin/env node
67873
68023
  `)) {
67874
68024
  return false;
67875
68025
  }
@@ -67891,7 +68041,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67891
68041
  if (typeof command !== "string" || !Array.isArray(args) || typeof args[0] !== "string") {
67892
68042
  return "invalid";
67893
68043
  }
67894
- const executable = path38.basename(command).toLowerCase();
68044
+ const executable = path39.basename(command).toLowerCase();
67895
68045
  const canonical = cursorMcpServerEntry("").args;
67896
68046
  if (executable === "npx" || executable === "npx.exe" || executable === "npx.cmd") {
67897
68047
  if (args.length !== canonical.length || args.some((a, i) => a !== canonical[i]))
@@ -67903,10 +68053,10 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67903
68053
  return {
67904
68054
  kind: "node",
67905
68055
  runtime: command,
67906
- entry: path38.isAbsolute(args[0]) ? args[0] : path38.resolve(path38.dirname(res.cursorMcp), args[0])
68056
+ entry: path39.isAbsolute(args[0]) ? args[0] : path39.resolve(path39.dirname(res.cursorMcp), args[0])
67907
68057
  };
67908
68058
  }, canonicalCursorHook, isCanonicalCursorHook = (command, res) => command === canonicalCursorHook || command === cursorHooksEntry(res.cursorPluginDir).command, registeredCursorHook = (res) => {
67909
- const hooksFile = path38.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
68059
+ const hooksFile = path39.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
67910
68060
  if (!existsSync16(hooksFile))
67911
68061
  return "invalid";
67912
68062
  const config = readJson(hooksFile);
@@ -67924,9 +68074,9 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67924
68074
  if (!m)
67925
68075
  return false;
67926
68076
  const entry = m[1].trim();
67927
- if (!path38.isAbsolute(entry))
68077
+ if (!path39.isAbsolute(entry))
67928
68078
  return false;
67929
- if (path38.resolve(entry) !== path38.resolve(path38.join(res.cursorPluginDir, "dist", "cursor-session-start.js"))) {
68079
+ if (path39.resolve(entry) !== path39.resolve(path39.join(res.cursorPluginDir, "dist", "cursor-session-start.js"))) {
67930
68080
  return false;
67931
68081
  }
67932
68082
  return validNodeEntry(entry, "node", res.env);
@@ -67935,7 +68085,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67935
68085
  const hosts = hostsFor(res.host);
67936
68086
  const registered = hosts.includes("cursor") ? registeredCursorLauncher(res) : null;
67937
68087
  const runtime = registered && registered !== "invalid" && registered.kind === "node" ? registered.runtime : "node";
67938
- const missing = hosts.includes("cursor") ? ["dist/mcp-server.js", "dist/cursor-session-start.js"].map((rel) => path38.join(res.cursorPluginDir, rel)).filter((p) => !validNodeEntry(p, runtime, res.env)).map((p) => `cursor: ${p}`) : [];
68088
+ 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}`) : [];
67939
68089
  if (hosts.includes("cursor")) {
67940
68090
  if (registered === "invalid") {
67941
68091
  missing.push(`cursor: canonical workit MCP launcher in ${res.cursorMcp}`);
@@ -67944,9 +68094,9 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67944
68094
  }
67945
68095
  const hook = registeredCursorHook(res);
67946
68096
  if (hook === "invalid") {
67947
- missing.push(`cursor: canonical session-start hook in ${path38.join(res.cursorPluginDir, "hooks", "hooks-cursor.json")}`);
68097
+ missing.push(`cursor: canonical session-start hook in ${path39.join(res.cursorPluginDir, "hooks", "hooks-cursor.json")}`);
67948
68098
  } else if (hook !== null && !isCanonicalCursorHook(hook, res) && !validLocalDistHook(hook, res)) {
67949
- missing.push(`cursor: canonical session-start hook in ${path38.join(res.cursorPluginDir, "hooks", "hooks-cursor.json")} (registered ${hook})`);
68099
+ missing.push(`cursor: canonical session-start hook in ${path39.join(res.cursorPluginDir, "hooks", "hooks-cursor.json")} (registered ${hook})`);
67950
68100
  }
67951
68101
  }
67952
68102
  if (dev) {
@@ -67982,10 +68132,10 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67982
68132
  const normal = entry.replaceAll("\\", "/").replace(/\/+$/, "");
67983
68133
  if (!normal.endsWith("local/workit") && !normal.endsWith("local/workflow-toolkit"))
67984
68134
  continue;
67985
- const dir = entry.startsWith("~") ? path38.join(res.home, entry.slice(1)) : entry;
68135
+ const dir = entry.startsWith("~") ? path39.join(res.home, entry.slice(1)) : entry;
67986
68136
  let state = null;
67987
68137
  try {
67988
- state = readdirSync8(dir).length === 0 ? "empty" : null;
68138
+ state = readdirSync10(dir).length === 0 ? "empty" : null;
67989
68139
  } catch {
67990
68140
  state = "missing";
67991
68141
  }
@@ -68007,17 +68157,26 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68007
68157
  status: "pass",
68008
68158
  detail: "no registered Workit host plugin is missing its files"
68009
68159
  };
68010
- return { id: "plugin_files", status: "warn", detail: problems.join("; "), fix: fixes.join("; ") };
68160
+ return {
68161
+ id: "plugin_files",
68162
+ status: "warn",
68163
+ detail: problems.join("; "),
68164
+ fix: fixes.join("; ")
68165
+ };
68011
68166
  }, CURSOR_HOOK_FIX = "Run `workit init` and select Cursor to install the bundled hook", checkCursorHook = (res) => {
68012
68167
  if (!hostsFor(res.host).includes("cursor"))
68013
- return { id: "cursor_hook", status: "pass", detail: "cursor hook not inspected on this host" };
68168
+ return {
68169
+ id: "cursor_hook",
68170
+ status: "pass",
68171
+ detail: "cursor hook not inspected on this host"
68172
+ };
68014
68173
  if (!existsSync16(res.cursorPluginDir))
68015
68174
  return {
68016
68175
  id: "cursor_hook",
68017
68176
  status: "pass",
68018
68177
  detail: "no Cursor plugin install — hook launcher not inspected"
68019
68178
  };
68020
- const launcher = path38.join(res.cursorPluginDir, "hooks", "launch.mjs");
68179
+ const launcher = path39.join(res.cursorPluginDir, "hooks", "launch.mjs");
68021
68180
  if (!existsSync16(launcher))
68022
68181
  return {
68023
68182
  id: "cursor_hook",
@@ -68025,7 +68184,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68025
68184
  detail: `cursor hook launcher mode: missing — ${launcher} is absent (an install from before the pinned launcher)`,
68026
68185
  fix: CURSOR_HOOK_FIX
68027
68186
  };
68028
- const hooksFile = path38.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
68187
+ const hooksFile = path39.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
68029
68188
  const registered = readJson(hooksFile);
68030
68189
  const sessionCommand = registered?.hooks?.sessionStart?.[0]?.command;
68031
68190
  const offLauncher = [
@@ -68084,7 +68243,11 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68084
68243
  detail: `${label}; probe ${ms} ms; ${silent}`,
68085
68244
  fix: "Open a Cursor agent chat, then re-run `workit doctor`; if this persists, re-run `workit init` with Cursor (it writes absolute hook paths)"
68086
68245
  };
68087
- return { id: "cursor_hook", status: "pass", detail: `${label}; probe ${ms} ms` };
68246
+ return {
68247
+ id: "cursor_hook",
68248
+ status: "pass",
68249
+ detail: `${label}; probe ${ms} ms`
68250
+ };
68088
68251
  }, SILENT_HOOK_GRACE_MS, mtimeMs = (file) => {
68089
68252
  try {
68090
68253
  return statSync6(file).mtimeMs;
@@ -68092,10 +68255,10 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68092
68255
  return null;
68093
68256
  }
68094
68257
  }, silentCursorHooks = (res) => {
68095
- const session = mtimeMs(path38.join(res.cursorHeartbeatDir, "cursor-session-last-start"));
68258
+ const session = mtimeMs(path39.join(res.cursorHeartbeatDir, "cursor-session-last-start"));
68096
68259
  if (session === null || Date.now() - session < SILENT_HOOK_GRACE_MS)
68097
68260
  return null;
68098
- const hook = mtimeMs(path38.join(res.cursorHeartbeatDir, "cursor-hook-last-run"));
68261
+ const hook = mtimeMs(path39.join(res.cursorHeartbeatDir, "cursor-hook-last-run"));
68099
68262
  if (hook !== null && hook >= session)
68100
68263
  return null;
68101
68264
  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`;
@@ -68191,7 +68354,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68191
68354
  }
68192
68355
  return { id: "stale_pin", status: "pass", detail: "opencode pin resolves" };
68193
68356
  }, pluginMcpSelectors = (res) => {
68194
- const p = path38.join(res.cursorPluginDir, "mcp.json");
68357
+ const p = path39.join(res.cursorPluginDir, "mcp.json");
68195
68358
  if (!existsSync16(p))
68196
68359
  return null;
68197
68360
  const cfg = readJson(p);
@@ -68225,19 +68388,19 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68225
68388
  return null;
68226
68389
  }
68227
68390
  }, installedPluginVersion = (res) => {
68228
- const pkg = readJson(path38.join(res.cursorPluginDir, "package.json"));
68391
+ const pkg = readJson(path39.join(res.cursorPluginDir, "package.json"));
68229
68392
  return typeof pkg?.version === "string" && pkg.version ? pkg.version : null;
68230
68393
  }, installedOpenCodeCache = (res) => {
68231
68394
  if (res.opencodePackageCacheDir !== null) {
68232
- const pkg = readJson(path38.join(res.opencodePackageCacheDir, "node_modules", "@brainervirus", "workit-opencode", "package.json"));
68395
+ const pkg = readJson(path39.join(res.opencodePackageCacheDir, "node_modules", "@brainervirus", "workit-opencode", "package.json"));
68233
68396
  return typeof pkg?.version === "string" && pkg.version ? { version: pkg.version, dir: res.opencodePackageCacheDir } : null;
68234
68397
  }
68235
68398
  const found = openCodeInstalledPlugin(res.home, res.env);
68236
68399
  if (!found)
68237
68400
  return null;
68238
- let dir = path38.dirname(path38.dirname(path38.dirname(found.root)));
68239
- if (path38.basename(dir) !== "workit-opencode@latest")
68240
- dir = path38.dirname(dir);
68401
+ let dir = path39.dirname(path39.dirname(path39.dirname(found.root)));
68402
+ if (path39.basename(dir) !== "workit-opencode@latest")
68403
+ dir = path39.dirname(dir);
68241
68404
  return { version: found.version, dir };
68242
68405
  }, checkOpenCodePackageCache = (res) => {
68243
68406
  if (!existsSync16(res.opencodeConfig)) {
@@ -68341,7 +68504,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68341
68504
  fix: "Re-run install-cursor-plugin.sh — it rewrites the workit MCP entry to the canonical @latest selector"
68342
68505
  };
68343
68506
  }
68344
- const hooksFile = path38.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
68507
+ const hooksFile = path39.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
68345
68508
  const hookCmd = readJson(hooksFile)?.hooks?.sessionStart?.[0]?.command ?? null;
68346
68509
  const canonicalHook = canonicalCursorHook;
68347
68510
  const staleHook = hookCmd !== null && !isCanonicalCursorHook(hookCmd, res) && !hookCmd.startsWith("node ") && hookCmd.includes("@brainervirus/workit-cursor@");
@@ -68363,7 +68526,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68363
68526
  };
68364
68527
  }
68365
68528
  const installed = installedPluginVersion(res);
68366
- const source = res.dev ? readJson(path38.join(res.dev, "packages/workit-cursor/package.json"))?.version ?? null : readJson(path38.join(packageRoot(), "package.json"))?.version ?? null;
68529
+ const source = res.dev ? readJson(path39.join(res.dev, "packages/workit-cursor/package.json"))?.version ?? null : readJson(path39.join(packageRoot(), "package.json"))?.version ?? null;
68367
68530
  const localDist = mcpSelectors === null && hookCmd !== null && !isCanonicalCursorHook(hookCmd, res) && hookCmd.startsWith("node ");
68368
68531
  if (localDist && installed !== null && source !== null && !semverAtLeast(installed, source)) {
68369
68532
  return {
@@ -68375,7 +68538,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68375
68538
  }
68376
68539
  if (localDist && installed !== null && source !== null && res.dev) {
68377
68540
  const entry = /^node\s+(.+)$/.exec((hookCmd ?? "").trim())?.[1]?.trim() ?? "";
68378
- const sourceBundle = entry && path38.isAbsolute(entry) ? path38.join(res.dev, "packages", "workit-cursor", "dist", path38.basename(entry)) : "";
68541
+ const sourceBundle = entry && path39.isAbsolute(entry) ? path39.join(res.dev, "packages", "workit-cursor", "dist", path39.basename(entry)) : "";
68379
68542
  if (entry && sourceBundle) {
68380
68543
  const installedHash = bundleHashOfFile(entry);
68381
68544
  const sourceHash = bundleHashOfFile(sourceBundle);
@@ -68383,7 +68546,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68383
68546
  return {
68384
68547
  id: "stale_install",
68385
68548
  status: "fail",
68386
- detail: `stale_install: installed workit-cursor ${installed} runs different bytes than the current runtime build (${path38.basename(entry)} hash mismatch)`,
68549
+ detail: `stale_install: installed workit-cursor ${installed} runs different bytes than the current runtime build (${path39.basename(entry)} hash mismatch)`,
68387
68550
  fix: "Re-run install-cursor-plugin.sh — it refreshes the plugin directory with the current build"
68388
68551
  };
68389
68552
  }
@@ -68483,7 +68646,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68483
68646
  }, checkMalformedConfig = (res) => {
68484
68647
  const files = [];
68485
68648
  for (const name of ["config.json", "youtrack.json", "vcs.json", "workspaces.json"]) {
68486
- const p = path38.join(res.configDir, name);
68649
+ const p = path39.join(res.configDir, name);
68487
68650
  if (existsSync16(p))
68488
68651
  files.push(p);
68489
68652
  }
@@ -68608,7 +68771,10 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68608
68771
  const slot = `${SESSION_HOOK_NAME} hook`;
68609
68772
  switch (hook.state) {
68610
68773
  case "not_git":
68611
- return { status: "pass", detail: `not inside a git work tree — skipping the ${slot}` };
68774
+ return {
68775
+ status: "pass",
68776
+ detail: `not inside a git work tree — skipping the ${slot}`
68777
+ };
68612
68778
  case "installed":
68613
68779
  return {
68614
68780
  status: "pass",
@@ -68701,17 +68867,17 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68701
68867
  return { ...installSessionHook(res.cwd, res.env), workspace: workspace.name };
68702
68868
  }, isPlaceholder = (p) => {
68703
68869
  try {
68704
- return readFileSync16(p, "utf8").trim() === TOKEN_PLACEHOLDER2;
68870
+ return readFileSync17(p, "utf8").trim() === TOKEN_PLACEHOLDER2;
68705
68871
  } catch {
68706
68872
  return false;
68707
68873
  }
68708
68874
  }, checkCredentialMetadata = (res) => {
68709
68875
  const tokenPaths = [];
68710
- const youtrackJson = readJson(path38.join(res.configDir, "youtrack.json"));
68876
+ const youtrackJson = readJson(path39.join(res.configDir, "youtrack.json"));
68711
68877
  if (youtrackJson) {
68712
- tokenPaths.push(typeof youtrackJson.tokenFile === "string" ? youtrackJson.tokenFile : path38.join(res.configDir, "youtrack.token"));
68713
- } else if (existsSync16(path38.join(res.configDir, "youtrack.token"))) {
68714
- tokenPaths.push(path38.join(res.configDir, "youtrack.token"));
68878
+ tokenPaths.push(typeof youtrackJson.tokenFile === "string" ? youtrackJson.tokenFile : path39.join(res.configDir, "youtrack.token"));
68879
+ } else if (existsSync16(path39.join(res.configDir, "youtrack.token"))) {
68880
+ tokenPaths.push(path39.join(res.configDir, "youtrack.token"));
68715
68881
  }
68716
68882
  if (tokenPaths.length === 0) {
68717
68883
  return {
@@ -68722,7 +68888,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68722
68888
  }
68723
68889
  const problems = [];
68724
68890
  for (const raw of tokenPaths) {
68725
- const p = path38.isAbsolute(raw) ? raw : path38.resolve(res.configDir, raw);
68891
+ const p = path39.isAbsolute(raw) ? raw : path39.resolve(res.configDir, raw);
68726
68892
  if (!existsSync16(p)) {
68727
68893
  problems.push(`${p} is missing`);
68728
68894
  continue;
@@ -68802,7 +68968,10 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68802
68968
  },
68803
68969
  ghLogin: (e) => {
68804
68970
  try {
68805
- const out = spawnSync16("gh", ["api", "user", "--jq", ".login"], { encoding: "utf8", env: e });
68971
+ const out = spawnSync16("gh", ["api", "user", "--jq", ".login"], {
68972
+ encoding: "utf8",
68973
+ env: e
68974
+ });
68806
68975
  const login = (out.stdout ?? "").trim();
68807
68976
  return out.status === 0 && login ? login : null;
68808
68977
  } catch {
@@ -68837,8 +69006,12 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68837
69006
  }), checkGithubIdentity = (res, probes = defaultIdentityProbes(res.env)) => {
68838
69007
  const remoteHost = githubHostFromRemote(probes.origin(res.cwd) ?? "");
68839
69008
  if (!remoteHost)
68840
- return { id: "github_identity", status: "pass", detail: "no GitHub remote configured" };
68841
- const vcsJson = readJson(res.env.WORKFLOW_VCS_CONFIG ?? path38.join(res.configDir, "vcs.json"));
69009
+ return {
69010
+ id: "github_identity",
69011
+ status: "pass",
69012
+ detail: "no GitHub remote configured"
69013
+ };
69014
+ const vcsJson = readJson(res.env.WORKFLOW_VCS_CONFIG ?? path39.join(res.configDir, "vcs.json"));
68842
69015
  const workspace = workspaceProviderForIdentity(res.cwd, res.configDir, res.env);
68843
69016
  if (workspace.error)
68844
69017
  return {
@@ -68849,7 +69022,11 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68849
69022
  };
68850
69023
  const provider = identityProvider(remoteHost, vcsJson, workspace.provider);
68851
69024
  if (provider !== "github")
68852
- return { id: "github_identity", status: "pass", detail: "no GitHub remote configured" };
69025
+ return {
69026
+ id: "github_identity",
69027
+ status: "pass",
69028
+ detail: "no GitHub remote configured"
69029
+ };
68853
69030
  const cliHost = String(vcsJson?.github?.host ?? "github.com").toLowerCase();
68854
69031
  const cliLogin = probes.ghLogin({ ...res.env, GH_HOST: cliHost });
68855
69032
  if (!cliLogin)
@@ -68865,8 +69042,12 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68865
69042
  }, checkGitLabIdentity = (res, probes = defaultIdentityProbes(res.env)) => {
68866
69043
  const remoteHost = githubHostFromRemote(probes.origin(res.cwd) ?? "");
68867
69044
  if (!remoteHost)
68868
- return { id: "gitlab_identity", status: "pass", detail: "no GitLab remote configured" };
68869
- const vcsJson = readJson(res.env.WORKFLOW_VCS_CONFIG ?? path38.join(res.configDir, "vcs.json"));
69045
+ return {
69046
+ id: "gitlab_identity",
69047
+ status: "pass",
69048
+ detail: "no GitLab remote configured"
69049
+ };
69050
+ const vcsJson = readJson(res.env.WORKFLOW_VCS_CONFIG ?? path39.join(res.configDir, "vcs.json"));
68870
69051
  const workspace = workspaceProviderForIdentity(res.cwd, res.configDir, res.env);
68871
69052
  if (workspace.error)
68872
69053
  return {
@@ -68877,7 +69058,11 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68877
69058
  };
68878
69059
  const provider = identityProvider(remoteHost, vcsJson, workspace.provider);
68879
69060
  if (provider !== "gitlab")
68880
- return { id: "gitlab_identity", status: "pass", detail: "no GitLab remote configured" };
69061
+ return {
69062
+ id: "gitlab_identity",
69063
+ status: "pass",
69064
+ detail: "no GitLab remote configured"
69065
+ };
68881
69066
  const cliHost = String(vcsJson?.gitlab?.host ?? "gitlab.com").toLowerCase();
68882
69067
  const cliLogin = probes.glabLogin?.({ ...res.env, GITLAB_HOST: cliHost }) ?? null;
68883
69068
  if (!cliLogin)
@@ -68892,11 +69077,11 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68892
69077
  { surface: "SSH", login: probes.sshLogin(remoteHost) }
68893
69078
  ]);
68894
69079
  }, checkLogWritable = (res) => {
68895
- const logsDir = path38.join(res.stateDir, "logs");
68896
- const probe = path38.join(logsDir, "doctor-probe.tmp");
69080
+ const logsDir = path39.join(res.stateDir, "logs");
69081
+ const probe = path39.join(logsDir, "doctor-probe.tmp");
68897
69082
  try {
68898
- mkdirSync7(logsDir, { recursive: true, mode: 448 });
68899
- writeFileSync7(probe, `{"probe":true}
69083
+ mkdirSync8(logsDir, { recursive: true, mode: 448 });
69084
+ writeFileSync8(probe, `{"probe":true}
68900
69085
  `, { mode: 384 });
68901
69086
  return {
68902
69087
  id: "log_writable",
@@ -68926,7 +69111,11 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68926
69111
  fix
68927
69112
  };
68928
69113
  if (lock.state === "absent")
68929
- return { id: "workspace_lock", status: "pass", detail: "no metadata lock held" };
69114
+ return {
69115
+ id: "workspace_lock",
69116
+ status: "pass",
69117
+ detail: "no metadata lock held"
69118
+ };
68930
69119
  if (lock.state === "stale")
68931
69120
  return {
68932
69121
  id: "workspace_lock",
@@ -68971,7 +69160,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68971
69160
  const counts = { skip: 0, late: 0 };
68972
69161
  let text = "";
68973
69162
  try {
68974
- text = readFileSync16(path38.join(stateDir, HOOK_SKIPS_FILE), "utf8");
69163
+ text = readFileSync17(path39.join(stateDir, HOOK_SKIPS_FILE), "utf8");
68975
69164
  } catch {
68976
69165
  return counts;
68977
69166
  }
@@ -68989,7 +69178,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68989
69178
  }
68990
69179
  return counts;
68991
69180
  }, checkHookDeadline = (res) => {
68992
- const file = path38.join(res.hookStateDir, HOOK_SKIPS_FILE);
69181
+ const file = path39.join(res.hookStateDir, HOOK_SKIPS_FILE);
68993
69182
  const { skip, late } = countHookSkips(res.hookStateDir, Date.now() - DAY_MS);
68994
69183
  const lateText = late > 0 ? `; ${late} answered past it in full` : "";
68995
69184
  if (skip > 0)
@@ -69020,11 +69209,15 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69020
69209
  status: "warn",
69021
69210
  detail: line.split("; ")[0],
69022
69211
  fix: line.split("; ")[1]
69023
- } : { id: "grant_endpoint", status: "pass", detail: "grants and default endpoint agree" };
69212
+ } : {
69213
+ id: "grant_endpoint",
69214
+ status: "pass",
69215
+ detail: "grants and default endpoint agree"
69216
+ };
69024
69217
  }, checkChecksConfig = (res) => {
69025
69218
  const root = checkRoot(res.cwd);
69026
- const current = existsSync16(path38.join(root, CHECKS_FILE));
69027
- const legacy = existsSync16(path38.join(root, LEGACY_CHECKS_FILE));
69219
+ const current = existsSync16(path39.join(root, CHECKS_FILE));
69220
+ const legacy = existsSync16(path39.join(root, LEGACY_CHECKS_FILE));
69028
69221
  if (!legacy)
69029
69222
  return {
69030
69223
  id: "checks_config",
@@ -69039,8 +69232,8 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69039
69232
  };
69040
69233
  }, fixChecksConfig = (options = {}) => {
69041
69234
  const root = checkRoot(resolve(options).cwd);
69042
- const from = path38.join(root, LEGACY_CHECKS_FILE);
69043
- const to = path38.join(root, CHECKS_FILE);
69235
+ const from = path39.join(root, LEGACY_CHECKS_FILE);
69236
+ const to = path39.join(root, CHECKS_FILE);
69044
69237
  if (!existsSync16(from))
69045
69238
  return { action: "none", detail: `no ${LEGACY_CHECKS_FILE} at ${root}` };
69046
69239
  if (existsSync16(to))
@@ -69100,7 +69293,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69100
69293
  status: "info",
69101
69294
  detail: "no Workit Claude Code plugin install recorded — skipping"
69102
69295
  };
69103
- const registry = readJson(path38.join(claudeConfigDir(res.home, res.env), "plugins", "installed_plugins.json"));
69296
+ const registry = readJson(path39.join(claudeConfigDir(res.home, res.env), "plugins", "installed_plugins.json"));
69104
69297
  const recorded = (install) => {
69105
69298
  const entries = registry?.plugins?.[install.id];
69106
69299
  const entry = Array.isArray(entries) ? entries.find((e) => e?.installPath === install.installPath) : null;
@@ -69150,7 +69343,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69150
69343
  }, HOOK_ISSUED_MARKER = "workit-issued-sessions/3", hookRecordsIssued = (root) => {
69151
69344
  let files;
69152
69345
  try {
69153
- files = readdirSync8(path38.join(root, "dist")).filter((f) => f.endsWith(".js"));
69346
+ files = readdirSync10(path39.join(root, "dist")).filter((f) => f.endsWith(".js"));
69154
69347
  } catch {
69155
69348
  return null;
69156
69349
  }
@@ -69158,7 +69351,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69158
69351
  return null;
69159
69352
  return files.some((file) => {
69160
69353
  try {
69161
- return readFileSync16(path38.join(root, "dist", file), "utf8").includes(HOOK_ISSUED_MARKER);
69354
+ return readFileSync17(path39.join(root, "dist", file), "utf8").includes(HOOK_ISSUED_MARKER);
69162
69355
  } catch {
69163
69356
  return false;
69164
69357
  }
@@ -69214,7 +69407,11 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69214
69407
  env,
69215
69408
  timeout: WORKIT_PROBE_TIMEOUT_MS,
69216
69409
  shell: true
69217
- }) : spawnSync16(bin, ["--version"], { encoding: "utf8", env, timeout: WORKIT_PROBE_TIMEOUT_MS });
69410
+ }) : spawnSync16(bin, ["--version"], {
69411
+ encoding: "utf8",
69412
+ env,
69413
+ timeout: WORKIT_PROBE_TIMEOUT_MS
69414
+ });
69218
69415
  const timedOut = r.error !== undefined && "code" in r.error && r.error.code === "ETIMEDOUT";
69219
69416
  const version = r.status === 0 ? (r.stdout ?? "").match(SEMVER)?.[0] ?? null : null;
69220
69417
  const probe = { version: timedOut ? null : version, timedOut };
@@ -69227,14 +69424,22 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69227
69424
  version: i.version
69228
69425
  })),
69229
69426
  { label: "Cursor plugin", version: installedPluginVersion(res) },
69230
- { label: "OpenCode plugin", version: installedOpenCodeCache(res)?.version ?? null }
69427
+ {
69428
+ label: "OpenCode plugin",
69429
+ version: installedOpenCodeCache(res)?.version ?? null
69430
+ }
69231
69431
  ].filter((p) => p.version !== null);
69232
69432
  const newest = plugins.reduce((best, p) => best && semverAtLeast(best.version, p.version) ? best : p, null);
69233
69433
  const target = newest?.version ?? "latest";
69234
69434
  const fix = `npm i -g ${CLI_PACKAGE}@${target} (or run it without a global install: npx -y ${CLI_PACKAGE}@${target} <command>)`;
69235
69435
  const bin = findOnPath(pathextNames("workit", res.env), res.env);
69236
69436
  if (!bin) {
69237
- return { id: "workit_on_path", status: "warn", detail: "no workit on PATH", fix };
69437
+ return {
69438
+ id: "workit_on_path",
69439
+ status: "warn",
69440
+ detail: "no workit on PATH",
69441
+ fix
69442
+ };
69238
69443
  }
69239
69444
  const { version, timedOut } = workitVersionAt(bin, res.env);
69240
69445
  if (!version) {
@@ -69269,7 +69474,11 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69269
69474
  const file = permissionTarget(host, paths).file;
69270
69475
  switch (health.state) {
69271
69476
  case "no-host":
69272
- return { id, status: "info", detail: `${host} not found; no permission block needed` };
69477
+ return {
69478
+ id,
69479
+ status: "info",
69480
+ detail: `${host} not found; no permission block needed`
69481
+ };
69273
69482
  case "absent":
69274
69483
  return {
69275
69484
  id,
@@ -69277,10 +69486,79 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
69277
69486
  detail: `no Workit permission block in ${file} (optional: \`${fix}\` lets agents run Workit's delivery verbs without a prompt)`
69278
69487
  };
69279
69488
  case "ok":
69280
- return { id, status: "pass", detail: `Workit's permission block is current in ${file}` };
69489
+ return {
69490
+ id,
69491
+ status: "pass",
69492
+ detail: `Workit's permission block is current in ${file}`
69493
+ };
69281
69494
  default:
69282
69495
  return { id, status: "warn", detail: health.detail, fix };
69283
69496
  }
69497
+ }, checkGrantRules = (host, id) => (res) => {
69498
+ const paths = {
69499
+ home: res.home,
69500
+ env: res.codexHome ? { ...res.env, CODEX_HOME: res.codexHome } : res.env,
69501
+ stateDir: res.stateDir,
69502
+ cwd: res.cwd
69503
+ };
69504
+ let entry = null;
69505
+ try {
69506
+ entry = resolveWorkspaceFrom(res.cwd, res.configDir);
69507
+ } catch {}
69508
+ if (!entry)
69509
+ return {
69510
+ id,
69511
+ status: "info",
69512
+ detail: "no Workit workspace here; no grants to cover"
69513
+ };
69514
+ const { grants } = configuredGrants(entry);
69515
+ const granted = ["push", "pr", "merge"].filter((kind) => kind === "merge" ? Boolean(grants.merge) : grants[kind] !== false);
69516
+ const coverage = permissionCoverage(host, grantedCommands(granted), paths);
69517
+ if (coverage.state === "no-host")
69518
+ return {
69519
+ id,
69520
+ status: "info",
69521
+ detail: `${host} not found; no rules to check`
69522
+ };
69523
+ if (coverage.state === "ok")
69524
+ return {
69525
+ id,
69526
+ status: "pass",
69527
+ detail: `${host} rules cover the granted Workit verbs (${granted.join(", ") || "none"}) and the check and lock verbs`
69528
+ };
69529
+ const shown = coverage.missing.slice(0, 4).join(", ");
69530
+ return {
69531
+ id,
69532
+ status: "warn",
69533
+ detail: `${host} rules in ${coverage.file} do not cover ${shown}${coverage.missing.length > 4 ? ", …" : ""}${existsSync16(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`,
69534
+ fix: `workit setup --hosts=${host}`
69535
+ };
69536
+ }, ago = (ms) => {
69537
+ const minutes = Math.max(0, Math.round(ms / 60000));
69538
+ if (minutes < 1)
69539
+ return "just now";
69540
+ if (minutes < 60)
69541
+ return `${minutes} min ago`;
69542
+ const hours = Math.round(minutes / 60);
69543
+ return hours < 48 ? `${hours} h ago` : `${Math.round(hours / 24)} d ago`;
69544
+ }, checkHookRuns = (res) => {
69545
+ const runs = readHookRuns(res.hookStateDir).filter((run) => run.event === "PreToolUse" || run.event === "SessionStart");
69546
+ if (runs.length === 0)
69547
+ return {
69548
+ id: "hook_runs",
69549
+ status: "info",
69550
+ detail: "no host hook run recorded yet (counted from this Workit version on; Claude Code launcher fast-path answers and Codex PostToolUse are not counted; start an agent session, then re-run `workit doctor`)"
69551
+ };
69552
+ const now = Date.now();
69553
+ const hosts = [...new Set(runs.map((run) => run.host))].toSorted();
69554
+ const parts = hosts.map((host) => {
69555
+ const seen = ["SessionStart", "PreToolUse"].map((event) => {
69556
+ const run = runs.find((r) => r.host === host && r.event === event);
69557
+ return `${event} ${run ? `${ago(now - Date.parse(run.at))} (${run.count})` : "never"}`;
69558
+ });
69559
+ return `${host}: ${seen.join(", ")}`;
69560
+ });
69561
+ return { id: "hook_runs", status: "pass", detail: parts.join("; ") };
69284
69562
  }, RUN_CHECKS, INSTALLER_REQUIRED, runDoctor = (options = {}) => {
69285
69563
  const res = resolve(options);
69286
69564
  const raw = RUN_CHECKS.map((fn) => fn(res));
@@ -69332,6 +69610,7 @@ var init_doctor = __esm(() => {
69332
69610
  init_host_install();
69333
69611
  init_skill_manifests();
69334
69612
  init_session_hook();
69613
+ init_hook_runs();
69335
69614
  init_host_permissions();
69336
69615
  OPENCODE_V1_FIX = `OpenCode < ${SUPPORT_MATRIX.opencode.minimum} cannot load Workit 3 (V2 plugin API only): upgrade OpenCode to ${SUPPORT_MATRIX.opencode.minimum}+, or stay on Workit 2.x by pinning "@brainervirus/workit-opencode@2" in the opencode.json "plugin" array`;
69337
69616
  AGENT_MARKER_VERSION = /^# Generated by Workit (\d+\.\d+\.\d+)\b/;
@@ -69371,10 +69650,14 @@ var init_doctor = __esm(() => {
69371
69650
  checkHeavyScope,
69372
69651
  checkHookDeadline,
69373
69652
  checkGrantEndpoint,
69653
+ checkHookRuns,
69374
69654
  checkChecksConfig,
69375
69655
  checkHostPermissions("claude-code", "claude_permissions"),
69376
69656
  checkHostPermissions("codex", "codex_permissions"),
69377
- checkHostPermissions("cursor", "cursor_permissions")
69657
+ checkHostPermissions("cursor", "cursor_permissions"),
69658
+ checkGrantRules("claude-code", "claude_grant_rules"),
69659
+ checkGrantRules("codex", "codex_grant_rules"),
69660
+ checkGrantRules("cursor", "cursor_grant_rules")
69378
69661
  ];
69379
69662
  INSTALLER_REQUIRED = new Set([
69380
69663
  "runtime",
@@ -69394,19 +69677,19 @@ import {
69394
69677
  cpSync as cpSync4,
69395
69678
  existsSync as existsSync17,
69396
69679
  lstatSync as lstatSync6,
69397
- mkdirSync as mkdirSync8,
69680
+ mkdirSync as mkdirSync9,
69398
69681
  mkdtempSync as mkdtempSync2,
69399
- readFileSync as readFileSync17,
69400
- readdirSync as readdirSync9,
69682
+ readFileSync as readFileSync18,
69683
+ readdirSync as readdirSync11,
69401
69684
  realpathSync as realpathSync8,
69402
69685
  renameSync as renameSync5,
69403
69686
  rmSync as rmSync5,
69404
69687
  statSync as statSync7,
69405
- writeFileSync as writeFileSync8
69688
+ writeFileSync as writeFileSync9
69406
69689
  } from "node:fs";
69407
69690
  import { createRequire as createRequire2 } from "node:module";
69408
69691
  import os13 from "node:os";
69409
- import path39 from "node:path";
69692
+ import path40 from "node:path";
69410
69693
  import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
69411
69694
  function parseList(raw) {
69412
69695
  return raw.split(",").map((s) => s.trim()).filter(Boolean);
@@ -69451,7 +69734,7 @@ function buildSetupPreview(values, opts = {}) {
69451
69734
  const current = readConfigFromDir(state.configDir);
69452
69735
  mutations.push({
69453
69736
  type: "merge-json",
69454
- path: path39.join(state.configDir, "config.json"),
69737
+ path: path40.join(state.configDir, "config.json"),
69455
69738
  value: {
69456
69739
  locale: values.locale,
69457
69740
  localeOptions: current.localeOptions,
@@ -69477,17 +69760,17 @@ function buildSetupPreview(values, opts = {}) {
69477
69760
  if (blocked.length === 0) {
69478
69761
  mutations.push({
69479
69762
  type: "update-workspaces",
69480
- path: path39.join(state.configDir, "workspaces.json"),
69763
+ path: path40.join(state.configDir, "workspaces.json"),
69481
69764
  entries: values.workspaces,
69482
69765
  expectedRevision: diskWorkspaceResult.revision
69483
69766
  });
69484
69767
  }
69485
69768
  }
69486
69769
  if (values.baseUrl.trim()) {
69487
- const ytPath = path39.join(state.configDir, "youtrack.json");
69770
+ const ytPath = path40.join(state.configDir, "youtrack.json");
69488
69771
  const ytExisting = readConfigRecord(ytPath);
69489
69772
  const ytConfigured = configuredTokenPath(ytExisting, "tokenFile");
69490
- const tokenPath = resolveTokenPath(ytConfigured, path39.join(state.configDir, "youtrack.token"), values.tokenPaths?.youtrack);
69773
+ const tokenPath = resolveTokenPath(ytConfigured, path40.join(state.configDir, "youtrack.token"), values.tokenPaths?.youtrack);
69491
69774
  const draft = youtrackDraft(values, tokenPath);
69492
69775
  if (ytConfigured !== null && tokenPath !== ytConfigured) {
69493
69776
  delete draft.tokenFile;
@@ -69515,7 +69798,7 @@ function buildSetupPreview(values, opts = {}) {
69515
69798
  });
69516
69799
  }
69517
69800
  if (values.vcsProvider !== "skip") {
69518
- const vcsPath = path39.join(state.configDir, "vcs.json");
69801
+ const vcsPath = path40.join(state.configDir, "vcs.json");
69519
69802
  mutations.push({
69520
69803
  type: "merge-json",
69521
69804
  path: vcsPath,
@@ -69544,7 +69827,7 @@ function buildSetupPreview(values, opts = {}) {
69544
69827
  mutations.push({
69545
69828
  type: "install-host",
69546
69829
  platform: "cursor",
69547
- path: path39.join(paths.home, ".cursor", "plugins", "local", ".workit-package-bootstrap"),
69830
+ path: path40.join(paths.home, ".cursor", "plugins", "local", ".workit-package-bootstrap"),
69548
69831
  commands
69549
69832
  });
69550
69833
  }
@@ -69557,7 +69840,7 @@ function buildSetupPreview(values, opts = {}) {
69557
69840
  mutations.push({
69558
69841
  type: "install-host",
69559
69842
  platform,
69560
- path: platform === "claude-code" ? claudeInstallRecord(paths.home, env) : platform === "codex" ? path39.join(env.CODEX_HOME ?? path39.join(paths.home, ".codex"), "plugins", "cache", "workflow-toolkit", "workit") : path39.join(env.PI_CODING_AGENT_DIR ?? path39.join(paths.home, ".pi", "agent"), "settings.json"),
69843
+ 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"),
69561
69844
  commands
69562
69845
  });
69563
69846
  }
@@ -69569,8 +69852,8 @@ function buildSetupPreview(values, opts = {}) {
69569
69852
  projectRefused = target.refused;
69570
69853
  if (target?.ok) {
69571
69854
  const root = target.root;
69572
- const gitignorePath = path39.join(root, ".gitignore");
69573
- const existing = existsSync17(gitignorePath) ? readFileSync17(gitignorePath, "utf8") : "";
69855
+ const gitignorePath = path40.join(root, ".gitignore");
69856
+ const existing = existsSync17(gitignorePath) ? readFileSync18(gitignorePath, "utf8") : "";
69574
69857
  const existingLines = new Set(existing.split(`
69575
69858
  `).map((l) => l.trim()).filter(Boolean));
69576
69859
  const entries = GITIGNORE_ENTRIES.filter((e) => e.trim() !== "" && !existingLines.has(e.trim()));
@@ -69607,10 +69890,10 @@ function deepMerge(base, patch) {
69607
69890
  return out;
69608
69891
  }
69609
69892
  function applyMutation(m) {
69610
- const dir = path39.dirname(m.path);
69893
+ const dir = path40.dirname(m.path);
69611
69894
  switch (m.type) {
69612
69895
  case "create-file": {
69613
- mkdirSync8(dir, { recursive: true });
69896
+ mkdirSync9(dir, { recursive: true });
69614
69897
  const res = writeFileExclusive(m.path, m.content, m.mode);
69615
69898
  return res === "created" ? { platform: "core", file: m.path, status: "Installed" } : {
69616
69899
  platform: "core",
@@ -69633,8 +69916,8 @@ function applyMutation(m) {
69633
69916
  if (existing.kind === "record" && JSON.stringify(existing.value) === JSON.stringify(merged)) {
69634
69917
  return { platform: "core", file: m.path, status: "Skipped", detail: "already configured" };
69635
69918
  }
69636
- mkdirSync8(dir, { recursive: true });
69637
- writeFileSync8(m.path, JSON.stringify(merged, null, 2) + `
69919
+ mkdirSync9(dir, { recursive: true });
69920
+ writeFileSync9(m.path, JSON.stringify(merged, null, 2) + `
69638
69921
  `, "utf8");
69639
69922
  return existing.kind === "record" ? { platform: "core", file: m.path, status: "Configured" } : { platform: "core", file: m.path, status: "Installed" };
69640
69923
  }
@@ -69675,10 +69958,10 @@ function applyMutation(m) {
69675
69958
  `;
69676
69959
  if (prev === next)
69677
69960
  return { platform: "core", file: m.path, status: "Skipped", detail: "already configured" };
69678
- mkdirSync8(dir, { recursive: true });
69961
+ mkdirSync9(dir, { recursive: true });
69679
69962
  const tmp = `${m.path}.${process.pid}.tmp`;
69680
69963
  try {
69681
- writeFileSync8(tmp, next, "utf8");
69964
+ writeFileSync9(tmp, next, "utf8");
69682
69965
  if (workspacesRevision(readFileSafe(m.path)) !== m.expectedRevision) {
69683
69966
  rmSync5(tmp, { force: true });
69684
69967
  return {
@@ -69713,11 +69996,11 @@ function applyMutation(m) {
69713
69996
  detail: "all entries already present"
69714
69997
  };
69715
69998
  }
69716
- mkdirSync8(dir, { recursive: true });
69999
+ mkdirSync9(dir, { recursive: true });
69717
70000
  const separator = existing && !existing.endsWith(`
69718
70001
  `) ? `
69719
70002
  ` : "";
69720
- writeFileSync8(m.path, existing + separator + (existing ? `
70003
+ writeFileSync9(m.path, existing + separator + (existing ? `
69721
70004
  ` : "") + add.join(`
69722
70005
  `) + `
69723
70006
  `, "utf8");
@@ -69756,8 +70039,8 @@ function applyMutation(m) {
69756
70039
  detail: "already configured"
69757
70040
  };
69758
70041
  }
69759
- mkdirSync8(path39.dirname(m.path), { recursive: true });
69760
- writeFileSync8(m.path, JSON.stringify(merged, null, 2) + `
70042
+ mkdirSync9(path40.dirname(m.path), { recursive: true });
70043
+ writeFileSync9(m.path, JSON.stringify(merged, null, 2) + `
69761
70044
  `, "utf8");
69762
70045
  return existing.kind === "record" ? { platform: "core", file: m.path, status: "Configured" } : { platform: "core", file: m.path, status: "Installed" };
69763
70046
  }
@@ -69765,11 +70048,11 @@ function applyMutation(m) {
69765
70048
  }
69766
70049
  function adapterRoot(platform, res, preferInstalledAdapter = false) {
69767
70050
  const candidates = [];
69768
- const stagedCursor = path39.join(res.home, ".cursor", "plugins", "local", ".workit-package-bootstrap", "node_modules", "@brainervirus", "workit-cursor");
70051
+ const stagedCursor = path40.join(res.home, ".cursor", "plugins", "local", ".workit-package-bootstrap", "node_modules", "@brainervirus", "workit-cursor");
69769
70052
  if (platform === "cursor" && preferInstalledAdapter)
69770
70053
  candidates.push(stagedCursor);
69771
70054
  if (res.dev) {
69772
- candidates.push(path39.join(res.dev, "packages", `workit-${platform}`));
70055
+ candidates.push(path40.join(res.dev, "packages", `workit-${platform}`));
69773
70056
  } else {
69774
70057
  candidates.push(...nodeResolvedAdapters(platform));
69775
70058
  if (platform === "cursor")
@@ -69779,10 +70062,10 @@ function adapterRoot(platform, res, preferInstalledAdapter = false) {
69779
70062
  if (cached)
69780
70063
  candidates.push(cached.root);
69781
70064
  }
69782
- let dir = path39.resolve(res.cwd);
70065
+ let dir = path40.resolve(res.cwd);
69783
70066
  while (true) {
69784
- candidates.push(path39.join(dir, "packages", `workit-${platform}`));
69785
- const parent = path39.dirname(dir);
70067
+ candidates.push(path40.join(dir, "packages", `workit-${platform}`));
70068
+ const parent = path40.dirname(dir);
69786
70069
  if (parent === dir)
69787
70070
  break;
69788
70071
  dir = parent;
@@ -69804,7 +70087,7 @@ function applyOpenCode(root, res) {
69804
70087
  detail: "workit-opencode package has no loadable plugin entry (src/plugin.ts or dist/plugin.js)"
69805
70088
  };
69806
70089
  }
69807
- mkdirSync8(path39.dirname(res.opencodeConfig), { recursive: true });
70090
+ mkdirSync9(path40.dirname(res.opencodeConfig), { recursive: true });
69808
70091
  const existing = readExisting(res.opencodeConfig);
69809
70092
  if (existing.kind === "malformed") {
69810
70093
  return {
@@ -69833,7 +70116,7 @@ function applyOpenCode(root, res) {
69833
70116
  detail: "already registered"
69834
70117
  };
69835
70118
  }
69836
- writeFileSync8(res.opencodeConfig, JSON.stringify(merged.config, null, 2) + `
70119
+ writeFileSync9(res.opencodeConfig, JSON.stringify(merged.config, null, 2) + `
69837
70120
  `, "utf8");
69838
70121
  return existing.kind === "record" ? {
69839
70122
  platform: "opencode",
@@ -69849,31 +70132,31 @@ function applyOpenCode(root, res) {
69849
70132
  }
69850
70133
  function copyPluginDir(src, dest) {
69851
70134
  const realSrc = realpathSync8(src);
69852
- const marker = path39.join(dest, ".workit-root");
70135
+ const marker = path40.join(dest, ".workit-root");
69853
70136
  const destIsLink = existsSync17(dest) && lstatSync6(dest).isSymbolicLink();
69854
70137
  const synced = !destIsLink && readFileSafe(marker)?.trim() === realSrc && samePluginContent(realSrc, dest, dest);
69855
70138
  if (synced)
69856
70139
  return "Skipped";
69857
70140
  const hadDir = existsSync17(dest);
69858
70141
  const rules = preservedCursorRules(realSrc, dest);
69859
- const parent = path39.dirname(dest);
69860
- mkdirSync8(parent, { recursive: true });
69861
- const swap = mkdtempSync2(path39.join(parent, `.${path39.basename(dest)}.swap-`));
69862
- const stage = path39.join(swap, "stage");
69863
- const backup = path39.join(swap, "backup");
70142
+ const parent = path40.dirname(dest);
70143
+ mkdirSync9(parent, { recursive: true });
70144
+ const swap = mkdtempSync2(path40.join(parent, `.${path40.basename(dest)}.swap-`));
70145
+ const stage = path40.join(swap, "stage");
70146
+ const backup = path40.join(swap, "backup");
69864
70147
  try {
69865
70148
  cpSync4(realSrc, stage, {
69866
70149
  recursive: true,
69867
- filter: (entry) => !path39.relative(realSrc, entry).split(path39.sep).includes("node_modules")
70150
+ filter: (entry) => !path40.relative(realSrc, entry).split(path40.sep).includes("node_modules")
69868
70151
  });
69869
- const stagedHooks = path39.join(stage, CURSOR_HOOKS_FILE);
70152
+ const stagedHooks = path40.join(stage, CURSOR_HOOKS_FILE);
69870
70153
  if (existsSync17(stagedHooks))
69871
- writeFileSync8(stagedHooks, localizedCursorHooks(readFileSync17(stagedHooks), dest));
70154
+ writeFileSync9(stagedHooks, localizedCursorHooks(readFileSync18(stagedHooks), dest));
69872
70155
  for (const [name, content] of rules) {
69873
- mkdirSync8(path39.join(stage, "rules"), { recursive: true });
69874
- writeFileSync8(path39.join(stage, "rules", name), content);
70156
+ mkdirSync9(path40.join(stage, "rules"), { recursive: true });
70157
+ writeFileSync9(path40.join(stage, "rules", name), content);
69875
70158
  }
69876
- writeFileSync8(path39.join(stage, ".workit-root"), realSrc + `
70159
+ writeFileSync9(path40.join(stage, ".workit-root"), realSrc + `
69877
70160
  `, "utf8");
69878
70161
  if (!samePluginContent(realSrc, stage, dest))
69879
70162
  throw new Error("staged adapter content is incomplete");
@@ -69896,7 +70179,7 @@ function copyPluginDir(src, dest) {
69896
70179
  return hadDir ? "Configured" : "Installed";
69897
70180
  }
69898
70181
  function applyCursorSettings(root, res) {
69899
- mkdirSync8(path39.dirname(res.cursorSettings), { recursive: true });
70182
+ mkdirSync9(path40.dirname(res.cursorSettings), { recursive: true });
69900
70183
  const settingsExisting = readExisting(res.cursorSettings);
69901
70184
  if (settingsExisting.kind === "malformed") {
69902
70185
  return {
@@ -69915,7 +70198,7 @@ function applyCursorSettings(root, res) {
69915
70198
  detail: "already registered"
69916
70199
  };
69917
70200
  }
69918
- writeFileSync8(res.cursorSettings, JSON.stringify(settings.config, null, 2) + `
70201
+ writeFileSync9(res.cursorSettings, JSON.stringify(settings.config, null, 2) + `
69919
70202
  `, "utf8");
69920
70203
  return {
69921
70204
  platform: "cursor",
@@ -69924,7 +70207,7 @@ function applyCursorSettings(root, res) {
69924
70207
  };
69925
70208
  }
69926
70209
  function applyCursorMcp(root, res) {
69927
- mkdirSync8(path39.dirname(res.cursorMcp), { recursive: true });
70210
+ mkdirSync9(path40.dirname(res.cursorMcp), { recursive: true });
69928
70211
  const mcpExisting = readExisting(res.cursorMcp);
69929
70212
  if (mcpExisting.kind === "malformed") {
69930
70213
  return {
@@ -69954,7 +70237,7 @@ function applyCursorMcp(root, res) {
69954
70237
  detail: "already registered"
69955
70238
  };
69956
70239
  }
69957
- writeFileSync8(res.cursorMcp, JSON.stringify(mcp.config, null, 2) + `
70240
+ writeFileSync9(res.cursorMcp, JSON.stringify(mcp.config, null, 2) + `
69958
70241
  `, "utf8");
69959
70242
  return {
69960
70243
  platform: "cursor",
@@ -70030,7 +70313,7 @@ function applySetupPreview(preview, options = {}) {
70030
70313
  let cursorCopyOk = false;
70031
70314
  for (const mutation of preview.mutations) {
70032
70315
  if (mutation.type === "install-host") {
70033
- const expectedPath = mutation.platform === "cursor" ? path39.join(res.home, ".cursor", "plugins", "local", ".workit-package-bootstrap") : mutation.platform === "codex" ? path39.join(res.env.CODEX_HOME ?? path39.join(res.home, ".codex"), "plugins", "cache", "workflow-toolkit", "workit") : mutation.platform === "pi" ? path39.join(res.env.PI_CODING_AGENT_DIR ?? path39.join(res.home, ".pi", "agent"), "settings.json") : mutation.platform === "claude-code" ? claudeInstallRecord(res.home, res.env) : "";
70316
+ 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) : "";
70034
70317
  if (mutation.path !== expectedPath) {
70035
70318
  entries.push({
70036
70319
  platform: mutation.platform,
@@ -70142,7 +70425,7 @@ function applySetupPreview(preview, options = {}) {
70142
70425
  if (preview.projectRefused) {
70143
70426
  entries.push({
70144
70427
  platform: "core",
70145
- file: path39.resolve(res.cwd),
70428
+ file: path40.resolve(res.cwd),
70146
70429
  status: "Skipped",
70147
70430
  detail: preview.projectRefused
70148
70431
  });
@@ -70223,12 +70506,12 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
70223
70506
  return configured ?? fallback;
70224
70507
  }, readConfigRecord = (file) => {
70225
70508
  try {
70226
- const value = JSON.parse(readFileSync17(file, "utf8"));
70509
+ const value = JSON.parse(readFileSync18(file, "utf8"));
70227
70510
  return isRecord6(value) ? value : null;
70228
70511
  } catch {
70229
70512
  return null;
70230
70513
  }
70231
- }, claudeInstallRecord = (home, env) => path39.join(claudeConfigDir(home, env), "plugins", "installed_plugins.json"), resolveSetupPaths = (options, resolvedConfigDir) => {
70514
+ }, claudeInstallRecord = (home, env) => path40.join(claudeConfigDir(home, env), "plugins", "installed_plugins.json"), resolveSetupPaths = (options, resolvedConfigDir) => {
70232
70515
  const env = options.env ?? process.env;
70233
70516
  const home = options.home ?? env.HOME ?? os13.homedir();
70234
70517
  return {
@@ -70236,15 +70519,15 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
70236
70519
  configDir: resolvedConfigDir,
70237
70520
  cwd: options.cwd ?? process.cwd(),
70238
70521
  env,
70239
- opencodeConfig: options.opencodeConfig ?? path39.join(home, ".config", "opencode", "opencode.json"),
70240
- cursorSettings: options.cursorSettings ?? path39.join(home, ".cursor", "settings.json"),
70241
- cursorMcp: options.cursorMcp ?? path39.join(home, ".cursor", "mcp.json"),
70242
- cursorPluginDir: options.cursorPluginDir ?? path39.join(home, ".cursor", "plugins", "local", "workit")
70522
+ opencodeConfig: options.opencodeConfig ?? path40.join(home, ".config", "opencode", "opencode.json"),
70523
+ cursorSettings: options.cursorSettings ?? path40.join(home, ".cursor", "settings.json"),
70524
+ cursorMcp: options.cursorMcp ?? path40.join(home, ".cursor", "mcp.json"),
70525
+ cursorPluginDir: options.cursorPluginDir ?? path40.join(home, ".cursor", "plugins", "local", "workit")
70243
70526
  };
70244
70527
  }, isRecord6 = (v) => v !== null && typeof v === "object" && !Array.isArray(v), readExisting = (p) => {
70245
70528
  let raw;
70246
70529
  try {
70247
- raw = readFileSync17(p, "utf8");
70530
+ raw = readFileSync18(p, "utf8");
70248
70531
  } catch {
70249
70532
  if (existsSync17(p))
70250
70533
  return { kind: "malformed", error: `${p} is not readable` };
@@ -70261,7 +70544,7 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
70261
70544
  return { kind: "malformed", error: `${p} is not a JSON object` };
70262
70545
  }, readFileSafe = (p) => {
70263
70546
  try {
70264
- return readFileSync17(p, "utf8");
70547
+ return readFileSync18(p, "utf8");
70265
70548
  } catch {
70266
70549
  return null;
70267
70550
  }
@@ -70276,15 +70559,15 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
70276
70559
  }
70277
70560
  }, isAdapter = (root, platform) => {
70278
70561
  try {
70279
- const pkg = JSON.parse(readFileSync17(path39.join(root, "package.json"), "utf8"));
70562
+ const pkg = JSON.parse(readFileSync18(path40.join(root, "package.json"), "utf8"));
70280
70563
  return pkg.name === `@brainervirus/workit-${platform}`;
70281
70564
  } catch {
70282
70565
  return false;
70283
70566
  }
70284
70567
  }, nodeResolvedAdapters = (platform) => {
70285
70568
  const name = `@brainervirus/workit-${platform}`;
70286
- const require2 = createRequire2(path39.join(packageRoot(), "package.json"));
70287
- return (require2.resolve.paths(name) ?? []).map((dir) => path39.join(dir, name));
70569
+ const require2 = createRequire2(path40.join(packageRoot(), "package.json"));
70570
+ return (require2.resolve.paths(name) ?? []).map((dir) => path40.join(dir, name));
70288
70571
  }, realRoot = (root) => {
70289
70572
  try {
70290
70573
  return realpathSync8(root);
@@ -70300,7 +70583,7 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
70300
70583
  if (!isDevOpenCodeAdapterRoot(root, opts.dev))
70301
70584
  return OPENCODE_NPM_PIN;
70302
70585
  for (const rel of ["src/plugin.ts", "dist/plugin.js"]) {
70303
- const entry = path39.join(root, rel);
70586
+ const entry = path40.join(root, rel);
70304
70587
  if (existsSync17(entry))
70305
70588
  return `file://${entry}`;
70306
70589
  }
@@ -70315,25 +70598,25 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
70315
70598
  }
70316
70599
  }, samePluginContent = (src, dest, pluginDir, relative = "") => {
70317
70600
  try {
70318
- for (const entry of readdirSync9(src, { withFileTypes: true })) {
70601
+ for (const entry of readdirSync11(src, { withFileTypes: true })) {
70319
70602
  if (entry.name === "node_modules")
70320
70603
  continue;
70321
- const source = path39.join(src, entry.name);
70322
- const installed = path39.join(dest, entry.name);
70323
- const rel = path39.join(relative, entry.name);
70604
+ const source = path40.join(src, entry.name);
70605
+ const installed = path40.join(dest, entry.name);
70606
+ const rel = path40.join(relative, entry.name);
70324
70607
  if (entry.isDirectory()) {
70325
70608
  if (!statSync7(installed).isDirectory() || !samePluginContent(source, installed, pluginDir, rel))
70326
70609
  return false;
70327
70610
  } else {
70328
- const expected = rel === CURSOR_HOOKS_FILE ? localizedCursorHooks(readFileSync17(source), pluginDir) : readFileSync17(source);
70329
- if (!expected.equals(readFileSync17(installed)))
70611
+ const expected = rel === CURSOR_HOOKS_FILE ? localizedCursorHooks(readFileSync18(source), pluginDir) : readFileSync18(source);
70612
+ if (!expected.equals(readFileSync18(installed)))
70330
70613
  return false;
70331
70614
  }
70332
70615
  }
70333
- for (const entry of readdirSync9(dest, { withFileTypes: true })) {
70334
- if (existsSync17(path39.join(src, entry.name)))
70616
+ for (const entry of readdirSync11(dest, { withFileTypes: true })) {
70617
+ if (existsSync17(path40.join(src, entry.name)))
70335
70618
  continue;
70336
- const rel = path39.join(relative, entry.name);
70619
+ const rel = path40.join(relative, entry.name);
70337
70620
  if (rel === ".workit-root")
70338
70621
  continue;
70339
70622
  if (relative === "rules" && entry.isFile() && entry.name.endsWith(".mdc"))
@@ -70346,32 +70629,32 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
70346
70629
  }
70347
70630
  }, preservedCursorRules = (src, dest) => {
70348
70631
  const preserved = new Map;
70349
- const sourceRules = path39.join(src, "rules");
70350
- const installedRules = path39.join(dest, "rules");
70632
+ const sourceRules = path40.join(src, "rules");
70633
+ const installedRules = path40.join(dest, "rules");
70351
70634
  try {
70352
- for (const entry of readdirSync9(installedRules, { withFileTypes: true })) {
70635
+ for (const entry of readdirSync11(installedRules, { withFileTypes: true })) {
70353
70636
  if (!entry.isFile() || !entry.name.endsWith(".mdc"))
70354
70637
  continue;
70355
- if (existsSync17(path39.join(sourceRules, entry.name)))
70638
+ if (existsSync17(path40.join(sourceRules, entry.name)))
70356
70639
  continue;
70357
- preserved.set(entry.name, readFileSync17(path39.join(installedRules, entry.name)));
70640
+ preserved.set(entry.name, readFileSync18(path40.join(installedRules, entry.name)));
70358
70641
  }
70359
70642
  } catch {}
70360
70643
  return preserved;
70361
70644
  }, removeLegacyCursorDir = (res) => {
70362
- const legacy = path39.join(res.home, ".cursor", "plugins", "local", "workflow-toolkit");
70645
+ const legacy = path40.join(res.home, ".cursor", "plugins", "local", "workflow-toolkit");
70363
70646
  if (legacy === res.cursorPluginDir || !existsSync17(legacy))
70364
70647
  return;
70365
- const legacyRules = path39.join(legacy, "rules");
70648
+ const legacyRules = path40.join(legacy, "rules");
70366
70649
  if (existsSync17(legacyRules)) {
70367
70650
  try {
70368
- mkdirSync8(path39.join(res.cursorPluginDir, "rules"), { recursive: true });
70369
- for (const entry of readdirSync9(legacyRules, { withFileTypes: true })) {
70651
+ mkdirSync9(path40.join(res.cursorPluginDir, "rules"), { recursive: true });
70652
+ for (const entry of readdirSync11(legacyRules, { withFileTypes: true })) {
70370
70653
  if (!entry.isFile() || !entry.name.endsWith(".mdc"))
70371
70654
  continue;
70372
- const target = path39.join(res.cursorPluginDir, "rules", entry.name);
70655
+ const target = path40.join(res.cursorPluginDir, "rules", entry.name);
70373
70656
  if (!existsSync17(target))
70374
- copyFileSync5(path39.join(legacyRules, entry.name), target);
70657
+ copyFileSync5(path40.join(legacyRules, entry.name), target);
70375
70658
  }
70376
70659
  } catch {}
70377
70660
  }
@@ -70405,16 +70688,16 @@ var init_setup = __esm(() => {
70405
70688
  { envKey: "WORKFLOW_GITHUB_HOST", affects: "vcs.json github.host" }
70406
70689
  ];
70407
70690
  SETUP_OVERRIDES = [...YT_OVERRIDES, ...VCS_OVERRIDES];
70408
- CURSOR_HOOKS_FILE = path39.join("hooks", "hooks-cursor.json");
70691
+ CURSOR_HOOKS_FILE = path40.join("hooks", "hooks-cursor.json");
70409
70692
  });
70410
70693
 
70411
70694
  // packages/workit-core/src/core/workspace-branch-policy.ts
70412
- import { mkdirSync as mkdirSync9, readFileSync as readFileSync18, renameSync as renameSync6, rmSync as rmSync6, writeFileSync as writeFileSync9 } from "node:fs";
70413
- import path40 from "node:path";
70695
+ import { mkdirSync as mkdirSync10, readFileSync as readFileSync19, renameSync as renameSync6, rmSync as rmSync6, writeFileSync as writeFileSync10 } from "node:fs";
70696
+ import path41 from "node:path";
70414
70697
  import { isDeepStrictEqual as isDeepStrictEqual3 } from "node:util";
70415
70698
  function applyWorkspaceBranchPolicy(opts) {
70416
70699
  const { workspace_root, env = process.env } = opts;
70417
- const dir = path40.join(env.WORKFLOW_TOOLKIT_CONFIG ?? configDir());
70700
+ const dir = path41.join(env.WORKFLOW_TOOLKIT_CONFIG ?? configDir());
70418
70701
  const {
70419
70702
  status,
70420
70703
  path: wsPath,
@@ -70426,7 +70709,7 @@ function applyWorkspaceBranchPolicy(opts) {
70426
70709
  if (status === "malformed" || status === "invalid")
70427
70710
  return { ok: false, error: workspacesError ?? `invalid workspaces.json: ${wsPath}` };
70428
70711
  const detection = detectBranchPolicy(workspace_root);
70429
- const name = String(env.WORKFLOW_BP_NAME ?? path40.basename(workspace_root));
70712
+ const name = String(env.WORKFLOW_BP_NAME ?? path41.basename(workspace_root));
70430
70713
  const integration = env.WORKFLOW_BP_INTEGRATION ?? detection.integration;
70431
70714
  const policy = {
70432
70715
  preset: detection.preset,
@@ -70475,10 +70758,10 @@ function applyWorkspaceBranchPolicy(opts) {
70475
70758
  ok: false,
70476
70759
  error: `workspaces.json changed while applying the branch policy: ${wsPath}`
70477
70760
  };
70478
- mkdirSync9(path40.dirname(wsPath), { recursive: true });
70761
+ mkdirSync10(path41.dirname(wsPath), { recursive: true });
70479
70762
  const tmp = `${wsPath}.${process.pid}.tmp`;
70480
70763
  try {
70481
- writeFileSync9(tmp, JSON.stringify({ ...document2, workspaces: next }, null, 2) + `
70764
+ writeFileSync10(tmp, JSON.stringify({ ...document2, workspaces: next }, null, 2) + `
70482
70765
  `, "utf8");
70483
70766
  if (workspacesRevision(readFileSafe2(wsPath)) !== revision) {
70484
70767
  rmSync6(tmp, { force: true });
@@ -70507,7 +70790,7 @@ function applyWorkspaceBranchPolicy(opts) {
70507
70790
  }
70508
70791
  var readFileSafe2 = (p) => {
70509
70792
  try {
70510
- return readFileSync18(p, "utf8");
70793
+ return readFileSync19(p, "utf8");
70511
70794
  } catch {
70512
70795
  return null;
70513
70796
  }
@@ -70760,7 +71043,7 @@ var init_logic = __esm(() => {
70760
71043
 
70761
71044
  // packages/workit-cli/src/wizard-state.ts
70762
71045
  import { existsSync as existsSync18, statSync as statSync8 } from "node:fs";
70763
- import path41 from "node:path";
71046
+ import path42 from "node:path";
70764
71047
  import { isDeepStrictEqual as isDeepStrictEqual4 } from "node:util";
70765
71048
  function resolveBasePath(values, env = process.env) {
70766
71049
  return env.WORKFLOW_WORKSPACE_ROOT?.trim() || values.basePath.trim();
@@ -71287,8 +71570,8 @@ var NEXT, PREV, skipsCustomBranch = (screen, preset) => (screen === "branchAllow
71287
71570
  const p = value.trim();
71288
71571
  if (!p)
71289
71572
  return "workspace root path is required";
71290
- return !path41.isAbsolute(p) || !isDirectory(p) ? `invalid workspace root "${p}" — enter an existing absolute directory` : null;
71291
- }, skipsBranchPolicy = (screen, basePath) => (screen === "branchPolicy" || screen === "branchPolicyDevelop") && !existsSync18(path41.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;
71573
+ return !path42.isAbsolute(p) || !isDirectory(p) ? `invalid workspace root "${p}" — enter an existing absolute directory` : null;
71574
+ }, skipsBranchPolicy = (screen, basePath) => (screen === "branchPolicy" || screen === "branchPolicyDevelop") && !existsSync18(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;
71292
71575
  var init_wizard_state = __esm(() => {
71293
71576
  init_config();
71294
71577
  init_workspaces();
@@ -71347,9 +71630,9 @@ var init_wizard_state = __esm(() => {
71347
71630
  });
71348
71631
 
71349
71632
  // packages/workit-cli/src/admin/uninstall.ts
71350
- import { existsSync as existsSync19, readFileSync as readFileSync19, realpathSync as realpathSync9, rmSync as rmSync7, writeFileSync as writeFileSync10 } from "node:fs";
71633
+ import { existsSync as existsSync19, readFileSync as readFileSync20, realpathSync as realpathSync9, rmSync as rmSync7, writeFileSync as writeFileSync11 } from "node:fs";
71351
71634
  import os14 from "node:os";
71352
- import path42 from "node:path";
71635
+ import path43 from "node:path";
71353
71636
  function cleanCursorSettings(settings, pluginDir) {
71354
71637
  const next = { ...settings };
71355
71638
  let changed = false;
@@ -71522,7 +71805,7 @@ function planUninstall(paths = {}) {
71522
71805
  plan.actions.push({
71523
71806
  kind: "edit-json-remove",
71524
71807
  path: file,
71525
- detail: `remove Workit's permission block from ${path42.basename(file)}`
71808
+ detail: `remove Workit's permission block from ${path43.basename(file)}`
71526
71809
  });
71527
71810
  }
71528
71811
  if (existsSync19(res.codexRules))
@@ -71556,8 +71839,8 @@ function applyUninstall(plan, paths = {}) {
71556
71839
  status = outcome.status;
71557
71840
  detail = outcome.detail;
71558
71841
  } else if (action.kind === "remove-dir") {
71559
- const resolved = path42.resolve(action.path);
71560
- const allowed = canonicalRemoveDirAllowed(resolved, res) || resolved === path42.resolve(res.codexPluginDir) && path42.basename(resolved) === "workit" && path42.basename(path42.dirname(resolved)) === "plugins";
71842
+ const resolved = path43.resolve(action.path);
71843
+ const allowed = canonicalRemoveDirAllowed(resolved, res) || resolved === path43.resolve(res.codexPluginDir) && path43.basename(resolved) === "workit" && path43.basename(path43.dirname(resolved)) === "plugins";
71561
71844
  if (!allowed) {
71562
71845
  status = "failed";
71563
71846
  detail = `refusing to remove non-canonical plugin directory: ${resolved}`;
@@ -71599,17 +71882,17 @@ var resolveUninstallPaths = (options = {}) => {
71599
71882
  claudeSettings: permissionTarget("claude-code", permissionPaths).file,
71600
71883
  cursorCliConfig: permissionTarget("cursor", permissionPaths).file,
71601
71884
  codexRules: permissionTarget("codex", permissionPaths).file,
71602
- opencodeConfig: options.opencodeConfig ?? path42.join(home, ".config", "opencode", "opencode.json"),
71603
- cursorSettings: options.cursorSettings ?? path42.join(home, ".cursor", "settings.json"),
71604
- cursorMcp: options.cursorMcp ?? path42.join(home, ".cursor", "mcp.json"),
71605
- cursorPluginDir: options.cursorPluginDir ?? path42.join(home, ".cursor", "plugins", "local", "workit"),
71606
- codexPluginDir: path42.join(home, ".codex", "plugins", "workit"),
71607
- piConfig: path42.join(home, ".pi", "config.json")
71885
+ opencodeConfig: options.opencodeConfig ?? path43.join(home, ".config", "opencode", "opencode.json"),
71886
+ cursorSettings: options.cursorSettings ?? path43.join(home, ".cursor", "settings.json"),
71887
+ cursorMcp: options.cursorMcp ?? path43.join(home, ".cursor", "mcp.json"),
71888
+ cursorPluginDir: options.cursorPluginDir ?? path43.join(home, ".cursor", "plugins", "local", "workit"),
71889
+ codexPluginDir: path43.join(home, ".codex", "plugins", "workit"),
71890
+ piConfig: path43.join(home, ".pi", "config.json")
71608
71891
  };
71609
71892
  }, isRecord7 = (v) => v !== null && typeof v === "object" && !Array.isArray(v), readJsonRecord = (file) => {
71610
71893
  let raw;
71611
71894
  try {
71612
- raw = readFileSync19(file, "utf8");
71895
+ raw = readFileSync20(file, "utf8");
71613
71896
  } catch {
71614
71897
  if (existsSync19(file))
71615
71898
  return { kind: "malformed", error: `${file} is not readable` };
@@ -71622,8 +71905,8 @@ var resolveUninstallPaths = (options = {}) => {
71622
71905
  return { kind: "malformed", error: `${file} is not valid JSON` };
71623
71906
  }
71624
71907
  }, stripTrailingSep = (p) => {
71625
- const j = path42.join(p);
71626
- return path42.dirname(j) === j ? j : j.replace(/[\\/]+$/, "");
71908
+ const j = path43.join(p);
71909
+ return path43.dirname(j) === j ? j : j.replace(/[\\/]+$/, "");
71627
71910
  }, CURSOR_LEGACY_IDENTITIES, permissionPathsOf = (paths) => {
71628
71911
  const env = paths.env ?? process.env;
71629
71912
  return {
@@ -71650,8 +71933,8 @@ var resolveUninstallPaths = (options = {}) => {
71650
71933
  return cleanPiConfig;
71651
71934
  return null;
71652
71935
  }, canonicalRemoveDirAllowed = (actionPath, res) => {
71653
- const expected = path42.resolve(res.cursorPluginDir);
71654
- if (!(actionPath === expected && path42.basename(expected) === "workit" && path42.basename(path42.dirname(expected)) === "local" && path42.basename(path42.dirname(path42.dirname(expected))) === "plugins")) {
71936
+ const expected = path43.resolve(res.cursorPluginDir);
71937
+ if (!(actionPath === expected && path43.basename(expected) === "workit" && path43.basename(path43.dirname(expected)) === "local" && path43.basename(path43.dirname(path43.dirname(expected))) === "plugins")) {
71655
71938
  return false;
71656
71939
  }
71657
71940
  try {
@@ -71674,7 +71957,7 @@ var resolveUninstallPaths = (options = {}) => {
71674
71957
  `;
71675
71958
  let current;
71676
71959
  try {
71677
- current = readFileSync19(target, "utf8");
71960
+ current = readFileSync20(target, "utf8");
71678
71961
  } catch (error) {
71679
71962
  return {
71680
71963
  status: "failed",
@@ -71685,7 +71968,7 @@ var resolveUninstallPaths = (options = {}) => {
71685
71968
  return { status: "skipped", detail: "already clean" };
71686
71969
  }
71687
71970
  try {
71688
- writeFileSync10(target, serialized, "utf8");
71971
+ writeFileSync11(target, serialized, "utf8");
71689
71972
  } catch (error) {
71690
71973
  return {
71691
71974
  status: "failed",
@@ -71703,7 +71986,7 @@ var resolveUninstallPaths = (options = {}) => {
71703
71986
  };
71704
71987
  const home = paths.home ?? paths.env?.HOME ?? os14.homedir();
71705
71988
  const env = paths.env ?? process.env;
71706
- const recorded = claudeWorkitInstalls(home, env, action.cwd).some((install) => install.id === id && install.scope === scope && (install.projectPath === null ? action.cwd === null : path42.resolve(install.projectPath) === path42.resolve(action.cwd ?? "")));
71989
+ 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 ?? "")));
71707
71990
  if (!recorded)
71708
71991
  return { status: "skipped", detail: `${id} (${scope} scope) is no longer installed` };
71709
71992
  const executable = findHostExecutable("claude", { home, env });
@@ -74465,14 +74748,14 @@ import {
74465
74748
  existsSync as existsSync20,
74466
74749
  mkdtempSync as mkdtempSync3,
74467
74750
  rmSync as rmSync8,
74468
- readFileSync as readFileSync20,
74469
- mkdirSync as mkdirSync10,
74751
+ readFileSync as readFileSync21,
74752
+ mkdirSync as mkdirSync11,
74470
74753
  copyFileSync as copyFileSync6,
74471
74754
  chmodSync as chmodSync2,
74472
74755
  cpSync as cpSync5,
74473
74756
  lstatSync as lstatSync7
74474
74757
  } from "node:fs";
74475
- import path43 from "node:path";
74758
+ import path44 from "node:path";
74476
74759
  import os16 from "node:os";
74477
74760
  import { createHash as createHash15 } from "node:crypto";
74478
74761
  function previewUpgrade(hosts = HOSTS2, deps = {}) {
@@ -74496,9 +74779,9 @@ function previewUpgrade(hosts = HOSTS2, deps = {}) {
74496
74779
  for (const file of [
74497
74780
  paths.opencodeConfig,
74498
74781
  paths.opencodeConfig + "c",
74499
- path43.join(home, ".cursor/settings.json"),
74500
- path43.join(home, ".cursor/mcp.json"),
74501
- path43.join(home, ".cursor/plugins/local/workit/package.json"),
74782
+ path44.join(home, ".cursor/settings.json"),
74783
+ path44.join(home, ".cursor/mcp.json"),
74784
+ path44.join(home, ".cursor/plugins/local/workit/package.json"),
74502
74785
  paths.codexConfig,
74503
74786
  paths.piSettings
74504
74787
  ])
@@ -74513,16 +74796,16 @@ function previewUpgrade(hosts = HOSTS2, deps = {}) {
74513
74796
  });
74514
74797
  const installedSources = sources(paths, run, hosts);
74515
74798
  if (installedSources.some((source) => source.host === "opencode")) {
74516
- const scratch = mkdtempSync3(path43.join(os16.tmpdir(), "workit-upgrade-opencode-"));
74799
+ const scratch = mkdtempSync3(path44.join(os16.tmpdir(), "workit-upgrade-opencode-"));
74517
74800
  let probe;
74518
74801
  try {
74519
74802
  probe = runner({
74520
74803
  ...deps,
74521
74804
  env: {
74522
74805
  ...deps.env,
74523
- XDG_DATA_HOME: path43.join(scratch, "data"),
74524
- XDG_STATE_HOME: path43.join(scratch, "state"),
74525
- XDG_CACHE_HOME: path43.join(scratch, "cache")
74806
+ XDG_DATA_HOME: path44.join(scratch, "data"),
74807
+ XDG_STATE_HOME: path44.join(scratch, "state"),
74808
+ XDG_CACHE_HOME: path44.join(scratch, "cache")
74526
74809
  }
74527
74810
  })("opencode", ["--version"]);
74528
74811
  } finally {
@@ -74568,7 +74851,7 @@ function previewUpgrade(hosts = HOSTS2, deps = {}) {
74568
74851
  env: deps.env,
74569
74852
  cwd: home,
74570
74853
  packageVersion: latest.stdout.trim(),
74571
- targetDir: path43.join(home, ".cursor/plugins/local/workit")
74854
+ targetDir: path44.join(home, ".cursor/plugins/local/workit")
74572
74855
  });
74573
74856
  plan.entries.push({
74574
74857
  host: source.host,
@@ -74598,11 +74881,11 @@ function applyUpgrade(plan, deps = {}) {
74598
74881
  ok: false,
74599
74882
  error: "Stop the selected running hosts before upgrading their loaded plugins"
74600
74883
  };
74601
- const backup = path43.join(home, ".local/state/workit/upgrades", new Date().toISOString().replaceAll(":", "-"));
74602
- mkdirSync10(backup, { recursive: true, mode: 448 });
74884
+ const backup = path44.join(home, ".local/state/workit/upgrades", new Date().toISOString().replaceAll(":", "-"));
74885
+ mkdirSync11(backup, { recursive: true, mode: 448 });
74603
74886
  for (const file of Object.keys(plan.configDigests))
74604
74887
  if (existsSync20(file)) {
74605
- const target = path43.join(backup, createHash15("sha256").update(file).digest("hex").slice(0, 12) + "-" + path43.basename(file));
74888
+ const target = path44.join(backup, createHash15("sha256").update(file).digest("hex").slice(0, 12) + "-" + path44.basename(file));
74606
74889
  copyFileSync6(file, target);
74607
74890
  chmodSync2(target, 384);
74608
74891
  }
@@ -74619,9 +74902,9 @@ function applyUpgrade(plan, deps = {}) {
74619
74902
  `, 384);
74620
74903
  }
74621
74904
  const run = runner(deps);
74622
- const cursorRoot = path43.join(home, ".cursor/plugins/local/workit");
74905
+ const cursorRoot = path44.join(home, ".cursor/plugins/local/workit");
74623
74906
  if (plan.entries.some((entry) => entry.host === "cursor") && existsSync20(cursorRoot))
74624
- cpSync5(cursorRoot, path43.join(backup, "cursor-package"), { recursive: true });
74907
+ cpSync5(cursorRoot, path44.join(backup, "cursor-package"), { recursive: true });
74625
74908
  for (const entry of plan.entries) {
74626
74909
  if (entry.host === "opencode")
74627
74910
  return {
@@ -74641,7 +74924,7 @@ function applyUpgrade(plan, deps = {}) {
74641
74924
  {
74642
74925
  type: "install-host",
74643
74926
  platform: "cursor",
74644
- path: path43.join(home, ".cursor/plugins/local/.workit-package-bootstrap"),
74927
+ path: path44.join(home, ".cursor/plugins/local/.workit-package-bootstrap"),
74645
74928
  commands: entry.commands.map((command) => ({
74646
74929
  ...command,
74647
74930
  purpose: command.purpose ?? "Upgrade Cursor"
@@ -74650,7 +74933,7 @@ function applyUpgrade(plan, deps = {}) {
74650
74933
  {
74651
74934
  type: "install-adapter",
74652
74935
  platform: "cursor",
74653
- path: path43.join(home, ".cursor/plugins/local/workit")
74936
+ path: path44.join(home, ".cursor/plugins/local/workit")
74654
74937
  }
74655
74938
  ]
74656
74939
  };
@@ -74664,7 +74947,7 @@ function applyUpgrade(plan, deps = {}) {
74664
74947
  return { exitCode: outcome.status ?? 1, stdout: outcome.stdout, stderr: "" };
74665
74948
  }
74666
74949
  });
74667
- const pkg = object2(path43.join(home, ".cursor/plugins/local/workit/package.json"));
74950
+ const pkg = object2(path44.join(home, ".cursor/plugins/local/workit/package.json"));
74668
74951
  if (!result.ok || pkg?.version !== entry.latest)
74669
74952
  return {
74670
74953
  ok: false,
@@ -74698,15 +74981,15 @@ function applyUpgrade(plan, deps = {}) {
74698
74981
  const currentRoot = run("npm", ["root", "--global"]);
74699
74982
  if (currentRoot.status !== 0 || currentRoot.stdout.trim() !== plan.cli.root)
74700
74983
  return { ok: false, backup, error: "Global npm location changed; preview again" };
74701
- const cliBackup = path43.join(backup, "cli-package");
74702
- cpSync5(path43.join(plan.cli.root, "@brainervirus/workit-cli"), cliBackup, { recursive: true });
74984
+ const cliBackup = path44.join(backup, "cli-package");
74985
+ cpSync5(path44.join(plan.cli.root, "@brainervirus/workit-cli"), cliBackup, { recursive: true });
74703
74986
  if (run("npm", ["install", "--global", `@brainervirus/workit-cli@${plan.cli.latest}`]).status !== 0)
74704
74987
  return {
74705
74988
  ok: false,
74706
74989
  backup,
74707
- error: `CLI update failed; preserved package at ${cliBackup}; use npm to repair or run node ${path43.join(cliBackup, "dist/index.js")}`
74990
+ error: `CLI update failed; preserved package at ${cliBackup}; use npm to repair or run node ${path44.join(cliBackup, "dist/index.js")}`
74708
74991
  };
74709
- const installed = object2(path43.join(plan.cli.root, "@brainervirus/workit-cli/package.json"));
74992
+ const installed = object2(path44.join(plan.cli.root, "@brainervirus/workit-cli/package.json"));
74710
74993
  if (installed?.name !== "@brainervirus/workit-cli" || installed.version !== plan.cli.latest)
74711
74994
  return {
74712
74995
  ok: false,
@@ -74731,12 +75014,12 @@ async function runUpgradeCommand(argv, deps = {}) {
74731
75014
  if (flags.has("--cli")) {
74732
75015
  const run = runner(deps);
74733
75016
  const root = run("npm", ["root", "--global"]);
74734
- if (root.status !== 0 || !path43.isAbsolute(root.stdout.trim())) {
75017
+ if (root.status !== 0 || !path44.isAbsolute(root.stdout.trim())) {
74735
75018
  plan.blocked.push("Global npm location could not be verified");
74736
75019
  } else {
74737
- const packageFile = path43.join(root.stdout.trim(), "@brainervirus/workit-cli/package.json");
75020
+ const packageFile = path44.join(root.stdout.trim(), "@brainervirus/workit-cli/package.json");
74738
75021
  const pkg = object2(packageFile);
74739
- if (pkg?.name !== "@brainervirus/workit-cli" || lstatSync7(path43.dirname(packageFile)).isSymbolicLink()) {
75022
+ if (pkg?.name !== "@brainervirus/workit-cli" || lstatSync7(path44.dirname(packageFile)).isSymbolicLink()) {
74740
75023
  plan.skipped.push({
74741
75024
  host: "cli",
74742
75025
  reason: "No managed global CLI install (local links preserved); use npx @brainervirus/workit-cli@latest"
@@ -74859,37 +75142,37 @@ var HOSTS2, upgradePaths = (deps) => {
74859
75142
  ...process.env,
74860
75143
  ...deps.home || deps.env?.HOME ? {
74861
75144
  HOME: home,
74862
- CODEX_HOME: path43.join(home, ".codex"),
74863
- PI_CODING_AGENT_DIR: path43.join(home, ".pi/agent"),
74864
- XDG_CONFIG_HOME: path43.join(home, ".config"),
75145
+ CODEX_HOME: path44.join(home, ".codex"),
75146
+ PI_CODING_AGENT_DIR: path44.join(home, ".pi/agent"),
75147
+ XDG_CONFIG_HOME: path44.join(home, ".config"),
74865
75148
  WORKFLOW_TOOLKIT_CONFIG: undefined,
74866
75149
  WORKFLOW_TOOLKIT_CONFIG_DIR: undefined
74867
75150
  } : {},
74868
75151
  ...deps.env,
74869
75152
  HOME: home
74870
75153
  };
74871
- const xdg = env.XDG_CONFIG_HOME || path43.join(home, ".config");
75154
+ const xdg = env.XDG_CONFIG_HOME || path44.join(home, ".config");
74872
75155
  return {
74873
75156
  home,
74874
75157
  env,
74875
- configDir: env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path43.join(xdg, "workit"),
74876
- opencodeConfig: path43.join(xdg, "opencode/opencode.json"),
74877
- piSettings: path43.join(env.PI_CODING_AGENT_DIR ?? path43.join(home, ".pi/agent"), "settings.json"),
74878
- codexConfig: path43.join(env.CODEX_HOME ?? path43.join(home, ".codex"), "config.toml")
75158
+ configDir: env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path44.join(xdg, "workit"),
75159
+ opencodeConfig: path44.join(xdg, "opencode/opencode.json"),
75160
+ piSettings: path44.join(env.PI_CODING_AGENT_DIR ?? path44.join(home, ".pi/agent"), "settings.json"),
75161
+ codexConfig: path44.join(env.CODEX_HOME ?? path44.join(home, ".codex"), "config.toml")
74879
75162
  };
74880
75163
  }, object2 = (file) => {
74881
75164
  if (!existsSync20(file))
74882
75165
  return null;
74883
75166
  let data;
74884
75167
  try {
74885
- data = JSON.parse(readFileSync20(file, "utf8"));
75168
+ data = JSON.parse(readFileSync21(file, "utf8"));
74886
75169
  } catch {
74887
75170
  throw new Error(`${file} is not valid JSON; use the native host to inspect JSONC settings`);
74888
75171
  }
74889
75172
  if (!data || typeof data !== "object" || Array.isArray(data))
74890
75173
  throw new Error(`${file} is not a configuration object`);
74891
75174
  return data;
74892
- }, digest2 = (file) => existsSync20(file) ? createHash15("sha256").update(readFileSync20(file)).digest("hex") : "missing", runner = (deps) => deps.run ?? ((command, args) => {
75175
+ }, digest2 = (file) => existsSync20(file) ? createHash15("sha256").update(readFileSync21(file)).digest("hex") : "missing", runner = (deps) => deps.run ?? ((command, args) => {
74893
75176
  const { home, env } = upgradePaths(deps);
74894
75177
  let step;
74895
75178
  try {
@@ -74915,9 +75198,9 @@ var HOSTS2, upgradePaths = (deps) => {
74915
75198
  for (const pin of plugins)
74916
75199
  if (typeof pin === "string" && isWorkitPlugin(pin))
74917
75200
  result.push(classify("opencode", pin));
74918
- const cursor = hosts.includes("cursor") ? object2(path43.join(home, ".cursor/plugins/local/workit/package.json")) : null;
75201
+ const cursor = hosts.includes("cursor") ? object2(path44.join(home, ".cursor/plugins/local/workit/package.json")) : null;
74919
75202
  if (cursor?.name === "@brainervirus/workit-cursor") {
74920
- const mcp = object2(path43.join(home, ".cursor/mcp.json"));
75203
+ const mcp = object2(path44.join(home, ".cursor/mcp.json"));
74921
75204
  const args = mcp?.mcpServers?.workit?.args ?? [];
74922
75205
  const selector = args.find((arg) => typeof arg === "string" && arg.startsWith("--package="));
74923
75206
  result.push(classify("cursor", typeof selector === "string" ? selector.slice(10) : "local"));
@@ -74930,7 +75213,7 @@ var HOSTS2, upgradePaths = (deps) => {
74930
75213
  if (typeof source !== "string")
74931
75214
  continue;
74932
75215
  const npm = /^(?:npm:)?@brainervirus\/workit-pi(?:@[^/]+)?$/.test(source);
74933
- const local = path43.isAbsolute(source) && source.replaceAll("\\", "/").endsWith("/packages/workit-pi") && object2(path43.join(source, "package.json"))?.name === "@brainervirus/workit-pi";
75216
+ const local = path44.isAbsolute(source) && source.replaceAll("\\", "/").endsWith("/packages/workit-pi") && object2(path44.join(source, "package.json"))?.name === "@brainervirus/workit-pi";
74934
75217
  if (npm || local)
74935
75218
  result.push(classify("pi", source));
74936
75219
  }
@@ -74977,9 +75260,9 @@ var HOSTS2, upgradePaths = (deps) => {
74977
75260
  }, piInstalledVersion = (listing, selector) => {
74978
75261
  const lines = listing.split(/\r?\n/).map((line) => line.trim());
74979
75262
  const index = lines.indexOf(selector);
74980
- if (index < 0 || !lines[index + 1] || !path43.isAbsolute(lines[index + 1]))
75263
+ if (index < 0 || !lines[index + 1] || !path44.isAbsolute(lines[index + 1]))
74981
75264
  return;
74982
- const pkg = object2(path43.join(lines[index + 1], "package.json"));
75265
+ const pkg = object2(path44.join(lines[index + 1], "package.json"));
74983
75266
  return pkg?.name === "@brainervirus/workit-pi" ? pkg.version : undefined;
74984
75267
  }, versionAtLeast = (installed, latest) => {
74985
75268
  if (!/^\d+\.\d+\.\d+$/.test(installed))
@@ -75033,7 +75316,7 @@ var init_launch = __esm(() => {
75033
75316
  // packages/workit-core/src/knowledge.ts
75034
75317
  import { spawnSync as spawnSync18 } from "node:child_process";
75035
75318
  import fs20 from "node:fs";
75036
- import path44 from "node:path";
75319
+ import path45 from "node:path";
75037
75320
  function lintKnowledge(root) {
75038
75321
  const seen = new Set;
75039
75322
  const unreadable = [];
@@ -75137,7 +75420,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
75137
75420
  const end = lines.indexOf("---", 1);
75138
75421
  return end === -1 ? lines : [...lines.slice(0, end + 1).map(() => ""), ...lines.slice(end + 1)];
75139
75422
  }, read = (root, file) => {
75140
- const full = path44.join(root, file);
75423
+ const full = path45.join(root, file);
75141
75424
  try {
75142
75425
  fs20.lstatSync(full);
75143
75426
  } catch {
@@ -75178,7 +75461,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
75178
75461
  }
75179
75462
  }, brokenLinks = (root, doc, tracked) => {
75180
75463
  const findings = [];
75181
- const base = path44.dirname(path44.join(root, doc.file));
75464
+ const base = path45.dirname(path45.join(root, doc.file));
75182
75465
  const missing = (target, line, how) => findings.push({
75183
75466
  rule: "broken-link",
75184
75467
  file: doc.file,
@@ -75197,7 +75480,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
75197
75480
  const local = localTarget(target);
75198
75481
  if (!local)
75199
75482
  continue;
75200
- const resolved = local.startsWith("/") ? path44.join(root, local) : path44.resolve(base, local);
75483
+ const resolved = local.startsWith("/") ? path45.join(root, local) : path45.resolve(base, local);
75201
75484
  if (!exists2(resolved))
75202
75485
  missing(target, index + 1, "link");
75203
75486
  }
@@ -75207,9 +75490,9 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
75207
75490
  continue;
75208
75491
  const relative = /^\.\.?\//.test(candidate);
75209
75492
  const first = candidate.split("/")[0];
75210
- if (!relative && !(tracked ? tracked.has(first) : exists2(path44.join(root, first))))
75493
+ if (!relative && !(tracked ? tracked.has(first) : exists2(path45.join(root, first))))
75211
75494
  continue;
75212
- const resolved = relative ? path44.resolve(base, candidate) : path44.join(root, candidate);
75495
+ const resolved = relative ? path45.resolve(base, candidate) : path45.join(root, candidate);
75213
75496
  if (!exists2(resolved))
75214
75497
  missing(span, index + 1, "pointer");
75215
75498
  }
@@ -75535,7 +75818,7 @@ import { spawn, spawnSync as spawnSync19 } from "node:child_process";
75535
75818
  import { createHash as createHash16 } from "node:crypto";
75536
75819
  import fs21 from "node:fs";
75537
75820
  import os17 from "node:os";
75538
- import path45 from "node:path";
75821
+ import path46 from "node:path";
75539
75822
  import { StringDecoder } from "node:string_decoder";
75540
75823
  function tailLines(text, lines = TAIL_LINES) {
75541
75824
  const all = text.replace(/\r\n?/gu, `
@@ -75655,7 +75938,7 @@ function planSpawn(argv, options) {
75655
75938
  return { file: argv[0], args: [], verbatim: false, shell: true };
75656
75939
  if (options.platform !== "win32")
75657
75940
  return { file: argv[0], args: argv.slice(1), verbatim: false, shell: false };
75658
- const win = path45.win32;
75941
+ const win = path46.win32;
75659
75942
  const isFile = options.isFile ?? ((file) => {
75660
75943
  try {
75661
75944
  return fs21.statSync(file).isFile();
@@ -75817,10 +76100,10 @@ function runCheckCommand(argv, options) {
75817
76100
  function storeLog(storeRoot, log) {
75818
76101
  const digest = logDigest(log);
75819
76102
  const ref = `blobs/logs/${digest.slice("sha256:".length)}.log`;
75820
- const file = path45.join(storeRoot, ref);
76103
+ const file = path46.join(storeRoot, ref);
75821
76104
  try {
75822
76105
  if (!fs21.existsSync(file)) {
75823
- fs21.mkdirSync(path45.dirname(file), { recursive: true });
76106
+ fs21.mkdirSync(path46.dirname(file), { recursive: true });
75824
76107
  const temp = `${file}.${process.pid}.${Date.now()}.tmp`;
75825
76108
  fs21.writeFileSync(temp, log, { mode: 384 });
75826
76109
  fs21.renameSync(temp, file);
@@ -75833,7 +76116,7 @@ function storeLog(storeRoot, log) {
75833
76116
  function pruneCheckLogs(storeRoot, options = {}) {
75834
76117
  const limits = { ...LOG_RETENTION, ...options.retention };
75835
76118
  const now = options.now ?? Date.now();
75836
- const dir = path45.join(storeRoot, "blobs", "logs");
76119
+ const dir = path46.join(storeRoot, "blobs", "logs");
75837
76120
  const report = { removed: 0, removedBytes: 0, kept: 0 };
75838
76121
  let names;
75839
76122
  try {
@@ -75843,7 +76126,7 @@ function pruneCheckLogs(storeRoot, options = {}) {
75843
76126
  }
75844
76127
  const files = names.flatMap((name) => {
75845
76128
  try {
75846
- const stat = fs21.statSync(path45.join(dir, name));
76129
+ const stat = fs21.statSync(path46.join(dir, name));
75847
76130
  return stat.isFile() ? [{ name, size: stat.size, mtimeMs: stat.mtimeMs }] : [];
75848
76131
  } catch {
75849
76132
  return [];
@@ -75862,7 +76145,7 @@ function pruneCheckLogs(storeRoot, options = {}) {
75862
76145
  continue;
75863
76146
  if (!options.dryRun)
75864
76147
  try {
75865
- fs21.rmSync(path45.join(dir, file.name), { force: true });
76148
+ fs21.rmSync(path46.join(dir, file.name), { force: true });
75866
76149
  } catch {
75867
76150
  continue;
75868
76151
  }
@@ -76413,12 +76696,12 @@ var init_workspace = __esm(() => {
76413
76696
 
76414
76697
  // packages/workit-core/src/core/heavy-rules.ts
76415
76698
  import fs22 from "node:fs";
76416
- import path46 from "node:path";
76699
+ import path47 from "node:path";
76417
76700
  function gitTop(cwd) {
76418
- for (let dir = path46.resolve(cwd);; dir = path46.dirname(dir)) {
76419
- if (fs22.existsSync(path46.join(dir, ".git")))
76701
+ for (let dir = path47.resolve(cwd);; dir = path47.dirname(dir)) {
76702
+ if (fs22.existsSync(path47.join(dir, ".git")))
76420
76703
  return dir;
76421
- if (path46.dirname(dir) === dir)
76704
+ if (path47.dirname(dir) === dir)
76422
76705
  return null;
76423
76706
  }
76424
76707
  }
@@ -76460,18 +76743,18 @@ var init_heavy_rules = () => {};
76460
76743
  // packages/workit-core/src/core/heavy.ts
76461
76744
  import fs23 from "node:fs";
76462
76745
  import os18 from "node:os";
76463
- import path47 from "node:path";
76746
+ import path48 from "node:path";
76464
76747
  function stateDir2(env, platform = process.platform) {
76465
76748
  if (env.WORKFLOW_TOOLKIT_STATE)
76466
76749
  return env.WORKFLOW_TOOLKIT_STATE;
76467
76750
  if (env.XDG_STATE_HOME)
76468
- return path47.join(env.XDG_STATE_HOME, "workit");
76751
+ return path48.join(env.XDG_STATE_HOME, "workit");
76469
76752
  const home = env.HOME || os18.homedir();
76470
76753
  if (platform === "darwin")
76471
- return path47.join(home, "Library", "Application Support", "workit");
76754
+ return path48.join(home, "Library", "Application Support", "workit");
76472
76755
  if (platform === "win32")
76473
- return path47.join(env.LOCALAPPDATA ?? path47.join(home, "AppData", "Local"), "workit");
76474
- return path47.join(home, ".local", "state", "workit");
76756
+ return path48.join(env.LOCALAPPDATA ?? path48.join(home, "AppData", "Local"), "workit");
76757
+ return path48.join(home, ".local", "state", "workit");
76475
76758
  }
76476
76759
  function positional(words, from, values = PM_VALUES) {
76477
76760
  let index = from;
@@ -76608,10 +76891,10 @@ function parsePattern(pattern) {
76608
76891
  }
76609
76892
  function machinePatterns(env) {
76610
76893
  const value = readJson2(heavyCommandsFile(env));
76611
- return isRecord8(value) ? stringList(value.patterns) : [];
76894
+ return isRecord8(value) ? stringList2(value.patterns) : [];
76612
76895
  }
76613
76896
  function repoPatterns(cwd) {
76614
- return repoHeavyCommands(gitTop(cwd) ?? path47.resolve(cwd));
76897
+ return repoHeavyCommands(gitTop(cwd) ?? path48.resolve(cwd));
76615
76898
  }
76616
76899
  function heavyLines(lines, options) {
76617
76900
  const found = [];
@@ -76690,13 +76973,13 @@ function leaseRewrite(command) {
76690
76973
  return null;
76691
76974
  return `${prefix}workit check --heavy -- ${rest}`;
76692
76975
  }
76693
- var HEAVY_COMMANDS_FILE = "heavy-commands.json", heavyCommandsFile = (env) => path47.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) => {
76976
+ var HEAVY_COMMANDS_FILE = "heavy-commands.json", heavyCommandsFile = (env) => path48.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) => {
76694
76977
  try {
76695
76978
  return JSON.parse(fs23.readFileSync(file, "utf8"));
76696
76979
  } catch {
76697
76980
  return;
76698
76981
  }
76699
- }, isRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), stringList = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [], linesOf = (command, dialect) => {
76982
+ }, isRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), stringList2 = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [], linesOf = (command, dialect) => {
76700
76983
  try {
76701
76984
  return commandLines(command, dialect);
76702
76985
  } catch {
@@ -76837,7 +77120,7 @@ var init_heavy = __esm(() => {
76837
77120
  import { randomUUID as randomUUID5 } from "node:crypto";
76838
77121
  import fs24 from "node:fs";
76839
77122
  import os19 from "node:os";
76840
- import path48 from "node:path";
77123
+ import path49 from "node:path";
76841
77124
  function memoryValue(value, host) {
76842
77125
  const text = typeof value === "number" ? String(value) : typeof value === "string" ? value : "";
76843
77126
  const percent = PERCENT.exec(text.trim());
@@ -77018,7 +77301,7 @@ function tryOnce(options, record, reclaimed) {
77018
77301
  const text = `${JSON.stringify(record)}
77019
77302
  `;
77020
77303
  for (let slot = 0;slot < options.slots; slot += 1) {
77021
- const file = path48.join(options.dir, `slot-${slot}.json`);
77304
+ const file = path49.join(options.dir, `slot-${slot}.json`);
77022
77305
  for (let attempt = 0;attempt < 2; attempt += 1) {
77023
77306
  try {
77024
77307
  const fd = fs24.openSync(file, "wx", 384);
@@ -77143,7 +77426,7 @@ function heldLease(dir, id, options = {}) {
77143
77426
  for (const name of names) {
77144
77427
  if (!/^slot-\d+\.json$/u.test(name))
77145
77428
  continue;
77146
- const lease = parseLease(readText5(path48.join(dir, name)));
77429
+ const lease = parseLease(readText5(path49.join(dir, name)));
77147
77430
  if (lease?.id === id && !staleReason(lease, options.probe) && (options.ancestor ?? isAncestor)(lease.pid))
77148
77431
  return lease;
77149
77432
  }
@@ -77198,10 +77481,10 @@ async function runScoped(run, wrapper, sinks) {
77198
77481
  }
77199
77482
  function firstNotice(env, session, key, now = Date.now()) {
77200
77483
  const id = (session ?? `ppid-${process.ppid}`).replace(/[^A-Za-z0-9_.-]/gu, "_").slice(0, 120);
77201
- const dir = path48.join(stateDir2(env), "notices");
77484
+ const dir = path49.join(stateDir2(env), "notices");
77202
77485
  try {
77203
77486
  fs24.mkdirSync(dir, { recursive: true, mode: 448 });
77204
- fs24.writeFileSync(path48.join(dir, `${key}-${id}`), `${new Date(now).toISOString()}
77487
+ fs24.writeFileSync(path49.join(dir, `${key}-${id}`), `${new Date(now).toISOString()}
77205
77488
  `, {
77206
77489
  flag: "wx",
77207
77490
  mode: 384
@@ -77211,7 +77494,7 @@ function firstNotice(env, session, key, now = Date.now()) {
77211
77494
  }
77212
77495
  try {
77213
77496
  for (const name of fs24.readdirSync(dir)) {
77214
- const file = path48.join(dir, name);
77497
+ const file = path49.join(dir, name);
77215
77498
  if (now - fs24.statSync(file).mtimeMs > NOTICE_TTL_MS)
77216
77499
  fs24.rmSync(file, { force: true });
77217
77500
  }
@@ -77221,7 +77504,7 @@ function firstNotice(env, session, key, now = Date.now()) {
77221
77504
  function leaseSlots(dir, slots, probe = {}) {
77222
77505
  const states = [];
77223
77506
  for (let slot = 0;slot < slots; slot += 1) {
77224
- const lease = parseLease(readText5(path48.join(dir, `slot-${slot}.json`)));
77507
+ const lease = parseLease(readText5(path49.join(dir, `slot-${slot}.json`)));
77225
77508
  states.push({
77226
77509
  slot,
77227
77510
  holder: lease ? holderOf(lease) : null,
@@ -77233,7 +77516,7 @@ function leaseSlots(dir, slots, probe = {}) {
77233
77516
  var DEFAULT_HEAVY_CHECKS, DEFAULT_SLOTS = 1, DEFAULT_WAIT_S = 600, DEFAULT_MEMORY_SHARE = 0.4, DEFAULT_CPU_SHARE = 0.7, MAX_SLOTS = 64, UNREADABLE_TTL_MS = 30000, GUARD_TTL_MS = 30000, hostShape = () => ({
77234
77517
  totalMemBytes: os19.totalmem(),
77235
77518
  cpus: Math.max(1, os19.availableParallelism?.() ?? os19.cpus().length)
77236
- }), isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), SIZE, PERCENT, UNITS, leaseDir = (env) => path48.join(stateDir2(env), "leases"), readText5 = (file) => {
77519
+ }), isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), SIZE, PERCENT, UNITS, leaseDir = (env) => path49.join(stateDir2(env), "leases"), readText5 = (file) => {
77237
77520
  try {
77238
77521
  return fs24.readFileSync(file, "utf8");
77239
77522
  } catch {
@@ -77288,7 +77571,7 @@ __export(exports_check, {
77288
77571
  workspaceResources: () => workspaceResources
77289
77572
  });
77290
77573
  import os20 from "node:os";
77291
- import path49 from "node:path";
77574
+ import path50 from "node:path";
77292
77575
  function parse6(argv) {
77293
77576
  const split = argv.indexOf("--");
77294
77577
  const head = split >= 0 ? argv.slice(0, split) : [...argv];
@@ -77486,7 +77769,7 @@ function hostToolWaitCapMs(env) {
77486
77769
  }
77487
77770
  async function workspaceResources(io) {
77488
77771
  const env = io.env;
77489
- const dir = env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path49.join(env.XDG_CONFIG_HOME || path49.join(env.HOME || os20.homedir(), ".config"), "workit");
77772
+ const dir = env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path50.join(env.XDG_CONFIG_HOME || path50.join(env.HOME || os20.homedir(), ".config"), "workit");
77490
77773
  try {
77491
77774
  await Promise.resolve().then(() => init_workspaces());
77492
77775
  const workspace = resolveWorkspaceFrom(io.cwd, dir, env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined);
@@ -77605,7 +77888,7 @@ async function run12(argv, io) {
77605
77888
  if (options.shell && command.length !== 1)
77606
77889
  return emit(io, fail2("invalid_input", '--shell takes the command as one string: workit check --shell -- "<cmd>"'));
77607
77890
  }
77608
- const relCwd = posix(path49.relative(top, runCwd));
77891
+ const relCwd = posix(path50.relative(top, runCwd));
77609
77892
  const configured = !options.shell && matchesNamedCheck(config, name, command, relCwd);
77610
77893
  const shadowed = !configured && name !== null ? config.checks.find((item) => item.name === name) : undefined;
77611
77894
  if (shadowed)
@@ -77667,7 +77950,7 @@ async function run12(argv, io) {
77667
77950
  const modifiedWorktree = key.tree !== null && treeAfter !== key.tree;
77668
77951
  const store = storeRoot(io.cwd);
77669
77952
  const blob = store.ok ? storeLog(store.value.root, result.log) : null;
77670
- const logPath = store.ok && blob ? path49.join(store.value.root, blob.ref) : null;
77953
+ const logPath = store.ok && blob ? path50.join(store.value.root, blob.ref) : null;
77671
77954
  const tail = tailLines(result.log, TAIL_LINES);
77672
77955
  const passed = result.exitCode === 0 && !result.timedOut;
77673
77956
  const bounded = boundedArgv(command);
@@ -77780,7 +78063,7 @@ async function run12(argv, io) {
77780
78063
  return recordError.code === "busy" ? 4 : recordError.code === "invalid_input" ? 2 : 5;
77781
78064
  return 0;
77782
78065
  }
77783
- var USAGE5 = 'workit check <name> [--full] [--no-lease --reason "<why>"] | workit check [--name <n>] [--shell] [--heavy] [--full] [--wait <s>] [--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(path49.sep).join("/") || ".", ENGINE_CODES2, FINGERPRINT_VARS, HOST_TOOL_WAIT_CAP_MS = 1e5;
78066
+ var USAGE5 = 'workit check <name> [--full] [--no-lease --reason "<why>"] | workit check [--name <n>] [--shell] [--heavy] [--full] [--wait <s>] [--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(path50.sep).join("/") || ".", ENGINE_CODES2, FINGERPRINT_VARS, HOST_TOOL_WAIT_CAP_MS = 1e5;
77784
78067
  var init_check = __esm(() => {
77785
78068
  init_check_config();
77786
78069
  init_checks3();
@@ -77806,7 +78089,7 @@ __export(exports_lock, {
77806
78089
  run: () => run13
77807
78090
  });
77808
78091
  import fs25 from "node:fs";
77809
- import path50 from "node:path";
78092
+ import path51 from "node:path";
77810
78093
  async function settingsFor(io) {
77811
78094
  const workspace = await workspaceResources(io);
77812
78095
  const config = loadCheckConfig(io.cwd);
@@ -77888,7 +78171,7 @@ function readPatterns(file) {
77888
78171
  return { patterns: [] };
77889
78172
  }
77890
78173
  function writePatterns(file, value) {
77891
- fs25.mkdirSync(path50.dirname(file), { recursive: true, mode: 448 });
78174
+ fs25.mkdirSync(path51.dirname(file), { recursive: true, mode: 448 });
77892
78175
  const temp = `${file}.${process.pid}.tmp`;
77893
78176
  fs25.writeFileSync(temp, `${JSON.stringify(value, null, 2)}
77894
78177
  `, { mode: 384 });
@@ -77974,9 +78257,9 @@ var exports_models = {};
77974
78257
  __export(exports_models, {
77975
78258
  run: () => run14
77976
78259
  });
77977
- import { existsSync as existsSync22, readdirSync as readdirSync10, readFileSync as readFileSync21, statSync as statSync9 } from "node:fs";
78260
+ import { existsSync as existsSync22, readdirSync as readdirSync12, readFileSync as readFileSync22, statSync as statSync9 } from "node:fs";
77978
78261
  import os21 from "node:os";
77979
- import path51 from "node:path";
78262
+ import path52 from "node:path";
77980
78263
  async function run14(argv, io) {
77981
78264
  const [sub, ...args] = argv.filter((arg) => arg !== "--json");
77982
78265
  if (sub !== "show")
@@ -78037,7 +78320,7 @@ var USAGE7 = "workit models show [--role <role>] [--tier <tier>] [--host <host>]
78037
78320
  const found = new Set;
78038
78321
  let text = "";
78039
78322
  try {
78040
- text = readFileSync21(file, "utf8");
78323
+ text = readFileSync22(file, "utf8");
78041
78324
  } catch {
78042
78325
  return found;
78043
78326
  }
@@ -78051,24 +78334,24 @@ var USAGE7 = "workit models show [--role <role>] [--tier <tier>] [--host <host>]
78051
78334
  } catch {}
78052
78335
  return found;
78053
78336
  }, matches3 = (ran, configured) => ran.toLowerCase().includes(configured.toLowerCase()), usageReport = (cwd, env, days) => {
78054
- const projects = path51.join(env.CLAUDE_CONFIG_DIR || path51.join(env.HOME || os21.homedir(), ".claude"), "projects");
78337
+ const projects = path52.join(env.CLAUDE_CONFIG_DIR || path52.join(env.HOME || os21.homedir(), ".claude"), "projects");
78055
78338
  const since = Date.now() - days * 86400000;
78056
78339
  const types = {};
78057
78340
  let agents = 0;
78058
78341
  const dirs = (dir) => {
78059
78342
  try {
78060
- return readdirSync10(dir).map((name) => path51.join(dir, name));
78343
+ return readdirSync12(dir).map((name) => path52.join(dir, name));
78061
78344
  } catch {
78062
78345
  return [];
78063
78346
  }
78064
78347
  };
78065
78348
  for (const project of dirs(projects))
78066
78349
  for (const session of dirs(project))
78067
- for (const meta of dirs(path51.join(session, "subagents")).filter((f) => f.endsWith(".meta.json"))) {
78350
+ for (const meta of dirs(path52.join(session, "subagents")).filter((f) => f.endsWith(".meta.json"))) {
78068
78351
  try {
78069
78352
  if (statSync9(meta).mtimeMs < since)
78070
78353
  continue;
78071
- const agentType = JSON.parse(readFileSync21(meta, "utf8")).agentType;
78354
+ const agentType = JSON.parse(readFileSync22(meta, "utf8")).agentType;
78072
78355
  const transcript = meta.replace(/\.meta\.json$/, ".jsonl");
78073
78356
  if (typeof agentType !== "string" || !existsSync22(transcript))
78074
78357
  continue;
@@ -78209,8 +78492,8 @@ var success2 = (data) => ({ ok: true, data }), failure3 = (code, error, unblock)
78209
78492
 
78210
78493
  // packages/workit-core/src/git/ops.ts
78211
78494
  import { spawnSync as spawnSync20 } from "node:child_process";
78212
- import { existsSync as existsSync23, readFileSync as readFileSync22 } from "node:fs";
78213
- import path52 from "node:path";
78495
+ import { existsSync as existsSync23, readFileSync as readFileSync23 } from "node:fs";
78496
+ import path53 from "node:path";
78214
78497
  function operationInProgress(cwd) {
78215
78498
  const markers = [
78216
78499
  ["rebase-merge", "rebase"],
@@ -78223,18 +78506,18 @@ function operationInProgress(cwd) {
78223
78506
  if (!run.ok)
78224
78507
  return null;
78225
78508
  const found = run.stdout.split(`
78226
- `).map((line) => path52.resolve(cwd, line.trim()));
78509
+ `).map((line) => path53.resolve(cwd, line.trim()));
78227
78510
  const conflicted = () => git5(cwd, ["ls-files", "-u"]).stdout.trim() !== "";
78228
78511
  for (const [index, [, operation]] of markers.entries()) {
78229
78512
  const marker = found[index];
78230
78513
  if (!marker || !existsSync23(marker))
78231
78514
  continue;
78232
- if (index === 1 && existsSync23(path52.join(marker, "applying")))
78515
+ if (index === 1 && existsSync23(path53.join(marker, "applying")))
78233
78516
  return { operation: "am", commitAllowed: false, branch: null };
78234
- if (index === 0 && existsSync23(path52.join(marker, "amend")) && !conflicted()) {
78517
+ if (index === 0 && existsSync23(path53.join(marker, "amend")) && !conflicted()) {
78235
78518
  let headName = "";
78236
78519
  try {
78237
- headName = readFileSync22(path52.join(marker, "head-name"), "utf8").trim();
78520
+ headName = readFileSync23(path53.join(marker, "head-name"), "utf8").trim();
78238
78521
  } catch {}
78239
78522
  const branch = headName.startsWith("refs/heads/") ? headName.slice("refs/heads/".length) : null;
78240
78523
  return { operation, commitAllowed: branch !== null, branch };
@@ -78562,7 +78845,7 @@ function gitCommit(cwd, input) {
78562
78845
  if (paths.some((value) => value.startsWith("-") || !value.trim()))
78563
78846
  return failure3("invalid_input", "paths must not be empty or start with -");
78564
78847
  const tracked = new Set(nulList(git5(cwd, ["ls-files", "-z", "--", ...paths]).stdout));
78565
- const addable = paths.filter((value) => existsSync23(path52.resolve(cwd, value)) || [...tracked].some((file) => file === value || file.startsWith(`${value}/`)));
78848
+ const addable = paths.filter((value) => existsSync23(path53.resolve(cwd, value)) || [...tracked].some((file) => file === value || file.startsWith(`${value}/`)));
78566
78849
  if (addable.length) {
78567
78850
  const added = git5(cwd, ["add", "-A", "--", ...addable]);
78568
78851
  if (!added.ok)
@@ -79101,12 +79384,12 @@ var init_ops = __esm(() => {
79101
79384
 
79102
79385
  // packages/workit-core/src/verdict-cover.ts
79103
79386
  import fs26 from "node:fs";
79104
- import path53 from "node:path";
79387
+ import path54 from "node:path";
79105
79388
  function chainsAbove(cwd, branch) {
79106
79389
  const root = storeRoot(cwd);
79107
79390
  if (!root.ok)
79108
79391
  return [];
79109
- const dir = path53.join(root.value.root, "stacks");
79392
+ const dir = path54.join(root.value.root, "stacks");
79110
79393
  let names = [];
79111
79394
  try {
79112
79395
  names = fs26.readdirSync(dir).filter((name) => name.endsWith(".json"));
@@ -79117,7 +79400,7 @@ function chainsAbove(cwd, branch) {
79117
79400
  for (const name of names.toSorted()) {
79118
79401
  let parsed;
79119
79402
  try {
79120
- parsed = JSON.parse(fs26.readFileSync(path53.join(dir, name), "utf8"));
79403
+ parsed = JSON.parse(fs26.readFileSync(path54.join(dir, name), "utf8"));
79121
79404
  } catch {
79122
79405
  continue;
79123
79406
  }
@@ -79212,10 +79495,10 @@ var init_pr_lane = __esm(() => {
79212
79495
 
79213
79496
  // packages/workit-core/src/forge/reruns.ts
79214
79497
  import fs27 from "node:fs";
79215
- import path54 from "node:path";
79498
+ import path55 from "node:path";
79216
79499
  function rerunLogPath(cwd) {
79217
79500
  const common = gitCommonDir(cwd);
79218
- return common ? path54.join(common, "workit", "ci-reruns.jsonl") : null;
79501
+ return common ? path55.join(common, "workit", "ci-reruns.jsonl") : null;
79219
79502
  }
79220
79503
  function rerunCounts(cwd, key) {
79221
79504
  const counts = new Map;
@@ -79250,7 +79533,7 @@ function recordReruns(cwd, rows) {
79250
79533
  if (!file)
79251
79534
  return false;
79252
79535
  try {
79253
- fs27.mkdirSync(path54.dirname(file), { recursive: true });
79536
+ fs27.mkdirSync(path55.dirname(file), { recursive: true });
79254
79537
  fs27.appendFileSync(file, rows.map((row) => `${JSON.stringify(row)}
79255
79538
  `).join(""));
79256
79539
  return true;
@@ -79263,7 +79546,7 @@ function withRerunLock(cwd, fn) {
79263
79546
  if (!file)
79264
79547
  return fn();
79265
79548
  const lock = `${file.slice(0, -".jsonl".length)}.lock`;
79266
- fs27.mkdirSync(path54.dirname(lock), { recursive: true });
79549
+ fs27.mkdirSync(path55.dirname(lock), { recursive: true });
79267
79550
  const until = Date.now() + LOCK_WAIT_MS2;
79268
79551
  for (;; ) {
79269
79552
  try {
@@ -80210,7 +80493,7 @@ var init_pr_ops = __esm(() => {
80210
80493
  import { spawnSync as spawnSync22 } from "node:child_process";
80211
80494
  import { createHash as createHash17, randomBytes as randomBytes4 } from "node:crypto";
80212
80495
  import fs28 from "node:fs";
80213
- import path55 from "node:path";
80496
+ import path56 from "node:path";
80214
80497
  function worktreeOf(cwd, branch) {
80215
80498
  const list = gitRun3(cwd, ["worktree", "list", "--porcelain"]);
80216
80499
  if (!list.ok)
@@ -80254,7 +80537,7 @@ function gitRestack(cwd, input) {
80254
80537
  if (!scratch)
80255
80538
  return { ok: false, conflict: false, worktree: cwd, error: "no store root" };
80256
80539
  fs28.mkdirSync(scratch, { recursive: true });
80257
- dir = path55.join(scratch, `${input.branch.replace(/[^A-Za-z0-9._-]+/gu, "_").slice(0, 40)}-${randomBytes4(4).toString("hex")}`);
80540
+ dir = path56.join(scratch, `${input.branch.replace(/[^A-Za-z0-9._-]+/gu, "_").slice(0, 40)}-${randomBytes4(4).toString("hex")}`);
80258
80541
  const added = gitRun3(cwd, ["worktree", "add", "-q", dir, input.branch], GIT_TIMEOUTS.worktree);
80259
80542
  if (!added.ok)
80260
80543
  return { ok: false, conflict: false, worktree: cwd, error: firstLine(added) };
@@ -80295,7 +80578,7 @@ function pruneScratch(cwd) {
80295
80578
  if (!scratch || !fs28.existsSync(scratch))
80296
80579
  return;
80297
80580
  for (const name of fs28.readdirSync(scratch)) {
80298
- const dir = path55.join(scratch, name);
80581
+ const dir = path56.join(scratch, name);
80299
80582
  if (!rebaseInProgress(dir) && !trackedDirt(dir))
80300
80583
  gitRun3(cwd, ["worktree", "remove", "--force", dir]);
80301
80584
  }
@@ -80305,7 +80588,7 @@ function stacksDir(cwd) {
80305
80588
  const root = storeRoot(cwd);
80306
80589
  if (!root.ok)
80307
80590
  return stackFail(root.code, root.error, root.unblock);
80308
- return { ok: true, data: path55.join(root.value.root, "stacks") };
80591
+ return { ok: true, data: path56.join(root.value.root, "stacks") };
80309
80592
  }
80310
80593
  function parseStack(raw) {
80311
80594
  if (!isRecord12(raw) || !Array.isArray(raw.branches))
@@ -80357,7 +80640,7 @@ function readStack(cwd, name) {
80357
80640
  const dir = stacksDir(cwd);
80358
80641
  if (!dir.ok)
80359
80642
  return dir;
80360
- const file = path55.join(dir.data, fileFor(name));
80643
+ const file = path56.join(dir.data, fileFor(name));
80361
80644
  let text;
80362
80645
  try {
80363
80646
  text = fs28.readFileSync(file, "utf8");
@@ -80378,7 +80661,7 @@ function writeStack(cwd, stack, now = new Date) {
80378
80661
  const dir = stacksDir(cwd);
80379
80662
  if (!dir.ok)
80380
80663
  return dir;
80381
- const file = path55.join(dir.data, fileFor(stack.name));
80664
+ const file = path56.join(dir.data, fileFor(stack.name));
80382
80665
  const temp = `${file}.${process.pid}.tmp`;
80383
80666
  try {
80384
80667
  fs28.mkdirSync(dir.data, { recursive: true });
@@ -80406,7 +80689,7 @@ function listStacks(cwd) {
80406
80689
  for (const name of names) {
80407
80690
  let parsed = null;
80408
80691
  try {
80409
- parsed = parseStack(JSON.parse(fs28.readFileSync(path55.join(dir.data, name), "utf8")));
80692
+ parsed = parseStack(JSON.parse(fs28.readFileSync(path56.join(dir.data, name), "utf8")));
80410
80693
  } catch {
80411
80694
  parsed = null;
80412
80695
  }
@@ -80465,7 +80748,7 @@ function takeLock(lock) {
80465
80748
  host: localLockHost(),
80466
80749
  nonce: randomBytes4(8).toString("hex")
80467
80750
  };
80468
- fs28.writeFileSync(path55.join(lock, OWNER), JSON.stringify(owner));
80751
+ fs28.writeFileSync(path56.join(lock, OWNER), JSON.stringify(owner));
80469
80752
  return owner;
80470
80753
  }
80471
80754
  function reapLock(lock, observed) {
@@ -80502,7 +80785,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
80502
80785
  return dir;
80503
80786
  if (!validName(name))
80504
80787
  return stackFail("invalid_input", "a stack name must be 1-200 printable characters");
80505
- const lock = path55.join(dir.data, `${fileFor(name)}.lock`);
80788
+ const lock = path56.join(dir.data, `${fileFor(name)}.lock`);
80506
80789
  try {
80507
80790
  fs28.mkdirSync(dir.data, { recursive: true });
80508
80791
  } catch (error) {
@@ -80532,7 +80815,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
80532
80815
  const touch = () => {
80533
80816
  try {
80534
80817
  const now = new Date;
80535
- fs28.utimesSync(path55.join(lock, OWNER), now, now);
80818
+ fs28.utimesSync(path56.join(lock, OWNER), now, now);
80536
80819
  } catch {}
80537
80820
  };
80538
80821
  const beat = setInterval(touch, HEARTBEAT_MS);
@@ -81383,7 +81666,7 @@ var STACK_VERSION = 1, stackFail = (code, error, unblock, data) => ({
81383
81666
  return !status.ok || status.stdout.trim() !== "";
81384
81667
  }, scratchDir = (cwd) => {
81385
81668
  const dir = stacksDir(cwd);
81386
- return dir.ok ? path55.join(dir.data, "worktrees") : null;
81669
+ return dir.ok ? path56.join(dir.data, "worktrees") : null;
81387
81670
  }, firstLine = (run) => (`${run.stderr}
81388
81671
  ${run.stdout}`.split(`
81389
81672
  `).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()}-${createHash17("sha256").update(name).digest("hex").slice(0, 12)}.json`, fileFor, validName = (name) => {
@@ -81398,12 +81681,12 @@ ${run.stdout}`.split(`
81398
81681
  }, 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) => {
81399
81682
  let raw = null;
81400
81683
  try {
81401
- raw = fs28.readFileSync(path55.join(lock, OWNER), "utf8");
81684
+ raw = fs28.readFileSync(path56.join(lock, OWNER), "utf8");
81402
81685
  } catch {
81403
81686
  raw = null;
81404
81687
  }
81405
81688
  let age = null;
81406
- for (const target of [path55.join(lock, OWNER), lock])
81689
+ for (const target of [path56.join(lock, OWNER), lock])
81407
81690
  try {
81408
81691
  age = Date.now() - fs28.statSync(target).mtimeMs;
81409
81692
  break;
@@ -81446,7 +81729,7 @@ var init_stack = __esm(() => {
81446
81729
  import { spawnSync as spawnSync23 } from "node:child_process";
81447
81730
  import { createHash as createHash18 } from "node:crypto";
81448
81731
  import fs29 from "node:fs";
81449
- import path56 from "node:path";
81732
+ import path57 from "node:path";
81450
81733
  function expandBraces2(pattern, limit = 64) {
81451
81734
  for (let index = 0;index < pattern.length; index += 1) {
81452
81735
  if (pattern[index] === "\\") {
@@ -81692,7 +81975,7 @@ function parsePlan(raw, defaults, name) {
81692
81975
  id,
81693
81976
  branch,
81694
81977
  base: optional("base") ?? "",
81695
- worktree: path56.resolve(defaults.root, optional("worktree") ?? path56.join(defaults.worktreeRoot, id)),
81978
+ worktree: path57.resolve(defaults.root, optional("worktree") ?? path57.join(defaults.worktreeRoot, id)),
81696
81979
  tier,
81697
81980
  reason,
81698
81981
  dependsOn: [...new Set(dependsOn ?? [])],
@@ -81821,12 +82104,12 @@ function regeneratedFiles(root, tracked) {
81821
82104
  const found = new Map;
81822
82105
  let scripts;
81823
82106
  try {
81824
- const manifest = JSON.parse(fs29.readFileSync(path56.join(root, "package.json"), "utf8"));
82107
+ const manifest = JSON.parse(fs29.readFileSync(path57.join(root, "package.json"), "utf8"));
81825
82108
  scripts = manifest.scripts ?? {};
81826
82109
  } catch {
81827
82110
  return found;
81828
82111
  }
81829
- const runner = fs29.existsSync(path56.join(root, "bun.lock")) ? "bun run" : fs29.existsSync(path56.join(root, "pnpm-lock.yaml")) ? "pnpm run" : fs29.existsSync(path56.join(root, "yarn.lock")) ? "yarn run" : "npm run";
82112
+ const runner = fs29.existsSync(path57.join(root, "bun.lock")) ? "bun run" : fs29.existsSync(path57.join(root, "pnpm-lock.yaml")) ? "pnpm run" : fs29.existsSync(path57.join(root, "yarn.lock")) ? "yarn run" : "npm run";
81830
82113
  const outputs = tracked.filter((file) => !CODE.test(file));
81831
82114
  for (const [name, command] of Object.entries(scripts)) {
81832
82115
  if (!name.startsWith("write:") || typeof command !== "string")
@@ -81834,7 +82117,7 @@ function regeneratedFiles(root, tracked) {
81834
82117
  for (const file of command.match(/[\w./-]+\.[cm]?[jt]s\b/gu) ?? []) {
81835
82118
  let source;
81836
82119
  try {
81837
- source = fs29.readFileSync(path56.join(root, file), "utf8");
82120
+ source = fs29.readFileSync(path57.join(root, file), "utf8");
81838
82121
  } catch {
81839
82122
  continue;
81840
82123
  }
@@ -81956,11 +82239,11 @@ function defaultTrunk(cwd) {
81956
82239
  }
81957
82240
  function mainCheckout(cwd) {
81958
82241
  const common = gitCommonDir(cwd);
81959
- return common && path56.basename(common) === ".git" ? path56.dirname(common) : path56.resolve(cwd);
82242
+ return common && path57.basename(common) === ".git" ? path57.dirname(common) : path57.resolve(cwd);
81960
82243
  }
81961
82244
  function worktreeRoot(cwd) {
81962
82245
  const main = mainCheckout(cwd);
81963
- return path56.join(path56.dirname(main), `${path56.basename(main)}-wt`);
82246
+ return path57.join(path57.dirname(main), `${path57.basename(main)}-wt`);
81964
82247
  }
81965
82248
  function sliceHash(slice) {
81966
82249
  const {
@@ -81980,7 +82263,7 @@ function fanoutsDir(cwd) {
81980
82263
  const root = storeRoot(cwd);
81981
82264
  if (!root.ok)
81982
82265
  return fanoutFail(root.code, root.error, root.unblock);
81983
- return { ok: true, data: path56.join(root.value.root, "fanouts") };
82266
+ return { ok: true, data: path57.join(root.value.root, "fanouts") };
81984
82267
  }
81985
82268
  function parseStored(raw) {
81986
82269
  if (!isRecord13(raw) || typeof raw.name !== "string" || typeof raw.trunk !== "string")
@@ -82048,7 +82331,7 @@ function readFanout(cwd, name) {
82048
82331
  const dir = fanoutsDir(cwd);
82049
82332
  if (!dir.ok)
82050
82333
  return dir;
82051
- const file = path56.join(dir.data, stackFileName(name));
82334
+ const file = path57.join(dir.data, stackFileName(name));
82052
82335
  let parsed = null;
82053
82336
  try {
82054
82337
  parsed = parseStored(JSON.parse(fs29.readFileSync(file, "utf8")));
@@ -82073,7 +82356,7 @@ function listFanouts(cwd) {
82073
82356
  for (const entry of names) {
82074
82357
  let parsed = null;
82075
82358
  try {
82076
- parsed = parseStored(JSON.parse(fs29.readFileSync(path56.join(dir.data, entry), "utf8")));
82359
+ parsed = parseStored(JSON.parse(fs29.readFileSync(path57.join(dir.data, entry), "utf8")));
82077
82360
  } catch {
82078
82361
  parsed = null;
82079
82362
  }
@@ -82112,7 +82395,7 @@ function writeFanout(cwd, plan) {
82112
82395
  const dir = fanoutsDir(cwd);
82113
82396
  if (!dir.ok)
82114
82397
  return dir;
82115
- const file = path56.join(dir.data, stackFileName(plan.name));
82398
+ const file = path57.join(dir.data, stackFileName(plan.name));
82116
82399
  const temp = `${file}.${process.pid}.tmp`;
82117
82400
  try {
82118
82401
  fs29.mkdirSync(dir.data, { recursive: true });
@@ -82323,13 +82606,13 @@ var init_fanout = __esm(() => {
82323
82606
  // packages/workit-core/src/forge/exec.ts
82324
82607
  import { spawnSync as spawnSync24 } from "node:child_process";
82325
82608
  import fs30 from "node:fs";
82326
- import path57 from "node:path";
82609
+ import path58 from "node:path";
82327
82610
  function findExecutable(bin, env) {
82328
- const dirs = (env.PATH ?? env.Path ?? "").split(path57.delimiter).filter(Boolean);
82611
+ const dirs = (env.PATH ?? env.Path ?? "").split(path58.delimiter).filter(Boolean);
82329
82612
  const exts = process.platform === "win32" ? [".exe"] : [""];
82330
82613
  for (const dir of dirs)
82331
82614
  for (const ext of exts) {
82332
- const candidate = path57.join(dir, `${bin}${ext}`);
82615
+ const candidate = path58.join(dir, `${bin}${ext}`);
82333
82616
  try {
82334
82617
  const stat = fs30.statSync(candidate);
82335
82618
  if (stat.isFile())
@@ -83839,7 +84122,7 @@ var init_live_session = __esm(() => {
83839
84122
  });
83840
84123
 
83841
84124
  // packages/workit-core/src/hooks/write-gate.ts
83842
- import path58 from "node:path";
84125
+ import path59 from "node:path";
83843
84126
  var CASE_INSENSITIVE, PREFIXES2, SCRIPT_SHELLS, cache3, MUTATING_GIT, DRY_N, MUTATING_WORKIT_GIT, CD2, PUSHD2, POPD2, UNKNOWN_DIR;
83844
84127
  var init_write_gate = __esm(() => {
83845
84128
  init_task_store();
@@ -83879,7 +84162,7 @@ var init_write_gate = __esm(() => {
83879
84162
  CD2 = new Set(["cd", "chdir", "set-location", "sl"]);
83880
84163
  PUSHD2 = new Set(["pushd", "push-location"]);
83881
84164
  POPD2 = new Set(["popd", "pop-location"]);
83882
- UNKNOWN_DIR = path58.resolve(path58.parse(process.cwd()).root, ".workit-unknown-dir");
84165
+ UNKNOWN_DIR = path59.resolve(path59.parse(process.cwd()).root, ".workit-unknown-dir");
83883
84166
  });
83884
84167
 
83885
84168
  // packages/workit-core/src/hooks/worktree-confine.ts
@@ -83904,20 +84187,20 @@ var init_worktree_confine = __esm(() => {
83904
84187
 
83905
84188
  // packages/workit-core/src/worktree-deps.ts
83906
84189
  import fs31 from "node:fs";
83907
- import path59 from "node:path";
84190
+ import path60 from "node:path";
83908
84191
  function moduleDirs(main) {
83909
84192
  const out = [];
83910
84193
  const walk = (relative, depth) => {
83911
84194
  let entries;
83912
84195
  try {
83913
- entries = fs31.readdirSync(path59.join(main, relative), { withFileTypes: true });
84196
+ entries = fs31.readdirSync(path60.join(main, relative), { withFileTypes: true });
83914
84197
  } catch {
83915
84198
  return;
83916
84199
  }
83917
84200
  for (const entry of entries) {
83918
84201
  if (!entry.isDirectory())
83919
84202
  continue;
83920
- const child = path59.join(relative, entry.name);
84203
+ const child = path60.join(relative, entry.name);
83921
84204
  if (entry.name === MODULES)
83922
84205
  out.push(child);
83923
84206
  else if (depth < MAX_DEPTH2 && !entry.name.startsWith("."))
@@ -83931,8 +84214,8 @@ function linkEntry(main, worktree, source, target) {
83931
84214
  const stat = fs31.lstatSync(source);
83932
84215
  if (stat.isSymbolicLink()) {
83933
84216
  const link = fs31.readlinkSync(source);
83934
- const outside = path59.isAbsolute(link) && within(link, main) && !path59.relative(main, link).split(path59.sep).includes(MODULES);
83935
- const to = outside ? path59.join(worktree, path59.relative(main, link)) : link;
84217
+ const outside = path60.isAbsolute(link) && within(link, main) && !path60.relative(main, link).split(path60.sep).includes(MODULES);
84218
+ const to = outside ? path60.join(worktree, path60.relative(main, link)) : link;
83936
84219
  fs31.symlinkSync(to, target, process.platform === "win32" ? "junction" : undefined);
83937
84220
  return;
83938
84221
  }
@@ -83942,8 +84225,8 @@ function mirror(main, worktree, source, target, top) {
83942
84225
  fs31.mkdirSync(target);
83943
84226
  let count = 0;
83944
84227
  for (const entry of fs31.readdirSync(source, { withFileTypes: true })) {
83945
- const from = path59.join(source, entry.name);
83946
- const to = path59.join(target, entry.name);
84228
+ const from = path60.join(source, entry.name);
84229
+ const to = path60.join(target, entry.name);
83947
84230
  if (top && entry.isDirectory() && (entry.name.startsWith("@") || entry.name === ".bin"))
83948
84231
  count += mirror(main, worktree, from, to, false);
83949
84232
  else {
@@ -83959,16 +84242,16 @@ function linkWorktreeDependencies(main, worktree) {
83959
84242
  const dirs = [];
83960
84243
  let entries = 0;
83961
84244
  for (const relative of moduleDirs(main)) {
83962
- const target = path59.join(worktree, relative);
83963
- if (!fs31.existsSync(path59.dirname(target)) || fs31.existsSync(target))
84245
+ const target = path60.join(worktree, relative);
84246
+ if (!fs31.existsSync(path60.dirname(target)) || fs31.existsSync(target))
83964
84247
  continue;
83965
- if (!gitRun4(worktree, ["check-ignore", "-q", `${relative.split(path59.sep).join("/")}/`]).ok) {
83966
- notes.push(`${relative.split(path59.sep).join("/")} is not ignored by git, so it was not linked from ${main}; install dependencies in the worktree yourself`);
84248
+ if (!gitRun4(worktree, ["check-ignore", "-q", `${relative.split(path60.sep).join("/")}/`]).ok) {
84249
+ notes.push(`${relative.split(path60.sep).join("/")} is not ignored by git, so it was not linked from ${main}; install dependencies in the worktree yourself`);
83967
84250
  continue;
83968
84251
  }
83969
84252
  try {
83970
- entries += mirror(main, worktree, path59.join(main, relative), target, true);
83971
- dirs.push(relative.split(path59.sep).join("/"));
84253
+ entries += mirror(main, worktree, path60.join(main, relative), target, true);
84254
+ dirs.push(relative.split(path60.sep).join("/"));
83972
84255
  } catch (error) {
83973
84256
  fs31.rmSync(target, { recursive: true, force: true });
83974
84257
  notes.push(`could not link ${relative} from ${main} (${error.message}); install dependencies in the worktree yourself`);
@@ -83981,8 +84264,8 @@ function linkWorktreeDependencies(main, worktree) {
83981
84264
  return { linked: { from: main, dirs, entries, ms }, notes };
83982
84265
  }
83983
84266
  var MODULES = "node_modules", MAX_DEPTH2 = 2, within = (child, parent) => {
83984
- const relative = path59.relative(parent, child);
83985
- return relative === "" || !relative.startsWith("..") && !path59.isAbsolute(relative);
84267
+ const relative = path60.relative(parent, child);
84268
+ return relative === "" || !relative.startsWith("..") && !path60.isAbsolute(relative);
83986
84269
  };
83987
84270
  var init_worktree_deps = __esm(() => {
83988
84271
  init_fanout();
@@ -83991,7 +84274,7 @@ var init_worktree_deps = __esm(() => {
83991
84274
  // packages/workit-core/src/fanout-worktree.ts
83992
84275
  import { randomBytes as randomBytes5 } from "node:crypto";
83993
84276
  import fs32 from "node:fs";
83994
- import path60 from "node:path";
84277
+ import path61 from "node:path";
83995
84278
  function rowSample(lines) {
83996
84279
  const out = [];
83997
84280
  let bytes = 0;
@@ -84051,7 +84334,7 @@ function adminDir(worktree) {
84051
84334
  const file = dir.stdout.trim();
84052
84335
  let token = null;
84053
84336
  try {
84054
- token = fs32.readFileSync(path60.join(file, FANOUT_TOKEN_FILE), "utf8").trim() || null;
84337
+ token = fs32.readFileSync(path61.join(file, FANOUT_TOKEN_FILE), "utf8").trim() || null;
84055
84338
  } catch {
84056
84339
  token = null;
84057
84340
  }
@@ -84059,7 +84342,7 @@ function adminDir(worktree) {
84059
84342
  const stat = worktreeDeps.stat(file);
84060
84343
  return {
84061
84344
  path: file,
84062
- id: path60.basename(file),
84345
+ id: path61.basename(file),
84063
84346
  ino: stat.ino.toString(),
84064
84347
  token,
84065
84348
  birthMs: stat.birthtimeNs > 0n ? Number(stat.birthtimeMs) : null,
@@ -84075,7 +84358,7 @@ function markAdminDir(worktree) {
84075
84358
  return null;
84076
84359
  const token = randomBytes5(16).toString("hex");
84077
84360
  try {
84078
- fs32.writeFileSync(path60.join(admin.path, FANOUT_TOKEN_FILE), `${token}
84361
+ fs32.writeFileSync(path61.join(admin.path, FANOUT_TOKEN_FILE), `${token}
84079
84362
  `);
84080
84363
  } catch {
84081
84364
  return null;
@@ -84090,7 +84373,7 @@ function excludeScratch(cwd) {
84090
84373
  const common = gitCommonDir(cwd);
84091
84374
  if (!common)
84092
84375
  return;
84093
- const file = path60.join(common, "info", "exclude");
84376
+ const file = path61.join(common, "info", "exclude");
84094
84377
  let text = "";
84095
84378
  try {
84096
84379
  text = fs32.readFileSync(file, "utf8");
@@ -84099,7 +84382,7 @@ function excludeScratch(cwd) {
84099
84382
  }
84100
84383
  if (text.split(/\r?\n/u).includes(EXCLUDE_LINE))
84101
84384
  return;
84102
- fs32.mkdirSync(path60.dirname(file), { recursive: true });
84385
+ fs32.mkdirSync(path61.dirname(file), { recursive: true });
84103
84386
  fs32.appendFileSync(file, `${text && !text.endsWith(`
84104
84387
  `) ? `
84105
84388
  ` : ""}# workit fanout: per-worker scratch dirs
@@ -84108,13 +84391,13 @@ ${EXCLUDE_LINE}
84108
84391
  }
84109
84392
  function worktreeDependencies(main, worktree) {
84110
84393
  for (const [name, install] of LOCKFILES2) {
84111
- const ours = readBytes(path60.join(main, name));
84112
- const theirs = readBytes(path60.join(worktree, name));
84394
+ const ours = readBytes(path61.join(main, name));
84395
+ const theirs = readBytes(path61.join(worktree, name));
84113
84396
  if (ours === null && theirs === null)
84114
84397
  continue;
84115
84398
  if (ours !== null && theirs !== null && ours.equals(theirs))
84116
84399
  continue;
84117
- if (fs32.existsSync(path60.join(worktree, "node_modules")))
84400
+ if (fs32.existsSync(path61.join(worktree, "node_modules")))
84118
84401
  break;
84119
84402
  const command = install(worktree);
84120
84403
  return {
@@ -84128,7 +84411,7 @@ function worktreeDependencies(main, worktree) {
84128
84411
  return { ...linkWorktreeDependencies(main, worktree), install: null };
84129
84412
  }
84130
84413
  function ensureScratch(worktree) {
84131
- const scratch = path60.join(worktree, SCRATCH_DIR);
84414
+ const scratch = path61.join(worktree, SCRATCH_DIR);
84132
84415
  fs32.mkdirSync(scratch, { recursive: true });
84133
84416
  return scratch;
84134
84417
  }
@@ -84367,7 +84650,7 @@ function unpushedCount(cwd, branch) {
84367
84650
  return count.ok ? Number(count.stdout.trim()) : null;
84368
84651
  }
84369
84652
  function removeScratch(worktree) {
84370
- const scratch = path60.join(worktree, SCRATCH_DIR);
84653
+ const scratch = path61.join(worktree, SCRATCH_DIR);
84371
84654
  let stat;
84372
84655
  try {
84373
84656
  stat = fs32.lstatSync(scratch);
@@ -84383,16 +84666,16 @@ var SLOW, SCRATCH_DIR = ".workit-scratch", EXCLUDE_LINE, DIRTY_ROW_BYTES = 2000,
84383
84666
  try {
84384
84667
  return fs32.realpathSync.native(target);
84385
84668
  } catch {
84386
- return path60.resolve(target);
84669
+ return path61.resolve(target);
84387
84670
  }
84388
84671
  }, samePath = (a, b) => {
84389
84672
  const left = canonical2(a);
84390
84673
  const right = canonical2(b);
84391
84674
  return process.platform === "win32" || process.platform === "darwin" ? left.toLowerCase() === right.toLowerCase() : left === right;
84392
84675
  }, inside3 = (child, parent) => {
84393
- const relative = path60.relative(canonical2(parent), canonical2(child));
84394
- return relative === "" || !relative.startsWith("..") && !path60.isAbsolute(relative);
84395
- }, slicePath = (cwd, slice) => path60.isAbsolute(slice.worktree) ? slice.worktree : path60.resolve(mainCheckout(cwd), slice.worktree), CLOCK_SLACK_MS = 2000, worktreeDeps, LOCKFILES2, readBytes = (file) => {
84676
+ const relative = path61.relative(canonical2(parent), canonical2(child));
84677
+ return relative === "" || !relative.startsWith("..") && !path61.isAbsolute(relative);
84678
+ }, slicePath = (cwd, slice) => path61.isAbsolute(slice.worktree) ? slice.worktree : path61.resolve(mainCheckout(cwd), slice.worktree), CLOCK_SLACK_MS = 2000, worktreeDeps, LOCKFILES2, readBytes = (file) => {
84396
84679
  try {
84397
84680
  return fs32.readFileSync(file);
84398
84681
  } catch {
@@ -84423,7 +84706,7 @@ var init_fanout_worktree = __esm(() => {
84423
84706
 
84424
84707
  // packages/workit-core/src/forge/merge-cleanup.ts
84425
84708
  import fs33 from "node:fs";
84426
- import path61 from "node:path";
84709
+ import path62 from "node:path";
84427
84710
  function cleanupMergedBranch(cwd, branch, mergedHead) {
84428
84711
  const out = { branchDeleted: false, worktreeRemoved: null, notes: [] };
84429
84712
  if (!branch || branch.startsWith("-"))
@@ -84483,13 +84766,13 @@ var SLOW2, isFanoutWorktree = (worktree) => {
84483
84766
  if (!dir.ok)
84484
84767
  return false;
84485
84768
  try {
84486
- return fs33.readFileSync(path61.join(dir.stdout.trim(), FANOUT_TOKEN_FILE), "utf8").trim() !== "";
84769
+ return fs33.readFileSync(path62.join(dir.stdout.trim(), FANOUT_TOKEN_FILE), "utf8").trim() !== "";
84487
84770
  } catch {
84488
84771
  return false;
84489
84772
  }
84490
84773
  }, inside4 = (child, parent) => {
84491
- const relative = path61.relative(fs33.realpathSync.native(parent), fs33.realpathSync.native(child));
84492
- return relative === "" || !relative.startsWith("..") && !path61.isAbsolute(relative);
84774
+ const relative = path62.relative(fs33.realpathSync.native(parent), fs33.realpathSync.native(child));
84775
+ return relative === "" || !relative.startsWith("..") && !path62.isAbsolute(relative);
84493
84776
  };
84494
84777
  var init_merge_cleanup = __esm(() => {
84495
84778
  init_fanout();
@@ -84770,7 +85053,7 @@ var init_duration = __esm(() => {
84770
85053
  });
84771
85054
 
84772
85055
  // packages/workit-cli/src/verbs/forge-common.ts
84773
- import { readFileSync as readFileSync23 } from "node:fs";
85056
+ import { readFileSync as readFileSync24 } from "node:fs";
84774
85057
  function parseFlags(argv, spec) {
84775
85058
  const parsed = { values: {}, booleans: new Set, lists: {}, positionals: [] };
84776
85059
  for (let index = 0;index < argv.length; index += 1) {
@@ -84925,7 +85208,7 @@ var init_forge_common = __esm(() => {
84925
85208
  forgeDeps = {
84926
85209
  runner: undefined,
84927
85210
  npm: undefined,
84928
- readStdin: () => readFileSync23(0, "utf8"),
85211
+ readStdin: () => readFileSync24(0, "utf8"),
84929
85212
  sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
84930
85213
  now: () => Date.now()
84931
85214
  };
@@ -84936,12 +85219,12 @@ var exports_pr = {};
84936
85219
  __export(exports_pr, {
84937
85220
  run: () => run15
84938
85221
  });
84939
- import { readFileSync as readFileSync24 } from "node:fs";
84940
- import path62 from "node:path";
85222
+ import { readFileSync as readFileSync25 } from "node:fs";
85223
+ import path63 from "node:path";
84941
85224
  function readBodyFile(io, file) {
84942
85225
  try {
84943
85226
  return {
84944
- body: file === "-" ? forgeDeps.readStdin() : readFileSync24(path62.resolve(io.cwd, file), "utf8")
85227
+ body: file === "-" ? forgeDeps.readStdin() : readFileSync25(path63.resolve(io.cwd, file), "utf8")
84945
85228
  };
84946
85229
  } catch {
84947
85230
  return `cannot read --body-file ${file}`;
@@ -85730,8 +86013,8 @@ var exports_git = {};
85730
86013
  __export(exports_git, {
85731
86014
  run: () => run17
85732
86015
  });
85733
- import { readFileSync as readFileSync25 } from "node:fs";
85734
- import path63 from "node:path";
86016
+ import { readFileSync as readFileSync26 } from "node:fs";
86017
+ import path64 from "node:path";
85735
86018
  function kindHint(cwd, kind) {
85736
86019
  let kinds = [...BRANCH_KINDS];
85737
86020
  try {
@@ -85835,7 +86118,7 @@ function commitMessage(parsed, io) {
85835
86118
 
85836
86119
  `);
85837
86120
  try {
85838
- return file === "-" ? readFileSync25(0, "utf8") : readFileSync25(path63.resolve(io.cwd, file), "utf8");
86121
+ return file === "-" ? readFileSync26(0, "utf8") : readFileSync26(path64.resolve(io.cwd, file), "utf8");
85839
86122
  } catch (error) {
85840
86123
  return {
85841
86124
  error: `cannot read -F ${file}: ${error instanceof Error ? error.message : String(error)}`
@@ -87245,7 +87528,7 @@ var init_stack2 = __esm(() => {
87245
87528
  // packages/workit-core/src/fanout-brief.ts
87246
87529
  import { createHash as createHash19 } from "node:crypto";
87247
87530
  import fs35 from "node:fs";
87248
- import path64 from "node:path";
87531
+ import path65 from "node:path";
87249
87532
  function workerSession(lead, slice, attempt) {
87250
87533
  const tail = attempt === null ? "" : `+try${attempt}`;
87251
87534
  const full = `${lead}-w-${slice}${tail}`;
@@ -87327,7 +87610,7 @@ function renderBrief(cwd, plan, input) {
87327
87610
  "STANDING:",
87328
87611
  ...standing.length ? standing.map((order) => ` - ${order.what}`) : [" - none recorded beyond this brief"],
87329
87612
  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)`,
87330
- ...exists && typeof made?.install === "string" && !fs35.existsSync(path64.join(planned, "node_modules")) ? [`INSTALL: \`${made.install}\` first: the main checkout's node_modules was not linked here`] : [],
87613
+ ...exists && typeof made?.install === "string" && !fs35.existsSync(path65.join(planned, "node_modules")) ? [`INSTALL: \`${made.install}\` first: the main checkout's node_modules was not linked here`] : [],
87331
87614
  ...identityLines(identity, minted),
87332
87615
  ...rules(mode, branch, slice.base, exists ? planned : null)
87333
87616
  ];
@@ -88068,7 +88351,7 @@ __export(exports_fanout, {
88068
88351
  run: () => run21
88069
88352
  });
88070
88353
  import fs36 from "node:fs";
88071
- import path65 from "node:path";
88354
+ import path66 from "node:path";
88072
88355
  function forgeFor(io, offline) {
88073
88356
  if (offline)
88074
88357
  return { forge: null, error: "--offline" };
@@ -88129,7 +88412,7 @@ function plan2(argv, io) {
88129
88412
  return usage4(io, "pass --trunk or --track, not both (--track picks the trunk)", PLAN_USAGE2);
88130
88413
  if (flags.positionals.length !== 1)
88131
88414
  return usage4(io, flags.positionals.length ? `unexpected argument ${flags.positionals[1]}` : "missing <plan.json>", PLAN_USAGE2);
88132
- const file = path65.resolve(io.cwd, flags.positionals[0]);
88415
+ const file = path66.resolve(io.cwd, flags.positionals[0]);
88133
88416
  let raw;
88134
88417
  try {
88135
88418
  raw = JSON.parse(fs36.readFileSync(file, "utf8"));
@@ -103670,7 +103953,7 @@ var init_ast = __esm(() => {
103670
103953
 
103671
103954
  // packages/workit-cli/src/test-audit/rules.ts
103672
103955
  import { builtinModules } from "node:module";
103673
- import path66 from "node:path";
103956
+ import path67 from "node:path";
103674
103957
  function testCallee(call) {
103675
103958
  let callee = call.callee;
103676
103959
  if (callee.type === "CallExpression")
@@ -104163,12 +104446,12 @@ function checkConstantsOnly(ctx, emit) {
104163
104446
  }
104164
104447
  function checkOverMocking(ctx, emit) {
104165
104448
  const { program } = ctx.parsed;
104166
- const unit = path66.basename(ctx.file).replace(/\.(?:[cm]?[jt]sx?)$/, "").replace(/\.(?:test|spec)$/, "");
104449
+ const unit = path67.basename(ctx.file).replace(/\.(?:[cm]?[jt]sx?)$/, "").replace(/\.(?:test|spec)$/, "");
104167
104450
  const mocked = find2(program, (node) => node.type === "CallExpression" && MODULE_MOCK.test(calleeName(node.callee) ?? "") && node.arguments[0]?.type === "StringLiteral");
104168
104451
  const internal = mocked.filter((call) => /^(?:\.|@\/|~\/)/.test(call.arguments[0].value));
104169
104452
  for (const call of mocked) {
104170
104453
  const spec = call.arguments[0].value;
104171
- const base = path66.basename(spec.replace(/\/index(?:\.[cm]?[jt]sx?)?$/, "")).replace(/\.(?:[cm]?[jt]sx?)$/, "");
104454
+ const base = path67.basename(spec.replace(/\/index(?:\.[cm]?[jt]sx?)?$/, "")).replace(/\.(?:[cm]?[jt]sx?)$/, "");
104172
104455
  if (base === unit)
104173
104456
  emit({
104174
104457
  rule: "over-mocking",
@@ -104557,8 +104840,8 @@ var init_rules = __esm(() => {
104557
104840
 
104558
104841
  // packages/workit-cli/src/test-audit/audit.ts
104559
104842
  import { spawnSync as spawnSync29 } from "node:child_process";
104560
- import { existsSync as existsSync24, readdirSync as readdirSync11, readFileSync as readFileSync26, statSync as statSync10 } from "node:fs";
104561
- import path67 from "node:path";
104843
+ import { existsSync as existsSync24, readdirSync as readdirSync13, readFileSync as readFileSync27, statSync as statSync10 } from "node:fs";
104844
+ import path68 from "node:path";
104562
104845
  function git7(cwd, args) {
104563
104846
  const run = spawnSync29("git", ["-c", "core.quotepath=off", ...args], {
104564
104847
  cwd,
@@ -104568,10 +104851,10 @@ function git7(cwd, args) {
104568
104851
  return { ok: run.status === 0, stdout: run.stdout ?? "" };
104569
104852
  }
104570
104853
  function walkTests(dir, out) {
104571
- for (const entry of readdirSync11(dir, { withFileTypes: true })) {
104854
+ for (const entry of readdirSync13(dir, { withFileTypes: true })) {
104572
104855
  if (entry.name.startsWith(".") && entry.name !== "." && entry.isDirectory())
104573
104856
  continue;
104574
- const full = path67.join(dir, entry.name);
104857
+ const full = path68.join(dir, entry.name);
104575
104858
  if (entry.isDirectory()) {
104576
104859
  if (!SKIP_DIRS.has(entry.name))
104577
104860
  walkTests(full, out);
@@ -104583,7 +104866,7 @@ function expandPaths(cwd, inputs) {
104583
104866
  const files = [];
104584
104867
  const missing = [];
104585
104868
  for (const input of inputs.length > 0 ? inputs : ["."]) {
104586
- const full = path67.resolve(cwd, input);
104869
+ const full = path68.resolve(cwd, input);
104587
104870
  if (!existsSync24(full))
104588
104871
  missing.push(input);
104589
104872
  else if (statSync10(full).isDirectory())
@@ -104620,11 +104903,11 @@ function changedLines(cwd, base) {
104620
104903
  for (let offset = 0;offset < count; offset += 1)
104621
104904
  lines.add(start + offset);
104622
104905
  }
104623
- changed.set(path67.join(root, file), lines);
104906
+ changed.set(path68.join(root, file), lines);
104624
104907
  }
104625
104908
  const untracked = git7(root, ["ls-files", "--others", "--exclude-standard", "-z"]);
104626
104909
  for (const file of untracked.stdout.split("\x00").filter(Boolean))
104627
- changed.set(path67.join(root, file), "all");
104910
+ changed.set(path68.join(root, file), "all");
104628
104911
  return changed;
104629
104912
  }
104630
104913
  function auditFiles(files, display) {
@@ -104637,7 +104920,7 @@ function auditFiles(files, display) {
104637
104920
  const shown = display(file);
104638
104921
  let parsed;
104639
104922
  try {
104640
- parsed = parseSource(readFileSync26(file, "utf8"), file);
104923
+ parsed = parseSource(readFileSync27(file, "utf8"), file);
104641
104924
  } catch (error) {
104642
104925
  parseErrors.push({
104643
104926
  file: shown,
@@ -104686,7 +104969,7 @@ function auditFiles(files, display) {
104686
104969
  durationMs: Math.round(performance.now() - started)
104687
104970
  };
104688
104971
  }
104689
- var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(path67.sep).join("/"), SEVERITY_ORDER, ruleIds;
104972
+ var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(path68.sep).join("/"), SEVERITY_ORDER, ruleIds;
104690
104973
  var init_audit = __esm(() => {
104691
104974
  init_ast();
104692
104975
  init_rules();
@@ -104702,21 +104985,21 @@ import { spawn as spawn2 } from "node:child_process";
104702
104985
  import {
104703
104986
  existsSync as existsSync25,
104704
104987
  lstatSync as lstatSync8,
104705
- mkdirSync as mkdirSync11,
104988
+ mkdirSync as mkdirSync12,
104706
104989
  mkdtempSync as mkdtempSync4,
104707
- readdirSync as readdirSync12,
104708
- readFileSync as readFileSync27,
104990
+ readdirSync as readdirSync14,
104991
+ readFileSync as readFileSync28,
104709
104992
  readlinkSync as readlinkSync3,
104710
104993
  realpathSync as realpathSync10,
104711
104994
  renameSync as renameSync7,
104712
104995
  rmSync as rmSync9,
104713
104996
  statSync as statSync11,
104714
104997
  symlinkSync,
104715
- writeFileSync as writeFileSync11,
104998
+ writeFileSync as writeFileSync12,
104716
104999
  copyFileSync as copyFileSync8
104717
105000
  } from "node:fs";
104718
105001
  import os22 from "node:os";
104719
- import path68 from "node:path";
105002
+ import path69 from "node:path";
104720
105003
  function mutantsFor(source, file, lines) {
104721
105004
  const parsed = parseSource(source, file);
104722
105005
  const out = [];
@@ -104789,7 +105072,7 @@ function relatedTests(source, testFiles) {
104789
105072
  for (const match of text.matchAll(SPECIFIER)) {
104790
105073
  const spec = match[1];
104791
105074
  if (spec.startsWith(".")) {
104792
- if (stripExt(path68.posix.join(path68.posix.dirname(file), spec)) === target)
105075
+ if (stripExt(path69.posix.join(path69.posix.dirname(file), spec)) === target)
104793
105076
  return true;
104794
105077
  } else if (spec.includes("/") && stripExt(spec).split("/").slice(-2).join("/") === tail)
104795
105078
  return true;
@@ -104801,7 +105084,7 @@ function removeStaleCopies(tmp = os22.tmpdir()) {
104801
105084
  let removed = 0;
104802
105085
  let names = [];
104803
105086
  try {
104804
- names = readdirSync12(tmp);
105087
+ names = readdirSync14(tmp);
104805
105088
  } catch {
104806
105089
  return 0;
104807
105090
  }
@@ -104809,12 +105092,12 @@ function removeStaleCopies(tmp = os22.tmpdir()) {
104809
105092
  for (const name of names) {
104810
105093
  if (!name.startsWith(TEMP_PREFIX))
104811
105094
  continue;
104812
- const dir = path68.join(tmp, name);
105095
+ const dir = path69.join(tmp, name);
104813
105096
  try {
104814
105097
  const stat = lstatSync8(dir);
104815
105098
  if (!stat.isDirectory() || uid !== undefined && stat.uid !== uid)
104816
105099
  continue;
104817
- const pid = Number(readFileSync27(path68.join(dir, PID_FILE), "utf8"));
105100
+ const pid = Number(readFileSync28(path69.join(dir, PID_FILE), "utf8"));
104818
105101
  if (Number.isInteger(pid) && pid > 0 && alive(pid))
104819
105102
  continue;
104820
105103
  } catch (error) {
@@ -104829,16 +105112,16 @@ function removeStaleCopies(tmp = os22.tmpdir()) {
104829
105112
  return removed;
104830
105113
  }
104831
105114
  function linkNodeModules(origin, target, repo, copy) {
104832
- mkdirSync11(target, { recursive: true });
104833
- for (const entry of readdirSync12(origin, { withFileTypes: true })) {
104834
- const from = path68.join(origin, entry.name);
104835
- const to = path68.join(target, entry.name);
105115
+ mkdirSync12(target, { recursive: true });
105116
+ for (const entry of readdirSync14(origin, { withFileTypes: true })) {
105117
+ const from = path69.join(origin, entry.name);
105118
+ const to = path69.join(target, entry.name);
104836
105119
  if (entry.name.startsWith("@") && entry.isDirectory()) {
104837
105120
  linkNodeModules(from, to, repo, copy);
104838
105121
  continue;
104839
105122
  }
104840
105123
  if (entry.name.startsWith(".") && entry.name !== ".bin" && entry.isDirectory()) {
104841
- mkdirSync11(to, { recursive: true });
105124
+ mkdirSync12(to, { recursive: true });
104842
105125
  continue;
104843
105126
  }
104844
105127
  if (entry.isSymbolicLink()) {
@@ -104848,9 +105131,9 @@ function linkNodeModules(origin, target, repo, copy) {
104848
105131
  } catch {
104849
105132
  continue;
104850
105133
  }
104851
- const relative = path68.relative(repo, real);
104852
- if (!relative.startsWith("..") && !path68.isAbsolute(relative) && !relative.split(path68.sep).includes("node_modules")) {
104853
- symlinkSync(path68.join(copy, relative), to, "junction");
105134
+ const relative = path69.relative(repo, real);
105135
+ if (!relative.startsWith("..") && !path69.isAbsolute(relative) && !relative.split(path69.sep).includes("node_modules")) {
105136
+ symlinkSync(path69.join(copy, relative), to, "junction");
104854
105137
  continue;
104855
105138
  }
104856
105139
  }
@@ -104866,7 +105149,7 @@ function copySymlink(repo, tree, from, to) {
104866
105149
  }
104867
105150
  const realRepo = realpathSync10(repo);
104868
105151
  if (real && inside5(realRepo, real)) {
104869
- symlinkSync(path68.relative(path68.dirname(to), path68.join(tree, path68.relative(realRepo, real))), to);
105152
+ symlinkSync(path69.relative(path69.dirname(to), path69.join(tree, path69.relative(realRepo, real))), to);
104870
105153
  return;
104871
105154
  }
104872
105155
  if (real && statSync11(real).isFile())
@@ -104875,23 +105158,23 @@ function copySymlink(repo, tree, from, to) {
104875
105158
  symlinkSync(readlinkSync3(from), to);
104876
105159
  }
104877
105160
  function writeInside(copy, file, content) {
104878
- const target = path68.join(copy, file);
105161
+ const target = path69.join(copy, file);
104879
105162
  try {
104880
105163
  const stat = lstatSync8(target);
104881
- if (!stat.isFile() || !inside5(realpathSync10(copy), realpathSync10(path68.dirname(target))))
105164
+ if (!stat.isFile() || !inside5(realpathSync10(copy), realpathSync10(path69.dirname(target))))
104882
105165
  return false;
104883
105166
  } catch {
104884
105167
  return false;
104885
105168
  }
104886
105169
  const temp = `${target}.workit-mutant-${process.pid}`;
104887
- writeFileSync11(temp, content);
105170
+ writeFileSync12(temp, content);
104888
105171
  renameSync7(temp, target);
104889
105172
  return true;
104890
105173
  }
104891
105174
  function copyWorkingTree(repo) {
104892
- const dir = mkdtempSync4(path68.join(os22.tmpdir(), TEMP_PREFIX));
104893
- writeFileSync11(path68.join(dir, PID_FILE), String(process.pid));
104894
- const tree = path68.join(dir, "tree");
105175
+ const dir = mkdtempSync4(path69.join(os22.tmpdir(), TEMP_PREFIX));
105176
+ writeFileSync12(path69.join(dir, PID_FILE), String(process.pid));
105177
+ const tree = path69.join(dir, "tree");
104895
105178
  const head = git7(repo, ["rev-parse", "--verify", "--quiet", "HEAD"]).stdout.trim();
104896
105179
  if (head && git7(dir, ["clone", "-q", "--shared", "--no-checkout", repo, tree]).ok) {
104897
105180
  const branch = git7(repo, ["symbolic-ref", "--quiet", "--short", "HEAD"]).stdout.trim();
@@ -104902,35 +105185,35 @@ function copyWorkingTree(repo) {
104902
105185
  git7(tree, ["update-ref", "--no-deref", "HEAD", head]);
104903
105186
  git7(tree, ["reset", "-q"]);
104904
105187
  } else
104905
- mkdirSync11(tree, { recursive: true });
105188
+ mkdirSync12(tree, { recursive: true });
104906
105189
  const listed = git7(repo, ["ls-files", "-co", "--exclude-standard", "-z"]).stdout.split("\x00");
104907
105190
  const dirs = new Set([""]);
104908
105191
  for (const relative of listed) {
104909
105192
  if (!relative)
104910
105193
  continue;
104911
- const from = path68.join(repo, relative);
105194
+ const from = path69.join(repo, relative);
104912
105195
  let stat;
104913
105196
  try {
104914
105197
  stat = lstatSync8(from);
104915
105198
  } catch {
104916
105199
  continue;
104917
105200
  }
104918
- const to = path68.join(tree, relative);
104919
- mkdirSync11(path68.dirname(to), { recursive: true });
105201
+ const to = path69.join(tree, relative);
105202
+ mkdirSync12(path69.dirname(to), { recursive: true });
104920
105203
  if (stat.isSymbolicLink())
104921
105204
  copySymlink(repo, tree, from, to);
104922
105205
  else if (stat.isFile())
104923
105206
  copyFileSync8(from, to);
104924
- let parent = path68.dirname(relative);
105207
+ let parent = path69.dirname(relative);
104925
105208
  while (parent !== "." && !dirs.has(parent)) {
104926
105209
  dirs.add(parent);
104927
- parent = path68.dirname(parent);
105210
+ parent = path69.dirname(parent);
104928
105211
  }
104929
105212
  }
104930
105213
  for (const parent of dirs) {
104931
- const modules = path68.join(repo, parent, "node_modules");
104932
- if (existsSync25(modules) && !existsSync25(path68.join(tree, parent, "node_modules")))
104933
- linkNodeModules(modules, path68.join(tree, parent, "node_modules"), repo, tree);
105214
+ const modules = path69.join(repo, parent, "node_modules");
105215
+ if (existsSync25(modules) && !existsSync25(path69.join(tree, parent, "node_modules")))
105216
+ linkNodeModules(modules, path69.join(tree, parent, "node_modules"), repo, tree);
104934
105217
  }
104935
105218
  return { dir, tree };
104936
105219
  }
@@ -104969,20 +105252,20 @@ async function runMutation(options) {
104969
105252
  const tracked = git7(repo, ["ls-files", "-co", "--exclude-standard", "-z"]).stdout.split("\x00").filter(Boolean);
104970
105253
  const testFiles = tracked.filter((file) => TEST_FILE.test(file)).map((file) => {
104971
105254
  try {
104972
- return { file, text: readFileSync27(path68.join(repo, file), "utf8") };
105255
+ return { file, text: readFileSync28(path69.join(repo, file), "utf8") };
104973
105256
  } catch {
104974
105257
  return { file, text: "" };
104975
105258
  }
104976
105259
  });
104977
105260
  const candidates = [];
104978
105261
  for (const [absolute, lines] of [...options.changed].toSorted(([a], [b]) => a.localeCompare(b))) {
104979
- const relative = toPosix(path68.relative(repo, absolute));
105262
+ const relative = toPosix(path69.relative(repo, absolute));
104980
105263
  if (!CODE_FILE.test(relative) || TEST_FILE.test(relative) || relative.endsWith(".d.ts"))
104981
105264
  continue;
104982
105265
  if (NOT_SOURCE.test(relative) || !existsSync25(absolute))
104983
105266
  continue;
104984
105267
  try {
104985
- candidates.push(...mutantsFor(readFileSync27(absolute, "utf8"), relative, lines));
105268
+ candidates.push(...mutantsFor(readFileSync28(absolute, "utf8"), relative, lines));
104986
105269
  } catch {}
104987
105270
  }
104988
105271
  const mutants = candidates.map((mutant, index) => ({ ...mutant, id: index + 1 }));
@@ -104990,9 +105273,9 @@ async function runMutation(options) {
104990
105273
  for (const mutant of mutants)
104991
105274
  if (!related.has(mutant.file))
104992
105275
  related.set(mutant.file, relatedTests(mutant.file, testFiles));
104993
- const cwdRelative = path68.relative(repo, options.cwd);
105276
+ const cwdRelative = path69.relative(repo, options.cwd);
104994
105277
  const asArg = (file) => {
104995
- const relative = toPosix(path68.relative(cwdRelative, file));
105278
+ const relative = toPosix(path69.relative(cwdRelative, file));
104996
105279
  return shellQuote(relative.startsWith(".") ? relative : `./${relative}`);
104997
105280
  };
104998
105281
  const commandFor = (tests) => options.command.replaceAll("{files}", () => tests.map(asArg).join(" "));
@@ -105028,7 +105311,7 @@ async function runMutation(options) {
105028
105311
  return finish3(options, 0, results, counts, started);
105029
105312
  removeStaleCopies();
105030
105313
  const { dir: copyDir, tree: copy } = copyWorkingTree(repo);
105031
- const copyCwd = path68.join(copy, cwdRelative);
105314
+ const copyCwd = path69.join(copy, cwdRelative);
105032
105315
  let current = null;
105033
105316
  const restore = () => {
105034
105317
  if (current)
@@ -105063,7 +105346,7 @@ async function runMutation(options) {
105063
105346
  record({ ...mutant, status: "skipped", durationMs: 0, tests, reason: "budget" });
105064
105347
  continue;
105065
105348
  }
105066
- const original = readFileSync27(path68.join(copy, mutant.file), "utf8");
105349
+ const original = readFileSync28(path69.join(copy, mutant.file), "utf8");
105067
105350
  const mutated = original.slice(0, mutant.start) + mutant.replacement + original.slice(mutant.end);
105068
105351
  current = { file: mutant.file, original };
105069
105352
  if (!writeInside(copy, mutant.file, mutated)) {
@@ -105120,8 +105403,8 @@ var NOT_SOURCE, FLIPS, isStringy = (node) => node.type === "StringLiteral" || no
105120
105403
  return error.code === "EPERM";
105121
105404
  }
105122
105405
  }, inside5 = (root, file) => {
105123
- const relative = path68.relative(root, file);
105124
- return relative === "" || !relative.startsWith("..") && !path68.isAbsolute(relative);
105406
+ const relative = path69.relative(root, file);
105407
+ return relative === "" || !relative.startsWith("..") && !path69.isAbsolute(relative);
105125
105408
  }, active, killTree = (child) => {
105126
105409
  try {
105127
105410
  if (child.pid && process.platform !== "win32")
@@ -105170,7 +105453,7 @@ __export(exports_test_audit, {
105170
105453
  run: () => run23
105171
105454
  });
105172
105455
  import { existsSync as existsSync26 } from "node:fs";
105173
- import path69 from "node:path";
105456
+ import path70 from "node:path";
105174
105457
  function parse8(argv) {
105175
105458
  const options = {
105176
105459
  paths: [],
@@ -105275,8 +105558,8 @@ async function run23(argv, io) {
105275
105558
  return emit(io, fail2("invalid_input", `${options}
105276
105559
  usage: ${USAGE15}`));
105277
105560
  const top = git7(io.cwd, ["rev-parse", "--show-toplevel"]);
105278
- const repo = top.ok ? path69.resolve(top.stdout.trim()) : null;
105279
- const display = (file) => toPosix(path69.relative(io.cwd, file) || file);
105561
+ const repo = top.ok ? path70.resolve(top.stdout.trim()) : null;
105562
+ const display = (file) => toPosix(path70.relative(io.cwd, file) || file);
105280
105563
  let base = null;
105281
105564
  let changed = null;
105282
105565
  if (options.diff || options.mutate) {
@@ -105414,8 +105697,8 @@ var exports_youtrack = {};
105414
105697
  __export(exports_youtrack, {
105415
105698
  run: () => run25
105416
105699
  });
105417
- import { readFileSync as readFileSync28 } from "node:fs";
105418
- import path70 from "node:path";
105700
+ import { readFileSync as readFileSync29 } from "node:fs";
105701
+ import path71 from "node:path";
105419
105702
  async function run25(argv, io) {
105420
105703
  const [sub, ...rest] = argv;
105421
105704
  if (sub !== "note" && sub !== "time" && sub !== "meeting")
@@ -105461,7 +105744,7 @@ async function run25(argv, io) {
105461
105744
  let markdown = flags.values.markdown ?? "";
105462
105745
  if (flags.values.file)
105463
105746
  try {
105464
- markdown = readFileSync28(path70.resolve(io.cwd, flags.values.file), "utf8");
105747
+ markdown = readFileSync29(path71.resolve(io.cwd, flags.values.file), "utf8");
105465
105748
  } catch (error) {
105466
105749
  return usage4(io, `cannot read ${flags.values.file}: ${String(error)}`, USAGE17);
105467
105750
  }
@@ -105529,8 +105812,8 @@ var exports_changelog = {};
105529
105812
  __export(exports_changelog, {
105530
105813
  run: () => run26
105531
105814
  });
105532
- import { readFileSync as readFileSync29 } from "node:fs";
105533
- import path71 from "node:path";
105815
+ import { readFileSync as readFileSync30 } from "node:fs";
105816
+ import path72 from "node:path";
105534
105817
  async function run26(argv, io) {
105535
105818
  const [sub, ...rest] = argv;
105536
105819
  if (sub !== "apply")
@@ -105576,7 +105859,7 @@ async function run26(argv, io) {
105576
105859
  ]);
105577
105860
  }
105578
105861
  var USAGE18 = "workit changelog apply (--entries <JSON|@file|-> | --normalize-only) [--path CHANGELOG.md] [--preview]", readEntries = (raw, cwd) => {
105579
- const text = raw === "-" ? readFileSync29(0, "utf8") : raw.startsWith("@") ? readFileSync29(path71.resolve(cwd, raw.slice(1)), "utf8") : raw;
105862
+ const text = raw === "-" ? readFileSync30(0, "utf8") : raw.startsWith("@") ? readFileSync30(path72.resolve(cwd, raw.slice(1)), "utf8") : raw;
105580
105863
  return JSON.parse(text);
105581
105864
  };
105582
105865
  var init_changelog2 = __esm(() => {
@@ -105592,7 +105875,7 @@ __export(exports_handoff, {
105592
105875
  run: () => run27
105593
105876
  });
105594
105877
  import fs37 from "node:fs";
105595
- import path72 from "node:path";
105878
+ import path73 from "node:path";
105596
105879
  import { parseArgs as parseArgs2 } from "node:util";
105597
105880
  function render3(brief) {
105598
105881
  const lines = [
@@ -105632,9 +105915,9 @@ function bounded(brief, cwd) {
105632
105915
  let file = null;
105633
105916
  if (store.ok)
105634
105917
  try {
105635
- const dir = path72.join(store.value.root, "handoff");
105918
+ const dir = path73.join(store.value.root, "handoff");
105636
105919
  fs37.mkdirSync(dir, { recursive: true });
105637
- file = path72.join(dir, `${(brief.branch ?? "detached").replaceAll(/[^\w.-]+/gu, "-")}.txt`);
105920
+ file = path73.join(dir, `${(brief.branch ?? "detached").replaceAll(/[^\w.-]+/gu, "-")}.txt`);
105638
105921
  fs37.writeFileSync(file, `${[...body, ...tail].join(`
105639
105922
  `)}
105640
105923
  `, { mode: 384 });
@@ -105706,7 +105989,7 @@ var init_handoff = __esm(() => {
105706
105989
  // packages/workit-cli/src/main.ts
105707
105990
  init_host_session();
105708
105991
  init_package();
105709
- import path73 from "node:path";
105992
+ import path74 from "node:path";
105710
105993
 
105711
105994
  // packages/workit-cli/src/verbs/registry.ts
105712
105995
  var TASK_FAMILY_NAMES = [
@@ -106612,7 +106895,7 @@ var defaultIo = (json) => ({
106612
106895
  });
106613
106896
  async function main(argv, overrides = {}, options = {}) {
106614
106897
  const parsed = parseGlobals(argv);
106615
- const cwd = path73.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
106898
+ const cwd = path74.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
106616
106899
  const io = { ...defaultIo(parsed.json), ...overrides, json: parsed.json, cwd };
106617
106900
  if (parsed.error)
106618
106901
  return emit(io, fail2("invalid_input", parsed.error));