@brainervirus/workit-codex 8.13.0 → 8.13.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.
@@ -6622,13 +6622,13 @@ var require_dist = __commonJS(function(exports, module) {
6622
6622
 
6623
6623
  // packages/workit-codex/scripts/launch-mcp.ts
6624
6624
  import { existsSync as existsSync10, realpathSync as realpathSync7, statSync as statSync3 } from "node:fs";
6625
- import path22 from "node:path";
6625
+ import path24 from "node:path";
6626
6626
  import { fileURLToPath as fileURLToPath3 } from "node:url";
6627
6627
 
6628
6628
  // packages/workit-core/src/core.ts
6629
6629
  import { spawnSync as spawnSync14 } from "node:child_process";
6630
6630
  import { existsSync as existsSync7, realpathSync as realpathSync5 } from "node:fs";
6631
- import path19 from "node:path";
6631
+ import path21 from "node:path";
6632
6632
 
6633
6633
  // packages/workit-core/src/core/task-contract.ts
6634
6634
  import { createHash, randomUUID } from "node:crypto";
@@ -15456,9 +15456,9 @@ function parseAdvertisedOperation(family, input, host) {
15456
15456
  });
15457
15457
  }
15458
15458
  // packages/workit-core/src/core/task-store.ts
15459
- import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
15460
- import * as fs7 from "node:fs";
15461
- import path6 from "node:path";
15459
+ import { createHash as createHash5, randomUUID as randomUUID3 } from "node:crypto";
15460
+ import * as fs8 from "node:fs";
15461
+ import path8 from "node:path";
15462
15462
 
15463
15463
  // node_modules/@openclaw/fs-safe/dist/errors.js
15464
15464
  var OPERATIONAL_CODES = new Set([
@@ -16061,8 +16061,14 @@ function acquireFileLockSync(targetPath, options) {
16061
16061
  }
16062
16062
  }
16063
16063
  }
16064
+ // packages/workit-core/src/host-session.ts
16065
+ import { createHash as createHash3, randomBytes as randomBytes2, timingSafeEqual } from "node:crypto";
16066
+ import fs5 from "node:fs";
16067
+ import path5 from "node:path";
16068
+
16064
16069
  // packages/workit-core/src/core/logger.ts
16065
16070
  import os from "node:os";
16071
+ import path3 from "node:path";
16066
16072
  var REDACTED = "[REDACTED]";
16067
16073
  var SECRET_VALUE = /\b(?:Bearer|Basic|Digest|Token)\s+\S+/gi;
16068
16074
  var KEY_EQ_VALUE = /\b([A-Za-z0-9_-]*(?:token|secret|password|passwd|apikey|api[_-]?key|authorization|credential|bearer)[A-Za-z0-9_-]*)([:=]\s*).+/gi;
@@ -16105,6 +16111,22 @@ var SENSITIVE_WORDS = new Set([
16105
16111
  ]);
16106
16112
  var STACK_WORDS = new Set(["stack", "stacktrace", "trace"]);
16107
16113
  var escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
16114
+ var resolveStateDir = () => {
16115
+ const override = process.env.WORKFLOW_TOOLKIT_STATE;
16116
+ if (override)
16117
+ return override;
16118
+ const home = os.homedir();
16119
+ if (process.env.XDG_STATE_HOME)
16120
+ return path3.join(process.env.XDG_STATE_HOME, "workit");
16121
+ switch (os.platform()) {
16122
+ case "darwin":
16123
+ return path3.join(home, "Library", "Application Support", "workit");
16124
+ case "win32":
16125
+ return path3.join(process.env.LOCALAPPDATA ?? path3.join(home, "AppData", "Local"), "workit");
16126
+ default:
16127
+ return path3.join(process.env.HOME ?? home, ".local", "state", "workit");
16128
+ }
16129
+ };
16108
16130
  var homePattern = new RegExp(`${escapeRegExp(os.homedir())}(?=[/\\\\]|$)|\\$HOME(?=[/\\\\]|$)`, "g");
