@brainervirus/workit-cursor 8.23.0 → 8.25.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,144 @@ function resolveRef(cwd, ref) {
17781
17781
  return null;
17782
17782
  return line(git(cwd, ["rev-parse", "--verify", "-q", `${ref}^{commit}`]));
17783
17783
  }
17784
+ function originHeadRef(cwd) {
17785
+ return line(git(cwd, ["symbolic-ref", "-q", "--short", "refs/remotes/origin/HEAD"]));
17786
+ }
17787
+ function ownChangeDrift(cwd, range) {
17788
+ const before = diffRaw(cwd, range.fromFork, range.from);
17789
+ const after = diffRaw(cwd, range.toFork, range.to);
17790
+ if (!before || !after)
17791
+ return null;
17792
+ const judged = new Map(before.map((entry) => [entry.path, entry]));
17793
+ const current = new Map(after.map((entry) => [entry.path, entry]));
17794
+ const same = (a, b) => a !== undefined && b !== undefined && a.oldMode === b.oldMode && a.oldBlob === b.oldBlob && a.newMode === b.newMode && a.newBlob === b.newBlob;
17795
+ return [...new Set([...judged.keys(), ...current.keys()])].filter((file) => !same(judged.get(file), current.get(file))).toSorted();
17796
+ }
17797
+ function sameOwnChange(cwd, range) {
17798
+ const fromFork = mergeBase(cwd, range.fromBase, range.from);
17799
+ const toFork = mergeBase(cwd, range.toBase, range.to);
17800
+ if (!fromFork || !toFork)
17801
+ return false;
17802
+ return ownChangeDrift(cwd, { from: range.from, to: range.to, fromFork, toFork })?.length === 0;
17803
+ }
17804
+ var LANE_DIFF = [
17805
+ "-c",
17806
+ "core.quotePath=false",
17807
+ "diff",
17808
+ "--no-color",
17809
+ "--no-ext-diff",
17810
+ "--no-textconv",
17811
+ "--no-renames"
17812
+ ];
17813
+ var laneRange = (fork, head) => {
17814
+ if (!safeArg(fork) || head !== null && !safeArg(head))
17815
+ return null;
17816
+ return head === null ? [fork] : [fork, head];
17817
+ };
17818
+ function diffNumstat(cwd, fork, head) {
17819
+ const range = laneRange(fork, head);
17820
+ if (!range)
17821
+ return null;
17822
+ const run = git(cwd, [...LANE_DIFF, "--numstat", "-z", ...range, "--"]);
17823
+ if (!run.ok)
17824
+ return null;
17825
+ const out = [];
17826
+ for (const record of run.stdout.split("\x00")) {
17827
+ const match = /^(-|\d+)\t(-|\d+)\t(.+)$/su.exec(record.replace(/^\n/u, ""));
17828
+ if (!match)
17829
+ continue;
17830
+ const binary = match[1] === "-";
17831
+ out.push({
17832
+ path: match[3],
17833
+ added: binary ? 0 : Number(match[1]),
17834
+ deleted: binary ? 0 : Number(match[2]),
17835
+ binary
17836
+ });
17837
+ }
17838
+ return out;
17839
+ }
17840
+ function diffRaw(cwd, fork, head) {
17841
+ const range = laneRange(fork, head);
17842
+ if (!range)
17843
+ return null;
17844
+ const run = git(cwd, [...LANE_DIFF, "--raw", "-z", "--no-abbrev", ...range, "--"]);
17845
+ if (!run.ok)
17846
+ return null;
17847
+ const fields = run.stdout.split("\x00");
17848
+ const out = [];
17849
+ for (let index = 0;index + 1 < fields.length; index += 2) {
17850
+ const meta = /^:(\d{6}) (\d{6}) ([0-9a-f]+) ([0-9a-f]+) [A-Z]\d*$/u.exec(fields[index].replace(/^\n/u, ""));
17851
+ if (!meta)
17852
+ return null;
17853
+ out.push({
17854
+ path: fields[index + 1],
17855
+ oldMode: meta[1],
17856
+ newMode: meta[2],
17857
+ oldBlob: meta[3],
17858
+ newBlob: meta[4]
17859
+ });
17860
+ }
17861
+ return out;
17862
+ }
17863
+ function readBlobs(cwd, ids) {
17864
+ const out = new Map;
17865
+ const wanted = [...new Set(ids)].filter((id) => /^[0-9a-f]{40,64}$/u.test(id));
17866
+ if (!wanted.length)
17867
+ return out;
17868
+ const run = spawnSync3("git", ["cat-file", "--batch"], {
17869
+ cwd,
17870
+ input: `${wanted.join(`
17871
+ `)}
17872
+ `,
17873
+ maxBuffer: MAX_BUFFER,
17874
+ timeout: GIT_TIMEOUTS.local,
17875
+ killSignal: "SIGKILL",
17876
+ windowsHide: true
17877
+ });
17878
+ if (run.status !== 0 || !run.stdout)
17879
+ return null;
17880
+ const bytes = run.stdout;
17881
+ let at = 0;
17882
+ for (const id of wanted) {
17883
+ const end = bytes.indexOf(10, at);
17884
+ if (end < 0)
17885
+ return null;
17886
+ const header = bytes.subarray(at, end).toString("utf8").split(" ");
17887
+ at = end + 1;
17888
+ if (header[1] === "missing")
17889
+ continue;
17890
+ const size = Number(header[2]);
17891
+ if (header[0] !== id || !Number.isSafeInteger(size))
17892
+ return null;
17893
+ out.set(id, bytes.subarray(at, at + size));
17894
+ at += size + 1;
17895
+ }
17896
+ return out;
17897
+ }
17898
+ function treeFilesNamed(cwd, rev, name) {
17899
+ if (!safeArg(rev))
17900
+ return null;
17901
+ const run = git(cwd, ["ls-tree", "-r", "-z", "--full-tree", rev]);
17902
+ if (!run.ok)
17903
+ return null;
17904
+ const out = new Map;
17905
+ for (const record of run.stdout.split("\x00")) {
17906
+ const match = /^\d{6} blob ([0-9a-f]+)\t(.+)$/su.exec(record);
17907
+ if (match && (match[2] === name || match[2].endsWith(`/${name}`)))
17908
+ out.set(match[2], match[1]);
17909
+ }
17910
+ return out;
17911
+ }
17912
+ function fileAt(cwd, rev, file) {
17913
+ if (!safeArg(rev))
17914
+ return null;
17915
+ const run = git(cwd, ["cat-file", "blob", `${rev}:${file}`]);
17916
+ return run.ok ? run.stdout : null;
17917
+ }
17918
+ function untrackedFiles(cwd) {
17919
+ const run = git(cwd, ["ls-files", "-z", "--others", "--exclude-standard"]);
17920
+ return run.ok ? run.stdout.split("\x00").filter(Boolean) : [];
17921
+ }
17784
17922
  var config2 = (cwd, key) => line(git(cwd, ["config", "--get", key]));
