@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.
@@ -6622,15 +6622,15 @@ var require_dist = __commonJS(function(exports, module) {
6622
6622
 
6623
6623
  // packages/workit-cursor/mcp/run-server.ts
6624
6624
  import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "node:fs";
6625
- import path25 from "node:path";
6625
+ import path26 from "node:path";
6626
6626
 
6627
6627
  // packages/workit-mcp/src/index.ts
6628
6628
  import { fileURLToPath as fileURLToPath3 } from "node:url";
6629
- import path23 from "node:path";
6629
+ import path24 from "node:path";
6630
6630
 
6631
6631
  // packages/workit-mcp/src/server.ts
6632
- import { existsSync as existsSync8, readFileSync as readFileSync6, realpathSync as realpathSync6 } from "node:fs";
6633
- import path22 from "node:path";
6632
+ import { existsSync as existsSync9, readFileSync as readFileSync7, realpathSync as realpathSync6 } from "node:fs";
6633
+ import path23 from "node:path";
6634
6634
 
6635
6635
  // node_modules/zod/v4/core/util.js
6636
6636
  function getEnumValues(entries) {
@@ -14943,8 +14943,8 @@ import { fileURLToPath as fileURLToPath2 } from "node:url";
14943
14943
 
14944
14944
  // packages/workit-core/src/core.ts
14945
14945
  import { spawnSync as spawnSync14 } from "node:child_process";
14946
- import { existsSync as existsSync7, realpathSync as realpathSync5 } from "node:fs";
14947
- import path21 from "node:path";
14946
+ import { existsSync as existsSync8, realpathSync as realpathSync5 } from "node:fs";
14947
+ import path22 from "node:path";
14948
14948
 
14949
14949
  // packages/workit-core/src/core/task-contract.ts
14950
14950
  import { createHash, randomUUID } from "node:crypto";
@@ -17240,7 +17240,7 @@ var workspaceConfigSchema = object2({
17240
17240
  }).passthrough().optional(),
17241
17241
  autoApprove: union([boolean2(), array(nonBlank)]).optional(),
17242
17242
  defaultEndpoint: unknown().optional(),
17243
- verification: _enum(["self", "independent"]).optional(),
17243
+ verification: _enum(["proportional", "self", "independent"]).optional(),
17244
17244
  delegation: unknown().optional(),
17245
17245
  trailers: boolean2().optional(),
17246
17246
  liveSessionGuard: boolean2().optional(),
@@ -17781,6 +17781,124 @@ function resolveRef(cwd, ref) {
17781
17781
  return null;
17782
17782
  return line(git(cwd, ["rev-parse", "--verify", "-q", `${ref}^{commit}`]));
17783
17783
  }
17784
+ var LANE_DIFF = [
17785
+ "-c",
17786
+ "core.quotePath=false",
17787
+ "diff",
17788
+ "--no-color",
17789
+ "--no-ext-diff",
17790
+ "--no-textconv",
17791
+ "--no-renames"
17792
+ ];
17793
+ var laneRange = (fork, head) => {
17794
+ if (!safeArg(fork) || head !== null && !safeArg(head))
17795
+ return null;
17796
+ return head === null ? [fork] : [fork, head];
17797
+ };
17798
+ function diffNumstat(cwd, fork, head) {
17799
+ const range = laneRange(fork, head);
17800
+ if (!range)
17801
+ return null;
17802
+ const run = git(cwd, [...LANE_DIFF, "--numstat", "-z", ...range, "--"]);
17803
+ if (!run.ok)
17804
+ return null;
17805
+ const out = [];
17806
+ for (const record of run.stdout.split("\x00")) {
17807
+ const match = /^(-|\d+)\t(-|\d+)\t(.+)$/su.exec(record.replace(/^\n/u, ""));
17808
+ if (!match)
17809
+ continue;
17810
+ const binary = match[1] === "-";
17811
+ out.push({
17812
+ path: match[3],
17813
+ added: binary ? 0 : Number(match[1]),
17814
+ deleted: binary ? 0 : Number(match[2]),
17815
+ binary
17816
+ });
17817
+ }
17818
+ return out;
17819
+ }
17820
+ function diffRaw(cwd, fork, head) {
17821
+ const range = laneRange(fork, head);
17822
+ if (!range)
17823
+ return null;
17824
+ const run = git(cwd, [...LANE_DIFF, "--raw", "-z", "--no-abbrev", ...range, "--"]);
17825
+ if (!run.ok)
17826
+ return null;
17827
+ const fields = run.stdout.split("\x00");
17828
+ const out = [];
17829
+ for (let index = 0;index + 1 < fields.length; index += 2) {
17830
+ const meta = /^:(\d{6}) (\d{6}) ([0-9a-f]+) ([0-9a-f]+) [A-Z]\d*$/u.exec(fields[index].replace(/^\n/u, ""));
17831
+ if (!meta)
17832
+ return null;
17833
+ out.push({
17834
+ path: fields[index + 1],
17835
+ oldMode: meta[1],
17836
+ newMode: meta[2],
17837
+ oldBlob: meta[3],
17838
+ newBlob: meta[4]
17839
+ });
17840
+ }
17841
+ return out;
17842
+ }
17843
+ function readBlobs(cwd, ids) {
17844
+ const out = new Map;
17845
+ const wanted = [...new Set(ids)].filter((id) => /^[0-9a-f]{40,64}$/u.test(id));
17846
+ if (!wanted.length)
17847
+ return out;
17848
+ const run = spawnSync3("git", ["cat-file", "--batch"], {
17849
+ cwd,
17850
+ input: `${wanted.join(`
17851
+ `)}
17852
+ `,
17853
+ maxBuffer: MAX_BUFFER,
17854
+ timeout: GIT_TIMEOUTS.local,
17855
+ killSignal: "SIGKILL",
17856
+ windowsHide: true
17857
+ });
17858
+ if (run.status !== 0 || !run.stdout)
17859
+ return null;
17860
+ const bytes = run.stdout;
17861
+ let at = 0;
17862
+ for (const id of wanted) {
17863
+ const end = bytes.indexOf(10, at);
17864
+ if (end < 0)
17865
+ return null;
17866
+ const header = bytes.subarray(at, end).toString("utf8").split(" ");
17867
+ at = end + 1;
17868
+ if (header[1] === "missing")
17869
+ continue;
17870
+ const size = Number(header[2]);
17871
+ if (header[0] !== id || !Number.isSafeInteger(size))
17872
+ return null;
17873
+ out.set(id, bytes.subarray(at, at + size));
17874
+ at += size + 1;
17875
+ }
17876
+ return out;
17877
+ }
17878
+ function treeFilesNamed(cwd, rev, name) {
17879
+ if (!safeArg(rev))
17880
+ return null;
17881
+ const run = git(cwd, ["ls-tree", "-r", "-z", "--full-tree", rev]);
17882
+ if (!run.ok)
17883
+ return null;
17884
+ const out = new Map;
17885
+ for (const record of run.stdout.split("\x00")) {
17886
+ const match = /^\d{6} blob ([0-9a-f]+)\t(.+)$/su.exec(record);
17887
+ if (match && (match[2] === name || match[2].endsWith(`/${name}`)))
17888
+ out.set(match[2], match[1]);
17889
+ }
17890
+ return out;
17891
+ }
17892
+ function fileAt(cwd, rev, file) {
17893
+ if (!safeArg(rev))
17894
+ return null;
17895
+ const run = git(cwd, ["cat-file", "blob", `${rev}:${file}`]);
17896
+ return run.ok ? run.stdout : null;
17897
+ }
17898
+ function untrackedFiles(cwd) {
17899
+ const run = git(cwd, ["ls-files", "-z", "--others", "--exclude-standard"]);
17900
+ return run.ok ? run.stdout.split("\x00").filter(Boolean) : [];
17901
+ }
17784
17902
  var config2 = (cwd, key) => line(git(cwd, ["config", "--get", key]));
17785
17903
  function currentBranch(cwd) {
17786
17904
  return line(git(cwd, ["symbolic-ref", "--short", "-q", "HEAD"]));
@@ -21289,9 +21407,9 @@ var workerBlocksTransition = (transition, state) => transition === "pause" ? fal
21289
21407
 
21290
21408
  // packages/workit-core/src/core/task-evaluation.ts
21291
21409
  import { createHash as createHash10 } from "node:crypto";
21292
- import * as fs13 from "node:fs";
21293
- import { spawnSync as spawnSync10 } from "node:child_process";
21294
- import path16 from "node:path";
21410
+ import * as fs14 from "node:fs";
21411
+ import { spawnSync as spawnSync11 } from "node:child_process";
21412
+ import path18 from "node:path";
21295
21413
 
21296
21414
  // packages/workit-core/src/check-config.ts
21297
21415
  import { spawnSync as spawnSync8 } from "node:child_process";
@@ -21511,8 +21629,8 @@ function checkCommand(args, version, onPath = workitAvailable()) {
21511
21629
  }
21512
21630
 
21513
21631
  // packages/workit-core/src/core/policy/derive.ts
21514
- import { existsSync as existsSync4 } from "node:fs";
21515
- import path15 from "node:path";
21632
+ import { existsSync as existsSync5 } from "node:fs";
21633
+ import path17 from "node:path";
21516
21634
 
21517
21635
  // packages/workit-core/src/ledger.ts
21518
21636
  import { spawnSync as spawnSync9 } from "node:child_process";
@@ -22356,7 +22474,8 @@ function checkVerdicts(cwd, branch, ledgerRows) {
22356
22474
  verdict: failing?.verdict ?? null,
22357
22475
  reasons: failing ? ["failing_verdict"] : !newestCurrent ? ["no_verdict"] : newestCurrent.reasons.length ? newestCurrent.reasons : ["type_check_only"]
22358
22476
  };
22359
- const selfEntry = failing ? undefined : verdicts.findLast((entry) => entry.current && !entry.independent && !untrusted(entry.reasons) && STRONG_RESULTS.has(String(entry.verdict.result)));
22477
+ 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))));
22478
+ const selfEntry = latestSelf && STRONG_RESULTS.has(String(latestSelf.verdict.result)) ? latestSelf : undefined;
22360
22479
  return {
22361
22480
  branch,
22362
22481
  head,
@@ -22378,12 +22497,721 @@ var OBSERVED_ONLY = new Set([
22378
22497
  ...PR_ROW_TYPES
22379
22498
  ]);
22380
22499
 
22500
+ // packages/workit-core/src/core/policy/lane.ts
22501
+ import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
22502
+ import path16 from "node:path";
22503
+
22504
+ // packages/workit-core/src/core/pr-create.ts
22505
+ import fs13 from "node:fs";
22506
+ import path15 from "node:path";
22507
+ import { spawnSync as spawnSync10 } from "node:child_process";
22508
+ // packages/workit-core/src/forge/pr-body.ts
22509
+ function parseGhIssue(value) {
22510
+ const m = /issues\/(\d+)/.exec(value);
22511
+ return m ? m[1] : String(value).trim().replace(/^#/, "");
22512
+ }
22513
+
22514
+ // packages/workit-core/src/core/pr-create.ts
22515
+ function whichOnPath(tool) {
22516
+ const names = process.platform === "win32" ? [tool, `${tool}.exe`, `${tool}.cmd`] : [tool];
22517
+ for (const dir of (process.env.PATH ?? "").split(path15.delimiter)) {
22518
+ if (!dir)
22519
+ continue;
22520
+ for (const name of names) {
22521
+ const candidate = path15.join(dir, name);
22522
+ try {
22523
+ fs13.accessSync(candidate, fs13.constants.X_OK);
22524
+ return candidate;
22525
+ } catch {}
22526
+ }
22527
+ }
22528
+ return null;
22529
+ }
22530
+ var hostingCliAvailable = (provider) => whichOnPath(provider === "gitlab" ? "glab" : "gh") !== null;
22531
+ var pushRemote = (cwd) => {
22532
+ const result = spawnSync10("git", ["remote", "get-url", "--push", "--all", "origin"], {
22533
+ cwd,
22534
+ encoding: "utf8"
22535
+ });
22536
+ if (result.status !== 0)
22537
+ return null;
22538
+ const urls = (result.stdout ?? "").split(/\r?\n/u).map((url) => url.trim()).filter(Boolean);
22539
+ return urls.length === 1 ? urls[0] : null;
22540
+ };
22541
+
22542
+ // packages/workit-core/src/forge/redact.ts
22543
+ 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_.-]*`;
22544
+ var ASSIGNMENT = new RegExp(String.raw`(?<![A-Za-z0-9])(["']?${KEY}["']?\s*[:=]\s*["']?)((?:bearer|basic|token|digest)\s+)?([^\s"',;&]+)`, "giu");
22545
+ var QUOTED_ASSIGNMENT = new RegExp(String.raw`(?<![A-Za-z0-9])(["']?${KEY}["']?\s*[:=]\s*)(["'])([^"'\n]*[^\s"'][^"'\n]*)\2`, "giu");
22546
+ var ANSI = new RegExp(String.raw`\u001b\[[0-9;?]*[ -/]*[@-~]|\u001b\][^\u0007]*\u0007`, "gu");
22547
+
22548
+ // packages/workit-core/src/git/ops.ts
22549
+ var COMMIT_TIMEOUT_MS = 10 * 60000;
22550
+
22551
+ // packages/workit-core/src/core/policy/attributes.ts
22552
+ function patternRegex(dir, pattern) {
22553
+ if (!pattern || pattern.endsWith("/") || pattern.startsWith('"') || pattern.startsWith("!"))
22554
+ return null;
22555
+ const anchored = pattern.includes("/");
22556
+ const body = pattern.replace(/^\//u, "");
22557
+ let source = "";
22558
+ for (let index = 0;index < body.length; index += 1) {
22559
+ const char = body[index];
22560
+ if (char === "*" && body[index + 1] === "*") {
22561
+ const slash = body[index + 2] === "/";
22562
+ source += slash ? "(?:.*/)?" : ".*";
22563
+ index += slash ? 2 : 1;
22564
+ } else if (char === "*")
22565
+ source += "[^/]*";
22566
+ else if (char === "?")
22567
+ source += "[^/]";
22568
+ else if (char === "[") {
22569
+ const end = body.indexOf("]", index + 2);
22570
+ if (end < 0)
22571
+ return null;
22572
+ const set = body.slice(index + 1, end).replace(/^!/u, "^").replace(/\\/gu, "\\\\");
22573
+ source += `[${set}]`;
22574
+ index = end;
22575
+ } else if (char === "\\" && index + 1 < body.length) {
22576
+ source += body[index + 1].replace(/[.*+?^${}()|[\]\\/]/gu, "\\$&");
22577
+ index += 1;
22578
+ } else
22579
+ source += char.replace(/[.*+?^${}()|[\]\\/]/gu, "\\$&");
22580
+ }
22581
+ const prefix = dir ? `${dir.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")}/` : "";
22582
+ try {
22583
+ return new RegExp(anchored ? `^${prefix}${source}$` : `^${prefix}(?:.*/)?${source}$`, "u");
22584
+ } catch {
22585
+ return null;
22586
+ }
22587
+ }
22588
+ function rulesOf(dir, text) {
22589
+ const out = [];
22590
+ for (const raw of text.split(`
22591
+ `)) {
22592
+ const line = raw.trim();
22593
+ if (!line || line.startsWith("#") || line.startsWith("[attr]"))
22594
+ continue;
22595
+ const [pattern, ...attributes] = line.split(/\s+/u);
22596
+ let generated = null;
22597
+ for (const attribute of attributes) {
22598
+ if (attribute === "linguist-generated" || attribute === "linguist-generated=true")
22599
+ generated = true;
22600
+ else if (attribute === "-linguist-generated" || attribute === "!linguist-generated" || attribute.startsWith("linguist-generated="))
22601
+ generated = false;
22602
+ }
22603
+ if (generated === null)
22604
+ continue;
22605
+ const regex = patternRegex(dir, pattern);
22606
+ if (regex)
22607
+ out.push({ regex, generated });
22608
+ }
22609
+ return out;
22610
+ }
22611
+ function generatedByAttributes(files, paths) {
22612
+ const rules = [...files].map(([file, text]) => {
22613
+ const dir = file.includes("/") ? file.slice(0, file.lastIndexOf("/")) : "";
22614
+ return {
22615
+ depth: dir ? dir.split("/").length : 0,
22616
+ rules: rulesOf(dir, text)
22617
+ };
22618
+ }).toSorted((left, right) => left.depth - right.depth).flatMap((entry) => entry.rules);
22619
+ const out = new Set;
22620
+ for (const file of paths) {
22621
+ const last = rules.findLast((rule) => rule.regex.test(file));
22622
+ if (last?.generated)
22623
+ out.add(file);
22624
+ }
22625
+ return out;
22626
+ }
22627
+
22628
+ // packages/workit-core/src/core/policy/substance.ts
22629
+ var SLASH_BLOCK = [["/*", "*/"]];
22630
+ var C_LIKE = { line: ["//"], block: SLASH_BLOCK, quotes: `"'` };
22631
+ var SYNTAXES = Object.fromEntries([
22632
+ ...["ts", "mts", "cts", "js", "mjs", "cjs"].map((ext) => [ext, { ...C_LIKE, js: true }]),
22633
+ ...["java", "kt", "kts", "scala", "swift", "dart", "groovy"].map((ext) => [
22634
+ ext,
22635
+ { ...C_LIKE, triple: true }
22636
+ ]),
22637
+ ["go", { ...C_LIKE, rawBacktick: true }],
22638
+ ...["css", "scss", "less"].map((ext) => [
22639
+ ext,
22640
+ { line: [], block: SLASH_BLOCK, quotes: `"'`, cssUrl: true }
22641
+ ]),
22642
+ ...["py", "pyi"].map((ext) => [
22643
+ ext,
22644
+ { line: ["#"], block: [], quotes: `"'`, triple: true, indented: true, fstring: true }
22645
+ ]),
22646
+ ["toml", { line: ["#"], block: [], quotes: `"`, literal: "'", triple: true }],
22647
+ ...["html", "htm", "xml", "svg", "xhtml"].map((ext) => [
22648
+ ext,
22649
+ { line: [], block: [["<!--", "-->"]], quotes: "", indented: true }
22650
+ ])
22651
+ ]);
22652
+ 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;
22653
+ var extensionOf = (file) => {
22654
+ const name = file.slice(file.lastIndexOf("/") + 1);
22655
+ const dot = name.lastIndexOf(".");
22656
+ return dot > 0 ? name.slice(dot + 1).toLowerCase() : "";
22657
+ };
22658
+ var CI_PATH = /^\.github\/|(?:^|\/)(?:\.gitlab-ci\.ya?ml|Jenkinsfile|azure-pipelines\.ya?ml|\.pre-commit-config\.ya?ml|\.circleci\/.*)$/u;
22659
+ var syntaxOf = (file) => CI_PATH.test(file) ? null : SYNTAXES[extensionOf(file)] ?? null;
22660
+ var SPACE = /[ \t\r\f\v]/u;
22661
+ var WORD = /[\w$]/u;
22662
+ var NO_SPACE_AFTER = "([{,;";
22663
+ var NO_SPACE_BEFORE = ")]},;";
22664
+ var REGEX_AFTER = "(,=:[!&|?{};+-*%<>~^";
22665
+ var REGEX_KEYWORDS = new Set([
22666
+ "return",
22667
+ "typeof",
22668
+ "instanceof",
22669
+ "case",
22670
+ "do",
22671
+ "else",
22672
+ "in",
22673
+ "of",
22674
+ "new",
22675
+ "delete",
22676
+ "void",
22677
+ "throw",
22678
+ "yield",
22679
+ "await"
22680
+ ]);
22681
+ function substanceOf(file, text) {
22682
+ const syntax = syntaxOf(file);
22683
+ if (!syntax)
22684
+ return plainSubstance(text);
22685
+ const markup = syntax.block.some(([open]) => open === "<!--");
22686
+ if (markup && (/<(?:script|style)\b|<!\[CDATA\[|<\?/iu.test(text) || /[^>\s][ \t]*<!--/u.test(text)))
22687
+ return plainSubstance(text);
22688
+ return lex(syntax, text);
22689
+ }
22690
+ function plainSubstance(text) {
22691
+ return text.split(`
22692
+ `).map((line) => line.replace(/[ \t\r\f\v]+$/u, "")).filter(Boolean).join(`
22693
+ `);
22694
+ }
22695
+ function lex(syntax, text) {
22696
+ const collapse = !syntax.indented;
22697
+ let out = "";
22698
+ let lineStart = 0;
22699
+ let kept = 0;
22700
+ let pendingSpace = false;
22701
+ const frames = [{ kind: "code", braces: 0 }];
22702
+ let index = 0;
22703
+ if (text.startsWith("#!")) {
22704
+ const end = text.indexOf(`
22705
+ `);
22706
+ out = end < 0 ? text : text.slice(0, end);
22707
+ kept = out.length;
22708
+ index = end < 0 ? text.length : end;
22709
+ }
22710
+ const emitCode = (chunk) => {
22711
+ if (collapse && pendingSpace && out.length > lineStart) {
22712
+ const before = out[out.length - 1];
22713
+ if (!NO_SPACE_AFTER.includes(before) && !NO_SPACE_BEFORE.includes(chunk[0]))
22714
+ out += " ";
22715
+ }
22716
+ pendingSpace = false;
22717
+ out += chunk;
22718
+ };
22719
+ const emitVerbatim = (chunk) => {
22720
+ emitCode(chunk);
22721
+ kept = out.length;
22722
+ };
22723
+ const newline = () => {
22724
+ if (!collapse) {
22725
+ let end = out.length;
22726
+ while (end > Math.max(lineStart, kept) && SPACE.test(out[end - 1]))
22727
+ end -= 1;
22728
+ out = out.slice(0, end);
22729
+ }
22730
+ pendingSpace = false;
22731
+ if (out.length > lineStart) {
22732
+ out += `
22733
+ `;
22734
+ lineStart = out.length;
22735
+ }
22736
+ };
22737
+ const regexAllowed = () => {
22738
+ let end = out.length;
22739
+ while (end > 0 && /\s/u.test(out[end - 1]))
22740
+ end -= 1;
22741
+ if (end === 0 || REGEX_AFTER.includes(out[end - 1]))
22742
+ return true;
22743
+ let start = end;
22744
+ while (start > 0 && WORD.test(out[start - 1]))
22745
+ start -= 1;
22746
+ return REGEX_KEYWORDS.has(out.slice(start, end));
22747
+ };
22748
+ const scanString = (quote, escapes, multiline) => {
22749
+ const prefix = text.slice(Math.max(0, index - 2), index).match(/[a-z]*$/iu)?.[0] ?? "";
22750
+ const fstring = syntax.fstring === true && /f/iu.test(prefix);
22751
+ let end = index + quote.length;
22752
+ while (end < text.length) {
22753
+ const char = text[end];
22754
+ if (escapes && char === "\\") {
22755
+ end += 2;
22756
+ continue;
22757
+ }
22758
+ if (text.startsWith(quote, end)) {
22759
+ if (fstring && unbalanced(text.slice(index + quote.length, end)))
22760
+ return false;
22761
+ emitVerbatim(text.slice(index, end + quote.length));
22762
+ index = end + quote.length;
22763
+ return true;
22764
+ }
22765
+ if (char === `
22766
+ ` && !multiline)
22767
+ return false;
22768
+ end += 1;
22769
+ }
22770
+ return false;
22771
+ };
22772
+ while (index < text.length) {
22773
+ const frame = frames[frames.length - 1];
22774
+ const char = text[index];
22775
+ if (frame.kind === "template") {
22776
+ if (char === "\\") {
22777
+ emitVerbatim(text.slice(index, index + 2));
22778
+ index += 2;
22779
+ } else if (char === "`") {
22780
+ emitVerbatim(char);
22781
+ frames.pop();
22782
+ index += 1;
22783
+ } else if (text.startsWith("${", index)) {
22784
+ emitVerbatim("${");
22785
+ frames.push({ kind: "code", braces: 0 });
22786
+ index += 2;
22787
+ } else {
22788
+ out += char;
22789
+ kept = out.length;
22790
+ index += 1;
22791
+ }
22792
+ continue;
22793
+ }
22794
+ if (char === `
22795
+ `) {
22796
+ newline();
22797
+ index += 1;
22798
+ continue;
22799
+ }
22800
+ if (SPACE.test(char)) {
22801
+ if (collapse)
22802
+ pendingSpace = true;
22803
+ else
22804
+ out += char;
22805
+ index += 1;
22806
+ continue;
22807
+ }
22808
+ const lineOpener = syntax.line.find((opener) => text.startsWith(opener, index));
22809
+ if (lineOpener) {
22810
+ const end = text.indexOf(`
22811
+ `, index);
22812
+ const comment = text.slice(index, end < 0 ? text.length : end);
22813
+ if (DIRECTIVE.test(comment.slice(lineOpener.length)))
22814
+ emitVerbatim(comment);
22815
+ else
22816
+ pendingSpace = true;
22817
+ index = end < 0 ? text.length : end;
22818
+ continue;
22819
+ }
22820
+ const block = syntax.block.find(([open]) => text.startsWith(open, index));
22821
+ if (block) {
22822
+ const end = text.indexOf(block[1], index + block[0].length);
22823
+ if (end < 0)
22824
+ return null;
22825
+ const comment = text.slice(index, end + block[1].length);
22826
+ if (DIRECTIVE.test(comment.slice(block[0].length, -block[1].length)))
22827
+ emitVerbatim(comment);
22828
+ else
22829
+ pendingSpace = true;
22830
+ if (comment.includes(`
22831
+ `))
22832
+ newline();
22833
+ index = end + block[1].length;
22834
+ continue;
22835
+ }
22836
+ if (syntax.triple && (char === '"' || char === "'") && text.startsWith(char.repeat(3), index)) {
22837
+ if (!scanString(char.repeat(3), !syntax.literal?.includes(char), true))
22838
+ return null;
22839
+ continue;
22840
+ }
22841
+ if (syntax.quotes.includes(char)) {
22842
+ if (!scanString(char, true, Boolean(syntax.multiline)))
22843
+ return null;
22844
+ continue;
22845
+ }
22846
+ if (syntax.literal?.includes(char)) {
22847
+ if (!scanString(char, false, false))
22848
+ return null;
22849
+ continue;
22850
+ }
22851
+ if (syntax.rawBacktick && char === "`") {
22852
+ if (!scanString("`", false, true))
22853
+ return null;
22854
+ continue;
22855
+ }
22856
+ if (syntax.js && char === "`") {
22857
+ emitVerbatim(char);
22858
+ frames.push({ kind: "template" });
22859
+ index += 1;
22860
+ continue;
22861
+ }
22862
+ if (syntax.cssUrl && /^url\(\s*[^"')\s]/iu.test(text.slice(index, index + 64)))
22863
+ return null;
22864
+ if (syntax.js && char === "/" && !regexAllowed() && out.trimEnd().endsWith(")")) {
22865
+ const lineEnd = text.indexOf(`
22866
+ `, index);
22867
+ if (text.slice(index + 1, lineEnd < 0 ? text.length : lineEnd).includes("/"))
22868
+ return null;
22869
+ }
22870
+ if (syntax.js && char === "/" && regexAllowed()) {
22871
+ let end = index + 1;
22872
+ let inClass = false;
22873
+ while (end < text.length && (inClass || text[end] !== "/")) {
22874
+ if (text[end] === `
22875
+ `)
22876
+ return null;
22877
+ if (text[end] === "\\")
22878
+ end += 1;
22879
+ else if (text[end] === "[")
22880
+ inClass = true;
22881
+ else if (text[end] === "]")
22882
+ inClass = false;
22883
+ end += 1;
22884
+ }
22885
+ if (end >= text.length)
22886
+ return null;
22887
+ emitVerbatim(text.slice(index, end + 1));
22888
+ index = end + 1;
22889
+ continue;
22890
+ }
22891
+ if (frames.length > 1 && frame.kind === "code") {
22892
+ if (char === "{")
22893
+ frame.braces += 1;
22894
+ else if (char === "}") {
22895
+ if (frame.braces === 0) {
22896
+ emitVerbatim(char);
22897
+ frames.pop();
22898
+ index += 1;
22899
+ continue;
22900
+ }
22901
+ frame.braces -= 1;
22902
+ }
22903
+ }
22904
+ emitCode(char);
22905
+ index += 1;
22906
+ }
22907
+ if (frames.length !== 1)
22908
+ return null;
22909
+ newline();
22910
+ return out;
22911
+ }
22912
+ function unbalanced(body) {
22913
+ let depth = 0;
22914
+ for (const part of body.replaceAll("{{", "").replaceAll("}}", "")) {
22915
+ if (part === "{")
22916
+ depth += 1;
22917
+ else if (part === "}")
22918
+ depth = Math.max(0, depth - 1);
22919
+ }
22920
+ return depth > 0;
22921
+ }
22922
+ function hasOpaqueLineBreak(text) {
22923
+ return /\r(?!\n)|[\u2028\u2029]/u.test(text);
22924
+ }
22925
+ var decoder = new TextDecoder("utf-8", { fatal: true });
22926
+ function textOf(bytes) {
22927
+ if (bytes.includes(0))
22928
+ return null;
22929
+ try {
22930
+ return decoder.decode(bytes);
22931
+ } catch {
22932
+ return null;
22933
+ }
22934
+ }
22935
+ function cosmeticChange(file, before, after) {
22936
+ const left = textOf(before);
22937
+ const right = textOf(after);
22938
+ if (left === null || right === null)
22939
+ return false;
22940
+ if (hasOpaqueLineBreak(left) || hasOpaqueLineBreak(right))
22941
+ return false;
22942
+ const a = substanceOf(file, left);
22943
+ return a !== null && a === substanceOf(file, right);
22944
+ }
22945
+
22946
+ // packages/workit-core/src/core/policy/lane.ts
22947
+ var LANE_THRESHOLDS = {
22948
+ selfMaxLines: 100,
22949
+ selfMaxFiles: 5,
22950
+ fullMinLines: 500
22951
+ };
22952
+ var RISK_TOKENS = new Set([
22953
+ "auth",
22954
+ "authn",
22955
+ "authz",
22956
+ "oauth",
22957
+ "security",
22958
+ "permission",
22959
+ "permissions",
22960
+ "secret",
22961
+ "secrets",
22962
+ "crypto",
22963
+ "gate",
22964
+ "gates",
22965
+ "policy",
22966
+ "policies",
22967
+ "hook",
22968
+ "hooks",
22969
+ "husky",
22970
+ "lefthook",
22971
+ "release",
22972
+ "releases",
22973
+ "migration",
22974
+ "migrations",
22975
+ "migrate",
22976
+ "workflows"
22977
+ ]);
22978
+ var RISK_FILES = new Set([
22979
+ ".gitlab-ci.yml",
22980
+ "Jenkinsfile",
22981
+ "azure-pipelines.yml",
22982
+ ".pre-commit-config.yaml",
22983
+ ".workit/risk-paths"
22984
+ ]);
22985
+ var RISK_NAMES = new Set([".gitattributes"]);
22986
+ var RISK_PATHS_FILE = ".workit/risk-paths";
22987
+ var LOCKFILES = new Set([
22988
+ "bun.lock",
22989
+ "bun.lockb",
22990
+ "package-lock.json",
22991
+ "npm-shrinkwrap.json",
22992
+ "yarn.lock",
22993
+ "pnpm-lock.yaml",
22994
+ "Cargo.lock",
22995
+ "go.sum",
22996
+ "poetry.lock",
22997
+ "uv.lock",
22998
+ "Pipfile.lock",
22999
+ "Gemfile.lock",
23000
+ "composer.lock"
23001
+ ]);
23002
+ var DOC_EXT = /\.(?:md|mdx|markdown|rst|adoc|txt)$/iu;
23003
+ var DOC_NAMES = /^(?:license|licence|notice|authors|changelog|changes|contributors)$/iu;
23004
+ var INSTRUCTIONS = /(?:^|\/)(?:AGENTS|CLAUDE|GEMINI|SKILL)\.md$|(?:^|\/)(?:skills|agents|commands|rules|prompts)\/[^/]+/iu;
23005
+ var TEST_PATH = /(?:^|\/)(?:test|tests|__tests__|spec|specs|fixtures)\/|\.(?:test|spec)\.[^/]+$/iu;
23006
+ var basename = (file) => file.slice(file.lastIndexOf("/") + 1);
23007
+ var isDoc = (file) => !INSTRUCTIONS.test(file) && (DOC_EXT.test(file) || DOC_NAMES.test(basename(file)));
23008
+ function kindOf(file) {
23009
+ if (file.binary)
23010
+ return "behavior";
23011
+ if (file.generated)
23012
+ return "generated";
23013
+ if (LOCKFILES.has(basename(file.path)))
23014
+ return "lockfile";
23015
+ if (isDoc(file.path))
23016
+ return "doc";
23017
+ if (file.cosmetic)
23018
+ return "cosmetic";
23019
+ return TEST_PATH.test(file.path) ? "test" : "behavior";
23020
+ }
23021
+ var globCache = new Map;
23022
+ function globMatch(pattern, file) {
23023
+ let regex = globCache.get(pattern);
23024
+ if (!regex) {
23025
+ let source = "";
23026
+ for (let index = 0;index < pattern.length; index += 1) {
23027
+ const char = pattern[index];
23028
+ if (char === "*" && pattern[index + 1] === "*") {
23029
+ source += pattern[index + 2] === "/" ? "(?:[^/]*/)*" : ".*";
23030
+ index += pattern[index + 2] === "/" ? 2 : 1;
23031
+ } else if (char === "*")
23032
+ source += "[^/]*";
23033
+ else if (char === "?")
23034
+ source += "[^/]";
23035
+ else
23036
+ source += char.replace(/[.+^${}()|[\]\\]/gu, "\\$&");
23037
+ }
23038
+ regex = new RegExp(`^${source}$`, "u");
23039
+ globCache.set(pattern, regex);
23040
+ }
23041
+ return regex.test(file) || file.startsWith(`${pattern.replace(/\/$/u, "")}/`);
23042
+ }
23043
+ function isRiskPath(file, extra = []) {
23044
+ if (extra.some((pattern) => globMatch(pattern, file)))
23045
+ return true;
23046
+ if (RISK_FILES.has(file) || RISK_NAMES.has(basename(file)))
23047
+ return true;
23048
+ if (TEST_PATH.test(file) || isDoc(file))
23049
+ return false;
23050
+ 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)));
23051
+ }
23052
+ var parseRiskPaths = (text) => text.split(`
23053
+ `).map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map((line) => line.replace(/^\//u, ""));
23054
+ function computeLane(input) {
23055
+ const riskFiles = input.files.filter((file) => isRiskPath(file.path, input.riskPaths)).map((file) => file.path);
23056
+ const risky = new Set(riskFiles);
23057
+ const kinds = input.files.map((file) => ({
23058
+ file,
23059
+ kind: risky.has(file.path) ? "behavior" : kindOf(file)
23060
+ }));
23061
+ const behavior = kinds.filter((entry) => entry.kind === "behavior" || entry.kind === "test" || entry.kind === "lockfile");
23062
+ const lines = behavior.filter((entry) => entry.kind !== "lockfile").reduce((sum, entry) => sum + entry.file.added + entry.file.deleted, 0);
23063
+ const opaque = behavior.filter((entry) => entry.kind === "lockfile" || entry.file.binary);
23064
+ const result = (lane, reasons) => ({
23065
+ lane,
23066
+ reasons,
23067
+ lines,
23068
+ files: behavior.length,
23069
+ riskFiles
23070
+ });
23071
+ const { selfMaxLines, selfMaxFiles, fullMinLines } = LANE_THRESHOLDS;
23072
+ if (input.riskTier === "high")
23073
+ return result("full", ["the task judgment records high risk"]);
23074
+ if (riskFiles.length)
23075
+ return result("full", [
23076
+ `touches a risk path: ${riskFiles.slice(0, 3).join(", ")}${riskFiles.length > 3 ? ", …" : ""}`
23077
+ ]);
23078
+ if (!behavior.length)
23079
+ return result("none", [
23080
+ input.files.length ? "only docs, comments, formatting or generated copies changed" : "no changes"
23081
+ ]);
23082
+ if (lines >= fullMinLines)
23083
+ return result("full", [`large diff: ${lines} lines (≥ ${fullMinLines})`]);
23084
+ if (lines > selfMaxLines)
23085
+ return result("focused", [`${lines} lines changed (> ${selfMaxLines})`]);
23086
+ if (behavior.length > selfMaxFiles)
23087
+ return result("focused", [`${behavior.length} behavior files changed (> ${selfMaxFiles})`]);
23088
+ if (opaque.length)
23089
+ return result("focused", [
23090
+ `a lockfile or binary changed: ${opaque.slice(0, 3).map((entry) => entry.file.path).join(", ")}${opaque.length > 3 ? ", …" : ""}`
23091
+ ]);
23092
+ return result("self", [
23093
+ `small change: ${lines} line${lines === 1 ? "" : "s"} in ${behavior.length} file${behavior.length === 1 ? "" : "s"}, no risk path`
23094
+ ]);
23095
+ }
23096
+ function untrackedStat(cwd, file) {
23097
+ try {
23098
+ const bytes = readFileSync4(path16.join(cwd, file));
23099
+ if (bytes.includes(0))
23100
+ return { path: file, added: 0, deleted: 0, binary: true };
23101
+ const text = bytes.toString("utf8");
23102
+ if (hasOpaqueLineBreak(text))
23103
+ return { path: file, added: 0, deleted: 0, binary: true };
23104
+ const lines = text.split(`
23105
+ `).length - (text.endsWith(`
23106
+ `) ? 1 : 0);
23107
+ return { path: file, added: lines, deleted: 0 };
23108
+ } catch {
23109
+ return { path: file, added: 0, deleted: 0, binary: true };
23110
+ }
23111
+ }
23112
+ var REGULAR = new Set(["100644", "100755"]);
23113
+ var ABSENT = /^0+$/u;
23114
+ function cosmeticFiles(cwd, fork, head) {
23115
+ const raw = diffRaw(cwd, fork, head);
23116
+ if (!raw)
23117
+ return null;
23118
+ const candidates = raw.filter((entry) => REGULAR.has(entry.oldMode) && entry.oldMode === entry.newMode && !ABSENT.test(entry.oldBlob) && (head === null || !ABSENT.test(entry.newBlob)));
23119
+ const blobs = readBlobs(cwd, candidates.flatMap((entry) => [entry.oldBlob, entry.newBlob]));
23120
+ if (!blobs)
23121
+ return null;
23122
+ const out = new Set;
23123
+ const opaque = new Set;
23124
+ for (const entry of candidates) {
23125
+ const before = blobs.get(entry.oldBlob);
23126
+ let after = blobs.get(entry.newBlob);
23127
+ if (!after && head === null && ABSENT.test(entry.newBlob))
23128
+ try {
23129
+ after = readFileSync4(path16.join(cwd, entry.path));
23130
+ } catch {
23131
+ after = undefined;
23132
+ }
23133
+ if (before && after && cosmeticChange(entry.path, before, after))
23134
+ out.add(entry.path);
23135
+ else if ([before, after].some((bytes) => bytes && hasOpaqueLineBreak(bytes.toString("utf8"))))
23136
+ opaque.add(entry.path);
23137
+ }
23138
+ return { cosmetic: out, opaque };
23139
+ }
23140
+ function generatedAt(cwd, fork, paths) {
23141
+ const files = treeFilesNamed(cwd, fork, ".gitattributes");
23142
+ const blobs = files?.size ? readBlobs(cwd, [...files.values()]) : null;
23143
+ if (!files || !blobs)
23144
+ return new Set;
23145
+ const texts = new Map;
23146
+ for (const [file, id] of files) {
23147
+ const bytes = blobs.get(id);
23148
+ if (bytes)
23149
+ texts.set(file, bytes.toString("utf8"));
23150
+ }
23151
+ return generatedByAttributes(texts, paths);
23152
+ }
23153
+ var forkOf = (cwd, base, head) => mergeBase(cwd, base, head ?? "HEAD");
23154
+ function laneFiles(cwd, fork, head) {
23155
+ const stats = diffNumstat(cwd, fork, head);
23156
+ const cosmetic = stats ? cosmeticFiles(cwd, fork, head) : null;
23157
+ if (!stats || !cosmetic)
23158
+ return null;
23159
+ const files = [
23160
+ ...stats.map((entry) => ({
23161
+ ...entry,
23162
+ ...cosmetic.opaque.has(entry.path) ? { binary: true } : {},
23163
+ cosmetic: !entry.binary && cosmetic.cosmetic.has(entry.path)
23164
+ })),
23165
+ ...head === null ? untrackedFiles(cwd).map((file) => untrackedStat(cwd, file)) : []
23166
+ ];
23167
+ const generated = generatedAt(cwd, fork, files.map((entry) => entry.path));
23168
+ return files.map((entry) => ({
23169
+ ...entry,
23170
+ generated: generated.has(entry.path)
23171
+ }));
23172
+ }
23173
+ function branchLane(cwd, options) {
23174
+ const candidates = options.base ? [`origin/${options.base}`, options.base] : [];
23175
+ const base = candidates.find((ref) => resolveRef(cwd, ref) !== null) ?? defaultBase(cwd) ?? null;
23176
+ const head = options.workingTree ? null : options.head;
23177
+ const fork = base && (options.workingTree || options.head) ? forkOf(cwd, base, head) : null;
23178
+ const files = fork ? laneFiles(cwd, fork, head) : null;
23179
+ const riskTier = options.judgment?.riskTier ?? null;
23180
+ if (!fork || !files) {
23181
+ const high = riskTier === "high";
23182
+ return {
23183
+ lane: high ? "full" : "focused",
23184
+ reasons: [
23185
+ `the diff of ${options.head?.slice(0, 12) ?? "(no head)"} against ${base ?? "(no base)"} cannot be read`,
23186
+ ...high ? ["the task judgment records high risk"] : []
23187
+ ],
23188
+ lines: 0,
23189
+ files: 0,
23190
+ riskFiles: [],
23191
+ base,
23192
+ head: options.head
23193
+ };
23194
+ }
23195
+ const repoRisk = parseRiskPaths(fileAt(cwd, fork, RISK_PATHS_FILE) ?? "");
23196
+ return {
23197
+ ...computeLane({
23198
+ files,
23199
+ riskTier,
23200
+ riskPaths: [...repoRisk, ...options.riskPaths ?? []]
23201
+ }),
23202
+ base,
23203
+ head: options.head
23204
+ };
23205
+ }
23206
+ var laneNeed = (lane) => lane === "none" ? "none" : lane === "self" ? "self" : "non-author";
23207
+
22381
23208
  // packages/workit-core/src/core/policy/derive.ts
22382
23209
  var RULES = {
22383
23210
  test: "check:test",
22384
23211
  self: "verdict:self",
22385
23212
  nonAuthor: "verdict:non-author",
22386
23213
  verified: "verdict:verified",
23214
+ lane: "verdict:lane",
22387
23215
  product: "decision:product",
22388
23216
  plan: "plan"
22389
23217
  };
@@ -22406,6 +23234,7 @@ var normalizedScope = (scope) => ({
22406
23234
  function deriveRequirements(judgment, scope, constraints, verification = "self") {
22407
23235
  const out = [];
22408
23236
  const base = { scope, dependentAction: null };
23237
+ const proportional = verification === "proportional";
22409
23238
  if (judgment.behaviorChange)
22410
23239
  out.push(derived2({
22411
23240
  ...base,
@@ -22416,7 +23245,17 @@ function deriveRequirements(judgment, scope, constraints, verification = "self")
22416
23245
  before: "close",
22417
23246
  acceptanceAllowed: false
22418
23247
  }));
22419
- if (judgment.behaviorChange && judgment.riskTier === "normal")
23248
+ if (proportional && judgment.riskTier === "normal")
23249
+ out.push(derived2({
23250
+ ...base,
23251
+ ruleId: RULES.lane,
23252
+ dimension: "review",
23253
+ 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.",
23254
+ 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.",
23255
+ before: "close",
23256
+ acceptanceAllowed: false
23257
+ }));
23258
+ if (!proportional && judgment.behaviorChange && judgment.riskTier === "normal")
22420
23259
  out.push(verification === "independent" ? derived2({
22421
23260
  ...base,
22422
23261
  ruleId: RULES.nonAuthor,
@@ -22519,7 +23358,7 @@ var productDecision = (task, ledger) => {
22519
23358
  };
22520
23359
  };
22521
23360
  var planRecorded = (task, root) => {
22522
- const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(path15.resolve(root, ref.path)));
23361
+ const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync5(path17.resolve(root, ref.path)));
22523
23362
  if (cited)
22524
23363
  return {
22525
23364
  met: true,
@@ -22533,14 +23372,30 @@ var planRecorded = (task, root) => {
22533
23372
  decisionIds: []
22534
23373
  };
22535
23374
  };
22536
- var verdict = (requirement, root, ledger) => {
23375
+ var workingLane = (task, root) => branchLane(root, { head: null, workingTree: true, judgment: latestJudgment(task) });
23376
+ var laneVerdict = (task, root, ledger) => {
23377
+ if (!ledger.branch() && latestJudgment(task)?.behaviorChange === false)
23378
+ return {
23379
+ met: true,
23380
+ reason: "no branch to read a lane from, and the judgment records no behavior change",
23381
+ decisionIds: []
23382
+ };
23383
+ const lane = workingLane(task, root);
23384
+ const label = `lane ${lane.lane} (${lane.reasons.join("; ")})`;
23385
+ const need = laneNeed(lane.lane);
23386
+ if (need === "none")
23387
+ return { met: true, reason: `${label}: no verdict needed`, decisionIds: [] };
23388
+ const status = verdict(need === "self" ? RULES.self : RULES.nonAuthor, root, ledger);
23389
+ return { ...status, reason: `${label}: ${status.reason}` };
23390
+ };
23391
+ var verdict = (ruleId, root, ledger) => {
22537
23392
  const branch = ledger.branch();
22538
23393
  if (!branch)
22539
23394
  return { met: false, reason: "no branch is checked out to hold a verdict", decisionIds: [] };
22540
23395
  const check = checkVerdicts(root, branch, ledger.rows());
22541
23396
  const failing = check.accepted.reasons.includes("failing_verdict");
22542
23397
  const strong = (entry) => STRONG_RESULTS.has(String(entry.verdict.result));
22543
- 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)));
23398
+ 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)));
22544
23399
  if (met)
22545
23400
  return {
22546
23401
  met: true,
@@ -22548,7 +23403,7 @@ var verdict = (requirement, root, ledger) => {
22548
23403
  decisionIds: []
22549
23404
  };
22550
23405
  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, " ");
22551
- 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>\``;
23406
+ 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>\``;
22552
23407
  return { met: false, reason: `${why}: ${unblock}`, decisionIds: [] };
22553
23408
  };
22554
23409
  function derivedRuleStatus(task, requirement, root, ledger) {
@@ -22560,7 +23415,9 @@ function derivedRuleStatus(task, requirement, root, ledger) {
22560
23415
  case RULES.self:
22561
23416
  case RULES.nonAuthor:
22562
23417
  case RULES.verified:
22563
- return verdict(requirement, root, ledger);
23418
+ return verdict(requirement.ruleId, root, ledger);
23419
+ case RULES.lane:
23420
+ return laneVerdict(task, root, ledger);
22564
23421
  default:
22565
23422
  return null;
22566
23423
  }
@@ -22568,14 +23425,14 @@ function derivedRuleStatus(task, requirement, root, ledger) {
22568
23425
 
22569
23426
  // packages/workit-core/src/core/task-evaluation.ts
22570
23427
  var digestBytes = (value) => createHash10("sha256").update(value).digest("hex");
22571
- var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path16.sep}`);
22572
- var relative = (root, candidate) => path16.relative(root, candidate).split(path16.sep).join("/") || ".";
23428
+ var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path18.sep}`);
23429
+ var relative = (root, candidate) => path18.relative(root, candidate).split(path18.sep).join("/") || ".";
22573
23430
  var canonicalPath = (value) => {
22574
23431
  if (typeof value !== "string" || !value)
22575
23432
  return null;
22576
23433
  if (value.includes("\\") || value.split("/").includes(".."))
22577
23434
  return null;
22578
- const normalized = path16.posix.normalize(value);
23435
+ const normalized = path18.posix.normalize(value);
22579
23436
  if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
22580
23437
  return null;
22581
23438
  return normalized === "." ? "." : normalized.replace(/\/$/, "");
@@ -22611,7 +23468,7 @@ var compareCodeUnits2 = (left, right) => {
22611
23468
  return left.length - right.length;
22612
23469
  };
22613
23470
  var gitPaths = (root) => {
22614
- const result = spawnSync10("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], {
23471
+ const result = spawnSync11("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], {
22615
23472
  cwd: root,
22616
23473
  encoding: "buffer"
22617
23474
  });
@@ -22623,21 +23480,21 @@ var gitPaths = (root) => {
22623
23480
  git: !/not a git repository/i.test(stderr)
22624
23481
  };
22625
23482
  }
22626
- const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path16.sep).join("/")) : [];
22627
- const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
23483
+ const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path18.sep).join("/")) : [];
23484
+ const stagedDeleted = spawnSync11("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
22628
23485
  if (stagedDeleted.status !== 0) {
22629
23486
  const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
22630
23487
  if (!/not a git repository/i.test(stderr))
22631
23488
  return { paths, uncertain: true, git: true };
22632
23489
  } else if (stagedDeleted.stdout) {
22633
- paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path16.sep).join("/")));
23490
+ paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path18.sep).join("/")));
22634
23491
  }
