@brainervirus/workit-pi 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.
package/dist/workit.js CHANGED
@@ -5,7 +5,7 @@ import { fileURLToPath as fileURLToPath2 } from "node:url";
5
5
  // packages/workit-core/src/core.ts
6
6
  import { spawnSync as spawnSync14 } from "node:child_process";
7
7
  import { existsSync as existsSync7, realpathSync as realpathSync5 } from "node:fs";
8
- import path19 from "node:path";
8
+ import path20 from "node:path";
9
9
 
10
10
  // packages/workit-core/src/core/task-contract.ts
11
11
  import { createHash, randomUUID } from "node:crypto";
@@ -8991,9 +8991,9 @@ function parseAdvertisedOperation(family, input, host) {
8991
8991
  });
8992
8992
  }
8993
8993
  // packages/workit-core/src/core/task-store.ts
8994
- import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
8995
- import * as fs7 from "node:fs";
8996
- import path6 from "node:path";
8994
+ import { createHash as createHash5, randomUUID as randomUUID3 } from "node:crypto";
8995
+ import * as fs8 from "node:fs";
8996
+ import path7 from "node:path";
8997
8997
 
8998
8998
  // node_modules/@openclaw/fs-safe/dist/errors.js
8999
8999
  var OPERATIONAL_CODES = new Set([
@@ -9597,63 +9597,15 @@ function acquireFileLockSync(targetPath, options) {
9597
9597
  }
9598
9598
  }
9599
9599
  // packages/workit-core/src/host-session.ts
9600
- var HOST_SESSION_VARS = [
9601
- ["OPENCODE_SESSION_ID", () => "opencode"],
9602
- ["PI_SESSION_ID", () => "pi"],
9603
- [
9604
- "CODEX_THREAD_ID",
9605
- (env) => env.CODEX_INTERNAL_ORIGINATOR_OVERRIDE === "Codex Desktop" || env.CODEX_ELECTRON_RESOURCES_PATH ? "codex_desktop" : "codex_cli"
9606
- ]
9607
- ];
9608
- var family = (host) => host?.replace(/_(?:cli|desktop)$/, "") ?? null;
9609
- function hostSessionFromEnv(env) {
9610
- const value = (key) => env[key]?.trim() || null;
9611
- let inner = null;
9612
- for (const [key, host] of HOST_SESSION_VARS) {
9613
- const session = value(key);
9614
- if (session) {
9615
- inner = { host: host(env), session };
9616
- break;
9617
- }
9618
- }
9619
- const declared = value("WORKIT_HOST");
9620
- if (env.WORKIT_SESSION_ID !== undefined) {
9621
- const inherited = inner !== null && declared !== null && family(declared) !== family(inner.host);
9622
- if (!inherited)
9623
- return { host: declared, session: value("WORKIT_SESSION_ID") };
9624
- }
9625
- return inner ? { host: inner.host, session: inner.session } : { host: declared, session: null };
9626
- }
9627
-
9628
- // packages/workit-core/src/core/package-root.ts
9629
- import { existsSync } from "node:fs";
9630
- import path3 from "node:path";
9631
- import { fileURLToPath } from "node:url";
9632
- var packageRoot = () => {
9633
- let dir = path3.dirname(fileURLToPath(import.meta.url));
9634
- while (true) {
9635
- const parent = path3.dirname(dir);
9636
- if (existsSync(path3.join(dir, "package.json")) || parent === dir)
9637
- return dir;
9638
- dir = parent;
9639
- }
9640
- };
9641
- var assetRoot = () => {
9642
- const root = packageRoot();
9643
- const assets = path3.join(root, "assets");
9644
- return existsSync(assets) ? assets : root;
9645
- };
9646
-
9647
- // packages/workit-core/src/core/store-lock.ts
9648
- import { spawnSync as spawnSync2 } from "node:child_process";
9600
+ import { createHash as createHash3 } from "node:crypto";
9649
9601
  import fs5 from "node:fs";
9650
- import { hostname } from "node:os";
9602
+ import path4 from "node:path";
9651
9603
 
9652
9604
  // packages/workit-core/src/store/paths.ts
9653
9605
  import { spawnSync } from "node:child_process";
9654
9606
  import { createHash as createHash2 } from "node:crypto";
9655
9607
  import fs4 from "node:fs";
9656
- import path4 from "node:path";
9608
+ import path3 from "node:path";
9657
9609
  var NOT_A_REPO = /not a git repository \(or any (of the parent directories|parent up to)/u;
9658
9610
  var gitRun = (cwd, args) => {
9659
9611
  const run = spawnSync("git", args, {
@@ -9695,14 +9647,14 @@ var DISCOVERY_ENV = [
9695
9647
  ];
9696
9648
  var isGitDir = (dir) => {
9697
9649
  try {
9698
- return fs4.statSync(path4.join(dir, "HEAD")).isFile() && fs4.statSync(path4.join(dir, "objects")).isDirectory() && fs4.statSync(path4.join(dir, "refs")).isDirectory();
9650
+ return fs4.statSync(path3.join(dir, "HEAD")).isFile() && fs4.statSync(path3.join(dir, "objects")).isDirectory() && fs4.statSync(path3.join(dir, "refs")).isDirectory();
9699
9651
  } catch {
9700
9652
  return false;
9701
9653
  }
9702
9654
  };
9703
9655
  var reftableRefs = (common) => {
9704
9656
  try {
9705
- return /^\s*refstorage\s*=\s*reftable\s*$/imu.test(fs4.readFileSync(path4.join(common, "config"), "utf8"));
9657
+ return /^\s*refstorage\s*=\s*reftable\s*$/imu.test(fs4.readFileSync(path3.join(common, "config"), "utf8"));
9706
9658
  } catch {
9707
9659
  return false;
9708
9660
  }
@@ -9722,7 +9674,7 @@ function fastGit(root) {
9722
9674
  if (device !== null && stat.dev !== device)
9723
9675
  return { kind: "none" };
9724
9676
  device = stat.dev;
9725
- const dotGit = path4.join(dir, ".git");
9677
+ const dotGit = path3.join(dir, ".git");
9726
9678
  let entry = null;
9727
9679
  try {
9728
9680
  entry = fs4.statSync(dotGit);
@@ -9743,19 +9695,19 @@ function fastGit(root) {
9743
9695
  const match = /^gitdir: (.+)$/mu.exec(text);
9744
9696
  if (!match)
9745
9697
  return null;
9746
- gitDir = path4.resolve(dir, match[1].trim());
9698
+ gitDir = path3.resolve(dir, match[1].trim());
9747
9699
  } else
9748
9700
  return null;
9749
- if (!fs4.existsSync(path4.join(gitDir, "HEAD")))
9701
+ if (!fs4.existsSync(path3.join(gitDir, "HEAD")))
9750
9702
  return null;
9751
9703
  } else if (isGitDir(dir))
9752
9704
  gitDir = dir;
9753
9705
  if (gitDir) {
9754
9706
  let common = gitDir;
9755
9707
  try {
9756
- common = path4.resolve(gitDir, fs4.readFileSync(path4.join(gitDir, "commondir"), "utf8").trim());
9708
+ common = path3.resolve(gitDir, fs4.readFileSync(path3.join(gitDir, "commondir"), "utf8").trim());
9757
9709
  } catch {}
9758
- if (!fs4.existsSync(path4.join(common, "objects")))
9710
+ if (!fs4.existsSync(path3.join(common, "objects")))
9759
9711
  return null;
9760
9712
  return {
9761
9713
  kind: "repo",
@@ -9765,26 +9717,26 @@ function fastGit(root) {
9765
9717
  reftable: reftableRefs(common)
9766
9718
  };
9767
9719
  }
9768
- const parent = path4.dirname(dir);
9720
+ const parent = path3.dirname(dir);
9769
9721
  if (parent === dir)
9770
9722
  return { kind: "none" };
9771
9723
  dir = parent;
9772
9724
  }
9773
9725
  }
9774
9726
  function resolveStore(root) {
9775
- root = path4.resolve(root);
9727
+ root = path3.resolve(root);
9776
9728
  let directory = false;
9777
9729
  try {
9778
9730
  directory = fs4.statSync(root).isDirectory();
9779
9731
  } catch {}
9780
9732
  if (!directory)
9781
- return { dir: path4.join(root, ".workit"), shared: false, top: null };
9733
+ return { dir: path3.join(root, ".workit"), shared: false, top: null };
9782
9734
  const fast = fastGit(root);
9783
9735
  if (fast?.kind === "none")
9784
- return { dir: path4.join(root, ".workit"), shared: false, top: null };
9736
+ return { dir: path3.join(root, ".workit"), shared: false, top: null };
9785
9737
  if (fast?.kind === "repo")
9786
9738
  return {
9787
- dir: path4.join(fast.common, "workit"),
9739
+ dir: path3.join(fast.common, "workit"),
9788
9740
  shared: true,
9789
9741
  top: fast.top,
9790
9742
  git: { gitDir: fast.gitDir, top: fast.top, reftable: fast.reftable }
@@ -9794,20 +9746,20 @@ function resolveStore(root) {
9794
9746
  if (run.ok && common) {
9795
9747
  const top = gitRun(root, ["rev-parse", "--path-format=absolute", "--show-toplevel"]);
9796
9748
  return {
9797
- dir: path4.join(real(path4.resolve(root, common)), "workit"),
9749
+ dir: path3.join(real(path3.resolve(root, common)), "workit"),
9798
9750
  shared: true,
9799
9751
  top: top.ok && top.stdout.trim() ? real(top.stdout.trim()) : null
9800
9752
  };
9801
9753
  }
9802
9754
  if (run.missing || !run.ok && NOT_A_REPO.test(run.stderr))
9803
- return { dir: path4.join(root, ".workit"), shared: false, top: null };
9755
+ return { dir: path3.join(root, ".workit"), shared: false, top: null };
9804
9756
  return new Error(`cannot locate the workit store: git rev-parse failed (${run.stderr.trim().split(`
9805
9757
  `)[0] || "no output"}); fix the repository (git status should work here)`);
9806
9758
  }
9807
9759
  var rebasingBranch = (gitDir) => {
9808
9760
  for (const state of ["rebase-merge", "rebase-apply"]) {
9809
9761
  try {
9810
- const ref = fs4.readFileSync(path4.join(gitDir, state, "head-name"), "utf8").trim();
9762
+ const ref = fs4.readFileSync(path3.join(gitDir, state, "head-name"), "utf8").trim();
9811
9763
  const match = /^refs\/heads\/(.+)$/u.exec(ref);
9812
9764
  if (match)
9813
9765
  return match[1];
@@ -9822,7 +9774,7 @@ function resolveTaskKey(root, location) {
9822
9774
  if (location.git && !location.git.reftable) {
9823
9775
  let head = "";
9824
9776
  try {
9825
- head = fs4.readFileSync(path4.join(location.git.gitDir, "HEAD"), "utf8").trim();
9777
+ head = fs4.readFileSync(path3.join(location.git.gitDir, "HEAD"), "utf8").trim();
9826
9778
  } catch {}
9827
9779
  const ref = /^ref: refs\/heads\/(.+)$/u.exec(head);
9828
9780
  if (ref && ref[1] !== ".invalid")
@@ -9853,7 +9805,7 @@ function resolveTaskKey(root, location) {
9853
9805
  return { key: `detached-${shortHash(real(worktree))}`, kind: "detached", branch: null };
9854
9806
  }
9855
9807
  function checkoutRootOf(root, location) {
9856
- const resolved = path4.resolve(root);
9808
+ const resolved = path3.resolve(root);
9857
9809
  let canonical = resolved;
9858
9810
  try {
9859
9811
  canonical = fs4.realpathSync(resolved);
@@ -9884,13 +9836,13 @@ function branchRenames(location) {
9884
9836
  }
9885
9837
  for (const entry of entries)
9886
9838
  if (entry.isDirectory())
9887
- walk(path4.join(dir, entry.name));
9839
+ walk(path3.join(dir, entry.name));
9888
9840
  else
9889
- files.push(path4.join(dir, entry.name));
9841
+ files.push(path3.join(dir, entry.name));
9890
9842
  };
9891
- walk(path4.join(path4.dirname(location.dir), "logs", "refs", "heads"));
9843
+ walk(path3.join(path3.dirname(location.dir), "logs", "refs", "heads"));
9892
9844
  if (location.git)
9893
- files.push(path4.join(location.git.gitDir, "logs", "HEAD"));
9845
+ files.push(path3.join(location.git.gitDir, "logs", "HEAD"));
9894
9846
  const seen = new Set;
9895
9847
  const renames = [];
9896
9848
  for (const file of files) {
@@ -9925,11 +9877,96 @@ var checkoutSlug = (root) => {
9925
9877
  let canonical = real(root);
9926
9878
  if (process.platform === "win32")
9927
9879
  canonical = canonical.toLowerCase();
9928
- const base = path4.basename(canonical).replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 40) || "root";
9880
+ const base = path3.basename(canonical).replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 40) || "root";
9929
9881
  return `${base}-${shortHash(canonical)}`;
9930
9882
  };
9931
9883
 
9884
+ // packages/workit-core/src/host-session.ts
9885
+ var HOST_SESSION_VARS = [
9886
+ ["OPENCODE_SESSION_ID", () => "opencode"],
9887
+ ["PI_SESSION_ID", () => "pi"],
9888
+ [
9889
+ "CODEX_THREAD_ID",
9890
+ (env) => env.CODEX_INTERNAL_ORIGINATOR_OVERRIDE === "Codex Desktop" || env.CODEX_ELECTRON_RESOURCES_PATH ? "codex_desktop" : "codex_cli"
9891
+ ]
9892
+ ];
9893
+ var family = (host) => host?.replace(/_(?:cli|desktop)$/, "") ?? null;
9894
+ function hostSessionFromEnv(env) {
9895
+ const value = (key) => env[key]?.trim() || null;
9896
+ let inner = null;
9897
+ for (const [key, host] of HOST_SESSION_VARS) {
9898
+ const session = value(key);
9899
+ if (session) {
9900
+ inner = { host: host(env), session };
9901
+ break;
9902
+ }
9903
+ }
9904
+ const declared = value("WORKIT_HOST");
9905
+ if (env.WORKIT_SESSION_ID !== undefined) {
9906
+ const inherited = inner !== null && declared !== null && family(declared) !== family(inner.host);
9907
+ if (!inherited)
9908
+ return { host: declared, session: value("WORKIT_SESSION_ID") };
9909
+ }
9910
+ return inner ? { host: inner.host, session: inner.session } : { host: declared, session: null };
9911
+ }
9912
+ var ISSUED_PER_LEAD = 64;
9913
+ var ISSUED_SESSIONS_MARKER = "workit-issued-sessions/1";
9914
+ var hash = (value) => createHash3("sha256").update(value).digest("hex").slice(0, 32);
9915
+ var issuedRoot = (cwd) => {
9916
+ const location = resolveStore(cwd);
9917
+ return location instanceof Error ? null : path4.join(location.dir, "hooks", "issued");
9918
+ };
9919
+ var issuedDir = (cwd, lead) => {
9920
+ const root = issuedRoot(cwd);
9921
+ return root === null ? null : path4.join(root, hash(lead));
9922
+ };
9923
+ function recordIssuedSession(cwd, lead, issued) {
9924
+ try {
9925
+ const dir = issuedDir(cwd, lead);
9926
+ if (!dir)
9927
+ return;
9928
+ fs5.mkdirSync(dir, { recursive: true });
9929
+ const own = hash(issued);
9930
+ fs5.writeFileSync(path4.join(dir, own), ISSUED_SESSIONS_MARKER);
9931
+ const entries = fs5.readdirSync(dir);
9932
+ if (entries.length <= ISSUED_PER_LEAD)
9933
+ return;
9934
+ const byAge = entries.filter((name) => name !== own).map((name) => ({ name, at: fs5.statSync(path4.join(dir, name)).mtimeMs })).toSorted((a, b) => a.at - b.at);
9935
+ for (const { name } of byAge.slice(0, entries.length - ISSUED_PER_LEAD))
9936
+ fs5.rmSync(path4.join(dir, name), { force: true });
9937
+ } catch {}
9938
+ }
9939
+ var OWN_CHILD_SHELL = new Set(["opencode", "pi"]);
9940
+ var SESSION_UNSAFE = /[^A-Za-z0-9_.:@/+-]/g;
9941
+ function childSessionId(lead, child) {
9942
+ const leaf = child.replace(SESSION_UNSAFE, "-").slice(-120);
9943
+ const prefix = lead.replace(SESSION_UNSAFE, "-").slice(0, 127 - leaf.length);
9944
+ return prefix ? `${prefix}:${leaf}` : leaf;
9945
+ }
9946
+
9947
+ // packages/workit-core/src/core/package-root.ts
9948
+ import { existsSync } from "node:fs";
9949
+ import path5 from "node:path";
9950
+ import { fileURLToPath } from "node:url";
9951
+ var packageRoot = () => {
9952
+ let dir = path5.dirname(fileURLToPath(import.meta.url));
9953
+ while (true) {
9954
+ const parent = path5.dirname(dir);
9955
+ if (existsSync(path5.join(dir, "package.json")) || parent === dir)
9956
+ return dir;
9957
+ dir = parent;
9958
+ }
9959
+ };
9960
+ var assetRoot = () => {
9961
+ const root = packageRoot();
9962
+ const assets = path5.join(root, "assets");
9963
+ return existsSync(assets) ? assets : root;
9964
+ };
9965
+
9932
9966
  // packages/workit-core/src/core/store-lock.ts
9967
+ import { spawnSync as spawnSync2 } from "node:child_process";
9968
+ import fs6 from "node:fs";
9969
+ import { hostname } from "node:os";
9933
9970
  var metadataLockSchema = object({
9934
9971
  pid: number2().int().nonnegative().safe(),
9935
9972
  processStart: string2().nullable(),
@@ -9970,7 +10007,7 @@ var parseProcStatStart = (stat) => {
9970
10007
  var processStartOf = (pid) => {
9971
10008
  if (process.platform === "linux") {
9972
10009
  try {
9973
- return parseProcStatStart(fs5.readFileSync(`/proc/${pid}/stat`, "utf8"));
10010
+ return parseProcStatStart(fs6.readFileSync(`/proc/${pid}/stat`, "utf8"));
9974
10011
  } catch {
9975
10012
  return null;
9976
10013
  }
@@ -9991,7 +10028,7 @@ var processStartOf = (pid) => {
9991
10028
  };
9992
10029
  var readTrimmed = (file) => {
9993
10030
  try {
9994
- return fs5.readFileSync(file, "utf8").trim() || null;
10031
+ return fs6.readFileSync(file, "utf8").trim() || null;
9995
10032
  } catch {
9996
10033
  return null;
9997
10034
  }
@@ -10002,7 +10039,7 @@ var localLockHost = () => {
10002
10039
  return cachedLockHost;
10003
10040
  let pidns = null;
10004
10041
  try {
10005
- pidns = /\[(\d+)\]/.exec(fs5.readlinkSync("/proc/self/ns/pid"))?.[1] ?? null;
10042
+ pidns = /\[(\d+)\]/.exec(fs6.readlinkSync("/proc/self/ns/pid"))?.[1] ?? null;
10006
10043
  } catch {}
10007
10044
  const boot = readTrimmed("/proc/sys/kernel/random/boot_id");
10008
10045
  cachedLockHost = pidns || boot ? `${hostname()}#${pidns ?? "?"}:${boot ?? "?"}` : hostname();
@@ -10048,7 +10085,7 @@ var classifyLockOwner = (payload, ageMs, localHost = localLockHost(), options =
10048
10085
  };
10049
10086
  var ageOf = (file, nowMs) => {
10050
10087
  try {
10051
- return nowMs - fs5.lstatSync(file).mtimeMs;
10088
+ return nowMs - fs6.lstatSync(file).mtimeMs;
10052
10089
  } catch {
10053
10090
  return null;
10054
10091
  }
@@ -10059,7 +10096,7 @@ var clearAbandonedReclaimGuard = (lockPath, nowMs = Date.now()) => {
10059
10096
  if (age === null || age <= RECLAIM_GUARD_TTL_MS)
10060
10097
  return false;
10061
10098
  try {
10062
- fs5.rmdirSync(guard);
10099
+ fs6.rmdirSync(guard);
10063
10100
  return true;
10064
10101
  } catch {
10065
10102
  return false;
@@ -10068,8 +10105,8 @@ var clearAbandonedReclaimGuard = (lockPath, nowMs = Date.now()) => {
10068
10105
 
10069
10106
  // packages/workit-core/src/store/event-log.ts
10070
10107
  import { randomUUID as randomUUID2 } from "node:crypto";
10071
- import fs6 from "node:fs";
10072
- import path5 from "node:path";
10108
+ import fs7 from "node:fs";
10109
+ import path6 from "node:path";
10073
10110
  var EVENT_VERSION = 1;
10074
10111
 
10075
10112
  class LogDamage extends Error {
@@ -10098,7 +10135,7 @@ var parseEvent = (line, file, offset) => {
10098
10135
  function readLog(file, from = 0, expectSeq = null) {
10099
10136
  let fd;
10100
10137
  try {
10101
- fd = fs6.openSync(file, "r");
10138
+ fd = fs7.openSync(file, "r");
10102
10139
  } catch (error) {
10103
10140
  if (error.code === "ENOENT")
10104
10141
  return null;
@@ -10107,13 +10144,13 @@ function readLog(file, from = 0, expectSeq = null) {
10107
10144
  let bytes;
10108
10145
  let size;
10109
10146
  try {
10110
- size = fs6.fstatSync(fd).size;
10147
+ size = fs7.fstatSync(fd).size;
10111
10148
  if (from > size)
10112
10149
  throw new LogDamage(`${file}: shorter than its snapshot`);
10113
10150
  bytes = Buffer.alloc(size - from);
10114
10151
  let read = 0;
10115
10152
  while (read < bytes.length) {
10116
- const got = fs6.readSync(fd, bytes, read, bytes.length - read, from + read);
10153
+ const got = fs7.readSync(fd, bytes, read, bytes.length - read, from + read);
10117
10154
  if (got === 0)
10118
10155
  break;
10119
10156
  read += got;
@@ -10121,7 +10158,7 @@ function readLog(file, from = 0, expectSeq = null) {
10121
10158
  bytes = bytes.subarray(0, read);
10122
10159
  size = from + read;
10123
10160
  } finally {
10124
- fs6.closeSync(fd);
10161
+ fs7.closeSync(fd);
10125
10162
  }
10126
10163
  const events = [];
10127
10164
  let start = 0;
@@ -10146,11 +10183,11 @@ function readLog(file, from = 0, expectSeq = null) {
10146
10183
  }
10147
10184
  var fsyncDirectory = (dir) => {
10148
10185
  try {
10149
- const fd = fs6.openSync(dir, "r");
10186
+ const fd = fs7.openSync(dir, "r");
10150
10187
  try {
10151
- fs6.fsyncSync(fd);
10188
+ fs7.fsyncSync(fd);
10152
10189
  } finally {
10153
- fs6.closeSync(fd);
10190
+ fs7.closeSync(fd);
10154
10191
  }
10155
10192
  } catch (error) {
10156
10193
  if (process.platform !== "win32")
@@ -10160,46 +10197,46 @@ var fsyncDirectory = (dir) => {
10160
10197
  function appendEvent(file, event, validEnd) {
10161
10198
  const line = Buffer.from(`${JSON.stringify(event)}
10162
10199
  `, "utf8");
10163
- const created = !fs6.existsSync(file);
10164
- if (!created && fs6.statSync(file).size !== validEnd) {
10165
- const cut = fs6.openSync(file, "r+");
10200
+ const created = !fs7.existsSync(file);
10201
+ if (!created && fs7.statSync(file).size !== validEnd) {
10202
+ const cut = fs7.openSync(file, "r+");
10166
10203
  try {
10167
- fs6.ftruncateSync(cut, validEnd);
10168
- fs6.fsyncSync(cut);
10204
+ fs7.ftruncateSync(cut, validEnd);
10205
+ fs7.fsyncSync(cut);
10169
10206
  } finally {
10170
- fs6.closeSync(cut);
10207
+ fs7.closeSync(cut);
10171
10208
  }
10172
10209
  }
10173
- const fd = fs6.openSync(file, "a", 384);
10210
+ const fd = fs7.openSync(file, "a", 384);
10174
10211
  try {
10175
10212
  let written = 0;
10176
10213
  while (written < line.length)
10177
- written += fs6.writeSync(fd, line, written, line.length - written);
10178
- fs6.fsyncSync(fd);
10214
+ written += fs7.writeSync(fd, line, written, line.length - written);
10215
+ fs7.fsyncSync(fd);
10179
10216
  } finally {
10180
- fs6.closeSync(fd);
10217
+ fs7.closeSync(fd);
10181
10218
  }
10182
10219
  if (created)
10183
- fsyncDirectory(path5.dirname(file));
10220
+ fsyncDirectory(path6.dirname(file));
10184
10221
  return validEnd;
10185
10222
  }
10186
10223
  function replaceFile(file, bytes, durable) {
10187
10224
  const temporary = `${file}.${process.pid}.${randomUUID2()}.tmp`;
10188
10225
  try {
10189
- const fd = fs6.openSync(temporary, "wx", 384);
10226
+ const fd = fs7.openSync(temporary, "wx", 384);
10190
10227
  try {
10191
- fs6.writeSync(fd, bytes);
10228
+ fs7.writeSync(fd, bytes);
10192
10229
  if (durable)
10193
- fs6.fsyncSync(fd);
10230
+ fs7.fsyncSync(fd);
10194
10231
  } finally {
10195
- fs6.closeSync(fd);
10232
+ fs7.closeSync(fd);
10196
10233
  }
10197
10234
  renameWithRetry(temporary, file);
10198
10235
  if (durable)
10199
- fsyncDirectory(path5.dirname(file));
10236
+ fsyncDirectory(path6.dirname(file));
10200
10237
  } catch (error) {
10201
10238
  try {
10202
- fs6.unlinkSync(temporary);
10239
+ fs7.unlinkSync(temporary);
10203
10240
  } catch {}
10204
10241
  throw error;
10205
10242
  }
@@ -10224,7 +10261,7 @@ var retryTransient = (run) => {
10224
10261
  }
10225
10262
  }
10226
10263
  };
10227
- var renameWithRetry = (from, to) => retryTransient(() => fs6.renameSync(from, to));
10264
+ var renameWithRetry = (from, to) => retryTransient(() => fs7.renameSync(from, to));
10228
10265
 
10229
10266
  // packages/workit-core/src/store/patch.ts
10230
10267
  var isPlainObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
@@ -10337,7 +10374,7 @@ var isPatch = (value) => Array.isArray(value) && value.every((op) => {
10337
10374
  });
10338
10375
 
10339
10376
  // packages/workit-core/src/store/reduce.ts
10340
- import { createHash as createHash3 } from "node:crypto";
10377
+ import { createHash as createHash4 } from "node:crypto";
10341
10378
  var OPENING_TYPES = new Set([
10342
10379
  "task.opened",
10343
10380
  "task.imported",
@@ -10366,7 +10403,7 @@ var isObject4 = (value) => typeof value === "object" && value !== null && !Array
10366
10403
  var isKey = (value) => isObject4(value) && typeof value.key === "string" && (value.kind === "branch" || value.kind === "detached" || value.kind === "dir") && (value.branch === null || typeof value.branch === "string");
10367
10404
  var BLOB_REF = "$blob";
10368
10405
  var blobRef = (value) => isObject4(value) && Object.keys(value).length === 1 && typeof value[BLOB_REF] === "string" && /^[0-9a-f]{64}$/.test(value[BLOB_REF]) ? value[BLOB_REF] : null;
10369
- var blobDigest = (value) => createHash3("sha256").update(JSON.stringify(value)).digest("hex");
10406
+ var blobDigest = (value) => createHash4("sha256").update(JSON.stringify(value)).digest("hex");
10370
10407
  var toBlob = (value, blobs) => {
10371
10408
  if (!isObject4(value))
10372
10409
  return value;
@@ -10521,7 +10558,7 @@ var indexEntry = (task, key, legacy, file) => {
10521
10558
  };
10522
10559
  var fileSignature = (file) => {
10523
10560
  try {
10524
- const stat = fs7.statSync(file, { bigint: true });
10561
+ const stat = fs8.statSync(file, { bigint: true });
10525
10562
  return `${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeNs}:${stat.ctimeNs}`;
10526
10563
  } catch {
10527
10564
  return null;
@@ -10539,7 +10576,7 @@ var cachedRuntimeVersion = null;
10539
10576
  var runtimeVersion = () => {
10540
10577
  if (cachedRuntimeVersion === null) {
10541
10578
  try {
10542
- const pkg = JSON.parse(fs7.readFileSync(path6.join(packageRoot(), "package.json"), "utf8"));
10579
+ const pkg = JSON.parse(fs8.readFileSync(path7.join(packageRoot(), "package.json"), "utf8"));
10543
10580
  cachedRuntimeVersion = typeof pkg.version === "string" && pkg.version ? pkg.version : "0.0.0";
10544
10581
  } catch {
10545
10582
  cachedRuntimeVersion = "0.0.0";
@@ -10565,14 +10602,14 @@ var isNewerVersion = (candidate, current) => {
10565
10602
  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);
10566
10603
  var readText = (file) => {
10567
10604
  try {
10568
- return fs7.readFileSync(file, "utf8");
10605
+ return fs8.readFileSync(file, "utf8");
10569
10606
  } catch {
10570
10607
  return "";
10571
10608
  }
10572
10609
  };
10573
10610
  var REFLOG_LINE = /^[0-9a-f]+ ([0-9a-f]+) .* (\d+) [+-]\d{4}\t(.*)$/u;
10574
10611
  var branchStart = (location, branch, aliases) => {
10575
- const first = readText(path6.join(path6.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
10612
+ const first = readText(path7.join(path7.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
10576
10613
  `, 1)[0];
10577
10614
  const created = REFLOG_LINE.exec(first);
10578
10615
  const start = created && /^branch: Created from (\S+)$/u.exec(created[3])?.[1];
@@ -10582,7 +10619,7 @@ var branchStart = (location, branch, aliases) => {
10582
10619
  return start;
10583
10620
  if (!location.git)
10584
10621
  return null;
10585
- for (const line of readText(path6.join(location.git.gitDir, "logs", "HEAD")).split(`
10622
+ for (const line of readText(path7.join(location.git.gitDir, "logs", "HEAD")).split(`
10586
10623
  `)) {
10587
10624
  const entry = REFLOG_LINE.exec(line);
10588
10625
  const moved = entry && /^checkout: moving from (\S+) to (\S+)$/u.exec(entry[3]);
@@ -10592,23 +10629,23 @@ var branchStart = (location, branch, aliases) => {
10592
10629
  }
10593
10630
  return null;
10594
10631
  };
10595
- var refExists = (common, ref) => fs7.existsSync(path6.join(common, ref)) || readText(path6.join(common, "packed-refs")).includes(` ${ref}
10632
+ var refExists = (common, ref) => fs8.existsSync(path7.join(common, ref)) || readText(path7.join(common, "packed-refs")).includes(` ${ref}
10596
10633
  `);
10597
10634
  var origins = new Map;
10598
10635
  var sameDirectoryIdentity = (left, right) => {
10599
- if (!path6.isAbsolute(left) || !path6.isAbsolute(right))
10636
+ if (!path7.isAbsolute(left) || !path7.isAbsolute(right))
10600
10637
  return false;
10601
- const normalizedLeft = path6.resolve(left);
10602
- const normalizedRight = path6.resolve(right);
10638
+ const normalizedLeft = path7.resolve(left);
10639
+ const normalizedRight = path7.resolve(right);
10603
10640
  try {
10604
- const a = fs7.statSync(normalizedLeft, { bigint: true });
10605
- const b = fs7.statSync(normalizedRight, { bigint: true });
10641
+ const a = fs8.statSync(normalizedLeft, { bigint: true });
10642
+ const b = fs8.statSync(normalizedRight, { bigint: true });
10606
10643
  if (!a.isDirectory() || !b.isDirectory())
10607
10644
  return false;
10608
10645
  if (process.platform === "win32" ? normalizedLeft.toLowerCase() === normalizedRight.toLowerCase() : normalizedLeft === normalizedRight)
10609
10646
  return true;
10610
- const canonicalLeft = fs7.realpathSync(normalizedLeft);
10611
- const canonicalRight = fs7.realpathSync(normalizedRight);
10647
+ const canonicalLeft = fs8.realpathSync(normalizedLeft);
10648
+ const canonicalRight = fs8.realpathSync(normalizedRight);
10612
10649
  if (process.platform === "win32" ? canonicalLeft.toLowerCase() === canonicalRight.toLowerCase() : canonicalLeft === canonicalRight)
10613
10650
  return true;
10614
10651
  return a.dev === b.dev && a.ino !== 0n && a.ino === b.ino;
@@ -10645,8 +10682,8 @@ class TaskStore {
10645
10682
  migrationChecked = false;
10646
10683
  compactDue = new Set;
10647
10684
  constructor(root, options = {}) {
10648
- const resolved = path6.resolve(root);
10649
- this.origin = fs7.existsSync(resolved) ? fs7.realpathSync(resolved) : resolved;
10685
+ const resolved = path7.resolve(root);
10686
+ this.origin = fs8.existsSync(resolved) ? fs8.realpathSync(resolved) : resolved;
10650
10687
  this.located = resolveStore(this.origin);
10651
10688
  this.root = checkoutRootOf(this.origin, this.located);
10652
10689
  this.lockTimeoutMs = options.lockTimeoutMs ?? defaultLockTimeout();
@@ -10654,7 +10691,7 @@ class TaskStore {
10654
10691
  this.migrateOnRead = options.migrateOnRead;
10655
10692
  }
10656
10693
  location() {
10657
- if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs7.existsSync(path6.join(this.root, ".git"))) {
10694
+ if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs8.existsSync(path7.join(this.root, ".git"))) {
10658
10695
  this.located = undefined;
10659
10696
  this.migrationChecked = false;
10660
10697
  }
@@ -10718,7 +10755,7 @@ class TaskStore {
10718
10755
  const tasksDir = this.paths().tasks;
10719
10756
  let names;
10720
10757
  try {
10721
- names = fs7.existsSync(tasksDir) ? fs7.readdirSync(tasksDir).filter((name) => validId(name)) : [];
10758
+ names = fs8.existsSync(tasksDir) ? fs8.readdirSync(tasksDir).filter((name) => validId(name)) : [];
10722
10759
  } catch (error) {
10723
10760
  return failure2("storage_error", `unable to list tasks: ${String(error)}`, {
10724
10761
  path: tasksDir
@@ -10759,7 +10796,7 @@ class TaskStore {
10759
10796
  const file = this.paths().workspace;
10760
10797
  let bytes;
10761
10798
  try {
10762
- bytes = retryTransient(() => fs7.readFileSync(file, "utf8"));
10799
+ bytes = retryTransient(() => fs8.readFileSync(file, "utf8"));
10763
10800
  } catch (error) {
10764
10801
  if (error.code === "ENOENT")
10765
10802
  return success(null, null, null);
@@ -10810,7 +10847,7 @@ class TaskStore {
10810
10847
  const moved = this.bindLocked(again.data.id, key, input.now);
10811
10848
  return moved.ok ? success(moved.data.revision, null, { task: moved.data, created: false, key }) : moved;
10812
10849
  }
10813
- const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path6.basename(this.root) || this.root;
10850
+ const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path7.basename(this.root) || this.root;
10814
10851
  const intent = {
10815
10852
  objective: input.objective?.trim() || `Work on ${label}`,
10816
10853
  scope: { description: `the checkout (${label})`, paths: ["."], exclusions: [] },
@@ -10870,14 +10907,14 @@ class TaskStore {
10870
10907
  const branch = key.ok ? key.data.branch : null;
10871
10908
  if (!branch || !location.ok)
10872
10909
  return success(null, null, null);
10873
- const common = path6.dirname(location.data.dir);
10874
- const heads = path6.join(common, "logs", "refs", "heads");
10875
- const headLog = location.data.git ? path6.join(location.data.git.gitDir, "logs", "HEAD") : "";
10910
+ const common = path7.dirname(location.data.dir);
10911
+ const heads = path7.join(common, "logs", "refs", "heads");
10912
+ const headLog = location.data.git ? path7.join(location.data.git.gitDir, "logs", "HEAD") : "";
10876
10913
  const signatures = [
10877
- path6.join(heads, branch),
10914
+ path7.join(heads, branch),
10878
10915
  headLog,
10879
10916
  heads,
10880
- path6.join(common, "packed-refs")
10917
+ path7.join(common, "packed-refs")
10881
10918
  ].map((file) => fileSignature(file) ?? "-");
10882
10919
  const slot = `${location.data.dir}\x00${headLog}\x00${branch}`;
10883
10920
  let resolved = origins.get(slot);
@@ -10889,7 +10926,7 @@ class TaskStore {
10889
10926
  aliases.push(rename.from);
10890
10927
  const start = branchStart(location.data, branch, aliases);
10891
10928
  const slash = start?.indexOf("/") ?? -1;
10892
- const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(path6.join(common, "config")).includes(`[remote "${start.slice(0, slash)}"]`));
10929
+ const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(path7.join(common, "config")).includes(`[remote "${start.slice(0, slash)}"]`));
10893
10930
  const name = start && (remote ? start.slice(slash + 1) : start);
10894
10931
  resolved = {
10895
10932
  signature: signatures.join("|"),
@@ -11127,13 +11164,13 @@ class TaskStore {
11127
11164
  if (!ready.ok)
11128
11165
  return ready;
11129
11166
  const dirs = this.paths();
11130
- const recovery = path6.join(this.root, ".workit", "recovery");
11131
- if (fs7.existsSync(recovery)) {
11167
+ const recovery = path7.join(this.root, ".workit", "recovery");
11168
+ if (fs8.existsSync(recovery)) {
11132
11169
  let files = 0;
11133
11170
  let bytes = 0;
11134
11171
  try {
11135
- for (const name of fs7.readdirSync(recovery)) {
11136
- const stat = fs7.lstatSync(path6.join(recovery, name));
11172
+ for (const name of fs8.readdirSync(recovery)) {
11173
+ const stat = fs8.lstatSync(path7.join(recovery, name));
11137
11174
  if (!stat.isFile())
11138
11175
  continue;
11139
11176
  files += 1;
@@ -11142,17 +11179,17 @@ class TaskStore {
11142
11179
  } catch {}
11143
11180
  const remove = options.pruneRecovery === true && !dryRun;
11144
11181
  if (remove)
11145
- fs7.rmSync(recovery, { recursive: true, force: true });
11182
+ fs8.rmSync(recovery, { recursive: true, force: true });
11146
11183
  report.legacyRecovery = { path: recovery, files, bytes, removed: remove };
11147
11184
  }
11148
- if (!fs7.existsSync(dirs.tasks))
11185
+ if (!fs8.existsSync(dirs.tasks))
11149
11186
  return success(null, null, report);
11150
- const names = fs7.readdirSync(dirs.tasks).filter((name) => validId(name));
11187
+ const names = fs8.readdirSync(dirs.tasks).filter((name) => validId(name));
11151
11188
  for (const name of names) {
11152
11189
  const file = this.eventsPath(name);
11153
11190
  let size = 0;
11154
11191
  try {
11155
- size = fs7.statSync(file).size;
11192
+ size = fs8.statSync(file).size;
11156
11193
  } catch {
11157
11194
  continue;
11158
11195
  }
@@ -11180,16 +11217,16 @@ class TaskStore {
11180
11217
  const references = new Set;
11181
11218
  for (const name of names)
11182
11219
  try {
11183
- for (const match of fs7.readFileSync(this.eventsPath(name), "utf8").matchAll(/"\$blob":"([0-9a-f]{64})"/g))
11220
+ for (const match of fs8.readFileSync(this.eventsPath(name), "utf8").matchAll(/"\$blob":"([0-9a-f]{64})"/g))
11184
11221
  references.add(match[1]);
11185
11222
  } catch {}
11186
- if (fs7.existsSync(dirs.blobs))
11187
- for (const name of fs7.readdirSync(dirs.blobs)) {
11223
+ if (fs8.existsSync(dirs.blobs))
11224
+ for (const name of fs8.readdirSync(dirs.blobs)) {
11188
11225
  const digest = name.replace(/\.json$/, "");
11189
- const file = path6.join(dirs.blobs, name);
11226
+ const file = path7.join(dirs.blobs, name);
11190
11227
  let stat;
11191
11228
  try {
11192
- stat = fs7.lstatSync(file);
11229
+ stat = fs8.lstatSync(file);
11193
11230
  } catch {
11194
11231
  continue;
11195
11232
  }
@@ -11200,11 +11237,11 @@ class TaskStore {
11200
11237
  report.blobs.removed += 1;
11201
11238
  report.blobs.removedBytes += stat.size;
11202
11239
  if (!dryRun)
11203
- fs7.rmSync(file, { force: true });
11240
+ fs8.rmSync(file, { force: true });
11204
11241
  }
11205
11242
  return success(null, null, null);
11206
11243
  };
11207
- const swept = dryRun ? sweep() : this.withLock(path6.join(dirs.dir, "gc.lock"), sweep);
11244
+ const swept = dryRun ? sweep() : this.withLock(path7.join(dirs.dir, "gc.lock"), sweep);
11208
11245
  if (!swept.ok)
11209
11246
  return swept;
11210
11247
  const temporaryDirs = [
@@ -11212,17 +11249,17 @@ class TaskStore {
11212
11249
  dirs.tasks,
11213
11250
  dirs.blobs,
11214
11251
  dirs.checkout,
11215
- ...names.map((name) => path6.join(dirs.tasks, name))
11252
+ ...names.map((name) => path7.join(dirs.tasks, name))
11216
11253
  ];
11217
11254
  for (const directory of temporaryDirs) {
11218
- if (!fs7.existsSync(directory))
11255
+ if (!fs8.existsSync(directory))
11219
11256
  continue;
11220
- for (const name of fs7.readdirSync(directory)) {
11257
+ for (const name of fs8.readdirSync(directory)) {
11221
11258
  if (!name.endsWith(".tmp") && !name.endsWith(".probe"))
11222
11259
  continue;
11223
- const file = path6.join(directory, name);
11260
+ const file = path7.join(directory, name);
11224
11261
  try {
11225
- const stat = fs7.lstatSync(file);
11262
+ const stat = fs8.lstatSync(file);
11226
11263
  if (!stat.isFile() || nowMs - stat.mtimeMs <= STALE_TEMPORARY_MS)
11227
11264
  continue;
11228
11265
  } catch {
@@ -11230,37 +11267,37 @@ class TaskStore {
11230
11267
  }
11231
11268
  report.temporary.removed += 1;
11232
11269
  if (!dryRun)
11233
- fs7.rmSync(file, { force: true });
11270
+ fs8.rmSync(file, { force: true });
11234
11271
  }
11235
11272
  }
11236
11273
  return success(null, null, report);
11237
11274
  }
11238
11275
  paths() {
11239
11276
  const location = this.location();
11240
- const dir = location.ok ? location.data.dir : path6.join(this.root, ".workit");
11241
- const checkout = path6.join(dir, "checkouts", checkoutSlug(this.root));
11277
+ const dir = location.ok ? location.data.dir : path7.join(this.root, ".workit");
11278
+ const checkout = path7.join(dir, "checkouts", checkoutSlug(this.root));
11242
11279
  return {
11243
11280
  dir,
11244
11281
  shared: location.ok ? location.data.shared : false,
11245
- marker: path6.join(dir, "store.json"),
11282
+ marker: path7.join(dir, "store.json"),
11246
11283
  checkout,
11247
- workspace: path6.join(checkout, "workspace.json"),
11248
- checkoutLock: path6.join(checkout, "metadata.lock"),
11249
- tasks: path6.join(dir, "tasks"),
11250
- index: path6.join(dir, "task-index.json"),
11251
- blobs: path6.join(dir, "blobs", "candidates"),
11252
- legacy: path6.join(dir, "legacy", checkoutSlug(this.root), "v2"),
11253
- v2: path6.join(this.root, ".workit")
11284
+ workspace: path7.join(checkout, "workspace.json"),
11285
+ checkoutLock: path7.join(checkout, "metadata.lock"),
11286
+ tasks: path7.join(dir, "tasks"),
11287
+ index: path7.join(dir, "task-index.json"),
11288
+ blobs: path7.join(dir, "blobs", "candidates"),
11289
+ legacy: path7.join(dir, "legacy", checkoutSlug(this.root), "v2"),
11290
+ v2: path7.join(this.root, ".workit")
11254
11291
  };
11255
11292
  }
11256
11293
  eventsPath(taskId) {
11257
- return path6.join(this.paths().tasks, taskId, "events.jsonl");
11294
+ return path7.join(this.paths().tasks, taskId, "events.jsonl");
11258
11295
  }
11259
11296
  snapshotPath(taskId) {
11260
- return path6.join(this.paths().tasks, taskId, "snapshot.json");
11297
+ return path7.join(this.paths().tasks, taskId, "snapshot.json");
11261
11298
  }
11262
11299
  taskLockPath(taskId) {
11263
- return path6.join(this.paths().tasks, taskId, "lock");
11300
+ return path7.join(this.paths().tasks, taskId, "lock");
11264
11301
  }
11265
11302
  ready(write = false) {
11266
11303
  const location = this.location();
@@ -11270,7 +11307,7 @@ class TaskStore {
11270
11307
  return success(null, null, null);
11271
11308
  const dirs = this.paths();
11272
11309
  try {
11273
- const marker = JSON.parse(fs7.readFileSync(dirs.marker, "utf8"));
11310
+ const marker = JSON.parse(fs8.readFileSync(dirs.marker, "utf8"));
11274
11311
  if (typeof marker.version === "number" && marker.version > STORE_FORMAT)
11275
11312
  return failure2("recovery_required", `the workit store at ${dirs.dir} has format ${marker.version}; upgrade Workit to use it`, { path: dirs.marker });
11276
11313
  } catch {}
@@ -11299,21 +11336,21 @@ class TaskStore {
11299
11336
  return {
11300
11337
  read: (digest) => {
11301
11338
  try {
11302
- return JSON.parse(fs7.readFileSync(path6.join(dir, `${digest}.json`), "utf8"));
11339
+ return JSON.parse(fs8.readFileSync(path7.join(dir, `${digest}.json`), "utf8"));
11303
11340
  } catch (error) {
11304
11341
  throw new LogDamage(`stored candidate ${digest} is missing or unreadable: ${String(error)}`);
11305
11342
  }
11306
11343
  },
11307
11344
  write: (digest, value) => {
11308
- const file = path6.join(dir, `${digest}.json`);
11309
- if (fs7.existsSync(file)) {
11345
+ const file = path7.join(dir, `${digest}.json`);
11346
+ if (fs8.existsSync(file)) {
11310
11347
  const stamp = new Date;
11311
11348
  try {
11312
- fs7.utimesSync(file, stamp, stamp);
11349
+ fs8.utimesSync(file, stamp, stamp);
11313
11350
  return;
11314
11351
  } catch {}
11315
11352
  }
11316
- fs7.mkdirSync(dir, { recursive: true });
11353
+ fs8.mkdirSync(dir, { recursive: true });
11317
11354
  replaceFile(file, JSON.stringify(value), true);
11318
11355
  }
11319
11356
  };
@@ -11395,7 +11432,7 @@ class TaskStore {
11395
11432
  }
11396
11433
  readSnapshot(taskId) {
11397
11434
  try {
11398
- const value = JSON.parse(fs7.readFileSync(this.snapshotPath(taskId), "utf8"));
11435
+ const value = JSON.parse(fs8.readFileSync(this.snapshotPath(taskId), "utf8"));
11399
11436
  if (!isObject5(value) || value.v !== 1 || value.task !== taskId || typeof value.seq !== "number" || typeof value.lastId !== "string" || typeof value.lastStart !== "number" || typeof value.end !== "number" || !isObject5(value.record))
11400
11437
  return null;
11401
11438
  return value;
@@ -11497,8 +11534,8 @@ class TaskStore {
11497
11534
  }
11498
11535
  }
11499
11536
  openTask(record, type, key, legacy = null) {
11500
- const dir = path6.join(this.paths().tasks, record.id);
11501
- fs7.mkdirSync(dir, { recursive: true });
11537
+ const dir = path7.join(this.paths().tasks, record.id);
11538
+ fs8.mkdirSync(dir, { recursive: true });
11502
11539
  const blobs = this.blobStore();
11503
11540
  const bound = key ? { ...key, boundAt: key.boundAt ?? new Date().toISOString() } : null;
11504
11541
  const event = this.event(record.id, 1, type, {
@@ -11550,11 +11587,11 @@ class TaskStore {
11550
11587
  } catch {}
11551
11588
  if (!latest || latest.events[0]?.id !== last.id)
11552
11589
  return failure2("busy", "the task log changed during compaction; retry", { taskId });
11553
- const appended = fs7.readFileSync(file).subarray(log.end, latest.end);
11590
+ const appended = fs8.readFileSync(file).subarray(log.end, latest.end);
11554
11591
  const bytes = Buffer.concat([Buffer.from(prefix, "utf8"), appended]);
11555
11592
  replaceFile(file, bytes.toString("utf8"), true);
11556
11593
  try {
11557
- fs7.rmSync(this.snapshotPath(taskId), { force: true });
11594
+ fs8.rmSync(this.snapshotPath(taskId), { force: true });
11558
11595
  } catch {}
11559
11596
  const reloaded = this.load(taskId);
11560
11597
  if (reloaded.ok && reloaded.data)
@@ -11567,7 +11604,7 @@ class TaskStore {
11567
11604
  }
11568
11605
  countEvents(file) {
11569
11606
  try {
11570
- const bytes = fs7.readFileSync(file);
11607
+ const bytes = fs8.readFileSync(file);
11571
11608
  let count = 0;
11572
11609
  for (let index = bytes.indexOf(10);index >= 0; index = bytes.indexOf(10, index + 1))
11573
11610
  count += 1;
@@ -11589,8 +11626,8 @@ class TaskStore {
11589
11626
  return bound.ok ? success(null, null, bound.data[0] ?? null) : bound;
11590
11627
  }
11591
11628
  withKeyLock(key, operation) {
11592
- const digest = createHash4("sha256").update(key).digest("hex").slice(0, 32);
11593
- return this.withLock(path6.join(this.paths().dir, "keys", `${digest}.lock`), operation);
11629
+ const digest = createHash5("sha256").update(key).digest("hex").slice(0, 32);
11630
+ return this.withLock(path7.join(this.paths().dir, "keys", `${digest}.lock`), operation);
11594
11631
  }
11595
11632
  bindLocked(taskId, key, timestamp) {
11596
11633
  const current = this.readWorkspace();
@@ -11731,7 +11768,7 @@ class TaskStore {
11731
11768
  writeWorkspace(record) {
11732
11769
  const file = this.paths().workspace;
11733
11770
  try {
11734
- fs7.mkdirSync(path6.dirname(file), { recursive: true });
11771
+ fs8.mkdirSync(path7.dirname(file), { recursive: true });
11735
11772
  replaceFile(file, `${canonicalJson(record)}
11736
11773
  `, true);
11737
11774
  return success(null, null, null);
@@ -11741,7 +11778,7 @@ class TaskStore {
11741
11778
  }
11742
11779
  readIndex() {
11743
11780
  try {
11744
- const value = JSON.parse(fs7.readFileSync(this.paths().index, "utf8"));
11781
+ const value = JSON.parse(fs8.readFileSync(this.paths().index, "utf8"));
11745
11782
  if (!isObject5(value) || value.version !== INDEX_VERSION || !isObject5(value.tasks))
11746
11783
  return {};
11747
11784
  const tasks = {};
@@ -11755,7 +11792,7 @@ class TaskStore {
11755
11792
  }
11756
11793
  writeIndex(entries) {
11757
11794
  try {
11758
- fs7.mkdirSync(this.paths().tasks, { recursive: true });
11795
+ fs8.mkdirSync(this.paths().tasks, { recursive: true });
11759
11796
  replaceFile(this.paths().index, JSON.stringify({
11760
11797
  version: INDEX_VERSION,
11761
11798
  tasks: Object.fromEntries(entries.map((entry) => [entry.id, entry]))
@@ -11809,23 +11846,23 @@ class TaskStore {
11809
11846
  return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", { expectedWorkspaceRevision: expected, actualWorkspaceRevision: actual });
11810
11847
  }
11811
11848
  v2Dirs() {
11812
- return [...new Set([this.root, this.origin])].map((dir) => path6.join(dir, ".workit"));
11849
+ return [...new Set([this.root, this.origin])].map((dir) => path7.join(dir, ".workit"));
11813
11850
  }
11814
11851
  pendingMigrations() {
11815
11852
  return this.v2Dirs().filter((dir) => {
11816
- const raw = this.readV2Workspace(path6.join(dir, "workspace.json"));
11853
+ const raw = this.readV2Workspace(path7.join(dir, "workspace.json"));
11817
11854
  return raw !== null && raw !== TOMBSTONE;
11818
11855
  });
11819
11856
  }
11820
11857
  migrateV2(v2) {
11821
11858
  const dirs = this.paths();
11822
- const v2Workspace = path6.join(v2, "workspace.json");
11823
- const v2Tasks = path6.join(v2, "tasks");
11824
- const legacy = path6.join(dirs.dir, "legacy", checkoutSlug(path6.dirname(v2)), "v2");
11859
+ const v2Workspace = path7.join(v2, "workspace.json");
11860
+ const v2Tasks = path7.join(v2, "tasks");
11861
+ const legacy = path7.join(dirs.dir, "legacy", checkoutSlug(path7.dirname(v2)), "v2");
11825
11862
  const raw = this.readV2Workspace(v2Workspace);
11826
11863
  if (raw === null || raw === TOMBSTONE)
11827
11864
  return success(null, null, null);
11828
- return this.withLock(dirs.checkoutLock, () => this.withLock(path6.join(v2, "metadata.lock"), () => {
11865
+ return this.withLock(dirs.checkoutLock, () => this.withLock(path7.join(v2, "metadata.lock"), () => {
11829
11866
  const workspace = this.readV2Workspace(v2Workspace);
11830
11867
  if (workspace === null || workspace === TOMBSTONE)
11831
11868
  return success(null, null, null);
@@ -11834,7 +11871,7 @@ class TaskStore {
11834
11871
  return failure2("recovery_required", `cannot migrate the 2.x store at ${v2}: ${parsedWorkspace.error}; move it aside to start fresh`, { path: v2Workspace });
11835
11872
  let files = [];
11836
11873
  try {
11837
- files = fs7.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path6.join(v2Tasks, name)));
11874
+ files = fs8.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path7.join(v2Tasks, name)));
11838
11875
  } catch {}
11839
11876
  const current = this.readWorkspace();
11840
11877
  if (!current.ok)
@@ -11852,22 +11889,22 @@ class TaskStore {
11852
11889
  let skipped = 0;
11853
11890
  const done = new Map;
11854
11891
  try {
11855
- fs7.mkdirSync(path6.join(legacy, "tasks"), { recursive: true });
11892
+ fs8.mkdirSync(path7.join(legacy, "tasks"), { recursive: true });
11856
11893
  for (const name of ["workspace.json", "index.json"])
11857
- if (fs7.existsSync(path6.join(v2, name)))
11858
- fs7.copyFileSync(path6.join(v2, name), path6.join(legacy, name));
11894
+ if (fs8.existsSync(path7.join(v2, name)))
11895
+ fs8.copyFileSync(path7.join(v2, name), path7.join(legacy, name));
11859
11896
  for (const name of files) {
11860
11897
  const id = name.slice(0, -5);
11861
- const file = path6.join(v2Tasks, name);
11862
- const bytes = fs7.readFileSync(file, "utf8");
11898
+ const file = path7.join(v2Tasks, name);
11899
+ const bytes = fs8.readFileSync(file, "utf8");
11863
11900
  const digest = sha256(bytes);
11864
- fs7.writeFileSync(path6.join(legacy, "tasks", name), bytes);
11901
+ fs8.writeFileSync(path7.join(legacy, "tasks", name), bytes);
11865
11902
  const parsed = this.parseRecord(bytes, taskRecordSchema, "2.x task");
11866
11903
  if (!parsed.ok || parsed.data.id !== id)
11867
11904
  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 });
11868
11905
  const record = { ...parsed.data, workspaceId: target.id };
11869
- const origin = { path: path6.join(legacy, "tasks", name), digest };
11870
- if (!fs7.existsSync(this.eventsPath(id))) {
11906
+ const origin = { path: path7.join(legacy, "tasks", name), digest };
11907
+ if (!fs8.existsSync(this.eventsPath(id))) {
11871
11908
  this.openTask(record, "migrated.from_v2", null, origin);
11872
11909
  migrated += 1;
11873
11910
  } else {
@@ -11902,8 +11939,8 @@ class TaskStore {
11902
11939
  try {
11903
11940
  let complete = true;
11904
11941
  for (const [name, digest] of done) {
11905
- const file = path6.join(v2Tasks, name);
11906
- if (sha256(fs7.readFileSync(file, "utf8")) !== digest) {
11942
+ const file = path7.join(v2Tasks, name);
11943
+ if (sha256(fs8.readFileSync(file, "utf8")) !== digest) {
11907
11944
  complete = false;
11908
11945
  continue;
11909
11946
  }
@@ -11913,7 +11950,7 @@ class TaskStore {
11913
11950
  return failure2("busy", `the 2.x store at ${v2} changed during migration; retry`, {
11914
11951
  path: v2
11915
11952
  });
11916
- fs7.rmSync(path6.join(v2, "index.json"), { force: true });
11953
+ fs8.rmSync(path7.join(v2, "index.json"), { force: true });
11917
11954
  this.writeTombstone(v2, target.id);
11918
11955
  } catch (error) {
11919
11956
  return failure2("storage_error", `cannot finish the 2.x migration: ${String(error)}`, {
@@ -11933,45 +11970,45 @@ class TaskStore {
11933
11970
  }
11934
11971
  adoptLocalStore() {
11935
11972
  const dirs = this.paths();
11936
- const marker = path6.join(dirs.v2, "store.json");
11937
- if (!dirs.shared || !fs7.existsSync(marker))
11973
+ const marker = path7.join(dirs.v2, "store.json");
11974
+ if (!dirs.shared || !fs8.existsSync(marker))
11938
11975
  return success(null, null, null);
11939
11976
  return this.withLock(dirs.checkoutLock, () => {
11940
- if (!fs7.existsSync(marker))
11977
+ if (!fs8.existsSync(marker))
11941
11978
  return success(null, null, null);
11942
11979
  let tasks = 0;
11943
11980
  try {
11944
11981
  const merge = (from, to) => {
11945
- if (!fs7.existsSync(to)) {
11946
- fs7.mkdirSync(path6.dirname(to), { recursive: true });
11982
+ if (!fs8.existsSync(to)) {
11983
+ fs8.mkdirSync(path7.dirname(to), { recursive: true });
11947
11984
  try {
11948
- fs7.renameSync(from, to);
11985
+ fs8.renameSync(from, to);
11949
11986
  } catch {
11950
- fs7.cpSync(from, to, { recursive: true, errorOnExist: true, force: false });
11951
- fs7.rmSync(from, { recursive: true, force: true });
11987
+ fs8.cpSync(from, to, { recursive: true, errorOnExist: true, force: false });
11988
+ fs8.rmSync(from, { recursive: true, force: true });
11952
11989
  }
11953
11990
  return;
11954
11991
  }
11955
- if (fs7.lstatSync(from).isDirectory() && fs7.lstatSync(to).isDirectory())
11956
- for (const name of fs7.readdirSync(from))
11957
- merge(path6.join(from, name), path6.join(to, name));
11992
+ if (fs8.lstatSync(from).isDirectory() && fs8.lstatSync(to).isDirectory())
11993
+ for (const name of fs8.readdirSync(from))
11994
+ merge(path7.join(from, name), path7.join(to, name));
11958
11995
  };
11959
11996
  for (const sub of ["tasks", "checkouts", "blobs", "legacy"]) {
11960
- const from = path6.join(dirs.v2, sub);
11961
- if (!fs7.existsSync(from))
11997
+ const from = path7.join(dirs.v2, sub);
11998
+ if (!fs8.existsSync(from))
11962
11999
  continue;
11963
12000
  if (sub === "tasks") {
11964
- for (const name of fs7.readdirSync(from))
11965
- if (validId(name) && !fs7.existsSync(path6.join(dirs.dir, sub, name)))
12001
+ for (const name of fs8.readdirSync(from))
12002
+ if (validId(name) && !fs8.existsSync(path7.join(dirs.dir, sub, name)))
11966
12003
  tasks += 1;
11967
12004
  }
11968
- merge(from, path6.join(dirs.dir, sub));
12005
+ merge(from, path7.join(dirs.dir, sub));
11969
12006
  }
11970
- const ledger = path6.join(dirs.v2, "ledger");
11971
- if (fs7.existsSync(ledger) && !fs7.existsSync(path6.join(dirs.dir, "ledger")))
11972
- merge(ledger, path6.join(dirs.dir, "ledger"));
11973
- fs7.rmSync(path6.join(dirs.v2, "task-index.json"), { force: true });
11974
- fs7.renameSync(marker, path6.join(dirs.v2, "store.moved.json"));
12007
+ const ledger = path7.join(dirs.v2, "ledger");
12008
+ if (fs8.existsSync(ledger) && !fs8.existsSync(path7.join(dirs.dir, "ledger")))
12009
+ merge(ledger, path7.join(dirs.dir, "ledger"));
12010
+ fs8.rmSync(path7.join(dirs.v2, "task-index.json"), { force: true });
12011
+ fs8.renameSync(marker, path7.join(dirs.v2, "store.moved.json"));
11975
12012
  } catch (error) {
11976
12013
  return failure2("storage_error", `cannot move ${dirs.v2} into ${dirs.dir}: ${String(error)}`, {
11977
12014
  path: dirs.v2
@@ -11991,7 +12028,7 @@ class TaskStore {
11991
12028
  readV2Workspace(file) {
11992
12029
  let bytes;
11993
12030
  try {
11994
- bytes = fs7.readFileSync(file, "utf8");
12031
+ bytes = fs8.readFileSync(file, "utf8");
11995
12032
  } catch {
11996
12033
  return null;
11997
12034
  }
@@ -12009,7 +12046,7 @@ class TaskStore {
12009
12046
  schemaVersion: SCHEMA_VERSION,
12010
12047
  id: workspaceId ?? newId(),
12011
12048
  revision: newRevision(),
12012
- root: path6.dirname(v2),
12049
+ root: path7.dirname(v2),
12013
12050
  runtime: { createdWith: version, updatedWith: version },
12014
12051
  writer: null,
12015
12052
  store: {
@@ -12020,12 +12057,12 @@ class TaskStore {
12020
12057
  },
12021
12058
  critical: ["store"]
12022
12059
  };
12023
- fs7.mkdirSync(v2, { recursive: true });
12024
- const ignore = path6.join(v2, ".gitignore");
12025
- if (!fs7.existsSync(ignore))
12026
- fs7.writeFileSync(ignore, `*
12060
+ fs8.mkdirSync(v2, { recursive: true });
12061
+ const ignore = path7.join(v2, ".gitignore");
12062
+ if (!fs8.existsSync(ignore))
12063
+ fs8.writeFileSync(ignore, `*
12027
12064
  `);
12028
- replaceFile(path6.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
12065
+ replaceFile(path7.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
12029
12066
  `, true);
12030
12067
  }
12031
12068
  stubFor(taskId) {
@@ -12041,7 +12078,7 @@ class TaskStore {
12041
12078
  }
12042
12079
  isStub(file) {
12043
12080
  try {
12044
- const value = JSON.parse(fs7.readFileSync(file, "utf8"));
12081
+ const value = JSON.parse(fs8.readFileSync(file, "utf8"));
12045
12082
  return isObject5(value) && isObject5(value.store) && value.store.format === "workit-store";
12046
12083
  } catch {
12047
12084
  return false;
@@ -12049,32 +12086,32 @@ class TaskStore {
12049
12086
  }
12050
12087
  writeTombstoneIfMissing() {
12051
12088
  try {
12052
- const v2 = path6.join(this.root, ".workit");
12053
- if (fs7.existsSync(path6.join(v2, "workspace.json")))
12089
+ const v2 = path7.join(this.root, ".workit");
12090
+ if (fs8.existsSync(path7.join(v2, "workspace.json")))
12054
12091
  return;
12055
12092
  let id = null;
12056
12093
  try {
12057
- id = JSON.parse(fs7.readFileSync(this.paths().workspace, "utf8")).id ?? null;
12094
+ id = JSON.parse(fs8.readFileSync(this.paths().workspace, "utf8")).id ?? null;
12058
12095
  } catch {}
12059
12096
  this.writeTombstone(v2, id);
12060
12097
  } catch {}
12061
12098
  }
12062
12099
  initializeStorage() {
12063
12100
  const dirs = this.paths();
12064
- retryTransient(() => fs7.mkdirSync(dirs.checkout, { recursive: true }));
12065
- retryTransient(() => fs7.mkdirSync(dirs.tasks, { recursive: true }));
12066
- if (!fs7.existsSync(dirs.marker))
12101
+ retryTransient(() => fs8.mkdirSync(dirs.checkout, { recursive: true }));
12102
+ retryTransient(() => fs8.mkdirSync(dirs.tasks, { recursive: true }));
12103
+ if (!fs8.existsSync(dirs.marker))
12067
12104
  replaceFile(dirs.marker, `${JSON.stringify({ format: "workit-store", version: STORE_FORMAT, createdWith: runtimeVersion() })}
12068
12105
  `, false);
12069
12106
  if (!dirs.shared) {
12070
- const ignore = path6.join(dirs.dir, ".gitignore");
12107
+ const ignore = path7.join(dirs.dir, ".gitignore");
12071
12108
  let current = null;
12072
12109
  try {
12073
- current = fs7.readFileSync(ignore, "utf8");
12110
+ current = fs8.readFileSync(ignore, "utf8");
12074
12111
  } catch {}
12075
12112
  if (current !== `*
12076
12113
  `)
12077
- retryTransient(() => fs7.writeFileSync(ignore, `*
12114
+ retryTransient(() => fs8.writeFileSync(ignore, `*
12078
12115
  `));
12079
12116
  }
12080
12117
  this.writeTombstoneIfMissing();
@@ -12090,7 +12127,7 @@ class TaskStore {
12090
12127
  shouldReclaim: ({ payload, nowMs }) => {
12091
12128
  let ageMs = null;
12092
12129
  try {
12093
- ageMs = nowMs - fs7.lstatSync(lockPath).mtimeMs;
12130
+ ageMs = nowMs - fs8.lstatSync(lockPath).mtimeMs;
12094
12131
  } catch {}
12095
12132
  return classifyLockOwner(payload, ageMs, localLockHost(), TASK_STORE_LOCK).state === "stale";
12096
12133
  },
@@ -12127,7 +12164,7 @@ class TaskStore {
12127
12164
  withLock(lockPath, operation) {
12128
12165
  try {
12129
12166
  this.initializeStorage();
12130
- fs7.mkdirSync(path6.dirname(lockPath), { recursive: true });
12167
+ fs8.mkdirSync(path7.dirname(lockPath), { recursive: true });
12131
12168
  } catch (error) {
12132
12169
  return failure2("storage_error", `unable to initialize store: ${String(error)}`, {
12133
12170
  path: this.paths().dir
@@ -12167,18 +12204,18 @@ class TaskStore {
12167
12204
  lockDirWritable(lockPath) {
12168
12205
  const probe = `${lockPath}.${process.pid}.${randomUUID3()}.probe`;
12169
12206
  try {
12170
- fs7.closeSync(fs7.openSync(probe, "wx", 384));
12207
+ fs8.closeSync(fs8.openSync(probe, "wx", 384));
12171
12208
  } catch {
12172
12209
  return false;
12173
12210
  }
12174
12211
  try {
12175
- fs7.rmSync(probe, { force: true });
12212
+ fs8.rmSync(probe, { force: true });
12176
12213
  } catch {}
12177
12214
  return true;
12178
12215
  }
12179
12216
  lockHolderPresent(lockPath) {
12180
12217
  try {
12181
- fs7.lstatSync(lockPath);
12218
+ fs8.lstatSync(lockPath);
12182
12219
  return true;
12183
12220
  } catch (error) {
12184
12221
  return error?.code !== "ENOENT";
@@ -12190,12 +12227,12 @@ class TaskStore {
12190
12227
  if (isTransientWindowsError(error) && !this.lockHolderPresent(lockPath) && !this.lockDirWritable(lockPath))
12191
12228
  return failure2("storage_error", `cannot create the workit lock (${code}); no other Workit call holds it`, {
12192
12229
  path: lockPath,
12193
- guidance: `Check permissions and the read-only attribute on ${path6.dirname(lockPath)}.`
12230
+ guidance: `Check permissions and the read-only attribute on ${path7.dirname(lockPath)}.`
12194
12231
  });
12195
12232
  if (code === "EEXIST" || code === "file_lock_timeout" || code === "file_lock_stale" || isTransientWindowsError(error)) {
12196
12233
  let lock = null;
12197
12234
  try {
12198
- lock = parseMetadataLockOrNull(fs7.readFileSync(lockPath, "utf8"));
12235
+ lock = parseMetadataLockOrNull(fs8.readFileSync(lockPath, "utf8"));
12199
12236
  } catch {}
12200
12237
  return failure2("busy", `workit lock is held by another Workit call${lock ? ` (pid ${lock.pid} on ${lock.host})` : ""}; retry shortly`, {
12201
12238
  outcome: "not_started",
@@ -12213,15 +12250,15 @@ var isUncertainWorker = (state) => UNCERTAIN_WORKER_STATES.includes(state);
12213
12250
  var workerBlocksTransition = (transition, state) => transition === "pause" ? false : isUncertainWorker(state);
12214
12251
 
12215
12252
  // packages/workit-core/src/core/task-evaluation.ts
12216
- import { createHash as createHash9 } from "node:crypto";
12217
- import * as fs12 from "node:fs";
12253
+ import { createHash as createHash10 } from "node:crypto";
12254
+ import * as fs13 from "node:fs";
12218
12255
  import { spawnSync as spawnSync10 } from "node:child_process";
12219
- import path14 from "node:path";
12256
+ import path15 from "node:path";
12220
12257
 
12221
12258
  // packages/workit-core/src/check-config.ts
12222
12259
  import { spawnSync as spawnSync3 } from "node:child_process";
12223
- import fs8 from "node:fs";
12224
- import path7 from "node:path";
12260
+ import fs9 from "node:fs";
12261
+ import path8 from "node:path";
12225
12262
  var SCRIPT_CHECKS = ["test", "lint", "typecheck", "check"];
12226
12263
  var CHECKS_FILE = "workit.checks.json";
12227
12264
  var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
@@ -12274,10 +12311,10 @@ var git = (cwd, args) => {
12274
12311
  return value || null;
12275
12312
  };
12276
12313
  function checkRoot(cwd) {
12277
- return path7.resolve(git(cwd, ["rev-parse", "--show-toplevel"]) ?? cwd);
12314
+ return path8.resolve(git(cwd, ["rev-parse", "--show-toplevel"]) ?? cwd);
12278
12315
  }
12279
12316
  var packageManager = (root) => {
12280
- const has = (file) => fs8.existsSync(path7.join(root, file));
12317
+ const has = (file) => fs9.existsSync(path8.join(root, file));
12281
12318
  if (has("bun.lock") || has("bun.lockb"))
12282
12319
  return "bun";
12283
12320
  if (has("pnpm-lock.yaml"))
@@ -12297,7 +12334,7 @@ var CHECK_NAME = /^[a-z0-9][a-z0-9:._-]{0,63}$/u;
12297
12334
  function detectedChecks(root) {
12298
12335
  const read = (file) => {
12299
12336
  try {
12300
- return fs8.readFileSync(path7.join(root, file), "utf8");
12337
+ return fs9.readFileSync(path8.join(root, file), "utf8");
12301
12338
  } catch {
12302
12339
  return null;
12303
12340
  }
@@ -12336,7 +12373,7 @@ function detectedChecks(root) {
12336
12373
  var GATES = ["testing", "verification"];
12337
12374
  function loadCheckConfig(cwd) {
12338
12375
  const root = checkRoot(cwd);
12339
- const file = path7.join(root, CHECKS_FILE);
12376
+ const file = path8.join(root, CHECKS_FILE);
12340
12377
  const none = (error = null) => ({
12341
12378
  source: error ? CHECKS_FILE : "none",
12342
12379
  root,
@@ -12346,7 +12383,7 @@ function loadCheckConfig(cwd) {
12346
12383
  });
12347
12384
  let text = null;
12348
12385
  try {
12349
- text = fs8.readFileSync(file, "utf8");
12386
+ text = fs9.readFileSync(file, "utf8");
12350
12387
  } catch (error) {
12351
12388
  if (error.code !== "ENOENT")
12352
12389
  return none(`cannot read ${CHECKS_FILE}: ${error.message}`);
@@ -12409,10 +12446,10 @@ function workitAvailable(env = process.env) {
12409
12446
  return workitOnPath;
12410
12447
  const windows = process.platform === "win32";
12411
12448
  const exts = windows ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
12412
- const dirs = (env.PATH ?? env.Path ?? "").split(path7.delimiter).filter(Boolean);
12449
+ const dirs = (env.PATH ?? env.Path ?? "").split(path8.delimiter).filter(Boolean);
12413
12450
  workitOnPath = dirs.some((dir) => exts.some((ext) => {
12414
12451
  try {
12415
- return fs8.statSync(path7.join(dir, `workit${ext}`)).isFile();
12452
+ return fs9.statSync(path8.join(dir, `workit${ext}`)).isFile();
12416
12453
  } catch {
12417
12454
  return false;
12418
12455
  }
@@ -12425,10 +12462,10 @@ function checkCommand(args, version, onPath = workitAvailable()) {
12425
12462
 
12426
12463
  // packages/workit-core/src/git/rev.ts
12427
12464
  import { spawnSync as spawnSync4 } from "node:child_process";
12428
- import { createHash as createHash5 } from "node:crypto";
12429
- import fs9 from "node:fs";
12465
+ import { createHash as createHash6 } from "node:crypto";
12466
+ import fs10 from "node:fs";
12430
12467
  import os from "node:os";
12431
- import path8 from "node:path";
12468
+ import path9 from "node:path";
12432
12469
  var MAX_BUFFER = 256 * 1024 * 1024;
12433
12470
  var GIT_TIMEOUTS = { local: 20000, worktree: 120000, network: 15000 };
12434
12471
  var git2 = (cwd, args, options = {}) => {
@@ -12463,10 +12500,10 @@ function headSha(cwd) {
12463
12500
  var emptyTree = (cwd) => line(git2(cwd, ["mktree"], { input: "" }));
12464
12501
  var MAX_UNTRACKED_BYTES = 5 * 1024 * 1024;
12465
12502
  var seedIndex = (from, to) => {
12466
- fs9.copyFileSync(from, to);
12467
- const { atimeNs, mtimeNs } = fs9.statSync(from, { bigint: true });
12503
+ fs10.copyFileSync(from, to);
12504
+ const { atimeNs, mtimeNs } = fs10.statSync(from, { bigint: true });
12468
12505
  const seconds = (ns) => (Number(ns / 1000n) - 1) / 1e6;
12469
- fs9.utimesSync(to, seconds(atimeNs), seconds(mtimeNs));
12506
+ fs10.utimesSync(to, seconds(atimeNs), seconds(mtimeNs));
12470
12507
  };
12471
12508
  function worktreeTree(cwd, options = {}) {
12472
12509
  const top = line(git2(cwd, ["rev-parse", "--show-toplevel"]));
@@ -12475,10 +12512,10 @@ function worktreeTree(cwd, options = {}) {
12475
12512
  return null;
12476
12513
  const cap = options.maxUntrackedBytes ?? MAX_UNTRACKED_BYTES;
12477
12514
  const timeoutMs = options.timeoutMs ?? GIT_TIMEOUTS.worktree;
12478
- const scratch = fs9.mkdtempSync(path8.join(os.tmpdir(), "workit-tree-"));
12515
+ const scratch = fs10.mkdtempSync(path9.join(os.tmpdir(), "workit-tree-"));
12479
12516
  try {
12480
- const tempIndex = path8.join(scratch, "index");
12481
- if (fs9.existsSync(indexPath))
12517
+ const tempIndex = path9.join(scratch, "index");
12518
+ if (fs10.existsSync(indexPath))
12482
12519
  seedIndex(indexPath, tempIndex);
12483
12520
  const env = { ...process.env, GIT_INDEX_FILE: tempIndex };
12484
12521
  const untracked = git2(top, ["ls-files", "--others", "--exclude-standard", "-z"], {
@@ -12490,7 +12527,7 @@ function worktreeTree(cwd, options = {}) {
12490
12527
  const skipped = [];
12491
12528
  for (const file of untracked.stdout.split("\x00").filter(Boolean)) {
12492
12529
  try {
12493
- const stat = fs9.statSync(path8.join(top, file));
12530
+ const stat = fs10.statSync(path9.join(top, file));
12494
12531
  if (stat.isFile() && stat.size > cap)
12495
12532
  skipped.push({ path: file, size: stat.size, mtimeMs: Math.trunc(stat.mtimeMs) });
12496
12533
  } catch {}
@@ -12507,10 +12544,10 @@ function worktreeTree(cwd, options = {}) {
12507
12544
  if (!tree)
12508
12545
  return null;
12509
12546
  const base = line(git2(top, ["rev-parse", "--verify", "-q", "HEAD^{tree}"])) ?? emptyTree(top);
12510
- const key = skipped.length ? `sha256:${createHash5("sha256").update(JSON.stringify({ tree, skipped })).digest("hex")}` : tree;
12547
+ const key = skipped.length ? `sha256:${createHash6("sha256").update(JSON.stringify({ tree, skipped })).digest("hex")}` : tree;
12511
12548
  return { tree, key, dirty: tree !== base || skipped.length > 0, skipped };
12512
12549
  } finally {
12513
- fs9.rmSync(scratch, { recursive: true, force: true });
12550
+ fs10.rmSync(scratch, { recursive: true, force: true });
12514
12551
  }
12515
12552
  }
12516
12553
  function worktreeSignal(cwd, options = {}) {
@@ -12530,16 +12567,16 @@ function worktreeSignal(cwd, options = {}) {
12530
12567
  });
12531
12568
  if (!status.ok)
12532
12569
  return null;
12533
- const hash = createHash5("sha256");
12570
+ const hash = createHash6("sha256");
12534
12571
  hash.update(`${headSha(top) ?? "unborn"}\x00`);
12535
12572
  for (const entry of status.stdout.split("\x00")) {
12536
12573
  if (entry.length < 4)
12537
12574
  continue;
12538
12575
  const file = entry.slice(3);
12539
- const absolute = path8.join(top, file);
12576
+ const absolute = path9.join(top, file);
12540
12577
  let stat = "-";
12541
12578
  try {
12542
- const info = fs9.lstatSync(absolute, { bigint: true });
12579
+ const info = fs10.lstatSync(absolute, { bigint: true });
12543
12580
  stat = `${info.mode.toString(8)}:${info.size}:${info.mtimeNs}`;
12544
12581
  if (info.isDirectory())
12545
12582
  stat += `:${headSha(absolute) ?? "-"}`;
@@ -12606,17 +12643,17 @@ function pushRemoteName(cwd, branch) {
12606
12643
 
12607
12644
  // packages/workit-core/src/core/policy/derive.ts
12608
12645
  import { existsSync as existsSync4 } from "node:fs";
12609
- import path13 from "node:path";
12646
+ import path14 from "node:path";
12610
12647
 
12611
12648
  // packages/workit-core/src/ledger.ts
12612
12649
  import { spawnSync as spawnSync9 } from "node:child_process";
12613
- import { createHash as createHash8, randomBytes as randomBytes2 } from "node:crypto";
12614
- import fs11 from "node:fs";
12615
- import path12 from "node:path";
12650
+ import { createHash as createHash9, randomBytes as randomBytes2 } from "node:crypto";
12651
+ import fs12 from "node:fs";
12652
+ import path13 from "node:path";
12616
12653
 
12617
12654
  // packages/workit-core/src/core/vcs-config.ts
12618
- import fs10 from "node:fs";
12619
- import path11 from "node:path";
12655
+ import fs11 from "node:fs";
12656
+ import path12 from "node:path";
12620
12657
  import { spawnSync as spawnSync8 } from "node:child_process";
12621
12658
 
12622
12659
  // packages/workit-core/src/core/config.ts
@@ -12630,7 +12667,7 @@ import {
12630
12667
  writeFileSync as writeFileSync2
12631
12668
  } from "node:fs";
12632
12669
  import os2 from "node:os";
12633
- import path9 from "node:path";
12670
+ import path10 from "node:path";
12634
12671
 
12635
12672
  // packages/workit-core/src/core/boundary.ts
12636
12673
  var EVENT = {
@@ -12674,7 +12711,7 @@ var mergePreset = (preset, input = {}, current = {
12674
12711
  protected: preset === "custom" ? input.protectedNames ?? current.branchPolicy.protected : [...defs.protected]
12675
12712
  };
12676
12713
  };
12677
- 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");
12714
+ 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");
12678
12715
  var migratedDir = null;
12679
12716
  var migrationFailed = false;
12680
12717
  var ensureConfigDir = (dir = resolveConfigDir()) => {
@@ -12684,7 +12721,7 @@ var ensureConfigDir = (dir = resolveConfigDir()) => {
12684
12721
  migratedDir = dir;
12685
12722
  return dir;
12686
12723
  }
12687
- const legacy = path9.join(process.env.XDG_CONFIG_HOME || path9.join(os2.homedir(), ".config"), "workflow-toolkit");
12724
+ const legacy = path10.join(process.env.XDG_CONFIG_HOME || path10.join(os2.homedir(), ".config"), "workflow-toolkit");
12688
12725
  if (!existsSync3(legacy)) {
12689
12726
  migratedDir = dir;
12690
12727
  return dir;
@@ -12697,8 +12734,8 @@ var ensureConfigDir = (dir = resolveConfigDir()) => {
12697
12734
  mkdirSync2(dir, { recursive: true });
12698
12735
  diagnosticLogger?.info(EVENT.migration, { from: legacy, to: dir });
12699
12736
  for (const entry of readdirSync2(legacy, { withFileTypes: true })) {
12700
- const src = path9.join(legacy, entry.name);
12701
- const dest = path9.join(dir, entry.name);
12737
+ const src = path10.join(legacy, entry.name);
12738
+ const dest = path10.join(dir, entry.name);
12702
12739
  if (existsSync3(dest))
12703
12740
  continue;
12704
12741
  try {
@@ -12770,7 +12807,7 @@ var parseConfigResult = (raw, file) => {
12770
12807
  return { status: "valid", path: file, config };
12771
12808
  };
12772
12809
  var readConfigTyped = (dir) => {
12773
- const file = path9.join(dir ?? configDir(), "config.json");
12810
+ const file = path10.join(dir ?? configDir(), "config.json");
12774
12811
  return parseConfigResult(readSafe(file), file);
12775
12812
  };
12776
12813
  var readConfig = () => {
@@ -12779,7 +12816,7 @@ var readConfig = () => {
12779
12816
  throw new Error(result.error);
12780
12817
  return result.config ?? DEFAULTS;
12781
12818
  };
12782
- var vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path9.join(configDir(), "vcs.json");
12819
+ var vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path10.join(configDir(), "vcs.json");
12783
12820
  var branchGlobPattern = (glob) => new RegExp(`^${glob.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`, "i");
12784
12821
  var resolveBranchPolicy = (config, workspace, repoPreset) => {
12785
12822
  const wp = workspace?.branchPolicy ?? {};
@@ -12821,9 +12858,9 @@ var resolveCommitPolicy = (config, workspace) => {
12821
12858
 
12822
12859
  // packages/workit-core/src/core/workspaces.ts
12823
12860
  import { spawnSync as spawnSync6 } from "node:child_process";
12824
- import { createHash as createHash6 } from "node:crypto";
12861
+ import { createHash as createHash7 } from "node:crypto";
12825
12862
  import { readFileSync as readFileSync3, realpathSync as realpathSync2 } from "node:fs";
12826
- import path10 from "node:path";
12863
+ import path11 from "node:path";
12827
12864
 
12828
12865
  // packages/workit-core/src/core/branch-policy.ts
12829
12866
  import { spawnSync as spawnSync5 } from "node:child_process";
@@ -12948,7 +12985,7 @@ var releaseTrackSchema = object({
12948
12985
  context.addIssue({ code: "custom", path: [field], message: "entries must be unique" });
12949
12986
  }
12950
12987
  }
12951
- 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(".."))) {
12988
+ 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(".."))) {
12952
12989
  context.addIssue({
12953
12990
  code: "custom",
12954
12991
  path: ["versionSource", "path"],
@@ -13008,7 +13045,7 @@ var workspacesFileSchema = object({ workspaces: array(workspaceConfigSchema).opt
13008
13045
  names.add(workspace.name);
13009
13046
  }
13010
13047
  });
13011
- var workspacesRevision = (contents) => createHash6("sha256").update(contents ?? "<missing>").digest("hex");
13048
+ var workspacesRevision = (contents) => createHash7("sha256").update(contents ?? "<missing>").digest("hex");
13012
13049
  var validateWorkspacesDocument = (parsed, file) => {
13013
13050
  if (!isConfigObject(parsed)) {
13014
13051
  return { status: "malformed", path: file, entries: [], error: `${file} is not a JSON object` };
@@ -13046,7 +13083,7 @@ var validateWorkspacesDocument = (parsed, file) => {
13046
13083
  };
13047
13084
  };
13048
13085
  var readWorkspacesResult = (dir = configDir()) => {
13049
- const file = path10.join(dir, "workspaces.json");
13086
+ const file = path11.join(dir, "workspaces.json");
13050
13087
  let raw;
13051
13088
  try {
13052
13089
  raw = readFileSync3(file, "utf8");
@@ -13157,9 +13194,9 @@ var mainCheckoutOf = (cwd) => {
13157
13194
  let main = null;
13158
13195
  const dirs = git(["rev-parse", "--path-format=absolute", "--git-dir", "--git-common-dir"]);
13159
13196
  const [gitDir, common] = (dirs ?? "").trim().split(/\r?\n/u);
13160
- if (gitDir && common && path10.resolve(gitDir) !== path10.resolve(common)) {
13197
+ if (gitDir && common && path11.resolve(gitDir) !== path11.resolve(common)) {
13161
13198
  const listed = /^worktree (.+)$/mu.exec(git(["worktree", "list", "--porcelain"]) ?? "")?.[1];
13162
- main = listed?.trim() || (path10.basename(common) === ".git" ? path10.dirname(common) : common);
13199
+ main = listed?.trim() || (path11.basename(common) === ".git" ? path11.dirname(common) : common);
13163
13200
  }
13164
13201
  mainCheckouts.set(cwd, main);
13165
13202
  return main;
@@ -13250,7 +13287,7 @@ var runtimeWorkspaceIndexSchema = object({
13250
13287
  workspaces: array(object({ name: nonBlank, glob: nonBlank }).passthrough()).optional()
13251
13288
  }).passthrough();
13252
13289
  var matchRuntimeWorkspace = (cwd) => {
13253
- const file = path10.join(configDir(), "workspaces.json");
13290
+ const file = path11.join(configDir(), "workspaces.json");
13254
13291
  let raw;
13255
13292
  try {
13256
13293
  raw = readFileSync3(file, "utf8");
@@ -13325,7 +13362,7 @@ function workspaceDefaultTarget(cwd, globalDefault) {
13325
13362
  }
13326
13363
 
13327
13364
  // packages/workit-core/src/core/release-tracks.ts
13328
- import { createHash as createHash7 } from "node:crypto";
13365
+ import { createHash as createHash8 } from "node:crypto";
13329
13366
  import { spawnSync as spawnSync7 } from "node:child_process";
13330
13367
  class ReleaseTrackError extends Error {
13331
13368
  }
@@ -13708,7 +13745,7 @@ function resolveTrackFor(cwd, options) {
13708
13745
  ]) ?? "",
13709
13746
  git3(cwd, ["config", "--get", recordedBaseKey(branch)]) ?? ""
13710
13747
  ] : [];
13711
- key = createHash7("sha256").update(JSON.stringify({ cwd, input, refs, head, own })).digest("hex");
13748
+ key = createHash8("sha256").update(JSON.stringify({ cwd, input, refs, head, own })).digest("hex");
13712
13749
  const hit = memo2.get(key);
13713
13750
  if (hit)
13714
13751
  return hit;
@@ -13723,7 +13760,7 @@ function resolveTrackFor(cwd, options) {
13723
13760
  }
13724
13761
 
13725
13762
  // packages/workit-core/src/core/vcs-config.ts
13726
- var workspacesPath = () => path11.join(configDir(), "workspaces.json");
13763
+ var workspacesPath = () => path12.join(configDir(), "workspaces.json");
13727
13764
  var vcsCwd = (cwd) => cwd ?? process.env.WORKFLOW_WORKSPACE_ROOT ?? process.cwd();
13728
13765
  var remoteProvider = (cwd) => {
13729
13766
  const r = spawnSync8("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" });
@@ -13813,7 +13850,7 @@ var readVcsConfig = () => {
13813
13850
  const file = vcsConfigPath();
13814
13851
  let raw;
13815
13852
  try {
13816
- raw = fs10.readFileSync(file, "utf8");
13853
+ raw = fs11.readFileSync(file, "utf8");
13817
13854
  } catch {
13818
13855
  return { status: "missing", path: file, config: {} };
13819
13856
  }
@@ -13898,7 +13935,7 @@ function vcsConfig(mode, cwd, options = {}) {
13898
13935
  const prov = cfg[provider] ?? {};
13899
13936
  const out = {
13900
13937
  ok: true,
13901
- configPath: path11.resolve(cfgPath),
13938
+ configPath: path12.resolve(cfgPath),
13902
13939
  provider,
13903
13940
  defaultTargetBranch: workspaceDefault,
13904
13941
  pr: cfg.pr ?? {},
@@ -14109,7 +14146,7 @@ function diffHash(cwd, base, head) {
14109
14146
  ], GIT_TIMEOUTS.worktree);
14110
14147
  if (!diff.ok || !diff.stdout)
14111
14148
  return null;
14112
- const hash = createHash8("sha256");
14149
+ const hash = createHash9("sha256");
14113
14150
  for (const line of diff.stdout.split(`
14114
14151
  `)) {
14115
14152
  if (line.startsWith("index "))
@@ -14121,14 +14158,14 @@ function diffHash(cwd, base, head) {
14121
14158
  return `sha256:${hash.digest("hex")}`;
14122
14159
  }
14123
14160
  function storeRoot(cwd) {
14124
- const location = resolveStore(path12.resolve(cwd));
14161
+ const location = resolveStore(path13.resolve(cwd));
14125
14162
  if (location instanceof Error)
14126
14163
  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");
14127
14164
  return { ok: true, value: { root: location.dir, shared: location.shared } };
14128
14165
  }
14129
14166
  function ledgerPath(cwd) {
14130
14167
  const root = storeRoot(cwd);
14131
- return root.ok ? { ok: true, value: path12.join(root.value.root, "ledger", "ledger.jsonl") } : root;
14168
+ return root.ok ? { ok: true, value: path13.join(root.value.root, "ledger", "ledger.jsonl") } : root;
14132
14169
  }
14133
14170
  var newId2 = () => `${Date.now().toString(36)}-${randomBytes2(6).toString("hex")}`;
14134
14171
  var NETWORK_FS_TYPES = new Set([
@@ -14148,7 +14185,7 @@ var onNetworkFs = (dir) => {
14148
14185
  if (process.platform !== "linux")
14149
14186
  return false;
14150
14187
  try {
14151
- return isNetworkFsType(fs11.statfsSync(dir).type);
14188
+ return isNetworkFsType(fs12.statfsSync(dir).type);
14152
14189
  } catch {
14153
14190
  return false;
14154
14191
  }
@@ -14158,15 +14195,15 @@ var LOCK_STALE_MS = 30000;
14158
14195
  var LOCK_OWNER = "owner";
14159
14196
  var lockToken = (lock) => {
14160
14197
  try {
14161
- return fs11.readFileSync(path12.join(lock, LOCK_OWNER), "utf8");
14198
+ return fs12.readFileSync(path13.join(lock, LOCK_OWNER), "utf8");
14162
14199
  } catch {
14163
14200
  return null;
14164
14201
  }
14165
14202
  };
14166
14203
  var lockAgeMs = (lock) => {
14167
- for (const target of [path12.join(lock, LOCK_OWNER), lock]) {
14204
+ for (const target of [path13.join(lock, LOCK_OWNER), lock]) {
14168
14205
  try {
14169
- return Date.now() - fs11.statSync(target).mtimeMs;
14206
+ return Date.now() - fs12.statSync(target).mtimeMs;
14170
14207
  } catch {}
14171
14208
  }
14172
14209
  return null;
@@ -14174,14 +14211,14 @@ var lockAgeMs = (lock) => {
14174
14211
  var ledgerLock = {
14175
14212
  acquire(lock) {
14176
14213
  try {
14177
- fs11.mkdirSync(lock);
14214
+ fs12.mkdirSync(lock);
14178
14215
  } catch (error) {
14179
14216
  if (error.code === "EEXIST")
14180
14217
  return null;
14181
14218
  throw error;
14182
14219
  }
14183
14220
  const token = `${process.pid}-${randomBytes2(8).toString("hex")}`;
14184
- fs11.writeFileSync(path12.join(lock, LOCK_OWNER), token);
14221
+ fs12.writeFileSync(path13.join(lock, LOCK_OWNER), token);
14185
14222
  return token;
14186
14223
  },
14187
14224
  release(lock, token) {
@@ -14189,35 +14226,35 @@ var ledgerLock = {
14189
14226
  return false;
14190
14227
  const tomb = `${lock}.release-${randomBytes2(6).toString("hex")}`;
14191
14228
  try {
14192
- fs11.renameSync(lock, tomb);
14229
+ fs12.renameSync(lock, tomb);
14193
14230
  } catch {
14194
14231
  return false;
14195
14232
  }
14196
14233
  if (lockToken(tomb) !== token) {
14197
14234
  try {
14198
- fs11.renameSync(tomb, lock);
14235
+ fs12.renameSync(tomb, lock);
14199
14236
  } catch {}
14200
14237
  return false;
14201
14238
  }
14202
- fs11.rmSync(tomb, { recursive: true, force: true });
14239
+ fs12.rmSync(tomb, { recursive: true, force: true });
14203
14240
  return true;
14204
14241
  },
14205
14242
  token: lockToken,
14206
14243
  reap(lock, observed) {
14207
14244
  const tomb = `${lock}.reap-${randomBytes2(6).toString("hex")}`;
14208
14245
  try {
14209
- fs11.renameSync(lock, tomb);
14246
+ fs12.renameSync(lock, tomb);
14210
14247
  } catch {
14211
14248
  return false;
14212
14249
  }
14213
14250
  if (lockToken(tomb) === observed) {
14214
- fs11.rmSync(tomb, { recursive: true, force: true });
14251
+ fs12.rmSync(tomb, { recursive: true, force: true });
14215
14252
  return true;
14216
14253
  }
14217
14254
  try {
14218
- fs11.renameSync(tomb, lock);
14255
+ fs12.renameSync(tomb, lock);
14219
14256
  } catch {
14220
- fs11.rmSync(tomb, { recursive: true, force: true });
14257
+ fs12.rmSync(tomb, { recursive: true, force: true });
14221
14258
  }
14222
14259
  return false;
14223
14260
  }
@@ -14244,14 +14281,14 @@ function withLedgerLock(file, fn, waitMs = LOCK_WAIT_MS) {
14244
14281
  ledgerLock.release(lock, token);
14245
14282
  }
14246
14283
  }
14247
- var sha2562 = (text) => createHash8("sha256").update(text).digest("hex");
14284
+ var sha2562 = (text) => createHash9("sha256").update(text).digest("hex");
14248
14285
  var chainHash = (prevHash, body) => sha2562(`${prevHash ?? ""}
14249
14286
  ${body}`);
14250
14287
  var TAIL_BYTES = 64 * 1024;
14251
14288
  var lastLine = (fd, size) => {
14252
14289
  for (let span = Math.min(size, TAIL_BYTES);span > 0; span = Math.min(size, span * 2)) {
14253
14290
  const buffer = Buffer.alloc(span);
14254
- fs11.readSync(fd, buffer, 0, span, size - span);
14291
+ fs12.readSync(fd, buffer, 0, span, size - span);
14255
14292
  const end = buffer.lastIndexOf(10);
14256
14293
  if (end < 0) {
14257
14294
  if (span === size)
@@ -14282,13 +14319,13 @@ var lastLine = (fd, size) => {
14282
14319
  };
14283
14320
  function appendLine(file, build, options) {
14284
14321
  const write = () => {
14285
- const fd = fs11.openSync(file, "a+");
14322
+ const fd = fs12.openSync(file, "a+");
14286
14323
  try {
14287
- const size = fs11.fstatSync(fd).size;
14324
+ const size = fs12.fstatSync(fd).size;
14288
14325
  let fence = "";
14289
14326
  if (size > 0) {
14290
14327
  const last = Buffer.alloc(1);
14291
- fs11.readSync(fd, last, 0, 1, size - 1);
14328
+ fs12.readSync(fd, last, 0, 1, size - 1);
14292
14329
  if (last[0] !== 10)
14293
14330
  fence = `
14294
14331
  `;
@@ -14297,17 +14334,17 @@ function appendLine(file, build, options) {
14297
14334
  if (!line.ok)
14298
14335
  return line;
14299
14336
  const bytes = Buffer.from(fence + line.value);
14300
- const written = fs11.writeSync(fd, bytes);
14337
+ const written = fs12.writeSync(fd, bytes);
14301
14338
  if (written !== bytes.length)
14302
14339
  return err("unavailable", `short write to ${file}: ${written} of ${bytes.length} bytes; the row is torn and will be skipped`);
14303
14340
  return { ok: true, value: undefined };
14304
14341
  } finally {
14305
- fs11.closeSync(fd);
14342
+ fs12.closeSync(fd);
14306
14343
  }
14307
14344
  };
14308
14345
  try {
14309
- fs11.mkdirSync(path12.dirname(file), { recursive: true });
14310
- if (!options.forceLock && !onNetworkFs(path12.dirname(file)))
14346
+ fs12.mkdirSync(path13.dirname(file), { recursive: true });
14347
+ if (!options.forceLock && !onNetworkFs(path13.dirname(file)))
14311
14348
  return write();
14312
14349
  const locked = withLedgerLock(file, write);
14313
14350
  return locked ?? err("busy", `ledger lock ${file}.lock is held`, "retry; remove the .lock directory if no workit process is running");
@@ -14379,7 +14416,7 @@ function readLedger(cwd, options = {}) {
14379
14416
  return file;
14380
14417
  let text = "";
14381
14418
  try {
14382
- text = fs11.readFileSync(file.value, "utf8");
14419
+ text = fs12.readFileSync(file.value, "utf8");
14383
14420
  } catch (error) {
14384
14421
  if (error.code === "ENOENT")
14385
14422
  return {
@@ -14573,11 +14610,20 @@ function authorSessions(cwd, rows, branch, range = { base: null, head: null }, s
14573
14610
  sessions.add(session);
14574
14611
  return sessions;
14575
14612
  }
14613
+ var derivesFrom = (derived, bare) => !bare.includes(":") && derived.endsWith(`:${bare}`);
14614
+ var authoredBy = (authors, session) => {
14615
+ if (authors.has(session))
14616
+ return true;
14617
+ for (const author of authors)
14618
+ if (derivesFrom(author, session) || derivesFrom(session, author))
14619
+ return true;
14620
+ return false;
14621
+ };
14576
14622
  var independenceReasons = (row, authors) => {
14577
14623
  const reasons = [];
14578
14624
  if (!row.actor.session)
14579
14625
  reasons.push("no_session");
14580
- else if (authors.has(row.actor.session))
14626
+ else if (authoredBy(authors, row.actor.session))
14581
14627
  reasons.push("author_session");
14582
14628
  if (row.self === true && !reasons.includes("no_session"))
14583
14629
  reasons.push("self");
@@ -14861,7 +14907,7 @@ var productDecision = (task, ledger) => {
14861
14907
  };
14862
14908
  };
14863
14909
  var planRecorded = (task, root) => {
14864
- const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(path13.resolve(root, ref.path)));
14910
+ const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(path14.resolve(root, ref.path)));
14865
14911
  if (cited)
14866
14912
  return {
14867
14913
  met: true,
@@ -14920,15 +14966,15 @@ function writeBlockers(task, root) {
14920
14966
  }
14921
14967
 
14922
14968
  // packages/workit-core/src/core/task-evaluation.ts
14923
- var digestBytes = (value) => createHash9("sha256").update(value).digest("hex");
14924
- var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path14.sep}`);
14925
- var relative = (root, candidate) => path14.relative(root, candidate).split(path14.sep).join("/") || ".";
14969
+ var digestBytes = (value) => createHash10("sha256").update(value).digest("hex");
14970
+ var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path15.sep}`);
14971
+ var relative = (root, candidate) => path15.relative(root, candidate).split(path15.sep).join("/") || ".";
14926
14972
  var canonicalPath = (value) => {
14927
14973
  if (typeof value !== "string" || !value)
14928
14974
  return null;
14929
14975
  if (value.includes("\\") || value.split("/").includes(".."))
14930
14976
  return null;
14931
- const normalized = path14.posix.normalize(value);
14977
+ const normalized = path15.posix.normalize(value);
14932
14978
  if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
14933
14979
  return null;
14934
14980
  return normalized === "." ? "." : normalized.replace(/\/$/, "");
@@ -14976,21 +15022,21 @@ var gitPaths = (root) => {
14976
15022
  git: !/not a git repository/i.test(stderr)
14977
15023
  };
14978
15024
  }
14979
- const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path14.sep).join("/")) : [];
15025
+ const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path15.sep).join("/")) : [];
14980
15026
  const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
14981
15027
  if (stagedDeleted.status !== 0) {
14982
15028
  const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
14983
15029
  if (!/not a git repository/i.test(stderr))
14984
15030
  return { paths, uncertain: true, git: true };
14985
15031
  } else if (stagedDeleted.stdout) {
14986
- paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path14.sep).join("/")));
15032
+ paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path15.sep).join("/")));
14987
15033
  }
14988
15034
  return { paths: [...new Set(paths)], uncertain: false, git: true };
14989
15035
  };
14990
15036
  var walk = (root, directory, output) => {
14991
15037
  let names;
14992
15038
  try {
14993
- names = fs12.readdirSync(directory);
15039
+ names = fs13.readdirSync(directory);
14994
15040
  } catch {
14995
15041
  return true;
14996
15042
  }
@@ -14998,10 +15044,10 @@ var walk = (root, directory, output) => {
14998
15044
  for (const name of names) {
14999
15045
  if (name === ".git" || name === ".workit")
15000
15046
  continue;
15001
- const target = path14.join(directory, name);
15047
+ const target = path15.join(directory, name);
15002
15048
  let stat;
15003
15049
  try {
15004
- stat = fs12.lstatSync(target);
15050
+ stat = fs13.lstatSync(target);
15005
15051
  } catch {
15006
15052
  uncertain = true;
15007
15053
  continue;
@@ -15016,14 +15062,14 @@ var walk = (root, directory, output) => {
15016
15062
  var scopeRoots = (root, scope) => {
15017
15063
  const roots = [];
15018
15064
  for (const item of scope.paths.length ? scope.paths : ["."]) {
15019
- const target = path14.resolve(root, item);
15065
+ const target = path15.resolve(root, item);
15020
15066
  if (!inside(root, target))
15021
15067
  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` }] });
15022
15068
  let ancestor = target;
15023
- while (!fs12.existsSync(ancestor) && ancestor !== root)
15024
- ancestor = path14.dirname(ancestor);
15069
+ while (!fs13.existsSync(ancestor) && ancestor !== root)
15070
+ ancestor = path15.dirname(ancestor);
15025
15071
  try {
15026
- if (!inside(root, fs12.realpathSync(ancestor)))
15072
+ if (!inside(root, fs13.realpathSync(ancestor)))
15027
15073
  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` }] });
15028
15074
  } catch {
15029
15075
  return failure2("invalid_input", `candidate scope cannot be inspected: ${item}`);
@@ -15035,7 +15081,7 @@ var scopeRoots = (root, scope) => {
15035
15081
  function captureCandidate(root, scope, environment = []) {
15036
15082
  let checkout;
15037
15083
  try {
15038
- checkout = fs12.realpathSync(root);
15084
+ checkout = fs13.realpathSync(root);
15039
15085
  } catch {
15040
15086
  return failure2("invalid_input", "candidate root does not exist");
15041
15087
  }
@@ -15053,11 +15099,11 @@ function captureCandidate(root, scope, environment = []) {
15053
15099
  if (item === ".git" || item === ".workit")
15054
15100
  continue;
15055
15101
  names.add(item);
15056
- if (!fs12.existsSync(target))
15102
+ if (!fs13.existsSync(target))
15057
15103
  continue;
15058
15104
  let stat;
15059
15105
  try {
15060
- stat = fs12.lstatSync(target);
15106
+ stat = fs13.lstatSync(target);
15061
15107
  } catch {
15062
15108
  uncertain = true;
15063
15109
  continue;
@@ -15073,17 +15119,17 @@ function captureCandidate(root, scope, environment = []) {
15073
15119
  for (const item of [...names].toSorted()) {
15074
15120
  if (!scopeMatches(item, normalizedScope))
15075
15121
  continue;
15076
- const target = path14.join(checkout, item);
15122
+ const target = path15.join(checkout, item);
15077
15123
  try {
15078
- const stat = fs12.lstatSync(target);
15124
+ const stat = fs13.lstatSync(target);
15079
15125
  if (stat.isSymbolicLink()) {
15080
- const link = fs12.readlinkSync(target);
15126
+ const link = fs13.readlinkSync(target);
15081
15127
  files.push({ path: item, kind: "symlink", digest: digestBytes(link), executable: null });
15082
15128
  } else if (stat.isFile()) {
15083
15129
  files.push({
15084
15130
  path: item,
15085
15131
  kind: "file",
15086
- digest: digestBytes(fs12.readFileSync(target)),
15132
+ digest: digestBytes(fs13.readFileSync(target)),
15087
15133
  executable: (stat.mode & 73) !== 0
15088
15134
  });
15089
15135
  } else if (!stat.isDirectory()) {
@@ -15248,7 +15294,7 @@ var findingVerificationPasses = (findingCandidateId, evidence) => evidence.statu
15248
15294
  var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
15249
15295
  let root;
15250
15296
  try {
15251
- root = fs12.realpathSync(checkoutRoot);
15297
+ root = fs13.realpathSync(checkoutRoot);
15252
15298
  } catch {
15253
15299
  return failure2("permission_denied", "checkout root is unavailable");
15254
15300
  }
@@ -15257,23 +15303,23 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
15257
15303
  continue;
15258
15304
  if (!reference.digest)
15259
15305
  return failure2("invalid_input", "document references require a byte digest");
15260
- const target = path14.resolve(root, reference.path);
15261
- if (target !== root && !target.startsWith(`${root}${path14.sep}`))
15306
+ const target = path15.resolve(root, reference.path);
15307
+ if (target !== root && !target.startsWith(`${root}${path15.sep}`))
15262
15308
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
15263
15309
  fields: [
15264
15310
  { path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
15265
15311
  ]
15266
15312
  });
15267
15313
  try {
15268
- const below = path14.relative(root, target);
15314
+ const below = path15.relative(root, target);
15269
15315
  let current = root;
15270
- for (const segment of below.split(path14.sep)) {
15316
+ for (const segment of below.split(path15.sep)) {
15271
15317
  if (!segment)
15272
15318
  continue;
15273
- current = path14.join(current, segment);
15274
- const stat = fs12.lstatSync(current);
15275
- const real = fs12.realpathSync(current);
15276
- if (real !== root && !real.startsWith(`${root}${path14.sep}`))
15319
+ current = path15.join(current, segment);
15320
+ const stat = fs13.lstatSync(current);
15321
+ const real = fs13.realpathSync(current);
15322
+ if (real !== root && !real.startsWith(`${root}${path15.sep}`))
15277
15323
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
15278
15324
  fields: [
15279
15325
  {
@@ -15289,7 +15335,7 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
15289
15335
  if (current !== target && !stat.isDirectory())
15290
15336
  return failure2("invalid_input", "document reference ancestor is not a directory");
15291
15337
  }
15292
- if (digestBytes(fs12.readFileSync(target)) !== reference.digest)
15338
+ if (digestBytes(fs13.readFileSync(target)) !== reference.digest)
15293
15339
  return failure2("permission_denied", "decision document bytes have changed");
15294
15340
  } catch {
15295
15341
  return failure2("invalid_input", "decision document is unavailable");
@@ -15658,7 +15704,8 @@ Autonomy contract:
15658
15704
  satisfies a gate; an ad-hoc \`workit check -- <cmd>\` never does.
15659
15705
  - Author is not verifier: your own verdict is \`--self\`, shown as
15660
15706
  self-reviewed, never verified. High risk, \`verification: independent\` and
15661
- merge need a verifier with its own session (\`WORKIT_SESSION_ID=<lead>-v<n>\`).
15707
+ merge need a verifier with its own host-derived session (a subagent's
15708
+ \`<lead>:<child>\`, set by the host); never hand-mint one such as \`<lead>-v1\`.
15662
15709
  - A local-commit endpoint does not imply PR readiness, and a local commit alone
15663
15710
  is not evidence of a requested remote push. Before reporting delivery,
15664
15711
  reconcile every requested item and observe it (\`workit verify-delivery\`).
@@ -15815,7 +15862,7 @@ var exportDigest = (bundle) => sha256({
15815
15862
  task: bundle.task
15816
15863
  });
15817
15864
  // packages/workit-core/src/core/branch.ts
15818
- import { createHash as createHash10 } from "node:crypto";
15865
+ import { createHash as createHash11 } from "node:crypto";
15819
15866
 
15820
15867
  // packages/workit-core/src/core/git.ts
15821
15868
  import { execFileSync } from "node:child_process";
@@ -15953,7 +16000,7 @@ var branchPolicySnapshotFor = (workspaceRoot) => {
15953
16000
  const source = resolved.provenance.branchPolicy;
15954
16001
  const allowed = branchPolicy.allowed.map((pattern) => `${pattern.source}/${pattern.flags}`).toSorted();
15955
16002
  const protectedRefs = [...branchPolicy.protected].map((name) => name.toLowerCase()).toSorted();
15956
- const fingerprint = createHash10("sha256").update(JSON.stringify({ allowed, protectedRefs, source })).digest("hex");
16003
+ const fingerprint = createHash11("sha256").update(JSON.stringify({ allowed, protectedRefs, source })).digest("hex");
15957
16004
  return {
15958
16005
  branchPolicy,
15959
16006
  namePolicy: { allowed: branchPolicy.allowed, protected: branchPolicy.protected },
@@ -16209,7 +16256,7 @@ var judgeInputSummary = (raw) => {
16209
16256
 
16210
16257
  // packages/workit-core/src/autonomy.ts
16211
16258
  import os3 from "node:os";
16212
- import path15 from "node:path";
16259
+ import path16 from "node:path";
16213
16260
  var accountHome = () => {
16214
16261
  try {
16215
16262
  return os3.userInfo().homedir;
@@ -16218,10 +16265,10 @@ var accountHome = () => {
16218
16265
  }
16219
16266
  };
16220
16267
  var grantsHome = { resolve: accountHome };
16221
- var grantsDir = () => path15.join(grantsHome.resolve(), ".config", "workit");
16268
+ var grantsDir = () => path16.join(grantsHome.resolve(), ".config", "workit");
16222
16269
  var grantsOverride = () => {
16223
- const configured = path15.resolve(resolveConfigDir());
16224
- 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`;
16270
+ const configured = path16.resolve(resolveConfigDir());
16271
+ 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`;
16225
16272
  };
16226
16273
  var GRANT_KINDS = ["push", "pr", "merge", "release", "rerun"];
16227
16274
  var DEFAULT_GRANTS = Object.freeze({
@@ -17993,7 +18040,7 @@ class WorkitCore {
17993
18040
  // packages/workit-core/src/core/repo-context.ts
17994
18041
  import { spawnSync as spawnSync11 } from "node:child_process";
17995
18042
  import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync4 } from "node:fs";
17996
- import path16 from "node:path";
18043
+ import path17 from "node:path";
17997
18044
  var isSafeContextRange = (value) => value.length <= 4096 && (() => {
17998
18045
  try {
17999
18046
  gitRevisionParts(value);
@@ -18127,7 +18174,7 @@ var findPrTemplate = (cwd) => {
18127
18174
  ]) {
18128
18175
  const parts = rel.split("/");
18129
18176
  const base = parts[parts.length - 1];
18130
- const dir = parts.length > 1 ? path16.join(cwd, ...parts.slice(0, -1)) : cwd;
18177
+ const dir = parts.length > 1 ? path17.join(cwd, ...parts.slice(0, -1)) : cwd;
18131
18178
  const actual = probeCaseInsensitive(dir, base);
18132
18179
  if (actual)
18133
18180
  return [...parts.slice(0, -1), actual].join("/");
@@ -18158,7 +18205,7 @@ var diffStatForRange = (cwd, range) => {
18158
18205
  return runGit(cwd, ["diff", "--stat", "--"]).stdout;
18159
18206
  };
18160
18207
  var packageScripts = (cwd, keys) => {
18161
- const pkgPath = path16.join(cwd, "package.json");
18208
+ const pkgPath = path17.join(cwd, "package.json");
18162
18209
  if (!existsSync6(pkgPath))
18163
18210
  return [];
18164
18211
  try {
@@ -18184,9 +18231,9 @@ var documentationFiles = (cwd) => {
18184
18231
  if (entry.isDirectory()) {
18185
18232
  if (excluded.has(entry.name))
18186
18233
  continue;
18187
- walk(path16.join(dir, entry.name), depth + 1);
18234
+ walk(path17.join(dir, entry.name), depth + 1);
18188
18235
  } else if (entry.isFile() && (entry.name === "README.md" || entry.name.endsWith(".md"))) {
18189
- matches.push("./" + path16.relative(cwd, path16.join(dir, entry.name)).replaceAll("\\", "/"));
18236
+ matches.push("./" + path17.relative(cwd, path17.join(dir, entry.name)).replaceAll("\\", "/"));
18190
18237
  }
18191
18238
  }
18192
18239
  };
@@ -18202,7 +18249,7 @@ var readTrimmed2 = (file, maxLines) => {
18202
18249
  `);
18203
18250
  };
18204
18251
  function prReadyContext(root, range) {
18205
- const cwd = path16.resolve(repoRoot(root));
18252
+ const cwd = path17.resolve(repoRoot(root));
18206
18253
  if (range !== undefined && !isResolvableContextRange(cwd, range))
18207
18254
  return invalidRange(cwd);
18208
18255
  let stdout = "";
@@ -18260,7 +18307,7 @@ ${status.stderr}` : "");
18260
18307
  stdout += `template_path: ${template}
18261
18308
 
18262
18309
  `;
18263
- stdout += readTrimmed2(path16.join(cwd, template), 220);
18310
+ stdout += readTrimmed2(path17.join(cwd, template), 220);
18264
18311
  } else {
18265
18312
  stdout += `template_path: none
18266
18313
 
@@ -18270,7 +18317,7 @@ ${status.stderr}` : "");
18270
18317
  stdout += `
18271
18318
  `;
18272
18319
  stdout += printSection("Recent Validation Signals");
18273
- if (existsSync6(path16.join(cwd, "package.json"))) {
18320
+ if (existsSync6(path17.join(cwd, "package.json"))) {
18274
18321
  stdout += `package.json detected. Common scripts:
18275
18322
  `;
18276
18323
  const found = packageScripts(cwd, ["lint", "format:check", "test", "build"]);
@@ -18279,7 +18326,7 @@ ${status.stderr}` : "");
18279
18326
  `) + `
18280
18327
  `;
18281
18328
  }
18282
- if (existsSync6(path16.join(cwd, "Cargo.toml")) || existsSync6(path16.join(cwd, "src-tauri/Cargo.toml"))) {
18329
+ if (existsSync6(path17.join(cwd, "Cargo.toml")) || existsSync6(path17.join(cwd, "src-tauri/Cargo.toml"))) {
18283
18330
  stdout += `Rust project detected.
18284
18331
  `;
18285
18332
  }
@@ -18312,7 +18359,7 @@ var CHANGELOG_RULES = `- Use an [Unreleased] section.
18312
18359
  - Apply with the host-native editor, preserving the repository changelog conventions.
18313
18360
  - If Unreleased already has duplicate category headings, normalize_only first.`;
18314
18361
  function changelogContext(root, range) {
18315
- const cwd = path16.resolve(repoRoot(root));
18362
+ const cwd = path17.resolve(repoRoot(root));
18316
18363
  if (range !== undefined && !isResolvableContextRange(cwd, range))
18317
18364
  return invalidRange(cwd);
18318
18365
  const resolvedRange = rangeArgOrDefault(range, cwd);
@@ -18330,7 +18377,7 @@ function changelogContext(root, range) {
18330
18377
  stdout += CHANGELOG_RULES + `
18331
18378
  `;
18332
18379
  stdout += printSection("Existing CHANGELOG.md");
18333
- const changelogPath = path16.join(cwd, "CHANGELOG.md");
18380
+ const changelogPath = path17.join(cwd, "CHANGELOG.md");
18334
18381
  if (existsSync6(changelogPath)) {
18335
18382
  stdout += readTrimmed2(changelogPath, 260) + `
18336
18383
  `;
@@ -18350,7 +18397,7 @@ function changelogContext(root, range) {
18350
18397
  return { stdout, stderr: "", exitCode: 0, cwd };
18351
18398
  }
18352
18399
  function docsRefreshContext(root, range) {
18353
- const cwd = path16.resolve(repoRoot(root));
18400
+ const cwd = path17.resolve(repoRoot(root));
18354
18401
  if (range !== undefined && !isResolvableContextRange(cwd, range))
18355
18402
  return invalidRange(cwd);
18356
18403
  const resolvedRange = rangeArgOrDefault(range, cwd);
@@ -18372,7 +18419,7 @@ function docsRefreshContext(root, range) {
18372
18419
  `) + `
18373
18420
  `;
18374
18421
  stdout += printSection("README Preview");
18375
- const readme = path16.join(cwd, "README.md");
18422
+ const readme = path17.join(cwd, "README.md");
18376
18423
  if (existsSync6(readme)) {
18377
18424
  stdout += readTrimmed2(readme, 220) + `
18378
18425
  `;
@@ -18381,7 +18428,7 @@ function docsRefreshContext(root, range) {
18381
18428
  `;
18382
18429
  }
18383
18430
  stdout += printSection("Package Scripts");
18384
- const pkgPath = path16.join(cwd, "package.json");
18431
+ const pkgPath = path17.join(cwd, "package.json");
18385
18432
  if (existsSync6(pkgPath)) {
18386
18433
  try {
18387
18434
  const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
@@ -18395,7 +18442,7 @@ function docsRefreshContext(root, range) {
18395
18442
  return { stdout, stderr: "", exitCode: 0, cwd };
18396
18443
  }
18397
18444
  function releaseNotesContext(root, rangeOrTag) {
18398
- const cwd = path16.resolve(repoRoot(root));
18445
+ const cwd = path17.resolve(repoRoot(root));
18399
18446
  if (!rangeOrTag) {
18400
18447
  return { stdout: "", stderr: `ERROR: release tag or range required
18401
18448
  `, exitCode: 1, cwd };
@@ -18433,7 +18480,7 @@ function releaseNotesContext(root, rangeOrTag) {
18433
18480
  `;
18434
18481
  stdout += printSection("Existing Release Files");
18435
18482
  for (const rel of ["CHANGELOG.md", "RELEASE_NOTES.md", ".github/releases.md"]) {
18436
- if (existsSync6(path16.join(cwd, rel)))
18483
+ if (existsSync6(path17.join(cwd, rel)))
18437
18484
  stdout += rel + `
18438
18485
  `;
18439
18486
  }
@@ -18464,8 +18511,8 @@ function releaseNotesContext(root, rangeOrTag) {
18464
18511
  import { spawnSync as spawnSync13 } from "node:child_process";
18465
18512
 
18466
18513
  // packages/workit-core/src/core/pr-create.ts
18467
- import fs13 from "node:fs";
18468
- import path17 from "node:path";
18514
+ import fs14 from "node:fs";
18515
+ import path18 from "node:path";
18469
18516
  import { spawnSync as spawnSync12 } from "node:child_process";
18470
18517
  // packages/workit-core/src/forge/pr-body.ts
18471
18518
  function parseGhIssue(value) {
@@ -18476,13 +18523,13 @@ function parseGhIssue(value) {
18476
18523
  // packages/workit-core/src/core/pr-create.ts
18477
18524
  function whichOnPath(tool) {
18478
18525
  const names = process.platform === "win32" ? [tool, `${tool}.exe`, `${tool}.cmd`] : [tool];
18479
- for (const dir of (process.env.PATH ?? "").split(path17.delimiter)) {
18526
+ for (const dir of (process.env.PATH ?? "").split(path18.delimiter)) {
18480
18527
  if (!dir)
18481
18528
  continue;
18482
18529
  for (const name of names) {
18483
- const candidate = path17.join(dir, name);
18530
+ const candidate = path18.join(dir, name);
18484
18531
  try {
18485
- fs13.accessSync(candidate, fs13.constants.X_OK);
18532
+ fs14.accessSync(candidate, fs14.constants.X_OK);
18486
18533
  return candidate;
18487
18534
  } catch {}
18488
18535
  }
@@ -18600,8 +18647,8 @@ var fetchGitLabIssueBody = async (ref, root, deps = {}) => {
18600
18647
  };
18601
18648
 
18602
18649
  // packages/workit-core/src/core/youtrack.ts
18603
- import fs14 from "node:fs";
18604
- import path18 from "node:path";
18650
+ import fs15 from "node:fs";
18651
+ import path19 from "node:path";
18605
18652
 
18606
18653
  // packages/workit-core/src/core/templates.ts
18607
18654
  var repoRoot2 = assetRoot();
@@ -18614,22 +18661,22 @@ var resolveWorkspaceRoot = (explicit) => explicit || process.cwd();
18614
18661
  // packages/workit-core/src/core/youtrack.ts
18615
18662
  var ISSUE_RE = /^[A-Z]+-\d+$/;
18616
18663
  var TOKEN_PLACEHOLDER = "YOUR_TOKEN_HERE";
18617
- var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path18.join(configDir(), "youtrack.json");
18618
- var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path18.join(resolveConfigDir(), "youtrack.json");
18664
+ var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path19.join(configDir(), "youtrack.json");
18665
+ var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path19.join(resolveConfigDir(), "youtrack.json");
18619
18666
  var youTrackTokenModeOk = (p) => {
18620
18667
  if (process.platform === "win32")
18621
18668
  return true;
18622
- const mode = fs14.statSync(p).mode & 511;
18669
+ const mode = fs15.statSync(p).mode & 511;
18623
18670
  return mode === 384;
18624
18671
  };
18625
18672
  function readYouTrackConfig(required) {
18626
18673
  const cfgPath = youTrackConfigPath();
18627
- if (!fs14.existsSync(cfgPath)) {
18674
+ if (!fs15.existsSync(cfgPath)) {
18628
18675
  return required ? { error: "ERROR: missing youtrack.json", path: cfgPath } : { config: {}, path: cfgPath };
18629
18676
  }
18630
18677
  let parsed;
18631
18678
  try {
18632
- parsed = JSON.parse(fs14.readFileSync(cfgPath, "utf8"));
18679
+ parsed = JSON.parse(fs15.readFileSync(cfgPath, "utf8"));
18633
18680
  } catch {
18634
18681
  return { error: `${cfgPath} is not valid JSON`, path: cfgPath };
18635
18682
  }
@@ -18640,11 +18687,11 @@ function readYouTrackConfig(required) {
18640
18687
  }
18641
18688
  var readYouTrackContextConfig = () => {
18642
18689
  const cfgPath = youTrackReadOnlyConfigPath();
18643
- if (!fs14.existsSync(cfgPath))
18690
+ if (!fs15.existsSync(cfgPath))
18644
18691
  return { data: {} };
18645
18692
  let parsed;
18646
18693
  try {
18647
- parsed = JSON.parse(fs14.readFileSync(cfgPath, "utf8"));
18694
+ parsed = JSON.parse(fs15.readFileSync(cfgPath, "utf8"));
18648
18695
  } catch {
18649
18696
  return { error: "YouTrack configuration is unavailable" };
18650
18697
  }
@@ -18683,12 +18730,12 @@ var youTrackToken = () => {
18683
18730
  if ("error" in loaded)
18684
18731
  return loaded;
18685
18732
  const tokenFile = String(loaded.config.tokenFile ?? "");
18686
- const tokenPath = tokenFile ? path18.isAbsolute(tokenFile) ? path18.resolve(tokenFile) : path18.resolve(process.cwd(), tokenFile) : "";
18687
- if (!tokenPath || !fs14.existsSync(tokenPath))
18733
+ const tokenPath = tokenFile ? path19.isAbsolute(tokenFile) ? path19.resolve(tokenFile) : path19.resolve(process.cwd(), tokenFile) : "";
18734
+ if (!tokenPath || !fs15.existsSync(tokenPath))
18688
18735
  return { error: "missing youtrack.token" };
18689
18736
  if (!youTrackTokenModeOk(tokenPath))
18690
18737
  return { error: "youtrack.token mode must be 0600" };
18691
- const token = fs14.readFileSync(tokenPath, "utf8").trim();
18738
+ const token = fs15.readFileSync(tokenPath, "utf8").trim();
18692
18739
  if (!token)
18693
18740
  return { error: "empty token file" };
18694
18741
  if (token === TOKEN_PLACEHOLDER || token.startsWith(TOKEN_PLACEHOLDER)) {
@@ -18753,9 +18800,9 @@ function resolveYouTrackFromPaths(spec_path, plan_path, workspace_root) {
18753
18800
  } catch {
18754
18801
  continue;
18755
18802
  }
18756
- if (!fs14.existsSync(full))
18803
+ if (!fs15.existsSync(full))
18757
18804
  continue;
18758
- const text = fs14.readFileSync(full, "utf8");
18805
+ const text = fs15.readFileSync(full, "utf8");
18759
18806
  const m = text.match(/^\*\*YouTrack:\*\*\s*`?([A-Z]+-\d+)`?/m);
18760
18807
  if (m)
18761
18808
  return m[1];
@@ -19040,15 +19087,15 @@ function resolveGitRevision(root, value) {
19040
19087
  }
19041
19088
  function resolveInside(root, candidate) {
19042
19089
  const base = realpathSync5(root);
19043
- const target = path19.resolve(base, candidate);
19044
- if (target !== base && !target.startsWith(base + path19.sep)) {
19090
+ const target = path20.resolve(base, candidate);
19091
+ if (target !== base && !target.startsWith(base + path20.sep)) {
19045
19092
  throw new Error("path must stay inside repository root");
19046
19093
  }
19047
19094
  let ancestor = target;
19048
19095
  while (!existsSync7(ancestor))
19049
- ancestor = path19.dirname(ancestor);
19096
+ ancestor = path20.dirname(ancestor);
19050
19097
  const canonicalAncestor = realpathSync5(ancestor);
19051
- if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path19.sep)) {
19098
+ if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path20.sep)) {
19052
19099
  throw new Error("path must stay inside repository root");
19053
19100
  }
19054
19101
  return target;
@@ -19092,9 +19139,9 @@ var capabilitiesFor = (descriptor, observed = {}) => descriptor.capabilities.map
19092
19139
  };
19093
19140
  });
19094
19141
  // packages/workit-core/src/hooks/context.ts
19095
- import { createHash as createHash11 } from "node:crypto";
19096
- import fs15 from "node:fs";
19097
- import path20 from "node:path";
19142
+ import { createHash as createHash12 } from "node:crypto";
19143
+ import fs16 from "node:fs";
19144
+ import path21 from "node:path";
19098
19145
  var MIGRATION_PENDING_NOTE = "workit migration pending — run `workit task status`";
19099
19146
  var migrationPending = (result) => !result.ok && result.code === "needs_input" && (result.error ?? "").startsWith(MIGRATION_PENDING);
19100
19147
  var boundTo = (entry, session) => entry.sessions.some((item) => item.host === session.host && item.handle === session.handle);
@@ -19179,7 +19226,7 @@ function entryCompactContext(store, entry, session, context) {
19179
19226
  return null;
19180
19227
  const freshness = { mode: "signal", current: () => recentSignal(store.root) };
19181
19228
  const observed = task?.data.evidence.some(isObservedCheck) ?? false;
19182
- const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [path20.resolve(store.root, ref.path)] : []));
19229
+ const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [path21.resolve(store.root, ref.path)] : []));
19183
19230
  const observedFiles = filesKey(files);
19184
19231
  const compact = new WorkitCore(store, context).compactContext(entry?.id ?? null, freshness, origin && { origin: origin.origin, taskId: origin.entry.id });
19185
19232
  if (!compact.ok || !compact.data)
@@ -19248,7 +19295,7 @@ var turnContextText = (input, descriptor) => {
19248
19295
  }
19249
19296
  };
19250
19297
  var TURN_TTL_MS = 7 * 24 * 60 * 60 * 1000;
19251
- var digestOf = (text) => createHash11("sha256").update(text).digest("hex");
19298
+ var digestOf = (text) => createHash12("sha256").update(text).digest("hex");
19252
19299
  var turnMarker = (input) => {
19253
19300
  if (!input.session.id)
19254
19301
  return null;
@@ -19257,32 +19304,32 @@ var turnMarker = (input) => {
19257
19304
  if (location instanceof Error)
19258
19305
  return null;
19259
19306
  const session = [input.host, input.session.id, input.session.agentId ?? ""].join("\x00");
19260
- return path20.join(location.dir, "hooks", `turn-${digestOf(session).slice(0, 32)}.json`);
19307
+ return path21.join(location.dir, "hooks", `turn-${digestOf(session).slice(0, 32)}.json`);
19261
19308
  } catch {
19262
19309
  return null;
19263
19310
  }
19264
19311
  };
19265
19312
  var writeTurnDigest = (file, digest) => {
19266
19313
  try {
19267
- fs15.mkdirSync(path20.dirname(file), { recursive: true });
19268
- fs15.writeFileSync(file, `${JSON.stringify({ digest })}
19314
+ fs16.mkdirSync(path21.dirname(file), { recursive: true });
19315
+ fs16.writeFileSync(file, `${JSON.stringify({ digest })}
19269
19316
  `);
19270
19317
  } catch {}
19271
19318
  };
19272
19319
  var clearTurnDigest = (file) => {
19273
19320
  try {
19274
- fs15.rmSync(file, { force: true });
19321
+ fs16.rmSync(file, { force: true });
19275
19322
  } catch {}
19276
19323
  };
19277
19324
  var pruneTurnDigests = (dir, now) => {
19278
19325
  try {
19279
- for (const name of fs15.readdirSync(dir)) {
19326
+ for (const name of fs16.readdirSync(dir)) {
19280
19327
  if (!name.startsWith("turn-"))
19281
19328
  continue;
19282
- const file = path20.join(dir, name);
19329
+ const file = path21.join(dir, name);
19283
19330
  try {
19284
- if (now - fs15.statSync(file).mtimeMs > TURN_TTL_MS)
19285
- fs15.rmSync(file, { force: true });
19331
+ if (now - fs16.statSync(file).mtimeMs > TURN_TTL_MS)
19332
+ fs16.rmSync(file, { force: true });
19286
19333
  } catch {}
19287
19334
  }
19288
19335
  } catch {}
@@ -19298,7 +19345,7 @@ var changedTurnContext = (input, text) => {
19298
19345
  return text;
19299
19346
  const digest = digestOf(text);
19300
19347
  try {
19301
- const previous = JSON.parse(fs15.readFileSync(file, "utf8"));
19348
+ const previous = JSON.parse(fs16.readFileSync(file, "utf8"));
19302
19349
  if (previous.digest === digest)
19303
19350
  return null;
19304
19351
  } catch {}
@@ -19309,7 +19356,7 @@ var seedTurnContext = (input, descriptor, text = turnContextText(input, descript
19309
19356
  const file = turnMarker(input);
19310
19357
  if (!file)
19311
19358
  return;
19312
- pruneTurnDigests(path20.dirname(file), Date.now());
19359
+ pruneTurnDigests(path21.dirname(file), Date.now());
19313
19360
  if (text)
19314
19361
  writeTurnDigest(file, digestOf(text));
19315
19362
  else
@@ -19322,7 +19369,7 @@ var shellPolicy = (cwd, command) => {
19322
19369
  };
19323
19370
  // packages/workit-core/src/hooks/write-gate.ts
19324
19371
  import { realpathSync as realpathSync6 } from "node:fs";
19325
- import path21 from "node:path";
19372
+ import path22 from "node:path";
19326
19373
 
19327
19374
  // packages/workit-core/src/hooks/shell-words.ts
19328
19375
  var closingQuote = (command, start, dialect) => {
@@ -19452,22 +19499,22 @@ var NONE2 = { kind: "none" };
19452
19499
  var CASE_INSENSITIVE = process.platform === "darwin" || process.platform === "win32";
19453
19500
  var canonical2 = (file) => {
19454
19501
  let rest = "";
19455
- for (let dir = path21.resolve(file);; dir = path21.dirname(dir)) {
19502
+ for (let dir = path22.resolve(file);; dir = path22.dirname(dir)) {
19456
19503
  try {
19457
- return path21.join(realpathSync6(dir), rest);
19504
+ return path22.join(realpathSync6(dir), rest);
19458
19505
  } catch {
19459
- if (path21.dirname(dir) === dir)
19460
- return path21.resolve(file);
19461
- rest = rest ? path21.join(path21.basename(dir), rest) : path21.basename(dir);
19506
+ if (path22.dirname(dir) === dir)
19507
+ return path22.resolve(file);
19508
+ rest = rest ? path22.join(path22.basename(dir), rest) : path22.basename(dir);
19462
19509
  }
19463
19510
  }
19464
19511
  };
19465
19512
  var exempt = (cwd, root, file, plans) => {
19466
19513
  const fold = (value) => CASE_INSENSITIVE ? value.toLowerCase() : value;
19467
- const relative = path21.relative(fold(canonical2(root)), fold(canonical2(path21.resolve(cwd, file))));
19468
- if (relative.startsWith("..") || path21.isAbsolute(relative))
19514
+ const relative = path22.relative(fold(canonical2(root)), fold(canonical2(path22.resolve(cwd, file))));
19515
+ if (relative.startsWith("..") || path22.isAbsolute(relative))
19469
19516
  return true;
19470
- const posix = relative.split(path21.sep).join("/");
19517
+ const posix = relative.split(path22.sep).join("/");
19471
19518
  const segments = posix.split("/");
19472
19519
  return /\.mdx?$/i.test(posix) || segments[0] === "docs" || segments.includes("plans") || [...plans].some((plan) => fold(plan) === posix);
19473
19520
  };
@@ -19565,7 +19612,7 @@ var shellWrites = (command) => {
19565
19612
  return { writes: true, targets: unknown ? null : targets };
19566
19613
  };
19567
19614
  var cache2 = new Map;
19568
- var planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(path21.resolve(root, file)) ?? "-").join("\x00");
19615
+ var planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(path22.resolve(root, file)) ?? "-").join("\x00");
19569
19616
  var gateFor = (cwd) => {
19570
19617
  const store = new TaskStore(cwd);
19571
19618
  const listed = store.listTaskIndex();
@@ -19625,15 +19672,15 @@ import { spawnSync as spawnSync16 } from "node:child_process";
19625
19672
 
19626
19673
  // packages/workit-core/src/hooks/raw-git.ts
19627
19674
  import { spawnSync as spawnSync15 } from "node:child_process";
19628
- import { createHash as createHash13 } from "node:crypto";
19629
- import fs17 from "node:fs";
19675
+ import { createHash as createHash14 } from "node:crypto";
19676
+ import fs18 from "node:fs";
19630
19677
  import os4 from "node:os";
19631
- import path23 from "node:path";
19678
+ import path24 from "node:path";
19632
19679
 
19633
19680
  // packages/workit-core/src/hooks/session-marker.ts
19634
- import { createHash as createHash12 } from "node:crypto";
19635
- import fs16 from "node:fs";
19636
- import path22 from "node:path";
19681
+ import { createHash as createHash13 } from "node:crypto";
19682
+ import fs17 from "node:fs";
19683
+ import path23 from "node:path";
19637
19684
  var sessionMarkerFile = (input, session, store) => {
19638
19685
  let dir = store;
19639
19686
  if (dir === undefined) {
@@ -19642,13 +19689,13 @@ var sessionMarkerFile = (input, session, store) => {
19642
19689
  return null;
19643
19690
  dir = location.dir;
19644
19691
  }
19645
- const name = createHash12("sha256").update(`${input.host}\x00${session}`).digest("hex").slice(0, 32);
19646
- return path22.join(dir, "hooks", `skills-${name}.json`);
19692
+ const name = createHash13("sha256").update(`${input.host}\x00${session}`).digest("hex").slice(0, 32);
19693
+ return path23.join(dir, "hooks", `skills-${name}.json`);
19647
19694
  };
19648
19695
  var list2 = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
19649
19696
  var readSessionMarker = (file) => {
19650
19697
  try {
19651
- const value = JSON.parse(fs16.readFileSync(file, "utf8"));
19698
+ const value = JSON.parse(fs17.readFileSync(file, "utf8"));
19652
19699
  return { nudged: list2(value.nudged), loaded: list2(value.loaded), raw: list2(value.raw) };
19653
19700
  } catch {
19654
19701
  return { nudged: [], loaded: [], raw: [] };
@@ -19656,8 +19703,8 @@ var readSessionMarker = (file) => {
19656
19703
  };
19657
19704
  var writeSessionMarker = (file, marker) => {
19658
19705
  try {
19659
- fs16.mkdirSync(path22.dirname(file), { recursive: true });
19660
- fs16.writeFileSync(file, JSON.stringify(marker));
19706
+ fs17.mkdirSync(path23.dirname(file), { recursive: true });
19707
+ fs17.writeFileSync(file, JSON.stringify(marker));
19661
19708
  } catch {}
19662
19709
  };
19663
19710
 
@@ -19678,12 +19725,12 @@ var GIT_VALUE_OPTIONS = new Set([
19678
19725
  "--config-env",
19679
19726
  "--super-prefix"
19680
19727
  ]);
19681
- var isAbsolute = (value) => path23.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\");
19728
+ var isAbsolute = (value) => path24.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\");
19682
19729
  var joinDir = (base, next) => {
19683
19730
  if (base === undefined || /[$`*?]/.test(next) || next === "-")
19684
19731
  return;
19685
- const expanded = next === "~" || next.startsWith("~/") ? path23.join(os4.homedir(), next.slice(1)) : next;
19686
- return base === null || isAbsolute(expanded) ? expanded : path23.join(base, expanded);
19732
+ const expanded = next === "~" || next.startsWith("~/") ? path24.join(os4.homedir(), next.slice(1)) : next;
19733
+ return base === null || isAbsolute(expanded) ? expanded : path24.join(base, expanded);
19687
19734
  };
19688
19735
  var cdTarget = (words) => {
19689
19736
  const args = words.slice(1);
@@ -19936,7 +19983,7 @@ var repoAt = (dir) => {
19936
19983
  return { location, dir, branch: resolveTaskKey(dir, location).branch };
19937
19984
  };
19938
19985
  var isWorkitWorkspace = (repo) => {
19939
- if (fs17.existsSync(repo.location.dir))
19986
+ if (fs18.existsSync(repo.location.dir))
19940
19987
  return true;
19941
19988
  try {
19942
19989
  return resolveRuntimeWorkspaceVcs(repo.location.top ?? repo.dir) !== null;
@@ -19967,17 +20014,17 @@ var headSha2 = (repo) => {
19967
20014
  if (!git || git.reftable)
19968
20015
  return null;
19969
20016
  try {
19970
- const head = fs17.readFileSync(path23.join(git.gitDir, "HEAD"), "utf8").trim();
20017
+ const head = fs18.readFileSync(path24.join(git.gitDir, "HEAD"), "utf8").trim();
19971
20018
  if (/^[0-9a-f]{40,64}$/.test(head))
19972
20019
  return head;
19973
20020
  const ref = /^ref: (refs\/.+)$/.exec(head)?.[1];
19974
20021
  if (!ref)
19975
20022
  return null;
19976
- const common = path23.dirname(repo.location.dir);
20023
+ const common = path24.dirname(repo.location.dir);
19977
20024
  try {
19978
- return fs17.readFileSync(path23.join(common, ref), "utf8").trim() || null;
20025
+ return fs18.readFileSync(path24.join(common, ref), "utf8").trim() || null;
19979
20026
  } catch {}
19980
- const packed = fs17.readFileSync(path23.join(common, "packed-refs"), "utf8");
20027
+ const packed = fs18.readFileSync(path24.join(common, "packed-refs"), "utf8");
19981
20028
  return new RegExp(`^([0-9a-f]{40,64}) ${ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`, "m").exec(packed)?.[1] ?? null;
19982
20029
  } catch {
19983
20030
  return null;
@@ -20014,7 +20061,7 @@ var actionsIn = (cwd, command, dialect) => {
20014
20061
  const action = rawAction(invocation);
20015
20062
  if (!action)
20016
20063
  continue;
20017
- const dir = path23.resolve(cwd, invocation.dir ?? ".");
20064
+ const dir = path24.resolve(cwd, invocation.dir ?? ".");
20018
20065
  if (!repos.has(dir)) {
20019
20066
  const repo = repoAt(dir);
20020
20067
  repos.set(dir, repo && isWorkitWorkspace(repo) ? repo : null);
@@ -20083,8 +20130,8 @@ function rawGitPre(input, command, options = {}) {
20083
20130
  var deny = (reason) => ({ kind: "deny", reason, unblock: null });
20084
20131
  var NEXT_COMMAND = "next";
20085
20132
  var MARKER_TTL_SECONDS = 3600;
20086
- var markerFile = (repo, session, key) => path23.join(repo.location.dir, "hooks", `commit-${createHash13("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`);
20087
- var callKey = (toolUseId, command) => toolUseId ?? `cmd:${createHash13("sha256").update(command).digest("hex")}`;
20133
+ var markerFile = (repo, session, key) => path24.join(repo.location.dir, "hooks", `commit-${createHash14("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`);
20134
+ var callKey = (toolUseId, command) => toolUseId ?? `cmd:${createHash14("sha256").update(command).digest("hex")}`;
20088
20135
  function noteRawCommit(input, command, key) {
20089
20136
  try {
20090
20137
  if (!input.session.id || !/\bcommit\b/.test(command))
@@ -20094,8 +20141,8 @@ function noteRawCommit(input, command, key) {
20094
20141
  if (action.kind !== "commit")
20095
20142
  continue;
20096
20143
  const file = markerFile(repo, input.session.id, key);
20097
- fs17.mkdirSync(path23.dirname(file), { recursive: true });
20098
- fs17.writeFileSync(file, `${JSON.stringify({ head: headSha2(repo), at })}
20144
+ fs18.mkdirSync(path24.dirname(file), { recursive: true });
20145
+ fs18.writeFileSync(file, `${JSON.stringify({ head: headSha2(repo), at })}
20099
20146
  `);
20100
20147
  }
20101
20148
  } catch {}
@@ -20118,11 +20165,11 @@ var headCommit = (dir) => {
20118
20165
  var settle2 = (input, repo, file) => {
20119
20166
  let marker;
20120
20167
  try {
20121
- marker = JSON.parse(fs17.readFileSync(file, "utf8"));
20168
+ marker = JSON.parse(fs18.readFileSync(file, "utf8"));
20122
20169
  } catch {
20123
20170
  return;
20124
20171
  }
20125
- fs17.rmSync(file, { force: true });
20172
+ fs18.rmSync(file, { force: true });
20126
20173
  const session = input.session.id;
20127
20174
  const now = Date.now() / 1000;
20128
20175
  if (typeof marker.at !== "number" || now - marker.at > MARKER_TTL_SECONDS)
@@ -20171,7 +20218,7 @@ function settlePendingCommit(input) {
20171
20218
  if (!repo)
20172
20219
  return;
20173
20220
  const file = markerFile(repo, input.session.id, NEXT_COMMAND);
20174
- if (fs17.existsSync(file))
20221
+ if (fs18.existsSync(file))
20175
20222
  settle2(input, repo, file);
20176
20223
  } catch {}
20177
20224
  }
@@ -20629,6 +20676,8 @@ ${subagentStartText({ ...input, cwd: "" }, descriptor, event)}`;
20629
20676
  if (role !== "judge" || !event.agentId)
20630
20677
  return readOnly;
20631
20678
  const own = subagentSession(session, event.agentId);
20679
+ if (session)
20680
+ recordIssuedSession(input.cwd || process.cwd(), session, own);
20632
20681
  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.`;
20633
20682
  };
20634
20683
  function handleHook(input, deps) {
@@ -20990,12 +21039,12 @@ var skillPromptNudge = (prompt, ctx) => process.env.WORKIT_PI_WORKER_SESSION ? n
20990
21039
  // packages/workit-pi/src/launches.ts
20991
21040
  import { mkdirSync as mkdirSync3, readFileSync as readFileSync6, readdirSync as readdirSync5, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
20992
21041
  import os5 from "node:os";
20993
- import path24 from "node:path";
21042
+ import path25 from "node:path";
20994
21043
  var launchDir = (root) => {
20995
21044
  const location = resolveStore(root);
20996
- return location instanceof Error ? null : path24.join(location.dir, "pi-launches");
21045
+ return location instanceof Error ? null : path25.join(location.dir, "pi-launches");
20997
21046
  };
20998
- var fileFor = (dir, workerId) => path24.join(dir, `${workerId.replace(/[^A-Za-z0-9-]/g, "_")}.json`);
21047
+ var fileFor = (dir, workerId) => path25.join(dir, `${workerId.replace(/[^A-Za-z0-9-]/g, "_")}.json`);
20999
21048
  var recordLaunch = (root, attempt) => {
21000
21049
  const dir = launchDir(root);
21001
21050
  if (!dir)
@@ -21041,7 +21090,7 @@ var abandonedLaunches = (root) => {
21041
21090
  const found = [];
21042
21091
  for (const name of names) {
21043
21092
  try {
21044
- const attempt = JSON.parse(readFileSync6(path24.join(dir, name), "utf8"));
21093
+ const attempt = JSON.parse(readFileSync6(path25.join(dir, name), "utf8"));
21045
21094
  if (typeof attempt.workerId === "string" && typeof attempt.session === "string") {
21046
21095
  if (!alive(attempt))
21047
21096
  found.push(attempt);
@@ -21215,7 +21264,7 @@ function launchWorker(assignment, options) {
21215
21264
  WORKIT_PI_WORKER_ID: workerId ?? "",
21216
21265
  WORKIT_PI_WORKER_SESSION: sessionId,
21217
21266
  WORKIT_HOST: "pi",
21218
- WORKIT_SESSION_ID: sessionId,
21267
+ WORKIT_SESSION_ID: options.leadSession ? childSessionId(options.leadSession, sessionId) : sessionId,
21219
21268
  WORKIT_PI_WORKER_ROLE: assignment.role,
21220
21269
  WORKIT_PI_WORKER_SCOPE: JSON.stringify(assignment.scope)
21221
21270
  };
@@ -21762,6 +21811,7 @@ function extension(pi) {
21762
21811
  const handle = launchSupervisedWorker(worker.data.assignment, {
21763
21812
  runtime: runtimeFor(ctx),
21764
21813
  binding,
21814
+ leadSession: ctx.sessionManager.getSessionId(),
21765
21815
  prompt: request.prompt,
21766
21816
  onPrepare: (pending) => {
21767
21817
  child = pending;