17785
17923
  function currentBranch(cwd) {
17786
17924
  return line(git(cwd, ["symbolic-ref", "--short", "-q", "HEAD"]));
@@ -21291,7 +21429,7 @@ var workerBlocksTransition = (transition, state) => transition === "pause" ? fal
21291
21429
  import { createHash as createHash10 } from "node:crypto";
21292
21430
  import * as fs13 from "node:fs";
21293
21431
  import { spawnSync as spawnSync10 } from "node:child_process";
21294
- import path16 from "node:path";
21432
+ import path17 from "node:path";
21295
21433
 
21296
21434
  // packages/workit-core/src/check-config.ts
21297
21435
  import { spawnSync as spawnSync8 } from "node:child_process";
@@ -21511,14 +21649,757 @@ function checkCommand(args, version, onPath = workitAvailable()) {
21511
21649
  }
21512
21650
 
21513
21651
  // packages/workit-core/src/core/policy/derive.ts
21514
- import { existsSync as existsSync4 } from "node:fs";
21515
- import path15 from "node:path";
21652
+ import { existsSync as existsSync5 } from "node:fs";
21653
+ import path16 from "node:path";
21516
21654
 
21517
21655
  // packages/workit-core/src/ledger.ts
21518
21656
  import { spawnSync as spawnSync9 } from "node:child_process";
21519
21657
  import { createHash as createHash9, randomBytes as randomBytes3 } from "node:crypto";
21520
21658
  import fs12 from "node:fs";
21659
+ import path15 from "node:path";
21660
+
21661
+ // packages/workit-core/src/core/policy/lane.ts
21662
+ import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
21521
21663
  import path14 from "node:path";
21664
+
21665
+ // packages/workit-core/src/git/default-base.ts
21666
+ var safeRef = (value) => value.length > 0 && !value.startsWith("-");
21667
+ var trackTrunk = (cwd) => {
21668
+ try {
21669
+ const resolved = vcsConfig("resolve", cwd);
21670
+ if (resolved.ok === false || !resolved.releaseTrack || resolved.releaseTrack.blocking)
21671
+ return null;
21672
+ const target = String(resolved.defaultTargetBranch ?? "").trim();
21673
+ return target && safeRef(target) ? target : null;
21674
+ } catch {
21675
+ return null;
21676
+ }
21677
+ };
21678
+ function defaultBase(cwd) {
21679
+ const trunk = trackTrunk(cwd);
21680
+ if (trunk) {
21681
+ for (const candidate of [`origin/${trunk}`, trunk])
21682
+ if (resolveRef(cwd, candidate))
21683
+ return candidate;
21684
+ }
21685
+ const originHead = originHeadRef(cwd);
21686
+ if (originHead && resolveRef(cwd, originHead))
21687
+ return originHead;
21688
+ for (const candidate of [
21689
+ "origin/main",
21690
+ "origin/master",
21691
+ "main",
21692
+ "master",
21693
+ "origin/develop",
21694
+ "develop"
21695
+ ])
21696
+ if (resolveRef(cwd, candidate))
21697
+ return candidate;
21698
+ return null;
21699
+ }
21700
+
21701
+ // packages/workit-core/src/core/policy/attributes.ts
21702
+ function patternRegex(dir, pattern) {
21703
+ if (!pattern || pattern.endsWith("/") || pattern.startsWith('"') || pattern.startsWith("!"))
21704
+ return null;
21705
+ const anchored = pattern.includes("/");
21706
+ const body = pattern.replace(/^\//u, "");
21707
+ let source = "";
21708
+ for (let index = 0;index < body.length; index += 1) {
21709
+ const char = body[index];
21710
+ if (char === "*" && body[index + 1] === "*") {
21711
+ const slash = body[index + 2] === "/";
21712
+ source += slash ? "(?:.*/)?" : ".*";
21713
+ index += slash ? 2 : 1;
21714
+ } else if (char === "*")
21715
+ source += "[^/]*";
21716
+ else if (char === "?")
21717
+ source += "[^/]";
21718
+ else if (char === "[") {
21719
+ const end = body.indexOf("]", index + 2);
21720
+ if (end < 0)
21721
+ return null;
21722
+ const set = body.slice(index + 1, end).replace(/^!/u, "^").replace(/\\/gu, "\\\\");
21723
+ source += `[${set}]`;
21724
+ index = end;
21725
+ } else if (char === "\\" && index + 1 < body.length) {
21726
+ source += body[index + 1].replace(/[.*+?^${}()|[\]\\/]/gu, "\\$&");
21727
+ index += 1;
21728
+ } else
21729
+ source += char.replace(/[.*+?^${}()|[\]\\/]/gu, "\\$&");
21730
+ }
21731
+ const prefix = dir ? `${dir.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")}/` : "";
21732
+ try {
21733
+ return new RegExp(anchored ? `^${prefix}${source}$` : `^${prefix}(?:.*/)?${source}$`, "u");
21734
+ } catch {
21735
+ return null;
21736
+ }
21737
+ }
21738
+ function rulesOf(dir, text) {
21739
+ const out = [];
21740
+ for (const raw of text.split(`
21741
+ `)) {
21742
+ const line = raw.trim();
21743
+ if (!line || line.startsWith("#") || line.startsWith("[attr]"))
21744
+ continue;
21745
+ const [pattern, ...attributes] = line.split(/\s+/u);
21746
+ let generated = null;
21747
+ for (const attribute of attributes) {
21748
+ if (attribute === "linguist-generated" || attribute === "linguist-generated=true")
21749
+ generated = true;
21750
+ else if (attribute === "-linguist-generated" || attribute === "!linguist-generated" || attribute.startsWith("linguist-generated="))
21751
+ generated = false;
21752
+ }
21753
+ if (generated === null)
21754
+ continue;
21755
+ const regex = patternRegex(dir, pattern);
21756
+ if (regex)
21757
+ out.push({ regex, generated });
21758
+ }
21759
+ return out;
21760
+ }
21761
+ function generatedByAttributes(files, paths) {
21762
+ const rules = [...files].map(([file, text]) => {
21763
+ const dir = file.includes("/") ? file.slice(0, file.lastIndexOf("/")) : "";
21764
+ return {
21765
+ depth: dir ? dir.split("/").length : 0,
21766
+ rules: rulesOf(dir, text)
21767
+ };
21768
+ }).toSorted((left, right) => left.depth - right.depth).flatMap((entry) => entry.rules);
21769
+ const out = new Set;
21770
+ for (const file of paths) {
21771
+ const last = rules.findLast((rule) => rule.regex.test(file));
21772
+ if (last?.generated)
21773
+ out.add(file);
21774
+ }
21775
+ return out;
21776
+ }
21777
+
21778
+ // packages/workit-core/src/core/policy/substance.ts
21779
+ var SLASH_BLOCK = [["/*", "*/"]];
21780
+ var C_LIKE = { line: ["//"], block: SLASH_BLOCK, quotes: `"'` };
21781
+ var SYNTAXES = Object.fromEntries([
21782
+ ...["ts", "mts", "cts", "js", "mjs", "cjs"].map((ext) => [ext, { ...C_LIKE, js: true }]),
21783
+ ...["java", "kt", "kts", "scala", "swift", "dart", "groovy"].map((ext) => [
21784
+ ext,
21785
+ { ...C_LIKE, triple: true }
21786
+ ]),
21787
+ ["go", { ...C_LIKE, rawBacktick: true }],
21788
+ ...["css", "scss", "less"].map((ext) => [
21789
+ ext,
21790
+ { line: [], block: SLASH_BLOCK, quotes: `"'`, cssUrl: true }
21791
+ ]),
21792
+ ...["py", "pyi"].map((ext) => [
21793
+ ext,
21794
+ { line: ["#"], block: [], quotes: `"'`, triple: true, indented: true, fstring: true }
21795
+ ]),
21796
+ ["toml", { line: ["#"], block: [], quotes: `"`, literal: "'", triple: true }],
21797
+ ...["html", "htm", "xml", "svg", "xhtml"].map((ext) => [
21798
+ ext,
21799
+ { line: [], block: [["<!--", "-->"]], quotes: "", indented: true }
21800
+ ])
21801
+ ]);
21802
+ 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;
21803
+ var extensionOf = (file) => {
21804
+ const name = file.slice(file.lastIndexOf("/") + 1);
21805
+ const dot = name.lastIndexOf(".");
21806
+ return dot > 0 ? name.slice(dot + 1).toLowerCase() : "";
21807
+ };
21808
+ var CI_PATH = /^\.github\/|(?:^|\/)(?:\.gitlab-ci\.ya?ml|Jenkinsfile|azure-pipelines\.ya?ml|\.pre-commit-config\.ya?ml|\.circleci\/.*)$/u;
21809
+ var syntaxOf = (file) => CI_PATH.test(file) ? null : SYNTAXES[extensionOf(file)] ?? null;
21810
+ var SPACE = /[ \t\r\f\v]/u;
21811
+ var WORD = /[\w$]/u;
21812
+ var NO_SPACE_AFTER = "([{,;";
21813
+ var NO_SPACE_BEFORE = ")]},;";
21814
+ var REGEX_AFTER = "(,=:[!&|?{};+-*%<>~^";
21815
+ var REGEX_KEYWORDS = new Set([
21816
+ "return",
21817
+ "typeof",
21818
+ "instanceof",
21819
+ "case",
21820
+ "do",
21821
+ "else",
21822
+ "in",
21823
+ "of",
21824
+ "new",
21825
+ "delete",
21826
+ "void",
21827
+ "throw",
21828
+ "yield",
21829
+ "await"
21830
+ ]);
21831
+ function substanceOf(file, text) {
21832
+ const syntax = syntaxOf(file);
21833
+ if (!syntax)
21834
+ return plainSubstance(text);
21835
+ const markup = syntax.block.some(([open]) => open === "<!--");
21836
+ if (markup && (/<(?:script|style)\b|<!\[CDATA\[|<\?/iu.test(text) || /[^>\s][ \t]*<!--/u.test(text)))
21837
+ return plainSubstance(text);
21838
+ return lex(syntax, text);
21839
+ }
21840
+ function plainSubstance(text) {
21841
+ return text.split(`
21842
+ `).map((line) => line.replace(/[ \t\r\f\v]+$/u, "")).filter(Boolean).join(`
21843
+ `);
21844
+ }
21845
+ function lex(syntax, text) {
21846
+ const collapse = !syntax.indented;
21847
+ let out = "";
21848
+ let lineStart = 0;
21849
+ let kept = 0;
21850
+ let pendingSpace = false;
21851
+ const frames = [{ kind: "code", braces: 0 }];
21852
+ let index = 0;
21853
+ if (text.startsWith("#!")) {
21854
+ const end = text.indexOf(`
21855
+ `);
21856
+ out = end < 0 ? text : text.slice(0, end);
21857
+ kept = out.length;
21858
+ index = end < 0 ? text.length : end;
21859
+ }
21860
+ const emitCode = (chunk) => {
21861
+ if (collapse && pendingSpace && out.length > lineStart) {
21862
+ const before = out[out.length - 1];
21863
+ if (!NO_SPACE_AFTER.includes(before) && !NO_SPACE_BEFORE.includes(chunk[0]))
21864
+ out += " ";
21865
+ }
21866
+ pendingSpace = false;
21867
+ out += chunk;
21868
+ };
21869
+ const emitVerbatim = (chunk) => {
21870
+ emitCode(chunk);
21871
+ kept = out.length;
21872
+ };
21873
+ const newline = () => {
21874
+ if (!collapse) {
21875
+ let end = out.length;
21876
+ while (end > Math.max(lineStart, kept) && SPACE.test(out[end - 1]))
21877
+ end -= 1;
21878
+ out = out.slice(0, end);
21879
+ }
21880
+ pendingSpace = false;
21881
+ if (out.length > lineStart) {
21882
+ out += `
21883
+ `;
21884
+ lineStart = out.length;
21885
+ }
21886
+ };
21887
+ const regexAllowed = () => {
21888
+ let end = out.length;
21889
+ while (end > 0 && /\s/u.test(out[end - 1]))
21890
+ end -= 1;
21891
+ if (end === 0 || REGEX_AFTER.includes(out[end - 1]))
21892
+ return true;
21893
+ let start = end;
21894
+ while (start > 0 && WORD.test(out[start - 1]))
21895
+ start -= 1;
21896
+ return REGEX_KEYWORDS.has(out.slice(start, end));
21897
+ };
21898
+ const scanString = (quote, escapes, multiline) => {
21899
+ const prefix = text.slice(Math.max(0, index - 2), index).match(/[a-z]*$/iu)?.[0] ?? "";
21900
+ const fstring = syntax.fstring === true && /f/iu.test(prefix);
21901
+ let end = index + quote.length;
21902
+ while (end < text.length) {
21903
+ const char = text[end];
21904
+ if (escapes && char === "\\") {
21905
+ end += 2;
21906
+ continue;
21907
+ }
21908
+ if (text.startsWith(quote, end)) {
21909
+ if (fstring && unbalanced(text.slice(index + quote.length, end)))
21910
+ return false;
21911
+ emitVerbatim(text.slice(index, end + quote.length));
21912
+ index = end + quote.length;
21913
+ return true;
21914
+ }
21915
+ if (char === `
21916
+ ` && !multiline)
21917
+ return false;
21918
+ end += 1;
21919
+ }
21920
+ return false;
21921
+ };
21922
+ while (index < text.length) {
21923
+ const frame = frames[frames.length - 1];
21924
+ const char = text[index];
21925
+ if (frame.kind === "template") {
21926
+ if (char === "\\") {
21927
+ emitVerbatim(text.slice(index, index + 2));
21928
+ index += 2;
21929
+ } else if (char === "`") {
21930
+ emitVerbatim(char);
21931
+ frames.pop();
21932
+ index += 1;
21933
+ } else if (text.startsWith("${", index)) {
21934
+ emitVerbatim("${");
21935
+ frames.push({ kind: "code", braces: 0 });
21936
+ index += 2;
21937
+ } else {
21938
+ out += char;
21939
+ kept = out.length;
21940
+ index += 1;
21941
+ }
21942
+ continue;
21943
+ }
21944
+ if (char === `
21945
+ `) {
21946
+ newline();
21947
+ index += 1;
21948
+ continue;
21949
+ }
21950
+ if (SPACE.test(char)) {
21951
+ if (collapse)
21952
+ pendingSpace = true;
21953
+ else
21954
+ out += char;
21955
+ index += 1;
21956
+ continue;
21957
+ }
21958
+ const lineOpener = syntax.line.find((opener) => text.startsWith(opener, index));
21959
+ if (lineOpener) {
21960
+ const end = text.indexOf(`
21961
+ `, index);
21962
+ const comment = text.slice(index, end < 0 ? text.length : end);
21963
+ if (DIRECTIVE.test(comment.slice(lineOpener.length)))
21964
+ emitVerbatim(comment);
21965
+ else
21966
+ pendingSpace = true;
21967
+ index = end < 0 ? text.length : end;
21968
+ continue;
21969
+ }
21970
+ const block = syntax.block.find(([open]) => text.startsWith(open, index));
21971
+ if (block) {
21972
+ const end = text.indexOf(block[1], index + block[0].length);
21973
+ if (end < 0)
21974
+ return null;
21975
+ const comment = text.slice(index, end + block[1].length);
21976
+ if (DIRECTIVE.test(comment.slice(block[0].length, -block[1].length)))
21977
+ emitVerbatim(comment);
21978
+ else
21979
+ pendingSpace = true;
21980
+ if (comment.includes(`
21981
+ `))
21982
+ newline();
21983
+ index = end + block[1].length;
21984
+ continue;
21985
+ }
21986
+ if (syntax.triple && (char === '"' || char === "'") && text.startsWith(char.repeat(3), index)) {
21987
+ if (!scanString(char.repeat(3), !syntax.literal?.includes(char), true))
21988
+ return null;
21989
+ continue;
21990
+ }
21991
+ if (syntax.quotes.includes(char)) {
21992
+ if (!scanString(char, true, Boolean(syntax.multiline)))
21993
+ return null;
21994
+ continue;
21995
+ }
21996
+ if (syntax.literal?.includes(char)) {
21997
+ if (!scanString(char, false, false))
21998
+ return null;
21999
+ continue;
22000
+ }
22001
+ if (syntax.rawBacktick && char === "`") {
22002
+ if (!scanString("`", false, true))
22003
+ return null;
22004
+ continue;
22005
+ }
22006
+ if (syntax.js && char === "`") {
22007
+ emitVerbatim(char);
22008
+ frames.push({ kind: "template" });
22009
+ index += 1;
22010
+ continue;
22011
+ }
22012
+ if (syntax.cssUrl && /^url\(\s*[^"')\s]/iu.test(text.slice(index, index + 64)))
22013
+ return null;
22014
+ if (syntax.js && char === "/" && !regexAllowed() && out.trimEnd().endsWith(")")) {
22015
+ const lineEnd = text.indexOf(`
22016
+ `, index);
22017
+ if (text.slice(index + 1, lineEnd < 0 ? text.length : lineEnd).includes("/"))
22018
+ return null;
22019
+ }
22020
+ if (syntax.js && char === "/" && regexAllowed()) {
22021
+ let end = index + 1;
22022
+ let inClass = false;
22023
+ while (end < text.length && (inClass || text[end] !== "/")) {
22024
+ if (text[end] === `
22025
+ `)
22026
+ return null;
22027
+ if (text[end] === "\\")
22028
+ end += 1;
22029
+ else if (text[end] === "[")
22030
+ inClass = true;
22031
+ else if (text[end] === "]")
22032
+ inClass = false;
22033
+ end += 1;
22034
+ }
22035
+ if (end >= text.length)
22036
+ return null;
22037
+ emitVerbatim(text.slice(index, end + 1));
22038
+ index = end + 1;
22039
+ continue;
22040
+ }
22041
+ if (frames.length > 1 && frame.kind === "code") {
22042
+ if (char === "{")
22043
+ frame.braces += 1;
22044
+ else if (char === "}") {
22045
+ if (frame.braces === 0) {
22046
+ emitVerbatim(char);
22047
+ frames.pop();
22048
+ index += 1;
22049
+ continue;
22050
+ }
22051
+ frame.braces -= 1;
22052
+ }
22053
+ }
22054
+ emitCode(char);
22055
+ index += 1;
22056
+ }
22057
+ if (frames.length !== 1)
22058
+ return null;
22059
+ newline();
22060
+ return out;
22061
+ }
22062
+ function unbalanced(body) {
22063
+ let depth = 0;
22064
+ for (const part of body.replaceAll("{{", "").replaceAll("}}", "")) {
22065
+ if (part === "{")
22066
+ depth += 1;
22067
+ else if (part === "}")
22068
+ depth = Math.max(0, depth - 1);
22069
+ }
22070
+ return depth > 0;
22071
+ }
22072
+ function hasOpaqueLineBreak(text) {
22073
+ return /\r(?!\n)|[\u2028\u2029]/u.test(text);
22074
+ }
22075
+ var decoder = new TextDecoder("utf-8", { fatal: true });
22076
+ function textOf(bytes) {
22077
+ if (bytes.includes(0))
22078
+ return null;
22079
+ try {
22080
+ return decoder.decode(bytes);
22081
+ } catch {
22082
+ return null;
22083
+ }
22084
+ }
22085
+ function cosmeticChange(file, before, after) {
22086
+ const left = textOf(before);
22087
+ const right = textOf(after);
22088
+ if (left === null || right === null)
22089
+ return false;
22090
+ if (hasOpaqueLineBreak(left) || hasOpaqueLineBreak(right))
22091
+ return false;
22092
+ const a = substanceOf(file, left);
22093
+ return a !== null && a === substanceOf(file, right);
22094
+ }
22095
+
22096
+ // packages/workit-core/src/core/policy/lane.ts
22097
+ var LANE_THRESHOLDS = {
22098
+ selfMaxLines: 100,
22099
+ selfMaxFiles: 5,
22100
+ fullMinLines: 500
22101
+ };
22102
+ var RISK_TOKENS = new Set([
22103
+ "auth",
22104
+ "authn",
22105
+ "authz",
22106
+ "oauth",
22107
+ "security",
22108
+ "permission",
22109
+ "permissions",
22110
+ "secret",
22111
+ "secrets",
22112
+ "crypto",
22113
+ "gate",
22114
+ "gates",
22115
+ "policy",
22116
+ "policies",
22117
+ "hook",
22118
+ "hooks",
22119
+ "husky",
22120
+ "lefthook",
22121
+ "release",
22122
+ "releases",
22123
+ "migration",
22124
+ "migrations",
22125
+ "migrate",
22126
+ "workflows"
22127
+ ]);
22128
+ var RISK_FILES = new Set([
22129
+ ".gitlab-ci.yml",
22130
+ "Jenkinsfile",
22131
+ "azure-pipelines.yml",
22132
+ ".pre-commit-config.yaml",
22133
+ ".workit/risk-paths"
22134
+ ]);
22135
+ var RISK_NAMES = new Set([".gitattributes"]);
22136
+ var RISK_PATHS_FILE = ".workit/risk-paths";
22137
+ var LOCKFILES = new Set([
22138
+ "bun.lock",
22139
+ "bun.lockb",
22140
+ "package-lock.json",
22141
+ "npm-shrinkwrap.json",
22142
+ "yarn.lock",
22143
+ "pnpm-lock.yaml",
22144
+ "Cargo.lock",
22145
+ "go.sum",
22146
+ "poetry.lock",
22147
+ "uv.lock",
22148
+ "Pipfile.lock",
22149
+ "Gemfile.lock",
22150
+ "composer.lock"
22151
+ ]);
22152
+ var DOC_EXT = /\.(?:md|mdx|markdown|rst|adoc)$/iu;
22153
+ var DOC_NAMES = /^(?:license|licence|notice|authors|changelog|changes|contributors)$/iu;
22154
+ var INSTRUCTIONS = /(?:^|\/)(?:AGENTS|CLAUDE|GEMINI|SKILL)\.md$|(?:^|\/)(?:skills|agents|commands|rules|prompts)\/[^/]+/iu;
22155
+ var TEST_PATH = /(?:^|\/)(?:test|tests|__tests__)\/|\.(?:test|spec)\.[^/]+$|_test\.[^/]+$/iu;
22156
+ var basename = (file) => file.slice(file.lastIndexOf("/") + 1);
22157
+ var isDoc = (file) => !INSTRUCTIONS.test(file) && (DOC_EXT.test(file) || DOC_NAMES.test(basename(file)));
22158
+ function kindOf(file) {
22159
+ if (file.binary)
22160
+ return "behavior";
22161
+ if (file.generated)
22162
+ return "generated";
22163
+ if (LOCKFILES.has(basename(file.path)))
22164
+ return "lockfile";
22165
+ if (isDoc(file.path))
22166
+ return "doc";
22167
+ if (file.cosmetic)
22168
+ return "cosmetic";
22169
+ return TEST_PATH.test(file.path) ? "test" : "behavior";
22170
+ }
22171
+ var globCache = new Map;
22172
+ function globMatch(pattern, file) {
22173
+ let regex = globCache.get(pattern);
22174
+ if (!regex) {
22175
+ let source = "";
22176
+ for (let index = 0;index < pattern.length; index += 1) {
22177
+ const char = pattern[index];
22178
+ if (char === "*" && pattern[index + 1] === "*") {
22179
+ source += pattern[index + 2] === "/" ? "(?:[^/]*/)*" : ".*";
22180
+ index += pattern[index + 2] === "/" ? 2 : 1;
22181
+ } else if (char === "*")
22182
+ source += "[^/]*";
22183
+ else if (char === "?")
22184
+ source += "[^/]";
22185
+ else
22186
+ source += char.replace(/[.+^${}()|[\]\\]/gu, "\\$&");
22187
+ }
22188
+ regex = new RegExp(`^${source}$`, "u");
22189
+ globCache.set(pattern, regex);
22190
+ }
22191
+ return regex.test(file) || file.startsWith(`${pattern.replace(/\/$/u, "")}/`);
22192
+ }
22193
+ function isRiskPath(file, extra = []) {
22194
+ if (extra.some((pattern) => globMatch(pattern, file)))
22195
+ return true;
22196
+ if (RISK_FILES.has(file) || RISK_NAMES.has(basename(file)))
22197
+ return true;
22198
+ if (TEST_PATH.test(file) || isDoc(file))
22199
+ return false;
22200
+ 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)));
22201
+ }
22202
+ var parseRiskPaths = (text) => text.split(`
22203
+ `).map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map((line) => line.replace(/^\//u, ""));
22204
+ function computeLane(input) {
22205
+ const riskFiles = input.files.filter((file) => isRiskPath(file.path, input.riskPaths)).map((file) => file.path);
22206
+ const risky = new Set(riskFiles);
22207
+ const kinds = input.files.map((file) => ({
22208
+ file,
22209
+ kind: risky.has(file.path) ? "behavior" : kindOf(file)
22210
+ }));
22211
+ const behavior = kinds.filter((entry) => entry.kind === "behavior" || entry.kind === "test" || entry.kind === "lockfile");
22212
+ const lines = behavior.filter((entry) => entry.kind !== "lockfile").reduce((sum, entry) => sum + entry.file.added + entry.file.deleted, 0);
22213
+ const opaque = behavior.filter((entry) => entry.kind === "lockfile" || entry.file.binary);
22214
+ const result = (lane, reasons) => ({
22215
+ lane,
22216
+ reasons,
22217
+ lines,
22218
+ files: behavior.length,
22219
+ riskFiles
22220
+ });
22221
+ const { selfMaxLines, selfMaxFiles, fullMinLines } = LANE_THRESHOLDS;
22222
+ if (input.riskTier === "high")
22223
+ return result("full", ["the task judgment records high risk"]);
22224
+ if (riskFiles.length)
22225
+ return result("full", [
22226
+ `touches a risk path: ${riskFiles.slice(0, 3).join(", ")}${riskFiles.length > 3 ? ", …" : ""}`
22227
+ ]);
22228
+ if (!behavior.length)
22229
+ return result("none", [
22230
+ input.files.length ? "only docs, comments, formatting or generated copies changed" : "no changes"
22231
+ ]);
22232
+ if (lines >= fullMinLines)
22233
+ return result("full", [`large diff: ${lines} lines (≥ ${fullMinLines})`]);
22234
+ if (lines > selfMaxLines)
22235
+ return result("focused", [`${lines} lines changed (> ${selfMaxLines})`]);
22236
+ if (behavior.length > selfMaxFiles)
22237
+ return result("focused", [`${behavior.length} behavior files changed (> ${selfMaxFiles})`]);
22238
+ if (opaque.length)
22239
+ return result("focused", [
22240
+ `a lockfile or binary changed: ${opaque.slice(0, 3).map((entry) => entry.file.path).join(", ")}${opaque.length > 3 ? ", …" : ""}`
22241
+ ]);
22242
+ return result("self", [
22243
+ `small change: ${lines} line${lines === 1 ? "" : "s"} in ${behavior.length} file${behavior.length === 1 ? "" : "s"}, no risk path`
22244
+ ]);
22245
+ }
22246
+ function untrackedStat(cwd, file) {
22247
+ try {
22248
+ const bytes = readFileSync4(path14.join(cwd, file));
22249
+ if (bytes.includes(0))
22250
+ return { path: file, added: 0, deleted: 0, binary: true };
22251
+ const text = bytes.toString("utf8");
22252
+ if (hasOpaqueLineBreak(text))
22253
+ return { path: file, added: 0, deleted: 0, binary: true };
22254
+ const lines = text.split(`
22255
+ `).length - (text.endsWith(`
22256
+ `) ? 1 : 0);
22257
+ return { path: file, added: lines, deleted: 0 };
22258
+ } catch {
22259
+ return { path: file, added: 0, deleted: 0, binary: true };
22260
+ }
22261
+ }
22262
+ var REGULAR = new Set(["100644", "100755"]);
22263
+ var ABSENT = /^0+$/u;
22264
+ function cosmeticFiles(cwd, fork, head) {
22265
+ const raw = diffRaw(cwd, fork, head);
22266
+ if (!raw)
22267
+ return null;
22268
+ const candidates = raw.filter((entry) => REGULAR.has(entry.oldMode) && entry.oldMode === entry.newMode && !ABSENT.test(entry.oldBlob) && (head === null || !ABSENT.test(entry.newBlob)));
22269
+ const blobs = readBlobs(cwd, candidates.flatMap((entry) => [entry.oldBlob, entry.newBlob]));
22270
+ if (!blobs)
22271
+ return null;
22272
+ const out = new Set;
22273
+ const opaque = new Set;
22274
+ for (const entry of candidates) {
22275
+ const before = blobs.get(entry.oldBlob);
22276
+ let after = blobs.get(entry.newBlob);
22277
+ if (!after && head === null && ABSENT.test(entry.newBlob))
22278
+ try {
22279
+ after = readFileSync4(path14.join(cwd, entry.path));
22280
+ } catch {
22281
+ after = undefined;
22282
+ }
22283
+ if (before && after && cosmeticChange(entry.path, before, after))
22284
+ out.add(entry.path);
22285
+ else if ([before, after].some((bytes) => bytes && hasOpaqueLineBreak(bytes.toString("utf8"))))
22286
+ opaque.add(entry.path);
22287
+ }
22288
+ return { cosmetic: out, opaque };
22289
+ }
22290
+ function generatedAt(cwd, fork, paths) {
22291
+ const files = treeFilesNamed(cwd, fork, ".gitattributes");
22292
+ const blobs = files?.size ? readBlobs(cwd, [...files.values()]) : null;
22293
+ if (!files || !blobs)
22294
+ return new Set;
22295
+ const texts = new Map;
22296
+ for (const [file, id] of files) {
22297
+ const bytes = blobs.get(id);
22298
+ if (bytes)
22299
+ texts.set(file, bytes.toString("utf8"));
22300
+ }
22301
+ return generatedByAttributes(texts, paths);
22302
+ }
22303
+ var forkOf = (cwd, base, head) => mergeBase(cwd, base, head ?? "HEAD");
22304
+ function laneFiles(cwd, fork, head, attributesAt = fork) {
22305
+ const stats = diffNumstat(cwd, fork, head);
22306
+ const cosmetic = stats ? cosmeticFiles(cwd, fork, head) : null;
22307
+ if (!stats || !cosmetic)
22308
+ return null;
22309
+ const files = [
22310
+ ...stats.map((entry) => ({
22311
+ ...entry,
22312
+ ...cosmetic.opaque.has(entry.path) ? { binary: true } : {},
22313
+ cosmetic: !entry.binary && cosmetic.cosmetic.has(entry.path)
22314
+ })),
22315
+ ...head === null ? untrackedFiles(cwd).map((file) => untrackedStat(cwd, file)) : []
22316
+ ];
22317
+ const generated = generatedAt(cwd, attributesAt, files.map((entry) => entry.path));
22318
+ return files.map((entry) => ({
22319
+ ...entry,
22320
+ generated: generated.has(entry.path)
22321
+ }));
22322
+ }
22323
+ function driftFiles(cwd, range) {
22324
+ if (range.fromFork === range.toFork)
22325
+ return laneFiles(cwd, range.from, range.to, range.toFork);
22326
+ const drifted = ownChangeDrift(cwd, range);
22327
+ const stats = drifted ? diffNumstat(cwd, range.from, range.to) : null;
22328
+ if (!drifted || !stats)
22329
+ return null;
22330
+ const byPath = new Map(stats.map((entry) => [entry.path, entry]));
22331
+ const generated = generatedAt(cwd, range.toFork, drifted);
22332
+ return drifted.map((file) => ({
22333
+ path: file,
22334
+ added: byPath.get(file)?.added ?? 0,
22335
+ deleted: byPath.get(file)?.deleted ?? 0,
22336
+ ...byPath.get(file)?.binary ? { binary: true } : {},
22337
+ cosmetic: false,
22338
+ generated: generated.has(file)
22339
+ }));
22340
+ }
22341
+ function branchLane(cwd, options) {
22342
+ const candidates = options.base ? [`origin/${options.base}`, options.base] : [];
22343
+ const base = candidates.find((ref) => resolveRef(cwd, ref) !== null) ?? defaultBase(cwd) ?? null;
22344
+ const head = options.workingTree ? null : options.head;
22345
+ const fork = base && (options.workingTree || options.head) ? forkOf(cwd, base, head) : null;
22346
+ const files = fork ? laneFiles(cwd, fork, head) : null;
22347
+ const riskTier = options.judgment?.riskTier ?? null;
22348
+ if (!fork || !files) {
22349
+ const high = riskTier === "high";
22350
+ return {
22351
+ lane: high ? "full" : "focused",
22352
+ reasons: [
22353
+ `the diff of ${options.head?.slice(0, 12) ?? "(no head)"} against ${base ?? "(no base)"} cannot be read`,
22354
+ ...high ? ["the task judgment records high risk"] : []
22355
+ ],
22356
+ lines: 0,
22357
+ files: 0,
22358
+ riskFiles: [],
22359
+ base,
22360
+ head: options.head
22361
+ };
22362
+ }
22363
+ const repoRisk = parseRiskPaths(fileAt(cwd, fork, RISK_PATHS_FILE) ?? "");
22364
+ return {
22365
+ ...computeLane({
22366
+ files,
22367
+ riskTier,
22368
+ riskPaths: [...repoRisk, ...options.riskPaths ?? []]
22369
+ }),
22370
+ base,
22371
+ head: options.head
22372
+ };
22373
+ }
22374
+ var laneNeed = (lane) => lane === "none" ? "none" : lane === "self" ? "self" : "non-author";
22375
+
22376
+ // packages/workit-core/src/core/policy/carry.ts
22377
+ var TEST_ONLY_KINDS = new Set(["doc", "cosmetic", "generated", "test"]);
22378
+ function verdictDrift(cwd, input) {
22379
+ const since = input.from;
22380
+ const stale = (reason, files = null, focused = false) => ({
22381
+ carries: false,
22382
+ since,
22383
+ files,
22384
+ focused,
22385
+ reason
22386
+ });
22387
+ const fromFork = mergeBase(cwd, input.fromBase, input.from);
22388
+ const toFork = mergeBase(cwd, input.toBase, input.to);
22389
+ const files = fromFork && toFork ? driftFiles(cwd, { from: input.from, to: input.to, fromFork, toFork }) : null;
22390
+ if (!fromFork || !toFork || !files)
22391
+ return stale(`the change since ${since.slice(0, 12)} cannot be read`);
22392
+ const riskPaths = [fromFork, toFork].flatMap((fork) => parseRiskPaths(fileAt(cwd, fork, RISK_PATHS_FILE) ?? ""));
22393
+ const lane = computeLane({ files, riskPaths });
22394
+ const paths = files.map((file) => file.path);
22395
+ if (lane.lane === "none")
22396
+ return { carries: true, rule: "lane-none", since, files: paths };
22397
+ if (input.kind === "unit" && lane.lane === "self" && files.every((file) => TEST_ONLY_KINDS.has(kindOf(file))))
22398
+ return { carries: true, rule: "tests-only", since, files: paths };
22399
+ return stale(lane.reasons[0] ?? `lane ${lane.lane}`, paths, lane.lane === "self");
22400
+ }
22401
+
22402
+ // packages/workit-core/src/ledger.ts
21522
22403
  var LEDGER_VERSION = 1;
21523
22404
  var MAX_LINE_BYTES = 4096;
21524
22405
  var PASSING = new Set(["verified", "tests-verified", "type-check-only"]);
@@ -21563,52 +22444,19 @@ var git4 = (cwd, args) => {
21563
22444
  const value = run.ok ? run.stdout.trim() : "";
21564
22445
  return value ? value : null;
21565
22446
  };
21566
- var safeRef = (value) => value.length > 0 && !value.startsWith("-");
22447
+ var safeRef2 = (value) => value.length > 0 && !value.startsWith("-");
21567
22448
  function resolveCommit(cwd, ref) {
21568
- if (!safeRef(ref))
22449
+ if (!safeRef2(ref))
21569
22450
  return null;
21570
22451
  return git4(cwd, ["rev-parse", "--verify", "-q", `${ref}^{commit}`]);
21571
22452
  }
21572
22453
  function branchHead(cwd, branch) {
21573
- if (!safeRef(branch))
22454
+ if (!safeRef2(branch))
21574
22455
  return null;
21575
22456
  return resolveCommit(cwd, `refs/heads/${branch}`) ?? resolveCommit(cwd, `refs/remotes/origin/${branch}`);
21576
22457
  }
21577
- var trackTrunk = (cwd) => {
21578
- try {
21579
- const resolved = vcsConfig("resolve", cwd);
21580
- if (resolved.ok === false || !resolved.releaseTrack || resolved.releaseTrack.blocking)
21581
- return null;
21582
- const target = String(resolved.defaultTargetBranch ?? "").trim();
21583
- return target && safeRef(target) ? target : null;
21584
- } catch {
21585
- return null;
21586
- }
21587
- };
21588
- function defaultBase(cwd) {
21589
- const trunk = trackTrunk(cwd);
21590
- if (trunk) {
21591
- for (const candidate of [`origin/${trunk}`, trunk])
21592
- if (resolveCommit(cwd, candidate))
21593
- return candidate;
21594
- }
21595
- const originHead = git4(cwd, ["symbolic-ref", "-q", "--short", "refs/remotes/origin/HEAD"]);
21596
- if (originHead && resolveCommit(cwd, originHead))
21597
- return originHead;
21598
- for (const candidate of [
21599
- "origin/main",
21600
- "origin/master",
21601
- "main",
21602
- "master",
21603
- "origin/develop",
21604
- "develop"
21605
- ])
21606
- if (resolveCommit(cwd, candidate))
21607
- return candidate;
21608
- return null;
21609
- }
21610
22458
  function diffHash(cwd, base, head) {
21611
- if (!safeRef(base) || !safeRef(head))
22459
+ if (!safeRef2(base) || !safeRef2(head))
21612
22460
  return null;
21613
22461
  const diff = gitRun2(cwd, [
21614
22462
  "diff",
@@ -21640,14 +22488,14 @@ function diffHash(cwd, base, head) {
21640
22488
  return `sha256:${hash.digest("hex")}`;
21641
22489
  }
21642
22490
  function storeRoot(cwd) {
21643
- const location = resolveStore(path14.resolve(cwd));
22491
+ const location = resolveStore(path15.resolve(cwd));
21644
22492
  if (location instanceof Error)
21645
22493
  return err("unavailable", location.message.replace(/; fix the repository.*$/u, ""), "fix the repository (git status should work here) or run from a non-git directory");
21646
22494
  return { ok: true, value: { root: location.dir, shared: location.shared } };
21647
22495
  }
21648
22496
  function ledgerPath(cwd) {
21649
22497
  const root = storeRoot(cwd);
21650
- return root.ok ? { ok: true, value: path14.join(root.value.root, "ledger", "ledger.jsonl") } : root;
22498
+ return root.ok ? { ok: true, value: path15.join(root.value.root, "ledger", "ledger.jsonl") } : root;
21651
22499
  }
21652
22500
  var newId2 = () => `${Date.now().toString(36)}-${randomBytes3(6).toString("hex")}`;
21653
22501
  var NETWORK_FS_TYPES = new Set([
@@ -21677,13 +22525,13 @@ var LOCK_STALE_MS = 30000;
21677
22525
  var LOCK_OWNER = "owner";
21678
22526
  var lockToken = (lock) => {
21679
22527
  try {
21680
- return fs12.readFileSync(path14.join(lock, LOCK_OWNER), "utf8");
22528
+ return fs12.readFileSync(path15.join(lock, LOCK_OWNER), "utf8");
21681
22529
  } catch {
21682
22530
  return null;
21683
22531
  }
21684
22532
  };
21685
22533
  var lockAgeMs = (lock) => {
21686
- for (const target of [path14.join(lock, LOCK_OWNER), lock]) {
22534
+ for (const target of [path15.join(lock, LOCK_OWNER), lock]) {
21687
22535
  try {
21688
22536
  return Date.now() - fs12.statSync(target).mtimeMs;
21689
22537
  } catch {}
@@ -21700,7 +22548,7 @@ var ledgerLock = {
21700
22548
  throw error;
21701
22549
  }
21702
22550
  const token = `${process.pid}-${randomBytes3(8).toString("hex")}`;
21703
- fs12.writeFileSync(path14.join(lock, LOCK_OWNER), token);
22551
+ fs12.writeFileSync(path15.join(lock, LOCK_OWNER), token);
21704
22552
  return token;
21705
22553
  },
21706
22554
  release(lock, token) {
@@ -21833,8 +22681,8 @@ function appendLine(file, build, options) {
21833
22681
  }
21834
22682
  };
21835
22683
  try {
21836
- fs12.mkdirSync(path14.dirname(file), { recursive: true });
21837
- if (!options.forceLock && !onNetworkFs(path14.dirname(file)))
22684
+ fs12.mkdirSync(path15.dirname(file), { recursive: true });
22685
+ if (!options.forceLock && !onNetworkFs(path15.dirname(file)))
21838
22686
  return write();
21839
22687
  const locked = withLedgerLock(file, write);
21840
22688
  return locked ?? err("busy", `ledger lock ${file}.lock is held`, "retry; remove the .lock directory if no workit process is running");
@@ -22065,7 +22913,7 @@ function verdictBasis(verdict, current) {
22065
22913
  }
22066
22914
  var isLiveVerdict = (row, retired) => row.type === "verdict" && typeof row.result === "string" && !retired.has(row.id);
22067
22915
  function trailerSessions(cwd, base, head) {
22068
- if (!base || !head || !safeRef(base) || !safeRef(head))
22916
+ if (!base || !head || !safeRef2(base) || !safeRef2(head))
22069
22917
  return [];
22070
22918
  const out = git4(cwd, [
22071
22919
  "log",
@@ -22078,7 +22926,7 @@ var RENAMED = /^branch: renamed refs\/heads\/(.+) to refs\/heads\/(.+)$/iu;
22078
22926
  function branchScope(cwd, branch) {
22079
22927
  const renamedAt = new Map;
22080
22928
  let since = Number.NEGATIVE_INFINITY;
22081
- if (safeRef(branch)) {
22929
+ if (safeRef2(branch)) {
22082
22930
  const log = git4(cwd, [
22083
22931
  "log",
22084
22932
  "-g",
@@ -22223,12 +23071,29 @@ function effectiveOf(rows, reasonsOf, sameCode, isCurrent) {
22223
23071
  }
22224
23072
  return effective;
22225
23073
  }
22226
- function restackCarries(rows, branch, from, to) {
23074
+ var restackExact = new WeakMap;
23075
+ function restackCarries(exactIn, rows, branch, from, to) {
22227
23076
  if (!from || !to)
22228
23077
  return false;
23078
+ const exact = (row, fromHead, head) => {
23079
+ if (exactIn === null)
23080
+ return true;
23081
+ const cwd = exactIn;
23082
+ let known = restackExact.get(row);
23083
+ if (known === undefined) {
23084
+ known = typeof row.fromBase === "string" && typeof row.toBase === "string" && sameOwnChange(cwd, {
23085
+ from: fromHead,
23086
+ to: head,
23087
+ fromBase: row.fromBase,
23088
+ toBase: row.toBase
23089
+ });
23090
+ restackExact.set(row, known);
23091
+ }
23092
+ return known;
23093
+ };
22229
23094
  const edges = new Map;
22230
23095
  for (const row of rows)
22231
- if (row.type === "stack.restacked" && row.observer === "workit_cli" && row.integrity === "verified" && row.branch === branch && row.patchEqual === true && typeof row.fromHead === "string" && row.head)
23096
+ if (row.type === "stack.restacked" && row.observer === "workit_cli" && row.integrity === "verified" && row.branch === branch && row.patchEqual === true && typeof row.fromHead === "string" && row.head && exact(row, row.fromHead, row.head))
22232
23097
  edges.set(row.fromHead, [...edges.get(row.fromHead) ?? [], row.head]);
22233
23098
  const seen = new Set([from]);
22234
23099
  const queue = [from];
@@ -22262,9 +23127,57 @@ function checkVerdicts(cwd, branch, ledgerRows) {
22262
23127
  return key;
22263
23128
  };
22264
23129
  const keyFor = (base) => keysAt(base, head);
22265
- const basisOf = (row) => {
23130
+ const driftCache = new Map;
23131
+ const driftOf = (row) => {
23132
+ if (driftCache.has(row))
23133
+ return driftCache.get(row) ?? null;
23134
+ let drift = null;
23135
+ const toBase = row.base ?? fallbackBase;
23136
+ const toBaseSha = toBase ? resolveCommit(cwd, toBase) : null;
23137
+ const fromBase = row.baseSha ?? toBaseSha;
23138
+ if (row.head && head && row.head !== head && toBaseSha && fromBase && !untrusted(reasonsOf(row)))
23139
+ drift = verdictDrift(cwd, {
23140
+ from: row.head,
23141
+ to: head,
23142
+ fromBase,
23143
+ toBase: toBaseSha,
23144
+ kind: typeof row.kind === "string" ? row.kind : "review"
23145
+ });
23146
+ driftCache.set(row, drift);
23147
+ return drift;
23148
+ };
23149
+ const exactCache = new Map;
23150
+ const exactCarry = (row) => {
23151
+ if (FAILING.has(String(row.result)))
23152
+ return true;
23153
+ let exact = exactCache.get(row);
23154
+ if (exact === undefined) {
23155
+ const toBase = row.base ?? fallbackBase;
23156
+ const toBaseSha = toBase ? resolveCommit(cwd, toBase) : null;
23157
+ const fromBase = row.baseSha ?? toBaseSha;
23158
+ exact = Boolean(row.head && head && toBaseSha && fromBase && sameOwnChange(cwd, { from: row.head, to: head, fromBase, toBase: toBaseSha }));
23159
+ exactCache.set(row, exact);
23160
+ }
23161
+ return exact;
23162
+ };
23163
+ const keyBasis = (row) => {
22266
23164
  const basis = verdictBasis(row, { head, ...keyFor(row.base ?? fallbackBase) });
22267
- return basis === "stale" && restackCarries(rows, branch, row.head, head) ? "carried" : basis;
23165
+ return basis === "carried" && !exactCarry(row) ? "stale" : basis;
23166
+ };
23167
+ const restacked = (row) => restackCarries(FAILING.has(String(row.result)) ? null : cwd, rows, branch, row.head, head);
23168
+ const carryOf = (row) => {
23169
+ if (keyBasis(row) !== "stale")
23170
+ return null;
23171
+ if (restacked(row))
23172
+ return null;
23173
+ const drift = driftOf(row);
23174
+ return drift?.carries ? { rule: drift.rule, since: drift.since, files: drift.files } : null;
23175
+ };
23176
+ const basisOf = (row) => {
23177
+ const basis = keyBasis(row);
23178
+ if (basis !== "stale")
23179
+ return basis;
23180
+ return restacked(row) || carryOf(row) ? "carried" : basis;
22268
23181
  };
22269
23182
  const sameCode = (failed, row) => {
22270
23183
  if (failed.head && failed.head === row.head)
@@ -22272,7 +23185,7 @@ function checkVerdicts(cwd, branch, ledgerRows) {
22272
23185
  const base = failed.base ?? fallbackBase;
22273
23186
  const stored = (row.base ?? fallbackBase) === base && row.baseSha !== null && row.baseSha === failed.baseSha;
22274
23187
  const keys = stored ? { patchId: row.patchId, diffHash: row.diffHash } : keysAt(base, row.head);
22275
- return verdictBasis(failed, { head: row.head, ...keys }) !== "stale" || restackCarries(rows, branch, failed.head, row.head);
23188
+ return verdictBasis(failed, { head: row.head, ...keys }) !== "stale" || restackCarries(null, rows, branch, failed.head, row.head);
22276
23189
  };
22277
23190
  const authors = authorSessions(cwd, rows, branch, { base: fallbackBase, head }, scope);
22278
23191
  const failureAuthorCache = new Map;
@@ -22328,6 +23241,7 @@ function checkVerdicts(cwd, branch, ledgerRows) {
22328
23241
  independent: independence.length === 0,
22329
23242
  accepted: reasons.length === 0,
22330
23243
  reasons,
23244
+ carry: basis === "carried" ? carryOf(row) : null,
22331
23245
  verdict: row
22332
23246
  });
22333
23247
  if (reasons.length === 0) {
@@ -22356,7 +23270,12 @@ function checkVerdicts(cwd, branch, ledgerRows) {
22356
23270
  verdict: failing?.verdict ?? null,
22357
23271
  reasons: failing ? ["failing_verdict"] : !newestCurrent ? ["no_verdict"] : newestCurrent.reasons.length ? newestCurrent.reasons : ["type_check_only"]
22358
23272
  };
22359
- const selfEntry = failing ? undefined : verdicts.findLast((entry) => entry.current && !entry.independent && !untrusted(entry.reasons) && STRONG_RESULTS.has(String(entry.verdict.result)));
23273
+ 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))));
23274
+ const selfEntry = latestSelf && STRONG_RESULTS.has(String(latestSelf.verdict.result)) ? latestSelf : undefined;
23275
+ const carryEntry = verdicts.find((entry) => entry.verdict === accepted.verdict && entry.accepted) ?? newestCurrent;
23276
+ const lastPass = accepted.accepted || failing || tampered.length ? undefined : verdicts.findLast((entry) => !entry.current && !untrusted(entry.reasons) && STRONG_RESULTS.has(String(entry.verdict.result)));
23277
+ const drift = lastPass ? driftOf(lastPass.verdict) : null;
23278
+ const reverify = drift && !drift.carries && drift.focused && drift.files ? { scope: "focused", since: drift.since, files: drift.files } : null;
22360
23279
  return {
22361
23280
  branch,
22362
23281
  head,
@@ -22365,6 +23284,8 @@ function checkVerdicts(cwd, branch, ledgerRows) {
22365
23284
  base: newestCurrent?.verdict.base ?? fallbackBase,
22366
23285
  patchId: keyFor(newestCurrent?.verdict.base ?? fallbackBase).patchId,
22367
23286
  current: { basis: newestCurrent?.basis ?? "none", verdict: newestCurrent?.verdict ?? null },
23287
+ carry: carryEntry?.carry ?? null,
23288
+ reverify,
22368
23289
  accepted,
22369
23290
  verdicts,
22370
23291
  authors: [...authors].toSorted(),
@@ -22384,6 +23305,7 @@ var RULES = {
22384
23305
  self: "verdict:self",
22385
23306
  nonAuthor: "verdict:non-author",
22386
23307
  verified: "verdict:verified",
23308
+ lane: "verdict:lane",
22387
23309
  product: "decision:product",
22388
23310
  plan: "plan"
22389
23311
  };
@@ -22406,6 +23328,7 @@ var normalizedScope = (scope) => ({
22406
23328
  function deriveRequirements(judgment, scope, constraints, verification = "self") {
22407
23329
  const out = [];
22408
23330
  const base = { scope, dependentAction: null };
23331
+ const proportional = verification === "proportional";
22409
23332
  if (judgment.behaviorChange)
22410
23333
  out.push(derived2({
22411
23334
  ...base,
@@ -22416,7 +23339,17 @@ function deriveRequirements(judgment, scope, constraints, verification = "self")
22416
23339
  before: "close",
22417
23340
  acceptanceAllowed: false
22418
23341
  }));
22419
- if (judgment.behaviorChange && judgment.riskTier === "normal")
23342
+ if (proportional && judgment.riskTier === "normal")
23343
+ out.push(derived2({
23344
+ ...base,
23345
+ ruleId: RULES.lane,
23346
+ dimension: "review",
23347
+ 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.",
23348
+ 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.",
23349
+ before: "close",
23350
+ acceptanceAllowed: false
23351
+ }));
23352
+ if (!proportional && judgment.behaviorChange && judgment.riskTier === "normal")
22420
23353
  out.push(verification === "independent" ? derived2({
22421
23354
  ...base,
22422
23355
  ruleId: RULES.nonAuthor,
@@ -22519,7 +23452,7 @@ var productDecision = (task, ledger) => {
22519
23452
  };
22520
23453
  };
22521
23454
  var planRecorded = (task, root) => {
22522
- const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(path15.resolve(root, ref.path)));
23455
+ const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync5(path16.resolve(root, ref.path)));
22523
23456
  if (cited)
22524
23457
  return {
22525
23458
  met: true,
@@ -22533,14 +23466,30 @@ var planRecorded = (task, root) => {
22533
23466
  decisionIds: []
22534
23467
  };
22535
23468
  };
22536
- var verdict = (requirement, root, ledger) => {
23469
+ var workingLane = (task, root) => branchLane(root, { head: null, workingTree: true, judgment: latestJudgment(task) });
23470
+ var laneVerdict = (task, root, ledger) => {
23471
+ if (!ledger.branch() && latestJudgment(task)?.behaviorChange === false)
23472
+ return {
23473
+ met: true,
23474
+ reason: "no branch to read a lane from, and the judgment records no behavior change",
23475
+ decisionIds: []
23476
+ };
23477
+ const lane = workingLane(task, root);
23478
+ const label = `lane ${lane.lane} (${lane.reasons.join("; ")})`;
23479
+ const need = laneNeed(lane.lane);
23480
+ if (need === "none")
23481
+ return { met: true, reason: `${label}: no verdict needed`, decisionIds: [] };
23482
+ const status = verdict(need === "self" ? RULES.self : RULES.nonAuthor, root, ledger);
23483
+ return { ...status, reason: `${label}: ${status.reason}` };
23484
+ };
23485
+ var verdict = (ruleId, root, ledger) => {
22537
23486
  const branch = ledger.branch();
22538
23487
  if (!branch)
22539
23488
  return { met: false, reason: "no branch is checked out to hold a verdict", decisionIds: [] };
22540
23489
  const check = checkVerdicts(root, branch, ledger.rows());
22541
23490
  const failing = check.accepted.reasons.includes("failing_verdict");
22542
23491
  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)));
23492
+ 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
23493
  if (met)
22545
23494
  return {
22546
23495
  met: true,
@@ -22548,7 +23497,7 @@ var verdict = (requirement, root, ledger) => {
22548
23497
  decisionIds: []
22549
23498
  };
22550
23499
  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>\``;
23500
+ 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
23501
  return { met: false, reason: `${why}: ${unblock}`, decisionIds: [] };
22553
23502
  };
22554
23503
  function derivedRuleStatus(task, requirement, root, ledger) {
@@ -22560,7 +23509,9 @@ function derivedRuleStatus(task, requirement, root, ledger) {
22560
23509
  case RULES.self:
22561
23510
  case RULES.nonAuthor:
22562
23511
  case RULES.verified:
22563
- return verdict(requirement, root, ledger);
23512
+ return verdict(requirement.ruleId, root, ledger);
23513
+ case RULES.lane:
23514
+ return laneVerdict(task, root, ledger);
22564
23515
  default:
22565
23516
  return null;
22566
23517
  }
@@ -22568,14 +23519,14 @@ function derivedRuleStatus(task, requirement, root, ledger) {
22568
23519
 
22569
23520
  // packages/workit-core/src/core/task-evaluation.ts
22570
23521
  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("/") || ".";
23522
+ var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path17.sep}`);
23523
+ var relative = (root, candidate) => path17.relative(root, candidate).split(path17.sep).join("/") || ".";
22573
23524
  var canonicalPath = (value) => {
22574
23525
  if (typeof value !== "string" || !value)
22575
23526
  return null;
22576
23527
  if (value.includes("\\") || value.split("/").includes(".."))
22577
23528
  return null;
22578
- const normalized = path16.posix.normalize(value);
23529
+ const normalized = path17.posix.normalize(value);
22579
23530
  if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
22580
23531
  return null;
22581
23532
  return normalized === "." ? "." : normalized.replace(/\/$/, "");
@@ -22623,14 +23574,14 @@ var gitPaths = (root) => {
22623
23574
  git: !/not a git repository/i.test(stderr)
22624
23575
  };
22625
23576
  }
22626
- const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path16.sep).join("/")) : [];
23577
+ const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path17.sep).join("/")) : [];
22627
23578
  const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
22628
23579
  if (stagedDeleted.status !== 0) {
22629
23580
  const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
22630
23581
  if (!/not a git repository/i.test(stderr))
22631
23582
  return { paths, uncertain: true, git: true };
22632
23583
  } else if (stagedDeleted.stdout) {
22633
- paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path16.sep).join("/")));
23584
+ paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path17.sep).join("/")));
22634
23585
  }
22635
23586
  return { paths: [...new Set(paths)], uncertain: false, git: true };
22636
23587
  };
@@ -22645,7 +23596,7 @@ var walk = (root, directory, output) => {
22645
23596
  for (const name of names) {
22646
23597
  if (name === ".git" || name === ".workit")
22647
23598
  continue;
22648
- const target = path16.join(directory, name);
23599
+ const target = path17.join(directory, name);
22649
23600
  let stat;
22650
23601
  try {
22651
23602
  stat = fs13.lstatSync(target);
@@ -22663,12 +23614,12 @@ var walk = (root, directory, output) => {
22663
23614
  var scopeRoots = (root, scope) => {
22664
23615
  const roots = [];
22665
23616
  for (const item of scope.paths.length ? scope.paths : ["."]) {
22666
- const target = path16.resolve(root, item);
23617
+ const target = path17.resolve(root, item);
22667
23618
  if (!inside(root, target))
22668
23619
  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
23620
  let ancestor = target;
22670
23621
  while (!fs13.existsSync(ancestor) && ancestor !== root)
22671
- ancestor = path16.dirname(ancestor);
23622
+ ancestor = path17.dirname(ancestor);
22672
23623
  try {
22673
23624
  if (!inside(root, fs13.realpathSync(ancestor)))
22674
23625
  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` }] });
@@ -22720,7 +23671,7 @@ function captureCandidate(root, scope, environment = []) {
22720
23671
  for (const item of [...names].toSorted()) {
22721
23672
  if (!scopeMatches(item, normalizedScope))
22722
23673
  continue;
22723
- const target = path16.join(checkout, item);
23674
+ const target = path17.join(checkout, item);
22724
23675
  try {
22725
23676
  const stat = fs13.lstatSync(target);
22726
23677
  if (stat.isSymbolicLink()) {
@@ -22904,23 +23855,23 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
22904
23855
  continue;
22905
23856
  if (!reference.digest)
22906
23857
  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}`))
23858
+ const target = path17.resolve(root, reference.path);
23859
+ if (target !== root && !target.startsWith(`${root}${path17.sep}`))
22909
23860
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
22910
23861
  fields: [
22911
23862
  { path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
22912
23863
  ]
22913
23864
  });
22914
23865
  try {
22915
- const below = path16.relative(root, target);
23866
+ const below = path17.relative(root, target);
22916
23867
  let current = root;
22917
- for (const segment of below.split(path16.sep)) {
23868
+ for (const segment of below.split(path17.sep)) {
22918
23869
  if (!segment)
22919
23870
  continue;
22920
- current = path16.join(current, segment);
23871
+ current = path17.join(current, segment);
22921
23872
  const stat = fs13.lstatSync(current);
22922
23873
  const real = fs13.realpathSync(current);
22923
- if (real !== root && !real.startsWith(`${root}${path16.sep}`))
23874
+ if (real !== root && !real.startsWith(`${root}${path17.sep}`))
22924
23875
  return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
22925
23876
  fields: [
22926
23877
  {
@@ -23779,7 +24730,7 @@ var judgeInputSummary = (raw) => {
23779
24730
 
23780
24731
  // packages/workit-core/src/autonomy.ts
23781
24732
  import os4 from "node:os";
23782
- import path17 from "node:path";
24733
+ import path18 from "node:path";
23783
24734
  var accountHome = () => {
23784
24735
  try {
23785
24736
  return os4.userInfo().homedir;
@@ -23788,10 +24739,10 @@ var accountHome = () => {
23788
24739
  }
23789
24740
  };
23790
24741
  var grantsHome = { resolve: accountHome };
23791
- var grantsDir = () => path17.join(grantsHome.resolve(), ".config", "workit");
24742
+ var grantsDir = () => path18.join(grantsHome.resolve(), ".config", "workit");
23792
24743
  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`;
24744
+ const configured = path18.resolve(resolveConfigDir());
24745
+ return configured === path18.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 ${path18.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
23795
24746
  };
23796
24747
  var GRANT_KINDS = ["push", "pr", "merge", "release", "rerun"];
23797
24748
  var DEFAULT_GRANTS = Object.freeze({
@@ -23844,8 +24795,16 @@ function endpointView(entry, context) {
23844
24795
  ...issue ? { endpointIssue: issue } : {}
23845
24796
  };
23846
24797
  }
23847
- var DEFAULT_VERIFICATION = "self";
23848
- var verificationOf = (entry) => entry?.verification === "independent" ? "independent" : "self";
24798
+ var VERIFICATION_MODES = [
24799
+ "proportional",
24800
+ "self",
24801
+ "independent"
24802
+ ];
24803
+ var DEFAULT_VERIFICATION = "proportional";
24804
+ var verificationOf = (entry) => {
24805
+ const value = entry?.verification;
24806
+ return VERIFICATION_MODES.includes(value) ? value : DEFAULT_VERIFICATION;
24807
+ };
23849
24808
  var isGrantValue = (value) => value === true || value === false || value === "verified";
23850
24809
  var normalized = (kind, value) => value === "verified" && kind !== "merge" ? true : value;
23851
24810
  var fromAutoApprove = (value) => {
@@ -25593,8 +26552,8 @@ class WorkitCore {
25593
26552
  }
25594
26553
  // packages/workit-core/src/core/repo-context.ts
25595
26554
  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";
26555
+ import { existsSync as existsSync7, readFileSync as readFileSync6, readdirSync as readdirSync4 } from "node:fs";
26556
+ import path19 from "node:path";
25598
26557
  var isSafeContextRange = (value) => value.length <= 4096 && (() => {
25599
26558
  try {
25600
26559
  gitRevisionParts(value);
@@ -25728,7 +26687,7 @@ var findPrTemplate = (cwd) => {
25728
26687
  ]) {
25729
26688
  const parts = rel.split("/");
25730
26689
  const base = parts[parts.length - 1];
25731
- const dir = parts.length > 1 ? path18.join(cwd, ...parts.slice(0, -1)) : cwd;
26690
+ const dir = parts.length > 1 ? path19.join(cwd, ...parts.slice(0, -1)) : cwd;
25732
26691
  const actual = probeCaseInsensitive(dir, base);
25733
26692
  if (actual)
25734
26693
  return [...parts.slice(0, -1), actual].join("/");
@@ -25759,11 +26718,11 @@ var diffStatForRange = (cwd, range) => {
25759
26718
  return runGit(cwd, ["diff", "--stat", "--"]).stdout;
25760
26719
  };
25761
26720
  var packageScripts = (cwd, keys) => {
25762
- const pkgPath = path18.join(cwd, "package.json");
25763
- if (!existsSync6(pkgPath))
26721
+ const pkgPath = path19.join(cwd, "package.json");
26722
+ if (!existsSync7(pkgPath))
25764
26723
  return [];
25765
26724
  try {
25766
- const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
26725
+ const pkg = JSON.parse(readFileSync6(pkgPath, "utf8"));
25767
26726
  return keys.filter((k) => pkg.scripts && typeof pkg.scripts[k] === "string").map((k) => `${k}: ${pkg.scripts?.[k]}`);
25768
26727
  } catch {
25769
26728
  return [];
@@ -25785,9 +26744,9 @@ var documentationFiles = (cwd) => {
25785
26744
  if (entry.isDirectory()) {
25786
26745
  if (excluded.has(entry.name))
25787
26746
  continue;
25788
- walk(path18.join(dir, entry.name), depth + 1);
26747
+ walk(path19.join(dir, entry.name), depth + 1);
25789
26748
  } else if (entry.isFile() && (entry.name === "README.md" || entry.name.endsWith(".md"))) {
25790
- matches.push("./" + path18.relative(cwd, path18.join(dir, entry.name)).replaceAll("\\", "/"));
26749
+ matches.push("./" + path19.relative(cwd, path19.join(dir, entry.name)).replaceAll("\\", "/"));
25791
26750
  }
25792
26751
  }
25793
26752
  };
@@ -25795,15 +26754,15 @@ var documentationFiles = (cwd) => {
25795
26754
  return matches.toSorted().slice(0, 200);
25796
26755
  };
25797
26756
  var readTrimmed2 = (file, maxLines) => {
25798
- if (!existsSync6(file))
26757
+ if (!existsSync7(file))
25799
26758
  return "";
25800
- const lines = readFileSync5(file, "utf8").split(`
26759
+ const lines = readFileSync6(file, "utf8").split(`
25801
26760
  `);
25802
26761
  return lines.slice(0, maxLines).join(`
25803
26762
  `);
25804
26763
  };
25805
26764
  function prReadyContext(root, range) {
25806
- const cwd = path18.resolve(repoRoot(root));
26765
+ const cwd = path19.resolve(repoRoot(root));
25807
26766
  if (range !== undefined && !isResolvableContextRange(cwd, range))
25808
26767
  return invalidRange(cwd);
25809
26768
  let stdout = "";
@@ -25861,7 +26820,7 @@ ${status.stderr}` : "");
25861
26820
  stdout += `template_path: ${template}
25862
26821
 
25863
26822
  `;
25864
- stdout += readTrimmed2(path18.join(cwd, template), 220);
26823
+ stdout += readTrimmed2(path19.join(cwd, template), 220);
25865
26824
  } else {
25866
26825
  stdout += `template_path: none
25867
26826
 
@@ -25871,7 +26830,7 @@ ${status.stderr}` : "");
25871
26830
  stdout += `
25872
26831
  `;
25873
26832
  stdout += printSection("Recent Validation Signals");
25874
- if (existsSync6(path18.join(cwd, "package.json"))) {
26833
+ if (existsSync7(path19.join(cwd, "package.json"))) {
25875
26834
  stdout += `package.json detected. Common scripts:
25876
26835
  `;
25877
26836
  const found = packageScripts(cwd, ["lint", "format:check", "test", "build"]);
@@ -25880,7 +26839,7 @@ ${status.stderr}` : "");
25880
26839
  `) + `
25881
26840
  `;
25882
26841
  }
25883
- if (existsSync6(path18.join(cwd, "Cargo.toml")) || existsSync6(path18.join(cwd, "src-tauri/Cargo.toml"))) {
26842
+ if (existsSync7(path19.join(cwd, "Cargo.toml")) || existsSync7(path19.join(cwd, "src-tauri/Cargo.toml"))) {
25884
26843
  stdout += `Rust project detected.
25885
26844
  `;
25886
26845
  }
@@ -25913,7 +26872,7 @@ var CHANGELOG_RULES = `- Use an [Unreleased] section.
25913
26872
  - Apply with the host-native editor, preserving the repository changelog conventions.
25914
26873
  - If Unreleased already has duplicate category headings, normalize_only first.`;
25915
26874
  function changelogContext(root, range) {
25916
- const cwd = path18.resolve(repoRoot(root));
26875
+ const cwd = path19.resolve(repoRoot(root));
25917
26876
  if (range !== undefined && !isResolvableContextRange(cwd, range))
25918
26877
  return invalidRange(cwd);
25919
26878
  const resolvedRange = rangeArgOrDefault(range, cwd);
@@ -25931,8 +26890,8 @@ function changelogContext(root, range) {
25931
26890
  stdout += CHANGELOG_RULES + `
25932
26891
  `;
25933
26892
  stdout += printSection("Existing CHANGELOG.md");
25934
- const changelogPath = path18.join(cwd, "CHANGELOG.md");
25935
- if (existsSync6(changelogPath)) {
26893
+ const changelogPath = path19.join(cwd, "CHANGELOG.md");
26894
+ if (existsSync7(changelogPath)) {
25936
26895
  stdout += readTrimmed2(changelogPath, 260) + `
25937
26896
  `;
25938
26897
  } else {
@@ -25951,7 +26910,7 @@ function changelogContext(root, range) {
25951
26910
  return { stdout, stderr: "", exitCode: 0, cwd };
25952
26911
  }
25953
26912
  function docsRefreshContext(root, range) {
25954
- const cwd = path18.resolve(repoRoot(root));
26913
+ const cwd = path19.resolve(repoRoot(root));
25955
26914
  if (range !== undefined && !isResolvableContextRange(cwd, range))
25956
26915
  return invalidRange(cwd);
25957
26916
  const resolvedRange = rangeArgOrDefault(range, cwd);
@@ -25973,8 +26932,8 @@ function docsRefreshContext(root, range) {
25973
26932
  `) + `
25974
26933
  `;
25975
26934
  stdout += printSection("README Preview");
25976
- const readme = path18.join(cwd, "README.md");
25977
- if (existsSync6(readme)) {
26935
+ const readme = path19.join(cwd, "README.md");
26936
+ if (existsSync7(readme)) {
25978
26937
  stdout += readTrimmed2(readme, 220) + `
25979
26938
  `;
25980
26939
  } else {
@@ -25982,10 +26941,10 @@ function docsRefreshContext(root, range) {
25982
26941
  `;
25983
26942
  }
25984
26943
  stdout += printSection("Package Scripts");
25985
- const pkgPath = path18.join(cwd, "package.json");
25986
- if (existsSync6(pkgPath)) {
26944
+ const pkgPath = path19.join(cwd, "package.json");
26945
+ if (existsSync7(pkgPath)) {
25987
26946
  try {
25988
- const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
26947
+ const pkg = JSON.parse(readFileSync6(pkgPath, "utf8"));
25989
26948
  stdout += JSON.stringify({ name: pkg.name, version: pkg.version, scripts: pkg.scripts }, null, 2) + `
25990
26949
  `;
25991
26950
  } catch {}
@@ -25996,7 +26955,7 @@ function docsRefreshContext(root, range) {
25996
26955
  return { stdout, stderr: "", exitCode: 0, cwd };
25997
26956
  }
25998
26957
  function releaseNotesContext(root, rangeOrTag) {
25999
- const cwd = path18.resolve(repoRoot(root));
26958
+ const cwd = path19.resolve(repoRoot(root));
26000
26959
  if (!rangeOrTag) {
26001
26960
  return { stdout: "", stderr: `ERROR: release tag or range required
26002
26961
  `, exitCode: 1, cwd };
@@ -26034,7 +26993,7 @@ function releaseNotesContext(root, rangeOrTag) {
26034
26993
  `;
26035
26994
  stdout += printSection("Existing Release Files");
26036
26995
  for (const rel of ["CHANGELOG.md", "RELEASE_NOTES.md", ".github/releases.md"]) {
26037
- if (existsSync6(path18.join(cwd, rel)))
26996
+ if (existsSync7(path19.join(cwd, rel)))
26038
26997
  stdout += rel + `
26039
26998
  `;
26040
26999
  }
@@ -26066,7 +27025,7 @@ import { spawnSync as spawnSync13 } from "node:child_process";
26066
27025
 
26067
27026
  // packages/workit-core/src/core/pr-create.ts
26068
27027
  import fs14 from "node:fs";
26069
- import path19 from "node:path";
27028
+ import path20 from "node:path";
26070
27029
  import { spawnSync as spawnSync12 } from "node:child_process";
26071
27030
  // packages/workit-core/src/forge/pr-body.ts
26072
27031
  function parseGhIssue(value) {
@@ -26077,11 +27036,11 @@ function parseGhIssue(value) {
26077
27036
  // packages/workit-core/src/core/pr-create.ts
26078
27037
  function whichOnPath(tool) {
26079
27038
  const names = process.platform === "win32" ? [tool, `${tool}.exe`, `${tool}.cmd`] : [tool];
26080
- for (const dir of (process.env.PATH ?? "").split(path19.delimiter)) {
27039
+ for (const dir of (process.env.PATH ?? "").split(path20.delimiter)) {
26081
27040
  if (!dir)
26082
27041
  continue;
26083
27042
  for (const name of names) {
26084
- const candidate = path19.join(dir, name);
27043
+ const candidate = path20.join(dir, name);
26085
27044
  try {
26086
27045
  fs14.accessSync(candidate, fs14.constants.X_OK);
26087
27046
  return candidate;
@@ -26202,7 +27161,7 @@ var fetchGitLabIssueBody = async (ref, root, deps = {}) => {
26202
27161
 
26203
27162
  // packages/workit-core/src/core/youtrack.ts
26204
27163
  import fs15 from "node:fs";
26205
- import path20 from "node:path";
27164
+ import path21 from "node:path";
26206
27165
 
26207
27166
  // packages/workit-core/src/core/templates.ts
26208
27167
  var repoRoot2 = assetRoot();
@@ -26215,8 +27174,8 @@ var resolveWorkspaceRoot = (explicit) => explicit || process.cwd();
26215
27174
  // packages/workit-core/src/core/youtrack.ts
26216
27175
  var ISSUE_RE = /^[A-Z]+-\d+$/;
26217
27176
  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");
27177
+ var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path21.join(configDir(), "youtrack.json");
27178
+ var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path21.join(resolveConfigDir(), "youtrack.json");
26220
27179
  var youTrackTokenModeOk = (p) => {
26221
27180
  if (process.platform === "win32")
26222
27181
  return true;
@@ -26284,7 +27243,7 @@ var youTrackToken = () => {
26284
27243
  if ("error" in loaded)
26285
27244
  return loaded;
26286
27245
  const tokenFile = String(loaded.config.tokenFile ?? "");
26287
- const tokenPath = tokenFile ? path20.isAbsolute(tokenFile) ? path20.resolve(tokenFile) : path20.resolve(process.cwd(), tokenFile) : "";
27246
+ const tokenPath = tokenFile ? path21.isAbsolute(tokenFile) ? path21.resolve(tokenFile) : path21.resolve(process.cwd(), tokenFile) : "";
26288
27247
  if (!tokenPath || !fs15.existsSync(tokenPath))
26289
27248
  return { error: "missing youtrack.token" };
26290
27249
  if (!youTrackTokenModeOk(tokenPath))
@@ -26626,15 +27585,15 @@ function resolveGitRevision(root, value) {
26626
27585
  }
26627
27586
  function resolveInside(root, candidate) {
26628
27587
  const base = realpathSync5(root);
26629
- const target = path21.resolve(base, candidate);
26630
- if (target !== base && !target.startsWith(base + path21.sep)) {
27588
+ const target = path22.resolve(base, candidate);
27589
+ if (target !== base && !target.startsWith(base + path22.sep)) {
26631
27590
  throw new Error("path must stay inside repository root");
26632
27591
  }
26633
27592
  let ancestor = target;
26634
- while (!existsSync7(ancestor))
26635
- ancestor = path21.dirname(ancestor);
27593
+ while (!existsSync8(ancestor))
27594
+ ancestor = path22.dirname(ancestor);
26636
27595
  const canonicalAncestor = realpathSync5(ancestor);
26637
- if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path21.sep)) {
27596
+ if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path22.sep)) {
26638
27597
  throw new Error("path must stay inside repository root");
26639
27598
  }
26640
27599
  return target;
@@ -26682,7 +27641,7 @@ var safeCapability = (value, allowed) => allowed.includes(value) ? value : "cont
26682
27641
  var TOOL_CAPABILITIES = [...CONTEXT_KINDS, "workspace", "native_caller_identity"];
26683
27642
  var VERSION = (() => {
26684
27643
  try {
26685
- const packageJson = JSON.parse(readFileSync6(new URL("../package.json", import.meta.url), "utf8"));
27644
+ const packageJson = JSON.parse(readFileSync7(new URL("../package.json", import.meta.url), "utf8"));
26686
27645
  return typeof packageJson.version === "string" ? packageJson.version : "0.0.0";
26687
27646
  } catch {
26688
27647
  return "0.0.0";
@@ -26692,13 +27651,13 @@ var rootVariants = (workspaceRoot) => {
26692
27651
  if (!workspaceRoot)
26693
27652
  return [];
26694
27653
  const roots = new Set;
26695
- for (const candidate of [workspaceRoot, path22.resolve(workspaceRoot)]) {
26696
- if (path22.isAbsolute(candidate) && candidate !== path22.parse(candidate).root)
27654
+ for (const candidate of [workspaceRoot, path23.resolve(workspaceRoot)]) {
27655
+ if (path23.isAbsolute(candidate) && candidate !== path23.parse(candidate).root)
26697
27656
  roots.add(candidate);
26698
27657
  }
26699
27658
  try {
26700
27659
  const canonical = realpathSync6(workspaceRoot);
26701
- if (canonical !== path22.parse(canonical).root)
27660
+ if (canonical !== path23.parse(canonical).root)
26702
27661
  roots.add(canonical);
26703
27662
  } catch {}
26704
27663
  return [...roots].toSorted((left, right) => right.length - left.length);
@@ -26780,12 +27739,12 @@ var thrownResult = (tool, error, workspaceRoot) => {
26780
27739
  };
26781
27740
  function createMcpServer(host, contextProvider) {
26782
27741
  assertMcpHost(host);
26783
- const here = path22.dirname(fileURLToPath2(import.meta.url));
27742
+ const here = path23.dirname(fileURLToPath2(import.meta.url));
26784
27743
  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)));
27744
+ path23.join(here, "server.ts"),
27745
+ path23.join(here, "..", "..", "workit-core", "src", "core", "task-contract.ts"),
27746
+ path23.join(here, "..", "..", "workit-core", "src", "core", "task-engine.ts")
27747
+ ].filter((file) => existsSync9(file)));
26789
27748
  let staleWarned = false;
26790
27749
  const server = new Server({ name: "workit", version: VERSION }, { capabilities: { tools: {}, resources: {} } });
26791
27750
  server.setRequestHandler(ListToolsRequestSchema, async () => {
@@ -26965,8 +27924,8 @@ var main = async () => {
26965
27924
  process.exitCode = 2;
26966
27925
  }
26967
27926
  };
26968
- var entryPath = process.argv[1] ? path23.resolve(process.argv[1]) : "";
26969
- if (entryPath === path23.resolve(fileURLToPath3(import.meta.url)))
27927
+ var entryPath = process.argv[1] ? path24.resolve(process.argv[1]) : "";
27928
+ if (entryPath === path24.resolve(fileURLToPath3(import.meta.url)))
26970
27929
  await main();
26971
27930
  // packages/workit-core/src/hooks/descriptor.ts
26972
27931
  var support = (descriptor, axis) => {
@@ -26996,6 +27955,25 @@ var capabilitiesFor = (descriptor, observed = {}) => descriptor.capabilities.map
26996
27955
  var signals = new Map;
26997
27956
  var cache = new Map;
26998
27957
  var TURN_TTL_MS = 7 * 24 * 60 * 60 * 1000;
27958
+ // packages/workit-core/src/hooks/delivery-verbs.ts
27959
+ var WORKIT_ALLOWED_VERBS = [
27960
+ "git",
27961
+ "pr",
27962
+ "ci",
27963
+ "stack",
27964
+ "release",
27965
+ "task",
27966
+ "ledger",
27967
+ "evidence",
27968
+ "finding",
27969
+ "decision",
27970
+ "worker",
27971
+ "verify-delivery",
27972
+ "policy",
27973
+ "doctor",
27974
+ "help"
27975
+ ];
27976
+ var ALLOWED = new Set(WORKIT_ALLOWED_VERBS);
26999
27977
  // packages/workit-core/src/core/heavy.ts
27000
27978
  var INFO_FLAGS = new Set(["--version", "-v", "-V", "--help", "-h", "help", "version"]);
27001
27979
  var sub = (...names) => new Set(names);
@@ -27120,7 +28098,7 @@ var EXEC = new Set(["exec", "x", "dlx"]);
27120
28098
  // packages/workit-core/src/core/heavy-words.ts
27121
28099
  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
28100
  // packages/workit-core/src/hooks/write-gate.ts
27123
- import path24 from "node:path";
28101
+ import path25 from "node:path";
27124
28102
 
27125
28103
  // packages/workit-core/src/core/live-session.ts
27126
28104
  import { spawnSync as spawnSync15 } from "node:child_process";
@@ -27161,7 +28139,7 @@ var MUTATING_WORKIT_GIT = new Set(["commit", "branch"]);
27161
28139
  var CD2 = new Set(["cd", "chdir", "set-location", "sl"]);
27162
28140
  var PUSHD2 = new Set(["pushd", "push-location"]);
27163
28141
  var POPD2 = new Set(["popd", "pop-location"]);
27164
- var UNKNOWN_DIR = path24.resolve(path24.parse(process.cwd()).root, ".workit-unknown-dir");
28142
+ var UNKNOWN_DIR = path25.resolve(path25.parse(process.cwd()).root, ".workit-unknown-dir");
27165
28143
  // packages/workit-core/src/core/skill-manifests.ts
27166
28144
  if (false) {}
27167
28145
 
@@ -27204,6 +28182,10 @@ var WRITE_TOOLS = new Set([
27204
28182
  // packages/workit-core/src/hooks/standing.ts
27205
28183
  var sinceStart = new Map;
27206
28184
  // packages/workit-core/src/hooks/cwd-normalize.ts
28185
+ var DIR = String.raw`[A-Za-z0-9_./@%+:,=-]+|'[^'$${"`"}\\\n]*'|"[^"$${"`"}\\!\n]*"`;
28186
+ var COMPOUND = new RegExp(String.raw`^\s*cd\s+(${DIR})\s*&&\s*(workit(?:\s[\s\S]*)?)$`, "u");
28187
+ var GLOBALS_FIRST = new RegExp(String.raw`^(\s*workit)((?:\s+(?:--json|--cwd(?:=|\s+)(?:${DIR})))+)\s+([a-z][a-z-]*)(?=\s|$)`, "u");
28188
+ var VERBS = new Set(WORKIT_ALLOWED_VERBS);
27207
28189
  var FILTERS = new Set(["tail", "head", "grep"]);
27208
28190
 
27209
28191
  // packages/workit-core/src/hooks/worktree-confine.ts
@@ -27387,7 +28369,7 @@ var cursorContextProvider = (workspaceRoot = process.env.WORKFLOW_WORKSPACE_ROOT
27387
28369
  var stampCursorSessionStart = (stateDir = resolveStateDir()) => {
27388
28370
  try {
27389
28371
  mkdirSync3(stateDir, { recursive: true });
27390
- writeFileSync3(path25.join(stateDir, "cursor-session-last-start"), `${JSON.stringify({ at: new Date().toISOString() })}
28372
+ writeFileSync3(path26.join(stateDir, "cursor-session-last-start"), `${JSON.stringify({ at: new Date().toISOString() })}
27391
28373
  `);
27392
28374
  } catch {}
27393
28375
  };