@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.
- package/.cursor-plugin/plugin.json +1 -1
- package/dist/cursor-session-start.js +1177 -303
- package/dist/mcp-server.js +972 -147
- package/dist/workit-hook.js +1151 -304
- package/package.json +3 -3
- package/skills/workit-fanout/SKILL.md +1 -1
- package/skills/workit-implement/SKILL.md +5 -5
- package/skills/workit-review/SKILL.md +3 -0
- package/skills/workit-ship/SKILL.md +1 -2
package/dist/mcp-server.js
CHANGED
|
@@ -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
|
|
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
|
|
6629
|
+
import path24 from "node:path";
|
|
6630
6630
|
|
|
6631
6631
|
// packages/workit-mcp/src/server.ts
|
|
6632
|
-
import { existsSync as
|
|
6633
|
-
import
|
|
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
|
|
14947
|
-
import
|
|
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
|
|
21293
|
-
import { spawnSync as
|
|
21294
|
-
import
|
|
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
|
|
21515
|
-
import
|
|
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
|
|
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 (
|
|
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" &&
|
|
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
|
|
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 && (
|
|
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 =
|
|
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}${
|
|
22572
|
-
var relative = (root, candidate) =>
|
|
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 =
|
|
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 =
|
|
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(
|
|
22627
|
-
const stagedDeleted =
|
|
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(
|
|
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 =
|
|
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 =
|
|
23505
|
+
const target = path18.join(directory, name);
|
|
22649
23506
|
let stat;
|
|
22650
23507
|
try {
|
|
22651
|
-
stat =
|
|
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 =
|
|
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 (!
|
|
22671
|
-
ancestor =
|
|
23527
|
+
while (!fs14.existsSync(ancestor) && ancestor !== root)
|
|
23528
|
+
ancestor = path18.dirname(ancestor);
|
|
22672
23529
|
try {
|
|
22673
|
-
if (!inside(root,
|
|
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 =
|
|
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 (!
|
|
23560
|
+
if (!fs14.existsSync(target))
|
|
22704
23561
|
continue;
|
|
22705
23562
|
let stat;
|
|
22706
23563
|
try {
|
|
22707
|
-
stat =
|
|
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 =
|
|
23580
|
+
const target = path18.join(checkout, item);
|
|
22724
23581
|
try {
|
|
22725
|
-
const stat =
|
|
23582
|
+
const stat = fs14.lstatSync(target);
|
|
22726
23583
|
if (stat.isSymbolicLink()) {
|
|
22727
|
-
const link =
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
22908
|
-
if (target !== root && !target.startsWith(`${root}${
|
|
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 =
|
|
23772
|
+
const below = path18.relative(root, target);
|
|
22916
23773
|
let current = root;
|
|
22917
|
-
for (const segment of below.split(
|
|
23774
|
+
for (const segment of below.split(path18.sep)) {
|
|
22918
23775
|
if (!segment)
|
|
22919
23776
|
continue;
|
|
22920
|
-
current =
|
|
22921
|
-
const stat =
|
|
22922
|
-
const real =
|
|
22923
|
-
if (real !== root && !real.startsWith(`${root}${
|
|
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(
|
|
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
|
|
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 = () =>
|
|
24648
|
+
var grantsDir = () => path19.join(grantsHome.resolve(), ".config", "workit");
|
|
23792
24649
|
var grantsOverride = () => {
|
|
23793
|
-
const configured =
|
|
23794
|
-
return configured ===
|
|
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
|
|
23848
|
-
|
|
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
|
|
25596
|
-
import { existsSync as
|
|
25597
|
-
import
|
|
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 =
|
|
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 ?
|
|
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 =
|
|
25763
|
-
if (!
|
|
26627
|
+
const pkgPath = path20.join(cwd, "package.json");
|
|
26628
|
+
if (!existsSync7(pkgPath))
|
|
25764
26629
|
return [];
|
|
25765
26630
|
try {
|
|
25766
|
-
const pkg = JSON.parse(
|
|
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(
|
|
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("./" +
|
|
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 (!
|
|
26663
|
+
if (!existsSync7(file))
|
|
25799
26664
|
return "";
|
|
25800
|
-
const lines =
|
|
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 =
|
|
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(
|
|
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 (
|
|
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 (
|
|
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 =
|
|
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 =
|
|
25935
|
-
if (
|
|
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 =
|
|
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 =
|
|
25977
|
-
if (
|
|
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 =
|
|
25986
|
-
if (
|
|
26850
|
+
const pkgPath = path20.join(cwd, "package.json");
|
|
26851
|
+
if (existsSync7(pkgPath)) {
|
|
25987
26852
|
try {
|
|
25988
|
-
const pkg = JSON.parse(
|
|
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 =
|
|
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 (
|
|
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
|
|
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 ??
|
|
26219
|
-
var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ??
|
|
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 ?
|
|
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 =
|
|
26630
|
-
if (target !== base && !target.startsWith(base +
|
|
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 (!
|
|
26635
|
-
ancestor =
|
|
27459
|
+
while (!existsSync8(ancestor))
|
|
27460
|
+
ancestor = path22.dirname(ancestor);
|
|
26636
27461
|
const canonicalAncestor = realpathSync5(ancestor);
|
|
26637
|
-
if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base +
|
|
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(
|
|
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,
|
|
26696
|
-
if (
|
|
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 !==
|
|
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 =
|
|
27608
|
+
const here = path23.dirname(fileURLToPath2(import.meta.url));
|
|
26784
27609
|
const sourceMarker = markSourcesLoaded([
|
|
26785
|
-
|
|
26786
|
-
|
|
26787
|
-
|
|
26788
|
-
].filter((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] ?
|
|
26969
|
-
if (entryPath ===
|
|
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
|
|
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 =
|
|
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(
|
|
28215
|
+
writeFileSync3(path26.join(stateDir, "cursor-session-last-start"), `${JSON.stringify({ at: new Date().toISOString() })}
|
|
27391
28216
|
`);
|
|
27392
28217
|
} catch {}
|
|
27393
28218
|
};
|