@brainervirus/workit-cursor 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.
@@ -8377,7 +8377,7 @@ import { realpathSync as realpathSync4 } from "node:fs";
8377
8377
 
8378
8378
  // packages/workit-core/src/core/policy/derive.ts
8379
8379
  import { existsSync as existsSync2 } from "node:fs";
8380
- import path8 from "node:path";
8380
+ import path9 from "node:path";
8381
8381
 
8382
8382
  // packages/workit-core/src/git/rev.ts
8383
8383
  import { spawnSync } from "node:child_process";
@@ -8564,7 +8564,7 @@ function pushRemoteName(cwd, branch) {
8564
8564
  import { spawnSync as spawnSync7 } from "node:child_process";
8565
8565
  import { createHash as createHash7, randomBytes } from "node:crypto";
8566
8566
  import fs5 from "node:fs";
8567
- import path7 from "node:path";
8567
+ import path8 from "node:path";
8568
8568
 
8569
8569
  // packages/workit-core/src/core/vcs-config.ts
8570
8570
  import fs2 from "node:fs";
@@ -8921,6 +8921,7 @@ var workspaceConfigSchema = object({
8921
8921
  autoApprove: union([boolean2(), array(nonBlank)]).optional(),
8922
8922
  defaultEndpoint: unknown().optional(),
8923
8923
  verification: _enum(["self", "independent"]).optional(),
8924
+ trailers: boolean2().optional(),
8924
8925
  autonomy: object(Object.fromEntries(["push", "pr", "merge", "release", "rerun"].map((kind) => [
8925
8926
  kind,
8926
8927
  union([boolean2(), literal("verified")]).optional()
@@ -9202,8 +9203,8 @@ var resolveRuntimeWorkspaceVcs = (cwd) => resolveRuntimeWorkspaceCandidate(cwd,
9202
9203
  var runtimeWorkspaceIndexSchema = object({
9203
9204
  workspaces: array(object({ name: nonBlank, glob: nonBlank }).passthrough()).optional()
9204
9205
  }).passthrough();
9205
- var matchRuntimeWorkspace = (cwd) => {
9206
- const file = path3.join(configDir(), "workspaces.json");
9206
+ var matchRuntimeWorkspace = (cwd, dir = configDir()) => {
9207
+ const file = path3.join(dir, "workspaces.json");
9207
9208
  let raw;
9208
9209
  try {
9209
9210
  raw = readFileSync2(file, "utf8");
@@ -9232,12 +9233,30 @@ var matchRuntimeWorkspace = (cwd) => {
9232
9233
  const matches = matchingEntries(cwd, entries ?? []);
9233
9234
  const workspaceName = process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined;
9234
9235
  const selected = selectWorkspaceMatch(matches, cwd, workspaceName);
9235
- return selected ? { file, selected } : null;
9236
+ return selected ? { file, selected, matches } : null;
9236
9237
  };
9237
9238
  var resolveRuntimeReleaseTracks = (cwd) => {
9238
9239
  const matched = matchRuntimeWorkspace(cwd);
9239
9240
  return matched ? { workspace: matched.selected.name, releaseTracks: matched.selected.releaseTracks } : null;
9240
9241
  };
9242
+ var workspaceTrailers = (cwd, dir) => {
9243
+ let matched;
9244
+ try {
9245
+ matched = matchRuntimeWorkspace(cwd, dir);
9246
+ } catch {
9247
+ return { enabled: true, workspace: null, from: null };
9248
+ }
9249
+ if (!matched)
9250
+ return { enabled: true, workspace: null, from: null };
9251
+ const { selected, matches } = matched;
9252
+ const enclosing = matches.filter((entry) => entry !== selected).toSorted((a, b) => globSpecificity(b.glob) - globSpecificity(a.glob));
9253
+ const source = [selected, ...enclosing].find((entry) => typeof entry.trailers === "boolean");
9254
+ return {
9255
+ enabled: source?.trailers !== false,
9256
+ workspace: selected.name,
9257
+ from: source?.name ?? null
9258
+ };
9259
+ };
9241
9260
  var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
9242
9261
  const matched = matchRuntimeWorkspace(cwd);
9243
9262
  if (!matched)
@@ -9802,13 +9821,72 @@ function vcsConfig(mode, cwd, options = {}) {
9802
9821
  // packages/workit-core/src/host-session.ts
9803
9822
  import { createHash as createHash6 } from "node:crypto";
9804
9823
  import fs4 from "node:fs";
9805
- import path6 from "node:path";
9824
+ import path7 from "node:path";
9825
+
9826
+ // packages/workit-core/src/core/logger.ts
9827
+ import os3 from "node:os";
9828
+ import path5 from "node:path";
9829
+ var SENSITIVE_WORDS = new Set([
9830
+ "token",
9831
+ "secret",
9832
+ "password",
9833
+ "passwd",
9834
+ "authorization",
9835
+ "credential",
9836
+ "credentials",
9837
+ "cookie",
9838
+ "api",
9839
+ "apikey",
9840
+ "apitoken",
9841
+ "accesstoken",
9842
+ "clientsecret",
9843
+ "refreshtoken",
9844
+ "key",
9845
+ "bearer",
9846
+ "prompt",
9847
+ "message",
9848
+ "messages",
9849
+ "content",
9850
+ "body",
9851
+ "args",
9852
+ "argument",
9853
+ "result",
9854
+ "results",
9855
+ "output",
9856
+ "issue",
9857
+ "description",
9858
+ "summary",
9859
+ "payload",
9860
+ "script",
9861
+ "command",
9862
+ "text",
9863
+ "query"
9864
+ ]);
9865
+ var STACK_WORDS = new Set(["stack", "stacktrace", "trace"]);
9866
+ var escapeRegExp2 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
9867
+ var resolveStateDir = () => {
9868
+ const override = process.env.WORKFLOW_TOOLKIT_STATE;
9869
+ if (override)
9870
+ return override;
9871
+ const home = os3.homedir();
9872
+ if (process.env.XDG_STATE_HOME)
9873
+ return path5.join(process.env.XDG_STATE_HOME, "workit");
9874
+ switch (os3.platform()) {
9875
+ case "darwin":
9876
+ return path5.join(home, "Library", "Application Support", "workit");
9877
+ case "win32":
9878
+ return path5.join(process.env.LOCALAPPDATA ?? path5.join(home, "AppData", "Local"), "workit");
9879
+ default:
9880
+ return path5.join(process.env.HOME ?? home, ".local", "state", "workit");
9881
+ }
9882
+ };
9883
+ var homePattern = new RegExp(`${escapeRegExp2(os3.homedir())}(?=[/\\\\]|$)|\\$HOME(?=[/\\\\]|$)`, "g");
9806
9884
 
9807
9885
  // packages/workit-core/src/store/paths.ts
9808
9886
  import { spawnSync as spawnSync6 } from "node:child_process";
9809
9887
  import { createHash as createHash5 } from "node:crypto";
9810
9888
  import fs3 from "node:fs";
9811
- import path5 from "node:path";
9889
+ import path6 from "node:path";
9812
9890
  var NOT_A_REPO = /not a git repository \(or any (of the parent directories|parent up to)/u;
9813
9891
  var gitRun = (cwd, args) => {
9814
9892
  const run = spawnSync6("git", args, {
@@ -9850,14 +9928,14 @@ var DISCOVERY_ENV = [
9850
9928
  ];
9851
9929
  var isGitDir = (dir) => {
9852
9930
  try {
9853
- return fs3.statSync(path5.join(dir, "HEAD")).isFile() && fs3.statSync(path5.join(dir, "objects")).isDirectory() && fs3.statSync(path5.join(dir, "refs")).isDirectory();
9931
+ return fs3.statSync(path6.join(dir, "HEAD")).isFile() && fs3.statSync(path6.join(dir, "objects")).isDirectory() && fs3.statSync(path6.join(dir, "refs")).isDirectory();
9854
9932
  } catch {
9855
9933
  return false;
9856
9934
  }
9857
9935
  };
9858
9936
  var reftableRefs = (common) => {
9859
9937
  try {
9860
- return /^\s*refstorage\s*=\s*reftable\s*$/imu.test(fs3.readFileSync(path5.join(common, "config"), "utf8"));
9938
+ return /^\s*refstorage\s*=\s*reftable\s*$/imu.test(fs3.readFileSync(path6.join(common, "config"), "utf8"));
9861
9939
  } catch {
9862
9940
  return false;
9863
9941
  }
@@ -9877,7 +9955,7 @@ function fastGit(root) {
9877
9955
  if (device !== null && stat.dev !== device)
9878
9956
  return { kind: "none" };
9879
9957
  device = stat.dev;
9880
- const dotGit = path5.join(dir, ".git");
9958
+ const dotGit = path6.join(dir, ".git");
9881
9959
  let entry = null;
9882
9960
  try {
9883
9961
  entry = fs3.statSync(dotGit);
@@ -9898,19 +9976,19 @@ function fastGit(root) {
9898
9976
  const match = /^gitdir: (.+)$/mu.exec(text);
9899
9977
  if (!match)
9900
9978
  return null;
9901
- gitDir = path5.resolve(dir, match[1].trim());
9979
+ gitDir = path6.resolve(dir, match[1].trim());
9902
9980
  } else
9903
9981
  return null;
9904
- if (!fs3.existsSync(path5.join(gitDir, "HEAD")))
9982
+ if (!fs3.existsSync(path6.join(gitDir, "HEAD")))
9905
9983
  return null;
9906
9984
  } else if (isGitDir(dir))
9907
9985
  gitDir = dir;
9908
9986
  if (gitDir) {
9909
9987
  let common = gitDir;
9910
9988
  try {
9911
- common = path5.resolve(gitDir, fs3.readFileSync(path5.join(gitDir, "commondir"), "utf8").trim());
9989
+ common = path6.resolve(gitDir, fs3.readFileSync(path6.join(gitDir, "commondir"), "utf8").trim());
9912
9990
  } catch {}
9913
- if (!fs3.existsSync(path5.join(common, "objects")))
9991
+ if (!fs3.existsSync(path6.join(common, "objects")))
9914
9992
  return null;
9915
9993
  return {
9916
9994
  kind: "repo",
@@ -9920,26 +9998,26 @@ function fastGit(root) {
9920
9998
  reftable: reftableRefs(common)
9921
9999
  };
9922
10000
  }
9923
- const parent = path5.dirname(dir);
10001
+ const parent = path6.dirname(dir);
9924
10002
  if (parent === dir)
9925
10003
  return { kind: "none" };
9926
10004
  dir = parent;
9927
10005
  }
9928
10006
  }
9929
10007
  function resolveStore(root) {
9930
- root = path5.resolve(root);
10008
+ root = path6.resolve(root);
9931
10009
  let directory = false;
9932
10010
  try {
9933
10011
  directory = fs3.statSync(root).isDirectory();
9934
10012
  } catch {}
9935
10013
  if (!directory)
9936
- return { dir: path5.join(root, ".workit"), shared: false, top: null };
10014
+ return { dir: path6.join(root, ".workit"), shared: false, top: null };
9937
10015
  const fast = fastGit(root);
9938
10016
  if (fast?.kind === "none")
9939
- return { dir: path5.join(root, ".workit"), shared: false, top: null };
10017
+ return { dir: path6.join(root, ".workit"), shared: false, top: null };
9940
10018
  if (fast?.kind === "repo")
9941
10019
  return {
9942
- dir: path5.join(fast.common, "workit"),
10020
+ dir: path6.join(fast.common, "workit"),
9943
10021
  shared: true,
9944
10022
  top: fast.top,
9945
10023
  git: { gitDir: fast.gitDir, top: fast.top, reftable: fast.reftable }
@@ -9949,20 +10027,20 @@ function resolveStore(root) {
9949
10027
  if (run.ok && common) {
9950
10028
  const top = gitRun(root, ["rev-parse", "--path-format=absolute", "--show-toplevel"]);
9951
10029
  return {
9952
- dir: path5.join(real(path5.resolve(root, common)), "workit"),
10030
+ dir: path6.join(real(path6.resolve(root, common)), "workit"),
9953
10031
  shared: true,
9954
10032
  top: top.ok && top.stdout.trim() ? real(top.stdout.trim()) : null
9955
10033
  };
9956
10034
  }
9957
10035
  if (run.missing || !run.ok && NOT_A_REPO.test(run.stderr))
9958
- return { dir: path5.join(root, ".workit"), shared: false, top: null };
10036
+ return { dir: path6.join(root, ".workit"), shared: false, top: null };
9959
10037
  return new Error(`cannot locate the workit store: git rev-parse failed (${run.stderr.trim().split(`
9960
10038
  `)[0] || "no output"}); fix the repository (git status should work here)`);
9961
10039
  }
9962
10040
  var rebasingBranch = (gitDir) => {
9963
10041
  for (const state of ["rebase-merge", "rebase-apply"]) {
9964
10042
  try {
9965
- const ref = fs3.readFileSync(path5.join(gitDir, state, "head-name"), "utf8").trim();
10043
+ const ref = fs3.readFileSync(path6.join(gitDir, state, "head-name"), "utf8").trim();
9966
10044
  const match = /^refs\/heads\/(.+)$/u.exec(ref);
9967
10045
  if (match)
9968
10046
  return match[1];
@@ -9977,7 +10055,7 @@ function resolveTaskKey(root, location) {
9977
10055
  if (location.git && !location.git.reftable) {
9978
10056
  let head = "";
9979
10057
  try {
9980
- head = fs3.readFileSync(path5.join(location.git.gitDir, "HEAD"), "utf8").trim();
10058
+ head = fs3.readFileSync(path6.join(location.git.gitDir, "HEAD"), "utf8").trim();
9981
10059
  } catch {}
9982
10060
  const ref = /^ref: refs\/heads\/(.+)$/u.exec(head);
9983
10061
  if (ref && ref[1] !== ".invalid")
@@ -10008,7 +10086,7 @@ function resolveTaskKey(root, location) {
10008
10086
  return { key: `detached-${shortHash(real(worktree))}`, kind: "detached", branch: null };
10009
10087
  }
10010
10088
  function checkoutRootOf(root, location) {
10011
- const resolved = path5.resolve(root);
10089
+ const resolved = path6.resolve(root);
10012
10090
  let canonical = resolved;
10013
10091
  try {
10014
10092
  canonical = fs3.realpathSync(resolved);
@@ -10039,13 +10117,13 @@ function branchRenames(location) {
10039
10117
  }
10040
10118
  for (const entry of entries)
10041
10119
  if (entry.isDirectory())
10042
- walk(path5.join(dir, entry.name));
10120
+ walk(path6.join(dir, entry.name));
10043
10121
  else
10044
- files.push(path5.join(dir, entry.name));
10122
+ files.push(path6.join(dir, entry.name));
10045
10123
  };
10046
- walk(path5.join(path5.dirname(location.dir), "logs", "refs", "heads"));
10124
+ walk(path6.join(path6.dirname(location.dir), "logs", "refs", "heads"));
10047
10125
  if (location.git)
10048
- files.push(path5.join(location.git.gitDir, "logs", "HEAD"));
10126
+ files.push(path6.join(location.git.gitDir, "logs", "HEAD"));
10049
10127
  const seen = new Set;
10050
10128
  const renames = [];
10051
10129
  for (const file of files) {
@@ -10080,7 +10158,7 @@ var checkoutSlug = (root) => {
10080
10158
  let canonical = real(root);
10081
10159
  if (process.platform === "win32")
10082
10160
  canonical = canonical.toLowerCase();
10083
- const base = path5.basename(canonical).replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 40) || "root";
10161
+ const base = path6.basename(canonical).replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 40) || "root";
10084
10162
  return `${base}-${shortHash(canonical)}`;
10085
10163
  };
10086
10164
 
@@ -10113,30 +10191,64 @@ function hostSessionFromEnv(env) {
10113
10191
  return inner ? { host: inner.host, session: inner.session } : { host: declared, session: null };
10114
10192
  }
10115
10193
  var ISSUED_PER_LEAD = 64;
10116
- var ISSUED_SESSIONS_MARKER = "workit-issued-sessions/1";
10194
+ var ISSUED_SESSIONS_MARKER = "workit-issued-sessions/2";
10117
10195
  var hash = (value) => createHash6("sha256").update(value).digest("hex").slice(0, 32);
10118
- var issuedRoot = (cwd) => {
10119
- const location = resolveStore(cwd);
10120
- return location instanceof Error ? null : path6.join(location.dir, "hooks", "issued");
10196
+ var userIssuedRoot = () => path7.join(resolveStateDir(), "issued");
10197
+ function migrateRepoIssued(cwd) {
10198
+ if (cwd === undefined)
10199
+ return;
10200
+ let old;
10201
+ try {
10202
+ const location = resolveStore(cwd);
10203
+ if (location instanceof Error)
10204
+ return;
10205
+ old = path7.join(location.dir, "hooks", "issued");
10206
+ if (!fs4.existsSync(old))
10207
+ return;
10208
+ } catch {
10209
+ return;
10210
+ }
10211
+ for (const lead of safeList(old)) {
10212
+ try {
10213
+ const from = path7.join(old, lead);
10214
+ if (!fs4.statSync(from).isDirectory())
10215
+ continue;
10216
+ const to = path7.join(userIssuedRoot(), lead);
10217
+ fs4.mkdirSync(to, { recursive: true, mode: 448 });
10218
+ for (const id of fs4.readdirSync(from)) {
10219
+ fs4.copyFileSync(path7.join(from, id), path7.join(to, id));
10220
+ fs4.rmSync(path7.join(from, id), { force: true });
10221
+ }
10222
+ removeIfEmpty(from);
10223
+ } catch {}
10224
+ }
10225
+ removeIfEmpty(old);
10226
+ }
10227
+ var safeList = (dir) => {
10228
+ try {
10229
+ return fs4.readdirSync(dir);
10230
+ } catch {
10231
+ return [];
10232
+ }
10121
10233
  };
10122
- var issuedDir = (cwd, lead) => {
10123
- const root = issuedRoot(cwd);
10124
- return root === null ? null : path6.join(root, hash(lead));
10234
+ var removeIfEmpty = (dir) => {
10235
+ try {
10236
+ fs4.rmdirSync(dir);
10237
+ } catch {}
10125
10238
  };
10126
10239
  function recordIssuedSession(cwd, lead, issued) {
10127
10240
  try {
10128
- const dir = issuedDir(cwd, lead);
10129
- if (!dir)
10130
- return;
10131
- fs4.mkdirSync(dir, { recursive: true });
10241
+ migrateRepoIssued(cwd);
10242
+ const dir = path7.join(userIssuedRoot(), hash(lead));
10243
+ fs4.mkdirSync(dir, { recursive: true, mode: 448 });
10132
10244
  const own = hash(issued);
10133
- fs4.writeFileSync(path6.join(dir, own), ISSUED_SESSIONS_MARKER);
10245
+ fs4.writeFileSync(path7.join(dir, own), ISSUED_SESSIONS_MARKER);
10134
10246
  const entries = fs4.readdirSync(dir);
10135
10247
  if (entries.length <= ISSUED_PER_LEAD)
10136
10248
  return;
10137
- const byAge = entries.filter((name) => name !== own).map((name) => ({ name, at: fs4.statSync(path6.join(dir, name)).mtimeMs })).toSorted((a, b) => a.at - b.at);
10249
+ const byAge = entries.filter((name) => name !== own).map((name) => ({ name, at: fs4.statSync(path7.join(dir, name)).mtimeMs })).toSorted((a, b) => a.at - b.at);
10138
10250
  for (const { name } of byAge.slice(0, entries.length - ISSUED_PER_LEAD))
10139
- fs4.rmSync(path6.join(dir, name), { force: true });
10251
+ fs4.rmSync(path7.join(dir, name), { force: true });
10140
10252
  } catch {}
10141
10253
  }
10142
10254
  var OWN_CHILD_SHELL = new Set(["opencode", "pi"]);
@@ -10258,14 +10370,14 @@ function diffHash(cwd, base, head) {
10258
10370
  return `sha256:${hash.digest("hex")}`;
10259
10371
  }
10260
10372
  function storeRoot(cwd) {
10261
- const location = resolveStore(path7.resolve(cwd));
10373
+ const location = resolveStore(path8.resolve(cwd));
10262
10374
  if (location instanceof Error)
10263
10375
  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");
10264
10376
  return { ok: true, value: { root: location.dir, shared: location.shared } };
10265
10377
  }
10266
10378
  function ledgerPath(cwd) {
10267
10379
  const root = storeRoot(cwd);
10268
- return root.ok ? { ok: true, value: path7.join(root.value.root, "ledger", "ledger.jsonl") } : root;
10380
+ return root.ok ? { ok: true, value: path8.join(root.value.root, "ledger", "ledger.jsonl") } : root;
10269
10381
  }
10270
10382
  var newId2 = () => `${Date.now().toString(36)}-${randomBytes(6).toString("hex")}`;
10271
10383
  var NETWORK_FS_TYPES = new Set([
@@ -10295,13 +10407,13 @@ var LOCK_STALE_MS = 30000;
10295
10407
  var LOCK_OWNER = "owner";
10296
10408
  var lockToken = (lock) => {
10297
10409
  try {
10298
- return fs5.readFileSync(path7.join(lock, LOCK_OWNER), "utf8");
10410
+ return fs5.readFileSync(path8.join(lock, LOCK_OWNER), "utf8");
10299
10411
  } catch {
10300
10412
  return null;
10301
10413
  }
10302
10414
  };
10303
10415
  var lockAgeMs = (lock) => {
10304
- for (const target of [path7.join(lock, LOCK_OWNER), lock]) {
10416
+ for (const target of [path8.join(lock, LOCK_OWNER), lock]) {
10305
10417
  try {
10306
10418
  return Date.now() - fs5.statSync(target).mtimeMs;
10307
10419
  } catch {}
@@ -10318,7 +10430,7 @@ var ledgerLock = {
10318
10430
  throw error;
10319
10431
  }
10320
10432
  const token = `${process.pid}-${randomBytes(8).toString("hex")}`;
10321
- fs5.writeFileSync(path7.join(lock, LOCK_OWNER), token);
10433
+ fs5.writeFileSync(path8.join(lock, LOCK_OWNER), token);
10322
10434
  return token;
10323
10435
  },
10324
10436
  release(lock, token) {
@@ -10443,8 +10555,8 @@ function appendLine(file, build, options) {
10443
10555
  }
10444
10556
  };
10445
10557
  try {
10446
- fs5.mkdirSync(path7.dirname(file), { recursive: true });
10447
- if (!options.forceLock && !onNetworkFs(path7.dirname(file)))
10558
+ fs5.mkdirSync(path8.dirname(file), { recursive: true });
10559
+ if (!options.forceLock && !onNetworkFs(path8.dirname(file)))
10448
10560
  return write();
10449
10561
  const locked = withLedgerLock(file, write);
10450
10562
  return locked ?? err("busy", `ledger lock ${file}.lock is held`, "retry; remove the .lock directory if no workit process is running");
@@ -11007,7 +11119,7 @@ var productDecision = (task, ledger) => {
11007
11119
  };
11008
11120
  };
11009
11121
  var planRecorded = (task, root) => {
11010
- const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync2(path8.resolve(root, ref.path)));
11122
+ const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync2(path9.resolve(root, ref.path)));
11011
11123
  if (cited)
11012
11124
  return {
11013
11125
  met: true,
@@ -11622,20 +11734,20 @@ var judgeInputSummary = (raw) => {
11622
11734
  };
11623
11735
 
11624
11736
  // packages/workit-core/src/autonomy.ts
11625
- import os3 from "node:os";
11626
- import path9 from "node:path";
11737
+ import os4 from "node:os";
11738
+ import path10 from "node:path";
11627
11739
  var accountHome = () => {
11628
11740
  try {
11629
- return os3.userInfo().homedir;
11741
+ return os4.userInfo().homedir;
11630
11742
  } catch {
11631
- return os3.homedir();
11743
+ return os4.homedir();
11632
11744
  }
11633
11745
  };
11634
11746
  var grantsHome = { resolve: accountHome };
11635
- var grantsDir = () => path9.join(grantsHome.resolve(), ".config", "workit");
11747
+ var grantsDir = () => path10.join(grantsHome.resolve(), ".config", "workit");
11636
11748
  var grantsOverride = () => {
11637
- const configured = path9.resolve(resolveConfigDir());
11638
- return configured === path9.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 ${path9.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
11749
+ const configured = path10.resolve(resolveConfigDir());
11750
+ return configured === path10.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 ${path10.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
11639
11751
  };
11640
11752
  var GRANT_KINDS = ["push", "pr", "merge", "release", "rerun"];
11641
11753
  var DEFAULT_GRANTS = Object.freeze({
@@ -11761,7 +11873,7 @@ var grantHint = (workspace, kind) => `ask the user to run, in their own terminal
11761
11873
  // packages/workit-core/src/core/task-store.ts
11762
11874
  import { createHash as createHash9, randomUUID as randomUUID3 } from "node:crypto";
11763
11875
  import * as fs11 from "node:fs";
11764
- import path14 from "node:path";
11876
+ import path15 from "node:path";
11765
11877
 
11766
11878
  // node_modules/@openclaw/fs-safe/dist/errors.js
11767
11879
  var OPERATIONAL_CODES = new Set([
@@ -11812,7 +11924,7 @@ function sameFileIdentity(left, right, platform = process.platform) {
11812
11924
  // node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.js
11813
11925
  import { randomBytes as randomBytes2 } from "node:crypto";
11814
11926
  import fsSync from "node:fs";
11815
- import path10 from "node:path";
11927
+ import path11 from "node:path";
11816
11928
 
11817
11929
  // node_modules/@openclaw/fs-safe/dist/bounded-read.js
11818
11930
  import fs6 from "node:fs";
@@ -11902,13 +12014,13 @@ ${ownershipToken}
11902
12014
  return { raw, ownershipToken };
11903
12015
  }
11904
12016
  function relativeSidecarLockPath(lockRoot, lockPath) {
11905
- const resolved = path10.resolve(lockPath);
11906
- const lexicalRelative = path10.relative(lockRoot.rootDir, resolved);
11907
- const relative = lexicalRelative !== ".." && !lexicalRelative.startsWith(`..${path10.sep}`) && !path10.isAbsolute(lexicalRelative) ? lexicalRelative : path10.relative(lockRoot.rootReal, resolved);
11908
- if (!relative || relative === ".." || relative.startsWith(`..${path10.sep}`) || path10.isAbsolute(relative)) {
12017
+ const resolved = path11.resolve(lockPath);
12018
+ const lexicalRelative = path11.relative(lockRoot.rootDir, resolved);
12019
+ const relative = lexicalRelative !== ".." && !lexicalRelative.startsWith(`..${path11.sep}`) && !path11.isAbsolute(lexicalRelative) ? lexicalRelative : path11.relative(lockRoot.rootReal, resolved);
12020
+ if (!relative || relative === ".." || relative.startsWith(`..${path11.sep}`) || path11.isAbsolute(relative)) {
11909
12021
  throw new FsSafeError("outside-workspace", "sidecar lock path is outside lockRoot");
11910
12022
  }
11911
- return relative.split(path10.sep).join(path10.posix.sep);
12023
+ return relative.split(path11.sep).join(path11.posix.sep);
11912
12024
  }
11913
12025
  function parseSidecarLockPayload(raw, parser) {
11914
12026
  if (parser) {
@@ -12055,7 +12167,7 @@ function getFsSafeLockConfig() {
12055
12167
 
12056
12168
  // node_modules/@openclaw/fs-safe/dist/file-lock-sync.js
12057
12169
  import fs8 from "node:fs";
12058
- import path11 from "node:path";
12170
+ import path12 from "node:path";
12059
12171
 
12060
12172
  // node_modules/@openclaw/fs-safe/dist/timing.js
12061
12173
  function sleepSync(ms) {
@@ -12146,26 +12258,26 @@ function canonicalLockParentSync(parent) {
12146
12258
  return process.platform === "win32" ? fs8.realpathSync.native(parent) : fs8.realpathSync(parent);
12147
12259
  }
12148
12260
  function normalizeTargetPath(targetPath) {
12149
- const resolved = path11.resolve(targetPath);
12150
- fs8.mkdirSync(path11.dirname(resolved), { recursive: true });
12261
+ const resolved = path12.resolve(targetPath);
12262
+ fs8.mkdirSync(path12.dirname(resolved), { recursive: true });
12151
12263
  try {
12152
- return path11.join(canonicalLockParentSync(path11.dirname(resolved)), path11.basename(resolved));
12264
+ return path12.join(canonicalLockParentSync(path12.dirname(resolved)), path12.basename(resolved));
12153
12265
  } catch {
12154
12266
  return resolved;
12155
12267
  }
12156
12268
  }
12157
12269
  function boundedLockPath(lockPath, lockRoot) {
12158
- const resolved = path11.resolve(lockPath);
12270
+ const resolved = path12.resolve(lockPath);
12159
12271
  if (!lockRoot)
12160
12272
  return resolved;
12161
12273
  relativeSidecarLockPath(lockRoot, resolved);
12162
- const parent = path11.dirname(resolved);
12274
+ const parent = path12.dirname(resolved);
12163
12275
  const parentReal = canonicalLockParentSync(parent);
12164
- const parentRelative = path11.relative(lockRoot.rootReal, parentReal);
12165
- if (parentRelative === ".." || parentRelative.startsWith(`..${path11.sep}`) || path11.isAbsolute(parentRelative)) {
12276
+ const parentRelative = path12.relative(lockRoot.rootReal, parentReal);
12277
+ if (parentRelative === ".." || parentRelative.startsWith(`..${path12.sep}`) || path12.isAbsolute(parentRelative)) {
12166
12278
  throw new FsSafeError("outside-workspace", "sidecar lock parent is outside lockRoot");
12167
12279
  }
12168
- return path11.join(parentReal, path11.basename(resolved));
12280
+ return path12.join(parentReal, path12.basename(resolved));
12169
12281
  }
12170
12282
  function defaultShouldReclaim(snapshot, staleMs, nowMs) {
12171
12283
  const createdAtMs = sidecarLockPayloadCreatedAtMs(snapshot.payload);
@@ -12366,13 +12478,13 @@ function acquireFileLockSync(targetPath, options) {
12366
12478
  }
12367
12479
  // packages/workit-core/src/core/package-root.ts
12368
12480
  import { existsSync as existsSync3 } from "node:fs";
12369
- import path12 from "node:path";
12481
+ import path13 from "node:path";
12370
12482
  import { fileURLToPath } from "node:url";
12371
12483
  var packageRoot = () => {
12372
- let dir = path12.dirname(fileURLToPath(import.meta.url));
12484
+ let dir = path13.dirname(fileURLToPath(import.meta.url));
12373
12485
  while (true) {
12374
- const parent = path12.dirname(dir);
12375
- if (existsSync3(path12.join(dir, "package.json")) || parent === dir)
12486
+ const parent = path13.dirname(dir);
12487
+ if (existsSync3(path13.join(dir, "package.json")) || parent === dir)
12376
12488
  return dir;
12377
12489
  dir = parent;
12378
12490
  }
@@ -12521,7 +12633,7 @@ var clearAbandonedReclaimGuard = (lockPath, nowMs = Date.now()) => {
12521
12633
  // packages/workit-core/src/store/event-log.ts
12522
12634
  import { randomUUID as randomUUID2 } from "node:crypto";
12523
12635
  import fs10 from "node:fs";
12524
- import path13 from "node:path";
12636
+ import path14 from "node:path";
12525
12637
  var EVENT_VERSION = 1;
12526
12638
 
12527
12639
  class LogDamage extends Error {
@@ -12632,7 +12744,7 @@ function appendEvent(file, event, validEnd) {
12632
12744
  fs10.closeSync(fd);
12633
12745
  }
12634
12746
  if (created)
12635
- fsyncDirectory(path13.dirname(file));
12747
+ fsyncDirectory(path14.dirname(file));
12636
12748
  return validEnd;
12637
12749
  }
12638
12750
  function replaceFile(file, bytes, durable) {
@@ -12648,7 +12760,7 @@ function replaceFile(file, bytes, durable) {
12648
12760
  }
12649
12761
  renameWithRetry(temporary, file);
12650
12762
  if (durable)
12651
- fsyncDirectory(path13.dirname(file));
12763
+ fsyncDirectory(path14.dirname(file));
12652
12764
  } catch (error) {
12653
12765
  try {
12654
12766
  fs10.unlinkSync(temporary);
@@ -12991,7 +13103,7 @@ var cachedRuntimeVersion = null;
12991
13103
  var runtimeVersion = () => {
12992
13104
  if (cachedRuntimeVersion === null) {
12993
13105
  try {
12994
- const pkg = JSON.parse(fs11.readFileSync(path14.join(packageRoot(), "package.json"), "utf8"));
13106
+ const pkg = JSON.parse(fs11.readFileSync(path15.join(packageRoot(), "package.json"), "utf8"));
12995
13107
  cachedRuntimeVersion = typeof pkg.version === "string" && pkg.version ? pkg.version : "0.0.0";
12996
13108
  } catch {
12997
13109
  cachedRuntimeVersion = "0.0.0";
@@ -13024,7 +13136,7 @@ var readText = (file) => {
13024
13136
  };
13025
13137
  var REFLOG_LINE = /^[0-9a-f]+ ([0-9a-f]+) .* (\d+) [+-]\d{4}\t(.*)$/u;
13026
13138
  var branchStart = (location, branch, aliases) => {
13027
- const first = readText(path14.join(path14.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
13139
+ const first = readText(path15.join(path15.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
13028
13140
  `, 1)[0];
13029
13141
  const created = REFLOG_LINE.exec(first);
13030
13142
  const start = created && /^branch: Created from (\S+)$/u.exec(created[3])?.[1];
@@ -13034,7 +13146,7 @@ var branchStart = (location, branch, aliases) => {
13034
13146
  return start;
13035
13147
  if (!location.git)
13036
13148
  return null;
13037
- for (const line of readText(path14.join(location.git.gitDir, "logs", "HEAD")).split(`
13149
+ for (const line of readText(path15.join(location.git.gitDir, "logs", "HEAD")).split(`
13038
13150
  `)) {
13039
13151
  const entry = REFLOG_LINE.exec(line);
13040
13152
  const moved = entry && /^checkout: moving from (\S+) to (\S+)$/u.exec(entry[3]);
@@ -13044,14 +13156,14 @@ var branchStart = (location, branch, aliases) => {
13044
13156
  }
13045
13157
  return null;
13046
13158
  };
13047
- var refExists = (common, ref) => fs11.existsSync(path14.join(common, ref)) || readText(path14.join(common, "packed-refs")).includes(` ${ref}
13159
+ var refExists = (common, ref) => fs11.existsSync(path15.join(common, ref)) || readText(path15.join(common, "packed-refs")).includes(` ${ref}
13048
13160
  `);
13049
13161
  var origins = new Map;
13050
13162
  var sameDirectoryIdentity = (left, right) => {
13051
- if (!path14.isAbsolute(left) || !path14.isAbsolute(right))
13163
+ if (!path15.isAbsolute(left) || !path15.isAbsolute(right))
13052
13164
  return false;
13053
- const normalizedLeft = path14.resolve(left);
13054
- const normalizedRight = path14.resolve(right);
13165
+ const normalizedLeft = path15.resolve(left);
13166
+ const normalizedRight = path15.resolve(right);
13055
13167
  try {
13056
13168
  const a = fs11.statSync(normalizedLeft, { bigint: true });
13057
13169
  const b = fs11.statSync(normalizedRight, { bigint: true });
@@ -13097,7 +13209,7 @@ class TaskStore {
13097
13209
  migrationChecked = false;
13098
13210
  compactDue = new Set;
13099
13211
  constructor(root, options = {}) {
13100
- const resolved = path14.resolve(root);
13212
+ const resolved = path15.resolve(root);
13101
13213
  this.origin = fs11.existsSync(resolved) ? fs11.realpathSync(resolved) : resolved;
13102
13214
  this.located = resolveStore(this.origin);
13103
13215
  this.root = checkoutRootOf(this.origin, this.located);
@@ -13106,7 +13218,7 @@ class TaskStore {
13106
13218
  this.migrateOnRead = options.migrateOnRead;
13107
13219
  }
13108
13220
  location() {
13109
- if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs11.existsSync(path14.join(this.root, ".git"))) {
13221
+ if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs11.existsSync(path15.join(this.root, ".git"))) {
13110
13222
  this.located = undefined;
13111
13223
  this.migrationChecked = false;
13112
13224
  }
@@ -13262,7 +13374,7 @@ class TaskStore {
13262
13374
  const moved = this.bindLocked(again.data.id, key, input.now);
13263
13375
  return moved.ok ? success(moved.data.revision, null, { task: moved.data, created: false, key }) : moved;
13264
13376
  }
13265
- const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path14.basename(this.root) || this.root;
13377
+ const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path15.basename(this.root) || this.root;
13266
13378
  const intent = {
13267
13379
  objective: input.objective?.trim() || `Work on ${label}`,
13268
13380
  scope: { description: `the checkout (${label})`, paths: ["."], exclusions: [] },
@@ -13322,14 +13434,14 @@ class TaskStore {
13322
13434
  const branch = key.ok ? key.data.branch : null;
13323
13435
  if (!branch || !location.ok)
13324
13436
  return success(null, null, null);
13325
- const common = path14.dirname(location.data.dir);
13326
- const heads = path14.join(common, "logs", "refs", "heads");
13327
- const headLog = location.data.git ? path14.join(location.data.git.gitDir, "logs", "HEAD") : "";
13437
+ const common = path15.dirname(location.data.dir);
13438
+ const heads = path15.join(common, "logs", "refs", "heads");
13439
+ const headLog = location.data.git ? path15.join(location.data.git.gitDir, "logs", "HEAD") : "";
13328
13440
  const signatures = [
13329
- path14.join(heads, branch),
13441
+ path15.join(heads, branch),
13330
13442
  headLog,
13331
13443
  heads,
13332
- path14.join(common, "packed-refs")
13444
+ path15.join(common, "packed-refs")
13333
13445
  ].map((file) => fileSignature(file) ?? "-");
13334
13446
  const slot = `${location.data.dir}\x00${headLog}\x00${branch}`;
13335
13447
  let resolved = origins.get(slot);
@@ -13341,7 +13453,7 @@ class TaskStore {
13341
13453
  aliases.push(rename.from);
13342
13454
  const start = branchStart(location.data, branch, aliases);
13343
13455
  const slash = start?.indexOf("/") ?? -1;
13344
- const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(path14.join(common, "config")).includes(`[remote "${start.slice(0, slash)}"]`));
13456
+ const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(path15.join(common, "config")).includes(`[remote "${start.slice(0, slash)}"]`));
13345
13457
  const name = start && (remote ? start.slice(slash + 1) : start);
13346
13458
  resolved = {
13347
13459
  signature: signatures.join("|"),
@@ -13579,13 +13691,13 @@ class TaskStore {
13579
13691
  if (!ready.ok)
13580
13692
  return ready;
13581
13693
  const dirs = this.paths();
13582
- const recovery = path14.join(this.root, ".workit", "recovery");
13694
+ const recovery = path15.join(this.root, ".workit", "recovery");
13583
13695
  if (fs11.existsSync(recovery)) {
13584
13696
  let files = 0;
13585
13697
  let bytes = 0;
13586
13698
  try {
13587
13699
  for (const name of fs11.readdirSync(recovery)) {
13588
- const stat = fs11.lstatSync(path14.join(recovery, name));
13700
+ const stat = fs11.lstatSync(path15.join(recovery, name));
13589
13701
  if (!stat.isFile())
13590
13702
  continue;
13591
13703
  files += 1;
@@ -13638,7 +13750,7 @@ class TaskStore {
13638
13750
  if (fs11.existsSync(dirs.blobs))
13639
13751
  for (const name of fs11.readdirSync(dirs.blobs)) {
13640
13752
  const digest = name.replace(/\.json$/, "");
13641
- const file = path14.join(dirs.blobs, name);
13753
+ const file = path15.join(dirs.blobs, name);
13642
13754
  let stat;
13643
13755
  try {
13644
13756
  stat = fs11.lstatSync(file);
@@ -13656,7 +13768,7 @@ class TaskStore {
13656
13768
  }
13657
13769
  return success(null, null, null);
13658
13770
  };
13659
- const swept = dryRun ? sweep() : this.withLock(path14.join(dirs.dir, "gc.lock"), sweep);
13771
+ const swept = dryRun ? sweep() : this.withLock(path15.join(dirs.dir, "gc.lock"), sweep);
13660
13772
  if (!swept.ok)
13661
13773
  return swept;
13662
13774
  const temporaryDirs = [
@@ -13664,7 +13776,7 @@ class TaskStore {
13664
13776
  dirs.tasks,
13665
13777
  dirs.blobs,
13666
13778
  dirs.checkout,
13667
- ...names.map((name) => path14.join(dirs.tasks, name))
13779
+ ...names.map((name) => path15.join(dirs.tasks, name))
13668
13780
  ];
13669
13781
  for (const directory of temporaryDirs) {
13670
13782
  if (!fs11.existsSync(directory))
@@ -13672,7 +13784,7 @@ class TaskStore {
13672
13784
  for (const name of fs11.readdirSync(directory)) {
13673
13785
  if (!name.endsWith(".tmp") && !name.endsWith(".probe"))
13674
13786
  continue;
13675
- const file = path14.join(directory, name);
13787
+ const file = path15.join(directory, name);
13676
13788
  try {
13677
13789
  const stat = fs11.lstatSync(file);
13678
13790
  if (!stat.isFile() || nowMs - stat.mtimeMs <= STALE_TEMPORARY_MS)
@@ -13689,30 +13801,30 @@ class TaskStore {
13689
13801
  }
13690
13802
  paths() {
13691
13803
  const location = this.location();
13692
- const dir = location.ok ? location.data.dir : path14.join(this.root, ".workit");
13693
- const checkout = path14.join(dir, "checkouts", checkoutSlug(this.root));
13804
+ const dir = location.ok ? location.data.dir : path15.join(this.root, ".workit");
13805
+ const checkout = path15.join(dir, "checkouts", checkoutSlug(this.root));
13694
13806
  return {
13695
13807
  dir,
13696
13808
  shared: location.ok ? location.data.shared : false,
13697
- marker: path14.join(dir, "store.json"),
13809
+ marker: path15.join(dir, "store.json"),
13698
13810
  checkout,
13699
- workspace: path14.join(checkout, "workspace.json"),
13700
- checkoutLock: path14.join(checkout, "metadata.lock"),
13701
- tasks: path14.join(dir, "tasks"),
13702
- index: path14.join(dir, "task-index.json"),
13703
- blobs: path14.join(dir, "blobs", "candidates"),
13704
- legacy: path14.join(dir, "legacy", checkoutSlug(this.root), "v2"),
13705
- v2: path14.join(this.root, ".workit")
13811
+ workspace: path15.join(checkout, "workspace.json"),
13812
+ checkoutLock: path15.join(checkout, "metadata.lock"),
13813
+ tasks: path15.join(dir, "tasks"),
13814
+ index: path15.join(dir, "task-index.json"),
13815
+ blobs: path15.join(dir, "blobs", "candidates"),
13816
+ legacy: path15.join(dir, "legacy", checkoutSlug(this.root), "v2"),
13817
+ v2: path15.join(this.root, ".workit")
13706
13818
  };
13707
13819
  }
13708
13820
  eventsPath(taskId) {
13709
- return path14.join(this.paths().tasks, taskId, "events.jsonl");
13821
+ return path15.join(this.paths().tasks, taskId, "events.jsonl");
13710
13822
  }
13711
13823
  snapshotPath(taskId) {
13712
- return path14.join(this.paths().tasks, taskId, "snapshot.json");
13824
+ return path15.join(this.paths().tasks, taskId, "snapshot.json");
13713
13825
  }
13714
13826
  taskLockPath(taskId) {
13715
- return path14.join(this.paths().tasks, taskId, "lock");
13827
+ return path15.join(this.paths().tasks, taskId, "lock");
13716
13828
  }
13717
13829
  ready(write = false) {
13718
13830
  const location = this.location();
@@ -13751,13 +13863,13 @@ class TaskStore {
13751
13863
  return {
13752
13864
  read: (digest) => {
13753
13865
  try {
13754
- return JSON.parse(fs11.readFileSync(path14.join(dir, `${digest}.json`), "utf8"));
13866
+ return JSON.parse(fs11.readFileSync(path15.join(dir, `${digest}.json`), "utf8"));
13755
13867
  } catch (error) {
13756
13868
  throw new LogDamage(`stored candidate ${digest} is missing or unreadable: ${String(error)}`);
13757
13869
  }
13758
13870
  },
13759
13871
  write: (digest, value) => {
13760
- const file = path14.join(dir, `${digest}.json`);
13872
+ const file = path15.join(dir, `${digest}.json`);
13761
13873
  if (fs11.existsSync(file)) {
13762
13874
  const stamp = new Date;
13763
13875
  try {
@@ -13949,7 +14061,7 @@ class TaskStore {
13949
14061
  }
13950
14062
  }
13951
14063
  openTask(record, type, key, legacy = null) {
13952
- const dir = path14.join(this.paths().tasks, record.id);
14064
+ const dir = path15.join(this.paths().tasks, record.id);
13953
14065
  fs11.mkdirSync(dir, { recursive: true });
13954
14066
  const blobs = this.blobStore();
13955
14067
  const bound = key ? { ...key, boundAt: key.boundAt ?? new Date().toISOString() } : null;
@@ -14042,7 +14154,7 @@ class TaskStore {
14042
14154
  }
14043
14155
  withKeyLock(key, operation) {
14044
14156
  const digest = createHash9("sha256").update(key).digest("hex").slice(0, 32);
14045
- return this.withLock(path14.join(this.paths().dir, "keys", `${digest}.lock`), operation);
14157
+ return this.withLock(path15.join(this.paths().dir, "keys", `${digest}.lock`), operation);
14046
14158
  }
14047
14159
  bindLocked(taskId, key, timestamp) {
14048
14160
  const current = this.readWorkspace();
@@ -14183,7 +14295,7 @@ class TaskStore {
14183
14295
  writeWorkspace(record) {
14184
14296
  const file = this.paths().workspace;
14185
14297
  try {
14186
- fs11.mkdirSync(path14.dirname(file), { recursive: true });
14298
+ fs11.mkdirSync(path15.dirname(file), { recursive: true });
14187
14299
  replaceFile(file, `${canonicalJson(record)}
14188
14300
  `, true);
14189
14301
  return success(null, null, null);
@@ -14261,23 +14373,23 @@ class TaskStore {
14261
14373
  return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", { expectedWorkspaceRevision: expected, actualWorkspaceRevision: actual });
14262
14374
  }
14263
14375
  v2Dirs() {
14264
- return [...new Set([this.root, this.origin])].map((dir) => path14.join(dir, ".workit"));
14376
+ return [...new Set([this.root, this.origin])].map((dir) => path15.join(dir, ".workit"));
14265
14377
  }
14266
14378
  pendingMigrations() {
14267
14379
  return this.v2Dirs().filter((dir) => {
14268
- const raw = this.readV2Workspace(path14.join(dir, "workspace.json"));
14380
+ const raw = this.readV2Workspace(path15.join(dir, "workspace.json"));
14269
14381
  return raw !== null && raw !== TOMBSTONE;
14270
14382
  });
14271
14383
  }
14272
14384
  migrateV2(v2) {
14273
14385
  const dirs = this.paths();
14274
- const v2Workspace = path14.join(v2, "workspace.json");
14275
- const v2Tasks = path14.join(v2, "tasks");
14276
- const legacy = path14.join(dirs.dir, "legacy", checkoutSlug(path14.dirname(v2)), "v2");
14386
+ const v2Workspace = path15.join(v2, "workspace.json");
14387
+ const v2Tasks = path15.join(v2, "tasks");
14388
+ const legacy = path15.join(dirs.dir, "legacy", checkoutSlug(path15.dirname(v2)), "v2");
14277
14389
  const raw = this.readV2Workspace(v2Workspace);
14278
14390
  if (raw === null || raw === TOMBSTONE)
14279
14391
  return success(null, null, null);
14280
- return this.withLock(dirs.checkoutLock, () => this.withLock(path14.join(v2, "metadata.lock"), () => {
14392
+ return this.withLock(dirs.checkoutLock, () => this.withLock(path15.join(v2, "metadata.lock"), () => {
14281
14393
  const workspace = this.readV2Workspace(v2Workspace);
14282
14394
  if (workspace === null || workspace === TOMBSTONE)
14283
14395
  return success(null, null, null);
@@ -14286,7 +14398,7 @@ class TaskStore {
14286
14398
  return failure2("recovery_required", `cannot migrate the 2.x store at ${v2}: ${parsedWorkspace.error}; move it aside to start fresh`, { path: v2Workspace });
14287
14399
  let files = [];
14288
14400
  try {
14289
- files = fs11.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path14.join(v2Tasks, name)));
14401
+ files = fs11.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path15.join(v2Tasks, name)));
14290
14402
  } catch {}
14291
14403
  const current = this.readWorkspace();
14292
14404
  if (!current.ok)
@@ -14304,21 +14416,21 @@ class TaskStore {
14304
14416
  let skipped = 0;
14305
14417
  const done = new Map;
14306
14418
  try {
14307
- fs11.mkdirSync(path14.join(legacy, "tasks"), { recursive: true });
14419
+ fs11.mkdirSync(path15.join(legacy, "tasks"), { recursive: true });
14308
14420
  for (const name of ["workspace.json", "index.json"])
14309
- if (fs11.existsSync(path14.join(v2, name)))
14310
- fs11.copyFileSync(path14.join(v2, name), path14.join(legacy, name));
14421
+ if (fs11.existsSync(path15.join(v2, name)))
14422
+ fs11.copyFileSync(path15.join(v2, name), path15.join(legacy, name));
14311
14423
  for (const name of files) {
14312
14424
  const id = name.slice(0, -5);
14313
- const file = path14.join(v2Tasks, name);
14425
+ const file = path15.join(v2Tasks, name);
14314
14426
  const bytes = fs11.readFileSync(file, "utf8");
14315
14427
  const digest = sha256(bytes);
14316
- fs11.writeFileSync(path14.join(legacy, "tasks", name), bytes);
14428
+ fs11.writeFileSync(path15.join(legacy, "tasks", name), bytes);
14317
14429
  const parsed = this.parseRecord(bytes, taskRecordSchema, "2.x task");
14318
14430
  if (!parsed.ok || parsed.data.id !== id)
14319
14431
  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 });
14320
14432
  const record = { ...parsed.data, workspaceId: target.id };
14321
- const origin = { path: path14.join(legacy, "tasks", name), digest };
14433
+ const origin = { path: path15.join(legacy, "tasks", name), digest };
14322
14434
  if (!fs11.existsSync(this.eventsPath(id))) {
14323
14435
  this.openTask(record, "migrated.from_v2", null, origin);
14324
14436
  migrated += 1;
@@ -14354,7 +14466,7 @@ class TaskStore {
14354
14466
  try {
14355
14467
  let complete = true;
14356
14468
  for (const [name, digest] of done) {
14357
- const file = path14.join(v2Tasks, name);
14469
+ const file = path15.join(v2Tasks, name);
14358
14470
  if (sha256(fs11.readFileSync(file, "utf8")) !== digest) {
14359
14471
  complete = false;
14360
14472
  continue;
@@ -14365,7 +14477,7 @@ class TaskStore {
14365
14477
  return failure2("busy", `the 2.x store at ${v2} changed during migration; retry`, {
14366
14478
  path: v2
14367
14479
  });
14368
- fs11.rmSync(path14.join(v2, "index.json"), { force: true });
14480
+ fs11.rmSync(path15.join(v2, "index.json"), { force: true });
14369
14481
  this.writeTombstone(v2, target.id);
14370
14482
  } catch (error) {
14371
14483
  return failure2("storage_error", `cannot finish the 2.x migration: ${String(error)}`, {
@@ -14385,7 +14497,7 @@ class TaskStore {
14385
14497
  }
14386
14498
  adoptLocalStore() {
14387
14499
  const dirs = this.paths();
14388
- const marker = path14.join(dirs.v2, "store.json");
14500
+ const marker = path15.join(dirs.v2, "store.json");
14389
14501
  if (!dirs.shared || !fs11.existsSync(marker))
14390
14502
  return success(null, null, null);
14391
14503
  return this.withLock(dirs.checkoutLock, () => {
@@ -14395,7 +14507,7 @@ class TaskStore {
14395
14507
  try {
14396
14508
  const merge = (from, to) => {
14397
14509
  if (!fs11.existsSync(to)) {
14398
- fs11.mkdirSync(path14.dirname(to), { recursive: true });
14510
+ fs11.mkdirSync(path15.dirname(to), { recursive: true });
14399
14511
  try {
14400
14512
  fs11.renameSync(from, to);
14401
14513
  } catch {
@@ -14406,24 +14518,24 @@ class TaskStore {
14406
14518
  }
14407
14519
  if (fs11.lstatSync(from).isDirectory() && fs11.lstatSync(to).isDirectory())
14408
14520
  for (const name of fs11.readdirSync(from))
14409
- merge(path14.join(from, name), path14.join(to, name));
14521
+ merge(path15.join(from, name), path15.join(to, name));
14410
14522
  };
14411
14523
  for (const sub of ["tasks", "checkouts", "blobs", "legacy"]) {
14412
- const from = path14.join(dirs.v2, sub);
14524
+ const from = path15.join(dirs.v2, sub);
14413
14525
  if (!fs11.existsSync(from))
14414
14526
  continue;
14415
14527
  if (sub === "tasks") {
14416
14528
  for (const name of fs11.readdirSync(from))
14417
- if (validId(name) && !fs11.existsSync(path14.join(dirs.dir, sub, name)))
14529
+ if (validId(name) && !fs11.existsSync(path15.join(dirs.dir, sub, name)))
14418
14530
  tasks += 1;
14419
14531
  }
14420
- merge(from, path14.join(dirs.dir, sub));
14532
+ merge(from, path15.join(dirs.dir, sub));
14421
14533
  }
14422
- const ledger = path14.join(dirs.v2, "ledger");
14423
- if (fs11.existsSync(ledger) && !fs11.existsSync(path14.join(dirs.dir, "ledger")))
14424
- merge(ledger, path14.join(dirs.dir, "ledger"));
14425
- fs11.rmSync(path14.join(dirs.v2, "task-index.json"), { force: true });
14426
- fs11.renameSync(marker, path14.join(dirs.v2, "store.moved.json"));
14534
+ const ledger = path15.join(dirs.v2, "ledger");
14535
+ if (fs11.existsSync(ledger) && !fs11.existsSync(path15.join(dirs.dir, "ledger")))
14536
+ merge(ledger, path15.join(dirs.dir, "ledger"));
14537
+ fs11.rmSync(path15.join(dirs.v2, "task-index.json"), { force: true });
14538
+ fs11.renameSync(marker, path15.join(dirs.v2, "store.moved.json"));
14427
14539
  } catch (error) {
14428
14540
  return failure2("storage_error", `cannot move ${dirs.v2} into ${dirs.dir}: ${String(error)}`, {
14429
14541
  path: dirs.v2
@@ -14461,7 +14573,7 @@ class TaskStore {
14461
14573
  schemaVersion: SCHEMA_VERSION,
14462
14574
  id: workspaceId ?? newId(),
14463
14575
  revision: newRevision(),
14464
- root: path14.dirname(v2),
14576
+ root: path15.dirname(v2),
14465
14577
  runtime: { createdWith: version, updatedWith: version },
14466
14578
  writer: null,
14467
14579
  store: {
@@ -14473,11 +14585,11 @@ class TaskStore {
14473
14585
  critical: ["store"]
14474
14586
  };
14475
14587
  fs11.mkdirSync(v2, { recursive: true });
14476
- const ignore = path14.join(v2, ".gitignore");
14588
+ const ignore = path15.join(v2, ".gitignore");
14477
14589
  if (!fs11.existsSync(ignore))
14478
14590
  fs11.writeFileSync(ignore, `*
14479
14591
  `);
14480
- replaceFile(path14.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
14592
+ replaceFile(path15.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
14481
14593
  `, true);
14482
14594
  }
14483
14595
  stubFor(taskId) {
@@ -14501,8 +14613,8 @@ class TaskStore {
14501
14613
  }
14502
14614
  writeTombstoneIfMissing() {
14503
14615
  try {
14504
- const v2 = path14.join(this.root, ".workit");
14505
- if (fs11.existsSync(path14.join(v2, "workspace.json")))
14616
+ const v2 = path15.join(this.root, ".workit");
14617
+ if (fs11.existsSync(path15.join(v2, "workspace.json")))
14506
14618
  return;
14507
14619
  let id = null;
14508
14620
  try {
@@ -14519,7 +14631,7 @@ class TaskStore {
14519
14631
  replaceFile(dirs.marker, `${JSON.stringify({ format: "workit-store", version: STORE_FORMAT, createdWith: runtimeVersion() })}
14520
14632
  `, false);
14521
14633
  if (!dirs.shared) {
14522
- const ignore = path14.join(dirs.dir, ".gitignore");
14634
+ const ignore = path15.join(dirs.dir, ".gitignore");
14523
14635
  let current = null;
14524
14636
  try {
14525
14637
  current = fs11.readFileSync(ignore, "utf8");
@@ -14579,7 +14691,7 @@ class TaskStore {
14579
14691
  withLock(lockPath, operation) {
14580
14692
  try {
14581
14693
  this.initializeStorage();
14582
- fs11.mkdirSync(path14.dirname(lockPath), { recursive: true });
14694
+ fs11.mkdirSync(path15.dirname(lockPath), { recursive: true });
14583
14695
  } catch (error) {
14584
14696
  return failure2("storage_error", `unable to initialize store: ${String(error)}`, {
14585
14697
  path: this.paths().dir
@@ -14642,7 +14754,7 @@ class TaskStore {
14642
14754
  if (isTransientWindowsError(error) && !this.lockHolderPresent(lockPath) && !this.lockDirWritable(lockPath))
14643
14755
  return failure2("storage_error", `cannot create the workit lock (${code}); no other Workit call holds it`, {
14644
14756
  path: lockPath,
14645
- guidance: `Check permissions and the read-only attribute on ${path14.dirname(lockPath)}.`
14757
+ guidance: `Check permissions and the read-only attribute on ${path15.dirname(lockPath)}.`
14646
14758
  });
14647
14759
  if (code === "EEXIST" || code === "file_lock_timeout" || code === "file_lock_stale" || isTransientWindowsError(error)) {
14648
14760
  let lock = null;
@@ -14669,12 +14781,12 @@ var workerBlocksTransition = (transition, state) => transition === "pause" ? fal
14669
14781
  import { createHash as createHash10 } from "node:crypto";
14670
14782
  import * as fs13 from "node:fs";
14671
14783
  import { spawnSync as spawnSync10 } from "node:child_process";
14672
- import path16 from "node:path";
14784
+ import path17 from "node:path";
14673
14785
 
14674
14786
  // packages/workit-core/src/check-config.ts
14675
14787
  import { spawnSync as spawnSync9 } from "node:child_process";
14676
14788
  import fs12 from "node:fs";
14677
- import path15 from "node:path";
14789
+ import path16 from "node:path";
14678
14790
  var SCRIPT_CHECKS = ["test", "lint", "typecheck", "check"];
14679
14791
  var CHECKS_FILE = "workit.checks.json";
14680
14792
  var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
@@ -14727,10 +14839,10 @@ var git4 = (cwd, args) => {
14727
14839
  return value || null;
14728
14840
  };
14729
14841
  function checkRoot(cwd) {
14730
- return path15.resolve(git4(cwd, ["rev-parse", "--show-toplevel"]) ?? cwd);
14842
+ return path16.resolve(git4(cwd, ["rev-parse", "--show-toplevel"]) ?? cwd);
14731
14843
  }
14732
14844
  var packageManager = (root) => {
14733
- const has = (file) => fs12.existsSync(path15.join(root, file));
14845
+ const has = (file) => fs12.existsSync(path16.join(root, file));
14734
14846
  if (has("bun.lock") || has("bun.lockb"))
14735
14847
  return "bun";
14736
14848
  if (has("pnpm-lock.yaml"))
@@ -14750,7 +14862,7 @@ var CHECK_NAME = /^[a-z0-9][a-z0-9:._-]{0,63}$/u;
14750
14862
  function detectedChecks(root) {
14751
14863
  const read = (file) => {
14752
14864
  try {
14753
- return fs12.readFileSync(path15.join(root, file), "utf8");
14865
+ return fs12.readFileSync(path16.join(root, file), "utf8");
14754
14866
  } catch {
14755
14867
  return null;
14756
14868
  }
@@ -14789,7 +14901,7 @@ function detectedChecks(root) {
14789
14901
  var GATES = ["testing", "verification"];
14790
14902
  function loadCheckConfig(cwd) {
14791
14903
  const root = checkRoot(cwd);
14792
- const file = path15.join(root, CHECKS_FILE);
14904
+ const file = path16.join(root, CHECKS_FILE);
14793
14905
  const none = (error = null) => ({
14794
14906
  source: error ? CHECKS_FILE : "none",
14795
14907
  root,
@@ -14838,7 +14950,7 @@ function loadCheckConfig(cwd) {
14838
14950
  gates[gate] = names;
14839
14951
  }
14840
14952
  }
14841
- return { source: CHECKS_FILE, root, checks, gates, error: null };
14953
+ return { source: CHECKS_FILE, root, checks, gates, error: null, resources: parsed.resources };
14842
14954
  }
14843
14955
  var sameArgv = (left, right) => left.length === right.length && left.every((item, index) => item === right[index]);
14844
14956
  function matchesNamedCheck(config, name, argv, cwd) {
@@ -14862,10 +14974,10 @@ function workitAvailable(env = process.env) {
14862
14974
  return workitOnPath;
14863
14975
  const windows = process.platform === "win32";
14864
14976
  const exts = windows ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
14865
- const dirs = (env.PATH ?? env.Path ?? "").split(path15.delimiter).filter(Boolean);
14977
+ const dirs = (env.PATH ?? env.Path ?? "").split(path16.delimiter).filter(Boolean);
14866
14978
  workitOnPath = dirs.some((dir) => exts.some((ext) => {
14867
14979
  try {
14868
- return fs12.statSync(path15.join(dir, `workit${ext}`)).isFile();
14980
+ return fs12.statSync(path16.join(dir, `workit${ext}`)).isFile();
14869
14981
  } catch {
14870
14982
  return false;
14871
14983
  }
@@ -14878,14 +14990,14 @@ function checkCommand(args, version, onPath = workitAvailable()) {
14878
14990
 
14879
14991
  // packages/workit-core/src/core/task-evaluation.ts
14880
14992
  var digestBytes = (value) => createHash10("sha256").update(value).digest("hex");
14881
- var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path16.sep}`);
14882
- var relative = (root, candidate) => path16.relative(root, candidate).split(path16.sep).join("/") || ".";
14993
+ var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path17.sep}`);
14994
+ var relative = (root, candidate) => path17.relative(root, candidate).split(path17.sep).join("/") || ".";
14883
14995
  var canonicalPath = (value) => {
14884
14996
  if (typeof value !== "string" || !value)
14885
14997
  return null;
14886
14998
  if (value.includes("\\") || value.split("/").includes(".."))
14887
14999
  return null;
14888
- const normalized = path16.posix.normalize(value);
15000
+ const normalized = path17.posix.normalize(value);
14889
15001
  if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
14890
15002
  return null;
14891
15003
  return normalized === "." ? "." : normalized.replace(/\/$/, "");
@@ -14933,14 +15045,14 @@ var gitPaths = (root) => {
14933
15045
  git: !/not a git repository/i.test(stderr)
14934
15046
  };
14935
15047
  }
14936
- const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path16.sep).join("/")) : [];
15048
+ const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path17.sep).join("/")) : [];
14937
15049
  const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
14938
15050
  if (stagedDeleted.status !== 0) {
14939
15051
  const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
14940
15052
  if (!/not a git repository/i.test(stderr))
14941
15053
  return { paths, uncertain: true, git: true };
14942
15054
  } else if (stagedDeleted.stdout) {
14943
- paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path16.sep).join("/")));
15055
+ paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path17.sep).join("/")));
14944
15056
  }
14945
15057
  return { paths: [...new Set(paths)], uncertain: false, git: true };
14946
15058
  };
@@ -14955,7 +15067,7 @@ var walk = (root, directory, output) => {
14955
15067
  for (const name of names) {
14956
15068
  if (name === ".git" || name === ".workit")
14957
15069
  continue;
14958
- const target = path16.join(directory, name);
15070
+ const target = path17.join(directory, name);
14959
15071
  let stat;
14960
15072
  try {
14961
15073
  stat = fs13.lstatSync(target);
@@ -14973,12 +15085,12 @@ var walk = (root, directory, output) => {
14973
15085
  var scopeRoots = (root, scope) => {
14974
15086
  const roots = [];
14975
15087
  for (const item of scope.paths.length ? scope.paths : ["."]) {
14976
- const target = path16.resolve(root, item);
15088
+ const target = path17.resolve(root, item);
14977
15089
  if (!inside(root, target))
14978
15090
  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` }] });
14979
15091
  let ancestor = target;
14980
15092
  while (!fs13.existsSync(ancestor) && ancestor !== root)
14981
- ancestor = path16.dirname(ancestor);
15093
+ ancestor = path17.dirname(ancestor);
14982
15094
  try {
14983
15095
  if (!inside(root, fs13.realpathSync(ancestor)))
14984
15096
  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` }] });
@@ -15030,7 +15142,7 @@ function captureCandidate(root, scope, environment = []) {
15030
15142
  for (const item of [...names].toSorted()) {
15031
15143
  if (!scopeMatches(item, normalizedScope))
15032
15144
  continue;
15033
- const target = path16.join(checkout, item);
15145
+ const target = path17.join(checkout, item);
15034
15146
  try {
15035
15147
  const stat = fs13.lstatSync(target);
15036
15148
  if (stat.isSymbolicLink()) {
@@ -15214,23 +15326,23 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
15214
15326
  continue;
15215
15327
  if (!reference.digest)
15216
15328
  return failure2("invalid_input", "document references require a byte digest");
15217
- const target = path16.resolve(root, reference.path);
15218
- if (target !== root && !target.startsWith(`${root}${path16.sep}`))
15329
+ const target = path17.resolve(root, reference.path);
15330
+ if (target !== root && !target.startsWith(`${root}${path17.sep}`))
15219
15331
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
15220
15332
  fields: [
15221
15333
  { path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
15222
15334
  ]
15223
15335
  });
15224
15336
  try {
15225
- const below = path16.relative(root, target);
15337
+ const below = path17.relative(root, target);
15226
15338
  let current = root;
15227
- for (const segment of below.split(path16.sep)) {
15339
+ for (const segment of below.split(path17.sep)) {
15228
15340
  if (!segment)
15229
15341
  continue;
15230
- current = path16.join(current, segment);
15342
+ current = path17.join(current, segment);
15231
15343
  const stat = fs13.lstatSync(current);
15232
15344
  const real = fs13.realpathSync(current);
15233
- if (real !== root && !real.startsWith(`${root}${path16.sep}`))
15345
+ if (real !== root && !real.startsWith(`${root}${path17.sep}`))
15234
15346
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
15235
15347
  fields: [
15236
15348
  {
@@ -15605,9 +15717,9 @@ Autonomy contract:
15605
15717
  ship), go to the effective endpoint in \`workit grant show\`: \`pr\` opens
15606
15718
  the PR; \`green\` babysits it without asking (workit-ship) to merge-ready,
15607
15719
  never merging; \`merged\` also lands it with \`workit pr merge\`.
15608
- Merge and release need a workspace grant, which only the user raises from
15609
- their own terminal (a blocked verb names how); never edit workspaces.json or
15610
- route around a grant_required.
15720
+ Merge and release need a workspace grant only the user raises from their
15721
+ own terminal (a blocked verb names how); never edit workspaces.json or route
15722
+ around a grant_required.
15611
15723
  - Ask only for a product or preference choice, or for authority you lack, with
15612
15724
  your recommended answer. Facts are yours: read, run or prototype.
15613
15725
  - Label claims measured (run and seen this session), inferred, or guess.
@@ -15616,17 +15728,19 @@ Autonomy contract:
15616
15728
  - Author is not verifier: your own verdict is \`--self\`, shown as
15617
15729
  self-reviewed, never verified. High risk, \`verification: independent\` and
15618
15730
  merge need a verifier with its own host-derived session (a subagent's
15619
- \`<lead>:<child>\`, set by the host); never hand-mint one such as \`<lead>-v1\`.
15731
+ \`<lead>:<child>\`); never hand-mint one (\`<lead>-v1\`).
15620
15732
  - A local-commit endpoint does not imply PR readiness, and a local commit alone
15621
15733
  is not evidence of a requested remote push. Before reporting delivery,
15622
15734
  reconcile every requested item and observe it (\`workit verify-delivery\`).
15623
15735
 
15624
15736
  CLI first: if a step has one right answer, use the \`workit\` verb instead of
15625
15737
  hand-running git, gh or glab (\`workit git|pr|ci|check\`; \`workit help\` lists
15626
- the rest; without \`workit\` on PATH, \`npx -y @brainervirus/workit-cli\`).
15738
+ the rest; lacking \`workit\`, \`npx -y @brainervirus/workit-cli\`).
15739
+ Add Co-Authored-By via \`workit git commit --trailer "K: v" -- <paths>\`, never
15740
+ an amend.
15627
15741
  The task families (task, policy, evidence, finding, decision, worker, state)
15628
15742
  are optional continuity for tracked work; each branch has one implicit task,
15629
- created by the first recording, and a solo edit needs no task. A decision
15743
+ and a solo edit needs no task. A decision
15630
15744
  records a user choice; it never authorizes an effect. Judge work once with
15631
15745
  \`workit policy assess --judge risk= behavior= product-choice= plan=\`.
15632
15746
  Across repositories, bind each item to its checkout, branch and endpoint,
@@ -17446,7 +17560,7 @@ var capabilitiesFor = (descriptor, observed = {}) => descriptor.capabilities.map
17446
17560
  // packages/workit-core/src/hooks/context.ts
17447
17561
  import { createHash as createHash11 } from "node:crypto";
17448
17562
  import fs14 from "node:fs";
17449
- import path17 from "node:path";
17563
+ import path18 from "node:path";
17450
17564
  var MIGRATION_PENDING_NOTE = "workit migration pending — run `workit task status`";
17451
17565
  var migrationPending = (result) => !result.ok && result.code === "needs_input" && (result.error ?? "").startsWith(MIGRATION_PENDING);
17452
17566
  var boundTo = (entry, session) => entry.sessions.some((item) => item.host === session.host && item.handle === session.handle);
@@ -17531,7 +17645,7 @@ function entryCompactContext(store, entry, session, context) {
17531
17645
  return null;
17532
17646
  const freshness = { mode: "signal", current: () => recentSignal(store.root) };
17533
17647
  const observed = task?.data.evidence.some(isObservedCheck) ?? false;
17534
- const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [path17.resolve(store.root, ref.path)] : []));
17648
+ const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [path18.resolve(store.root, ref.path)] : []));
17535
17649
  const observedFiles = filesKey(files);
17536
17650
  const compact = new WorkitCore(store, context).compactContext(entry?.id ?? null, freshness, origin && { origin: origin.origin, taskId: origin.entry.id });
17537
17651
  if (!compact.ok || !compact.data)
@@ -17609,14 +17723,14 @@ var turnMarker = (input) => {
17609
17723
  if (location instanceof Error)
17610
17724
  return null;
17611
17725
  const session = [input.host, input.session.id, input.session.agentId ?? ""].join("\x00");
17612
- return path17.join(location.dir, "hooks", `turn-${digestOf(session).slice(0, 32)}.json`);
17726
+ return path18.join(location.dir, "hooks", `turn-${digestOf(session).slice(0, 32)}.json`);
17613
17727
  } catch {
17614
17728
  return null;
17615
17729
  }
17616
17730
  };
17617
17731
  var writeTurnDigest = (file, digest) => {
17618
17732
  try {
17619
- fs14.mkdirSync(path17.dirname(file), { recursive: true });
17733
+ fs14.mkdirSync(path18.dirname(file), { recursive: true });
17620
17734
  fs14.writeFileSync(file, `${JSON.stringify({ digest })}
17621
17735
  `);
17622
17736
  } catch {}
@@ -17631,7 +17745,7 @@ var pruneTurnDigests = (dir, now) => {
17631
17745
  for (const name of fs14.readdirSync(dir)) {
17632
17746
  if (!name.startsWith("turn-"))
17633
17747
  continue;
17634
- const file = path17.join(dir, name);
17748
+ const file = path18.join(dir, name);
17635
17749
  try {
17636
17750
  if (now - fs14.statSync(file).mtimeMs > TURN_TTL_MS)
17637
17751
  fs14.rmSync(file, { force: true });
@@ -17661,7 +17775,7 @@ var seedTurnContext = (input, descriptor, text = turnContextText(input, descript
17661
17775
  const file = turnMarker(input);
17662
17776
  if (!file)
17663
17777
  return;
17664
- pruneTurnDigests(path17.dirname(file), Date.now());
17778
+ pruneTurnDigests(path18.dirname(file), Date.now());
17665
17779
  if (text)
17666
17780
  writeTurnDigest(file, digestOf(text));
17667
17781
  else
@@ -17670,14 +17784,14 @@ var seedTurnContext = (input, descriptor, text = turnContextText(input, descript
17670
17784
  // packages/workit-core/src/core/route-intent.ts
17671
17785
  import { spawnSync as spawnSync12 } from "node:child_process";
17672
17786
  import { existsSync as existsSync6 } from "node:fs";
17673
- import path20 from "node:path";
17787
+ import path21 from "node:path";
17674
17788
 
17675
17789
  // packages/workit-core/src/hooks/raw-git.ts
17676
17790
  import { spawnSync as spawnSync11 } from "node:child_process";
17677
17791
  import { createHash as createHash14 } from "node:crypto";
17678
17792
  import fs16 from "node:fs";
17679
- import os4 from "node:os";
17680
- import path19 from "node:path";
17793
+ import os5 from "node:os";
17794
+ import path20 from "node:path";
17681
17795
 
17682
17796
  // packages/workit-core/src/core/branch.ts
17683
17797
  import { createHash as createHash12 } from "node:crypto";
@@ -17890,7 +18004,7 @@ var globOf = (pattern) => pattern.source.replace(/^\^|\$$/gu, "").replaceAll(".*
17890
18004
  // packages/workit-core/src/hooks/session-marker.ts
17891
18005
  import { createHash as createHash13 } from "node:crypto";
17892
18006
  import fs15 from "node:fs";
17893
- import path18 from "node:path";
18007
+ import path19 from "node:path";
17894
18008
  var sessionMarkerFile = (input, session, store) => {
17895
18009
  let dir = store;
17896
18010
  if (dir === undefined) {
@@ -17900,7 +18014,7 @@ var sessionMarkerFile = (input, session, store) => {
17900
18014
  dir = location.dir;
17901
18015
  }
17902
18016
  const name = createHash13("sha256").update(`${input.host}\x00${session}`).digest("hex").slice(0, 32);
17903
- return path18.join(dir, "hooks", `skills-${name}.json`);
18017
+ return path19.join(dir, "hooks", `skills-${name}.json`);
17904
18018
  };
17905
18019
  var list2 = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
17906
18020
  var readSessionMarker = (file) => {
@@ -17913,7 +18027,7 @@ var readSessionMarker = (file) => {
17913
18027
  };
17914
18028
  var writeSessionMarker = (file, marker) => {
17915
18029
  try {
17916
- fs15.mkdirSync(path18.dirname(file), { recursive: true });
18030
+ fs15.mkdirSync(path19.dirname(file), { recursive: true });
17917
18031
  fs15.writeFileSync(file, JSON.stringify(marker));
17918
18032
  } catch {}
17919
18033
  };
@@ -18058,12 +18172,12 @@ var GIT_VALUE_OPTIONS = new Set([
18058
18172
  "--config-env",
18059
18173
  "--super-prefix"
18060
18174
  ]);
18061
- var isAbsolute = (value) => path19.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\");
18175
+ var isAbsolute = (value) => path20.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\");
18062
18176
  var joinDir = (base, next) => {
18063
18177
  if (base === undefined || /[$`*?]/.test(next) || next === "-")
18064
18178
  return;
18065
- const expanded = next === "~" || next.startsWith("~/") ? path19.join(os4.homedir(), next.slice(1)) : next;
18066
- return base === null || isAbsolute(expanded) ? expanded : path19.join(base, expanded);
18179
+ const expanded = next === "~" || next.startsWith("~/") ? path20.join(os5.homedir(), next.slice(1)) : next;
18180
+ return base === null || isAbsolute(expanded) ? expanded : path20.join(base, expanded);
18067
18181
  };
18068
18182
  var cdTarget = (words) => {
18069
18183
  const args = words.slice(1);
@@ -18114,7 +18228,7 @@ function rawInvocations(command, dialect = "posix", depth = 0) {
18114
18228
  const name = commandName(words[0]);
18115
18229
  if (CD.has(name)) {
18116
18230
  const target = cdTarget(words);
18117
- dir = target === null ? os4.homedir() : joinDir(dir, target);
18231
+ dir = target === null ? os5.homedir() : joinDir(dir, target);
18118
18232
  continue;
18119
18233
  }
18120
18234
  if (PUSHD.has(name)) {
@@ -18372,17 +18486,17 @@ var headSha2 = (repo) => {
18372
18486
  if (!git || git.reftable)
18373
18487
  return null;
18374
18488
  try {
18375
- const head = fs16.readFileSync(path19.join(git.gitDir, "HEAD"), "utf8").trim();
18489
+ const head = fs16.readFileSync(path20.join(git.gitDir, "HEAD"), "utf8").trim();
18376
18490
  if (/^[0-9a-f]{40,64}$/.test(head))
18377
18491
  return head;
18378
18492
  const ref = /^ref: (refs\/.+)$/.exec(head)?.[1];
18379
18493
  if (!ref)
18380
18494
  return null;
18381
- const common = path19.dirname(repo.location.dir);
18495
+ const common = path20.dirname(repo.location.dir);
18382
18496
  try {
18383
- return fs16.readFileSync(path19.join(common, ref), "utf8").trim() || null;
18497
+ return fs16.readFileSync(path20.join(common, ref), "utf8").trim() || null;
18384
18498
  } catch {}
18385
- const packed = fs16.readFileSync(path19.join(common, "packed-refs"), "utf8");
18499
+ const packed = fs16.readFileSync(path20.join(common, "packed-refs"), "utf8");
18386
18500
  return new RegExp(`^([0-9a-f]{40,64}) ${ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`, "m").exec(packed)?.[1] ?? null;
18387
18501
  } catch {
18388
18502
  return null;
@@ -18471,7 +18585,7 @@ var actionsIn = (cwd, command, dialect) => {
18471
18585
  const action = rawAction(invocation);
18472
18586
  if (!action)
18473
18587
  continue;
18474
- const dir = path19.resolve(cwd, invocation.dir ?? ".");
18588
+ const dir = path20.resolve(cwd, invocation.dir ?? ".");
18475
18589
  if (!repos.has(dir)) {
18476
18590
  const repo = repoAt(dir);
18477
18591
  repos.set(dir, repo && isWorkitWorkspace(repo) ? repo : null);
@@ -18551,7 +18665,7 @@ function rawGitPre(input, command, options = {}) {
18551
18665
  var deny = (reason) => ({ kind: "deny", reason, unblock: null });
18552
18666
  var NEXT_COMMAND = "next";
18553
18667
  var MARKER_TTL_SECONDS = 3600;
18554
- var markerFile = (repo, session, key) => path19.join(repo.location.dir, "hooks", `commit-${createHash14("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`);
18668
+ var markerFile = (repo, session, key) => path20.join(repo.location.dir, "hooks", `commit-${createHash14("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`);
18555
18669
  var callKey = (toolUseId, command) => toolUseId ?? `cmd:${createHash14("sha256").update(command).digest("hex")}`;
18556
18670
  function noteRawCommit(input, command, key) {
18557
18671
  try {
@@ -18562,7 +18676,7 @@ function noteRawCommit(input, command, key) {
18562
18676
  if (action.kind !== "commit")
18563
18677
  continue;
18564
18678
  const file = markerFile(repo, input.session.id, key);
18565
- fs16.mkdirSync(path19.dirname(file), { recursive: true });
18679
+ fs16.mkdirSync(path20.dirname(file), { recursive: true });
18566
18680
  fs16.writeFileSync(file, `${JSON.stringify({ head: headSha2(repo), at })}
18567
18681
  `);
18568
18682
  }
@@ -18735,7 +18849,7 @@ var shellBranchPolicyViolation = (root, command, dialect = "posix") => {
18735
18849
  for (const target of shellBranchTargets(command, dialect)) {
18736
18850
  if (target.dir === undefined)
18737
18851
  continue;
18738
- const dir = target.dir === null ? root : path20.resolve(root, target.dir);
18852
+ const dir = target.dir === null ? root : path21.resolve(root, target.dir);
18739
18853
  if (target.dir !== null && (!existsSync6(dir) || !inWorkitWorkspace(dir)))
18740
18854
  continue;
18741
18855
  if (localBranchExists(dir, target.branch))
@@ -18755,27 +18869,27 @@ var shellPolicy = (cwd, command, dialect = "posix") => {
18755
18869
  };
18756
18870
  // packages/workit-core/src/hooks/write-gate.ts
18757
18871
  import { realpathSync as realpathSync5 } from "node:fs";
18758
- import path21 from "node:path";
18872
+ import path22 from "node:path";
18759
18873
  var NONE3 = { kind: "none" };
18760
18874
  var CASE_INSENSITIVE = process.platform === "darwin" || process.platform === "win32";
18761
18875
  var canonical2 = (file) => {
18762
18876
  let rest = "";
18763
- for (let dir = path21.resolve(file);; dir = path21.dirname(dir)) {
18877
+ for (let dir = path22.resolve(file);; dir = path22.dirname(dir)) {
18764
18878
  try {
18765
- return path21.join(realpathSync5(dir), rest);
18879
+ return path22.join(realpathSync5(dir), rest);
18766
18880
  } catch {
18767
- if (path21.dirname(dir) === dir)
18768
- return path21.resolve(file);
18769
- rest = rest ? path21.join(path21.basename(dir), rest) : path21.basename(dir);
18881
+ if (path22.dirname(dir) === dir)
18882
+ return path22.resolve(file);
18883
+ rest = rest ? path22.join(path22.basename(dir), rest) : path22.basename(dir);
18770
18884
  }
18771
18885
  }
18772
18886
  };
18773
18887
  var exempt = (cwd, root, file, plans) => {
18774
18888
  const fold = (value) => CASE_INSENSITIVE ? value.toLowerCase() : value;
18775
- const relative = path21.relative(fold(canonical2(root)), fold(canonical2(path21.resolve(cwd, file))));
18776
- if (relative.startsWith("..") || path21.isAbsolute(relative))
18889
+ const relative = path22.relative(fold(canonical2(root)), fold(canonical2(path22.resolve(cwd, file))));
18890
+ if (relative.startsWith("..") || path22.isAbsolute(relative))
18777
18891
  return true;
18778
- const posix = relative.split(path21.sep).join("/");
18892
+ const posix = relative.split(path22.sep).join("/");
18779
18893
  const segments = posix.split("/");
18780
18894
  return /\.mdx?$/i.test(posix) || segments[0] === "docs" || segments.includes("plans") || [...plans].some((plan) => fold(plan) === posix);
18781
18895
  };
@@ -18873,7 +18987,7 @@ var shellWrites = (command) => {
18873
18987
  return { writes: true, targets: unknown ? null : targets };
18874
18988
  };
18875
18989
  var cache2 = new Map;
18876
- var planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(path21.resolve(root, file)) ?? "-").join("\x00");
18990
+ var planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(path22.resolve(root, file)) ?? "-").join("\x00");
18877
18991
  var gateFor = (cwd) => {
18878
18992
  const store = new TaskStore(cwd);
18879
18993
  const listed = store.listTaskIndex();
@@ -19314,12 +19428,12 @@ ${line}` };
19314
19428
  };
19315
19429
  // packages/workit-core/src/hooks/hosts/fields.ts
19316
19430
  import { existsSync as existsSync7, realpathSync as realpathSync6, statSync as statSync2 } from "node:fs";
19317
- import path22 from "node:path";
19431
+ import path23 from "node:path";
19318
19432
  var isRecord4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
19319
19433
  var nonEmpty2 = (value) => typeof value === "string" && value.trim() !== "";
19320
19434
  var optionalText = (value) => typeof value === "string" ? value : null;
19321
19435
  var existingDirectory = (value) => {
19322
- if (!nonEmpty2(value) || !path22.isAbsolute(value) || !existsSync7(value))
19436
+ if (!nonEmpty2(value) || !path23.isAbsolute(value) || !existsSync7(value))
19323
19437
  return null;
19324
19438
  try {
19325
19439
  return statSync2(value).isDirectory() ? realpathSync6(value) : null;
@@ -19402,7 +19516,7 @@ var workitRole = (descriptor, agentType) => {
19402
19516
  };
19403
19517
  var subagentSession = (session, agentId) => [session, agentId].filter((part) => Boolean(part)).join(":").replace(/[^A-Za-z0-9_.:@/+-]/g, "-").slice(0, 128);
19404
19518
  var CLAUDE_WORKTREE = /[\\/]\.claude[\\/]worktrees[\\/]/;
19405
- 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`).';
19519
+ 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\`).`;
19406
19520
  var subagentStartText = (input, descriptor, event) => {
19407
19521
  const session = input.session.id ?? null;
19408
19522
  const role = workitRole(descriptor, event.agentType);
@@ -19410,9 +19524,9 @@ var subagentStartText = (input, descriptor, event) => {
19410
19524
  const isolated = descriptor.subagents.worktreeIsolation === "native" && (role === "implementer" || CLAUDE_WORKTREE.test(input.cwd));
19411
19525
  const guide = role === "implementer" ? branchGuidance(input.cwd) : null;
19412
19526
  if (role === "implementer" && isolated)
19413
- 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.`;
19527
+ 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.`;
19414
19528
  if (isolated)
19415
- return `${ISOLATED_GIT}
19529
+ return `${isolatedGit(input.cwd)}
19416
19530
  ${subagentStartText({ ...input, cwd: "" }, descriptor, event)}`;
19417
19531
  if (role === "implementer")
19418
19532
  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.`;
@@ -20058,7 +20172,7 @@ var codexAdapter = {
20058
20172
 
20059
20173
  // packages/workit-core/src/hooks/hosts/cursor.ts
20060
20174
  import fs17 from "node:fs";
20061
- import path23 from "node:path";
20175
+ import path24 from "node:path";
20062
20176
  var undocumented = { support: "undocumented", native: null };
20063
20177
  var none = { support: "none", native: null };
20064
20178
  var CURSOR_DESCRIPTOR = {
@@ -20255,7 +20369,7 @@ var protocolEvent2 = (input) => {
20255
20369
  };
20256
20370
  var TRANSCRIPT_TAIL_BYTES = 256 * 1024;
20257
20371
  var lastAssistantText = (file) => {
20258
- if (!file || !path23.isAbsolute(file))
20372
+ if (!file || !path24.isAbsolute(file))
20259
20373
  return null;
20260
20374
  try {
20261
20375
  const size = fs17.statSync(file).size;
@@ -20292,7 +20406,7 @@ var lastAssistantText = (file) => {
20292
20406
  return null;
20293
20407
  }
20294
20408
  };
20295
- var within = (root, dir) => dir === root || dir.startsWith(root.endsWith(path23.sep) ? root : `${root}${path23.sep}`);
20409
+ var within = (root, dir) => dir === root || dir.startsWith(root.endsWith(path24.sep) ? root : `${root}${path24.sep}`);
20296
20410
  var hookCwd = (input) => {
20297
20411
  const cwd = existingDirectory(input.cwd);
20298
20412
  if (cwd && input.hook_event_name === "beforeShellExecution")