22635
23492
  return { paths: [...new Set(paths)], uncertain: false, git: true };
22636
23493
  };
22637
23494
  var walk = (root, directory, output) => {
22638
23495
  let names;
22639
23496
  try {
22640
- names = fs13.readdirSync(directory);
23497
+ names = fs14.readdirSync(directory);
22641
23498
  } catch {
22642
23499
  return true;
22643
23500
  }
@@ -22645,10 +23502,10 @@ var walk = (root, directory, output) => {
22645
23502
  for (const name of names) {
22646
23503
  if (name === ".git" || name === ".workit")
22647
23504
  continue;
22648
- const target = path16.join(directory, name);
23505
+ const target = path18.join(directory, name);
22649
23506
  let stat;
22650
23507
  try {
22651
- stat = fs13.lstatSync(target);
23508
+ stat = fs14.lstatSync(target);
22652
23509
  } catch {
22653
23510
  uncertain = true;
22654
23511
  continue;
@@ -22663,14 +23520,14 @@ var walk = (root, directory, output) => {
22663
23520
  var scopeRoots = (root, scope) => {
22664
23521
  const roots = [];
22665
23522
  for (const item of scope.paths.length ? scope.paths : ["."]) {
22666
- const target = path16.resolve(root, item);
23523
+ const target = path18.resolve(root, item);
22667
23524
  if (!inside(root, target))
22668
23525
  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` }] });
22669
23526
  let ancestor = target;
22670
- while (!fs13.existsSync(ancestor) && ancestor !== root)
22671
- ancestor = path16.dirname(ancestor);
23527
+ while (!fs14.existsSync(ancestor) && ancestor !== root)
23528
+ ancestor = path18.dirname(ancestor);
22672
23529
  try {
22673
- if (!inside(root, fs13.realpathSync(ancestor)))
23530
+ if (!inside(root, fs14.realpathSync(ancestor)))
22674
23531
  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` }] });
22675
23532
  } catch {
22676
23533
  return failure2("invalid_input", `candidate scope cannot be inspected: ${item}`);
@@ -22682,7 +23539,7 @@ var scopeRoots = (root, scope) => {
22682
23539
  function captureCandidate(root, scope, environment = []) {
22683
23540
  let checkout;
22684
23541
  try {
22685
- checkout = fs13.realpathSync(root);
23542
+ checkout = fs14.realpathSync(root);
22686
23543
  } catch {
22687
23544
  return failure2("invalid_input", "candidate root does not exist");
22688
23545
  }
@@ -22700,11 +23557,11 @@ function captureCandidate(root, scope, environment = []) {
22700
23557
  if (item === ".git" || item === ".workit")
22701
23558
  continue;
22702
23559
  names.add(item);
22703
- if (!fs13.existsSync(target))
23560
+ if (!fs14.existsSync(target))
22704
23561
  continue;
22705
23562
  let stat;
22706
23563
  try {
22707
- stat = fs13.lstatSync(target);
23564
+ stat = fs14.lstatSync(target);
22708
23565
  } catch {
22709
23566
  uncertain = true;
22710
23567
  continue;
@@ -22720,17 +23577,17 @@ function captureCandidate(root, scope, environment = []) {
22720
23577
  for (const item of [...names].toSorted()) {
22721
23578
  if (!scopeMatches(item, normalizedScope))
22722
23579
  continue;
22723
- const target = path16.join(checkout, item);
23580
+ const target = path18.join(checkout, item);
22724
23581
  try {
22725
- const stat = fs13.lstatSync(target);
23582
+ const stat = fs14.lstatSync(target);
22726
23583
  if (stat.isSymbolicLink()) {
22727
- const link = fs13.readlinkSync(target);
23584
+ const link = fs14.readlinkSync(target);
22728
23585
  files.push({ path: item, kind: "symlink", digest: digestBytes(link), executable: null });
22729
23586
  } else if (stat.isFile()) {
22730
23587
  files.push({
22731
23588
  path: item,
22732
23589
  kind: "file",
22733
- digest: digestBytes(fs13.readFileSync(target)),
23590
+ digest: digestBytes(fs14.readFileSync(target)),
22734
23591
  executable: (stat.mode & 73) !== 0
22735
23592
  });
22736
23593
  } else if (!stat.isDirectory()) {
@@ -22755,7 +23612,7 @@ function captureCandidate(root, scope, environment = []) {
22755
23612
  const values = supplied.toSorted((left, right) => compareCodeUnits2(left.name, right.name)).map(({ name, value }) => ({ name, value, refs: [] }));
22756
23613
  if (values.some(({ value }) => value === null))
22757
23614
  completeness = "uncertain";
22758
- const headResult = spawnSync10("git", ["rev-parse", "HEAD"], { cwd: checkout, encoding: "utf8" });
23615
+ const headResult = spawnSync11("git", ["rev-parse", "HEAD"], { cwd: checkout, encoding: "utf8" });
22759
23616
  if (headResult.status !== 0 && !/not a git repository/i.test(headResult.stderr ?? ""))
22760
23617
  completeness = "uncertain";
22761
23618
  const head = headResult.status === 0 ? headResult.stdout.trim() : null;
@@ -22895,7 +23752,7 @@ var findingVerificationPasses = (findingCandidateId, evidence) => evidence.statu
22895
23752
  var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
22896
23753
  let root;
22897
23754
  try {
22898
- root = fs13.realpathSync(checkoutRoot);
23755
+ root = fs14.realpathSync(checkoutRoot);
22899
23756
  } catch {
22900
23757
  return failure2("permission_denied", "checkout root is unavailable");
22901
23758
  }
@@ -22904,23 +23761,23 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
22904
23761
  continue;
22905
23762
  if (!reference.digest)
22906
23763
  return failure2("invalid_input", "document references require a byte digest");
22907
- const target = path16.resolve(root, reference.path);
22908
- if (target !== root && !target.startsWith(`${root}${path16.sep}`))
23764
+ const target = path18.resolve(root, reference.path);
23765
+ if (target !== root && !target.startsWith(`${root}${path18.sep}`))
22909
23766
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
22910
23767
  fields: [
22911
23768
  { path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
22912
23769
  ]
22913
23770
  });
22914
23771
  try {
22915
- const below = path16.relative(root, target);
23772
+ const below = path18.relative(root, target);
22916
23773
  let current = root;
22917
- for (const segment of below.split(path16.sep)) {
23774
+ for (const segment of below.split(path18.sep)) {
22918
23775
  if (!segment)
22919
23776
  continue;
22920
- current = path16.join(current, segment);
22921
- const stat = fs13.lstatSync(current);
22922
- const real = fs13.realpathSync(current);
22923
- if (real !== root && !real.startsWith(`${root}${path16.sep}`))
23777
+ current = path18.join(current, segment);
23778
+ const stat = fs14.lstatSync(current);
23779
+ const real = fs14.realpathSync(current);
23780
+ if (real !== root && !real.startsWith(`${root}${path18.sep}`))
22924
23781
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
22925
23782
  fields: [
22926
23783
  {
@@ -22936,7 +23793,7 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
22936
23793
  if (current !== target && !stat.isDirectory())
22937
23794
  return failure2("invalid_input", "document reference ancestor is not a directory");
22938
23795
  }
22939
- if (digestBytes(fs13.readFileSync(target)) !== reference.digest)
23796
+ if (digestBytes(fs14.readFileSync(target)) !== reference.digest)
22940
23797
  return failure2("permission_denied", "decision document bytes have changed");
22941
23798
  } catch {
22942
23799
  return failure2("invalid_input", "decision document is unavailable");
@@ -23779,7 +24636,7 @@ var judgeInputSummary = (raw) => {
23779
24636
 
23780
24637
  // packages/workit-core/src/autonomy.ts
23781
24638
  import os4 from "node:os";
23782
- import path17 from "node:path";
24639
+ import path19 from "node:path";
23783
24640
  var accountHome = () => {
23784
24641
  try {
23785
24642
  return os4.userInfo().homedir;
@@ -23788,10 +24645,10 @@ var accountHome = () => {
23788
24645
  }
23789
24646
  };
23790
24647
  var grantsHome = { resolve: accountHome };
23791
- var grantsDir = () => path17.join(grantsHome.resolve(), ".config", "workit");
24648
+ var grantsDir = () => path19.join(grantsHome.resolve(), ".config", "workit");
23792
24649
  var grantsOverride = () => {
23793
- const configured = path17.resolve(resolveConfigDir());
23794
- 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`;
24650
+ const configured = path19.resolve(resolveConfigDir());
24651
+ 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`;
23795
24652
  };
23796
24653
  var GRANT_KINDS = ["push", "pr", "merge", "release", "rerun"];
23797
24654
  var DEFAULT_GRANTS = Object.freeze({
@@ -23844,8 +24701,16 @@ function endpointView(entry, context) {
23844
24701
  ...issue ? { endpointIssue: issue } : {}
23845
24702
  };
23846
24703
  }
23847
- var DEFAULT_VERIFICATION = "self";
23848
- var verificationOf = (entry) => entry?.verification === "independent" ? "independent" : "self";
24704
+ var VERIFICATION_MODES = [
24705
+ "proportional",
24706
+ "self",
24707
+ "independent"
24708
+ ];
24709
+ var DEFAULT_VERIFICATION = "proportional";
24710
+ var verificationOf = (entry) => {
24711
+ const value = entry?.verification;
24712
+ return VERIFICATION_MODES.includes(value) ? value : DEFAULT_VERIFICATION;
24713
+ };
23849
24714
  var isGrantValue = (value) => value === true || value === false || value === "verified";
23850
24715
  var normalized = (kind, value) => value === "verified" && kind !== "merge" ? true : value;
23851
24716
  var fromAutoApprove = (value) => {
@@ -25592,9 +26457,9 @@ class WorkitCore {
25592
26457
  }
25593
26458
  }
25594
26459
  // packages/workit-core/src/core/repo-context.ts
25595
- import { spawnSync as spawnSync11 } from "node:child_process";
25596
- import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync4 } from "node:fs";
25597
- import path18 from "node:path";
26460
+ import { spawnSync as spawnSync12 } from "node:child_process";
26461
+ import { existsSync as existsSync7, readFileSync as readFileSync6, readdirSync as readdirSync4 } from "node:fs";
26462
+ import path20 from "node:path";
25598
26463
  var isSafeContextRange = (value) => value.length <= 4096 && (() => {
25599
26464
  try {
25600
26465
  gitRevisionParts(value);
@@ -25621,7 +26486,7 @@ var invalidRange = (cwd) => ({
25621
26486
  cwd
25622
26487
  });
25623
26488
  var runGit = (cwd, args) => {
25624
- const result = spawnSync11("git", args, { cwd, encoding: "utf8" });
26489
+ const result = spawnSync12("git", args, { cwd, encoding: "utf8" });
25625
26490
  return {
25626
26491
  stdout: (result.stdout ?? "").trimEnd(),
25627
26492
  stderr: (result.stderr ?? "").trimEnd(),
@@ -25728,7 +26593,7 @@ var findPrTemplate = (cwd) => {
25728
26593
  ]) {
25729
26594
  const parts = rel.split("/");
25730
26595
  const base = parts[parts.length - 1];
25731
- const dir = parts.length > 1 ? path18.join(cwd, ...parts.slice(0, -1)) : cwd;
26596
+ const dir = parts.length > 1 ? path20.join(cwd, ...parts.slice(0, -1)) : cwd;
25732
26597
  const actual = probeCaseInsensitive(dir, base);
25733
26598
  if (actual)
25734
26599
  return [...parts.slice(0, -1), actual].join("/");
@@ -25759,11 +26624,11 @@ var diffStatForRange = (cwd, range) => {
25759
26624
  return runGit(cwd, ["diff", "--stat", "--"]).stdout;
25760
26625
  };
25761
26626
  var packageScripts = (cwd, keys) => {
25762
- const pkgPath = path18.join(cwd, "package.json");
25763
- if (!existsSync6(pkgPath))
26627
+ const pkgPath = path20.join(cwd, "package.json");
26628
+ if (!existsSync7(pkgPath))
25764
26629
  return [];
25765
26630
  try {
25766
- const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
26631
+ const pkg = JSON.parse(readFileSync6(pkgPath, "utf8"));
25767
26632
  return keys.filter((k) => pkg.scripts && typeof pkg.scripts[k] === "string").map((k) => `${k}: ${pkg.scripts?.[k]}`);
25768
26633
  } catch {
25769
26634
  return [];
@@ -25785,9 +26650,9 @@ var documentationFiles = (cwd) => {
25785
26650
  if (entry.isDirectory()) {
25786
26651
  if (excluded.has(entry.name))
25787
26652
  continue;
25788
- walk(path18.join(dir, entry.name), depth + 1);
26653
+ walk(path20.join(dir, entry.name), depth + 1);
25789
26654
  } else if (entry.isFile() && (entry.name === "README.md" || entry.name.endsWith(".md"))) {
25790
- matches.push("./" + path18.relative(cwd, path18.join(dir, entry.name)).replaceAll("\\", "/"));
26655
+ matches.push("./" + path20.relative(cwd, path20.join(dir, entry.name)).replaceAll("\\", "/"));
25791
26656
  }
25792
26657
  }
25793
26658
  };
@@ -25795,15 +26660,15 @@ var documentationFiles = (cwd) => {
25795
26660
  return matches.toSorted().slice(0, 200);
25796
26661
  };
25797
26662
  var readTrimmed2 = (file, maxLines) => {
25798
- if (!existsSync6(file))
26663
+ if (!existsSync7(file))
25799
26664
  return "";
25800
- const lines = readFileSync5(file, "utf8").split(`
26665
+ const lines = readFileSync6(file, "utf8").split(`
25801
26666
  `);
25802
26667
  return lines.slice(0, maxLines).join(`
25803
26668
  `);
25804
26669
  };
25805
26670
  function prReadyContext(root, range) {
25806
- const cwd = path18.resolve(repoRoot(root));
26671
+ const cwd = path20.resolve(repoRoot(root));
25807
26672
  if (range !== undefined && !isResolvableContextRange(cwd, range))
25808
26673
  return invalidRange(cwd);
25809
26674
  let stdout = "";
@@ -25861,7 +26726,7 @@ ${status.stderr}` : "");
25861
26726
  stdout += `template_path: ${template}
25862
26727
 
25863
26728
  `;
25864
- stdout += readTrimmed2(path18.join(cwd, template), 220);
26729
+ stdout += readTrimmed2(path20.join(cwd, template), 220);
25865
26730
  } else {
25866
26731
  stdout += `template_path: none
25867
26732
 
@@ -25871,7 +26736,7 @@ ${status.stderr}` : "");
25871
26736
  stdout += `
25872
26737
  `;
25873
26738
  stdout += printSection("Recent Validation Signals");
25874
- if (existsSync6(path18.join(cwd, "package.json"))) {
26739
+ if (existsSync7(path20.join(cwd, "package.json"))) {
25875
26740
  stdout += `package.json detected. Common scripts:
25876
26741
  `;
25877
26742
  const found = packageScripts(cwd, ["lint", "format:check", "test", "build"]);
@@ -25880,7 +26745,7 @@ ${status.stderr}` : "");
25880
26745
  `) + `
25881
26746
  `;
25882
26747
  }
25883
- if (existsSync6(path18.join(cwd, "Cargo.toml")) || existsSync6(path18.join(cwd, "src-tauri/Cargo.toml"))) {
26748
+ if (existsSync7(path20.join(cwd, "Cargo.toml")) || existsSync7(path20.join(cwd, "src-tauri/Cargo.toml"))) {
25884
26749
  stdout += `Rust project detected.
25885
26750
  `;
25886
26751
  }
@@ -25913,7 +26778,7 @@ var CHANGELOG_RULES = `- Use an [Unreleased] section.
25913
26778
  - Apply with the host-native editor, preserving the repository changelog conventions.
25914
26779
  - If Unreleased already has duplicate category headings, normalize_only first.`;
25915
26780
  function changelogContext(root, range) {
25916
- const cwd = path18.resolve(repoRoot(root));
26781
+ const cwd = path20.resolve(repoRoot(root));
25917
26782
  if (range !== undefined && !isResolvableContextRange(cwd, range))
25918
26783
  return invalidRange(cwd);
25919
26784
  const resolvedRange = rangeArgOrDefault(range, cwd);
@@ -25931,8 +26796,8 @@ function changelogContext(root, range) {
25931
26796
  stdout += CHANGELOG_RULES + `
25932
26797
  `;
25933
26798
  stdout += printSection("Existing CHANGELOG.md");
25934
- const changelogPath = path18.join(cwd, "CHANGELOG.md");
25935
- if (existsSync6(changelogPath)) {
26799
+ const changelogPath = path20.join(cwd, "CHANGELOG.md");
26800
+ if (existsSync7(changelogPath)) {
25936
26801
  stdout += readTrimmed2(changelogPath, 260) + `
25937
26802
  `;
25938
26803
  } else {
@@ -25951,7 +26816,7 @@ function changelogContext(root, range) {
25951
26816
  return { stdout, stderr: "", exitCode: 0, cwd };
25952
26817
  }
25953
26818
  function docsRefreshContext(root, range) {
25954
- const cwd = path18.resolve(repoRoot(root));
26819
+ const cwd = path20.resolve(repoRoot(root));
25955
26820
  if (range !== undefined && !isResolvableContextRange(cwd, range))
25956
26821
  return invalidRange(cwd);
25957
26822
  const resolvedRange = rangeArgOrDefault(range, cwd);
@@ -25973,8 +26838,8 @@ function docsRefreshContext(root, range) {
25973
26838
  `) + `
25974
26839
  `;
25975
26840
  stdout += printSection("README Preview");
25976
- const readme = path18.join(cwd, "README.md");
25977
- if (existsSync6(readme)) {
26841
+ const readme = path20.join(cwd, "README.md");
26842
+ if (existsSync7(readme)) {
25978
26843
  stdout += readTrimmed2(readme, 220) + `
25979
26844
  `;
25980
26845
  } else {
@@ -25982,10 +26847,10 @@ function docsRefreshContext(root, range) {
25982
26847
  `;
25983
26848
  }
25984
26849
  stdout += printSection("Package Scripts");
25985
- const pkgPath = path18.join(cwd, "package.json");
25986
- if (existsSync6(pkgPath)) {
26850
+ const pkgPath = path20.join(cwd, "package.json");
26851
+ if (existsSync7(pkgPath)) {
25987
26852
  try {
25988
- const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
26853
+ const pkg = JSON.parse(readFileSync6(pkgPath, "utf8"));
25989
26854
  stdout += JSON.stringify({ name: pkg.name, version: pkg.version, scripts: pkg.scripts }, null, 2) + `
25990
26855
  `;
25991
26856
  } catch {}
@@ -25996,7 +26861,7 @@ function docsRefreshContext(root, range) {
25996
26861
  return { stdout, stderr: "", exitCode: 0, cwd };
25997
26862
  }
25998
26863
  function releaseNotesContext(root, rangeOrTag) {
25999
- const cwd = path18.resolve(repoRoot(root));
26864
+ const cwd = path20.resolve(repoRoot(root));
26000
26865
  if (!rangeOrTag) {
26001
26866
  return { stdout: "", stderr: `ERROR: release tag or range required
26002
26867
  `, exitCode: 1, cwd };
@@ -26034,7 +26899,7 @@ function releaseNotesContext(root, rangeOrTag) {
26034
26899
  `;
26035
26900
  stdout += printSection("Existing Release Files");
26036
26901
  for (const rel of ["CHANGELOG.md", "RELEASE_NOTES.md", ".github/releases.md"]) {
26037
- if (existsSync6(path18.join(cwd, rel)))
26902
+ if (existsSync7(path20.join(cwd, rel)))
26038
26903
  stdout += rel + `
26039
26904
  `;
26040
26905
  }
@@ -26063,46 +26928,6 @@ function releaseNotesContext(root, rangeOrTag) {
26063
26928
 
26064
26929
  // packages/workit-core/src/core/tracker-issues.ts
26065
26930
  import { spawnSync as spawnSync13 } from "node:child_process";
26066
-
26067
- // packages/workit-core/src/core/pr-create.ts
26068
- import fs14 from "node:fs";
26069
- import path19 from "node:path";
26070
- import { spawnSync as spawnSync12 } from "node:child_process";
26071
- // packages/workit-core/src/forge/pr-body.ts
26072
- function parseGhIssue(value) {
26073
- const m = /issues\/(\d+)/.exec(value);
26074
- return m ? m[1] : String(value).trim().replace(/^#/, "");
26075
- }
26076
-
26077
- // packages/workit-core/src/core/pr-create.ts
26078
- function whichOnPath(tool) {
26079
- const names = process.platform === "win32" ? [tool, `${tool}.exe`, `${tool}.cmd`] : [tool];
26080
- for (const dir of (process.env.PATH ?? "").split(path19.delimiter)) {
26081
- if (!dir)
26082
- continue;
26083
- for (const name of names) {
26084
- const candidate = path19.join(dir, name);
26085
- try {
26086
- fs14.accessSync(candidate, fs14.constants.X_OK);
26087
- return candidate;
26088
- } catch {}
26089
- }
26090
- }
26091
- return null;
26092
- }
26093
- var hostingCliAvailable = (provider) => whichOnPath(provider === "gitlab" ? "glab" : "gh") !== null;
26094
- var pushRemote = (cwd) => {
26095
- const result = spawnSync12("git", ["remote", "get-url", "--push", "--all", "origin"], {
26096
- cwd,
26097
- encoding: "utf8"
26098
- });
26099
- if (result.status !== 0)
26100
- return null;
26101
- const urls = (result.stdout ?? "").split(/\r?\n/u).map((url) => url.trim()).filter(Boolean);
26102
- return urls.length === 1 ? urls[0] : null;
26103
- };
26104
-
26105
- // packages/workit-core/src/core/tracker-issues.ts
26106
26931
  var repoPathFromRemote = (remote) => {
26107
26932
  let rest = (remote || "").trim().replace(/\/+$/, "");
26108
26933
  if (!rest)
@@ -26202,7 +27027,7 @@ var fetchGitLabIssueBody = async (ref, root, deps = {}) => {
26202
27027
 
26203
27028
  // packages/workit-core/src/core/youtrack.ts
26204
27029
  import fs15 from "node:fs";
26205
- import path20 from "node:path";
27030
+ import path21 from "node:path";
26206
27031
 
26207
27032
  // packages/workit-core/src/core/templates.ts
26208
27033
  var repoRoot2 = assetRoot();
@@ -26215,8 +27040,8 @@ var resolveWorkspaceRoot = (explicit) => explicit || process.cwd();
26215
27040
  // packages/workit-core/src/core/youtrack.ts
26216
27041
  var ISSUE_RE = /^[A-Z]+-\d+$/;
26217
27042
  var TOKEN_PLACEHOLDER = "YOUR_TOKEN_HERE";
26218
- var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path20.join(configDir(), "youtrack.json");
26219
- var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path20.join(resolveConfigDir(), "youtrack.json");
27043
+ var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path21.join(configDir(), "youtrack.json");
27044
+ var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path21.join(resolveConfigDir(), "youtrack.json");
26220
27045
  var youTrackTokenModeOk = (p) => {
26221
27046
  if (process.platform === "win32")
26222
27047
  return true;
@@ -26284,7 +27109,7 @@ var youTrackToken = () => {
26284
27109
  if ("error" in loaded)
26285
27110
  return loaded;
26286
27111
  const tokenFile = String(loaded.config.tokenFile ?? "");
26287
- const tokenPath = tokenFile ? path20.isAbsolute(tokenFile) ? path20.resolve(tokenFile) : path20.resolve(process.cwd(), tokenFile) : "";
27112
+ const tokenPath = tokenFile ? path21.isAbsolute(tokenFile) ? path21.resolve(tokenFile) : path21.resolve(process.cwd(), tokenFile) : "";
26288
27113
  if (!tokenPath || !fs15.existsSync(tokenPath))
26289
27114
  return { error: "missing youtrack.token" };
26290
27115
  if (!youTrackTokenModeOk(tokenPath))
@@ -26626,15 +27451,15 @@ function resolveGitRevision(root, value) {
26626
27451
  }
26627
27452
  function resolveInside(root, candidate) {
26628
27453
  const base = realpathSync5(root);
26629
- const target = path21.resolve(base, candidate);
26630
- if (target !== base && !target.startsWith(base + path21.sep)) {
27454
+ const target = path22.resolve(base, candidate);
27455
+ if (target !== base && !target.startsWith(base + path22.sep)) {
26631
27456
  throw new Error("path must stay inside repository root");
26632
27457
  }
26633
27458
  let ancestor = target;
26634
- while (!existsSync7(ancestor))
26635
- ancestor = path21.dirname(ancestor);
27459
+ while (!existsSync8(ancestor))
27460
+ ancestor = path22.dirname(ancestor);
26636
27461
  const canonicalAncestor = realpathSync5(ancestor);
26637
- if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path21.sep)) {
27462
+ if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path22.sep)) {
26638
27463
  throw new Error("path must stay inside repository root");
26639
27464
  }
26640
27465
  return target;
@@ -26682,7 +27507,7 @@ var safeCapability = (value, allowed) => allowed.includes(value) ? value : "cont
26682
27507
  var TOOL_CAPABILITIES = [...CONTEXT_KINDS, "workspace", "native_caller_identity"];
26683
27508
  var VERSION = (() => {
26684
27509
  try {
26685
- const packageJson = JSON.parse(readFileSync6(new URL("../package.json", import.meta.url), "utf8"));
27510
+ const packageJson = JSON.parse(readFileSync7(new URL("../package.json", import.meta.url), "utf8"));
26686
27511
  return typeof packageJson.version === "string" ? packageJson.version : "0.0.0";
26687
27512
  } catch {
26688
27513
  return "0.0.0";
@@ -26692,13 +27517,13 @@ var rootVariants = (workspaceRoot) => {
26692
27517
  if (!workspaceRoot)
26693
27518
  return [];
26694
27519
  const roots = new Set;
26695
- for (const candidate of [workspaceRoot, path22.resolve(workspaceRoot)]) {
26696
- if (path22.isAbsolute(candidate) && candidate !== path22.parse(candidate).root)
27520
+ for (const candidate of [workspaceRoot, path23.resolve(workspaceRoot)]) {
27521
+ if (path23.isAbsolute(candidate) && candidate !== path23.parse(candidate).root)
26697
27522
  roots.add(candidate);
26698
27523
  }
26699
27524
  try {
26700
27525
  const canonical = realpathSync6(workspaceRoot);
26701
- if (canonical !== path22.parse(canonical).root)
27526
+ if (canonical !== path23.parse(canonical).root)
26702
27527
  roots.add(canonical);
26703
27528
  } catch {}
26704
27529
  return [...roots].toSorted((left, right) => right.length - left.length);
@@ -26780,12 +27605,12 @@ var thrownResult = (tool, error, workspaceRoot) => {
26780
27605
  };
26781
27606
  function createMcpServer(host, contextProvider) {
26782
27607
  assertMcpHost(host);
26783
- const here = path22.dirname(fileURLToPath2(import.meta.url));
27608
+ const here = path23.dirname(fileURLToPath2(import.meta.url));
26784
27609
  const sourceMarker = markSourcesLoaded([
26785
- path22.join(here, "server.ts"),
26786
- path22.join(here, "..", "..", "workit-core", "src", "core", "task-contract.ts"),
26787
- path22.join(here, "..", "..", "workit-core", "src", "core", "task-engine.ts")
26788
- ].filter((file) => existsSync8(file)));
27610
+ path23.join(here, "server.ts"),
27611
+ path23.join(here, "..", "..", "workit-core", "src", "core", "task-contract.ts"),
27612
+ path23.join(here, "..", "..", "workit-core", "src", "core", "task-engine.ts")
27613
+ ].filter((file) => existsSync9(file)));
26789
27614
  let staleWarned = false;
26790
27615
  const server = new Server({ name: "workit", version: VERSION }, { capabilities: { tools: {}, resources: {} } });
26791
27616
  server.setRequestHandler(ListToolsRequestSchema, async () => {
@@ -26965,8 +27790,8 @@ var main = async () => {
26965
27790
  process.exitCode = 2;
26966
27791
  }
26967
27792
  };
26968
- var entryPath = process.argv[1] ? path23.resolve(process.argv[1]) : "";
26969
- if (entryPath === path23.resolve(fileURLToPath3(import.meta.url)))
27793
+ var entryPath = process.argv[1] ? path24.resolve(process.argv[1]) : "";
27794
+ if (entryPath === path24.resolve(fileURLToPath3(import.meta.url)))
26970
27795
  await main();
26971
27796
  // packages/workit-core/src/hooks/descriptor.ts
26972
27797
  var support = (descriptor, axis) => {
@@ -27120,7 +27945,7 @@ var EXEC = new Set(["exec", "x", "dlx"]);
27120
27945
  // packages/workit-core/src/core/heavy-words.ts
27121
27946
  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(" "));
27122
27947
  // packages/workit-core/src/hooks/write-gate.ts
27123
- import path24 from "node:path";
27948
+ import path25 from "node:path";
27124
27949
 
27125
27950
  // packages/workit-core/src/core/live-session.ts
27126
27951
  import { spawnSync as spawnSync15 } from "node:child_process";
@@ -27161,7 +27986,7 @@ var MUTATING_WORKIT_GIT = new Set(["commit", "branch"]);
27161
27986
  var CD2 = new Set(["cd", "chdir", "set-location", "sl"]);
27162
27987
  var PUSHD2 = new Set(["pushd", "push-location"]);
27163
27988
  var POPD2 = new Set(["popd", "pop-location"]);
27164
- var UNKNOWN_DIR = path24.resolve(path24.parse(process.cwd()).root, ".workit-unknown-dir");
27989
+ var UNKNOWN_DIR = path25.resolve(path25.parse(process.cwd()).root, ".workit-unknown-dir");
27165
27990
  // packages/workit-core/src/core/skill-manifests.ts
27166
27991
  if (false) {}
27167
27992
 
@@ -27387,7 +28212,7 @@ var cursorContextProvider = (workspaceRoot = process.env.WORKFLOW_WORKSPACE_ROOT
27387
28212
  var stampCursorSessionStart = (stateDir = resolveStateDir()) => {
27388
28213
  try {
27389
28214
  mkdirSync3(stateDir, { recursive: true });
27390
- writeFileSync3(path25.join(stateDir, "cursor-session-last-start"), `${JSON.stringify({ at: new Date().toISOString() })}
28215
+ writeFileSync3(path26.join(stateDir, "cursor-session-last-start"), `${JSON.stringify({ at: new Date().toISOString() })}
27391
28216
  `);
27392
28217
  } catch {}
27393
28218
  };