@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.
@@ -6739,8 +6739,8 @@ function requirementId(input) {
6739
6739
  import { realpathSync as realpathSync4 } from "node:fs";
6740
6740
 
6741
6741
  // packages/workit-core/src/core/policy/derive.ts
6742
- import { existsSync as existsSync2 } from "node:fs";
6743
- import path10 from "node:path";
6742
+ import { existsSync as existsSync3 } from "node:fs";
6743
+ import path11 from "node:path";
6744
6744
 
6745
6745
  // packages/workit-core/src/git/rev.ts
6746
6746
  import { spawnSync } from "node:child_process";
@@ -6903,6 +6903,124 @@ function resolveRef(cwd, ref) {
6903
6903
  return null;
6904
6904
  return line(git(cwd, ["rev-parse", "--verify", "-q", `${ref}^{commit}`]));
6905
6905
  }
6906
+ var LANE_DIFF = [
6907
+ "-c",
6908
+ "core.quotePath=false",
6909
+ "diff",
6910
+ "--no-color",
6911
+ "--no-ext-diff",
6912
+ "--no-textconv",
6913
+ "--no-renames"
6914
+ ];
6915
+ var laneRange = (fork, head) => {
6916
+ if (!safeArg(fork) || head !== null && !safeArg(head))
6917
+ return null;
6918
+ return head === null ? [fork] : [fork, head];
6919
+ };
6920
+ function diffNumstat(cwd, fork, head) {
6921
+ const range = laneRange(fork, head);
6922
+ if (!range)
6923
+ return null;
6924
+ const run = git(cwd, [...LANE_DIFF, "--numstat", "-z", ...range, "--"]);
6925
+ if (!run.ok)
6926
+ return null;
6927
+ const out = [];
6928
+ for (const record of run.stdout.split("\x00")) {
6929
+ const match = /^(-|\d+)\t(-|\d+)\t(.+)$/su.exec(record.replace(/^\n/u, ""));
6930
+ if (!match)
6931
+ continue;
6932
+ const binary = match[1] === "-";
6933
+ out.push({
6934
+ path: match[3],
6935
+ added: binary ? 0 : Number(match[1]),
6936
+ deleted: binary ? 0 : Number(match[2]),
6937
+ binary
6938
+ });
6939
+ }
6940
+ return out;
6941
+ }
6942
+ function diffRaw(cwd, fork, head) {
6943
+ const range = laneRange(fork, head);
6944
+ if (!range)
6945
+ return null;
6946
+ const run = git(cwd, [...LANE_DIFF, "--raw", "-z", "--no-abbrev", ...range, "--"]);
6947
+ if (!run.ok)
6948
+ return null;
6949
+ const fields = run.stdout.split("\x00");
6950
+ const out = [];
6951
+ for (let index = 0;index + 1 < fields.length; index += 2) {
6952
+ const meta = /^:(\d{6}) (\d{6}) ([0-9a-f]+) ([0-9a-f]+) [A-Z]\d*$/u.exec(fields[index].replace(/^\n/u, ""));
6953
+ if (!meta)
6954
+ return null;
6955
+ out.push({
6956
+ path: fields[index + 1],
6957
+ oldMode: meta[1],
6958
+ newMode: meta[2],
6959
+ oldBlob: meta[3],
6960
+ newBlob: meta[4]
6961
+ });
6962
+ }
6963
+ return out;
6964
+ }
6965
+ function readBlobs(cwd, ids) {
6966
+ const out = new Map;
6967
+ const wanted = [...new Set(ids)].filter((id) => /^[0-9a-f]{40,64}$/u.test(id));
6968
+ if (!wanted.length)
6969
+ return out;
6970
+ const run = spawnSync("git", ["cat-file", "--batch"], {
6971
+ cwd,
6972
+ input: `${wanted.join(`
6973
+ `)}
6974
+ `,
6975
+ maxBuffer: MAX_BUFFER,
6976
+ timeout: GIT_TIMEOUTS.local,
6977
+ killSignal: "SIGKILL",
6978
+ windowsHide: true
6979
+ });
6980
+ if (run.status !== 0 || !run.stdout)
6981
+ return null;
6982
+ const bytes = run.stdout;
6983
+ let at = 0;
6984
+ for (const id of wanted) {
6985
+ const end = bytes.indexOf(10, at);
6986
+ if (end < 0)
6987
+ return null;
6988
+ const header = bytes.subarray(at, end).toString("utf8").split(" ");
6989
+ at = end + 1;
6990
+ if (header[1] === "missing")
6991
+ continue;
6992
+ const size = Number(header[2]);
6993
+ if (header[0] !== id || !Number.isSafeInteger(size))
6994
+ return null;
6995
+ out.set(id, bytes.subarray(at, at + size));
6996
+ at += size + 1;
6997
+ }
6998
+ return out;
6999
+ }
7000
+ function treeFilesNamed(cwd, rev, name) {
7001
+ if (!safeArg(rev))
7002
+ return null;
7003
+ const run = git(cwd, ["ls-tree", "-r", "-z", "--full-tree", rev]);
7004
+ if (!run.ok)
7005
+ return null;
7006
+ const out = new Map;
7007
+ for (const record of run.stdout.split("\x00")) {
7008
+ const match = /^\d{6} blob ([0-9a-f]+)\t(.+)$/su.exec(record);
7009
+ if (match && (match[2] === name || match[2].endsWith(`/${name}`)))
7010
+ out.set(match[2], match[1]);
7011
+ }
7012
+ return out;
7013
+ }
7014
+ function fileAt(cwd, rev, file) {
7015
+ if (!safeArg(rev))
7016
+ return null;
7017
+ const run = git(cwd, ["cat-file", "blob", `${rev}:${file}`]);
7018
+ return run.ok ? run.stdout : null;
7019
+ }
7020
+ function untrackedFiles(cwd) {
7021
+ const run = git(cwd, ["ls-files", "-z", "--others", "--exclude-standard"]);
7022
+ return run.ok ? run.stdout.split("\x00").filter(Boolean) : [];
7023
+ }
6906
7024
  var config2 = (cwd, key) => line(git(cwd, ["config", "--get", key]));
6907
7025
  function currentBranch(cwd) {
6908
7026
  return line(git(cwd, ["symbolic-ref", "--short", "-q", "HEAD"]));
@@ -7716,7 +7834,7 @@ var workspaceConfigSchema = object({
7716
7834
  }).passthrough().optional(),
7717
7835
  autoApprove: union([boolean2(), array(nonBlank)]).optional(),
7718
7836
  defaultEndpoint: unknown().optional(),
7719
- verification: _enum(["self", "independent"]).optional(),
7837
+ verification: _enum(["proportional", "self", "independent"]).optional(),
7720
7838
  delegation: unknown().optional(),
7721
7839
  trailers: boolean2().optional(),
7722
7840
  liveSessionGuard: boolean2().optional(),
@@ -10011,7 +10129,8 @@ function checkVerdicts(cwd, branch, ledgerRows) {
10011
10129
  verdict: failing?.verdict ?? null,
10012
10130
  reasons: failing ? ["failing_verdict"] : !newestCurrent ? ["no_verdict"] : newestCurrent.reasons.length ? newestCurrent.reasons : ["type_check_only"]
10013
10131
  };
10014
- const selfEntry = failing ? undefined : verdicts.findLast((entry) => entry.current && !entry.independent && !untrusted(entry.reasons) && STRONG_RESULTS.has(String(entry.verdict.result)));
10132
+ 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))));
10133
+ const selfEntry = latestSelf && STRONG_RESULTS.has(String(latestSelf.verdict.result)) ? latestSelf : undefined;
10015
10134
  return {
10016
10135
  branch,
10017
10136
  head,
@@ -10055,12 +10174,682 @@ var OBSERVED_ONLY = new Set([
10055
10174
  ...PR_ROW_TYPES
10056
10175
  ]);
10057
10176
 
10177
+ // packages/workit-core/src/core/policy/lane.ts
10178
+ import { existsSync as existsSync2, readFileSync as readFileSync3 } from "node:fs";
10179
+ import path10 from "node:path";
10180
+ // packages/workit-core/src/forge/redact.ts
10181
+ var 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_.-]*`;
10182
+ var ASSIGNMENT = new RegExp(String.raw`(?<![A-Za-z0-9])(["']?${KEY}["']?\s*[:=]\s*["']?)((?:bearer|basic|token|digest)\s+)?([^\s"',;&]+)`, "giu");
10183
+ var QUOTED_ASSIGNMENT = new RegExp(String.raw`(?<![A-Za-z0-9])(["']?${KEY}["']?\s*[:=]\s*)(["'])([^"'\n]*[^\s"'][^"'\n]*)\2`, "giu");
10184
+ var ANSI = new RegExp(String.raw`\u001b\[[0-9;?]*[ -/]*[@-~]|\u001b\][^\u0007]*\u0007`, "gu");
10185
+
10186
+ // packages/workit-core/src/git/ops.ts
10187
+ var COMMIT_TIMEOUT_MS = 10 * 60000;
10188
+
10189
+ // packages/workit-core/src/core/policy/attributes.ts
10190
+ function patternRegex(dir, pattern) {
10191
+ if (!pattern || pattern.endsWith("/") || pattern.startsWith('"') || pattern.startsWith("!"))
10192
+ return null;
10193
+ const anchored = pattern.includes("/");
10194
+ const body = pattern.replace(/^\//u, "");
10195
+ let source = "";
10196
+ for (let index = 0;index < body.length; index += 1) {
10197
+ const char = body[index];
10198
+ if (char === "*" && body[index + 1] === "*") {
10199
+ const slash = body[index + 2] === "/";
10200
+ source += slash ? "(?:.*/)?" : ".*";
10201
+ index += slash ? 2 : 1;
10202
+ } else if (char === "*")
10203
+ source += "[^/]*";
10204
+ else if (char === "?")
10205
+ source += "[^/]";
10206
+ else if (char === "[") {
10207
+ const end = body.indexOf("]", index + 2);
10208
+ if (end < 0)
10209
+ return null;
10210
+ const set = body.slice(index + 1, end).replace(/^!/u, "^").replace(/\\/gu, "\\\\");
10211
+ source += `[${set}]`;
10212
+ index = end;
10213
+ } else if (char === "\\" && index + 1 < body.length) {
10214
+ source += body[index + 1].replace(/[.*+?^${}()|[\]\\/]/gu, "\\$&");
10215
+ index += 1;
10216
+ } else
10217
+ source += char.replace(/[.*+?^${}()|[\]\\/]/gu, "\\$&");
10218
+ }
10219
+ const prefix = dir ? `${dir.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")}/` : "";
10220
+ try {
10221
+ return new RegExp(anchored ? `^${prefix}${source}$` : `^${prefix}(?:.*/)?${source}$`, "u");
10222
+ } catch {
10223
+ return null;
10224
+ }
10225
+ }
10226
+ function rulesOf(dir, text) {
10227
+ const out = [];
10228
+ for (const raw of text.split(`
10229
+ `)) {
10230
+ const line = raw.trim();
10231
+ if (!line || line.startsWith("#") || line.startsWith("[attr]"))
10232
+ continue;
10233
+ const [pattern, ...attributes] = line.split(/\s+/u);
10234
+ let generated = null;
10235
+ for (const attribute of attributes) {
10236
+ if (attribute === "linguist-generated" || attribute === "linguist-generated=true")
10237
+ generated = true;
10238
+ else if (attribute === "-linguist-generated" || attribute === "!linguist-generated" || attribute.startsWith("linguist-generated="))
10239
+ generated = false;
10240
+ }
10241
+ if (generated === null)
10242
+ continue;
10243
+ const regex = patternRegex(dir, pattern);
10244
+ if (regex)
10245
+ out.push({ regex, generated });
10246
+ }
10247
+ return out;
10248
+ }
10249
+ function generatedByAttributes(files, paths) {
10250
+ const rules = [...files].map(([file, text]) => {
10251
+ const dir = file.includes("/") ? file.slice(0, file.lastIndexOf("/")) : "";
10252
+ return {
10253
+ depth: dir ? dir.split("/").length : 0,
10254
+ rules: rulesOf(dir, text)
10255
+ };
10256
+ }).toSorted((left, right) => left.depth - right.depth).flatMap((entry) => entry.rules);
10257
+ const out = new Set;
10258
+ for (const file of paths) {
10259
+ const last = rules.findLast((rule) => rule.regex.test(file));
10260
+ if (last?.generated)
10261
+ out.add(file);
10262
+ }
10263
+ return out;
10264
+ }
10265
+
10266
+ // packages/workit-core/src/core/policy/substance.ts
10267
+ var SLASH_BLOCK = [["/*", "*/"]];
10268
+ var C_LIKE = { line: ["//"], block: SLASH_BLOCK, quotes: `"'` };
10269
+ var SYNTAXES = Object.fromEntries([
10270
+ ...["ts", "mts", "cts", "js", "mjs", "cjs"].map((ext) => [ext, { ...C_LIKE, js: true }]),
10271
+ ...["java", "kt", "kts", "scala", "swift", "dart", "groovy"].map((ext) => [
10272
+ ext,
10273
+ { ...C_LIKE, triple: true }
10274
+ ]),
10275
+ ["go", { ...C_LIKE, rawBacktick: true }],
10276
+ ...["css", "scss", "less"].map((ext) => [
10277
+ ext,
10278
+ { line: [], block: SLASH_BLOCK, quotes: `"'`, cssUrl: true }
10279
+ ]),
10280
+ ...["py", "pyi"].map((ext) => [
10281
+ ext,
10282
+ { line: ["#"], block: [], quotes: `"'`, triple: true, indented: true, fstring: true }
10283
+ ]),
10284
+ ["toml", { line: ["#"], block: [], quotes: `"`, literal: "'", triple: true }],
10285
+ ...["html", "htm", "xml", "svg", "xhtml"].map((ext) => [
10286
+ ext,
10287
+ { line: [], block: [["<!--", "-->"]], quotes: "", indented: true }
10288
+ ])
10289
+ ]);
10290
+ var 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;
10291
+ var extensionOf = (file) => {
10292
+ const name = file.slice(file.lastIndexOf("/") + 1);
10293
+ const dot = name.lastIndexOf(".");
10294
+ return dot > 0 ? name.slice(dot + 1).toLowerCase() : "";
10295
+ };
10296
+ var CI_PATH = /^\.github\/|(?:^|\/)(?:\.gitlab-ci\.ya?ml|Jenkinsfile|azure-pipelines\.ya?ml|\.pre-commit-config\.ya?ml|\.circleci\/.*)$/u;
10297
+ var syntaxOf = (file) => CI_PATH.test(file) ? null : SYNTAXES[extensionOf(file)] ?? null;
10298
+ var SPACE = /[ \t\r\f\v]/u;
10299
+ var WORD = /[\w$]/u;
10300
+ var NO_SPACE_AFTER = "([{,;";
10301
+ var NO_SPACE_BEFORE = ")]},;";
10302
+ var REGEX_AFTER = "(,=:[!&|?{};+-*%<>~^";
10303
+ var REGEX_KEYWORDS = new Set([
10304
+ "return",
10305
+ "typeof",
10306
+ "instanceof",
10307
+ "case",
10308
+ "do",
10309
+ "else",
10310
+ "in",
10311
+ "of",
10312
+ "new",
10313
+ "delete",
10314
+ "void",
10315
+ "throw",
10316
+ "yield",
10317
+ "await"
10318
+ ]);
10319
+ function substanceOf(file, text) {
10320
+ const syntax = syntaxOf(file);
10321
+ if (!syntax)
10322
+ return plainSubstance(text);
10323
+ const markup = syntax.block.some(([open]) => open === "<!--");
10324
+ if (markup && (/<(?:script|style)\b|<!\[CDATA\[|<\?/iu.test(text) || /[^>\s][ \t]*<!--/u.test(text)))
10325
+ return plainSubstance(text);
10326
+ return lex(syntax, text);
10327
+ }
10328
+ function plainSubstance(text) {
10329
+ return text.split(`
10330
+ `).map((line) => line.replace(/[ \t\r\f\v]+$/u, "")).filter(Boolean).join(`
10331
+ `);
10332
+ }
10333
+ function lex(syntax, text) {
10334
+ const collapse = !syntax.indented;
10335
+ let out = "";
10336
+ let lineStart = 0;
10337
+ let kept = 0;
10338
+ let pendingSpace = false;
10339
+ const frames = [{ kind: "code", braces: 0 }];
10340
+ let index = 0;
10341
+ if (text.startsWith("#!")) {
10342
+ const end = text.indexOf(`
10343
+ `);
10344
+ out = end < 0 ? text : text.slice(0, end);
10345
+ kept = out.length;
10346
+ index = end < 0 ? text.length : end;
10347
+ }
10348
+ const emitCode = (chunk) => {
10349
+ if (collapse && pendingSpace && out.length > lineStart) {
10350
+ const before = out[out.length - 1];
10351
+ if (!NO_SPACE_AFTER.includes(before) && !NO_SPACE_BEFORE.includes(chunk[0]))
10352
+ out += " ";
10353
+ }
10354
+ pendingSpace = false;
10355
+ out += chunk;
10356
+ };
10357
+ const emitVerbatim = (chunk) => {
10358
+ emitCode(chunk);
10359
+ kept = out.length;
10360
+ };
10361
+ const newline = () => {
10362
+ if (!collapse) {
10363
+ let end = out.length;
10364
+ while (end > Math.max(lineStart, kept) && SPACE.test(out[end - 1]))
10365
+ end -= 1;
10366
+ out = out.slice(0, end);
10367
+ }
10368
+ pendingSpace = false;
10369
+ if (out.length > lineStart) {
10370
+ out += `
10371
+ `;
10372
+ lineStart = out.length;
10373
+ }
10374
+ };
10375
+ const regexAllowed = () => {
10376
+ let end = out.length;
10377
+ while (end > 0 && /\s/u.test(out[end - 1]))
10378
+ end -= 1;
10379
+ if (end === 0 || REGEX_AFTER.includes(out[end - 1]))
10380
+ return true;
10381
+ let start = end;
10382
+ while (start > 0 && WORD.test(out[start - 1]))
10383
+ start -= 1;
10384
+ return REGEX_KEYWORDS.has(out.slice(start, end));
10385
+ };
10386
+ const scanString = (quote, escapes, multiline) => {
10387
+ const prefix = text.slice(Math.max(0, index - 2), index).match(/[a-z]*$/iu)?.[0] ?? "";
10388
+ const fstring = syntax.fstring === true && /f/iu.test(prefix);
10389
+ let end = index + quote.length;
10390
+ while (end < text.length) {
10391
+ const char = text[end];
10392
+ if (escapes && char === "\\") {
10393
+ end += 2;
10394
+ continue;
10395
+ }
10396
+ if (text.startsWith(quote, end)) {
10397
+ if (fstring && unbalanced(text.slice(index + quote.length, end)))
10398
+ return false;
10399
+ emitVerbatim(text.slice(index, end + quote.length));
10400
+ index = end + quote.length;
10401
+ return true;
10402
+ }
10403
+ if (char === `
10404
+ ` && !multiline)
10405
+ return false;
10406
+ end += 1;
10407
+ }
10408
+ return false;
10409
+ };
10410
+ while (index < text.length) {
10411
+ const frame = frames[frames.length - 1];
10412
+ const char = text[index];
10413
+ if (frame.kind === "template") {
10414
+ if (char === "\\") {
10415
+ emitVerbatim(text.slice(index, index + 2));
10416
+ index += 2;
10417
+ } else if (char === "`") {
10418
+ emitVerbatim(char);
10419
+ frames.pop();
10420
+ index += 1;
10421
+ } else if (text.startsWith("${", index)) {
10422
+ emitVerbatim("${");
10423
+ frames.push({ kind: "code", braces: 0 });
10424
+ index += 2;
10425
+ } else {
10426
+ out += char;
10427
+ kept = out.length;
10428
+ index += 1;
10429
+ }
10430
+ continue;
10431
+ }
10432
+ if (char === `
10433
+ `) {
10434
+ newline();
10435
+ index += 1;
10436
+ continue;
10437
+ }
10438
+ if (SPACE.test(char)) {
10439
+ if (collapse)
10440
+ pendingSpace = true;
10441
+ else
10442
+ out += char;
10443
+ index += 1;
10444
+ continue;
10445
+ }
10446
+ const lineOpener = syntax.line.find((opener) => text.startsWith(opener, index));
10447
+ if (lineOpener) {
10448
+ const end = text.indexOf(`
10449
+ `, index);
10450
+ const comment = text.slice(index, end < 0 ? text.length : end);
10451
+ if (DIRECTIVE.test(comment.slice(lineOpener.length)))
10452
+ emitVerbatim(comment);
10453
+ else
10454
+ pendingSpace = true;
10455
+ index = end < 0 ? text.length : end;
10456
+ continue;
10457
+ }
10458
+ const block = syntax.block.find(([open]) => text.startsWith(open, index));
10459
+ if (block) {
10460
+ const end = text.indexOf(block[1], index + block[0].length);
10461
+ if (end < 0)
10462
+ return null;
10463
+ const comment = text.slice(index, end + block[1].length);
10464
+ if (DIRECTIVE.test(comment.slice(block[0].length, -block[1].length)))
10465
+ emitVerbatim(comment);
10466
+ else
10467
+ pendingSpace = true;
10468
+ if (comment.includes(`
10469
+ `))
10470
+ newline();
10471
+ index = end + block[1].length;
10472
+ continue;
10473
+ }
10474
+ if (syntax.triple && (char === '"' || char === "'") && text.startsWith(char.repeat(3), index)) {
10475
+ if (!scanString(char.repeat(3), !syntax.literal?.includes(char), true))
10476
+ return null;
10477
+ continue;
10478
+ }
10479
+ if (syntax.quotes.includes(char)) {
10480
+ if (!scanString(char, true, Boolean(syntax.multiline)))
10481
+ return null;
10482
+ continue;
10483
+ }
10484
+ if (syntax.literal?.includes(char)) {
10485
+ if (!scanString(char, false, false))
10486
+ return null;
10487
+ continue;
10488
+ }
10489
+ if (syntax.rawBacktick && char === "`") {
10490
+ if (!scanString("`", false, true))
10491
+ return null;
10492
+ continue;
10493
+ }
10494
+ if (syntax.js && char === "`") {
10495
+ emitVerbatim(char);
10496
+ frames.push({ kind: "template" });
10497
+ index += 1;
10498
+ continue;
10499
+ }
10500
+ if (syntax.cssUrl && /^url\(\s*[^"')\s]/iu.test(text.slice(index, index + 64)))
10501
+ return null;
10502
+ if (syntax.js && char === "/" && !regexAllowed() && out.trimEnd().endsWith(")")) {
10503
+ const lineEnd = text.indexOf(`
10504
+ `, index);
10505
+ if (text.slice(index + 1, lineEnd < 0 ? text.length : lineEnd).includes("/"))
10506
+ return null;
10507
+ }
10508
+ if (syntax.js && char === "/" && regexAllowed()) {
10509
+ let end = index + 1;
10510
+ let inClass = false;
10511
+ while (end < text.length && (inClass || text[end] !== "/")) {
10512
+ if (text[end] === `
10513
+ `)
10514
+ return null;
10515
+ if (text[end] === "\\")
10516
+ end += 1;
10517
+ else if (text[end] === "[")
10518
+ inClass = true;
10519
+ else if (text[end] === "]")
10520
+ inClass = false;
10521
+ end += 1;
10522
+ }
10523
+ if (end >= text.length)
10524
+ return null;
10525
+ emitVerbatim(text.slice(index, end + 1));
10526
+ index = end + 1;
10527
+ continue;
10528
+ }
10529
+ if (frames.length > 1 && frame.kind === "code") {
10530
+ if (char === "{")
10531
+ frame.braces += 1;
10532
+ else if (char === "}") {
10533
+ if (frame.braces === 0) {
10534
+ emitVerbatim(char);
10535
+ frames.pop();
10536
+ index += 1;
10537
+ continue;
10538
+ }
10539
+ frame.braces -= 1;
10540
+ }
10541
+ }
10542
+ emitCode(char);
10543
+ index += 1;
10544
+ }
10545
+ if (frames.length !== 1)
10546
+ return null;
10547
+ newline();
10548
+ return out;
10549
+ }
10550
+ function unbalanced(body) {
10551
+ let depth = 0;
10552
+ for (const part of body.replaceAll("{{", "").replaceAll("}}", "")) {
10553
+ if (part === "{")
10554
+ depth += 1;
10555
+ else if (part === "}")
10556
+ depth = Math.max(0, depth - 1);
10557
+ }
10558
+ return depth > 0;
10559
+ }
10560
+ function hasOpaqueLineBreak(text) {
10561
+ return /\r(?!\n)|[\u2028\u2029]/u.test(text);
10562
+ }
10563
+ var decoder = new TextDecoder("utf-8", { fatal: true });
10564
+ function textOf(bytes) {
10565
+ if (bytes.includes(0))
10566
+ return null;
10567
+ try {
10568
+ return decoder.decode(bytes);
10569
+ } catch {
10570
+ return null;
10571
+ }
10572
+ }
10573
+ function cosmeticChange(file, before, after) {
10574
+ const left = textOf(before);
10575
+ const right = textOf(after);
10576
+ if (left === null || right === null)
10577
+ return false;
10578
+ if (hasOpaqueLineBreak(left) || hasOpaqueLineBreak(right))
10579
+ return false;
10580
+ const a = substanceOf(file, left);
10581
+ return a !== null && a === substanceOf(file, right);
10582
+ }
10583
+
10584
+ // packages/workit-core/src/core/policy/lane.ts
10585
+ var LANE_THRESHOLDS = {
10586
+ selfMaxLines: 100,
10587
+ selfMaxFiles: 5,
10588
+ fullMinLines: 500
10589
+ };
10590
+ var RISK_TOKENS = new Set([
10591
+ "auth",
10592
+ "authn",
10593
+ "authz",
10594
+ "oauth",
10595
+ "security",
10596
+ "permission",
10597
+ "permissions",
10598
+ "secret",
10599
+ "secrets",
10600
+ "crypto",
10601
+ "gate",
10602
+ "gates",
10603
+ "policy",
10604
+ "policies",
10605
+ "hook",
10606
+ "hooks",
10607
+ "husky",
10608
+ "lefthook",
10609
+ "release",
10610
+ "releases",
10611
+ "migration",
10612
+ "migrations",
10613
+ "migrate",
10614
+ "workflows"
10615
+ ]);
10616
+ var RISK_FILES = new Set([
10617
+ ".gitlab-ci.yml",
10618
+ "Jenkinsfile",
10619
+ "azure-pipelines.yml",
10620
+ ".pre-commit-config.yaml",
10621
+ ".workit/risk-paths"
10622
+ ]);
10623
+ var RISK_NAMES = new Set([".gitattributes"]);
10624
+ var RISK_PATHS_FILE = ".workit/risk-paths";
10625
+ var LOCKFILES = new Set([
10626
+ "bun.lock",
10627
+ "bun.lockb",
10628
+ "package-lock.json",
10629
+ "npm-shrinkwrap.json",
10630
+ "yarn.lock",
10631
+ "pnpm-lock.yaml",
10632
+ "Cargo.lock",
10633
+ "go.sum",
10634
+ "poetry.lock",
10635
+ "uv.lock",
10636
+ "Pipfile.lock",
10637
+ "Gemfile.lock",
10638
+ "composer.lock"
10639
+ ]);
10640
+ var DOC_EXT = /\.(?:md|mdx|markdown|rst|adoc|txt)$/iu;
10641
+ var DOC_NAMES = /^(?:license|licence|notice|authors|changelog|changes|contributors)$/iu;
10642
+ var INSTRUCTIONS = /(?:^|\/)(?:AGENTS|CLAUDE|GEMINI|SKILL)\.md$|(?:^|\/)(?:skills|agents|commands|rules|prompts)\/[^/]+/iu;
10643
+ var TEST_PATH = /(?:^|\/)(?:test|tests|__tests__|spec|specs|fixtures)\/|\.(?:test|spec)\.[^/]+$/iu;
10644
+ var basename = (file) => file.slice(file.lastIndexOf("/") + 1);
10645
+ var isDoc = (file) => !INSTRUCTIONS.test(file) && (DOC_EXT.test(file) || DOC_NAMES.test(basename(file)));
10646
+ function kindOf(file) {
10647
+ if (file.binary)
10648
+ return "behavior";
10649
+ if (file.generated)
10650
+ return "generated";
10651
+ if (LOCKFILES.has(basename(file.path)))
10652
+ return "lockfile";
10653
+ if (isDoc(file.path))
10654
+ return "doc";
10655
+ if (file.cosmetic)
10656
+ return "cosmetic";
10657
+ return TEST_PATH.test(file.path) ? "test" : "behavior";
10658
+ }
10659
+ var globCache = new Map;
10660
+ function globMatch(pattern, file) {
10661
+ let regex = globCache.get(pattern);
10662
+ if (!regex) {
10663
+ let source = "";
10664
+ for (let index = 0;index < pattern.length; index += 1) {
10665
+ const char = pattern[index];
10666
+ if (char === "*" && pattern[index + 1] === "*") {
10667
+ source += pattern[index + 2] === "/" ? "(?:[^/]*/)*" : ".*";
10668
+ index += pattern[index + 2] === "/" ? 2 : 1;
10669
+ } else if (char === "*")
10670
+ source += "[^/]*";
10671
+ else if (char === "?")
10672
+ source += "[^/]";
10673
+ else
10674
+ source += char.replace(/[.+^${}()|[\]\\]/gu, "\\$&");
10675
+ }
10676
+ regex = new RegExp(`^${source}$`, "u");
10677
+ globCache.set(pattern, regex);
10678
+ }
10679
+ return regex.test(file) || file.startsWith(`${pattern.replace(/\/$/u, "")}/`);
10680
+ }
10681
+ function isRiskPath(file, extra = []) {
10682
+ if (extra.some((pattern) => globMatch(pattern, file)))
10683
+ return true;
10684
+ if (RISK_FILES.has(file) || RISK_NAMES.has(basename(file)))
10685
+ return true;
10686
+ if (TEST_PATH.test(file) || isDoc(file))
10687
+ return false;
10688
+ 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)));
10689
+ }
10690
+ var parseRiskPaths = (text) => text.split(`
10691
+ `).map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map((line) => line.replace(/^\//u, ""));
10692
+ function computeLane(input) {
10693
+ const riskFiles = input.files.filter((file) => isRiskPath(file.path, input.riskPaths)).map((file) => file.path);
10694
+ const risky = new Set(riskFiles);
10695
+ const kinds = input.files.map((file) => ({
10696
+ file,
10697
+ kind: risky.has(file.path) ? "behavior" : kindOf(file)
10698
+ }));
10699
+ const behavior = kinds.filter((entry) => entry.kind === "behavior" || entry.kind === "test" || entry.kind === "lockfile");
10700
+ const lines = behavior.filter((entry) => entry.kind !== "lockfile").reduce((sum, entry) => sum + entry.file.added + entry.file.deleted, 0);
10701
+ const opaque = behavior.filter((entry) => entry.kind === "lockfile" || entry.file.binary);
10702
+ const result = (lane, reasons) => ({
10703
+ lane,
10704
+ reasons,
10705
+ lines,
10706
+ files: behavior.length,
10707
+ riskFiles
10708
+ });
10709
+ const { selfMaxLines, selfMaxFiles, fullMinLines } = LANE_THRESHOLDS;
10710
+ if (input.riskTier === "high")
10711
+ return result("full", ["the task judgment records high risk"]);
10712
+ if (riskFiles.length)
10713
+ return result("full", [
10714
+ `touches a risk path: ${riskFiles.slice(0, 3).join(", ")}${riskFiles.length > 3 ? ", …" : ""}`
10715
+ ]);
10716
+ if (!behavior.length)
10717
+ return result("none", [
10718
+ input.files.length ? "only docs, comments, formatting or generated copies changed" : "no changes"
10719
+ ]);
10720
+ if (lines >= fullMinLines)
10721
+ return result("full", [`large diff: ${lines} lines (≥ ${fullMinLines})`]);
10722
+ if (lines > selfMaxLines)
10723
+ return result("focused", [`${lines} lines changed (> ${selfMaxLines})`]);
10724
+ if (behavior.length > selfMaxFiles)
10725
+ return result("focused", [`${behavior.length} behavior files changed (> ${selfMaxFiles})`]);
10726
+ if (opaque.length)
10727
+ return result("focused", [
10728
+ `a lockfile or binary changed: ${opaque.slice(0, 3).map((entry) => entry.file.path).join(", ")}${opaque.length > 3 ? ", …" : ""}`
10729
+ ]);
10730
+ return result("self", [
10731
+ `small change: ${lines} line${lines === 1 ? "" : "s"} in ${behavior.length} file${behavior.length === 1 ? "" : "s"}, no risk path`
10732
+ ]);
10733
+ }
10734
+ function untrackedStat(cwd, file) {
10735
+ try {
10736
+ const bytes = readFileSync3(path10.join(cwd, file));
10737
+ if (bytes.includes(0))
10738
+ return { path: file, added: 0, deleted: 0, binary: true };
10739
+ const text = bytes.toString("utf8");
10740
+ if (hasOpaqueLineBreak(text))
10741
+ return { path: file, added: 0, deleted: 0, binary: true };
10742
+ const lines = text.split(`
10743
+ `).length - (text.endsWith(`
10744
+ `) ? 1 : 0);
10745
+ return { path: file, added: lines, deleted: 0 };
10746
+ } catch {
10747
+ return { path: file, added: 0, deleted: 0, binary: true };
10748
+ }
10749
+ }
10750
+ var REGULAR = new Set(["100644", "100755"]);
10751
+ var ABSENT = /^0+$/u;
10752
+ function cosmeticFiles(cwd, fork, head) {
10753
+ const raw = diffRaw(cwd, fork, head);
10754
+ if (!raw)
10755
+ return null;
10756
+ const candidates = raw.filter((entry) => REGULAR.has(entry.oldMode) && entry.oldMode === entry.newMode && !ABSENT.test(entry.oldBlob) && (head === null || !ABSENT.test(entry.newBlob)));
10757
+ const blobs = readBlobs(cwd, candidates.flatMap((entry) => [entry.oldBlob, entry.newBlob]));
10758
+ if (!blobs)
10759
+ return null;
10760
+ const out = new Set;
10761
+ const opaque = new Set;
10762
+ for (const entry of candidates) {
10763
+ const before = blobs.get(entry.oldBlob);
10764
+ let after = blobs.get(entry.newBlob);
10765
+ if (!after && head === null && ABSENT.test(entry.newBlob))
10766
+ try {
10767
+ after = readFileSync3(path10.join(cwd, entry.path));
10768
+ } catch {
10769
+ after = undefined;
10770
+ }
10771
+ if (before && after && cosmeticChange(entry.path, before, after))
10772
+ out.add(entry.path);
10773
+ else if ([before, after].some((bytes) => bytes && hasOpaqueLineBreak(bytes.toString("utf8"))))
10774
+ opaque.add(entry.path);
10775
+ }
10776
+ return { cosmetic: out, opaque };
10777
+ }
10778
+ function generatedAt(cwd, fork, paths) {
10779
+ const files = treeFilesNamed(cwd, fork, ".gitattributes");
10780
+ const blobs = files?.size ? readBlobs(cwd, [...files.values()]) : null;
10781
+ if (!files || !blobs)
10782
+ return new Set;
10783
+ const texts = new Map;
10784
+ for (const [file, id] of files) {
10785
+ const bytes = blobs.get(id);
10786
+ if (bytes)
10787
+ texts.set(file, bytes.toString("utf8"));
10788
+ }
10789
+ return generatedByAttributes(texts, paths);
10790
+ }
10791
+ var forkOf = (cwd, base, head) => mergeBase(cwd, base, head ?? "HEAD");
10792
+ function laneFiles(cwd, fork, head) {
10793
+ const stats = diffNumstat(cwd, fork, head);
10794
+ const cosmetic = stats ? cosmeticFiles(cwd, fork, head) : null;
10795
+ if (!stats || !cosmetic)
10796
+ return null;
10797
+ const files = [
10798
+ ...stats.map((entry) => ({
10799
+ ...entry,
10800
+ ...cosmetic.opaque.has(entry.path) ? { binary: true } : {},
10801
+ cosmetic: !entry.binary && cosmetic.cosmetic.has(entry.path)
10802
+ })),
10803
+ ...head === null ? untrackedFiles(cwd).map((file) => untrackedStat(cwd, file)) : []
10804
+ ];
10805
+ const generated = generatedAt(cwd, fork, files.map((entry) => entry.path));
10806
+ return files.map((entry) => ({
10807
+ ...entry,
10808
+ generated: generated.has(entry.path)
10809
+ }));
10810
+ }
10811
+ function branchLane(cwd, options) {
10812
+ const candidates = options.base ? [`origin/${options.base}`, options.base] : [];
10813
+ const base = candidates.find((ref) => resolveRef(cwd, ref) !== null) ?? defaultBase(cwd) ?? null;
10814
+ const head = options.workingTree ? null : options.head;
10815
+ const fork = base && (options.workingTree || options.head) ? forkOf(cwd, base, head) : null;
10816
+ const files = fork ? laneFiles(cwd, fork, head) : null;
10817
+ const riskTier = options.judgment?.riskTier ?? null;
10818
+ if (!fork || !files) {
10819
+ const high = riskTier === "high";
10820
+ return {
10821
+ lane: high ? "full" : "focused",
10822
+ reasons: [
10823
+ `the diff of ${options.head?.slice(0, 12) ?? "(no head)"} against ${base ?? "(no base)"} cannot be read`,
10824
+ ...high ? ["the task judgment records high risk"] : []
10825
+ ],
10826
+ lines: 0,
10827
+ files: 0,
10828
+ riskFiles: [],
10829
+ base,
10830
+ head: options.head
10831
+ };
10832
+ }
10833
+ const repoRisk = parseRiskPaths(fileAt(cwd, fork, RISK_PATHS_FILE) ?? "");
10834
+ return {
10835
+ ...computeLane({
10836
+ files,
10837
+ riskTier,
10838
+ riskPaths: [...repoRisk, ...options.riskPaths ?? []]
10839
+ }),
10840
+ base,
10841
+ head: options.head
10842
+ };
10843
+ }
10844
+ var laneNeed = (lane) => lane === "none" ? "none" : lane === "self" ? "self" : "non-author";
10845
+
10058
10846
  // packages/workit-core/src/core/policy/derive.ts
10059
10847
  var RULES = {
10060
10848
  test: "check:test",
10061
10849
  self: "verdict:self",
10062
10850
  nonAuthor: "verdict:non-author",
10063
10851
  verified: "verdict:verified",
10852
+ lane: "verdict:lane",
10064
10853
  product: "decision:product",
10065
10854
  plan: "plan"
10066
10855
  };
@@ -10083,6 +10872,7 @@ var normalizedScope = (scope) => ({
10083
10872
  function deriveRequirements(judgment, scope, constraints, verification = "self") {
10084
10873
  const out = [];
10085
10874
  const base = { scope, dependentAction: null };
10875
+ const proportional = verification === "proportional";
10086
10876
  if (judgment.behaviorChange)
10087
10877
  out.push(derived2({
10088
10878
  ...base,
@@ -10093,7 +10883,17 @@ function deriveRequirements(judgment, scope, constraints, verification = "self")
10093
10883
  before: "close",
10094
10884
  acceptanceAllowed: false
10095
10885
  }));
10096
- if (judgment.behaviorChange && judgment.riskTier === "normal")
10886
+ if (proportional && judgment.riskTier === "normal")
10887
+ out.push(derived2({
10888
+ ...base,
10889
+ ruleId: RULES.lane,
10890
+ dimension: "review",
10891
+ 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.",
10892
+ 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.",
10893
+ before: "close",
10894
+ acceptanceAllowed: false
10895
+ }));
10896
+ if (!proportional && judgment.behaviorChange && judgment.riskTier === "normal")
10097
10897
  out.push(verification === "independent" ? derived2({
10098
10898
  ...base,
10099
10899
  ruleId: RULES.nonAuthor,
@@ -10196,7 +10996,7 @@ var productDecision = (task, ledger) => {
10196
10996
  };
10197
10997
  };
10198
10998
  var planRecorded = (task, root) => {
10199
- const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync2(path10.resolve(root, ref.path)));
10999
+ const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync3(path11.resolve(root, ref.path)));
10200
11000
  if (cited)
10201
11001
  return {
10202
11002
  met: true,
@@ -10210,14 +11010,30 @@ var planRecorded = (task, root) => {
10210
11010
  decisionIds: []
10211
11011
  };
10212
11012
  };
10213
- var verdict = (requirement, root, ledger) => {
11013
+ var workingLane = (task, root) => branchLane(root, { head: null, workingTree: true, judgment: latestJudgment(task) });
11014
+ var laneVerdict = (task, root, ledger) => {
11015
+ if (!ledger.branch() && latestJudgment(task)?.behaviorChange === false)
11016
+ return {
11017
+ met: true,
11018
+ reason: "no branch to read a lane from, and the judgment records no behavior change",
11019
+ decisionIds: []
11020
+ };
11021
+ const lane = workingLane(task, root);
11022
+ const label = `lane ${lane.lane} (${lane.reasons.join("; ")})`;
11023
+ const need = laneNeed(lane.lane);
11024
+ if (need === "none")
11025
+ return { met: true, reason: `${label}: no verdict needed`, decisionIds: [] };
11026
+ const status = verdict(need === "self" ? RULES.self : RULES.nonAuthor, root, ledger);
11027
+ return { ...status, reason: `${label}: ${status.reason}` };
11028
+ };
11029
+ var verdict = (ruleId, root, ledger) => {
10214
11030
  const branch = ledger.branch();
10215
11031
  if (!branch)
10216
11032
  return { met: false, reason: "no branch is checked out to hold a verdict", decisionIds: [] };
10217
11033
  const check = checkVerdicts(root, branch, ledger.rows());
10218
11034
  const failing = check.accepted.reasons.includes("failing_verdict");
10219
11035
  const strong = (entry) => STRONG_RESULTS.has(String(entry.verdict.result));
10220
- 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)));
11036
+ 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)));
10221
11037
  if (met)
10222
11038
  return {
10223
11039
  met: true,
@@ -10225,7 +11041,7 @@ var verdict = (requirement, root, ledger) => {
10225
11041
  decisionIds: []
10226
11042
  };
10227
11043
  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, " ");
10228
- 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>\``;
11044
+ 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>\``;
10229
11045
  return { met: false, reason: `${why}: ${unblock}`, decisionIds: [] };
10230
11046
  };
10231
11047
  function derivedRuleStatus(task, requirement, root, ledger) {
@@ -10237,7 +11053,9 @@ function derivedRuleStatus(task, requirement, root, ledger) {
10237
11053
  case RULES.self:
10238
11054
  case RULES.nonAuthor:
10239
11055
  case RULES.verified:
10240
- return verdict(requirement, root, ledger);
11056
+ return verdict(requirement.ruleId, root, ledger);
11057
+ case RULES.lane:
11058
+ return laneVerdict(task, root, ledger);
10241
11059
  default:
10242
11060
  return null;
10243
11061
  }
@@ -10812,7 +11630,7 @@ var judgeInputSummary = (raw) => {
10812
11630
 
10813
11631
  // packages/workit-core/src/autonomy.ts
10814
11632
  import os4 from "node:os";
10815
- import path11 from "node:path";
11633
+ import path12 from "node:path";
10816
11634
  var accountHome = () => {
10817
11635
  try {
10818
11636
  return os4.userInfo().homedir;
@@ -10821,10 +11639,10 @@ var accountHome = () => {
10821
11639
  }
10822
11640
  };
10823
11641
  var grantsHome = { resolve: accountHome };
10824
- var grantsDir = () => path11.join(grantsHome.resolve(), ".config", "workit");
11642
+ var grantsDir = () => path12.join(grantsHome.resolve(), ".config", "workit");
10825
11643
  var grantsOverride = () => {
10826
- const configured = path11.resolve(resolveConfigDir());
10827
- 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`;
11644
+ const configured = path12.resolve(resolveConfigDir());
11645
+ 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`;
10828
11646
  };
10829
11647
  var GRANT_KINDS = ["push", "pr", "merge", "release", "rerun"];
10830
11648
  var DEFAULT_GRANTS = Object.freeze({
@@ -10877,8 +11695,16 @@ function endpointView(entry, context) {
10877
11695
  ...issue ? { endpointIssue: issue } : {}
10878
11696
  };
10879
11697
  }
10880
- var DEFAULT_VERIFICATION = "self";
10881
- var verificationOf = (entry) => entry?.verification === "independent" ? "independent" : "self";
11698
+ var VERIFICATION_MODES = [
11699
+ "proportional",
11700
+ "self",
11701
+ "independent"
11702
+ ];
11703
+ var DEFAULT_VERIFICATION = "proportional";
11704
+ var verificationOf = (entry) => {
11705
+ const value = entry?.verification;
11706
+ return VERIFICATION_MODES.includes(value) ? value : DEFAULT_VERIFICATION;
11707
+ };
10882
11708
  var isGrantValue = (value) => value === true || value === false || value === "verified";
10883
11709
  var normalized = (kind, value) => value === "verified" && kind !== "merge" ? true : value;
10884
11710
  var fromAutoApprove = (value) => {
@@ -10950,7 +11776,7 @@ var grantHint = (workspace, kind) => `ask the user to run, in their own terminal
10950
11776
  // packages/workit-core/src/core/task-store.ts
10951
11777
  import { createHash as createHash11, randomUUID as randomUUID3 } from "node:crypto";
10952
11778
  import * as fs12 from "node:fs";
10953
- import path16 from "node:path";
11779
+ import path17 from "node:path";
10954
11780
 
10955
11781
  // node_modules/@openclaw/fs-safe/dist/errors.js
10956
11782
  var OPERATIONAL_CODES = new Set([
@@ -11001,7 +11827,7 @@ function sameFileIdentity(left, right, platform = process.platform) {
11001
11827
  // node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.js
11002
11828
  import { randomBytes as randomBytes3 } from "node:crypto";
11003
11829
  import fsSync from "node:fs";
11004
- import path12 from "node:path";
11830
+ import path13 from "node:path";
11005
11831
 
11006
11832
  // node_modules/@openclaw/fs-safe/dist/bounded-read.js
11007
11833
  import fs8 from "node:fs";
@@ -11091,13 +11917,13 @@ ${ownershipToken}
11091
11917
  return { raw, ownershipToken };
11092
11918
  }
11093
11919
  function relativeSidecarLockPath(lockRoot, lockPath) {
11094
- const resolved = path12.resolve(lockPath);
11095
- const lexicalRelative = path12.relative(lockRoot.rootDir, resolved);
11096
- const relative = lexicalRelative !== ".." && !lexicalRelative.startsWith(`..${path12.sep}`) && !path12.isAbsolute(lexicalRelative) ? lexicalRelative : path12.relative(lockRoot.rootReal, resolved);
11097
- if (!relative || relative === ".." || relative.startsWith(`..${path12.sep}`) || path12.isAbsolute(relative)) {
11920
+ const resolved = path13.resolve(lockPath);
11921
+ const lexicalRelative = path13.relative(lockRoot.rootDir, resolved);
11922
+ const relative = lexicalRelative !== ".." && !lexicalRelative.startsWith(`..${path13.sep}`) && !path13.isAbsolute(lexicalRelative) ? lexicalRelative : path13.relative(lockRoot.rootReal, resolved);
11923
+ if (!relative || relative === ".." || relative.startsWith(`..${path13.sep}`) || path13.isAbsolute(relative)) {
11098
11924
  throw new FsSafeError("outside-workspace", "sidecar lock path is outside lockRoot");
11099
11925
  }
11100
- return relative.split(path12.sep).join(path12.posix.sep);
11926
+ return relative.split(path13.sep).join(path13.posix.sep);
11101
11927
  }
11102
11928
  function parseSidecarLockPayload(raw, parser) {
11103
11929
  if (parser) {
@@ -11244,7 +12070,7 @@ function getFsSafeLockConfig() {
11244
12070
 
11245
12071
  // node_modules/@openclaw/fs-safe/dist/file-lock-sync.js
11246
12072
  import fs10 from "node:fs";
11247
- import path13 from "node:path";
12073
+ import path14 from "node:path";
11248
12074
 
11249
12075
  // node_modules/@openclaw/fs-safe/dist/timing.js
11250
12076
  function sleepSync(ms) {
@@ -11335,26 +12161,26 @@ function canonicalLockParentSync(parent) {
11335
12161
  return process.platform === "win32" ? fs10.realpathSync.native(parent) : fs10.realpathSync(parent);
11336
12162
  }
11337
12163
  function normalizeTargetPath(targetPath) {
11338
- const resolved = path13.resolve(targetPath);
11339
- fs10.mkdirSync(path13.dirname(resolved), { recursive: true });
12164
+ const resolved = path14.resolve(targetPath);
12165
+ fs10.mkdirSync(path14.dirname(resolved), { recursive: true });
11340
12166
  try {
11341
- return path13.join(canonicalLockParentSync(path13.dirname(resolved)), path13.basename(resolved));
12167
+ return path14.join(canonicalLockParentSync(path14.dirname(resolved)), path14.basename(resolved));
11342
12168
  } catch {
11343
12169
  return resolved;
11344
12170
  }
11345
12171
  }
11346
12172
  function boundedLockPath(lockPath, lockRoot) {
11347
- const resolved = path13.resolve(lockPath);
12173
+ const resolved = path14.resolve(lockPath);
11348
12174
  if (!lockRoot)
11349
12175
  return resolved;
11350
12176
  relativeSidecarLockPath(lockRoot, resolved);
11351
- const parent = path13.dirname(resolved);
12177
+ const parent = path14.dirname(resolved);
11352
12178
  const parentReal = canonicalLockParentSync(parent);
11353
- const parentRelative = path13.relative(lockRoot.rootReal, parentReal);
11354
- if (parentRelative === ".." || parentRelative.startsWith(`..${path13.sep}`) || path13.isAbsolute(parentRelative)) {
12179
+ const parentRelative = path14.relative(lockRoot.rootReal, parentReal);
12180
+ if (parentRelative === ".." || parentRelative.startsWith(`..${path14.sep}`) || path14.isAbsolute(parentRelative)) {
11355
12181
  throw new FsSafeError("outside-workspace", "sidecar lock parent is outside lockRoot");
11356
12182
  }
11357
- return path13.join(parentReal, path13.basename(resolved));
12183
+ return path14.join(parentReal, path14.basename(resolved));
11358
12184
  }
11359
12185
  function defaultShouldReclaim(snapshot, staleMs, nowMs) {
11360
12186
  const createdAtMs = sidecarLockPayloadCreatedAtMs(snapshot.payload);
@@ -11554,14 +12380,14 @@ function acquireFileLockSync(targetPath, options) {
11554
12380
  }
11555
12381
  }
11556
12382
  // packages/workit-core/src/core/package-root.ts
11557
- import { existsSync as existsSync3 } from "node:fs";
11558
- import path14 from "node:path";
12383
+ import { existsSync as existsSync4 } from "node:fs";
12384
+ import path15 from "node:path";
11559
12385
  import { fileURLToPath } from "node:url";
11560
12386
  var packageRoot = () => {
11561
- let dir = path14.dirname(fileURLToPath(import.meta.url));
12387
+ let dir = path15.dirname(fileURLToPath(import.meta.url));
11562
12388
  while (true) {
11563
- const parent = path14.dirname(dir);
11564
- if (existsSync3(path14.join(dir, "package.json")) || parent === dir)
12389
+ const parent = path15.dirname(dir);
12390
+ if (existsSync4(path15.join(dir, "package.json")) || parent === dir)
11565
12391
  return dir;
11566
12392
  dir = parent;
11567
12393
  }
@@ -11570,7 +12396,7 @@ var packageRoot = () => {
11570
12396
  // packages/workit-core/src/store/event-log.ts
11571
12397
  import { randomUUID as randomUUID2 } from "node:crypto";
11572
12398
  import fs11 from "node:fs";
11573
- import path15 from "node:path";
12399
+ import path16 from "node:path";
11574
12400
  var EVENT_VERSION = 1;
11575
12401
 
11576
12402
  class LogDamage extends Error {
@@ -11681,7 +12507,7 @@ function appendEvent(file, event, validEnd) {
11681
12507
  fs11.closeSync(fd);
11682
12508
  }
11683
12509
  if (created)
11684
- fsyncDirectory(path15.dirname(file));
12510
+ fsyncDirectory(path16.dirname(file));
11685
12511
  return validEnd;
11686
12512
  }
11687
12513
  function replaceFile(file, bytes, durable) {
@@ -11697,7 +12523,7 @@ function replaceFile(file, bytes, durable) {
11697
12523
  }
11698
12524
  renameWithRetry(temporary, file);
11699
12525
  if (durable)
11700
- fsyncDirectory(path15.dirname(file));
12526
+ fsyncDirectory(path16.dirname(file));
11701
12527
  } catch (error) {
11702
12528
  try {
11703
12529
  fs11.unlinkSync(temporary);
@@ -12040,7 +12866,7 @@ var cachedRuntimeVersion = null;
12040
12866
  var runtimeVersion = () => {
12041
12867
  if (cachedRuntimeVersion === null) {
12042
12868
  try {
12043
- const pkg = JSON.parse(fs12.readFileSync(path16.join(packageRoot(), "package.json"), "utf8"));
12869
+ const pkg = JSON.parse(fs12.readFileSync(path17.join(packageRoot(), "package.json"), "utf8"));
12044
12870
  cachedRuntimeVersion = typeof pkg.version === "string" && pkg.version ? pkg.version : "0.0.0";
12045
12871
  } catch {
12046
12872
  cachedRuntimeVersion = "0.0.0";
@@ -12073,7 +12899,7 @@ var readText = (file) => {
12073
12899
  };
12074
12900
  var REFLOG_LINE = /^[0-9a-f]+ ([0-9a-f]+) .* (\d+) [+-]\d{4}\t(.*)$/u;
12075
12901
  var branchStart = (location, branch, aliases) => {
12076
- const first = readText(path16.join(path16.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
12902
+ const first = readText(path17.join(path17.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
12077
12903
  `, 1)[0];
12078
12904
  const created = REFLOG_LINE.exec(first);
12079
12905
  const start = created && /^branch: Created from (\S+)$/u.exec(created[3])?.[1];
@@ -12083,7 +12909,7 @@ var branchStart = (location, branch, aliases) => {
12083
12909
  return start;
12084
12910
  if (!location.git)
12085
12911
  return null;
12086
- for (const line of readText(path16.join(location.git.gitDir, "logs", "HEAD")).split(`
12912
+ for (const line of readText(path17.join(location.git.gitDir, "logs", "HEAD")).split(`
12087
12913
  `)) {
12088
12914
  const entry = REFLOG_LINE.exec(line);
12089
12915
  const moved = entry && /^checkout: moving from (\S+) to (\S+)$/u.exec(entry[3]);
@@ -12093,14 +12919,14 @@ var branchStart = (location, branch, aliases) => {
12093
12919
  }
12094
12920
  return null;
12095
12921
  };
12096
- var refExists = (common, ref) => fs12.existsSync(path16.join(common, ref)) || readText(path16.join(common, "packed-refs")).includes(` ${ref}
12922
+ var refExists = (common, ref) => fs12.existsSync(path17.join(common, ref)) || readText(path17.join(common, "packed-refs")).includes(` ${ref}
12097
12923
  `);
12098
12924
  var origins = new Map;
12099
12925
  var sameDirectoryIdentity = (left, right) => {
12100
- if (!path16.isAbsolute(left) || !path16.isAbsolute(right))
12926
+ if (!path17.isAbsolute(left) || !path17.isAbsolute(right))
12101
12927
  return false;
12102
- const normalizedLeft = path16.resolve(left);
12103
- const normalizedRight = path16.resolve(right);
12928
+ const normalizedLeft = path17.resolve(left);
12929
+ const normalizedRight = path17.resolve(right);
12104
12930
  try {
12105
12931
  const a = fs12.statSync(normalizedLeft, { bigint: true });
12106
12932
  const b = fs12.statSync(normalizedRight, { bigint: true });
@@ -12146,7 +12972,7 @@ class TaskStore {
12146
12972
  migrationChecked = false;
12147
12973
  compactDue = new Set;
12148
12974
  constructor(root, options = {}) {
12149
- const resolved = path16.resolve(root);
12975
+ const resolved = path17.resolve(root);
12150
12976
  this.origin = fs12.existsSync(resolved) ? fs12.realpathSync(resolved) : resolved;
12151
12977
  this.located = resolveStore(this.origin);
12152
12978
  this.root = checkoutRootOf(this.origin, this.located);
@@ -12155,7 +12981,7 @@ class TaskStore {
12155
12981
  this.migrateOnRead = options.migrateOnRead;
12156
12982
  }
12157
12983
  location() {
12158
- if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs12.existsSync(path16.join(this.root, ".git"))) {
12984
+ if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs12.existsSync(path17.join(this.root, ".git"))) {
12159
12985
  this.located = undefined;
12160
12986
  this.migrationChecked = false;
12161
12987
  }
@@ -12311,7 +13137,7 @@ class TaskStore {
12311
13137
  const moved = this.bindLocked(again.data.id, key, input.now);
12312
13138
  return moved.ok ? success(moved.data.revision, null, { task: moved.data, created: false, key }) : moved;
12313
13139
  }
12314
- const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path16.basename(this.root) || this.root;
13140
+ const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path17.basename(this.root) || this.root;
12315
13141
  const intent = {
12316
13142
  objective: input.objective?.trim() || `Work on ${label}`,
12317
13143
  scope: { description: `the checkout (${label})`, paths: ["."], exclusions: [] },
@@ -12377,14 +13203,14 @@ class TaskStore {
12377
13203
  const branch = key.ok ? key.data.branch : null;
12378
13204
  if (!branch || !location.ok)
12379
13205
  return success(null, null, null);
12380
- const common = path16.dirname(location.data.dir);
12381
- const heads = path16.join(common, "logs", "refs", "heads");
12382
- const headLog = location.data.git ? path16.join(location.data.git.gitDir, "logs", "HEAD") : "";
13206
+ const common = path17.dirname(location.data.dir);
13207
+ const heads = path17.join(common, "logs", "refs", "heads");
13208
+ const headLog = location.data.git ? path17.join(location.data.git.gitDir, "logs", "HEAD") : "";
12383
13209
  const signatures = [
12384
- path16.join(heads, branch),
13210
+ path17.join(heads, branch),
12385
13211
  headLog,
12386
13212
  heads,
12387
- path16.join(common, "packed-refs")
13213
+ path17.join(common, "packed-refs")
12388
13214
  ].map((file) => fileSignature(file) ?? "-");
12389
13215
  const slot = `${location.data.dir}\x00${headLog}\x00${branch}`;
12390
13216
  let resolved = origins.get(slot);
@@ -12396,7 +13222,7 @@ class TaskStore {
12396
13222
  aliases.push(rename.from);
12397
13223
  const start = branchStart(location.data, branch, aliases);
12398
13224
  const slash = start?.indexOf("/") ?? -1;
12399
- 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)}"]`));
13225
+ 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)}"]`));
12400
13226
  const name = start && (remote ? start.slice(slash + 1) : start);
12401
13227
  resolved = {
12402
13228
  signature: signatures.join("|"),
@@ -12634,13 +13460,13 @@ class TaskStore {
12634
13460
  if (!ready.ok)
12635
13461
  return ready;
12636
13462
  const dirs = this.paths();
12637
- const recovery = path16.join(this.root, ".workit", "recovery");
13463
+ const recovery = path17.join(this.root, ".workit", "recovery");
12638
13464
  if (fs12.existsSync(recovery)) {
12639
13465
  let files = 0;
12640
13466
  let bytes = 0;
12641
13467
  try {
12642
13468
  for (const name of fs12.readdirSync(recovery)) {
12643
- const stat = fs12.lstatSync(path16.join(recovery, name));
13469
+ const stat = fs12.lstatSync(path17.join(recovery, name));
12644
13470
  if (!stat.isFile())
12645
13471
  continue;
12646
13472
  files += 1;
@@ -12693,7 +13519,7 @@ class TaskStore {
12693
13519
  if (fs12.existsSync(dirs.blobs))
12694
13520
  for (const name of fs12.readdirSync(dirs.blobs)) {
12695
13521
  const digest = name.replace(/\.json$/, "");
12696
- const file = path16.join(dirs.blobs, name);
13522
+ const file = path17.join(dirs.blobs, name);
12697
13523
  let stat;
12698
13524
  try {
12699
13525
  stat = fs12.lstatSync(file);
@@ -12711,7 +13537,7 @@ class TaskStore {
12711
13537
  }
12712
13538
  return success(null, null, null);
12713
13539
  };
12714
- const swept = dryRun ? sweep() : this.withLock(path16.join(dirs.dir, "gc.lock"), sweep);
13540
+ const swept = dryRun ? sweep() : this.withLock(path17.join(dirs.dir, "gc.lock"), sweep);
12715
13541
  if (!swept.ok)
12716
13542
  return swept;
12717
13543
  const temporaryDirs = [
@@ -12719,7 +13545,7 @@ class TaskStore {
12719
13545
  dirs.tasks,
12720
13546
  dirs.blobs,
12721
13547
  dirs.checkout,
12722
- ...names.map((name) => path16.join(dirs.tasks, name))
13548
+ ...names.map((name) => path17.join(dirs.tasks, name))
12723
13549
  ];
12724
13550
  for (const directory of temporaryDirs) {
12725
13551
  if (!fs12.existsSync(directory))
@@ -12727,7 +13553,7 @@ class TaskStore {
12727
13553
  for (const name of fs12.readdirSync(directory)) {
12728
13554
  if (!name.endsWith(".tmp") && !name.endsWith(".probe"))
12729
13555
  continue;
12730
- const file = path16.join(directory, name);
13556
+ const file = path17.join(directory, name);
12731
13557
  try {
12732
13558
  const stat = fs12.lstatSync(file);
12733
13559
  if (!stat.isFile() || nowMs - stat.mtimeMs <= STALE_TEMPORARY_MS)
@@ -12744,30 +13570,30 @@ class TaskStore {
12744
13570
  }
12745
13571
  paths() {
12746
13572
  const location = this.location();
12747
- const dir = location.ok ? location.data.dir : path16.join(this.root, ".workit");
12748
- const checkout = path16.join(dir, "checkouts", checkoutSlug(this.root));
13573
+ const dir = location.ok ? location.data.dir : path17.join(this.root, ".workit");
13574
+ const checkout = path17.join(dir, "checkouts", checkoutSlug(this.root));
12749
13575
  return {
12750
13576
  dir,
12751
13577
  shared: location.ok ? location.data.shared : false,
12752
- marker: path16.join(dir, "store.json"),
13578
+ marker: path17.join(dir, "store.json"),
12753
13579
  checkout,
12754
- workspace: path16.join(checkout, "workspace.json"),
12755
- checkoutLock: path16.join(checkout, "metadata.lock"),
12756
- tasks: path16.join(dir, "tasks"),
12757
- index: path16.join(dir, "task-index.json"),
12758
- blobs: path16.join(dir, "blobs", "candidates"),
12759
- legacy: path16.join(dir, "legacy", checkoutSlug(this.root), "v2"),
12760
- v2: path16.join(this.root, ".workit")
13580
+ workspace: path17.join(checkout, "workspace.json"),
13581
+ checkoutLock: path17.join(checkout, "metadata.lock"),
13582
+ tasks: path17.join(dir, "tasks"),
13583
+ index: path17.join(dir, "task-index.json"),
13584
+ blobs: path17.join(dir, "blobs", "candidates"),
13585
+ legacy: path17.join(dir, "legacy", checkoutSlug(this.root), "v2"),
13586
+ v2: path17.join(this.root, ".workit")
12761
13587
  };
12762
13588
  }
12763
13589
  eventsPath(taskId) {
12764
- return path16.join(this.paths().tasks, taskId, "events.jsonl");
13590
+ return path17.join(this.paths().tasks, taskId, "events.jsonl");
12765
13591
  }
12766
13592
  snapshotPath(taskId) {
12767
- return path16.join(this.paths().tasks, taskId, "snapshot.json");
13593
+ return path17.join(this.paths().tasks, taskId, "snapshot.json");
12768
13594
  }
12769
13595
  taskLockPath(taskId) {
12770
- return path16.join(this.paths().tasks, taskId, "lock");
13596
+ return path17.join(this.paths().tasks, taskId, "lock");
12771
13597
  }
12772
13598
  ready(write = false) {
12773
13599
  const location = this.location();
@@ -12806,13 +13632,13 @@ class TaskStore {
12806
13632
  return {
12807
13633
  read: (digest) => {
12808
13634
  try {
12809
- return JSON.parse(fs12.readFileSync(path16.join(dir, `${digest}.json`), "utf8"));
13635
+ return JSON.parse(fs12.readFileSync(path17.join(dir, `${digest}.json`), "utf8"));
12810
13636
  } catch (error) {
12811
13637
  throw new LogDamage(`stored candidate ${digest} is missing or unreadable: ${String(error)}`);
12812
13638
  }
12813
13639
  },
12814
13640
  write: (digest, value) => {
12815
- const file = path16.join(dir, `${digest}.json`);
13641
+ const file = path17.join(dir, `${digest}.json`);
12816
13642
  if (fs12.existsSync(file)) {
12817
13643
  const stamp = new Date;
12818
13644
  try {
@@ -13004,7 +13830,7 @@ class TaskStore {
13004
13830
  }
13005
13831
  }
13006
13832
  openTask(record, type, key, legacy = null) {
13007
- const dir = path16.join(this.paths().tasks, record.id);
13833
+ const dir = path17.join(this.paths().tasks, record.id);
13008
13834
  fs12.mkdirSync(dir, { recursive: true });
13009
13835
  const blobs = this.blobStore();
13010
13836
  const bound = key ? { ...key, boundAt: key.boundAt ?? new Date().toISOString() } : null;
@@ -13097,7 +13923,7 @@ class TaskStore {
13097
13923
  }
13098
13924
  withKeyLock(key, operation) {
13099
13925
  const digest = createHash11("sha256").update(key).digest("hex").slice(0, 32);
13100
- return this.withLock(path16.join(this.paths().dir, "keys", `${digest}.lock`), operation);
13926
+ return this.withLock(path17.join(this.paths().dir, "keys", `${digest}.lock`), operation);
13101
13927
  }
13102
13928
  bindLocked(taskId, key, timestamp) {
13103
13929
  const current = this.readWorkspace();
@@ -13238,7 +14064,7 @@ class TaskStore {
13238
14064
  writeWorkspace(record) {
13239
14065
  const file = this.paths().workspace;
13240
14066
  try {
13241
- fs12.mkdirSync(path16.dirname(file), { recursive: true });
14067
+ fs12.mkdirSync(path17.dirname(file), { recursive: true });
13242
14068
  replaceFile(file, `${canonicalJson(record)}
13243
14069
  `, true);
13244
14070
  return success(null, null, null);
@@ -13316,23 +14142,23 @@ class TaskStore {
13316
14142
  return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", { expectedWorkspaceRevision: expected, actualWorkspaceRevision: actual });
13317
14143
  }
13318
14144
  v2Dirs() {
13319
- return [...new Set([this.root, this.origin])].map((dir) => path16.join(dir, ".workit"));
14145
+ return [...new Set([this.root, this.origin])].map((dir) => path17.join(dir, ".workit"));
13320
14146
  }
13321
14147
  pendingMigrations() {
13322
14148
  return this.v2Dirs().filter((dir) => {
13323
- const raw = this.readV2Workspace(path16.join(dir, "workspace.json"));
14149
+ const raw = this.readV2Workspace(path17.join(dir, "workspace.json"));
13324
14150
  return raw !== null && raw !== TOMBSTONE;
13325
14151
  });
13326
14152
  }
13327
14153
  migrateV2(v2) {
13328
14154
  const dirs = this.paths();
13329
- const v2Workspace = path16.join(v2, "workspace.json");
13330
- const v2Tasks = path16.join(v2, "tasks");
13331
- const legacy = path16.join(dirs.dir, "legacy", checkoutSlug(path16.dirname(v2)), "v2");
14155
+ const v2Workspace = path17.join(v2, "workspace.json");
14156
+ const v2Tasks = path17.join(v2, "tasks");
14157
+ const legacy = path17.join(dirs.dir, "legacy", checkoutSlug(path17.dirname(v2)), "v2");
13332
14158
  const raw = this.readV2Workspace(v2Workspace);
13333
14159
  if (raw === null || raw === TOMBSTONE)
13334
14160
  return success(null, null, null);
13335
- return this.withLock(dirs.checkoutLock, () => this.withLock(path16.join(v2, "metadata.lock"), () => {
14161
+ return this.withLock(dirs.checkoutLock, () => this.withLock(path17.join(v2, "metadata.lock"), () => {
13336
14162
  const workspace = this.readV2Workspace(v2Workspace);
13337
14163
  if (workspace === null || workspace === TOMBSTONE)
13338
14164
  return success(null, null, null);
@@ -13341,7 +14167,7 @@ class TaskStore {
13341
14167
  return failure2("recovery_required", `cannot migrate the 2.x store at ${v2}: ${parsedWorkspace.error}; move it aside to start fresh`, { path: v2Workspace });
13342
14168
  let files = [];
13343
14169
  try {
13344
- files = fs12.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path16.join(v2Tasks, name)));
14170
+ files = fs12.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path17.join(v2Tasks, name)));
13345
14171
  } catch {}
13346
14172
  const current = this.readWorkspace();
13347
14173
  if (!current.ok)
@@ -13359,21 +14185,21 @@ class TaskStore {
13359
14185
  let skipped = 0;
13360
14186
  const done = new Map;
13361
14187
  try {
13362
- fs12.mkdirSync(path16.join(legacy, "tasks"), { recursive: true });
14188
+ fs12.mkdirSync(path17.join(legacy, "tasks"), { recursive: true });
13363
14189
  for (const name of ["workspace.json", "index.json"])
13364
- if (fs12.existsSync(path16.join(v2, name)))
13365
- fs12.copyFileSync(path16.join(v2, name), path16.join(legacy, name));
14190
+ if (fs12.existsSync(path17.join(v2, name)))
14191
+ fs12.copyFileSync(path17.join(v2, name), path17.join(legacy, name));
13366
14192
  for (const name of files) {
13367
14193
  const id = name.slice(0, -5);
13368
- const file = path16.join(v2Tasks, name);
14194
+ const file = path17.join(v2Tasks, name);
13369
14195
  const bytes = fs12.readFileSync(file, "utf8");
13370
14196
  const digest = sha256(bytes);
13371
- fs12.writeFileSync(path16.join(legacy, "tasks", name), bytes);
14197
+ fs12.writeFileSync(path17.join(legacy, "tasks", name), bytes);
13372
14198
  const parsed = this.parseRecord(bytes, taskRecordSchema, "2.x task");
13373
14199
  if (!parsed.ok || parsed.data.id !== id)
13374
14200
  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 });
13375
14201
  const record = { ...parsed.data, workspaceId: target.id };
13376
- const origin = { path: path16.join(legacy, "tasks", name), digest };
14202
+ const origin = { path: path17.join(legacy, "tasks", name), digest };
13377
14203
  if (!fs12.existsSync(this.eventsPath(id))) {
13378
14204
  this.openTask(record, "migrated.from_v2", null, origin);
13379
14205
  migrated += 1;
@@ -13409,7 +14235,7 @@ class TaskStore {
13409
14235
  try {
13410
14236
  let complete = true;
13411
14237
  for (const [name, digest] of done) {
13412
- const file = path16.join(v2Tasks, name);
14238
+ const file = path17.join(v2Tasks, name);
13413
14239
  if (sha256(fs12.readFileSync(file, "utf8")) !== digest) {
13414
14240
  complete = false;
13415
14241
  continue;
@@ -13420,7 +14246,7 @@ class TaskStore {
13420
14246
  return failure2("busy", `the 2.x store at ${v2} changed during migration; retry`, {
13421
14247
  path: v2
13422
14248
  });
13423
- fs12.rmSync(path16.join(v2, "index.json"), { force: true });
14249
+ fs12.rmSync(path17.join(v2, "index.json"), { force: true });
13424
14250
  this.writeTombstone(v2, target.id);
13425
14251
  } catch (error) {
13426
14252
  return failure2("storage_error", `cannot finish the 2.x migration: ${String(error)}`, {
@@ -13440,7 +14266,7 @@ class TaskStore {
13440
14266
  }
13441
14267
  adoptLocalStore() {
13442
14268
  const dirs = this.paths();
13443
- const marker = path16.join(dirs.v2, "store.json");
14269
+ const marker = path17.join(dirs.v2, "store.json");
13444
14270
  if (!dirs.shared || !fs12.existsSync(marker))
13445
14271
  return success(null, null, null);
13446
14272
  return this.withLock(dirs.checkoutLock, () => {
@@ -13450,7 +14276,7 @@ class TaskStore {
13450
14276
  try {
13451
14277
  const merge = (from, to) => {
13452
14278
  if (!fs12.existsSync(to)) {
13453
- fs12.mkdirSync(path16.dirname(to), { recursive: true });
14279
+ fs12.mkdirSync(path17.dirname(to), { recursive: true });
13454
14280
  try {
13455
14281
  fs12.renameSync(from, to);
13456
14282
  } catch {
@@ -13461,24 +14287,24 @@ class TaskStore {
13461
14287
  }
13462
14288
  if (fs12.lstatSync(from).isDirectory() && fs12.lstatSync(to).isDirectory())
13463
14289
  for (const name of fs12.readdirSync(from))
13464
- merge(path16.join(from, name), path16.join(to, name));
14290
+ merge(path17.join(from, name), path17.join(to, name));
13465
14291
  };
13466
14292
  for (const sub of ["tasks", "checkouts", "blobs", "legacy"]) {
13467
- const from = path16.join(dirs.v2, sub);
14293
+ const from = path17.join(dirs.v2, sub);
13468
14294
  if (!fs12.existsSync(from))
13469
14295
  continue;
13470
14296
  if (sub === "tasks") {
13471
14297
  for (const name of fs12.readdirSync(from))
13472
- if (validId(name) && !fs12.existsSync(path16.join(dirs.dir, sub, name)))
14298
+ if (validId(name) && !fs12.existsSync(path17.join(dirs.dir, sub, name)))
13473
14299
  tasks += 1;
13474
14300
  }
13475
- merge(from, path16.join(dirs.dir, sub));
14301
+ merge(from, path17.join(dirs.dir, sub));
13476
14302
  }
13477
- const ledger = path16.join(dirs.v2, "ledger");
13478
- if (fs12.existsSync(ledger) && !fs12.existsSync(path16.join(dirs.dir, "ledger")))
13479
- merge(ledger, path16.join(dirs.dir, "ledger"));
13480
- fs12.rmSync(path16.join(dirs.v2, "task-index.json"), { force: true });
13481
- fs12.renameSync(marker, path16.join(dirs.v2, "store.moved.json"));
14303
+ const ledger = path17.join(dirs.v2, "ledger");
14304
+ if (fs12.existsSync(ledger) && !fs12.existsSync(path17.join(dirs.dir, "ledger")))
14305
+ merge(ledger, path17.join(dirs.dir, "ledger"));
14306
+ fs12.rmSync(path17.join(dirs.v2, "task-index.json"), { force: true });
14307
+ fs12.renameSync(marker, path17.join(dirs.v2, "store.moved.json"));
13482
14308
  } catch (error) {
13483
14309
  return failure2("storage_error", `cannot move ${dirs.v2} into ${dirs.dir}: ${String(error)}`, {
13484
14310
  path: dirs.v2
@@ -13516,7 +14342,7 @@ class TaskStore {
13516
14342
  schemaVersion: SCHEMA_VERSION,
13517
14343
  id: workspaceId ?? newId(),
13518
14344
  revision: newRevision(),
13519
- root: path16.dirname(v2),
14345
+ root: path17.dirname(v2),
13520
14346
  runtime: { createdWith: version, updatedWith: version },
13521
14347
  writer: null,
13522
14348
  store: {
@@ -13528,11 +14354,11 @@ class TaskStore {
13528
14354
  critical: ["store"]
13529
14355
  };
13530
14356
  fs12.mkdirSync(v2, { recursive: true });
13531
- const ignore = path16.join(v2, ".gitignore");
14357
+ const ignore = path17.join(v2, ".gitignore");
13532
14358
  if (!fs12.existsSync(ignore))
13533
14359
  fs12.writeFileSync(ignore, `*
13534
14360
  `);
13535
- replaceFile(path16.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
14361
+ replaceFile(path17.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
13536
14362
  `, true);
13537
14363
  }
13538
14364
  stubFor(taskId) {
@@ -13556,8 +14382,8 @@ class TaskStore {
13556
14382
  }
13557
14383
  writeTombstoneIfMissing() {
13558
14384
  try {
13559
- const v2 = path16.join(this.root, ".workit");
13560
- if (fs12.existsSync(path16.join(v2, "workspace.json")))
14385
+ const v2 = path17.join(this.root, ".workit");
14386
+ if (fs12.existsSync(path17.join(v2, "workspace.json")))
13561
14387
  return;
13562
14388
  let id = null;
13563
14389
  try {
@@ -13574,7 +14400,7 @@ class TaskStore {
13574
14400
  replaceFile(dirs.marker, `${JSON.stringify({ format: "workit-store", version: STORE_FORMAT, createdWith: runtimeVersion() })}
13575
14401
  `, false);
13576
14402
  if (!dirs.shared) {
13577
- const ignore = path16.join(dirs.dir, ".gitignore");
14403
+ const ignore = path17.join(dirs.dir, ".gitignore");
13578
14404
  let current = null;
13579
14405
  try {
13580
14406
  current = fs12.readFileSync(ignore, "utf8");
@@ -13634,7 +14460,7 @@ class TaskStore {
13634
14460
  withLock(lockPath, operation) {
13635
14461
  try {
13636
14462
  this.initializeStorage();
13637
- fs12.mkdirSync(path16.dirname(lockPath), { recursive: true });
14463
+ fs12.mkdirSync(path17.dirname(lockPath), { recursive: true });
13638
14464
  } catch (error) {
13639
14465
  return failure2("storage_error", `unable to initialize store: ${String(error)}`, {
13640
14466
  path: this.paths().dir
@@ -13697,7 +14523,7 @@ class TaskStore {
13697
14523
  if (isTransientWindowsError(error) && !this.lockHolderPresent(lockPath) && !this.lockDirWritable(lockPath))
13698
14524
  return failure2("storage_error", `cannot create the workit lock (${code}); no other Workit call holds it`, {
13699
14525
  path: lockPath,
13700
- guidance: `Check permissions and the read-only attribute on ${path16.dirname(lockPath)}.`
14526
+ guidance: `Check permissions and the read-only attribute on ${path17.dirname(lockPath)}.`
13701
14527
  });
13702
14528
  if (code === "EEXIST" || code === "file_lock_timeout" || code === "file_lock_stale" || isTransientWindowsError(error)) {
13703
14529
  let lock = null;
@@ -13724,18 +14550,18 @@ var workerBlocksTransition = (transition, state) => transition === "pause" ? fal
13724
14550
  import { createHash as createHash12 } from "node:crypto";
13725
14551
  import * as fs14 from "node:fs";
13726
14552
  import { spawnSync as spawnSync10 } from "node:child_process";
13727
- import path18 from "node:path";
14553
+ import path19 from "node:path";
13728
14554
 
13729
14555
  // packages/workit-core/src/check-config.ts
13730
14556
  import { spawnSync as spawnSync9 } from "node:child_process";
13731
14557
  import fs13 from "node:fs";
13732
- import path17 from "node:path";
14558
+ import path18 from "node:path";
13733
14559
  var SCRIPT_CHECKS = ["test", "lint", "typecheck", "check"];
13734
14560
  var CHECKS_FILE = ".workit/checks.json";
13735
14561
  var LEGACY_CHECKS_FILE = "workit.checks.json";
13736
14562
  function checksConfigFile(root) {
13737
- const current = path17.join(root, CHECKS_FILE);
13738
- const legacy = path17.join(root, LEGACY_CHECKS_FILE);
14563
+ const current = path18.join(root, CHECKS_FILE);
14564
+ const legacy = path18.join(root, LEGACY_CHECKS_FILE);
13739
14565
  return !fs13.existsSync(current) && fs13.existsSync(legacy) ? legacy : current;
13740
14566
  }
13741
14567
  function repoHeavyCommands(root) {
@@ -13786,7 +14612,7 @@ function splitCommand(command) {
13786
14612
  argv.push(current);
13787
14613
  return argv.length ? argv : new Error("empty command");
13788
14614
  }
13789
- var git4 = (cwd, args) => {
14615
+ var git5 = (cwd, args) => {
13790
14616
  const run = spawnSync9("git", args, {
13791
14617
  cwd,
13792
14618
  encoding: "utf8",
@@ -13798,10 +14624,10 @@ var git4 = (cwd, args) => {
13798
14624
  return value || null;
13799
14625
  };
13800
14626
  function checkRoot(cwd) {
13801
- return path17.resolve(git4(cwd, ["rev-parse", "--show-toplevel"]) ?? cwd);
14627
+ return path18.resolve(git5(cwd, ["rev-parse", "--show-toplevel"]) ?? cwd);
13802
14628
  }
13803
14629
  var packageManager = (root) => {
13804
- const has = (file) => fs13.existsSync(path17.join(root, file));
14630
+ const has = (file) => fs13.existsSync(path18.join(root, file));
13805
14631
  if (has("bun.lock") || has("bun.lockb"))
13806
14632
  return "bun";
13807
14633
  if (has("pnpm-lock.yaml"))
@@ -13821,7 +14647,7 @@ var CHECK_NAME = /^[a-z0-9][a-z0-9:._-]{0,63}$/u;
13821
14647
  function detectedChecks(root) {
13822
14648
  const read = (file) => {
13823
14649
  try {
13824
- return fs13.readFileSync(path17.join(root, file), "utf8");
14650
+ return fs13.readFileSync(path18.join(root, file), "utf8");
13825
14651
  } catch {
13826
14652
  return null;
13827
14653
  }
@@ -13861,7 +14687,7 @@ var GATES = ["testing", "verification"];
13861
14687
  function loadCheckConfig(cwd) {
13862
14688
  const root = checkRoot(cwd);
13863
14689
  const file = checksConfigFile(root);
13864
- const legacy = path17.basename(file) === LEGACY_CHECKS_FILE;
14690
+ const legacy = path18.basename(file) === LEGACY_CHECKS_FILE;
13865
14691
  const label = legacy ? LEGACY_CHECKS_FILE : CHECKS_FILE;
13866
14692
  const note = legacy ? {
13867
14693
  note: `${LEGACY_CHECKS_FILE} is deprecated; move it to ${CHECKS_FILE} (workit doctor --fix)`
@@ -13939,10 +14765,10 @@ function workitAvailable(env = process.env) {
13939
14765
  return workitOnPath;
13940
14766
  const windows = process.platform === "win32";
13941
14767
  const exts = windows ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
13942
- const dirs = (env.PATH ?? env.Path ?? "").split(path17.delimiter).filter(Boolean);
14768
+ const dirs = (env.PATH ?? env.Path ?? "").split(path18.delimiter).filter(Boolean);
13943
14769
  workitOnPath = dirs.some((dir) => exts.some((ext) => {
13944
14770
  try {
13945
- return fs13.statSync(path17.join(dir, `workit${ext}`)).isFile();
14771
+ return fs13.statSync(path18.join(dir, `workit${ext}`)).isFile();
13946
14772
  } catch {
13947
14773
  return false;
13948
14774
  }
@@ -13955,14 +14781,14 @@ function checkCommand(args, version, onPath = workitAvailable()) {
13955
14781
 
13956
14782
  // packages/workit-core/src/core/task-evaluation.ts
13957
14783
  var digestBytes = (value) => createHash12("sha256").update(value).digest("hex");
13958
- var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path18.sep}`);
13959
- var relative = (root, candidate) => path18.relative(root, candidate).split(path18.sep).join("/") || ".";
14784
+ var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path19.sep}`);
14785
+ var relative = (root, candidate) => path19.relative(root, candidate).split(path19.sep).join("/") || ".";
13960
14786
  var canonicalPath = (value) => {
13961
14787
  if (typeof value !== "string" || !value)
13962
14788
  return null;
13963
14789
  if (value.includes("\\") || value.split("/").includes(".."))
13964
14790
  return null;
13965
- const normalized = path18.posix.normalize(value);
14791
+ const normalized = path19.posix.normalize(value);
13966
14792
  if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
13967
14793
  return null;
13968
14794
  return normalized === "." ? "." : normalized.replace(/\/$/, "");
@@ -14010,14 +14836,14 @@ var gitPaths = (root) => {
14010
14836
  git: !/not a git repository/i.test(stderr)
14011
14837
  };
14012
14838
  }
14013
- const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path18.sep).join("/")) : [];
14839
+ const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path19.sep).join("/")) : [];
14014
14840
  const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
14015
14841
  if (stagedDeleted.status !== 0) {
14016
14842
  const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
14017
14843
  if (!/not a git repository/i.test(stderr))
14018
14844
  return { paths, uncertain: true, git: true };
14019
14845
  } else if (stagedDeleted.stdout) {
14020
- paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path18.sep).join("/")));
14846
+ paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path19.sep).join("/")));
14021
14847
  }
14022
14848
  return { paths: [...new Set(paths)], uncertain: false, git: true };
14023
14849
  };
@@ -14032,7 +14858,7 @@ var walk = (root, directory, output) => {
14032
14858
  for (const name of names) {
14033
14859
  if (name === ".git" || name === ".workit")
14034
14860
  continue;
14035
- const target = path18.join(directory, name);
14861
+ const target = path19.join(directory, name);
14036
14862
  let stat;
14037
14863
  try {
14038
14864
  stat = fs14.lstatSync(target);
@@ -14050,12 +14876,12 @@ var walk = (root, directory, output) => {
14050
14876
  var scopeRoots = (root, scope) => {
14051
14877
  const roots = [];
14052
14878
  for (const item of scope.paths.length ? scope.paths : ["."]) {
14053
- const target = path18.resolve(root, item);
14879
+ const target = path19.resolve(root, item);
14054
14880
  if (!inside(root, target))
14055
14881
  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` }] });
14056
14882
  let ancestor = target;
14057
14883
  while (!fs14.existsSync(ancestor) && ancestor !== root)
14058
- ancestor = path18.dirname(ancestor);
14884
+ ancestor = path19.dirname(ancestor);
14059
14885
  try {
14060
14886
  if (!inside(root, fs14.realpathSync(ancestor)))
14061
14887
  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` }] });
@@ -14107,7 +14933,7 @@ function captureCandidate(root, scope, environment = []) {
14107
14933
  for (const item of [...names].toSorted()) {
14108
14934
  if (!scopeMatches(item, normalizedScope))
14109
14935
  continue;
14110
- const target = path18.join(checkout, item);
14936
+ const target = path19.join(checkout, item);
14111
14937
  try {
14112
14938
  const stat = fs14.lstatSync(target);
14113
14939
  if (stat.isSymbolicLink()) {
@@ -14291,23 +15117,23 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
14291
15117
  continue;
14292
15118
  if (!reference.digest)
14293
15119
  return failure2("invalid_input", "document references require a byte digest");
14294
- const target = path18.resolve(root, reference.path);
14295
- if (target !== root && !target.startsWith(`${root}${path18.sep}`))
15120
+ const target = path19.resolve(root, reference.path);
15121
+ if (target !== root && !target.startsWith(`${root}${path19.sep}`))
14296
15122
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
14297
15123
  fields: [
14298
15124
  { path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
14299
15125
  ]
14300
15126
  });
14301
15127
  try {
14302
- const below = path18.relative(root, target);
15128
+ const below = path19.relative(root, target);
14303
15129
  let current = root;
14304
- for (const segment of below.split(path18.sep)) {
15130
+ for (const segment of below.split(path19.sep)) {
14305
15131
  if (!segment)
14306
15132
  continue;
14307
- current = path18.join(current, segment);
15133
+ current = path19.join(current, segment);
14308
15134
  const stat = fs14.lstatSync(current);
14309
15135
  const real = fs14.realpathSync(current);
14310
- if (real !== root && !real.startsWith(`${root}${path18.sep}`))
15136
+ if (real !== root && !real.startsWith(`${root}${path19.sep}`))
14311
15137
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
14312
15138
  fields: [
14313
15139
  {
@@ -14740,9 +15566,9 @@ Autonomy contract:
14740
15566
  Prose is a note: only a configured check the CLI ran (\`workit check <name>\`)
14741
15567
  satisfies a gate; an ad-hoc \`workit check -- <cmd>\` never does.
14742
15568
  - Author is not verifier: your own verdict is \`--self\`, shown as
14743
- self-reviewed, never verified. High risk, \`verification: independent\` and
14744
- merge need a verifier with its own host-derived session (a subagent's
14745
- \`<lead>:<child>\`); never hand-mint one (\`<lead>-v1\`).
15569
+ self-reviewed, never verified. High risk, a focused or full lane and
15570
+ merge under \`verification: self|independent\` need a verifier with its
15571
+ own host-derived session (a subagent's \`<lead>:<child>\`); never hand-mint one (\`<lead>-v1\`).
14746
15572
  - A local-commit endpoint does not imply PR readiness, and a local commit alone
14747
15573
  is not evidence of a requested remote push. Before reporting delivery,
14748
15574
  reconcile every requested item and observe it (\`workit verify-delivery\`).
@@ -16608,7 +17434,7 @@ var capabilitiesFor = (descriptor, observed = {}) => descriptor.capabilities.map
16608
17434
  // packages/workit-core/src/hooks/context.ts
16609
17435
  import { createHash as createHash13 } from "node:crypto";
16610
17436
  import fs15 from "node:fs";
16611
- import path19 from "node:path";
17437
+ import path20 from "node:path";
16612
17438
  var MIGRATION_PENDING_NOTE = "workit migration pending — run `workit task status`";
16613
17439
  var migrationPending = (result) => !result.ok && result.code === "needs_input" && (result.error ?? "").startsWith(MIGRATION_PENDING);
16614
17440
  var boundTo = (entry, session) => entry.sessions.some((item) => item.host === session.host && item.handle === session.handle);
@@ -16693,7 +17519,7 @@ function entryCompactContext(store, entry, session, context) {
16693
17519
  return null;
16694
17520
  const freshness = { mode: "signal", current: () => recentSignal(store.root) };
16695
17521
  const observed = task?.data.evidence.some(isObservedCheck) ?? false;
16696
- const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [path19.resolve(store.root, ref.path)] : []));
17522
+ const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [path20.resolve(store.root, ref.path)] : []));
16697
17523
  const observedFiles = filesKey(files);
16698
17524
  const compact = new WorkitCore(store, context).compactContext(entry?.id ?? null, freshness, origin && { origin: origin.origin, taskId: origin.entry.id });
16699
17525
  if (!compact.ok || !compact.data)
@@ -16771,14 +17597,14 @@ var turnMarker = (input) => {
16771
17597
  if (location instanceof Error)
16772
17598
  return null;
16773
17599
  const session = [input.host, input.session.id, input.session.agentId ?? ""].join("\x00");
16774
- return path19.join(location.dir, "hooks", `turn-${digestOf(session).slice(0, 32)}.json`);
17600
+ return path20.join(location.dir, "hooks", `turn-${digestOf(session).slice(0, 32)}.json`);
16775
17601
  } catch {
16776
17602
  return null;
16777
17603
  }
16778
17604
  };
16779
17605
  var writeTurnDigest = (file, digest) => {
16780
17606
  try {
16781
- fs15.mkdirSync(path19.dirname(file), { recursive: true });
17607
+ fs15.mkdirSync(path20.dirname(file), { recursive: true });
16782
17608
  fs15.writeFileSync(file, `${JSON.stringify({ digest })}
16783
17609
  `);
16784
17610
  } catch {}
@@ -16793,7 +17619,7 @@ var pruneTurnDigests = (dir, now) => {
16793
17619
  for (const name of fs15.readdirSync(dir)) {
16794
17620
  if (!name.startsWith("turn-"))
16795
17621
  continue;
16796
- const file = path19.join(dir, name);
17622
+ const file = path20.join(dir, name);
16797
17623
  try {
16798
17624
  if (now - fs15.statSync(file).mtimeMs > TURN_TTL_MS)
16799
17625
  fs15.rmSync(file, { force: true });
@@ -16823,7 +17649,7 @@ var seedTurnContext = (input, descriptor, text = turnContextText(input, descript
16823
17649
  const file = turnMarker(input);
16824
17650
  if (!file)
16825
17651
  return;
16826
- pruneTurnDigests(path19.dirname(file), Date.now());
17652
+ pruneTurnDigests(path20.dirname(file), Date.now());
16827
17653
  if (text)
16828
17654
  writeTurnDigest(file, digestOf(text));
16829
17655
  else
@@ -16831,20 +17657,20 @@ var seedTurnContext = (input, descriptor, text = turnContextText(input, descript
16831
17657
  };
16832
17658
  // packages/workit-core/src/core/route-intent.ts
16833
17659
  import { spawnSync as spawnSync12 } from "node:child_process";
16834
- import { existsSync as existsSync6 } from "node:fs";
16835
- import path22 from "node:path";
17660
+ import { existsSync as existsSync7 } from "node:fs";
17661
+ import path23 from "node:path";
16836
17662
 
16837
17663
  // packages/workit-core/src/hooks/raw-git.ts
16838
17664
  import { spawnSync as spawnSync11 } from "node:child_process";
16839
17665
  import { createHash as createHash15 } from "node:crypto";
16840
17666
  import fs17 from "node:fs";
16841
17667
  import os5 from "node:os";
16842
- import path21 from "node:path";
17668
+ import path22 from "node:path";
16843
17669
 
16844
17670
  // packages/workit-core/src/hooks/session-marker.ts
16845
17671
  import { createHash as createHash14 } from "node:crypto";
16846
17672
  import fs16 from "node:fs";
16847
- import path20 from "node:path";
17673
+ import path21 from "node:path";
16848
17674
  var sessionMarkerFile = (input, session, store) => {
16849
17675
  let dir = store;
16850
17676
  if (dir === undefined) {
@@ -16854,7 +17680,7 @@ var sessionMarkerFile = (input, session, store) => {
16854
17680
  dir = location.dir;
16855
17681
  }
16856
17682
  const name = createHash14("sha256").update(`${input.host}\x00${session}`).digest("hex").slice(0, 32);
16857
- return path20.join(dir, "hooks", `skills-${name}.json`);
17683
+ return path21.join(dir, "hooks", `skills-${name}.json`);
16858
17684
  };
16859
17685
  var list2 = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
16860
17686
  var EMPTY = { nudged: [], loaded: [], raw: [], stops: [], judges: [] };
@@ -16881,7 +17707,7 @@ var parseMarker = (text) => {
16881
17707
  };
16882
17708
  var readSessionMarker = (file) => parseMarker(readRaw(file));
16883
17709
  var writeAtomic = (file, marker) => {
16884
- fs16.mkdirSync(path20.dirname(file), { recursive: true });
17710
+ fs16.mkdirSync(path21.dirname(file), { recursive: true });
16885
17711
  const temp = `${file}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
16886
17712
  try {
16887
17713
  fs16.writeFileSync(temp, JSON.stringify(marker));
@@ -17409,17 +18235,17 @@ var GIT_VALUE_OPTIONS = new Set([
17409
18235
  ]);
17410
18236
  var GIT_CONFIG_OPTIONS = new Set(["-c", "--config-env", "--git-dir"]);
17411
18237
  var GIT_CONFIG_ENV = /^GIT_(?:CONFIG\w*|DIR|COMMON_DIR|WORK_TREE)$/;
17412
- var ASSIGNMENT = /^([A-Za-z_]\w*)=([\s\S]*)$/;
18238
+ var ASSIGNMENT2 = /^([A-Za-z_]\w*)=([\s\S]*)$/;
17413
18239
  var MAX_DEPTH = 4;
17414
18240
  var MAX_EXPANSIONS = 16;
17415
- var isAbsolute = (value) => path21.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\");
18241
+ var isAbsolute = (value) => path22.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\");
17416
18242
  var HERE = /^(?:\$PWD|\$\{PWD\}|\$\(\s*pwd\s*\)|`pwd`|\$\(\s*git\s+rev-parse\s+--show-toplevel\s*\))(?=$|[\\/])/;
17417
18243
  var joinDir = (base, raw) => {
17418
18244
  const next = raw.replace(HERE, ".");
17419
18245
  if (base === undefined || /[$`*?]/.test(next) || next === "-")
17420
18246
  return;
17421
- const expanded = next === "~" || next.startsWith("~/") ? path21.join(os5.homedir(), next.slice(1)) : next;
17422
- return base === null || isAbsolute(expanded) ? expanded : path21.join(base, expanded);
18247
+ const expanded = next === "~" || next.startsWith("~/") ? path22.join(os5.homedir(), next.slice(1)) : next;
18248
+ return base === null || isAbsolute(expanded) ? expanded : path22.join(base, expanded);
17423
18249
  };
17424
18250
  var rebase = (base, inner) => inner === null ? base : inner === undefined ? undefined : joinDir(base, inner);
17425
18251
  var cdTarget = (words) => {
@@ -17436,7 +18262,7 @@ var stripPrefixes = (input) => {
17436
18262
  const first = words[0];
17437
18263
  if (first === undefined)
17438
18264
  return { words, env };
17439
- const assignment = ASSIGNMENT.exec(first);
18265
+ const assignment = ASSIGNMENT2.exec(first);
17440
18266
  if (assignment) {
17441
18267
  if (GIT_CONFIG_ENV.test(assignment[1]))
17442
18268
  env[assignment[1]] = assignment[2];
@@ -17495,10 +18321,10 @@ var assignments = (words, vars) => {
17495
18321
  while (rest[0]?.startsWith("-"))
17496
18322
  rest = rest.slice(1);
17497
18323
  }
17498
- if (rest.length === 0 || !rest.every((word) => ASSIGNMENT.test(word)))
18324
+ if (rest.length === 0 || !rest.every((word) => ASSIGNMENT2.test(word)))
17499
18325
  return null;
17500
18326
  return rest.map((word) => {
17501
- const [, name, value] = ASSIGNMENT.exec(word);
18327
+ const [, name, value] = ASSIGNMENT2.exec(word);
17502
18328
  return [name, expandWord(value, vars)];
17503
18329
  });
17504
18330
  };
@@ -17686,7 +18512,7 @@ var splitString = (line) => {
17686
18512
  return line.slice(index).join(" ").slice(15);
17687
18513
  if (/^-S./.test(word))
17688
18514
  return [word.slice(2), ...line.slice(index + 1)].join(" ");
17689
- if (!word.startsWith("-") && !ASSIGNMENT.test(word))
18515
+ if (!word.startsWith("-") && !ASSIGNMENT2.test(word))
17690
18516
  return null;
17691
18517
  }
17692
18518
  return null;
@@ -18270,17 +19096,17 @@ var headSha2 = (repo) => {
18270
19096
  if (!git || git.reftable)
18271
19097
  return null;
18272
19098
  try {
18273
- const head = fs17.readFileSync(path21.join(git.gitDir, "HEAD"), "utf8").trim();
19099
+ const head = fs17.readFileSync(path22.join(git.gitDir, "HEAD"), "utf8").trim();
18274
19100
  if (/^[0-9a-f]{40,64}$/.test(head))
18275
19101
  return head;
18276
19102
  const ref = /^ref: (refs\/.+)$/.exec(head)?.[1];
18277
19103
  if (!ref)
18278
19104
  return null;
18279
- const common = path21.dirname(repo.location.dir);
19105
+ const common = path22.dirname(repo.location.dir);
18280
19106
  try {
18281
- return fs17.readFileSync(path21.join(common, ref), "utf8").trim() || null;
19107
+ return fs17.readFileSync(path22.join(common, ref), "utf8").trim() || null;
18282
19108
  } catch {}
18283
- const packed = fs17.readFileSync(path21.join(common, "packed-refs"), "utf8");
19109
+ const packed = fs17.readFileSync(path22.join(common, "packed-refs"), "utf8");
18284
19110
  return new RegExp(`^([0-9a-f]{40,64}) ${ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`, "m").exec(packed)?.[1] ?? null;
18285
19111
  } catch {
18286
19112
  return null;
@@ -18368,7 +19194,7 @@ var expandGitAliases = (root, invocation, cache = new Map, depth = 0) => {
18368
19194
  const sub = invocation.args[0];
18369
19195
  if (invocation.tool !== "git" || invocation.dir === undefined || !sub || sub.startsWith("-") || GIT_COMMANDS.has(sub) || depth >= MAX_DEPTH)
18370
19196
  return [invocation];
18371
- const dir = path21.resolve(root, invocation.dir ?? ".");
19197
+ const dir = path22.resolve(root, invocation.dir ?? ".");
18372
19198
  if (!fs17.existsSync(dir))
18373
19199
  return [invocation];
18374
19200
  const config = gitConfig(dir, invocation, cache);
@@ -18391,11 +19217,11 @@ var expandGitAliases = (root, invocation, cache = new Map, depth = 0) => {
18391
19217
  var normalizedUrl = (url, dir) => {
18392
19218
  const trimmed = url.trim();
18393
19219
  if (/^file:\/\//i.test(trimmed))
18394
- return path21.resolve(dir, trimmed.slice(7)).replace(/\/+$/, "").replace(/\.git$/, "");
19220
+ return path22.resolve(dir, trimmed.slice(7)).replace(/\/+$/, "").replace(/\.git$/, "");
18395
19221
  const scheme = /^[a-z][a-z0-9+.-]*:\/\//i.exec(trimmed);
18396
19222
  const scp = !scheme && /^(?:[^@/\\]+@)?[^/\\:]{2,}:/.test(trimmed);
18397
19223
  if (!scheme && !scp)
18398
- return path21.resolve(dir, trimmed).replace(/\/+$/, "").replace(/\.git$/, "");
19224
+ return path22.resolve(dir, trimmed).replace(/\/+$/, "").replace(/\.git$/, "");
18399
19225
  const value = scheme ? trimmed.slice(scheme[0].length).replace(/^[^@/]*@/, "").replace(/^([^/:]+):\d+(?=\/)/, "$1") : trimmed.replace(/^[^@/]*@/, "").replace(":", "/");
18400
19226
  return value.toLowerCase().replace(/\/{2,}/g, "/").replace(/^www\./, "").replace(/\/+$/, "").replace(/\.git$/, "");
18401
19227
  };
@@ -18415,7 +19241,7 @@ var rewrittenUrl = (url, config) => {
18415
19241
  }
18416
19242
  return url;
18417
19243
  };
18418
- var pushUrl = (config, remote, dir) => {
19244
+ var pushUrl2 = (config, remote, dir) => {
18419
19245
  const configured = configValue(config, `remote.${remote}.pushurl`) ?? configValue(config, `remote.${remote}.url`);
18420
19246
  return normalizedUrl(rewrittenUrl(configured ?? remote, config), dir);
18421
19247
  };
@@ -18443,7 +19269,7 @@ var toPushRemote = (repo, remote, config) => {
18443
19269
  const pushRemote = pushRemoteOf(config, repo.branch);
18444
19270
  if (pushRemote === null || pushRemote === remote)
18445
19271
  return true;
18446
- return pushUrl(config, remote, repo.dir) === pushUrl(config, pushRemote, repo.dir);
19272
+ return pushUrl2(config, remote, repo.dir) === pushUrl2(config, pushRemote, repo.dir);
18447
19273
  };
18448
19274
  var quote = (text) => `\`${text}\``;
18449
19275
  var refusal = (action, branch, dir) => {
@@ -18619,7 +19445,7 @@ var actionsIn = (cwd, command, dialect, cache = new Map) => {
18619
19445
  const out = [];
18620
19446
  const repos = new Map;
18621
19447
  const repoFor = (relative) => {
18622
- const dir = path21.resolve(cwd, relative ?? ".");
19448
+ const dir = path22.resolve(cwd, relative ?? ".");
18623
19449
  if (!repos.has(dir)) {
18624
19450
  const repo = repoAt(dir);
18625
19451
  repos.set(dir, repo && isWorkitWorkspace(repo) ? repo : null);
@@ -18705,7 +19531,7 @@ var analysisDenial = (error) => ({
18705
19531
  });
18706
19532
  var NEXT_COMMAND = "next";
18707
19533
  var MARKER_TTL_SECONDS = 3600;
18708
- var markerFile = (repo, session, key) => path21.join(repo.location.dir, "hooks", `commit-${createHash15("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`);
19534
+ var markerFile = (repo, session, key) => path22.join(repo.location.dir, "hooks", `commit-${createHash15("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`);
18709
19535
  var callKey = (toolUseId, command) => toolUseId ?? `cmd:${createHash15("sha256").update(command).digest("hex")}`;
18710
19536
  function noteRawCommit(input, command, key) {
18711
19537
  try {
@@ -18716,7 +19542,7 @@ function noteRawCommit(input, command, key) {
18716
19542
  if (action.kind !== "commit")
18717
19543
  continue;
18718
19544
  const file = markerFile(repo, input.session.id, key);
18719
- fs17.mkdirSync(path21.dirname(file), { recursive: true });
19545
+ fs17.mkdirSync(path22.dirname(file), { recursive: true });
18720
19546
  fs17.writeFileSync(file, `${JSON.stringify({ head: headSha2(repo), at })}
18721
19547
  `);
18722
19548
  }
@@ -18947,8 +19773,8 @@ var judgedDir = (root, dir) => {
18947
19773
  return null;
18948
19774
  if (dir === null)
18949
19775
  return root;
18950
- const resolved = path22.resolve(root, dir);
18951
- return existsSync6(resolved) && inWorkitWorkspace(resolved) ? resolved : null;
19776
+ const resolved = path23.resolve(root, dir);
19777
+ return existsSync7(resolved) && inWorkitWorkspace(resolved) ? resolved : null;
18952
19778
  };
18953
19779
  var shellBranchPolicyViolation = (root, command, dialect = "posix") => {
18954
19780
  let judged = false;
@@ -18984,7 +19810,7 @@ var shellPolicy = (cwd, command, dialect = "posix") => {
18984
19810
  // packages/workit-core/src/core/heavy-rules.ts
18985
19811
  import fs18 from "node:fs";
18986
19812
  import os6 from "node:os";
18987
- import path23 from "node:path";
19813
+ import path24 from "node:path";
18988
19814
  var EMPTY2 = () => ({ deny: [], allow: [] });
18989
19815
  var readText2 = (file) => {
18990
19816
  try {
@@ -19025,19 +19851,19 @@ function parseJsonc(text) {
19025
19851
  return JSON.parse(out.replace(/,(\s*[}\]])/gu, "$1"));
19026
19852
  }
19027
19853
  function gitTop(cwd) {
19028
- for (let dir = path23.resolve(cwd);; dir = path23.dirname(dir)) {
19029
- if (fs18.existsSync(path23.join(dir, ".git")))
19854
+ for (let dir = path24.resolve(cwd);; dir = path24.dirname(dir)) {
19855
+ if (fs18.existsSync(path24.join(dir, ".git")))
19030
19856
  return dir;
19031
- if (path23.dirname(dir) === dir)
19857
+ if (path24.dirname(dir) === dir)
19032
19858
  return null;
19033
19859
  }
19034
19860
  }
19035
19861
  var projectDirs = (cwd) => {
19036
19862
  const top = gitTop(cwd);
19037
19863
  const dirs = [];
19038
- for (let dir = path23.resolve(cwd);; dir = path23.dirname(dir)) {
19864
+ for (let dir = path24.resolve(cwd);; dir = path24.dirname(dir)) {
19039
19865
  dirs.push(dir);
19040
- if (!top || dir === top || path23.dirname(dir) === dir)
19866
+ if (!top || dir === top || path24.dirname(dir) === dir)
19041
19867
  return dirs;
19042
19868
  }
19043
19869
  };
@@ -19049,12 +19875,12 @@ var CLAUDE_MANAGED = {
19049
19875
  };
19050
19876
  function claudeSettingsFiles(cwd, env, platform = process.platform) {
19051
19877
  const project = env.CLAUDE_PROJECT_DIR || gitTop(cwd) || cwd;
19052
- const user = env.CLAUDE_CONFIG_DIR || path23.join(homeOf(env), ".claude");
19878
+ const user = env.CLAUDE_CONFIG_DIR || path24.join(homeOf(env), ".claude");
19053
19879
  return [
19054
19880
  ...CLAUDE_MANAGED[platform] ? [CLAUDE_MANAGED[platform]] : [],
19055
- path23.join(user, "settings.json"),
19056
- path23.join(project, ".claude", "settings.json"),
19057
- path23.join(project, ".claude", "settings.local.json")
19881
+ path24.join(user, "settings.json"),
19882
+ path24.join(project, ".claude", "settings.json"),
19883
+ path24.join(project, ".claude", "settings.local.json")
19058
19884
  ];
19059
19885
  }
19060
19886
  var bashPattern = (entry) => {
@@ -19144,10 +19970,10 @@ var opencodeConfig = (value, rules) => {
19144
19970
  function opencodeRules(cwd, env = process.env) {
19145
19971
  const rules = EMPTY2();
19146
19972
  try {
19147
- const config = env.XDG_CONFIG_HOME || path23.join(homeOf(env), ".config");
19973
+ const config = env.XDG_CONFIG_HOME || path24.join(homeOf(env), ".config");
19148
19974
  const files = [
19149
- ...OPENCODE_NAMES.map((name) => path23.join(config, "opencode", name)),
19150
- ...projectDirs(cwd).flatMap((dir) => OPENCODE_NAMES.flatMap((name) => [path23.join(dir, name), path23.join(dir, ".opencode", name)])),
19975
+ ...OPENCODE_NAMES.map((name) => path24.join(config, "opencode", name)),
19976
+ ...projectDirs(cwd).flatMap((dir) => OPENCODE_NAMES.flatMap((name) => [path24.join(dir, name), path24.join(dir, ".opencode", name)])),
19151
19977
  ...env.OPENCODE_CONFIG ? [env.OPENCODE_CONFIG] : []
19152
19978
  ];
19153
19979
  for (const file of files) {
@@ -19191,9 +20017,9 @@ var codexRule = (body) => {
19191
20017
  function codexRules(cwd, env = process.env) {
19192
20018
  const rules = EMPTY2();
19193
20019
  try {
19194
- const home = env.CODEX_HOME || path23.join(homeOf(env), ".codex");
20020
+ const home = env.CODEX_HOME || path24.join(homeOf(env), ".codex");
19195
20021
  const top = gitTop(cwd) ?? cwd;
19196
- for (const dir of [path23.join(home, "rules"), path23.join(top, ".codex", "rules")]) {
20022
+ for (const dir of [path24.join(home, "rules"), path24.join(top, ".codex", "rules")]) {
19197
20023
  let files;
19198
20024
  try {
19199
20025
  files = fs18.readdirSync(dir).filter((name) => name.endsWith(".rules"));
@@ -19203,7 +20029,7 @@ function codexRules(cwd, env = process.env) {
19203
20029
  return "unreadable";
19204
20030
  }
19205
20031
  for (const name of files) {
19206
- const text = readText2(path23.join(dir, name)) ?? "";
20032
+ const text = readText2(path24.join(dir, name)) ?? "";
19207
20033
  for (const part of text.split(/\bprefix_rule\s*\(/u).slice(1)) {
19208
20034
  const rule = codexRule(part);
19209
20035
  if (!rule)
@@ -19222,8 +20048,8 @@ function cursorRules(cwd, env = process.env) {
19222
20048
  try {
19223
20049
  const top = gitTop(cwd) ?? cwd;
19224
20050
  for (const file of [
19225
- path23.join(homeOf(env), ".cursor", "cli-config.json"),
19226
- path23.join(top, ".cursor", "cli.json")
20051
+ path24.join(homeOf(env), ".cursor", "cli-config.json"),
20052
+ path24.join(top, ".cursor", "cli.json")
19227
20053
  ]) {
19228
20054
  const text = readText2(file);
19229
20055
  if (text === null)
@@ -19299,21 +20125,21 @@ function wrapAllowed(read, words, command, options = {}) {
19299
20125
  // packages/workit-core/src/core/heavy.ts
19300
20126
  import fs19 from "node:fs";
19301
20127
  import os7 from "node:os";
19302
- import path24 from "node:path";
20128
+ import path25 from "node:path";
19303
20129
  function stateDir(env, platform = process.platform) {
19304
20130
  if (env.WORKFLOW_TOOLKIT_STATE)
19305
20131
  return env.WORKFLOW_TOOLKIT_STATE;
19306
20132
  if (env.XDG_STATE_HOME)
19307
- return path24.join(env.XDG_STATE_HOME, "workit");
20133
+ return path25.join(env.XDG_STATE_HOME, "workit");
19308
20134
  const home = env.HOME || os7.homedir();
19309
20135
  if (platform === "darwin")
19310
- return path24.join(home, "Library", "Application Support", "workit");
20136
+ return path25.join(home, "Library", "Application Support", "workit");
19311
20137
  if (platform === "win32")
19312
- return path24.join(env.LOCALAPPDATA ?? path24.join(home, "AppData", "Local"), "workit");
19313
- return path24.join(home, ".local", "state", "workit");
20138
+ return path25.join(env.LOCALAPPDATA ?? path25.join(home, "AppData", "Local"), "workit");
20139
+ return path25.join(home, ".local", "state", "workit");
19314
20140
  }
19315
20141
  var HEAVY_COMMANDS_FILE = "heavy-commands.json";
19316
- var heavyCommandsFile = (env) => path24.join(stateDir(env), HEAVY_COMMANDS_FILE);
20142
+ var heavyCommandsFile = (env) => path25.join(stateDir(env), HEAVY_COMMANDS_FILE);
19317
20143
  var HEAVY_SCRIPT = /^(?:test|tests|t|tst|unit|integration|e2e|coverage|cov|lint|eslint|typecheck|type-check|types|tsc|check|verify|validate|build|compile|bundle|ci|sonar|cypress|playwright|jest|vitest|mocha|bench|benchmark|all)(?:$|[:_.-])/iu;
19318
20144
  var INFO_FLAGS = new Set(["--version", "-v", "-V", "--help", "-h", "help", "version"]);
19319
20145
  var WATCH_FLAG = /^(?:--watch(?:All)?(?:=.*)?|-w|--serve)$/u;
@@ -19588,7 +20414,7 @@ function machinePatterns(env) {
19588
20414
  return isRecord5(value) ? stringList(value.patterns) : [];
19589
20415
  }
19590
20416
  function repoPatterns(cwd) {
19591
- return repoHeavyCommands(gitTop(cwd) ?? path24.resolve(cwd));
20417
+ return repoHeavyCommands(gitTop(cwd) ?? path25.resolve(cwd));
19592
20418
  }
19593
20419
  function heavyLines(lines, options) {
19594
20420
  const found = [];
@@ -19666,12 +20492,12 @@ function heavyPlan(command, options) {
19666
20492
  }
19667
20493
  function workitOnPath2(env = process.env) {
19668
20494
  const names = process.platform === "win32" ? ["workit.exe", "workit.cmd", "workit"] : ["workit"];
19669
- for (const dir of (env.PATH ?? "").split(path24.delimiter))
20495
+ for (const dir of (env.PATH ?? "").split(path25.delimiter))
19670
20496
  for (const name of names) {
19671
20497
  if (!dir)
19672
20498
  continue;
19673
20499
  try {
19674
- fs19.accessSync(path24.join(dir, name), fs19.constants.X_OK);
20500
+ fs19.accessSync(path25.join(dir, name), fs19.constants.X_OK);
19675
20501
  return true;
19676
20502
  } catch {}
19677
20503
  }
@@ -19690,20 +20516,20 @@ function leaseRewrite(command) {
19690
20516
  // packages/workit-core/src/core/heavy-words.ts
19691
20517
  import fs20 from "node:fs";
19692
20518
  import os8 from "node:os";
19693
- import path25 from "node:path";
20519
+ import path26 from "node:path";
19694
20520
  var HEAVY_WORDS = new Set(("npm npx pnpm pnpx yarn bun bunx deno corepack make gmake docker podman nerdctl " + "python python3 py uv poetry pdm pipenv hatch rye bundle rake nx " + "jest vitest mocha ava tap karma jasmine nyc c8 tsc vue-tsc svelte-check eslint stylelint " + "tslint webpack webpack-cli rollup parcel tsup vite next nuxt nuxi astro ng react-scripts " + "playwright cypress wdio testcafe turbo lerna sonar-scanner sonarless sonarless-mcp go " + "golangci-lint gotestsum staticcheck cargo mvn mvnw gradle gradlew ant sbt bazel bazelisk " + "buck2 dotnet msbuild pytest py.test tox nox mypy pyright pylint coverage maturin pip pip3 " + "rspec rails phpunit pest phpstan psalm composer mix swift xcodebuild flutter dart pod cmake " + "ninja meson ctest scons docker-compose buildah earthly").split(" "));
19695
20521
  var wordsOf = (command) => command.split(/[\s;&|()<>`'"]+/u).map((word) => (word.split(/[\\/]/u).at(-1) ?? "").toLowerCase().replace(/\.(?:exe|cmd|bat)$/u, "")).filter(Boolean);
19696
20522
  var stateDir2 = (env) => {
19697
20523
  if (env.WORKFLOW_TOOLKIT_STATE)
19698
20524
  return env.WORKFLOW_TOOLKIT_STATE;
19699
20525
  if (env.XDG_STATE_HOME)
19700
- return path25.join(env.XDG_STATE_HOME, "workit");
20526
+ return path26.join(env.XDG_STATE_HOME, "workit");
19701
20527
  const home = env.HOME || os8.homedir();
19702
20528
  if (process.platform === "darwin")
19703
- return path25.join(home, "Library", "Application Support", "workit");
20529
+ return path26.join(home, "Library", "Application Support", "workit");
19704
20530
  if (process.platform === "win32")
19705
- return path25.join(env.LOCALAPPDATA ?? path25.join(home, "AppData", "Local"), "workit");
19706
- return path25.join(home, ".local", "state", "workit");
20531
+ return path26.join(env.LOCALAPPDATA ?? path26.join(home, "AppData", "Local"), "workit");
20532
+ return path26.join(home, ".local", "state", "workit");
19707
20533
  };
19708
20534
  var readJson2 = (file) => {
19709
20535
  try {
@@ -19714,15 +20540,15 @@ var readJson2 = (file) => {
19714
20540
  };
19715
20541
  var patternWords = (cwd, env) => {
19716
20542
  const patterns = [];
19717
- const machine = readJson2(path25.join(stateDir2(env), "heavy-commands.json"));
20543
+ const machine = readJson2(path26.join(stateDir2(env), "heavy-commands.json"));
19718
20544
  if (Array.isArray(machine?.patterns))
19719
20545
  patterns.push(...machine.patterns);
19720
- for (let dir = path25.resolve(cwd);; dir = path25.dirname(dir)) {
19721
- if (fs20.existsSync(path25.join(dir, ".git"))) {
20546
+ for (let dir = path26.resolve(cwd);; dir = path26.dirname(dir)) {
20547
+ if (fs20.existsSync(path26.join(dir, ".git"))) {
19722
20548
  patterns.push(...repoHeavyCommands(dir));
19723
20549
  break;
19724
20550
  }
19725
- if (path25.dirname(dir) === dir)
20551
+ if (path26.dirname(dir) === dir)
19726
20552
  break;
19727
20553
  }
19728
20554
  const words = new Set;
@@ -19792,16 +20618,16 @@ var splitDenial = (plan) => ({
19792
20618
  unblock: plan.unblock
19793
20619
  });
19794
20620
  // packages/workit-core/src/hooks/write-gate.ts
19795
- import { existsSync as existsSync7, realpathSync as realpathSync5 } from "node:fs";
20621
+ import { existsSync as existsSync8, realpathSync as realpathSync5 } from "node:fs";
19796
20622
  import os10 from "node:os";
19797
- import path27 from "node:path";
20623
+ import path28 from "node:path";
19798
20624
 
19799
20625
  // packages/workit-core/src/core/live-session.ts
19800
20626
  import { spawnSync as spawnSync13 } from "node:child_process";
19801
20627
  import { createHash as createHash16 } from "node:crypto";
19802
20628
  import fs21 from "node:fs";
19803
20629
  import os9 from "node:os";
19804
- import path26 from "node:path";
20630
+ import path27 from "node:path";
19805
20631
  var LIVE_SESSION_TTL_MS = 15 * 60000;
19806
20632
  var HEARTBEAT_EVERY_MS = 30000;
19807
20633
  var liveProbe = {
@@ -19875,15 +20701,15 @@ var liveOwner = (input, transport, env = process.env) => {
19875
20701
  };
19876
20702
  };
19877
20703
  var checkoutOf = (target) => {
19878
- let dir = path26.resolve(target);
19879
- while (!fs21.existsSync(dir) && path26.dirname(dir) !== dir)
19880
- dir = path26.dirname(dir);
20704
+ let dir = path27.resolve(target);
20705
+ while (!fs21.existsSync(dir) && path27.dirname(dir) !== dir)
20706
+ dir = path27.dirname(dir);
19881
20707
  if (fs21.existsSync(dir) && !fs21.statSync(dir).isDirectory())
19882
- dir = path26.dirname(dir);
19883
- const parts = dir.split(path26.sep);
20708
+ dir = path27.dirname(dir);
20709
+ const parts = dir.split(path27.sep);
19884
20710
  const dotGit = parts.lastIndexOf(".git");
19885
20711
  if (dotGit > 0)
19886
- dir = parts.slice(0, dotGit).join(path26.sep) || path26.sep;
20712
+ dir = parts.slice(0, dotGit).join(path27.sep) || path27.sep;
19887
20713
  const location = resolveStore(dir);
19888
20714
  if (location instanceof Error || !location.shared || !location.top)
19889
20715
  return null;
@@ -19893,9 +20719,9 @@ var checkoutOf = (target) => {
19893
20719
  } catch {}
19894
20720
  return top;
19895
20721
  };
19896
- var markerFile2 = (top) => path26.join(resolveStateDir(), "live-sessions", `${createHash16("sha256").update(checkoutKey(top)).digest("hex").slice(0, 32)}.json`);
20722
+ var markerFile2 = (top) => path27.join(resolveStateDir(), "live-sessions", `${createHash16("sha256").update(checkoutKey(top)).digest("hex").slice(0, 32)}.json`);
19897
20723
  var checkoutKey = (top, platform = process.platform) => {
19898
- let key = path26.resolve(top);
20724
+ let key = path27.resolve(top);
19899
20725
  try {
19900
20726
  key = fs21.realpathSync.native(key);
19901
20727
  } catch {}
@@ -19990,7 +20816,7 @@ var claimLiveSession = (target, owner, deps = {}) => {
19990
20816
  checkout,
19991
20817
  heartbeatAt: now.toISOString()
19992
20818
  };
19993
- fs21.mkdirSync(path26.dirname(file), { recursive: true });
20819
+ fs21.mkdirSync(path27.dirname(file), { recursive: true });
19994
20820
  const temp = `${file}.${process.pid}.tmp`;
19995
20821
  fs21.writeFileSync(temp, JSON.stringify(marker));
19996
20822
  fs21.renameSync(temp, file);
@@ -20002,22 +20828,22 @@ var NONE3 = { kind: "none" };
20002
20828
  var CASE_INSENSITIVE = process.platform === "darwin" || process.platform === "win32";
20003
20829
  var canonical2 = (file) => {
20004
20830
  let rest = "";
20005
- for (let dir = path27.resolve(file);; dir = path27.dirname(dir)) {
20831
+ for (let dir = path28.resolve(file);; dir = path28.dirname(dir)) {
20006
20832
  try {
20007
- return path27.join(realpathSync5.native(dir), rest);
20833
+ return path28.join(realpathSync5.native(dir), rest);
20008
20834
  } catch {
20009
- if (path27.dirname(dir) === dir)
20010
- return path27.resolve(file);
20011
- rest = rest ? path27.join(path27.basename(dir), rest) : path27.basename(dir);
20835
+ if (path28.dirname(dir) === dir)
20836
+ return path28.resolve(file);
20837
+ rest = rest ? path28.join(path28.basename(dir), rest) : path28.basename(dir);
20012
20838
  }
20013
20839
  }
20014
20840
  };
20015
20841
  var exempt = (cwd, root, file, plans) => {
20016
20842
  const fold = (value) => CASE_INSENSITIVE ? value.toLowerCase() : value;
20017
- const relative = path27.relative(fold(canonical2(root)), fold(canonical2(path27.resolve(cwd, file))));
20018
- if (relative.startsWith("..") || path27.isAbsolute(relative))
20843
+ const relative = path28.relative(fold(canonical2(root)), fold(canonical2(path28.resolve(cwd, file))));
20844
+ if (relative.startsWith("..") || path28.isAbsolute(relative))
20019
20845
  return true;
20020
- const posix = relative.split(path27.sep).join("/");
20846
+ const posix = relative.split(path28.sep).join("/");
20021
20847
  const segments = posix.split("/");
20022
20848
  return /\.mdx?$/i.test(posix) || segments[0] === "docs" || segments.includes("plans") || [...plans].some((plan) => fold(plan) === posix);
20023
20849
  };
@@ -20194,10 +21020,10 @@ var linkSources = (args, at) => {
20194
21020
  const sources = names.filter((name, index) => into >= 0 ? name !== dest : index < names.length - 1 || names.length === 1);
20195
21021
  const target = dest === undefined ? null : at(dest);
20196
21022
  const symbolic = args.some((arg) => /^-[a-zA-Z]*s|^--symbolic$/.test(arg));
20197
- const base = target === null ? null : into >= 0 || sources.length > 1 || existsSync7(target) || /[\\/]$/.test(dest ?? "") ? target : path27.dirname(target);
21023
+ const base = target === null ? null : into >= 0 || sources.length > 1 || existsSync8(target) || /[\\/]$/.test(dest ?? "") ? target : path28.dirname(target);
20198
21024
  return sources.flatMap((source) => {
20199
- if (symbolic && base !== null && !path27.isAbsolute(homeExpanded(source)))
20200
- return [path27.resolve(base, source)];
21025
+ if (symbolic && base !== null && !path28.isAbsolute(homeExpanded(source)))
21026
+ return [path28.resolve(base, source)];
20201
21027
  const resolved = at(source);
20202
21028
  return resolved ? [resolved] : [];
20203
21029
  });
@@ -20226,7 +21052,7 @@ var shellWrites = (command, depth = 0) => {
20226
21052
  return { writes: true, targets: unknown ? null : targets };
20227
21053
  };
20228
21054
  var cache2 = new Map;
20229
- var planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(path27.resolve(root, file)) ?? "-").join("\x00");
21055
+ var planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(path28.resolve(root, file)) ?? "-").join("\x00");
20230
21056
  var gateFor = (cwd) => {
20231
21057
  const store = new TaskStore(cwd);
20232
21058
  const listed = store.listTaskIndex();
@@ -20305,13 +21131,13 @@ var gitMutationDirs = (cwd, command, dialect) => {
20305
21131
  return [];
20306
21132
  if (sub === "stash" && ["list", "show"].includes(rest[0] ?? ""))
20307
21133
  return [];
20308
- return [path27.resolve(cwd, invocation.dir ?? ".")];
21134
+ return [path28.resolve(cwd, invocation.dir ?? ".")];
20309
21135
  });
20310
21136
  };
20311
21137
  var CD2 = new Set(["cd", "chdir", "set-location", "sl"]);
20312
21138
  var PUSHD2 = new Set(["pushd", "push-location"]);
20313
21139
  var POPD2 = new Set(["popd", "pop-location"]);
20314
- var UNKNOWN_DIR = path27.resolve(path27.parse(process.cwd()).root, ".workit-unknown-dir");
21140
+ var UNKNOWN_DIR = path28.resolve(path28.parse(process.cwd()).root, ".workit-unknown-dir");
20315
21141
  var cdInto = (dir, words, strict = false) => {
20316
21142
  const lost = strict ? UNKNOWN_DIR : undefined;
20317
21143
  const named = words.slice(1).find((word) => !word.startsWith("-") || word === "-");
@@ -20320,7 +21146,7 @@ var cdInto = (dir, words, strict = false) => {
20320
21146
  return lost;
20321
21147
  if (dir === undefined)
20322
21148
  return lost;
20323
- return target === undefined ? os10.homedir() : path27.resolve(dir, target);
21149
+ return target === undefined ? os10.homedir() : path28.resolve(dir, target);
20324
21150
  };
20325
21151
  var quoteWord2 = (word) => /^[\w@%+=:,./-]+$/.test(word) ? word : `'${word.replaceAll("'", "'\\''")}'`;
20326
21152
  var homeExpanded = (file) => {
@@ -20334,7 +21160,7 @@ var segmentTargets = (cwd, command, dialect, depth = 0, strict = false) => {
20334
21160
  const groups = [];
20335
21161
  const at = (file) => {
20336
21162
  const home = homeExpanded(file);
20337
- return path27.isAbsolute(home) ? home : dir === undefined ? null : path27.resolve(dir, home);
21163
+ return path28.isAbsolute(home) ? home : dir === undefined ? null : path28.resolve(dir, home);
20338
21164
  };
20339
21165
  for (const segment of segmentsOf(command, dialect)) {
20340
21166
  if (segment.group === "open") {
@@ -20374,7 +21200,7 @@ var segmentTargets = (cwd, command, dialect, depth = 0, strict = false) => {
20374
21200
  for (const file of opaque ?? []) {
20375
21201
  const resolved = at(file);
20376
21202
  if (resolved)
20377
- targets.push(file === "." ? path27.join(resolved, DIR_TARGET) : resolved);
21203
+ targets.push(file === "." ? path28.join(resolved, DIR_TARGET) : resolved);
20378
21204
  }
20379
21205
  const ln = words.findIndex((word) => /^ln$/i.test(word.split(/[\\/]/).at(-1) ?? ""));
20380
21206
  if (ln >= 0 && words.slice(0, ln).every((word) => PREFIXES2.has(word)))
@@ -20389,7 +21215,7 @@ var segmentTargets = (cwd, command, dialect, depth = 0, strict = false) => {
20389
21215
  const edits = editsOf(segment.words);
20390
21216
  if (edits === null) {
20391
21217
  if (dir !== undefined)
20392
- targets.push(path27.join(dir, DIR_TARGET));
21218
+ targets.push(path28.join(dir, DIR_TARGET));
20393
21219
  } else
20394
21220
  for (const file of edits) {
20395
21221
  const resolved = at(file);
@@ -20400,20 +21226,20 @@ var segmentTargets = (cwd, command, dialect, depth = 0, strict = false) => {
20400
21226
  for (const invocation of workitInvocations(segment.words.map(quoteWord2).join(" "), "posix")) {
20401
21227
  const { at: runsIn, args } = workitCwd(dir, invocation);
20402
21228
  if (args[0] === "git" && MUTATING_WORKIT_GIT.has(args[1] ?? "") && !inert(args.slice(2), ""))
20403
- targets.push(path27.join(runsIn, DIR_TARGET));
21229
+ targets.push(path28.join(runsIn, DIR_TARGET));
20404
21230
  }
20405
21231
  }
20406
21232
  return targets;
20407
21233
  };
20408
21234
  var workitCwd = (dir, args) => {
20409
21235
  const { rest, cwd } = skipWorkitGlobals(args);
20410
- return { at: cwd === null ? dir : path27.resolve(dir, homeExpanded(cwd)), args: rest };
21236
+ return { at: cwd === null ? dir : path28.resolve(dir, homeExpanded(cwd)), args: rest };
20411
21237
  };
20412
21238
  var shellMutationTargets = (cwd, command, dialect = "posix", strict = false) => {
20413
21239
  try {
20414
21240
  return [
20415
21241
  ...segmentTargets(cwd, command, dialect, 0, strict),
20416
- ...gitMutationDirs(cwd, command, dialect).map((dir) => path27.join(dir, DIR_TARGET))
21242
+ ...gitMutationDirs(cwd, command, dialect).map((dir) => path28.join(dir, DIR_TARGET))
20417
21243
  ];
20418
21244
  } catch {
20419
21245
  return [];
@@ -20450,7 +21276,7 @@ var liveDeny = ({ marker, checkout, ageMs, file }) => {
20450
21276
  var guarded = (targets) => {
20451
21277
  const seen = new Set;
20452
21278
  return targets.filter((target) => {
20453
- const dir = path27.dirname(target);
21279
+ const dir = path28.dirname(target);
20454
21280
  if (seen.has(dir))
20455
21281
  return false;
20456
21282
  seen.add(dir);
@@ -20471,7 +21297,7 @@ var claimAll = (owner, targets, deps) => {
20471
21297
  for (const target of guarded(targets))
20472
21298
  claimLiveSession(target, owner, deps);
20473
21299
  };
20474
- var liveTargets = (cwd, paths) => paths?.length ? paths.map((file) => path27.resolve(cwd, file)) : [path27.join(cwd, DIR_TARGET)];
21300
+ var liveTargets = (cwd, paths) => paths?.length ? paths.map((file) => path28.resolve(cwd, file)) : [path28.join(cwd, DIR_TARGET)];
20475
21301
  var issuedTarget = (cwd, targets) => {
20476
21302
  const state = resolveStateDir();
20477
21303
  const found = targets.find((target) => underIssued(state, cwd, homeExpanded(target), process.platform, canonical2));
@@ -20479,7 +21305,7 @@ var issuedTarget = (cwd, targets) => {
20479
21305
  };
20480
21306
  var underIssued = (state, cwd, target, platform = process.platform, real = (file) => file) => {
20481
21307
  const win = platform === "win32";
20482
- const p = win ? path27.win32 : path27.posix;
21308
+ const p = win ? path28.win32 : path28.posix;
20483
21309
  const fold = (value) => win || platform === "darwin" ? value.toLowerCase() : value;
20484
21310
  const named = win ? target.replace(/^\/([a-zA-Z])(?=\/|$)/, "$1:") : target;
20485
21311
  const relative = p.relative(fold(real(p.resolve(state))), fold(real(p.resolve(cwd, named))));
@@ -20570,6 +21396,24 @@ function beforeWriteGate(cwd, paths) {
20570
21396
  }
20571
21397
  // packages/workit-core/src/hooks/stop.ts
20572
21398
  import { spawnSync as spawnSync14 } from "node:child_process";
21399
+
21400
+ // packages/workit-core/src/core/policy/current-judgment.ts
21401
+ function currentJudgment(cwd) {
21402
+ try {
21403
+ const store = new TaskStore(cwd);
21404
+ const listed = store.listTaskIndex();
21405
+ const key = store.currentKey();
21406
+ if (!listed.ok || !key.ok)
21407
+ return null;
21408
+ const entry = listed.data.filter((item) => item.key === key.data.key && item.status !== "closed").toSorted((left, right) => right.updatedAt.localeCompare(left.updatedAt))[0];
21409
+ const task = entry ? store.readTask(entry.id) : null;
21410
+ return task?.ok === true ? latestJudgment(task.data) : null;
21411
+ } catch {
21412
+ return null;
21413
+ }
21414
+ }
21415
+
21416
+ // packages/workit-core/src/hooks/stop.ts
20573
21417
  var NONE4 = { kind: "none" };
20574
21418
  var QUESTION = /[??؟](?=[\s*_`"')\]>]*(?:\s|$))|¿/;
20575
21419
  var OFFER = /\b(?:let me know|want me to|should I|shall I|would you like|do you want|if you(?:'d| would) like|may I|can I go ahead)\b/i;
@@ -20662,29 +21506,32 @@ var redChecks = (rows, pr, head, endpoint) => {
20662
21506
  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)" : ""}.`
20663
21507
  };
20664
21508
  };
20665
- var taskJudgment = (cwd) => {
20666
- try {
20667
- const store = new TaskStore(cwd);
20668
- const listed = store.listTaskIndex();
20669
- const key = store.currentKey();
20670
- if (!listed.ok || !key.ok)
20671
- return null;
20672
- const entry = listed.data.filter((item) => item.key === key.data.key && item.status !== "closed").toSorted((left, right) => right.updatedAt.localeCompare(left.updatedAt))[0];
20673
- const task = entry ? store.readTask(entry.id) : null;
20674
- return task?.ok === true ? latestJudgment(task.data) : null;
20675
- } catch {
20676
- return null;
20677
- }
21509
+ var prBase = (rows) => {
21510
+ const seen = rows.findLast((row) => (row.type === "pr.status" || row.type === "pr.created") && row.observer === "workit_cli" && typeof row.base === "string");
21511
+ return typeof seen?.base === "string" ? seen.base : null;
20678
21512
  };
20679
- var unverified = (cwd, branch, all, descriptor, verification) => {
21513
+ var unverified = (cwd, branch, all, descriptor, verification, head) => {
20680
21514
  const check = checkVerdicts(cwd, branch, all);
20681
21515
  if (check.accepted.accepted || check.accepted.reasons.includes("failing_verdict"))
20682
21516
  return null;
20683
- const judgment = taskJudgment(cwd);
21517
+ const judgment = currentJudgment(cwd);
20684
21518
  const high = judgment?.riskTier === "high";
20685
- if (judgment && !judgment.behaviorChange && !high)
20686
- return null;
20687
- const independent = verification === "independent" || high;
21519
+ let independent;
21520
+ if (verification === "proportional") {
21521
+ const lane = branchLane(cwd, {
21522
+ base: prBase(all.filter((row) => row.branch === branch)),
21523
+ head,
21524
+ judgment
21525
+ });
21526
+ const need = laneNeed(lane.lane);
21527
+ if (need === "none")
21528
+ return null;
21529
+ independent = need === "non-author";
21530
+ } else {
21531
+ if (judgment && !judgment.behaviorChange && !high)
21532
+ return null;
21533
+ independent = verification === "independent" || high;
21534
+ }
20688
21535
  if (!independent && check.review === "self-reviewed")
20689
21536
  return null;
20690
21537
  const has = check.review === "self-reviewed" ? "only a self verdict" : "no current verdict";
@@ -20731,7 +21578,7 @@ function stopObligation(input, descriptor) {
20731
21578
  }
20732
21579
  if (!delivered || endpoint !== "green" && endpoint !== "merged")
20733
21580
  return null;
20734
- const left = unverified(input.cwd, branch, all, descriptor, autonomy.verification);
21581
+ const left = unverified(input.cwd, branch, all, descriptor, autonomy.verification, head);
20735
21582
  return left ? { ...left, head } : null;
20736
21583
  } catch {
20737
21584
  return null;
@@ -20992,13 +21839,13 @@ ${line}` };
20992
21839
  return decision;
20993
21840
  };
20994
21841
  // packages/workit-core/src/hooks/hosts/fields.ts
20995
- import { existsSync as existsSync8, realpathSync as realpathSync6, statSync as statSync2 } from "node:fs";
20996
- import path28 from "node:path";
21842
+ import { existsSync as existsSync9, realpathSync as realpathSync6, statSync as statSync2 } from "node:fs";
21843
+ import path29 from "node:path";
20997
21844
  var isRecord6 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
20998
21845
  var nonEmpty2 = (value) => typeof value === "string" && value.trim() !== "";
20999
21846
  var optionalText = (value) => typeof value === "string" ? value : null;
21000
21847
  var existingDirectory = (value) => {
21001
- if (!nonEmpty2(value) || !path28.isAbsolute(value) || !existsSync8(value))
21848
+ if (!nonEmpty2(value) || !path29.isAbsolute(value) || !existsSync9(value))
21002
21849
  return null;
21003
21850
  try {
21004
21851
  return statSync2(value).isDirectory() ? realpathSync6(value) : null;
@@ -21066,9 +21913,9 @@ var writeTargets = (input) => {
21066
21913
  };
21067
21914
  // packages/workit-core/src/hooks/standing.ts
21068
21915
  import fs22 from "node:fs";
21069
- import path29 from "node:path";
21916
+ import path30 from "node:path";
21070
21917
  var readPlans = (store) => {
21071
- const dir = path29.join(store, "fanouts");
21918
+ const dir = path30.join(store, "fanouts");
21072
21919
  let names;
21073
21920
  try {
21074
21921
  names = fs22.readdirSync(dir).filter((name) => name.endsWith(".json"));
@@ -21078,7 +21925,7 @@ var readPlans = (store) => {
21078
21925
  const plans = [];
21079
21926
  for (const name of names) {
21080
21927
  try {
21081
- const raw = JSON.parse(fs22.readFileSync(path29.join(dir, name), "utf8"));
21928
+ const raw = JSON.parse(fs22.readFileSync(path30.join(dir, name), "utf8"));
21082
21929
  if (typeof raw.name !== "string" || !Array.isArray(raw.slices))
21083
21930
  continue;
21084
21931
  const texts = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string" && item !== "") : [];
@@ -21204,40 +22051,40 @@ var cwdRewrite = (command) => {
21204
22051
  // packages/workit-core/src/hooks/worktree-confine.ts
21205
22052
  import { createHash as createHash17 } from "node:crypto";
21206
22053
  import fs23 from "node:fs";
21207
- import path30 from "node:path";
22054
+ import path31 from "node:path";
21208
22055
  var FANOUT_TOKEN_FILE = "workit-fanout-token";
21209
22056
  var NONE5 = { kind: "none" };
21210
22057
  var CASE_INSENSITIVE2 = process.platform === "darwin" || process.platform === "win32";
21211
22058
  var canonical3 = (file) => {
21212
22059
  let rest = "";
21213
- for (let dir = path30.resolve(file);; dir = path30.dirname(dir)) {
22060
+ for (let dir = path31.resolve(file);; dir = path31.dirname(dir)) {
21214
22061
  try {
21215
- return path30.join(fs23.realpathSync.native(dir), rest);
22062
+ return path31.join(fs23.realpathSync.native(dir), rest);
21216
22063
  } catch {
21217
- if (path30.dirname(dir) === dir)
21218
- return path30.resolve(file);
21219
- rest = rest ? path30.join(path30.basename(dir), rest) : path30.basename(dir);
22064
+ if (path31.dirname(dir) === dir)
22065
+ return path31.resolve(file);
22066
+ rest = rest ? path31.join(path31.basename(dir), rest) : path31.basename(dir);
21220
22067
  }
21221
22068
  }
21222
22069
  };
21223
22070
  var within = (child, parent) => {
21224
22071
  const fold = (value) => CASE_INSENSITIVE2 ? value.toLowerCase() : value;
21225
- const relative = path30.relative(fold(parent), fold(child));
21226
- return relative === "" || !relative.startsWith("..") && !path30.isAbsolute(relative);
22072
+ const relative = path31.relative(fold(parent), fold(child));
22073
+ return relative === "" || !relative.startsWith("..") && !path31.isAbsolute(relative);
21227
22074
  };
21228
22075
  var checkoutOf2 = (file) => {
21229
- for (let dir = canonical3(file);; dir = path30.dirname(dir)) {
21230
- const dotGit = path30.join(dir, ".git");
22076
+ for (let dir = canonical3(file);; dir = path31.dirname(dir)) {
22077
+ const dotGit = path31.join(dir, ".git");
21231
22078
  if (fs23.existsSync(dotGit)) {
21232
22079
  if (!fs23.statSync(dotGit).isFile())
21233
22080
  return { root: dir, workit: false };
21234
22081
  const admin = /^gitdir:\s*(.+)$/mu.exec(fs23.readFileSync(dotGit, "utf8"))?.[1]?.trim();
21235
22082
  return {
21236
22083
  root: dir,
21237
- workit: Boolean(admin) && fs23.existsSync(path30.join(path30.resolve(dir, admin), FANOUT_TOKEN_FILE))
22084
+ workit: Boolean(admin) && fs23.existsSync(path31.join(path31.resolve(dir, admin), FANOUT_TOKEN_FILE))
21238
22085
  };
21239
22086
  }
21240
- if (path30.dirname(dir) === dir)
22087
+ if (path31.dirname(dir) === dir)
21241
22088
  return null;
21242
22089
  }
21243
22090
  };
@@ -21249,8 +22096,8 @@ var workitWorktreeOf = (file) => {
21249
22096
  return null;
21250
22097
  }
21251
22098
  };
21252
- var bindingDir = () => path30.join(resolveStateDir(), "worktree-bind");
21253
- var bindingFile = (session, agentId) => path30.join(bindingDir(), `${createHash17("sha256").update(`${session}\x00${agentId}`).digest("hex").slice(0, 32)}.json`);
22099
+ var bindingDir = () => path31.join(resolveStateDir(), "worktree-bind");
22100
+ var bindingFile = (session, agentId) => path31.join(bindingDir(), `${createHash17("sha256").update(`${session}\x00${agentId}`).digest("hex").slice(0, 32)}.json`);
21254
22101
  var readBinding = (file) => {
21255
22102
  try {
21256
22103
  const value = JSON.parse(fs23.readFileSync(file, "utf8"));
@@ -21275,7 +22122,7 @@ var bind = (input, worktree) => {
21275
22122
  agentId,
21276
22123
  at: new Date().toISOString()
21277
22124
  };
21278
- fs23.mkdirSync(path30.dirname(file), { recursive: true });
22125
+ fs23.mkdirSync(path31.dirname(file), { recursive: true });
21279
22126
  fs23.writeFileSync(file, JSON.stringify(binding));
21280
22127
  try {
21281
22128
  if (inWorkitWorkspace(input.cwd))
@@ -21294,25 +22141,25 @@ var hostIsolated = (cwd, agentId) => {
21294
22141
  const checkout = checkoutOf2(cwd);
21295
22142
  if (!checkout)
21296
22143
  return false;
21297
- const dotGit = path30.join(checkout.root, ".git");
22144
+ const dotGit = path31.join(checkout.root, ".git");
21298
22145
  if (!fs23.statSync(dotGit).isFile())
21299
22146
  return false;
21300
22147
  const admin = /^gitdir:\s*(.+)$/mu.exec(fs23.readFileSync(dotGit, "utf8"))?.[1]?.trim();
21301
22148
  if (!admin)
21302
22149
  return false;
21303
- const adminDir = path30.resolve(checkout.root, admin);
21304
- const back = fs23.readFileSync(path30.join(adminDir, "gitdir"), "utf8").trim();
21305
- if (path30.relative(canonical3(path30.resolve(adminDir, back)), canonical3(dotGit)) !== "")
22150
+ const adminDir = path31.resolve(checkout.root, admin);
22151
+ const back = fs23.readFileSync(path31.join(adminDir, "gitdir"), "utf8").trim();
22152
+ if (path31.relative(canonical3(path31.resolve(adminDir, back)), canonical3(dotGit)) !== "")
21306
22153
  return false;
21307
- const common = path30.join(adminDir, "commondir");
21308
- const gitDir = fs23.existsSync(common) ? path30.resolve(adminDir, fs23.readFileSync(common, "utf8").trim()) : adminDir;
21309
- const expected = path30.join(path30.dirname(canonical3(gitDir)), ".claude", "worktrees", `agent-${agentId}`);
21310
- return path30.relative(canonical3(expected), checkout.root) === "";
22154
+ const common = path31.join(adminDir, "commondir");
22155
+ const gitDir = fs23.existsSync(common) ? path31.resolve(adminDir, fs23.readFileSync(common, "utf8").trim()) : adminDir;
22156
+ const expected = path31.join(path31.dirname(canonical3(gitDir)), ".claude", "worktrees", `agent-${agentId}`);
22157
+ return path31.relative(canonical3(expected), checkout.root) === "";
21311
22158
  } catch {
21312
22159
  return false;
21313
22160
  }
21314
22161
  };
21315
- var shown = (target) => path30.basename(target) === ".workit-live-target" ? path30.dirname(target) : target;
22162
+ var shown = (target) => path31.basename(target) === ".workit-live-target" ? path31.dirname(target) : target;
21316
22163
  var unboundDeny = (input, target) => {
21317
22164
  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.";
21318
22165
  return {
@@ -21342,7 +22189,7 @@ function confineImplementer(input, targets) {
21342
22189
  try {
21343
22190
  if (!input.session.agentId || hostIsolated(input.cwd, input.session.agentId))
21344
22191
  return NONE5;
21345
- if (targets.some((target) => within(path30.resolve(target), UNKNOWN_DIR)))
22192
+ if (targets.some((target) => within(path31.resolve(target), UNKNOWN_DIR)))
21346
22193
  return unknownDirDeny(input, boundWorktree(input));
21347
22194
  const bindings = canonical3(bindingDir());
21348
22195
  const judged = targets.map((named) => ({ named, real: canonical3(named) })).filter(({ real }) => within(real, bindings) || checkoutOf2(real) !== null);
@@ -21662,7 +22509,7 @@ var dispatchHook = (adapter, raw, env = process.env) => {
21662
22509
  };
21663
22510
  // packages/workit-core/src/hooks/deadline.ts
21664
22511
  import { appendFileSync, mkdirSync as mkdirSync3 } from "node:fs";
21665
- import path31 from "node:path";
22512
+ import path32 from "node:path";
21666
22513
  var HOOK_SKIP_TEXT = "workit context skipped: host under load";
21667
22514
  var HOOK_DEADLINE_MS = 8000;
21668
22515
  var HOST_DEADLINES = {
@@ -21680,7 +22527,7 @@ var hookDeadlineMs = (env, host = "", native) => {
21680
22527
  const row = HOST_DEADLINES[host];
21681
22528
  return override(env) ?? (row ? native === undefined ? Math.min(...Object.values(row)) : row[native] ?? row[""] : HOOK_DEADLINE_MS);
21682
22529
  };
21683
- var skipsFile = (stateDir) => path31.join(stateDir, HOOK_SKIPS_FILE);
22530
+ var skipsFile = (stateDir) => path32.join(stateDir, HOOK_SKIPS_FILE);
21684
22531
  var recordHookSkip = (skip, stateDir = resolveStateDir()) => {
21685
22532
  try {
21686
22533
  mkdirSync3(stateDir, { recursive: true });
@@ -22325,7 +23172,7 @@ var codexAdapter = {
22325
23172
 
22326
23173
  // packages/workit-core/src/hooks/hosts/cursor.ts
22327
23174
  import fs24 from "node:fs";
22328
- import path32 from "node:path";
23175
+ import path33 from "node:path";
22329
23176
  var undocumented = { support: "undocumented", native: null };
22330
23177
  var none = { support: "none", native: null };
22331
23178
  var CURSOR_DESCRIPTOR = {
@@ -22522,7 +23369,7 @@ var protocolEvent2 = (input) => {
22522
23369
  };
22523
23370
  var TRANSCRIPT_TAIL_BYTES = 256 * 1024;
22524
23371
  var lastAssistantText = (file) => {
22525
- if (!file || !path32.isAbsolute(file))
23372
+ if (!file || !path33.isAbsolute(file))
22526
23373
  return null;
22527
23374
  try {
22528
23375
  const size = fs24.statSync(file).size;
@@ -22559,7 +23406,7 @@ var lastAssistantText = (file) => {
22559
23406
  return null;
22560
23407
  }
22561
23408
  };
22562
- var within3 = (root, dir) => dir === root || dir.startsWith(root.endsWith(path32.sep) ? root : `${root}${path32.sep}`);
23409
+ var within3 = (root, dir) => dir === root || dir.startsWith(root.endsWith(path33.sep) ? root : `${root}${path33.sep}`);
22563
23410
  var hookCwd = (input) => {
22564
23411
  const cwd = existingDirectory(input.cwd);
22565
23412
  if (cwd && input.hook_event_name === "beforeShellExecution")