@brainervirus/workit-codex 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.
@@ -26,7 +26,7 @@ var capabilitiesFor = (descriptor, observed = {}) => descriptor.capabilities.map
26
26
  // packages/workit-core/src/hooks/context.ts
27
27
  import { createHash as createHash11 } from "node:crypto";
28
28
  import fs14 from "node:fs";
29
- import path17 from "node:path";
29
+ import path18 from "node:path";
30
30
 
31
31
  // packages/workit-core/src/core/methods.ts
32
32
  var METHODS = {
@@ -91,9 +91,9 @@ Autonomy contract:
91
91
  ship), go to the effective endpoint in \`workit grant show\`: \`pr\` opens
92
92
  the PR; \`green\` babysits it without asking (workit-ship) to merge-ready,
93
93
  never merging; \`merged\` also lands it with \`workit pr merge\`.
94
- Merge and release need a workspace grant, which only the user raises from
95
- their own terminal (a blocked verb names how); never edit workspaces.json or
96
- route around a grant_required.
94
+ Merge and release need a workspace grant only the user raises from their
95
+ own terminal (a blocked verb names how); never edit workspaces.json or route
96
+ around a grant_required.
97
97
  - Ask only for a product or preference choice, or for authority you lack, with
98
98
  your recommended answer. Facts are yours: read, run or prototype.
99
99
  - Label claims measured (run and seen this session), inferred, or guess.
@@ -102,17 +102,19 @@ Autonomy contract:
102
102
  - Author is not verifier: your own verdict is \`--self\`, shown as
103
103
  self-reviewed, never verified. High risk, \`verification: independent\` and
104
104
  merge need a verifier with its own host-derived session (a subagent's
105
- \`<lead>:<child>\`, set by the host); never hand-mint one such as \`<lead>-v1\`.
105
+ \`<lead>:<child>\`); never hand-mint one (\`<lead>-v1\`).
106
106
  - A local-commit endpoint does not imply PR readiness, and a local commit alone
107
107
  is not evidence of a requested remote push. Before reporting delivery,
108
108
  reconcile every requested item and observe it (\`workit verify-delivery\`).
109
109
 
110
110
  CLI first: if a step has one right answer, use the \`workit\` verb instead of
111
111
  hand-running git, gh or glab (\`workit git|pr|ci|check\`; \`workit help\` lists
112
- the rest; without \`workit\` on PATH, \`npx -y @brainervirus/workit-cli\`).
112
+ the rest; lacking \`workit\`, \`npx -y @brainervirus/workit-cli\`).
113
+ Add Co-Authored-By via \`workit git commit --trailer "K: v" -- <paths>\`, never
114
+ an amend.
113
115
  The task families (task, policy, evidence, finding, decision, worker, state)
114
116
  are optional continuity for tracked work; each branch has one implicit task,
115
- created by the first recording, and a solo edit needs no task. A decision
117
+ and a solo edit needs no task. A decision
116
118
  records a user choice; it never authorizes an effect. Judge work once with
117
119
  \`workit policy assess --judge risk= behavior= product-choice= plan=\`.
118
120
  Across repositories, bind each item to its checkout, branch and endpoint,
@@ -8791,7 +8793,7 @@ function requirementId(input) {
8791
8793
  import { createHash as createHash10 } from "node:crypto";
8792
8794
  import * as fs13 from "node:fs";
8793
8795
  import { spawnSync as spawnSync10 } from "node:child_process";
8794
- import path15 from "node:path";
8796
+ import path16 from "node:path";
8795
8797
 
8796
8798
  // packages/workit-core/src/check-config.ts
8797
8799
  import { spawnSync as spawnSync2 } from "node:child_process";
@@ -8960,7 +8962,7 @@ function loadCheckConfig(cwd) {
8960
8962
  gates[gate] = names;
8961
8963
  }
8962
8964
  }
8963
- return { source: CHECKS_FILE, root, checks, gates, error: null };
8965
+ return { source: CHECKS_FILE, root, checks, gates, error: null, resources: parsed.resources };
8964
8966
  }
8965
8967
  var sameArgv = (left, right) => left.length === right.length && left.every((item, index) => item === right[index]);
8966
8968
  function matchesNamedCheck(config, name, argv, cwd) {
@@ -9182,7 +9184,7 @@ function pushRemoteName(cwd, branch) {
9182
9184
  // packages/workit-core/src/core/task-store.ts
9183
9185
  import { createHash as createHash6, randomUUID as randomUUID3 } from "node:crypto";
9184
9186
  import * as fs10 from "node:fs";
9185
- import path9 from "node:path";
9187
+ import path10 from "node:path";
9186
9188
 
9187
9189
  // node_modules/@openclaw/fs-safe/dist/errors.js
9188
9190
  var OPERATIONAL_CODES = new Set([
@@ -9788,7 +9790,68 @@ function acquireFileLockSync(targetPath, options) {
9788
9790
  // packages/workit-core/src/host-session.ts
9789
9791
  import { createHash as createHash4 } from "node:crypto";
9790
9792
  import fs7 from "node:fs";
9793
+ import path7 from "node:path";
9794
+
9795
+ // packages/workit-core/src/core/logger.ts
9796
+ import os2 from "node:os";
9791
9797
  import path6 from "node:path";
9798
+ var SENSITIVE_WORDS = new Set([
9799
+ "token",
9800
+ "secret",
9801
+ "password",
9802
+ "passwd",
9803
+ "authorization",
9804
+ "credential",
9805
+ "credentials",
9806
+ "cookie",
9807
+ "api",
9808
+ "apikey",
9809
+ "apitoken",
9810
+ "accesstoken",
9811
+ "clientsecret",
9812
+ "refreshtoken",
9813
+ "key",
9814
+ "bearer",
9815
+ "prompt",
9816
+ "message",
9817
+ "messages",
9818
+ "content",
9819
+ "body",
9820
+ "args",
9821
+ "argument",
9822
+ "result",
9823
+ "results",
9824
+ "output",
9825
+ "issue",
9826
+ "description",
9827
+ "summary",
9828
+ "payload",
9829
+ "script",
9830
+ "command",
9831
+ "text",
9832
+ "query"
9833
+ ]);
9834
+ var STACK_WORDS = new Set(["stack", "stacktrace", "trace"]);
9835
+ var escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
9836
+ var resolveStateDir = () => {
9837
+ const override = process.env.WORKFLOW_TOOLKIT_STATE;
9838
+ if (override)
9839
+ return override;
9840
+ const home = os2.homedir();
9841
+ if (process.env.XDG_STATE_HOME)
9842
+ return path6.join(process.env.XDG_STATE_HOME, "workit");
9843
+ switch (os2.platform()) {
9844
+ case "darwin":
9845
+ return path6.join(home, "Library", "Application Support", "workit");
9846
+ case "win32":
9847
+ return path6.join(process.env.LOCALAPPDATA ?? path6.join(home, "AppData", "Local"), "workit");
9848
+ default:
9849
+ return path6.join(process.env.HOME ?? home, ".local", "state", "workit");
9850
+ }
9851
+ };
9852
+ var homePattern = new RegExp(`${escapeRegExp(os2.homedir())}(?=[/\\\\]|$)|\\$HOME(?=[/\\\\]|$)`, "g");
9853
+
9854
+ // packages/workit-core/src/host-session.ts
9792
9855
  var HOST_SESSION_VARS = [
9793
9856
  ["OPENCODE_SESSION_ID", () => "opencode"],
9794
9857
  ["PI_SESSION_ID", () => "pi"],
@@ -9817,43 +9880,77 @@ function hostSessionFromEnv(env) {
9817
9880
  return inner ? { host: inner.host, session: inner.session } : { host: declared, session: null };
9818
9881
  }
9819
9882
  var ISSUED_PER_LEAD = 64;
9820
- var ISSUED_SESSIONS_MARKER = "workit-issued-sessions/1";
9883
+ var ISSUED_SESSIONS_MARKER = "workit-issued-sessions/2";
9821
9884
  var hash = (value) => createHash4("sha256").update(value).digest("hex").slice(0, 32);
9822
- var issuedRoot = (cwd) => {
9823
- const location = resolveStore(cwd);
9824
- return location instanceof Error ? null : path6.join(location.dir, "hooks", "issued");
9885
+ var userIssuedRoot = () => path7.join(resolveStateDir(), "issued");
9886
+ function migrateRepoIssued(cwd) {
9887
+ if (cwd === undefined)
9888
+ return;
9889
+ let old;
9890
+ try {
9891
+ const location = resolveStore(cwd);
9892
+ if (location instanceof Error)
9893
+ return;
9894
+ old = path7.join(location.dir, "hooks", "issued");
9895
+ if (!fs7.existsSync(old))
9896
+ return;
9897
+ } catch {
9898
+ return;
9899
+ }
9900
+ for (const lead of safeList(old)) {
9901
+ try {
9902
+ const from = path7.join(old, lead);
9903
+ if (!fs7.statSync(from).isDirectory())
9904
+ continue;
9905
+ const to = path7.join(userIssuedRoot(), lead);
9906
+ fs7.mkdirSync(to, { recursive: true, mode: 448 });
9907
+ for (const id of fs7.readdirSync(from)) {
9908
+ fs7.copyFileSync(path7.join(from, id), path7.join(to, id));
9909
+ fs7.rmSync(path7.join(from, id), { force: true });
9910
+ }
9911
+ removeIfEmpty(from);
9912
+ } catch {}
9913
+ }
9914
+ removeIfEmpty(old);
9915
+ }
9916
+ var safeList = (dir) => {
9917
+ try {
9918
+ return fs7.readdirSync(dir);
9919
+ } catch {
9920
+ return [];
9921
+ }
9825
9922
  };
9826
- var issuedDir = (cwd, lead) => {
9827
- const root = issuedRoot(cwd);
9828
- return root === null ? null : path6.join(root, hash(lead));
9923
+ var removeIfEmpty = (dir) => {
9924
+ try {
9925
+ fs7.rmdirSync(dir);
9926
+ } catch {}
9829
9927
  };
9830
9928
  function recordIssuedSession(cwd, lead, issued) {
9831
9929
  try {
9832
- const dir = issuedDir(cwd, lead);
9833
- if (!dir)
9834
- return;
9835
- fs7.mkdirSync(dir, { recursive: true });
9930
+ migrateRepoIssued(cwd);
9931
+ const dir = path7.join(userIssuedRoot(), hash(lead));
9932
+ fs7.mkdirSync(dir, { recursive: true, mode: 448 });
9836
9933
  const own = hash(issued);
9837
- fs7.writeFileSync(path6.join(dir, own), ISSUED_SESSIONS_MARKER);
9934
+ fs7.writeFileSync(path7.join(dir, own), ISSUED_SESSIONS_MARKER);
9838
9935
  const entries = fs7.readdirSync(dir);
9839
9936
  if (entries.length <= ISSUED_PER_LEAD)
9840
9937
  return;
9841
- const byAge = entries.filter((name) => name !== own).map((name) => ({ name, at: fs7.statSync(path6.join(dir, name)).mtimeMs })).toSorted((a, b) => a.at - b.at);
9938
+ const byAge = entries.filter((name) => name !== own).map((name) => ({ name, at: fs7.statSync(path7.join(dir, name)).mtimeMs })).toSorted((a, b) => a.at - b.at);
9842
9939
  for (const { name } of byAge.slice(0, entries.length - ISSUED_PER_LEAD))
9843
- fs7.rmSync(path6.join(dir, name), { force: true });
9940
+ fs7.rmSync(path7.join(dir, name), { force: true });
9844
9941
  } catch {}
9845
9942
  }
9846
9943
  var OWN_CHILD_SHELL = new Set(["opencode", "pi"]);
9847
9944
 
9848
9945
  // packages/workit-core/src/core/package-root.ts
9849
9946
  import { existsSync } from "node:fs";
9850
- import path7 from "node:path";
9947
+ import path8 from "node:path";
9851
9948
  import { fileURLToPath } from "node:url";
9852
9949
  var packageRoot = () => {
9853
- let dir = path7.dirname(fileURLToPath(import.meta.url));
9950
+ let dir = path8.dirname(fileURLToPath(import.meta.url));
9854
9951
  while (true) {
9855
- const parent = path7.dirname(dir);
9856
- if (existsSync(path7.join(dir, "package.json")) || parent === dir)
9952
+ const parent = path8.dirname(dir);
9953
+ if (existsSync(path8.join(dir, "package.json")) || parent === dir)
9857
9954
  return dir;
9858
9955
  dir = parent;
9859
9956
  }
@@ -10002,7 +10099,7 @@ var clearAbandonedReclaimGuard = (lockPath, nowMs = Date.now()) => {
10002
10099
  // packages/workit-core/src/store/event-log.ts
10003
10100
  import { randomUUID as randomUUID2 } from "node:crypto";
10004
10101
  import fs9 from "node:fs";
10005
- import path8 from "node:path";
10102
+ import path9 from "node:path";
10006
10103
  var EVENT_VERSION = 1;
10007
10104
 
10008
10105
  class LogDamage extends Error {
@@ -10113,7 +10210,7 @@ function appendEvent(file, event, validEnd) {
10113
10210
  fs9.closeSync(fd);
10114
10211
  }
10115
10212
  if (created)
10116
- fsyncDirectory(path8.dirname(file));
10213
+ fsyncDirectory(path9.dirname(file));
10117
10214
  return validEnd;
10118
10215
  }
10119
10216
  function replaceFile(file, bytes, durable) {
@@ -10129,7 +10226,7 @@ function replaceFile(file, bytes, durable) {
10129
10226
  }
10130
10227
  renameWithRetry(temporary, file);
10131
10228
  if (durable)
10132
- fsyncDirectory(path8.dirname(file));
10229
+ fsyncDirectory(path9.dirname(file));
10133
10230
  } catch (error) {
10134
10231
  try {
10135
10232
  fs9.unlinkSync(temporary);
@@ -10472,7 +10569,7 @@ var cachedRuntimeVersion = null;
10472
10569
  var runtimeVersion = () => {
10473
10570
  if (cachedRuntimeVersion === null) {
10474
10571
  try {
10475
- const pkg = JSON.parse(fs10.readFileSync(path9.join(packageRoot(), "package.json"), "utf8"));
10572
+ const pkg = JSON.parse(fs10.readFileSync(path10.join(packageRoot(), "package.json"), "utf8"));
10476
10573
  cachedRuntimeVersion = typeof pkg.version === "string" && pkg.version ? pkg.version : "0.0.0";
10477
10574
  } catch {
10478
10575
  cachedRuntimeVersion = "0.0.0";
@@ -10505,7 +10602,7 @@ var readText = (file) => {
10505
10602
  };
10506
10603
  var REFLOG_LINE = /^[0-9a-f]+ ([0-9a-f]+) .* (\d+) [+-]\d{4}\t(.*)$/u;
10507
10604
  var branchStart = (location, branch, aliases) => {
10508
- const first = readText(path9.join(path9.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
10605
+ const first = readText(path10.join(path10.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
10509
10606
  `, 1)[0];
