@brainervirus/workit-codex 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.
@@ -6621,14 +6621,14 @@ var require_dist = __commonJS(function(exports, module) {
6621
6621
  });
6622
6622
 
6623
6623
  // packages/workit-codex/scripts/launch-mcp.ts
6624
- import { existsSync as existsSync10, realpathSync as realpathSync7, statSync as statSync3 } from "node:fs";
6625
- import path25 from "node:path";
6624
+ import { existsSync as existsSync11, realpathSync as realpathSync7, statSync as statSync3 } from "node:fs";
6625
+ import path26 from "node:path";
6626
6626
  import { fileURLToPath as fileURLToPath3 } from "node:url";
6627
6627
 
6628
6628
  // packages/workit-core/src/core.ts
6629
6629
  import { spawnSync as spawnSync14 } from "node:child_process";
6630
- import { existsSync as existsSync7, realpathSync as realpathSync5 } from "node:fs";
6631
- import path21 from "node:path";
6630
+ import { existsSync as existsSync8, realpathSync as realpathSync5 } from "node:fs";
6631
+ import path22 from "node:path";
6632
6632
 
6633
6633
  // packages/workit-core/src/core/task-contract.ts
6634
6634
  import { createHash, randomUUID } from "node:crypto";
@@ -14859,7 +14859,7 @@ var workspaceConfigSchema = object({
14859
14859
  }).passthrough().optional(),
14860
14860
  autoApprove: union([boolean2(), array(nonBlank)]).optional(),
14861
14861
  defaultEndpoint: unknown().optional(),
14862
- verification: _enum(["self", "independent"]).optional(),
14862
+ verification: _enum(["proportional", "self", "independent"]).optional(),
14863
14863
  delegation: unknown().optional(),
14864
14864
  trailers: boolean2().optional(),
14865
14865
  liveSessionGuard: boolean2().optional(),
@@ -15400,6 +15400,124 @@ function resolveRef(cwd, ref) {
15400
15400
  return null;
15401
15401
  return line(git(cwd, ["rev-parse", "--verify", "-q", `${ref}^{commit}`]));
15402
15402
  }
15403
+ var LANE_DIFF = [
15404
+ "-c",
15405
+ "core.quotePath=false",
15406
+ "diff",
15407
+ "--no-color",
15408
+ "--no-ext-diff",
15409
+ "--no-textconv",
15410
+ "--no-renames"
15411
+ ];
15412
+ var laneRange = (fork, head) => {
15413
+ if (!safeArg(fork) || head !== null && !safeArg(head))
15414
+ return null;
15415
+ return head === null ? [fork] : [fork, head];
15416
+ };
15417
+ function diffNumstat(cwd, fork, head) {
15418
+ const range = laneRange(fork, head);
15419
+ if (!range)
15420
+ return null;
15421
+ const run = git(cwd, [...LANE_DIFF, "--numstat", "-z", ...range, "--"]);
15422
+ if (!run.ok)
15423
+ return null;
15424
+ const out = [];
15425
+ for (const record of run.stdout.split("\x00")) {
15426
+ const match = /^(-|\d+)\t(-|\d+)\t(.+)$/su.exec(record.replace(/^\n/u, ""));
15427
+ if (!match)
15428
+ continue;
15429
+ const binary = match[1] === "-";
15430
+ out.push({
15431
+ path: match[3],
15432
+ added: binary ? 0 : Number(match[1]),
15433
+ deleted: binary ? 0 : Number(match[2]),
15434
+ binary
15435
+ });
15436
+ }
15437
+ return out;
15438
+ }
15439
+ function diffRaw(cwd, fork, head) {
15440
+ const range = laneRange(fork, head);
15441
+ if (!range)
15442
+ return null;
15443
+ const run = git(cwd, [...LANE_DIFF, "--raw", "-z", "--no-abbrev", ...range, "--"]);
15444
+ if (!run.ok)
15445
+ return null;
15446
+ const fields = run.stdout.split("\x00");
15447
+ const out = [];
15448
+ for (let index = 0;index + 1 < fields.length; index += 2) {
15449
+ const meta = /^:(\d{6}) (\d{6}) ([0-9a-f]+) ([0-9a-f]+) [A-Z]\d*$/u.exec(fields[index].replace(/^\n/u, ""));
15450
+ if (!meta)
15451
+ return null;
15452
+ out.push({
15453
+ path: fields[index + 1],
15454
+ oldMode: meta[1],
15455
+ newMode: meta[2],
15456
+ oldBlob: meta[3],
15457
+ newBlob: meta[4]
15458
+ });
15459
+ }
15460
+ return out;
15461
+ }
15462
+ function readBlobs(cwd, ids) {
15463
+ const out = new Map;
15464
+ const wanted = [...new Set(ids)].filter((id) => /^[0-9a-f]{40,64}$/u.test(id));
15465
+ if (!wanted.length)
15466
+ return out;
15467
+ const run = spawnSync3("git", ["cat-file", "--batch"], {
15468
+ cwd,
15469
+ input: `${wanted.join(`
15470
+ `)}
15471
+ `,
15472
+ maxBuffer: MAX_BUFFER,
15473
+ timeout: GIT_TIMEOUTS.local,
15474
+ killSignal: "SIGKILL",
15475
+ windowsHide: true
15476
+ });
15477
+ if (run.status !== 0 || !run.stdout)
15478
+ return null;
15479
+ const bytes = run.stdout;
15480
+ let at = 0;
15481
+ for (const id of wanted) {
15482
+ const end = bytes.indexOf(10, at);
15483
+ if (end < 0)
15484
+ return null;
15485
+ const header = bytes.subarray(at, end).toString("utf8").split(" ");
15486
+ at = end + 1;
15487
+ if (header[1] === "missing")
15488
+ continue;
15489
+ const size = Number(header[2]);
15490
+ if (header[0] !== id || !Number.isSafeInteger(size))
15491
+ return null;
15492
+ out.set(id, bytes.subarray(at, at + size));
15493
+ at += size + 1;
15494
+ }
15495
+ return out;
15496
+ }
15497
+ function treeFilesNamed(cwd, rev, name) {
15498
+ if (!safeArg(rev))
15499
+ return null;
15500
+ const run = git(cwd, ["ls-tree", "-r", "-z", "--full-tree", rev]);
15501
+ if (!run.ok)
15502
+ return null;
15503
+ const out = new Map;
15504
+ for (const record of run.stdout.split("\x00")) {
15505
+ const match = /^\d{6} blob ([0-9a-f]+)\t(.+)$/su.exec(record);
15506
+ if (match && (match[2] === name || match[2].endsWith(`/${name}`)))
15507
+ out.set(match[2], match[1]);
15508
+ }
15509
+ return out;
15510
+ }
15511
+ function fileAt(cwd, rev, file) {
15512
+ if (!safeArg(rev))
15513
+ return null;
15514
+ const run = git(cwd, ["cat-file", "blob", `${rev}:${file}`]);
15515
+ return run.ok ? run.stdout : null;
15516
+ }
15517
+ function untrackedFiles(cwd) {
15518
+ const run = git(cwd, ["ls-files", "-z", "--others", "--exclude-standard"]);
15519
+ return run.ok ? run.stdout.split("\x00").filter(Boolean) : [];
15520
+ }
15403
15521
  var config2 = (cwd, key) => line(git(cwd, ["config", "--get", key]));