16109
16131
  var applyPatterns = (value) => {
16110
16132
  let out = value;
@@ -16122,7 +16144,7 @@ var redactSecrets = (value) => applyPatterns(value);
16122
16144
  import { spawnSync } from "node:child_process";
16123
16145
  import { createHash as createHash2 } from "node:crypto";
16124
16146
  import fs4 from "node:fs";
16125
- import path3 from "node:path";
16147
+ import path4 from "node:path";
16126
16148
  var NOT_A_REPO = /not a git repository \(or any (of the parent directories|parent up to)/u;
16127
16149
  var gitRun = (cwd, args) => {
16128
16150
  const run = spawnSync("git", args, {
@@ -16164,14 +16186,14 @@ var DISCOVERY_ENV = [
16164
16186
  ];
16165
16187
  var isGitDir = (dir) => {
16166
16188
  try {
16167
- return fs4.statSync(path3.join(dir, "HEAD")).isFile() && fs4.statSync(path3.join(dir, "objects")).isDirectory() && fs4.statSync(path3.join(dir, "refs")).isDirectory();
16189
+ return fs4.statSync(path4.join(dir, "HEAD")).isFile() && fs4.statSync(path4.join(dir, "objects")).isDirectory() && fs4.statSync(path4.join(dir, "refs")).isDirectory();
16168
16190
  } catch {
16169
16191
  return false;
16170
16192
  }
16171
16193
  };
16172
16194
  var reftableRefs = (common) => {
16173
16195
  try {
16174
- return /^\s*refstorage\s*=\s*reftable\s*$/imu.test(fs4.readFileSync(path3.join(common, "config"), "utf8"));
16196
+ return /^\s*refstorage\s*=\s*reftable\s*$/imu.test(fs4.readFileSync(path4.join(common, "config"), "utf8"));
16175
16197
  } catch {
16176
16198
  return false;
16177
16199
  }
@@ -16191,7 +16213,7 @@ function fastGit(root) {
16191
16213
  if (device !== null && stat.dev !== device)
16192
16214
  return { kind: "none" };
16193
16215
  device = stat.dev;
16194
- const dotGit = path3.join(dir, ".git");
16216
+ const dotGit = path4.join(dir, ".git");
16195
16217
  let entry = null;
16196
16218
  try {
16197
16219
  entry = fs4.statSync(dotGit);
@@ -16212,19 +16234,19 @@ function fastGit(root) {
16212
16234
  const match = /^gitdir: (.+)$/mu.exec(text);
16213
16235
  if (!match)
16214
16236
  return null;
16215
- gitDir = path3.resolve(dir, match[1].trim());
16237
+ gitDir = path4.resolve(dir, match[1].trim());
16216
16238
  } else
16217
16239
  return null;
16218
- if (!fs4.existsSync(path3.join(gitDir, "HEAD")))
16240
+ if (!fs4.existsSync(path4.join(gitDir, "HEAD")))
16219
16241
  return null;
16220
16242
  } else if (isGitDir(dir))
16221
16243
  gitDir = dir;
16222
16244
  if (gitDir) {
16223
16245
  let common = gitDir;
16224
16246
  try {
16225
- common = path3.resolve(gitDir, fs4.readFileSync(path3.join(gitDir, "commondir"), "utf8").trim());
16247
+ common = path4.resolve(gitDir, fs4.readFileSync(path4.join(gitDir, "commondir"), "utf8").trim());
16226
16248
  } catch {}
16227
- if (!fs4.existsSync(path3.join(common, "objects")))
16249
+ if (!fs4.existsSync(path4.join(common, "objects")))
16228
16250
  return null;
16229
16251
  return {
16230
16252
  kind: "repo",
@@ -16234,26 +16256,26 @@ function fastGit(root) {
16234
16256
  reftable: reftableRefs(common)
16235
16257
  };
16236
16258
  }
16237
- const parent = path3.dirname(dir);
16259
+ const parent = path4.dirname(dir);
16238
16260
  if (parent === dir)
16239
16261
  return { kind: "none" };
16240
16262
  dir = parent;
16241
16263
  }
16242
16264
  }
16243
16265
  function resolveStore(root) {
16244
- root = path3.resolve(root);
16266
+ root = path4.resolve(root);
16245
16267
  let directory = false;
16246
16268
  try {
16247
16269
  directory = fs4.statSync(root).isDirectory();
16248
16270
  } catch {}
16249
16271
  if (!directory)
16250
- return { dir: path3.join(root, ".workit"), shared: false, top: null };
16272
+ return { dir: path4.join(root, ".workit"), shared: false, top: null };
16251
16273
  const fast = fastGit(root);
16252
16274
  if (fast?.kind === "none")
16253
- return { dir: path3.join(root, ".workit"), shared: false, top: null };
16275
+ return { dir: path4.join(root, ".workit"), shared: false, top: null };
16254
16276
  if (fast?.kind === "repo")
16255
16277
  return {
16256
- dir: path3.join(fast.common, "workit"),
16278
+ dir: path4.join(fast.common, "workit"),
16257
16279
  shared: true,
16258
16280
  top: fast.top,
16259
16281
  git: { gitDir: fast.gitDir, top: fast.top, reftable: fast.reftable }
@@ -16263,20 +16285,20 @@ function resolveStore(root) {
16263
16285
  if (run.ok && common) {
16264
16286
  const top = gitRun(root, ["rev-parse", "--path-format=absolute", "--show-toplevel"]);
16265
16287
  return {
16266
- dir: path3.join(real(path3.resolve(root, common)), "workit"),
16288
+ dir: path4.join(real(path4.resolve(root, common)), "workit"),
16267
16289
  shared: true,
16268
16290
  top: top.ok && top.stdout.trim() ? real(top.stdout.trim()) : null
16269
16291
  };
16270
16292
  }
16271
16293
  if (run.missing || !run.ok && NOT_A_REPO.test(run.stderr))
16272
- return { dir: path3.join(root, ".workit"), shared: false, top: null };
16294
+ return { dir: path4.join(root, ".workit"), shared: false, top: null };
16273
16295
  return new Error(`cannot locate the workit store: git rev-parse failed (${run.stderr.trim().split(`
16274
16296
  `)[0] || "no output"}); fix the repository (git status should work here)`);
16275
16297
  }
16276
16298
  var rebasingBranch = (gitDir) => {
16277
16299
  for (const state of ["rebase-merge", "rebase-apply"]) {
16278
16300
  try {
16279
- const ref = fs4.readFileSync(path3.join(gitDir, state, "head-name"), "utf8").trim();
16301
+ const ref = fs4.readFileSync(path4.join(gitDir, state, "head-name"), "utf8").trim();
16280
16302
  const match = /^refs\/heads\/(.+)$/u.exec(ref);
16281
16303
  if (match)
16282
16304
  return match[1];
@@ -16291,7 +16313,7 @@ function resolveTaskKey(root, location) {
16291
16313
  if (location.git && !location.git.reftable) {
16292
16314
  let head = "";
16293
16315
  try {
16294
- head = fs4.readFileSync(path3.join(location.git.gitDir, "HEAD"), "utf8").trim();
16316
+ head = fs4.readFileSync(path4.join(location.git.gitDir, "HEAD"), "utf8").trim();
16295
16317
  } catch {}
16296
16318
  const ref = /^ref: refs\/heads\/(.+)$/u.exec(head);
16297
16319
  if (ref && ref[1] !== ".invalid")
@@ -16322,7 +16344,7 @@ function resolveTaskKey(root, location) {
16322
16344
  return { key: `detached-${shortHash(real(worktree))}`, kind: "detached", branch: null };
16323
16345
  }
16324
16346
  function checkoutRootOf(root, location) {
16325
- const resolved = path3.resolve(root);
16347
+ const resolved = path4.resolve(root);
16326
16348
  let canonical = resolved;
16327
16349
  try {
16328
16350
  canonical = fs4.realpathSync(resolved);
@@ -16353,13 +16375,13 @@ function branchRenames(location) {
16353
16375
  }
16354
16376
  for (const entry of entries)
16355
16377
  if (entry.isDirectory())
16356
- walk(path3.join(dir, entry.name));
16378
+ walk(path4.join(dir, entry.name));
16357
16379
  else
16358
- files.push(path3.join(dir, entry.name));
16380
+ files.push(path4.join(dir, entry.name));
16359
16381
  };
16360
- walk(path3.join(path3.dirname(location.dir), "logs", "refs", "heads"));
16382
+ walk(path4.join(path4.dirname(location.dir), "logs", "refs", "heads"));
16361
16383
  if (location.git)
16362
- files.push(path3.join(location.git.gitDir, "logs", "HEAD"));
16384
+ files.push(path4.join(location.git.gitDir, "logs", "HEAD"));
16363
16385
  const seen = new Set;
16364
16386
  const renames = [];
16365
16387
  for (const file of files) {
@@ -16394,7 +16416,7 @@ var checkoutSlug = (root) => {
16394
16416
  let canonical = real(root);
16395
16417
  if (process.platform === "win32")
16396
16418
  canonical = canonical.toLowerCase();
16397
- const base = path3.basename(canonical).replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 40) || "root";
16419
+ const base = path4.basename(canonical).replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 40) || "root";
16398
16420
  return `${base}-${shortHash(canonical)}`;
16399
16421
  };
16400
16422
 
@@ -16426,30 +16448,113 @@ function hostSessionFromEnv(env) {
16426
16448
  }
16427
16449
  return inner ? { host: inner.host, session: inner.session } : { host: declared, session: null };
16428
16450
  }
16451
+ var hash = (value) => createHash3("sha256").update(value).digest("hex").slice(0, 32);
16452
+ var userIssuedRoot = () => path5.join(resolveStateDir(), "issued");
16453
+ var userTokenRoot = () => path5.join(resolveStateDir(), "issued-tokens");
16454
+ function migrateRepoIssued(cwd) {
16455
+ if (cwd === undefined)
16456
+ return;
16457
+ let old;
16458
+ try {
16459
+ const location = resolveStore(cwd);
16460
+ if (location instanceof Error)
16461
+ return;
16462
+ old = path5.join(location.dir, "hooks", "issued");
16463
+ if (!fs5.existsSync(old))
16464
+ return;
16465
+ } catch {
16466
+ return;
16467
+ }
16468
+ for (const lead of safeList(old)) {
16469
+ try {
16470
+ const from = path5.join(old, lead);
16471
+ if (!fs5.statSync(from).isDirectory())
16472
+ continue;
16473
+ const to = path5.join(userIssuedRoot(), lead);
16474
+ fs5.mkdirSync(to, { recursive: true, mode: 448 });
16475
+ for (const id of fs5.readdirSync(from)) {
16476
+ try {
16477
+ fs5.copyFileSync(path5.join(from, id), path5.join(to, id), fs5.constants.COPYFILE_EXCL);
16478
+ } catch (error) {
16479
+ if (error.code !== "EEXIST")
16480
+ throw error;
16481
+ }
16482
+ fs5.rmSync(path5.join(from, id), { force: true });
16483
+ }
16484
+ removeIfEmpty(from);
16485
+ } catch {}
16486
+ }
16487
+ removeIfEmpty(old);
16488
+ }
16489
+ var safeList = (dir) => {
16490
+ try {
16491
+ return fs5.readdirSync(dir);
16492
+ } catch {
16493
+ return [];
16494
+ }
16495
+ };
16496
+ var removeIfEmpty = (dir) => {
16497
+ try {
16498
+ fs5.rmdirSync(dir);
16499
+ } catch {}
16500
+ };
16501
+ var issuedRecord = (cwd, claimed) => {
16502
+ const cut = claimed.lastIndexOf(":");
16503
+ if (cut <= 0)
16504
+ return null;
16505
+ migrateRepoIssued(cwd);
16506
+ try {
16507
+ return fs5.readFileSync(path5.join(userIssuedRoot(), hash(claimed.slice(0, cut)), hash(claimed)), "utf8");
16508
+ } catch {
16509
+ return null;
16510
+ }
16511
+ };
16512
+ var TOKEN_HASH = /^([0-9a-f]{64})$/mu;
16513
+ var issuedToken = (claimed) => {
16514
+ const cut = claimed.lastIndexOf(":");
16515
+ if (cut <= 0)
16516
+ return { stored: null, leadBound: false };
16517
+ const dir = path5.join(userTokenRoot(), hash(claimed.slice(0, cut)));
16518
+ try {
16519
+ const text = fs5.readFileSync(path5.join(dir, hash(claimed)), "utf8");
16520
+ return { stored: TOKEN_HASH.exec(text)?.[1] ?? null, leadBound: true };
16521
+ } catch {
16522
+ return { stored: null, leadBound: safeList(dir).length > 0 };
16523
+ }
16524
+ };
16525
+ function issuedBinding(cwd, claimed) {
16526
+ const record = issuedRecord(cwd, claimed);
16527
+ const { stored, leadBound } = issuedToken(claimed);
16528
+ if (stored)
16529
+ return "token";
16530
+ if (record === null)
16531
+ return null;
16532
+ return leadBound ? "token" : "legacy";
16533
+ }
16429
16534
  var OWN_CHILD_SHELL = new Set(["opencode", "pi"]);
16430
16535
 
16431
16536
  // packages/workit-core/src/core/package-root.ts
16432
16537
  import { existsSync } from "node:fs";
16433
- import path4 from "node:path";
16538
+ import path6 from "node:path";
16434
16539
  import { fileURLToPath } from "node:url";
16435
16540
  var packageRoot = () => {
16436
- let dir = path4.dirname(fileURLToPath(import.meta.url));
16541
+ let dir = path6.dirname(fileURLToPath(import.meta.url));
16437
16542
  while (true) {
16438
- const parent = path4.dirname(dir);
16439
- if (existsSync(path4.join(dir, "package.json")) || parent === dir)
16543
+ const parent = path6.dirname(dir);
16544
+ if (existsSync(path6.join(dir, "package.json")) || parent === dir)
16440
16545
  return dir;
16441
16546
  dir = parent;
16442
16547
  }
16443
16548
  };
16444
16549
  var assetRoot = () => {
16445
16550
  const root = packageRoot();
16446
- const assets = path4.join(root, "assets");
16551
+ const assets = path6.join(root, "assets");
16447
16552
  return existsSync(assets) ? assets : root;
16448
16553
  };
16449
16554
 
16450
16555
  // packages/workit-core/src/core/store-lock.ts
16451
16556
  import { spawnSync as spawnSync2 } from "node:child_process";
16452
- import fs5 from "node:fs";
16557
+ import fs6 from "node:fs";
16453
16558
  import { hostname } from "node:os";
16454
16559
  var metadataLockSchema = object({
16455
16560
  pid: number2().int().nonnegative().safe(),
@@ -16461,8 +16566,10 @@ var metadataLockSchema = object({
16461
16566
  var FOREIGN_LOCK_TTL_MS = 10 * 60000;
16462
16567
  var UNREADABLE_LOCK_TTL_MS = 30000;
16463
16568
  var RECLAIM_GUARD_TTL_MS = 30000;
16464
- var defaultLockTimeoutMs = 250;
16569
+ var IN_PROCESS_LOCK_TIMEOUT_MS = 250;
16570
+ var defaultLockTimeoutMs = IN_PROCESS_LOCK_TIMEOUT_MS;
16465
16571
  var defaultLockTimeout = () => defaultLockTimeoutMs;
16572
+ var hostAwareLockTimeout = (cliMs) => defaultLockTimeoutMs > IN_PROCESS_LOCK_TIMEOUT_MS ? cliMs : IN_PROCESS_LOCK_TIMEOUT_MS;
16466
16573
  var parseMetadataLock = (raw) => {
16467
16574
  let value;
16468
16575
  try {
@@ -16491,7 +16598,7 @@ var parseProcStatStart = (stat) => {
16491
16598
  var processStartOf = (pid) => {
16492
16599
  if (process.platform === "linux") {
16493
16600
  try {
16494
- return parseProcStatStart(fs5.readFileSync(`/proc/${pid}/stat`, "utf8"));
16601
+ return parseProcStatStart(fs6.readFileSync(`/proc/${pid}/stat`, "utf8"));
16495
16602
  } catch {
16496
16603
  return null;
16497
16604
  }
@@ -16512,7 +16619,7 @@ var processStartOf = (pid) => {
16512
16619
  };
16513
16620
  var readTrimmed = (file) => {
16514
16621
  try {
16515
- return fs5.readFileSync(file, "utf8").trim() || null;
16622
+ return fs6.readFileSync(file, "utf8").trim() || null;
16516
16623
  } catch {
16517
16624
  return null;
16518
16625
  }
@@ -16523,7 +16630,7 @@ var localLockHost = () => {
16523
16630
  return cachedLockHost;
16524
16631
  let pidns = null;
16525
16632
  try {
16526
- pidns = /\[(\d+)\]/.exec(fs5.readlinkSync("/proc/self/ns/pid"))?.[1] ?? null;
16633
+ pidns = /\[(\d+)\]/.exec(fs6.readlinkSync("/proc/self/ns/pid"))?.[1] ?? null;
16527
16634
  } catch {}
16528
16635
  const boot = readTrimmed("/proc/sys/kernel/random/boot_id");
16529
16636
  cachedLockHost = pidns || boot ? `${hostname()}#${pidns ?? "?"}:${boot ?? "?"}` : hostname();
@@ -16569,7 +16676,7 @@ var classifyLockOwner = (payload, ageMs, localHost = localLockHost(), options =
16569
16676
  };
16570
16677
  var ageOf = (file, nowMs) => {
16571
16678
  try {
16572
- return nowMs - fs5.lstatSync(file).mtimeMs;
16679
+ return nowMs - fs6.lstatSync(file).mtimeMs;
16573
16680
  } catch {
16574
16681
  return null;
16575
16682
  }
@@ -16580,7 +16687,7 @@ var clearAbandonedReclaimGuard = (lockPath, nowMs = Date.now()) => {
16580
16687
  if (age === null || age <= RECLAIM_GUARD_TTL_MS)
16581
16688
  return false;
16582
16689
  try {
16583
- fs5.rmdirSync(guard);
16690
+ fs6.rmdirSync(guard);
16584
16691
  return true;
16585
16692
  } catch {
16586
16693
  return false;
@@ -16589,8 +16696,8 @@ var clearAbandonedReclaimGuard = (lockPath, nowMs = Date.now()) => {
16589
16696
 
16590
16697
  // packages/workit-core/src/store/event-log.ts
16591
16698
  import { randomUUID as randomUUID2 } from "node:crypto";
16592
- import fs6 from "node:fs";
16593
- import path5 from "node:path";
16699
+ import fs7 from "node:fs";
16700
+ import path7 from "node:path";
16594
16701
  var EVENT_VERSION = 1;
16595
16702
 
16596
16703
  class LogDamage extends Error {
@@ -16619,7 +16726,7 @@ var parseEvent = (line, file, offset) => {
16619
16726
  function readLog(file, from = 0, expectSeq = null) {
16620
16727
  let fd;
16621
16728
  try {
16622
- fd = fs6.openSync(file, "r");
16729
+ fd = fs7.openSync(file, "r");
16623
16730
  } catch (error) {
16624
16731
  if (error.code === "ENOENT")
16625
16732
  return null;
@@ -16628,13 +16735,13 @@ function readLog(file, from = 0, expectSeq = null) {
16628
16735
  let bytes;
16629
16736
  let size;
16630
16737
  try {
16631
- size = fs6.fstatSync(fd).size;
16738
+ size = fs7.fstatSync(fd).size;
16632
16739
  if (from > size)
16633
16740
  throw new LogDamage(`${file}: shorter than its snapshot`);
16634
16741
  bytes = Buffer.alloc(size - from);
16635
16742
  let read = 0;
16636
16743
  while (read < bytes.length) {
16637
- const got = fs6.readSync(fd, bytes, read, bytes.length - read, from + read);
16744
+ const got = fs7.readSync(fd, bytes, read, bytes.length - read, from + read);
16638
16745
  if (got === 0)
16639
16746
  break;
16640
16747
  read += got;
@@ -16642,7 +16749,7 @@ function readLog(file, from = 0, expectSeq = null) {
16642
16749
  bytes = bytes.subarray(0, read);
16643
16750
  size = from + read;
16644
16751
  } finally {
16645
- fs6.closeSync(fd);
16752
+ fs7.closeSync(fd);
16646
16753
  }
16647
16754
  const events = [];
16648
16755
  let start = 0;
@@ -16667,11 +16774,11 @@ function readLog(file, from = 0, expectSeq = null) {
16667
16774
  }
16668
16775
  var fsyncDirectory = (dir) => {
16669
16776
  try {
16670
- const fd = fs6.openSync(dir, "r");
16777
+ const fd = fs7.openSync(dir, "r");
16671
16778
  try {
16672
- fs6.fsyncSync(fd);
16779
+ fs7.fsyncSync(fd);
16673
16780
  } finally {
16674
- fs6.closeSync(fd);
16781
+ fs7.closeSync(fd);
16675
16782
  }
16676
16783
  } catch (error) {
16677
16784
  if (process.platform !== "win32")
@@ -16681,46 +16788,46 @@ var fsyncDirectory = (dir) => {
16681
16788
  function appendEvent(file, event, validEnd) {
16682
16789
  const line = Buffer.from(`${JSON.stringify(event)}
16683
16790
  `, "utf8");
16684
- const created = !fs6.existsSync(file);
16685
- if (!created && fs6.statSync(file).size !== validEnd) {
16686
- const cut = fs6.openSync(file, "r+");
16791
+ const created = !fs7.existsSync(file);
16792
+ if (!created && fs7.statSync(file).size !== validEnd) {
16793
+ const cut = fs7.openSync(file, "r+");
16687
16794
  try {
16688
- fs6.ftruncateSync(cut, validEnd);
16689
- fs6.fsyncSync(cut);
16795
+ fs7.ftruncateSync(cut, validEnd);
16796
+ fs7.fsyncSync(cut);
16690
16797
  } finally {
16691
- fs6.closeSync(cut);
16798
+ fs7.closeSync(cut);
16692
16799
  }
16693
16800
  }
16694
- const fd = fs6.openSync(file, "a", 384);
16801
+ const fd = fs7.openSync(file, "a", 384);
16695
16802
  try {
16696
16803
  let written = 0;
16697
16804
  while (written < line.length)
16698
- written += fs6.writeSync(fd, line, written, line.length - written);
16699
- fs6.fsyncSync(fd);
16805
+ written += fs7.writeSync(fd, line, written, line.length - written);
16806
+ fs7.fsyncSync(fd);
16700
16807
  } finally {
16701
- fs6.closeSync(fd);
16808
+ fs7.closeSync(fd);
16702
16809
  }
16703
16810
  if (created)
16704
- fsyncDirectory(path5.dirname(file));
16811
+ fsyncDirectory(path7.dirname(file));
16705
16812
  return validEnd;
16706
16813
  }
16707
16814
  function replaceFile(file, bytes, durable) {
16708
16815
  const temporary = `${file}.${process.pid}.${randomUUID2()}.tmp`;
16709
16816
  try {
16710
- const fd = fs6.openSync(temporary, "wx", 384);
16817
+ const fd = fs7.openSync(temporary, "wx", 384);
16711
16818
  try {
16712
- fs6.writeSync(fd, bytes);
16819
+ fs7.writeSync(fd, bytes);
16713
16820
  if (durable)
16714
- fs6.fsyncSync(fd);
16821
+ fs7.fsyncSync(fd);
16715
16822
  } finally {
16716
- fs6.closeSync(fd);
16823
+ fs7.closeSync(fd);
16717
16824
  }
16718
16825
  renameWithRetry(temporary, file);
16719
16826
  if (durable)
16720
- fsyncDirectory(path5.dirname(file));
16827
+ fsyncDirectory(path7.dirname(file));
16721
16828
  } catch (error) {
16722
16829
  try {
16723
- fs6.unlinkSync(temporary);
16830
+ fs7.unlinkSync(temporary);
16724
16831
  } catch {}
16725
16832
  throw error;
16726
16833
  }
@@ -16745,7 +16852,7 @@ var retryTransient = (run) => {
16745
16852
  }
16746
16853
  }
16747
16854
  };
16748
- var renameWithRetry = (from, to) => retryTransient(() => fs6.renameSync(from, to));
16855
+ var renameWithRetry = (from, to) => retryTransient(() => fs7.renameSync(from, to));
16749
16856
 
16750
16857
  // packages/workit-core/src/store/patch.ts
16751
16858
  var isPlainObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
@@ -16858,7 +16965,7 @@ var isPatch = (value) => Array.isArray(value) && value.every((op) => {
16858
16965
  });
16859
16966
 
16860
16967
  // packages/workit-core/src/store/reduce.ts
16861
- import { createHash as createHash3 } from "node:crypto";
16968
+ import { createHash as createHash4 } from "node:crypto";
16862
16969
  var OPENING_TYPES = new Set([
16863
16970
  "task.opened",
16864
16971
  "task.imported",
@@ -16887,7 +16994,7 @@ var isObject4 = (value) => typeof value === "object" && value !== null && !Array
16887
16994
  var isKey = (value) => isObject4(value) && typeof value.key === "string" && (value.kind === "branch" || value.kind === "detached" || value.kind === "dir") && (value.branch === null || typeof value.branch === "string");
16888
16995
  var BLOB_REF = "$blob";
16889
16996
  var blobRef = (value) => isObject4(value) && Object.keys(value).length === 1 && typeof value[BLOB_REF] === "string" && /^[0-9a-f]{64}$/.test(value[BLOB_REF]) ? value[BLOB_REF] : null;
16890
- var blobDigest = (value) => createHash3("sha256").update(JSON.stringify(value)).digest("hex");
16997
+ var blobDigest = (value) => createHash4("sha256").update(JSON.stringify(value)).digest("hex");
16891
16998
  var toBlob = (value, blobs) => {
16892
16999
  if (!isObject4(value))
16893
17000
  return value;
@@ -17042,7 +17149,7 @@ var indexEntry = (task, key, legacy, file) => {
17042
17149
  };
17043
17150
  var fileSignature = (file) => {
17044
17151
  try {
17045
- const stat = fs7.statSync(file, { bigint: true });
17152
+ const stat = fs8.statSync(file, { bigint: true });
17046
17153
  return `${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeNs}:${stat.ctimeNs}`;
17047
17154
  } catch {
17048
17155
  return null;
@@ -17060,7 +17167,7 @@ var cachedRuntimeVersion = null;
17060
17167
  var runtimeVersion = () => {
17061
17168
  if (cachedRuntimeVersion === null) {
17062
17169
  try {
17063
- const pkg = JSON.parse(fs7.readFileSync(path6.join(packageRoot(), "package.json"), "utf8"));
17170
+ const pkg = JSON.parse(fs8.readFileSync(path8.join(packageRoot(), "package.json"), "utf8"));
17064
17171
  cachedRuntimeVersion = typeof pkg.version === "string" && pkg.version ? pkg.version : "0.0.0";
17065
17172
  } catch {
17066
17173
  cachedRuntimeVersion = "0.0.0";
@@ -17086,14 +17193,14 @@ var isNewerVersion = (candidate, current) => {
17086
17193
  var validId = (value) => /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(value);
17087
17194
  var readText = (file) => {
17088
17195
  try {
17089
- return fs7.readFileSync(file, "utf8");
17196
+ return fs8.readFileSync(file, "utf8");
17090
17197
  } catch {
17091
17198
  return "";
17092
17199
  }
17093
17200
  };
17094
17201
  var REFLOG_LINE = /^[0-9a-f]+ ([0-9a-f]+) .* (\d+) [+-]\d{4}\t(.*)$/u;
17095
17202
  var branchStart = (location, branch, aliases) => {
17096
- const first = readText(path6.join(path6.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
17203
+ const first = readText(path8.join(path8.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
17097
17204
  `, 1)[0];
17098
17205
  const created = REFLOG_LINE.exec(first);
17099
17206
  const start = created && /^branch: Created from (\S+)$/u.exec(created[3])?.[1];
@@ -17103,7 +17210,7 @@ var branchStart = (location, branch, aliases) => {
17103
17210
  return start;
17104
17211
  if (!location.git)
17105
17212
  return null;
17106
- for (const line of readText(path6.join(location.git.gitDir, "logs", "HEAD")).split(`
17213
+ for (const line of readText(path8.join(location.git.gitDir, "logs", "HEAD")).split(`
17107
17214
  `)) {
17108
17215
  const entry = REFLOG_LINE.exec(line);
17109
17216
  const moved = entry && /^checkout: moving from (\S+) to (\S+)$/u.exec(entry[3]);
@@ -17113,23 +17220,23 @@ var branchStart = (location, branch, aliases) => {
17113
17220
  }
17114
17221
  return null;
17115
17222
  };
17116
- var refExists = (common, ref) => fs7.existsSync(path6.join(common, ref)) || readText(path6.join(common, "packed-refs")).includes(` ${ref}
17223
+ var refExists = (common, ref) => fs8.existsSync(path8.join(common, ref)) || readText(path8.join(common, "packed-refs")).includes(` ${ref}
17117
17224
  `);
17118
17225
  var origins = new Map;
17119
17226
  var sameDirectoryIdentity = (left, right) => {
17120
- if (!path6.isAbsolute(left) || !path6.isAbsolute(right))
17227
+ if (!path8.isAbsolute(left) || !path8.isAbsolute(right))
17121
17228
  return false;
17122
- const normalizedLeft = path6.resolve(left);
17123
- const normalizedRight = path6.resolve(right);
17229
+ const normalizedLeft = path8.resolve(left);
17230
+ const normalizedRight = path8.resolve(right);
17124
17231
  try {
17125
- const a = fs7.statSync(normalizedLeft, { bigint: true });
17126
- const b = fs7.statSync(normalizedRight, { bigint: true });
17232
+ const a = fs8.statSync(normalizedLeft, { bigint: true });
17233
+ const b = fs8.statSync(normalizedRight, { bigint: true });
17127
17234
  if (!a.isDirectory() || !b.isDirectory())
17128
17235
  return false;
17129
17236
  if (process.platform === "win32" ? normalizedLeft.toLowerCase() === normalizedRight.toLowerCase() : normalizedLeft === normalizedRight)
17130
17237
  return true;
17131
- const canonicalLeft = fs7.realpathSync(normalizedLeft);
17132
- const canonicalRight = fs7.realpathSync(normalizedRight);
17238
+ const canonicalLeft = fs8.realpathSync(normalizedLeft);
17239
+ const canonicalRight = fs8.realpathSync(normalizedRight);
17133
17240
  if (process.platform === "win32" ? canonicalLeft.toLowerCase() === canonicalRight.toLowerCase() : canonicalLeft === canonicalRight)
17134
17241
  return true;
17135
17242
  return a.dev === b.dev && a.ino !== 0n && a.ino === b.ino;
@@ -17166,8 +17273,8 @@ class TaskStore {
17166
17273
  migrationChecked = false;
17167
17274
  compactDue = new Set;
17168
17275
  constructor(root, options = {}) {
17169
- const resolved = path6.resolve(root);
17170
- this.origin = fs7.existsSync(resolved) ? fs7.realpathSync(resolved) : resolved;
17276
+ const resolved = path8.resolve(root);
17277
+ this.origin = fs8.existsSync(resolved) ? fs8.realpathSync(resolved) : resolved;
17171
17278
  this.located = resolveStore(this.origin);
17172
17279
  this.root = checkoutRootOf(this.origin, this.located);
17173
17280
  this.lockTimeoutMs = options.lockTimeoutMs ?? defaultLockTimeout();
@@ -17175,7 +17282,7 @@ class TaskStore {
17175
17282
  this.migrateOnRead = options.migrateOnRead;
17176
17283
  }
17177
17284
  location() {
17178
- if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs7.existsSync(path6.join(this.root, ".git"))) {
17285
+ if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs8.existsSync(path8.join(this.root, ".git"))) {
17179
17286
  this.located = undefined;
17180
17287
  this.migrationChecked = false;
17181
17288
  }
@@ -17239,7 +17346,7 @@ class TaskStore {
17239
17346
  const tasksDir = this.paths().tasks;
17240
17347
  let names;
17241
17348
  try {
17242
- names = fs7.existsSync(tasksDir) ? fs7.readdirSync(tasksDir).filter((name) => validId(name)) : [];
17349
+ names = fs8.existsSync(tasksDir) ? fs8.readdirSync(tasksDir).filter((name) => validId(name)) : [];
17243
17350
  } catch (error) {
17244
17351
  return failure2("storage_error", `unable to list tasks: ${String(error)}`, {
17245
17352
  path: tasksDir
@@ -17280,7 +17387,7 @@ class TaskStore {
17280
17387
  const file = this.paths().workspace;
17281
17388
  let bytes;
17282
17389
  try {
17283
- bytes = retryTransient(() => fs7.readFileSync(file, "utf8"));
17390
+ bytes = retryTransient(() => fs8.readFileSync(file, "utf8"));
17284
17391
  } catch (error) {
17285
17392
  if (error.code === "ENOENT")
17286
17393
  return success(null, null, null);
@@ -17331,7 +17438,7 @@ class TaskStore {
17331
17438
  const moved = this.bindLocked(again.data.id, key, input.now);
17332
17439
  return moved.ok ? success(moved.data.revision, null, { task: moved.data, created: false, key }) : moved;
17333
17440
  }
17334
- const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path6.basename(this.root) || this.root;
17441
+ const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path8.basename(this.root) || this.root;
17335
17442
  const intent = {
17336
17443
  objective: input.objective?.trim() || `Work on ${label}`,
17337
17444
  scope: { description: `the checkout (${label})`, paths: ["."], exclusions: [] },
@@ -17391,14 +17498,14 @@ class TaskStore {
17391
17498
  const branch = key.ok ? key.data.branch : null;
17392
17499
  if (!branch || !location.ok)
17393
17500
  return success(null, null, null);
17394
- const common = path6.dirname(location.data.dir);
17395
- const heads = path6.join(common, "logs", "refs", "heads");
17396
- const headLog = location.data.git ? path6.join(location.data.git.gitDir, "logs", "HEAD") : "";
17501
+ const common = path8.dirname(location.data.dir);
17502
+ const heads = path8.join(common, "logs", "refs", "heads");
17503
+ const headLog = location.data.git ? path8.join(location.data.git.gitDir, "logs", "HEAD") : "";
17397
17504
  const signatures = [
17398
- path6.join(heads, branch),
17505
+ path8.join(heads, branch),
17399
17506
  headLog,
17400
17507
  heads,
17401
- path6.join(common, "packed-refs")
17508
+ path8.join(common, "packed-refs")
17402
17509
  ].map((file) => fileSignature(file) ?? "-");
17403
17510
  const slot = `${location.data.dir}\x00${headLog}\x00${branch}`;
17404
17511
  let resolved = origins.get(slot);
@@ -17410,7 +17517,7 @@ class TaskStore {
17410
17517
  aliases.push(rename.from);
17411
17518
  const start = branchStart(location.data, branch, aliases);
17412
17519
  const slash = start?.indexOf("/") ?? -1;
17413
- const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(path6.join(common, "config")).includes(`[remote "${start.slice(0, slash)}"]`));
17520
+ const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(path8.join(common, "config")).includes(`[remote "${start.slice(0, slash)}"]`));
17414
17521
  const name = start && (remote ? start.slice(slash + 1) : start);
17415
17522
  resolved = {
17416
17523
  signature: signatures.join("|"),
@@ -17648,13 +17755,13 @@ class TaskStore {
17648
17755
  if (!ready.ok)
17649
17756
  return ready;
17650
17757
  const dirs = this.paths();
17651
- const recovery = path6.join(this.root, ".workit", "recovery");
17652
- if (fs7.existsSync(recovery)) {
17758
+ const recovery = path8.join(this.root, ".workit", "recovery");
17759
+ if (fs8.existsSync(recovery)) {
17653
17760
  let files = 0;
17654
17761
  let bytes = 0;
17655
17762
  try {
17656
- for (const name of fs7.readdirSync(recovery)) {
17657
- const stat = fs7.lstatSync(path6.join(recovery, name));
17763
+ for (const name of fs8.readdirSync(recovery)) {
17764
+ const stat = fs8.lstatSync(path8.join(recovery, name));
17658
17765
  if (!stat.isFile())
17659
17766
  continue;
17660
17767
  files += 1;
@@ -17663,17 +17770,17 @@ class TaskStore {
17663
17770
  } catch {}
17664
17771
  const remove = options.pruneRecovery === true && !dryRun;
17665
17772
  if (remove)
17666
- fs7.rmSync(recovery, { recursive: true, force: true });
17773
+ fs8.rmSync(recovery, { recursive: true, force: true });
17667
17774
  report.legacyRecovery = { path: recovery, files, bytes, removed: remove };
17668
17775
  }
17669
- if (!fs7.existsSync(dirs.tasks))
17776
+ if (!fs8.existsSync(dirs.tasks))
17670
17777
  return success(null, null, report);
17671
- const names = fs7.readdirSync(dirs.tasks).filter((name) => validId(name));
17778
+ const names = fs8.readdirSync(dirs.tasks).filter((name) => validId(name));
17672
17779
  for (const name of names) {
17673
17780
  const file = this.eventsPath(name);
17674
17781
  let size = 0;
17675
17782
  try {
17676
- size = fs7.statSync(file).size;
17783
+ size = fs8.statSync(file).size;
17677
17784
  } catch {
17678
17785
  continue;
17679
17786
  }
@@ -17701,16 +17808,16 @@ class TaskStore {
17701
17808
  const references = new Set;
17702
17809
  for (const name of names)
17703
17810
  try {
17704
- for (const match of fs7.readFileSync(this.eventsPath(name), "utf8").matchAll(/"\$blob":"([0-9a-f]{64})"/g))
17811
+ for (const match of fs8.readFileSync(this.eventsPath(name), "utf8").matchAll(/"\$blob":"([0-9a-f]{64})"/g))
17705
17812
  references.add(match[1]);
17706
17813
  } catch {}
17707
- if (fs7.existsSync(dirs.blobs))
17708
- for (const name of fs7.readdirSync(dirs.blobs)) {
17814
+ if (fs8.existsSync(dirs.blobs))
17815
+ for (const name of fs8.readdirSync(dirs.blobs)) {
17709
17816
  const digest = name.replace(/\.json$/, "");
17710
- const file = path6.join(dirs.blobs, name);
17817
+ const file = path8.join(dirs.blobs, name);
17711
17818
  let stat;
17712
17819
  try {
17713
- stat = fs7.lstatSync(file);
17820
+ stat = fs8.lstatSync(file);
17714
17821
  } catch {
17715
17822
  continue;
17716
17823
  }
@@ -17721,11 +17828,11 @@ class TaskStore {
17721
17828
  report.blobs.removed += 1;
17722
17829
  report.blobs.removedBytes += stat.size;
17723
17830
  if (!dryRun)
17724
- fs7.rmSync(file, { force: true });
17831
+ fs8.rmSync(file, { force: true });
17725
17832
  }
17726
17833
  return success(null, null, null);
17727
17834
  };
17728
- const swept = dryRun ? sweep() : this.withLock(path6.join(dirs.dir, "gc.lock"), sweep);
17835
+ const swept = dryRun ? sweep() : this.withLock(path8.join(dirs.dir, "gc.lock"), sweep);
17729
17836
  if (!swept.ok)
17730
17837
  return swept;
17731
17838
  const temporaryDirs = [
@@ -17733,17 +17840,17 @@ class TaskStore {
17733
17840
  dirs.tasks,
17734
17841
  dirs.blobs,
17735
17842
  dirs.checkout,
17736
- ...names.map((name) => path6.join(dirs.tasks, name))
17843
+ ...names.map((name) => path8.join(dirs.tasks, name))
17737
17844
  ];
17738
17845
  for (const directory of temporaryDirs) {
17739
- if (!fs7.existsSync(directory))
17846
+ if (!fs8.existsSync(directory))
17740
17847
  continue;
17741
- for (const name of fs7.readdirSync(directory)) {
17848
+ for (const name of fs8.readdirSync(directory)) {
17742
17849
  if (!name.endsWith(".tmp") && !name.endsWith(".probe"))
17743
17850
  continue;
17744
- const file = path6.join(directory, name);
17851
+ const file = path8.join(directory, name);
17745
17852
  try {
17746
- const stat = fs7.lstatSync(file);
17853
+ const stat = fs8.lstatSync(file);
17747
17854
  if (!stat.isFile() || nowMs - stat.mtimeMs <= STALE_TEMPORARY_MS)
17748
17855
  continue;
17749
17856
  } catch {
@@ -17751,37 +17858,37 @@ class TaskStore {
17751
17858
  }
17752
17859
  report.temporary.removed += 1;
17753
17860
  if (!dryRun)
17754
- fs7.rmSync(file, { force: true });
17861
+ fs8.rmSync(file, { force: true });
17755
17862
  }
17756
17863
  }
17757
17864
  return success(null, null, report);
17758
17865
  }
17759
17866
  paths() {
17760
17867
  const location = this.location();
17761
- const dir = location.ok ? location.data.dir : path6.join(this.root, ".workit");
17762
- const checkout = path6.join(dir, "checkouts", checkoutSlug(this.root));
17868
+ const dir = location.ok ? location.data.dir : path8.join(this.root, ".workit");
17869
+ const checkout = path8.join(dir, "checkouts", checkoutSlug(this.root));
17763
17870
  return {
17764
17871
  dir,
17765
17872
  shared: location.ok ? location.data.shared : false,
17766
- marker: path6.join(dir, "store.json"),
17873
+ marker: path8.join(dir, "store.json"),
17767
17874
  checkout,
17768
- workspace: path6.join(checkout, "workspace.json"),
17769
- checkoutLock: path6.join(checkout, "metadata.lock"),
17770
- tasks: path6.join(dir, "tasks"),
17771
- index: path6.join(dir, "task-index.json"),
17772
- blobs: path6.join(dir, "blobs", "candidates"),
17773
- legacy: path6.join(dir, "legacy", checkoutSlug(this.root), "v2"),
17774
- v2: path6.join(this.root, ".workit")
17875
+ workspace: path8.join(checkout, "workspace.json"),
17876
+ checkoutLock: path8.join(checkout, "metadata.lock"),
17877
+ tasks: path8.join(dir, "tasks"),
17878
+ index: path8.join(dir, "task-index.json"),
17879
+ blobs: path8.join(dir, "blobs", "candidates"),
17880
+ legacy: path8.join(dir, "legacy", checkoutSlug(this.root), "v2"),
17881
+ v2: path8.join(this.root, ".workit")
17775
17882
  };
17776
17883
  }
17777
17884
  eventsPath(taskId) {
17778
- return path6.join(this.paths().tasks, taskId, "events.jsonl");
17885
+ return path8.join(this.paths().tasks, taskId, "events.jsonl");
17779
17886
  }
17780
17887
  snapshotPath(taskId) {
17781
- return path6.join(this.paths().tasks, taskId, "snapshot.json");
17888
+ return path8.join(this.paths().tasks, taskId, "snapshot.json");
17782
17889
  }
17783
17890
  taskLockPath(taskId) {
17784
- return path6.join(this.paths().tasks, taskId, "lock");
17891
+ return path8.join(this.paths().tasks, taskId, "lock");
17785
17892
  }
17786
17893
  ready(write = false) {
17787
17894
  const location = this.location();
@@ -17791,7 +17898,7 @@ class TaskStore {
17791
17898
  return success(null, null, null);
17792
17899
  const dirs = this.paths();
17793
17900
  try {
17794
- const marker = JSON.parse(fs7.readFileSync(dirs.marker, "utf8"));
17901
+ const marker = JSON.parse(fs8.readFileSync(dirs.marker, "utf8"));
17795
17902
  if (typeof marker.version === "number" && marker.version > STORE_FORMAT)
17796
17903
  return failure2("recovery_required", `the workit store at ${dirs.dir} has format ${marker.version}; upgrade Workit to use it`, { path: dirs.marker });
17797
17904
  } catch {}
@@ -17820,21 +17927,21 @@ class TaskStore {
17820
17927
  return {
17821
17928
  read: (digest) => {
17822
17929
  try {
17823
- return JSON.parse(fs7.readFileSync(path6.join(dir, `${digest}.json`), "utf8"));
17930
+ return JSON.parse(fs8.readFileSync(path8.join(dir, `${digest}.json`), "utf8"));
17824
17931
  } catch (error) {
17825
17932
  throw new LogDamage(`stored candidate ${digest} is missing or unreadable: ${String(error)}`);
17826
17933
  }
17827
17934
  },
17828
17935
  write: (digest, value) => {
17829
- const file = path6.join(dir, `${digest}.json`);
17830
- if (fs7.existsSync(file)) {
17936
+ const file = path8.join(dir, `${digest}.json`);
17937
+ if (fs8.existsSync(file)) {
17831
17938
  const stamp = new Date;
17832
17939
  try {
17833
- fs7.utimesSync(file, stamp, stamp);
17940
+ fs8.utimesSync(file, stamp, stamp);
17834
17941
  return;
17835
17942
  } catch {}
17836
17943
  }
17837
- fs7.mkdirSync(dir, { recursive: true });
17944
+ fs8.mkdirSync(dir, { recursive: true });
17838
17945
  replaceFile(file, JSON.stringify(value), true);
17839
17946
  }
17840
17947
  };
@@ -17916,7 +18023,7 @@ class TaskStore {
17916
18023
  }
17917
18024
  readSnapshot(taskId) {
17918
18025
  try {
17919
- const value = JSON.parse(fs7.readFileSync(this.snapshotPath(taskId), "utf8"));
18026
+ const value = JSON.parse(fs8.readFileSync(this.snapshotPath(taskId), "utf8"));
17920
18027
  if (!isObject5(value) || value.v !== 1 || value.task !== taskId || typeof value.seq !== "number" || typeof value.lastId !== "string" || typeof value.lastStart !== "number" || typeof value.end !== "number" || !isObject5(value.record))
17921
18028
  return null;
17922
18029
  return value;
@@ -18018,8 +18125,8 @@ class TaskStore {
18018
18125
  }
18019
18126
  }
18020
18127
  openTask(record, type, key, legacy = null) {
18021
- const dir = path6.join(this.paths().tasks, record.id);
18022
- fs7.mkdirSync(dir, { recursive: true });
18128
+ const dir = path8.join(this.paths().tasks, record.id);
18129
+ fs8.mkdirSync(dir, { recursive: true });
18023
18130
  const blobs = this.blobStore();
18024
18131
  const bound = key ? { ...key, boundAt: key.boundAt ?? new Date().toISOString() } : null;
18025
18132
  const event = this.event(record.id, 1, type, {
@@ -18071,11 +18178,11 @@ class TaskStore {
18071
18178
  } catch {}
18072
18179
  if (!latest || latest.events[0]?.id !== last.id)
18073
18180
  return failure2("busy", "the task log changed during compaction; retry", { taskId });
18074
- const appended = fs7.readFileSync(file).subarray(log.end, latest.end);
18181
+ const appended = fs8.readFileSync(file).subarray(log.end, latest.end);
18075
18182
  const bytes = Buffer.concat([Buffer.from(prefix, "utf8"), appended]);
18076
18183
  replaceFile(file, bytes.toString("utf8"), true);
18077
18184
  try {
18078
- fs7.rmSync(this.snapshotPath(taskId), { force: true });
18185
+ fs8.rmSync(this.snapshotPath(taskId), { force: true });
18079
18186
  } catch {}
18080
18187
  const reloaded = this.load(taskId);
18081
18188
  if (reloaded.ok && reloaded.data)
@@ -18088,7 +18195,7 @@ class TaskStore {
18088
18195
  }
18089
18196
  countEvents(file) {
18090
18197
  try {
18091
- const bytes = fs7.readFileSync(file);
18198
+ const bytes = fs8.readFileSync(file);
18092
18199
  let count = 0;
18093
18200
  for (let index = bytes.indexOf(10);index >= 0; index = bytes.indexOf(10, index + 1))
18094
18201
  count += 1;
@@ -18110,8 +18217,8 @@ class TaskStore {
18110
18217
  return bound.ok ? success(null, null, bound.data[0] ?? null) : bound;
18111
18218
  }
18112
18219
  withKeyLock(key, operation) {
18113
- const digest = createHash4("sha256").update(key).digest("hex").slice(0, 32);
18114
- return this.withLock(path6.join(this.paths().dir, "keys", `${digest}.lock`), operation);
18220
+ const digest = createHash5("sha256").update(key).digest("hex").slice(0, 32);
18221
+ return this.withLock(path8.join(this.paths().dir, "keys", `${digest}.lock`), operation);
18115
18222
  }
18116
18223
  bindLocked(taskId, key, timestamp) {
18117
18224
  const current = this.readWorkspace();
@@ -18252,7 +18359,7 @@ class TaskStore {
18252
18359
  writeWorkspace(record) {
18253
18360
  const file = this.paths().workspace;
18254
18361
  try {
18255
- fs7.mkdirSync(path6.dirname(file), { recursive: true });
18362
+ fs8.mkdirSync(path8.dirname(file), { recursive: true });
18256
18363
  replaceFile(file, `${canonicalJson(record)}
18257
18364
  `, true);
18258
18365
  return success(null, null, null);
@@ -18262,7 +18369,7 @@ class TaskStore {
18262
18369
  }
18263
18370
  readIndex() {
18264
18371
  try {
18265
- const value = JSON.parse(fs7.readFileSync(this.paths().index, "utf8"));
18372
+ const value = JSON.parse(fs8.readFileSync(this.paths().index, "utf8"));
18266
18373
  if (!isObject5(value) || value.version !== INDEX_VERSION || !isObject5(value.tasks))
18267
18374
  return {};
18268
18375
  const tasks = {};
@@ -18276,7 +18383,7 @@ class TaskStore {
18276
18383
  }
18277
18384
  writeIndex(entries) {
18278
18385
  try {
18279
- fs7.mkdirSync(this.paths().tasks, { recursive: true });
18386
+ fs8.mkdirSync(this.paths().tasks, { recursive: true });
18280
18387
  replaceFile(this.paths().index, JSON.stringify({
18281
18388
  version: INDEX_VERSION,
18282
18389
  tasks: Object.fromEntries(entries.map((entry) => [entry.id, entry]))
@@ -18330,23 +18437,23 @@ class TaskStore {
18330
18437
  return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", { expectedWorkspaceRevision: expected, actualWorkspaceRevision: actual });
18331
18438
  }
18332
18439
  v2Dirs() {
18333
- return [...new Set([this.root, this.origin])].map((dir) => path6.join(dir, ".workit"));
18440
+ return [...new Set([this.root, this.origin])].map((dir) => path8.join(dir, ".workit"));
18334
18441
  }
18335
18442
  pendingMigrations() {
18336
18443
  return this.v2Dirs().filter((dir) => {
18337
- const raw = this.readV2Workspace(path6.join(dir, "workspace.json"));
18444
+ const raw = this.readV2Workspace(path8.join(dir, "workspace.json"));
18338
18445
  return raw !== null && raw !== TOMBSTONE;
18339
18446
  });
18340
18447
  }
18341
18448
  migrateV2(v2) {
18342
18449
  const dirs = this.paths();
18343
- const v2Workspace = path6.join(v2, "workspace.json");
18344
- const v2Tasks = path6.join(v2, "tasks");
18345
- const legacy = path6.join(dirs.dir, "legacy", checkoutSlug(path6.dirname(v2)), "v2");
18450
+ const v2Workspace = path8.join(v2, "workspace.json");
18451
+ const v2Tasks = path8.join(v2, "tasks");
18452
+ const legacy = path8.join(dirs.dir, "legacy", checkoutSlug(path8.dirname(v2)), "v2");
18346
18453
  const raw = this.readV2Workspace(v2Workspace);
18347
18454
  if (raw === null || raw === TOMBSTONE)
18348
18455
  return success(null, null, null);
18349
- return this.withLock(dirs.checkoutLock, () => this.withLock(path6.join(v2, "metadata.lock"), () => {
18456
+ return this.withLock(dirs.checkoutLock, () => this.withLock(path8.join(v2, "metadata.lock"), () => {
18350
18457
  const workspace = this.readV2Workspace(v2Workspace);
18351
18458
  if (workspace === null || workspace === TOMBSTONE)
18352
18459
  return success(null, null, null);
@@ -18355,7 +18462,7 @@ class TaskStore {
18355
18462
  return failure2("recovery_required", `cannot migrate the 2.x store at ${v2}: ${parsedWorkspace.error}; move it aside to start fresh`, { path: v2Workspace });
18356
18463
  let files = [];
18357
18464
  try {
18358
- files = fs7.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path6.join(v2Tasks, name)));
18465
+ files = fs8.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path8.join(v2Tasks, name)));
18359
18466
  } catch {}
18360
18467
  const current = this.readWorkspace();
18361
18468
  if (!current.ok)
@@ -18373,22 +18480,22 @@ class TaskStore {
18373
18480
  let skipped = 0;
18374
18481
  const done = new Map;
18375
18482
  try {
18376
- fs7.mkdirSync(path6.join(legacy, "tasks"), { recursive: true });
18483
+ fs8.mkdirSync(path8.join(legacy, "tasks"), { recursive: true });
18377
18484
  for (const name of ["workspace.json", "index.json"])
18378
- if (fs7.existsSync(path6.join(v2, name)))
18379
- fs7.copyFileSync(path6.join(v2, name), path6.join(legacy, name));
18485
+ if (fs8.existsSync(path8.join(v2, name)))
18486
+ fs8.copyFileSync(path8.join(v2, name), path8.join(legacy, name));
18380
18487
  for (const name of files) {
18381
18488
  const id = name.slice(0, -5);
18382
- const file = path6.join(v2Tasks, name);
18383
- const bytes = fs7.readFileSync(file, "utf8");
18489
+ const file = path8.join(v2Tasks, name);
18490
+ const bytes = fs8.readFileSync(file, "utf8");
18384
18491
  const digest = sha256(bytes);
18385
- fs7.writeFileSync(path6.join(legacy, "tasks", name), bytes);
18492
+ fs8.writeFileSync(path8.join(legacy, "tasks", name), bytes);
18386
18493
  const parsed = this.parseRecord(bytes, taskRecordSchema, "2.x task");
18387
18494
  if (!parsed.ok || parsed.data.id !== id)
18388
18495
  return failure2("recovery_required", `cannot migrate 2.x task ${id}: ${parsed.ok ? "file name and record ID differ" : parsed.error}; move ${file} aside to continue`, { path: file });
18389
18496
  const record = { ...parsed.data, workspaceId: target.id };
18390
- const origin = { path: path6.join(legacy, "tasks", name), digest };
18391
- if (!fs7.existsSync(this.eventsPath(id))) {
18497
+ const origin = { path: path8.join(legacy, "tasks", name), digest };
18498
+ if (!fs8.existsSync(this.eventsPath(id))) {
18392
18499
  this.openTask(record, "migrated.from_v2", null, origin);
18393
18500
  migrated += 1;
18394
18501
  } else {
@@ -18423,8 +18530,8 @@ class TaskStore {
18423
18530
  try {
18424
18531
  let complete = true;
18425
18532
  for (const [name, digest] of done) {
18426
- const file = path6.join(v2Tasks, name);
18427
- if (sha256(fs7.readFileSync(file, "utf8")) !== digest) {
18533
+ const file = path8.join(v2Tasks, name);
18534
+ if (sha256(fs8.readFileSync(file, "utf8")) !== digest) {
18428
18535
  complete = false;
18429
18536
  continue;
18430
18537
  }
@@ -18434,7 +18541,7 @@ class TaskStore {
18434
18541
  return failure2("busy", `the 2.x store at ${v2} changed during migration; retry`, {
18435
18542
  path: v2
18436
18543
  });
18437
- fs7.rmSync(path6.join(v2, "index.json"), { force: true });
18544
+ fs8.rmSync(path8.join(v2, "index.json"), { force: true });
18438
18545
  this.writeTombstone(v2, target.id);
18439
18546
  } catch (error) {
18440
18547
  return failure2("storage_error", `cannot finish the 2.x migration: ${String(error)}`, {
@@ -18454,45 +18561,45 @@ class TaskStore {
18454
18561
  }
18455
18562
  adoptLocalStore() {
18456
18563
  const dirs = this.paths();
18457
- const marker = path6.join(dirs.v2, "store.json");
18458
- if (!dirs.shared || !fs7.existsSync(marker))
18564
+ const marker = path8.join(dirs.v2, "store.json");
18565
+ if (!dirs.shared || !fs8.existsSync(marker))
18459
18566
  return success(null, null, null);
18460
18567
  return this.withLock(dirs.checkoutLock, () => {
18461
- if (!fs7.existsSync(marker))
18568
+ if (!fs8.existsSync(marker))
18462
18569
  return success(null, null, null);
18463
18570
  let tasks = 0;
18464
18571
  try {
18465
18572
  const merge = (from, to) => {
18466
- if (!fs7.existsSync(to)) {
18467
- fs7.mkdirSync(path6.dirname(to), { recursive: true });
18573
+ if (!fs8.existsSync(to)) {
18574
+ fs8.mkdirSync(path8.dirname(to), { recursive: true });
18468
18575
  try {
18469
- fs7.renameSync(from, to);
18576
+ fs8.renameSync(from, to);
18470
18577
  } catch {
18471
- fs7.cpSync(from, to, { recursive: true, errorOnExist: true, force: false });
18472
- fs7.rmSync(from, { recursive: true, force: true });
18578
+ fs8.cpSync(from, to, { recursive: true, errorOnExist: true, force: false });
18579
+ fs8.rmSync(from, { recursive: true, force: true });
18473
18580
  }
18474
18581
  return;
18475
18582
  }
18476
- if (fs7.lstatSync(from).isDirectory() && fs7.lstatSync(to).isDirectory())
18477
- for (const name of fs7.readdirSync(from))
18478
- merge(path6.join(from, name), path6.join(to, name));
18583
+ if (fs8.lstatSync(from).isDirectory() && fs8.lstatSync(to).isDirectory())
18584
+ for (const name of fs8.readdirSync(from))
18585
+ merge(path8.join(from, name), path8.join(to, name));
18479
18586
  };
18480
18587
  for (const sub of ["tasks", "checkouts", "blobs", "legacy"]) {
18481
- const from = path6.join(dirs.v2, sub);
18482
- if (!fs7.existsSync(from))
18588
+ const from = path8.join(dirs.v2, sub);
18589
+ if (!fs8.existsSync(from))
18483
18590
  continue;
18484
18591
  if (sub === "tasks") {
18485
- for (const name of fs7.readdirSync(from))
18486
- if (validId(name) && !fs7.existsSync(path6.join(dirs.dir, sub, name)))
18592
+ for (const name of fs8.readdirSync(from))
18593
+ if (validId(name) && !fs8.existsSync(path8.join(dirs.dir, sub, name)))
18487
18594
  tasks += 1;
18488
18595
  }
18489
- merge(from, path6.join(dirs.dir, sub));
18596
+ merge(from, path8.join(dirs.dir, sub));
18490
18597
  }
18491
- const ledger = path6.join(dirs.v2, "ledger");
18492
- if (fs7.existsSync(ledger) && !fs7.existsSync(path6.join(dirs.dir, "ledger")))
18493
- merge(ledger, path6.join(dirs.dir, "ledger"));
18494
- fs7.rmSync(path6.join(dirs.v2, "task-index.json"), { force: true });
18495
- fs7.renameSync(marker, path6.join(dirs.v2, "store.moved.json"));
18598
+ const ledger = path8.join(dirs.v2, "ledger");
18599
+ if (fs8.existsSync(ledger) && !fs8.existsSync(path8.join(dirs.dir, "ledger")))
18600
+ merge(ledger, path8.join(dirs.dir, "ledger"));
18601
+ fs8.rmSync(path8.join(dirs.v2, "task-index.json"), { force: true });
18602
+ fs8.renameSync(marker, path8.join(dirs.v2, "store.moved.json"));
18496
18603
  } catch (error) {
18497
18604
  return failure2("storage_error", `cannot move ${dirs.v2} into ${dirs.dir}: ${String(error)}`, {
18498
18605
  path: dirs.v2
@@ -18512,7 +18619,7 @@ class TaskStore {
18512
18619
  readV2Workspace(file) {
18513
18620
  let bytes;
18514
18621
  try {
18515
- bytes = fs7.readFileSync(file, "utf8");
18622
+ bytes = fs8.readFileSync(file, "utf8");
18516
18623
  } catch {
18517
18624
  return null;
18518
18625
  }
@@ -18530,7 +18637,7 @@ class TaskStore {
18530
18637
  schemaVersion: SCHEMA_VERSION,
18531
18638
  id: workspaceId ?? newId(),
18532
18639
  revision: newRevision(),
18533
- root: path6.dirname(v2),
18640
+ root: path8.dirname(v2),
18534
18641
  runtime: { createdWith: version, updatedWith: version },
18535
18642
  writer: null,
18536
18643
  store: {
@@ -18541,12 +18648,12 @@ class TaskStore {
18541
18648
  },
18542
18649
  critical: ["store"]
18543
18650
  };
18544
- fs7.mkdirSync(v2, { recursive: true });
18545
- const ignore = path6.join(v2, ".gitignore");
18546
- if (!fs7.existsSync(ignore))
18547
- fs7.writeFileSync(ignore, `*
18651
+ fs8.mkdirSync(v2, { recursive: true });
18652
+ const ignore = path8.join(v2, ".gitignore");
18653
+ if (!fs8.existsSync(ignore))
18654
+ fs8.writeFileSync(ignore, `*
18548
18655
  `);
18549
- replaceFile(path6.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
18656
+ replaceFile(path8.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
18550
18657
  `, true);
18551
18658
  }
18552
18659
  stubFor(taskId) {
@@ -18562,7 +18669,7 @@ class TaskStore {
18562
18669
  }
18563
18670
  isStub(file) {
18564
18671
  try {
18565
- const value = JSON.parse(fs7.readFileSync(file, "utf8"));
18672
+ const value = JSON.parse(fs8.readFileSync(file, "utf8"));
18566
18673
  return isObject5(value) && isObject5(value.store) && value.store.format === "workit-store";
18567
18674
  } catch {
18568
18675
  return false;
@@ -18570,32 +18677,32 @@ class TaskStore {
18570
18677
  }
18571
18678
  writeTombstoneIfMissing() {
18572
18679
  try {
18573
- const v2 = path6.join(this.root, ".workit");
18574
- if (fs7.existsSync(path6.join(v2, "workspace.json")))
18680
+ const v2 = path8.join(this.root, ".workit");
18681
+ if (fs8.existsSync(path8.join(v2, "workspace.json")))
18575
18682
  return;
18576
18683
  let id = null;
18577
18684
  try {
18578
- id = JSON.parse(fs7.readFileSync(this.paths().workspace, "utf8")).id ?? null;
18685
+ id = JSON.parse(fs8.readFileSync(this.paths().workspace, "utf8")).id ?? null;
18579
18686
  } catch {}
18580
18687
  this.writeTombstone(v2, id);
18581
18688
  } catch {}
18582
18689
  }
18583
18690
  initializeStorage() {
18584
18691
  const dirs = this.paths();
18585
- retryTransient(() => fs7.mkdirSync(dirs.checkout, { recursive: true }));
18586
- retryTransient(() => fs7.mkdirSync(dirs.tasks, { recursive: true }));
18587
- if (!fs7.existsSync(dirs.marker))
18692
+ retryTransient(() => fs8.mkdirSync(dirs.checkout, { recursive: true }));
18693
+ retryTransient(() => fs8.mkdirSync(dirs.tasks, { recursive: true }));
18694
+ if (!fs8.existsSync(dirs.marker))
18588
18695
  replaceFile(dirs.marker, `${JSON.stringify({ format: "workit-store", version: STORE_FORMAT, createdWith: runtimeVersion() })}
18589
18696
  `, false);
18590
18697
  if (!dirs.shared) {
18591
- const ignore = path6.join(dirs.dir, ".gitignore");
18698
+ const ignore = path8.join(dirs.dir, ".gitignore");
18592
18699
  let current = null;
18593
18700
  try {
18594
- current = fs7.readFileSync(ignore, "utf8");
18701
+ current = fs8.readFileSync(ignore, "utf8");
18595
18702
  } catch {}
18596
18703
  if (current !== `*
18597
18704
  `)
18598
- retryTransient(() => fs7.writeFileSync(ignore, `*
18705
+ retryTransient(() => fs8.writeFileSync(ignore, `*
18599
18706
  `));
18600
18707
  }
18601
18708
  this.writeTombstoneIfMissing();
@@ -18611,7 +18718,7 @@ class TaskStore {
18611
18718
  shouldReclaim: ({ payload, nowMs }) => {
18612
18719
  let ageMs = null;
18613
18720
  try {
18614
- ageMs = nowMs - fs7.lstatSync(lockPath).mtimeMs;
18721
+ ageMs = nowMs - fs8.lstatSync(lockPath).mtimeMs;
18615
18722
  } catch {}
18616
18723
  return classifyLockOwner(payload, ageMs, localLockHost(), TASK_STORE_LOCK).state === "stale";
18617
18724
  },
@@ -18648,7 +18755,7 @@ class TaskStore {
18648
18755
  withLock(lockPath, operation) {
18649
18756
  try {
18650
18757
  this.initializeStorage();
18651
- fs7.mkdirSync(path6.dirname(lockPath), { recursive: true });
18758
+ fs8.mkdirSync(path8.dirname(lockPath), { recursive: true });
18652
18759
  } catch (error) {
18653
18760
  return failure2("storage_error", `unable to initialize store: ${String(error)}`, {
18654
18761
  path: this.paths().dir
@@ -18688,18 +18795,18 @@ class TaskStore {
18688
18795
  lockDirWritable(lockPath) {
18689
18796
  const probe = `${lockPath}.${process.pid}.${randomUUID3()}.probe`;
18690
18797
  try {
18691
- fs7.closeSync(fs7.openSync(probe, "wx", 384));
18798
+ fs8.closeSync(fs8.openSync(probe, "wx", 384));
18692
18799
  } catch {
18693
18800
  return false;
18694
18801
  }
18695
18802
  try {
18696
- fs7.rmSync(probe, { force: true });
18803
+ fs8.rmSync(probe, { force: true });
18697
18804
  } catch {}
18698
18805
  return true;
18699
18806
  }
18700
18807
  lockHolderPresent(lockPath) {
18701
18808
  try {
18702
- fs7.lstatSync(lockPath);
18809
+ fs8.lstatSync(lockPath);
18703
18810
  return true;
18704
18811
  } catch (error) {
18705
18812
  return error?.code !== "ENOENT";
@@ -18711,12 +18818,12 @@ class TaskStore {
18711
18818
  if (isTransientWindowsError(error) && !this.lockHolderPresent(lockPath) && !this.lockDirWritable(lockPath))
18712
18819
  return failure2("storage_error", `cannot create the workit lock (${code}); no other Workit call holds it`, {
18713
18820
  path: lockPath,
18714
- guidance: `Check permissions and the read-only attribute on ${path6.dirname(lockPath)}.`
18821
+ guidance: `Check permissions and the read-only attribute on ${path8.dirname(lockPath)}.`
18715
18822
  });
18716
18823
  if (code === "EEXIST" || code === "file_lock_timeout" || code === "file_lock_stale" || isTransientWindowsError(error)) {
18717
18824
  let lock = null;
18718
18825
  try {
18719
- lock = parseMetadataLockOrNull(fs7.readFileSync(lockPath, "utf8"));
18826
+ lock = parseMetadataLockOrNull(fs8.readFileSync(lockPath, "utf8"));
18720
18827
  } catch {}
18721
18828
  return failure2("busy", `workit lock is held by another Workit call${lock ? ` (pid ${lock.pid} on ${lock.host})` : ""}; retry shortly`, {
18722
18829
  outcome: "not_started",
@@ -18734,15 +18841,15 @@ var isUncertainWorker = (state) => UNCERTAIN_WORKER_STATES.includes(state);
18734
18841
  var workerBlocksTransition = (transition, state) => transition === "pause" ? false : isUncertainWorker(state);
18735
18842
 
18736
18843
  // packages/workit-core/src/core/task-evaluation.ts
18737
- import { createHash as createHash9 } from "node:crypto";
18738
- import * as fs12 from "node:fs";
18844
+ import { createHash as createHash10 } from "node:crypto";
18845
+ import * as fs13 from "node:fs";
18739
18846
  import { spawnSync as spawnSync10 } from "node:child_process";
18740
- import path14 from "node:path";
18847
+ import path16 from "node:path";
18741
18848
 
18742
18849
  // packages/workit-core/src/check-config.ts
18743
18850
  import { spawnSync as spawnSync3 } from "node:child_process";
18744
- import fs8 from "node:fs";
18745
- import path7 from "node:path";
18851
+ import fs9 from "node:fs";
18852
+ import path9 from "node:path";
18746
18853
  var SCRIPT_CHECKS = ["test", "lint", "typecheck", "check"];
18747
18854
  var CHECKS_FILE = "workit.checks.json";
18748
18855
  var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
@@ -18795,10 +18902,10 @@ var git = (cwd, args) => {
18795
18902
  return value || null;
18796
18903
  };
18797
18904
  function checkRoot(cwd) {
18798
- return path7.resolve(git(cwd, ["rev-parse", "--show-toplevel"]) ?? cwd);
18905
+ return path9.resolve(git(cwd, ["rev-parse", "--show-toplevel"]) ?? cwd);
18799
18906
  }
18800
18907
  var packageManager = (root) => {
18801
- const has = (file) => fs8.existsSync(path7.join(root, file));
18908
+ const has = (file) => fs9.existsSync(path9.join(root, file));
18802
18909
  if (has("bun.lock") || has("bun.lockb"))
18803
18910
  return "bun";
18804
18911
  if (has("pnpm-lock.yaml"))
@@ -18818,7 +18925,7 @@ var CHECK_NAME = /^[a-z0-9][a-z0-9:._-]{0,63}$/u;
18818
18925
  function detectedChecks(root) {
18819
18926
  const read = (file) => {
18820
18927
  try {
18821
- return fs8.readFileSync(path7.join(root, file), "utf8");
18928
+ return fs9.readFileSync(path9.join(root, file), "utf8");
18822
18929
  } catch {
18823
18930
  return null;
18824
18931
  }
@@ -18857,7 +18964,7 @@ function detectedChecks(root) {
18857
18964
  var GATES = ["testing", "verification"];
18858
18965
  function loadCheckConfig(cwd) {
18859
18966
  const root = checkRoot(cwd);
18860
- const file = path7.join(root, CHECKS_FILE);
18967
+ const file = path9.join(root, CHECKS_FILE);
18861
18968
  const none = (error = null) => ({
18862
18969
  source: error ? CHECKS_FILE : "none",
18863
18970
  root,
@@ -18867,7 +18974,7 @@ function loadCheckConfig(cwd) {
18867
18974
  });
18868
18975
  let text = null;
18869
18976
  try {
18870
- text = fs8.readFileSync(file, "utf8");
18977
+ text = fs9.readFileSync(file, "utf8");
18871
18978
  } catch (error) {
18872
18979
  if (error.code !== "ENOENT")
18873
18980
  return none(`cannot read ${CHECKS_FILE}: ${error.message}`);
@@ -18930,10 +19037,10 @@ function workitAvailable(env = process.env) {
18930
19037
  return workitOnPath;
18931
19038
  const windows = process.platform === "win32";
18932
19039
  const exts = windows ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
18933
- const dirs = (env.PATH ?? env.Path ?? "").split(path7.delimiter).filter(Boolean);
19040
+ const dirs = (env.PATH ?? env.Path ?? "").split(path9.delimiter).filter(Boolean);
18934
19041
  workitOnPath = dirs.some((dir) => exts.some((ext) => {
18935
19042
  try {
18936
- return fs8.statSync(path7.join(dir, `workit${ext}`)).isFile();
19043
+ return fs9.statSync(path9.join(dir, `workit${ext}`)).isFile();
18937
19044
  } catch {
18938
19045
  return false;
18939
19046
  }
@@ -18946,10 +19053,10 @@ function checkCommand(args, version, onPath = workitAvailable()) {
18946
19053
 
18947
19054
  // packages/workit-core/src/git/rev.ts
18948
19055
  import { spawnSync as spawnSync4 } from "node:child_process";
18949
- import { createHash as createHash5 } from "node:crypto";
18950
- import fs9 from "node:fs";
19056
+ import { createHash as createHash6 } from "node:crypto";
19057
+ import fs10 from "node:fs";
18951
19058
  import os2 from "node:os";
18952
- import path8 from "node:path";
19059
+ import path10 from "node:path";
18953
19060
  var MAX_BUFFER = 256 * 1024 * 1024;
18954
19061
  var GIT_TIMEOUTS = { local: 20000, worktree: 120000, network: 15000 };
18955
19062
  var git2 = (cwd, args, options = {}) => {
@@ -18984,10 +19091,10 @@ function headSha(cwd) {
18984
19091
  var emptyTree = (cwd) => line(git2(cwd, ["mktree"], { input: "" }));
18985
19092
  var MAX_UNTRACKED_BYTES = 5 * 1024 * 1024;
18986
19093
  var seedIndex = (from, to) => {
18987
- fs9.copyFileSync(from, to);
18988
- const { atimeNs, mtimeNs } = fs9.statSync(from, { bigint: true });
19094
+ fs10.copyFileSync(from, to);
19095
+ const { atimeNs, mtimeNs } = fs10.statSync(from, { bigint: true });
18989
19096
  const seconds = (ns) => (Number(ns / 1000n) - 1) / 1e6;
18990
- fs9.utimesSync(to, seconds(atimeNs), seconds(mtimeNs));
19097
+ fs10.utimesSync(to, seconds(atimeNs), seconds(mtimeNs));
18991
19098
  };
18992
19099
  function worktreeTree(cwd, options = {}) {
18993
19100
  const top = line(git2(cwd, ["rev-parse", "--show-toplevel"]));
@@ -18996,10 +19103,10 @@ function worktreeTree(cwd, options = {}) {
18996
19103
  return null;
18997
19104
  const cap = options.maxUntrackedBytes ?? MAX_UNTRACKED_BYTES;
18998
19105
  const timeoutMs = options.timeoutMs ?? GIT_TIMEOUTS.worktree;
18999
- const scratch = fs9.mkdtempSync(path8.join(os2.tmpdir(), "workit-tree-"));
19106
+ const scratch = fs10.mkdtempSync(path10.join(os2.tmpdir(), "workit-tree-"));
19000
19107
  try {
19001
- const tempIndex = path8.join(scratch, "index");
19002
- if (fs9.existsSync(indexPath))
19108
+ const tempIndex = path10.join(scratch, "index");
19109
+ if (fs10.existsSync(indexPath))
19003
19110
  seedIndex(indexPath, tempIndex);
19004
19111
  const env = { ...process.env, GIT_INDEX_FILE: tempIndex };
19005
19112
  const untracked = git2(top, ["ls-files", "--others", "--exclude-standard", "-z"], {
@@ -19011,7 +19118,7 @@ function worktreeTree(cwd, options = {}) {
19011
19118
  const skipped = [];
19012
19119
  for (const file of untracked.stdout.split("\x00").filter(Boolean)) {
19013
19120
  try {
19014
- const stat = fs9.statSync(path8.join(top, file));
19121
+ const stat = fs10.statSync(path10.join(top, file));
19015
19122
  if (stat.isFile() && stat.size > cap)
19016
19123
  skipped.push({ path: file, size: stat.size, mtimeMs: Math.trunc(stat.mtimeMs) });
19017
19124
  } catch {}
@@ -19028,10 +19135,10 @@ function worktreeTree(cwd, options = {}) {
19028
19135
  if (!tree)
19029
19136
  return null;
19030
19137
  const base = line(git2(top, ["rev-parse", "--verify", "-q", "HEAD^{tree}"])) ?? emptyTree(top);
19031
- const key = skipped.length ? `sha256:${createHash5("sha256").update(JSON.stringify({ tree, skipped })).digest("hex")}` : tree;
19138
+ const key = skipped.length ? `sha256:${createHash6("sha256").update(JSON.stringify({ tree, skipped })).digest("hex")}` : tree;
19032
19139
  return { tree, key, dirty: tree !== base || skipped.length > 0, skipped };
19033
19140
  } finally {
19034
- fs9.rmSync(scratch, { recursive: true, force: true });
19141
+ fs10.rmSync(scratch, { recursive: true, force: true });
19035
19142
  }
19036
19143
  }
19037
19144
  function worktreeSignal(cwd, options = {}) {
@@ -19051,16 +19158,16 @@ function worktreeSignal(cwd, options = {}) {
19051
19158
  });
19052
19159
  if (!status.ok)
19053
19160
  return null;
19054
- const hash = createHash5("sha256");
19161
+ const hash = createHash6("sha256");
19055
19162
  hash.update(`${headSha(top) ?? "unborn"}\x00`);
19056
19163
  for (const entry of status.stdout.split("\x00")) {
19057
19164
  if (entry.length < 4)
19058
19165
  continue;
19059
19166
  const file = entry.slice(3);
19060
- const absolute = path8.join(top, file);
19167
+ const absolute = path10.join(top, file);
19061
19168
  let stat = "-";
19062
19169
  try {
19063
- const info = fs9.lstatSync(absolute, { bigint: true });
19170
+ const info = fs10.lstatSync(absolute, { bigint: true });
19064
19171
  stat = `${info.mode.toString(8)}:${info.size}:${info.mtimeNs}`;
19065
19172
  if (info.isDirectory())
19066
19173
  stat += `:${headSha(absolute) ?? "-"}`;
@@ -19127,17 +19234,17 @@ function pushRemoteName(cwd, branch) {
19127
19234
 
19128
19235
  // packages/workit-core/src/core/policy/derive.ts
19129
19236
  import { existsSync as existsSync4 } from "node:fs";
19130
- import path13 from "node:path";
19237
+ import path15 from "node:path";
19131
19238
 
19132
19239
  // packages/workit-core/src/ledger.ts
19133
19240
  import { spawnSync as spawnSync9 } from "node:child_process";
19134
- import { createHash as createHash8, randomBytes as randomBytes2 } from "node:crypto";
19135
- import fs11 from "node:fs";
19136
- import path12 from "node:path";
19241
+ import { createHash as createHash9, randomBytes as randomBytes3 } from "node:crypto";
19242
+ import fs12 from "node:fs";
19243
+ import path14 from "node:path";
19137
19244
 
19138
19245
  // packages/workit-core/src/core/vcs-config.ts
19139
- import fs10 from "node:fs";
19140
- import path11 from "node:path";
19246
+ import fs11 from "node:fs";
19247
+ import path13 from "node:path";
19141
19248
  import { spawnSync as spawnSync8 } from "node:child_process";
19142
19249
 
19143
19250
  // packages/workit-core/src/core/config.ts
@@ -19151,7 +19258,7 @@ import {
19151
19258
  writeFileSync as writeFileSync2
19152
19259
  } from "node:fs";
19153
19260
  import os3 from "node:os";
19154
- import path9 from "node:path";
19261
+ import path11 from "node:path";
19155
19262
 
19156
19263
  // packages/workit-core/src/core/boundary.ts
19157
19264
  import { statSync as statSync2 } from "node:fs";
@@ -19210,7 +19317,7 @@ var mergePreset = (preset, input = {}, current = {
19210
19317
  protected: preset === "custom" ? input.protectedNames ?? current.branchPolicy.protected : [...defs.protected]
19211
19318
  };
19212
19319
  };
19213
- var resolveConfigDir = () => process.env.WORKFLOW_TOOLKIT_CONFIG ?? process.env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path9.join(process.env.XDG_CONFIG_HOME || path9.join(os3.homedir(), ".config"), "workit");
19320
+ var resolveConfigDir = () => process.env.WORKFLOW_TOOLKIT_CONFIG ?? process.env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path11.join(process.env.XDG_CONFIG_HOME || path11.join(os3.homedir(), ".config"), "workit");
19214
19321
  var migratedDir = null;
19215
19322
  var migrationFailed = false;
19216
19323
  var ensureConfigDir = (dir = resolveConfigDir()) => {
@@ -19220,7 +19327,7 @@ var ensureConfigDir = (dir = resolveConfigDir()) => {
19220
19327
  migratedDir = dir;
19221
19328
  return dir;
19222
19329
  }
19223
- const legacy = path9.join(process.env.XDG_CONFIG_HOME || path9.join(os3.homedir(), ".config"), "workflow-toolkit");
19330
+ const legacy = path11.join(process.env.XDG_CONFIG_HOME || path11.join(os3.homedir(), ".config"), "workflow-toolkit");
19224
19331
  if (!existsSync3(legacy)) {
19225
19332
  migratedDir = dir;
19226
19333
  return dir;
@@ -19233,8 +19340,8 @@ var ensureConfigDir = (dir = resolveConfigDir()) => {
19233
19340
  mkdirSync2(dir, { recursive: true });
19234
19341
  diagnosticLogger?.info(EVENT.migration, { from: legacy, to: dir });
19235
19342
  for (const entry of readdirSync2(legacy, { withFileTypes: true })) {
19236
- const src = path9.join(legacy, entry.name);
19237
- const dest = path9.join(dir, entry.name);
19343
+ const src = path11.join(legacy, entry.name);
19344
+ const dest = path11.join(dir, entry.name);
19238
19345
  if (existsSync3(dest))
19239
19346
  continue;
19240
19347
  try {
@@ -19306,7 +19413,7 @@ var parseConfigResult = (raw, file) => {
19306
19413
  return { status: "valid", path: file, config };
19307
19414
  };
19308
19415
  var readConfigTyped = (dir) => {
19309
- const file = path9.join(dir ?? configDir(), "config.json");
19416
+ const file = path11.join(dir ?? configDir(), "config.json");
19310
19417
  return parseConfigResult(readSafe(file), file);
19311
19418
  };
19312
19419
  var readConfig = () => {
@@ -19315,7 +19422,7 @@ var readConfig = () => {
19315
19422
  throw new Error(result.error);
19316
19423
  return result.config ?? DEFAULTS;
19317
19424
  };
19318
- var vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path9.join(configDir(), "vcs.json");
19425
+ var vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path11.join(configDir(), "vcs.json");
19319
19426
  var branchGlobPattern = (glob) => new RegExp(`^${glob.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`, "i");
19320
19427
  var resolveBranchPolicy = (config, workspace, repoPreset) => {
19321
19428
  const wp = workspace?.branchPolicy ?? {};
@@ -19347,9 +19454,9 @@ var COMMIT_PRESETS = [
19347
19454
 
19348
19455
  // packages/workit-core/src/core/workspaces.ts
19349
19456
  import { spawnSync as spawnSync6 } from "node:child_process";
19350
- import { createHash as createHash6 } from "node:crypto";
19457
+ import { createHash as createHash7 } from "node:crypto";
19351
19458
  import { readFileSync as readFileSync3, realpathSync as realpathSync2 } from "node:fs";
19352
- import path10 from "node:path";
19459
+ import path12 from "node:path";
19353
19460
 
19354
19461
  // packages/workit-core/src/core/branch-policy.ts
19355
19462
  import { spawnSync as spawnSync5 } from "node:child_process";
@@ -19474,7 +19581,7 @@ var releaseTrackSchema = object({
19474
19581
  context.addIssue({ code: "custom", path: [field], message: "entries must be unique" });
19475
19582
  }
19476
19583
  }
19477
- if (track.versionSource?.kind === "package-json" && (path10.posix.isAbsolute(track.versionSource.path.replaceAll("\\", "/")) || /^[A-Za-z]:\//u.test(track.versionSource.path.replaceAll("\\", "/")) || track.versionSource.path.replaceAll("\\", "/").split("/").includes(".."))) {
19584
+ if (track.versionSource?.kind === "package-json" && (path12.posix.isAbsolute(track.versionSource.path.replaceAll("\\", "/")) || /^[A-Za-z]:\//u.test(track.versionSource.path.replaceAll("\\", "/")) || track.versionSource.path.replaceAll("\\", "/").split("/").includes(".."))) {
19478
19585
  context.addIssue({
19479
19586
  code: "custom",
19480
19587
  path: ["versionSource", "path"],
@@ -19535,7 +19642,7 @@ var workspacesFileSchema = object({ workspaces: array(workspaceConfigSchema).opt
19535
19642
  names.add(workspace.name);
19536
19643
  }
19537
19644
  });
19538
- var workspacesRevision = (contents) => createHash6("sha256").update(contents ?? "<missing>").digest("hex");
19645
+ var workspacesRevision = (contents) => createHash7("sha256").update(contents ?? "<missing>").digest("hex");
19539
19646
  var validateWorkspacesDocument = (parsed, file) => {
19540
19647
  if (!isConfigObject(parsed)) {
19541
19648
  return { status: "malformed", path: file, entries: [], error: `${file} is not a JSON object` };
@@ -19573,7 +19680,7 @@ var validateWorkspacesDocument = (parsed, file) => {
19573
19680
  };
19574
19681
  };
19575
19682
  var readWorkspacesResult = (dir = configDir()) => {
19576
- const file = path10.join(dir, "workspaces.json");
19683
+ const file = path12.join(dir, "workspaces.json");
19577
19684
  let raw;
19578
19685
  try {
19579
19686
  raw = readFileSync3(file, "utf8");
@@ -19684,9 +19791,9 @@ var mainCheckoutOf = (cwd) => {
19684
19791
  let main = null;
19685
19792
  const dirs = git(["rev-parse", "--path-format=absolute", "--git-dir", "--git-common-dir"]);
19686
19793
  const [gitDir, common] = (dirs ?? "").trim().split(/\r?\n/u);
19687
- if (gitDir && common && path10.resolve(gitDir) !== path10.resolve(common)) {
19794
+ if (gitDir && common && path12.resolve(gitDir) !== path12.resolve(common)) {
19688
19795
  const listed = /^worktree (.+)$/mu.exec(git(["worktree", "list", "--porcelain"]) ?? "")?.[1];
19689
- main = listed?.trim() || (path10.basename(common) === ".git" ? path10.dirname(common) : common);
19796
+ main = listed?.trim() || (path12.basename(common) === ".git" ? path12.dirname(common) : common);
19690
19797
  }
19691
19798
  mainCheckouts.set(cwd, main);
19692
19799
  return main;
@@ -19777,7 +19884,7 @@ var runtimeWorkspaceIndexSchema = object({
19777
19884
  workspaces: array(object({ name: nonBlank, glob: nonBlank }).passthrough()).optional()
19778
19885
  }).passthrough();
19779
19886
  var matchRuntimeWorkspace = (cwd, dir = configDir()) => {
19780
- const file = path10.join(dir, "workspaces.json");
19887
+ const file = path12.join(dir, "workspaces.json");
19781
19888
  let raw;
19782
19889
  try {
19783
19890
  raw = readFileSync3(file, "utf8");
@@ -19852,7 +19959,7 @@ function workspaceDefaultTarget(cwd, globalDefault) {
19852
19959
  }
19853
19960
 
19854
19961
  // packages/workit-core/src/core/release-tracks.ts
19855
- import { createHash as createHash7 } from "node:crypto";
19962
+ import { createHash as createHash8 } from "node:crypto";
19856
19963
  import { spawnSync as spawnSync7 } from "node:child_process";
19857
19964
  var KNOWN_FIELDS = new Set([
19858
19965
  "strategy",
@@ -20222,7 +20329,7 @@ function resolveTrackFor(cwd, options) {
20222
20329
  ]) ?? "",
20223
20330
  git3(cwd, ["config", "--get", recordedBaseKey(branch)]) ?? ""
20224
20331
  ] : [];
20225
- key = createHash7("sha256").update(JSON.stringify({ cwd, input, refs, head, own })).digest("hex");
20332
+ key = createHash8("sha256").update(JSON.stringify({ cwd, input, refs, head, own })).digest("hex");
20226
20333
  const hit = memo2.get(key);
20227
20334
  if (hit)
20228
20335
  return hit;
@@ -20237,7 +20344,7 @@ function resolveTrackFor(cwd, options) {
20237
20344
  }
20238
20345
 
20239
20346
  // packages/workit-core/src/core/vcs-config.ts
20240
- var workspacesPath = () => path11.join(configDir(), "workspaces.json");
20347
+ var workspacesPath = () => path13.join(configDir(), "workspaces.json");
20241
20348
  var vcsCwd = (cwd) => cwd ?? process.env.WORKFLOW_WORKSPACE_ROOT ?? process.cwd();
20242
20349
  var remoteProvider = (cwd) => {
20243
20350
  const r = spawnSync8("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" });
@@ -20327,7 +20434,7 @@ var readVcsConfig = () => {
20327
20434
  const file = vcsConfigPath();
20328
20435
  let raw;
20329
20436
  try {
20330
- raw = fs10.readFileSync(file, "utf8");
20437
+ raw = fs11.readFileSync(file, "utf8");
20331
20438
  } catch {
20332
20439
  return { status: "missing", path: file, config: {} };
20333
20440
  }
@@ -20412,7 +20519,7 @@ function vcsConfig(mode, cwd, options = {}) {
20412
20519
  const prov = cfg[provider] ?? {};
20413
20520
  const out = {
20414
20521
  ok: true,
20415
- configPath: path11.resolve(cfgPath),
20522
+ configPath: path13.resolve(cfgPath),
20416
20523
  provider,
20417
20524
  defaultTargetBranch: workspaceDefault,
20418
20525
  pr: cfg.pr ?? {},
@@ -20623,7 +20730,7 @@ function diffHash(cwd, base, head) {
20623
20730
  ], GIT_TIMEOUTS.worktree);
20624
20731
  if (!diff.ok || !diff.stdout)
20625
20732
  return null;
20626
- const hash = createHash8("sha256");
20733
+ const hash = createHash9("sha256");
20627
20734
  for (const line of diff.stdout.split(`
20628
20735
  `)) {
20629
20736
  if (line.startsWith("index "))
@@ -20635,16 +20742,16 @@ function diffHash(cwd, base, head) {
20635
20742
  return `sha256:${hash.digest("hex")}`;
20636
20743
  }
20637
20744
  function storeRoot(cwd) {
20638
- const location = resolveStore(path12.resolve(cwd));
20745
+ const location = resolveStore(path14.resolve(cwd));
20639
20746
  if (location instanceof Error)
20640
20747
  return err("unavailable", location.message.replace(/; fix the repository.*$/u, ""), "fix the repository (git status should work here) or run from a non-git directory");
20641
20748
  return { ok: true, value: { root: location.dir, shared: location.shared } };
20642
20749
  }
20643
20750
  function ledgerPath(cwd) {
20644
20751
  const root = storeRoot(cwd);
20645
- return root.ok ? { ok: true, value: path12.join(root.value.root, "ledger", "ledger.jsonl") } : root;
20752
+ return root.ok ? { ok: true, value: path14.join(root.value.root, "ledger", "ledger.jsonl") } : root;
20646
20753
  }
20647
- var newId2 = () => `${Date.now().toString(36)}-${randomBytes2(6).toString("hex")}`;
20754
+ var newId2 = () => `${Date.now().toString(36)}-${randomBytes3(6).toString("hex")}`;
20648
20755
  var NETWORK_FS_TYPES = new Set([
20649
20756
  26985,
20650
20757
  20859,
@@ -20662,7 +20769,7 @@ var onNetworkFs = (dir) => {
20662
20769
  if (process.platform !== "linux")
20663
20770
  return false;
20664
20771
  try {
20665
- return isNetworkFsType(fs11.statfsSync(dir).type);
20772
+ return isNetworkFsType(fs12.statfsSync(dir).type);
20666
20773
  } catch {
20667
20774
  return false;
20668
20775
  }
@@ -20672,15 +20779,15 @@ var LOCK_STALE_MS = 30000;
20672
20779
  var LOCK_OWNER = "owner";
20673
20780
  var lockToken = (lock) => {
20674
20781
  try {
20675
- return fs11.readFileSync(path12.join(lock, LOCK_OWNER), "utf8");
20782
+ return fs12.readFileSync(path14.join(lock, LOCK_OWNER), "utf8");
20676
20783
  } catch {
20677
20784
  return null;
20678
20785
  }
20679
20786
  };
20680
20787
  var lockAgeMs = (lock) => {
20681
- for (const target of [path12.join(lock, LOCK_OWNER), lock]) {
20788
+ for (const target of [path14.join(lock, LOCK_OWNER), lock]) {
20682
20789
  try {
20683
- return Date.now() - fs11.statSync(target).mtimeMs;
20790
+ return Date.now() - fs12.statSync(target).mtimeMs;
20684
20791
  } catch {}
20685
20792
  }
20686
20793
  return null;
@@ -20688,55 +20795,55 @@ var lockAgeMs = (lock) => {
20688
20795
  var ledgerLock = {
20689
20796
  acquire(lock) {
20690
20797
  try {
20691
- fs11.mkdirSync(lock);
20798
+ fs12.mkdirSync(lock);
20692
20799
  } catch (error) {
20693
20800
  if (error.code === "EEXIST")
20694
20801
  return null;
20695
20802
  throw error;
20696
20803
  }
20697
- const token = `${process.pid}-${randomBytes2(8).toString("hex")}`;
20698
- fs11.writeFileSync(path12.join(lock, LOCK_OWNER), token);
20804
+ const token = `${process.pid}-${randomBytes3(8).toString("hex")}`;
20805
+ fs12.writeFileSync(path14.join(lock, LOCK_OWNER), token);
20699
20806
  return token;
20700
20807
  },
20701
20808
  release(lock, token) {
20702
20809
  if (lockToken(lock) !== token)
20703
20810
  return false;
20704
- const tomb = `${lock}.release-${randomBytes2(6).toString("hex")}`;
20811
+ const tomb = `${lock}.release-${randomBytes3(6).toString("hex")}`;
20705
20812
  try {
20706
- fs11.renameSync(lock, tomb);
20813
+ fs12.renameSync(lock, tomb);
20707
20814
  } catch {
20708
20815
  return false;
20709
20816
  }
20710
20817
  if (lockToken(tomb) !== token) {
20711
20818
  try {
20712
- fs11.renameSync(tomb, lock);
20819
+ fs12.renameSync(tomb, lock);
20713
20820
  } catch {}
20714
20821
  return false;
20715
20822
  }
20716
- fs11.rmSync(tomb, { recursive: true, force: true });
20823
+ fs12.rmSync(tomb, { recursive: true, force: true });
20717
20824
  return true;
20718
20825
  },
20719
20826
  token: lockToken,
20720
20827
  reap(lock, observed) {
20721
- const tomb = `${lock}.reap-${randomBytes2(6).toString("hex")}`;
20828
+ const tomb = `${lock}.reap-${randomBytes3(6).toString("hex")}`;
20722
20829
  try {
20723
- fs11.renameSync(lock, tomb);
20830
+ fs12.renameSync(lock, tomb);
20724
20831
  } catch {
20725
20832
  return false;
20726
20833
  }
20727
20834
  if (lockToken(tomb) === observed) {
20728
- fs11.rmSync(tomb, { recursive: true, force: true });
20835
+ fs12.rmSync(tomb, { recursive: true, force: true });
20729
20836
  return true;
20730
20837
  }
20731
20838
  try {
20732
- fs11.renameSync(tomb, lock);
20839
+ fs12.renameSync(tomb, lock);
20733
20840
  } catch {
20734
- fs11.rmSync(tomb, { recursive: true, force: true });
20841
+ fs12.rmSync(tomb, { recursive: true, force: true });
20735
20842
  }
20736
20843
  return false;
20737
20844
  }
20738
20845
  };
20739
- function withLedgerLock(file, fn, waitMs = LOCK_WAIT_MS) {
20846
+ function withLedgerLock(file, fn, waitMs = hostAwareLockTimeout(LOCK_WAIT_MS)) {
20740
20847
  const lock = `${file}.lock`;
20741
20848
  const deadline = Date.now() + waitMs;
20742
20849
  let token = null;
@@ -20758,14 +20865,14 @@ function withLedgerLock(file, fn, waitMs = LOCK_WAIT_MS) {
20758
20865
  ledgerLock.release(lock, token);
20759
20866
  }
20760
20867
  }
20761
- var sha2562 = (text) => createHash8("sha256").update(text).digest("hex");
20868
+ var sha2562 = (text) => createHash9("sha256").update(text).digest("hex");
20762
20869
  var chainHash = (prevHash, body) => sha2562(`${prevHash ?? ""}
20763
20870
  ${body}`);
20764
20871
  var TAIL_BYTES = 64 * 1024;
20765
20872
  var lastLine = (fd, size) => {
20766
20873
  for (let span = Math.min(size, TAIL_BYTES);span > 0; span = Math.min(size, span * 2)) {
20767
20874
  const buffer = Buffer.alloc(span);
20768
- fs11.readSync(fd, buffer, 0, span, size - span);
20875
+ fs12.readSync(fd, buffer, 0, span, size - span);
20769
20876
  const end = buffer.lastIndexOf(10);
20770
20877
  if (end < 0) {
20771
20878
  if (span === size)
@@ -20794,15 +20901,23 @@ var lastLine = (fd, size) => {
20794
20901
  }
20795
20902
  return null;
20796
20903
  };
20904
+ var tighten = (fd) => {
20905
+ try {
20906
+ if ((fs12.fstatSync(fd).mode & 63) !== 0)
20907
+ fs12.fchmodSync(fd, 384);
20908
+ } catch {}
20909
+ };
20797
20910
  function appendLine(file, build, options) {
20798
20911
  const write = () => {
20799
- const fd = fs11.openSync(file, "a+");
20912
+ const fd = fs12.openSync(file, "a+", 384);
20800
20913
  try {
20801
- const size = fs11.fstatSync(fd).size;
20914
+ if (process.platform !== "win32")
20915
+ tighten(fd);
20916
+ const size = fs12.fstatSync(fd).size;
20802
20917
  let fence = "";
20803
20918
  if (size > 0) {
20804
20919
  const last = Buffer.alloc(1);
20805
- fs11.readSync(fd, last, 0, 1, size - 1);
20920
+ fs12.readSync(fd, last, 0, 1, size - 1);
20806
20921
  if (last[0] !== 10)
20807
20922
  fence = `
20808
20923
  `;
@@ -20811,17 +20926,17 @@ function appendLine(file, build, options) {
20811
20926
  if (!line.ok)
20812
20927
  return line;
20813
20928
  const bytes = Buffer.from(fence + line.value);
20814
- const written = fs11.writeSync(fd, bytes);
20929
+ const written = fs12.writeSync(fd, bytes);
20815
20930
  if (written !== bytes.length)
20816
20931
  return err("unavailable", `short write to ${file}: ${written} of ${bytes.length} bytes; the row is torn and will be skipped`);
20817
20932
  return { ok: true, value: undefined };
20818
20933
  } finally {
20819
- fs11.closeSync(fd);
20934
+ fs12.closeSync(fd);
20820
20935
  }
20821
20936
  };
20822
20937
  try {
20823
- fs11.mkdirSync(path12.dirname(file), { recursive: true });
20824
- if (!options.forceLock && !onNetworkFs(path12.dirname(file)))
20938
+ fs12.mkdirSync(path14.dirname(file), { recursive: true });
20939
+ if (!options.forceLock && !onNetworkFs(path14.dirname(file)))
20825
20940
  return write();
20826
20941
  const locked = withLedgerLock(file, write);
20827
20942
  return locked ?? err("busy", `ledger lock ${file}.lock is held`, "retry; remove the .lock directory if no workit process is running");
@@ -20889,8 +21004,10 @@ function readLedger(cwd, options = {}) {
20889
21004
  if (!file.ok)
20890
21005
  return file;
20891
21006
  let text = "";
21007
+ let stat = null;
20892
21008
  try {
20893
- text = fs11.readFileSync(file.value, "utf8");
21009
+ stat = fs12.statSync(file.value);
21010
+ text = fs12.readFileSync(file.value, "utf8");
20894
21011
  } catch (error) {
20895
21012
  if (error.code === "ENOENT")
20896
21013
  return {
@@ -20909,6 +21026,7 @@ function readLedger(cwd, options = {}) {
20909
21026
  const integrity = { chained: 0, legacy: 0, unverified: [] };
20910
21027
  const earlier = new Set([null]);
20911
21028
  let chainStarted = false;
21029
+ const ids = new Set;
20912
21030
  for (const raw of text.split(`
20913
21031
  `)) {
20914
21032
  const trimmed = raw.trim();
@@ -20942,6 +21060,10 @@ function readLedger(cwd, options = {}) {
20942
21060
  reason = "unsigned";
20943
21061
  else
20944
21062
  rowIntegrity = "legacy";
21063
+ if (options.integrity && !reason && ids.has(parsed.id))
21064
+ reason = "duplicate_id";
21065
+ if (options.integrity)
21066
+ ids.add(parsed.id);
20945
21067
  if (reason)
20946
21068
  rowIntegrity = "unverified";
20947
21069
  const pr = typeof parsed.pr === "number" && Number.isInteger(parsed.pr) ? parsed.pr : undefined;
@@ -20965,7 +21087,8 @@ function readLedger(cwd, options = {}) {
20965
21087
  seq: rows.length + 1,
20966
21088
  superseded: false,
20967
21089
  supersedeIgnored: false,
20968
- ...rowIntegrity ? { integrity: rowIntegrity } : {}
21090
+ ...rowIntegrity ? { integrity: rowIntegrity } : {},
21091
+ ...reason ? { integrityReason: reason } : {}
20969
21092
  };
20970
21093
  rows.push(row);
20971
21094
  if (!options.integrity)
@@ -20993,18 +21116,48 @@ function readLedger(cwd, options = {}) {
20993
21116
  const byId = new Map;
20994
21117
  for (const row of rows) {
20995
21118
  const target = row.supersedes ? byId.get(row.supersedes) : undefined;
20996
- if (target && supersedeAllowed(row, target, renameAwareBranch(scopeOf, row.branch)) === null)
21119
+ if (target && row.integrity !== "unverified" && supersedeAllowed(row, target, renameAwareBranch(scopeOf, row.branch)) === null)
20997
21120
  target.superseded = true;
20998
21121
  else if (row.supersedes)
20999
21122
  row.supersedeIgnored = true;
21000
21123
  if (!byId.has(row.id))
21001
21124
  byId.set(row.id, row);
21002
21125
  }
21126
+ if (options.integrity && stat && Buffer.byteLength(text) === stat.size)
21127
+ tamperCache.set(file.value, {
21128
+ size: stat.size,
21129
+ stamp: fileStamp(stat),
21130
+ breaks: integrity.unverified.filter((row) => TAMPER_REASONS.has(row.reason))
21131
+ });
21003
21132
  return {
21004
21133
  ok: true,
21005
21134
  value: { path: file.value, rows, skipped, integrity: options.integrity ? integrity : null }
21006
21135
  };
21007
21136
  }
21137
+ var TAMPER_REASONS = new Set(["hash_mismatch", "broken_link"]);
21138
+ var tamperCache = new Map;
21139
+ var fileStamp = (stat) => `${stat.ino}:${stat.mtimeMs}:${stat.ctimeMs}`;
21140
+ function ledgerTampering(cwd) {
21141
+ const file = ledgerPath(cwd);
21142
+ if (!file.ok)
21143
+ return [];
21144
+ try {
21145
+ const stat = fs12.statSync(file.value);
21146
+ const cached = tamperCache.get(file.value);
21147
+ if (cached && cached.size === stat.size && cached.stamp === fileStamp(stat))
21148
+ return cached.breaks;
21149
+ } catch {
21150
+ return [];
21151
+ }
21152
+ const read = readLedger(cwd, { integrity: true });
21153
+ return read.ok ? (read.value.integrity?.unverified ?? []).filter((row) => TAMPER_REASONS.has(row.reason)) : [];
21154
+ }
21155
+ function tamperedUnblock(cwd) {
21156
+ const file = ledgerPath(cwd);
21157
+ const where = file.ok ? file.value : "the ledger file";
21158
+ return `workit ledger verify-integrity # lists the edited or missing rows; if the edit is understood, move ${where} aside (mv ${where} ${where}.tampered-<date>) and record the verdicts again`;
21159
+ }
21160
+ var tamperedWarning = (cwd, breaks) => `the ledger was edited, or a row was removed or moved (${breaks.slice(0, 3).map((row) => `${row.reason} at row ${row.seq}`).join(", ")}${breaks.length > 3 ? ", …" : ""}): no verdict is accepted until it is repaired. ${tamperedUnblock(cwd)}`;
21008
21161
  function verdictBasis(verdict, current) {
21009
21162
  if (verdict.head && verdict.head === current.head)
21010
21163
  return "fresh";
@@ -21012,7 +21165,7 @@ function verdictBasis(verdict, current) {
21012
21165
  return "carried";
21013
21166
  return "stale";
21014
21167
  }
21015
- var isLiveVerdict = (row) => row.type === "verdict" && typeof row.result === "string" && !row.superseded;
21168
+ var isLiveVerdict = (row, retired) => row.type === "verdict" && typeof row.result === "string" && !retired.has(row.id);
21016
21169
  function trailerSessions(cwd, base, head) {
21017
21170
  if (!base || !head || !safeRef(base) || !safeRef(head))
21018
21171
  return [];
@@ -21093,6 +21246,56 @@ var authoredBy = (authors, session) => {
21093
21246
  return true;
21094
21247
  return false;
21095
21248
  };
21249
+ var TRUST_REASONS = new Set([
21250
+ "unsigned",
21251
+ "hash_mismatch",
21252
+ "broken_link",
21253
+ "duplicate_id",
21254
+ "unissued_session",
21255
+ "unbound_session"
21256
+ ]);
21257
+ var SHELL_VOUCHED_HOSTS = new Set([
21258
+ "cli",
21259
+ "opencode",
21260
+ "pi",
21261
+ "codex_cli",
21262
+ "codex_desktop"
21263
+ ]);
21264
+ function sessionTrust(cwd, row) {
21265
+ const session = row.actor.session;
21266
+ if (!session || row.self === true)
21267
+ return null;
21268
+ const source = typeof row.sessionSource === "string" ? row.sessionSource : "env";
21269
+ const host = row.actor.host;
21270
+ const issuedOnly = source === "flag" ? host !== "cli" : source === "env" && session.includes(":") && !SHELL_VOUCHED_HOSTS.has(host);
21271
+ if (!issuedOnly)
21272
+ return null;
21273
+ const binding = issuedBinding(cwd, session);
21274
+ if (binding === null)
21275
+ return "unissued_session";
21276
+ return binding === "token" && row.sessionBound !== true ? "unbound_session" : null;
21277
+ }
21278
+ function trustReasons(cwd, row) {
21279
+ if (row.integrity === "unverified")
21280
+ return [row.integrityReason ?? "unsigned"];
21281
+ if (row.integrity !== "verified")
21282
+ return ["unsigned"];
21283
+ const session = sessionTrust(cwd, row);
21284
+ return session ? [session] : [];
21285
+ }
21286
+ function withIntegrity(cwd, rows) {
21287
+ if (rows.every((row) => row.integrity !== undefined))
21288
+ return rows;
21289
+ const read = readLedger(cwd, { integrity: true });
21290
+ const bySeq = new Map(read.ok ? read.value.rows.map((row) => [row.seq, row]) : []);
21291
+ return rows.map((row) => {
21292
+ if (row.integrity !== undefined)
21293
+ return row;
21294
+ const fresh = bySeq.get(row.seq);
21295
+ return fresh && fresh.id === row.id && fresh.at === row.at ? fresh : row;
21296
+ });
21297
+ }
21298
+ var untrusted = (reasons) => reasons.some((reason) => TRUST_REASONS.has(reason));
21096
21299
  var independenceReasons = (row, authors) => {
21097
21300
  const reasons = [];
21098
21301
  if (!row.actor.session)
@@ -21103,15 +21306,17 @@ var independenceReasons = (row, authors) => {
21103
21306
  reasons.push("self");
21104
21307
  return reasons;
21105
21308
  };
21106
- function effectiveOf(rows, authors, sameCode, isCurrent) {
21309
+ function effectiveOf(rows, reasonsOf, sameCode, isCurrent) {
21107
21310
  let effective = null;
21108
21311
  for (const row of rows) {
21109
21312
  if (!effective) {
21110
21313
  effective = row;
21111
21314
  continue;
21112
21315
  }
21113
- const rowIndependent = independenceReasons(row, authors).length === 0;
21114
- const effIndependent = independenceReasons(effective, authors).length === 0;
21316
+ if (untrusted(reasonsOf(row)) && !untrusted(reasonsOf(effective)))
21317
+ continue;
21318
+ const rowIndependent = reasonsOf(row).length === 0;
21319
+ const effIndependent = reasonsOf(effective).length === 0;
21115
21320
  if (effIndependent && !rowIndependent && isCurrent(effective))
21116
21321
  continue;
21117
21322
  if (effIndependent && FAILING.has(String(effective.result)) && row.actor.session === effective.actor.session && sameCode(effective, row))
@@ -21125,7 +21330,7 @@ function restackCarries(rows, branch, from, to) {
21125
21330
  return false;
21126
21331
  const edges = new Map;
21127
21332
  for (const row of rows)
21128
- if (row.type === "stack.restacked" && row.observer === "workit_cli" && row.branch === branch && row.patchEqual === true && typeof row.fromHead === "string" && row.head)
21333
+ if (row.type === "stack.restacked" && row.observer === "workit_cli" && row.integrity === "verified" && row.branch === branch && row.patchEqual === true && typeof row.fromHead === "string" && row.head)
21129
21334
  edges.set(row.fromHead, [...edges.get(row.fromHead) ?? [], row.head]);
21130
21335
  const seen = new Set([from]);
21131
21336
  const queue = [from];
@@ -21141,7 +21346,8 @@ function restackCarries(rows, branch, from, to) {
21141
21346
  }
21142
21347
  return false;
21143
21348
  }
21144
- function checkVerdicts(cwd, branch, rows) {
21349
+ function checkVerdicts(cwd, branch, ledgerRows) {
21350
+ const rows = withIntegrity(cwd, ledgerRows);
21145
21351
  const head = branchHead(cwd, branch);
21146
21352
  const fallbackBase = defaultBase(cwd);
21147
21353
  const scope = branchScope(cwd, branch);
@@ -21171,21 +21377,47 @@ function checkVerdicts(cwd, branch, rows) {
21171
21377
  return verdictBasis(failed, { head: row.head, ...keys }) !== "stale" || restackCarries(rows, branch, failed.head, row.head);
21172
21378
  };
21173
21379
  const authors = authorSessions(cwd, rows, branch, { base: fallbackBase, head }, scope);
21380
+ const failureAuthorCache = new Map;
21381
+ const failureAuthors = (row) => {
21382
+ let set = failureAuthorCache.get(row.seq);
21383
+ if (!set) {
21384
+ set = authorSessions(cwd, rows.filter((other) => other.integrity === "verified" && other.seq < row.seq), branch, { base: null, head: null }, scope);
21385
+ failureAuthorCache.set(row.seq, set);
21386
+ }
21387
+ return set;
21388
+ };
21389
+ const reasonCache = new Map;
21390
+ const reasonsOf = (row) => {
21391
+ let reasons = reasonCache.get(row);
21392
+ if (!reasons) {
21393
+ const failing = FAILING.has(String(row.result));
21394
+ reasons = [
21395
+ ...trustReasons(cwd, row),
21396
+ ...independenceReasons(row, failing ? failureAuthors(row) : authors)
21397
+ ];
21398
+ reasonCache.set(row, reasons);
21399
+ }
21400
+ return reasons;
21401
+ };
21402
+ const retired = new Set;
21403
+ for (const row of rows)
21404
+ if (row.type === "verdict" && row.supersedes && !row.supersedeIgnored && trustReasons(cwd, row).length === 0)
21405
+ retired.add(row.supersedes);
21174
21406
  const byKind = new Map;
21175
21407
  for (const row of rows)
21176
- if (isLiveVerdict(row) && scope(row)) {
21408
+ if (isLiveVerdict(row, retired) && scope(row)) {
21177
21409
  const kind = typeof row.kind === "string" ? row.kind : "review";
21178
21410
  byKind.set(kind, [...byKind.get(kind) ?? [], row]);
21179
21411
  }
21180
21412
  const verdicts = [];
21181
21413
  const warnings = [];
21182
21414
  for (const [kind, list] of byKind) {
21183
- const row = effectiveOf(list, authors, sameCode, (candidate) => basisOf(candidate) !== "stale");
21415
+ const row = effectiveOf(list, reasonsOf, sameCode, (candidate) => basisOf(candidate) !== "stale");
21184
21416
  if (!row)
21185
21417
  continue;
21186
21418
  const basis = basisOf(row);
21187
21419
  const current = basis !== "stale";
21188
- const independence = independenceReasons(row, authors);
21420
+ const independence = reasonsOf(row);
21189
21421
  const reasons = [
21190
21422
  ...current ? [] : ["stale"],
21191
21423
  ...PASSING.has(String(row.result)) ? [] : ["not_passing"],
@@ -21202,23 +21434,31 @@ function checkVerdicts(cwd, branch, rows) {
21202
21434
  });
21203
21435
  if (reasons.length === 0) {
21204
21436
  for (const later of list)
21205
- if (later.seq > row.seq && independenceReasons(later, authors).length > 0 && FAILING.has(String(later.result)) && basisOf(later) !== "stale")
21437
+ if (later.seq > row.seq && reasonsOf(later).length > 0 && !untrusted(reasonsOf(later)) && FAILING.has(String(later.result)) && basisOf(later) !== "stale")
21206
21438
  warnings.push(`the author's own (self) ${String(later.result)} ${kind} verdict ${later.id} by ${later.actor.session ?? "no session"} on the current code is newer than the accepted pass ${row.id}: read it before merging`);
21207
21439
  }
21208
21440
  }
21209
21441
  for (const row of rows)
21210
21442
  if (row.integrity === "unverified" && scope(row))
21211
21443
  warnings.push(`ledger row ${row.id} (${row.type}) on ${row.branch ?? branch} is unverified: the workit CLI did not write it or it changed afterwards (workit ledger verify-integrity)`);
21444
+ const tampered = ledgerTampering(cwd);
21445
+ if (tampered.length) {
21446
+ warnings.push(tamperedWarning(cwd, tampered));
21447
+ for (const entry of verdicts) {
21448
+ entry.accepted = false;
21449
+ entry.reasons = [...entry.reasons, "ledger_tampered"];
21450
+ }
21451
+ }
21212
21452
  verdicts.sort((a, b) => a.verdict.seq - b.verdict.seq);
21213
21453
  const newestCurrent = verdicts.findLast((entry) => entry.current) ?? verdicts.at(-1) ?? null;
21214
21454
  const failing = verdicts.find((entry) => entry.current && entry.independent && FAILING.has(String(entry.verdict.result)));
21215
21455
  const newestAccepted = verdicts.findLast((entry) => entry.accepted && STRONG_RESULTS.has(String(entry.verdict.result))) ?? null;
21216
- const accepted = newestAccepted && !failing ? { accepted: true, verdict: newestAccepted.verdict, reasons: [] } : {
21456
+ const accepted = tampered.length ? { accepted: false, verdict: null, reasons: ["ledger_tampered"] } : newestAccepted && !failing ? { accepted: true, verdict: newestAccepted.verdict, reasons: [] } : {
21217
21457
  accepted: false,
21218
21458
  verdict: failing?.verdict ?? null,
21219
21459
  reasons: failing ? ["failing_verdict"] : !newestCurrent ? ["no_verdict"] : newestCurrent.reasons.length ? newestCurrent.reasons : ["type_check_only"]
21220
21460
  };
21221
- const selfEntry = failing ? undefined : verdicts.findLast((entry) => entry.current && !entry.independent && STRONG_RESULTS.has(String(entry.verdict.result)));
21461
+ const selfEntry = failing ? undefined : verdicts.findLast((entry) => entry.current && !entry.independent && !untrusted(entry.reasons) && STRONG_RESULTS.has(String(entry.verdict.result)));
21222
21462
  return {
21223
21463
  branch,
21224
21464
  head,
@@ -21381,7 +21621,7 @@ var productDecision = (task, ledger) => {
21381
21621
  };
21382
21622
  };
21383
21623
  var planRecorded = (task, root) => {
21384
- const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(path13.resolve(root, ref.path)));
21624
+ const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(path15.resolve(root, ref.path)));
21385
21625
  if (cited)
21386
21626
  return {
21387
21627
  met: true,
@@ -21429,15 +21669,15 @@ function derivedRuleStatus(task, requirement, root, ledger) {
21429
21669
  }
21430
21670
 
21431
21671
  // packages/workit-core/src/core/task-evaluation.ts
21432
- var digestBytes = (value) => createHash9("sha256").update(value).digest("hex");
21433
- var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path14.sep}`);
21434
- var relative = (root, candidate) => path14.relative(root, candidate).split(path14.sep).join("/") || ".";
21672
+ var digestBytes = (value) => createHash10("sha256").update(value).digest("hex");
21673
+ var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path16.sep}`);
21674
+ var relative = (root, candidate) => path16.relative(root, candidate).split(path16.sep).join("/") || ".";
21435
21675
  var canonicalPath = (value) => {
21436
21676
  if (typeof value !== "string" || !value)
21437
21677
  return null;
21438
21678
  if (value.includes("\\") || value.split("/").includes(".."))
21439
21679
  return null;
21440
- const normalized = path14.posix.normalize(value);
21680
+ const normalized = path16.posix.normalize(value);
21441
21681
  if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
21442
21682
  return null;
21443
21683
  return normalized === "." ? "." : normalized.replace(/\/$/, "");
@@ -21485,21 +21725,21 @@ var gitPaths = (root) => {
21485
21725
  git: !/not a git repository/i.test(stderr)
21486
21726
  };
21487
21727
  }
21488
- const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path14.sep).join("/")) : [];
21728
+ const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path16.sep).join("/")) : [];
21489
21729
  const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
21490
21730
  if (stagedDeleted.status !== 0) {
21491
21731
  const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
21492
21732
  if (!/not a git repository/i.test(stderr))
21493
21733
  return { paths, uncertain: true, git: true };
21494
21734
  } else if (stagedDeleted.stdout) {
21495
- paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path14.sep).join("/")));
21735
+ paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path16.sep).join("/")));
21496
21736
  }
21497
21737
  return { paths: [...new Set(paths)], uncertain: false, git: true };
21498
21738
  };
21499
21739
  var walk = (root, directory, output) => {
21500
21740
  let names;
21501
21741
  try {
21502
- names = fs12.readdirSync(directory);
21742
+ names = fs13.readdirSync(directory);
21503
21743
  } catch {
21504
21744
  return true;
21505
21745
  }
@@ -21507,10 +21747,10 @@ var walk = (root, directory, output) => {
21507
21747
  for (const name of names) {
21508
21748
  if (name === ".git" || name === ".workit")
21509
21749
  continue;
21510
- const target = path14.join(directory, name);
21750
+ const target = path16.join(directory, name);
21511
21751
  let stat;
21512
21752
  try {
21513
- stat = fs12.lstatSync(target);
21753
+ stat = fs13.lstatSync(target);
21514
21754
  } catch {
21515
21755
  uncertain = true;
21516
21756
  continue;
@@ -21525,14 +21765,14 @@ var walk = (root, directory, output) => {
21525
21765
  var scopeRoots = (root, scope) => {
21526
21766
  const roots = [];
21527
21767
  for (const item of scope.paths.length ? scope.paths : ["."]) {
21528
- const target = path14.resolve(root, item);
21768
+ const target = path16.resolve(root, item);
21529
21769
  if (!inside(root, target))
21530
21770
  return failure2("invalid_input", `candidate scope escapes checkout: ${item} — keep one task per repository and coordinate a separate linked task in the other checkout`, { fields: [{ path: "scope.paths", reason: `${item} is outside the checkout` }] });
21531
21771
  let ancestor = target;
21532
- while (!fs12.existsSync(ancestor) && ancestor !== root)
21533
- ancestor = path14.dirname(ancestor);
21772
+ while (!fs13.existsSync(ancestor) && ancestor !== root)
21773
+ ancestor = path16.dirname(ancestor);
21534
21774
  try {
21535
- if (!inside(root, fs12.realpathSync(ancestor)))
21775
+ if (!inside(root, fs13.realpathSync(ancestor)))
21536
21776
  return failure2("invalid_input", `candidate scope escapes checkout through a symlink: ${item} — keep one task per repository and coordinate a separate linked task in the other checkout`, { fields: [{ path: "scope.paths", reason: `${item} resolves outside the checkout` }] });
21537
21777
  } catch {
21538
21778
  return failure2("invalid_input", `candidate scope cannot be inspected: ${item}`);
@@ -21544,7 +21784,7 @@ var scopeRoots = (root, scope) => {
21544
21784
  function captureCandidate(root, scope, environment = []) {
21545
21785
  let checkout;
21546
21786
  try {
21547
- checkout = fs12.realpathSync(root);
21787
+ checkout = fs13.realpathSync(root);
21548
21788
  } catch {
21549
21789
  return failure2("invalid_input", "candidate root does not exist");
21550
21790
  }
@@ -21562,11 +21802,11 @@ function captureCandidate(root, scope, environment = []) {
21562
21802
  if (item === ".git" || item === ".workit")
21563
21803
  continue;
21564
21804
  names.add(item);
21565
- if (!fs12.existsSync(target))
21805
+ if (!fs13.existsSync(target))
21566
21806
  continue;
21567
21807
  let stat;
21568
21808
  try {
21569
- stat = fs12.lstatSync(target);
21809
+ stat = fs13.lstatSync(target);
21570
21810
  } catch {
21571
21811
  uncertain = true;
21572
21812
  continue;
@@ -21582,17 +21822,17 @@ function captureCandidate(root, scope, environment = []) {
21582
21822
  for (const item of [...names].toSorted()) {
21583
21823
  if (!scopeMatches(item, normalizedScope))
21584
21824
  continue;
21585
- const target = path14.join(checkout, item);
21825
+ const target = path16.join(checkout, item);
21586
21826
  try {
21587
- const stat = fs12.lstatSync(target);
21827
+ const stat = fs13.lstatSync(target);
21588
21828
  if (stat.isSymbolicLink()) {
21589
- const link = fs12.readlinkSync(target);
21829
+ const link = fs13.readlinkSync(target);
21590
21830
  files.push({ path: item, kind: "symlink", digest: digestBytes(link), executable: null });
21591
21831
  } else if (stat.isFile()) {
21592
21832
  files.push({
21593
21833
  path: item,
21594
21834
  kind: "file",
21595
- digest: digestBytes(fs12.readFileSync(target)),
21835
+ digest: digestBytes(fs13.readFileSync(target)),
21596
21836
  executable: (stat.mode & 73) !== 0
21597
21837
  });
21598
21838
  } else if (!stat.isDirectory()) {
@@ -21757,7 +21997,7 @@ var findingVerificationPasses = (findingCandidateId, evidence) => evidence.statu
21757
21997
  var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
21758
21998
  let root;
21759
21999
  try {
21760
- root = fs12.realpathSync(checkoutRoot);
22000
+ root = fs13.realpathSync(checkoutRoot);
21761
22001
  } catch {
21762
22002
  return failure2("permission_denied", "checkout root is unavailable");
21763
22003
  }
@@ -21766,23 +22006,23 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
21766
22006
  continue;
21767
22007
  if (!reference.digest)
21768
22008
  return failure2("invalid_input", "document references require a byte digest");
21769
- const target = path14.resolve(root, reference.path);
21770
- if (target !== root && !target.startsWith(`${root}${path14.sep}`))
22009
+ const target = path16.resolve(root, reference.path);
22010
+ if (target !== root && !target.startsWith(`${root}${path16.sep}`))
21771
22011
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
21772
22012
  fields: [
21773
22013
  { path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
21774
22014
  ]
21775
22015
  });
21776
22016
  try {
21777
- const below = path14.relative(root, target);
22017
+ const below = path16.relative(root, target);
21778
22018
  let current = root;
21779
- for (const segment of below.split(path14.sep)) {
22019
+ for (const segment of below.split(path16.sep)) {
21780
22020
  if (!segment)
21781
22021
  continue;
21782
- current = path14.join(current, segment);
21783
- const stat = fs12.lstatSync(current);
21784
- const real = fs12.realpathSync(current);
21785
- if (real !== root && !real.startsWith(`${root}${path14.sep}`))
22022
+ current = path16.join(current, segment);
22023
+ const stat = fs13.lstatSync(current);
22024
+ const real = fs13.realpathSync(current);
22025
+ if (real !== root && !real.startsWith(`${root}${path16.sep}`))
21786
22026
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
21787
22027
  fields: [
21788
22028
  {
@@ -21798,7 +22038,7 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
21798
22038
  if (current !== target && !stat.isDirectory())
21799
22039
  return failure2("invalid_input", "document reference ancestor is not a directory");
21800
22040
  }
21801
- if (digestBytes(fs12.readFileSync(target)) !== reference.digest)
22041
+ if (digestBytes(fs13.readFileSync(target)) !== reference.digest)
21802
22042
  return failure2("permission_denied", "decision document bytes have changed");
21803
22043
  } catch {
21804
22044
  return failure2("invalid_input", "decision document is unavailable");
@@ -22656,7 +22896,7 @@ var judgeInputSummary = (raw) => {
22656
22896
 
22657
22897
  // packages/workit-core/src/autonomy.ts
22658
22898
  import os4 from "node:os";
22659
- import path15 from "node:path";
22899
+ import path17 from "node:path";
22660
22900
  var accountHome = () => {
22661
22901
  try {
22662
22902
  return os4.userInfo().homedir;
@@ -22665,10 +22905,10 @@ var accountHome = () => {
22665
22905
  }
22666
22906
  };
22667
22907
  var grantsHome = { resolve: accountHome };
22668
- var grantsDir = () => path15.join(grantsHome.resolve(), ".config", "workit");
22908
+ var grantsDir = () => path17.join(grantsHome.resolve(), ".config", "workit");
22669
22909
  var grantsOverride = () => {
22670
- const configured = path15.resolve(resolveConfigDir());
22671
- return configured === path15.resolve(grantsDir()) ? null : `the config directory is redirected to ${configured} (WORKFLOW_TOOLKIT_CONFIG, WORKFLOW_TOOLKIT_CONFIG_DIR or XDG_CONFIG_HOME); grants are read only from ${path15.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
22910
+ const configured = path17.resolve(resolveConfigDir());
22911
+ return configured === path17.resolve(grantsDir()) ? null : `the config directory is redirected to ${configured} (WORKFLOW_TOOLKIT_CONFIG, WORKFLOW_TOOLKIT_CONFIG_DIR or XDG_CONFIG_HOME); grants are read only from ${path17.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
22672
22912
  };
22673
22913
  var GRANT_KINDS = ["push", "pr", "merge", "release", "rerun"];
22674
22914
  var DEFAULT_GRANTS = Object.freeze({
@@ -24440,7 +24680,7 @@ class WorkitCore {
24440
24680
  // packages/workit-core/src/core/repo-context.ts
24441
24681
  import { spawnSync as spawnSync11 } from "node:child_process";
24442
24682
  import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync4 } from "node:fs";
24443
- import path16 from "node:path";
24683
+ import path18 from "node:path";
24444
24684
  var isSafeContextRange = (value) => value.length <= 4096 && (() => {
24445
24685
  try {
24446
24686
  gitRevisionParts(value);
@@ -24574,7 +24814,7 @@ var findPrTemplate = (cwd) => {
24574
24814
  ]) {
24575
24815
  const parts = rel.split("/");
24576
24816
  const base = parts[parts.length - 1];
24577
- const dir = parts.length > 1 ? path16.join(cwd, ...parts.slice(0, -1)) : cwd;
24817
+ const dir = parts.length > 1 ? path18.join(cwd, ...parts.slice(0, -1)) : cwd;
24578
24818
  const actual = probeCaseInsensitive(dir, base);
24579
24819
  if (actual)
24580
24820
  return [...parts.slice(0, -1), actual].join("/");
@@ -24605,7 +24845,7 @@ var diffStatForRange = (cwd, range) => {
24605
24845
  return runGit(cwd, ["diff", "--stat", "--"]).stdout;
24606
24846
  };
24607
24847
  var packageScripts = (cwd, keys) => {
24608
- const pkgPath = path16.join(cwd, "package.json");
24848
+ const pkgPath = path18.join(cwd, "package.json");
24609
24849
  if (!existsSync6(pkgPath))
24610
24850
  return [];
24611
24851
  try {
@@ -24631,9 +24871,9 @@ var documentationFiles = (cwd) => {
24631
24871
  if (entry.isDirectory()) {
24632
24872
  if (excluded.has(entry.name))
24633
24873
  continue;
24634
- walk(path16.join(dir, entry.name), depth + 1);
24874
+ walk(path18.join(dir, entry.name), depth + 1);
24635
24875
  } else if (entry.isFile() && (entry.name === "README.md" || entry.name.endsWith(".md"))) {
24636
- matches.push("./" + path16.relative(cwd, path16.join(dir, entry.name)).replaceAll("\\", "/"));
24876
+ matches.push("./" + path18.relative(cwd, path18.join(dir, entry.name)).replaceAll("\\", "/"));
24637
24877
  }
24638
24878
  }
24639
24879
  };
@@ -24649,7 +24889,7 @@ var readTrimmed2 = (file, maxLines) => {
24649
24889
  `);
24650
24890
  };
24651
24891
  function prReadyContext(root, range) {
24652
- const cwd = path16.resolve(repoRoot(root));
24892
+ const cwd = path18.resolve(repoRoot(root));
24653
24893
  if (range !== undefined && !isResolvableContextRange(cwd, range))
24654
24894
  return invalidRange(cwd);
24655
24895
  let stdout = "";
@@ -24707,7 +24947,7 @@ ${status.stderr}` : "");
24707
24947
  stdout += `template_path: ${template}
24708
24948
 
24709
24949
  `;
24710
- stdout += readTrimmed2(path16.join(cwd, template), 220);
24950
+ stdout += readTrimmed2(path18.join(cwd, template), 220);
24711
24951
  } else {
24712
24952
  stdout += `template_path: none
24713
24953
 
@@ -24717,7 +24957,7 @@ ${status.stderr}` : "");
24717
24957
  stdout += `
24718
24958
  `;
24719
24959
  stdout += printSection("Recent Validation Signals");
24720
- if (existsSync6(path16.join(cwd, "package.json"))) {
24960
+ if (existsSync6(path18.join(cwd, "package.json"))) {
24721
24961
  stdout += `package.json detected. Common scripts:
24722
24962
  `;
24723
24963
  const found = packageScripts(cwd, ["lint", "format:check", "test", "build"]);
@@ -24726,7 +24966,7 @@ ${status.stderr}` : "");
24726
24966
  `) + `
24727
24967
  `;
24728
24968
  }
24729
- if (existsSync6(path16.join(cwd, "Cargo.toml")) || existsSync6(path16.join(cwd, "src-tauri/Cargo.toml"))) {
24969
+ if (existsSync6(path18.join(cwd, "Cargo.toml")) || existsSync6(path18.join(cwd, "src-tauri/Cargo.toml"))) {
24730
24970
  stdout += `Rust project detected.
24731
24971
  `;
24732
24972
  }
@@ -24759,7 +24999,7 @@ var CHANGELOG_RULES = `- Use an [Unreleased] section.
24759
24999
  - Apply with the host-native editor, preserving the repository changelog conventions.
24760
25000
  - If Unreleased already has duplicate category headings, normalize_only first.`;
24761
25001
  function changelogContext(root, range) {
24762
- const cwd = path16.resolve(repoRoot(root));
25002
+ const cwd = path18.resolve(repoRoot(root));
24763
25003
  if (range !== undefined && !isResolvableContextRange(cwd, range))
24764
25004
  return invalidRange(cwd);
24765
25005
  const resolvedRange = rangeArgOrDefault(range, cwd);
@@ -24777,7 +25017,7 @@ function changelogContext(root, range) {
24777
25017
  stdout += CHANGELOG_RULES + `
24778
25018
  `;
24779
25019
  stdout += printSection("Existing CHANGELOG.md");
24780
- const changelogPath = path16.join(cwd, "CHANGELOG.md");
25020
+ const changelogPath = path18.join(cwd, "CHANGELOG.md");
24781
25021
  if (existsSync6(changelogPath)) {
24782
25022
  stdout += readTrimmed2(changelogPath, 260) + `
24783
25023
  `;
@@ -24797,7 +25037,7 @@ function changelogContext(root, range) {
24797
25037
  return { stdout, stderr: "", exitCode: 0, cwd };
24798
25038
  }
24799
25039
  function docsRefreshContext(root, range) {
24800
- const cwd = path16.resolve(repoRoot(root));
25040
+ const cwd = path18.resolve(repoRoot(root));
24801
25041
  if (range !== undefined && !isResolvableContextRange(cwd, range))
24802
25042
  return invalidRange(cwd);
24803
25043
  const resolvedRange = rangeArgOrDefault(range, cwd);
@@ -24819,7 +25059,7 @@ function docsRefreshContext(root, range) {
24819
25059
  `) + `
24820
25060
  `;
24821
25061
  stdout += printSection("README Preview");
24822
- const readme = path16.join(cwd, "README.md");
25062
+ const readme = path18.join(cwd, "README.md");
24823
25063
  if (existsSync6(readme)) {
24824
25064
  stdout += readTrimmed2(readme, 220) + `
24825
25065
  `;
@@ -24828,7 +25068,7 @@ function docsRefreshContext(root, range) {
24828
25068
  `;
24829
25069
  }
24830
25070
  stdout += printSection("Package Scripts");
24831
- const pkgPath = path16.join(cwd, "package.json");
25071
+ const pkgPath = path18.join(cwd, "package.json");
24832
25072
  if (existsSync6(pkgPath)) {
24833
25073
  try {
24834
25074
  const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
@@ -24842,7 +25082,7 @@ function docsRefreshContext(root, range) {
24842
25082
  return { stdout, stderr: "", exitCode: 0, cwd };
24843
25083
  }
24844
25084
  function releaseNotesContext(root, rangeOrTag) {
24845
- const cwd = path16.resolve(repoRoot(root));
25085
+ const cwd = path18.resolve(repoRoot(root));
24846
25086
  if (!rangeOrTag) {
24847
25087
  return { stdout: "", stderr: `ERROR: release tag or range required
24848
25088
  `, exitCode: 1, cwd };
@@ -24880,7 +25120,7 @@ function releaseNotesContext(root, rangeOrTag) {
24880
25120
  `;
24881
25121
  stdout += printSection("Existing Release Files");
24882
25122
  for (const rel of ["CHANGELOG.md", "RELEASE_NOTES.md", ".github/releases.md"]) {
24883
- if (existsSync6(path16.join(cwd, rel)))
25123
+ if (existsSync6(path18.join(cwd, rel)))
24884
25124
  stdout += rel + `
24885
25125
  `;
24886
25126
  }
@@ -24911,8 +25151,8 @@ function releaseNotesContext(root, rangeOrTag) {
24911
25151
  import { spawnSync as spawnSync13 } from "node:child_process";
24912
25152
 
24913
25153
  // packages/workit-core/src/core/pr-create.ts
24914
- import fs13 from "node:fs";
24915
- import path17 from "node:path";
25154
+ import fs14 from "node:fs";
25155
+ import path19 from "node:path";
24916
25156
  import { spawnSync as spawnSync12 } from "node:child_process";
24917
25157
  // packages/workit-core/src/forge/pr-body.ts
24918
25158
  function parseGhIssue(value) {
@@ -24923,13 +25163,13 @@ function parseGhIssue(value) {
24923
25163
  // packages/workit-core/src/core/pr-create.ts
24924
25164
  function whichOnPath(tool) {
24925
25165
  const names = process.platform === "win32" ? [tool, `${tool}.exe`, `${tool}.cmd`] : [tool];
24926
- for (const dir of (process.env.PATH ?? "").split(path17.delimiter)) {
25166
+ for (const dir of (process.env.PATH ?? "").split(path19.delimiter)) {
24927
25167
  if (!dir)
24928
25168
  continue;
24929
25169
  for (const name of names) {
24930
- const candidate = path17.join(dir, name);
25170
+ const candidate = path19.join(dir, name);
24931
25171
  try {
24932
- fs13.accessSync(candidate, fs13.constants.X_OK);
25172
+ fs14.accessSync(candidate, fs14.constants.X_OK);
24933
25173
  return candidate;
24934
25174
  } catch {}
24935
25175
  }
@@ -25047,8 +25287,8 @@ var fetchGitLabIssueBody = async (ref, root, deps = {}) => {
25047
25287
  };
25048
25288
 
25049
25289
  // packages/workit-core/src/core/youtrack.ts
25050
- import fs14 from "node:fs";
25051
- import path18 from "node:path";
25290
+ import fs15 from "node:fs";
25291
+ import path20 from "node:path";
25052
25292
 
25053
25293
  // packages/workit-core/src/core/templates.ts
25054
25294
  var repoRoot2 = assetRoot();
@@ -25061,22 +25301,22 @@ var resolveWorkspaceRoot = (explicit) => explicit || process.cwd();
25061
25301
  // packages/workit-core/src/core/youtrack.ts
25062
25302
  var ISSUE_RE = /^[A-Z]+-\d+$/;
25063
25303
  var TOKEN_PLACEHOLDER = "YOUR_TOKEN_HERE";
25064
- var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path18.join(configDir(), "youtrack.json");
25065
- var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path18.join(resolveConfigDir(), "youtrack.json");
25304
+ var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path20.join(configDir(), "youtrack.json");
25305
+ var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path20.join(resolveConfigDir(), "youtrack.json");
25066
25306
  var youTrackTokenModeOk = (p) => {
25067
25307
  if (process.platform === "win32")
25068
25308
  return true;
25069
- const mode = fs14.statSync(p).mode & 511;
25309
+ const mode = fs15.statSync(p).mode & 511;
25070
25310
  return mode === 384;
25071
25311
  };
25072
25312
  function readYouTrackConfig(required) {
25073
25313
  const cfgPath = youTrackConfigPath();
25074
- if (!fs14.existsSync(cfgPath)) {
25314
+ if (!fs15.existsSync(cfgPath)) {
25075
25315
  return required ? { error: "ERROR: missing youtrack.json", path: cfgPath } : { config: {}, path: cfgPath };
25076
25316
  }
25077
25317
  let parsed;
25078
25318
  try {
25079
- parsed = JSON.parse(fs14.readFileSync(cfgPath, "utf8"));
25319
+ parsed = JSON.parse(fs15.readFileSync(cfgPath, "utf8"));
25080
25320
  } catch {
25081
25321
  return { error: `${cfgPath} is not valid JSON`, path: cfgPath };
25082
25322
  }
@@ -25087,11 +25327,11 @@ function readYouTrackConfig(required) {
25087
25327
  }
25088
25328
  var readYouTrackContextConfig = () => {
25089
25329
  const cfgPath = youTrackReadOnlyConfigPath();
25090
- if (!fs14.existsSync(cfgPath))
25330
+ if (!fs15.existsSync(cfgPath))
25091
25331
  return { data: {} };
25092
25332
  let parsed;
25093
25333
  try {
25094
- parsed = JSON.parse(fs14.readFileSync(cfgPath, "utf8"));
25334
+ parsed = JSON.parse(fs15.readFileSync(cfgPath, "utf8"));
25095
25335
  } catch {
25096
25336
  return { error: "YouTrack configuration is unavailable" };
25097
25337
  }
@@ -25130,12 +25370,12 @@ var youTrackToken = () => {
25130
25370
  if ("error" in loaded)
25131
25371
  return loaded;
25132
25372
  const tokenFile = String(loaded.config.tokenFile ?? "");
25133
- const tokenPath = tokenFile ? path18.isAbsolute(tokenFile) ? path18.resolve(tokenFile) : path18.resolve(process.cwd(), tokenFile) : "";
25134
- if (!tokenPath || !fs14.existsSync(tokenPath))
25373
+ const tokenPath = tokenFile ? path20.isAbsolute(tokenFile) ? path20.resolve(tokenFile) : path20.resolve(process.cwd(), tokenFile) : "";
25374
+ if (!tokenPath || !fs15.existsSync(tokenPath))
25135
25375
  return { error: "missing youtrack.token" };
25136
25376
  if (!youTrackTokenModeOk(tokenPath))
25137
25377
  return { error: "youtrack.token mode must be 0600" };
25138
- const token = fs14.readFileSync(tokenPath, "utf8").trim();
25378
+ const token = fs15.readFileSync(tokenPath, "utf8").trim();
25139
25379
  if (!token)
25140
25380
  return { error: "empty token file" };
25141
25381
  if (token === TOKEN_PLACEHOLDER || token.startsWith(TOKEN_PLACEHOLDER)) {
@@ -25200,9 +25440,9 @@ function resolveYouTrackFromPaths(spec_path, plan_path, workspace_root) {
25200
25440
  } catch {
25201
25441
  continue;
25202
25442
  }
25203
- if (!fs14.existsSync(full))
25443
+ if (!fs15.existsSync(full))
25204
25444
  continue;
25205
- const text = fs14.readFileSync(full, "utf8");
25445
+ const text = fs15.readFileSync(full, "utf8");
25206
25446
  const m = text.match(/^\*\*YouTrack:\*\*\s*`?([A-Z]+-\d+)`?/m);
25207
25447
  if (m)
25208
25448
  return m[1];
@@ -25472,15 +25712,15 @@ function resolveGitRevision(root, value) {
25472
25712
  }
25473
25713
  function resolveInside(root, candidate) {
25474
25714
  const base = realpathSync5(root);
25475
- const target = path19.resolve(base, candidate);
25476
- if (target !== base && !target.startsWith(base + path19.sep)) {
25715
+ const target = path21.resolve(base, candidate);
25716
+ if (target !== base && !target.startsWith(base + path21.sep)) {
25477
25717
  throw new Error("path must stay inside repository root");
25478
25718
  }
25479
25719
  let ancestor = target;
25480
25720
  while (!existsSync7(ancestor))
25481
- ancestor = path19.dirname(ancestor);
25721
+ ancestor = path21.dirname(ancestor);
25482
25722
  const canonicalAncestor = realpathSync5(ancestor);
25483
- if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path19.sep)) {
25723
+ if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path21.sep)) {
25484
25724
  throw new Error("path must stay inside repository root");
25485
25725
  }
25486
25726
  return target;
@@ -25512,7 +25752,7 @@ var SUPPORT_MATRIX = {
25512
25752
 
25513
25753
  // packages/workit-mcp/src/server.ts
25514
25754
  import { existsSync as existsSync8, readFileSync as readFileSync6, realpathSync as realpathSync6 } from "node:fs";
25515
- import path20 from "node:path";
25755
+ import path22 from "node:path";
25516
25756
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
25517
25757
  function isZ4Schema(s) {
25518
25758
  const schema = s;
@@ -27926,13 +28166,13 @@ var rootVariants = (workspaceRoot) => {
27926
28166
  if (!workspaceRoot)
27927
28167
  return [];
27928
28168
  const roots = new Set;
27929
- for (const candidate of [workspaceRoot, path20.resolve(workspaceRoot)]) {
27930
- if (path20.isAbsolute(candidate) && candidate !== path20.parse(candidate).root)
28169
+ for (const candidate of [workspaceRoot, path22.resolve(workspaceRoot)]) {
28170
+ if (path22.isAbsolute(candidate) && candidate !== path22.parse(candidate).root)
27931
28171
  roots.add(candidate);
27932
28172
  }
27933
28173
  try {
27934
28174
  const canonical = realpathSync6(workspaceRoot);
27935
- if (canonical !== path20.parse(canonical).root)
28175
+ if (canonical !== path22.parse(canonical).root)
27936
28176
  roots.add(canonical);
27937
28177
  } catch {}
27938
28178
  return [...roots].toSorted((left, right) => right.length - left.length);
@@ -28014,11 +28254,11 @@ var thrownResult = (tool, error, workspaceRoot) => {
28014
28254
  };
28015
28255
  function createMcpServer(host, contextProvider) {
28016
28256
  assertMcpHost(host);
28017
- const here = path20.dirname(fileURLToPath2(import.meta.url));
28257
+ const here = path22.dirname(fileURLToPath2(import.meta.url));
28018
28258
  const sourceMarker = markSourcesLoaded([
28019
- path20.join(here, "server.ts"),
28020
- path20.join(here, "..", "..", "workit-core", "src", "core", "task-contract.ts"),
28021
- path20.join(here, "..", "..", "workit-core", "src", "core", "task-engine.ts")
28259
+ path22.join(here, "server.ts"),
28260
+ path22.join(here, "..", "..", "workit-core", "src", "core", "task-contract.ts"),
28261
+ path22.join(here, "..", "..", "workit-core", "src", "core", "task-engine.ts")
28022
28262
  ].filter((file) => existsSync8(file)));
28023
28263
  let staleWarned = false;
28024
28264
  const server = new Server({ name: "workit", version: VERSION }, { capabilities: { tools: {}, resources: {} } });
@@ -28401,14 +28641,14 @@ import {
28401
28641
  writeFileSync as writeFileSync3
28402
28642
  } from "node:fs";
28403
28643
  import os5 from "node:os";
28404
- import path21 from "node:path";
28644
+ import path23 from "node:path";
28405
28645
  var CODEX_AGENT_MARKER = "# Generated by Workit";
28406
28646
  var codexHomeOfInstall = (pluginRoot) => {
28407
- const parts = path21.resolve(pluginRoot).split(path21.sep);
28647
+ const parts = path23.resolve(pluginRoot).split(path23.sep);
28408
28648
  const cache = parts.length - 4;
28409
- return cache >= 2 && parts[cache] === "cache" && parts[cache - 1] === "plugins" ? parts.slice(0, cache - 1).join(path21.sep) || path21.sep : null;
28649
+ return cache >= 2 && parts[cache] === "cache" && parts[cache - 1] === "plugins" ? parts.slice(0, cache - 1).join(path23.sep) || path23.sep : null;
28410
28650
  };
28411
- var codexHomeFor = (pluginRoot, env) => codexHomeOfInstall(pluginRoot) ?? (env.CODEX_HOME || path21.join(env.HOME || os5.homedir(), ".codex"));
28651
+ var codexHomeFor = (pluginRoot, env) => codexHomeOfInstall(pluginRoot) ?? (env.CODEX_HOME || path23.join(env.HOME || os5.homedir(), ".codex"));
28412
28652
  var MARKER_VERSION = /^# Generated by Workit (\d+\.\d+\.\d+)\b/;
28413
28653
  var agentMarkerVersion = (text) => MARKER_VERSION.exec(text)?.[1] ?? null;
28414
28654
  var stampCodexAgent = (content, version) => version && content.startsWith(CODEX_AGENT_MARKER) && !agentMarkerVersion(content) ? `${CODEX_AGENT_MARKER} ${version}${content.slice(CODEX_AGENT_MARKER.length)}` : content;
@@ -28422,7 +28662,7 @@ var versionAtLeast = (version, min) => {
28422
28662
  };
28423
28663
  var pluginVersion = (pluginRoot) => {
28424
28664
  try {
28425
- const version = JSON.parse(readFileSync7(path21.join(pluginRoot, "package.json"), "utf8")).version;
28665
+ const version = JSON.parse(readFileSync7(path23.join(pluginRoot, "package.json"), "utf8")).version;
28426
28666
  return typeof version === "string" && /^\d+\.\d+\.\d+/.test(version) ? version.match(/^\d+\.\d+\.\d+/)[0] : null;
28427
28667
  } catch {
28428
28668
  return null;
@@ -28436,15 +28676,15 @@ var lstatOrNull = (file) => {
28436
28676
  }
28437
28677
  };
28438
28678
  var installCodexAgents = (pluginRoot, codexHome) => {
28439
- const source = path21.join(pluginRoot, "agents");
28679
+ const source = path23.join(pluginRoot, "agents");
28440
28680
  if (!existsSync9(source))
28441
28681
  return [];
28442
28682
  const version = pluginVersion(pluginRoot);
28443
- const target = path21.join(codexHome, "agents");
28683
+ const target = path23.join(codexHome, "agents");
28444
28684
  const results = [];
28445
28685
  for (const file of readdirSync5(source).filter((name) => name.endsWith(".toml")).toSorted()) {
28446
- const content = stampCodexAgent(readFileSync7(path21.join(source, file), "utf8"), version);
28447
- const dest = path21.join(target, file);
28686
+ const content = stampCodexAgent(readFileSync7(path23.join(source, file), "utf8"), version);
28687
+ const dest = path23.join(target, file);
28448
28688
  const stat = lstatOrNull(dest);
28449
28689
  if (stat?.isSymbolicLink()) {
28450
28690
  results.push({ file: dest, action: "skipped-symlink" });
@@ -28480,7 +28720,7 @@ var installCodexAgents = (pluginRoot, codexHome) => {
28480
28720
  results.push({ file: dest, action: "kept-newer-version" });
28481
28721
  continue;
28482
28722
  }
28483
- const temp = path21.join(target, `.${file}.${process.pid}.${Date.now()}.tmp`);
28723
+ const temp = path23.join(target, `.${file}.${process.pid}.${Date.now()}.tmp`);
28484
28724
  writeFileSync3(temp, content, { flag: "wx" });
28485
28725
  try {
28486
28726
  renameSync2(temp, dest);
@@ -28502,8 +28742,8 @@ var codexQualification = (host) => host === "codex_cli" ? { surface: host, cli:
28502
28742
  var resolveCodexWorkspaceRoot = (pluginRoot, env) => {
28503
28743
  const explicit = env.WORKFLOW_WORKSPACE_ROOT;
28504
28744
  const inherited = env.PWD;
28505
- const candidate = explicit ?? (inherited && path22.resolve(inherited) !== path22.resolve(pluginRoot) ? inherited : undefined);
28506
- if (!candidate || !path22.isAbsolute(candidate) || !existsSync10(candidate))
28745
+ const candidate = explicit ?? (inherited && path24.resolve(inherited) !== path24.resolve(pluginRoot) ? inherited : undefined);
28746
+ if (!candidate || !path24.isAbsolute(candidate) || !existsSync10(candidate))
28507
28747
  return null;
28508
28748
  try {
28509
28749
  if (!statSync3(candidate).isDirectory())
@@ -28542,7 +28782,7 @@ var codexContextProvider = (host = detectCodexSurface(process.env), root) => ({
28542
28782
  };
28543
28783
  }
28544
28784
  });
28545
- var pluginRoot = () => path22.resolve(path22.dirname(fileURLToPath3(import.meta.url)), "..");
28785
+ var pluginRoot = () => path24.resolve(path24.dirname(fileURLToPath3(import.meta.url)), "..");
28546
28786
  var syncCodexAgents = (root) => {
28547
28787
  const codexHome = codexHomeOfInstall(root);
28548
28788
  if (!codexHome)