@brainervirus/workit-codex 8.9.1 → 8.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -24,9 +24,9 @@ var capabilitiesFor = (descriptor, observed = {}) => descriptor.capabilities.map
24
24
  };
25
25
  });
26
26
  // packages/workit-core/src/hooks/context.ts
27
- import { createHash as createHash10 } from "node:crypto";
28
- import fs13 from "node:fs";
29
- import path16 from "node:path";
27
+ import { createHash as createHash11 } from "node:crypto";
28
+ import fs14 from "node:fs";
29
+ import path17 from "node:path";
30
30
 
31
31
  // packages/workit-core/src/core/methods.ts
32
32
  var METHODS = {
@@ -101,7 +101,8 @@ Autonomy contract:
101
101
  satisfies a gate; an ad-hoc \`workit check -- <cmd>\` never does.
102
102
  - Author is not verifier: your own verdict is \`--self\`, shown as
103
103
  self-reviewed, never verified. High risk, \`verification: independent\` and
104
- merge need a verifier with its own session (\`WORKIT_SESSION_ID=<lead>-v<n>\`).
104
+ merge need a verifier with its own host-derived session (a subagent's
105
+ \`<lead>:<child>\`, set by the host); never hand-mint one such as \`<lead>-v1\`.
105
106
  - A local-commit endpoint does not imply PR readiness, and a local commit alone
106
107
  is not evidence of a requested remote push. Before reporting delivery,
107
108
  reconcile every requested item and observe it (\`workit verify-delivery\`).
@@ -8787,10 +8788,10 @@ function requirementId(input) {
8787
8788
  }
8788
8789
 
8789
8790
  // packages/workit-core/src/core/task-evaluation.ts
8790
- import { createHash as createHash9 } from "node:crypto";
8791
- import * as fs12 from "node:fs";
8791
+ import { createHash as createHash10 } from "node:crypto";
8792
+ import * as fs13 from "node:fs";
8792
8793
  import { spawnSync as spawnSync10 } from "node:child_process";
8793
- import path14 from "node:path";
8794
+ import path15 from "node:path";
8794
8795
 
8795
8796
  // packages/workit-core/src/check-config.ts
8796
8797
  import { spawnSync as spawnSync2 } from "node:child_process";
@@ -9179,9 +9180,9 @@ function pushRemoteName(cwd, branch) {
9179
9180
  }
9180
9181
 
9181
9182
  // packages/workit-core/src/core/task-store.ts
9182
- import { createHash as createHash5, randomUUID as randomUUID3 } from "node:crypto";
9183
- import * as fs9 from "node:fs";
9184
- import path8 from "node:path";
9183
+ import { createHash as createHash6, randomUUID as randomUUID3 } from "node:crypto";
9184
+ import * as fs10 from "node:fs";
9185
+ import path9 from "node:path";
9185
9186
 
9186
9187
  // node_modules/@openclaw/fs-safe/dist/errors.js
9187
9188
  var OPERATIONAL_CODES = new Set([
@@ -9785,6 +9786,9 @@ function acquireFileLockSync(targetPath, options) {
9785
9786
  }
9786
9787
  }
9787
9788
  // packages/workit-core/src/host-session.ts
9789
+ import { createHash as createHash4 } from "node:crypto";
9790
+ import fs7 from "node:fs";
9791
+ import path6 from "node:path";
9788
9792
  var HOST_SESSION_VARS = [
9789
9793
  ["OPENCODE_SESSION_ID", () => "opencode"],
9790
9794
  ["PI_SESSION_ID", () => "pi"],
@@ -9812,16 +9816,44 @@ function hostSessionFromEnv(env) {
9812
9816
  }
9813
9817
  return inner ? { host: inner.host, session: inner.session } : { host: declared, session: null };
9814
9818
  }
9819
+ var ISSUED_PER_LEAD = 64;
9820
+ var ISSUED_SESSIONS_MARKER = "workit-issued-sessions/1";
9821
+ var hash = (value) => createHash4("sha256").update(value).digest("hex").slice(0, 32);
9822
+ var issuedRoot = (cwd) => {
9823
+ const location = resolveStore(cwd);
9824
+ return location instanceof Error ? null : path6.join(location.dir, "hooks", "issued");
9825
+ };
9826
+ var issuedDir = (cwd, lead) => {
9827
+ const root = issuedRoot(cwd);
9828
+ return root === null ? null : path6.join(root, hash(lead));
9829
+ };
9830
+ function recordIssuedSession(cwd, lead, issued) {
9831
+ try {
9832
+ const dir = issuedDir(cwd, lead);
9833
+ if (!dir)
9834
+ return;
9835
+ fs7.mkdirSync(dir, { recursive: true });
9836
+ const own = hash(issued);
9837
+ fs7.writeFileSync(path6.join(dir, own), ISSUED_SESSIONS_MARKER);
9838
+ const entries = fs7.readdirSync(dir);
9839
+ if (entries.length <= ISSUED_PER_LEAD)
9840
+ return;
9841
+ const byAge = entries.filter((name) => name !== own).map((name) => ({ name, at: fs7.statSync(path6.join(dir, name)).mtimeMs })).toSorted((a, b) => a.at - b.at);
9842
+ for (const { name } of byAge.slice(0, entries.length - ISSUED_PER_LEAD))
9843
+ fs7.rmSync(path6.join(dir, name), { force: true });
9844
+ } catch {}
9845
+ }
9846
+ var OWN_CHILD_SHELL = new Set(["opencode", "pi"]);
9815
9847
 
9816
9848
  // packages/workit-core/src/core/package-root.ts
9817
9849
  import { existsSync } from "node:fs";
9818
- import path6 from "node:path";
9850
+ import path7 from "node:path";
9819
9851
  import { fileURLToPath } from "node:url";
9820
9852
  var packageRoot = () => {
9821
- let dir = path6.dirname(fileURLToPath(import.meta.url));
9853
+ let dir = path7.dirname(fileURLToPath(import.meta.url));
9822
9854
  while (true) {
9823
- const parent = path6.dirname(dir);
9824
- if (existsSync(path6.join(dir, "package.json")) || parent === dir)
9855
+ const parent = path7.dirname(dir);
9856
+ if (existsSync(path7.join(dir, "package.json")) || parent === dir)
9825
9857
  return dir;
9826
9858
  dir = parent;
9827
9859
  }
@@ -9829,7 +9861,7 @@ var packageRoot = () => {
9829
9861
 
9830
9862
  // packages/workit-core/src/core/store-lock.ts
9831
9863
  import { spawnSync as spawnSync4 } from "node:child_process";
9832
- import fs7 from "node:fs";
9864
+ import fs8 from "node:fs";
9833
9865
  import { hostname } from "node:os";
9834
9866
  var metadataLockSchema = object({
9835
9867
  pid: number2().int().nonnegative().safe(),
@@ -9871,7 +9903,7 @@ var parseProcStatStart = (stat) => {
9871
9903
  var processStartOf = (pid) => {
9872
9904
  if (process.platform === "linux") {
9873
9905
  try {
9874
- return parseProcStatStart(fs7.readFileSync(`/proc/${pid}/stat`, "utf8"));
9906
+ return parseProcStatStart(fs8.readFileSync(`/proc/${pid}/stat`, "utf8"));
9875
9907
  } catch {
9876
9908
  return null;
9877
9909
  }
@@ -9892,7 +9924,7 @@ var processStartOf = (pid) => {
9892
9924
  };
9893
9925
  var readTrimmed = (file) => {
9894
9926
  try {
9895
- return fs7.readFileSync(file, "utf8").trim() || null;
9927
+ return fs8.readFileSync(file, "utf8").trim() || null;
9896
9928
  } catch {
9897
9929
  return null;
9898
9930
  }
@@ -9903,7 +9935,7 @@ var localLockHost = () => {
9903
9935
  return cachedLockHost;
9904
9936
  let pidns = null;
9905
9937
  try {
9906
- pidns = /\[(\d+)\]/.exec(fs7.readlinkSync("/proc/self/ns/pid"))?.[1] ?? null;
9938
+ pidns = /\[(\d+)\]/.exec(fs8.readlinkSync("/proc/self/ns/pid"))?.[1] ?? null;
9907
9939
  } catch {}
9908
9940
  const boot = readTrimmed("/proc/sys/kernel/random/boot_id");
9909
9941
  cachedLockHost = pidns || boot ? `${hostname()}#${pidns ?? "?"}:${boot ?? "?"}` : hostname();
@@ -9949,7 +9981,7 @@ var classifyLockOwner = (payload, ageMs, localHost = localLockHost(), options =
9949
9981
  };
9950
9982
  var ageOf = (file, nowMs) => {
9951
9983
  try {
9952
- return nowMs - fs7.lstatSync(file).mtimeMs;
9984
+ return nowMs - fs8.lstatSync(file).mtimeMs;
9953
9985
  } catch {
9954
9986
  return null;
9955
9987
  }
@@ -9960,7 +9992,7 @@ var clearAbandonedReclaimGuard = (lockPath, nowMs = Date.now()) => {
9960
9992
  if (age === null || age <= RECLAIM_GUARD_TTL_MS)
9961
9993
  return false;
9962
9994
  try {
9963
- fs7.rmdirSync(guard);
9995
+ fs8.rmdirSync(guard);
9964
9996
  return true;
9965
9997
  } catch {
9966
9998
  return false;
@@ -9969,8 +10001,8 @@ var clearAbandonedReclaimGuard = (lockPath, nowMs = Date.now()) => {
9969
10001
 
9970
10002
  // packages/workit-core/src/store/event-log.ts
9971
10003
  import { randomUUID as randomUUID2 } from "node:crypto";
9972
- import fs8 from "node:fs";
9973
- import path7 from "node:path";
10004
+ import fs9 from "node:fs";
10005
+ import path8 from "node:path";
9974
10006
  var EVENT_VERSION = 1;
9975
10007
 
9976
10008
  class LogDamage extends Error {
@@ -9999,7 +10031,7 @@ var parseEvent = (line, file, offset) => {
9999
10031
  function readLog(file, from = 0, expectSeq = null) {
10000
10032
  let fd;
10001
10033
  try {
10002
- fd = fs8.openSync(file, "r");
10034
+ fd = fs9.openSync(file, "r");
10003
10035
  } catch (error) {
10004
10036
  if (error.code === "ENOENT")
10005
10037
  return null;
@@ -10008,13 +10040,13 @@ function readLog(file, from = 0, expectSeq = null) {
10008
10040
  let bytes;
10009
10041
  let size;
10010
10042
  try {
10011
- size = fs8.fstatSync(fd).size;
10043
+ size = fs9.fstatSync(fd).size;
10012
10044
  if (from > size)
10013
10045
  throw new LogDamage(`${file}: shorter than its snapshot`);
10014
10046
  bytes = Buffer.alloc(size - from);
10015
10047
  let read = 0;
10016
10048
  while (read < bytes.length) {
10017
- const got = fs8.readSync(fd, bytes, read, bytes.length - read, from + read);
10049
+ const got = fs9.readSync(fd, bytes, read, bytes.length - read, from + read);
10018
10050
  if (got === 0)
10019
10051
  break;
10020
10052
  read += got;
@@ -10022,7 +10054,7 @@ function readLog(file, from = 0, expectSeq = null) {
10022
10054
  bytes = bytes.subarray(0, read);
10023
10055
  size = from + read;
10024
10056
  } finally {
10025
- fs8.closeSync(fd);
10057
+ fs9.closeSync(fd);
10026
10058
  }
10027
10059
  const events = [];
10028
10060
  let start = 0;
@@ -10047,11 +10079,11 @@ function readLog(file, from = 0, expectSeq = null) {
10047
10079
  }
10048
10080
  var fsyncDirectory = (dir) => {
10049
10081
  try {
10050
- const fd = fs8.openSync(dir, "r");
10082
+ const fd = fs9.openSync(dir, "r");
10051
10083
  try {
10052
- fs8.fsyncSync(fd);
10084
+ fs9.fsyncSync(fd);
10053
10085
  } finally {
10054
- fs8.closeSync(fd);
10086
+ fs9.closeSync(fd);
10055
10087
  }
10056
10088
  } catch (error) {
10057
10089
  if (process.platform !== "win32")
@@ -10061,46 +10093,46 @@ var fsyncDirectory = (dir) => {
10061
10093
  function appendEvent(file, event, validEnd) {
10062
10094
  const line = Buffer.from(`${JSON.stringify(event)}
10063
10095
  `, "utf8");
10064
- const created = !fs8.existsSync(file);
10065
- if (!created && fs8.statSync(file).size !== validEnd) {
10066
- const cut = fs8.openSync(file, "r+");
10096
+ const created = !fs9.existsSync(file);
10097
+ if (!created && fs9.statSync(file).size !== validEnd) {
10098
+ const cut = fs9.openSync(file, "r+");
10067
10099
  try {
10068
- fs8.ftruncateSync(cut, validEnd);
10069
- fs8.fsyncSync(cut);
10100
+ fs9.ftruncateSync(cut, validEnd);
10101
+ fs9.fsyncSync(cut);
10070
10102
  } finally {
10071
- fs8.closeSync(cut);
10103
+ fs9.closeSync(cut);
10072
10104
  }
10073
10105
  }
10074
- const fd = fs8.openSync(file, "a", 384);
10106
+ const fd = fs9.openSync(file, "a", 384);
10075
10107
  try {
10076
10108
  let written = 0;
10077
10109
  while (written < line.length)
10078
- written += fs8.writeSync(fd, line, written, line.length - written);
10079
- fs8.fsyncSync(fd);
10110
+ written += fs9.writeSync(fd, line, written, line.length - written);
10111
+ fs9.fsyncSync(fd);
10080
10112
  } finally {
10081
- fs8.closeSync(fd);
10113
+ fs9.closeSync(fd);
10082
10114
  }
10083
10115
  if (created)
10084
- fsyncDirectory(path7.dirname(file));
10116
+ fsyncDirectory(path8.dirname(file));
10085
10117
  return validEnd;
10086
10118
  }
10087
10119
  function replaceFile(file, bytes, durable) {
10088
10120
  const temporary = `${file}.${process.pid}.${randomUUID2()}.tmp`;
10089
10121
  try {
10090
- const fd = fs8.openSync(temporary, "wx", 384);
10122
+ const fd = fs9.openSync(temporary, "wx", 384);
10091
10123
  try {
10092
- fs8.writeSync(fd, bytes);
10124
+ fs9.writeSync(fd, bytes);
10093
10125
  if (durable)
10094
- fs8.fsyncSync(fd);
10126
+ fs9.fsyncSync(fd);
10095
10127
  } finally {
10096
- fs8.closeSync(fd);
10128
+ fs9.closeSync(fd);
10097
10129
  }
10098
10130
  renameWithRetry(temporary, file);
10099
10131
  if (durable)
10100
- fsyncDirectory(path7.dirname(file));
10132
+ fsyncDirectory(path8.dirname(file));
10101
10133
  } catch (error) {
10102
10134
  try {
10103
- fs8.unlinkSync(temporary);
10135
+ fs9.unlinkSync(temporary);
10104
10136
  } catch {}
10105
10137
  throw error;
10106
10138
  }
@@ -10125,7 +10157,7 @@ var retryTransient = (run) => {
10125
10157
  }
10126
10158
  }
10127
10159
  };
10128
- var renameWithRetry = (from, to) => retryTransient(() => fs8.renameSync(from, to));
10160
+ var renameWithRetry = (from, to) => retryTransient(() => fs9.renameSync(from, to));
10129
10161
 
10130
10162
  // packages/workit-core/src/store/patch.ts
10131
10163
  var isPlainObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
@@ -10238,7 +10270,7 @@ var isPatch = (value) => Array.isArray(value) && value.every((op) => {
10238
10270
  });
10239
10271
 
10240
10272
  // packages/workit-core/src/store/reduce.ts
10241
- import { createHash as createHash4 } from "node:crypto";
10273
+ import { createHash as createHash5 } from "node:crypto";
10242
10274
  var OPENING_TYPES = new Set([
10243
10275
  "task.opened",
10244
10276
  "task.imported",
@@ -10267,7 +10299,7 @@ var isObject3 = (value) => typeof value === "object" && value !== null && !Array
10267
10299
  var isKey = (value) => isObject3(value) && typeof value.key === "string" && (value.kind === "branch" || value.kind === "detached" || value.kind === "dir") && (value.branch === null || typeof value.branch === "string");
10268
10300
  var BLOB_REF = "$blob";
10269
10301
  var blobRef = (value) => isObject3(value) && Object.keys(value).length === 1 && typeof value[BLOB_REF] === "string" && /^[0-9a-f]{64}$/.test(value[BLOB_REF]) ? value[BLOB_REF] : null;
10270
- var blobDigest = (value) => createHash4("sha256").update(JSON.stringify(value)).digest("hex");
10302
+ var blobDigest = (value) => createHash5("sha256").update(JSON.stringify(value)).digest("hex");
10271
10303
  var toBlob = (value, blobs) => {
10272
10304
  if (!isObject3(value))
10273
10305
  return value;
@@ -10422,7 +10454,7 @@ var indexEntry = (task, key, legacy, file) => {
10422
10454
  };
10423
10455
  var fileSignature = (file) => {
10424
10456
  try {
10425
- const stat = fs9.statSync(file, { bigint: true });
10457
+ const stat = fs10.statSync(file, { bigint: true });
10426
10458
  return `${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeNs}:${stat.ctimeNs}`;
10427
10459
  } catch {
10428
10460
  return null;
@@ -10440,7 +10472,7 @@ var cachedRuntimeVersion = null;
10440
10472
  var runtimeVersion = () => {
10441
10473
  if (cachedRuntimeVersion === null) {
10442
10474
  try {
10443
- const pkg = JSON.parse(fs9.readFileSync(path8.join(packageRoot(), "package.json"), "utf8"));
10475
+ const pkg = JSON.parse(fs10.readFileSync(path9.join(packageRoot(), "package.json"), "utf8"));
10444
10476
  cachedRuntimeVersion = typeof pkg.version === "string" && pkg.version ? pkg.version : "0.0.0";
10445
10477
  } catch {
10446
10478
  cachedRuntimeVersion = "0.0.0";
@@ -10466,14 +10498,14 @@ var isNewerVersion = (candidate, current) => {
10466
10498
  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);
10467
10499
  var readText = (file) => {
10468
10500
  try {
10469
- return fs9.readFileSync(file, "utf8");
10501
+ return fs10.readFileSync(file, "utf8");
10470
10502
  } catch {
10471
10503
  return "";
10472
10504
  }
10473
10505
  };
10474
10506
  var REFLOG_LINE = /^[0-9a-f]+ ([0-9a-f]+) .* (\d+) [+-]\d{4}\t(.*)$/u;
10475
10507
  var branchStart = (location, branch, aliases) => {
10476
- const first = readText(path8.join(path8.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
10508
+ const first = readText(path9.join(path9.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
10477
10509
  `, 1)[0];
10478
10510
  const created = REFLOG_LINE.exec(first);
10479
10511
  const start = created && /^branch: Created from (\S+)$/u.exec(created[3])?.[1];
@@ -10483,7 +10515,7 @@ var branchStart = (location, branch, aliases) => {
10483
10515
  return start;
10484
10516
  if (!location.git)
10485
10517
  return null;
10486
- for (const line of readText(path8.join(location.git.gitDir, "logs", "HEAD")).split(`
10518
+ for (const line of readText(path9.join(location.git.gitDir, "logs", "HEAD")).split(`
10487
10519
  `)) {
10488
10520
  const entry = REFLOG_LINE.exec(line);
10489
10521
  const moved = entry && /^checkout: moving from (\S+) to (\S+)$/u.exec(entry[3]);
@@ -10493,23 +10525,23 @@ var branchStart = (location, branch, aliases) => {
10493
10525
  }
10494
10526
  return null;
10495
10527
  };
10496
- var refExists = (common, ref) => fs9.existsSync(path8.join(common, ref)) || readText(path8.join(common, "packed-refs")).includes(` ${ref}
10528
+ var refExists = (common, ref) => fs10.existsSync(path9.join(common, ref)) || readText(path9.join(common, "packed-refs")).includes(` ${ref}
10497
10529
  `);
10498
10530
  var origins = new Map;
10499
10531
  var sameDirectoryIdentity = (left, right) => {
10500
- if (!path8.isAbsolute(left) || !path8.isAbsolute(right))
10532
+ if (!path9.isAbsolute(left) || !path9.isAbsolute(right))
10501
10533
  return false;
10502
- const normalizedLeft = path8.resolve(left);
10503
- const normalizedRight = path8.resolve(right);
10534
+ const normalizedLeft = path9.resolve(left);
10535
+ const normalizedRight = path9.resolve(right);
10504
10536
  try {
10505
- const a = fs9.statSync(normalizedLeft, { bigint: true });
10506
- const b = fs9.statSync(normalizedRight, { bigint: true });
10537
+ const a = fs10.statSync(normalizedLeft, { bigint: true });
10538
+ const b = fs10.statSync(normalizedRight, { bigint: true });
10507
10539
  if (!a.isDirectory() || !b.isDirectory())
10508
10540
  return false;
10509
10541
  if (process.platform === "win32" ? normalizedLeft.toLowerCase() === normalizedRight.toLowerCase() : normalizedLeft === normalizedRight)
10510
10542
  return true;
10511
- const canonicalLeft = fs9.realpathSync(normalizedLeft);
10512
- const canonicalRight = fs9.realpathSync(normalizedRight);
10543
+ const canonicalLeft = fs10.realpathSync(normalizedLeft);
10544
+ const canonicalRight = fs10.realpathSync(normalizedRight);
10513
10545
  if (process.platform === "win32" ? canonicalLeft.toLowerCase() === canonicalRight.toLowerCase() : canonicalLeft === canonicalRight)
10514
10546
  return true;
10515
10547
  return a.dev === b.dev && a.ino !== 0n && a.ino === b.ino;
@@ -10546,8 +10578,8 @@ class TaskStore {
10546
10578
  migrationChecked = false;
10547
10579
  compactDue = new Set;
10548
10580
  constructor(root, options = {}) {
10549
- const resolved = path8.resolve(root);
10550
- this.origin = fs9.existsSync(resolved) ? fs9.realpathSync(resolved) : resolved;
10581
+ const resolved = path9.resolve(root);
10582
+ this.origin = fs10.existsSync(resolved) ? fs10.realpathSync(resolved) : resolved;
10551
10583
  this.located = resolveStore(this.origin);
10552
10584
  this.root = checkoutRootOf(this.origin, this.located);
10553
10585
  this.lockTimeoutMs = options.lockTimeoutMs ?? defaultLockTimeout();
@@ -10555,7 +10587,7 @@ class TaskStore {
10555
10587
  this.migrateOnRead = options.migrateOnRead;
10556
10588
  }
10557
10589
  location() {
10558
- if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs9.existsSync(path8.join(this.root, ".git"))) {
10590
+ if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs10.existsSync(path9.join(this.root, ".git"))) {
10559
10591
  this.located = undefined;
10560
10592
  this.migrationChecked = false;
10561
10593
  }
@@ -10619,7 +10651,7 @@ class TaskStore {
10619
10651
  const tasksDir = this.paths().tasks;
10620
10652
  let names;
10621
10653
  try {
10622
- names = fs9.existsSync(tasksDir) ? fs9.readdirSync(tasksDir).filter((name) => validId(name)) : [];
10654
+ names = fs10.existsSync(tasksDir) ? fs10.readdirSync(tasksDir).filter((name) => validId(name)) : [];
10623
10655
  } catch (error) {
10624
10656
  return failure2("storage_error", `unable to list tasks: ${String(error)}`, {
10625
10657
  path: tasksDir
@@ -10660,7 +10692,7 @@ class TaskStore {
10660
10692
  const file = this.paths().workspace;
10661
10693
  let bytes;
10662
10694
  try {
10663
- bytes = retryTransient(() => fs9.readFileSync(file, "utf8"));
10695
+ bytes = retryTransient(() => fs10.readFileSync(file, "utf8"));
10664
10696
  } catch (error) {
10665
10697
  if (error.code === "ENOENT")
10666
10698
  return success(null, null, null);
@@ -10711,7 +10743,7 @@ class TaskStore {
10711
10743
  const moved = this.bindLocked(again.data.id, key, input.now);
10712
10744
  return moved.ok ? success(moved.data.revision, null, { task: moved.data, created: false, key }) : moved;
10713
10745
  }
10714
- const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path8.basename(this.root) || this.root;
10746
+ const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path9.basename(this.root) || this.root;
10715
10747
  const intent = {
10716
10748
  objective: input.objective?.trim() || `Work on ${label}`,
10717
10749
  scope: { description: `the checkout (${label})`, paths: ["."], exclusions: [] },
@@ -10771,14 +10803,14 @@ class TaskStore {
10771
10803
  const branch = key.ok ? key.data.branch : null;
10772
10804
  if (!branch || !location.ok)
10773
10805
  return success(null, null, null);
10774
- const common = path8.dirname(location.data.dir);
10775
- const heads = path8.join(common, "logs", "refs", "heads");
10776
- const headLog = location.data.git ? path8.join(location.data.git.gitDir, "logs", "HEAD") : "";
10806
+ const common = path9.dirname(location.data.dir);
10807
+ const heads = path9.join(common, "logs", "refs", "heads");
10808
+ const headLog = location.data.git ? path9.join(location.data.git.gitDir, "logs", "HEAD") : "";
10777
10809
  const signatures = [
10778
- path8.join(heads, branch),
10810
+ path9.join(heads, branch),
10779
10811
  headLog,
10780
10812
  heads,
10781
- path8.join(common, "packed-refs")
10813
+ path9.join(common, "packed-refs")
10782
10814
  ].map((file) => fileSignature(file) ?? "-");
10783
10815
  const slot = `${location.data.dir}\x00${headLog}\x00${branch}`;
10784
10816
  let resolved = origins.get(slot);
@@ -10790,7 +10822,7 @@ class TaskStore {
10790
10822
  aliases.push(rename.from);
10791
10823
  const start = branchStart(location.data, branch, aliases);
10792
10824
  const slash = start?.indexOf("/") ?? -1;
10793
- 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)}"]`));
10825
+ const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(path9.join(common, "config")).includes(`[remote "${start.slice(0, slash)}"]`));
10794
10826
  const name = start && (remote ? start.slice(slash + 1) : start);
10795
10827
  resolved = {
10796
10828
  signature: signatures.join("|"),
@@ -11028,13 +11060,13 @@ class TaskStore {
11028
11060
  if (!ready.ok)
11029
11061
  return ready;
11030
11062
  const dirs = this.paths();
11031
- const recovery = path8.join(this.root, ".workit", "recovery");
11032
- if (fs9.existsSync(recovery)) {
11063
+ const recovery = path9.join(this.root, ".workit", "recovery");
11064
+ if (fs10.existsSync(recovery)) {
11033
11065
  let files = 0;
11034
11066
  let bytes = 0;
11035
11067
  try {
11036
- for (const name of fs9.readdirSync(recovery)) {
11037
- const stat = fs9.lstatSync(path8.join(recovery, name));
11068
+ for (const name of fs10.readdirSync(recovery)) {
11069
+ const stat = fs10.lstatSync(path9.join(recovery, name));
11038
11070
  if (!stat.isFile())
11039
11071
  continue;
11040
11072
  files += 1;
@@ -11043,17 +11075,17 @@ class TaskStore {
11043
11075
  } catch {}
11044
11076
  const remove = options.pruneRecovery === true && !dryRun;
11045
11077
  if (remove)
11046
- fs9.rmSync(recovery, { recursive: true, force: true });
11078
+ fs10.rmSync(recovery, { recursive: true, force: true });
11047
11079
  report.legacyRecovery = { path: recovery, files, bytes, removed: remove };
11048
11080
  }
11049
- if (!fs9.existsSync(dirs.tasks))
11081
+ if (!fs10.existsSync(dirs.tasks))
11050
11082
  return success(null, null, report);
11051
- const names = fs9.readdirSync(dirs.tasks).filter((name) => validId(name));
11083
+ const names = fs10.readdirSync(dirs.tasks).filter((name) => validId(name));
11052
11084
  for (const name of names) {
11053
11085
  const file = this.eventsPath(name);
11054
11086
  let size = 0;
11055
11087
  try {
11056
- size = fs9.statSync(file).size;
11088
+ size = fs10.statSync(file).size;
11057
11089
  } catch {
11058
11090
  continue;
11059
11091
  }
@@ -11081,16 +11113,16 @@ class TaskStore {
11081
11113
  const references = new Set;
11082
11114
  for (const name of names)
11083
11115
  try {
11084
- for (const match of fs9.readFileSync(this.eventsPath(name), "utf8").matchAll(/"\$blob":"([0-9a-f]{64})"/g))
11116
+ for (const match of fs10.readFileSync(this.eventsPath(name), "utf8").matchAll(/"\$blob":"([0-9a-f]{64})"/g))
11085
11117
  references.add(match[1]);
11086
11118
  } catch {}
11087
- if (fs9.existsSync(dirs.blobs))
11088
- for (const name of fs9.readdirSync(dirs.blobs)) {
11119
+ if (fs10.existsSync(dirs.blobs))
11120
+ for (const name of fs10.readdirSync(dirs.blobs)) {
11089
11121
  const digest = name.replace(/\.json$/, "");
11090
- const file = path8.join(dirs.blobs, name);
11122
+ const file = path9.join(dirs.blobs, name);
11091
11123
  let stat;
11092
11124
  try {
11093
- stat = fs9.lstatSync(file);
11125
+ stat = fs10.lstatSync(file);
11094
11126
  } catch {
11095
11127
  continue;
11096
11128
  }
@@ -11101,11 +11133,11 @@ class TaskStore {
11101
11133
  report.blobs.removed += 1;
11102
11134
  report.blobs.removedBytes += stat.size;
11103
11135
  if (!dryRun)
11104
- fs9.rmSync(file, { force: true });
11136
+ fs10.rmSync(file, { force: true });
11105
11137
  }
11106
11138
  return success(null, null, null);
11107
11139
  };
11108
- const swept = dryRun ? sweep() : this.withLock(path8.join(dirs.dir, "gc.lock"), sweep);
11140
+ const swept = dryRun ? sweep() : this.withLock(path9.join(dirs.dir, "gc.lock"), sweep);
11109
11141
  if (!swept.ok)
11110
11142
  return swept;
11111
11143
  const temporaryDirs = [
@@ -11113,17 +11145,17 @@ class TaskStore {
11113
11145
  dirs.tasks,
11114
11146
  dirs.blobs,
11115
11147
  dirs.checkout,
11116
- ...names.map((name) => path8.join(dirs.tasks, name))
11148
+ ...names.map((name) => path9.join(dirs.tasks, name))
11117
11149
  ];
11118
11150
  for (const directory of temporaryDirs) {
11119
- if (!fs9.existsSync(directory))
11151
+ if (!fs10.existsSync(directory))
11120
11152
  continue;
11121
- for (const name of fs9.readdirSync(directory)) {
11153
+ for (const name of fs10.readdirSync(directory)) {
11122
11154
  if (!name.endsWith(".tmp") && !name.endsWith(".probe"))
11123
11155
  continue;
11124
- const file = path8.join(directory, name);
11156
+ const file = path9.join(directory, name);
11125
11157
  try {
11126
- const stat = fs9.lstatSync(file);
11158
+ const stat = fs10.lstatSync(file);
11127
11159
  if (!stat.isFile() || nowMs - stat.mtimeMs <= STALE_TEMPORARY_MS)
11128
11160
  continue;
11129
11161
  } catch {
@@ -11131,37 +11163,37 @@ class TaskStore {
11131
11163
  }
11132
11164
  report.temporary.removed += 1;
11133
11165
  if (!dryRun)
11134
- fs9.rmSync(file, { force: true });
11166
+ fs10.rmSync(file, { force: true });
11135
11167
  }
11136
11168
  }
11137
11169
  return success(null, null, report);
11138
11170
  }
11139
11171
  paths() {
11140
11172
  const location = this.location();
11141
- const dir = location.ok ? location.data.dir : path8.join(this.root, ".workit");
11142
- const checkout = path8.join(dir, "checkouts", checkoutSlug(this.root));
11173
+ const dir = location.ok ? location.data.dir : path9.join(this.root, ".workit");
11174
+ const checkout = path9.join(dir, "checkouts", checkoutSlug(this.root));
11143
11175
  return {
11144
11176
  dir,
11145
11177
  shared: location.ok ? location.data.shared : false,
11146
- marker: path8.join(dir, "store.json"),
11178
+ marker: path9.join(dir, "store.json"),
11147
11179
  checkout,
11148
- workspace: path8.join(checkout, "workspace.json"),
11149
- checkoutLock: path8.join(checkout, "metadata.lock"),
11150
- tasks: path8.join(dir, "tasks"),
11151
- index: path8.join(dir, "task-index.json"),
11152
- blobs: path8.join(dir, "blobs", "candidates"),
11153
- legacy: path8.join(dir, "legacy", checkoutSlug(this.root), "v2"),
11154
- v2: path8.join(this.root, ".workit")
11180
+ workspace: path9.join(checkout, "workspace.json"),
11181
+ checkoutLock: path9.join(checkout, "metadata.lock"),
11182
+ tasks: path9.join(dir, "tasks"),
11183
+ index: path9.join(dir, "task-index.json"),
11184
+ blobs: path9.join(dir, "blobs", "candidates"),
11185
+ legacy: path9.join(dir, "legacy", checkoutSlug(this.root), "v2"),
11186
+ v2: path9.join(this.root, ".workit")
11155
11187
  };
11156
11188
  }
11157
11189
  eventsPath(taskId) {
11158
- return path8.join(this.paths().tasks, taskId, "events.jsonl");
11190
+ return path9.join(this.paths().tasks, taskId, "events.jsonl");
11159
11191
  }
11160
11192
  snapshotPath(taskId) {
11161
- return path8.join(this.paths().tasks, taskId, "snapshot.json");
11193
+ return path9.join(this.paths().tasks, taskId, "snapshot.json");
11162
11194
  }
11163
11195
  taskLockPath(taskId) {
11164
- return path8.join(this.paths().tasks, taskId, "lock");
11196
+ return path9.join(this.paths().tasks, taskId, "lock");
11165
11197
  }
11166
11198
  ready(write = false) {
11167
11199
  const location = this.location();
@@ -11171,7 +11203,7 @@ class TaskStore {
11171
11203
  return success(null, null, null);
11172
11204
  const dirs = this.paths();
11173
11205
  try {
11174
- const marker = JSON.parse(fs9.readFileSync(dirs.marker, "utf8"));
11206
+ const marker = JSON.parse(fs10.readFileSync(dirs.marker, "utf8"));
11175
11207
  if (typeof marker.version === "number" && marker.version > STORE_FORMAT)
11176
11208
  return failure2("recovery_required", `the workit store at ${dirs.dir} has format ${marker.version}; upgrade Workit to use it`, { path: dirs.marker });
11177
11209
  } catch {}
@@ -11200,21 +11232,21 @@ class TaskStore {
11200
11232
  return {
11201
11233
  read: (digest) => {
11202
11234
  try {
11203
- return JSON.parse(fs9.readFileSync(path8.join(dir, `${digest}.json`), "utf8"));
11235
+ return JSON.parse(fs10.readFileSync(path9.join(dir, `${digest}.json`), "utf8"));
11204
11236
  } catch (error) {
11205
11237
  throw new LogDamage(`stored candidate ${digest} is missing or unreadable: ${String(error)}`);
11206
11238
  }
11207
11239
  },
11208
11240
  write: (digest, value) => {
11209
- const file = path8.join(dir, `${digest}.json`);
11210
- if (fs9.existsSync(file)) {
11241
+ const file = path9.join(dir, `${digest}.json`);
11242
+ if (fs10.existsSync(file)) {
11211
11243
  const stamp = new Date;
11212
11244
  try {
11213
- fs9.utimesSync(file, stamp, stamp);
11245
+ fs10.utimesSync(file, stamp, stamp);
11214
11246
  return;
11215
11247
  } catch {}
11216
11248
  }
11217
- fs9.mkdirSync(dir, { recursive: true });
11249
+ fs10.mkdirSync(dir, { recursive: true });
11218
11250
  replaceFile(file, JSON.stringify(value), true);
11219
11251
  }
11220
11252
  };
@@ -11296,7 +11328,7 @@ class TaskStore {
11296
11328
  }
11297
11329
  readSnapshot(taskId) {
11298
11330
  try {
11299
- const value = JSON.parse(fs9.readFileSync(this.snapshotPath(taskId), "utf8"));
11331
+ const value = JSON.parse(fs10.readFileSync(this.snapshotPath(taskId), "utf8"));
11300
11332
  if (!isObject4(value) || value.v !== 1 || value.task !== taskId || typeof value.seq !== "number" || typeof value.lastId !== "string" || typeof value.lastStart !== "number" || typeof value.end !== "number" || !isObject4(value.record))
11301
11333
  return null;
11302
11334
  return value;
@@ -11398,8 +11430,8 @@ class TaskStore {
11398
11430
  }
11399
11431
  }
11400
11432
  openTask(record, type, key, legacy = null) {
11401
- const dir = path8.join(this.paths().tasks, record.id);
11402
- fs9.mkdirSync(dir, { recursive: true });
11433
+ const dir = path9.join(this.paths().tasks, record.id);
11434
+ fs10.mkdirSync(dir, { recursive: true });
11403
11435
  const blobs = this.blobStore();
11404
11436
  const bound = key ? { ...key, boundAt: key.boundAt ?? new Date().toISOString() } : null;
11405
11437
  const event = this.event(record.id, 1, type, {
@@ -11451,11 +11483,11 @@ class TaskStore {
11451
11483
  } catch {}
11452
11484
  if (!latest || latest.events[0]?.id !== last.id)
11453
11485
  return failure2("busy", "the task log changed during compaction; retry", { taskId });
11454
- const appended = fs9.readFileSync(file).subarray(log.end, latest.end);
11486
+ const appended = fs10.readFileSync(file).subarray(log.end, latest.end);
11455
11487
  const bytes = Buffer.concat([Buffer.from(prefix, "utf8"), appended]);
11456
11488
  replaceFile(file, bytes.toString("utf8"), true);
11457
11489
  try {
11458
- fs9.rmSync(this.snapshotPath(taskId), { force: true });
11490
+ fs10.rmSync(this.snapshotPath(taskId), { force: true });
11459
11491
  } catch {}
11460
11492
  const reloaded = this.load(taskId);
11461
11493
  if (reloaded.ok && reloaded.data)
@@ -11468,7 +11500,7 @@ class TaskStore {
11468
11500
  }
11469
11501
  countEvents(file) {
11470
11502
  try {
11471
- const bytes = fs9.readFileSync(file);
11503
+ const bytes = fs10.readFileSync(file);
11472
11504
  let count = 0;
11473
11505
  for (let index = bytes.indexOf(10);index >= 0; index = bytes.indexOf(10, index + 1))
11474
11506
  count += 1;
@@ -11490,8 +11522,8 @@ class TaskStore {
11490
11522
  return bound.ok ? success(null, null, bound.data[0] ?? null) : bound;
11491
11523
  }
11492
11524
  withKeyLock(key, operation) {
11493
- const digest = createHash5("sha256").update(key).digest("hex").slice(0, 32);
11494
- return this.withLock(path8.join(this.paths().dir, "keys", `${digest}.lock`), operation);
11525
+ const digest = createHash6("sha256").update(key).digest("hex").slice(0, 32);
11526
+ return this.withLock(path9.join(this.paths().dir, "keys", `${digest}.lock`), operation);
11495
11527
  }
11496
11528
  bindLocked(taskId, key, timestamp) {
11497
11529
  const current = this.readWorkspace();
@@ -11632,7 +11664,7 @@ class TaskStore {
11632
11664
  writeWorkspace(record) {
11633
11665
  const file = this.paths().workspace;
11634
11666
  try {
11635
- fs9.mkdirSync(path8.dirname(file), { recursive: true });
11667
+ fs10.mkdirSync(path9.dirname(file), { recursive: true });
11636
11668
  replaceFile(file, `${canonicalJson(record)}
11637
11669
  `, true);
11638
11670
  return success(null, null, null);
@@ -11642,7 +11674,7 @@ class TaskStore {
11642
11674
  }
11643
11675
  readIndex() {
11644
11676
  try {
11645
- const value = JSON.parse(fs9.readFileSync(this.paths().index, "utf8"));
11677
+ const value = JSON.parse(fs10.readFileSync(this.paths().index, "utf8"));
11646
11678
  if (!isObject4(value) || value.version !== INDEX_VERSION || !isObject4(value.tasks))
11647
11679
  return {};
11648
11680
  const tasks = {};
@@ -11656,7 +11688,7 @@ class TaskStore {
11656
11688
  }
11657
11689
  writeIndex(entries) {
11658
11690
  try {
11659
- fs9.mkdirSync(this.paths().tasks, { recursive: true });
11691
+ fs10.mkdirSync(this.paths().tasks, { recursive: true });
11660
11692
  replaceFile(this.paths().index, JSON.stringify({
11661
11693
  version: INDEX_VERSION,
11662
11694
  tasks: Object.fromEntries(entries.map((entry) => [entry.id, entry]))
@@ -11710,23 +11742,23 @@ class TaskStore {
11710
11742
  return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", { expectedWorkspaceRevision: expected, actualWorkspaceRevision: actual });
11711
11743
  }
11712
11744
  v2Dirs() {
11713
- return [...new Set([this.root, this.origin])].map((dir) => path8.join(dir, ".workit"));
11745
+ return [...new Set([this.root, this.origin])].map((dir) => path9.join(dir, ".workit"));
11714
11746
  }
11715
11747
  pendingMigrations() {
11716
11748
  return this.v2Dirs().filter((dir) => {
11717
- const raw = this.readV2Workspace(path8.join(dir, "workspace.json"));
11749
+ const raw = this.readV2Workspace(path9.join(dir, "workspace.json"));
11718
11750
  return raw !== null && raw !== TOMBSTONE;
11719
11751
  });
11720
11752
  }
11721
11753
  migrateV2(v2) {
11722
11754
  const dirs = this.paths();
11723
- const v2Workspace = path8.join(v2, "workspace.json");
11724
- const v2Tasks = path8.join(v2, "tasks");
11725
- const legacy = path8.join(dirs.dir, "legacy", checkoutSlug(path8.dirname(v2)), "v2");
11755
+ const v2Workspace = path9.join(v2, "workspace.json");
11756
+ const v2Tasks = path9.join(v2, "tasks");
11757
+ const legacy = path9.join(dirs.dir, "legacy", checkoutSlug(path9.dirname(v2)), "v2");
11726
11758
  const raw = this.readV2Workspace(v2Workspace);
11727
11759
  if (raw === null || raw === TOMBSTONE)
11728
11760
  return success(null, null, null);
11729
- return this.withLock(dirs.checkoutLock, () => this.withLock(path8.join(v2, "metadata.lock"), () => {
11761
+ return this.withLock(dirs.checkoutLock, () => this.withLock(path9.join(v2, "metadata.lock"), () => {
11730
11762
  const workspace = this.readV2Workspace(v2Workspace);
11731
11763
  if (workspace === null || workspace === TOMBSTONE)
11732
11764
  return success(null, null, null);
@@ -11735,7 +11767,7 @@ class TaskStore {
11735
11767
  return failure2("recovery_required", `cannot migrate the 2.x store at ${v2}: ${parsedWorkspace.error}; move it aside to start fresh`, { path: v2Workspace });
11736
11768
  let files = [];
11737
11769
  try {
11738
- files = fs9.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path8.join(v2Tasks, name)));
11770
+ files = fs10.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path9.join(v2Tasks, name)));
11739
11771
  } catch {}
11740
11772
  const current = this.readWorkspace();
11741
11773
  if (!current.ok)
@@ -11753,22 +11785,22 @@ class TaskStore {
11753
11785
  let skipped = 0;
11754
11786
  const done = new Map;
11755
11787
  try {
11756
- fs9.mkdirSync(path8.join(legacy, "tasks"), { recursive: true });
11788
+ fs10.mkdirSync(path9.join(legacy, "tasks"), { recursive: true });
11757
11789
  for (const name of ["workspace.json", "index.json"])
11758
- if (fs9.existsSync(path8.join(v2, name)))
11759
- fs9.copyFileSync(path8.join(v2, name), path8.join(legacy, name));
11790
+ if (fs10.existsSync(path9.join(v2, name)))
11791
+ fs10.copyFileSync(path9.join(v2, name), path9.join(legacy, name));
11760
11792
  for (const name of files) {
11761
11793
  const id = name.slice(0, -5);
11762
- const file = path8.join(v2Tasks, name);
11763
- const bytes = fs9.readFileSync(file, "utf8");
11794
+ const file = path9.join(v2Tasks, name);
11795
+ const bytes = fs10.readFileSync(file, "utf8");
11764
11796
  const digest = sha256(bytes);
11765
- fs9.writeFileSync(path8.join(legacy, "tasks", name), bytes);
11797
+ fs10.writeFileSync(path9.join(legacy, "tasks", name), bytes);
11766
11798
  const parsed = this.parseRecord(bytes, taskRecordSchema, "2.x task");
11767
11799
  if (!parsed.ok || parsed.data.id !== id)
11768
11800
  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 });
11769
11801
  const record = { ...parsed.data, workspaceId: target.id };
11770
- const origin = { path: path8.join(legacy, "tasks", name), digest };
11771
- if (!fs9.existsSync(this.eventsPath(id))) {
11802
+ const origin = { path: path9.join(legacy, "tasks", name), digest };
11803
+ if (!fs10.existsSync(this.eventsPath(id))) {
11772
11804
  this.openTask(record, "migrated.from_v2", null, origin);
11773
11805
  migrated += 1;
11774
11806
  } else {
@@ -11803,8 +11835,8 @@ class TaskStore {
11803
11835
  try {
11804
11836
  let complete = true;
11805
11837
  for (const [name, digest] of done) {
11806
- const file = path8.join(v2Tasks, name);
11807
- if (sha256(fs9.readFileSync(file, "utf8")) !== digest) {
11838
+ const file = path9.join(v2Tasks, name);
11839
+ if (sha256(fs10.readFileSync(file, "utf8")) !== digest) {
11808
11840
  complete = false;
11809
11841
  continue;
11810
11842
  }
@@ -11814,7 +11846,7 @@ class TaskStore {
11814
11846
  return failure2("busy", `the 2.x store at ${v2} changed during migration; retry`, {
11815
11847
  path: v2
11816
11848
  });
11817
- fs9.rmSync(path8.join(v2, "index.json"), { force: true });
11849
+ fs10.rmSync(path9.join(v2, "index.json"), { force: true });
11818
11850
  this.writeTombstone(v2, target.id);
11819
11851
  } catch (error) {
11820
11852
  return failure2("storage_error", `cannot finish the 2.x migration: ${String(error)}`, {
@@ -11834,45 +11866,45 @@ class TaskStore {
11834
11866
  }
11835
11867
  adoptLocalStore() {
11836
11868
  const dirs = this.paths();
11837
- const marker = path8.join(dirs.v2, "store.json");
11838
- if (!dirs.shared || !fs9.existsSync(marker))
11869
+ const marker = path9.join(dirs.v2, "store.json");
11870
+ if (!dirs.shared || !fs10.existsSync(marker))
11839
11871
  return success(null, null, null);
11840
11872
  return this.withLock(dirs.checkoutLock, () => {
11841
- if (!fs9.existsSync(marker))
11873
+ if (!fs10.existsSync(marker))
11842
11874
  return success(null, null, null);
11843
11875
  let tasks = 0;
11844
11876
  try {
11845
11877
  const merge = (from, to) => {
11846
- if (!fs9.existsSync(to)) {
11847
- fs9.mkdirSync(path8.dirname(to), { recursive: true });
11878
+ if (!fs10.existsSync(to)) {
11879
+ fs10.mkdirSync(path9.dirname(to), { recursive: true });
11848
11880
  try {
11849
- fs9.renameSync(from, to);
11881
+ fs10.renameSync(from, to);
11850
11882
  } catch {
11851
- fs9.cpSync(from, to, { recursive: true, errorOnExist: true, force: false });
11852
- fs9.rmSync(from, { recursive: true, force: true });
11883
+ fs10.cpSync(from, to, { recursive: true, errorOnExist: true, force: false });
11884
+ fs10.rmSync(from, { recursive: true, force: true });
11853
11885
  }
11854
11886
  return;
11855
11887
  }
11856
- if (fs9.lstatSync(from).isDirectory() && fs9.lstatSync(to).isDirectory())
11857
- for (const name of fs9.readdirSync(from))
11858
- merge(path8.join(from, name), path8.join(to, name));
11888
+ if (fs10.lstatSync(from).isDirectory() && fs10.lstatSync(to).isDirectory())
11889
+ for (const name of fs10.readdirSync(from))
11890
+ merge(path9.join(from, name), path9.join(to, name));
11859
11891
  };
11860
11892
  for (const sub of ["tasks", "checkouts", "blobs", "legacy"]) {
11861
- const from = path8.join(dirs.v2, sub);
11862
- if (!fs9.existsSync(from))
11893
+ const from = path9.join(dirs.v2, sub);
11894
+ if (!fs10.existsSync(from))
11863
11895
  continue;
11864
11896
  if (sub === "tasks") {
11865
- for (const name of fs9.readdirSync(from))
11866
- if (validId(name) && !fs9.existsSync(path8.join(dirs.dir, sub, name)))
11897
+ for (const name of fs10.readdirSync(from))
11898
+ if (validId(name) && !fs10.existsSync(path9.join(dirs.dir, sub, name)))
11867
11899
  tasks += 1;
11868
11900
  }
11869
- merge(from, path8.join(dirs.dir, sub));
11901
+ merge(from, path9.join(dirs.dir, sub));
11870
11902
  }
11871
- const ledger = path8.join(dirs.v2, "ledger");
11872
- if (fs9.existsSync(ledger) && !fs9.existsSync(path8.join(dirs.dir, "ledger")))
11873
- merge(ledger, path8.join(dirs.dir, "ledger"));
11874
- fs9.rmSync(path8.join(dirs.v2, "task-index.json"), { force: true });
11875
- fs9.renameSync(marker, path8.join(dirs.v2, "store.moved.json"));
11903
+ const ledger = path9.join(dirs.v2, "ledger");
11904
+ if (fs10.existsSync(ledger) && !fs10.existsSync(path9.join(dirs.dir, "ledger")))
11905
+ merge(ledger, path9.join(dirs.dir, "ledger"));
11906
+ fs10.rmSync(path9.join(dirs.v2, "task-index.json"), { force: true });
11907
+ fs10.renameSync(marker, path9.join(dirs.v2, "store.moved.json"));
11876
11908
  } catch (error) {
11877
11909
  return failure2("storage_error", `cannot move ${dirs.v2} into ${dirs.dir}: ${String(error)}`, {
11878
11910
  path: dirs.v2
@@ -11892,7 +11924,7 @@ class TaskStore {
11892
11924
  readV2Workspace(file) {
11893
11925
  let bytes;
11894
11926
  try {
11895
- bytes = fs9.readFileSync(file, "utf8");
11927
+ bytes = fs10.readFileSync(file, "utf8");
11896
11928
  } catch {
11897
11929
  return null;
11898
11930
  }
@@ -11910,7 +11942,7 @@ class TaskStore {
11910
11942
  schemaVersion: SCHEMA_VERSION,
11911
11943
  id: workspaceId ?? newId(),
11912
11944
  revision: newRevision(),
11913
- root: path8.dirname(v2),
11945
+ root: path9.dirname(v2),
11914
11946
  runtime: { createdWith: version, updatedWith: version },
11915
11947
  writer: null,
11916
11948
  store: {
@@ -11921,12 +11953,12 @@ class TaskStore {
11921
11953
  },
11922
11954
  critical: ["store"]
11923
11955
  };
11924
- fs9.mkdirSync(v2, { recursive: true });
11925
- const ignore = path8.join(v2, ".gitignore");
11926
- if (!fs9.existsSync(ignore))
11927
- fs9.writeFileSync(ignore, `*
11956
+ fs10.mkdirSync(v2, { recursive: true });
11957
+ const ignore = path9.join(v2, ".gitignore");
11958
+ if (!fs10.existsSync(ignore))
11959
+ fs10.writeFileSync(ignore, `*
11928
11960
  `);
11929
- replaceFile(path8.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
11961
+ replaceFile(path9.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
11930
11962
  `, true);
11931
11963
  }
11932
11964
  stubFor(taskId) {
@@ -11942,7 +11974,7 @@ class TaskStore {
11942
11974
  }
11943
11975
  isStub(file) {
11944
11976
  try {
11945
- const value = JSON.parse(fs9.readFileSync(file, "utf8"));
11977
+ const value = JSON.parse(fs10.readFileSync(file, "utf8"));
11946
11978
  return isObject4(value) && isObject4(value.store) && value.store.format === "workit-store";
11947
11979
  } catch {
11948
11980
  return false;
@@ -11950,32 +11982,32 @@ class TaskStore {
11950
11982
  }
11951
11983
  writeTombstoneIfMissing() {
11952
11984
  try {
11953
- const v2 = path8.join(this.root, ".workit");
11954
- if (fs9.existsSync(path8.join(v2, "workspace.json")))
11985
+ const v2 = path9.join(this.root, ".workit");
11986
+ if (fs10.existsSync(path9.join(v2, "workspace.json")))
11955
11987
  return;
11956
11988
  let id = null;
11957
11989
  try {
11958
- id = JSON.parse(fs9.readFileSync(this.paths().workspace, "utf8")).id ?? null;
11990
+ id = JSON.parse(fs10.readFileSync(this.paths().workspace, "utf8")).id ?? null;
11959
11991
  } catch {}
11960
11992
  this.writeTombstone(v2, id);
11961
11993
  } catch {}
11962
11994
  }
11963
11995
  initializeStorage() {
11964
11996
  const dirs = this.paths();
11965
- retryTransient(() => fs9.mkdirSync(dirs.checkout, { recursive: true }));
11966
- retryTransient(() => fs9.mkdirSync(dirs.tasks, { recursive: true }));
11967
- if (!fs9.existsSync(dirs.marker))
11997
+ retryTransient(() => fs10.mkdirSync(dirs.checkout, { recursive: true }));
11998
+ retryTransient(() => fs10.mkdirSync(dirs.tasks, { recursive: true }));
11999
+ if (!fs10.existsSync(dirs.marker))
11968
12000
  replaceFile(dirs.marker, `${JSON.stringify({ format: "workit-store", version: STORE_FORMAT, createdWith: runtimeVersion() })}
11969
12001
  `, false);
11970
12002
  if (!dirs.shared) {
11971
- const ignore = path8.join(dirs.dir, ".gitignore");
12003
+ const ignore = path9.join(dirs.dir, ".gitignore");
11972
12004
  let current = null;
11973
12005
  try {
11974
- current = fs9.readFileSync(ignore, "utf8");
12006
+ current = fs10.readFileSync(ignore, "utf8");
11975
12007
  } catch {}
11976
12008
  if (current !== `*
11977
12009
  `)
11978
- retryTransient(() => fs9.writeFileSync(ignore, `*
12010
+ retryTransient(() => fs10.writeFileSync(ignore, `*
11979
12011
  `));
11980
12012
  }
11981
12013
  this.writeTombstoneIfMissing();
@@ -11991,7 +12023,7 @@ class TaskStore {
11991
12023
  shouldReclaim: ({ payload, nowMs }) => {
11992
12024
  let ageMs = null;
11993
12025
  try {
11994
- ageMs = nowMs - fs9.lstatSync(lockPath).mtimeMs;
12026
+ ageMs = nowMs - fs10.lstatSync(lockPath).mtimeMs;
11995
12027
  } catch {}
11996
12028
  return classifyLockOwner(payload, ageMs, localLockHost(), TASK_STORE_LOCK).state === "stale";
11997
12029
  },
@@ -12028,7 +12060,7 @@ class TaskStore {
12028
12060
  withLock(lockPath, operation) {
12029
12061
  try {
12030
12062
  this.initializeStorage();
12031
- fs9.mkdirSync(path8.dirname(lockPath), { recursive: true });
12063
+ fs10.mkdirSync(path9.dirname(lockPath), { recursive: true });
12032
12064
  } catch (error) {
12033
12065
  return failure2("storage_error", `unable to initialize store: ${String(error)}`, {
12034
12066
  path: this.paths().dir
@@ -12068,18 +12100,18 @@ class TaskStore {
12068
12100
  lockDirWritable(lockPath) {
12069
12101
  const probe = `${lockPath}.${process.pid}.${randomUUID3()}.probe`;
12070
12102
  try {
12071
- fs9.closeSync(fs9.openSync(probe, "wx", 384));
12103
+ fs10.closeSync(fs10.openSync(probe, "wx", 384));
12072
12104
  } catch {
12073
12105
  return false;
12074
12106
  }
12075
12107
  try {
12076
- fs9.rmSync(probe, { force: true });
12108
+ fs10.rmSync(probe, { force: true });
12077
12109
  } catch {}
12078
12110
  return true;
12079
12111
  }
12080
12112
  lockHolderPresent(lockPath) {
12081
12113
  try {
12082
- fs9.lstatSync(lockPath);
12114
+ fs10.lstatSync(lockPath);
12083
12115
  return true;
12084
12116
  } catch (error) {
12085
12117
  return error?.code !== "ENOENT";
@@ -12091,12 +12123,12 @@ class TaskStore {
12091
12123
  if (isTransientWindowsError(error) && !this.lockHolderPresent(lockPath) && !this.lockDirWritable(lockPath))
12092
12124
  return failure2("storage_error", `cannot create the workit lock (${code}); no other Workit call holds it`, {
12093
12125
  path: lockPath,
12094
- guidance: `Check permissions and the read-only attribute on ${path8.dirname(lockPath)}.`
12126
+ guidance: `Check permissions and the read-only attribute on ${path9.dirname(lockPath)}.`
12095
12127
  });
12096
12128
  if (code === "EEXIST" || code === "file_lock_timeout" || code === "file_lock_stale" || isTransientWindowsError(error)) {
12097
12129
  let lock = null;
12098
12130
  try {
12099
- lock = parseMetadataLockOrNull(fs9.readFileSync(lockPath, "utf8"));
12131
+ lock = parseMetadataLockOrNull(fs10.readFileSync(lockPath, "utf8"));
12100
12132
  } catch {}
12101
12133
  return failure2("busy", `workit lock is held by another Workit call${lock ? ` (pid ${lock.pid} on ${lock.host})` : ""}; retry shortly`, {
12102
12134
  outcome: "not_started",
@@ -12111,17 +12143,17 @@ class TaskStore {
12111
12143
 
12112
12144
  // packages/workit-core/src/core/policy/derive.ts
12113
12145
  import { existsSync as existsSync4 } from "node:fs";
12114
- import path13 from "node:path";
12146
+ import path14 from "node:path";
12115
12147
 
12116
12148
  // packages/workit-core/src/ledger.ts
12117
12149
  import { spawnSync as spawnSync9 } from "node:child_process";
12118
- import { createHash as createHash8, randomBytes as randomBytes2 } from "node:crypto";
12119
- import fs11 from "node:fs";
12120
- import path12 from "node:path";
12150
+ import { createHash as createHash9, randomBytes as randomBytes2 } from "node:crypto";
12151
+ import fs12 from "node:fs";
12152
+ import path13 from "node:path";
12121
12153
 
12122
12154
  // packages/workit-core/src/core/vcs-config.ts
12123
- import fs10 from "node:fs";
12124
- import path11 from "node:path";
12155
+ import fs11 from "node:fs";
12156
+ import path12 from "node:path";
12125
12157
  import { spawnSync as spawnSync8 } from "node:child_process";
12126
12158
 
12127
12159
  // packages/workit-core/src/core/config.ts
@@ -12135,7 +12167,7 @@ import {
12135
12167
  writeFileSync as writeFileSync2
12136
12168
  } from "node:fs";
12137
12169
  import os2 from "node:os";
12138
- import path9 from "node:path";
12170
+ import path10 from "node:path";
12139
12171
 
12140
12172
  // packages/workit-core/src/core/boundary.ts
12141
12173
  var EVENT = {
@@ -12179,7 +12211,7 @@ var mergePreset = (preset, input = {}, current = {
12179
12211
  protected: preset === "custom" ? input.protectedNames ?? current.branchPolicy.protected : [...defs.protected]
12180
12212
  };
12181
12213
  };
12182
- var resolveConfigDir = () => process.env.WORKFLOW_TOOLKIT_CONFIG ?? process.env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path9.join(process.env.XDG_CONFIG_HOME || path9.join(os2.homedir(), ".config"), "workit");
12214
+ var resolveConfigDir = () => process.env.WORKFLOW_TOOLKIT_CONFIG ?? process.env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path10.join(process.env.XDG_CONFIG_HOME || path10.join(os2.homedir(), ".config"), "workit");
12183
12215
  var migratedDir = null;
12184
12216
  var migrationFailed = false;
12185
12217
  var ensureConfigDir = (dir = resolveConfigDir()) => {
@@ -12189,7 +12221,7 @@ var ensureConfigDir = (dir = resolveConfigDir()) => {
12189
12221
  migratedDir = dir;
12190
12222
  return dir;
12191
12223
  }
12192
- const legacy = path9.join(process.env.XDG_CONFIG_HOME || path9.join(os2.homedir(), ".config"), "workflow-toolkit");
12224
+ const legacy = path10.join(process.env.XDG_CONFIG_HOME || path10.join(os2.homedir(), ".config"), "workflow-toolkit");
12193
12225
  if (!existsSync3(legacy)) {
12194
12226
  migratedDir = dir;
12195
12227
  return dir;
@@ -12202,8 +12234,8 @@ var ensureConfigDir = (dir = resolveConfigDir()) => {
12202
12234
  mkdirSync2(dir, { recursive: true });
12203
12235
  diagnosticLogger?.info(EVENT.migration, { from: legacy, to: dir });
12204
12236
  for (const entry of readdirSync2(legacy, { withFileTypes: true })) {
12205
- const src = path9.join(legacy, entry.name);
12206
- const dest = path9.join(dir, entry.name);
12237
+ const src = path10.join(legacy, entry.name);
12238
+ const dest = path10.join(dir, entry.name);
12207
12239
  if (existsSync3(dest))
12208
12240
  continue;
12209
12241
  try {
@@ -12275,7 +12307,7 @@ var parseConfigResult = (raw, file) => {
12275
12307
  return { status: "valid", path: file, config };
12276
12308
  };
12277
12309
  var readConfigTyped = (dir) => {
12278
- const file = path9.join(dir ?? configDir(), "config.json");
12310
+ const file = path10.join(dir ?? configDir(), "config.json");
12279
12311
  return parseConfigResult(readSafe(file), file);
12280
12312
  };
12281
12313
  var readConfig = () => {
@@ -12284,7 +12316,7 @@ var readConfig = () => {
12284
12316
  throw new Error(result.error);
12285
12317
  return result.config ?? DEFAULTS;
12286
12318
  };
12287
- var vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path9.join(configDir(), "vcs.json");
12319
+ var vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path10.join(configDir(), "vcs.json");
12288
12320
  var branchGlobPattern = (glob) => new RegExp(`^${glob.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`, "i");
12289
12321
  var resolveBranchPolicy = (config, workspace, repoPreset) => {
12290
12322
  const wp = workspace?.branchPolicy ?? {};
@@ -12326,9 +12358,9 @@ var resolveCommitPolicy = (config, workspace) => {
12326
12358
 
12327
12359
  // packages/workit-core/src/core/workspaces.ts
12328
12360
  import { spawnSync as spawnSync6 } from "node:child_process";
12329
- import { createHash as createHash6 } from "node:crypto";
12361
+ import { createHash as createHash7 } from "node:crypto";
12330
12362
  import { readFileSync as readFileSync3, realpathSync as realpathSync2 } from "node:fs";
12331
- import path10 from "node:path";
12363
+ import path11 from "node:path";
12332
12364
 
12333
12365
  // packages/workit-core/src/core/branch-policy.ts
12334
12366
  import { spawnSync as spawnSync5 } from "node:child_process";
@@ -12453,7 +12485,7 @@ var releaseTrackSchema = object({
12453
12485
  context.addIssue({ code: "custom", path: [field], message: "entries must be unique" });
12454
12486
  }
12455
12487
  }
12456
- 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(".."))) {
12488
+ if (track.versionSource?.kind === "package-json" && (path11.posix.isAbsolute(track.versionSource.path.replaceAll("\\", "/")) || /^[A-Za-z]:\//u.test(track.versionSource.path.replaceAll("\\", "/")) || track.versionSource.path.replaceAll("\\", "/").split("/").includes(".."))) {
12457
12489
  context.addIssue({
12458
12490
  code: "custom",
12459
12491
  path: ["versionSource", "path"],
@@ -12513,7 +12545,7 @@ var workspacesFileSchema = object({ workspaces: array(workspaceConfigSchema).opt
12513
12545
  names.add(workspace.name);
12514
12546
  }
12515
12547
  });
12516
- var workspacesRevision = (contents) => createHash6("sha256").update(contents ?? "<missing>").digest("hex");
12548
+ var workspacesRevision = (contents) => createHash7("sha256").update(contents ?? "<missing>").digest("hex");
12517
12549
  var validateWorkspacesDocument = (parsed, file) => {
12518
12550
  if (!isConfigObject(parsed)) {
12519
12551
  return { status: "malformed", path: file, entries: [], error: `${file} is not a JSON object` };
@@ -12551,7 +12583,7 @@ var validateWorkspacesDocument = (parsed, file) => {
12551
12583
  };
12552
12584
  };
12553
12585
  var readWorkspacesResult = (dir = configDir()) => {
12554
- const file = path10.join(dir, "workspaces.json");
12586
+ const file = path11.join(dir, "workspaces.json");
12555
12587
  let raw;
12556
12588
  try {
12557
12589
  raw = readFileSync3(file, "utf8");
@@ -12662,9 +12694,9 @@ var mainCheckoutOf = (cwd) => {
12662
12694
  let main = null;
12663
12695
  const dirs = git(["rev-parse", "--path-format=absolute", "--git-dir", "--git-common-dir"]);
12664
12696
  const [gitDir, common] = (dirs ?? "").trim().split(/\r?\n/u);
12665
- if (gitDir && common && path10.resolve(gitDir) !== path10.resolve(common)) {
12697
+ if (gitDir && common && path11.resolve(gitDir) !== path11.resolve(common)) {
12666
12698
  const listed = /^worktree (.+)$/mu.exec(git(["worktree", "list", "--porcelain"]) ?? "")?.[1];
12667
- main = listed?.trim() || (path10.basename(common) === ".git" ? path10.dirname(common) : common);
12699
+ main = listed?.trim() || (path11.basename(common) === ".git" ? path11.dirname(common) : common);
12668
12700
  }
12669
12701
  mainCheckouts.set(cwd, main);
12670
12702
  return main;
@@ -12755,7 +12787,7 @@ var runtimeWorkspaceIndexSchema = object({
12755
12787
  workspaces: array(object({ name: nonBlank, glob: nonBlank }).passthrough()).optional()
12756
12788
  }).passthrough();
12757
12789
  var matchRuntimeWorkspace = (cwd) => {
12758
- const file = path10.join(configDir(), "workspaces.json");
12790
+ const file = path11.join(configDir(), "workspaces.json");
12759
12791
  let raw;
12760
12792
  try {
12761
12793
  raw = readFileSync3(file, "utf8");
@@ -12830,7 +12862,7 @@ function workspaceDefaultTarget(cwd, globalDefault) {
12830
12862
  }
12831
12863
 
12832
12864
  // packages/workit-core/src/core/release-tracks.ts
12833
- import { createHash as createHash7 } from "node:crypto";
12865
+ import { createHash as createHash8 } from "node:crypto";
12834
12866
  import { spawnSync as spawnSync7 } from "node:child_process";
12835
12867
  class ReleaseTrackError extends Error {
12836
12868
  }
@@ -13213,7 +13245,7 @@ function resolveTrackFor(cwd, options) {
13213
13245
  ]) ?? "",
13214
13246
  git3(cwd, ["config", "--get", recordedBaseKey(branch)]) ?? ""
13215
13247
  ] : [];
13216
- key = createHash7("sha256").update(JSON.stringify({ cwd, input, refs, head, own })).digest("hex");
13248
+ key = createHash8("sha256").update(JSON.stringify({ cwd, input, refs, head, own })).digest("hex");
13217
13249
  const hit = memo2.get(key);
13218
13250
  if (hit)
13219
13251
  return hit;
@@ -13228,7 +13260,7 @@ function resolveTrackFor(cwd, options) {
13228
13260
  }
13229
13261
 
13230
13262
  // packages/workit-core/src/core/vcs-config.ts
13231
- var workspacesPath = () => path11.join(configDir(), "workspaces.json");
13263
+ var workspacesPath = () => path12.join(configDir(), "workspaces.json");
13232
13264
  var vcsCwd = (cwd) => cwd ?? process.env.WORKFLOW_WORKSPACE_ROOT ?? process.cwd();
13233
13265
  var remoteProvider = (cwd) => {
13234
13266
  const r = spawnSync8("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" });
@@ -13245,7 +13277,7 @@ var readVcsConfig = () => {
13245
13277
  const file = vcsConfigPath();
13246
13278
  let raw;
13247
13279
  try {
13248
- raw = fs10.readFileSync(file, "utf8");
13280
+ raw = fs11.readFileSync(file, "utf8");
13249
13281
  } catch {
13250
13282
  return { status: "missing", path: file, config: {} };
13251
13283
  }
@@ -13330,7 +13362,7 @@ function vcsConfig(mode, cwd, options = {}) {
13330
13362
  const prov = cfg[provider] ?? {};
13331
13363
  const out = {
13332
13364
  ok: true,
13333
- configPath: path11.resolve(cfgPath),
13365
+ configPath: path12.resolve(cfgPath),
13334
13366
  provider,
13335
13367
  defaultTargetBranch: workspaceDefault,
13336
13368
  pr: cfg.pr ?? {},
@@ -13456,7 +13488,7 @@ function diffHash(cwd, base, head) {
13456
13488
  ], GIT_TIMEOUTS.worktree);
13457
13489
  if (!diff.ok || !diff.stdout)
13458
13490
  return null;
13459
- const hash = createHash8("sha256");
13491
+ const hash = createHash9("sha256");
13460
13492
  for (const line of diff.stdout.split(`
13461
13493
  `)) {
13462
13494
  if (line.startsWith("index "))
@@ -13468,14 +13500,14 @@ function diffHash(cwd, base, head) {
13468
13500
  return `sha256:${hash.digest("hex")}`;
13469
13501
  }
13470
13502
  function storeRoot(cwd) {
13471
- const location = resolveStore(path12.resolve(cwd));
13503
+ const location = resolveStore(path13.resolve(cwd));
13472
13504
  if (location instanceof Error)
13473
13505
  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");
13474
13506
  return { ok: true, value: { root: location.dir, shared: location.shared } };
13475
13507
  }
13476
13508
  function ledgerPath(cwd) {
13477
13509
  const root = storeRoot(cwd);
13478
- return root.ok ? { ok: true, value: path12.join(root.value.root, "ledger", "ledger.jsonl") } : root;
13510
+ return root.ok ? { ok: true, value: path13.join(root.value.root, "ledger", "ledger.jsonl") } : root;
13479
13511
  }
13480
13512
  var newId2 = () => `${Date.now().toString(36)}-${randomBytes2(6).toString("hex")}`;
13481
13513
  var NETWORK_FS_TYPES = new Set([
@@ -13495,7 +13527,7 @@ var onNetworkFs = (dir) => {
13495
13527
  if (process.platform !== "linux")
13496
13528
  return false;
13497
13529
  try {
13498
- return isNetworkFsType(fs11.statfsSync(dir).type);
13530
+ return isNetworkFsType(fs12.statfsSync(dir).type);
13499
13531
  } catch {
13500
13532
  return false;
13501
13533
  }
@@ -13505,15 +13537,15 @@ var LOCK_STALE_MS = 30000;
13505
13537
  var LOCK_OWNER = "owner";
13506
13538
  var lockToken = (lock) => {
13507
13539
  try {
13508
- return fs11.readFileSync(path12.join(lock, LOCK_OWNER), "utf8");
13540
+ return fs12.readFileSync(path13.join(lock, LOCK_OWNER), "utf8");
13509
13541
  } catch {
13510
13542
  return null;
13511
13543
  }
13512
13544
  };
13513
13545
  var lockAgeMs = (lock) => {
13514
- for (const target of [path12.join(lock, LOCK_OWNER), lock]) {
13546
+ for (const target of [path13.join(lock, LOCK_OWNER), lock]) {
13515
13547
  try {
13516
- return Date.now() - fs11.statSync(target).mtimeMs;
13548
+ return Date.now() - fs12.statSync(target).mtimeMs;
13517
13549
  } catch {}
13518
13550
  }
13519
13551
  return null;
@@ -13521,14 +13553,14 @@ var lockAgeMs = (lock) => {
13521
13553
  var ledgerLock = {
13522
13554
  acquire(lock) {
13523
13555
  try {
13524
- fs11.mkdirSync(lock);
13556
+ fs12.mkdirSync(lock);
13525
13557
  } catch (error) {
13526
13558
  if (error.code === "EEXIST")
13527
13559
  return null;
13528
13560
  throw error;
13529
13561
  }
13530
13562
  const token = `${process.pid}-${randomBytes2(8).toString("hex")}`;
13531
- fs11.writeFileSync(path12.join(lock, LOCK_OWNER), token);
13563
+ fs12.writeFileSync(path13.join(lock, LOCK_OWNER), token);
13532
13564
  return token;
13533
13565
  },
13534
13566
  release(lock, token) {
@@ -13536,35 +13568,35 @@ var ledgerLock = {
13536
13568
  return false;
13537
13569
  const tomb = `${lock}.release-${randomBytes2(6).toString("hex")}`;
13538
13570
  try {
13539
- fs11.renameSync(lock, tomb);
13571
+ fs12.renameSync(lock, tomb);
13540
13572
  } catch {
13541
13573
  return false;
13542
13574
  }
13543
13575
  if (lockToken(tomb) !== token) {
13544
13576
  try {
13545
- fs11.renameSync(tomb, lock);
13577
+ fs12.renameSync(tomb, lock);
13546
13578
  } catch {}
13547
13579
  return false;
13548
13580
  }
13549
- fs11.rmSync(tomb, { recursive: true, force: true });
13581
+ fs12.rmSync(tomb, { recursive: true, force: true });
13550
13582
  return true;
13551
13583
  },
13552
13584
  token: lockToken,
13553
13585
  reap(lock, observed) {
13554
13586
  const tomb = `${lock}.reap-${randomBytes2(6).toString("hex")}`;
13555
13587
  try {
13556
- fs11.renameSync(lock, tomb);
13588
+ fs12.renameSync(lock, tomb);
13557
13589
  } catch {
13558
13590
  return false;
13559
13591
  }
13560
13592
  if (lockToken(tomb) === observed) {
13561
- fs11.rmSync(tomb, { recursive: true, force: true });
13593
+ fs12.rmSync(tomb, { recursive: true, force: true });
13562
13594
  return true;
13563
13595
  }
13564
13596
  try {
13565
- fs11.renameSync(tomb, lock);
13597
+ fs12.renameSync(tomb, lock);
13566
13598
  } catch {
13567
- fs11.rmSync(tomb, { recursive: true, force: true });
13599
+ fs12.rmSync(tomb, { recursive: true, force: true });
13568
13600
  }
13569
13601
  return false;
13570
13602
  }
@@ -13591,14 +13623,14 @@ function withLedgerLock(file, fn, waitMs = LOCK_WAIT_MS) {
13591
13623
  ledgerLock.release(lock, token);
13592
13624
  }
13593
13625
  }
13594
- var sha2562 = (text) => createHash8("sha256").update(text).digest("hex");
13626
+ var sha2562 = (text) => createHash9("sha256").update(text).digest("hex");
13595
13627
  var chainHash = (prevHash, body) => sha2562(`${prevHash ?? ""}
13596
13628
  ${body}`);
13597
13629
  var TAIL_BYTES = 64 * 1024;
13598
13630
  var lastLine = (fd, size) => {
13599
13631
  for (let span = Math.min(size, TAIL_BYTES);span > 0; span = Math.min(size, span * 2)) {
13600
13632
  const buffer = Buffer.alloc(span);
13601
- fs11.readSync(fd, buffer, 0, span, size - span);
13633
+ fs12.readSync(fd, buffer, 0, span, size - span);
13602
13634
  const end = buffer.lastIndexOf(10);
13603
13635
  if (end < 0) {
13604
13636
  if (span === size)
@@ -13629,13 +13661,13 @@ var lastLine = (fd, size) => {
13629
13661
  };
13630
13662
  function appendLine(file, build, options) {
13631
13663
  const write = () => {
13632
- const fd = fs11.openSync(file, "a+");
13664
+ const fd = fs12.openSync(file, "a+");
13633
13665
  try {
13634
- const size = fs11.fstatSync(fd).size;
13666
+ const size = fs12.fstatSync(fd).size;
13635
13667
  let fence = "";
13636
13668
  if (size > 0) {
13637
13669
  const last = Buffer.alloc(1);
13638
- fs11.readSync(fd, last, 0, 1, size - 1);
13670
+ fs12.readSync(fd, last, 0, 1, size - 1);
13639
13671
  if (last[0] !== 10)
13640
13672
  fence = `
13641
13673
  `;
@@ -13644,17 +13676,17 @@ function appendLine(file, build, options) {
13644
13676
  if (!line.ok)
13645
13677
  return line;
13646
13678
  const bytes = Buffer.from(fence + line.value);
13647
- const written = fs11.writeSync(fd, bytes);
13679
+ const written = fs12.writeSync(fd, bytes);
13648
13680
  if (written !== bytes.length)
13649
13681
  return err("unavailable", `short write to ${file}: ${written} of ${bytes.length} bytes; the row is torn and will be skipped`);
13650
13682
  return { ok: true, value: undefined };
13651
13683
  } finally {
13652
- fs11.closeSync(fd);
13684
+ fs12.closeSync(fd);
13653
13685
  }
13654
13686
  };
13655
13687
  try {
13656
- fs11.mkdirSync(path12.dirname(file), { recursive: true });
13657
- if (!options.forceLock && !onNetworkFs(path12.dirname(file)))
13688
+ fs12.mkdirSync(path13.dirname(file), { recursive: true });
13689
+ if (!options.forceLock && !onNetworkFs(path13.dirname(file)))
13658
13690
  return write();
13659
13691
  const locked = withLedgerLock(file, write);
13660
13692
  return locked ?? err("busy", `ledger lock ${file}.lock is held`, "retry; remove the .lock directory if no workit process is running");
@@ -13726,7 +13758,7 @@ function readLedger(cwd, options = {}) {
13726
13758
  return file;
13727
13759
  let text = "";
13728
13760
  try {
13729
- text = fs11.readFileSync(file.value, "utf8");
13761
+ text = fs12.readFileSync(file.value, "utf8");
13730
13762
  } catch (error) {
13731
13763
  if (error.code === "ENOENT")
13732
13764
  return {
@@ -13920,11 +13952,20 @@ function authorSessions(cwd, rows, branch, range = { base: null, head: null }, s
13920
13952
  sessions.add(session);
13921
13953
  return sessions;
13922
13954
  }
13955
+ var derivesFrom = (derived, bare) => !bare.includes(":") && derived.endsWith(`:${bare}`);
13956
+ var authoredBy = (authors, session) => {
13957
+ if (authors.has(session))
13958
+ return true;
13959
+ for (const author of authors)
13960
+ if (derivesFrom(author, session) || derivesFrom(session, author))
13961
+ return true;
13962
+ return false;
13963
+ };
13923
13964
  var independenceReasons = (row, authors) => {
13924
13965
  const reasons = [];
13925
13966
  if (!row.actor.session)
13926
13967
  reasons.push("no_session");
13927
- else if (authors.has(row.actor.session))
13968
+ else if (authoredBy(authors, row.actor.session))
13928
13969
  reasons.push("author_session");
13929
13970
  if (row.self === true && !reasons.includes("no_session"))
13930
13971
  reasons.push("self");
@@ -14208,7 +14249,7 @@ var productDecision = (task, ledger) => {
14208
14249
  };
14209
14250
  };
14210
14251
  var planRecorded = (task, root) => {
14211
- const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(path13.resolve(root, ref.path)));
14252
+ const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(path14.resolve(root, ref.path)));
14212
14253
  if (cited)
14213
14254
  return {
14214
14255
  met: true,
@@ -14267,15 +14308,15 @@ function writeBlockers(task, root) {
14267
14308
  }
14268
14309
 
14269
14310
  // packages/workit-core/src/core/task-evaluation.ts
14270
- var digestBytes = (value) => createHash9("sha256").update(value).digest("hex");
14271
- var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path14.sep}`);
14272
- var relative = (root, candidate) => path14.relative(root, candidate).split(path14.sep).join("/") || ".";
14311
+ var digestBytes = (value) => createHash10("sha256").update(value).digest("hex");
14312
+ var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path15.sep}`);
14313
+ var relative = (root, candidate) => path15.relative(root, candidate).split(path15.sep).join("/") || ".";
14273
14314
  var canonicalPath = (value) => {
14274
14315
  if (typeof value !== "string" || !value)
14275
14316
  return null;
14276
14317
  if (value.includes("\\") || value.split("/").includes(".."))
14277
14318
  return null;
14278
- const normalized = path14.posix.normalize(value);
14319
+ const normalized = path15.posix.normalize(value);
14279
14320
  if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
14280
14321
  return null;
14281
14322
  return normalized === "." ? "." : normalized.replace(/\/$/, "");
@@ -14323,21 +14364,21 @@ var gitPaths = (root) => {
14323
14364
  git: !/not a git repository/i.test(stderr)
14324
14365
  };
14325
14366
  }
14326
- const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path14.sep).join("/")) : [];
14367
+ const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path15.sep).join("/")) : [];
14327
14368
  const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
14328
14369
  if (stagedDeleted.status !== 0) {
14329
14370
  const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
14330
14371
  if (!/not a git repository/i.test(stderr))
14331
14372
  return { paths, uncertain: true, git: true };
14332
14373
  } else if (stagedDeleted.stdout) {
14333
- paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path14.sep).join("/")));
14374
+ paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path15.sep).join("/")));
14334
14375
  }
14335
14376
  return { paths: [...new Set(paths)], uncertain: false, git: true };
14336
14377
  };
14337
14378
  var walk = (root, directory, output) => {
14338
14379
  let names;
14339
14380
  try {
14340
- names = fs12.readdirSync(directory);
14381
+ names = fs13.readdirSync(directory);
14341
14382
  } catch {
14342
14383
  return true;
14343
14384
  }
@@ -14345,10 +14386,10 @@ var walk = (root, directory, output) => {
14345
14386
  for (const name of names) {
14346
14387
  if (name === ".git" || name === ".workit")
14347
14388
  continue;
14348
- const target = path14.join(directory, name);
14389
+ const target = path15.join(directory, name);
14349
14390
  let stat;
14350
14391
  try {
14351
- stat = fs12.lstatSync(target);
14392
+ stat = fs13.lstatSync(target);
14352
14393
  } catch {
14353
14394
  uncertain = true;
14354
14395
  continue;
@@ -14363,14 +14404,14 @@ var walk = (root, directory, output) => {
14363
14404
  var scopeRoots = (root, scope) => {
14364
14405
  const roots = [];
14365
14406
  for (const item of scope.paths.length ? scope.paths : ["."]) {
14366
- const target = path14.resolve(root, item);
14407
+ const target = path15.resolve(root, item);
14367
14408
  if (!inside(root, target))
14368
14409
  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` }] });
14369
14410
  let ancestor = target;
14370
- while (!fs12.existsSync(ancestor) && ancestor !== root)
14371
- ancestor = path14.dirname(ancestor);
14411
+ while (!fs13.existsSync(ancestor) && ancestor !== root)
14412
+ ancestor = path15.dirname(ancestor);
14372
14413
  try {
14373
- if (!inside(root, fs12.realpathSync(ancestor)))
14414
+ if (!inside(root, fs13.realpathSync(ancestor)))
14374
14415
  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` }] });
14375
14416
  } catch {
14376
14417
  return failure2("invalid_input", `candidate scope cannot be inspected: ${item}`);
@@ -14382,7 +14423,7 @@ var scopeRoots = (root, scope) => {
14382
14423
  function captureCandidate(root, scope, environment = []) {
14383
14424
  let checkout;
14384
14425
  try {
14385
- checkout = fs12.realpathSync(root);
14426
+ checkout = fs13.realpathSync(root);
14386
14427
  } catch {
14387
14428
  return failure2("invalid_input", "candidate root does not exist");
14388
14429
  }
@@ -14400,11 +14441,11 @@ function captureCandidate(root, scope, environment = []) {
14400
14441
  if (item === ".git" || item === ".workit")
14401
14442
  continue;
14402
14443
  names.add(item);
14403
- if (!fs12.existsSync(target))
14444
+ if (!fs13.existsSync(target))
14404
14445
  continue;
14405
14446
  let stat;
14406
14447
  try {
14407
- stat = fs12.lstatSync(target);
14448
+ stat = fs13.lstatSync(target);
14408
14449
  } catch {
14409
14450
  uncertain = true;
14410
14451
  continue;
@@ -14420,17 +14461,17 @@ function captureCandidate(root, scope, environment = []) {
14420
14461
  for (const item of [...names].toSorted()) {
14421
14462
  if (!scopeMatches(item, normalizedScope))
14422
14463
  continue;
14423
- const target = path14.join(checkout, item);
14464
+ const target = path15.join(checkout, item);
14424
14465
  try {
14425
- const stat = fs12.lstatSync(target);
14466
+ const stat = fs13.lstatSync(target);
14426
14467
  if (stat.isSymbolicLink()) {
14427
- const link = fs12.readlinkSync(target);
14468
+ const link = fs13.readlinkSync(target);
14428
14469
  files.push({ path: item, kind: "symlink", digest: digestBytes(link), executable: null });
14429
14470
  } else if (stat.isFile()) {
14430
14471
  files.push({
14431
14472
  path: item,
14432
14473
  kind: "file",
14433
- digest: digestBytes(fs12.readFileSync(target)),
14474
+ digest: digestBytes(fs13.readFileSync(target)),
14434
14475
  executable: (stat.mode & 73) !== 0
14435
14476
  });
14436
14477
  } else if (!stat.isDirectory()) {
@@ -14595,7 +14636,7 @@ var findingVerificationPasses = (findingCandidateId, evidence) => evidence.statu
14595
14636
  var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
14596
14637
  let root;
14597
14638
  try {
14598
- root = fs12.realpathSync(checkoutRoot);
14639
+ root = fs13.realpathSync(checkoutRoot);
14599
14640
  } catch {
14600
14641
  return failure2("permission_denied", "checkout root is unavailable");
14601
14642
  }
@@ -14604,23 +14645,23 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
14604
14645
  continue;
14605
14646
  if (!reference.digest)
14606
14647
  return failure2("invalid_input", "document references require a byte digest");
14607
- const target = path14.resolve(root, reference.path);
14608
- if (target !== root && !target.startsWith(`${root}${path14.sep}`))
14648
+ const target = path15.resolve(root, reference.path);
14649
+ if (target !== root && !target.startsWith(`${root}${path15.sep}`))
14609
14650
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
14610
14651
  fields: [
14611
14652
  { path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
14612
14653
  ]
14613
14654
  });
14614
14655
  try {
14615
- const below = path14.relative(root, target);
14656
+ const below = path15.relative(root, target);
14616
14657
  let current = root;
14617
- for (const segment of below.split(path14.sep)) {
14658
+ for (const segment of below.split(path15.sep)) {
14618
14659
  if (!segment)
14619
14660
  continue;
14620
- current = path14.join(current, segment);
14621
- const stat = fs12.lstatSync(current);
14622
- const real = fs12.realpathSync(current);
14623
- if (real !== root && !real.startsWith(`${root}${path14.sep}`))
14661
+ current = path15.join(current, segment);
14662
+ const stat = fs13.lstatSync(current);
14663
+ const real = fs13.realpathSync(current);
14664
+ if (real !== root && !real.startsWith(`${root}${path15.sep}`))
14624
14665
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
14625
14666
  fields: [
14626
14667
  {
@@ -14636,7 +14677,7 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
14636
14677
  if (current !== target && !stat.isDirectory())
14637
14678
  return failure2("invalid_input", "document reference ancestor is not a directory");
14638
14679
  }
14639
- if (digestBytes(fs12.readFileSync(target)) !== reference.digest)
14680
+ if (digestBytes(fs13.readFileSync(target)) !== reference.digest)
14640
14681
  return failure2("permission_denied", "decision document bytes have changed");
14641
14682
  } catch {
14642
14683
  return failure2("invalid_input", "decision document is unavailable");
@@ -15493,7 +15534,7 @@ var judgeInputSummary = (raw) => {
15493
15534
 
15494
15535
  // packages/workit-core/src/autonomy.ts
15495
15536
  import os3 from "node:os";
15496
- import path15 from "node:path";
15537
+ import path16 from "node:path";
15497
15538
  var accountHome = () => {
15498
15539
  try {
15499
15540
  return os3.userInfo().homedir;
@@ -15502,10 +15543,10 @@ var accountHome = () => {
15502
15543
  }
15503
15544
  };
15504
15545
  var grantsHome = { resolve: accountHome };
15505
- var grantsDir = () => path15.join(grantsHome.resolve(), ".config", "workit");
15546
+ var grantsDir = () => path16.join(grantsHome.resolve(), ".config", "workit");
15506
15547
  var grantsOverride = () => {
15507
- const configured = path15.resolve(resolveConfigDir());
15508
- 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`;
15548
+ const configured = path16.resolve(resolveConfigDir());
15549
+ return configured === path16.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 ${path16.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
15509
15550
  };
15510
15551
  var GRANT_KINDS = ["push", "pr", "merge", "release", "rerun"];
15511
15552
  var DEFAULT_GRANTS = Object.freeze({
@@ -17487,7 +17528,7 @@ function entryCompactContext(store, entry, session, context) {
17487
17528
  return null;
17488
17529
  const freshness = { mode: "signal", current: () => recentSignal(store.root) };
17489
17530
  const observed = task?.data.evidence.some(isObservedCheck) ?? false;
17490
- const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [path16.resolve(store.root, ref.path)] : []));
17531
+ const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [path17.resolve(store.root, ref.path)] : []));
17491
17532
  const observedFiles = filesKey(files);
17492
17533
  const compact = new WorkitCore(store, context).compactContext(entry?.id ?? null, freshness, origin && { origin: origin.origin, taskId: origin.entry.id });
17493
17534
  if (!compact.ok || !compact.data)
@@ -17556,7 +17597,7 @@ var turnContextText = (input, descriptor) => {
17556
17597
  }
17557
17598
  };
17558
17599
  var TURN_TTL_MS = 7 * 24 * 60 * 60 * 1000;
17559
- var digestOf = (text) => createHash10("sha256").update(text).digest("hex");
17600
+ var digestOf = (text) => createHash11("sha256").update(text).digest("hex");
17560
17601
  var turnMarker = (input) => {
17561
17602
  if (!input.session.id)
17562
17603
  return null;
@@ -17565,32 +17606,32 @@ var turnMarker = (input) => {
17565
17606
  if (location instanceof Error)
17566
17607
  return null;
17567
17608
  const session = [input.host, input.session.id, input.session.agentId ?? ""].join("\x00");
17568
- return path16.join(location.dir, "hooks", `turn-${digestOf(session).slice(0, 32)}.json`);
17609
+ return path17.join(location.dir, "hooks", `turn-${digestOf(session).slice(0, 32)}.json`);
17569
17610
  } catch {
17570
17611
  return null;
17571
17612
  }
17572
17613
  };
17573
17614
  var writeTurnDigest = (file, digest) => {
17574
17615
  try {
17575
- fs13.mkdirSync(path16.dirname(file), { recursive: true });
17576
- fs13.writeFileSync(file, `${JSON.stringify({ digest })}
17616
+ fs14.mkdirSync(path17.dirname(file), { recursive: true });
17617
+ fs14.writeFileSync(file, `${JSON.stringify({ digest })}
17577
17618
  `);
17578
17619
  } catch {}
17579
17620
  };
17580
17621
  var clearTurnDigest = (file) => {
17581
17622
  try {
17582
- fs13.rmSync(file, { force: true });
17623
+ fs14.rmSync(file, { force: true });
17583
17624
  } catch {}
17584
17625
  };
17585
17626
  var pruneTurnDigests = (dir, now) => {
17586
17627
  try {
17587
- for (const name of fs13.readdirSync(dir)) {
17628
+ for (const name of fs14.readdirSync(dir)) {
17588
17629
  if (!name.startsWith("turn-"))
17589
17630
  continue;
17590
- const file = path16.join(dir, name);
17631
+ const file = path17.join(dir, name);
17591
17632
  try {
17592
- if (now - fs13.statSync(file).mtimeMs > TURN_TTL_MS)
17593
- fs13.rmSync(file, { force: true });
17633
+ if (now - fs14.statSync(file).mtimeMs > TURN_TTL_MS)
17634
+ fs14.rmSync(file, { force: true });
17594
17635
  } catch {}
17595
17636
  }
17596
17637
  } catch {}
@@ -17606,7 +17647,7 @@ var changedTurnContext = (input, text) => {
17606
17647
  return text;
17607
17648
  const digest = digestOf(text);
17608
17649
  try {
17609
- const previous = JSON.parse(fs13.readFileSync(file, "utf8"));
17650
+ const previous = JSON.parse(fs14.readFileSync(file, "utf8"));
17610
17651
  if (previous.digest === digest)
17611
17652
  return null;
17612
17653
  } catch {}
@@ -17617,14 +17658,14 @@ var seedTurnContext = (input, descriptor, text = turnContextText(input, descript
17617
17658
  const file = turnMarker(input);
17618
17659
  if (!file)
17619
17660
  return;
17620
- pruneTurnDigests(path16.dirname(file), Date.now());
17661
+ pruneTurnDigests(path17.dirname(file), Date.now());
17621
17662
  if (text)
17622
17663
  writeTurnDigest(file, digestOf(text));
17623
17664
  else
17624
17665
  clearTurnDigest(file);
17625
17666
  };
17626
17667
  // packages/workit-core/src/core/branch.ts
17627
- import { createHash as createHash11 } from "node:crypto";
17668
+ import { createHash as createHash12 } from "node:crypto";
17628
17669
  var withReleaseTracks = (workspaceRoot, policy) => {
17629
17670
  const read = workspaceReleaseTracks(workspaceRoot);
17630
17671
  if (read.error)
@@ -17692,7 +17733,7 @@ var branchPolicySnapshotFor = (workspaceRoot) => {
17692
17733
  const source = resolved.provenance.branchPolicy;
17693
17734
  const allowed = branchPolicy.allowed.map((pattern) => `${pattern.source}/${pattern.flags}`).toSorted();
17694
17735
  const protectedRefs = [...branchPolicy.protected].map((name) => name.toLowerCase()).toSorted();
17695
- const fingerprint = createHash11("sha256").update(JSON.stringify({ allowed, protectedRefs, source })).digest("hex");
17736
+ const fingerprint = createHash12("sha256").update(JSON.stringify({ allowed, protectedRefs, source })).digest("hex");
17696
17737
  return {
17697
17738
  branchPolicy,
17698
17739
  namePolicy: { allowed: branchPolicy.allowed, protected: branchPolicy.protected },
@@ -17741,7 +17782,7 @@ var shellPolicy = (cwd, command) => {
17741
17782
  };
17742
17783
  // packages/workit-core/src/hooks/write-gate.ts
17743
17784
  import { realpathSync as realpathSync5 } from "node:fs";
17744
- import path17 from "node:path";
17785
+ import path18 from "node:path";
17745
17786
 
17746
17787
  // packages/workit-core/src/hooks/shell-words.ts
17747
17788
  var closingQuote = (command, start, dialect) => {
@@ -17871,22 +17912,22 @@ var NONE2 = { kind: "none" };
17871
17912
  var CASE_INSENSITIVE = process.platform === "darwin" || process.platform === "win32";
17872
17913
  var canonical2 = (file) => {
17873
17914
  let rest = "";
17874
- for (let dir = path17.resolve(file);; dir = path17.dirname(dir)) {
17915
+ for (let dir = path18.resolve(file);; dir = path18.dirname(dir)) {
17875
17916
  try {
17876
- return path17.join(realpathSync5(dir), rest);
17917
+ return path18.join(realpathSync5(dir), rest);
17877
17918
  } catch {
17878
- if (path17.dirname(dir) === dir)
17879
- return path17.resolve(file);
17880
- rest = rest ? path17.join(path17.basename(dir), rest) : path17.basename(dir);
17919
+ if (path18.dirname(dir) === dir)
17920
+ return path18.resolve(file);
17921
+ rest = rest ? path18.join(path18.basename(dir), rest) : path18.basename(dir);
17881
17922
  }
17882
17923
  }
17883
17924
  };
17884
17925
  var exempt = (cwd, root, file, plans) => {
17885
17926
  const fold = (value) => CASE_INSENSITIVE ? value.toLowerCase() : value;
17886
- const relative = path17.relative(fold(canonical2(root)), fold(canonical2(path17.resolve(cwd, file))));
17887
- if (relative.startsWith("..") || path17.isAbsolute(relative))
17927
+ const relative = path18.relative(fold(canonical2(root)), fold(canonical2(path18.resolve(cwd, file))));
17928
+ if (relative.startsWith("..") || path18.isAbsolute(relative))
17888
17929
  return true;
17889
- const posix = relative.split(path17.sep).join("/");
17930
+ const posix = relative.split(path18.sep).join("/");
17890
17931
  const segments = posix.split("/");
17891
17932
  return /\.mdx?$/i.test(posix) || segments[0] === "docs" || segments.includes("plans") || [...plans].some((plan) => fold(plan) === posix);
17892
17933
  };
@@ -17984,7 +18025,7 @@ var shellWrites = (command) => {
17984
18025
  return { writes: true, targets: unknown ? null : targets };
17985
18026
  };
17986
18027
  var cache2 = new Map;
17987
- var planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(path17.resolve(root, file)) ?? "-").join("\x00");
18028
+ var planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(path18.resolve(root, file)) ?? "-").join("\x00");
17988
18029
  var gateFor = (cwd) => {
17989
18030
  const store = new TaskStore(cwd);
17990
18031
  const listed = store.listTaskIndex();
@@ -18044,15 +18085,15 @@ import { spawnSync as spawnSync12 } from "node:child_process";
18044
18085
 
18045
18086
  // packages/workit-core/src/hooks/raw-git.ts
18046
18087
  import { spawnSync as spawnSync11 } from "node:child_process";
18047
- import { createHash as createHash13 } from "node:crypto";
18048
- import fs15 from "node:fs";
18088
+ import { createHash as createHash14 } from "node:crypto";
18089
+ import fs16 from "node:fs";
18049
18090
  import os4 from "node:os";
18050
- import path19 from "node:path";
18091
+ import path20 from "node:path";
18051
18092
 
18052
18093
  // packages/workit-core/src/hooks/session-marker.ts
18053
- import { createHash as createHash12 } from "node:crypto";
18054
- import fs14 from "node:fs";
18055
- import path18 from "node:path";
18094
+ import { createHash as createHash13 } from "node:crypto";
18095
+ import fs15 from "node:fs";
18096
+ import path19 from "node:path";
18056
18097
  var sessionMarkerFile = (input, session, store) => {
18057
18098
  let dir = store;
18058
18099
  if (dir === undefined) {
@@ -18061,13 +18102,13 @@ var sessionMarkerFile = (input, session, store) => {
18061
18102
  return null;
18062
18103
  dir = location.dir;
18063
18104
  }
18064
- const name = createHash12("sha256").update(`${input.host}\x00${session}`).digest("hex").slice(0, 32);
18065
- return path18.join(dir, "hooks", `skills-${name}.json`);
18105
+ const name = createHash13("sha256").update(`${input.host}\x00${session}`).digest("hex").slice(0, 32);
18106
+ return path19.join(dir, "hooks", `skills-${name}.json`);
18066
18107
  };
18067
18108
  var list2 = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
18068
18109
  var readSessionMarker = (file) => {
18069
18110
  try {
18070
- const value = JSON.parse(fs14.readFileSync(file, "utf8"));
18111
+ const value = JSON.parse(fs15.readFileSync(file, "utf8"));
18071
18112
  return { nudged: list2(value.nudged), loaded: list2(value.loaded), raw: list2(value.raw) };
18072
18113
  } catch {
18073
18114
  return { nudged: [], loaded: [], raw: [] };
@@ -18075,8 +18116,8 @@ var readSessionMarker = (file) => {
18075
18116
  };
18076
18117
  var writeSessionMarker = (file, marker) => {
18077
18118
  try {
18078
- fs14.mkdirSync(path18.dirname(file), { recursive: true });
18079
- fs14.writeFileSync(file, JSON.stringify(marker));
18119
+ fs15.mkdirSync(path19.dirname(file), { recursive: true });
18120
+ fs15.writeFileSync(file, JSON.stringify(marker));
18080
18121
  } catch {}
18081
18122
  };
18082
18123
 
@@ -18097,12 +18138,12 @@ var GIT_VALUE_OPTIONS = new Set([
18097
18138
  "--config-env",
18098
18139
  "--super-prefix"
18099
18140
  ]);
18100
- var isAbsolute = (value) => path19.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\");
18141
+ var isAbsolute = (value) => path20.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\");
18101
18142
  var joinDir = (base, next) => {
18102
18143
  if (base === undefined || /[$`*?]/.test(next) || next === "-")
18103
18144
  return;
18104
- const expanded = next === "~" || next.startsWith("~/") ? path19.join(os4.homedir(), next.slice(1)) : next;
18105
- return base === null || isAbsolute(expanded) ? expanded : path19.join(base, expanded);
18145
+ const expanded = next === "~" || next.startsWith("~/") ? path20.join(os4.homedir(), next.slice(1)) : next;
18146
+ return base === null || isAbsolute(expanded) ? expanded : path20.join(base, expanded);
18106
18147
  };
18107
18148
  var cdTarget = (words) => {
18108
18149
  const args = words.slice(1);
@@ -18355,7 +18396,7 @@ var repoAt = (dir) => {
18355
18396
  return { location, dir, branch: resolveTaskKey(dir, location).branch };
18356
18397
  };
18357
18398
  var isWorkitWorkspace = (repo) => {
18358
- if (fs15.existsSync(repo.location.dir))
18399
+ if (fs16.existsSync(repo.location.dir))
18359
18400
  return true;
18360
18401
  try {
18361
18402
  return resolveRuntimeWorkspaceVcs(repo.location.top ?? repo.dir) !== null;
@@ -18386,17 +18427,17 @@ var headSha2 = (repo) => {
18386
18427
  if (!git || git.reftable)
18387
18428
  return null;
18388
18429
  try {
18389
- const head = fs15.readFileSync(path19.join(git.gitDir, "HEAD"), "utf8").trim();
18430
+ const head = fs16.readFileSync(path20.join(git.gitDir, "HEAD"), "utf8").trim();
18390
18431
  if (/^[0-9a-f]{40,64}$/.test(head))
18391
18432
  return head;
18392
18433
  const ref = /^ref: (refs\/.+)$/.exec(head)?.[1];
18393
18434
  if (!ref)
18394
18435
  return null;
18395
- const common = path19.dirname(repo.location.dir);
18436
+ const common = path20.dirname(repo.location.dir);
18396
18437
  try {
18397
- return fs15.readFileSync(path19.join(common, ref), "utf8").trim() || null;
18438
+ return fs16.readFileSync(path20.join(common, ref), "utf8").trim() || null;
18398
18439
  } catch {}
18399
- const packed = fs15.readFileSync(path19.join(common, "packed-refs"), "utf8");
18440
+ const packed = fs16.readFileSync(path20.join(common, "packed-refs"), "utf8");
18400
18441
  return new RegExp(`^([0-9a-f]{40,64}) ${ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`, "m").exec(packed)?.[1] ?? null;
18401
18442
  } catch {
18402
18443
  return null;
@@ -18433,7 +18474,7 @@ var actionsIn = (cwd, command, dialect) => {
18433
18474
  const action = rawAction(invocation);
18434
18475
  if (!action)
18435
18476
  continue;
18436
- const dir = path19.resolve(cwd, invocation.dir ?? ".");
18477
+ const dir = path20.resolve(cwd, invocation.dir ?? ".");
18437
18478
  if (!repos.has(dir)) {
18438
18479
  const repo = repoAt(dir);
18439
18480
  repos.set(dir, repo && isWorkitWorkspace(repo) ? repo : null);
@@ -18502,8 +18543,8 @@ function rawGitPre(input, command, options = {}) {
18502
18543
  var deny = (reason) => ({ kind: "deny", reason, unblock: null });
18503
18544
  var NEXT_COMMAND = "next";
18504
18545
  var MARKER_TTL_SECONDS = 3600;
18505
- var markerFile = (repo, session, key) => path19.join(repo.location.dir, "hooks", `commit-${createHash13("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`);
18506
- var callKey = (toolUseId, command) => toolUseId ?? `cmd:${createHash13("sha256").update(command).digest("hex")}`;
18546
+ var markerFile = (repo, session, key) => path20.join(repo.location.dir, "hooks", `commit-${createHash14("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`);
18547
+ var callKey = (toolUseId, command) => toolUseId ?? `cmd:${createHash14("sha256").update(command).digest("hex")}`;
18507
18548
  function noteRawCommit(input, command, key) {
18508
18549
  try {
18509
18550
  if (!input.session.id || !/\bcommit\b/.test(command))
@@ -18513,8 +18554,8 @@ function noteRawCommit(input, command, key) {
18513
18554
  if (action.kind !== "commit")
18514
18555
  continue;
18515
18556
  const file = markerFile(repo, input.session.id, key);
18516
- fs15.mkdirSync(path19.dirname(file), { recursive: true });
18517
- fs15.writeFileSync(file, `${JSON.stringify({ head: headSha2(repo), at })}
18557
+ fs16.mkdirSync(path20.dirname(file), { recursive: true });
18558
+ fs16.writeFileSync(file, `${JSON.stringify({ head: headSha2(repo), at })}
18518
18559
  `);
18519
18560
  }
18520
18561
  } catch {}
@@ -18537,11 +18578,11 @@ var headCommit = (dir) => {
18537
18578
  var settle2 = (input, repo, file) => {
18538
18579
  let marker;
18539
18580
  try {
18540
- marker = JSON.parse(fs15.readFileSync(file, "utf8"));
18581
+ marker = JSON.parse(fs16.readFileSync(file, "utf8"));
18541
18582
  } catch {
18542
18583
  return;
18543
18584
  }
18544
- fs15.rmSync(file, { force: true });
18585
+ fs16.rmSync(file, { force: true });
18545
18586
  const session = input.session.id;
18546
18587
  const now = Date.now() / 1000;
18547
18588
  if (typeof marker.at !== "number" || now - marker.at > MARKER_TTL_SECONDS)
@@ -18590,7 +18631,7 @@ function settlePendingCommit(input) {
18590
18631
  if (!repo)
18591
18632
  return;
18592
18633
  const file = markerFile(repo, input.session.id, NEXT_COMMAND);
18593
- if (fs15.existsSync(file))
18634
+ if (fs16.existsSync(file))
18594
18635
  settle2(input, repo, file);
18595
18636
  } catch {}
18596
18637
  }
@@ -18980,12 +19021,12 @@ ${line}` };
18980
19021
  };
18981
19022
  // packages/workit-core/src/hooks/hosts/fields.ts
18982
19023
  import { existsSync as existsSync6, realpathSync as realpathSync6, statSync as statSync2 } from "node:fs";
18983
- import path20 from "node:path";
19024
+ import path21 from "node:path";
18984
19025
  var isRecord4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
18985
19026
  var nonEmpty2 = (value) => typeof value === "string" && value.trim() !== "";
18986
19027
  var optionalText = (value) => typeof value === "string" ? value : null;
18987
19028
  var existingDirectory = (value) => {
18988
- if (!nonEmpty2(value) || !path20.isAbsolute(value) || !existsSync6(value))
19029
+ if (!nonEmpty2(value) || !path21.isAbsolute(value) || !existsSync6(value))
18989
19030
  return null;
18990
19031
  try {
18991
19032
  return statSync2(value).isDirectory() ? realpathSync6(value) : null;
@@ -19085,6 +19126,8 @@ ${subagentStartText({ ...input, cwd: "" }, descriptor, event)}`;
19085
19126
  if (role !== "judge" || !event.agentId)
19086
19127
  return readOnly;
19087
19128
  const own = subagentSession(session, event.agentId);
19129
+ if (session)
19130
+ recordIssuedSession(input.cwd || process.cwd(), session, own);
19088
19131
  return `${readOnly} Its own Workit session is ${own}: record verdicts with \`workit ledger verdict <result> --session ${own} ...\` so the ledger tells it apart from the author.`;
19089
19132
  };
19090
19133
  function handleHook(input, deps) {
@@ -19716,12 +19759,12 @@ var codexAdapter = {
19716
19759
  };
19717
19760
  },
19718
19761
  render: render2,
19719
- addendum: (input) => `<workit-codex-mutations>Codex MCP is read-only: unattested callers cannot mutate. Run workit verbs with the workit CLI on the shell (node_modules/.bin/workit, or npx -y @brainervirus/workit-cli): check, git branch|commit|push, pr, ci, stack, ledger, handoff; task-family mutations take --json${input.session.id ? ` --actor ${input.session.id}` : ""}. workit acts as this thread (CODEX_THREAD_ID${input.session.id ? `=${input.session.id}` : ""}) unless WORKIT_SESSION_ID is set. A verifier or reviewer records workit ledger verdict under its own session, never the author's: a workit-verifier or workit-reviewer agent uses the --session its SubagentStart context names; any other uses one the lead assigns (WORKIT_HOST=codex_cli WORKIT_SESSION_ID=<lead>-v<n>). Merge and release need a workspace grant (workit grant show); a question answer is not host permission.</workit-codex-mutations>`
19762
+ addendum: (input) => `<workit-codex-mutations>Codex MCP is read-only: unattested callers cannot mutate. Run workit verbs with the workit CLI on the shell (node_modules/.bin/workit, or npx -y @brainervirus/workit-cli): check, git branch|commit|push, pr, ci, stack, ledger, handoff; task-family mutations take --json${input.session.id ? ` --actor ${input.session.id}` : ""}. workit acts as this thread (CODEX_THREAD_ID${input.session.id ? `=${input.session.id}` : ""}) unless WORKIT_SESSION_ID is set. A verifier or reviewer records workit ledger verdict under its own session, never the author's: a workit-verifier or workit-reviewer agent uses the --session its SubagentStart context names; any other passes --as verifier (an id derived from its own thread). A hand-minted id such as <lead>-v1 is refused as forged_session. Merge and release need a workspace grant (workit grant show); a question answer is not host permission.</workit-codex-mutations>`
19720
19763
  };
19721
19764
 
19722
19765
  // packages/workit-core/src/hooks/hosts/cursor.ts
19723
- import fs16 from "node:fs";
19724
- import path21 from "node:path";
19766
+ import fs17 from "node:fs";
19767
+ import path22 from "node:path";
19725
19768
  var undocumented = { support: "undocumented", native: null };
19726
19769
  var none = { support: "none", native: null };
19727
19770
  var CURSOR_DESCRIPTOR = {
@@ -19918,17 +19961,17 @@ var protocolEvent2 = (input) => {
19918
19961
  };
19919
19962
  var TRANSCRIPT_TAIL_BYTES = 256 * 1024;
19920
19963
  var lastAssistantText = (file) => {
19921
- if (!file || !path21.isAbsolute(file))
19964
+ if (!file || !path22.isAbsolute(file))
19922
19965
  return null;
19923
19966
  try {
19924
- const size = fs16.statSync(file).size;
19967
+ const size = fs17.statSync(file).size;
19925
19968
  const start = Math.max(0, size - TRANSCRIPT_TAIL_BYTES);
19926
19969
  const buffer = Buffer.alloc(size - start);
19927
- const fd = fs16.openSync(file, "r");
19970
+ const fd = fs17.openSync(file, "r");
19928
19971
  try {
19929
- fs16.readSync(fd, buffer, 0, buffer.length, start);
19972
+ fs17.readSync(fd, buffer, 0, buffer.length, start);
19930
19973
  } finally {
19931
- fs16.closeSync(fd);
19974
+ fs17.closeSync(fd);
19932
19975
  }
19933
19976
  const lines = buffer.toString("utf8").split(`
19934
19977
  `);
@@ -19955,7 +19998,7 @@ var lastAssistantText = (file) => {
19955
19998
  return null;
19956
19999
  }
19957
20000
  };
19958
- var within = (root, dir) => dir === root || dir.startsWith(root.endsWith(path21.sep) ? root : `${root}${path21.sep}`);
20001
+ var within = (root, dir) => dir === root || dir.startsWith(root.endsWith(path22.sep) ? root : `${root}${path22.sep}`);
19959
20002
  var hookCwd = (input) => {
19960
20003
  const cwd = existingDirectory(input.cwd);
19961
20004
  if (cwd && input.hook_event_name === "beforeShellExecution")