@brainervirus/workit-pi 8.11.0 → 8.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 spawnSync16 } from "node:child_process";
7
7
  import { existsSync as existsSync8, realpathSync as realpathSync5 } from "node:fs";
8
- import path23 from "node:path";
8
+ import path24 from "node:path";
9
9
 
10
10
  // packages/workit-core/src/core/task-contract.ts
11
11
  import { createHash, randomUUID } from "node:crypto";
@@ -8993,7 +8993,7 @@ function parseAdvertisedOperation(family, input, host) {
8993
8993
  // packages/workit-core/src/core/task-store.ts
8994
8994
  import { createHash as createHash5, randomUUID as randomUUID3 } from "node:crypto";
8995
8995
  import * as fs8 from "node:fs";
8996
- import path7 from "node:path";
8996
+ import path8 from "node:path";
8997
8997
 
8998
8998
  // node_modules/@openclaw/fs-safe/dist/errors.js
8999
8999
  var OPERATIONAL_CODES = new Set([
@@ -9599,13 +9599,72 @@ function acquireFileLockSync(targetPath, options) {
9599
9599
  // packages/workit-core/src/host-session.ts
9600
9600
  import { createHash as createHash3 } from "node:crypto";
9601
9601
  import fs5 from "node:fs";
9602
- import path4 from "node:path";
9602
+ import path5 from "node:path";
9603
+
9604
+ // packages/workit-core/src/core/logger.ts
9605
+ import os from "node:os";
9606
+ import path3 from "node:path";
9607
+ var SENSITIVE_WORDS = new Set([
9608
+ "token",
9609
+ "secret",
9610
+ "password",
9611
+ "passwd",
9612
+ "authorization",
9613
+ "credential",
9614
+ "credentials",
9615
+ "cookie",
9616
+ "api",
9617
+ "apikey",
9618
+ "apitoken",
9619
+ "accesstoken",
9620
+ "clientsecret",
9621
+ "refreshtoken",
9622
+ "key",
9623
+ "bearer",
9624
+ "prompt",
9625
+ "message",
9626
+ "messages",
9627
+ "content",
9628
+ "body",
9629
+ "args",
9630
+ "argument",
9631
+ "result",
9632
+ "results",
9633
+ "output",
9634
+ "issue",
9635
+ "description",
9636
+ "summary",
9637
+ "payload",
9638
+ "script",
9639
+ "command",
9640
+ "text",
9641
+ "query"
9642
+ ]);
9643
+ var STACK_WORDS = new Set(["stack", "stacktrace", "trace"]);
9644
+ var escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
9645
+ var resolveStateDir = () => {
9646
+ const override = process.env.WORKFLOW_TOOLKIT_STATE;
9647
+ if (override)
9648
+ return override;
9649
+ const home = os.homedir();
9650
+ if (process.env.XDG_STATE_HOME)
9651
+ return path3.join(process.env.XDG_STATE_HOME, "workit");
9652
+ switch (os.platform()) {
9653
+ case "darwin":
9654
+ return path3.join(home, "Library", "Application Support", "workit");
9655
+ case "win32":
9656
+ return path3.join(process.env.LOCALAPPDATA ?? path3.join(home, "AppData", "Local"), "workit");
9657
+ default:
9658
+ return path3.join(process.env.HOME ?? home, ".local", "state", "workit");
9659
+ }
9660
+ };
9661
+ var homePattern = new RegExp(`${escapeRegExp(os.homedir())}(?=[/\\\\]|$)|\\$HOME(?=[/\\\\]|$)`, "g");
9603
9662
 
9604
9663
  // packages/workit-core/src/store/paths.ts
9605
9664
  import { spawnSync } from "node:child_process";
9606
9665
  import { createHash as createHash2 } from "node:crypto";
9607
9666
  import fs4 from "node:fs";
9608
- import path3 from "node:path";
9667
+ import path4 from "node:path";
9609
9668
  var NOT_A_REPO = /not a git repository \(or any (of the parent directories|parent up to)/u;
9610
9669
  var gitRun = (cwd, args) => {
9611
9670
  const run = spawnSync("git", args, {
@@ -9647,14 +9706,14 @@ var DISCOVERY_ENV = [
9647
9706
  ];
9648
9707
  var isGitDir = (dir) => {
9649
9708
  try {
9650
- return fs4.statSync(path3.join(dir, "HEAD")).isFile() && fs4.statSync(path3.join(dir, "objects")).isDirectory() && fs4.statSync(path3.join(dir, "refs")).isDirectory();
9709
+ return fs4.statSync(path4.join(dir, "HEAD")).isFile() && fs4.statSync(path4.join(dir, "objects")).isDirectory() && fs4.statSync(path4.join(dir, "refs")).isDirectory();
9651
9710
  } catch {
9652
9711
  return false;
9653
9712
  }
9654
9713
  };
9655
9714
  var reftableRefs = (common) => {
9656
9715
  try {
9657
- return /^\s*refstorage\s*=\s*reftable\s*$/imu.test(fs4.readFileSync(path3.join(common, "config"), "utf8"));
9716
+ return /^\s*refstorage\s*=\s*reftable\s*$/imu.test(fs4.readFileSync(path4.join(common, "config"), "utf8"));
9658
9717
  } catch {
9659
9718
  return false;
9660
9719
  }
@@ -9674,7 +9733,7 @@ function fastGit(root) {
9674
9733
  if (device !== null && stat.dev !== device)
9675
9734
  return { kind: "none" };
9676
9735
  device = stat.dev;
9677
- const dotGit = path3.join(dir, ".git");
9736
+ const dotGit = path4.join(dir, ".git");
9678
9737
  let entry = null;
9679
9738
  try {
9680
9739
  entry = fs4.statSync(dotGit);
@@ -9695,19 +9754,19 @@ function fastGit(root) {
9695
9754
  const match = /^gitdir: (.+)$/mu.exec(text);
9696
9755
  if (!match)
9697
9756
  return null;
9698
- gitDir = path3.resolve(dir, match[1].trim());
9757
+ gitDir = path4.resolve(dir, match[1].trim());
9699
9758
  } else
9700
9759
  return null;
9701
- if (!fs4.existsSync(path3.join(gitDir, "HEAD")))
9760
+ if (!fs4.existsSync(path4.join(gitDir, "HEAD")))
9702
9761
  return null;
9703
9762
  } else if (isGitDir(dir))
9704
9763
  gitDir = dir;
9705
9764
  if (gitDir) {
9706
9765
  let common = gitDir;
9707
9766
  try {
9708
- common = path3.resolve(gitDir, fs4.readFileSync(path3.join(gitDir, "commondir"), "utf8").trim());
9767
+ common = path4.resolve(gitDir, fs4.readFileSync(path4.join(gitDir, "commondir"), "utf8").trim());
9709
9768
  } catch {}
9710
- if (!fs4.existsSync(path3.join(common, "objects")))
9769
+ if (!fs4.existsSync(path4.join(common, "objects")))
9711
9770
  return null;
9712
9771
  return {
9713
9772
  kind: "repo",
@@ -9717,26 +9776,26 @@ function fastGit(root) {
9717
9776
  reftable: reftableRefs(common)
9718
9777
  };
9719
9778
  }
9720
- const parent = path3.dirname(dir);
9779
+ const parent = path4.dirname(dir);
9721
9780
  if (parent === dir)
9722
9781
  return { kind: "none" };
9723
9782
  dir = parent;
9724
9783
  }
9725
9784
  }
9726
9785
  function resolveStore(root) {
9727
- root = path3.resolve(root);
9786
+ root = path4.resolve(root);
9728
9787
  let directory = false;
9729
9788
  try {
9730
9789
  directory = fs4.statSync(root).isDirectory();
9731
9790
  } catch {}
9732
9791
  if (!directory)
9733
- return { dir: path3.join(root, ".workit"), shared: false, top: null };
9792
+ return { dir: path4.join(root, ".workit"), shared: false, top: null };
9734
9793
  const fast = fastGit(root);
9735
9794
  if (fast?.kind === "none")
9736
- return { dir: path3.join(root, ".workit"), shared: false, top: null };
9795
+ return { dir: path4.join(root, ".workit"), shared: false, top: null };
9737
9796
  if (fast?.kind === "repo")
9738
9797
  return {
9739
- dir: path3.join(fast.common, "workit"),
9798
+ dir: path4.join(fast.common, "workit"),
9740
9799
  shared: true,
9741
9800
  top: fast.top,
9742
9801
  git: { gitDir: fast.gitDir, top: fast.top, reftable: fast.reftable }
@@ -9746,20 +9805,20 @@ function resolveStore(root) {
9746
9805
  if (run.ok && common) {
9747
9806
  const top = gitRun(root, ["rev-parse", "--path-format=absolute", "--show-toplevel"]);
9748
9807
  return {
9749
- dir: path3.join(real(path3.resolve(root, common)), "workit"),
9808
+ dir: path4.join(real(path4.resolve(root, common)), "workit"),
9750
9809
  shared: true,
9751
9810
  top: top.ok && top.stdout.trim() ? real(top.stdout.trim()) : null
9752
9811
  };
9753
9812
  }
9754
9813
  if (run.missing || !run.ok && NOT_A_REPO.test(run.stderr))
9755
- return { dir: path3.join(root, ".workit"), shared: false, top: null };
9814
+ return { dir: path4.join(root, ".workit"), shared: false, top: null };
9756
9815
  return new Error(`cannot locate the workit store: git rev-parse failed (${run.stderr.trim().split(`
9757
9816
  `)[0] || "no output"}); fix the repository (git status should work here)`);
9758
9817
  }
9759
9818
  var rebasingBranch = (gitDir) => {
9760
9819
  for (const state of ["rebase-merge", "rebase-apply"]) {
9761
9820
  try {
9762
- const ref = fs4.readFileSync(path3.join(gitDir, state, "head-name"), "utf8").trim();
9821
+ const ref = fs4.readFileSync(path4.join(gitDir, state, "head-name"), "utf8").trim();
9763
9822
  const match = /^refs\/heads\/(.+)$/u.exec(ref);
9764
9823
  if (match)
9765
9824
  return match[1];
@@ -9774,7 +9833,7 @@ function resolveTaskKey(root, location) {
9774
9833
  if (location.git && !location.git.reftable) {
9775
9834
  let head = "";
9776
9835
  try {
9777
- head = fs4.readFileSync(path3.join(location.git.gitDir, "HEAD"), "utf8").trim();
9836
+ head = fs4.readFileSync(path4.join(location.git.gitDir, "HEAD"), "utf8").trim();
9778
9837
  } catch {}
9779
9838
  const ref = /^ref: refs\/heads\/(.+)$/u.exec(head);
9780
9839
  if (ref && ref[1] !== ".invalid")
@@ -9805,7 +9864,7 @@ function resolveTaskKey(root, location) {
9805
9864
  return { key: `detached-${shortHash(real(worktree))}`, kind: "detached", branch: null };
9806
9865
  }
9807
9866
  function checkoutRootOf(root, location) {
9808
- const resolved = path3.resolve(root);
9867
+ const resolved = path4.resolve(root);
9809
9868
  let canonical = resolved;
9810
9869
  try {
9811
9870
  canonical = fs4.realpathSync(resolved);
@@ -9836,13 +9895,13 @@ function branchRenames(location) {
9836
9895
  }
9837
9896
  for (const entry of entries)
9838
9897
  if (entry.isDirectory())
9839
- walk(path3.join(dir, entry.name));
9898
+ walk(path4.join(dir, entry.name));
9840
9899
  else
9841
- files.push(path3.join(dir, entry.name));
9900
+ files.push(path4.join(dir, entry.name));
9842
9901
  };
9843
- walk(path3.join(path3.dirname(location.dir), "logs", "refs", "heads"));
9902
+ walk(path4.join(path4.dirname(location.dir), "logs", "refs", "heads"));
9844
9903
  if (location.git)
9845
- files.push(path3.join(location.git.gitDir, "logs", "HEAD"));
9904
+ files.push(path4.join(location.git.gitDir, "logs", "HEAD"));
9846
9905
  const seen = new Set;
9847
9906
  const renames = [];
9848
9907
  for (const file of files) {
@@ -9877,7 +9936,7 @@ var checkoutSlug = (root) => {
9877
9936
  let canonical = real(root);
9878
9937
  if (process.platform === "win32")
9879
9938
  canonical = canonical.toLowerCase();
9880
- const base = path3.basename(canonical).replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 40) || "root";
9939
+ const base = path4.basename(canonical).replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 40) || "root";
9881
9940
  return `${base}-${shortHash(canonical)}`;
9882
9941
  };
9883
9942
 
@@ -9910,30 +9969,64 @@ function hostSessionFromEnv(env) {
9910
9969
  return inner ? { host: inner.host, session: inner.session } : { host: declared, session: null };
9911
9970
  }
9912
9971
  var ISSUED_PER_LEAD = 64;
9913
- var ISSUED_SESSIONS_MARKER = "workit-issued-sessions/1";
9972
+ var ISSUED_SESSIONS_MARKER = "workit-issued-sessions/2";
9914
9973
  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");
9974
+ var userIssuedRoot = () => path5.join(resolveStateDir(), "issued");
9975
+ function migrateRepoIssued(cwd) {
9976
+ if (cwd === undefined)
9977
+ return;
9978
+ let old;
9979
+ try {
9980
+ const location = resolveStore(cwd);
9981
+ if (location instanceof Error)
9982
+ return;
9983
+ old = path5.join(location.dir, "hooks", "issued");
9984
+ if (!fs5.existsSync(old))
9985
+ return;
9986
+ } catch {
9987
+ return;
9988
+ }
9989
+ for (const lead of safeList(old)) {
9990
+ try {
9991
+ const from = path5.join(old, lead);
9992
+ if (!fs5.statSync(from).isDirectory())
9993
+ continue;
9994
+ const to = path5.join(userIssuedRoot(), lead);
9995
+ fs5.mkdirSync(to, { recursive: true, mode: 448 });
9996
+ for (const id of fs5.readdirSync(from)) {
9997
+ fs5.copyFileSync(path5.join(from, id), path5.join(to, id));
9998
+ fs5.rmSync(path5.join(from, id), { force: true });
9999
+ }
10000
+ removeIfEmpty(from);
10001
+ } catch {}
10002
+ }
10003
+ removeIfEmpty(old);
10004
+ }
10005
+ var safeList = (dir) => {
10006
+ try {
10007
+ return fs5.readdirSync(dir);
10008
+ } catch {
10009
+ return [];
10010
+ }
9918
10011
  };
9919
- var issuedDir = (cwd, lead) => {
9920
- const root = issuedRoot(cwd);
9921
- return root === null ? null : path4.join(root, hash(lead));
10012
+ var removeIfEmpty = (dir) => {
10013
+ try {
10014
+ fs5.rmdirSync(dir);
10015
+ } catch {}
9922
10016
  };
9923
10017
  function recordIssuedSession(cwd, lead, issued) {
9924
10018
  try {
9925
- const dir = issuedDir(cwd, lead);
9926
- if (!dir)
9927
- return;
9928
- fs5.mkdirSync(dir, { recursive: true });
10019
+ migrateRepoIssued(cwd);
10020
+ const dir = path5.join(userIssuedRoot(), hash(lead));
10021
+ fs5.mkdirSync(dir, { recursive: true, mode: 448 });
9929
10022
  const own = hash(issued);
9930
- fs5.writeFileSync(path4.join(dir, own), ISSUED_SESSIONS_MARKER);
10023
+ fs5.writeFileSync(path5.join(dir, own), ISSUED_SESSIONS_MARKER);
9931
10024
  const entries = fs5.readdirSync(dir);
9932
10025
  if (entries.length <= ISSUED_PER_LEAD)
9933
10026
  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);
10027
+ const byAge = entries.filter((name) => name !== own).map((name) => ({ name, at: fs5.statSync(path5.join(dir, name)).mtimeMs })).toSorted((a, b) => a.at - b.at);
9935
10028
  for (const { name } of byAge.slice(0, entries.length - ISSUED_PER_LEAD))
9936
- fs5.rmSync(path4.join(dir, name), { force: true });
10029
+ fs5.rmSync(path5.join(dir, name), { force: true });
9937
10030
  } catch {}
9938
10031
  }
9939
10032
  var OWN_CHILD_SHELL = new Set(["opencode", "pi"]);
@@ -9946,20 +10039,20 @@ function childSessionId(lead, child) {
9946
10039
 
9947
10040
  // packages/workit-core/src/core/package-root.ts
9948
10041
  import { existsSync } from "node:fs";
9949
- import path5 from "node:path";
10042
+ import path6 from "node:path";
9950
10043
  import { fileURLToPath } from "node:url";
9951
10044
  var packageRoot = () => {
9952
- let dir = path5.dirname(fileURLToPath(import.meta.url));
10045
+ let dir = path6.dirname(fileURLToPath(import.meta.url));
9953
10046
  while (true) {
9954
- const parent = path5.dirname(dir);
9955
- if (existsSync(path5.join(dir, "package.json")) || parent === dir)
10047
+ const parent = path6.dirname(dir);
10048
+ if (existsSync(path6.join(dir, "package.json")) || parent === dir)
9956
10049
  return dir;
9957
10050
  dir = parent;
9958
10051
  }
9959
10052
  };
9960
10053
  var assetRoot = () => {
9961
10054
  const root = packageRoot();
9962
- const assets = path5.join(root, "assets");
10055
+ const assets = path6.join(root, "assets");
9963
10056
  return existsSync(assets) ? assets : root;
9964
10057
  };
9965
10058
 
@@ -10106,7 +10199,7 @@ var clearAbandonedReclaimGuard = (lockPath, nowMs = Date.now()) => {
10106
10199
  // packages/workit-core/src/store/event-log.ts
10107
10200
  import { randomUUID as randomUUID2 } from "node:crypto";
10108
10201
  import fs7 from "node:fs";
10109
- import path6 from "node:path";
10202
+ import path7 from "node:path";
10110
10203
  var EVENT_VERSION = 1;
10111
10204
 
10112
10205
  class LogDamage extends Error {
@@ -10217,7 +10310,7 @@ function appendEvent(file, event, validEnd) {
10217
10310
  fs7.closeSync(fd);
10218
10311
  }
10219
10312
  if (created)
10220
- fsyncDirectory(path6.dirname(file));
10313
+ fsyncDirectory(path7.dirname(file));
10221
10314
  return validEnd;
10222
10315
  }
10223
10316
  function replaceFile(file, bytes, durable) {
@@ -10233,7 +10326,7 @@ function replaceFile(file, bytes, durable) {
10233
10326
  }
10234
10327
  renameWithRetry(temporary, file);
10235
10328
  if (durable)
10236
- fsyncDirectory(path6.dirname(file));
10329
+ fsyncDirectory(path7.dirname(file));
10237
10330
  } catch (error) {
10238
10331
  try {
10239
10332
  fs7.unlinkSync(temporary);
@@ -10576,7 +10669,7 @@ var cachedRuntimeVersion = null;
10576
10669
  var runtimeVersion = () => {
10577
10670
  if (cachedRuntimeVersion === null) {
10578
10671
  try {
10579
- const pkg = JSON.parse(fs8.readFileSync(path7.join(packageRoot(), "package.json"), "utf8"));
10672
+ const pkg = JSON.parse(fs8.readFileSync(path8.join(packageRoot(), "package.json"), "utf8"));
10580
10673
  cachedRuntimeVersion = typeof pkg.version === "string" && pkg.version ? pkg.version : "0.0.0";
10581
10674
  } catch {
10582
10675
  cachedRuntimeVersion = "0.0.0";
@@ -10609,7 +10702,7 @@ var readText = (file) => {
10609
10702
  };
10610
10703
  var REFLOG_LINE = /^[0-9a-f]+ ([0-9a-f]+) .* (\d+) [+-]\d{4}\t(.*)$/u;
10611
10704
  var branchStart = (location, branch, aliases) => {
10612
- const first = readText(path7.join(path7.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
10705
+ const first = readText(path8.join(path8.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
10613
10706
  `, 1)[0];
10614
10707
  const created = REFLOG_LINE.exec(first);
10615
10708
  const start = created && /^branch: Created from (\S+)$/u.exec(created[3])?.[1];
@@ -10619,7 +10712,7 @@ var branchStart = (location, branch, aliases) => {
10619
10712
  return start;
10620
10713
  if (!location.git)
10621
10714
  return null;
10622
- for (const line of readText(path7.join(location.git.gitDir, "logs", "HEAD")).split(`
10715
+ for (const line of readText(path8.join(location.git.gitDir, "logs", "HEAD")).split(`
10623
10716
  `)) {
10624
10717
  const entry = REFLOG_LINE.exec(line);
10625
10718
  const moved = entry && /^checkout: moving from (\S+) to (\S+)$/u.exec(entry[3]);
@@ -10629,14 +10722,14 @@ var branchStart = (location, branch, aliases) => {
10629
10722
  }
10630
10723
  return null;
10631
10724
  };
10632
- var refExists = (common, ref) => fs8.existsSync(path7.join(common, ref)) || readText(path7.join(common, "packed-refs")).includes(` ${ref}
10725
+ var refExists = (common, ref) => fs8.existsSync(path8.join(common, ref)) || readText(path8.join(common, "packed-refs")).includes(` ${ref}
10633
10726
  `);
10634
10727
  var origins = new Map;
10635
10728
  var sameDirectoryIdentity = (left, right) => {
10636
- if (!path7.isAbsolute(left) || !path7.isAbsolute(right))
10729
+ if (!path8.isAbsolute(left) || !path8.isAbsolute(right))
10637
10730
  return false;
10638
- const normalizedLeft = path7.resolve(left);
10639
- const normalizedRight = path7.resolve(right);
10731
+ const normalizedLeft = path8.resolve(left);
10732
+ const normalizedRight = path8.resolve(right);
10640
10733
  try {
10641
10734
  const a = fs8.statSync(normalizedLeft, { bigint: true });
10642
10735
  const b = fs8.statSync(normalizedRight, { bigint: true });
@@ -10682,7 +10775,7 @@ class TaskStore {
10682
10775
  migrationChecked = false;
10683
10776
  compactDue = new Set;
10684
10777
  constructor(root, options = {}) {
10685
- const resolved = path7.resolve(root);
10778
+ const resolved = path8.resolve(root);
10686
10779
  this.origin = fs8.existsSync(resolved) ? fs8.realpathSync(resolved) : resolved;
10687
10780
  this.located = resolveStore(this.origin);
10688
10781
  this.root = checkoutRootOf(this.origin, this.located);
@@ -10691,7 +10784,7 @@ class TaskStore {
10691
10784
  this.migrateOnRead = options.migrateOnRead;
10692
10785
  }
10693
10786
  location() {
10694
- if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs8.existsSync(path7.join(this.root, ".git"))) {
10787
+ if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs8.existsSync(path8.join(this.root, ".git"))) {
10695
10788
  this.located = undefined;
10696
10789
  this.migrationChecked = false;
10697
10790
  }
@@ -10847,7 +10940,7 @@ class TaskStore {
10847
10940
  const moved = this.bindLocked(again.data.id, key, input.now);
10848
10941
  return moved.ok ? success(moved.data.revision, null, { task: moved.data, created: false, key }) : moved;
10849
10942
  }
10850
- const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path7.basename(this.root) || this.root;
10943
+ const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path8.basename(this.root) || this.root;
10851
10944
  const intent = {
10852
10945
  objective: input.objective?.trim() || `Work on ${label}`,
10853
10946
  scope: { description: `the checkout (${label})`, paths: ["."], exclusions: [] },
@@ -10907,14 +11000,14 @@ class TaskStore {
10907
11000
  const branch = key.ok ? key.data.branch : null;
10908
11001
  if (!branch || !location.ok)
10909
11002
  return success(null, null, null);
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") : "";
11003
+ const common = path8.dirname(location.data.dir);
11004
+ const heads = path8.join(common, "logs", "refs", "heads");
11005
+ const headLog = location.data.git ? path8.join(location.data.git.gitDir, "logs", "HEAD") : "";
10913
11006
  const signatures = [
10914
- path7.join(heads, branch),
11007
+ path8.join(heads, branch),
10915
11008
  headLog,
10916
11009
  heads,
10917
- path7.join(common, "packed-refs")
11010
+ path8.join(common, "packed-refs")
10918
11011
  ].map((file) => fileSignature(file) ?? "-");
10919
11012
  const slot = `${location.data.dir}\x00${headLog}\x00${branch}`;
10920
11013
  let resolved = origins.get(slot);
@@ -10926,7 +11019,7 @@ class TaskStore {
10926
11019
  aliases.push(rename.from);
10927
11020
  const start = branchStart(location.data, branch, aliases);
10928
11021
  const slash = start?.indexOf("/") ?? -1;
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)}"]`));
11022
+ const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(path8.join(common, "config")).includes(`[remote "${start.slice(0, slash)}"]`));
10930
11023
  const name = start && (remote ? start.slice(slash + 1) : start);
10931
11024
  resolved = {
10932
11025
  signature: signatures.join("|"),
@@ -11164,13 +11257,13 @@ class TaskStore {
11164
11257
  if (!ready.ok)
11165
11258
  return ready;
11166
11259
  const dirs = this.paths();
11167
- const recovery = path7.join(this.root, ".workit", "recovery");
11260
+ const recovery = path8.join(this.root, ".workit", "recovery");
11168
11261
  if (fs8.existsSync(recovery)) {
11169
11262
  let files = 0;
11170
11263
  let bytes = 0;
11171
11264
  try {
11172
11265
  for (const name of fs8.readdirSync(recovery)) {
11173
- const stat = fs8.lstatSync(path7.join(recovery, name));
11266
+ const stat = fs8.lstatSync(path8.join(recovery, name));
11174
11267
  if (!stat.isFile())
11175
11268
  continue;
11176
11269
  files += 1;
@@ -11223,7 +11316,7 @@ class TaskStore {
11223
11316
  if (fs8.existsSync(dirs.blobs))
11224
11317
  for (const name of fs8.readdirSync(dirs.blobs)) {
11225
11318
  const digest = name.replace(/\.json$/, "");
11226
- const file = path7.join(dirs.blobs, name);
11319
+ const file = path8.join(dirs.blobs, name);
11227
11320
  let stat;
11228
11321
  try {
11229
11322
  stat = fs8.lstatSync(file);
@@ -11241,7 +11334,7 @@ class TaskStore {
11241
11334
  }
11242
11335
  return success(null, null, null);
11243
11336
  };
11244
- const swept = dryRun ? sweep() : this.withLock(path7.join(dirs.dir, "gc.lock"), sweep);
11337
+ const swept = dryRun ? sweep() : this.withLock(path8.join(dirs.dir, "gc.lock"), sweep);
11245
11338
  if (!swept.ok)
11246
11339
  return swept;
11247
11340
  const temporaryDirs = [
@@ -11249,7 +11342,7 @@ class TaskStore {
11249
11342
  dirs.tasks,
11250
11343
  dirs.blobs,
11251
11344
  dirs.checkout,
11252
- ...names.map((name) => path7.join(dirs.tasks, name))
11345
+ ...names.map((name) => path8.join(dirs.tasks, name))
11253
11346
  ];
11254
11347
  for (const directory of temporaryDirs) {
11255
11348
  if (!fs8.existsSync(directory))
@@ -11257,7 +11350,7 @@ class TaskStore {
11257
11350
  for (const name of fs8.readdirSync(directory)) {
11258
11351
  if (!name.endsWith(".tmp") && !name.endsWith(".probe"))
11259
11352
  continue;
11260
- const file = path7.join(directory, name);
11353
+ const file = path8.join(directory, name);
11261
11354
  try {
11262
11355
  const stat = fs8.lstatSync(file);
11263
11356
  if (!stat.isFile() || nowMs - stat.mtimeMs <= STALE_TEMPORARY_MS)
@@ -11274,30 +11367,30 @@ class TaskStore {
11274
11367
  }
11275
11368
  paths() {
11276
11369
  const location = this.location();
11277
- const dir = location.ok ? location.data.dir : path7.join(this.root, ".workit");
11278
- const checkout = path7.join(dir, "checkouts", checkoutSlug(this.root));
11370
+ const dir = location.ok ? location.data.dir : path8.join(this.root, ".workit");
11371
+ const checkout = path8.join(dir, "checkouts", checkoutSlug(this.root));
11279
11372
  return {
11280
11373
  dir,
11281
11374
  shared: location.ok ? location.data.shared : false,
11282
- marker: path7.join(dir, "store.json"),
11375
+ marker: path8.join(dir, "store.json"),
11283
11376
  checkout,
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")
11377
+ workspace: path8.join(checkout, "workspace.json"),
11378
+ checkoutLock: path8.join(checkout, "metadata.lock"),
11379
+ tasks: path8.join(dir, "tasks"),
11380
+ index: path8.join(dir, "task-index.json"),
11381
+ blobs: path8.join(dir, "blobs", "candidates"),
11382
+ legacy: path8.join(dir, "legacy", checkoutSlug(this.root), "v2"),
11383
+ v2: path8.join(this.root, ".workit")
11291
11384
  };
11292
11385
  }
11293
11386
  eventsPath(taskId) {
11294
- return path7.join(this.paths().tasks, taskId, "events.jsonl");
11387
+ return path8.join(this.paths().tasks, taskId, "events.jsonl");
11295
11388
  }
11296
11389
  snapshotPath(taskId) {
11297
- return path7.join(this.paths().tasks, taskId, "snapshot.json");
11390
+ return path8.join(this.paths().tasks, taskId, "snapshot.json");
11298
11391
  }
11299
11392
  taskLockPath(taskId) {
11300
- return path7.join(this.paths().tasks, taskId, "lock");
11393
+ return path8.join(this.paths().tasks, taskId, "lock");
11301
11394
  }
11302
11395
  ready(write = false) {
11303
11396
  const location = this.location();
@@ -11336,13 +11429,13 @@ class TaskStore {
11336
11429
  return {
11337
11430
  read: (digest) => {
11338
11431
  try {
11339
- return JSON.parse(fs8.readFileSync(path7.join(dir, `${digest}.json`), "utf8"));
11432
+ return JSON.parse(fs8.readFileSync(path8.join(dir, `${digest}.json`), "utf8"));
11340
11433
  } catch (error) {
11341
11434
  throw new LogDamage(`stored candidate ${digest} is missing or unreadable: ${String(error)}`);
11342
11435
  }
11343
11436
  },
11344
11437
  write: (digest, value) => {
11345
- const file = path7.join(dir, `${digest}.json`);
11438
+ const file = path8.join(dir, `${digest}.json`);
11346
11439
  if (fs8.existsSync(file)) {
11347
11440
  const stamp = new Date;
11348
11441
  try {
@@ -11534,7 +11627,7 @@ class TaskStore {
11534
11627
  }
11535
11628
  }
11536
11629
  openTask(record, type, key, legacy = null) {
11537
- const dir = path7.join(this.paths().tasks, record.id);
11630
+ const dir = path8.join(this.paths().tasks, record.id);
11538
11631
  fs8.mkdirSync(dir, { recursive: true });
11539
11632
  const blobs = this.blobStore();
11540
11633
  const bound = key ? { ...key, boundAt: key.boundAt ?? new Date().toISOString() } : null;
@@ -11627,7 +11720,7 @@ class TaskStore {
11627
11720
  }
11628
11721
  withKeyLock(key, operation) {
11629
11722
  const digest = createHash5("sha256").update(key).digest("hex").slice(0, 32);
11630
- return this.withLock(path7.join(this.paths().dir, "keys", `${digest}.lock`), operation);
11723
+ return this.withLock(path8.join(this.paths().dir, "keys", `${digest}.lock`), operation);
11631
11724
  }
11632
11725
  bindLocked(taskId, key, timestamp) {
11633
11726
  const current = this.readWorkspace();
@@ -11768,7 +11861,7 @@ class TaskStore {
11768
11861
  writeWorkspace(record) {
11769
11862
  const file = this.paths().workspace;
11770
11863
  try {
11771
- fs8.mkdirSync(path7.dirname(file), { recursive: true });
11864
+ fs8.mkdirSync(path8.dirname(file), { recursive: true });
11772
11865
  replaceFile(file, `${canonicalJson(record)}
11773
11866
  `, true);
11774
11867
  return success(null, null, null);
@@ -11846,23 +11939,23 @@ class TaskStore {
11846
11939
  return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", { expectedWorkspaceRevision: expected, actualWorkspaceRevision: actual });
11847
11940
  }
11848
11941
  v2Dirs() {
11849
- return [...new Set([this.root, this.origin])].map((dir) => path7.join(dir, ".workit"));
11942
+ return [...new Set([this.root, this.origin])].map((dir) => path8.join(dir, ".workit"));
11850
11943
  }
11851
11944
  pendingMigrations() {
11852
11945
  return this.v2Dirs().filter((dir) => {
11853
- const raw = this.readV2Workspace(path7.join(dir, "workspace.json"));
11946
+ const raw = this.readV2Workspace(path8.join(dir, "workspace.json"));
11854
11947
  return raw !== null && raw !== TOMBSTONE;
11855
11948
  });
11856
11949
  }
11857
11950
  migrateV2(v2) {
11858
11951
  const dirs = this.paths();
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");
11952
+ const v2Workspace = path8.join(v2, "workspace.json");
11953
+ const v2Tasks = path8.join(v2, "tasks");
11954
+ const legacy = path8.join(dirs.dir, "legacy", checkoutSlug(path8.dirname(v2)), "v2");
11862
11955
  const raw = this.readV2Workspace(v2Workspace);
11863
11956
  if (raw === null || raw === TOMBSTONE)
11864
11957
  return success(null, null, null);
11865
- return this.withLock(dirs.checkoutLock, () => this.withLock(path7.join(v2, "metadata.lock"), () => {
11958
+ return this.withLock(dirs.checkoutLock, () => this.withLock(path8.join(v2, "metadata.lock"), () => {
11866
11959
  const workspace = this.readV2Workspace(v2Workspace);
11867
11960
  if (workspace === null || workspace === TOMBSTONE)
11868
11961
  return success(null, null, null);
@@ -11871,7 +11964,7 @@ class TaskStore {
11871
11964
  return failure2("recovery_required", `cannot migrate the 2.x store at ${v2}: ${parsedWorkspace.error}; move it aside to start fresh`, { path: v2Workspace });
11872
11965
  let files = [];
11873
11966
  try {
11874
- files = fs8.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path7.join(v2Tasks, name)));
11967
+ files = fs8.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path8.join(v2Tasks, name)));
11875
11968
  } catch {}
11876
11969
  const current = this.readWorkspace();
11877
11970
  if (!current.ok)
@@ -11889,21 +11982,21 @@ class TaskStore {
11889
11982
  let skipped = 0;
11890
11983
  const done = new Map;
11891
11984
  try {
11892
- fs8.mkdirSync(path7.join(legacy, "tasks"), { recursive: true });
11985
+ fs8.mkdirSync(path8.join(legacy, "tasks"), { recursive: true });
11893
11986
  for (const name of ["workspace.json", "index.json"])
11894
- if (fs8.existsSync(path7.join(v2, name)))
11895
- fs8.copyFileSync(path7.join(v2, name), path7.join(legacy, name));
11987
+ if (fs8.existsSync(path8.join(v2, name)))
11988
+ fs8.copyFileSync(path8.join(v2, name), path8.join(legacy, name));
11896
11989
  for (const name of files) {
11897
11990
  const id = name.slice(0, -5);
11898
- const file = path7.join(v2Tasks, name);
11991
+ const file = path8.join(v2Tasks, name);
11899
11992
  const bytes = fs8.readFileSync(file, "utf8");
11900
11993
  const digest = sha256(bytes);
11901
- fs8.writeFileSync(path7.join(legacy, "tasks", name), bytes);
11994
+ fs8.writeFileSync(path8.join(legacy, "tasks", name), bytes);
11902
11995
  const parsed = this.parseRecord(bytes, taskRecordSchema, "2.x task");
11903
11996
  if (!parsed.ok || parsed.data.id !== id)
11904
11997
  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 });
11905
11998
  const record = { ...parsed.data, workspaceId: target.id };
11906
- const origin = { path: path7.join(legacy, "tasks", name), digest };
11999
+ const origin = { path: path8.join(legacy, "tasks", name), digest };
11907
12000
  if (!fs8.existsSync(this.eventsPath(id))) {
11908
12001
  this.openTask(record, "migrated.from_v2", null, origin);
11909
12002
  migrated += 1;
@@ -11939,7 +12032,7 @@ class TaskStore {
11939
12032
  try {
11940
12033
  let complete = true;
11941
12034
  for (const [name, digest] of done) {
11942
- const file = path7.join(v2Tasks, name);
12035
+ const file = path8.join(v2Tasks, name);
11943
12036
  if (sha256(fs8.readFileSync(file, "utf8")) !== digest) {
11944
12037
  complete = false;
11945
12038
  continue;
@@ -11950,7 +12043,7 @@ class TaskStore {
11950
12043
  return failure2("busy", `the 2.x store at ${v2} changed during migration; retry`, {
11951
12044
  path: v2
11952
12045
  });
11953
- fs8.rmSync(path7.join(v2, "index.json"), { force: true });
12046
+ fs8.rmSync(path8.join(v2, "index.json"), { force: true });
11954
12047
  this.writeTombstone(v2, target.id);
11955
12048
  } catch (error) {
11956
12049
  return failure2("storage_error", `cannot finish the 2.x migration: ${String(error)}`, {
@@ -11970,7 +12063,7 @@ class TaskStore {
11970
12063
  }
11971
12064
  adoptLocalStore() {
11972
12065
  const dirs = this.paths();
11973
- const marker = path7.join(dirs.v2, "store.json");
12066
+ const marker = path8.join(dirs.v2, "store.json");
11974
12067
  if (!dirs.shared || !fs8.existsSync(marker))
11975
12068
  return success(null, null, null);
11976
12069
  return this.withLock(dirs.checkoutLock, () => {
@@ -11980,7 +12073,7 @@ class TaskStore {
11980
12073
  try {
11981
12074
  const merge = (from, to) => {
11982
12075
  if (!fs8.existsSync(to)) {
11983
- fs8.mkdirSync(path7.dirname(to), { recursive: true });
12076
+ fs8.mkdirSync(path8.dirname(to), { recursive: true });
11984
12077
  try {
11985
12078
  fs8.renameSync(from, to);
11986
12079
  } catch {
@@ -11991,24 +12084,24 @@ class TaskStore {
11991
12084
  }
11992
12085
  if (fs8.lstatSync(from).isDirectory() && fs8.lstatSync(to).isDirectory())
11993
12086
  for (const name of fs8.readdirSync(from))
11994
- merge(path7.join(from, name), path7.join(to, name));
12087
+ merge(path8.join(from, name), path8.join(to, name));
11995
12088
  };
11996
12089
  for (const sub of ["tasks", "checkouts", "blobs", "legacy"]) {
11997
- const from = path7.join(dirs.v2, sub);
12090
+ const from = path8.join(dirs.v2, sub);
11998
12091
  if (!fs8.existsSync(from))
11999
12092
  continue;
12000
12093
  if (sub === "tasks") {
12001
12094
  for (const name of fs8.readdirSync(from))
12002
- if (validId(name) && !fs8.existsSync(path7.join(dirs.dir, sub, name)))
12095
+ if (validId(name) && !fs8.existsSync(path8.join(dirs.dir, sub, name)))
12003
12096
  tasks += 1;
12004
12097
  }
12005
- merge(from, path7.join(dirs.dir, sub));
12098
+ merge(from, path8.join(dirs.dir, sub));
12006
12099
  }
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"));
12100
+ const ledger = path8.join(dirs.v2, "ledger");
12101
+ if (fs8.existsSync(ledger) && !fs8.existsSync(path8.join(dirs.dir, "ledger")))
12102
+ merge(ledger, path8.join(dirs.dir, "ledger"));
12103
+ fs8.rmSync(path8.join(dirs.v2, "task-index.json"), { force: true });
12104
+ fs8.renameSync(marker, path8.join(dirs.v2, "store.moved.json"));
12012
12105
  } catch (error) {
12013
12106
  return failure2("storage_error", `cannot move ${dirs.v2} into ${dirs.dir}: ${String(error)}`, {
12014
12107
  path: dirs.v2
@@ -12046,7 +12139,7 @@ class TaskStore {
12046
12139
  schemaVersion: SCHEMA_VERSION,
12047
12140
  id: workspaceId ?? newId(),
12048
12141
  revision: newRevision(),
12049
- root: path7.dirname(v2),
12142
+ root: path8.dirname(v2),
12050
12143
  runtime: { createdWith: version, updatedWith: version },
12051
12144
  writer: null,
12052
12145
  store: {
@@ -12058,11 +12151,11 @@ class TaskStore {
12058
12151
  critical: ["store"]
12059
12152
  };
12060
12153
  fs8.mkdirSync(v2, { recursive: true });
12061
- const ignore = path7.join(v2, ".gitignore");
12154
+ const ignore = path8.join(v2, ".gitignore");
12062
12155
  if (!fs8.existsSync(ignore))
12063
12156
  fs8.writeFileSync(ignore, `*
12064
12157
  `);
12065
- replaceFile(path7.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
12158
+ replaceFile(path8.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
12066
12159
  `, true);
12067
12160
  }
12068
12161
  stubFor(taskId) {
@@ -12086,8 +12179,8 @@ class TaskStore {
12086
12179
  }
12087
12180
  writeTombstoneIfMissing() {
12088
12181
  try {
12089
- const v2 = path7.join(this.root, ".workit");
12090
- if (fs8.existsSync(path7.join(v2, "workspace.json")))
12182
+ const v2 = path8.join(this.root, ".workit");
12183
+ if (fs8.existsSync(path8.join(v2, "workspace.json")))
12091
12184
  return;
12092
12185
  let id = null;
12093
12186
  try {
@@ -12104,7 +12197,7 @@ class TaskStore {
12104
12197
  replaceFile(dirs.marker, `${JSON.stringify({ format: "workit-store", version: STORE_FORMAT, createdWith: runtimeVersion() })}
12105
12198
  `, false);
12106
12199
  if (!dirs.shared) {
12107
- const ignore = path7.join(dirs.dir, ".gitignore");
12200
+ const ignore = path8.join(dirs.dir, ".gitignore");
12108
12201
  let current = null;
12109
12202
  try {
12110
12203
  current = fs8.readFileSync(ignore, "utf8");
@@ -12164,7 +12257,7 @@ class TaskStore {
12164
12257
  withLock(lockPath, operation) {
12165
12258
  try {
12166
12259
  this.initializeStorage();
12167
- fs8.mkdirSync(path7.dirname(lockPath), { recursive: true });
12260
+ fs8.mkdirSync(path8.dirname(lockPath), { recursive: true });
12168
12261
  } catch (error) {
12169
12262
  return failure2("storage_error", `unable to initialize store: ${String(error)}`, {
12170
12263
  path: this.paths().dir
@@ -12227,7 +12320,7 @@ class TaskStore {
12227
12320
  if (isTransientWindowsError(error) && !this.lockHolderPresent(lockPath) && !this.lockDirWritable(lockPath))
12228
12321
  return failure2("storage_error", `cannot create the workit lock (${code}); no other Workit call holds it`, {
12229
12322
  path: lockPath,
12230
- guidance: `Check permissions and the read-only attribute on ${path7.dirname(lockPath)}.`
12323
+ guidance: `Check permissions and the read-only attribute on ${path8.dirname(lockPath)}.`
12231
12324
  });
12232
12325
  if (code === "EEXIST" || code === "file_lock_timeout" || code === "file_lock_stale" || isTransientWindowsError(error)) {
12233
12326
  let lock = null;
@@ -12253,12 +12346,12 @@ var workerBlocksTransition = (transition, state) => transition === "pause" ? fal
12253
12346
  import { createHash as createHash10 } from "node:crypto";
12254
12347
  import * as fs13 from "node:fs";
12255
12348
  import { spawnSync as spawnSync10 } from "node:child_process";
12256
- import path15 from "node:path";
12349
+ import path16 from "node:path";
12257
12350
 
12258
12351
  // packages/workit-core/src/check-config.ts
12259
12352
  import { spawnSync as spawnSync3 } from "node:child_process";
12260
12353
  import fs9 from "node:fs";
12261
- import path8 from "node:path";
12354
+ import path9 from "node:path";
12262
12355
  var SCRIPT_CHECKS = ["test", "lint", "typecheck", "check"];
12263
12356
  var CHECKS_FILE = "workit.checks.json";
12264
12357
  var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
@@ -12311,10 +12404,10 @@ var git = (cwd, args) => {
12311
12404
  return value || null;
12312
12405
  };
12313
12406
  function checkRoot(cwd) {
12314
- return path8.resolve(git(cwd, ["rev-parse", "--show-toplevel"]) ?? cwd);
12407
+ return path9.resolve(git(cwd, ["rev-parse", "--show-toplevel"]) ?? cwd);
12315
12408
  }
12316
12409
  var packageManager = (root) => {
12317
- const has = (file) => fs9.existsSync(path8.join(root, file));
12410
+ const has = (file) => fs9.existsSync(path9.join(root, file));
12318
12411
  if (has("bun.lock") || has("bun.lockb"))
12319
12412
  return "bun";
12320
12413
  if (has("pnpm-lock.yaml"))
@@ -12334,7 +12427,7 @@ var CHECK_NAME = /^[a-z0-9][a-z0-9:._-]{0,63}$/u;
12334
12427
  function detectedChecks(root) {
12335
12428
  const read = (file) => {
12336
12429
  try {
12337
- return fs9.readFileSync(path8.join(root, file), "utf8");
12430
+ return fs9.readFileSync(path9.join(root, file), "utf8");
12338
12431
  } catch {
12339
12432
  return null;
12340
12433
  }
@@ -12373,7 +12466,7 @@ function detectedChecks(root) {
12373
12466
  var GATES = ["testing", "verification"];
12374
12467
  function loadCheckConfig(cwd) {
12375
12468
  const root = checkRoot(cwd);
12376
- const file = path8.join(root, CHECKS_FILE);
12469
+ const file = path9.join(root, CHECKS_FILE);
12377
12470
  const none = (error = null) => ({
12378
12471
  source: error ? CHECKS_FILE : "none",
12379
12472
  root,
@@ -12422,7 +12515,7 @@ function loadCheckConfig(cwd) {
12422
12515
  gates[gate] = names;
12423
12516
  }
12424
12517
  }
12425
- return { source: CHECKS_FILE, root, checks, gates, error: null };
12518
+ return { source: CHECKS_FILE, root, checks, gates, error: null, resources: parsed.resources };
12426
12519
  }
12427
12520
  var sameArgv = (left, right) => left.length === right.length && left.every((item, index) => item === right[index]);
12428
12521
  function matchesNamedCheck(config, name, argv, cwd) {
@@ -12446,10 +12539,10 @@ function workitAvailable(env = process.env) {
12446
12539
  return workitOnPath;
12447
12540
  const windows = process.platform === "win32";
12448
12541
  const exts = windows ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
12449
- const dirs = (env.PATH ?? env.Path ?? "").split(path8.delimiter).filter(Boolean);
12542
+ const dirs = (env.PATH ?? env.Path ?? "").split(path9.delimiter).filter(Boolean);
12450
12543
  workitOnPath = dirs.some((dir) => exts.some((ext) => {
12451
12544
  try {
12452
- return fs9.statSync(path8.join(dir, `workit${ext}`)).isFile();
12545
+ return fs9.statSync(path9.join(dir, `workit${ext}`)).isFile();
12453
12546
  } catch {
12454
12547
  return false;
12455
12548
  }
@@ -12464,8 +12557,8 @@ function checkCommand(args, version, onPath = workitAvailable()) {
12464
12557
  import { spawnSync as spawnSync4 } from "node:child_process";
12465
12558
  import { createHash as createHash6 } from "node:crypto";
12466
12559
  import fs10 from "node:fs";
12467
- import os from "node:os";
12468
- import path9 from "node:path";
12560
+ import os2 from "node:os";
12561
+ import path10 from "node:path";
12469
12562
  var MAX_BUFFER = 256 * 1024 * 1024;
12470
12563
  var GIT_TIMEOUTS = { local: 20000, worktree: 120000, network: 15000 };
12471
12564
  var git2 = (cwd, args, options = {}) => {
@@ -12512,9 +12605,9 @@ function worktreeTree(cwd, options = {}) {
12512
12605
  return null;
12513
12606
  const cap = options.maxUntrackedBytes ?? MAX_UNTRACKED_BYTES;
12514
12607
  const timeoutMs = options.timeoutMs ?? GIT_TIMEOUTS.worktree;
12515
- const scratch = fs10.mkdtempSync(path9.join(os.tmpdir(), "workit-tree-"));
12608
+ const scratch = fs10.mkdtempSync(path10.join(os2.tmpdir(), "workit-tree-"));
12516
12609
  try {
12517
- const tempIndex = path9.join(scratch, "index");
12610
+ const tempIndex = path10.join(scratch, "index");
12518
12611
  if (fs10.existsSync(indexPath))
12519
12612
  seedIndex(indexPath, tempIndex);
12520
12613
  const env = { ...process.env, GIT_INDEX_FILE: tempIndex };
@@ -12527,7 +12620,7 @@ function worktreeTree(cwd, options = {}) {
12527
12620
  const skipped = [];
12528
12621
  for (const file of untracked.stdout.split("\x00").filter(Boolean)) {
12529
12622
  try {
12530
- const stat = fs10.statSync(path9.join(top, file));
12623
+ const stat = fs10.statSync(path10.join(top, file));
12531
12624
  if (stat.isFile() && stat.size > cap)
12532
12625
  skipped.push({ path: file, size: stat.size, mtimeMs: Math.trunc(stat.mtimeMs) });
12533
12626
  } catch {}
@@ -12573,7 +12666,7 @@ function worktreeSignal(cwd, options = {}) {
12573
12666
  if (entry.length < 4)
12574
12667
  continue;
12575
12668
  const file = entry.slice(3);
12576
- const absolute = path9.join(top, file);
12669
+ const absolute = path10.join(top, file);
12577
12670
  let stat = "-";
12578
12671
  try {
12579
12672
  const info = fs10.lstatSync(absolute, { bigint: true });
@@ -12643,17 +12736,17 @@ function pushRemoteName(cwd, branch) {
12643
12736
 
12644
12737
  // packages/workit-core/src/core/policy/derive.ts
12645
12738
  import { existsSync as existsSync4 } from "node:fs";
12646
- import path14 from "node:path";
12739
+ import path15 from "node:path";
12647
12740
 
12648
12741
  // packages/workit-core/src/ledger.ts
12649
12742
  import { spawnSync as spawnSync9 } from "node:child_process";
12650
12743
  import { createHash as createHash9, randomBytes as randomBytes2 } from "node:crypto";
12651
12744
  import fs12 from "node:fs";
12652
- import path13 from "node:path";
12745
+ import path14 from "node:path";
12653
12746
 
12654
12747
  // packages/workit-core/src/core/vcs-config.ts
12655
12748
  import fs11 from "node:fs";
12656
- import path12 from "node:path";
12749
+ import path13 from "node:path";
12657
12750
  import { spawnSync as spawnSync8 } from "node:child_process";
12658
12751
 
12659
12752
  // packages/workit-core/src/core/config.ts
@@ -12666,8 +12759,8 @@ import {
12666
12759
  readdirSync as readdirSync2,
12667
12760
  writeFileSync as writeFileSync2
12668
12761
  } from "node:fs";
12669
- import os2 from "node:os";
12670
- import path10 from "node:path";
12762
+ import os3 from "node:os";
12763
+ import path11 from "node:path";
12671
12764
 
12672
12765
  // packages/workit-core/src/core/boundary.ts
12673
12766
  var EVENT = {
@@ -12711,7 +12804,7 @@ var mergePreset = (preset, input = {}, current = {
12711
12804
  protected: preset === "custom" ? input.protectedNames ?? current.branchPolicy.protected : [...defs.protected]
12712
12805
  };
12713
12806
  };
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");
12807
+ var resolveConfigDir = () => process.env.WORKFLOW_TOOLKIT_CONFIG ?? process.env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path11.join(process.env.XDG_CONFIG_HOME || path11.join(os3.homedir(), ".config"), "workit");
12715
12808
  var migratedDir = null;
12716
12809
  var migrationFailed = false;
12717
12810
  var ensureConfigDir = (dir = resolveConfigDir()) => {
@@ -12721,7 +12814,7 @@ var ensureConfigDir = (dir = resolveConfigDir()) => {
12721
12814
  migratedDir = dir;
12722
12815
  return dir;
12723
12816
  }
12724
- const legacy = path10.join(process.env.XDG_CONFIG_HOME || path10.join(os2.homedir(), ".config"), "workflow-toolkit");
12817
+ const legacy = path11.join(process.env.XDG_CONFIG_HOME || path11.join(os3.homedir(), ".config"), "workflow-toolkit");
12725
12818
  if (!existsSync3(legacy)) {
12726
12819
  migratedDir = dir;
12727
12820
  return dir;
@@ -12734,8 +12827,8 @@ var ensureConfigDir = (dir = resolveConfigDir()) => {
12734
12827
  mkdirSync2(dir, { recursive: true });
12735
12828
  diagnosticLogger?.info(EVENT.migration, { from: legacy, to: dir });
12736
12829
  for (const entry of readdirSync2(legacy, { withFileTypes: true })) {
12737
- const src = path10.join(legacy, entry.name);
12738
- const dest = path10.join(dir, entry.name);
12830
+ const src = path11.join(legacy, entry.name);
12831
+ const dest = path11.join(dir, entry.name);
12739
12832
  if (existsSync3(dest))
12740
12833
  continue;
12741
12834
  try {
@@ -12807,7 +12900,7 @@ var parseConfigResult = (raw, file) => {
12807
12900
  return { status: "valid", path: file, config };
12808
12901
  };
12809
12902
  var readConfigTyped = (dir) => {
12810
- const file = path10.join(dir ?? configDir(), "config.json");
12903
+ const file = path11.join(dir ?? configDir(), "config.json");
12811
12904
  return parseConfigResult(readSafe(file), file);
12812
12905
  };
12813
12906
  var readConfig = () => {
@@ -12816,7 +12909,7 @@ var readConfig = () => {
12816
12909
  throw new Error(result.error);
12817
12910
  return result.config ?? DEFAULTS;
12818
12911
  };
12819
- var vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path10.join(configDir(), "vcs.json");
12912
+ var vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path11.join(configDir(), "vcs.json");
12820
12913
  var branchGlobPattern = (glob) => new RegExp(`^${glob.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`, "i");
12821
12914
  var resolveBranchPolicy = (config, workspace, repoPreset) => {
12822
12915
  const wp = workspace?.branchPolicy ?? {};
@@ -12860,7 +12953,7 @@ var resolveCommitPolicy = (config, workspace) => {
12860
12953
  import { spawnSync as spawnSync6 } from "node:child_process";
12861
12954
  import { createHash as createHash7 } from "node:crypto";
12862
12955
  import { readFileSync as readFileSync3, realpathSync as realpathSync2 } from "node:fs";
12863
- import path11 from "node:path";
12956
+ import path12 from "node:path";
12864
12957
 
12865
12958
  // packages/workit-core/src/core/branch-policy.ts
12866
12959
  import { spawnSync as spawnSync5 } from "node:child_process";
@@ -12986,7 +13079,7 @@ var releaseTrackSchema = object({
12986
13079
  context.addIssue({ code: "custom", path: [field], message: "entries must be unique" });
12987
13080
  }
12988
13081
  }
12989
- 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(".."))) {
13082
+ if (track.versionSource?.kind === "package-json" && (path12.posix.isAbsolute(track.versionSource.path.replaceAll("\\", "/")) || /^[A-Za-z]:\//u.test(track.versionSource.path.replaceAll("\\", "/")) || track.versionSource.path.replaceAll("\\", "/").split("/").includes(".."))) {
12990
13083
  context.addIssue({
12991
13084
  code: "custom",
12992
13085
  path: ["versionSource", "path"],
@@ -13006,6 +13099,7 @@ var workspaceConfigSchema = object({
13006
13099
  autoApprove: union([boolean2(), array(nonBlank)]).optional(),
13007
13100
  defaultEndpoint: unknown().optional(),
13008
13101
  verification: _enum(["self", "independent"]).optional(),
13102
+ trailers: boolean2().optional(),
13009
13103
  autonomy: object(Object.fromEntries(["push", "pr", "merge", "release", "rerun"].map((kind) => [
13010
13104
  kind,
13011
13105
  union([boolean2(), literal("verified")]).optional()
@@ -13084,7 +13178,7 @@ var validateWorkspacesDocument = (parsed, file) => {
13084
13178
  };
13085
13179
  };
13086
13180
  var readWorkspacesResult = (dir = configDir()) => {
13087
- const file = path11.join(dir, "workspaces.json");
13181
+ const file = path12.join(dir, "workspaces.json");
13088
13182
  let raw;
13089
13183
  try {
13090
13184
  raw = readFileSync3(file, "utf8");
@@ -13195,9 +13289,9 @@ var mainCheckoutOf = (cwd) => {
13195
13289
  let main = null;
13196
13290
  const dirs = git(["rev-parse", "--path-format=absolute", "--git-dir", "--git-common-dir"]);
13197
13291
  const [gitDir, common] = (dirs ?? "").trim().split(/\r?\n/u);
13198
- if (gitDir && common && path11.resolve(gitDir) !== path11.resolve(common)) {
13292
+ if (gitDir && common && path12.resolve(gitDir) !== path12.resolve(common)) {
13199
13293
  const listed = /^worktree (.+)$/mu.exec(git(["worktree", "list", "--porcelain"]) ?? "")?.[1];
13200
- main = listed?.trim() || (path11.basename(common) === ".git" ? path11.dirname(common) : common);
13294
+ main = listed?.trim() || (path12.basename(common) === ".git" ? path12.dirname(common) : common);
13201
13295
  }
13202
13296
  mainCheckouts.set(cwd, main);
13203
13297
  return main;
@@ -13287,8 +13381,8 @@ var resolveRuntimeWorkspaceVcs = (cwd) => resolveRuntimeWorkspaceCandidate(cwd,
13287
13381
  var runtimeWorkspaceIndexSchema = object({
13288
13382
  workspaces: array(object({ name: nonBlank, glob: nonBlank }).passthrough()).optional()
13289
13383
  }).passthrough();
13290
- var matchRuntimeWorkspace = (cwd) => {
13291
- const file = path11.join(configDir(), "workspaces.json");
13384
+ var matchRuntimeWorkspace = (cwd, dir = configDir()) => {
13385
+ const file = path12.join(dir, "workspaces.json");
13292
13386
  let raw;
13293
13387
  try {
13294
13388
  raw = readFileSync3(file, "utf8");
@@ -13317,12 +13411,30 @@ var matchRuntimeWorkspace = (cwd) => {
13317
13411
  const matches = matchingEntries(cwd, entries ?? []);
13318
13412
  const workspaceName = process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined;
13319
13413
  const selected = selectWorkspaceMatch(matches, cwd, workspaceName);
13320
- return selected ? { file, selected } : null;
13414
+ return selected ? { file, selected, matches } : null;
13321
13415
  };
13322
13416
  var resolveRuntimeReleaseTracks = (cwd) => {
13323
13417
  const matched = matchRuntimeWorkspace(cwd);
13324
13418
  return matched ? { workspace: matched.selected.name, releaseTracks: matched.selected.releaseTracks } : null;
13325
13419
  };
13420
+ var workspaceTrailers = (cwd, dir) => {
13421
+ let matched;
13422
+ try {
13423
+ matched = matchRuntimeWorkspace(cwd, dir);
13424
+ } catch {
13425
+ return { enabled: true, workspace: null, from: null };
13426
+ }
13427
+ if (!matched)
13428
+ return { enabled: true, workspace: null, from: null };
13429
+ const { selected, matches } = matched;
13430
+ const enclosing = matches.filter((entry) => entry !== selected).toSorted((a, b) => globSpecificity(b.glob) - globSpecificity(a.glob));
13431
+ const source = [selected, ...enclosing].find((entry) => typeof entry.trailers === "boolean");
13432
+ return {
13433
+ enabled: source?.trailers !== false,
13434
+ workspace: selected.name,
13435
+ from: source?.name ?? null
13436
+ };
13437
+ };
13326
13438
  var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
13327
13439
  const matched = matchRuntimeWorkspace(cwd);
13328
13440
  if (!matched)
@@ -13659,7 +13771,7 @@ var git3 = (cwd, args) => {
13659
13771
  return run.status === 0 ? (run.stdout ?? "").trim() : null;
13660
13772
  };
13661
13773
  var recordedBaseKey = (branch) => `branch.${branch}.workitBase`;
13662
- var escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
13774
+ var escapeRegExp2 = (text) => text.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
13663
13775
  var reflog = (cwd, ref) => (git3(cwd, ["log", "-g", "--date=unix", "--format=%H%x09%gd%x09%gs", ref, "--"]) ?? "").split(`
13664
13776
  `).map((line) => {
13665
13777
  const [sha = "", selector = "", ...subject] = line.split("\t");
@@ -13691,7 +13803,7 @@ function gitTrackProbe(cwd) {
13691
13803
  const created = own.at(-1);
13692
13804
  if (!created || created.subject !== "branch: Created from HEAD")
13693
13805
  return null;
13694
- const pattern = new RegExp(`^checkout: moving from (\\S+) to ${escapeRegExp(branch)}$`, "u");
13806
+ const pattern = new RegExp(`^checkout: moving from (\\S+) to ${escapeRegExp2(branch)}$`, "u");
13695
13807
  const entry = reflog(cwd, "HEAD").findLast((item) => item.time >= created.time && item.sha === created.sha && pattern.test(item.subject));
13696
13808
  return entry ? pattern.exec(entry.subject)?.[1] ?? null : null;
13697
13809
  },
@@ -13761,7 +13873,7 @@ function resolveTrackFor(cwd, options) {
13761
13873
  }
13762
13874
 
13763
13875
  // packages/workit-core/src/core/vcs-config.ts
13764
- var workspacesPath = () => path12.join(configDir(), "workspaces.json");
13876
+ var workspacesPath = () => path13.join(configDir(), "workspaces.json");
13765
13877
  var vcsCwd = (cwd) => cwd ?? process.env.WORKFLOW_WORKSPACE_ROOT ?? process.cwd();
13766
13878
  var remoteProvider = (cwd) => {
13767
13879
  const r = spawnSync8("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" });
@@ -13936,7 +14048,7 @@ function vcsConfig(mode, cwd, options = {}) {
13936
14048
  const prov = cfg[provider] ?? {};
13937
14049
  const out = {
13938
14050
  ok: true,
13939
- configPath: path12.resolve(cfgPath),
14051
+ configPath: path13.resolve(cfgPath),
13940
14052
  provider,
13941
14053
  defaultTargetBranch: workspaceDefault,
13942
14054
  pr: cfg.pr ?? {},
@@ -14159,14 +14271,14 @@ function diffHash(cwd, base, head) {
14159
14271
  return `sha256:${hash.digest("hex")}`;
14160
14272
  }
14161
14273
  function storeRoot(cwd) {
14162
- const location = resolveStore(path13.resolve(cwd));
14274
+ const location = resolveStore(path14.resolve(cwd));
14163
14275
  if (location instanceof Error)
14164
14276
  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");
14165
14277
  return { ok: true, value: { root: location.dir, shared: location.shared } };
14166
14278
  }
14167
14279
  function ledgerPath(cwd) {
14168
14280
  const root = storeRoot(cwd);
14169
- return root.ok ? { ok: true, value: path13.join(root.value.root, "ledger", "ledger.jsonl") } : root;
14281
+ return root.ok ? { ok: true, value: path14.join(root.value.root, "ledger", "ledger.jsonl") } : root;
14170
14282
  }
14171
14283
  var newId2 = () => `${Date.now().toString(36)}-${randomBytes2(6).toString("hex")}`;
14172
14284
  var NETWORK_FS_TYPES = new Set([
@@ -14196,13 +14308,13 @@ var LOCK_STALE_MS = 30000;
14196
14308
  var LOCK_OWNER = "owner";
14197
14309
  var lockToken = (lock) => {
14198
14310
  try {
14199
- return fs12.readFileSync(path13.join(lock, LOCK_OWNER), "utf8");
14311
+ return fs12.readFileSync(path14.join(lock, LOCK_OWNER), "utf8");
14200
14312
  } catch {
14201
14313
  return null;
14202
14314
  }
14203
14315
  };
14204
14316
  var lockAgeMs = (lock) => {
14205
- for (const target of [path13.join(lock, LOCK_OWNER), lock]) {
14317
+ for (const target of [path14.join(lock, LOCK_OWNER), lock]) {
14206
14318
  try {
14207
14319
  return Date.now() - fs12.statSync(target).mtimeMs;
14208
14320
  } catch {}
@@ -14219,7 +14331,7 @@ var ledgerLock = {
14219
14331
  throw error;
14220
14332
  }
14221
14333
  const token = `${process.pid}-${randomBytes2(8).toString("hex")}`;
14222
- fs12.writeFileSync(path13.join(lock, LOCK_OWNER), token);
14334
+ fs12.writeFileSync(path14.join(lock, LOCK_OWNER), token);
14223
14335
  return token;
14224
14336
  },
14225
14337
  release(lock, token) {
@@ -14344,8 +14456,8 @@ function appendLine(file, build, options) {
14344
14456
  }
14345
14457
  };
14346
14458
  try {
14347
- fs12.mkdirSync(path13.dirname(file), { recursive: true });
14348
- if (!options.forceLock && !onNetworkFs(path13.dirname(file)))
14459
+ fs12.mkdirSync(path14.dirname(file), { recursive: true });
14460
+ if (!options.forceLock && !onNetworkFs(path14.dirname(file)))
14349
14461
  return write();
14350
14462
  const locked = withLedgerLock(file, write);
14351
14463
  return locked ?? err("busy", `ledger lock ${file}.lock is held`, "retry; remove the .lock directory if no workit process is running");
@@ -14908,7 +15020,7 @@ var productDecision = (task, ledger) => {
14908
15020
  };
14909
15021
  };
14910
15022
  var planRecorded = (task, root) => {
14911
- const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(path14.resolve(root, ref.path)));
15023
+ const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(path15.resolve(root, ref.path)));
14912
15024
  if (cited)
14913
15025
  return {
14914
15026
  met: true,
@@ -14968,14 +15080,14 @@ function writeBlockers(task, root) {
14968
15080
 
14969
15081
  // packages/workit-core/src/core/task-evaluation.ts
14970
15082
  var digestBytes = (value) => createHash10("sha256").update(value).digest("hex");
14971
- var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path15.sep}`);
14972
- var relative = (root, candidate) => path15.relative(root, candidate).split(path15.sep).join("/") || ".";
15083
+ var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path16.sep}`);
15084
+ var relative = (root, candidate) => path16.relative(root, candidate).split(path16.sep).join("/") || ".";
14973
15085
  var canonicalPath = (value) => {
14974
15086
  if (typeof value !== "string" || !value)
14975
15087
  return null;
14976
15088
  if (value.includes("\\") || value.split("/").includes(".."))
14977
15089
  return null;
14978
- const normalized = path15.posix.normalize(value);
15090
+ const normalized = path16.posix.normalize(value);
14979
15091
  if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
14980
15092
  return null;
14981
15093
  return normalized === "." ? "." : normalized.replace(/\/$/, "");
@@ -15023,14 +15135,14 @@ var gitPaths = (root) => {
15023
15135
  git: !/not a git repository/i.test(stderr)
15024
15136
  };
15025
15137
  }
15026
- const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path15.sep).join("/")) : [];
15138
+ const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path16.sep).join("/")) : [];
15027
15139
  const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
15028
15140
  if (stagedDeleted.status !== 0) {
15029
15141
  const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
15030
15142
  if (!/not a git repository/i.test(stderr))
15031
15143
  return { paths, uncertain: true, git: true };
15032
15144
  } else if (stagedDeleted.stdout) {
15033
- paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path15.sep).join("/")));
15145
+ paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path16.sep).join("/")));
15034
15146
  }
15035
15147
  return { paths: [...new Set(paths)], uncertain: false, git: true };
15036
15148
  };
@@ -15045,7 +15157,7 @@ var walk = (root, directory, output) => {
15045
15157
  for (const name of names) {
15046
15158
  if (name === ".git" || name === ".workit")
15047
15159
  continue;
15048
- const target = path15.join(directory, name);
15160
+ const target = path16.join(directory, name);
15049
15161
  let stat;
15050
15162
  try {
15051
15163
  stat = fs13.lstatSync(target);
@@ -15063,12 +15175,12 @@ var walk = (root, directory, output) => {
15063
15175
  var scopeRoots = (root, scope) => {
15064
15176
  const roots = [];
15065
15177
  for (const item of scope.paths.length ? scope.paths : ["."]) {
15066
- const target = path15.resolve(root, item);
15178
+ const target = path16.resolve(root, item);
15067
15179
  if (!inside(root, target))
15068
15180
  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` }] });
15069
15181
  let ancestor = target;
15070
15182
  while (!fs13.existsSync(ancestor) && ancestor !== root)
15071
- ancestor = path15.dirname(ancestor);
15183
+ ancestor = path16.dirname(ancestor);
15072
15184
  try {
15073
15185
  if (!inside(root, fs13.realpathSync(ancestor)))
15074
15186
  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` }] });
@@ -15120,7 +15232,7 @@ function captureCandidate(root, scope, environment = []) {
15120
15232
  for (const item of [...names].toSorted()) {
15121
15233
  if (!scopeMatches(item, normalizedScope))
15122
15234
  continue;
15123
- const target = path15.join(checkout, item);
15235
+ const target = path16.join(checkout, item);
15124
15236
  try {
15125
15237
  const stat = fs13.lstatSync(target);
15126
15238
  if (stat.isSymbolicLink()) {
@@ -15304,23 +15416,23 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
15304
15416
  continue;
15305
15417
  if (!reference.digest)
15306
15418
  return failure2("invalid_input", "document references require a byte digest");
15307
- const target = path15.resolve(root, reference.path);
15308
- if (target !== root && !target.startsWith(`${root}${path15.sep}`))
15419
+ const target = path16.resolve(root, reference.path);
15420
+ if (target !== root && !target.startsWith(`${root}${path16.sep}`))
15309
15421
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
15310
15422
  fields: [
15311
15423
  { path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
15312
15424
  ]
15313
15425
  });
15314
15426
  try {
15315
- const below = path15.relative(root, target);
15427
+ const below = path16.relative(root, target);
15316
15428
  let current = root;
15317
- for (const segment of below.split(path15.sep)) {
15429
+ for (const segment of below.split(path16.sep)) {
15318
15430
  if (!segment)
15319
15431
  continue;
15320
- current = path15.join(current, segment);
15432
+ current = path16.join(current, segment);
15321
15433
  const stat = fs13.lstatSync(current);
15322
15434
  const real = fs13.realpathSync(current);
15323
- if (real !== root && !real.startsWith(`${root}${path15.sep}`))
15435
+ if (real !== root && !real.startsWith(`${root}${path16.sep}`))
15324
15436
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
15325
15437
  fields: [
15326
15438
  {
@@ -15695,9 +15807,9 @@ Autonomy contract:
15695
15807
  ship), go to the effective endpoint in \`workit grant show\`: \`pr\` opens
15696
15808
  the PR; \`green\` babysits it without asking (workit-ship) to merge-ready,
15697
15809
  never merging; \`merged\` also lands it with \`workit pr merge\`.
15698
- Merge and release need a workspace grant, which only the user raises from
15699
- their own terminal (a blocked verb names how); never edit workspaces.json or
15700
- route around a grant_required.
15810
+ Merge and release need a workspace grant only the user raises from their
15811
+ own terminal (a blocked verb names how); never edit workspaces.json or route
15812
+ around a grant_required.
15701
15813
  - Ask only for a product or preference choice, or for authority you lack, with
15702
15814
  your recommended answer. Facts are yours: read, run or prototype.
15703
15815
  - Label claims measured (run and seen this session), inferred, or guess.
@@ -15706,17 +15818,19 @@ Autonomy contract:
15706
15818
  - Author is not verifier: your own verdict is \`--self\`, shown as
15707
15819
  self-reviewed, never verified. High risk, \`verification: independent\` and
15708
15820
  merge need a verifier with its own host-derived session (a subagent's
15709
- \`<lead>:<child>\`, set by the host); never hand-mint one such as \`<lead>-v1\`.
15821
+ \`<lead>:<child>\`); never hand-mint one (\`<lead>-v1\`).
15710
15822
  - A local-commit endpoint does not imply PR readiness, and a local commit alone
15711
15823
  is not evidence of a requested remote push. Before reporting delivery,
15712
15824
  reconcile every requested item and observe it (\`workit verify-delivery\`).
15713
15825
 
15714
15826
  CLI first: if a step has one right answer, use the \`workit\` verb instead of
15715
15827
  hand-running git, gh or glab (\`workit git|pr|ci|check\`; \`workit help\` lists
15716
- the rest; without \`workit\` on PATH, \`npx -y @brainervirus/workit-cli\`).
15828
+ the rest; lacking \`workit\`, \`npx -y @brainervirus/workit-cli\`).
15829
+ Add Co-Authored-By via \`workit git commit --trailer "K: v" -- <paths>\`, never
15830
+ an amend.
15717
15831
  The task families (task, policy, evidence, finding, decision, worker, state)
15718
15832
  are optional continuity for tracked work; each branch has one implicit task,
15719
- created by the first recording, and a solo edit needs no task. A decision
15833
+ and a solo edit needs no task. A decision
15720
15834
  records a user choice; it never authorizes an effect. Judge work once with
15721
15835
  \`workit policy assess --judge risk= behavior= product-choice= plan=\`.
15722
15836
  Across repositories, bind each item to its checkout, branch and endpoint,
@@ -15865,14 +15979,14 @@ var exportDigest = (bundle) => sha256({
15865
15979
  // packages/workit-core/src/core/route-intent.ts
15866
15980
  import { spawnSync as spawnSync12 } from "node:child_process";
15867
15981
  import { existsSync as existsSync6 } from "node:fs";
15868
- import path18 from "node:path";
15982
+ import path19 from "node:path";
15869
15983
 
15870
15984
  // packages/workit-core/src/hooks/raw-git.ts
15871
15985
  import { spawnSync as spawnSync11 } from "node:child_process";
15872
15986
  import { createHash as createHash13 } from "node:crypto";
15873
15987
  import fs15 from "node:fs";
15874
- import os3 from "node:os";
15875
- import path17 from "node:path";
15988
+ import os4 from "node:os";
15989
+ import path18 from "node:path";
15876
15990
 
15877
15991
  // packages/workit-core/src/core/branch.ts
15878
15992
  import { createHash as createHash11 } from "node:crypto";
@@ -16155,7 +16269,7 @@ var globOf = (pattern) => pattern.source.replace(/^\^|\$$/gu, "").replaceAll(".*
16155
16269
  // packages/workit-core/src/hooks/session-marker.ts
16156
16270
  import { createHash as createHash12 } from "node:crypto";
16157
16271
  import fs14 from "node:fs";
16158
- import path16 from "node:path";
16272
+ import path17 from "node:path";
16159
16273
  var sessionMarkerFile = (input, session, store) => {
16160
16274
  let dir = store;
16161
16275
  if (dir === undefined) {
@@ -16165,7 +16279,7 @@ var sessionMarkerFile = (input, session, store) => {
16165
16279
  dir = location.dir;
16166
16280
  }
16167
16281
  const name = createHash12("sha256").update(`${input.host}\x00${session}`).digest("hex").slice(0, 32);
16168
- return path16.join(dir, "hooks", `skills-${name}.json`);
16282
+ return path17.join(dir, "hooks", `skills-${name}.json`);
16169
16283
  };
16170
16284
  var list2 = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
16171
16285
  var readSessionMarker = (file) => {
@@ -16178,7 +16292,7 @@ var readSessionMarker = (file) => {
16178
16292
  };
16179
16293
  var writeSessionMarker = (file, marker) => {
16180
16294
  try {
16181
- fs14.mkdirSync(path16.dirname(file), { recursive: true });
16295
+ fs14.mkdirSync(path17.dirname(file), { recursive: true });
16182
16296
  fs14.writeFileSync(file, JSON.stringify(marker));
16183
16297
  } catch {}
16184
16298
  };
@@ -16323,12 +16437,12 @@ var GIT_VALUE_OPTIONS = new Set([
16323
16437
  "--config-env",
16324
16438
  "--super-prefix"
16325
16439
  ]);
16326
- var isAbsolute = (value) => path17.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\");
16440
+ var isAbsolute = (value) => path18.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\");
16327
16441
  var joinDir = (base, next) => {
16328
16442
  if (base === undefined || /[$`*?]/.test(next) || next === "-")
16329
16443
  return;
16330
- const expanded = next === "~" || next.startsWith("~/") ? path17.join(os3.homedir(), next.slice(1)) : next;
16331
- return base === null || isAbsolute(expanded) ? expanded : path17.join(base, expanded);
16444
+ const expanded = next === "~" || next.startsWith("~/") ? path18.join(os4.homedir(), next.slice(1)) : next;
16445
+ return base === null || isAbsolute(expanded) ? expanded : path18.join(base, expanded);
16332
16446
  };
16333
16447
  var cdTarget = (words) => {
16334
16448
  const args = words.slice(1);
@@ -16379,7 +16493,7 @@ function rawInvocations(command, dialect = "posix", depth = 0) {
16379
16493
  const name = commandName(words[0]);
16380
16494
  if (CD.has(name)) {
16381
16495
  const target = cdTarget(words);
16382
- dir = target === null ? os3.homedir() : joinDir(dir, target);
16496
+ dir = target === null ? os4.homedir() : joinDir(dir, target);
16383
16497
  continue;
16384
16498
  }
16385
16499
  if (PUSHD.has(name)) {
@@ -16637,17 +16751,17 @@ var headSha2 = (repo) => {
16637
16751
  if (!git || git.reftable)
16638
16752
  return null;
16639
16753
  try {
16640
- const head = fs15.readFileSync(path17.join(git.gitDir, "HEAD"), "utf8").trim();
16754
+ const head = fs15.readFileSync(path18.join(git.gitDir, "HEAD"), "utf8").trim();
16641
16755
  if (/^[0-9a-f]{40,64}$/.test(head))
16642
16756
  return head;
16643
16757
  const ref = /^ref: (refs\/.+)$/.exec(head)?.[1];
16644
16758
  if (!ref)
16645
16759
  return null;
16646
- const common = path17.dirname(repo.location.dir);
16760
+ const common = path18.dirname(repo.location.dir);
16647
16761
  try {
16648
- return fs15.readFileSync(path17.join(common, ref), "utf8").trim() || null;
16762
+ return fs15.readFileSync(path18.join(common, ref), "utf8").trim() || null;
16649
16763
  } catch {}
16650
- const packed = fs15.readFileSync(path17.join(common, "packed-refs"), "utf8");
16764
+ const packed = fs15.readFileSync(path18.join(common, "packed-refs"), "utf8");
16651
16765
  return new RegExp(`^([0-9a-f]{40,64}) ${ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`, "m").exec(packed)?.[1] ?? null;
16652
16766
  } catch {
16653
16767
  return null;
@@ -16736,7 +16850,7 @@ var actionsIn = (cwd, command, dialect) => {
16736
16850
  const action = rawAction(invocation);
16737
16851
  if (!action)
16738
16852
  continue;
16739
- const dir = path17.resolve(cwd, invocation.dir ?? ".");
16853
+ const dir = path18.resolve(cwd, invocation.dir ?? ".");
16740
16854
  if (!repos.has(dir)) {
16741
16855
  const repo = repoAt(dir);
16742
16856
  repos.set(dir, repo && isWorkitWorkspace(repo) ? repo : null);
@@ -16816,7 +16930,7 @@ function rawGitPre(input, command, options = {}) {
16816
16930
  var deny = (reason) => ({ kind: "deny", reason, unblock: null });
16817
16931
  var NEXT_COMMAND = "next";
16818
16932
  var MARKER_TTL_SECONDS = 3600;
16819
- var markerFile = (repo, session, key) => path17.join(repo.location.dir, "hooks", `commit-${createHash13("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`);
16933
+ var markerFile = (repo, session, key) => path18.join(repo.location.dir, "hooks", `commit-${createHash13("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`);
16820
16934
  var callKey = (toolUseId, command) => toolUseId ?? `cmd:${createHash13("sha256").update(command).digest("hex")}`;
16821
16935
  function noteRawCommit(input, command, key) {
16822
16936
  try {
@@ -16827,7 +16941,7 @@ function noteRawCommit(input, command, key) {
16827
16941
  if (action.kind !== "commit")
16828
16942
  continue;
16829
16943
  const file = markerFile(repo, input.session.id, key);
16830
- fs15.mkdirSync(path17.dirname(file), { recursive: true });
16944
+ fs15.mkdirSync(path18.dirname(file), { recursive: true });
16831
16945
  fs15.writeFileSync(file, `${JSON.stringify({ head: headSha2(repo), at })}
16832
16946
  `);
16833
16947
  }
@@ -17000,7 +17114,7 @@ var shellBranchPolicyViolation = (root, command, dialect = "posix") => {
17000
17114
  for (const target of shellBranchTargets(command, dialect)) {
17001
17115
  if (target.dir === undefined)
17002
17116
  continue;
17003
- const dir = target.dir === null ? root : path18.resolve(root, target.dir);
17117
+ const dir = target.dir === null ? root : path19.resolve(root, target.dir);
17004
17118
  if (target.dir !== null && (!existsSync6(dir) || !inWorkitWorkspace(dir)))
17005
17119
  continue;
17006
17120
  if (localBranchExists(dir, target.branch))
@@ -17226,20 +17340,20 @@ var judgeInputSummary = (raw) => {
17226
17340
  };
17227
17341
 
17228
17342
  // packages/workit-core/src/autonomy.ts
17229
- import os4 from "node:os";
17230
- import path19 from "node:path";
17343
+ import os5 from "node:os";
17344
+ import path20 from "node:path";
17231
17345
  var accountHome = () => {
17232
17346
  try {
17233
- return os4.userInfo().homedir;
17347
+ return os5.userInfo().homedir;
17234
17348
  } catch {
17235
- return os4.homedir();
17349
+ return os5.homedir();
17236
17350
  }
17237
17351
  };
17238
17352
  var grantsHome = { resolve: accountHome };
17239
- var grantsDir = () => path19.join(grantsHome.resolve(), ".config", "workit");
17353
+ var grantsDir = () => path20.join(grantsHome.resolve(), ".config", "workit");
17240
17354
  var grantsOverride = () => {
17241
- const configured = path19.resolve(resolveConfigDir());
17242
- return configured === path19.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 ${path19.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
17355
+ const configured = path20.resolve(resolveConfigDir());
17356
+ return configured === path20.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 ${path20.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
17243
17357
  };
17244
17358
  var GRANT_KINDS = ["push", "pr", "merge", "release", "rerun"];
17245
17359
  var DEFAULT_GRANTS = Object.freeze({
@@ -19011,7 +19125,7 @@ class WorkitCore {
19011
19125
  // packages/workit-core/src/core/repo-context.ts
19012
19126
  import { spawnSync as spawnSync13 } from "node:child_process";
19013
19127
  import { existsSync as existsSync7, readFileSync as readFileSync5, readdirSync as readdirSync4 } from "node:fs";
19014
- import path20 from "node:path";
19128
+ import path21 from "node:path";
19015
19129
  var isSafeContextRange = (value) => value.length <= 4096 && (() => {
19016
19130
  try {
19017
19131
  gitRevisionParts(value);
@@ -19145,7 +19259,7 @@ var findPrTemplate = (cwd) => {
19145
19259
  ]) {
19146
19260
  const parts = rel.split("/");
19147
19261
  const base = parts[parts.length - 1];
19148
- const dir = parts.length > 1 ? path20.join(cwd, ...parts.slice(0, -1)) : cwd;
19262
+ const dir = parts.length > 1 ? path21.join(cwd, ...parts.slice(0, -1)) : cwd;
19149
19263
  const actual = probeCaseInsensitive(dir, base);
19150
19264
  if (actual)
19151
19265
  return [...parts.slice(0, -1), actual].join("/");
@@ -19176,7 +19290,7 @@ var diffStatForRange = (cwd, range) => {
19176
19290
  return runGit(cwd, ["diff", "--stat", "--"]).stdout;
19177
19291
  };
19178
19292
  var packageScripts = (cwd, keys) => {
19179
- const pkgPath = path20.join(cwd, "package.json");
19293
+ const pkgPath = path21.join(cwd, "package.json");
19180
19294
  if (!existsSync7(pkgPath))
19181
19295
  return [];
19182
19296
  try {
@@ -19202,9 +19316,9 @@ var documentationFiles = (cwd) => {
19202
19316
  if (entry.isDirectory()) {
19203
19317
  if (excluded.has(entry.name))
19204
19318
  continue;
19205
- walk(path20.join(dir, entry.name), depth + 1);
19319
+ walk(path21.join(dir, entry.name), depth + 1);
19206
19320
  } else if (entry.isFile() && (entry.name === "README.md" || entry.name.endsWith(".md"))) {
19207
- matches.push("./" + path20.relative(cwd, path20.join(dir, entry.name)).replaceAll("\\", "/"));
19321
+ matches.push("./" + path21.relative(cwd, path21.join(dir, entry.name)).replaceAll("\\", "/"));
19208
19322
  }
19209
19323
  }
19210
19324
  };
@@ -19220,7 +19334,7 @@ var readTrimmed2 = (file, maxLines) => {
19220
19334
  `);
19221
19335
  };
19222
19336
  function prReadyContext(root, range) {
19223
- const cwd = path20.resolve(repoRoot(root));
19337
+ const cwd = path21.resolve(repoRoot(root));
19224
19338
  if (range !== undefined && !isResolvableContextRange(cwd, range))
19225
19339
  return invalidRange(cwd);
19226
19340
  let stdout = "";
@@ -19278,7 +19392,7 @@ ${status.stderr}` : "");
19278
19392
  stdout += `template_path: ${template}
19279
19393
 
19280
19394
  `;
19281
- stdout += readTrimmed2(path20.join(cwd, template), 220);
19395
+ stdout += readTrimmed2(path21.join(cwd, template), 220);
19282
19396
  } else {
19283
19397
  stdout += `template_path: none
19284
19398
 
@@ -19288,7 +19402,7 @@ ${status.stderr}` : "");
19288
19402
  stdout += `
19289
19403
  `;
19290
19404
  stdout += printSection("Recent Validation Signals");
19291
- if (existsSync7(path20.join(cwd, "package.json"))) {
19405
+ if (existsSync7(path21.join(cwd, "package.json"))) {
19292
19406
  stdout += `package.json detected. Common scripts:
19293
19407
  `;
19294
19408
  const found = packageScripts(cwd, ["lint", "format:check", "test", "build"]);
@@ -19297,7 +19411,7 @@ ${status.stderr}` : "");
19297
19411
  `) + `
19298
19412
  `;
19299
19413
  }
19300
- if (existsSync7(path20.join(cwd, "Cargo.toml")) || existsSync7(path20.join(cwd, "src-tauri/Cargo.toml"))) {
19414
+ if (existsSync7(path21.join(cwd, "Cargo.toml")) || existsSync7(path21.join(cwd, "src-tauri/Cargo.toml"))) {
19301
19415
  stdout += `Rust project detected.
19302
19416
  `;
19303
19417
  }
@@ -19330,7 +19444,7 @@ var CHANGELOG_RULES = `- Use an [Unreleased] section.
19330
19444
  - Apply with the host-native editor, preserving the repository changelog conventions.
19331
19445
  - If Unreleased already has duplicate category headings, normalize_only first.`;
19332
19446
  function changelogContext(root, range) {
19333
- const cwd = path20.resolve(repoRoot(root));
19447
+ const cwd = path21.resolve(repoRoot(root));
19334
19448
  if (range !== undefined && !isResolvableContextRange(cwd, range))
19335
19449
  return invalidRange(cwd);
19336
19450
  const resolvedRange = rangeArgOrDefault(range, cwd);
@@ -19348,7 +19462,7 @@ function changelogContext(root, range) {
19348
19462
  stdout += CHANGELOG_RULES + `
19349
19463
  `;
19350
19464
  stdout += printSection("Existing CHANGELOG.md");
19351
- const changelogPath = path20.join(cwd, "CHANGELOG.md");
19465
+ const changelogPath = path21.join(cwd, "CHANGELOG.md");
19352
19466
  if (existsSync7(changelogPath)) {
19353
19467
  stdout += readTrimmed2(changelogPath, 260) + `
19354
19468
  `;
@@ -19368,7 +19482,7 @@ function changelogContext(root, range) {
19368
19482
  return { stdout, stderr: "", exitCode: 0, cwd };
19369
19483
  }
19370
19484
  function docsRefreshContext(root, range) {
19371
- const cwd = path20.resolve(repoRoot(root));
19485
+ const cwd = path21.resolve(repoRoot(root));
19372
19486
  if (range !== undefined && !isResolvableContextRange(cwd, range))
19373
19487
  return invalidRange(cwd);
19374
19488
  const resolvedRange = rangeArgOrDefault(range, cwd);
@@ -19390,7 +19504,7 @@ function docsRefreshContext(root, range) {
19390
19504
  `) + `
19391
19505
  `;
19392
19506
  stdout += printSection("README Preview");
19393
- const readme = path20.join(cwd, "README.md");
19507
+ const readme = path21.join(cwd, "README.md");
19394
19508
  if (existsSync7(readme)) {
19395
19509
  stdout += readTrimmed2(readme, 220) + `
19396
19510
  `;
@@ -19399,7 +19513,7 @@ function docsRefreshContext(root, range) {
19399
19513
  `;
19400
19514
  }
19401
19515
  stdout += printSection("Package Scripts");
19402
- const pkgPath = path20.join(cwd, "package.json");
19516
+ const pkgPath = path21.join(cwd, "package.json");
19403
19517
  if (existsSync7(pkgPath)) {
19404
19518
  try {
19405
19519
  const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
@@ -19413,7 +19527,7 @@ function docsRefreshContext(root, range) {
19413
19527
  return { stdout, stderr: "", exitCode: 0, cwd };
19414
19528
  }
19415
19529
  function releaseNotesContext(root, rangeOrTag) {
19416
- const cwd = path20.resolve(repoRoot(root));
19530
+ const cwd = path21.resolve(repoRoot(root));
19417
19531
  if (!rangeOrTag) {
19418
19532
  return { stdout: "", stderr: `ERROR: release tag or range required
19419
19533
  `, exitCode: 1, cwd };
@@ -19451,7 +19565,7 @@ function releaseNotesContext(root, rangeOrTag) {
19451
19565
  `;
19452
19566
  stdout += printSection("Existing Release Files");
19453
19567
  for (const rel of ["CHANGELOG.md", "RELEASE_NOTES.md", ".github/releases.md"]) {
19454
- if (existsSync7(path20.join(cwd, rel)))
19568
+ if (existsSync7(path21.join(cwd, rel)))
19455
19569
  stdout += rel + `
19456
19570
  `;
19457
19571
  }
@@ -19483,7 +19597,7 @@ import { spawnSync as spawnSync15 } from "node:child_process";
19483
19597
 
19484
19598
  // packages/workit-core/src/core/pr-create.ts
19485
19599
  import fs16 from "node:fs";
19486
- import path21 from "node:path";
19600
+ import path22 from "node:path";
19487
19601
  import { spawnSync as spawnSync14 } from "node:child_process";
19488
19602
  // packages/workit-core/src/forge/pr-body.ts
19489
19603
  function parseGhIssue(value) {
@@ -19494,11 +19608,11 @@ function parseGhIssue(value) {
19494
19608
  // packages/workit-core/src/core/pr-create.ts
19495
19609
  function whichOnPath(tool) {
19496
19610
  const names = process.platform === "win32" ? [tool, `${tool}.exe`, `${tool}.cmd`] : [tool];
19497
- for (const dir of (process.env.PATH ?? "").split(path21.delimiter)) {
19611
+ for (const dir of (process.env.PATH ?? "").split(path22.delimiter)) {
19498
19612
  if (!dir)
19499
19613
  continue;
19500
19614
  for (const name of names) {
19501
- const candidate = path21.join(dir, name);
19615
+ const candidate = path22.join(dir, name);
19502
19616
  try {
19503
19617
  fs16.accessSync(candidate, fs16.constants.X_OK);
19504
19618
  return candidate;
@@ -19619,7 +19733,7 @@ var fetchGitLabIssueBody = async (ref, root, deps = {}) => {
19619
19733
 
19620
19734
  // packages/workit-core/src/core/youtrack.ts
19621
19735
  import fs17 from "node:fs";
19622
- import path22 from "node:path";
19736
+ import path23 from "node:path";
19623
19737
 
19624
19738
  // packages/workit-core/src/core/templates.ts
19625
19739
  var repoRoot2 = assetRoot();
@@ -19632,8 +19746,8 @@ var resolveWorkspaceRoot = (explicit) => explicit || process.cwd();
19632
19746
  // packages/workit-core/src/core/youtrack.ts
19633
19747
  var ISSUE_RE = /^[A-Z]+-\d+$/;
19634
19748
  var TOKEN_PLACEHOLDER = "YOUR_TOKEN_HERE";
19635
- var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path22.join(configDir(), "youtrack.json");
19636
- var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path22.join(resolveConfigDir(), "youtrack.json");
19749
+ var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path23.join(configDir(), "youtrack.json");
19750
+ var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path23.join(resolveConfigDir(), "youtrack.json");
19637
19751
  var youTrackTokenModeOk = (p) => {
19638
19752
  if (process.platform === "win32")
19639
19753
  return true;
@@ -19701,7 +19815,7 @@ var youTrackToken = () => {
19701
19815
  if ("error" in loaded)
19702
19816
  return loaded;
19703
19817
  const tokenFile = String(loaded.config.tokenFile ?? "");
19704
- const tokenPath = tokenFile ? path22.isAbsolute(tokenFile) ? path22.resolve(tokenFile) : path22.resolve(process.cwd(), tokenFile) : "";
19818
+ const tokenPath = tokenFile ? path23.isAbsolute(tokenFile) ? path23.resolve(tokenFile) : path23.resolve(process.cwd(), tokenFile) : "";
19705
19819
  if (!tokenPath || !fs17.existsSync(tokenPath))
19706
19820
  return { error: "missing youtrack.token" };
19707
19821
  if (!youTrackTokenModeOk(tokenPath))
@@ -20058,15 +20172,15 @@ function resolveGitRevision(root, value) {
20058
20172
  }
20059
20173
  function resolveInside(root, candidate) {
20060
20174
  const base = realpathSync5(root);
20061
- const target = path23.resolve(base, candidate);
20062
- if (target !== base && !target.startsWith(base + path23.sep)) {
20175
+ const target = path24.resolve(base, candidate);
20176
+ if (target !== base && !target.startsWith(base + path24.sep)) {
20063
20177
  throw new Error("path must stay inside repository root");
20064
20178
  }
20065
20179
  let ancestor = target;
20066
20180
  while (!existsSync8(ancestor))
20067
- ancestor = path23.dirname(ancestor);
20181
+ ancestor = path24.dirname(ancestor);
20068
20182
  const canonicalAncestor = realpathSync5(ancestor);
20069
- if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path23.sep)) {
20183
+ if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path24.sep)) {
20070
20184
  throw new Error("path must stay inside repository root");
20071
20185
  }
20072
20186
  return target;
@@ -20112,7 +20226,7 @@ var capabilitiesFor = (descriptor, observed = {}) => descriptor.capabilities.map
20112
20226
  // packages/workit-core/src/hooks/context.ts
20113
20227
  import { createHash as createHash14 } from "node:crypto";
20114
20228
  import fs18 from "node:fs";
20115
- import path24 from "node:path";
20229
+ import path25 from "node:path";
20116
20230
  var MIGRATION_PENDING_NOTE = "workit migration pending — run `workit task status`";
20117
20231
  var migrationPending = (result) => !result.ok && result.code === "needs_input" && (result.error ?? "").startsWith(MIGRATION_PENDING);
20118
20232
  var boundTo = (entry, session) => entry.sessions.some((item) => item.host === session.host && item.handle === session.handle);
@@ -20197,7 +20311,7 @@ function entryCompactContext(store, entry, session, context) {
20197
20311
  return null;
20198
20312
  const freshness = { mode: "signal", current: () => recentSignal(store.root) };
20199
20313
  const observed = task?.data.evidence.some(isObservedCheck) ?? false;
20200
- const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [path24.resolve(store.root, ref.path)] : []));
20314
+ const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [path25.resolve(store.root, ref.path)] : []));
20201
20315
  const observedFiles = filesKey(files);
20202
20316
  const compact = new WorkitCore(store, context).compactContext(entry?.id ?? null, freshness, origin && { origin: origin.origin, taskId: origin.entry.id });
20203
20317
  if (!compact.ok || !compact.data)
@@ -20275,14 +20389,14 @@ var turnMarker = (input) => {
20275
20389
  if (location instanceof Error)
20276
20390
  return null;
20277
20391
  const session = [input.host, input.session.id, input.session.agentId ?? ""].join("\x00");
20278
- return path24.join(location.dir, "hooks", `turn-${digestOf(session).slice(0, 32)}.json`);
20392
+ return path25.join(location.dir, "hooks", `turn-${digestOf(session).slice(0, 32)}.json`);
20279
20393
  } catch {
20280
20394
  return null;
20281
20395
  }
20282
20396
  };
20283
20397
  var writeTurnDigest = (file, digest) => {
20284
20398
  try {
20285
- fs18.mkdirSync(path24.dirname(file), { recursive: true });
20399
+ fs18.mkdirSync(path25.dirname(file), { recursive: true });
20286
20400
  fs18.writeFileSync(file, `${JSON.stringify({ digest })}
20287
20401
  `);
20288
20402
  } catch {}
@@ -20297,7 +20411,7 @@ var pruneTurnDigests = (dir, now) => {
20297
20411
  for (const name of fs18.readdirSync(dir)) {
20298
20412
  if (!name.startsWith("turn-"))
20299
20413
  continue;
20300
- const file = path24.join(dir, name);
20414
+ const file = path25.join(dir, name);
20301
20415
  try {
20302
20416
  if (now - fs18.statSync(file).mtimeMs > TURN_TTL_MS)
20303
20417
  fs18.rmSync(file, { force: true });
@@ -20327,7 +20441,7 @@ var seedTurnContext = (input, descriptor, text = turnContextText(input, descript
20327
20441
  const file = turnMarker(input);
20328
20442
  if (!file)
20329
20443
  return;
20330
- pruneTurnDigests(path24.dirname(file), Date.now());
20444
+ pruneTurnDigests(path25.dirname(file), Date.now());
20331
20445
  if (text)
20332
20446
  writeTurnDigest(file, digestOf(text));
20333
20447
  else
@@ -20340,27 +20454,27 @@ var shellPolicy = (cwd, command, dialect = "posix") => {
20340
20454
  };
20341
20455
  // packages/workit-core/src/hooks/write-gate.ts
20342
20456
  import { realpathSync as realpathSync6 } from "node:fs";
20343
- import path25 from "node:path";
20457
+ import path26 from "node:path";
20344
20458
  var NONE3 = { kind: "none" };
20345
20459
  var CASE_INSENSITIVE = process.platform === "darwin" || process.platform === "win32";
20346
20460
  var canonical2 = (file) => {
20347
20461
  let rest = "";
20348
- for (let dir = path25.resolve(file);; dir = path25.dirname(dir)) {
20462
+ for (let dir = path26.resolve(file);; dir = path26.dirname(dir)) {
20349
20463
  try {
20350
- return path25.join(realpathSync6(dir), rest);
20464
+ return path26.join(realpathSync6(dir), rest);
20351
20465
  } catch {
20352
- if (path25.dirname(dir) === dir)
20353
- return path25.resolve(file);
20354
- rest = rest ? path25.join(path25.basename(dir), rest) : path25.basename(dir);
20466
+ if (path26.dirname(dir) === dir)
20467
+ return path26.resolve(file);
20468
+ rest = rest ? path26.join(path26.basename(dir), rest) : path26.basename(dir);
20355
20469
  }
20356
20470
  }
20357
20471
  };
20358
20472
  var exempt = (cwd, root, file, plans) => {
20359
20473
  const fold = (value) => CASE_INSENSITIVE ? value.toLowerCase() : value;
20360
- const relative = path25.relative(fold(canonical2(root)), fold(canonical2(path25.resolve(cwd, file))));
20361
- if (relative.startsWith("..") || path25.isAbsolute(relative))
20474
+ const relative = path26.relative(fold(canonical2(root)), fold(canonical2(path26.resolve(cwd, file))));
20475
+ if (relative.startsWith("..") || path26.isAbsolute(relative))
20362
20476
  return true;
20363
- const posix = relative.split(path25.sep).join("/");
20477
+ const posix = relative.split(path26.sep).join("/");
20364
20478
  const segments = posix.split("/");
20365
20479
  return /\.mdx?$/i.test(posix) || segments[0] === "docs" || segments.includes("plans") || [...plans].some((plan) => fold(plan) === posix);
20366
20480
  };
@@ -20458,7 +20572,7 @@ var shellWrites = (command) => {
20458
20572
  return { writes: true, targets: unknown ? null : targets };
20459
20573
  };
20460
20574
  var cache2 = new Map;
20461
- var planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(path25.resolve(root, file)) ?? "-").join("\x00");
20575
+ var planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(path26.resolve(root, file)) ?? "-").join("\x00");
20462
20576
  var gateFor = (cwd) => {
20463
20577
  const store = new TaskStore(cwd);
20464
20578
  const listed = store.listTaskIndex();
@@ -20950,7 +21064,7 @@ var workitRole = (descriptor, agentType) => {
20950
21064
  };
20951
21065
  var subagentSession = (session, agentId) => [session, agentId].filter((part) => Boolean(part)).join(":").replace(/[^A-Za-z0-9_.:@/+-]/g, "-").slice(0, 128);
20952
21066
  var CLAUDE_WORKTREE = /[\\/]\.claude[\\/]worktrees[\\/]/;
20953
- var ISOLATED_GIT = 'Run git as plain, separate commands inside your worktree (`git switch -c <branch> <base>`, `git commit --trailer "Workit-Session=<your session>"`, `git push`; `workit doctor --fix` can install a commit-msg hook that adds the trailer), never `workit git …`: Claude Code\'s worktree isolation refuses a command that wraps git and cannot be turned off (https://code.claude.com/docs/en/worktrees#how-claude-code-enforces-isolation). Never dodge that check by renaming or re-wrapping git. Use workit for the non-git verbs (`workit check`, `workit ledger`, `workit pr`).';
21067
+ var isolatedGit = (cwd) => `Run git as plain, separate commands inside your worktree (\`git switch -c <branch> <base>\`, ${workspaceTrailers(cwd).enabled ? '`git commit --trailer "Workit-Session=<your session>"`, `git push`; `workit doctor --fix` can install a prepare-commit-msg hook that adds the trailer' : "`git commit` (this workspace sets trailers: false: add no Workit-Session trailer), `git push`"}; add Co-Authored-By with \`git commit --trailer\` in the same commit, never by amending), never \`workit git …\`: Claude Code's worktree isolation refuses a command that wraps git and cannot be turned off (https://code.claude.com/docs/en/worktrees#how-claude-code-enforces-isolation). Never dodge that check by renaming or re-wrapping git. Use workit for the non-git verbs (\`workit check\`, \`workit ledger\`, \`workit pr\`).`;
20954
21068
  var subagentStartText = (input, descriptor, event) => {
20955
21069
  const session = input.session.id ?? null;
20956
21070
  const role = workitRole(descriptor, event.agentType);
@@ -20958,9 +21072,9 @@ var subagentStartText = (input, descriptor, event) => {
20958
21072
  const isolated = descriptor.subagents.worktreeIsolation === "native" && (role === "implementer" || CLAUDE_WORKTREE.test(input.cwd));
20959
21073
  const guide = role === "implementer" ? branchGuidance(input.cwd) : null;
20960
21074
  if (role === "implementer" && isolated)
20961
- return `Workit observed ${who} working in its own git worktree: it may edit and commit there, within its brief's scope. ${ISOLATED_GIT} Plain git is expected here, and the branch name is still policy-checked: a raw \`git switch -c\`, \`git checkout -b\`, \`git branch\` or \`git worktree add -b\` onto a protected or non-compliant name is denied, so use a policy-compliant branch.${guide ? ` ${guide}` : " (e.g. feature/<slug>)"} Never record a verdict on your own work. Never push, open a PR, or merge unless the brief asks for it.`;
21075
+ return `Workit observed ${who} working in its own git worktree: it may edit and commit there, within its brief's scope. ${isolatedGit(input.cwd)} Plain git is expected here, and the branch name is still policy-checked: a raw \`git switch -c\`, \`git checkout -b\`, \`git branch\` or \`git worktree add -b\` onto a protected or non-compliant name is denied, so use a policy-compliant branch.${guide ? ` ${guide}` : " (e.g. feature/<slug>)"} Never record a verdict on your own work. Never push, open a PR, or merge unless the brief asks for it.`;
20962
21076
  if (isolated)
20963
- return `${ISOLATED_GIT}
21077
+ return `${isolatedGit(input.cwd)}
20964
21078
  ${subagentStartText({ ...input, cwd: "" }, descriptor, event)}`;
20965
21079
  if (role === "implementer")
20966
21080
  return `Workit observed ${who} as an implementer: it edits and commits only in its own git worktree (the lead makes one with \`workit fanout worktree create <slice>\`), never in the lead's checkout, within its brief's scope. Before the first commit, switch to a policy-compliant branch with \`workit git branch <branch> --base <base>\` (or \`--kind <kind> --slug <slug>\`, which picks the base); branch policy hooks still deny protected or non-compliant branches, raw git included.${guide ? ` ${guide}` : " (e.g. feature/<slug>)"} Never record a verdict on your own work. Never push, open a PR, or merge unless the brief asks for it.`;
@@ -21330,13 +21444,13 @@ var skillPromptNudge = (prompt, ctx) => process.env.WORKIT_PI_WORKER_SESSION ? n
21330
21444
 
21331
21445
  // packages/workit-pi/src/launches.ts
21332
21446
  import { mkdirSync as mkdirSync3, readFileSync as readFileSync6, readdirSync as readdirSync5, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
21333
- import os5 from "node:os";
21334
- import path26 from "node:path";
21447
+ import os6 from "node:os";
21448
+ import path27 from "node:path";
21335
21449
  var launchDir = (root) => {
21336
21450
  const location = resolveStore(root);
21337
- return location instanceof Error ? null : path26.join(location.dir, "pi-launches");
21451
+ return location instanceof Error ? null : path27.join(location.dir, "pi-launches");
21338
21452
  };
21339
- var fileFor = (dir, workerId) => path26.join(dir, `${workerId.replace(/[^A-Za-z0-9-]/g, "_")}.json`);
21453
+ var fileFor = (dir, workerId) => path27.join(dir, `${workerId.replace(/[^A-Za-z0-9-]/g, "_")}.json`);
21340
21454
  var recordLaunch = (root, attempt) => {
21341
21455
  const dir = launchDir(root);
21342
21456
  if (!dir)
@@ -21346,7 +21460,7 @@ var recordLaunch = (root, attempt) => {
21346
21460
  writeFileSync3(fileFor(dir, attempt.workerId), JSON.stringify({
21347
21461
  ...attempt,
21348
21462
  pid: process.pid,
21349
- host: os5.hostname(),
21463
+ host: os6.hostname(),
21350
21464
  at: new Date().toISOString()
21351
21465
  }), { flag: "wx" });
21352
21466
  return true;
@@ -21360,7 +21474,7 @@ var clearLaunch = (root, workerId) => {
21360
21474
  rmSync2(fileFor(dir, workerId), { force: true });
21361
21475
  };
21362
21476
  var alive = (attempt) => {
21363
- if (attempt.host !== os5.hostname())
21477
+ if (attempt.host !== os6.hostname())
21364
21478
  return true;
21365
21479
  try {
21366
21480
  process.kill(attempt.pid, 0);
@@ -21382,7 +21496,7 @@ var abandonedLaunches = (root) => {
21382
21496
  const found = [];
21383
21497
  for (const name of names) {
21384
21498
  try {
21385
- const attempt = JSON.parse(readFileSync6(path26.join(dir, name), "utf8"));
21499
+ const attempt = JSON.parse(readFileSync6(path27.join(dir, name), "utf8"));
21386
21500
  if (typeof attempt.workerId === "string" && typeof attempt.session === "string") {
21387
21501
  if (!alive(attempt))
21388
21502
  found.push(attempt);