15404
15522
  function currentBranch(cwd) {
15405
15523
  return line(git(cwd, ["symbolic-ref", "--short", "-q", "HEAD"]));
@@ -18908,9 +19026,9 @@ var workerBlocksTransition = (transition, state) => transition === "pause" ? fal
18908
19026
 
18909
19027
  // packages/workit-core/src/core/task-evaluation.ts
18910
19028
  import { createHash as createHash10 } from "node:crypto";
18911
- import * as fs13 from "node:fs";
18912
- import { spawnSync as spawnSync10 } from "node:child_process";
18913
- import path16 from "node:path";
19029
+ import * as fs14 from "node:fs";
19030
+ import { spawnSync as spawnSync11 } from "node:child_process";
19031
+ import path18 from "node:path";
18914
19032
 
18915
19033
  // packages/workit-core/src/check-config.ts
18916
19034
  import { spawnSync as spawnSync8 } from "node:child_process";
@@ -19130,8 +19248,8 @@ function checkCommand(args, version, onPath = workitAvailable()) {
19130
19248
  }
19131
19249
 
19132
19250
  // packages/workit-core/src/core/policy/derive.ts
19133
- import { existsSync as existsSync4 } from "node:fs";
19134
- import path15 from "node:path";
19251
+ import { existsSync as existsSync5 } from "node:fs";
19252
+ import path17 from "node:path";
19135
19253
 
19136
19254
  // packages/workit-core/src/ledger.ts
19137
19255
  import { spawnSync as spawnSync9 } from "node:child_process";
@@ -19975,7 +20093,8 @@ function checkVerdicts(cwd, branch, ledgerRows) {
19975
20093
  verdict: failing?.verdict ?? null,
19976
20094
  reasons: failing ? ["failing_verdict"] : !newestCurrent ? ["no_verdict"] : newestCurrent.reasons.length ? newestCurrent.reasons : ["type_check_only"]
19977
20095
  };
19978
- const selfEntry = failing ? undefined : verdicts.findLast((entry) => entry.current && !entry.independent && !untrusted(entry.reasons) && STRONG_RESULTS.has(String(entry.verdict.result)));
20096
+ 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))));
20097
+ const selfEntry = latestSelf && STRONG_RESULTS.has(String(latestSelf.verdict.result)) ? latestSelf : undefined;
19979
20098
  return {
19980
20099
  branch,
19981
20100
  head,
@@ -19997,12 +20116,721 @@ var OBSERVED_ONLY = new Set([
19997
20116
  ...PR_ROW_TYPES
19998
20117
  ]);
19999
20118
 
20119
+ // packages/workit-core/src/core/policy/lane.ts
20120
+ import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
20121
+ import path16 from "node:path";
20122
+
20123
+ // packages/workit-core/src/core/pr-create.ts
20124
+ import fs13 from "node:fs";
20125
+ import path15 from "node:path";
20126
+ import { spawnSync as spawnSync10 } from "node:child_process";
20127
+ // packages/workit-core/src/forge/pr-body.ts
20128
+ function parseGhIssue(value) {
20129
+ const m = /issues\/(\d+)/.exec(value);
20130
+ return m ? m[1] : String(value).trim().replace(/^#/, "");
20131
+ }
20132
+
20133
+ // packages/workit-core/src/core/pr-create.ts
20134
+ function whichOnPath(tool) {
20135
+ const names = process.platform === "win32" ? [tool, `${tool}.exe`, `${tool}.cmd`] : [tool];
20136
+ for (const dir of (process.env.PATH ?? "").split(path15.delimiter)) {
20137
+ if (!dir)
20138
+ continue;
20139
+ for (const name of names) {
20140
+ const candidate = path15.join(dir, name);
20141
+ try {
20142
+ fs13.accessSync(candidate, fs13.constants.X_OK);
20143
+ return candidate;
20144
+ } catch {}
20145
+ }
20146
+ }
20147
+ return null;
20148
+ }
20149
+ var hostingCliAvailable = (provider) => whichOnPath(provider === "gitlab" ? "glab" : "gh") !== null;
20150
+ var pushRemote = (cwd) => {
20151
+ const result = spawnSync10("git", ["remote", "get-url", "--push", "--all", "origin"], {
20152
+ cwd,
20153
+ encoding: "utf8"
20154
+ });
20155
+ if (result.status !== 0)
20156
+ return null;
20157
+ const urls = (result.stdout ?? "").split(/\r?\n/u).map((url) => url.trim()).filter(Boolean);
20158
+ return urls.length === 1 ? urls[0] : null;
20159
+ };
20160
+
20161
+ // packages/workit-core/src/forge/redact.ts
20162
+ 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_.-]*`;
20163
+ var ASSIGNMENT = new RegExp(String.raw`(?<![A-Za-z0-9])(["']?${KEY}["']?\s*[:=]\s*["']?)((?:bearer|basic|token|digest)\s+)?([^\s"',;&]+)`, "giu");
20164
+ var QUOTED_ASSIGNMENT = new RegExp(String.raw`(?<![A-Za-z0-9])(["']?${KEY}["']?\s*[:=]\s*)(["'])([^"'\n]*[^\s"'][^"'\n]*)\2`, "giu");
20165
+ var ANSI = new RegExp(String.raw`\u001b\[[0-9;?]*[ -/]*[@-~]|\u001b\][^\u0007]*\u0007`, "gu");
20166
+
20167
+ // packages/workit-core/src/git/ops.ts
20168
+ var COMMIT_TIMEOUT_MS = 10 * 60000;
20169
+
20170
+ // packages/workit-core/src/core/policy/attributes.ts
20171
+ function patternRegex(dir, pattern) {
20172
+ if (!pattern || pattern.endsWith("/") || pattern.startsWith('"') || pattern.startsWith("!"))
20173
+ return null;
20174
+ const anchored = pattern.includes("/");
20175
+ const body = pattern.replace(/^\//u, "");
20176
+ let source = "";
20177
+ for (let index = 0;index < body.length; index += 1) {
20178
+ const char = body[index];
20179
+ if (char === "*" && body[index + 1] === "*") {
20180
+ const slash = body[index + 2] === "/";
20181
+ source += slash ? "(?:.*/)?" : ".*";
20182
+ index += slash ? 2 : 1;
20183
+ } else if (char === "*")
20184
+ source += "[^/]*";
20185
+ else if (char === "?")
20186
+ source += "[^/]";
20187
+ else if (char === "[") {
20188
+ const end = body.indexOf("]", index + 2);
20189
+ if (end < 0)
20190
+ return null;
20191
+ const set = body.slice(index + 1, end).replace(/^!/u, "^").replace(/\\/gu, "\\\\");
20192
+ source += `[${set}]`;
20193
+ index = end;
20194
+ } else if (char === "\\" && index + 1 < body.length) {
20195
+ source += body[index + 1].replace(/[.*+?^${}()|[\]\\/]/gu, "\\$&");
20196
+ index += 1;
20197
+ } else
20198
+ source += char.replace(/[.*+?^${}()|[\]\\/]/gu, "\\$&");
20199
+ }
20200
+ const prefix = dir ? `${dir.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")}/` : "";
20201
+ try {
20202
+ return new RegExp(anchored ? `^${prefix}${source}$` : `^${prefix}(?:.*/)?${source}$`, "u");
20203
+ } catch {
20204
+ return null;
20205
+ }
20206
+ }
20207
+ function rulesOf(dir, text) {
20208
+ const out = [];
20209
+ for (const raw of text.split(`
20210
+ `)) {
20211
+ const line = raw.trim();
20212
+ if (!line || line.startsWith("#") || line.startsWith("[attr]"))
20213
+ continue;
20214
+ const [pattern, ...attributes] = line.split(/\s+/u);
20215
+ let generated = null;
20216
+ for (const attribute of attributes) {
20217
+ if (attribute === "linguist-generated" || attribute === "linguist-generated=true")
20218
+ generated = true;
20219
+ else if (attribute === "-linguist-generated" || attribute === "!linguist-generated" || attribute.startsWith("linguist-generated="))
20220
+ generated = false;
20221
+ }
20222
+ if (generated === null)
20223
+ continue;
20224
+ const regex = patternRegex(dir, pattern);
20225
+ if (regex)
20226
+ out.push({ regex, generated });
20227
+ }
20228
+ return out;
20229
+ }
20230
+ function generatedByAttributes(files, paths) {
20231
+ const rules = [...files].map(([file, text]) => {
20232
+ const dir = file.includes("/") ? file.slice(0, file.lastIndexOf("/")) : "";
20233
+ return {
20234
+ depth: dir ? dir.split("/").length : 0,
20235
+ rules: rulesOf(dir, text)
20236
+ };
20237
+ }).toSorted((left, right) => left.depth - right.depth).flatMap((entry) => entry.rules);
20238
+ const out = new Set;
20239
+ for (const file of paths) {
20240
+ const last = rules.findLast((rule) => rule.regex.test(file));
20241
+ if (last?.generated)
20242
+ out.add(file);
20243
+ }
20244
+ return out;
20245
+ }
20246
+
20247
+ // packages/workit-core/src/core/policy/substance.ts
20248
+ var SLASH_BLOCK = [["/*", "*/"]];
20249
+ var C_LIKE = { line: ["//"], block: SLASH_BLOCK, quotes: `"'` };
20250
+ var SYNTAXES = Object.fromEntries([
20251
+ ...["ts", "mts", "cts", "js", "mjs", "cjs"].map((ext) => [ext, { ...C_LIKE, js: true }]),
20252
+ ...["java", "kt", "kts", "scala", "swift", "dart", "groovy"].map((ext) => [
20253
+ ext,
20254
+ { ...C_LIKE, triple: true }
20255
+ ]),
20256
+ ["go", { ...C_LIKE, rawBacktick: true }],
20257
+ ...["css", "scss", "less"].map((ext) => [
20258
+ ext,
20259
+ { line: [], block: SLASH_BLOCK, quotes: `"'`, cssUrl: true }
20260
+ ]),
20261
+ ...["py", "pyi"].map((ext) => [
20262
+ ext,
20263
+ { line: ["#"], block: [], quotes: `"'`, triple: true, indented: true, fstring: true }
20264
+ ]),
20265
+ ["toml", { line: ["#"], block: [], quotes: `"`, literal: "'", triple: true }],
20266
+ ...["html", "htm", "xml", "svg", "xhtml"].map((ext) => [
20267
+ ext,
20268
+ { line: [], block: [["<!--", "-->"]], quotes: "", indented: true }
20269
+ ])
20270
+ ]);
20271
+ 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;
20272
+ var extensionOf = (file) => {
20273
+ const name = file.slice(file.lastIndexOf("/") + 1);
20274
+ const dot = name.lastIndexOf(".");
20275
+ return dot > 0 ? name.slice(dot + 1).toLowerCase() : "";
20276
+ };
20277
+ var CI_PATH = /^\.github\/|(?:^|\/)(?:\.gitlab-ci\.ya?ml|Jenkinsfile|azure-pipelines\.ya?ml|\.pre-commit-config\.ya?ml|\.circleci\/.*)$/u;
20278
+ var syntaxOf = (file) => CI_PATH.test(file) ? null : SYNTAXES[extensionOf(file)] ?? null;
20279
+ var SPACE = /[ \t\r\f\v]/u;
20280
+ var WORD = /[\w$]/u;
20281
+ var NO_SPACE_AFTER = "([{,;";
20282
+ var NO_SPACE_BEFORE = ")]},;";
20283
+ var REGEX_AFTER = "(,=:[!&|?{};+-*%<>~^";
20284
+ var REGEX_KEYWORDS = new Set([
20285
+ "return",
20286
+ "typeof",
20287
+ "instanceof",
20288
+ "case",
20289
+ "do",
20290
+ "else",
20291
+ "in",
20292
+ "of",
20293
+ "new",
20294
+ "delete",
20295
+ "void",
20296
+ "throw",
20297
+ "yield",
20298
+ "await"
20299
+ ]);
20300
+ function substanceOf(file, text) {
20301
+ const syntax = syntaxOf(file);
20302
+ if (!syntax)
20303
+ return plainSubstance(text);
20304
+ const markup = syntax.block.some(([open]) => open === "<!--");
20305
+ if (markup && (/<(?:script|style)\b|<!\[CDATA\[|<\?/iu.test(text) || /[^>\s][ \t]*<!--/u.test(text)))
20306
+ return plainSubstance(text);
20307
+ return lex(syntax, text);
20308
+ }
20309
+ function plainSubstance(text) {
20310
+ return text.split(`
20311
+ `).map((line) => line.replace(/[ \t\r\f\v]+$/u, "")).filter(Boolean).join(`
20312
+ `);
20313
+ }
20314
+ function lex(syntax, text) {
20315
+ const collapse = !syntax.indented;
20316
+ let out = "";
20317
+ let lineStart = 0;
20318
+ let kept = 0;
20319
+ let pendingSpace = false;
20320
+ const frames = [{ kind: "code", braces: 0 }];
20321
+ let index = 0;
20322
+ if (text.startsWith("#!")) {
20323
+ const end = text.indexOf(`
20324
+ `);
20325
+ out = end < 0 ? text : text.slice(0, end);
20326
+ kept = out.length;
20327
+ index = end < 0 ? text.length : end;
20328
+ }
20329
+ const emitCode = (chunk) => {
20330
+ if (collapse && pendingSpace && out.length > lineStart) {
20331
+ const before = out[out.length - 1];
20332
+ if (!NO_SPACE_AFTER.includes(before) && !NO_SPACE_BEFORE.includes(chunk[0]))
20333
+ out += " ";
20334
+ }
20335
+ pendingSpace = false;
20336
+ out += chunk;
20337
+ };
20338
+ const emitVerbatim = (chunk) => {
20339
+ emitCode(chunk);
20340
+ kept = out.length;
20341
+ };
20342
+ const newline = () => {
20343
+ if (!collapse) {
20344
+ let end = out.length;
20345
+ while (end > Math.max(lineStart, kept) && SPACE.test(out[end - 1]))
20346
+ end -= 1;
20347
+ out = out.slice(0, end);
20348
+ }
20349
+ pendingSpace = false;
20350
+ if (out.length > lineStart) {
20351
+ out += `
20352
+ `;
20353
+ lineStart = out.length;
20354
+ }
20355
+ };
20356
+ const regexAllowed = () => {
20357
+ let end = out.length;
20358
+ while (end > 0 && /\s/u.test(out[end - 1]))
20359
+ end -= 1;
20360
+ if (end === 0 || REGEX_AFTER.includes(out[end - 1]))
20361
+ return true;
20362
+ let start = end;
20363
+ while (start > 0 && WORD.test(out[start - 1]))
20364
+ start -= 1;
20365
+ return REGEX_KEYWORDS.has(out.slice(start, end));
20366
+ };
20367
+ const scanString = (quote, escapes, multiline) => {
20368
+ const prefix = text.slice(Math.max(0, index - 2), index).match(/[a-z]*$/iu)?.[0] ?? "";
20369
+ const fstring = syntax.fstring === true && /f/iu.test(prefix);
20370
+ let end = index + quote.length;
20371
+ while (end < text.length) {
20372
+ const char = text[end];
20373
+ if (escapes && char === "\\") {
20374
+ end += 2;
20375
+ continue;
20376
+ }
20377
+ if (text.startsWith(quote, end)) {
20378
+ if (fstring && unbalanced(text.slice(index + quote.length, end)))
20379
+ return false;
20380
+ emitVerbatim(text.slice(index, end + quote.length));
20381
+ index = end + quote.length;
20382
+ return true;
20383
+ }
20384
+ if (char === `
20385
+ ` && !multiline)
20386
+ return false;
20387
+ end += 1;
20388
+ }
20389
+ return false;
20390
+ };
20391
+ while (index < text.length) {
20392
+ const frame = frames[frames.length - 1];
20393
+ const char = text[index];
20394
+ if (frame.kind === "template") {
20395
+ if (char === "\\") {
20396
+ emitVerbatim(text.slice(index, index + 2));
20397
+ index += 2;
20398
+ } else if (char === "`") {
20399
+ emitVerbatim(char);
20400
+ frames.pop();
20401
+ index += 1;
20402
+ } else if (text.startsWith("${", index)) {
20403
+ emitVerbatim("${");
20404
+ frames.push({ kind: "code", braces: 0 });
20405
+ index += 2;
20406
+ } else {
20407
+ out += char;
20408
+ kept = out.length;
20409
+ index += 1;
20410
+ }
20411
+ continue;
20412
+ }
20413
+ if (char === `
20414
+ `) {
20415
+ newline();
20416
+ index += 1;
20417
+ continue;
20418
+ }
20419
+ if (SPACE.test(char)) {
20420
+ if (collapse)
20421
+ pendingSpace = true;
20422
+ else
20423
+ out += char;
20424
+ index += 1;
20425
+ continue;
20426
+ }
20427
+ const lineOpener = syntax.line.find((opener) => text.startsWith(opener, index));
20428
+ if (lineOpener) {
20429
+ const end = text.indexOf(`
20430
+ `, index);
20431
+ const comment = text.slice(index, end < 0 ? text.length : end);
20432
+ if (DIRECTIVE.test(comment.slice(lineOpener.length)))
20433
+ emitVerbatim(comment);
20434
+ else
20435
+ pendingSpace = true;
20436
+ index = end < 0 ? text.length : end;
20437
+ continue;
20438
+ }
20439
+ const block = syntax.block.find(([open]) => text.startsWith(open, index));
20440
+ if (block) {
20441
+ const end = text.indexOf(block[1], index + block[0].length);
20442
+ if (end < 0)
20443
+ return null;
20444
+ const comment = text.slice(index, end + block[1].length);
20445
+ if (DIRECTIVE.test(comment.slice(block[0].length, -block[1].length)))
20446
+ emitVerbatim(comment);
20447
+ else
20448
+ pendingSpace = true;
20449
+ if (comment.includes(`
20450
+ `))
20451
+ newline();
20452
+ index = end + block[1].length;
20453
+ continue;
20454
+ }
20455
+ if (syntax.triple && (char === '"' || char === "'") && text.startsWith(char.repeat(3), index)) {
20456
+ if (!scanString(char.repeat(3), !syntax.literal?.includes(char), true))
20457
+ return null;
20458
+ continue;
20459
+ }
20460
+ if (syntax.quotes.includes(char)) {
20461
+ if (!scanString(char, true, Boolean(syntax.multiline)))
20462
+ return null;
20463
+ continue;
20464
+ }
20465
+ if (syntax.literal?.includes(char)) {
20466
+ if (!scanString(char, false, false))
20467
+ return null;
20468
+ continue;
20469
+ }
20470
+ if (syntax.rawBacktick && char === "`") {
20471
+ if (!scanString("`", false, true))
20472
+ return null;
20473
+ continue;
20474
+ }
20475
+ if (syntax.js && char === "`") {
20476
+ emitVerbatim(char);
20477
+ frames.push({ kind: "template" });
20478
+ index += 1;
20479
+ continue;
20480
+ }
20481
+ if (syntax.cssUrl && /^url\(\s*[^"')\s]/iu.test(text.slice(index, index + 64)))
20482
+ return null;
20483
+ if (syntax.js && char === "/" && !regexAllowed() && out.trimEnd().endsWith(")")) {
20484
+ const lineEnd = text.indexOf(`
20485
+ `, index);
20486
+ if (text.slice(index + 1, lineEnd < 0 ? text.length : lineEnd).includes("/"))
20487
+ return null;
20488
+ }
20489
+ if (syntax.js && char === "/" && regexAllowed()) {
20490
+ let end = index + 1;
20491
+ let inClass = false;
20492
+ while (end < text.length && (inClass || text[end] !== "/")) {
20493
+ if (text[end] === `
20494
+ `)
20495
+ return null;
20496
+ if (text[end] === "\\")
20497
+ end += 1;
20498
+ else if (text[end] === "[")
20499
+ inClass = true;
20500
+ else if (text[end] === "]")
20501
+ inClass = false;
20502
+ end += 1;
20503
+ }
20504
+ if (end >= text.length)
20505
+ return null;
20506
+ emitVerbatim(text.slice(index, end + 1));
20507
+ index = end + 1;
20508
+ continue;
20509
+ }
20510
+ if (frames.length > 1 && frame.kind === "code") {
20511
+ if (char === "{")
20512
+ frame.braces += 1;
20513
+ else if (char === "}") {
20514
+ if (frame.braces === 0) {
20515
+ emitVerbatim(char);
20516
+ frames.pop();
20517
+ index += 1;
20518
+ continue;
20519
+ }
20520
+ frame.braces -= 1;
20521
+ }
20522
+ }
20523
+ emitCode(char);
20524
+ index += 1;
20525
+ }
20526
+ if (frames.length !== 1)
20527
+ return null;
20528
+ newline();
20529
+ return out;
20530
+ }
20531
+ function unbalanced(body) {
20532
+ let depth = 0;
20533
+ for (const part of body.replaceAll("{{", "").replaceAll("}}", "")) {
20534
+ if (part === "{")
20535
+ depth += 1;
20536
+ else if (part === "}")
20537
+ depth = Math.max(0, depth - 1);
20538
+ }
20539
+ return depth > 0;
20540
+ }
20541
+ function hasOpaqueLineBreak(text) {
20542
+ return /\r(?!\n)|[\u2028\u2029]/u.test(text);
20543
+ }
20544
+ var decoder = new TextDecoder("utf-8", { fatal: true });
20545
+ function textOf(bytes) {
20546
+ if (bytes.includes(0))
20547
+ return null;
20548
+ try {
20549
+ return decoder.decode(bytes);
20550
+ } catch {
20551
+ return null;
20552
+ }
20553
+ }
20554
+ function cosmeticChange(file, before, after) {
20555
+ const left = textOf(before);
20556
+ const right = textOf(after);
20557
+ if (left === null || right === null)
20558
+ return false;
20559
+ if (hasOpaqueLineBreak(left) || hasOpaqueLineBreak(right))
20560
+ return false;
20561
+ const a = substanceOf(file, left);
20562
+ return a !== null && a === substanceOf(file, right);
20563
+ }
20564
+
20565
+ // packages/workit-core/src/core/policy/lane.ts
20566
+ var LANE_THRESHOLDS = {
20567
+ selfMaxLines: 100,
20568
+ selfMaxFiles: 5,
20569
+ fullMinLines: 500
20570
+ };
20571
+ var RISK_TOKENS = new Set([
20572
+ "auth",
20573
+ "authn",
20574
+ "authz",
20575
+ "oauth",
20576
+ "security",
20577
+ "permission",
20578
+ "permissions",
20579
+ "secret",
20580
+ "secrets",
20581
+ "crypto",
20582
+ "gate",
20583
+ "gates",
20584
+ "policy",
20585
+ "policies",
20586
+ "hook",
20587
+ "hooks",
20588
+ "husky",
20589
+ "lefthook",
20590
+ "release",
20591
+ "releases",
20592
+ "migration",
20593
+ "migrations",
20594
+ "migrate",
20595
+ "workflows"
20596
+ ]);
20597
+ var RISK_FILES = new Set([
20598
+ ".gitlab-ci.yml",
20599
+ "Jenkinsfile",
20600
+ "azure-pipelines.yml",
20601
+ ".pre-commit-config.yaml",
20602
+ ".workit/risk-paths"
20603
+ ]);
20604
+ var RISK_NAMES = new Set([".gitattributes"]);
20605
+ var RISK_PATHS_FILE = ".workit/risk-paths";
20606
+ var LOCKFILES = new Set([
20607
+ "bun.lock",
20608
+ "bun.lockb",
20609
+ "package-lock.json",
20610
+ "npm-shrinkwrap.json",
20611
+ "yarn.lock",
20612
+ "pnpm-lock.yaml",
20613
+ "Cargo.lock",
20614
+ "go.sum",
20615
+ "poetry.lock",
20616
+ "uv.lock",
20617
+ "Pipfile.lock",
20618
+ "Gemfile.lock",
20619
+ "composer.lock"
20620
+ ]);
20621
+ var DOC_EXT = /\.(?:md|mdx|markdown|rst|adoc|txt)$/iu;
20622
+ var DOC_NAMES = /^(?:license|licence|notice|authors|changelog|changes|contributors)$/iu;
20623
+ var INSTRUCTIONS = /(?:^|\/)(?:AGENTS|CLAUDE|GEMINI|SKILL)\.md$|(?:^|\/)(?:skills|agents|commands|rules|prompts)\/[^/]+/iu;
20624
+ var TEST_PATH = /(?:^|\/)(?:test|tests|__tests__|spec|specs|fixtures)\/|\.(?:test|spec)\.[^/]+$/iu;
20625
+ var basename = (file) => file.slice(file.lastIndexOf("/") + 1);
20626
+ var isDoc = (file) => !INSTRUCTIONS.test(file) && (DOC_EXT.test(file) || DOC_NAMES.test(basename(file)));
20627
+ function kindOf(file) {
20628
+ if (file.binary)
20629
+ return "behavior";
20630
+ if (file.generated)
20631
+ return "generated";
20632
+ if (LOCKFILES.has(basename(file.path)))
20633
+ return "lockfile";
20634
+ if (isDoc(file.path))
20635
+ return "doc";
20636
+ if (file.cosmetic)
20637
+ return "cosmetic";
20638
+ return TEST_PATH.test(file.path) ? "test" : "behavior";
20639
+ }
20640
+ var globCache = new Map;
20641
+ function globMatch(pattern, file) {
20642
+ let regex = globCache.get(pattern);
20643
+ if (!regex) {
20644
+ let source = "";
20645
+ for (let index = 0;index < pattern.length; index += 1) {
20646
+ const char = pattern[index];
20647
+ if (char === "*" && pattern[index + 1] === "*") {
20648
+ source += pattern[index + 2] === "/" ? "(?:[^/]*/)*" : ".*";
20649
+ index += pattern[index + 2] === "/" ? 2 : 1;
20650
+ } else if (char === "*")
20651
+ source += "[^/]*";
20652
+ else if (char === "?")
20653
+ source += "[^/]";
20654
+ else
20655
+ source += char.replace(/[.+^${}()|[\]\\]/gu, "\\$&");
20656
+ }
20657
+ regex = new RegExp(`^${source}$`, "u");
20658
+ globCache.set(pattern, regex);
20659
+ }
20660
+ return regex.test(file) || file.startsWith(`${pattern.replace(/\/$/u, "")}/`);
20661
+ }
20662
+ function isRiskPath(file, extra = []) {
20663
+ if (extra.some((pattern) => globMatch(pattern, file)))
20664
+ return true;
20665
+ if (RISK_FILES.has(file) || RISK_NAMES.has(basename(file)))
20666
+ return true;
20667
+ if (TEST_PATH.test(file) || isDoc(file))
20668
+ return false;
20669
+ 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)));
20670
+ }
20671
+ var parseRiskPaths = (text) => text.split(`
20672
+ `).map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map((line) => line.replace(/^\//u, ""));
20673
+ function computeLane(input) {
20674
+ const riskFiles = input.files.filter((file) => isRiskPath(file.path, input.riskPaths)).map((file) => file.path);
20675
+ const risky = new Set(riskFiles);
20676
+ const kinds = input.files.map((file) => ({
20677
+ file,
20678
+ kind: risky.has(file.path) ? "behavior" : kindOf(file)
20679
+ }));
20680
+ const behavior = kinds.filter((entry) => entry.kind === "behavior" || entry.kind === "test" || entry.kind === "lockfile");
20681
+ const lines = behavior.filter((entry) => entry.kind !== "lockfile").reduce((sum, entry) => sum + entry.file.added + entry.file.deleted, 0);
20682
+ const opaque = behavior.filter((entry) => entry.kind === "lockfile" || entry.file.binary);
20683
+ const result = (lane, reasons) => ({
20684
+ lane,
20685
+ reasons,
20686
+ lines,
20687
+ files: behavior.length,
20688
+ riskFiles
20689
+ });
20690
+ const { selfMaxLines, selfMaxFiles, fullMinLines } = LANE_THRESHOLDS;
20691
+ if (input.riskTier === "high")
20692
+ return result("full", ["the task judgment records high risk"]);
20693
+ if (riskFiles.length)
20694
+ return result("full", [
20695
+ `touches a risk path: ${riskFiles.slice(0, 3).join(", ")}${riskFiles.length > 3 ? ", …" : ""}`
20696
+ ]);
20697
+ if (!behavior.length)
20698
+ return result("none", [
20699
+ input.files.length ? "only docs, comments, formatting or generated copies changed" : "no changes"
20700
+ ]);
20701
+ if (lines >= fullMinLines)
20702
+ return result("full", [`large diff: ${lines} lines (≥ ${fullMinLines})`]);
20703
+ if (lines > selfMaxLines)
20704
+ return result("focused", [`${lines} lines changed (> ${selfMaxLines})`]);
20705
+ if (behavior.length > selfMaxFiles)
20706
+ return result("focused", [`${behavior.length} behavior files changed (> ${selfMaxFiles})`]);
20707
+ if (opaque.length)
20708
+ return result("focused", [
20709
+ `a lockfile or binary changed: ${opaque.slice(0, 3).map((entry) => entry.file.path).join(", ")}${opaque.length > 3 ? ", …" : ""}`
20710
+ ]);
20711
+ return result("self", [
20712
+ `small change: ${lines} line${lines === 1 ? "" : "s"} in ${behavior.length} file${behavior.length === 1 ? "" : "s"}, no risk path`
20713
+ ]);
20714
+ }
20715
+ function untrackedStat(cwd, file) {
20716
+ try {
20717
+ const bytes = readFileSync4(path16.join(cwd, file));
20718
+ if (bytes.includes(0))
20719
+ return { path: file, added: 0, deleted: 0, binary: true };
20720
+ const text = bytes.toString("utf8");
20721
+ if (hasOpaqueLineBreak(text))
20722
+ return { path: file, added: 0, deleted: 0, binary: true };
20723
+ const lines = text.split(`
20724
+ `).length - (text.endsWith(`
20725
+ `) ? 1 : 0);
20726
+ return { path: file, added: lines, deleted: 0 };
20727
+ } catch {
20728
+ return { path: file, added: 0, deleted: 0, binary: true };
20729
+ }
20730
+ }
20731
+ var REGULAR = new Set(["100644", "100755"]);
20732
+ var ABSENT = /^0+$/u;
20733
+ function cosmeticFiles(cwd, fork, head) {
20734
+ const raw = diffRaw(cwd, fork, head);
20735
+ if (!raw)
20736
+ return null;
20737
+ const candidates = raw.filter((entry) => REGULAR.has(entry.oldMode) && entry.oldMode === entry.newMode && !ABSENT.test(entry.oldBlob) && (head === null || !ABSENT.test(entry.newBlob)));
20738
+ const blobs = readBlobs(cwd, candidates.flatMap((entry) => [entry.oldBlob, entry.newBlob]));
20739
+ if (!blobs)
20740
+ return null;
20741
+ const out = new Set;
20742
+ const opaque = new Set;
20743
+ for (const entry of candidates) {
20744
+ const before = blobs.get(entry.oldBlob);
20745
+ let after = blobs.get(entry.newBlob);
20746
+ if (!after && head === null && ABSENT.test(entry.newBlob))
20747
+ try {
20748
+ after = readFileSync4(path16.join(cwd, entry.path));
20749
+ } catch {
20750
+ after = undefined;
20751
+ }
20752
+ if (before && after && cosmeticChange(entry.path, before, after))
20753
+ out.add(entry.path);
20754
+ else if ([before, after].some((bytes) => bytes && hasOpaqueLineBreak(bytes.toString("utf8"))))
20755
+ opaque.add(entry.path);
20756
+ }
20757
+ return { cosmetic: out, opaque };
20758
+ }
20759
+ function generatedAt(cwd, fork, paths) {
20760
+ const files = treeFilesNamed(cwd, fork, ".gitattributes");
20761
+ const blobs = files?.size ? readBlobs(cwd, [...files.values()]) : null;
20762
+ if (!files || !blobs)
20763
+ return new Set;
20764
+ const texts = new Map;
20765
+ for (const [file, id] of files) {
20766
+ const bytes = blobs.get(id);
20767
+ if (bytes)
20768
+ texts.set(file, bytes.toString("utf8"));
20769
+ }
20770
+ return generatedByAttributes(texts, paths);
20771
+ }
20772
+ var forkOf = (cwd, base, head) => mergeBase(cwd, base, head ?? "HEAD");
20773
+ function laneFiles(cwd, fork, head) {
20774
+ const stats = diffNumstat(cwd, fork, head);
20775
+ const cosmetic = stats ? cosmeticFiles(cwd, fork, head) : null;
20776
+ if (!stats || !cosmetic)
20777
+ return null;
20778
+ const files = [
20779
+ ...stats.map((entry) => ({
20780
+ ...entry,
20781
+ ...cosmetic.opaque.has(entry.path) ? { binary: true } : {},
20782
+ cosmetic: !entry.binary && cosmetic.cosmetic.has(entry.path)
20783
+ })),
20784
+ ...head === null ? untrackedFiles(cwd).map((file) => untrackedStat(cwd, file)) : []
20785
+ ];
20786
+ const generated = generatedAt(cwd, fork, files.map((entry) => entry.path));
20787
+ return files.map((entry) => ({
20788
+ ...entry,
20789
+ generated: generated.has(entry.path)
20790
+ }));
20791
+ }
20792
+ function branchLane(cwd, options) {
20793
+ const candidates = options.base ? [`origin/${options.base}`, options.base] : [];
20794
+ const base = candidates.find((ref) => resolveRef(cwd, ref) !== null) ?? defaultBase(cwd) ?? null;
20795
+ const head = options.workingTree ? null : options.head;
20796
+ const fork = base && (options.workingTree || options.head) ? forkOf(cwd, base, head) : null;
20797
+ const files = fork ? laneFiles(cwd, fork, head) : null;
20798
+ const riskTier = options.judgment?.riskTier ?? null;
20799
+ if (!fork || !files) {
20800
+ const high = riskTier === "high";
20801
+ return {
20802
+ lane: high ? "full" : "focused",
20803
+ reasons: [
20804
+ `the diff of ${options.head?.slice(0, 12) ?? "(no head)"} against ${base ?? "(no base)"} cannot be read`,
20805
+ ...high ? ["the task judgment records high risk"] : []
20806
+ ],
20807
+ lines: 0,
20808
+ files: 0,
20809
+ riskFiles: [],
20810
+ base,
20811
+ head: options.head
20812
+ };
20813
+ }
20814
+ const repoRisk = parseRiskPaths(fileAt(cwd, fork, RISK_PATHS_FILE) ?? "");
20815
+ return {
20816
+ ...computeLane({
20817
+ files,
20818
+ riskTier,
20819
+ riskPaths: [...repoRisk, ...options.riskPaths ?? []]
20820
+ }),
20821
+ base,
20822
+ head: options.head
20823
+ };
20824
+ }
20825
+ var laneNeed = (lane) => lane === "none" ? "none" : lane === "self" ? "self" : "non-author";
20826
+
20000
20827
  // packages/workit-core/src/core/policy/derive.ts
20001
20828
  var RULES = {
20002
20829
  test: "check:test",
20003
20830
  self: "verdict:self",
20004
20831
  nonAuthor: "verdict:non-author",
20005
20832
  verified: "verdict:verified",
20833
+ lane: "verdict:lane",
20006
20834
  product: "decision:product",
20007
20835
  plan: "plan"
20008
20836
  };
@@ -20025,6 +20853,7 @@ var normalizedScope = (scope) => ({
20025
20853
  function deriveRequirements(judgment, scope, constraints, verification = "self") {
20026
20854
  const out = [];
20027
20855
  const base = { scope, dependentAction: null };
20856
+ const proportional = verification === "proportional";
20028
20857
  if (judgment.behaviorChange)
20029
20858
  out.push(derived2({
20030
20859
  ...base,
@@ -20035,7 +20864,17 @@ function deriveRequirements(judgment, scope, constraints, verification = "self")
20035
20864
  before: "close",
20036
20865
  acceptanceAllowed: false
20037
20866
  }));
20038
- if (judgment.behaviorChange && judgment.riskTier === "normal")
20867
+ if (proportional && judgment.riskTier === "normal")
20868
+ out.push(derived2({
20869
+ ...base,
20870
+ ruleId: RULES.lane,
20871
+ dimension: "review",
20872
+ 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.",
20873
+ 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.",
20874
+ before: "close",
20875
+ acceptanceAllowed: false
20876
+ }));
20877
+ if (!proportional && judgment.behaviorChange && judgment.riskTier === "normal")
20039
20878
  out.push(verification === "independent" ? derived2({
20040
20879
  ...base,
20041
20880
  ruleId: RULES.nonAuthor,
@@ -20138,7 +20977,7 @@ var productDecision = (task, ledger) => {
20138
20977
  };
20139
20978
  };
20140
20979
  var planRecorded = (task, root) => {
20141
- const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(path15.resolve(root, ref.path)));
20980
+ const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync5(path17.resolve(root, ref.path)));
20142
20981
  if (cited)
20143
20982
  return {
20144
20983
  met: true,
@@ -20152,14 +20991,30 @@ var planRecorded = (task, root) => {
20152
20991
  decisionIds: []
20153
20992
  };
20154
20993
  };
20155
- var verdict = (requirement, root, ledger) => {
20994
+ var workingLane = (task, root) => branchLane(root, { head: null, workingTree: true, judgment: latestJudgment(task) });
20995
+ var laneVerdict = (task, root, ledger) => {
20996
+ if (!ledger.branch() && latestJudgment(task)?.behaviorChange === false)
20997
+ return {
20998
+ met: true,
20999
+ reason: "no branch to read a lane from, and the judgment records no behavior change",
21000
+ decisionIds: []
21001
+ };
21002
+ const lane = workingLane(task, root);
21003
+ const label = `lane ${lane.lane} (${lane.reasons.join("; ")})`;
21004
+ const need = laneNeed(lane.lane);
21005
+ if (need === "none")
21006
+ return { met: true, reason: `${label}: no verdict needed`, decisionIds: [] };
21007
+ const status = verdict(need === "self" ? RULES.self : RULES.nonAuthor, root, ledger);
21008
+ return { ...status, reason: `${label}: ${status.reason}` };
21009
+ };
21010
+ var verdict = (ruleId, root, ledger) => {
20156
21011
  const branch = ledger.branch();
20157
21012
  if (!branch)
20158
21013
  return { met: false, reason: "no branch is checked out to hold a verdict", decisionIds: [] };
20159
21014
  const check = checkVerdicts(root, branch, ledger.rows());
20160
21015
  const failing = check.accepted.reasons.includes("failing_verdict");
20161
21016
  const strong = (entry) => STRONG_RESULTS.has(String(entry.verdict.result));
20162
- 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)));
21017
+ 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)));
20163
21018
  if (met)
20164
21019
  return {
20165
21020
  met: true,
@@ -20167,7 +21022,7 @@ var verdict = (requirement, root, ledger) => {
20167
21022
  decisionIds: []
20168
21023
  };
20169
21024
  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, " ");
20170
- 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>\``;
21025
+ 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>\``;
20171
21026
  return { met: false, reason: `${why}: ${unblock}`, decisionIds: [] };
20172
21027
  };
20173
21028
  function derivedRuleStatus(task, requirement, root, ledger) {
@@ -20179,7 +21034,9 @@ function derivedRuleStatus(task, requirement, root, ledger) {
20179
21034
  case RULES.self:
20180
21035
  case RULES.nonAuthor:
20181
21036
  case RULES.verified:
20182
- return verdict(requirement, root, ledger);
21037
+ return verdict(requirement.ruleId, root, ledger);
21038
+ case RULES.lane:
21039
+ return laneVerdict(task, root, ledger);
20183
21040
  default:
20184
21041
  return null;
20185
21042
  }
@@ -20187,14 +21044,14 @@ function derivedRuleStatus(task, requirement, root, ledger) {
20187
21044
 
20188
21045
  // packages/workit-core/src/core/task-evaluation.ts
20189
21046
  var digestBytes = (value) => createHash10("sha256").update(value).digest("hex");
20190
- var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path16.sep}`);
20191
- var relative = (root, candidate) => path16.relative(root, candidate).split(path16.sep).join("/") || ".";
21047
+ var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path18.sep}`);
21048
+ var relative = (root, candidate) => path18.relative(root, candidate).split(path18.sep).join("/") || ".";
20192
21049
  var canonicalPath = (value) => {
20193
21050
  if (typeof value !== "string" || !value)
20194
21051
  return null;
20195
21052
  if (value.includes("\\") || value.split("/").includes(".."))
20196
21053
  return null;
20197
- const normalized = path16.posix.normalize(value);
21054
+ const normalized = path18.posix.normalize(value);
20198
21055
  if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
20199
21056
  return null;
20200
21057
  return normalized === "." ? "." : normalized.replace(/\/$/, "");
@@ -20230,7 +21087,7 @@ var compareCodeUnits2 = (left, right) => {
20230
21087
  return left.length - right.length;
20231
21088
  };
20232
21089
  var gitPaths = (root) => {
20233
- const result = spawnSync10("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], {
21090
+ const result = spawnSync11("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], {
20234
21091
  cwd: root,
20235
21092
  encoding: "buffer"
20236
21093
  });
@@ -20242,21 +21099,21 @@ var gitPaths = (root) => {
20242
21099
  git: !/not a git repository/i.test(stderr)
20243
21100
  };
20244
21101
  }
20245
- const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path16.sep).join("/")) : [];
20246
- const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
21102
+ const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path18.sep).join("/")) : [];
21103
+ const stagedDeleted = spawnSync11("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
20247
21104
  if (stagedDeleted.status !== 0) {
20248
21105
  const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
20249
21106
  if (!/not a git repository/i.test(stderr))
20250
21107
  return { paths, uncertain: true, git: true };
20251
21108
  } else if (stagedDeleted.stdout) {
20252
- paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path16.sep).join("/")));
21109
+ paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path18.sep).join("/")));
20253
21110
  }
