@brainervirus/workit-cursor 8.23.0 → 8.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6981,6 +6981,110 @@ function resolveRef(cwd, ref) {
6981
6981
  return null;
6982
6982
  return line(git(cwd, ["rev-parse", "--verify", "-q", `${ref}^{commit}`]));
6983
6983
  }
6984
+ function diffNumstat(cwd, fork, head) {
6985
+ const range = laneRange(fork, head);
6986
+ if (!range)
6987
+ return null;
6988
+ const run = git(cwd, [...LANE_DIFF, "--numstat", "-z", ...range, "--"]);
6989
+ if (!run.ok)
6990
+ return null;
6991
+ const out = [];
6992
+ for (const record of run.stdout.split("\x00")) {
6993
+ const match = /^(-|\d+)\t(-|\d+)\t(.+)$/su.exec(record.replace(/^\n/u, ""));
6994
+ if (!match)
6995
+ continue;
6996
+ const binary = match[1] === "-";
6997
+ out.push({
6998
+ path: match[3],
6999
+ added: binary ? 0 : Number(match[1]),
7000
+ deleted: binary ? 0 : Number(match[2]),
7001
+ binary
7002
+ });
7003
+ }
7004
+ return out;
7005
+ }
7006
+ function diffRaw(cwd, fork, head) {
7007
+ const range = laneRange(fork, head);
7008
+ if (!range)
7009
+ return null;
7010
+ const run = git(cwd, [...LANE_DIFF, "--raw", "-z", "--no-abbrev", ...range, "--"]);
7011
+ if (!run.ok)
7012
+ return null;
7013
+ const fields = run.stdout.split("\x00");
7014
+ const out = [];
7015
+ for (let index = 0;index + 1 < fields.length; index += 2) {
7016
+ const meta = /^:(\d{6}) (\d{6}) ([0-9a-f]+) ([0-9a-f]+) [A-Z]\d*$/u.exec(fields[index].replace(/^\n/u, ""));
7017
+ if (!meta)
7018
+ return null;
7019
+ out.push({
7020
+ path: fields[index + 1],
7021
+ oldMode: meta[1],
7022
+ newMode: meta[2],
7023
+ oldBlob: meta[3],
7024
+ newBlob: meta[4]
7025
+ });
7026
+ }
7027
+ return out;
7028
+ }
7029
+ function readBlobs(cwd, ids) {
7030
+ const out = new Map;
7031
+ const wanted = [...new Set(ids)].filter((id) => /^[0-9a-f]{40,64}$/u.test(id));
7032
+ if (!wanted.length)
7033
+ return out;
7034
+ const run = spawnSync("git", ["cat-file", "--batch"], {
7035
+ cwd,
7036
+ input: `${wanted.join(`
7037
+ `)}
7038
+ `,
7039
+ maxBuffer: MAX_BUFFER,
7040
+ timeout: GIT_TIMEOUTS.local,
7041
+ killSignal: "SIGKILL",
7042
+ windowsHide: true
7043
+ });
7044
+ if (run.status !== 0 || !run.stdout)
7045
+ return null;
7046
+ const bytes = run.stdout;
7047
+ let at = 0;
7048
+ for (const id of wanted) {
7049
+ const end = bytes.indexOf(10, at);
7050
+ if (end < 0)
7051
+ return null;
7052
+ const header = bytes.subarray(at, end).toString("utf8").split(" ");
7053
+ at = end + 1;
7054
+ if (header[1] === "missing")
7055
+ continue;
7056
+ const size = Number(header[2]);
7057
+ if (header[0] !== id || !Number.isSafeInteger(size))
7058
+ return null;
7059
+ out.set(id, bytes.subarray(at, at + size));
7060
+ at += size + 1;
7061
+ }
7062
+ return out;
7063
+ }
7064
+ function treeFilesNamed(cwd, rev, name) {
7065
+ if (!safeArg(rev))
7066
+ return null;
7067
+ const run = git(cwd, ["ls-tree", "-r", "-z", "--full-tree", rev]);
7068
+ if (!run.ok)
7069
+ return null;
7070
+ const out = new Map;
7071
+ for (const record of run.stdout.split("\x00")) {
7072
+ const match = /^\d{6} blob ([0-9a-f]+)\t(.+)$/su.exec(record);
7073
+ if (match && (match[2] === name || match[2].endsWith(`/${name}`)))
7074
+ out.set(match[2], match[1]);
7075
+ }
7076
+ return out;
7077
+ }
7078
+ function fileAt(cwd, rev, file) {
7079
+ if (!safeArg(rev))
7080
+ return null;
7081
+ const run = git(cwd, ["cat-file", "blob", `${rev}:${file}`]);
7082
+ return run.ok ? run.stdout : null;
7083
+ }
7084
+ function untrackedFiles(cwd) {
7085
+ const run = git(cwd, ["ls-files", "-z", "--others", "--exclude-standard"]);
7086
+ return run.ok ? run.stdout.split("\x00").filter(Boolean) : [];
7087
+ }
6984
7088
  function currentBranch(cwd) {
6985
7089
  return line(git(cwd, ["symbolic-ref", "--short", "-q", "HEAD"]));
6986
7090
  }
@@ -7027,11 +7131,24 @@ var MAX_BUFFER, GIT_TIMEOUTS, git = (cwd, args, options = {}) => {
7027
7131
  const { atimeNs, mtimeNs } = fs.statSync(from, { bigint: true });
7028
7132
  const seconds = (ns) => (Number(ns / 1000n) - 1) / 1e6;
7029
7133
  fs.utimesSync(to, seconds(atimeNs), seconds(mtimeNs));
7134
+ }, LANE_DIFF, laneRange = (fork, head) => {
7135
+ if (!safeArg(fork) || head !== null && !safeArg(head))
7136
+ return null;
7137
+ return head === null ? [fork] : [fork, head];
7030
7138
  }, config2 = (cwd, key) => line(git(cwd, ["config", "--get", key]));
7031
7139
  var init_rev = __esm(() => {
7032
7140
  MAX_BUFFER = 256 * 1024 * 1024;
7033
7141
  GIT_TIMEOUTS = { local: 20000, worktree: 120000, network: 15000 };
7034
7142
  MAX_UNTRACKED_BYTES = 5 * 1024 * 1024;
7143
+ LANE_DIFF = [
7144
+ "-c",
7145
+ "core.quotePath=false",
7146
+ "diff",
7147
+ "--no-color",
7148
+ "--no-ext-diff",
7149
+ "--no-textconv",
7150
+ "--no-renames"
7151
+ ];
7035
7152
  });
7036
7153
 
7037
7154
  // packages/workit-core/src/store/paths.ts
@@ -8094,7 +8211,7 @@ var init_workspaces = __esm(() => {
8094
8211
  }).passthrough().optional(),
8095
8212
  autoApprove: union([boolean2(), array(nonBlank)]).optional(),
8096
8213
  defaultEndpoint: unknown().optional(),
8097
- verification: _enum(["self", "independent"]).optional(),
8214
+ verification: _enum(["proportional", "self", "independent"]).optional(),
8098
8215
  delegation: unknown().optional(),
8099
8216
  trailers: boolean2().optional(),
8100
8217
  liveSessionGuard: boolean2().optional(),
@@ -9787,7 +9904,8 @@ function checkVerdicts(cwd, branch, ledgerRows) {
9787
9904
  verdict: failing?.verdict ?? null,
9788
9905
  reasons: failing ? ["failing_verdict"] : !newestCurrent ? ["no_verdict"] : newestCurrent.reasons.length ? newestCurrent.reasons : ["type_check_only"]
9789
9906
  };
9790
- const selfEntry = failing ? undefined : verdicts.findLast((entry) => entry.current && !entry.independent && !untrusted(entry.reasons) && STRONG_RESULTS.has(String(entry.verdict.result)));
9907
+ const latestSelf = failing ? undefined : verdicts.findLast((entry) => entry.current && !entry.independent && !untrusted(entry.reasons) && (STRONG_RESULTS.has(String(entry.verdict.result)) || FAILING.has(String(entry.verdict.result))));
9908
+ const selfEntry = latestSelf && STRONG_RESULTS.has(String(latestSelf.verdict.result)) ? latestSelf : undefined;
9791
9909
  return {
9792
9910
  branch,
9793
9911
  head,
@@ -10068,12 +10186,709 @@ var init_ledger = __esm(() => {
10068
10186
  ]);
10069
10187
  });
10070
10188
 