10510
10607
  const created = REFLOG_LINE.exec(first);
10511
10608
  const start = created && /^branch: Created from (\S+)$/u.exec(created[3])?.[1];
@@ -10515,7 +10612,7 @@ var branchStart = (location, branch, aliases) => {
10515
10612
  return start;
10516
10613
  if (!location.git)
10517
10614
  return null;
10518
- for (const line of readText(path9.join(location.git.gitDir, "logs", "HEAD")).split(`
10615
+ for (const line of readText(path10.join(location.git.gitDir, "logs", "HEAD")).split(`
10519
10616
  `)) {
10520
10617
  const entry = REFLOG_LINE.exec(line);
10521
10618
  const moved = entry && /^checkout: moving from (\S+) to (\S+)$/u.exec(entry[3]);
@@ -10525,14 +10622,14 @@ var branchStart = (location, branch, aliases) => {
10525
10622
  }
10526
10623
  return null;
10527
10624
  };
10528
- var refExists = (common, ref) => fs10.existsSync(path9.join(common, ref)) || readText(path9.join(common, "packed-refs")).includes(` ${ref}
10625
+ var refExists = (common, ref) => fs10.existsSync(path10.join(common, ref)) || readText(path10.join(common, "packed-refs")).includes(` ${ref}
10529
10626
  `);
10530
10627
  var origins = new Map;
10531
10628
  var sameDirectoryIdentity = (left, right) => {
10532
- if (!path9.isAbsolute(left) || !path9.isAbsolute(right))
10629
+ if (!path10.isAbsolute(left) || !path10.isAbsolute(right))
10533
10630
  return false;
10534
- const normalizedLeft = path9.resolve(left);
10535
- const normalizedRight = path9.resolve(right);
10631
+ const normalizedLeft = path10.resolve(left);
10632
+ const normalizedRight = path10.resolve(right);
10536
10633
  try {
10537
10634
  const a = fs10.statSync(normalizedLeft, { bigint: true });
10538
10635
  const b = fs10.statSync(normalizedRight, { bigint: true });
@@ -10578,7 +10675,7 @@ class TaskStore {
10578
10675
  migrationChecked = false;
10579
10676
  compactDue = new Set;
10580
10677
  constructor(root, options = {}) {
10581
- const resolved = path9.resolve(root);
10678
+ const resolved = path10.resolve(root);
10582
10679
  this.origin = fs10.existsSync(resolved) ? fs10.realpathSync(resolved) : resolved;
10583
10680
  this.located = resolveStore(this.origin);
10584
10681
  this.root = checkoutRootOf(this.origin, this.located);
@@ -10587,7 +10684,7 @@ class TaskStore {
10587
10684
  this.migrateOnRead = options.migrateOnRead;
10588
10685
  }
10589
10686
  location() {
10590
- if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs10.existsSync(path9.join(this.root, ".git"))) {
10687
+ if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs10.existsSync(path10.join(this.root, ".git"))) {
10591
10688
  this.located = undefined;
10592
10689
  this.migrationChecked = false;
10593
10690
  }
@@ -10743,7 +10840,7 @@ class TaskStore {
10743
10840
  const moved = this.bindLocked(again.data.id, key, input.now);
10744
10841
  return moved.ok ? success(moved.data.revision, null, { task: moved.data, created: false, key }) : moved;
10745
10842
  }
10746
- const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path9.basename(this.root) || this.root;
10843
+ const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path10.basename(this.root) || this.root;
10747
10844
  const intent = {
10748
10845
  objective: input.objective?.trim() || `Work on ${label}`,
10749
10846
  scope: { description: `the checkout (${label})`, paths: ["."], exclusions: [] },
@@ -10803,14 +10900,14 @@ class TaskStore {
10803
10900
  const branch = key.ok ? key.data.branch : null;
10804
10901
  if (!branch || !location.ok)
10805
10902
  return success(null, null, null);
10806
- const common = path9.dirname(location.data.dir);
10807
- const heads = path9.join(common, "logs", "refs", "heads");
10808
- const headLog = location.data.git ? path9.join(location.data.git.gitDir, "logs", "HEAD") : "";
10903
+ const common = path10.dirname(location.data.dir);
10904
+ const heads = path10.join(common, "logs", "refs", "heads");
10905
+ const headLog = location.data.git ? path10.join(location.data.git.gitDir, "logs", "HEAD") : "";
10809
10906
  const signatures = [
10810
- path9.join(heads, branch),
10907
+ path10.join(heads, branch),
10811
10908
  headLog,
10812
10909
  heads,
10813
- path9.join(common, "packed-refs")
10910
+ path10.join(common, "packed-refs")
10814
10911
  ].map((file) => fileSignature(file) ?? "-");
10815
10912
  const slot = `${location.data.dir}\x00${headLog}\x00${branch}`;
10816
10913
  let resolved = origins.get(slot);
@@ -10822,7 +10919,7 @@ class TaskStore {
10822
10919
  aliases.push(rename.from);
10823
10920
  const start = branchStart(location.data, branch, aliases);
10824
10921
  const slash = start?.indexOf("/") ?? -1;
10825
- const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(path9.join(common, "config")).includes(`[remote "${start.slice(0, slash)}"]`));
10922
+ const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(path10.join(common, "config")).includes(`[remote "${start.slice(0, slash)}"]`));
10826
10923
  const name = start && (remote ? start.slice(slash + 1) : start);
10827
10924
  resolved = {
10828
10925
  signature: signatures.join("|"),
@@ -11060,13 +11157,13 @@ class TaskStore {
11060
11157
  if (!ready.ok)
11061
11158
  return ready;
11062
11159
  const dirs = this.paths();
11063
- const recovery = path9.join(this.root, ".workit", "recovery");
11160
+ const recovery = path10.join(this.root, ".workit", "recovery");
11064
11161
  if (fs10.existsSync(recovery)) {
11065
11162
  let files = 0;
11066
11163
  let bytes = 0;
11067
11164
  try {
11068
11165
  for (const name of fs10.readdirSync(recovery)) {
11069
- const stat = fs10.lstatSync(path9.join(recovery, name));
11166
+ const stat = fs10.lstatSync(path10.join(recovery, name));
11070
11167
  if (!stat.isFile())
11071
11168
  continue;
11072
11169
  files += 1;
@@ -11119,7 +11216,7 @@ class TaskStore {
11119
11216
  if (fs10.existsSync(dirs.blobs))
11120
11217
  for (const name of fs10.readdirSync(dirs.blobs)) {
11121
11218
  const digest = name.replace(/\.json$/, "");
11122
- const file = path9.join(dirs.blobs, name);
11219
+ const file = path10.join(dirs.blobs, name);
11123
11220
  let stat;
11124
11221
  try {
11125
11222
  stat = fs10.lstatSync(file);
@@ -11137,7 +11234,7 @@ class TaskStore {
11137
11234
  }
11138
11235
  return success(null, null, null);
11139
11236
  };
11140
- const swept = dryRun ? sweep() : this.withLock(path9.join(dirs.dir, "gc.lock"), sweep);
11237
+ const swept = dryRun ? sweep() : this.withLock(path10.join(dirs.dir, "gc.lock"), sweep);
11141
11238
  if (!swept.ok)
11142
11239
  return swept;
11143
11240
  const temporaryDirs = [
@@ -11145,7 +11242,7 @@ class TaskStore {
11145
11242
  dirs.tasks,
11146
11243
  dirs.blobs,
11147
11244
  dirs.checkout,
11148
- ...names.map((name) => path9.join(dirs.tasks, name))
11245
+ ...names.map((name) => path10.join(dirs.tasks, name))
11149
11246
  ];
11150
11247
  for (const directory of temporaryDirs) {
11151
11248
  if (!fs10.existsSync(directory))
@@ -11153,7 +11250,7 @@ class TaskStore {
11153
11250
  for (const name of fs10.readdirSync(directory)) {
11154
11251
  if (!name.endsWith(".tmp") && !name.endsWith(".probe"))
11155
11252
  continue;
11156
- const file = path9.join(directory, name);
11253
+ const file = path10.join(directory, name);
11157
11254
  try {
11158
11255
  const stat = fs10.lstatSync(file);
11159
11256
  if (!stat.isFile() || nowMs - stat.mtimeMs <= STALE_TEMPORARY_MS)
@@ -11170,30 +11267,30 @@ class TaskStore {
11170
11267
  }
11171
11268
  paths() {
11172
11269
  const location = this.location();
11173
- const dir = location.ok ? location.data.dir : path9.join(this.root, ".workit");
11174
- const checkout = path9.join(dir, "checkouts", checkoutSlug(this.root));
11270
+ const dir = location.ok ? location.data.dir : path10.join(this.root, ".workit");
11271
+ const checkout = path10.join(dir, "checkouts", checkoutSlug(this.root));
11175
11272
  return {
11176
11273
  dir,
11177
11274
  shared: location.ok ? location.data.shared : false,
11178
- marker: path9.join(dir, "store.json"),
11275
+ marker: path10.join(dir, "store.json"),
11179
11276
  checkout,
11180
- workspace: path9.join(checkout, "workspace.json"),
11181
- checkoutLock: path9.join(checkout, "metadata.lock"),
11182
- tasks: path9.join(dir, "tasks"),
11183
- index: path9.join(dir, "task-index.json"),
11184
- blobs: path9.join(dir, "blobs", "candidates"),
11185
- legacy: path9.join(dir, "legacy", checkoutSlug(this.root), "v2"),
11186
- v2: path9.join(this.root, ".workit")
11277
+ workspace: path10.join(checkout, "workspace.json"),
11278
+ checkoutLock: path10.join(checkout, "metadata.lock"),
11279
+ tasks: path10.join(dir, "tasks"),
11280
+ index: path10.join(dir, "task-index.json"),
11281
+ blobs: path10.join(dir, "blobs", "candidates"),
11282
+ legacy: path10.join(dir, "legacy", checkoutSlug(this.root), "v2"),
11283
+ v2: path10.join(this.root, ".workit")
11187
11284
  };
11188
11285
  }
11189
11286
  eventsPath(taskId) {
11190
- return path9.join(this.paths().tasks, taskId, "events.jsonl");
11287
+ return path10.join(this.paths().tasks, taskId, "events.jsonl");
11191
11288
  }
11192
11289
  snapshotPath(taskId) {
11193
- return path9.join(this.paths().tasks, taskId, "snapshot.json");
11290
+ return path10.join(this.paths().tasks, taskId, "snapshot.json");
11194
11291
  }
11195
11292
  taskLockPath(taskId) {
11196
- return path9.join(this.paths().tasks, taskId, "lock");
11293
+ return path10.join(this.paths().tasks, taskId, "lock");
11197
11294
  }
11198
11295
  ready(write = false) {
11199
11296
  const location = this.location();
@@ -11232,13 +11329,13 @@ class TaskStore {
11232
11329
  return {
11233
11330
  read: (digest) => {
11234
11331
  try {
11235
- return JSON.parse(fs10.readFileSync(path9.join(dir, `${digest}.json`), "utf8"));
11332
+ return JSON.parse(fs10.readFileSync(path10.join(dir, `${digest}.json`), "utf8"));
11236
11333
  } catch (error) {
11237
11334
  throw new LogDamage(`stored candidate ${digest} is missing or unreadable: ${String(error)}`);
11238
11335
  }
11239
11336
  },
11240
11337
  write: (digest, value) => {
11241
- const file = path9.join(dir, `${digest}.json`);
11338
+ const file = path10.join(dir, `${digest}.json`);
11242
11339
  if (fs10.existsSync(file)) {
11243
11340
  const stamp = new Date;
11244
11341
  try {
@@ -11430,7 +11527,7 @@ class TaskStore {
11430
11527
  }
11431
11528
  }
11432
11529
  openTask(record, type, key, legacy = null) {
11433
- const dir = path9.join(this.paths().tasks, record.id);
11530
+ const dir = path10.join(this.paths().tasks, record.id);
11434
11531
  fs10.mkdirSync(dir, { recursive: true });
11435
11532
  const blobs = this.blobStore();
11436
11533
  const bound = key ? { ...key, boundAt: key.boundAt ?? new Date().toISOString() } : null;
@@ -11523,7 +11620,7 @@ class TaskStore {
11523
11620
  }
11524
11621
  withKeyLock(key, operation) {
11525
11622
  const digest = createHash6("sha256").update(key).digest("hex").slice(0, 32);
11526
- return this.withLock(path9.join(this.paths().dir, "keys", `${digest}.lock`), operation);
11623
+ return this.withLock(path10.join(this.paths().dir, "keys", `${digest}.lock`), operation);
11527
11624
  }
11528
11625
  bindLocked(taskId, key, timestamp) {
11529
11626
  const current = this.readWorkspace();
@@ -11664,7 +11761,7 @@ class TaskStore {
11664
11761
  writeWorkspace(record) {
11665
11762
  const file = this.paths().workspace;
11666
11763
  try {
11667
- fs10.mkdirSync(path9.dirname(file), { recursive: true });
11764
+ fs10.mkdirSync(path10.dirname(file), { recursive: true });
11668
11765
  replaceFile(file, `${canonicalJson(record)}
11669
11766
  `, true);
11670
11767
  return success(null, null, null);
@@ -11742,23 +11839,23 @@ class TaskStore {
11742
11839
  return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", { expectedWorkspaceRevision: expected, actualWorkspaceRevision: actual });
11743
11840
  }
11744
11841
  v2Dirs() {
11745
- return [...new Set([this.root, this.origin])].map((dir) => path9.join(dir, ".workit"));
11842
+ return [...new Set([this.root, this.origin])].map((dir) => path10.join(dir, ".workit"));
11746
11843
  }
11747
11844
  pendingMigrations() {
11748
11845
  return this.v2Dirs().filter((dir) => {
11749
- const raw = this.readV2Workspace(path9.join(dir, "workspace.json"));
11846
+ const raw = this.readV2Workspace(path10.join(dir, "workspace.json"));
11750
11847
  return raw !== null && raw !== TOMBSTONE;
11751
11848
  });
11752
11849
  }
11753
11850
  migrateV2(v2) {
11754
11851
  const dirs = this.paths();
11755
- const v2Workspace = path9.join(v2, "workspace.json");
11756
- const v2Tasks = path9.join(v2, "tasks");
11757
- const legacy = path9.join(dirs.dir, "legacy", checkoutSlug(path9.dirname(v2)), "v2");
11852
+ const v2Workspace = path10.join(v2, "workspace.json");
11853
+ const v2Tasks = path10.join(v2, "tasks");
11854
+ const legacy = path10.join(dirs.dir, "legacy", checkoutSlug(path10.dirname(v2)), "v2");
11758
11855
  const raw = this.readV2Workspace(v2Workspace);
11759
11856
  if (raw === null || raw === TOMBSTONE)
11760
11857
  return success(null, null, null);
11761
- return this.withLock(dirs.checkoutLock, () => this.withLock(path9.join(v2, "metadata.lock"), () => {
11858
+ return this.withLock(dirs.checkoutLock, () => this.withLock(path10.join(v2, "metadata.lock"), () => {
11762
11859
  const workspace = this.readV2Workspace(v2Workspace);
11763
11860
  if (workspace === null || workspace === TOMBSTONE)
11764
11861
  return success(null, null, null);
@@ -11767,7 +11864,7 @@ class TaskStore {
11767
11864
  return failure2("recovery_required", `cannot migrate the 2.x store at ${v2}: ${parsedWorkspace.error}; move it aside to start fresh`, { path: v2Workspace });
11768
11865
  let files = [];
11769
11866
  try {
11770
- files = fs10.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path9.join(v2Tasks, name)));
11867
+ files = fs10.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path10.join(v2Tasks, name)));
11771
11868
  } catch {}
11772
11869
  const current = this.readWorkspace();
11773
11870
  if (!current.ok)
@@ -11785,21 +11882,21 @@ class TaskStore {
11785
11882
  let skipped = 0;
11786
11883
  const done = new Map;
11787
11884
  try {
11788
- fs10.mkdirSync(path9.join(legacy, "tasks"), { recursive: true });
11885
+ fs10.mkdirSync(path10.join(legacy, "tasks"), { recursive: true });
11789
11886
  for (const name of ["workspace.json", "index.json"])
11790
- if (fs10.existsSync(path9.join(v2, name)))
11791
- fs10.copyFileSync(path9.join(v2, name), path9.join(legacy, name));
11887
+ if (fs10.existsSync(path10.join(v2, name)))
11888
+ fs10.copyFileSync(path10.join(v2, name), path10.join(legacy, name));
11792
11889
  for (const name of files) {
11793
11890
  const id = name.slice(0, -5);
11794
- const file = path9.join(v2Tasks, name);
11891
+ const file = path10.join(v2Tasks, name);
11795
11892
  const bytes = fs10.readFileSync(file, "utf8");
11796
11893
  const digest = sha256(bytes);
11797
- fs10.writeFileSync(path9.join(legacy, "tasks", name), bytes);
11894
+ fs10.writeFileSync(path10.join(legacy, "tasks", name), bytes);
11798
11895
  const parsed = this.parseRecord(bytes, taskRecordSchema, "2.x task");
11799
11896
  if (!parsed.ok || parsed.data.id !== id)
11800
11897
  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 });
11801
11898
  const record = { ...parsed.data, workspaceId: target.id };
11802
- const origin = { path: path9.join(legacy, "tasks", name), digest };
11899
+ const origin = { path: path10.join(legacy, "tasks", name), digest };
11803
11900
  if (!fs10.existsSync(this.eventsPath(id))) {
11804
11901
  this.openTask(record, "migrated.from_v2", null, origin);
11805
11902
  migrated += 1;
@@ -11835,7 +11932,7 @@ class TaskStore {
11835
11932
  try {
11836
11933
  let complete = true;
11837
11934
  for (const [name, digest] of done) {
11838
- const file = path9.join(v2Tasks, name);
11935
+ const file = path10.join(v2Tasks, name);
11839
11936
  if (sha256(fs10.readFileSync(file, "utf8")) !== digest) {
11840
11937
  complete = false;
11841
11938
  continue;
@@ -11846,7 +11943,7 @@ class TaskStore {
11846
11943
  return failure2("busy", `the 2.x store at ${v2} changed during migration; retry`, {
11847
11944
  path: v2
11848
11945
  });
11849
- fs10.rmSync(path9.join(v2, "index.json"), { force: true });
11946
+ fs10.rmSync(path10.join(v2, "index.json"), { force: true });
11850
11947
  this.writeTombstone(v2, target.id);
11851
11948
  } catch (error) {
11852
11949
  return failure2("storage_error", `cannot finish the 2.x migration: ${String(error)}`, {
@@ -11866,7 +11963,7 @@ class TaskStore {
11866
11963
  }
11867
11964
  adoptLocalStore() {
11868
11965
  const dirs = this.paths();
11869
- const marker = path9.join(dirs.v2, "store.json");
11966
+ const marker = path10.join(dirs.v2, "store.json");
11870
11967
  if (!dirs.shared || !fs10.existsSync(marker))
11871
11968
  return success(null, null, null);
11872
11969
  return this.withLock(dirs.checkoutLock, () => {
@@ -11876,7 +11973,7 @@ class TaskStore {
11876
11973
  try {
11877
11974
  const merge = (from, to) => {
11878
11975
  if (!fs10.existsSync(to)) {
11879
- fs10.mkdirSync(path9.dirname(to), { recursive: true });
11976
+ fs10.mkdirSync(path10.dirname(to), { recursive: true });
11880
11977
  try {
11881
11978
  fs10.renameSync(from, to);
11882
11979
  } catch {
@@ -11887,24 +11984,24 @@ class TaskStore {
11887
11984
  }
11888
11985
  if (fs10.lstatSync(from).isDirectory() && fs10.lstatSync(to).isDirectory())
11889
11986
  for (const name of fs10.readdirSync(from))
11890
- merge(path9.join(from, name), path9.join(to, name));
11987
+ merge(path10.join(from, name), path10.join(to, name));
11891
11988
  };
11892
11989
  for (const sub of ["tasks", "checkouts", "blobs", "legacy"]) {
11893
- const from = path9.join(dirs.v2, sub);
11990
+ const from = path10.join(dirs.v2, sub);
11894
11991
  if (!fs10.existsSync(from))
11895
11992
  continue;
11896
11993
  if (sub === "tasks") {
11897
11994
  for (const name of fs10.readdirSync(from))
11898
- if (validId(name) && !fs10.existsSync(path9.join(dirs.dir, sub, name)))
11995
+ if (validId(name) && !fs10.existsSync(path10.join(dirs.dir, sub, name)))
11899
11996
  tasks += 1;
11900
11997
  }
11901
- merge(from, path9.join(dirs.dir, sub));
11998
+ merge(from, path10.join(dirs.dir, sub));
11902
11999
  }
11903
- const ledger = path9.join(dirs.v2, "ledger");
11904
- if (fs10.existsSync(ledger) && !fs10.existsSync(path9.join(dirs.dir, "ledger")))
11905
- merge(ledger, path9.join(dirs.dir, "ledger"));
11906
- fs10.rmSync(path9.join(dirs.v2, "task-index.json"), { force: true });
11907
- fs10.renameSync(marker, path9.join(dirs.v2, "store.moved.json"));
12000
+ const ledger = path10.join(dirs.v2, "ledger");
12001
+ if (fs10.existsSync(ledger) && !fs10.existsSync(path10.join(dirs.dir, "ledger")))
12002
+ merge(ledger, path10.join(dirs.dir, "ledger"));
12003
+ fs10.rmSync(path10.join(dirs.v2, "task-index.json"), { force: true });
12004
+ fs10.renameSync(marker, path10.join(dirs.v2, "store.moved.json"));
11908
12005
  } catch (error) {
11909
12006
  return failure2("storage_error", `cannot move ${dirs.v2} into ${dirs.dir}: ${String(error)}`, {
11910
12007
  path: dirs.v2
@@ -11942,7 +12039,7 @@ class TaskStore {
11942
12039
  schemaVersion: SCHEMA_VERSION,
11943
12040
  id: workspaceId ?? newId(),
11944
12041
  revision: newRevision(),
11945
- root: path9.dirname(v2),
12042
+ root: path10.dirname(v2),
11946
12043
  runtime: { createdWith: version, updatedWith: version },
11947
12044
  writer: null,
11948
12045
  store: {
@@ -11954,11 +12051,11 @@ class TaskStore {
11954
12051
  critical: ["store"]
11955
12052
  };
11956
12053
  fs10.mkdirSync(v2, { recursive: true });
11957
- const ignore = path9.join(v2, ".gitignore");
12054
+ const ignore = path10.join(v2, ".gitignore");
11958
12055
  if (!fs10.existsSync(ignore))
11959
12056
  fs10.writeFileSync(ignore, `*
11960
12057
  `);
11961
- replaceFile(path9.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
12058
+ replaceFile(path10.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
11962
12059
  `, true);
11963
12060
  }
11964
12061
  stubFor(taskId) {
@@ -11982,8 +12079,8 @@ class TaskStore {
11982
12079
  }
11983
12080
  writeTombstoneIfMissing() {
11984
12081
  try {
11985
- const v2 = path9.join(this.root, ".workit");
11986
- if (fs10.existsSync(path9.join(v2, "workspace.json")))
12082
+ const v2 = path10.join(this.root, ".workit");
12083
+ if (fs10.existsSync(path10.join(v2, "workspace.json")))
11987
12084
  return;
11988
12085
  let id = null;
11989
12086
  try {
@@ -12000,7 +12097,7 @@ class TaskStore {
12000
12097
  replaceFile(dirs.marker, `${JSON.stringify({ format: "workit-store", version: STORE_FORMAT, createdWith: runtimeVersion() })}
12001
12098
  `, false);
12002
12099
  if (!dirs.shared) {
12003
- const ignore = path9.join(dirs.dir, ".gitignore");
12100
+ const ignore = path10.join(dirs.dir, ".gitignore");
12004
12101
  let current = null;
12005
12102
  try {
12006
12103
  current = fs10.readFileSync(ignore, "utf8");
@@ -12060,7 +12157,7 @@ class TaskStore {
12060
12157
  withLock(lockPath, operation) {
12061
12158
  try {
12062
12159
  this.initializeStorage();
12063
- fs10.mkdirSync(path9.dirname(lockPath), { recursive: true });
12160
+ fs10.mkdirSync(path10.dirname(lockPath), { recursive: true });
12064
12161
  } catch (error) {
12065
12162
  return failure2("storage_error", `unable to initialize store: ${String(error)}`, {
12066
12163
  path: this.paths().dir
@@ -12123,7 +12220,7 @@ class TaskStore {
12123
12220
  if (isTransientWindowsError(error) && !this.lockHolderPresent(lockPath) && !this.lockDirWritable(lockPath))
12124
12221
  return failure2("storage_error", `cannot create the workit lock (${code}); no other Workit call holds it`, {
12125
12222
  path: lockPath,
12126
- guidance: `Check permissions and the read-only attribute on ${path9.dirname(lockPath)}.`
12223
+ guidance: `Check permissions and the read-only attribute on ${path10.dirname(lockPath)}.`
12127
12224
  });
12128
12225
  if (code === "EEXIST" || code === "file_lock_timeout" || code === "file_lock_stale" || isTransientWindowsError(error)) {
12129
12226
  let lock = null;
@@ -12143,17 +12240,17 @@ class TaskStore {
12143
12240
 
12144
12241
  // packages/workit-core/src/core/policy/derive.ts
12145
12242
  import { existsSync as existsSync4 } from "node:fs";
12146
- import path14 from "node:path";
12243
+ import path15 from "node:path";
12147
12244
 
12148
12245
  // packages/workit-core/src/ledger.ts
12149
12246
  import { spawnSync as spawnSync9 } from "node:child_process";
12150
12247
  import { createHash as createHash9, randomBytes as randomBytes2 } from "node:crypto";
12151
12248
  import fs12 from "node:fs";
12152
- import path13 from "node:path";
12249
+ import path14 from "node:path";
12153
12250
 
12154
12251
  // packages/workit-core/src/core/vcs-config.ts
12155
12252
  import fs11 from "node:fs";
12156
- import path12 from "node:path";
12253
+ import path13 from "node:path";
12157
12254
  import { spawnSync as spawnSync8 } from "node:child_process";
12158
12255
 
12159
12256
  // packages/workit-core/src/core/config.ts
@@ -12166,8 +12263,8 @@ import {
12166
12263
  readdirSync as readdirSync2,
12167
12264
  writeFileSync as writeFileSync2
12168
12265
  } from "node:fs";
12169
- import os2 from "node:os";
12170
- import path10 from "node:path";
12266
+ import os3 from "node:os";
12267
+ import path11 from "node:path";
12171
12268
 
12172
12269
  // packages/workit-core/src/core/boundary.ts
12173
12270
  var EVENT = {
@@ -12211,7 +12308,7 @@ var mergePreset = (preset, input = {}, current = {
12211
12308
  protected: preset === "custom" ? input.protectedNames ?? current.branchPolicy.protected : [...defs.protected]
12212
12309
  };
12213
12310
  };
12214
- var resolveConfigDir = () => process.env.WORKFLOW_TOOLKIT_CONFIG ?? process.env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path10.join(process.env.XDG_CONFIG_HOME || path10.join(os2.homedir(), ".config"), "workit");
12311
+ 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");
12215
12312
  var migratedDir = null;
12216
12313
  var migrationFailed = false;
12217
12314
  var ensureConfigDir = (dir = resolveConfigDir()) => {
@@ -12221,7 +12318,7 @@ var ensureConfigDir = (dir = resolveConfigDir()) => {
12221
12318
  migratedDir = dir;
12222
12319
  return dir;
12223
12320
  }
12224
- const legacy = path10.join(process.env.XDG_CONFIG_HOME || path10.join(os2.homedir(), ".config"), "workflow-toolkit");
12321
+ const legacy = path11.join(process.env.XDG_CONFIG_HOME || path11.join(os3.homedir(), ".config"), "workflow-toolkit");
12225
12322
  if (!existsSync3(legacy)) {
12226
12323
  migratedDir = dir;
12227
12324
  return dir;
@@ -12234,8 +12331,8 @@ var ensureConfigDir = (dir = resolveConfigDir()) => {
12234
12331
  mkdirSync2(dir, { recursive: true });
12235
12332
  diagnosticLogger?.info(EVENT.migration, { from: legacy, to: dir });
12236
12333
  for (const entry of readdirSync2(legacy, { withFileTypes: true })) {
12237
- const src = path10.join(legacy, entry.name);
12238
- const dest = path10.join(dir, entry.name);
12334
+ const src = path11.join(legacy, entry.name);
12335
+ const dest = path11.join(dir, entry.name);
12239
12336
  if (existsSync3(dest))
12240
12337
  continue;
12241
12338
  try {
@@ -12307,7 +12404,7 @@ var parseConfigResult = (raw, file) => {
12307
12404
  return { status: "valid", path: file, config };
12308
12405
  };
12309
12406
  var readConfigTyped = (dir) => {
12310
- const file = path10.join(dir ?? configDir(), "config.json");
12407
+ const file = path11.join(dir ?? configDir(), "config.json");
12311
12408
  return parseConfigResult(readSafe(file), file);
12312
12409
  };
12313
12410
  var readConfig = () => {
@@ -12316,7 +12413,7 @@ var readConfig = () => {
12316
12413
  throw new Error(result.error);
12317
12414
  return result.config ?? DEFAULTS;
12318
12415
  };
12319
- var vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path10.join(configDir(), "vcs.json");
12416
+ var vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path11.join(configDir(), "vcs.json");
12320
12417
  var branchGlobPattern = (glob) => new RegExp(`^${glob.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`, "i");
12321
12418
  var resolveBranchPolicy = (config, workspace, repoPreset) => {
12322
12419
  const wp = workspace?.branchPolicy ?? {};
@@ -12360,7 +12457,7 @@ var resolveCommitPolicy = (config, workspace) => {
12360
12457
  import { spawnSync as spawnSync6 } from "node:child_process";
12361
12458
  import { createHash as createHash7 } from "node:crypto";
12362
12459
  import { readFileSync as readFileSync3, realpathSync as realpathSync2 } from "node:fs";
12363
- import path11 from "node:path";
12460
+ import path12 from "node:path";
12364
12461
 
12365
12462
  // packages/workit-core/src/core/branch-policy.ts
12366
12463
  import { spawnSync as spawnSync5 } from "node:child_process";
@@ -12486,7 +12583,7 @@ var releaseTrackSchema = object({
12486
12583
  context.addIssue({ code: "custom", path: [field], message: "entries must be unique" });
12487
12584
  }
12488
12585
  }
12489
- 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(".."))) {
12586
+ 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(".."))) {
12490
12587
  context.addIssue({
12491
12588
  code: "custom",
12492
12589
  path: ["versionSource", "path"],
@@ -12506,6 +12603,7 @@ var workspaceConfigSchema = object({
12506
12603
  autoApprove: union([boolean2(), array(nonBlank)]).optional(),
12507
12604
  defaultEndpoint: unknown().optional(),
12508
12605
  verification: _enum(["self", "independent"]).optional(),
12606
+ trailers: boolean2().optional(),
12509
12607
  autonomy: object(Object.fromEntries(["push", "pr", "merge", "release", "rerun"].map((kind) => [
12510
12608
  kind,
12511
12609
  union([boolean2(), literal("verified")]).optional()
@@ -12584,7 +12682,7 @@ var validateWorkspacesDocument = (parsed, file) => {
12584
12682
  };
12585
12683
  };
12586
12684
  var readWorkspacesResult = (dir = configDir()) => {
12587
- const file = path11.join(dir, "workspaces.json");
12685
+ const file = path12.join(dir, "workspaces.json");
12588
12686
  let raw;
12589
12687
  try {
12590
12688
  raw = readFileSync3(file, "utf8");
@@ -12695,9 +12793,9 @@ var mainCheckoutOf = (cwd) => {
12695
12793
  let main = null;
12696
12794
  const dirs = git(["rev-parse", "--path-format=absolute", "--git-dir", "--git-common-dir"]);
12697
12795
  const [gitDir, common] = (dirs ?? "").trim().split(/\r?\n/u);
12698
- if (gitDir && common && path11.resolve(gitDir) !== path11.resolve(common)) {
12796
+ if (gitDir && common && path12.resolve(gitDir) !== path12.resolve(common)) {
12699
12797
  const listed = /^worktree (.+)$/mu.exec(git(["worktree", "list", "--porcelain"]) ?? "")?.[1];
12700
- main = listed?.trim() || (path11.basename(common) === ".git" ? path11.dirname(common) : common);
12798
+ main = listed?.trim() || (path12.basename(common) === ".git" ? path12.dirname(common) : common);
12701
12799
  }
12702
12800
  mainCheckouts.set(cwd, main);
12703
12801
  return main;
@@ -12787,8 +12885,8 @@ var resolveRuntimeWorkspaceVcs = (cwd) => resolveRuntimeWorkspaceCandidate(cwd,
12787
12885
  var runtimeWorkspaceIndexSchema = object({
12788
12886
  workspaces: array(object({ name: nonBlank, glob: nonBlank }).passthrough()).optional()
12789
12887
  }).passthrough();
12790
- var matchRuntimeWorkspace = (cwd) => {
12791
- const file = path11.join(configDir(), "workspaces.json");
12888
+ var matchRuntimeWorkspace = (cwd, dir = configDir()) => {
12889
+ const file = path12.join(dir, "workspaces.json");
12792
12890
  let raw;
12793
12891
  try {
12794
12892
  raw = readFileSync3(file, "utf8");
@@ -12817,12 +12915,30 @@ var matchRuntimeWorkspace = (cwd) => {
12817
12915
  const matches = matchingEntries(cwd, entries ?? []);
12818
12916
  const workspaceName = process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined;
12819
12917
  const selected = selectWorkspaceMatch(matches, cwd, workspaceName);
12820
- return selected ? { file, selected } : null;
12918
+ return selected ? { file, selected, matches } : null;
12821
12919
  };
12822
12920
  var resolveRuntimeReleaseTracks = (cwd) => {
12823
12921
  const matched = matchRuntimeWorkspace(cwd);
12824
12922
  return matched ? { workspace: matched.selected.name, releaseTracks: matched.selected.releaseTracks } : null;
12825
12923
  };
12924
+ var workspaceTrailers = (cwd, dir) => {
12925
+ let matched;
12926
+ try {
12927
+ matched = matchRuntimeWorkspace(cwd, dir);
12928
+ } catch {
12929
+ return { enabled: true, workspace: null, from: null };
12930
+ }
12931
+ if (!matched)
12932
+ return { enabled: true, workspace: null, from: null };
12933
+ const { selected, matches } = matched;
12934
+ const enclosing = matches.filter((entry) => entry !== selected).toSorted((a, b) => globSpecificity(b.glob) - globSpecificity(a.glob));
12935
+ const source = [selected, ...enclosing].find((entry) => typeof entry.trailers === "boolean");
12936
+ return {
12937
+ enabled: source?.trailers !== false,
12938
+ workspace: selected.name,
12939
+ from: source?.name ?? null
12940
+ };
12941
+ };
12826
12942
  var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
12827
12943
  const matched = matchRuntimeWorkspace(cwd);
12828
12944
  if (!matched)
@@ -13159,7 +13275,7 @@ var git3 = (cwd, args) => {
13159
13275
  return run.status === 0 ? (run.stdout ?? "").trim() : null;
13160
13276
  };
13161
13277
  var recordedBaseKey = (branch) => `branch.${branch}.workitBase`;
13162
- var escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
13278
+ var escapeRegExp2 = (text) => text.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
13163
13279
  var reflog = (cwd, ref) => (git3(cwd, ["log", "-g", "--date=unix", "--format=%H%x09%gd%x09%gs", ref, "--"]) ?? "").split(`
13164
13280
  `).map((line) => {
13165
13281
  const [sha = "", selector = "", ...subject] = line.split("\t");
@@ -13191,7 +13307,7 @@ function gitTrackProbe(cwd) {
13191
13307
  const created = own.at(-1);
13192
13308
  if (!created || created.subject !== "branch: Created from HEAD")
13193
13309
  return null;
13194
- const pattern = new RegExp(`^checkout: moving from (\\S+) to ${escapeRegExp(branch)}$`, "u");
13310
+ const pattern = new RegExp(`^checkout: moving from (\\S+) to ${escapeRegExp2(branch)}$`, "u");
13195
13311
  const entry = reflog(cwd, "HEAD").findLast((item) => item.time >= created.time && item.sha === created.sha && pattern.test(item.subject));
13196
13312
  return entry ? pattern.exec(entry.subject)?.[1] ?? null : null;
13197
13313
  },
@@ -13261,7 +13377,7 @@ function resolveTrackFor(cwd, options) {
13261
13377
  }
13262
13378
 
13263
13379
  // packages/workit-core/src/core/vcs-config.ts
13264
- var workspacesPath = () => path12.join(configDir(), "workspaces.json");
13380
+ var workspacesPath = () => path13.join(configDir(), "workspaces.json");
13265
13381
  var vcsCwd = (cwd) => cwd ?? process.env.WORKFLOW_WORKSPACE_ROOT ?? process.cwd();
13266
13382
  var remoteProvider = (cwd) => {
13267
13383
  const r = spawnSync8("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" });
@@ -13363,7 +13479,7 @@ function vcsConfig(mode, cwd, options = {}) {
13363
13479
  const prov = cfg[provider] ?? {};
13364
13480
  const out = {
13365
13481
  ok: true,
13366
- configPath: path12.resolve(cfgPath),
13482
+ configPath: path13.resolve(cfgPath),
13367
13483
  provider,
13368
13484
  defaultTargetBranch: workspaceDefault,
13369
13485
  pr: cfg.pr ?? {},
@@ -13501,14 +13617,14 @@ function diffHash(cwd, base, head) {
13501
13617
  return `sha256:${hash.digest("hex")}`;
13502
13618
  }
13503
13619
  function storeRoot(cwd) {
13504
- const location = resolveStore(path13.resolve(cwd));
13620
+ const location = resolveStore(path14.resolve(cwd));
13505
13621
  if (location instanceof Error)
13506
13622
  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");
13507
13623
  return { ok: true, value: { root: location.dir, shared: location.shared } };
13508
13624
  }
13509
13625
  function ledgerPath(cwd) {
13510
13626
  const root = storeRoot(cwd);
13511
- return root.ok ? { ok: true, value: path13.join(root.value.root, "ledger", "ledger.jsonl") } : root;
13627
+ return root.ok ? { ok: true, value: path14.join(root.value.root, "ledger", "ledger.jsonl") } : root;
13512
13628
  }
13513
13629
  var newId2 = () => `${Date.now().toString(36)}-${randomBytes2(6).toString("hex")}`;
13514
13630
  var NETWORK_FS_TYPES = new Set([
@@ -13538,13 +13654,13 @@ var LOCK_STALE_MS = 30000;
13538
13654
  var LOCK_OWNER = "owner";
13539
13655
  var lockToken = (lock) => {
13540
13656
  try {
13541
- return fs12.readFileSync(path13.join(lock, LOCK_OWNER), "utf8");
13657
+ return fs12.readFileSync(path14.join(lock, LOCK_OWNER), "utf8");
13542
13658
  } catch {
13543
13659
  return null;
13544
13660
  }
13545
13661
  };
13546
13662
  var lockAgeMs = (lock) => {
13547
- for (const target of [path13.join(lock, LOCK_OWNER), lock]) {
13663
+ for (const target of [path14.join(lock, LOCK_OWNER), lock]) {
13548
13664
  try {
13549
13665
  return Date.now() - fs12.statSync(target).mtimeMs;
13550
13666
  } catch {}
@@ -13561,7 +13677,7 @@ var ledgerLock = {
13561
13677
  throw error;
13562
13678
  }
13563
13679
  const token = `${process.pid}-${randomBytes2(8).toString("hex")}`;
13564
- fs12.writeFileSync(path13.join(lock, LOCK_OWNER), token);
13680
+ fs12.writeFileSync(path14.join(lock, LOCK_OWNER), token);
13565
13681
  return token;
13566
13682
  },
13567
13683
  release(lock, token) {
@@ -13686,8 +13802,8 @@ function appendLine(file, build, options) {
13686
13802
  }
13687
13803
  };
13688
13804
  try {
13689
- fs12.mkdirSync(path13.dirname(file), { recursive: true });
13690
- if (!options.forceLock && !onNetworkFs(path13.dirname(file)))
13805
+ fs12.mkdirSync(path14.dirname(file), { recursive: true });
13806
+ if (!options.forceLock && !onNetworkFs(path14.dirname(file)))
13691
13807
  return write();
13692
13808
  const locked = withLedgerLock(file, write);
13693
13809
  return locked ?? err("busy", `ledger lock ${file}.lock is held`, "retry; remove the .lock directory if no workit process is running");
@@ -14250,7 +14366,7 @@ var productDecision = (task, ledger) => {
14250
14366
  };
14251
14367
  };
14252
14368
  var planRecorded = (task, root) => {
14253
- const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(path14.resolve(root, ref.path)));
14369
+ const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(path15.resolve(root, ref.path)));
14254
14370
  if (cited)
14255
14371
  return {
14256
14372
  met: true,
@@ -14310,14 +14426,14 @@ function writeBlockers(task, root) {
14310
14426
 
14311
14427
  // packages/workit-core/src/core/task-evaluation.ts
14312
14428
  var digestBytes = (value) => createHash10("sha256").update(value).digest("hex");
14313
- var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path15.sep}`);
14314
- var relative = (root, candidate) => path15.relative(root, candidate).split(path15.sep).join("/") || ".";
14429
+ var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path16.sep}`);
14430
+ var relative = (root, candidate) => path16.relative(root, candidate).split(path16.sep).join("/") || ".";
14315
14431
  var canonicalPath = (value) => {
14316
14432
  if (typeof value !== "string" || !value)
14317
14433
  return null;
14318
14434
  if (value.includes("\\") || value.split("/").includes(".."))
14319
14435
  return null;
14320
- const normalized = path15.posix.normalize(value);
14436
+ const normalized = path16.posix.normalize(value);
14321
14437
  if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
14322
14438
  return null;
14323
14439
  return normalized === "." ? "." : normalized.replace(/\/$/, "");
@@ -14365,14 +14481,14 @@ var gitPaths = (root) => {
14365
14481
  git: !/not a git repository/i.test(stderr)
14366
14482
  };
14367
14483
  }
14368
- const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path15.sep).join("/")) : [];
14484
+ const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path16.sep).join("/")) : [];
14369
14485
  const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
14370
14486
  if (stagedDeleted.status !== 0) {
14371
14487
  const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
14372
14488
  if (!/not a git repository/i.test(stderr))
14373
14489
  return { paths, uncertain: true, git: true };
14374
14490
  } else if (stagedDeleted.stdout) {
14375
- paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path15.sep).join("/")));
14491
+ paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path16.sep).join("/")));
14376
14492
  }
14377
14493
  return { paths: [...new Set(paths)], uncertain: false, git: true };
14378
14494
  };
@@ -14387,7 +14503,7 @@ var walk = (root, directory, output) => {
14387
14503
  for (const name of names) {
14388
14504
  if (name === ".git" || name === ".workit")
14389
14505
  continue;
14390
- const target = path15.join(directory, name);
14506
+ const target = path16.join(directory, name);
14391
14507
  let stat;
14392
14508
  try {
14393
14509
  stat = fs13.lstatSync(target);
@@ -14405,12 +14521,12 @@ var walk = (root, directory, output) => {
14405
14521
  var scopeRoots = (root, scope) => {
14406
14522
  const roots = [];
14407
14523
  for (const item of scope.paths.length ? scope.paths : ["."]) {
14408
- const target = path15.resolve(root, item);
14524
+ const target = path16.resolve(root, item);
14409
14525
  if (!inside(root, target))
14410
14526
  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` }] });
14411
14527
  let ancestor = target;
14412
14528
  while (!fs13.existsSync(ancestor) && ancestor !== root)
14413
- ancestor = path15.dirname(ancestor);
14529
+ ancestor = path16.dirname(ancestor);
14414
14530
  try {
14415
14531
  if (!inside(root, fs13.realpathSync(ancestor)))
14416
14532
  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` }] });
@@ -14462,7 +14578,7 @@ function captureCandidate(root, scope, environment = []) {
14462
14578
  for (const item of [...names].toSorted()) {
14463
14579
  if (!scopeMatches(item, normalizedScope))
14464
14580
  continue;
14465
- const target = path15.join(checkout, item);
14581
+ const target = path16.join(checkout, item);
14466
14582
  try {
14467
14583
  const stat = fs13.lstatSync(target);
14468
14584
  if (stat.isSymbolicLink()) {
@@ -14646,23 +14762,23 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
14646
14762
  continue;
14647
14763
  if (!reference.digest)
14648
14764
  return failure2("invalid_input", "document references require a byte digest");
14649
- const target = path15.resolve(root, reference.path);
14650
- if (target !== root && !target.startsWith(`${root}${path15.sep}`))
14765
+ const target = path16.resolve(root, reference.path);
14766
+ if (target !== root && !target.startsWith(`${root}${path16.sep}`))
14651
14767
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
14652
14768
  fields: [
14653
14769
  { path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
14654
14770
  ]
14655
14771
  });
14656
14772
  try {
14657
- const below = path15.relative(root, target);
14773
+ const below = path16.relative(root, target);
14658
14774
  let current = root;
14659
- for (const segment of below.split(path15.sep)) {
14775
+ for (const segment of below.split(path16.sep)) {
14660
14776
  if (!segment)
14661
14777
  continue;
14662
- current = path15.join(current, segment);
14778
+ current = path16.join(current, segment);
14663
14779
  const stat = fs13.lstatSync(current);
14664
14780
  const real = fs13.realpathSync(current);
14665
- if (real !== root && !real.startsWith(`${root}${path15.sep}`))
14781
+ if (real !== root && !real.startsWith(`${root}${path16.sep}`))
14666
14782
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
14667
14783
  fields: [
14668
14784
  {
@@ -15534,20 +15650,20 @@ var judgeInputSummary = (raw) => {
15534
15650
  };
15535
15651
 
15536
15652
  // packages/workit-core/src/autonomy.ts
15537
- import os3 from "node:os";
15538
- import path16 from "node:path";
15653
+ import os4 from "node:os";
15654
+ import path17 from "node:path";
15539
15655
  var accountHome = () => {
15540
15656
  try {
15541
- return os3.userInfo().homedir;
15657
+ return os4.userInfo().homedir;
15542
15658
  } catch {
15543
- return os3.homedir();
15659
+ return os4.homedir();
15544
15660
  }
15545
15661
  };
15546
15662
  var grantsHome = { resolve: accountHome };
15547
- var grantsDir = () => path16.join(grantsHome.resolve(), ".config", "workit");
15663
+ var grantsDir = () => path17.join(grantsHome.resolve(), ".config", "workit");
15548
15664
  var grantsOverride = () => {
15549
- const configured = path16.resolve(resolveConfigDir());
15550
- return configured === path16.resolve(grantsDir()) ? null : `the config directory is redirected to ${configured} (WORKFLOW_TOOLKIT_CONFIG, WORKFLOW_TOOLKIT_CONFIG_DIR or XDG_CONFIG_HOME); grants are read only from ${path16.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
15665
+ const configured = path17.resolve(resolveConfigDir());
15666
+ return configured === path17.resolve(grantsDir()) ? null : `the config directory is redirected to ${configured} (WORKFLOW_TOOLKIT_CONFIG, WORKFLOW_TOOLKIT_CONFIG_DIR or XDG_CONFIG_HOME); grants are read only from ${path17.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
15551
15667
  };
15552
15668
  var GRANT_KINDS = ["push", "pr", "merge", "release", "rerun"];
15553
15669
  var DEFAULT_GRANTS = Object.freeze({
@@ -17529,7 +17645,7 @@ function entryCompactContext(store, entry, session, context) {
17529
17645
  return null;
17530
17646
  const freshness = { mode: "signal", current: () => recentSignal(store.root) };
17531
17647
  const observed = task?.data.evidence.some(isObservedCheck) ?? false;
17532
- 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)] : []));
17533
17649
  const observedFiles = filesKey(files);
17534
17650
  const compact = new WorkitCore(store, context).compactContext(entry?.id ?? null, freshness, origin && { origin: origin.origin, taskId: origin.entry.id });
17535
17651
  if (!compact.ok || !compact.data)
@@ -17607,14 +17723,14 @@ var turnMarker = (input) => {
17607
17723
  if (location instanceof Error)
17608
17724
  return null;
17609
17725
  const session = [input.host, input.session.id, input.session.agentId ?? ""].join("\x00");
17610
- 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`);
17611
17727
  } catch {
17612
17728
  return null;
17613
17729
  }
17614
17730
  };
17615
17731
  var writeTurnDigest = (file, digest) => {
17616
17732
  try {
17617
- fs14.mkdirSync(path17.dirname(file), { recursive: true });
17733
+ fs14.mkdirSync(path18.dirname(file), { recursive: true });
17618
17734
  fs14.writeFileSync(file, `${JSON.stringify({ digest })}
17619
17735
  `);
17620
17736
  } catch {}
@@ -17629,7 +17745,7 @@ var pruneTurnDigests = (dir, now) => {
17629
17745
  for (const name of fs14.readdirSync(dir)) {
17630
17746
  if (!name.startsWith("turn-"))
17631
17747
  continue;
17632
- const file = path17.join(dir, name);
17748
+ const file = path18.join(dir, name);
17633
17749
  try {
17634
17750
  if (now - fs14.statSync(file).mtimeMs > TURN_TTL_MS)
17635
17751
  fs14.rmSync(file, { force: true });
@@ -17659,7 +17775,7 @@ var seedTurnContext = (input, descriptor, text = turnContextText(input, descript
17659
17775
  const file = turnMarker(input);
17660
17776
  if (!file)
17661
17777
  return;
17662
- pruneTurnDigests(path17.dirname(file), Date.now());
17778
+ pruneTurnDigests(path18.dirname(file), Date.now());
17663
17779
  if (text)
17664
17780
  writeTurnDigest(file, digestOf(text));
17665
17781
  else
@@ -17668,14 +17784,14 @@ var seedTurnContext = (input, descriptor, text = turnContextText(input, descript
17668
17784
  // packages/workit-core/src/core/route-intent.ts
17669
17785
  import { spawnSync as spawnSync12 } from "node:child_process";
17670
17786
  import { existsSync as existsSync6 } from "node:fs";
17671
- import path20 from "node:path";
17787
+ import path21 from "node:path";
17672
17788
 
17673
17789
  // packages/workit-core/src/hooks/raw-git.ts
17674
17790
  import { spawnSync as spawnSync11 } from "node:child_process";
17675
17791
  import { createHash as createHash14 } from "node:crypto";
17676
17792
  import fs16 from "node:fs";
17677
- import os4 from "node:os";
17678
- import path19 from "node:path";
17793
+ import os5 from "node:os";
17794
+ import path20 from "node:path";
17679
17795
 
17680
17796
  // packages/workit-core/src/core/branch.ts
17681
17797
  import { createHash as createHash12 } from "node:crypto";
@@ -17888,7 +18004,7 @@ var globOf = (pattern) => pattern.source.replace(/^\^|\$$/gu, "").replaceAll(".*
17888
18004
  // packages/workit-core/src/hooks/session-marker.ts
17889
18005
  import { createHash as createHash13 } from "node:crypto";
17890
18006
  import fs15 from "node:fs";
17891
- import path18 from "node:path";
18007
+ import path19 from "node:path";
17892
18008
  var sessionMarkerFile = (input, session, store) => {
17893
18009
  let dir = store;
17894
18010
  if (dir === undefined) {
@@ -17898,7 +18014,7 @@ var sessionMarkerFile = (input, session, store) => {
17898
18014
  dir = location.dir;
17899
18015
  }
17900
18016
  const name = createHash13("sha256").update(`${input.host}\x00${session}`).digest("hex").slice(0, 32);
17901
- return path18.join(dir, "hooks", `skills-${name}.json`);
18017
+ return path19.join(dir, "hooks", `skills-${name}.json`);
17902
18018
  };
17903
18019
  var list2 = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
17904
18020
  var readSessionMarker = (file) => {
@@ -17911,7 +18027,7 @@ var readSessionMarker = (file) => {
17911
18027
  };
17912
18028
  var writeSessionMarker = (file, marker) => {
17913
18029
  try {
17914
- fs15.mkdirSync(path18.dirname(file), { recursive: true });
18030
+ fs15.mkdirSync(path19.dirname(file), { recursive: true });
17915
18031
  fs15.writeFileSync(file, JSON.stringify(marker));
17916
18032
  } catch {}
17917
18033
  };
@@ -18056,12 +18172,12 @@ var GIT_VALUE_OPTIONS = new Set([
18056
18172
  "--config-env",
18057
18173
  "--super-prefix"
18058
18174
  ]);
18059
- 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("\\\\");
18060
18176
  var joinDir = (base, next) => {
18061
18177
  if (base === undefined || /[$`*?]/.test(next) || next === "-")
18062
18178
  return;
18063
- const expanded = next === "~" || next.startsWith("~/") ? path19.join(os4.homedir(), next.slice(1)) : next;
18064
- 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);
18065
18181
  };
18066
18182
  var cdTarget = (words) => {
18067
18183
  const args = words.slice(1);
@@ -18112,7 +18228,7 @@ function rawInvocations(command, dialect = "posix", depth = 0) {
18112
18228
  const name = commandName(words[0]);
18113
18229
  if (CD.has(name)) {
18114
18230
  const target = cdTarget(words);
18115
- dir = target === null ? os4.homedir() : joinDir(dir, target);
18231
+ dir = target === null ? os5.homedir() : joinDir(dir, target);
18116
18232
  continue;
18117
18233
  }
18118
18234
  if (PUSHD.has(name)) {
@@ -18370,17 +18486,17 @@ var headSha2 = (repo) => {
18370
18486
  if (!git || git.reftable)
18371
18487
  return null;
18372
18488
  try {
18373
- const head = fs16.readFileSync(path19.join(git.gitDir, "HEAD"), "utf8").trim();
18489
+ const head = fs16.readFileSync(path20.join(git.gitDir, "HEAD"), "utf8").trim();
18374
18490
  if (/^[0-9a-f]{40,64}$/.test(head))
18375
18491
  return head;
18376
18492
  const ref = /^ref: (refs\/.+)$/.exec(head)?.[1];
18377
18493
  if (!ref)
18378
18494
  return null;
18379
- const common = path19.dirname(repo.location.dir);
18495
+ const common = path20.dirname(repo.location.dir);
18380
18496
  try {
18381
- return fs16.readFileSync(path19.join(common, ref), "utf8").trim() || null;
18497
+ return fs16.readFileSync(path20.join(common, ref), "utf8").trim() || null;
18382
18498
  } catch {}
18383
- const packed = fs16.readFileSync(path19.join(common, "packed-refs"), "utf8");
18499
+ const packed = fs16.readFileSync(path20.join(common, "packed-refs"), "utf8");
18384
18500
  return new RegExp(`^([0-9a-f]{40,64}) ${ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`, "m").exec(packed)?.[1] ?? null;
18385
18501
  } catch {
18386
18502
  return null;
@@ -18469,7 +18585,7 @@ var actionsIn = (cwd, command, dialect) => {
18469
18585
  const action = rawAction(invocation);
18470
18586
  if (!action)
18471
18587
  continue;
18472
- const dir = path19.resolve(cwd, invocation.dir ?? ".");
18588
+ const dir = path20.resolve(cwd, invocation.dir ?? ".");
18473
18589
  if (!repos.has(dir)) {
18474
18590
  const repo = repoAt(dir);
18475
18591
  repos.set(dir, repo && isWorkitWorkspace(repo) ? repo : null);
@@ -18549,7 +18665,7 @@ function rawGitPre(input, command, options = {}) {
18549
18665
  var deny = (reason) => ({ kind: "deny", reason, unblock: null });
18550
18666
  var NEXT_COMMAND = "next";
18551
18667
  var MARKER_TTL_SECONDS = 3600;
18552
- 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`);
18553
18669
  var callKey = (toolUseId, command) => toolUseId ?? `cmd:${createHash14("sha256").update(command).digest("hex")}`;
18554
18670
  function noteRawCommit(input, command, key) {
18555
18671
  try {
@@ -18560,7 +18676,7 @@ function noteRawCommit(input, command, key) {
18560
18676
  if (action.kind !== "commit")
18561
18677
  continue;
18562
18678
  const file = markerFile(repo, input.session.id, key);
18563
- fs16.mkdirSync(path19.dirname(file), { recursive: true });
18679
+ fs16.mkdirSync(path20.dirname(file), { recursive: true });
18564
18680
  fs16.writeFileSync(file, `${JSON.stringify({ head: headSha2(repo), at })}
18565
18681
  `);
18566
18682
  }
@@ -18733,7 +18849,7 @@ var shellBranchPolicyViolation = (root, command, dialect = "posix") => {
18733
18849
  for (const target of shellBranchTargets(command, dialect)) {
18734
18850
  if (target.dir === undefined)
18735
18851
  continue;
18736
- const dir = target.dir === null ? root : path20.resolve(root, target.dir);
18852
+ const dir = target.dir === null ? root : path21.resolve(root, target.dir);
18737
18853
  if (target.dir !== null && (!existsSync6(dir) || !inWorkitWorkspace(dir)))
18738
18854
  continue;
18739
18855
  if (localBranchExists(dir, target.branch))
@@ -18753,27 +18869,27 @@ var shellPolicy = (cwd, command, dialect = "posix") => {
18753
18869
  };
18754
18870
  // packages/workit-core/src/hooks/write-gate.ts
18755
18871
  import { realpathSync as realpathSync5 } from "node:fs";
18756
- import path21 from "node:path";
18872
+ import path22 from "node:path";
18757
18873
  var NONE3 = { kind: "none" };
18758
18874
  var CASE_INSENSITIVE = process.platform === "darwin" || process.platform === "win32";
18759
18875
  var canonical2 = (file) => {
18760
18876
  let rest = "";
18761
- for (let dir = path21.resolve(file);; dir = path21.dirname(dir)) {
18877
+ for (let dir = path22.resolve(file);; dir = path22.dirname(dir)) {
18762
18878
  try {
18763
- return path21.join(realpathSync5(dir), rest);
18879
+ return path22.join(realpathSync5(dir), rest);
18764
18880
  } catch {
18765
- if (path21.dirname(dir) === dir)
18766
- return path21.resolve(file);
18767
- 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);
18768
18884
  }
18769
18885
  }
18770
18886
  };
18771
18887
  var exempt = (cwd, root, file, plans) => {
18772
18888
  const fold = (value) => CASE_INSENSITIVE ? value.toLowerCase() : value;
18773
- const relative = path21.relative(fold(canonical2(root)), fold(canonical2(path21.resolve(cwd, file))));
18774
- 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))
18775
18891
  return true;
18776
- const posix = relative.split(path21.sep).join("/");
18892
+ const posix = relative.split(path22.sep).join("/");
18777
18893
  const segments = posix.split("/");
18778
18894
  return /\.mdx?$/i.test(posix) || segments[0] === "docs" || segments.includes("plans") || [...plans].some((plan) => fold(plan) === posix);
18779
18895
  };
@@ -18871,7 +18987,7 @@ var shellWrites = (command) => {
18871
18987
  return { writes: true, targets: unknown ? null : targets };
18872
18988
  };
18873
18989
  var cache2 = new Map;
18874
- 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");
18875
18991
  var gateFor = (cwd) => {
18876
18992
  const store = new TaskStore(cwd);
18877
18993
  const listed = store.listTaskIndex();
@@ -19312,12 +19428,12 @@ ${line}` };
19312
19428
  };
19313
19429
  // packages/workit-core/src/hooks/hosts/fields.ts
19314
19430
  import { existsSync as existsSync7, realpathSync as realpathSync6, statSync as statSync2 } from "node:fs";
19315
- import path22 from "node:path";
19431
+ import path23 from "node:path";
19316
19432
  var isRecord4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
19317
19433
  var nonEmpty2 = (value) => typeof value === "string" && value.trim() !== "";
19318
19434
  var optionalText = (value) => typeof value === "string" ? value : null;
19319
19435
  var existingDirectory = (value) => {
19320
- if (!nonEmpty2(value) || !path22.isAbsolute(value) || !existsSync7(value))
19436
+ if (!nonEmpty2(value) || !path23.isAbsolute(value) || !existsSync7(value))
19321
19437
  return null;
19322
19438
  try {
19323
19439
  return statSync2(value).isDirectory() ? realpathSync6(value) : null;
@@ -19400,7 +19516,7 @@ var workitRole = (descriptor, agentType) => {
19400
19516
  };
19401
19517
  var subagentSession = (session, agentId) => [session, agentId].filter((part) => Boolean(part)).join(":").replace(/[^A-Za-z0-9_.:@/+-]/g, "-").slice(0, 128);
19402
19518
  var CLAUDE_WORKTREE = /[\\/]\.claude[\\/]worktrees[\\/]/;
19403
- 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\`).`;
19404
19520
  var subagentStartText = (input, descriptor, event) => {
19405
19521
  const session = input.session.id ?? null;
19406
19522
  const role = workitRole(descriptor, event.agentType);
@@ -19408,9 +19524,9 @@ var subagentStartText = (input, descriptor, event) => {
19408
19524
  const isolated = descriptor.subagents.worktreeIsolation === "native" && (role === "implementer" || CLAUDE_WORKTREE.test(input.cwd));
19409
19525
  const guide = role === "implementer" ? branchGuidance(input.cwd) : null;
19410
19526
  if (role === "implementer" && isolated)
19411
- 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.`;
19412
19528
  if (isolated)
19413
- return `${ISOLATED_GIT}
19529
+ return `${isolatedGit(input.cwd)}
19414
19530
  ${subagentStartText({ ...input, cwd: "" }, descriptor, event)}`;
19415
19531
  if (role === "implementer")
19416
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.`;
@@ -20056,7 +20172,7 @@ var codexAdapter = {
20056
20172
 
20057
20173
  // packages/workit-core/src/hooks/hosts/cursor.ts
20058
20174
  import fs17 from "node:fs";
20059
- import path23 from "node:path";
20175
+ import path24 from "node:path";
20060
20176
  var undocumented = { support: "undocumented", native: null };
20061
20177
  var none = { support: "none", native: null };
20062
20178
  var CURSOR_DESCRIPTOR = {
@@ -20253,7 +20369,7 @@ var protocolEvent2 = (input) => {
20253
20369
  };
20254
20370
  var TRANSCRIPT_TAIL_BYTES = 256 * 1024;
20255
20371
  var lastAssistantText = (file) => {
20256
- if (!file || !path23.isAbsolute(file))
20372
+ if (!file || !path24.isAbsolute(file))
20257
20373
  return null;
20258
20374
  try {
20259
20375
  const size = fs17.statSync(file).size;
@@ -20290,7 +20406,7 @@ var lastAssistantText = (file) => {
20290
20406
  return null;
20291
20407
  }
20292
20408
  };
20293
- 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}`);
20294
20410
  var hookCwd = (input) => {
20295
20411
  const cwd = existingDirectory(input.cwd);
20296
20412
  if (cwd && input.hook_event_name === "beforeShellExecution")