20254
21111
  return { paths: [...new Set(paths)], uncertain: false, git: true };
20255
21112
  };
20256
21113
  var walk = (root, directory, output) => {
20257
21114
  let names;
20258
21115
  try {
20259
- names = fs13.readdirSync(directory);
21116
+ names = fs14.readdirSync(directory);
20260
21117
  } catch {
20261
21118
  return true;
20262
21119
  }
@@ -20264,10 +21121,10 @@ var walk = (root, directory, output) => {
20264
21121
  for (const name of names) {
20265
21122
  if (name === ".git" || name === ".workit")
20266
21123
  continue;
20267
- const target = path16.join(directory, name);
21124
+ const target = path18.join(directory, name);
20268
21125
  let stat;
20269
21126
  try {
20270
- stat = fs13.lstatSync(target);
21127
+ stat = fs14.lstatSync(target);
20271
21128
  } catch {
20272
21129
  uncertain = true;
20273
21130
  continue;
@@ -20282,14 +21139,14 @@ var walk = (root, directory, output) => {
20282
21139
  var scopeRoots = (root, scope) => {
20283
21140
  const roots = [];
20284
21141
  for (const item of scope.paths.length ? scope.paths : ["."]) {
20285
- const target = path16.resolve(root, item);
21142
+ const target = path18.resolve(root, item);
20286
21143
  if (!inside(root, target))
20287
21144
  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` }] });
20288
21145
  let ancestor = target;
20289
- while (!fs13.existsSync(ancestor) && ancestor !== root)
20290
- ancestor = path16.dirname(ancestor);
21146
+ while (!fs14.existsSync(ancestor) && ancestor !== root)
21147
+ ancestor = path18.dirname(ancestor);
20291
21148
  try {
20292
- if (!inside(root, fs13.realpathSync(ancestor)))
21149
+ if (!inside(root, fs14.realpathSync(ancestor)))
20293
21150
  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` }] });
20294
21151
  } catch {
20295
21152
  return failure2("invalid_input", `candidate scope cannot be inspected: ${item}`);
@@ -20301,7 +21158,7 @@ var scopeRoots = (root, scope) => {
20301
21158
  function captureCandidate(root, scope, environment = []) {
20302
21159
  let checkout;
20303
21160
  try {
20304
- checkout = fs13.realpathSync(root);
21161
+ checkout = fs14.realpathSync(root);
20305
21162
  } catch {
20306
21163
  return failure2("invalid_input", "candidate root does not exist");
20307
21164
  }
@@ -20319,11 +21176,11 @@ function captureCandidate(root, scope, environment = []) {
20319
21176
  if (item === ".git" || item === ".workit")
20320
21177
  continue;
20321
21178
  names.add(item);
20322
- if (!fs13.existsSync(target))
21179
+ if (!fs14.existsSync(target))
20323
21180
  continue;
20324
21181
  let stat;
20325
21182
  try {
20326
- stat = fs13.lstatSync(target);
21183
+ stat = fs14.lstatSync(target);
20327
21184
  } catch {
20328
21185
  uncertain = true;
20329
21186
  continue;
@@ -20339,17 +21196,17 @@ function captureCandidate(root, scope, environment = []) {
20339
21196
  for (const item of [...names].toSorted()) {
20340
21197
  if (!scopeMatches(item, normalizedScope))
20341
21198
  continue;
20342
- const target = path16.join(checkout, item);
21199
+ const target = path18.join(checkout, item);
20343
21200
  try {
20344
- const stat = fs13.lstatSync(target);
21201
+ const stat = fs14.lstatSync(target);
20345
21202
  if (stat.isSymbolicLink()) {
20346
- const link = fs13.readlinkSync(target);
21203
+ const link = fs14.readlinkSync(target);
20347
21204
  files.push({ path: item, kind: "symlink", digest: digestBytes(link), executable: null });
20348
21205
  } else if (stat.isFile()) {
20349
21206
  files.push({
20350
21207
  path: item,
20351
21208
  kind: "file",
20352
- digest: digestBytes(fs13.readFileSync(target)),
21209
+ digest: digestBytes(fs14.readFileSync(target)),
20353
21210
  executable: (stat.mode & 73) !== 0
20354
21211
  });
20355
21212
  } else if (!stat.isDirectory()) {
@@ -20374,7 +21231,7 @@ function captureCandidate(root, scope, environment = []) {
20374
21231
  const values = supplied.toSorted((left, right) => compareCodeUnits2(left.name, right.name)).map(({ name, value }) => ({ name, value, refs: [] }));
20375
21232
  if (values.some(({ value }) => value === null))
20376
21233
  completeness = "uncertain";
20377
- const headResult = spawnSync10("git", ["rev-parse", "HEAD"], { cwd: checkout, encoding: "utf8" });
21234
+ const headResult = spawnSync11("git", ["rev-parse", "HEAD"], { cwd: checkout, encoding: "utf8" });
20378
21235
  if (headResult.status !== 0 && !/not a git repository/i.test(headResult.stderr ?? ""))
20379
21236
  completeness = "uncertain";
20380
21237
  const head = headResult.status === 0 ? headResult.stdout.trim() : null;
@@ -20514,7 +21371,7 @@ var findingVerificationPasses = (findingCandidateId, evidence) => evidence.statu
20514
21371
  var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
20515
21372
  let root;
20516
21373
  try {
20517
- root = fs13.realpathSync(checkoutRoot);
21374
+ root = fs14.realpathSync(checkoutRoot);
20518
21375
  } catch {
20519
21376
  return failure2("permission_denied", "checkout root is unavailable");
20520
21377
  }
@@ -20523,23 +21380,23 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
20523
21380
  continue;
20524
21381
  if (!reference.digest)
20525
21382
  return failure2("invalid_input", "document references require a byte digest");
20526
- const target = path16.resolve(root, reference.path);
20527
- if (target !== root && !target.startsWith(`${root}${path16.sep}`))
21383
+ const target = path18.resolve(root, reference.path);
21384
+ if (target !== root && !target.startsWith(`${root}${path18.sep}`))
20528
21385
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
20529
21386
  fields: [
20530
21387
  { path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
20531
21388
  ]
20532
21389
  });
20533
21390
  try {
20534
- const below = path16.relative(root, target);
21391
+ const below = path18.relative(root, target);
20535
21392
  let current = root;
20536
- for (const segment of below.split(path16.sep)) {
21393
+ for (const segment of below.split(path18.sep)) {
20537
21394
  if (!segment)
20538
21395
  continue;
20539
- current = path16.join(current, segment);
20540
- const stat = fs13.lstatSync(current);
20541
- const real = fs13.realpathSync(current);
20542
- if (real !== root && !real.startsWith(`${root}${path16.sep}`))
21396
+ current = path18.join(current, segment);
21397
+ const stat = fs14.lstatSync(current);
21398
+ const real = fs14.realpathSync(current);
21399
+ if (real !== root && !real.startsWith(`${root}${path18.sep}`))
20543
21400
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
20544
21401
  fields: [
20545
21402
  {
@@ -20555,7 +21412,7 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
20555
21412
  if (current !== target && !stat.isDirectory())
20556
21413
  return failure2("invalid_input", "document reference ancestor is not a directory");
20557
21414
  }
20558
- if (digestBytes(fs13.readFileSync(target)) !== reference.digest)
21415
+ if (digestBytes(fs14.readFileSync(target)) !== reference.digest)
20559
21416
  return failure2("permission_denied", "decision document bytes have changed");
20560
21417
  } catch {
20561
21418
  return failure2("invalid_input", "decision document is unavailable");
@@ -21398,7 +22255,7 @@ var judgeInputSummary = (raw) => {
21398
22255
 
21399
22256
  // packages/workit-core/src/autonomy.ts
21400
22257
  import os4 from "node:os";
21401
- import path17 from "node:path";
22258
+ import path19 from "node:path";
21402
22259
  var accountHome = () => {
21403
22260
  try {
21404
22261
  return os4.userInfo().homedir;
@@ -21407,10 +22264,10 @@ var accountHome = () => {
21407
22264
  }
21408
22265
  };
21409
22266
  var grantsHome = { resolve: accountHome };
21410
- var grantsDir = () => path17.join(grantsHome.resolve(), ".config", "workit");
22267
+ var grantsDir = () => path19.join(grantsHome.resolve(), ".config", "workit");
21411
22268
  var grantsOverride = () => {
21412
- const configured = path17.resolve(resolveConfigDir());
21413
- return configured === path17.resolve(grantsDir()) ? null : `the config directory is redirected to ${configured} (WORKFLOW_TOOLKIT_CONFIG, WORKFLOW_TOOLKIT_CONFIG_DIR or XDG_CONFIG_HOME); grants are read only from ${path17.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
22269
+ const configured = path19.resolve(resolveConfigDir());
22270
+ return configured === path19.resolve(grantsDir()) ? null : `the config directory is redirected to ${configured} (WORKFLOW_TOOLKIT_CONFIG, WORKFLOW_TOOLKIT_CONFIG_DIR or XDG_CONFIG_HOME); grants are read only from ${path19.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
21414
22271
  };
21415
22272
  var GRANT_KINDS = ["push", "pr", "merge", "release", "rerun"];
21416
22273
  var DEFAULT_GRANTS = Object.freeze({
@@ -21463,8 +22320,16 @@ function endpointView(entry, context) {
21463
22320
  ...issue ? { endpointIssue: issue } : {}
21464
22321
  };
21465
22322
  }
21466
- var DEFAULT_VERIFICATION = "self";
21467
- var verificationOf = (entry) => entry?.verification === "independent" ? "independent" : "self";
22323
+ var VERIFICATION_MODES = [
22324
+ "proportional",
22325
+ "self",
22326
+ "independent"
22327
+ ];
22328
+ var DEFAULT_VERIFICATION = "proportional";
22329
+ var verificationOf = (entry) => {
22330
+ const value = entry?.verification;
22331
+ return VERIFICATION_MODES.includes(value) ? value : DEFAULT_VERIFICATION;
22332
+ };
21468
22333
  var isGrantValue = (value) => value === true || value === false || value === "verified";
21469
22334
  var normalized = (kind, value) => value === "verified" && kind !== "merge" ? true : value;
21470
22335
  var fromAutoApprove = (value) => {
@@ -23211,9 +24076,9 @@ class WorkitCore {
23211
24076
  }
23212
24077
  }
23213
24078
  // packages/workit-core/src/core/repo-context.ts
23214
- import { spawnSync as spawnSync11 } from "node:child_process";
23215
- import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync4 } from "node:fs";
23216
- import path18 from "node:path";
24079
+ import { spawnSync as spawnSync12 } from "node:child_process";
24080
+ import { existsSync as existsSync7, readFileSync as readFileSync6, readdirSync as readdirSync4 } from "node:fs";
24081
+ import path20 from "node:path";
23217
24082
  var isSafeContextRange = (value) => value.length <= 4096 && (() => {
23218
24083
  try {
23219
24084
  gitRevisionParts(value);
@@ -23240,7 +24105,7 @@ var invalidRange = (cwd) => ({
23240
24105
  cwd
23241
24106
  });
23242
24107
  var runGit = (cwd, args) => {
23243
- const result = spawnSync11("git", args, { cwd, encoding: "utf8" });
24108
+ const result = spawnSync12("git", args, { cwd, encoding: "utf8" });
23244
24109
  return {
23245
24110
  stdout: (result.stdout ?? "").trimEnd(),
23246
24111
  stderr: (result.stderr ?? "").trimEnd(),
@@ -23347,7 +24212,7 @@ var findPrTemplate = (cwd) => {
23347
24212
  ]) {
23348
24213
  const parts = rel.split("/");
23349
24214
  const base = parts[parts.length - 1];
23350
- const dir = parts.length > 1 ? path18.join(cwd, ...parts.slice(0, -1)) : cwd;
24215
+ const dir = parts.length > 1 ? path20.join(cwd, ...parts.slice(0, -1)) : cwd;
23351
24216
  const actual = probeCaseInsensitive(dir, base);
23352
24217
  if (actual)
23353
24218
  return [...parts.slice(0, -1), actual].join("/");
@@ -23378,11 +24243,11 @@ var diffStatForRange = (cwd, range) => {
23378
24243
  return runGit(cwd, ["diff", "--stat", "--"]).stdout;
23379
24244
  };
23380
24245
  var packageScripts = (cwd, keys) => {
23381
- const pkgPath = path18.join(cwd, "package.json");
23382
- if (!existsSync6(pkgPath))
24246
+ const pkgPath = path20.join(cwd, "package.json");
24247
+ if (!existsSync7(pkgPath))
23383
24248
  return [];
23384
24249
  try {
23385
- const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
24250
+ const pkg = JSON.parse(readFileSync6(pkgPath, "utf8"));
23386
24251
  return keys.filter((k) => pkg.scripts && typeof pkg.scripts[k] === "string").map((k) => `${k}: ${pkg.scripts?.[k]}`);
23387
24252
  } catch {
23388
24253
  return [];
@@ -23404,9 +24269,9 @@ var documentationFiles = (cwd) => {
23404
24269
  if (entry.isDirectory()) {
23405
24270
  if (excluded.has(entry.name))
23406
24271
  continue;
23407
- walk(path18.join(dir, entry.name), depth + 1);
24272
+ walk(path20.join(dir, entry.name), depth + 1);
23408
24273
  } else if (entry.isFile() && (entry.name === "README.md" || entry.name.endsWith(".md"))) {
23409
- matches.push("./" + path18.relative(cwd, path18.join(dir, entry.name)).replaceAll("\\", "/"));
24274
+ matches.push("./" + path20.relative(cwd, path20.join(dir, entry.name)).replaceAll("\\", "/"));
23410
24275
  }
23411
24276
  }
23412
24277
  };
@@ -23414,15 +24279,15 @@ var documentationFiles = (cwd) => {
23414
24279
  return matches.toSorted().slice(0, 200);
23415
24280
  };
23416
24281
  var readTrimmed2 = (file, maxLines) => {
23417
- if (!existsSync6(file))
24282
+ if (!existsSync7(file))
23418
24283
  return "";
23419
- const lines = readFileSync5(file, "utf8").split(`
24284
+ const lines = readFileSync6(file, "utf8").split(`
23420
24285
  `);
23421
24286
  return lines.slice(0, maxLines).join(`
23422
24287
  `);
23423
24288
  };
23424
24289
  function prReadyContext(root, range) {
23425
- const cwd = path18.resolve(repoRoot(root));
24290
+ const cwd = path20.resolve(repoRoot(root));
23426
24291
  if (range !== undefined && !isResolvableContextRange(cwd, range))
23427
24292
  return invalidRange(cwd);
23428
24293
  let stdout = "";
@@ -23480,7 +24345,7 @@ ${status.stderr}` : "");
23480
24345
  stdout += `template_path: ${template}
23481
24346
 
23482
24347
  `;
23483
- stdout += readTrimmed2(path18.join(cwd, template), 220);
24348
+ stdout += readTrimmed2(path20.join(cwd, template), 220);
23484
24349
  } else {
23485
24350
  stdout += `template_path: none
23486
24351
 
@@ -23490,7 +24355,7 @@ ${status.stderr}` : "");
23490
24355
  stdout += `
23491
24356
  `;
23492
24357
  stdout += printSection("Recent Validation Signals");
23493
- if (existsSync6(path18.join(cwd, "package.json"))) {
24358
+ if (existsSync7(path20.join(cwd, "package.json"))) {
23494
24359
  stdout += `package.json detected. Common scripts:
23495
24360
  `;
23496
24361
  const found = packageScripts(cwd, ["lint", "format:check", "test", "build"]);
@@ -23499,7 +24364,7 @@ ${status.stderr}` : "");
23499
24364
  `) + `
23500
24365
  `;
23501
24366
  }
23502
- if (existsSync6(path18.join(cwd, "Cargo.toml")) || existsSync6(path18.join(cwd, "src-tauri/Cargo.toml"))) {
24367
+ if (existsSync7(path20.join(cwd, "Cargo.toml")) || existsSync7(path20.join(cwd, "src-tauri/Cargo.toml"))) {
23503
24368
  stdout += `Rust project detected.
23504
24369
  `;
23505
24370
  }
@@ -23532,7 +24397,7 @@ var CHANGELOG_RULES = `- Use an [Unreleased] section.
23532
24397
  - Apply with the host-native editor, preserving the repository changelog conventions.
23533
24398
  - If Unreleased already has duplicate category headings, normalize_only first.`;
23534
24399
  function changelogContext(root, range) {
23535
- const cwd = path18.resolve(repoRoot(root));
24400
+ const cwd = path20.resolve(repoRoot(root));
23536
24401
  if (range !== undefined && !isResolvableContextRange(cwd, range))
23537
24402
  return invalidRange(cwd);
23538
24403
  const resolvedRange = rangeArgOrDefault(range, cwd);
@@ -23550,8 +24415,8 @@ function changelogContext(root, range) {
23550
24415
  stdout += CHANGELOG_RULES + `
23551
24416
  `;
23552
24417
  stdout += printSection("Existing CHANGELOG.md");
23553
- const changelogPath = path18.join(cwd, "CHANGELOG.md");
23554
- if (existsSync6(changelogPath)) {
24418
+ const changelogPath = path20.join(cwd, "CHANGELOG.md");
24419
+ if (existsSync7(changelogPath)) {
23555
24420
  stdout += readTrimmed2(changelogPath, 260) + `
23556
24421
  `;
23557
24422
  } else {
@@ -23570,7 +24435,7 @@ function changelogContext(root, range) {
23570
24435
  return { stdout, stderr: "", exitCode: 0, cwd };
23571
24436
  }
23572
24437
  function docsRefreshContext(root, range) {
23573
- const cwd = path18.resolve(repoRoot(root));
24438
+ const cwd = path20.resolve(repoRoot(root));
23574
24439
  if (range !== undefined && !isResolvableContextRange(cwd, range))
23575
24440
  return invalidRange(cwd);
23576
24441
  const resolvedRange = rangeArgOrDefault(range, cwd);
@@ -23592,8 +24457,8 @@ function docsRefreshContext(root, range) {
23592
24457
  `) + `
23593
24458
  `;
23594
24459
  stdout += printSection("README Preview");
23595
- const readme = path18.join(cwd, "README.md");
23596
- if (existsSync6(readme)) {
24460
+ const readme = path20.join(cwd, "README.md");
24461
+ if (existsSync7(readme)) {
23597
24462
  stdout += readTrimmed2(readme, 220) + `
23598
24463
  `;
23599
24464
  } else {
@@ -23601,10 +24466,10 @@ function docsRefreshContext(root, range) {
23601
24466
  `;
23602
24467
  }
23603
24468
  stdout += printSection("Package Scripts");
23604
- const pkgPath = path18.join(cwd, "package.json");
23605
- if (existsSync6(pkgPath)) {
24469
+ const pkgPath = path20.join(cwd, "package.json");
24470
+ if (existsSync7(pkgPath)) {
23606
24471
  try {
23607
- const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
24472
+ const pkg = JSON.parse(readFileSync6(pkgPath, "utf8"));
23608
24473
  stdout += JSON.stringify({ name: pkg.name, version: pkg.version, scripts: pkg.scripts }, null, 2) + `
23609
24474
  `;
23610
24475
  } catch {}
@@ -23615,7 +24480,7 @@ function docsRefreshContext(root, range) {
23615
24480
  return { stdout, stderr: "", exitCode: 0, cwd };
23616
24481
  }
23617
24482
  function releaseNotesContext(root, rangeOrTag) {
23618
- const cwd = path18.resolve(repoRoot(root));
24483
+ const cwd = path20.resolve(repoRoot(root));
23619
24484
  if (!rangeOrTag) {
23620
24485
  return { stdout: "", stderr: `ERROR: release tag or range required
23621
24486
  `, exitCode: 1, cwd };
@@ -23653,7 +24518,7 @@ function releaseNotesContext(root, rangeOrTag) {
23653
24518
  `;
23654
24519
  stdout += printSection("Existing Release Files");
23655
24520
  for (const rel of ["CHANGELOG.md", "RELEASE_NOTES.md", ".github/releases.md"]) {
23656
- if (existsSync6(path18.join(cwd, rel)))
24521
+ if (existsSync7(path20.join(cwd, rel)))
23657
24522
  stdout += rel + `
23658
24523
  `;
23659
24524
  }
@@ -23682,46 +24547,6 @@ function releaseNotesContext(root, rangeOrTag) {
23682
24547
 
23683
24548
  // packages/workit-core/src/core/tracker-issues.ts
23684
24549
  import { spawnSync as spawnSync13 } from "node:child_process";
23685
-
23686
- // packages/workit-core/src/core/pr-create.ts
23687
- import fs14 from "node:fs";
23688
- import path19 from "node:path";
23689
- import { spawnSync as spawnSync12 } from "node:child_process";
23690
- // packages/workit-core/src/forge/pr-body.ts
23691
- function parseGhIssue(value) {
23692
- const m = /issues\/(\d+)/.exec(value);
23693
- return m ? m[1] : String(value).trim().replace(/^#/, "");
23694
- }
23695
-
23696
- // packages/workit-core/src/core/pr-create.ts
23697
- function whichOnPath(tool) {
23698
- const names = process.platform === "win32" ? [tool, `${tool}.exe`, `${tool}.cmd`] : [tool];
23699
- for (const dir of (process.env.PATH ?? "").split(path19.delimiter)) {
23700
- if (!dir)
23701
- continue;
23702
- for (const name of names) {
23703
- const candidate = path19.join(dir, name);
23704
- try {
23705
- fs14.accessSync(candidate, fs14.constants.X_OK);
23706
- return candidate;
23707
- } catch {}
23708
- }
23709
- }
23710
- return null;
23711
- }
23712
- var hostingCliAvailable = (provider) => whichOnPath(provider === "gitlab" ? "glab" : "gh") !== null;
23713
- var pushRemote = (cwd) => {
23714
- const result = spawnSync12("git", ["remote", "get-url", "--push", "--all", "origin"], {
23715
- cwd,
23716
- encoding: "utf8"
23717
- });
23718
- if (result.status !== 0)
23719
- return null;
23720
- const urls = (result.stdout ?? "").split(/\r?\n/u).map((url) => url.trim()).filter(Boolean);
23721
- return urls.length === 1 ? urls[0] : null;
23722
- };
23723
-
23724
- // packages/workit-core/src/core/tracker-issues.ts
23725
24550
  var repoPathFromRemote = (remote) => {
23726
24551
  let rest = (remote || "").trim().replace(/\/+$/, "");
23727
24552
  if (!rest)
@@ -23821,7 +24646,7 @@ var fetchGitLabIssueBody = async (ref, root, deps = {}) => {
23821
24646
 
23822
24647
  // packages/workit-core/src/core/youtrack.ts
23823
24648
  import fs15 from "node:fs";
23824
- import path20 from "node:path";
24649
+ import path21 from "node:path";
23825
24650
 
23826
24651
  // packages/workit-core/src/core/templates.ts
23827
24652
  var repoRoot2 = assetRoot();
@@ -23834,8 +24659,8 @@ var resolveWorkspaceRoot = (explicit) => explicit || process.cwd();
23834
24659
  // packages/workit-core/src/core/youtrack.ts
23835
24660
  var ISSUE_RE = /^[A-Z]+-\d+$/;
23836
24661
  var TOKEN_PLACEHOLDER = "YOUR_TOKEN_HERE";
23837
- var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path20.join(configDir(), "youtrack.json");
23838
- var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path20.join(resolveConfigDir(), "youtrack.json");
24662
+ var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path21.join(configDir(), "youtrack.json");
24663
+ var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path21.join(resolveConfigDir(), "youtrack.json");
23839
24664
  var youTrackTokenModeOk = (p) => {
23840
24665
  if (process.platform === "win32")
23841
24666
  return true;
@@ -23903,7 +24728,7 @@ var youTrackToken = () => {
23903
24728
  if ("error" in loaded)
23904
24729
  return loaded;
23905
24730
  const tokenFile = String(loaded.config.tokenFile ?? "");
23906
- const tokenPath = tokenFile ? path20.isAbsolute(tokenFile) ? path20.resolve(tokenFile) : path20.resolve(process.cwd(), tokenFile) : "";
24731
+ const tokenPath = tokenFile ? path21.isAbsolute(tokenFile) ? path21.resolve(tokenFile) : path21.resolve(process.cwd(), tokenFile) : "";
23907
24732
  if (!tokenPath || !fs15.existsSync(tokenPath))
23908
24733
  return { error: "missing youtrack.token" };
23909
24734
  if (!youTrackTokenModeOk(tokenPath))
@@ -24245,15 +25070,15 @@ function resolveGitRevision(root, value) {
24245
25070
  }
24246
25071
  function resolveInside(root, candidate) {
24247
25072
  const base = realpathSync5(root);
24248
- const target = path21.resolve(base, candidate);
24249
- if (target !== base && !target.startsWith(base + path21.sep)) {
25073
+ const target = path22.resolve(base, candidate);
25074
+ if (target !== base && !target.startsWith(base + path22.sep)) {
24250
25075
  throw new Error("path must stay inside repository root");
24251
25076
  }
24252
25077
  let ancestor = target;
24253
- while (!existsSync7(ancestor))
24254
- ancestor = path21.dirname(ancestor);
25078
+ while (!existsSync8(ancestor))
25079
+ ancestor = path22.dirname(ancestor);
24255
25080
  const canonicalAncestor = realpathSync5(ancestor);
24256
- if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path21.sep)) {
25081
+ if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path22.sep)) {
24257
25082
  throw new Error("path must stay inside repository root");
24258
25083
  }
24259
25084
  return target;
@@ -24284,8 +25109,8 @@ var SUPPORT_MATRIX = {
24284
25109
  };
24285
25110
 
24286
25111
  // packages/workit-mcp/src/server.ts
24287
- import { existsSync as existsSync8, readFileSync as readFileSync6, realpathSync as realpathSync6 } from "node:fs";
24288
- import path22 from "node:path";
25112
+ import { existsSync as existsSync9, readFileSync as readFileSync7, realpathSync as realpathSync6 } from "node:fs";
25113
+ import path23 from "node:path";
24289
25114
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
24290
25115
  function isZ4Schema(s) {
24291
25116
  const schema = s;
@@ -26689,7 +27514,7 @@ var safeCapability = (value, allowed) => allowed.includes(value) ? value : "cont
26689
27514
  var TOOL_CAPABILITIES = [...CONTEXT_KINDS, "workspace", "native_caller_identity"];
26690
27515
  var VERSION = (() => {
26691
27516
  try {
26692
- const packageJson = JSON.parse(readFileSync6(new URL("../package.json", import.meta.url), "utf8"));
27517
+ const packageJson = JSON.parse(readFileSync7(new URL("../package.json", import.meta.url), "utf8"));
26693
27518
  return typeof packageJson.version === "string" ? packageJson.version : "0.0.0";
26694
27519
  } catch {
26695
27520
  return "0.0.0";
@@ -26699,13 +27524,13 @@ var rootVariants = (workspaceRoot) => {
26699
27524
  if (!workspaceRoot)
26700
27525
  return [];
26701
27526
  const roots = new Set;
26702
- for (const candidate of [workspaceRoot, path22.resolve(workspaceRoot)]) {
26703
- if (path22.isAbsolute(candidate) && candidate !== path22.parse(candidate).root)
27527
+ for (const candidate of [workspaceRoot, path23.resolve(workspaceRoot)]) {
27528
+ if (path23.isAbsolute(candidate) && candidate !== path23.parse(candidate).root)
26704
27529
  roots.add(candidate);
26705
27530
  }
26706
27531
  try {
26707
27532
  const canonical = realpathSync6(workspaceRoot);
26708
- if (canonical !== path22.parse(canonical).root)
27533
+ if (canonical !== path23.parse(canonical).root)
26709
27534
  roots.add(canonical);
26710
27535
  } catch {}
26711
27536
  return [...roots].toSorted((left, right) => right.length - left.length);
@@ -26787,12 +27612,12 @@ var thrownResult = (tool, error, workspaceRoot) => {
26787
27612
  };
26788
27613
  function createMcpServer(host, contextProvider) {
26789
27614
  assertMcpHost(host);
26790
- const here = path22.dirname(fileURLToPath2(import.meta.url));
27615
+ const here = path23.dirname(fileURLToPath2(import.meta.url));
26791
27616
  const sourceMarker = markSourcesLoaded([
26792
- path22.join(here, "server.ts"),
26793
- path22.join(here, "..", "..", "workit-core", "src", "core", "task-contract.ts"),
26794
- path22.join(here, "..", "..", "workit-core", "src", "core", "task-engine.ts")
26795
- ].filter((file) => existsSync8(file)));
27617
+ path23.join(here, "server.ts"),
27618
+ path23.join(here, "..", "..", "workit-core", "src", "core", "task-contract.ts"),
27619
+ path23.join(here, "..", "..", "workit-core", "src", "core", "task-engine.ts")
27620
+ ].filter((file) => existsSync9(file)));
26796
27621
  let staleWarned = false;
26797
27622
  const server = new Server({ name: "workit", version: VERSION }, { capabilities: { tools: {}, resources: {} } });
26798
27623
  server.setRequestHandler(ListToolsRequestSchema, async () => {
@@ -27109,7 +27934,7 @@ var EXEC = new Set(["exec", "x", "dlx"]);
27109
27934
  // packages/workit-core/src/core/heavy-words.ts
27110
27935
  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(" "));
27111
27936
  // packages/workit-core/src/hooks/write-gate.ts
27112
- import path23 from "node:path";
27937
+ import path24 from "node:path";
27113
27938
 
27114
27939
  // packages/workit-core/src/core/live-session.ts
27115
27940
  import { spawnSync as spawnSync15 } from "node:child_process";
@@ -27150,7 +27975,7 @@ var MUTATING_WORKIT_GIT = new Set(["commit", "branch"]);
27150
27975
  var CD2 = new Set(["cd", "chdir", "set-location", "sl"]);
27151
27976
  var PUSHD2 = new Set(["pushd", "push-location"]);
27152
27977
  var POPD2 = new Set(["popd", "pop-location"]);
27153
- var UNKNOWN_DIR = path23.resolve(path23.parse(process.cwd()).root, ".workit-unknown-dir");
27978
+ var UNKNOWN_DIR = path24.resolve(path24.parse(process.cwd()).root, ".workit-unknown-dir");
27154
27979
  // packages/workit-core/src/core/skill-manifests.ts
27155
27980
  if (false) {}
27156
27981
 
@@ -27363,24 +28188,24 @@ if (false)
27363
28188
 
27364
28189
  // packages/workit-codex/scripts/agents.ts
27365
28190
  import {
27366
- existsSync as existsSync9,
28191
+ existsSync as existsSync10,
27367
28192
  lstatSync as lstatSync3,
27368
28193
  mkdirSync as mkdirSync3,
27369
28194
  readdirSync as readdirSync5,
27370
- readFileSync as readFileSync7,
28195
+ readFileSync as readFileSync8,
27371
28196
  renameSync as renameSync2,
27372
28197
  rmSync as rmSync2,
27373
28198
  writeFileSync as writeFileSync3
27374
28199
  } from "node:fs";
27375
28200
  import os5 from "node:os";
27376
- import path24 from "node:path";
28201
+ import path25 from "node:path";
27377
28202
  var CODEX_AGENT_MARKER = "# Generated by Workit";
27378
28203
  var codexHomeOfInstall = (pluginRoot) => {
27379
- const parts = path24.resolve(pluginRoot).split(path24.sep);
28204
+ const parts = path25.resolve(pluginRoot).split(path25.sep);
27380
28205
  const cache = parts.length - 4;
27381
- return cache >= 2 && parts[cache] === "cache" && parts[cache - 1] === "plugins" ? parts.slice(0, cache - 1).join(path24.sep) || path24.sep : null;
28206
+ return cache >= 2 && parts[cache] === "cache" && parts[cache - 1] === "plugins" ? parts.slice(0, cache - 1).join(path25.sep) || path25.sep : null;
27382
28207
  };
27383
- var codexHomeFor = (pluginRoot, env) => codexHomeOfInstall(pluginRoot) ?? (env.CODEX_HOME || path24.join(env.HOME || os5.homedir(), ".codex"));
28208
+ var codexHomeFor = (pluginRoot, env) => codexHomeOfInstall(pluginRoot) ?? (env.CODEX_HOME || path25.join(env.HOME || os5.homedir(), ".codex"));
27384
28209
  var MARKER_VERSION = /^# Generated by Workit (\d+\.\d+\.\d+)\b/;
27385
28210
  var agentMarkerVersion = (text) => MARKER_VERSION.exec(text)?.[1] ?? null;
27386
28211
  var stampCodexAgent = (content, version) => version && content.startsWith(CODEX_AGENT_MARKER) && !agentMarkerVersion(content) ? `${CODEX_AGENT_MARKER} ${version}${content.slice(CODEX_AGENT_MARKER.length)}` : content;
@@ -27394,7 +28219,7 @@ var versionAtLeast = (version, min) => {
27394
28219
  };
27395
28220
  var pluginVersion = (pluginRoot) => {
27396
28221
  try {
27397
- const version = JSON.parse(readFileSync7(path24.join(pluginRoot, "package.json"), "utf8")).version;
28222
+ const version = JSON.parse(readFileSync8(path25.join(pluginRoot, "package.json"), "utf8")).version;
27398
28223
  return typeof version === "string" && /^\d+\.\d+\.\d+/.test(version) ? version.match(/^\d+\.\d+\.\d+/)[0] : null;
27399
28224
  } catch {
27400
28225
  return null;
@@ -27408,15 +28233,15 @@ var lstatOrNull = (file) => {
27408
28233
  }
27409
28234
  };
27410
28235
  var installCodexAgents = (pluginRoot, codexHome) => {
27411
- const source = path24.join(pluginRoot, "agents");
27412
- if (!existsSync9(source))
28236
+ const source = path25.join(pluginRoot, "agents");
28237
+ if (!existsSync10(source))
27413
28238
  return [];
27414
28239
  const version = pluginVersion(pluginRoot);
27415
- const target = path24.join(codexHome, "agents");
28240
+ const target = path25.join(codexHome, "agents");
27416
28241
  const results = [];
27417
28242
  for (const file of readdirSync5(source).filter((name) => name.endsWith(".toml")).toSorted()) {
27418
- const content = stampCodexAgent(readFileSync7(path24.join(source, file), "utf8"), version);
27419
- const dest = path24.join(target, file);
28243
+ const content = stampCodexAgent(readFileSync8(path25.join(source, file), "utf8"), version);
28244
+ const dest = path25.join(target, file);
27420
28245
  const stat = lstatOrNull(dest);
27421
28246
  if (stat?.isSymbolicLink()) {
27422
28247
  results.push({ file: dest, action: "skipped-symlink" });
@@ -27438,7 +28263,7 @@ var installCodexAgents = (pluginRoot, codexHome) => {
27438
28263
  results.push({ file: dest, action: "kept-user-file" });
27439
28264
  continue;
27440
28265
  }
27441
- const current = readFileSync7(dest, "utf8");
28266
+ const current = readFileSync8(dest, "utf8");
27442
28267
  if (current === content) {
27443
28268
  results.push({ file: dest, action: "current" });
27444
28269
  continue;
@@ -27452,7 +28277,7 @@ var installCodexAgents = (pluginRoot, codexHome) => {
27452
28277
  results.push({ file: dest, action: "kept-newer-version" });
27453
28278
  continue;
27454
28279
  }
27455
- const temp = path24.join(target, `.${file}.${process.pid}.${Date.now()}.tmp`);
28280
+ const temp = path25.join(target, `.${file}.${process.pid}.${Date.now()}.tmp`);
27456
28281
  writeFileSync3(temp, content, { flag: "wx" });
27457
28282
  try {
27458
28283
  renameSync2(temp, dest);
@@ -27474,8 +28299,8 @@ var codexQualification = (host) => host === "codex_cli" ? { surface: host, cli:
27474
28299
  var resolveCodexWorkspaceRoot = (pluginRoot, env) => {
27475
28300
  const explicit = env.WORKFLOW_WORKSPACE_ROOT;
27476
28301
  const inherited = env.PWD;
27477
- const candidate = explicit ?? (inherited && path25.resolve(inherited) !== path25.resolve(pluginRoot) ? inherited : undefined);
27478
- if (!candidate || !path25.isAbsolute(candidate) || !existsSync10(candidate))
28302
+ const candidate = explicit ?? (inherited && path26.resolve(inherited) !== path26.resolve(pluginRoot) ? inherited : undefined);
28303
+ if (!candidate || !path26.isAbsolute(candidate) || !existsSync11(candidate))
27479
28304
  return null;
27480
28305
  try {
27481
28306
  if (!statSync3(candidate).isDirectory())
@@ -27514,7 +28339,7 @@ var codexContextProvider = (host = detectCodexSurface(process.env), root) => ({
27514
28339
  };
27515
28340
  }
27516
28341
  });
27517
- var pluginRoot = () => path25.resolve(path25.dirname(fileURLToPath3(import.meta.url)), "..");
28342
+ var pluginRoot = () => path26.resolve(path26.dirname(fileURLToPath3(import.meta.url)), "..");
27518
28343
  var syncCodexAgents = (root) => {
27519
28344
  const codexHome = codexHomeOfInstall(root);
27520
28345
  if (!codexHome)