10071
- // packages/workit-core/src/core/policy/derive.ts
10072
- import { existsSync as existsSync2 } from "node:fs";
10189
+ // packages/workit-core/src/forge/pr-body.ts
10190
+ var init_pr_body = __esm(() => {
10191
+ init_vcs_config();
10192
+ });
10193
+
10194
+ // packages/workit-core/src/core/pr-create.ts
10195
+ var init_pr_create = __esm(() => {
10196
+ init_vcs_config();
10197
+ init_vcs_config();
10198
+ init_branch();
10199
+ init_pr_body();
10200
+ });
10201
+
10202
+ // packages/workit-core/src/forge/redact.ts
10203
+ var KEY, ASSIGNMENT, QUOTED_ASSIGNMENT, ANSI;
10204
+ var init_redact = __esm(() => {
10205
+ KEY = String.raw`[A-Za-z0-9_.-]*?(?:token|secret|password|passwd|pwd|api[_-]?key|access[_-]?key|account[_-]?key|private[_-]?key|client[_-]?secret|credentials?|authorization|cookie|signature)[A-Za-z0-9_.-]*`;
10206
+ ASSIGNMENT = new RegExp(String.raw`(?<![A-Za-z0-9])(["']?${KEY}["']?\s*[:=]\s*["']?)((?:bearer|basic|token|digest)\s+)?([^\s"',;&]+)`, "giu");
10207
+ QUOTED_ASSIGNMENT = new RegExp(String.raw`(?<![A-Za-z0-9])(["']?${KEY}["']?\s*[:=]\s*)(["'])([^"'\n]*[^\s"'][^"'\n]*)\2`, "giu");
10208
+ ANSI = new RegExp(String.raw`\u001b\[[0-9;?]*[ -/]*[@-~]|\u001b\][^\u0007]*\u0007`, "gu");
10209
+ });
10210
+ // packages/workit-core/src/git/ops.ts
10211
+ var COMMIT_TIMEOUT_MS;
10212
+ var init_ops = __esm(() => {
10213
+ init_branch();
10214
+ init_branch_policy();
10215
+ init_commit_flavors();
10216
+ init_pr_create();
10217
+ init_release_tracks();
10218
+ init_vcs_config();
10219
+ init_workspaces();
10220
+ init_redact();
10221
+ init_host_session();
10222
+ init_ledger();
10223
+ init_rev();
10224
+ COMMIT_TIMEOUT_MS = 10 * 60000;
10225
+ });
10226
+
10227
+ // packages/workit-core/src/core/policy/attributes.ts
10228
+ function patternRegex(dir, pattern) {
10229
+ if (!pattern || pattern.endsWith("/") || pattern.startsWith('"') || pattern.startsWith("!"))
10230
+ return null;
10231
+ const anchored = pattern.includes("/");
10232
+ const body = pattern.replace(/^\//u, "");
10233
+ let source = "";
10234
+ for (let index = 0;index < body.length; index += 1) {
10235
+ const char = body[index];
10236
+ if (char === "*" && body[index + 1] === "*") {
10237
+ const slash = body[index + 2] === "/";
10238
+ source += slash ? "(?:.*/)?" : ".*";
10239
+ index += slash ? 2 : 1;
10240
+ } else if (char === "*")
10241
+ source += "[^/]*";
10242
+ else if (char === "?")
10243
+ source += "[^/]";
10244
+ else if (char === "[") {
10245
+ const end = body.indexOf("]", index + 2);
10246
+ if (end < 0)
10247
+ return null;
10248
+ const set = body.slice(index + 1, end).replace(/^!/u, "^").replace(/\\/gu, "\\\\");
10249
+ source += `[${set}]`;
10250
+ index = end;
10251
+ } else if (char === "\\" && index + 1 < body.length) {
10252
+ source += body[index + 1].replace(/[.*+?^${}()|[\]\\/]/gu, "\\$&");
10253
+ index += 1;
10254
+ } else
10255
+ source += char.replace(/[.*+?^${}()|[\]\\/]/gu, "\\$&");
10256
+ }
10257
+ const prefix = dir ? `${dir.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")}/` : "";
10258
+ try {
10259
+ return new RegExp(anchored ? `^${prefix}${source}$` : `^${prefix}(?:.*/)?${source}$`, "u");
10260
+ } catch {
10261
+ return null;
10262
+ }
10263
+ }
10264
+ function rulesOf(dir, text) {
10265
+ const out = [];
10266
+ for (const raw of text.split(`
10267
+ `)) {
10268
+ const line = raw.trim();
10269
+ if (!line || line.startsWith("#") || line.startsWith("[attr]"))
10270
+ continue;
10271
+ const [pattern, ...attributes] = line.split(/\s+/u);
10272
+ let generated = null;
10273
+ for (const attribute of attributes) {
10274
+ if (attribute === "linguist-generated" || attribute === "linguist-generated=true")
10275
+ generated = true;
10276
+ else if (attribute === "-linguist-generated" || attribute === "!linguist-generated" || attribute.startsWith("linguist-generated="))
10277
+ generated = false;
10278
+ }
10279
+ if (generated === null)
10280
+ continue;
10281
+ const regex = patternRegex(dir, pattern);
10282
+ if (regex)
10283
+ out.push({ regex, generated });
10284
+ }
10285
+ return out;
10286
+ }
10287
+ function generatedByAttributes(files, paths) {
10288
+ const rules = [...files].map(([file, text]) => {
10289
+ const dir = file.includes("/") ? file.slice(0, file.lastIndexOf("/")) : "";
10290
+ return {
10291
+ depth: dir ? dir.split("/").length : 0,
10292
+ rules: rulesOf(dir, text)
10293
+ };
10294
+ }).toSorted((left, right) => left.depth - right.depth).flatMap((entry) => entry.rules);
10295
+ const out = new Set;
10296
+ for (const file of paths) {
10297
+ const last = rules.findLast((rule) => rule.regex.test(file));
10298
+ if (last?.generated)
10299
+ out.add(file);
10300
+ }
10301
+ return out;
10302
+ }
10303
+
10304
+ // packages/workit-core/src/core/policy/substance.ts
10305
+ function substanceOf(file, text) {
10306
+ const syntax = syntaxOf(file);
10307
+ if (!syntax)
10308
+ return plainSubstance(text);
10309
+ const markup = syntax.block.some(([open]) => open === "<!--");
10310
+ if (markup && (/<(?:script|style)\b|<!\[CDATA\[|<\?/iu.test(text) || /[^>\s][ \t]*<!--/u.test(text)))
10311
+ return plainSubstance(text);
10312
+ return lex(syntax, text);
10313
+ }
10314
+ function plainSubstance(text) {
10315
+ return text.split(`
10316
+ `).map((line) => line.replace(/[ \t\r\f\v]+$/u, "")).filter(Boolean).join(`
10317
+ `);
10318
+ }
10319
+ function lex(syntax, text) {
10320
+ const collapse = !syntax.indented;
10321
+ let out = "";
10322
+ let lineStart = 0;
10323
+ let kept = 0;
10324
+ let pendingSpace = false;
10325
+ const frames = [{ kind: "code", braces: 0 }];
10326
+ let index = 0;
10327
+ if (text.startsWith("#!")) {
10328
+ const end = text.indexOf(`
10329
+ `);
10330
+ out = end < 0 ? text : text.slice(0, end);
10331
+ kept = out.length;
10332
+ index = end < 0 ? text.length : end;
10333
+ }
10334
+ const emitCode = (chunk) => {
10335
+ if (collapse && pendingSpace && out.length > lineStart) {
10336
+ const before = out[out.length - 1];
10337
+ if (!NO_SPACE_AFTER.includes(before) && !NO_SPACE_BEFORE.includes(chunk[0]))
10338
+ out += " ";
10339
+ }
10340
+ pendingSpace = false;
10341
+ out += chunk;
10342
+ };
10343
+ const emitVerbatim = (chunk) => {
10344
+ emitCode(chunk);
10345
+ kept = out.length;
10346
+ };
10347
+ const newline = () => {
10348
+ if (!collapse) {
10349
+ let end = out.length;
10350
+ while (end > Math.max(lineStart, kept) && SPACE.test(out[end - 1]))
10351
+ end -= 1;
10352
+ out = out.slice(0, end);
10353
+ }
10354
+ pendingSpace = false;
10355
+ if (out.length > lineStart) {
10356
+ out += `
10357
+ `;
10358
+ lineStart = out.length;
10359
+ }
10360
+ };
10361
+ const regexAllowed = () => {
10362
+ let end = out.length;
10363
+ while (end > 0 && /\s/u.test(out[end - 1]))
10364
+ end -= 1;
10365
+ if (end === 0 || REGEX_AFTER.includes(out[end - 1]))
10366
+ return true;
10367
+ let start = end;
10368
+ while (start > 0 && WORD.test(out[start - 1]))
10369
+ start -= 1;
10370
+ return REGEX_KEYWORDS.has(out.slice(start, end));
10371
+ };
10372
+ const scanString = (quote, escapes, multiline) => {
10373
+ const prefix = text.slice(Math.max(0, index - 2), index).match(/[a-z]*$/iu)?.[0] ?? "";
10374
+ const fstring = syntax.fstring === true && /f/iu.test(prefix);
10375
+ let end = index + quote.length;
10376
+ while (end < text.length) {
10377
+ const char = text[end];
10378
+ if (escapes && char === "\\") {
10379
+ end += 2;
10380
+ continue;
10381
+ }
10382
+ if (text.startsWith(quote, end)) {
10383
+ if (fstring && unbalanced(text.slice(index + quote.length, end)))
10384
+ return false;
10385
+ emitVerbatim(text.slice(index, end + quote.length));
10386
+ index = end + quote.length;
10387
+ return true;
10388
+ }
10389
+ if (char === `
10390
+ ` && !multiline)
10391
+ return false;
10392
+ end += 1;
10393
+ }
10394
+ return false;
10395
+ };
10396
+ while (index < text.length) {
10397
+ const frame = frames[frames.length - 1];
10398
+ const char = text[index];
10399
+ if (frame.kind === "template") {
10400
+ if (char === "\\") {
10401
+ emitVerbatim(text.slice(index, index + 2));
10402
+ index += 2;
10403
+ } else if (char === "`") {
10404
+ emitVerbatim(char);
10405
+ frames.pop();
10406
+ index += 1;
10407
+ } else if (text.startsWith("${", index)) {
10408
+ emitVerbatim("${");
10409
+ frames.push({ kind: "code", braces: 0 });
10410
+ index += 2;
10411
+ } else {
10412
+ out += char;
10413
+ kept = out.length;
10414
+ index += 1;
10415
+ }
10416
+ continue;
10417
+ }
10418
+ if (char === `
10419
+ `) {
10420
+ newline();
10421
+ index += 1;
10422
+ continue;
10423
+ }
10424
+ if (SPACE.test(char)) {
10425
+ if (collapse)
10426
+ pendingSpace = true;
10427
+ else
10428
+ out += char;
10429
+ index += 1;
10430
+ continue;
10431
+ }
10432
+ const lineOpener = syntax.line.find((opener) => text.startsWith(opener, index));
10433
+ if (lineOpener) {
10434
+ const end = text.indexOf(`
10435
+ `, index);
10436
+ const comment = text.slice(index, end < 0 ? text.length : end);
10437
+ if (DIRECTIVE.test(comment.slice(lineOpener.length)))
10438
+ emitVerbatim(comment);
10439
+ else
10440
+ pendingSpace = true;
10441
+ index = end < 0 ? text.length : end;
10442
+ continue;
10443
+ }
10444
+ const block = syntax.block.find(([open]) => text.startsWith(open, index));
10445
+ if (block) {
10446
+ const end = text.indexOf(block[1], index + block[0].length);
10447
+ if (end < 0)
10448
+ return null;
10449
+ const comment = text.slice(index, end + block[1].length);
10450
+ if (DIRECTIVE.test(comment.slice(block[0].length, -block[1].length)))
10451
+ emitVerbatim(comment);
10452
+ else
10453
+ pendingSpace = true;
10454
+ if (comment.includes(`
10455
+ `))
10456
+ newline();
10457
+ index = end + block[1].length;
10458
+ continue;
10459
+ }
10460
+ if (syntax.triple && (char === '"' || char === "'") && text.startsWith(char.repeat(3), index)) {
10461
+ if (!scanString(char.repeat(3), !syntax.literal?.includes(char), true))
10462
+ return null;
10463
+ continue;
10464
+ }
10465
+ if (syntax.quotes.includes(char)) {
10466
+ if (!scanString(char, true, Boolean(syntax.multiline)))
10467
+ return null;
10468
+ continue;
10469
+ }
10470
+ if (syntax.literal?.includes(char)) {
10471
+ if (!scanString(char, false, false))
10472
+ return null;
10473
+ continue;
10474
+ }
10475
+ if (syntax.rawBacktick && char === "`") {
10476
+ if (!scanString("`", false, true))
10477
+ return null;
10478
+ continue;
10479
+ }
10480
+ if (syntax.js && char === "`") {
10481
+ emitVerbatim(char);
10482
+ frames.push({ kind: "template" });
10483
+ index += 1;
10484
+ continue;
10485
+ }
10486
+ if (syntax.cssUrl && /^url\(\s*[^"')\s]/iu.test(text.slice(index, index + 64)))
10487
+ return null;
10488
+ if (syntax.js && char === "/" && !regexAllowed() && out.trimEnd().endsWith(")")) {
10489
+ const lineEnd = text.indexOf(`
10490
+ `, index);
10491
+ if (text.slice(index + 1, lineEnd < 0 ? text.length : lineEnd).includes("/"))
10492
+ return null;
10493
+ }
10494
+ if (syntax.js && char === "/" && regexAllowed()) {
10495
+ let end = index + 1;
10496
+ let inClass = false;
10497
+ while (end < text.length && (inClass || text[end] !== "/")) {
10498
+ if (text[end] === `
10499
+ `)
10500
+ return null;
10501
+ if (text[end] === "\\")
10502
+ end += 1;
10503
+ else if (text[end] === "[")
10504
+ inClass = true;
10505
+ else if (text[end] === "]")
10506
+ inClass = false;
10507
+ end += 1;
10508
+ }
10509
+ if (end >= text.length)
10510
+ return null;
10511
+ emitVerbatim(text.slice(index, end + 1));
10512
+ index = end + 1;
10513
+ continue;
10514
+ }
10515
+ if (frames.length > 1 && frame.kind === "code") {
10516
+ if (char === "{")
10517
+ frame.braces += 1;
10518
+ else if (char === "}") {
10519
+ if (frame.braces === 0) {
10520
+ emitVerbatim(char);
10521
+ frames.pop();
10522
+ index += 1;
10523
+ continue;
10524
+ }
10525
+ frame.braces -= 1;
10526
+ }
10527
+ }
10528
+ emitCode(char);
10529
+ index += 1;
10530
+ }
10531
+ if (frames.length !== 1)
10532
+ return null;
10533
+ newline();
10534
+ return out;
10535
+ }
10536
+ function unbalanced(body) {
10537
+ let depth = 0;
10538
+ for (const part of body.replaceAll("{{", "").replaceAll("}}", "")) {
10539
+ if (part === "{")
10540
+ depth += 1;
10541
+ else if (part === "}")
10542
+ depth = Math.max(0, depth - 1);
10543
+ }
10544
+ return depth > 0;
10545
+ }
10546
+ function hasOpaqueLineBreak(text) {
10547
+ return /\r(?!\n)|[\u2028\u2029]/u.test(text);
10548
+ }
10549
+ function textOf(bytes) {
10550
+ if (bytes.includes(0))
10551
+ return null;
10552
+ try {
10553
+ return decoder.decode(bytes);
10554
+ } catch {
10555
+ return null;
10556
+ }
10557
+ }
10558
+ function cosmeticChange(file, before, after) {
10559
+ const left = textOf(before);
10560
+ const right = textOf(after);
10561
+ if (left === null || right === null)
10562
+ return false;
10563
+ if (hasOpaqueLineBreak(left) || hasOpaqueLineBreak(right))
10564
+ return false;
10565
+ const a = substanceOf(file, left);
10566
+ return a !== null && a === substanceOf(file, right);
10567
+ }
10568
+ var SLASH_BLOCK, C_LIKE, SYNTAXES, DIRECTIVE, extensionOf = (file) => {
10569
+ const name = file.slice(file.lastIndexOf("/") + 1);
10570
+ const dot = name.lastIndexOf(".");
10571
+ return dot > 0 ? name.slice(dot + 1).toLowerCase() : "";
10572
+ }, CI_PATH, syntaxOf = (file) => CI_PATH.test(file) ? null : SYNTAXES[extensionOf(file)] ?? null, SPACE, WORD, NO_SPACE_AFTER = "([{,;", NO_SPACE_BEFORE = ")]},;", REGEX_AFTER = "(,=:[!&|?{};+-*%<>~^", REGEX_KEYWORDS, decoder;
10573
+ var init_substance = __esm(() => {
10574
+ SLASH_BLOCK = [["/*", "*/"]];
10575
+ C_LIKE = { line: ["//"], block: SLASH_BLOCK, quotes: `"'` };
10576
+ SYNTAXES = Object.fromEntries([
10577
+ ...["ts", "mts", "cts", "js", "mjs", "cjs"].map((ext) => [ext, { ...C_LIKE, js: true }]),
10578
+ ...["java", "kt", "kts", "scala", "swift", "dart", "groovy"].map((ext) => [
10579
+ ext,
10580
+ { ...C_LIKE, triple: true }
10581
+ ]),
10582
+ ["go", { ...C_LIKE, rawBacktick: true }],
10583
+ ...["css", "scss", "less"].map((ext) => [
10584
+ ext,
10585
+ { line: [], block: SLASH_BLOCK, quotes: `"'`, cssUrl: true }
10586
+ ]),
10587
+ ...["py", "pyi"].map((ext) => [
10588
+ ext,
10589
+ { line: ["#"], block: [], quotes: `"'`, triple: true, indented: true, fstring: true }
10590
+ ]),
10591
+ ["toml", { line: ["#"], block: [], quotes: `"`, literal: "'", triple: true }],
10592
+ ...["html", "htm", "xml", "svg", "xhtml"].map((ext) => [
10593
+ ext,
10594
+ { line: [], block: [["<!--", "-->"]], quotes: "", indented: true }
10595
+ ])
10596
+ ]);
10597
+ DIRECTIVE = /@ts-|eslint|prettier|biome|oxlint|istanbul|\bc8\b|\bv8\b|@jsx|@flow|@vite|webpack|__PURE__|__NO_SIDE_EFFECTS__|source(?:Mapping)?URL|^\/\s*<|go:|\+build|nolint|noqa|type:|pyright|mypy|pylint|pragma|coding[:=]|fmt:|NOSONAR|@license|@preserve|@refresh|environment|language=|cython|ruff|isort|deno-|@vitest|@jest|swiftlint|ktlint|checkstyle|suppress|nullable|#(?:end)?region/iu;
10598
+ CI_PATH = /^\.github\/|(?:^|\/)(?:\.gitlab-ci\.ya?ml|Jenkinsfile|azure-pipelines\.ya?ml|\.pre-commit-config\.ya?ml|\.circleci\/.*)$/u;
10599
+ SPACE = /[ \t\r\f\v]/u;
10600
+ WORD = /[\w$]/u;
10601
+ REGEX_KEYWORDS = new Set([
10602
+ "return",
10603
+ "typeof",
10604
+ "instanceof",
10605
+ "case",
10606
+ "do",
10607
+ "else",
10608
+ "in",
10609
+ "of",
10610
+ "new",
10611
+ "delete",
10612
+ "void",
10613
+ "throw",
10614
+ "yield",
10615
+ "await"
10616
+ ]);
10617
+ decoder = new TextDecoder("utf-8", { fatal: true });
10618
+ });
10619
+
10620
+ // packages/workit-core/src/core/policy/lane.ts
10621
+ import { existsSync as existsSync2, readFileSync as readFileSync3 } from "node:fs";
10073
10622
  import path10 from "node:path";
10623
+ function kindOf(file) {
10624
+ if (file.binary)
10625
+ return "behavior";
10626
+ if (file.generated)
10627
+ return "generated";
10628
+ if (LOCKFILES.has(basename(file.path)))
10629
+ return "lockfile";
10630
+ if (isDoc(file.path))
10631
+ return "doc";
10632
+ if (file.cosmetic)
10633
+ return "cosmetic";
10634
+ return TEST_PATH.test(file.path) ? "test" : "behavior";
10635
+ }
10636
+ function globMatch(pattern, file) {
10637
+ let regex = globCache.get(pattern);
10638
+ if (!regex) {
10639
+ let source = "";
10640
+ for (let index = 0;index < pattern.length; index += 1) {
10641
+ const char = pattern[index];
10642
+ if (char === "*" && pattern[index + 1] === "*") {
10643
+ source += pattern[index + 2] === "/" ? "(?:[^/]*/)*" : ".*";
10644
+ index += pattern[index + 2] === "/" ? 2 : 1;
10645
+ } else if (char === "*")
10646
+ source += "[^/]*";
10647
+ else if (char === "?")
10648
+ source += "[^/]";
10649
+ else
10650
+ source += char.replace(/[.+^${}()|[\]\\]/gu, "\\$&");
10651
+ }
10652
+ regex = new RegExp(`^${source}$`, "u");
10653
+ globCache.set(pattern, regex);
10654
+ }
10655
+ return regex.test(file) || file.startsWith(`${pattern.replace(/\/$/u, "")}/`);
10656
+ }
10657
+ function isRiskPath(file, extra = []) {
10658
+ if (extra.some((pattern) => globMatch(pattern, file)))
10659
+ return true;
10660
+ if (RISK_FILES.has(file) || RISK_NAMES.has(basename(file)))
10661
+ return true;
10662
+ if (TEST_PATH.test(file) || isDoc(file))
10663
+ return false;
10664
+ return file.split("/").map((segment, index, all) => index === all.length - 1 ? segment.replace(/\.[^.]+$/u, "") : segment).some((segment) => segment.toLowerCase().split(/[-_.]/u).some((token) => RISK_TOKENS.has(token)));
10665
+ }
10666
+ function computeLane(input) {
10667
+ const riskFiles = input.files.filter((file) => isRiskPath(file.path, input.riskPaths)).map((file) => file.path);
10668
+ const risky = new Set(riskFiles);
10669
+ const kinds = input.files.map((file) => ({
10670
+ file,
10671
+ kind: risky.has(file.path) ? "behavior" : kindOf(file)
10672
+ }));
10673
+ const behavior = kinds.filter((entry) => entry.kind === "behavior" || entry.kind === "test" || entry.kind === "lockfile");
10674
+ const lines = behavior.filter((entry) => entry.kind !== "lockfile").reduce((sum, entry) => sum + entry.file.added + entry.file.deleted, 0);
10675
+ const opaque = behavior.filter((entry) => entry.kind === "lockfile" || entry.file.binary);
10676
+ const result = (lane, reasons) => ({
10677
+ lane,
10678
+ reasons,
10679
+ lines,
10680
+ files: behavior.length,
10681
+ riskFiles
10682
+ });
10683
+ const { selfMaxLines, selfMaxFiles, fullMinLines } = LANE_THRESHOLDS;
10684
+ if (input.riskTier === "high")
10685
+ return result("full", ["the task judgment records high risk"]);
10686
+ if (riskFiles.length)
10687
+ return result("full", [
10688
+ `touches a risk path: ${riskFiles.slice(0, 3).join(", ")}${riskFiles.length > 3 ? ", …" : ""}`
10689
+ ]);
10690
+ if (!behavior.length)
10691
+ return result("none", [
10692
+ input.files.length ? "only docs, comments, formatting or generated copies changed" : "no changes"
10693
+ ]);
10694
+ if (lines >= fullMinLines)
10695
+ return result("full", [`large diff: ${lines} lines (≥ ${fullMinLines})`]);
10696
+ if (lines > selfMaxLines)
10697
+ return result("focused", [`${lines} lines changed (> ${selfMaxLines})`]);
10698
+ if (behavior.length > selfMaxFiles)
10699
+ return result("focused", [`${behavior.length} behavior files changed (> ${selfMaxFiles})`]);
10700
+ if (opaque.length)
10701
+ return result("focused", [
10702
+ `a lockfile or binary changed: ${opaque.slice(0, 3).map((entry) => entry.file.path).join(", ")}${opaque.length > 3 ? ", …" : ""}`
10703
+ ]);
10704
+ return result("self", [
10705
+ `small change: ${lines} line${lines === 1 ? "" : "s"} in ${behavior.length} file${behavior.length === 1 ? "" : "s"}, no risk path`
10706
+ ]);
10707
+ }
10708
+ function untrackedStat(cwd, file) {
10709
+ try {
10710
+ const bytes = readFileSync3(path10.join(cwd, file));
10711
+ if (bytes.includes(0))
10712
+ return { path: file, added: 0, deleted: 0, binary: true };
10713
+ const text = bytes.toString("utf8");
10714
+ if (hasOpaqueLineBreak(text))
10715
+ return { path: file, added: 0, deleted: 0, binary: true };
10716
+ const lines = text.split(`
10717
+ `).length - (text.endsWith(`
10718
+ `) ? 1 : 0);
10719
+ return { path: file, added: lines, deleted: 0 };
10720
+ } catch {
10721
+ return { path: file, added: 0, deleted: 0, binary: true };
10722
+ }
10723
+ }
10724
+ function cosmeticFiles(cwd, fork, head) {
10725
+ const raw = diffRaw(cwd, fork, head);
10726
+ if (!raw)
10727
+ return null;
10728
+ const candidates = raw.filter((entry) => REGULAR.has(entry.oldMode) && entry.oldMode === entry.newMode && !ABSENT.test(entry.oldBlob) && (head === null || !ABSENT.test(entry.newBlob)));
10729
+ const blobs = readBlobs(cwd, candidates.flatMap((entry) => [entry.oldBlob, entry.newBlob]));
10730
+ if (!blobs)
10731
+ return null;
10732
+ const out = new Set;
10733
+ const opaque = new Set;
10734
+ for (const entry of candidates) {
10735
+ const before = blobs.get(entry.oldBlob);
10736
+ let after = blobs.get(entry.newBlob);
10737
+ if (!after && head === null && ABSENT.test(entry.newBlob))
10738
+ try {
10739
+ after = readFileSync3(path10.join(cwd, entry.path));
10740
+ } catch {
10741
+ after = undefined;
10742
+ }
10743
+ if (before && after && cosmeticChange(entry.path, before, after))
10744
+ out.add(entry.path);
10745
+ else if ([before, after].some((bytes) => bytes && hasOpaqueLineBreak(bytes.toString("utf8"))))
10746
+ opaque.add(entry.path);
10747
+ }
10748
+ return { cosmetic: out, opaque };
10749
+ }
10750
+ function generatedAt(cwd, fork, paths) {
10751
+ const files = treeFilesNamed(cwd, fork, ".gitattributes");
10752
+ const blobs = files?.size ? readBlobs(cwd, [...files.values()]) : null;
10753
+ if (!files || !blobs)
10754
+ return new Set;
10755
+ const texts = new Map;
10756
+ for (const [file, id] of files) {
10757
+ const bytes = blobs.get(id);
10758
+ if (bytes)
10759
+ texts.set(file, bytes.toString("utf8"));
10760
+ }
10761
+ return generatedByAttributes(texts, paths);
10762
+ }
10763
+ function laneFiles(cwd, fork, head) {
10764
+ const stats = diffNumstat(cwd, fork, head);
10765
+ const cosmetic = stats ? cosmeticFiles(cwd, fork, head) : null;
10766
+ if (!stats || !cosmetic)
10767
+ return null;
10768
+ const files = [
10769
+ ...stats.map((entry) => ({
10770
+ ...entry,
10771
+ ...cosmetic.opaque.has(entry.path) ? { binary: true } : {},
10772
+ cosmetic: !entry.binary && cosmetic.cosmetic.has(entry.path)
10773
+ })),
10774
+ ...head === null ? untrackedFiles(cwd).map((file) => untrackedStat(cwd, file)) : []
10775
+ ];
10776
+ const generated = generatedAt(cwd, fork, files.map((entry) => entry.path));
10777
+ return files.map((entry) => ({
10778
+ ...entry,
10779
+ generated: generated.has(entry.path)
10780
+ }));
10781
+ }
10782
+ function branchLane(cwd, options) {
10783
+ const candidates = options.base ? [`origin/${options.base}`, options.base] : [];
10784
+ const base = candidates.find((ref) => resolveRef(cwd, ref) !== null) ?? defaultBase(cwd) ?? null;
10785
+ const head = options.workingTree ? null : options.head;
10786
+ const fork = base && (options.workingTree || options.head) ? forkOf(cwd, base, head) : null;
10787
+ const files = fork ? laneFiles(cwd, fork, head) : null;
10788
+ const riskTier = options.judgment?.riskTier ?? null;
10789
+ if (!fork || !files) {
10790
+ const high = riskTier === "high";
10791
+ return {
10792
+ lane: high ? "full" : "focused",
10793
+ reasons: [
10794
+ `the diff of ${options.head?.slice(0, 12) ?? "(no head)"} against ${base ?? "(no base)"} cannot be read`,
10795
+ ...high ? ["the task judgment records high risk"] : []
10796
+ ],
10797
+ lines: 0,
10798
+ files: 0,
10799
+ riskFiles: [],
10800
+ base,
10801
+ head: options.head
10802
+ };
10803
+ }
10804
+ const repoRisk = parseRiskPaths(fileAt(cwd, fork, RISK_PATHS_FILE) ?? "");
10805
+ return {
10806
+ ...computeLane({
10807
+ files,
10808
+ riskTier,
10809
+ riskPaths: [...repoRisk, ...options.riskPaths ?? []]
10810
+ }),
10811
+ base,
10812
+ head: options.head
10813
+ };
10814
+ }
10815
+ var LANE_THRESHOLDS, RISK_TOKENS, RISK_FILES, RISK_NAMES, RISK_PATHS_FILE = ".workit/risk-paths", LOCKFILES, DOC_EXT, DOC_NAMES, INSTRUCTIONS, TEST_PATH, basename = (file) => file.slice(file.lastIndexOf("/") + 1), isDoc = (file) => !INSTRUCTIONS.test(file) && (DOC_EXT.test(file) || DOC_NAMES.test(basename(file))), globCache, parseRiskPaths = (text) => text.split(`
10816
+ `).map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map((line) => line.replace(/^\//u, "")), REGULAR, ABSENT, forkOf = (cwd, base, head) => mergeBase(cwd, base, head ?? "HEAD"), laneNeed = (lane) => lane === "none" ? "none" : lane === "self" ? "self" : "non-author";
10817
+ var init_lane = __esm(() => {
10818
+ init_rev();
10819
+ init_ops();
10820
+ init_ledger();
10821
+ init_substance();
10822
+ LANE_THRESHOLDS = {
10823
+ selfMaxLines: 100,
10824
+ selfMaxFiles: 5,
10825
+ fullMinLines: 500
10826
+ };
10827
+ RISK_TOKENS = new Set([
10828
+ "auth",
10829
+ "authn",
10830
+ "authz",
10831
+ "oauth",
10832
+ "security",
10833
+ "permission",
10834
+ "permissions",
10835
+ "secret",
10836
+ "secrets",
10837
+ "crypto",
10838
+ "gate",
10839
+ "gates",
10840
+ "policy",
10841
+ "policies",
10842
+ "hook",
10843
+ "hooks",
10844
+ "husky",
10845
+ "lefthook",
10846
+ "release",
10847
+ "releases",
10848
+ "migration",
10849
+ "migrations",
10850
+ "migrate",
10851
+ "workflows"
10852
+ ]);
10853
+ RISK_FILES = new Set([
10854
+ ".gitlab-ci.yml",
10855
+ "Jenkinsfile",
10856
+ "azure-pipelines.yml",
10857
+ ".pre-commit-config.yaml",
10858
+ ".workit/risk-paths"
10859
+ ]);
10860
+ RISK_NAMES = new Set([".gitattributes"]);
10861
+ LOCKFILES = new Set([
10862
+ "bun.lock",
10863
+ "bun.lockb",
10864
+ "package-lock.json",
10865
+ "npm-shrinkwrap.json",
10866
+ "yarn.lock",
10867
+ "pnpm-lock.yaml",
10868
+ "Cargo.lock",
10869
+ "go.sum",
10870
+ "poetry.lock",
10871
+ "uv.lock",
10872
+ "Pipfile.lock",
10873
+ "Gemfile.lock",
10874
+ "composer.lock"
10875
+ ]);
10876
+ DOC_EXT = /\.(?:md|mdx|markdown|rst|adoc|txt)$/iu;
10877
+ DOC_NAMES = /^(?:license|licence|notice|authors|changelog|changes|contributors)$/iu;
10878
+ INSTRUCTIONS = /(?:^|\/)(?:AGENTS|CLAUDE|GEMINI|SKILL)\.md$|(?:^|\/)(?:skills|agents|commands|rules|prompts)\/[^/]+/iu;
10879
+ TEST_PATH = /(?:^|\/)(?:test|tests|__tests__|spec|specs|fixtures)\/|\.(?:test|spec)\.[^/]+$/iu;
10880
+ globCache = new Map;
10881
+ REGULAR = new Set(["100644", "100755"]);
10882
+ ABSENT = /^0+$/u;
10883
+ });
10884
+
10885
+ // packages/workit-core/src/core/policy/derive.ts
10886
+ import { existsSync as existsSync3 } from "node:fs";
10887
+ import path11 from "node:path";
10074
10888
  function deriveRequirements(judgment, scope, constraints, verification = "self") {
10075
10889
  const out = [];
10076
10890
  const base = { scope, dependentAction: null };
10891
+ const proportional = verification === "proportional";
10077
10892
  if (judgment.behaviorChange)
10078
10893
  out.push(derived2({
10079
10894
  ...base,
@@ -10084,7 +10899,17 @@ function deriveRequirements(judgment, scope, constraints, verification = "self")
10084
10899
  before: "close",
10085
10900
  acceptanceAllowed: false
10086
10901
  }));
10087
- if (judgment.behaviorChange && judgment.riskTier === "normal")
10902
+ if (proportional && judgment.riskTier === "normal")
10903
+ out.push(derived2({
10904
+ ...base,
10905
+ ruleId: RULES.lane,
10906
+ dimension: "review",
10907
+ reason: "The review lane computed from the diff decides the verdict: none needs none, self the author's own (shown as self-reviewed), focused and full a non-author one.",
10908
+ satisfaction: "Read the lane in `workit policy assess` or `workit pr status`; record what it asks: `workit ledger verdict tests-verified --self --how <what you ran>` for self, or hand focused and full to a verifier.",
10909
+ before: "close",
10910
+ acceptanceAllowed: false
10911
+ }));
10912
+ if (!proportional && judgment.behaviorChange && judgment.riskTier === "normal")
10088
10913
  out.push(verification === "independent" ? derived2({
10089
10914
  ...base,
10090
10915
  ruleId: RULES.nonAuthor,
@@ -10163,7 +10988,9 @@ function derivedRuleStatus(task, requirement, root, ledger) {
10163
10988
  case RULES.self:
10164
10989
  case RULES.nonAuthor:
10165
10990
  case RULES.verified:
10166
- return verdict(requirement, root, ledger);
10991
+ return verdict(requirement.ruleId, root, ledger);
10992
+ case RULES.lane:
10993
+ return laneVerdict(task, root, ledger);
10167
10994
  default:
10168
10995
  return null;
10169
10996
  }
@@ -10222,7 +11049,7 @@ var RULES, derived2 = (spec) => ({
10222
11049
  decisionIds: []
10223
11050
  };
10224
11051
  }, planRecorded = (task, root) => {
10225
- const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync2(path10.resolve(root, ref.path)));
11052
+ const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync3(path11.resolve(root, ref.path)));
10226
11053
  if (cited)
10227
11054
  return {
10228
11055
  met: true,
@@ -10235,14 +11062,28 @@ var RULES, derived2 = (spec) => ({
10235
11062
  reason: "no plan recorded: write it (docs/ and Markdown writes stay allowed), then `workit policy assess --ref <path>`",
10236
11063
  decisionIds: []
10237
11064
  };
10238
- }, verdict = (requirement, root, ledger) => {
11065
+ }, workingLane = (task, root) => branchLane(root, { head: null, workingTree: true, judgment: latestJudgment(task) }), laneVerdict = (task, root, ledger) => {
11066
+ if (!ledger.branch() && latestJudgment(task)?.behaviorChange === false)
11067
+ return {
11068
+ met: true,
11069
+ reason: "no branch to read a lane from, and the judgment records no behavior change",
11070
+ decisionIds: []
11071
+ };
11072
+ const lane = workingLane(task, root);
11073
+ const label = `lane ${lane.lane} (${lane.reasons.join("; ")})`;
11074
+ const need = laneNeed(lane.lane);
11075
+ if (need === "none")
11076
+ return { met: true, reason: `${label}: no verdict needed`, decisionIds: [] };
11077
+ const status = verdict(need === "self" ? RULES.self : RULES.nonAuthor, root, ledger);
11078
+ return { ...status, reason: `${label}: ${status.reason}` };
11079
+ }, verdict = (ruleId, root, ledger) => {
10239
11080
  const branch = ledger.branch();
10240
11081
  if (!branch)
10241
11082
  return { met: false, reason: "no branch is checked out to hold a verdict", decisionIds: [] };
10242
11083
  const check = checkVerdicts(root, branch, ledger.rows());
10243
11084
  const failing = check.accepted.reasons.includes("failing_verdict");
10244
11085
  const strong = (entry) => STRONG_RESULTS.has(String(entry.verdict.result));
10245
- const met = !failing && (requirement.ruleId === RULES.verified ? check.verdicts.find((entry) => entry.accepted && entry.kind === "live" && String(entry.verdict.result) === "verified") : requirement.ruleId === RULES.nonAuthor ? check.verdicts.find((entry) => entry.accepted && strong(entry)) : check.verdicts.find((entry) => entry.current && strong(entry)));
11086
+ const met = !failing && (ruleId === RULES.verified ? check.verdicts.find((entry) => entry.accepted && entry.kind === "live" && String(entry.verdict.result) === "verified") : ruleId === RULES.nonAuthor ? check.verdicts.find((entry) => entry.accepted && strong(entry)) : check.verdicts.find((entry) => entry.current && strong(entry)));
10246
11087
  if (met)
10247
11088
  return {
10248
11089
  met: true,
@@ -10250,18 +11091,20 @@ var RULES, derived2 = (spec) => ({
10250
11091
  decisionIds: []
10251
11092
  };
10252
11093
  const why = failing ? "a current independent verdict fails" : check.verdicts.some((entry) => entry.current && entry.verdict.result === "type-check-only") ? "type-check-only does not prove a behavior change" : (check.accepted.reasons.join(", ") || "no_verdict").replace(/_/g, " ");
10253
- const unblock = requirement.ruleId === RULES.self ? "record your own verdict after an observed `workit check test`: `workit ledger verdict tests-verified --self --how <what you ran>` (shown as self-reviewed), or have a verifier record one" : `an independent session records \`workit ledger verdict verified${requirement.ruleId === RULES.verified ? " --kind live" : ""} --how <what it exercised>\``;
11094
+ const unblock = ruleId === RULES.self ? "record your own verdict after an observed `workit check test`: `workit ledger verdict tests-verified --self --how <what you ran>` (shown as self-reviewed), or have a verifier record one" : `an independent session records \`workit ledger verdict verified${ruleId === RULES.verified ? " --kind live" : ""} --how <what it exercised>\``;
10254
11095
  return { met: false, reason: `${why}: ${unblock}`, decisionIds: [] };
10255
11096
  };
10256
11097
  var init_derive = __esm(() => {
10257
11098
  init_rev();
10258
11099
  init_ledger();
11100
+ init_lane();
10259
11101
  init_task_contract();
10260
11102
  RULES = {
10261
11103
  test: "check:test",
10262
11104
  self: "verdict:self",
10263
11105
  nonAuthor: "verdict:non-author",
10264
11106
  verified: "verdict:verified",
11107
+ lane: "verdict:lane",
10265
11108
  product: "decision:product",
10266
11109
  plan: "plan"
10267
11110
  };
@@ -10819,7 +11662,7 @@ var init_safe_write = () => {};
10819
11662
 
10820
11663
  // packages/workit-core/src/autonomy.ts
10821
11664
  import os4 from "node:os";
10822
- import path11 from "node:path";
11665
+ import path12 from "node:path";
10823
11666
  function endpointOf(entry) {
10824
11667
  const raw = entry?.defaultEndpoint;
10825
11668
  if (raw === undefined)
@@ -10916,10 +11759,13 @@ var accountHome = () => {
10916
11759
  } catch {
10917
11760
  return os4.homedir();
10918
11761
  }
10919
- }, grantsHome, grantsDir = () => path11.join(grantsHome.resolve(), ".config", "workit"), grantsOverride = () => {
10920
- const configured = path11.resolve(resolveConfigDir());
10921
- return configured === path11.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 ${path11.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
10922
- }, GRANT_KINDS, DEFAULT_GRANTS, DEFAULT_ENDPOINTS, DEFAULT_ENDPOINT = "commit", isDefaultEndpoint = (value) => typeof value === "string" && DEFAULT_ENDPOINTS.includes(value), DEFAULT_VERIFICATION = "self", verificationOf = (entry) => entry?.verification === "independent" ? "independent" : "self", isGrantValue = (value) => value === true || value === false || value === "verified", normalized = (kind, value) => value === "verified" && kind !== "merge" ? true : value, fromAutoApprove = (value) => {
11762
+ }, grantsHome, grantsDir = () => path12.join(grantsHome.resolve(), ".config", "workit"), grantsOverride = () => {
11763
+ const configured = path12.resolve(resolveConfigDir());
11764
+ return configured === path12.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 ${path12.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
11765
+ }, GRANT_KINDS, DEFAULT_GRANTS, DEFAULT_ENDPOINTS, DEFAULT_ENDPOINT = "commit", isDefaultEndpoint = (value) => typeof value === "string" && DEFAULT_ENDPOINTS.includes(value), VERIFICATION_MODES, DEFAULT_VERIFICATION = "proportional", verificationOf = (entry) => {
11766
+ const value = entry?.verification;
11767
+ return VERIFICATION_MODES.includes(value) ? value : DEFAULT_VERIFICATION;
11768
+ }, isGrantValue = (value) => value === true || value === false || value === "verified", normalized = (kind, value) => value === "verified" && kind !== "merge" ? true : value, fromAutoApprove = (value) => {
10923
11769
  if (value === true)
10924
11770
  return { push: true, pr: true, merge: "verified" };
10925
11771
  if (!Array.isArray(value))
@@ -10946,6 +11792,11 @@ var init_autonomy = __esm(() => {
10946
11792
  rerun: true
10947
11793
  });
10948
11794
  DEFAULT_ENDPOINTS = ["commit", "pr", "green", "merged"];
11795
+ VERIFICATION_MODES = [
11796
+ "proportional",
11797
+ "self",
11798
+ "independent"
11799
+ ];
10949
11800
  });
10950
11801
 
10951
11802
  // node_modules/@openclaw/fs-safe/dist/errors.js
@@ -11058,7 +11909,7 @@ var init_read_open_flags = () => {};
11058
11909
  // node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.js
11059
11910
  import { randomBytes as randomBytes3 } from "node:crypto";
11060
11911
  import fsSync from "node:fs";
11061
- import path12 from "node:path";
11912
+ import path13 from "node:path";
11062
11913
  function parseSidecarLockSnapshot(snapshot, parser) {
11063
11914
  return snapshot && { ...snapshot, payload: parseSidecarLockPayload(snapshot.raw, parser) };
11064
11915
  }
@@ -11086,13 +11937,13 @@ ${ownershipToken}
11086
11937
  return { raw, ownershipToken };
11087
11938
  }
11088
11939
  function relativeSidecarLockPath(lockRoot, lockPath) {
11089
- const resolved = path12.resolve(lockPath);
11090
- const lexicalRelative = path12.relative(lockRoot.rootDir, resolved);
11091
- const relative = lexicalRelative !== ".." && !lexicalRelative.startsWith(`..${path12.sep}`) && !path12.isAbsolute(lexicalRelative) ? lexicalRelative : path12.relative(lockRoot.rootReal, resolved);
11092
- if (!relative || relative === ".." || relative.startsWith(`..${path12.sep}`) || path12.isAbsolute(relative)) {
11940
+ const resolved = path13.resolve(lockPath);
11941
+ const lexicalRelative = path13.relative(lockRoot.rootDir, resolved);
11942
+ const relative = lexicalRelative !== ".." && !lexicalRelative.startsWith(`..${path13.sep}`) && !path13.isAbsolute(lexicalRelative) ? lexicalRelative : path13.relative(lockRoot.rootReal, resolved);
11943
+ if (!relative || relative === ".." || relative.startsWith(`..${path13.sep}`) || path13.isAbsolute(relative)) {
11093
11944
  throw new FsSafeError("outside-workspace", "sidecar lock path is outside lockRoot");
11094
11945
  }
11095
- return relative.split(path12.sep).join(path12.posix.sep);
11946
+ return relative.split(path13.sep).join(path13.posix.sep);
11096
11947
  }
11097
11948
  function parseSidecarLockPayload(raw, parser) {
11098
11949
  if (parser) {
@@ -11262,7 +12113,7 @@ function sleepSync(ms) {
11262
12113
 
11263
12114
  // node_modules/@openclaw/fs-safe/dist/file-lock-sync.js
11264
12115
  import fs10 from "node:fs";
11265
- import path13 from "node:path";
12116
+ import path14 from "node:path";
11266
12117
  function getSyncHeldLocks() {
11267
12118
  const globalWithState = globalThis;
11268
12119
  if (!globalWithState[SYNC_HELD_LOCKS_KEY]) {
@@ -11340,26 +12191,26 @@ function canonicalLockParentSync(parent) {
11340
12191
  return process.platform === "win32" ? fs10.realpathSync.native(parent) : fs10.realpathSync(parent);
11341
12192
  }
11342
12193
  function normalizeTargetPath(targetPath) {
11343
- const resolved = path13.resolve(targetPath);
11344
- fs10.mkdirSync(path13.dirname(resolved), { recursive: true });
12194
+ const resolved = path14.resolve(targetPath);
12195
+ fs10.mkdirSync(path14.dirname(resolved), { recursive: true });
11345
12196
  try {
11346
- return path13.join(canonicalLockParentSync(path13.dirname(resolved)), path13.basename(resolved));
12197
+ return path14.join(canonicalLockParentSync(path14.dirname(resolved)), path14.basename(resolved));
11347
12198
  } catch {
11348
12199
  return resolved;
11349
12200
  }
11350
12201
  }
11351
12202
  function boundedLockPath(lockPath, lockRoot) {
11352
- const resolved = path13.resolve(lockPath);
12203
+ const resolved = path14.resolve(lockPath);
11353
12204
  if (!lockRoot)
11354
12205
  return resolved;
11355
12206
  relativeSidecarLockPath(lockRoot, resolved);
11356
- const parent = path13.dirname(resolved);
12207
+ const parent = path14.dirname(resolved);
11357
12208
  const parentReal = canonicalLockParentSync(parent);
11358
- const parentRelative = path13.relative(lockRoot.rootReal, parentReal);
11359
- if (parentRelative === ".." || parentRelative.startsWith(`..${path13.sep}`) || path13.isAbsolute(parentRelative)) {
12209
+ const parentRelative = path14.relative(lockRoot.rootReal, parentReal);
12210
+ if (parentRelative === ".." || parentRelative.startsWith(`..${path14.sep}`) || path14.isAbsolute(parentRelative)) {
11360
12211
  throw new FsSafeError("outside-workspace", "sidecar lock parent is outside lockRoot");
11361
12212
  }
11362
- return path13.join(parentReal, path13.basename(resolved));
12213
+ return path14.join(parentReal, path14.basename(resolved));
11363
12214
  }
11364
12215
  function defaultShouldReclaim(snapshot, staleMs, nowMs) {
11365
12216
  const createdAtMs = sidecarLockPayloadCreatedAtMs(snapshot.payload);
@@ -11575,14 +12426,14 @@ var init_file_lock = __esm(() => {
11575
12426
  });
11576
12427
 
11577
12428
  // packages/workit-core/src/core/package-root.ts
11578
- import { existsSync as existsSync3 } from "node:fs";
11579
- import path14 from "node:path";
12429
+ import { existsSync as existsSync4 } from "node:fs";
12430
+ import path15 from "node:path";
11580
12431
  import { fileURLToPath } from "node:url";
11581
12432
  var packageRoot = () => {
11582
- let dir = path14.dirname(fileURLToPath(import.meta.url));
12433
+ let dir = path15.dirname(fileURLToPath(import.meta.url));
11583
12434
  while (true) {
11584
- const parent = path14.dirname(dir);
11585
- if (existsSync3(path14.join(dir, "package.json")) || parent === dir)
12435
+ const parent = path15.dirname(dir);
12436
+ if (existsSync4(path15.join(dir, "package.json")) || parent === dir)
11586
12437
  return dir;
11587
12438
  dir = parent;
11588
12439
  }
@@ -11592,7 +12443,7 @@ var init_package_root = () => {};
11592
12443
  // packages/workit-core/src/store/event-log.ts
11593
12444
  import { randomUUID as randomUUID2 } from "node:crypto";
11594
12445
  import fs11 from "node:fs";
11595
- import path15 from "node:path";
12446
+ import path16 from "node:path";
11596
12447
  function readLog(file, from = 0, expectSeq = null) {
11597
12448
  let fd;
11598
12449
  try {
@@ -11665,7 +12516,7 @@ function appendEvent(file, event, validEnd) {
11665
12516
  fs11.closeSync(fd);
11666
12517
  }
11667
12518
  if (created)
11668
- fsyncDirectory(path15.dirname(file));
12519
+ fsyncDirectory(path16.dirname(file));
11669
12520
  return validEnd;
11670
12521
  }
11671
12522
  function replaceFile(file, bytes, durable) {
@@ -11681,7 +12532,7 @@ function replaceFile(file, bytes, durable) {
11681
12532
  }
11682
12533
  renameWithRetry(temporary, file);
11683
12534
  if (durable)
11684
- fsyncDirectory(path15.dirname(file));
12535
+ fsyncDirectory(path16.dirname(file));
11685
12536
  } catch (error) {
11686
12537
  try {
11687
12538
  fs11.unlinkSync(temporary);
@@ -11991,7 +12842,7 @@ var init_notes = __esm(() => {
11991
12842
  // packages/workit-core/src/core/task-store.ts
11992
12843
  import { createHash as createHash11, randomUUID as randomUUID3 } from "node:crypto";
11993
12844
  import * as fs12 from "node:fs";
11994
- import path16 from "node:path";
12845
+ import path17 from "node:path";
11995
12846
 
11996
12847
  class TaskStore {
11997
12848
  root;
@@ -12003,7 +12854,7 @@ class TaskStore {
12003
12854
  migrationChecked = false;
12004
12855
  compactDue = new Set;
12005
12856
  constructor(root, options = {}) {
12006
- const resolved = path16.resolve(root);
12857
+ const resolved = path17.resolve(root);
12007
12858
  this.origin = fs12.existsSync(resolved) ? fs12.realpathSync(resolved) : resolved;
12008
12859
  this.located = resolveStore(this.origin);
12009
12860
  this.root = checkoutRootOf(this.origin, this.located);
@@ -12012,7 +12863,7 @@ class TaskStore {
12012
12863
  this.migrateOnRead = options.migrateOnRead;
12013
12864
  }
12014
12865
  location() {
12015
- if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs12.existsSync(path16.join(this.root, ".git"))) {
12866
+ if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs12.existsSync(path17.join(this.root, ".git"))) {
12016
12867
  this.located = undefined;
12017
12868
  this.migrationChecked = false;
12018
12869
  }
@@ -12168,7 +13019,7 @@ class TaskStore {
12168
13019
  const moved = this.bindLocked(again.data.id, key, input.now);
12169
13020
  return moved.ok ? success(moved.data.revision, null, { task: moved.data, created: false, key }) : moved;
12170
13021
  }
12171
- const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path16.basename(this.root) || this.root;
13022
+ const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path17.basename(this.root) || this.root;
12172
13023
  const intent = {
12173
13024
  objective: input.objective?.trim() || `Work on ${label}`,
12174
13025
  scope: { description: `the checkout (${label})`, paths: ["."], exclusions: [] },
@@ -12234,14 +13085,14 @@ class TaskStore {
12234
13085
  const branch = key.ok ? key.data.branch : null;
12235
13086
  if (!branch || !location.ok)
12236
13087
  return success(null, null, null);
12237
- const common = path16.dirname(location.data.dir);
12238
- const heads = path16.join(common, "logs", "refs", "heads");
12239
- const headLog = location.data.git ? path16.join(location.data.git.gitDir, "logs", "HEAD") : "";
13088
+ const common = path17.dirname(location.data.dir);
13089
+ const heads = path17.join(common, "logs", "refs", "heads");
13090
+ const headLog = location.data.git ? path17.join(location.data.git.gitDir, "logs", "HEAD") : "";
12240
13091
  const signatures = [
12241
- path16.join(heads, branch),
13092
+ path17.join(heads, branch),
12242
13093
  headLog,
12243
13094
  heads,
12244
- path16.join(common, "packed-refs")
13095
+ path17.join(common, "packed-refs")
12245
13096
  ].map((file) => fileSignature(file) ?? "-");
12246
13097
  const slot = `${location.data.dir}\x00${headLog}\x00${branch}`;
12247
13098
  let resolved = origins.get(slot);
@@ -12253,7 +13104,7 @@ class TaskStore {
12253
13104
  aliases.push(rename.from);
12254
13105
  const start = branchStart(location.data, branch, aliases);
12255
13106
  const slash = start?.indexOf("/") ?? -1;
12256
- const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(path16.join(common, "config")).includes(`[remote "${start.slice(0, slash)}"]`));
13107
+ const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(path17.join(common, "config")).includes(`[remote "${start.slice(0, slash)}"]`));
12257
13108
  const name = start && (remote ? start.slice(slash + 1) : start);
12258
13109
  resolved = {
12259
13110
  signature: signatures.join("|"),
@@ -12491,13 +13342,13 @@ class TaskStore {
12491
13342
  if (!ready.ok)
12492
13343
  return ready;
12493
13344
  const dirs = this.paths();
12494
- const recovery = path16.join(this.root, ".workit", "recovery");
13345
+ const recovery = path17.join(this.root, ".workit", "recovery");
12495
13346
  if (fs12.existsSync(recovery)) {
12496
13347
  let files = 0;
12497
13348
  let bytes = 0;
12498
13349
  try {
12499
13350
  for (const name of fs12.readdirSync(recovery)) {
12500
- const stat = fs12.lstatSync(path16.join(recovery, name));
13351
+ const stat = fs12.lstatSync(path17.join(recovery, name));
12501
13352
  if (!stat.isFile())
12502
13353
  continue;
12503
13354
  files += 1;
@@ -12550,7 +13401,7 @@ class TaskStore {
12550
13401
  if (fs12.existsSync(dirs.blobs))
12551
13402
  for (const name of fs12.readdirSync(dirs.blobs)) {
12552
13403
  const digest = name.replace(/\.json$/, "");
12553
- const file = path16.join(dirs.blobs, name);
13404
+ const file = path17.join(dirs.blobs, name);
12554
13405
  let stat;
12555
13406
  try {
12556
13407
  stat = fs12.lstatSync(file);
@@ -12568,7 +13419,7 @@ class TaskStore {
12568
13419
  }
12569
13420
  return success(null, null, null);
12570
13421
  };
12571
- const swept = dryRun ? sweep() : this.withLock(path16.join(dirs.dir, "gc.lock"), sweep);
13422
+ const swept = dryRun ? sweep() : this.withLock(path17.join(dirs.dir, "gc.lock"), sweep);
12572
13423
  if (!swept.ok)
12573
13424
  return swept;
12574
13425
  const temporaryDirs = [
@@ -12576,7 +13427,7 @@ class TaskStore {
12576
13427
  dirs.tasks,
12577
13428
  dirs.blobs,
12578
13429
  dirs.checkout,
12579
- ...names.map((name) => path16.join(dirs.tasks, name))
13430
+ ...names.map((name) => path17.join(dirs.tasks, name))
12580
13431
  ];
12581
13432
  for (const directory of temporaryDirs) {
12582
13433
  if (!fs12.existsSync(directory))
@@ -12584,7 +13435,7 @@ class TaskStore {
12584
13435
  for (const name of fs12.readdirSync(directory)) {
12585
13436
  if (!name.endsWith(".tmp") && !name.endsWith(".probe"))
12586
13437
  continue;
12587
- const file = path16.join(directory, name);
13438
+ const file = path17.join(directory, name);
12588
13439
  try {
12589
13440
  const stat = fs12.lstatSync(file);
12590
13441
  if (!stat.isFile() || nowMs - stat.mtimeMs <= STALE_TEMPORARY_MS)
@@ -12601,30 +13452,30 @@ class TaskStore {
12601
13452
  }
12602
13453
  paths() {
12603
13454
  const location = this.location();
12604
- const dir = location.ok ? location.data.dir : path16.join(this.root, ".workit");
12605
- const checkout = path16.join(dir, "checkouts", checkoutSlug(this.root));
13455
+ const dir = location.ok ? location.data.dir : path17.join(this.root, ".workit");
13456
+ const checkout = path17.join(dir, "checkouts", checkoutSlug(this.root));
12606
13457
  return {
12607
13458
  dir,
12608
13459
  shared: location.ok ? location.data.shared : false,
12609
- marker: path16.join(dir, "store.json"),
13460
+ marker: path17.join(dir, "store.json"),
12610
13461
  checkout,
12611
- workspace: path16.join(checkout, "workspace.json"),
12612
- checkoutLock: path16.join(checkout, "metadata.lock"),
12613
- tasks: path16.join(dir, "tasks"),
12614
- index: path16.join(dir, "task-index.json"),
12615
- blobs: path16.join(dir, "blobs", "candidates"),
12616
- legacy: path16.join(dir, "legacy", checkoutSlug(this.root), "v2"),
12617
- v2: path16.join(this.root, ".workit")
13462
+ workspace: path17.join(checkout, "workspace.json"),
13463
+ checkoutLock: path17.join(checkout, "metadata.lock"),
13464
+ tasks: path17.join(dir, "tasks"),
13465
+ index: path17.join(dir, "task-index.json"),
13466
+ blobs: path17.join(dir, "blobs", "candidates"),
13467
+ legacy: path17.join(dir, "legacy", checkoutSlug(this.root), "v2"),
13468
+ v2: path17.join(this.root, ".workit")
12618
13469
  };
12619
13470
  }
12620
13471
  eventsPath(taskId) {
12621
- return path16.join(this.paths().tasks, taskId, "events.jsonl");
13472
+ return path17.join(this.paths().tasks, taskId, "events.jsonl");
12622
13473
  }
12623
13474
  snapshotPath(taskId) {
12624
- return path16.join(this.paths().tasks, taskId, "snapshot.json");
13475
+ return path17.join(this.paths().tasks, taskId, "snapshot.json");
12625
13476
  }
12626
13477
  taskLockPath(taskId) {
12627
- return path16.join(this.paths().tasks, taskId, "lock");
13478
+ return path17.join(this.paths().tasks, taskId, "lock");
12628
13479
  }
12629
13480
  ready(write = false) {
12630
13481
  const location = this.location();
@@ -12663,13 +13514,13 @@ class TaskStore {
12663
13514
  return {
12664
13515
  read: (digest) => {
12665
13516
  try {
12666
- return JSON.parse(fs12.readFileSync(path16.join(dir, `${digest}.json`), "utf8"));
13517
+ return JSON.parse(fs12.readFileSync(path17.join(dir, `${digest}.json`), "utf8"));
12667
13518
  } catch (error) {
12668
13519
  throw new LogDamage(`stored candidate ${digest} is missing or unreadable: ${String(error)}`);
12669
13520
  }
12670
13521
  },
12671
13522
  write: (digest, value) => {
12672
- const file = path16.join(dir, `${digest}.json`);
13523
+ const file = path17.join(dir, `${digest}.json`);
12673
13524
  if (fs12.existsSync(file)) {
12674
13525
  const stamp = new Date;
12675
13526
  try {
@@ -12861,7 +13712,7 @@ class TaskStore {
12861
13712
  }
12862
13713
  }
12863
13714
  openTask(record, type, key, legacy = null) {
12864
- const dir = path16.join(this.paths().tasks, record.id);
13715
+ const dir = path17.join(this.paths().tasks, record.id);
12865
13716
  fs12.mkdirSync(dir, { recursive: true });
12866
13717
  const blobs = this.blobStore();
12867
13718
  const bound = key ? { ...key, boundAt: key.boundAt ?? new Date().toISOString() } : null;
@@ -12954,7 +13805,7 @@ class TaskStore {
12954
13805
  }
12955
13806
  withKeyLock(key, operation) {
12956
13807
  const digest = createHash11("sha256").update(key).digest("hex").slice(0, 32);
12957
- return this.withLock(path16.join(this.paths().dir, "keys", `${digest}.lock`), operation);
13808
+ return this.withLock(path17.join(this.paths().dir, "keys", `${digest}.lock`), operation);
12958
13809
  }
12959
13810
  bindLocked(taskId, key, timestamp) {
12960
13811
  const current = this.readWorkspace();
@@ -13095,7 +13946,7 @@ class TaskStore {
13095
13946
  writeWorkspace(record) {
13096
13947
  const file = this.paths().workspace;
13097
13948
  try {
13098
- fs12.mkdirSync(path16.dirname(file), { recursive: true });
13949
+ fs12.mkdirSync(path17.dirname(file), { recursive: true });
13099
13950
  replaceFile(file, `${canonicalJson(record)}
13100
13951
  `, true);
13101
13952
  return success(null, null, null);
@@ -13173,23 +14024,23 @@ class TaskStore {
13173
14024
  return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", { expectedWorkspaceRevision: expected, actualWorkspaceRevision: actual });
13174
14025
  }
13175
14026
  v2Dirs() {
13176
- return [...new Set([this.root, this.origin])].map((dir) => path16.join(dir, ".workit"));
14027
+ return [...new Set([this.root, this.origin])].map((dir) => path17.join(dir, ".workit"));
13177
14028
  }
13178
14029
  pendingMigrations() {
13179
14030
  return this.v2Dirs().filter((dir) => {
13180
- const raw = this.readV2Workspace(path16.join(dir, "workspace.json"));
14031
+ const raw = this.readV2Workspace(path17.join(dir, "workspace.json"));
13181
14032
  return raw !== null && raw !== TOMBSTONE;
13182
14033
  });
13183
14034
  }
13184
14035
  migrateV2(v2) {
13185
14036
  const dirs = this.paths();
13186
- const v2Workspace = path16.join(v2, "workspace.json");
13187
- const v2Tasks = path16.join(v2, "tasks");
13188
- const legacy = path16.join(dirs.dir, "legacy", checkoutSlug(path16.dirname(v2)), "v2");
14037
+ const v2Workspace = path17.join(v2, "workspace.json");
14038
+ const v2Tasks = path17.join(v2, "tasks");
14039
+ const legacy = path17.join(dirs.dir, "legacy", checkoutSlug(path17.dirname(v2)), "v2");
13189
14040
  const raw = this.readV2Workspace(v2Workspace);
13190
14041
  if (raw === null || raw === TOMBSTONE)
13191
14042
  return success(null, null, null);
13192
- return this.withLock(dirs.checkoutLock, () => this.withLock(path16.join(v2, "metadata.lock"), () => {
14043
+ return this.withLock(dirs.checkoutLock, () => this.withLock(path17.join(v2, "metadata.lock"), () => {
13193
14044
  const workspace = this.readV2Workspace(v2Workspace);
13194
14045
  if (workspace === null || workspace === TOMBSTONE)
13195
14046
  return success(null, null, null);
@@ -13198,7 +14049,7 @@ class TaskStore {
13198
14049
  return failure2("recovery_required", `cannot migrate the 2.x store at ${v2}: ${parsedWorkspace.error}; move it aside to start fresh`, { path: v2Workspace });
13199
14050
  let files = [];
13200
14051
  try {
13201
- files = fs12.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path16.join(v2Tasks, name)));
14052
+ files = fs12.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path17.join(v2Tasks, name)));
13202
14053
  } catch {}
13203
14054
  const current = this.readWorkspace();
13204
14055
  if (!current.ok)
@@ -13216,21 +14067,21 @@ class TaskStore {
13216
14067
  let skipped = 0;
13217
14068
  const done = new Map;
13218
14069
  try {
13219
- fs12.mkdirSync(path16.join(legacy, "tasks"), { recursive: true });
14070
+ fs12.mkdirSync(path17.join(legacy, "tasks"), { recursive: true });
13220
14071
  for (const name of ["workspace.json", "index.json"])
13221
- if (fs12.existsSync(path16.join(v2, name)))
13222
- fs12.copyFileSync(path16.join(v2, name), path16.join(legacy, name));
14072
+ if (fs12.existsSync(path17.join(v2, name)))
14073
+ fs12.copyFileSync(path17.join(v2, name), path17.join(legacy, name));
13223
14074
  for (const name of files) {
13224
14075
  const id = name.slice(0, -5);
13225
- const file = path16.join(v2Tasks, name);
14076
+ const file = path17.join(v2Tasks, name);
13226
14077
  const bytes = fs12.readFileSync(file, "utf8");
13227
14078
  const digest = sha256(bytes);
13228
- fs12.writeFileSync(path16.join(legacy, "tasks", name), bytes);
14079
+ fs12.writeFileSync(path17.join(legacy, "tasks", name), bytes);
13229
14080
  const parsed = this.parseRecord(bytes, taskRecordSchema, "2.x task");
13230
14081
  if (!parsed.ok || parsed.data.id !== id)
13231
14082
  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 });
13232
14083
  const record = { ...parsed.data, workspaceId: target.id };
13233
- const origin = { path: path16.join(legacy, "tasks", name), digest };
14084
+ const origin = { path: path17.join(legacy, "tasks", name), digest };
13234
14085
  if (!fs12.existsSync(this.eventsPath(id))) {
13235
14086
  this.openTask(record, "migrated.from_v2", null, origin);
13236
14087
  migrated += 1;
@@ -13266,7 +14117,7 @@ class TaskStore {
13266
14117
  try {
13267
14118
  let complete = true;
13268
14119
  for (const [name, digest] of done) {
13269
- const file = path16.join(v2Tasks, name);
14120
+ const file = path17.join(v2Tasks, name);
13270
14121
  if (sha256(fs12.readFileSync(file, "utf8")) !== digest) {
13271
14122
  complete = false;
13272
14123
  continue;
@@ -13277,7 +14128,7 @@ class TaskStore {
13277
14128
  return failure2("busy", `the 2.x store at ${v2} changed during migration; retry`, {
13278
14129
  path: v2
13279
14130
  });
13280
- fs12.rmSync(path16.join(v2, "index.json"), { force: true });
14131
+ fs12.rmSync(path17.join(v2, "index.json"), { force: true });
13281
14132
  this.writeTombstone(v2, target.id);
13282
14133
  } catch (error) {
13283
14134
  return failure2("storage_error", `cannot finish the 2.x migration: ${String(error)}`, {
@@ -13297,7 +14148,7 @@ class TaskStore {
13297
14148
  }
13298
14149
  adoptLocalStore() {
13299
14150
  const dirs = this.paths();
13300
- const marker = path16.join(dirs.v2, "store.json");
14151
+ const marker = path17.join(dirs.v2, "store.json");
13301
14152
  if (!dirs.shared || !fs12.existsSync(marker))
13302
14153
  return success(null, null, null);
13303
14154
  return this.withLock(dirs.checkoutLock, () => {
@@ -13307,7 +14158,7 @@ class TaskStore {
13307
14158
  try {
13308
14159
  const merge = (from, to) => {
13309
14160
  if (!fs12.existsSync(to)) {
13310
- fs12.mkdirSync(path16.dirname(to), { recursive: true });
14161
+ fs12.mkdirSync(path17.dirname(to), { recursive: true });
13311
14162
  try {
13312
14163
  fs12.renameSync(from, to);
13313
14164
  } catch {
@@ -13318,24 +14169,24 @@ class TaskStore {
13318
14169
  }
13319
14170
  if (fs12.lstatSync(from).isDirectory() && fs12.lstatSync(to).isDirectory())
13320
14171
  for (const name of fs12.readdirSync(from))
13321
- merge(path16.join(from, name), path16.join(to, name));
14172
+ merge(path17.join(from, name), path17.join(to, name));
13322
14173
  };
13323
14174
  for (const sub of ["tasks", "checkouts", "blobs", "legacy"]) {
13324
- const from = path16.join(dirs.v2, sub);
14175
+ const from = path17.join(dirs.v2, sub);
13325
14176
  if (!fs12.existsSync(from))
13326
14177
  continue;
13327
14178
  if (sub === "tasks") {
13328
14179
  for (const name of fs12.readdirSync(from))
13329
- if (validId(name) && !fs12.existsSync(path16.join(dirs.dir, sub, name)))
14180
+ if (validId(name) && !fs12.existsSync(path17.join(dirs.dir, sub, name)))
13330
14181
  tasks += 1;
13331
14182
  }
13332
- merge(from, path16.join(dirs.dir, sub));
14183
+ merge(from, path17.join(dirs.dir, sub));
13333
14184
  }
13334
- const ledger = path16.join(dirs.v2, "ledger");
13335
- if (fs12.existsSync(ledger) && !fs12.existsSync(path16.join(dirs.dir, "ledger")))
13336
- merge(ledger, path16.join(dirs.dir, "ledger"));
13337
- fs12.rmSync(path16.join(dirs.v2, "task-index.json"), { force: true });
13338
- fs12.renameSync(marker, path16.join(dirs.v2, "store.moved.json"));
14185
+ const ledger = path17.join(dirs.v2, "ledger");
14186
+ if (fs12.existsSync(ledger) && !fs12.existsSync(path17.join(dirs.dir, "ledger")))
14187
+ merge(ledger, path17.join(dirs.dir, "ledger"));
14188
+ fs12.rmSync(path17.join(dirs.v2, "task-index.json"), { force: true });
14189
+ fs12.renameSync(marker, path17.join(dirs.v2, "store.moved.json"));
13339
14190
  } catch (error) {
13340
14191
  return failure2("storage_error", `cannot move ${dirs.v2} into ${dirs.dir}: ${String(error)}`, {
13341
14192
  path: dirs.v2
@@ -13373,7 +14224,7 @@ class TaskStore {
13373
14224
  schemaVersion: SCHEMA_VERSION,
13374
14225
  id: workspaceId ?? newId(),
13375
14226
  revision: newRevision(),
13376
- root: path16.dirname(v2),
14227
+ root: path17.dirname(v2),
13377
14228
  runtime: { createdWith: version, updatedWith: version },
13378
14229
  writer: null,
13379
14230
  store: {
@@ -13385,11 +14236,11 @@ class TaskStore {
13385
14236
  critical: ["store"]
13386
14237
  };
13387
14238
  fs12.mkdirSync(v2, { recursive: true });
13388
- const ignore = path16.join(v2, ".gitignore");
14239
+ const ignore = path17.join(v2, ".gitignore");
13389
14240
  if (!fs12.existsSync(ignore))
13390
14241
  fs12.writeFileSync(ignore, `*
13391
14242
  `);
13392
- replaceFile(path16.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
14243
+ replaceFile(path17.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
13393
14244
  `, true);
13394
14245
  }
13395
14246
  stubFor(taskId) {
@@ -13413,8 +14264,8 @@ class TaskStore {
13413
14264
  }
13414
14265
  writeTombstoneIfMissing() {
13415
14266
  try {
13416
- const v2 = path16.join(this.root, ".workit");
13417
- if (fs12.existsSync(path16.join(v2, "workspace.json")))
14267
+ const v2 = path17.join(this.root, ".workit");
14268
+ if (fs12.existsSync(path17.join(v2, "workspace.json")))
13418
14269
  return;
13419
14270
  let id = null;
13420
14271
  try {
@@ -13431,7 +14282,7 @@ class TaskStore {
13431
14282
  replaceFile(dirs.marker, `${JSON.stringify({ format: "workit-store", version: STORE_FORMAT, createdWith: runtimeVersion() })}
13432
14283
  `, false);
13433
14284
  if (!dirs.shared) {
13434
- const ignore = path16.join(dirs.dir, ".gitignore");
14285
+ const ignore = path17.join(dirs.dir, ".gitignore");
13435
14286
  let current = null;
13436
14287
  try {
13437
14288
  current = fs12.readFileSync(ignore, "utf8");
@@ -13491,7 +14342,7 @@ class TaskStore {
13491
14342
  withLock(lockPath, operation) {
13492
14343
  try {
13493
14344
  this.initializeStorage();
13494
- fs12.mkdirSync(path16.dirname(lockPath), { recursive: true });
14345
+ fs12.mkdirSync(path17.dirname(lockPath), { recursive: true });
13495
14346
  } catch (error) {
13496
14347
  return failure2("storage_error", `unable to initialize store: ${String(error)}`, {
13497
14348
  path: this.paths().dir
@@ -13554,7 +14405,7 @@ class TaskStore {
13554
14405
  if (isTransientWindowsError(error) && !this.lockHolderPresent(lockPath) && !this.lockDirWritable(lockPath))
13555
14406
  return failure2("storage_error", `cannot create the workit lock (${code}); no other Workit call holds it`, {
13556
14407
  path: lockPath,
13557
- guidance: `Check permissions and the read-only attribute on ${path16.dirname(lockPath)}.`
14408
+ guidance: `Check permissions and the read-only attribute on ${path17.dirname(lockPath)}.`
13558
14409
  });
13559
14410
  if (code === "EEXIST" || code === "file_lock_timeout" || code === "file_lock_stale" || isTransientWindowsError(error)) {
13560
14411
  let lock = null;
@@ -13612,7 +14463,7 @@ var MIGRATION_PENDING = "workit migration pending", STORE_FORMAT = 3, STORE_MIN_
13612
14463
  }, now = () => new Date().toISOString().replace(/\.\d{3}Z$/, "Z"), oldestFirst = (left, right) => left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id), cachedRuntimeVersion = null, runtimeVersion = () => {
13613
14464
  if (cachedRuntimeVersion === null) {
13614
14465
  try {
13615
- const pkg = JSON.parse(fs12.readFileSync(path16.join(packageRoot(), "package.json"), "utf8"));
14466
+ const pkg = JSON.parse(fs12.readFileSync(path17.join(packageRoot(), "package.json"), "utf8"));
13616
14467
  cachedRuntimeVersion = typeof pkg.version === "string" && pkg.version ? pkg.version : "0.0.0";
13617
14468
  } catch {
13618
14469
  cachedRuntimeVersion = "0.0.0";
@@ -13639,7 +14490,7 @@ var MIGRATION_PENDING = "workit migration pending", STORE_FORMAT = 3, STORE_MIN_
13639
14490
  return "";
13640
14491
  }
13641
14492
  }, REFLOG_LINE, branchStart = (location, branch, aliases) => {
13642
- const first = readText(path16.join(path16.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
14493
+ const first = readText(path17.join(path17.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
13643
14494
  `, 1)[0];
13644
14495
  const created = REFLOG_LINE.exec(first);
13645
14496
  const start = created && /^branch: Created from (\S+)$/u.exec(created[3])?.[1];
@@ -13649,7 +14500,7 @@ var MIGRATION_PENDING = "workit migration pending", STORE_FORMAT = 3, STORE_MIN_
13649
14500
  return start;
13650
14501
  if (!location.git)
13651
14502
  return null;
13652
- for (const line of readText(path16.join(location.git.gitDir, "logs", "HEAD")).split(`
14503
+ for (const line of readText(path17.join(location.git.gitDir, "logs", "HEAD")).split(`
13653
14504
  `)) {
13654
14505
  const entry = REFLOG_LINE.exec(line);
13655
14506
  const moved = entry && /^checkout: moving from (\S+) to (\S+)$/u.exec(entry[3]);
@@ -13658,12 +14509,12 @@ var MIGRATION_PENDING = "workit migration pending", STORE_FORMAT = 3, STORE_MIN_
13658
14509
  return moved[1];
13659
14510
  }
13660
14511
  return null;
13661
- }, refExists = (common, ref) => fs12.existsSync(path16.join(common, ref)) || readText(path16.join(common, "packed-refs")).includes(` ${ref}
14512
+ }, refExists = (common, ref) => fs12.existsSync(path17.join(common, ref)) || readText(path17.join(common, "packed-refs")).includes(` ${ref}
13662
14513
  `), origins, sameDirectoryIdentity = (left, right) => {
13663
- if (!path16.isAbsolute(left) || !path16.isAbsolute(right))
14514
+ if (!path17.isAbsolute(left) || !path17.isAbsolute(right))
13664
14515
  return false;
13665
- const normalizedLeft = path16.resolve(left);
13666
- const normalizedRight = path16.resolve(right);
14516
+ const normalizedLeft = path17.resolve(left);
14517
+ const normalizedRight = path17.resolve(right);
13667
14518
  try {
13668
14519
  const a = fs12.statSync(normalizedLeft, { bigint: true });
13669
14520
  const b = fs12.statSync(normalizedRight, { bigint: true });
@@ -13721,10 +14572,10 @@ var init_workers = __esm(() => {
13721
14572
  // packages/workit-core/src/check-config.ts
13722
14573
  import { spawnSync as spawnSync9 } from "node:child_process";
13723
14574
  import fs13 from "node:fs";
13724
- import path17 from "node:path";
14575
+ import path18 from "node:path";
13725
14576
  function checksConfigFile(root) {
13726
- const current = path17.join(root, CHECKS_FILE);
13727
- const legacy = path17.join(root, LEGACY_CHECKS_FILE);
14577
+ const current = path18.join(root, CHECKS_FILE);
14578
+ const legacy = path18.join(root, LEGACY_CHECKS_FILE);
13728
14579
  return !fs13.existsSync(current) && fs13.existsSync(legacy) ? legacy : current;
13729
14580
  }
13730
14581
  function repoHeavyCommands(root) {
@@ -13774,12 +14625,12 @@ function splitCommand(command) {
13774
14625
  return argv.length ? argv : new Error("empty command");
13775
14626
  }
13776
14627
  function checkRoot(cwd) {
13777
- return path17.resolve(git4(cwd, ["rev-parse", "--show-toplevel"]) ?? cwd);
14628
+ return path18.resolve(git5(cwd, ["rev-parse", "--show-toplevel"]) ?? cwd);
13778
14629
  }
13779
14630
  function detectedChecks(root) {
13780
14631
  const read = (file) => {
13781
14632
  try {
13782
- return fs13.readFileSync(path17.join(root, file), "utf8");
14633
+ return fs13.readFileSync(path18.join(root, file), "utf8");
13783
14634
  } catch {
13784
14635
  return null;
13785
14636
  }
@@ -13818,7 +14669,7 @@ function detectedChecks(root) {
13818
14669
  function loadCheckConfig(cwd) {
13819
14670
  const root = checkRoot(cwd);
13820
14671
  const file = checksConfigFile(root);
13821
- const legacy = path17.basename(file) === LEGACY_CHECKS_FILE;
14672
+ const legacy = path18.basename(file) === LEGACY_CHECKS_FILE;
13822
14673
  const label = legacy ? LEGACY_CHECKS_FILE : CHECKS_FILE;
13823
14674
  const note = legacy ? {
13824
14675
  note: `${LEGACY_CHECKS_FILE} is deprecated; move it to ${CHECKS_FILE} (workit doctor --fix)`
@@ -13894,10 +14745,10 @@ function workitAvailable(env = process.env) {
13894
14745
  return workitOnPath;
13895
14746
  const windows = process.platform === "win32";
13896
14747
  const exts = windows ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
13897
- const dirs = (env.PATH ?? env.Path ?? "").split(path17.delimiter).filter(Boolean);
14748
+ const dirs = (env.PATH ?? env.Path ?? "").split(path18.delimiter).filter(Boolean);
13898
14749
  workitOnPath = dirs.some((dir) => exts.some((ext) => {
13899
14750
  try {
13900
- return fs13.statSync(path17.join(dir, `workit${ext}`)).isFile();
14751
+ return fs13.statSync(path18.join(dir, `workit${ext}`)).isFile();
13901
14752
  } catch {
13902
14753
  return false;
13903
14754
  }
@@ -13907,7 +14758,7 @@ function workitAvailable(env = process.env) {
13907
14758
  function checkCommand(args, version, onPath = workitAvailable()) {
13908
14759
  return onPath ? `workit check ${args}` : `npx -y @brainervirus/workit-cli@${version} check ${args}`;
13909
14760
  }
13910
- var SCRIPT_CHECKS, CHECKS_FILE = ".workit/checks.json", LEGACY_CHECKS_FILE = "workit.checks.json", isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), SHELL_META, git4 = (cwd, args) => {
14761
+ var SCRIPT_CHECKS, CHECKS_FILE = ".workit/checks.json", LEGACY_CHECKS_FILE = "workit.checks.json", isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), SHELL_META, git5 = (cwd, args) => {
13911
14762
  const run = spawnSync9("git", args, {
13912
14763
  cwd,
13913
14764
  encoding: "utf8",
@@ -13918,7 +14769,7 @@ var SCRIPT_CHECKS, CHECKS_FILE = ".workit/checks.json", LEGACY_CHECKS_FILE = "wo
13918
14769
  const value = run.status === 0 ? (run.stdout ?? "").trim() : "";
13919
14770
  return value || null;
13920
14771
  }, packageManager = (root) => {
13921
- const has = (file) => fs13.existsSync(path17.join(root, file));
14772
+ const has = (file) => fs13.existsSync(path18.join(root, file));
13922
14773
  if (has("bun.lock") || has("bun.lockb"))
13923
14774
  return "bun";
13924
14775
  if (has("pnpm-lock.yaml"))
@@ -13944,7 +14795,7 @@ var init_check_config = __esm(() => {
13944
14795
  import { createHash as createHash12 } from "node:crypto";
13945
14796
  import * as fs14 from "node:fs";
13946
14797
  import { spawnSync as spawnSync10 } from "node:child_process";
13947
- import path18 from "node:path";
14798
+ import path19 from "node:path";
13948
14799
  function captureCandidate(root, scope, environment = []) {
13949
14800
  let checkout;
13950
14801
  try {
@@ -13986,7 +14837,7 @@ function captureCandidate(root, scope, environment = []) {
13986
14837
  for (const item of [...names].toSorted()) {
13987
14838
  if (!scopeMatches(item, normalizedScope))
13988
14839
  continue;
13989
- const target = path18.join(checkout, item);
14840
+ const target = path19.join(checkout, item);
13990
14841
  try {
13991
14842
  const stat = fs14.lstatSync(target);
13992
14843
  if (stat.isSymbolicLink()) {
@@ -14395,12 +15246,12 @@ function boundTaskSummary(summary) {
14395
15246
  brief.truncated = JSON.stringify(brief).includes("…") || progress.blockers.length > BRIEF_BLOCKERS || unmet.length > BRIEF_OPEN;
14396
15247
  return brief;
14397
15248
  }
14398
- var digestBytes = (value) => createHash12("sha256").update(value).digest("hex"), inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path18.sep}`), relative = (root, candidate) => path18.relative(root, candidate).split(path18.sep).join("/") || ".", canonicalPath = (value) => {
15249
+ var digestBytes = (value) => createHash12("sha256").update(value).digest("hex"), inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path19.sep}`), relative = (root, candidate) => path19.relative(root, candidate).split(path19.sep).join("/") || ".", canonicalPath = (value) => {
14399
15250
  if (typeof value !== "string" || !value)
14400
15251
  return null;
14401
15252
  if (value.includes("\\") || value.split("/").includes(".."))
14402
15253
  return null;
14403
- const normalized = path18.posix.normalize(value);
15254
+ const normalized = path19.posix.normalize(value);
14404
15255
  if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
14405
15256
  return null;
14406
15257
  return normalized === "." ? "." : normalized.replace(/\/$/, "");
@@ -14442,14 +15293,14 @@ var digestBytes = (value) => createHash12("sha256").update(value).digest("hex"),
14442
15293
  git: !/not a git repository/i.test(stderr)
14443
15294
  };
14444
15295
  }
14445
- const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path18.sep).join("/")) : [];
15296
+ const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path19.sep).join("/")) : [];
14446
15297
  const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
14447
15298
  if (stagedDeleted.status !== 0) {
14448
15299
  const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
14449
15300
  if (!/not a git repository/i.test(stderr))
14450
15301
  return { paths, uncertain: true, git: true };
14451
15302
  } else if (stagedDeleted.stdout) {
14452
- paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path18.sep).join("/")));
15303
+ paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path19.sep).join("/")));
14453
15304
  }
14454
15305
  return { paths: [...new Set(paths)], uncertain: false, git: true };
14455
15306
  }, walk = (root, directory, output) => {
@@ -14463,7 +15314,7 @@ var digestBytes = (value) => createHash12("sha256").update(value).digest("hex"),
14463
15314
  for (const name of names) {
14464
15315
  if (name === ".git" || name === ".workit")
14465
15316
  continue;
14466
- const target = path18.join(directory, name);
15317
+ const target = path19.join(directory, name);
14467
15318
  let stat;
14468
15319
  try {
14469
15320
  stat = fs14.lstatSync(target);
@@ -14480,12 +15331,12 @@ var digestBytes = (value) => createHash12("sha256").update(value).digest("hex"),
14480
15331
  }, scopeRoots = (root, scope) => {
14481
15332
  const roots = [];
14482
15333
  for (const item of scope.paths.length ? scope.paths : ["."]) {
14483
- const target = path18.resolve(root, item);
15334
+ const target = path19.resolve(root, item);
14484
15335
  if (!inside(root, target))
14485
15336
  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` }] });
14486
15337
  let ancestor = target;
14487
15338
  while (!fs14.existsSync(ancestor) && ancestor !== root)
14488
- ancestor = path18.dirname(ancestor);
15339
+ ancestor = path19.dirname(ancestor);
14489
15340
  try {
14490
15341
  if (!inside(root, fs14.realpathSync(ancestor)))
14491
15342
  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` }] });
@@ -14549,23 +15400,23 @@ var digestBytes = (value) => createHash12("sha256").update(value).digest("hex"),
14549
15400
  continue;
14550
15401
  if (!reference.digest)
14551
15402
  return failure2("invalid_input", "document references require a byte digest");
14552
- const target = path18.resolve(root, reference.path);
14553
- if (target !== root && !target.startsWith(`${root}${path18.sep}`))
15403
+ const target = path19.resolve(root, reference.path);
15404
+ if (target !== root && !target.startsWith(`${root}${path19.sep}`))
14554
15405
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
14555
15406
  fields: [
14556
15407
  { path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
14557
15408
  ]
14558
15409
  });
14559
15410
  try {
14560
- const below = path18.relative(root, target);
15411
+ const below = path19.relative(root, target);
14561
15412
  let current = root;
14562
- for (const segment of below.split(path18.sep)) {
15413
+ for (const segment of below.split(path19.sep)) {
14563
15414
  if (!segment)
14564
15415
  continue;
14565
- current = path18.join(current, segment);
15416
+ current = path19.join(current, segment);
14566
15417
  const stat = fs14.lstatSync(current);
14567
15418
  const real = fs14.realpathSync(current);
14568
- if (real !== root && !real.startsWith(`${root}${path18.sep}`))
15419
+ if (real !== root && !real.startsWith(`${root}${path19.sep}`))
14569
15420
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
14570
15421
  fields: [
14571
15422
  {
@@ -14693,9 +15544,9 @@ Autonomy contract:
14693
15544
  Prose is a note: only a configured check the CLI ran (\`workit check <name>\`)
14694
15545
  satisfies a gate; an ad-hoc \`workit check -- <cmd>\` never does.
14695
15546
  - Author is not verifier: your own verdict is \`--self\`, shown as
14696
- self-reviewed, never verified. High risk, \`verification: independent\` and
14697
- merge need a verifier with its own host-derived session (a subagent's
14698
- \`<lead>:<child>\`); never hand-mint one (\`<lead>-v1\`).
15547
+ self-reviewed, never verified. High risk, a focused or full lane and
15548
+ merge under \`verification: self|independent\` need a verifier with its
15549
+ own host-derived session (a subagent's \`<lead>:<child>\`); never hand-mint one (\`<lead>-v1\`).
14699
15550
  - A local-commit endpoint does not imply PR readiness, and a local commit alone
14700
15551
  is not evidence of a requested remote push. Before reporting delivery,
14701
15552
  reconcile every requested item and observe it (\`workit verify-delivery\`).
@@ -16566,7 +17417,7 @@ var support = (descriptor, axis) => {
16566
17417
  // packages/workit-core/src/hooks/context.ts
16567
17418
  import { createHash as createHash13 } from "node:crypto";
16568
17419
  import fs15 from "node:fs";
16569
- import path19 from "node:path";
17420
+ import path20 from "node:path";
16570
17421
  function sessionCompactContext(store, session, context, selection = "session-bound") {
16571
17422
  const listed = store.listTaskIndex();
16572
17423
  if (!listed.ok)
@@ -16601,7 +17452,7 @@ function entryCompactContext(store, entry, session, context) {
16601
17452
  return null;
16602
17453
  const freshness = { mode: "signal", current: () => recentSignal(store.root) };
16603
17454
  const observed = task?.data.evidence.some(isObservedCheck) ?? false;
16604
- const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [path19.resolve(store.root, ref.path)] : []));
17455
+ const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [path20.resolve(store.root, ref.path)] : []));
16605
17456
  const observedFiles = filesKey(files);
16606
17457
  const compact = new WorkitCore(store, context).compactContext(entry?.id ?? null, freshness, origin && { origin: origin.origin, taskId: origin.entry.id });
16607
17458
  if (!compact.ok || !compact.data)
@@ -16707,13 +17558,13 @@ ${options.addendum}` : ""}
16707
17558
  if (location instanceof Error)
16708
17559
  return null;
16709
17560
  const session = [input.host, input.session.id, input.session.agentId ?? ""].join("\x00");
16710
- return path19.join(location.dir, "hooks", `turn-${digestOf(session).slice(0, 32)}.json`);
17561
+ return path20.join(location.dir, "hooks", `turn-${digestOf(session).slice(0, 32)}.json`);
16711
17562
  } catch {
16712
17563
  return null;
16713
17564
  }
16714
17565
  }, writeTurnDigest = (file, digest) => {
16715
17566
  try {
16716
- fs15.mkdirSync(path19.dirname(file), { recursive: true });
17567
+ fs15.mkdirSync(path20.dirname(file), { recursive: true });
16717
17568
  fs15.writeFileSync(file, `${JSON.stringify({ digest })}
16718
17569
  `);
16719
17570
  } catch {}
@@ -16726,7 +17577,7 @@ ${options.addendum}` : ""}
16726
17577
  for (const name of fs15.readdirSync(dir)) {
16727
17578
  if (!name.startsWith("turn-"))
16728
17579
  continue;
16729
- const file = path19.join(dir, name);
17580
+ const file = path20.join(dir, name);
16730
17581
  try {
16731
17582
  if (now - fs15.statSync(file).mtimeMs > TURN_TTL_MS)
16732
17583
  fs15.rmSync(file, { force: true });
@@ -16754,7 +17605,7 @@ ${options.addendum}` : ""}
16754
17605
  const file = turnMarker(input);
16755
17606
  if (!file)
16756
17607
  return;
16757
- pruneTurnDigests(path19.dirname(file), Date.now());
17608
+ pruneTurnDigests(path20.dirname(file), Date.now());
16758
17609
  if (text)
16759
17610
  writeTurnDigest(file, digestOf(text));
16760
17611
  else
@@ -16776,7 +17627,7 @@ var init_context = __esm(() => {
16776
17627
  // packages/workit-core/src/hooks/session-marker.ts
16777
17628
  import { createHash as createHash14 } from "node:crypto";
16778
17629
  import fs16 from "node:fs";
16779
- import path20 from "node:path";
17630
+ import path21 from "node:path";
16780
17631
  var sessionMarkerFile = (input, session, store) => {
16781
17632
  let dir = store;
16782
17633
  if (dir === undefined) {
@@ -16786,7 +17637,7 @@ var sessionMarkerFile = (input, session, store) => {
16786
17637
  dir = location.dir;
16787
17638
  }
16788
17639
  const name = createHash14("sha256").update(`${input.host}\x00${session}`).digest("hex").slice(0, 32);
16789
- return path20.join(dir, "hooks", `skills-${name}.json`);
17640
+ return path21.join(dir, "hooks", `skills-${name}.json`);
16790
17641
  }, list2 = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [], EMPTY, readRaw = (file) => {
16791
17642
  try {
16792
17643
  return fs16.readFileSync(file, "utf8");
@@ -16807,7 +17658,7 @@ var sessionMarkerFile = (input, session, store) => {
16807
17658
  return { ...EMPTY };
16808
17659
  }
16809
17660
  }, readSessionMarker = (file) => parseMarker(readRaw(file)), writeAtomic = (file, marker) => {
16810
- fs16.mkdirSync(path20.dirname(file), { recursive: true });
17661
+ fs16.mkdirSync(path21.dirname(file), { recursive: true });
16811
17662
  const temp = `${file}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
16812
17663
  try {
16813
17664
  fs16.writeFileSync(temp, JSON.stringify(marker));
@@ -17277,7 +18128,7 @@ import { spawnSync as spawnSync11 } from "node:child_process";
17277
18128
  import { createHash as createHash15 } from "node:crypto";
17278
18129
  import fs17 from "node:fs";
17279
18130
  import os5 from "node:os";
17280
- import path21 from "node:path";
18131
+ import path22 from "node:path";
17281
18132
  function rawInvocations(command, dialect = "posix", depth = 0) {
17282
18133
  if (depth > 0)
17283
18134
  return walk2(command, dialect, depth);
@@ -17576,7 +18427,7 @@ function noteRawCommit(input, command, key) {
17576
18427
  if (action.kind !== "commit")
17577
18428
  continue;
17578
18429
  const file = markerFile(repo, input.session.id, key);
17579
- fs17.mkdirSync(path21.dirname(file), { recursive: true });
18430
+ fs17.mkdirSync(path22.dirname(file), { recursive: true });
17580
18431
  fs17.writeFileSync(file, `${JSON.stringify({ head: headSha2(repo), at })}
17581
18432
  `);
17582
18433
  }
@@ -17603,12 +18454,12 @@ function settlePendingCommit(input) {
17603
18454
  settle2(input, repo, file);
17604
18455
  } catch {}
17605
18456
  }
17606
- var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLARATIONS, SCRIPT_FLAG, CD, PUSHD, POPD, GIT_VALUE_OPTIONS, GIT_CONFIG_OPTIONS, GIT_CONFIG_ENV, ASSIGNMENT, MAX_DEPTH = 4, MAX_EXPANSIONS = 16, isAbsolute = (value) => path21.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\"), HERE, joinDir = (base, raw) => {
18457
+ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLARATIONS, SCRIPT_FLAG, CD, PUSHD, POPD, GIT_VALUE_OPTIONS, GIT_CONFIG_OPTIONS, GIT_CONFIG_ENV, ASSIGNMENT2, MAX_DEPTH = 4, MAX_EXPANSIONS = 16, isAbsolute = (value) => path22.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\"), HERE, joinDir = (base, raw) => {
17607
18458
  const next = raw.replace(HERE, ".");
17608
18459
  if (base === undefined || /[$`*?]/.test(next) || next === "-")
17609
18460
  return;
17610
- const expanded = next === "~" || next.startsWith("~/") ? path21.join(os5.homedir(), next.slice(1)) : next;
17611
- return base === null || isAbsolute(expanded) ? expanded : path21.join(base, expanded);
18461
+ const expanded = next === "~" || next.startsWith("~/") ? path22.join(os5.homedir(), next.slice(1)) : next;
18462
+ return base === null || isAbsolute(expanded) ? expanded : path22.join(base, expanded);
17612
18463
  }, rebase = (base, inner) => inner === null ? base : inner === undefined ? undefined : joinDir(base, inner), cdTarget = (words) => {
17613
18464
  const args = words.slice(1);
17614
18465
  const flag = args.findIndex((word) => /^-(?:literal)?path$/i.test(word));
@@ -17622,7 +18473,7 @@ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLA
17622
18473
  const first = words[0];
17623
18474
  if (first === undefined)
17624
18475
  return { words, env };
17625
- const assignment = ASSIGNMENT.exec(first);
18476
+ const assignment = ASSIGNMENT2.exec(first);
17626
18477
  if (assignment) {
17627
18478
  if (GIT_CONFIG_ENV.test(assignment[1]))
17628
18479
  env[assignment[1]] = assignment[2];
@@ -17676,10 +18527,10 @@ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLA
17676
18527
  while (rest[0]?.startsWith("-"))
17677
18528
  rest = rest.slice(1);
17678
18529
  }
17679
- if (rest.length === 0 || !rest.every((word) => ASSIGNMENT.test(word)))
18530
+ if (rest.length === 0 || !rest.every((word) => ASSIGNMENT2.test(word)))
17680
18531
  return null;
17681
18532
  return rest.map((word) => {
17682
- const [, name, value] = ASSIGNMENT.exec(word);
18533
+ const [, name, value] = ASSIGNMENT2.exec(word);
17683
18534
  return [name, expandWord(value, vars)];
17684
18535
  });
17685
18536
  }, literalOutput = (segment) => {
@@ -17844,7 +18695,7 @@ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLA
17844
18695
  return line.slice(index).join(" ").slice(15);
17845
18696
  if (/^-S./.test(word))
17846
18697
  return [word.slice(2), ...line.slice(index + 1)].join(" ");
17847
- if (!word.startsWith("-") && !ASSIGNMENT.test(word))
18698
+ if (!word.startsWith("-") && !ASSIGNMENT2.test(word))
17848
18699
  return null;
17849
18700
  }
17850
18701
  return null;
@@ -18096,17 +18947,17 @@ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLA
18096
18947
  if (!git || git.reftable)
18097
18948
  return null;
18098
18949
  try {
18099
- const head = fs17.readFileSync(path21.join(git.gitDir, "HEAD"), "utf8").trim();
18950
+ const head = fs17.readFileSync(path22.join(git.gitDir, "HEAD"), "utf8").trim();
18100
18951
  if (/^[0-9a-f]{40,64}$/.test(head))
18101
18952
  return head;
18102
18953
  const ref = /^ref: (refs\/.+)$/.exec(head)?.[1];
18103
18954
  if (!ref)
18104
18955
  return null;
18105
- const common = path21.dirname(repo.location.dir);
18956
+ const common = path22.dirname(repo.location.dir);
18106
18957
  try {
18107
- return fs17.readFileSync(path21.join(common, ref), "utf8").trim() || null;
18958
+ return fs17.readFileSync(path22.join(common, ref), "utf8").trim() || null;
18108
18959
  } catch {}
18109
- const packed = fs17.readFileSync(path21.join(common, "packed-refs"), "utf8");
18960
+ const packed = fs17.readFileSync(path22.join(common, "packed-refs"), "utf8");
18110
18961
  return new RegExp(`^([0-9a-f]{40,64}) ${ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`, "m").exec(packed)?.[1] ?? null;
18111
18962
  } catch {
18112
18963
  return null;
@@ -18172,7 +19023,7 @@ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLA
18172
19023
  const sub = invocation.args[0];
18173
19024
  if (invocation.tool !== "git" || invocation.dir === undefined || !sub || sub.startsWith("-") || GIT_COMMANDS.has(sub) || depth >= MAX_DEPTH)
18174
19025
  return [invocation];
18175
- const dir = path21.resolve(root, invocation.dir ?? ".");
19026
+ const dir = path22.resolve(root, invocation.dir ?? ".");
18176
19027
  if (!fs17.existsSync(dir))
18177
19028
  return [invocation];
18178
19029
  const config = gitConfig(dir, invocation, cache);
@@ -18194,11 +19045,11 @@ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLA
18194
19045
  }, normalizedUrl = (url, dir) => {
18195
19046
  const trimmed = url.trim();
18196
19047
  if (/^file:\/\//i.test(trimmed))
18197
- return path21.resolve(dir, trimmed.slice(7)).replace(/\/+$/, "").replace(/\.git$/, "");
19048
+ return path22.resolve(dir, trimmed.slice(7)).replace(/\/+$/, "").replace(/\.git$/, "");
18198
19049
  const scheme = /^[a-z][a-z0-9+.-]*:\/\//i.exec(trimmed);
18199
19050
  const scp = !scheme && /^(?:[^@/\\]+@)?[^/\\:]{2,}:/.test(trimmed);
18200
19051
  if (!scheme && !scp)
18201
- return path21.resolve(dir, trimmed).replace(/\/+$/, "").replace(/\.git$/, "");
19052
+ return path22.resolve(dir, trimmed).replace(/\/+$/, "").replace(/\.git$/, "");
18202
19053
  const value = scheme ? trimmed.slice(scheme[0].length).replace(/^[^@/]*@/, "").replace(/^([^/:]+):\d+(?=\/)/, "$1") : trimmed.replace(/^[^@/]*@/, "").replace(":", "/");
18203
19054
  return value.toLowerCase().replace(/\/{2,}/g, "/").replace(/^www\./, "").replace(/\/+$/, "").replace(/\.git$/, "");
18204
19055
  }, rewrittenUrl = (url, config) => {
@@ -18216,7 +19067,7 @@ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLA
18216
19067
  return best.base + url.slice(best.prefix.length);
18217
19068
  }
18218
19069
  return url;
18219
- }, pushUrl = (config, remote, dir) => {
19070
+ }, pushUrl2 = (config, remote, dir) => {
18220
19071
  const configured = configValue(config, `remote.${remote}.pushurl`) ?? configValue(config, `remote.${remote}.url`);
18221
19072
  return normalizedUrl(rewrittenUrl(configured ?? remote, config), dir);
18222
19073
  }, pushRemoteOf = (config, branch) => {
@@ -18242,7 +19093,7 @@ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLA
18242
19093
  const pushRemote = pushRemoteOf(config, repo.branch);
18243
19094
  if (pushRemote === null || pushRemote === remote)
18244
19095
  return true;
18245
- return pushUrl(config, remote, repo.dir) === pushUrl(config, pushRemote, repo.dir);
19096
+ return pushUrl2(config, remote, repo.dir) === pushUrl2(config, pushRemote, repo.dir);
18246
19097
  }, quote = (text) => `\`${text}\``, refusal = (action, branch, dir) => {
18247
19098
  if (action.kind === "merge")
18248
19099
  return `workit: raw ${quote(action.via === "api" ? `${action.forge} api` : action.forge === "gh" ? "gh pr merge" : "glab mr merge")}${action.via === "api" ? " merge" : ""} bypasses the merge grant and the verdict gate. Run ${quote("workit pr merge")} instead (it checks both; ${quote("workit help pr")}).`;
@@ -18404,7 +19255,7 @@ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLA
18404
19255
  const out = [];
18405
19256
  const repos = new Map;
18406
19257
  const repoFor = (relative) => {
18407
- const dir = path21.resolve(cwd, relative ?? ".");
19258
+ const dir = path22.resolve(cwd, relative ?? ".");
18408
19259
  if (!repos.has(dir)) {
18409
19260
  const repo = repoAt(dir);
18410
19261
  repos.set(dir, repo && isWorkitWorkspace(repo) ? repo : null);
@@ -18448,7 +19299,7 @@ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLA
18448
19299
  kind: "deny",
18449
19300
  reason: `workit: the shell hook could not analyze this command (${error.message}), so it does not run. ${SPLIT_IT}`,
18450
19301
  unblock: SPLIT_IT
18451
- }), NEXT_COMMAND = "next", MARKER_TTL_SECONDS = 3600, markerFile = (repo, session, key) => path21.join(repo.location.dir, "hooks", `commit-${createHash15("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`), callKey = (toolUseId, command) => toolUseId ?? `cmd:${createHash15("sha256").update(command).digest("hex")}`, headCommit = (dir) => {
19302
+ }), NEXT_COMMAND = "next", MARKER_TTL_SECONDS = 3600, markerFile = (repo, session, key) => path22.join(repo.location.dir, "hooks", `commit-${createHash15("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`), callKey = (toolUseId, command) => toolUseId ?? `cmd:${createHash15("sha256").update(command).digest("hex")}`, headCommit = (dir) => {
18452
19303
  const run = spawnSync11("git", [
18453
19304
  "log",
18454
19305
  "-1",
@@ -18554,7 +19405,7 @@ var init_raw_git = __esm(() => {
18554
19405
  ]);
18555
19406
  GIT_CONFIG_OPTIONS = new Set(["-c", "--config-env", "--git-dir"]);
18556
19407
  GIT_CONFIG_ENV = /^GIT_(?:CONFIG\w*|DIR|COMMON_DIR|WORK_TREE)$/;
18557
- ASSIGNMENT = /^([A-Za-z_]\w*)=([\s\S]*)$/;
19408
+ ASSIGNMENT2 = /^([A-Za-z_]\w*)=([\s\S]*)$/;
18558
19409
  HERE = /^(?:\$PWD|\$\{PWD\}|\$\(\s*pwd\s*\)|`pwd`|\$\(\s*git\s+rev-parse\s+--show-toplevel\s*\))(?=$|[\\/])/;
18559
19410
  VARIABLE = /\$(?:\{(\w+)\}|(\w+))/g;
18560
19411
  XARGS_VALUES = new Set(["-n", "-L", "-l", "-P", "-d", "-E", "-e", "-s", "-a", "--arg-file", "--delimiter"].concat([
@@ -18647,8 +19498,8 @@ var init_raw_git = __esm(() => {
18647
19498
 
18648
19499
  // packages/workit-core/src/core/route-intent.ts
18649
19500
  import { spawnSync as spawnSync12 } from "node:child_process";
18650
- import { existsSync as existsSync6 } from "node:fs";
18651
- import path22 from "node:path";
19501
+ import { existsSync as existsSync7 } from "node:fs";
19502
+ import path23 from "node:path";
18652
19503
  var UNKNOWABLE, SWITCH_CREATE, CHECKOUT_CREATE, WORKTREE_CREATE, SUBTREE_CREATE, BRANCH_NO_CREATE, BRANCH_RENAME, longOption = (name, flags) => flags.has(name) || name.length >= 3 && [...flags].some((flag) => flag.startsWith("--") && flag.startsWith(name)), shortsOf = (flags) => [...flags].filter((flag) => /^-[^-]$/u.test(flag)).join("").replaceAll("-", ""), flagValue = (args, flags) => {
18653
19504
  const shorts = shortsOf(flags);
18654
19505
  for (let index = 1;index < args.length; index++) {
@@ -18774,8 +19625,8 @@ var UNKNOWABLE, SWITCH_CREATE, CHECKOUT_CREATE, WORKTREE_CREATE, SUBTREE_CREATE,
18774
19625
  return null;
18775
19626
  if (dir === null)
18776
19627
  return root;
18777
- const resolved = path22.resolve(root, dir);
18778
- return existsSync6(resolved) && inWorkitWorkspace(resolved) ? resolved : null;
19628
+ const resolved = path23.resolve(root, dir);
19629
+ return existsSync7(resolved) && inWorkitWorkspace(resolved) ? resolved : null;
18779
19630
  }, shellBranchPolicyViolation = (root, command, dialect = "posix") => {
18780
19631
  let judged = false;
18781
19632
  const cache = new Map;
@@ -18829,7 +19680,7 @@ var init_policy = __esm(() => {
18829
19680
  // packages/workit-core/src/core/heavy-rules.ts
18830
19681
  import fs18 from "node:fs";
18831
19682
  import os6 from "node:os";
18832
- import path23 from "node:path";
19683
+ import path24 from "node:path";
18833
19684
  function parseJsonc(text) {
18834
19685
  let out = "";
18835
19686
  for (let index = 0;index < text.length; index += 1) {
@@ -18859,21 +19710,21 @@ function parseJsonc(text) {
18859
19710
  return JSON.parse(out.replace(/,(\s*[}\]])/gu, "$1"));
18860
19711
  }
18861
19712
  function gitTop(cwd) {
18862
- for (let dir = path23.resolve(cwd);; dir = path23.dirname(dir)) {
18863
- if (fs18.existsSync(path23.join(dir, ".git")))
19713
+ for (let dir = path24.resolve(cwd);; dir = path24.dirname(dir)) {
19714
+ if (fs18.existsSync(path24.join(dir, ".git")))
18864
19715
  return dir;
18865
- if (path23.dirname(dir) === dir)
19716
+ if (path24.dirname(dir) === dir)
18866
19717
  return null;
18867
19718
  }
18868
19719
  }
18869
19720
  function claudeSettingsFiles(cwd, env, platform = process.platform) {
18870
19721
  const project = env.CLAUDE_PROJECT_DIR || gitTop(cwd) || cwd;
18871
- const user = env.CLAUDE_CONFIG_DIR || path23.join(homeOf(env), ".claude");
19722
+ const user = env.CLAUDE_CONFIG_DIR || path24.join(homeOf(env), ".claude");
18872
19723
  return [
18873
19724
  ...CLAUDE_MANAGED[platform] ? [CLAUDE_MANAGED[platform]] : [],
18874
- path23.join(user, "settings.json"),
18875
- path23.join(project, ".claude", "settings.json"),
18876
- path23.join(project, ".claude", "settings.local.json")
19725
+ path24.join(user, "settings.json"),
19726
+ path24.join(project, ".claude", "settings.json"),
19727
+ path24.join(project, ".claude", "settings.local.json")
18877
19728
  ];
18878
19729
  }
18879
19730
  function claudeRules(cwd, env = process.env) {
@@ -18918,10 +19769,10 @@ function claudeRules(cwd, env = process.env) {
18918
19769
  function opencodeRules(cwd, env = process.env) {
18919
19770
  const rules = EMPTY2();
18920
19771
  try {
18921
- const config = env.XDG_CONFIG_HOME || path23.join(homeOf(env), ".config");
19772
+ const config = env.XDG_CONFIG_HOME || path24.join(homeOf(env), ".config");
18922
19773
  const files = [
18923
- ...OPENCODE_NAMES.map((name) => path23.join(config, "opencode", name)),
18924
- ...projectDirs(cwd).flatMap((dir) => OPENCODE_NAMES.flatMap((name) => [path23.join(dir, name), path23.join(dir, ".opencode", name)])),
19774
+ ...OPENCODE_NAMES.map((name) => path24.join(config, "opencode", name)),
19775
+ ...projectDirs(cwd).flatMap((dir) => OPENCODE_NAMES.flatMap((name) => [path24.join(dir, name), path24.join(dir, ".opencode", name)])),
18925
19776
  ...env.OPENCODE_CONFIG ? [env.OPENCODE_CONFIG] : []
18926
19777
  ];
18927
19778
  for (const file of files) {
@@ -18939,9 +19790,9 @@ function opencodeRules(cwd, env = process.env) {
18939
19790
  function codexRules(cwd, env = process.env) {
18940
19791
  const rules = EMPTY2();
18941
19792
  try {
18942
- const home = env.CODEX_HOME || path23.join(homeOf(env), ".codex");
19793
+ const home = env.CODEX_HOME || path24.join(homeOf(env), ".codex");
18943
19794
  const top = gitTop(cwd) ?? cwd;
18944
- for (const dir of [path23.join(home, "rules"), path23.join(top, ".codex", "rules")]) {
19795
+ for (const dir of [path24.join(home, "rules"), path24.join(top, ".codex", "rules")]) {
18945
19796
  let files;
18946
19797
  try {
18947
19798
  files = fs18.readdirSync(dir).filter((name) => name.endsWith(".rules"));
@@ -18951,7 +19802,7 @@ function codexRules(cwd, env = process.env) {
18951
19802
  return "unreadable";
18952
19803
  }
18953
19804
  for (const name of files) {
18954
- const text = readText2(path23.join(dir, name)) ?? "";
19805
+ const text = readText2(path24.join(dir, name)) ?? "";
18955
19806
  for (const part of text.split(/\bprefix_rule\s*\(/u).slice(1)) {
18956
19807
  const rule = codexRule(part);
18957
19808
  if (!rule)
@@ -18970,8 +19821,8 @@ function cursorRules(cwd, env = process.env) {
18970
19821
  try {
18971
19822
  const top = gitTop(cwd) ?? cwd;
18972
19823
  for (const file of [
18973
- path23.join(homeOf(env), ".cursor", "cli-config.json"),
18974
- path23.join(top, ".cursor", "cli.json")
19824
+ path24.join(homeOf(env), ".cursor", "cli-config.json"),
19825
+ path24.join(top, ".cursor", "cli.json")
18975
19826
  ]) {
18976
19827
  const text = readText2(file);
18977
19828
  if (text === null)
@@ -19033,9 +19884,9 @@ var EMPTY2 = () => ({ deny: [], allow: [] }), readText2 = (file) => {
19033
19884
  }, isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), projectDirs = (cwd) => {
19034
19885
  const top = gitTop(cwd);
19035
19886
  const dirs = [];
19036
- for (let dir = path23.resolve(cwd);; dir = path23.dirname(dir)) {
19887
+ for (let dir = path24.resolve(cwd);; dir = path24.dirname(dir)) {
19037
19888
  dirs.push(dir);
19038
- if (!top || dir === top || path23.dirname(dir) === dir)
19889
+ if (!top || dir === top || path24.dirname(dir) === dir)
19039
19890
  return dirs;
19040
19891
  }
19041
19892
  }, homeOf = (env) => env.HOME || os6.homedir(), CLAUDE_MANAGED, bashPattern = (entry) => {
@@ -19133,18 +19984,18 @@ var init_heavy_rules = __esm(() => {
19133
19984
  // packages/workit-core/src/core/heavy.ts
19134
19985
  import fs19 from "node:fs";
19135
19986
  import os7 from "node:os";
19136
- import path24 from "node:path";
19987
+ import path25 from "node:path";
19137
19988
  function stateDir(env, platform = process.platform) {
19138
19989
  if (env.WORKFLOW_TOOLKIT_STATE)
19139
19990
  return env.WORKFLOW_TOOLKIT_STATE;
19140
19991
  if (env.XDG_STATE_HOME)
19141
- return path24.join(env.XDG_STATE_HOME, "workit");
19992
+ return path25.join(env.XDG_STATE_HOME, "workit");
19142
19993
  const home = env.HOME || os7.homedir();
19143
19994
  if (platform === "darwin")
19144
- return path24.join(home, "Library", "Application Support", "workit");
19995
+ return path25.join(home, "Library", "Application Support", "workit");
19145
19996
  if (platform === "win32")
19146
- return path24.join(env.LOCALAPPDATA ?? path24.join(home, "AppData", "Local"), "workit");
19147
- return path24.join(home, ".local", "state", "workit");
19997
+ return path25.join(env.LOCALAPPDATA ?? path25.join(home, "AppData", "Local"), "workit");
19998
+ return path25.join(home, ".local", "state", "workit");
19148
19999
  }
19149
20000
  function positional2(words, from, values = PM_VALUES) {
19150
20001
  let index = from;
@@ -19284,7 +20135,7 @@ function machinePatterns(env) {
19284
20135
  return isRecord5(value) ? stringList(value.patterns) : [];
19285
20136
  }
19286
20137
  function repoPatterns(cwd) {
19287
- return repoHeavyCommands(gitTop(cwd) ?? path24.resolve(cwd));
20138
+ return repoHeavyCommands(gitTop(cwd) ?? path25.resolve(cwd));
19288
20139
  }
19289
20140
  function heavyLines(lines, options) {
19290
20141
  const found = [];
@@ -19353,12 +20204,12 @@ function heavyPlan(command, options) {
19353
20204
  }
19354
20205
  function workitOnPath2(env = process.env) {
19355
20206
  const names = process.platform === "win32" ? ["workit.exe", "workit.cmd", "workit"] : ["workit"];
19356
- for (const dir of (env.PATH ?? "").split(path24.delimiter))
20207
+ for (const dir of (env.PATH ?? "").split(path25.delimiter))
19357
20208
  for (const name of names) {
19358
20209
  if (!dir)
19359
20210
  continue;
19360
20211
  try {
19361
- fs19.accessSync(path24.join(dir, name), fs19.constants.X_OK);
20212
+ fs19.accessSync(path25.join(dir, name), fs19.constants.X_OK);
19362
20213
  return true;
19363
20214
  } catch {}
19364
20215
  }
@@ -19372,7 +20223,7 @@ function leaseRewrite(command) {
19372
20223
  return null;
19373
20224
  return `${prefix}workit check --heavy -- ${rest}`;
19374
20225
  }
19375
- var HEAVY_COMMANDS_FILE = "heavy-commands.json", heavyCommandsFile = (env) => path24.join(stateDir(env), HEAVY_COMMANDS_FILE), HEAVY_SCRIPT, INFO_FLAGS, WATCH_FLAG, WATCH_SCRIPT, sub = (...names) => new Set(names), TOOLS, PM_VALUES, baseName2 = (word) => (word?.split(/[\\/]/u).at(-1) ?? "").toLowerCase().replace(/\.(?:exe|cmd|bat|ps1)$/u, ""), WORKIT, PYTHONS, NPM_INSTALL, NPM_RUN, NPM_TEST, EXEC, globWord = (word) => new RegExp(`^${word.replace(/[.+?^${}()|[\]\\]/gu, "\\$&").replaceAll("*", ".*")}$`, "u"), matches = (matchers, words) => matchers.length <= words.length && matchers.every((matcher, index) => index === 0 ? matcher.test(words[0]) || matcher.test(baseName2(words[0])) : matcher.test(words[index])), readJson = (file) => {
20226
+ var HEAVY_COMMANDS_FILE = "heavy-commands.json", heavyCommandsFile = (env) => path25.join(stateDir(env), HEAVY_COMMANDS_FILE), HEAVY_SCRIPT, INFO_FLAGS, WATCH_FLAG, WATCH_SCRIPT, sub = (...names) => new Set(names), TOOLS, PM_VALUES, baseName2 = (word) => (word?.split(/[\\/]/u).at(-1) ?? "").toLowerCase().replace(/\.(?:exe|cmd|bat|ps1)$/u, ""), WORKIT, PYTHONS, NPM_INSTALL, NPM_RUN, NPM_TEST, EXEC, globWord = (word) => new RegExp(`^${word.replace(/[.+?^${}()|[\]\\]/gu, "\\$&").replaceAll("*", ".*")}$`, "u"), matches = (matchers, words) => matchers.length <= words.length && matchers.every((matcher, index) => index === 0 ? matcher.test(words[0]) || matcher.test(baseName2(words[0])) : matcher.test(words[index])), readJson = (file) => {
19376
20227
  try {
19377
20228
  return JSON.parse(fs19.readFileSync(file, "utf8"));
19378
20229
  } catch {
@@ -19518,7 +20369,7 @@ var init_heavy = __esm(() => {
19518
20369
  // packages/workit-core/src/core/heavy-words.ts
19519
20370
  import fs20 from "node:fs";
19520
20371
  import os8 from "node:os";
19521
- import path25 from "node:path";
20372
+ import path26 from "node:path";
19522
20373
  function maybeHeavy(command, cwd, env = process.env) {
19523
20374
  try {
19524
20375
  const words = wordsOf(command);
@@ -19534,13 +20385,13 @@ var HEAVY_WORDS, wordsOf = (command) => command.split(/[\s;&|()<>`'"]+/u).map((w
19534
20385
  if (env.WORKFLOW_TOOLKIT_STATE)
19535
20386
  return env.WORKFLOW_TOOLKIT_STATE;
19536
20387
  if (env.XDG_STATE_HOME)
19537
- return path25.join(env.XDG_STATE_HOME, "workit");
20388
+ return path26.join(env.XDG_STATE_HOME, "workit");
19538
20389
  const home = env.HOME || os8.homedir();
19539
20390
  if (process.platform === "darwin")
19540
- return path25.join(home, "Library", "Application Support", "workit");
20391
+ return path26.join(home, "Library", "Application Support", "workit");
19541
20392
  if (process.platform === "win32")
19542
- return path25.join(env.LOCALAPPDATA ?? path25.join(home, "AppData", "Local"), "workit");
19543
- return path25.join(home, ".local", "state", "workit");
20393
+ return path26.join(env.LOCALAPPDATA ?? path26.join(home, "AppData", "Local"), "workit");
20394
+ return path26.join(home, ".local", "state", "workit");
19544
20395
  }, readJson2 = (file) => {
19545
20396
  try {
19546
20397
  return JSON.parse(fs20.readFileSync(file, "utf8"));
@@ -19549,15 +20400,15 @@ var HEAVY_WORDS, wordsOf = (command) => command.split(/[\s;&|()<>`'"]+/u).map((w
19549
20400
  }
19550
20401
  }, patternWords = (cwd, env) => {
19551
20402
  const patterns = [];
19552
- const machine = readJson2(path25.join(stateDir2(env), "heavy-commands.json"));
20403
+ const machine = readJson2(path26.join(stateDir2(env), "heavy-commands.json"));
19553
20404
  if (Array.isArray(machine?.patterns))
19554
20405
  patterns.push(...machine.patterns);
19555
- for (let dir = path25.resolve(cwd);; dir = path25.dirname(dir)) {
19556
- if (fs20.existsSync(path25.join(dir, ".git"))) {
20406
+ for (let dir = path26.resolve(cwd);; dir = path26.dirname(dir)) {
20407
+ if (fs20.existsSync(path26.join(dir, ".git"))) {
19557
20408
  patterns.push(...repoHeavyCommands(dir));
19558
20409
  break;
19559
20410
  }
19560
- if (path25.dirname(dir) === dir)
20411
+ if (path26.dirname(dir) === dir)
19561
20412
  break;
19562
20413
  }
19563
20414
  const words = new Set;
@@ -19627,7 +20478,7 @@ import { spawnSync as spawnSync13 } from "node:child_process";
19627
20478
  import { createHash as createHash16 } from "node:crypto";
19628
20479
  import fs21 from "node:fs";
19629
20480
  import os9 from "node:os";
19630
- import path26 from "node:path";
20481
+ import path27 from "node:path";
19631
20482
  var LIVE_SESSION_TTL_MS, HEARTBEAT_EVERY_MS = 30000, liveProbe, leadOf = (session) => session.split(":")[0].replace(/-w-.*$/su, "") || session, familyOf = (host) => host.replace(/_(?:cli|desktop)$/u, ""), processAlive = (pid) => {
19632
20483
  try {
19633
20484
  process.kill(pid, 0);
@@ -19685,15 +20536,15 @@ var LIVE_SESSION_TTL_MS, HEARTBEAT_EVERY_MS = 30000, liveProbe, leadOf = (sessio
19685
20536
  pid: () => hostPid(transport)
19686
20537
  };
19687
20538
  }, checkoutOf = (target) => {
19688
- let dir = path26.resolve(target);
19689
- while (!fs21.existsSync(dir) && path26.dirname(dir) !== dir)
19690
- dir = path26.dirname(dir);
20539
+ let dir = path27.resolve(target);
20540
+ while (!fs21.existsSync(dir) && path27.dirname(dir) !== dir)
20541
+ dir = path27.dirname(dir);
19691
20542
  if (fs21.existsSync(dir) && !fs21.statSync(dir).isDirectory())
19692
- dir = path26.dirname(dir);
19693
- const parts = dir.split(path26.sep);
20543
+ dir = path27.dirname(dir);
20544
+ const parts = dir.split(path27.sep);
19694
20545
  const dotGit = parts.lastIndexOf(".git");
19695
20546
  if (dotGit > 0)
19696
- dir = parts.slice(0, dotGit).join(path26.sep) || path26.sep;
20547
+ dir = parts.slice(0, dotGit).join(path27.sep) || path27.sep;
19697
20548
  const location = resolveStore(dir);
19698
20549
  if (location instanceof Error || !location.shared || !location.top)
19699
20550
  return null;
@@ -19702,8 +20553,8 @@ var LIVE_SESSION_TTL_MS, HEARTBEAT_EVERY_MS = 30000, liveProbe, leadOf = (sessio
19702
20553
  top = fs21.realpathSync.native(top);
19703
20554
  } catch {}
19704
20555
  return top;
19705
- }, markerFile2 = (top) => path26.join(resolveStateDir(), "live-sessions", `${createHash16("sha256").update(checkoutKey(top)).digest("hex").slice(0, 32)}.json`), checkoutKey = (top, platform = process.platform) => {
19706
- let key = path26.resolve(top);
20556
+ }, markerFile2 = (top) => path27.join(resolveStateDir(), "live-sessions", `${createHash16("sha256").update(checkoutKey(top)).digest("hex").slice(0, 32)}.json`), checkoutKey = (top, platform = process.platform) => {
20557
+ let key = path27.resolve(top);
19707
20558
  try {
19708
20559
  key = fs21.realpathSync.native(key);
19709
20560
  } catch {}
@@ -19791,7 +20642,7 @@ var LIVE_SESSION_TTL_MS, HEARTBEAT_EVERY_MS = 30000, liveProbe, leadOf = (sessio
19791
20642
  checkout,
19792
20643
  heartbeatAt: now.toISOString()
19793
20644
  };
19794
- fs21.mkdirSync(path26.dirname(file), { recursive: true });
20645
+ fs21.mkdirSync(path27.dirname(file), { recursive: true });
19795
20646
  const temp = `${file}.${process.pid}.tmp`;
19796
20647
  fs21.writeFileSync(temp, JSON.stringify(marker));
19797
20648
  fs21.renameSync(temp, file);
@@ -19812,9 +20663,9 @@ var init_live_session = __esm(() => {
19812
20663
  });
19813
20664
 
19814
20665
  // packages/workit-core/src/hooks/write-gate.ts
19815
- import { existsSync as existsSync7, realpathSync as realpathSync5 } from "node:fs";
20666
+ import { existsSync as existsSync8, realpathSync as realpathSync5 } from "node:fs";
19816
20667
  import os10 from "node:os";
19817
- import path27 from "node:path";
20668
+ import path28 from "node:path";
19818
20669
  function writeGate(cwd, paths, owner, deps) {
19819
20670
  const forged = paths?.length ? issuedTarget(cwd, paths) : null;
19820
20671
  if (forged)
@@ -19872,21 +20723,21 @@ function beforeWriteGate(cwd, paths) {
19872
20723
  }
19873
20724
  var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
19874
20725
  let rest = "";
19875
- for (let dir = path27.resolve(file);; dir = path27.dirname(dir)) {
20726
+ for (let dir = path28.resolve(file);; dir = path28.dirname(dir)) {
19876
20727
  try {
19877
- return path27.join(realpathSync5.native(dir), rest);
20728
+ return path28.join(realpathSync5.native(dir), rest);
19878
20729
  } catch {
19879
- if (path27.dirname(dir) === dir)
19880
- return path27.resolve(file);
19881
- rest = rest ? path27.join(path27.basename(dir), rest) : path27.basename(dir);
20730
+ if (path28.dirname(dir) === dir)
20731
+ return path28.resolve(file);
20732
+ rest = rest ? path28.join(path28.basename(dir), rest) : path28.basename(dir);
19882
20733
  }
19883
20734
  }
19884
20735
  }, exempt = (cwd, root, file, plans) => {
19885
20736
  const fold = (value) => CASE_INSENSITIVE ? value.toLowerCase() : value;
19886
- const relative = path27.relative(fold(canonical2(root)), fold(canonical2(path27.resolve(cwd, file))));
19887
- if (relative.startsWith("..") || path27.isAbsolute(relative))
20737
+ const relative = path28.relative(fold(canonical2(root)), fold(canonical2(path28.resolve(cwd, file))));
20738
+ if (relative.startsWith("..") || path28.isAbsolute(relative))
19888
20739
  return true;
19889
- const posix = relative.split(path27.sep).join("/");
20740
+ const posix = relative.split(path28.sep).join("/");
19890
20741
  const segments = posix.split("/");
19891
20742
  return /\.mdx?$/i.test(posix) || segments[0] === "docs" || segments.includes("plans") || [...plans].some((plan) => fold(plan) === posix);
19892
20743
  }, PREFIXES2, operands = (words) => words.filter((item) => !item.startsWith("-")), SCRIPT_SHELLS, wrappedScript = (input) => {
@@ -20053,10 +20904,10 @@ var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
20053
20904
  const sources = names.filter((name, index) => into >= 0 ? name !== dest : index < names.length - 1 || names.length === 1);
20054
20905
  const target = dest === undefined ? null : at(dest);
20055
20906
  const symbolic = args.some((arg) => /^-[a-zA-Z]*s|^--symbolic$/.test(arg));
20056
- const base = target === null ? null : into >= 0 || sources.length > 1 || existsSync7(target) || /[\\/]$/.test(dest ?? "") ? target : path27.dirname(target);
20907
+ const base = target === null ? null : into >= 0 || sources.length > 1 || existsSync8(target) || /[\\/]$/.test(dest ?? "") ? target : path28.dirname(target);
20057
20908
  return sources.flatMap((source) => {
20058
- if (symbolic && base !== null && !path27.isAbsolute(homeExpanded(source)))
20059
- return [path27.resolve(base, source)];
20909
+ if (symbolic && base !== null && !path28.isAbsolute(homeExpanded(source)))
20910
+ return [path28.resolve(base, source)];
20060
20911
  const resolved = at(source);
20061
20912
  return resolved ? [resolved] : [];
20062
20913
  });
@@ -20082,7 +20933,7 @@ var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
20082
20933
  if (!unknown && targets.length === 0)
20083
20934
  return { writes: false, targets: null };
20084
20935
  return { writes: true, targets: unknown ? null : targets };
20085
- }, cache2, planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(path27.resolve(root, file)) ?? "-").join("\x00"), gateFor = (cwd) => {
20936
+ }, cache2, planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(path28.resolve(root, file)) ?? "-").join("\x00"), gateFor = (cwd) => {
20086
20937
  const store = new TaskStore(cwd);
20087
20938
  const listed = store.listTaskIndex();
20088
20939
  if (!listed.ok)
@@ -20135,7 +20986,7 @@ var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
20135
20986
  return [];
20136
20987
  if (sub === "stash" && ["list", "show"].includes(rest[0] ?? ""))
20137
20988
  return [];
20138
- return [path27.resolve(cwd, invocation.dir ?? ".")];
20989
+ return [path28.resolve(cwd, invocation.dir ?? ".")];
20139
20990
  });
20140
20991
  }, CD2, PUSHD2, POPD2, UNKNOWN_DIR, cdInto = (dir, words, strict = false) => {
20141
20992
  const lost = strict ? UNKNOWN_DIR : undefined;
@@ -20145,7 +20996,7 @@ var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
20145
20996
  return lost;
20146
20997
  if (dir === undefined)
20147
20998
  return lost;
20148
- return target === undefined ? os10.homedir() : path27.resolve(dir, target);
20999
+ return target === undefined ? os10.homedir() : path28.resolve(dir, target);
20149
21000
  }, quoteWord2 = (word) => /^[\w@%+=:,./-]+$/.test(word) ? word : `'${word.replaceAll("'", "'\\''")}'`, homeExpanded = (file) => {
20150
21001
  const match = /^(?:~|\$HOME|\$\{HOME\})(?=\/|$)/.exec(file);
20151
21002
  return match ? (process.env.HOME || os10.homedir()) + file.slice(match[0].length) : file;
@@ -20156,7 +21007,7 @@ var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
20156
21007
  const groups = [];
20157
21008
  const at = (file) => {
20158
21009
  const home = homeExpanded(file);
20159
- return path27.isAbsolute(home) ? home : dir === undefined ? null : path27.resolve(dir, home);
21010
+ return path28.isAbsolute(home) ? home : dir === undefined ? null : path28.resolve(dir, home);
20160
21011
  };
20161
21012
  for (const segment of segmentsOf(command, dialect)) {
20162
21013
  if (segment.group === "open") {
@@ -20196,7 +21047,7 @@ var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
20196
21047
  for (const file of opaque ?? []) {
20197
21048
  const resolved = at(file);
20198
21049
  if (resolved)
20199
- targets.push(file === "." ? path27.join(resolved, DIR_TARGET) : resolved);
21050
+ targets.push(file === "." ? path28.join(resolved, DIR_TARGET) : resolved);
20200
21051
  }
20201
21052
  const ln = words.findIndex((word) => /^ln$/i.test(word.split(/[\\/]/).at(-1) ?? ""));
20202
21053
  if (ln >= 0 && words.slice(0, ln).every((word) => PREFIXES2.has(word)))
@@ -20211,7 +21062,7 @@ var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
20211
21062
  const edits = editsOf(segment.words);
20212
21063
  if (edits === null) {
20213
21064
  if (dir !== undefined)
20214
- targets.push(path27.join(dir, DIR_TARGET));
21065
+ targets.push(path28.join(dir, DIR_TARGET));
20215
21066
  } else
20216
21067
  for (const file of edits) {
20217
21068
  const resolved = at(file);
@@ -20222,18 +21073,18 @@ var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
20222
21073
  for (const invocation of workitInvocations(segment.words.map(quoteWord2).join(" "), "posix")) {
20223
21074
  const { at: runsIn, args } = workitCwd(dir, invocation);
20224
21075
  if (args[0] === "git" && MUTATING_WORKIT_GIT.has(args[1] ?? "") && !inert(args.slice(2), ""))
20225
- targets.push(path27.join(runsIn, DIR_TARGET));
21076
+ targets.push(path28.join(runsIn, DIR_TARGET));
20226
21077
  }
20227
21078
  }
20228
21079
  return targets;
20229
21080
  }, workitCwd = (dir, args) => {
20230
21081
  const { rest, cwd } = skipWorkitGlobals(args);
20231
- return { at: cwd === null ? dir : path27.resolve(dir, homeExpanded(cwd)), args: rest };
21082
+ return { at: cwd === null ? dir : path28.resolve(dir, homeExpanded(cwd)), args: rest };
20232
21083
  }, shellMutationTargets = (cwd, command, dialect = "posix", strict = false) => {
20233
21084
  try {
20234
21085
  return [
20235
21086
  ...segmentTargets(cwd, command, dialect, 0, strict),
20236
- ...gitMutationDirs(cwd, command, dialect).map((dir) => path27.join(dir, DIR_TARGET))
21087
+ ...gitMutationDirs(cwd, command, dialect).map((dir) => path28.join(dir, DIR_TARGET))
20237
21088
  ];
20238
21089
  } catch {
20239
21090
  return [];
@@ -20258,7 +21109,7 @@ var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
20258
21109
  }, guarded = (targets) => {
20259
21110
  const seen = new Set;
20260
21111
  return targets.filter((target) => {
20261
- const dir = path27.dirname(target);
21112
+ const dir = path28.dirname(target);
20262
21113
  if (seen.has(dir))
20263
21114
  return false;
20264
21115
  seen.add(dir);
@@ -20276,13 +21127,13 @@ var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
20276
21127
  }, claimAll = (owner, targets, deps) => {
20277
21128
  for (const target of guarded(targets))
20278
21129
  claimLiveSession(target, owner, deps);
20279
- }, liveTargets = (cwd, paths) => paths?.length ? paths.map((file) => path27.resolve(cwd, file)) : [path27.join(cwd, DIR_TARGET)], issuedTarget = (cwd, targets) => {
21130
+ }, liveTargets = (cwd, paths) => paths?.length ? paths.map((file) => path28.resolve(cwd, file)) : [path28.join(cwd, DIR_TARGET)], issuedTarget = (cwd, targets) => {
20280
21131
  const state = resolveStateDir();
20281
21132
  const found = targets.find((target) => underIssued(state, cwd, homeExpanded(target), process.platform, canonical2));
20282
21133
  return found ?? null;
20283
21134
  }, underIssued = (state, cwd, target, platform = process.platform, real = (file) => file) => {
20284
21135
  const win = platform === "win32";
20285
- const p = win ? path27.win32 : path27.posix;
21136
+ const p = win ? path28.win32 : path28.posix;
20286
21137
  const fold = (value) => win || platform === "darwin" ? value.toLowerCase() : value;
20287
21138
  const named = win ? target.replace(/^\/([a-zA-Z])(?=\/|$)/, "$1:") : target;
20288
21139
  const relative = p.relative(fold(real(p.resolve(state))), fold(real(p.resolve(cwd, named))));
@@ -20353,7 +21204,7 @@ var init_write_gate = __esm(() => {
20353
21204
  CD2 = new Set(["cd", "chdir", "set-location", "sl"]);
20354
21205
  PUSHD2 = new Set(["pushd", "push-location"]);
20355
21206
  POPD2 = new Set(["popd", "pop-location"]);
20356
- UNKNOWN_DIR = path27.resolve(path27.parse(process.cwd()).root, ".workit-unknown-dir");
21207
+ UNKNOWN_DIR = path28.resolve(path28.parse(process.cwd()).root, ".workit-unknown-dir");
20357
21208
  HOST_LABELS = {
20358
21209
  claude_code: "Claude Code",
20359
21210
  opencode: "OpenCode",
@@ -20364,6 +21215,26 @@ var init_write_gate = __esm(() => {
20364
21215
  };
20365
21216
  });
20366
21217
 
21218
+ // packages/workit-core/src/core/policy/current-judgment.ts
21219
+ function currentJudgment(cwd) {
21220
+ try {
21221
+ const store = new TaskStore(cwd);
21222
+ const listed = store.listTaskIndex();
21223
+ const key = store.currentKey();
21224
+ if (!listed.ok || !key.ok)
21225
+ return null;
21226
+ const entry = listed.data.filter((item) => item.key === key.data.key && item.status !== "closed").toSorted((left, right) => right.updatedAt.localeCompare(left.updatedAt))[0];
21227
+ const task = entry ? store.readTask(entry.id) : null;
21228
+ return task?.ok === true ? latestJudgment(task.data) : null;
21229
+ } catch {
21230
+ return null;
21231
+ }
21232
+ }
21233
+ var init_current_judgment = __esm(() => {
21234
+ init_task_store();
21235
+ init_derive();
21236
+ });
21237
+
20367
21238
  // packages/workit-core/src/hooks/stop.ts
20368
21239
  import { spawnSync as spawnSync14 } from "node:child_process";
20369
21240
  function stopObligation(input, descriptor) {
@@ -20402,7 +21273,7 @@ function stopObligation(input, descriptor) {
20402
21273
  }
20403
21274
  if (!delivered || endpoint !== "green" && endpoint !== "merged")
20404
21275
  return null;
20405
- const left = unverified(input.cwd, branch, all, descriptor, autonomy.verification);
21276
+ const left = unverified(input.cwd, branch, all, descriptor, autonomy.verification, head);
20406
21277
  return left ? { ...left, head } : null;
20407
21278
  } catch {
20408
21279
  return null;
@@ -20505,28 +21376,31 @@ var NONE4, QUESTION, OFFER, YES_NO, LIST_ITEM, asksUser = (message) => {
20505
21376
  kind: "checks",
20506
21377
  reason: `PR #${pr}'s checks were last seen ${state} at ${short(head)}, and this workspace's endpoint is \`${endpoint}\`: run \`workit ci wait --pr ${pr}\`${state === "failing" ? " after fixing the failures `workit pr status` lists (then push)" : ""}.`
20507
21378
  };
20508
- }, taskJudgment = (cwd) => {
20509
- try {
20510
- const store = new TaskStore(cwd);
20511
- const listed = store.listTaskIndex();
20512
- const key = store.currentKey();
20513
- if (!listed.ok || !key.ok)
20514
- return null;
20515
- const entry = listed.data.filter((item) => item.key === key.data.key && item.status !== "closed").toSorted((left, right) => right.updatedAt.localeCompare(left.updatedAt))[0];
20516
- const task = entry ? store.readTask(entry.id) : null;
20517
- return task?.ok === true ? latestJudgment(task.data) : null;
20518
- } catch {
20519
- return null;
20520
- }
20521
- }, unverified = (cwd, branch, all, descriptor, verification) => {
21379
+ }, prBase = (rows) => {
21380
+ const seen = rows.findLast((row) => (row.type === "pr.status" || row.type === "pr.created") && row.observer === "workit_cli" && typeof row.base === "string");
21381
+ return typeof seen?.base === "string" ? seen.base : null;
21382
+ }, unverified = (cwd, branch, all, descriptor, verification, head) => {
20522
21383
  const check = checkVerdicts(cwd, branch, all);
20523
21384
  if (check.accepted.accepted || check.accepted.reasons.includes("failing_verdict"))
20524
21385
  return null;
20525
- const judgment = taskJudgment(cwd);
21386
+ const judgment = currentJudgment(cwd);
20526
21387
  const high = judgment?.riskTier === "high";
20527
- if (judgment && !judgment.behaviorChange && !high)
20528
- return null;
20529
- const independent = verification === "independent" || high;
21388
+ let independent;
21389
+ if (verification === "proportional") {
21390
+ const lane = branchLane(cwd, {
21391
+ base: prBase(all.filter((row) => row.branch === branch)),
21392
+ head,
21393
+ judgment
21394
+ });
21395
+ const need = laneNeed(lane.lane);
21396
+ if (need === "none")
21397
+ return null;
21398
+ independent = need === "non-author";
21399
+ } else {
21400
+ if (judgment && !judgment.behaviorChange && !high)
21401
+ return null;
21402
+ independent = verification === "independent" || high;
21403
+ }
20530
21404
  if (!independent && check.review === "self-reviewed")
20531
21405
  return null;
20532
21406
  const has = check.review === "self-reviewed" ? "only a self verdict" : "no current verdict";
@@ -20539,8 +21413,8 @@ var NONE4, QUESTION, OFFER, YES_NO, LIST_ITEM, asksUser = (message) => {
20539
21413
  };
20540
21414
  var init_stop = __esm(() => {
20541
21415
  init_autonomy();
20542
- init_derive();
20543
- init_task_store();
21416
+ init_current_judgment();
21417
+ init_lane();
20544
21418
  init_rev();
20545
21419
  init_ledger();
20546
21420
  init_raw_git();
@@ -20781,10 +21655,10 @@ var init_skill_nudge = __esm(() => {
20781
21655
  });
20782
21656
 
20783
21657
  // packages/workit-core/src/hooks/hosts/fields.ts
20784
- import { existsSync as existsSync8, realpathSync as realpathSync6, statSync as statSync2 } from "node:fs";
20785
- import path28 from "node:path";
21658
+ import { existsSync as existsSync9, realpathSync as realpathSync6, statSync as statSync2 } from "node:fs";
21659
+ import path29 from "node:path";
20786
21660
  var isRecord6 = (value) => value !== null && typeof value === "object" && !Array.isArray(value), nonEmpty2 = (value) => typeof value === "string" && value.trim() !== "", optionalText = (value) => typeof value === "string" ? value : null, existingDirectory = (value) => {
20787
- if (!nonEmpty2(value) || !path28.isAbsolute(value) || !existsSync8(value))
21661
+ if (!nonEmpty2(value) || !path29.isAbsolute(value) || !existsSync9(value))
20788
21662
  return null;
20789
21663
  try {
20790
21664
  return statSync2(value).isDirectory() ? realpathSync6(value) : null;
@@ -20850,9 +21724,9 @@ var init_fields = __esm(() => {
20850
21724
 
20851
21725
  // packages/workit-core/src/hooks/standing.ts
20852
21726
  import fs22 from "node:fs";
20853
- import path29 from "node:path";
21727
+ import path30 from "node:path";
20854
21728
  var readPlans = (store) => {
20855
- const dir = path29.join(store, "fanouts");
21729
+ const dir = path30.join(store, "fanouts");
20856
21730
  let names;
20857
21731
  try {
20858
21732
  names = fs22.readdirSync(dir).filter((name) => name.endsWith(".json"));
@@ -20862,7 +21736,7 @@ var readPlans = (store) => {
20862
21736
  const plans = [];
20863
21737
  for (const name of names) {
20864
21738
  try {
20865
- const raw = JSON.parse(fs22.readFileSync(path29.join(dir, name), "utf8"));
21739
+ const raw = JSON.parse(fs22.readFileSync(path30.join(dir, name), "utf8"));
20866
21740
  if (typeof raw.name !== "string" || !Array.isArray(raw.slices))
20867
21741
  continue;
20868
21742
  const texts = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string" && item !== "") : [];
@@ -20988,12 +21862,12 @@ var init_cwd_normalize = __esm(() => {
20988
21862
  // packages/workit-core/src/hooks/worktree-confine.ts
20989
21863
  import { createHash as createHash17 } from "node:crypto";
20990
21864
  import fs23 from "node:fs";
20991
- import path30 from "node:path";
21865
+ import path31 from "node:path";
20992
21866
  function confineImplementer(input, targets) {
20993
21867
  try {
20994
21868
  if (!input.session.agentId || hostIsolated(input.cwd, input.session.agentId))
20995
21869
  return NONE5;
20996
- if (targets.some((target) => within(path30.resolve(target), UNKNOWN_DIR)))
21870
+ if (targets.some((target) => within(path31.resolve(target), UNKNOWN_DIR)))
20997
21871
  return unknownDirDeny(input, boundWorktree(input));
20998
21872
  const bindings = canonical3(bindingDir());
20999
21873
  const judged = targets.map((named) => ({ named, real: canonical3(named) })).filter(({ real }) => within(real, bindings) || checkoutOf2(real) !== null);
@@ -21028,32 +21902,32 @@ function confineImplementerShell(input, command, dialect = "posix") {
21028
21902
  }
21029
21903
  var FANOUT_TOKEN_FILE = "workit-fanout-token", NONE5, CASE_INSENSITIVE2, canonical3 = (file) => {
21030
21904
  let rest = "";
21031
- for (let dir = path30.resolve(file);; dir = path30.dirname(dir)) {
21905
+ for (let dir = path31.resolve(file);; dir = path31.dirname(dir)) {
21032
21906
  try {
21033
- return path30.join(fs23.realpathSync.native(dir), rest);
21907
+ return path31.join(fs23.realpathSync.native(dir), rest);
21034
21908
  } catch {
21035
- if (path30.dirname(dir) === dir)
21036
- return path30.resolve(file);
21037
- rest = rest ? path30.join(path30.basename(dir), rest) : path30.basename(dir);
21909
+ if (path31.dirname(dir) === dir)
21910
+ return path31.resolve(file);
21911
+ rest = rest ? path31.join(path31.basename(dir), rest) : path31.basename(dir);
21038
21912
  }
21039
21913
  }
21040
21914
  }, within = (child, parent) => {
21041
21915
  const fold = (value) => CASE_INSENSITIVE2 ? value.toLowerCase() : value;
21042
- const relative = path30.relative(fold(parent), fold(child));
21043
- return relative === "" || !relative.startsWith("..") && !path30.isAbsolute(relative);
21916
+ const relative = path31.relative(fold(parent), fold(child));
21917
+ return relative === "" || !relative.startsWith("..") && !path31.isAbsolute(relative);
21044
21918
  }, checkoutOf2 = (file) => {
21045
- for (let dir = canonical3(file);; dir = path30.dirname(dir)) {
21046
- const dotGit = path30.join(dir, ".git");
21919
+ for (let dir = canonical3(file);; dir = path31.dirname(dir)) {
21920
+ const dotGit = path31.join(dir, ".git");
21047
21921
  if (fs23.existsSync(dotGit)) {
21048
21922
  if (!fs23.statSync(dotGit).isFile())
21049
21923
  return { root: dir, workit: false };
21050
21924
  const admin = /^gitdir:\s*(.+)$/mu.exec(fs23.readFileSync(dotGit, "utf8"))?.[1]?.trim();
21051
21925
  return {
21052
21926
  root: dir,
21053
- workit: Boolean(admin) && fs23.existsSync(path30.join(path30.resolve(dir, admin), FANOUT_TOKEN_FILE))
21927
+ workit: Boolean(admin) && fs23.existsSync(path31.join(path31.resolve(dir, admin), FANOUT_TOKEN_FILE))
21054
21928
  };
21055
21929
  }
21056
- if (path30.dirname(dir) === dir)
21930
+ if (path31.dirname(dir) === dir)
21057
21931
  return null;
21058
21932
  }
21059
21933
  }, workitWorktreeOf = (file) => {
@@ -21063,7 +21937,7 @@ var FANOUT_TOKEN_FILE = "workit-fanout-token", NONE5, CASE_INSENSITIVE2, canonic
21063
21937
  } catch {
21064
21938
  return null;
21065
21939
  }
21066
- }, bindingDir = () => path30.join(resolveStateDir(), "worktree-bind"), bindingFile = (session, agentId) => path30.join(bindingDir(), `${createHash17("sha256").update(`${session}\x00${agentId}`).digest("hex").slice(0, 32)}.json`), readBinding = (file) => {
21940
+ }, bindingDir = () => path31.join(resolveStateDir(), "worktree-bind"), bindingFile = (session, agentId) => path31.join(bindingDir(), `${createHash17("sha256").update(`${session}\x00${agentId}`).digest("hex").slice(0, 32)}.json`), readBinding = (file) => {
21067
21941
  try {
21068
21942
  const value = JSON.parse(fs23.readFileSync(file, "utf8"));
21069
21943
  return typeof value.worktree === "string" ? value : null;
@@ -21085,7 +21959,7 @@ var FANOUT_TOKEN_FILE = "workit-fanout-token", NONE5, CASE_INSENSITIVE2, canonic
21085
21959
  agentId,
21086
21960
  at: new Date().toISOString()
21087
21961
  };
21088
- fs23.mkdirSync(path30.dirname(file), { recursive: true });
21962
+ fs23.mkdirSync(path31.dirname(file), { recursive: true });
21089
21963
  fs23.writeFileSync(file, JSON.stringify(binding));
21090
21964
  try {
21091
21965
  if (inWorkitWorkspace(input.cwd))
@@ -21103,24 +21977,24 @@ var FANOUT_TOKEN_FILE = "workit-fanout-token", NONE5, CASE_INSENSITIVE2, canonic
21103
21977
  const checkout = checkoutOf2(cwd);
21104
21978
  if (!checkout)
21105
21979
  return false;
21106
- const dotGit = path30.join(checkout.root, ".git");
21980
+ const dotGit = path31.join(checkout.root, ".git");
21107
21981
  if (!fs23.statSync(dotGit).isFile())
21108
21982
  return false;
21109
21983
  const admin = /^gitdir:\s*(.+)$/mu.exec(fs23.readFileSync(dotGit, "utf8"))?.[1]?.trim();
21110
21984
  if (!admin)
21111
21985
  return false;
21112
- const adminDir = path30.resolve(checkout.root, admin);
21113
- const back = fs23.readFileSync(path30.join(adminDir, "gitdir"), "utf8").trim();
21114
- if (path30.relative(canonical3(path30.resolve(adminDir, back)), canonical3(dotGit)) !== "")
21986
+ const adminDir = path31.resolve(checkout.root, admin);
21987
+ const back = fs23.readFileSync(path31.join(adminDir, "gitdir"), "utf8").trim();
21988
+ if (path31.relative(canonical3(path31.resolve(adminDir, back)), canonical3(dotGit)) !== "")
21115
21989
  return false;
21116
- const common = path30.join(adminDir, "commondir");
21117
- const gitDir = fs23.existsSync(common) ? path30.resolve(adminDir, fs23.readFileSync(common, "utf8").trim()) : adminDir;
21118
- const expected = path30.join(path30.dirname(canonical3(gitDir)), ".claude", "worktrees", `agent-${agentId}`);
21119
- return path30.relative(canonical3(expected), checkout.root) === "";
21990
+ const common = path31.join(adminDir, "commondir");
21991
+ const gitDir = fs23.existsSync(common) ? path31.resolve(adminDir, fs23.readFileSync(common, "utf8").trim()) : adminDir;
21992
+ const expected = path31.join(path31.dirname(canonical3(gitDir)), ".claude", "worktrees", `agent-${agentId}`);
21993
+ return path31.relative(canonical3(expected), checkout.root) === "";
21120
21994
  } catch {
21121
21995
  return false;
21122
21996
  }
21123
- }, shown = (target) => path30.basename(target) === ".workit-live-target" ? path30.dirname(target) : target, unboundDeny = (input, target) => {
21997
+ }, shown = (target) => path31.basename(target) === ".workit-live-target" ? path31.dirname(target) : target, unboundDeny = (input, target) => {
21124
21998
  const unblock = "Work only in the worktree your brief names, which the lead made with `workit fanout worktree create <slice>`: edit files under it and run one verb per call against it (`workit --cwd <worktree> git commit -m … -- <paths>`, `workit --cwd <worktree> check <name>`). If your brief names no worktree, stop and report that to the lead.";
21125
21999
  return {
21126
22000
  kind: "deny",
@@ -21445,14 +22319,14 @@ var init_handle = __esm(() => {
21445
22319
 
21446
22320
  // packages/workit-core/src/hooks/deadline.ts
21447
22321
  import { appendFileSync, mkdirSync as mkdirSync3 } from "node:fs";
21448
- import path31 from "node:path";
22322
+ import path32 from "node:path";
21449
22323
  var HOOK_SKIP_TEXT = "workit context skipped: host under load", HOOK_DEADLINE_MS = 8000, HOST_DEADLINES, HOOK_SKIPS_FILE = "hook-skips.jsonl", override = (env) => {
21450
22324
  const value = Number(env.WORKIT_HOOK_DEADLINE_MS);
21451
22325
  return Number.isFinite(value) && value > 0 ? value : null;
21452
22326
  }, hookDeadlineMs = (env, host = "", native) => {
21453
22327
  const row = HOST_DEADLINES[host];
21454
22328
  return override(env) ?? (row ? native === undefined ? Math.min(...Object.values(row)) : row[native] ?? row[""] : HOOK_DEADLINE_MS);
21455
- }, skipsFile = (stateDir) => path31.join(stateDir, HOOK_SKIPS_FILE), recordHookSkip = (skip, stateDir = resolveStateDir()) => {
22329
+ }, skipsFile = (stateDir) => path32.join(stateDir, HOOK_SKIPS_FILE), recordHookSkip = (skip, stateDir = resolveStateDir()) => {
21456
22330
  try {
21457
22331
  mkdirSync3(stateDir, { recursive: true });
21458
22332
  appendFileSync(skipsFile(stateDir), `${JSON.stringify(skip)}
@@ -22097,7 +22971,7 @@ var init_codex = __esm(() => {
22097
22971
 
22098
22972
  // packages/workit-core/src/hooks/hosts/cursor.ts
22099
22973
  import fs24 from "node:fs";
22100
- import path32 from "node:path";
22974
+ import path33 from "node:path";
22101
22975
  var undocumented, none, CURSOR_DESCRIPTOR, EVENTS3, parseCursorHookInput = (value) => {
22102
22976
  if (!isRecord6(value) || !Object.hasOwn(EVENTS3, String(value.hook_event_name)))
22103
22977
  return { ok: false, error: "hook_event_name is required" };
@@ -22178,7 +23052,7 @@ var undocumented, none, CURSOR_DESCRIPTOR, EVENTS3, parseCursorHookInput = (valu
22178
23052
  };
22179
23053
  }
22180
23054
  }, TRANSCRIPT_TAIL_BYTES, lastAssistantText = (file) => {
22181
- if (!file || !path32.isAbsolute(file))
23055
+ if (!file || !path33.isAbsolute(file))
22182
23056
  return null;
22183
23057
  try {
22184
23058
  const size = fs24.statSync(file).size;
@@ -22214,7 +23088,7 @@ var undocumented, none, CURSOR_DESCRIPTOR, EVENTS3, parseCursorHookInput = (valu
22214
23088
  } catch {
22215
23089
  return null;
22216
23090
  }
22217
- }, within3 = (root, dir) => dir === root || dir.startsWith(root.endsWith(path32.sep) ? root : `${root}${path32.sep}`), hookCwd = (input) => {
23091
+ }, within3 = (root, dir) => dir === root || dir.startsWith(root.endsWith(path33.sep) ? root : `${root}${path33.sep}`), hookCwd = (input) => {
22218
23092
  const cwd = existingDirectory(input.cwd);
22219
23093
  if (cwd && input.hook_event_name === "beforeShellExecution")
22220
23094
  return cwd;