@brainervirus/workit-cli 8.27.0 → 8.28.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +333 -156
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -8412,11 +8412,15 @@ var withReleaseTracks = (workspaceRoot, policy) => {
8412
8412
  correction,
8413
8413
  error: `commit_style: commit subject ${JSON.stringify(attempted)} violates ${source} ${policy.preset} policy; ${correction}`
8414
8414
  };
8415
+ }, rethrowRuntimeBug = (error) => {
8416
+ if (error instanceof TypeError || error instanceof ReferenceError)
8417
+ throw error;
8415
8418
  }, validateBranchNameFor = (workspaceRoot, name) => {
8416
8419
  try {
8417
8420
  const resolved = branchPolicySnapshotFor(workspaceRoot);
8418
8421
  return validateBranchNamePolicy(name, resolved.namePolicy, resolved.source);
8419
8422
  } catch (error) {
8423
+ rethrowRuntimeBug(error);
8420
8424
  const correction = "repair or select a valid workspace policy before creating a branch";
8421
8425
  return {
8422
8426
  ok: false,
@@ -8434,6 +8438,7 @@ var withReleaseTracks = (workspaceRoot, policy) => {
8434
8438
  const resolved = commitPolicySnapshotFor(workspaceRoot);
8435
8439
  return validateCommitMessagePolicy(message, resolved.policy, resolved.source);
8436
8440
  } catch (error) {
8441
+ rethrowRuntimeBug(error);
8437
8442
  const correction = "repair or select a valid workspace policy before committing";
8438
8443
  return {
8439
8444
  ok: false,
@@ -9240,7 +9245,7 @@ var package_default;
9240
9245
  var init_package = __esm(() => {
9241
9246
  package_default = {
9242
9247
  name: "@brainervirus/workit-cli",
9243
- version: "8.27.0",
9248
+ version: "8.28.1",
9244
9249
  private: false,
9245
9250
  description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
9246
9251
  keywords: [
@@ -9278,13 +9283,13 @@ var init_package = __esm(() => {
9278
9283
  },
9279
9284
  dependencies: {
9280
9285
  "@babel/parser": "7.29.9",
9281
- "@brainervirus/workit-cursor": "^8.27.0",
9286
+ "@brainervirus/workit-cursor": "^8.28.1",
9282
9287
  "@inkjs/ui": "2.0.0",
9283
9288
  ink: "7.1.1",
9284
9289
  react: "19.2.8"
9285
9290
  },
9286
9291
  devDependencies: {
9287
- "@brainervirus/workit-core": "^8.27.0"
9292
+ "@brainervirus/workit-core": "^8.28.1"
9288
9293
  },
9289
9294
  engines: {
9290
9295
  node: ">=24"
@@ -16358,7 +16363,7 @@ var str2 = (d, values) => ({
16358
16363
  description: typeof description === "string" ? description : "",
16359
16364
  paths: ["."],
16360
16365
  exclusions: []
16361
- }), LISTS, ENVELOPE;
16366
+ }), LISTS, ENVELOPE, NOT_FLAT;
16362
16367
  var init_operation_input = __esm(() => {
16363
16368
  init_task_contract();
16364
16369
  scopeFields = {
@@ -16480,6 +16485,7 @@ var init_operation_input = __esm(() => {
16480
16485
  "expectedWorkspaceRevision",
16481
16486
  "judgment"
16482
16487
  ]);
16488
+ NOT_FLAT = new Set(["schemaVersion", "action", "workspaceId"]);
16483
16489
  });
16484
16490
 
16485
16491
  // packages/workit-core/src/core/policy/judgment.ts
@@ -65551,6 +65557,21 @@ var MODEL_ROLES, MODEL_TIERS, HOST_KEYS, BUILT_IN_CLAUDE_CODE, isObject9 = (valu
65551
65557
  }
65552
65558
  }
65553
65559
  return issues;
65560
+ }, roleForAgentType = (agentType, prompt) => {
65561
+ switch (agentType) {
65562
+ case "workit:implementer": {
65563
+ const tier = typeof prompt === "string" ? /^[ \t]*TIER:[ \t]*(mundane|standard|hard)\b/im.exec(prompt)?.[1] : undefined;
65564
+ return { role: "implementer", tier: tier?.toLowerCase() ?? "standard" };
65565
+ }
65566
+ case "workit:verifier":
65567
+ return { role: "verifier" };
65568
+ case "workit:reviewer":
65569
+ return { role: "reviewer" };
65570
+ case "Explore":
65571
+ return { role: "explore" };
65572
+ default:
65573
+ return null;
65574
+ }
65554
65575
  };
65555
65576
  var init_role_models = __esm(() => {
65556
65577
  init_workspaces();
@@ -67025,6 +67046,21 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67025
67046
  return null;
67026
67047
  dir = parent;
67027
67048
  }
67049
+ }, listClaudeProcesses = () => {
67050
+ const r = spawnSync16("ps", ["-eo", "pid=,lstart=,args="], { encoding: "utf8", timeout: 5000 });
67051
+ if (r.status !== 0 || typeof r.stdout !== "string")
67052
+ return null;
67053
+ const found = [];
67054
+ for (const row of r.stdout.split(`
67055
+ `)) {
67056
+ const m = /^\s*(\d+)\s+(\w{3}\s+\w{3}\s+\d+\s+[\d:]+\s+\d{4})\s+(.*)$/.exec(row);
67057
+ if (!m || !/^(\S*\/)?claude(\s|$)/.test(m[3]))
67058
+ continue;
67059
+ const startedMs = Date.parse(m[2]);
67060
+ if (Number.isFinite(startedMs))
67061
+ found.push({ pid: Number(m[1]), startedMs, args: m[3] });
67062
+ }
67063
+ return found;
67028
67064
  }, resolve = (options) => {
67029
67065
  const env = options.env ?? process.env;
67030
67066
  const home = options.home ?? env.HOME ?? os12.homedir();
@@ -67052,7 +67088,8 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
67052
67088
  env,
67053
67089
  installer: options.installer ?? false,
67054
67090
  cliVersion: options.cliVersion ?? null,
67055
- scopeProbe: options.scopeProbe ?? probeScope
67091
+ scopeProbe: options.scopeProbe ?? probeScope,
67092
+ claudeProcesses: options.claudeProcesses ?? listClaudeProcesses
67056
67093
  };
67057
67094
  }, readJson = (p) => {
67058
67095
  try {
@@ -68892,6 +68929,68 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
68892
68929
  fix: repair,
68893
68930
  registryProbed
68894
68931
  };
68932
+ }, checkClaudeSessionPlugin = (res) => {
68933
+ const id = "claude_session_plugin";
68934
+ if (process.platform === "win32")
68935
+ return {
68936
+ id,
68937
+ status: "info",
68938
+ detail: "running Claude Code sessions are not checked on Windows"
68939
+ };
68940
+ const installs = claudeWorkitInstalls(res.home, res.env, res.cwd).filter((install) => install.version);
68941
+ if (installs.length === 0)
68942
+ return {
68943
+ id,
68944
+ status: "info",
68945
+ detail: "no Workit Claude Code plugin install recorded — skipping"
68946
+ };
68947
+ const registry = readJson(path38.join(claudeConfigDir(res.home, res.env), "plugins", "installed_plugins.json"));
68948
+ const recorded = (install) => {
68949
+ const entries = registry?.plugins?.[install.id];
68950
+ const entry = Array.isArray(entries) ? entries.find((e) => e?.installPath === install.installPath) : null;
68951
+ for (const stamp of [entry?.lastUpdated, entry?.installedAt]) {
68952
+ const ms = typeof stamp === "string" ? Date.parse(stamp) : NaN;
68953
+ if (Number.isFinite(ms))
68954
+ return ms;
68955
+ }
68956
+ try {
68957
+ return statSync6(install.installPath).mtimeMs;
68958
+ } catch {
68959
+ return null;
68960
+ }
68961
+ };
68962
+ const latest = installs.map((install) => ({ install, at: recorded(install) })).filter((one) => one.at !== null).toSorted((a, b) => b.at - a.at)[0];
68963
+ if (!latest)
68964
+ return {
68965
+ id,
68966
+ status: "info",
68967
+ detail: "no install time recorded for the Workit plugin — skipping"
68968
+ };
68969
+ const running = res.claudeProcesses();
68970
+ if (running === null)
68971
+ return {
68972
+ id,
68973
+ status: "info",
68974
+ detail: "could not list running claude processes (ps) — skipping"
68975
+ };
68976
+ const stale = running.filter((proc) => proc.startedMs < latest.at);
68977
+ if (stale.length === 0)
68978
+ return {
68979
+ id,
68980
+ status: "info",
68981
+ detail: `${running.length} running claude process(es), none started before Workit ${latest.install.version} was installed`
68982
+ };
68983
+ const sessionOf = (args) => /(?:--resume|--session-id|-r)[ =]([0-9a-f]{8}-[0-9a-f-]{27})/i.exec(args)?.[1] ?? null;
68984
+ const rows = stale.map((proc) => {
68985
+ const session = sessionOf(proc.args);
68986
+ return `pid ${proc.pid} started ${new Date(proc.startedMs).toISOString()}${session ? ` (session ${session})` : ""}`;
68987
+ });
68988
+ const first = stale.map((proc) => sessionOf(proc.args)).find((one) => one);
68989
+ return {
68990
+ id,
68991
+ status: "warn",
68992
+ detail: `started before Workit ${latest.install.version} was installed: ${rows.join("; ")}; quit and start \`claude --resume ${first ?? "<session id>"}\` to load it (\`/resume\` keeps the old plugin)`
68993
+ };
68895
68994
  }, HOOK_ISSUED_MARKER = "workit-issued-sessions/3", hookRecordsIssued = (root) => {
68896
68995
  let files;
68897
68996
  try {
@@ -69093,6 +69192,7 @@ var init_doctor = __esm(() => {
69093
69192
  checkPiExtension,
69094
69193
  checkOpencodeVersion,
69095
69194
  checkClaudePlugin,
69195
+ checkClaudeSessionPlugin,
69096
69196
  checkHookIssuedSessions,
69097
69197
  checkWorkitOnPath,
69098
69198
  checkAssets,
@@ -77403,6 +77503,9 @@ var exports_models = {};
77403
77503
  __export(exports_models, {
77404
77504
  run: () => run13
77405
77505
  });
77506
+ import { existsSync as existsSync21, readdirSync as readdirSync10, readFileSync as readFileSync21, statSync as statSync9 } from "node:fs";
77507
+ import os21 from "node:os";
77508
+ import path51 from "node:path";
77406
77509
  async function run13(argv, io) {
77407
77510
  const [sub, ...args] = argv.filter((arg) => arg !== "--json");
77408
77511
  if (sub !== "show")
@@ -77410,13 +77513,27 @@ async function run13(argv, io) {
77410
77513
  const role = flag3(args, "--role");
77411
77514
  const tier = flag3(args, "--tier");
77412
77515
  const hostFlag = flag3(args, "--host");
77413
- for (const value of [role, tier, hostFlag])
77516
+ const daysFlag = flag3(args, "--days");
77517
+ for (const value of [role, tier, hostFlag, daysFlag])
77414
77518
  if (value instanceof Error)
77415
77519
  return emit(io, fail2("invalid_input", value.message));
77416
77520
  if (role && !MODEL_ROLES.includes(role))
77417
77521
  return emit(io, fail2("invalid_input", `unknown role ${role}: ${MODEL_ROLES.join(", ")}`));
77418
77522
  if (tier && !MODEL_TIERS.includes(tier))
77419
77523
  return emit(io, fail2("invalid_input", `unknown tier ${tier}: ${MODEL_TIERS.join(", ")}`));
77524
+ const days = daysFlag === null ? 7 : Number(daysFlag);
77525
+ if (!Number.isFinite(days) || days <= 0)
77526
+ return emit(io, fail2("invalid_input", "--days needs a positive number"));
77527
+ if (args.includes("--report")) {
77528
+ const report = usageReport(io.cwd, io.env, days);
77529
+ return emit(io, ok2(report), (data) => [
77530
+ `subagent models over the last ${data.days} days (${data.agents} agents)`,
77531
+ ...Object.entries(data.types).flatMap(([type, use]) => [
77532
+ ` ${type}${use.role ? ` (role ${use.role}, default ${use.defaults.join("/") || "host default"})` : ""}: ${Object.entries(use.models).map(([model, count]) => `${model} x${count}`).join(", ")}`,
77533
+ ...use.flagged.map((model) => ` flag: ran on ${model}, not the role default`)
77534
+ ])
77535
+ ]);
77536
+ }
77420
77537
  const envHost = actorFromEnv(io.env).host;
77421
77538
  const host = hostFlag ?? (envHost === "cli" ? "claude_code" : envHost);
77422
77539
  const row = (selector) => resolveRoleModel(io.cwd, selector, host) ?? { model: null, effort: null, source: "none" };
@@ -77439,13 +77556,73 @@ async function run13(argv, io) {
77439
77556
  ...(data.issues ?? []).map((issue) => `note: ${issue}`)
77440
77557
  ]);
77441
77558
  }
77442
- var USAGE6 = "workit models show [--role <role>] [--tier <tier>] [--host <host>] [--json]", flag3 = (argv, name) => {
77559
+ var USAGE6 = "workit models show [--role <role>] [--tier <tier>] [--host <host>] [--report [--days <n>]] [--json]", flag3 = (argv, name) => {
77443
77560
  const at = argv.findIndex((arg) => arg === name || arg.startsWith(`${name}=`));
77444
77561
  if (at < 0)
77445
77562
  return null;
77446
77563
  const value = argv[at].includes("=") ? argv[at].slice(name.length + 1) : argv[at + 1];
77447
77564
  return value && !value.startsWith("--") ? value : new Error(`${name} needs a value`);
77448
- }, line2 = (label, entry) => ` ${label}: ${entry.model ? `${entry.model}${entry.effort ? ` (effort ${entry.effort})` : ""} [${entry.source}]` : "host default (nothing configured)"}`;
77565
+ }, line2 = (label, entry) => ` ${label}: ${entry.model ? `${entry.model}${entry.effort ? ` (effort ${entry.effort})` : ""} [${entry.source}]` : "host default (nothing configured)"}`, modelsOf = (file) => {
77566
+ const found = new Set;
77567
+ let text = "";
77568
+ try {
77569
+ text = readFileSync21(file, "utf8");
77570
+ } catch {
77571
+ return found;
77572
+ }
77573
+ for (const row of text.split(`
77574
+ `))
77575
+ if (row.includes('"type":"assistant"'))
77576
+ try {
77577
+ const model = JSON.parse(row).message?.model;
77578
+ if (typeof model === "string" && model && !model.startsWith("<"))
77579
+ found.add(model);
77580
+ } catch {}
77581
+ return found;
77582
+ }, matches3 = (ran, configured) => ran.toLowerCase().includes(configured.toLowerCase()), usageReport = (cwd, env, days) => {
77583
+ const projects = path51.join(env.CLAUDE_CONFIG_DIR || path51.join(env.HOME || os21.homedir(), ".claude"), "projects");
77584
+ const since = Date.now() - days * 86400000;
77585
+ const types = {};
77586
+ let agents = 0;
77587
+ const dirs = (dir) => {
77588
+ try {
77589
+ return readdirSync10(dir).map((name) => path51.join(dir, name));
77590
+ } catch {
77591
+ return [];
77592
+ }
77593
+ };
77594
+ for (const project of dirs(projects))
77595
+ for (const session of dirs(project))
77596
+ for (const meta of dirs(path51.join(session, "subagents")).filter((f) => f.endsWith(".meta.json"))) {
77597
+ try {
77598
+ if (statSync9(meta).mtimeMs < since)
77599
+ continue;
77600
+ const agentType = JSON.parse(readFileSync21(meta, "utf8")).agentType;
77601
+ const transcript = meta.replace(/\.meta\.json$/, ".jsonl");
77602
+ if (typeof agentType !== "string" || !existsSync21(transcript))
77603
+ continue;
77604
+ const ran = modelsOf(transcript);
77605
+ if (!ran.size)
77606
+ continue;
77607
+ agents += 1;
77608
+ const selector = roleForAgentType(agentType);
77609
+ const entry = types[agentType] ??= {
77610
+ role: selector?.role ?? null,
77611
+ defaults: selector ? [
77612
+ ...new Set((selector.role === "implementer" ? MODEL_TIERS.map((tier) => ({ ...selector, tier })) : [selector]).flatMap((one) => resolveRoleModel(cwd, one, "claude_code")?.model ?? []))
77613
+ ] : [],
77614
+ models: {},
77615
+ flagged: []
77616
+ };
77617
+ for (const model of ran) {
77618
+ entry.models[model] = (entry.models[model] ?? 0) + 1;
77619
+ if (entry.models[model] === 1 && entry.defaults.length && !entry.defaults.some((d) => matches3(model, d)))
77620
+ entry.flagged.push(model);
77621
+ }
77622
+ } catch {}
77623
+ }
77624
+ return { days, agents, types };
77625
+ };
77449
77626
  var init_models = __esm(() => {
77450
77627
  init_role_models();
77451
77628
  init_ledger();
@@ -77561,8 +77738,8 @@ var success2 = (data) => ({ ok: true, data }), failure3 = (code, error, unblock)
77561
77738
 
77562
77739
  // packages/workit-core/src/git/ops.ts
77563
77740
  import { spawnSync as spawnSync20 } from "node:child_process";
77564
- import { existsSync as existsSync21, readFileSync as readFileSync21 } from "node:fs";
77565
- import path51 from "node:path";
77741
+ import { existsSync as existsSync22, readFileSync as readFileSync22 } from "node:fs";
77742
+ import path52 from "node:path";
77566
77743
  function operationInProgress(cwd) {
77567
77744
  const markers = [
77568
77745
  ["rebase-merge", "rebase"],
@@ -77575,18 +77752,18 @@ function operationInProgress(cwd) {
77575
77752
  if (!run.ok)
77576
77753
  return null;
77577
77754
  const found = run.stdout.split(`
77578
- `).map((line) => path51.resolve(cwd, line.trim()));
77755
+ `).map((line) => path52.resolve(cwd, line.trim()));
77579
77756
  const conflicted = () => git5(cwd, ["ls-files", "-u"]).stdout.trim() !== "";
77580
77757
  for (const [index, [, operation]] of markers.entries()) {
77581
77758
  const marker = found[index];
77582
- if (!marker || !existsSync21(marker))
77759
+ if (!marker || !existsSync22(marker))
77583
77760
  continue;
77584
- if (index === 1 && existsSync21(path51.join(marker, "applying")))
77761
+ if (index === 1 && existsSync22(path52.join(marker, "applying")))
77585
77762
  return { operation: "am", commitAllowed: false, branch: null };
77586
- if (index === 0 && existsSync21(path51.join(marker, "amend")) && !conflicted()) {
77763
+ if (index === 0 && existsSync22(path52.join(marker, "amend")) && !conflicted()) {
77587
77764
  let headName = "";
77588
77765
  try {
77589
- headName = readFileSync21(path51.join(marker, "head-name"), "utf8").trim();
77766
+ headName = readFileSync22(path52.join(marker, "head-name"), "utf8").trim();
77590
77767
  } catch {}
77591
77768
  const branch = headName.startsWith("refs/heads/") ? headName.slice("refs/heads/".length) : null;
77592
77769
  return { operation, commitAllowed: branch !== null, branch };
@@ -77914,7 +78091,7 @@ function gitCommit(cwd, input) {
77914
78091
  if (paths.some((value) => value.startsWith("-") || !value.trim()))
77915
78092
  return failure3("invalid_input", "paths must not be empty or start with -");
77916
78093
  const tracked = new Set(nulList(git5(cwd, ["ls-files", "-z", "--", ...paths]).stdout));
77917
- const addable = paths.filter((value) => existsSync21(path51.resolve(cwd, value)) || [...tracked].some((file) => file === value || file.startsWith(`${value}/`)));
78094
+ const addable = paths.filter((value) => existsSync22(path52.resolve(cwd, value)) || [...tracked].some((file) => file === value || file.startsWith(`${value}/`)));
77918
78095
  if (addable.length) {
77919
78096
  const added = git5(cwd, ["add", "-A", "--", ...addable]);
77920
78097
  if (!added.ok)
@@ -78441,12 +78618,12 @@ var init_ops = __esm(() => {
78441
78618
 
78442
78619
  // packages/workit-core/src/verdict-cover.ts
78443
78620
  import fs26 from "node:fs";
78444
- import path52 from "node:path";
78621
+ import path53 from "node:path";
78445
78622
  function chainsAbove(cwd, branch) {
78446
78623
  const root = storeRoot(cwd);
78447
78624
  if (!root.ok)
78448
78625
  return [];
78449
- const dir = path52.join(root.value.root, "stacks");
78626
+ const dir = path53.join(root.value.root, "stacks");
78450
78627
  let names = [];
78451
78628
  try {
78452
78629
  names = fs26.readdirSync(dir).filter((name) => name.endsWith(".json"));
@@ -78457,7 +78634,7 @@ function chainsAbove(cwd, branch) {
78457
78634
  for (const name of names.toSorted()) {
78458
78635
  let parsed;
78459
78636
  try {
78460
- parsed = JSON.parse(fs26.readFileSync(path52.join(dir, name), "utf8"));
78637
+ parsed = JSON.parse(fs26.readFileSync(path53.join(dir, name), "utf8"));
78461
78638
  } catch {
78462
78639
  continue;
78463
78640
  }
@@ -78552,10 +78729,10 @@ var init_pr_lane = __esm(() => {
78552
78729
 
78553
78730
  // packages/workit-core/src/forge/reruns.ts
78554
78731
  import fs27 from "node:fs";
78555
- import path53 from "node:path";
78732
+ import path54 from "node:path";
78556
78733
  function rerunLogPath(cwd) {
78557
78734
  const common = gitCommonDir(cwd);
78558
- return common ? path53.join(common, "workit", "ci-reruns.jsonl") : null;
78735
+ return common ? path54.join(common, "workit", "ci-reruns.jsonl") : null;
78559
78736
  }
78560
78737
  function rerunCounts(cwd, key) {
78561
78738
  const counts = new Map;
@@ -78590,7 +78767,7 @@ function recordReruns(cwd, rows) {
78590
78767
  if (!file)
78591
78768
  return false;
78592
78769
  try {
78593
- fs27.mkdirSync(path53.dirname(file), { recursive: true });
78770
+ fs27.mkdirSync(path54.dirname(file), { recursive: true });
78594
78771
  fs27.appendFileSync(file, rows.map((row) => `${JSON.stringify(row)}
78595
78772
  `).join(""));
78596
78773
  return true;
@@ -78603,7 +78780,7 @@ function withRerunLock(cwd, fn) {
78603
78780
  if (!file)
78604
78781
  return fn();
78605
78782
  const lock = `${file.slice(0, -".jsonl".length)}.lock`;
78606
- fs27.mkdirSync(path53.dirname(lock), { recursive: true });
78783
+ fs27.mkdirSync(path54.dirname(lock), { recursive: true });
78607
78784
  const until = Date.now() + LOCK_WAIT_MS2;
78608
78785
  for (;; ) {
78609
78786
  try {
@@ -79518,7 +79695,7 @@ var init_pr_ops = __esm(() => {
79518
79695
  import { spawnSync as spawnSync22 } from "node:child_process";
79519
79696
  import { createHash as createHash17, randomBytes as randomBytes4 } from "node:crypto";
79520
79697
  import fs28 from "node:fs";
79521
- import path54 from "node:path";
79698
+ import path55 from "node:path";
79522
79699
  function worktreeOf(cwd, branch) {
79523
79700
  const list = gitRun3(cwd, ["worktree", "list", "--porcelain"]);
79524
79701
  if (!list.ok)
@@ -79562,7 +79739,7 @@ function gitRestack(cwd, input) {
79562
79739
  if (!scratch)
79563
79740
  return { ok: false, conflict: false, worktree: cwd, error: "no store root" };
79564
79741
  fs28.mkdirSync(scratch, { recursive: true });
79565
- dir = path54.join(scratch, `${input.branch.replace(/[^A-Za-z0-9._-]+/gu, "_").slice(0, 40)}-${randomBytes4(4).toString("hex")}`);
79742
+ dir = path55.join(scratch, `${input.branch.replace(/[^A-Za-z0-9._-]+/gu, "_").slice(0, 40)}-${randomBytes4(4).toString("hex")}`);
79566
79743
  const added = gitRun3(cwd, ["worktree", "add", "-q", dir, input.branch], GIT_TIMEOUTS.worktree);
79567
79744
  if (!added.ok)
79568
79745
  return { ok: false, conflict: false, worktree: cwd, error: firstLine(added) };
@@ -79603,7 +79780,7 @@ function pruneScratch(cwd) {
79603
79780
  if (!scratch || !fs28.existsSync(scratch))
79604
79781
  return;
79605
79782
  for (const name of fs28.readdirSync(scratch)) {
79606
- const dir = path54.join(scratch, name);
79783
+ const dir = path55.join(scratch, name);
79607
79784
  if (!rebaseInProgress(dir) && !trackedDirt(dir))
79608
79785
  gitRun3(cwd, ["worktree", "remove", "--force", dir]);
79609
79786
  }
@@ -79613,7 +79790,7 @@ function stacksDir(cwd) {
79613
79790
  const root = storeRoot(cwd);
79614
79791
  if (!root.ok)
79615
79792
  return stackFail(root.code, root.error, root.unblock);
79616
- return { ok: true, data: path54.join(root.value.root, "stacks") };
79793
+ return { ok: true, data: path55.join(root.value.root, "stacks") };
79617
79794
  }
79618
79795
  function parseStack(raw) {
79619
79796
  if (!isRecord12(raw) || !Array.isArray(raw.branches))
@@ -79665,7 +79842,7 @@ function readStack(cwd, name) {
79665
79842
  const dir = stacksDir(cwd);
79666
79843
  if (!dir.ok)
79667
79844
  return dir;
79668
- const file = path54.join(dir.data, fileFor(name));
79845
+ const file = path55.join(dir.data, fileFor(name));
79669
79846
  let text;
79670
79847
  try {
79671
79848
  text = fs28.readFileSync(file, "utf8");
@@ -79686,7 +79863,7 @@ function writeStack(cwd, stack, now = new Date) {
79686
79863
  const dir = stacksDir(cwd);
79687
79864
  if (!dir.ok)
79688
79865
  return dir;
79689
- const file = path54.join(dir.data, fileFor(stack.name));
79866
+ const file = path55.join(dir.data, fileFor(stack.name));
79690
79867
  const temp = `${file}.${process.pid}.tmp`;
79691
79868
  try {
79692
79869
  fs28.mkdirSync(dir.data, { recursive: true });
@@ -79714,7 +79891,7 @@ function listStacks(cwd) {
79714
79891
  for (const name of names) {
79715
79892
  let parsed = null;
79716
79893
  try {
79717
- parsed = parseStack(JSON.parse(fs28.readFileSync(path54.join(dir.data, name), "utf8")));
79894
+ parsed = parseStack(JSON.parse(fs28.readFileSync(path55.join(dir.data, name), "utf8")));
79718
79895
  } catch {
79719
79896
  parsed = null;
79720
79897
  }
@@ -79773,7 +79950,7 @@ function takeLock(lock) {
79773
79950
  host: localLockHost(),
79774
79951
  nonce: randomBytes4(8).toString("hex")
79775
79952
  };
79776
- fs28.writeFileSync(path54.join(lock, OWNER), JSON.stringify(owner));
79953
+ fs28.writeFileSync(path55.join(lock, OWNER), JSON.stringify(owner));
79777
79954
  return owner;
79778
79955
  }
79779
79956
  function reapLock(lock, observed) {
@@ -79810,7 +79987,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
79810
79987
  return dir;
79811
79988
  if (!validName(name))
79812
79989
  return stackFail("invalid_input", "a stack name must be 1-200 printable characters");
79813
- const lock = path54.join(dir.data, `${fileFor(name)}.lock`);
79990
+ const lock = path55.join(dir.data, `${fileFor(name)}.lock`);
79814
79991
  try {
79815
79992
  fs28.mkdirSync(dir.data, { recursive: true });
79816
79993
  } catch (error) {
@@ -79840,7 +80017,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
79840
80017
  const touch = () => {
79841
80018
  try {
79842
80019
  const now = new Date;
79843
- fs28.utimesSync(path54.join(lock, OWNER), now, now);
80020
+ fs28.utimesSync(path55.join(lock, OWNER), now, now);
79844
80021
  } catch {}
79845
80022
  };
79846
80023
  const beat = setInterval(touch, HEARTBEAT_MS);
@@ -80691,7 +80868,7 @@ var STACK_VERSION = 1, stackFail = (code, error, unblock, data) => ({
80691
80868
  return !status.ok || status.stdout.trim() !== "";
80692
80869
  }, scratchDir = (cwd) => {
80693
80870
  const dir = stacksDir(cwd);
80694
- return dir.ok ? path54.join(dir.data, "worktrees") : null;
80871
+ return dir.ok ? path55.join(dir.data, "worktrees") : null;
80695
80872
  }, firstLine = (run) => (`${run.stderr}
80696
80873
  ${run.stdout}`.split(`
80697
80874
  `).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) => {
@@ -80706,12 +80883,12 @@ ${run.stdout}`.split(`
80706
80883
  }, 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) => {
80707
80884
  let raw = null;
80708
80885
  try {
80709
- raw = fs28.readFileSync(path54.join(lock, OWNER), "utf8");
80886
+ raw = fs28.readFileSync(path55.join(lock, OWNER), "utf8");
80710
80887
  } catch {
80711
80888
  raw = null;
80712
80889
  }
80713
80890
  let age = null;
80714
- for (const target of [path54.join(lock, OWNER), lock])
80891
+ for (const target of [path55.join(lock, OWNER), lock])
80715
80892
  try {
80716
80893
  age = Date.now() - fs28.statSync(target).mtimeMs;
80717
80894
  break;
@@ -80754,7 +80931,7 @@ var init_stack = __esm(() => {
80754
80931
  import { spawnSync as spawnSync23 } from "node:child_process";
80755
80932
  import { createHash as createHash18 } from "node:crypto";
80756
80933
  import fs29 from "node:fs";
80757
- import path55 from "node:path";
80934
+ import path56 from "node:path";
80758
80935
  function expandBraces2(pattern, limit = 64) {
80759
80936
  for (let index = 0;index < pattern.length; index += 1) {
80760
80937
  if (pattern[index] === "\\") {
@@ -81000,7 +81177,7 @@ function parsePlan(raw, defaults, name) {
81000
81177
  id,
81001
81178
  branch,
81002
81179
  base: optional("base") ?? "",
81003
- worktree: path55.resolve(defaults.root, optional("worktree") ?? path55.join(defaults.worktreeRoot, id)),
81180
+ worktree: path56.resolve(defaults.root, optional("worktree") ?? path56.join(defaults.worktreeRoot, id)),
81004
81181
  tier,
81005
81182
  reason,
81006
81183
  dependsOn: [...new Set(dependsOn ?? [])],
@@ -81231,11 +81408,11 @@ function defaultTrunk(cwd) {
81231
81408
  }
81232
81409
  function mainCheckout(cwd) {
81233
81410
  const common = gitCommonDir(cwd);
81234
- return common && path55.basename(common) === ".git" ? path55.dirname(common) : path55.resolve(cwd);
81411
+ return common && path56.basename(common) === ".git" ? path56.dirname(common) : path56.resolve(cwd);
81235
81412
  }
81236
81413
  function worktreeRoot(cwd) {
81237
81414
  const main = mainCheckout(cwd);
81238
- return path55.join(path55.dirname(main), `${path55.basename(main)}-wt`);
81415
+ return path56.join(path56.dirname(main), `${path56.basename(main)}-wt`);
81239
81416
  }
81240
81417
  function sliceHash(slice) {
81241
81418
  const {
@@ -81255,7 +81432,7 @@ function fanoutsDir(cwd) {
81255
81432
  const root = storeRoot(cwd);
81256
81433
  if (!root.ok)
81257
81434
  return fanoutFail(root.code, root.error, root.unblock);
81258
- return { ok: true, data: path55.join(root.value.root, "fanouts") };
81435
+ return { ok: true, data: path56.join(root.value.root, "fanouts") };
81259
81436
  }
81260
81437
  function parseStored(raw) {
81261
81438
  if (!isRecord13(raw) || typeof raw.name !== "string" || typeof raw.trunk !== "string")
@@ -81323,7 +81500,7 @@ function readFanout(cwd, name) {
81323
81500
  const dir = fanoutsDir(cwd);
81324
81501
  if (!dir.ok)
81325
81502
  return dir;
81326
- const file = path55.join(dir.data, stackFileName(name));
81503
+ const file = path56.join(dir.data, stackFileName(name));
81327
81504
  let parsed = null;
81328
81505
  try {
81329
81506
  parsed = parseStored(JSON.parse(fs29.readFileSync(file, "utf8")));
@@ -81348,7 +81525,7 @@ function listFanouts(cwd) {
81348
81525
  for (const entry of names) {
81349
81526
  let parsed = null;
81350
81527
  try {
81351
- parsed = parseStored(JSON.parse(fs29.readFileSync(path55.join(dir.data, entry), "utf8")));
81528
+ parsed = parseStored(JSON.parse(fs29.readFileSync(path56.join(dir.data, entry), "utf8")));
81352
81529
  } catch {
81353
81530
  parsed = null;
81354
81531
  }
@@ -81387,7 +81564,7 @@ function writeFanout(cwd, plan) {
81387
81564
  const dir = fanoutsDir(cwd);
81388
81565
  if (!dir.ok)
81389
81566
  return dir;
81390
- const file = path55.join(dir.data, stackFileName(plan.name));
81567
+ const file = path56.join(dir.data, stackFileName(plan.name));
81391
81568
  const temp = `${file}.${process.pid}.tmp`;
81392
81569
  try {
81393
81570
  fs29.mkdirSync(dir.data, { recursive: true });
@@ -81594,13 +81771,13 @@ var init_fanout = __esm(() => {
81594
81771
  // packages/workit-core/src/forge/exec.ts
81595
81772
  import { spawnSync as spawnSync24 } from "node:child_process";
81596
81773
  import fs30 from "node:fs";
81597
- import path56 from "node:path";
81774
+ import path57 from "node:path";
81598
81775
  function findExecutable(bin, env) {
81599
- const dirs = (env.PATH ?? env.Path ?? "").split(path56.delimiter).filter(Boolean);
81776
+ const dirs = (env.PATH ?? env.Path ?? "").split(path57.delimiter).filter(Boolean);
81600
81777
  const exts = process.platform === "win32" ? [".exe"] : [""];
81601
81778
  for (const dir of dirs)
81602
81779
  for (const ext of exts) {
81603
- const candidate = path56.join(dir, `${bin}${ext}`);
81780
+ const candidate = path57.join(dir, `${bin}${ext}`);
81604
81781
  try {
81605
81782
  const stat = fs30.statSync(candidate);
81606
81783
  if (stat.isFile())
@@ -83344,7 +83521,7 @@ var init_duration = __esm(() => {
83344
83521
  });
83345
83522
 
83346
83523
  // packages/workit-cli/src/verbs/forge-common.ts
83347
- import { readFileSync as readFileSync22 } from "node:fs";
83524
+ import { readFileSync as readFileSync23 } from "node:fs";
83348
83525
  function parseFlags(argv, spec) {
83349
83526
  const parsed = { values: {}, booleans: new Set, lists: {}, positionals: [] };
83350
83527
  for (let index = 0;index < argv.length; index += 1) {
@@ -83488,7 +83665,7 @@ var init_forge_common = __esm(() => {
83488
83665
  forgeDeps = {
83489
83666
  runner: undefined,
83490
83667
  npm: undefined,
83491
- readStdin: () => readFileSync22(0, "utf8"),
83668
+ readStdin: () => readFileSync23(0, "utf8"),
83492
83669
  sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
83493
83670
  now: () => Date.now()
83494
83671
  };
@@ -83499,12 +83676,12 @@ var exports_pr = {};
83499
83676
  __export(exports_pr, {
83500
83677
  run: () => run14
83501
83678
  });
83502
- import { readFileSync as readFileSync23 } from "node:fs";
83503
- import path57 from "node:path";
83679
+ import { readFileSync as readFileSync24 } from "node:fs";
83680
+ import path58 from "node:path";
83504
83681
  function readBodyFile(io, file) {
83505
83682
  try {
83506
83683
  return {
83507
- body: file === "-" ? forgeDeps.readStdin() : readFileSync23(path57.resolve(io.cwd, file), "utf8")
83684
+ body: file === "-" ? forgeDeps.readStdin() : readFileSync24(path58.resolve(io.cwd, file), "utf8")
83508
83685
  };
83509
83686
  } catch {
83510
83687
  return `cannot read --body-file ${file}`;
@@ -84209,8 +84386,8 @@ var exports_git = {};
84209
84386
  __export(exports_git, {
84210
84387
  run: () => run16
84211
84388
  });
84212
- import { readFileSync as readFileSync24 } from "node:fs";
84213
- import path58 from "node:path";
84389
+ import { readFileSync as readFileSync25 } from "node:fs";
84390
+ import path59 from "node:path";
84214
84391
  function kindHint(cwd, kind) {
84215
84392
  let kinds = [...BRANCH_KINDS];
84216
84393
  try {
@@ -84314,7 +84491,7 @@ function commitMessage(parsed, io) {
84314
84491
 
84315
84492
  `);
84316
84493
  try {
84317
- return file === "-" ? readFileSync24(0, "utf8") : readFileSync24(path58.resolve(io.cwd, file), "utf8");
84494
+ return file === "-" ? readFileSync25(0, "utf8") : readFileSync25(path59.resolve(io.cwd, file), "utf8");
84318
84495
  } catch (error) {
84319
84496
  return {
84320
84497
  error: `cannot read -F ${file}: ${error instanceof Error ? error.message : String(error)}`
@@ -85735,7 +85912,7 @@ var init_live_session = __esm(() => {
85735
85912
  });
85736
85913
 
85737
85914
  // packages/workit-core/src/hooks/write-gate.ts
85738
- import path59 from "node:path";
85915
+ import path60 from "node:path";
85739
85916
  var CASE_INSENSITIVE, PREFIXES2, SCRIPT_SHELLS, cache3, MUTATING_GIT, DRY_N, MUTATING_WORKIT_GIT, CD2, PUSHD2, POPD2, UNKNOWN_DIR;
85740
85917
  var init_write_gate = __esm(() => {
85741
85918
  init_task_store();
@@ -85775,7 +85952,7 @@ var init_write_gate = __esm(() => {
85775
85952
  CD2 = new Set(["cd", "chdir", "set-location", "sl"]);
85776
85953
  PUSHD2 = new Set(["pushd", "push-location"]);
85777
85954
  POPD2 = new Set(["popd", "pop-location"]);
85778
- UNKNOWN_DIR = path59.resolve(path59.parse(process.cwd()).root, ".workit-unknown-dir");
85955
+ UNKNOWN_DIR = path60.resolve(path60.parse(process.cwd()).root, ".workit-unknown-dir");
85779
85956
  });
85780
85957
 
85781
85958
  // packages/workit-core/src/hooks/worktree-confine.ts
@@ -85800,20 +85977,20 @@ var init_worktree_confine = __esm(() => {
85800
85977
 
85801
85978
  // packages/workit-core/src/worktree-deps.ts
85802
85979
  import fs32 from "node:fs";
85803
- import path60 from "node:path";
85980
+ import path61 from "node:path";
85804
85981
  function moduleDirs(main) {
85805
85982
  const out = [];
85806
85983
  const walk = (relative, depth) => {
85807
85984
  let entries;
85808
85985
  try {
85809
- entries = fs32.readdirSync(path60.join(main, relative), { withFileTypes: true });
85986
+ entries = fs32.readdirSync(path61.join(main, relative), { withFileTypes: true });
85810
85987
  } catch {
85811
85988
  return;
85812
85989
  }
85813
85990
  for (const entry of entries) {
85814
85991
  if (!entry.isDirectory())
85815
85992
  continue;
85816
- const child = path60.join(relative, entry.name);
85993
+ const child = path61.join(relative, entry.name);
85817
85994
  if (entry.name === MODULES)
85818
85995
  out.push(child);
85819
85996
  else if (depth < MAX_DEPTH2 && !entry.name.startsWith("."))
@@ -85827,8 +86004,8 @@ function linkEntry(main, worktree, source, target) {
85827
86004
  const stat = fs32.lstatSync(source);
85828
86005
  if (stat.isSymbolicLink()) {
85829
86006
  const link = fs32.readlinkSync(source);
85830
- const outside = path60.isAbsolute(link) && within(link, main) && !path60.relative(main, link).split(path60.sep).includes(MODULES);
85831
- const to = outside ? path60.join(worktree, path60.relative(main, link)) : link;
86007
+ const outside = path61.isAbsolute(link) && within(link, main) && !path61.relative(main, link).split(path61.sep).includes(MODULES);
86008
+ const to = outside ? path61.join(worktree, path61.relative(main, link)) : link;
85832
86009
  fs32.symlinkSync(to, target, process.platform === "win32" ? "junction" : undefined);
85833
86010
  return;
85834
86011
  }
@@ -85838,8 +86015,8 @@ function mirror(main, worktree, source, target, top) {
85838
86015
  fs32.mkdirSync(target);
85839
86016
  let count = 0;
85840
86017
  for (const entry of fs32.readdirSync(source, { withFileTypes: true })) {
85841
- const from = path60.join(source, entry.name);
85842
- const to = path60.join(target, entry.name);
86018
+ const from = path61.join(source, entry.name);
86019
+ const to = path61.join(target, entry.name);
85843
86020
  if (top && entry.isDirectory() && (entry.name.startsWith("@") || entry.name === ".bin"))
85844
86021
  count += mirror(main, worktree, from, to, false);
85845
86022
  else {
@@ -85855,16 +86032,16 @@ function linkWorktreeDependencies(main, worktree) {
85855
86032
  const dirs = [];
85856
86033
  let entries = 0;
85857
86034
  for (const relative of moduleDirs(main)) {
85858
- const target = path60.join(worktree, relative);
85859
- if (!fs32.existsSync(path60.dirname(target)) || fs32.existsSync(target))
86035
+ const target = path61.join(worktree, relative);
86036
+ if (!fs32.existsSync(path61.dirname(target)) || fs32.existsSync(target))
85860
86037
  continue;
85861
- if (!gitRun4(worktree, ["check-ignore", "-q", `${relative.split(path60.sep).join("/")}/`]).ok) {
85862
- 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`);
86038
+ if (!gitRun4(worktree, ["check-ignore", "-q", `${relative.split(path61.sep).join("/")}/`]).ok) {
86039
+ notes.push(`${relative.split(path61.sep).join("/")} is not ignored by git, so it was not linked from ${main}; install dependencies in the worktree yourself`);
85863
86040
  continue;
85864
86041
  }
85865
86042
  try {
85866
- entries += mirror(main, worktree, path60.join(main, relative), target, true);
85867
- dirs.push(relative.split(path60.sep).join("/"));
86043
+ entries += mirror(main, worktree, path61.join(main, relative), target, true);
86044
+ dirs.push(relative.split(path61.sep).join("/"));
85868
86045
  } catch (error) {
85869
86046
  fs32.rmSync(target, { recursive: true, force: true });
85870
86047
  notes.push(`could not link ${relative} from ${main} (${error.message}); install dependencies in the worktree yourself`);
@@ -85877,8 +86054,8 @@ function linkWorktreeDependencies(main, worktree) {
85877
86054
  return { linked: { from: main, dirs, entries, ms }, notes };
85878
86055
  }
85879
86056
  var MODULES = "node_modules", MAX_DEPTH2 = 2, within = (child, parent) => {
85880
- const relative = path60.relative(parent, child);
85881
- return relative === "" || !relative.startsWith("..") && !path60.isAbsolute(relative);
86057
+ const relative = path61.relative(parent, child);
86058
+ return relative === "" || !relative.startsWith("..") && !path61.isAbsolute(relative);
85882
86059
  };
85883
86060
  var init_worktree_deps = __esm(() => {
85884
86061
  init_fanout();
@@ -85887,7 +86064,7 @@ var init_worktree_deps = __esm(() => {
85887
86064
  // packages/workit-core/src/fanout-worktree.ts
85888
86065
  import { randomBytes as randomBytes5 } from "node:crypto";
85889
86066
  import fs33 from "node:fs";
85890
- import path61 from "node:path";
86067
+ import path62 from "node:path";
85891
86068
  function rowSample(lines) {
85892
86069
  const out = [];
85893
86070
  let bytes = 0;
@@ -85947,7 +86124,7 @@ function adminDir(worktree) {
85947
86124
  const file = dir.stdout.trim();
85948
86125
  let token = null;
85949
86126
  try {
85950
- token = fs33.readFileSync(path61.join(file, FANOUT_TOKEN_FILE), "utf8").trim() || null;
86127
+ token = fs33.readFileSync(path62.join(file, FANOUT_TOKEN_FILE), "utf8").trim() || null;
85951
86128
  } catch {
85952
86129
  token = null;
85953
86130
  }
@@ -85955,7 +86132,7 @@ function adminDir(worktree) {
85955
86132
  const stat = worktreeDeps.stat(file);
85956
86133
  return {
85957
86134
  path: file,
85958
- id: path61.basename(file),
86135
+ id: path62.basename(file),
85959
86136
  ino: stat.ino.toString(),
85960
86137
  token,
85961
86138
  birthMs: stat.birthtimeNs > 0n ? Number(stat.birthtimeMs) : null,
@@ -85971,7 +86148,7 @@ function markAdminDir(worktree) {
85971
86148
  return null;
85972
86149
  const token = randomBytes5(16).toString("hex");
85973
86150
  try {
85974
- fs33.writeFileSync(path61.join(admin.path, FANOUT_TOKEN_FILE), `${token}
86151
+ fs33.writeFileSync(path62.join(admin.path, FANOUT_TOKEN_FILE), `${token}
85975
86152
  `);
85976
86153
  } catch {
85977
86154
  return null;
@@ -85986,7 +86163,7 @@ function excludeScratch(cwd) {
85986
86163
  const common = gitCommonDir(cwd);
85987
86164
  if (!common)
85988
86165
  return;
85989
- const file = path61.join(common, "info", "exclude");
86166
+ const file = path62.join(common, "info", "exclude");
85990
86167
  let text = "";
85991
86168
  try {
85992
86169
  text = fs33.readFileSync(file, "utf8");
@@ -85995,7 +86172,7 @@ function excludeScratch(cwd) {
85995
86172
  }
85996
86173
  if (text.split(/\r?\n/u).includes(EXCLUDE_LINE))
85997
86174
  return;
85998
- fs33.mkdirSync(path61.dirname(file), { recursive: true });
86175
+ fs33.mkdirSync(path62.dirname(file), { recursive: true });
85999
86176
  fs33.appendFileSync(file, `${text && !text.endsWith(`
86000
86177
  `) ? `
86001
86178
  ` : ""}# workit fanout: per-worker scratch dirs
@@ -86003,7 +86180,7 @@ ${EXCLUDE_LINE}
86003
86180
  `);
86004
86181
  }
86005
86182
  function ensureScratch(worktree) {
86006
- const scratch = path61.join(worktree, SCRATCH_DIR);
86183
+ const scratch = path62.join(worktree, SCRATCH_DIR);
86007
86184
  fs33.mkdirSync(scratch, { recursive: true });
86008
86185
  return scratch;
86009
86186
  }
@@ -86231,7 +86408,7 @@ function unpushedCount(cwd, branch) {
86231
86408
  return count.ok ? Number(count.stdout.trim()) : null;
86232
86409
  }
86233
86410
  function removeScratch(worktree) {
86234
- const scratch = path61.join(worktree, SCRATCH_DIR);
86411
+ const scratch = path62.join(worktree, SCRATCH_DIR);
86235
86412
  let stat;
86236
86413
  try {
86237
86414
  stat = fs33.lstatSync(scratch);
@@ -86247,16 +86424,16 @@ var SLOW, SCRATCH_DIR = ".workit-scratch", EXCLUDE_LINE, DIRTY_ROW_BYTES = 2000,
86247
86424
  try {
86248
86425
  return fs33.realpathSync.native(target);
86249
86426
  } catch {
86250
- return path61.resolve(target);
86427
+ return path62.resolve(target);
86251
86428
  }
86252
86429
  }, samePath = (a, b) => {
86253
86430
  const left = canonical2(a);
86254
86431
  const right = canonical2(b);
86255
86432
  return process.platform === "win32" || process.platform === "darwin" ? left.toLowerCase() === right.toLowerCase() : left === right;
86256
86433
  }, inside3 = (child, parent) => {
86257
- const relative = path61.relative(canonical2(parent), canonical2(child));
86258
- return relative === "" || !relative.startsWith("..") && !path61.isAbsolute(relative);
86259
- }, slicePath = (cwd, slice) => path61.isAbsolute(slice.worktree) ? slice.worktree : path61.resolve(mainCheckout(cwd), slice.worktree), CLOCK_SLACK_MS = 2000, worktreeDeps, worktreeFailed = (stderr) => fanoutFail("failed", `git worktree add failed: ${stderr.trim().split(`
86434
+ const relative = path62.relative(canonical2(parent), canonical2(child));
86435
+ return relative === "" || !relative.startsWith("..") && !path62.isAbsolute(relative);
86436
+ }, slicePath = (cwd, slice) => path62.isAbsolute(slice.worktree) ? slice.worktree : path62.resolve(mainCheckout(cwd), slice.worktree), CLOCK_SLACK_MS = 2000, worktreeDeps, worktreeFailed = (stderr) => fanoutFail("failed", `git worktree add failed: ${stderr.trim().split(`
86260
86437
  `)[0] || "unknown error"}`);
86261
86438
  var init_fanout_worktree = __esm(() => {
86262
86439
  init_ops();
@@ -87092,7 +87269,7 @@ __export(exports_fanout, {
87092
87269
  run: () => run20
87093
87270
  });
87094
87271
  import fs34 from "node:fs";
87095
- import path62 from "node:path";
87272
+ import path63 from "node:path";
87096
87273
  function forgeFor(io, offline) {
87097
87274
  if (offline)
87098
87275
  return { forge: null, error: "--offline" };
@@ -87153,7 +87330,7 @@ function plan2(argv, io) {
87153
87330
  return usage3(io, "pass --trunk or --track, not both (--track picks the trunk)", PLAN_USAGE2);
87154
87331
  if (flags.positionals.length !== 1)
87155
87332
  return usage3(io, flags.positionals.length ? `unexpected argument ${flags.positionals[1]}` : "missing <plan.json>", PLAN_USAGE2);
87156
- const file = path62.resolve(io.cwd, flags.positionals[0]);
87333
+ const file = path63.resolve(io.cwd, flags.positionals[0]);
87157
87334
  let raw;
87158
87335
  try {
87159
87336
  raw = JSON.parse(fs34.readFileSync(file, "utf8"));
@@ -102692,7 +102869,7 @@ var init_ast = __esm(() => {
102692
102869
 
102693
102870
  // packages/workit-cli/src/test-audit/rules.ts
102694
102871
  import { builtinModules } from "node:module";
102695
- import path63 from "node:path";
102872
+ import path64 from "node:path";
102696
102873
  function testCallee(call) {
102697
102874
  let callee = call.callee;
102698
102875
  if (callee.type === "CallExpression")
@@ -103185,12 +103362,12 @@ function checkConstantsOnly(ctx, emit) {
103185
103362
  }
103186
103363
  function checkOverMocking(ctx, emit) {
103187
103364
  const { program } = ctx.parsed;
103188
- const unit = path63.basename(ctx.file).replace(/\.(?:[cm]?[jt]sx?)$/, "").replace(/\.(?:test|spec)$/, "");
103365
+ const unit = path64.basename(ctx.file).replace(/\.(?:[cm]?[jt]sx?)$/, "").replace(/\.(?:test|spec)$/, "");
103189
103366
  const mocked = find2(program, (node) => node.type === "CallExpression" && MODULE_MOCK.test(calleeName(node.callee) ?? "") && node.arguments[0]?.type === "StringLiteral");
103190
103367
  const internal = mocked.filter((call) => /^(?:\.|@\/|~\/)/.test(call.arguments[0].value));
103191
103368
  for (const call of mocked) {
103192
103369
  const spec = call.arguments[0].value;
103193
- const base = path63.basename(spec.replace(/\/index(?:\.[cm]?[jt]sx?)?$/, "")).replace(/\.(?:[cm]?[jt]sx?)$/, "");
103370
+ const base = path64.basename(spec.replace(/\/index(?:\.[cm]?[jt]sx?)?$/, "")).replace(/\.(?:[cm]?[jt]sx?)$/, "");
103194
103371
  if (base === unit)
103195
103372
  emit({
103196
103373
  rule: "over-mocking",
@@ -103579,8 +103756,8 @@ var init_rules = __esm(() => {
103579
103756
 
103580
103757
  // packages/workit-cli/src/test-audit/audit.ts
103581
103758
  import { spawnSync as spawnSync29 } from "node:child_process";
103582
- import { existsSync as existsSync22, readdirSync as readdirSync10, readFileSync as readFileSync25, statSync as statSync9 } from "node:fs";
103583
- import path64 from "node:path";
103759
+ import { existsSync as existsSync23, readdirSync as readdirSync11, readFileSync as readFileSync26, statSync as statSync10 } from "node:fs";
103760
+ import path65 from "node:path";
103584
103761
  function git7(cwd, args) {
103585
103762
  const run = spawnSync29("git", ["-c", "core.quotepath=off", ...args], {
103586
103763
  cwd,
@@ -103590,10 +103767,10 @@ function git7(cwd, args) {
103590
103767
  return { ok: run.status === 0, stdout: run.stdout ?? "" };
103591
103768
  }
103592
103769
  function walkTests(dir, out) {
103593
- for (const entry of readdirSync10(dir, { withFileTypes: true })) {
103770
+ for (const entry of readdirSync11(dir, { withFileTypes: true })) {
103594
103771
  if (entry.name.startsWith(".") && entry.name !== "." && entry.isDirectory())
103595
103772
  continue;
103596
- const full = path64.join(dir, entry.name);
103773
+ const full = path65.join(dir, entry.name);
103597
103774
  if (entry.isDirectory()) {
103598
103775
  if (!SKIP_DIRS.has(entry.name))
103599
103776
  walkTests(full, out);
@@ -103605,10 +103782,10 @@ function expandPaths(cwd, inputs) {
103605
103782
  const files = [];
103606
103783
  const missing = [];
103607
103784
  for (const input of inputs.length > 0 ? inputs : ["."]) {
103608
- const full = path64.resolve(cwd, input);
103609
- if (!existsSync22(full))
103785
+ const full = path65.resolve(cwd, input);
103786
+ if (!existsSync23(full))
103610
103787
  missing.push(input);
103611
- else if (statSync9(full).isDirectory())
103788
+ else if (statSync10(full).isDirectory())
103612
103789
  walkTests(full, files);
103613
103790
  else
103614
103791
  files.push(full);
@@ -103642,11 +103819,11 @@ function changedLines(cwd, base) {
103642
103819
  for (let offset = 0;offset < count; offset += 1)
103643
103820
  lines.add(start + offset);
103644
103821
  }
103645
- changed.set(path64.join(root, file), lines);
103822
+ changed.set(path65.join(root, file), lines);
103646
103823
  }
103647
103824
  const untracked = git7(root, ["ls-files", "--others", "--exclude-standard", "-z"]);
103648
103825
  for (const file of untracked.stdout.split("\x00").filter(Boolean))
103649
- changed.set(path64.join(root, file), "all");
103826
+ changed.set(path65.join(root, file), "all");
103650
103827
  return changed;
103651
103828
  }
103652
103829
  function auditFiles(files, display) {
@@ -103659,7 +103836,7 @@ function auditFiles(files, display) {
103659
103836
  const shown = display(file);
103660
103837
  let parsed;
103661
103838
  try {
103662
- parsed = parseSource(readFileSync25(file, "utf8"), file);
103839
+ parsed = parseSource(readFileSync26(file, "utf8"), file);
103663
103840
  } catch (error) {
103664
103841
  parseErrors.push({
103665
103842
  file: shown,
@@ -103708,7 +103885,7 @@ function auditFiles(files, display) {
103708
103885
  durationMs: Math.round(performance.now() - started)
103709
103886
  };
103710
103887
  }
103711
- var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(path64.sep).join("/"), SEVERITY_ORDER, ruleIds;
103888
+ var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(path65.sep).join("/"), SEVERITY_ORDER, ruleIds;
103712
103889
  var init_audit = __esm(() => {
103713
103890
  init_ast();
103714
103891
  init_rules();
@@ -103722,23 +103899,23 @@ var init_audit = __esm(() => {
103722
103899
  // packages/workit-cli/src/test-audit/mutate.ts
103723
103900
  import { spawn as spawn2 } from "node:child_process";
103724
103901
  import {
103725
- existsSync as existsSync23,
103902
+ existsSync as existsSync24,
103726
103903
  lstatSync as lstatSync8,
103727
103904
  mkdirSync as mkdirSync11,
103728
103905
  mkdtempSync as mkdtempSync4,
103729
- readdirSync as readdirSync11,
103730
- readFileSync as readFileSync26,
103906
+ readdirSync as readdirSync12,
103907
+ readFileSync as readFileSync27,
103731
103908
  readlinkSync as readlinkSync3,
103732
103909
  realpathSync as realpathSync10,
103733
103910
  renameSync as renameSync7,
103734
103911
  rmSync as rmSync9,
103735
- statSync as statSync10,
103912
+ statSync as statSync11,
103736
103913
  symlinkSync,
103737
103914
  writeFileSync as writeFileSync11,
103738
103915
  copyFileSync as copyFileSync7
103739
103916
  } from "node:fs";
103740
- import os21 from "node:os";
103741
- import path65 from "node:path";
103917
+ import os22 from "node:os";
103918
+ import path66 from "node:path";
103742
103919
  function mutantsFor(source, file, lines) {
103743
103920
  const parsed = parseSource(source, file);
103744
103921
  const out = [];
@@ -103811,7 +103988,7 @@ function relatedTests(source, testFiles) {
103811
103988
  for (const match of text.matchAll(SPECIFIER)) {
103812
103989
  const spec = match[1];
103813
103990
  if (spec.startsWith(".")) {
103814
- if (stripExt(path65.posix.join(path65.posix.dirname(file), spec)) === target)
103991
+ if (stripExt(path66.posix.join(path66.posix.dirname(file), spec)) === target)
103815
103992
  return true;
103816
103993
  } else if (spec.includes("/") && stripExt(spec).split("/").slice(-2).join("/") === tail)
103817
103994
  return true;
@@ -103819,11 +103996,11 @@ function relatedTests(source, testFiles) {
103819
103996
  return false;
103820
103997
  }).map((entry) => entry.file);
103821
103998
  }
103822
- function removeStaleCopies(tmp = os21.tmpdir()) {
103999
+ function removeStaleCopies(tmp = os22.tmpdir()) {
103823
104000
  let removed = 0;
103824
104001
  let names = [];
103825
104002
  try {
103826
- names = readdirSync11(tmp);
104003
+ names = readdirSync12(tmp);
103827
104004
  } catch {
103828
104005
  return 0;
103829
104006
  }
@@ -103831,12 +104008,12 @@ function removeStaleCopies(tmp = os21.tmpdir()) {
103831
104008
  for (const name of names) {
103832
104009
  if (!name.startsWith(TEMP_PREFIX))
103833
104010
  continue;
103834
- const dir = path65.join(tmp, name);
104011
+ const dir = path66.join(tmp, name);
103835
104012
  try {
103836
104013
  const stat = lstatSync8(dir);
103837
104014
  if (!stat.isDirectory() || uid !== undefined && stat.uid !== uid)
103838
104015
  continue;
103839
- const pid = Number(readFileSync26(path65.join(dir, PID_FILE), "utf8"));
104016
+ const pid = Number(readFileSync27(path66.join(dir, PID_FILE), "utf8"));
103840
104017
  if (Number.isInteger(pid) && pid > 0 && alive(pid))
103841
104018
  continue;
103842
104019
  } catch (error) {
@@ -103852,9 +104029,9 @@ function removeStaleCopies(tmp = os21.tmpdir()) {
103852
104029
  }
103853
104030
  function linkNodeModules(origin, target, repo, copy) {
103854
104031
  mkdirSync11(target, { recursive: true });
103855
- for (const entry of readdirSync11(origin, { withFileTypes: true })) {
103856
- const from = path65.join(origin, entry.name);
103857
- const to = path65.join(target, entry.name);
104032
+ for (const entry of readdirSync12(origin, { withFileTypes: true })) {
104033
+ const from = path66.join(origin, entry.name);
104034
+ const to = path66.join(target, entry.name);
103858
104035
  if (entry.name.startsWith("@") && entry.isDirectory()) {
103859
104036
  linkNodeModules(from, to, repo, copy);
103860
104037
  continue;
@@ -103870,9 +104047,9 @@ function linkNodeModules(origin, target, repo, copy) {
103870
104047
  } catch {
103871
104048
  continue;
103872
104049
  }
103873
- const relative = path65.relative(repo, real);
103874
- if (!relative.startsWith("..") && !path65.isAbsolute(relative) && !relative.split(path65.sep).includes("node_modules")) {
103875
- symlinkSync(path65.join(copy, relative), to, "junction");
104050
+ const relative = path66.relative(repo, real);
104051
+ if (!relative.startsWith("..") && !path66.isAbsolute(relative) && !relative.split(path66.sep).includes("node_modules")) {
104052
+ symlinkSync(path66.join(copy, relative), to, "junction");
103876
104053
  continue;
103877
104054
  }
103878
104055
  }
@@ -103888,19 +104065,19 @@ function copySymlink(repo, tree, from, to) {
103888
104065
  }
103889
104066
  const realRepo = realpathSync10(repo);
103890
104067
  if (real && inside4(realRepo, real)) {
103891
- symlinkSync(path65.relative(path65.dirname(to), path65.join(tree, path65.relative(realRepo, real))), to);
104068
+ symlinkSync(path66.relative(path66.dirname(to), path66.join(tree, path66.relative(realRepo, real))), to);
103892
104069
  return;
103893
104070
  }
103894
- if (real && statSync10(real).isFile())
104071
+ if (real && statSync11(real).isFile())
103895
104072
  copyFileSync7(real, to);
103896
104073
  else
103897
104074
  symlinkSync(readlinkSync3(from), to);
103898
104075
  }
103899
104076
  function writeInside(copy, file, content) {
103900
- const target = path65.join(copy, file);
104077
+ const target = path66.join(copy, file);
103901
104078
  try {
103902
104079
  const stat = lstatSync8(target);
103903
- if (!stat.isFile() || !inside4(realpathSync10(copy), realpathSync10(path65.dirname(target))))
104080
+ if (!stat.isFile() || !inside4(realpathSync10(copy), realpathSync10(path66.dirname(target))))
103904
104081
  return false;
103905
104082
  } catch {
103906
104083
  return false;
@@ -103911,9 +104088,9 @@ function writeInside(copy, file, content) {
103911
104088
  return true;
103912
104089
  }
103913
104090
  function copyWorkingTree(repo) {
103914
- const dir = mkdtempSync4(path65.join(os21.tmpdir(), TEMP_PREFIX));
103915
- writeFileSync11(path65.join(dir, PID_FILE), String(process.pid));
103916
- const tree = path65.join(dir, "tree");
104091
+ const dir = mkdtempSync4(path66.join(os22.tmpdir(), TEMP_PREFIX));
104092
+ writeFileSync11(path66.join(dir, PID_FILE), String(process.pid));
104093
+ const tree = path66.join(dir, "tree");
103917
104094
  const head = git7(repo, ["rev-parse", "--verify", "--quiet", "HEAD"]).stdout.trim();
103918
104095
  if (head && git7(dir, ["clone", "-q", "--shared", "--no-checkout", repo, tree]).ok) {
103919
104096
  const branch = git7(repo, ["symbolic-ref", "--quiet", "--short", "HEAD"]).stdout.trim();
@@ -103930,29 +104107,29 @@ function copyWorkingTree(repo) {
103930
104107
  for (const relative of listed) {
103931
104108
  if (!relative)
103932
104109
  continue;
103933
- const from = path65.join(repo, relative);
104110
+ const from = path66.join(repo, relative);
103934
104111
  let stat;
103935
104112
  try {
103936
104113
  stat = lstatSync8(from);
103937
104114
  } catch {
103938
104115
  continue;
103939
104116
  }
103940
- const to = path65.join(tree, relative);
103941
- mkdirSync11(path65.dirname(to), { recursive: true });
104117
+ const to = path66.join(tree, relative);
104118
+ mkdirSync11(path66.dirname(to), { recursive: true });
103942
104119
  if (stat.isSymbolicLink())
103943
104120
  copySymlink(repo, tree, from, to);
103944
104121
  else if (stat.isFile())
103945
104122
  copyFileSync7(from, to);
103946
- let parent = path65.dirname(relative);
104123
+ let parent = path66.dirname(relative);
103947
104124
  while (parent !== "." && !dirs.has(parent)) {
103948
104125
  dirs.add(parent);
103949
- parent = path65.dirname(parent);
104126
+ parent = path66.dirname(parent);
103950
104127
  }
103951
104128
  }
103952
104129
  for (const parent of dirs) {
103953
- const modules = path65.join(repo, parent, "node_modules");
103954
- if (existsSync23(modules) && !existsSync23(path65.join(tree, parent, "node_modules")))
103955
- linkNodeModules(modules, path65.join(tree, parent, "node_modules"), repo, tree);
104130
+ const modules = path66.join(repo, parent, "node_modules");
104131
+ if (existsSync24(modules) && !existsSync24(path66.join(tree, parent, "node_modules")))
104132
+ linkNodeModules(modules, path66.join(tree, parent, "node_modules"), repo, tree);
103956
104133
  }
103957
104134
  return { dir, tree };
103958
104135
  }
@@ -103991,20 +104168,20 @@ async function runMutation(options) {
103991
104168
  const tracked = git7(repo, ["ls-files", "-co", "--exclude-standard", "-z"]).stdout.split("\x00").filter(Boolean);
103992
104169
  const testFiles = tracked.filter((file) => TEST_FILE.test(file)).map((file) => {
103993
104170
  try {
103994
- return { file, text: readFileSync26(path65.join(repo, file), "utf8") };
104171
+ return { file, text: readFileSync27(path66.join(repo, file), "utf8") };
103995
104172
  } catch {
103996
104173
  return { file, text: "" };
103997
104174
  }
103998
104175
  });
103999
104176
  const candidates = [];
104000
104177
  for (const [absolute, lines] of [...options.changed].toSorted(([a], [b]) => a.localeCompare(b))) {
104001
- const relative = toPosix(path65.relative(repo, absolute));
104178
+ const relative = toPosix(path66.relative(repo, absolute));
104002
104179
  if (!CODE_FILE.test(relative) || TEST_FILE.test(relative) || relative.endsWith(".d.ts"))
104003
104180
  continue;
104004
- if (NOT_SOURCE.test(relative) || !existsSync23(absolute))
104181
+ if (NOT_SOURCE.test(relative) || !existsSync24(absolute))
104005
104182
  continue;
104006
104183
  try {
104007
- candidates.push(...mutantsFor(readFileSync26(absolute, "utf8"), relative, lines));
104184
+ candidates.push(...mutantsFor(readFileSync27(absolute, "utf8"), relative, lines));
104008
104185
  } catch {}
104009
104186
  }
104010
104187
  const mutants = candidates.map((mutant, index) => ({ ...mutant, id: index + 1 }));
@@ -104012,9 +104189,9 @@ async function runMutation(options) {
104012
104189
  for (const mutant of mutants)
104013
104190
  if (!related.has(mutant.file))
104014
104191
  related.set(mutant.file, relatedTests(mutant.file, testFiles));
104015
- const cwdRelative = path65.relative(repo, options.cwd);
104192
+ const cwdRelative = path66.relative(repo, options.cwd);
104016
104193
  const asArg = (file) => {
104017
- const relative = toPosix(path65.relative(cwdRelative, file));
104194
+ const relative = toPosix(path66.relative(cwdRelative, file));
104018
104195
  return shellQuote(relative.startsWith(".") ? relative : `./${relative}`);
104019
104196
  };
104020
104197
  const commandFor = (tests) => options.command.replaceAll("{files}", () => tests.map(asArg).join(" "));
@@ -104050,7 +104227,7 @@ async function runMutation(options) {
104050
104227
  return finish3(options, 0, results, counts, started);
104051
104228
  removeStaleCopies();
104052
104229
  const { dir: copyDir, tree: copy } = copyWorkingTree(repo);
104053
- const copyCwd = path65.join(copy, cwdRelative);
104230
+ const copyCwd = path66.join(copy, cwdRelative);
104054
104231
  let current = null;
104055
104232
  const restore = () => {
104056
104233
  if (current)
@@ -104085,7 +104262,7 @@ async function runMutation(options) {
104085
104262
  record({ ...mutant, status: "skipped", durationMs: 0, tests, reason: "budget" });
104086
104263
  continue;
104087
104264
  }
104088
- const original = readFileSync26(path65.join(copy, mutant.file), "utf8");
104265
+ const original = readFileSync27(path66.join(copy, mutant.file), "utf8");
104089
104266
  const mutated = original.slice(0, mutant.start) + mutant.replacement + original.slice(mutant.end);
104090
104267
  current = { file: mutant.file, original };
104091
104268
  if (!writeInside(copy, mutant.file, mutated)) {
@@ -104142,8 +104319,8 @@ var NOT_SOURCE, FLIPS, isStringy = (node) => node.type === "StringLiteral" || no
104142
104319
  return error.code === "EPERM";
104143
104320
  }
104144
104321
  }, inside4 = (root, file) => {
104145
- const relative = path65.relative(root, file);
104146
- return relative === "" || !relative.startsWith("..") && !path65.isAbsolute(relative);
104322
+ const relative = path66.relative(root, file);
104323
+ return relative === "" || !relative.startsWith("..") && !path66.isAbsolute(relative);
104147
104324
  }, active, killTree = (child) => {
104148
104325
  try {
104149
104326
  if (child.pid && process.platform !== "win32")
@@ -104191,8 +104368,8 @@ var exports_test_audit = {};
104191
104368
  __export(exports_test_audit, {
104192
104369
  run: () => run22
104193
104370
  });
104194
- import { existsSync as existsSync24 } from "node:fs";
104195
- import path66 from "node:path";
104371
+ import { existsSync as existsSync25 } from "node:fs";
104372
+ import path67 from "node:path";
104196
104373
  function parse8(argv) {
104197
104374
  const options = {
104198
104375
  paths: [],
@@ -104297,8 +104474,8 @@ async function run22(argv, io) {
104297
104474
  return emit(io, fail2("invalid_input", `${options}
104298
104475
  usage: ${USAGE14}`));
104299
104476
  const top = git7(io.cwd, ["rev-parse", "--show-toplevel"]);
104300
- const repo = top.ok ? path66.resolve(top.stdout.trim()) : null;
104301
- const display = (file) => toPosix(path66.relative(io.cwd, file) || file);
104477
+ const repo = top.ok ? path67.resolve(top.stdout.trim()) : null;
104478
+ const display = (file) => toPosix(path67.relative(io.cwd, file) || file);
104302
104479
  let base = null;
104303
104480
  let changed = null;
104304
104481
  if (options.diff || options.mutate) {
@@ -104315,7 +104492,7 @@ usage: ${USAGE14}`));
104315
104492
  }
104316
104493
  let files;
104317
104494
  if (options.diff && changed)
104318
- files = [...changed.keys()].filter((file) => TEST_FILE.test(toPosix(file)) && existsSync24(file)).toSorted();
104495
+ files = [...changed.keys()].filter((file) => TEST_FILE.test(toPosix(file)) && existsSync25(file)).toSorted();
104319
104496
  else {
104320
104497
  const expanded = expandPaths(io.cwd, options.paths);
104321
104498
  if (expanded.missing.length > 0)
@@ -104436,8 +104613,8 @@ var exports_youtrack = {};
104436
104613
  __export(exports_youtrack, {
104437
104614
  run: () => run24
104438
104615
  });
104439
- import { readFileSync as readFileSync27 } from "node:fs";
104440
- import path67 from "node:path";
104616
+ import { readFileSync as readFileSync28 } from "node:fs";
104617
+ import path68 from "node:path";
104441
104618
  async function run24(argv, io) {
104442
104619
  const [sub, ...rest] = argv;
104443
104620
  if (sub !== "note" && sub !== "time" && sub !== "meeting")
@@ -104483,7 +104660,7 @@ async function run24(argv, io) {
104483
104660
  let markdown = flags.values.markdown ?? "";
104484
104661
  if (flags.values.file)
104485
104662
  try {
104486
- markdown = readFileSync27(path67.resolve(io.cwd, flags.values.file), "utf8");
104663
+ markdown = readFileSync28(path68.resolve(io.cwd, flags.values.file), "utf8");
104487
104664
  } catch (error) {
104488
104665
  return usage3(io, `cannot read ${flags.values.file}: ${String(error)}`, USAGE16);
104489
104666
  }
@@ -104551,8 +104728,8 @@ var exports_changelog = {};
104551
104728
  __export(exports_changelog, {
104552
104729
  run: () => run25
104553
104730
  });
104554
- import { readFileSync as readFileSync28 } from "node:fs";
104555
- import path68 from "node:path";
104731
+ import { readFileSync as readFileSync29 } from "node:fs";
104732
+ import path69 from "node:path";
104556
104733
  async function run25(argv, io) {
104557
104734
  const [sub, ...rest] = argv;
104558
104735
  if (sub !== "apply")
@@ -104598,7 +104775,7 @@ async function run25(argv, io) {
104598
104775
  ]);
104599
104776
  }
104600
104777
  var USAGE17 = "workit changelog apply (--entries <JSON|@file|-> | --normalize-only) [--path CHANGELOG.md] [--preview]", readEntries = (raw, cwd) => {
104601
- const text = raw === "-" ? readFileSync28(0, "utf8") : raw.startsWith("@") ? readFileSync28(path68.resolve(cwd, raw.slice(1)), "utf8") : raw;
104778
+ const text = raw === "-" ? readFileSync29(0, "utf8") : raw.startsWith("@") ? readFileSync29(path69.resolve(cwd, raw.slice(1)), "utf8") : raw;
104602
104779
  return JSON.parse(text);
104603
104780
  };
104604
104781
  var init_changelog2 = __esm(() => {
@@ -104695,7 +104872,7 @@ var init_handoff = __esm(() => {
104695
104872
  // packages/workit-cli/src/main.ts
104696
104873
  init_host_session();
104697
104874
  init_package();
104698
- import path69 from "node:path";
104875
+ import path70 from "node:path";
104699
104876
 
104700
104877
  // packages/workit-cli/src/verbs/registry.ts
104701
104878
  var TASK_FAMILY_NAMES = [
@@ -104940,7 +105117,7 @@ var VERBS = [
104940
105117
  subcommands: [
104941
105118
  {
104942
105119
  name: "show",
104943
- usage: "workit models show [--role <role>] [--tier <mundane|standard|hard>] [--host <host>] [--json]",
105120
+ usage: "workit models show [--role <role>] [--tier <mundane|standard|hard>] [--host <host>] [--report [--days <n>]] [--json]",
104944
105121
  summary: "Print the resolved model and effort per role for a host (default: the lead's host, else claude_code) and where each came from"
104945
105122
  }
104946
105123
  ],
@@ -105557,7 +105734,7 @@ var defaultIo = (json) => ({
105557
105734
  });
105558
105735
  async function main(argv, overrides = {}, options = {}) {
105559
105736
  const parsed = parseGlobals(argv);
105560
- const cwd = path69.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
105737
+ const cwd = path70.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
105561
105738
  const io = { ...defaultIo(parsed.json), ...overrides, json: parsed.json, cwd };
105562
105739
  if (parsed.error)
105563
105740
  return emit(io, fail2("invalid_input", parsed.error));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-cli",
3
- "version": "8.27.0",
3
+ "version": "8.28.1",
4
4
  "private": false,
5
5
  "description": "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
6
6
  "keywords": [
@@ -38,13 +38,13 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "@babel/parser": "7.29.9",
41
- "@brainervirus/workit-cursor": "^8.27.0",
41
+ "@brainervirus/workit-cursor": "^8.28.1",
42
42
  "@inkjs/ui": "2.0.0",
43
43
  "ink": "7.1.1",
44
44
  "react": "19.2.8"
45
45
  },
46
46
  "devDependencies": {
47
- "@brainervirus/workit-core": "^8.27.0"
47
+ "@brainervirus/workit-core": "^8.28.1"
48
48
  },
49
49
  "engines": {
50
50
  "node": ">=24"