@brainervirus/workit-mcp 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/dist/index.js +968 -143
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -6620,11 +6620,11 @@ var require_dist = __commonJS(function(exports, module) {
|
|
|
6620
6620
|
|
|
6621
6621
|
// packages/workit-mcp/src/index.ts
|
|
6622
6622
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
6623
|
-
import
|
|
6623
|
+
import path24 from "node:path";
|
|
6624
6624
|
|
|
6625
6625
|
// packages/workit-mcp/src/server.ts
|
|
6626
|
-
import { existsSync as
|
|
6627
|
-
import
|
|
6626
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7, realpathSync as realpathSync6 } from "node:fs";
|
|
6627
|
+
import path23 from "node:path";
|
|
6628
6628
|
|
|
6629
6629
|
// node_modules/zod/v4/core/util.js
|
|
6630
6630
|
function getEnumValues(entries) {
|
|
@@ -14937,8 +14937,8 @@ import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
|
14937
14937
|
|
|
14938
14938
|
// packages/workit-core/src/core.ts
|
|
14939
14939
|
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
14940
|
-
import { existsSync as
|
|
14941
|
-
import
|
|
14940
|
+
import { existsSync as existsSync8, realpathSync as realpathSync5 } from "node:fs";
|
|
14941
|
+
import path22 from "node:path";
|
|
14942
14942
|
|
|
14943
14943
|
// packages/workit-core/src/core/task-contract.ts
|
|
14944
14944
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -17234,7 +17234,7 @@ var workspaceConfigSchema = object2({
|
|
|
17234
17234
|
}).passthrough().optional(),
|
|
17235
17235
|
autoApprove: union([boolean2(), array(nonBlank)]).optional(),
|
|
17236
17236
|
defaultEndpoint: unknown().optional(),
|
|
17237
|
-
verification: _enum(["self", "independent"]).optional(),
|
|
17237
|
+
verification: _enum(["proportional", "self", "independent"]).optional(),
|
|
17238
17238
|
delegation: unknown().optional(),
|
|
17239
17239
|
trailers: boolean2().optional(),
|
|
17240
17240
|
liveSessionGuard: boolean2().optional(),
|
|
@@ -17775,6 +17775,124 @@ function resolveRef(cwd, ref) {
|
|
|
17775
17775
|
return null;
|
|
17776
17776
|
return line(git(cwd, ["rev-parse", "--verify", "-q", `${ref}^{commit}`]));
|
|
17777
17777
|
}
|
|
17778
|
+
var LANE_DIFF = [
|
|
17779
|
+
"-c",
|
|
17780
|
+
"core.quotePath=false",
|
|
17781
|
+
"diff",
|
|
17782
|
+
"--no-color",
|
|
17783
|
+
"--no-ext-diff",
|
|
17784
|
+
"--no-textconv",
|
|
17785
|
+
"--no-renames"
|
|
17786
|
+
];
|
|
17787
|
+
var laneRange = (fork, head) => {
|
|
17788
|
+
if (!safeArg(fork) || head !== null && !safeArg(head))
|
|
17789
|
+
return null;
|
|
17790
|
+
return head === null ? [fork] : [fork, head];
|
|
17791
|
+
};
|
|
17792
|
+
function diffNumstat(cwd, fork, head) {
|
|
17793
|
+
const range = laneRange(fork, head);
|
|
17794
|
+
if (!range)
|
|
17795
|
+
return null;
|
|
17796
|
+
const run = git(cwd, [...LANE_DIFF, "--numstat", "-z", ...range, "--"]);
|
|
17797
|
+
if (!run.ok)
|
|
17798
|
+
return null;
|
|
17799
|
+
const out = [];
|
|
17800
|
+
for (const record of run.stdout.split("\x00")) {
|
|
17801
|
+
const match = /^(-|\d+)\t(-|\d+)\t(.+)$/su.exec(record.replace(/^\n/u, ""));
|
|
17802
|
+
if (!match)
|
|
17803
|
+
continue;
|
|
17804
|
+
const binary = match[1] === "-";
|
|
17805
|
+
out.push({
|
|
17806
|
+
path: match[3],
|
|
17807
|
+
added: binary ? 0 : Number(match[1]),
|
|
17808
|
+
deleted: binary ? 0 : Number(match[2]),
|
|
17809
|
+
binary
|
|
17810
|
+
});
|
|
17811
|
+
}
|
|
17812
|
+
return out;
|
|
17813
|
+
}
|
|
17814
|
+
function diffRaw(cwd, fork, head) {
|
|
17815
|
+
const range = laneRange(fork, head);
|
|
17816
|
+
if (!range)
|
|
17817
|
+
return null;
|
|
17818
|
+
const run = git(cwd, [...LANE_DIFF, "--raw", "-z", "--no-abbrev", ...range, "--"]);
|
|
17819
|
+
if (!run.ok)
|
|
17820
|
+
return null;
|
|
17821
|
+
const fields = run.stdout.split("\x00");
|
|
17822
|
+
const out = [];
|
|
17823
|
+
for (let index = 0;index + 1 < fields.length; index += 2) {
|
|
17824
|
+
const meta = /^:(\d{6}) (\d{6}) ([0-9a-f]+) ([0-9a-f]+) [A-Z]\d*$/u.exec(fields[index].replace(/^\n/u, ""));
|
|
17825
|
+
if (!meta)
|
|
17826
|
+
return null;
|
|
17827
|
+
out.push({
|
|
17828
|
+
path: fields[index + 1],
|
|
17829
|
+
oldMode: meta[1],
|
|
17830
|
+
newMode: meta[2],
|
|
17831
|
+
oldBlob: meta[3],
|
|
17832
|
+
newBlob: meta[4]
|
|
17833
|
+
});
|
|
17834
|
+
}
|
|
17835
|
+
return out;
|
|
17836
|
+
}
|
|
17837
|
+
function readBlobs(cwd, ids) {
|
|
17838
|
+
const out = new Map;
|
|
17839
|
+
const wanted = [...new Set(ids)].filter((id) => /^[0-9a-f]{40,64}$/u.test(id));
|
|
17840
|
+
if (!wanted.length)
|
|
17841
|
+
return out;
|
|
17842
|
+
const run = spawnSync3("git", ["cat-file", "--batch"], {
|
|
17843
|
+
cwd,
|
|
17844
|
+
input: `${wanted.join(`
|
|
17845
|
+
`)}
|
|
17846
|
+
`,
|
|
17847
|
+
maxBuffer: MAX_BUFFER,
|
|
17848
|
+
timeout: GIT_TIMEOUTS.local,
|
|
17849
|
+
killSignal: "SIGKILL",
|
|
17850
|
+
windowsHide: true
|
|
17851
|
+
});
|
|
17852
|
+
if (run.status !== 0 || !run.stdout)
|
|
17853
|
+
return null;
|
|
17854
|
+
const bytes = run.stdout;
|
|
17855
|
+
let at = 0;
|
|
17856
|
+
for (const id of wanted) {
|
|
17857
|
+
const end = bytes.indexOf(10, at);
|
|
17858
|
+
if (end < 0)
|
|
17859
|
+
return null;
|
|
17860
|
+
const header = bytes.subarray(at, end).toString("utf8").split(" ");
|
|
17861
|
+
at = end + 1;
|
|
17862
|
+
if (header[1] === "missing")
|
|
17863
|
+
continue;
|
|
17864
|
+
const size = Number(header[2]);
|
|
17865
|
+
if (header[0] !== id || !Number.isSafeInteger(size))
|
|
17866
|
+
return null;
|
|
17867
|
+
out.set(id, bytes.subarray(at, at + size));
|
|
17868
|
+
at += size + 1;
|
|
17869
|
+
}
|
|
17870
|
+
return out;
|
|
17871
|
+
}
|
|
17872
|
+
function treeFilesNamed(cwd, rev, name) {
|
|
17873
|
+
if (!safeArg(rev))
|
|
17874
|
+
return null;
|
|
17875
|
+
const run = git(cwd, ["ls-tree", "-r", "-z", "--full-tree", rev]);
|
|
17876
|
+
if (!run.ok)
|
|
17877
|
+
return null;
|
|
17878
|
+
const out = new Map;
|
|
17879
|
+
for (const record of run.stdout.split("\x00")) {
|
|
17880
|
+
const match = /^\d{6} blob ([0-9a-f]+)\t(.+)$/su.exec(record);
|
|
17881
|
+
if (match && (match[2] === name || match[2].endsWith(`/${name}`)))
|
|
17882
|
+
out.set(match[2], match[1]);
|
|
17883
|
+
}
|
|
17884
|
+
return out;
|
|
17885
|
+
}
|
|
17886
|
+
function fileAt(cwd, rev, file) {
|
|
17887
|
+
if (!safeArg(rev))
|
|
17888
|
+
return null;
|
|
17889
|
+
const run = git(cwd, ["cat-file", "blob", `${rev}:${file}`]);
|
|
17890
|
+
return run.ok ? run.stdout : null;
|
|
17891
|
+
}
|
|
17892
|
+
function untrackedFiles(cwd) {
|
|
17893
|
+
const run = git(cwd, ["ls-files", "-z", "--others", "--exclude-standard"]);
|
|
17894
|
+
return run.ok ? run.stdout.split("\x00").filter(Boolean) : [];
|
|
17895
|
+
}
|
|
17778
17896
|
var config2 = (cwd, key) => line(git(cwd, ["config", "--get", key]));
|
|
17779
17897
|
function currentBranch(cwd) {
|
|
17780
17898
|
return line(git(cwd, ["symbolic-ref", "--short", "-q", "HEAD"]));
|
|
@@ -21283,9 +21401,9 @@ var workerBlocksTransition = (transition, state) => transition === "pause" ? fal
|
|
|
21283
21401
|
|
|
21284
21402
|
// packages/workit-core/src/core/task-evaluation.ts
|
|
21285
21403
|
import { createHash as createHash10 } from "node:crypto";
|
|
21286
|
-
import * as
|
|
21287
|
-
import { spawnSync as
|
|
21288
|
-
import
|
|
21404
|
+
import * as fs14 from "node:fs";
|
|
21405
|
+
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
21406
|
+
import path18 from "node:path";
|
|
21289
21407
|
|
|
21290
21408
|
// packages/workit-core/src/check-config.ts
|
|
21291
21409
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
@@ -21505,8 +21623,8 @@ function checkCommand(args, version, onPath = workitAvailable()) {
|
|
|
21505
21623
|
}
|
|
21506
21624
|
|
|
21507
21625
|
// packages/workit-core/src/core/policy/derive.ts
|
|
21508
|
-
import { existsSync as
|
|
21509
|
-
import
|
|
21626
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
21627
|
+
import path17 from "node:path";
|
|
21510
21628
|
|
|
21511
21629
|
// packages/workit-core/src/ledger.ts
|
|
21512
21630
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
@@ -22350,7 +22468,8 @@ function checkVerdicts(cwd, branch, ledgerRows) {
|
|
|
22350
22468
|
verdict: failing?.verdict ?? null,
|
|
22351
22469
|
reasons: failing ? ["failing_verdict"] : !newestCurrent ? ["no_verdict"] : newestCurrent.reasons.length ? newestCurrent.reasons : ["type_check_only"]
|
|
22352
22470
|
};
|
|
22353
|
-
const
|
|
22471
|
+
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))));
|
|
22472
|
+
const selfEntry = latestSelf && STRONG_RESULTS.has(String(latestSelf.verdict.result)) ? latestSelf : undefined;
|
|
22354
22473
|
return {
|
|
22355
22474
|
branch,
|
|
22356
22475
|
head,
|
|
@@ -22372,12 +22491,721 @@ var OBSERVED_ONLY = new Set([
|
|
|
22372
22491
|
...PR_ROW_TYPES
|
|
22373
22492
|
]);
|
|
22374
22493
|
|
|
22494
|
+
// packages/workit-core/src/core/policy/lane.ts
|
|
22495
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
22496
|
+
import path16 from "node:path";
|
|
22497
|
+
|
|
22498
|
+
// packages/workit-core/src/core/pr-create.ts
|
|
22499
|
+
import fs13 from "node:fs";
|
|
22500
|
+
import path15 from "node:path";
|
|
22501
|
+
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
22502
|
+
// packages/workit-core/src/forge/pr-body.ts
|
|
22503
|
+
function parseGhIssue(value) {
|
|
22504
|
+
const m = /issues\/(\d+)/.exec(value);
|
|
22505
|
+
return m ? m[1] : String(value).trim().replace(/^#/, "");
|
|
22506
|
+
}
|
|
22507
|
+
|
|
22508
|
+
// packages/workit-core/src/core/pr-create.ts
|
|
22509
|
+
function whichOnPath(tool) {
|
|
22510
|
+
const names = process.platform === "win32" ? [tool, `${tool}.exe`, `${tool}.cmd`] : [tool];
|
|
22511
|
+
for (const dir of (process.env.PATH ?? "").split(path15.delimiter)) {
|
|
22512
|
+
if (!dir)
|
|
22513
|
+
continue;
|
|
22514
|
+
for (const name of names) {
|
|
22515
|
+
const candidate = path15.join(dir, name);
|
|
22516
|
+
try {
|
|
22517
|
+
fs13.accessSync(candidate, fs13.constants.X_OK);
|
|
22518
|
+
return candidate;
|
|
22519
|
+
} catch {}
|
|
22520
|
+
}
|
|
22521
|
+
}
|
|
22522
|
+
return null;
|
|
22523
|
+
}
|
|
22524
|
+
var hostingCliAvailable = (provider) => whichOnPath(provider === "gitlab" ? "glab" : "gh") !== null;
|
|
22525
|
+
var pushRemote = (cwd) => {
|
|
22526
|
+
const result = spawnSync10("git", ["remote", "get-url", "--push", "--all", "origin"], {
|
|
22527
|
+
cwd,
|
|
22528
|
+
encoding: "utf8"
|
|
22529
|
+
});
|
|
22530
|
+
if (result.status !== 0)
|
|
22531
|
+
return null;
|
|
22532
|
+
const urls = (result.stdout ?? "").split(/\r?\n/u).map((url) => url.trim()).filter(Boolean);
|
|
22533
|
+
return urls.length === 1 ? urls[0] : null;
|
|
22534
|
+
};
|
|
22535
|
+
|
|
22536
|
+
// packages/workit-core/src/forge/redact.ts
|
|
22537
|
+
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_.-]*`;
|
|
22538
|
+
var ASSIGNMENT = new RegExp(String.raw`(?<![A-Za-z0-9])(["']?${KEY}["']?\s*[:=]\s*["']?)((?:bearer|basic|token|digest)\s+)?([^\s"',;&]+)`, "giu");
|
|
22539
|
+
var QUOTED_ASSIGNMENT = new RegExp(String.raw`(?<![A-Za-z0-9])(["']?${KEY}["']?\s*[:=]\s*)(["'])([^"'\n]*[^\s"'][^"'\n]*)\2`, "giu");
|
|
22540
|
+
var ANSI = new RegExp(String.raw`\u001b\[[0-9;?]*[ -/]*[@-~]|\u001b\][^\u0007]*\u0007`, "gu");
|
|
22541
|
+
|
|
22542
|
+
// packages/workit-core/src/git/ops.ts
|
|
22543
|
+
var COMMIT_TIMEOUT_MS = 10 * 60000;
|
|
22544
|
+
|
|
22545
|
+
// packages/workit-core/src/core/policy/attributes.ts
|
|
22546
|
+
function patternRegex(dir, pattern) {
|
|
22547
|
+
if (!pattern || pattern.endsWith("/") || pattern.startsWith('"') || pattern.startsWith("!"))
|
|
22548
|
+
return null;
|
|
22549
|
+
const anchored = pattern.includes("/");
|
|
22550
|
+
const body = pattern.replace(/^\//u, "");
|
|
22551
|
+
let source = "";
|
|
22552
|
+
for (let index = 0;index < body.length; index += 1) {
|
|
22553
|
+
const char = body[index];
|
|
22554
|
+
if (char === "*" && body[index + 1] === "*") {
|
|
22555
|
+
const slash = body[index + 2] === "/";
|
|
22556
|
+
source += slash ? "(?:.*/)?" : ".*";
|
|
22557
|
+
index += slash ? 2 : 1;
|
|
22558
|
+
} else if (char === "*")
|
|
22559
|
+
source += "[^/]*";
|
|
22560
|
+
else if (char === "?")
|
|
22561
|
+
source += "[^/]";
|
|
22562
|
+
else if (char === "[") {
|
|
22563
|
+
const end = body.indexOf("]", index + 2);
|
|
22564
|
+
if (end < 0)
|
|
22565
|
+
return null;
|
|
22566
|
+
const set = body.slice(index + 1, end).replace(/^!/u, "^").replace(/\\/gu, "\\\\");
|
|
22567
|
+
source += `[${set}]`;
|
|
22568
|
+
index = end;
|
|
22569
|
+
} else if (char === "\\" && index + 1 < body.length) {
|
|
22570
|
+
source += body[index + 1].replace(/[.*+?^${}()|[\]\\/]/gu, "\\$&");
|
|
22571
|
+
index += 1;
|
|
22572
|
+
} else
|
|
22573
|
+
source += char.replace(/[.*+?^${}()|[\]\\/]/gu, "\\$&");
|
|
22574
|
+
}
|
|
22575
|
+
const prefix = dir ? `${dir.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")}/` : "";
|
|
22576
|
+
try {
|
|
22577
|
+
return new RegExp(anchored ? `^${prefix}${source}$` : `^${prefix}(?:.*/)?${source}$`, "u");
|
|
22578
|
+
} catch {
|
|
22579
|
+
return null;
|
|
22580
|
+
}
|
|
22581
|
+
}
|
|
22582
|
+
function rulesOf(dir, text) {
|
|
22583
|
+
const out = [];
|
|
22584
|
+
for (const raw of text.split(`
|
|
22585
|
+
`)) {
|
|
22586
|
+
const line = raw.trim();
|
|
22587
|
+
if (!line || line.startsWith("#") || line.startsWith("[attr]"))
|
|
22588
|
+
continue;
|
|
22589
|
+
const [pattern, ...attributes] = line.split(/\s+/u);
|
|
22590
|
+
let generated = null;
|
|
22591
|
+
for (const attribute of attributes) {
|
|
22592
|
+
if (attribute === "linguist-generated" || attribute === "linguist-generated=true")
|
|
22593
|
+
generated = true;
|
|
22594
|
+
else if (attribute === "-linguist-generated" || attribute === "!linguist-generated" || attribute.startsWith("linguist-generated="))
|
|
22595
|
+
generated = false;
|
|
22596
|
+
}
|
|
22597
|
+
if (generated === null)
|
|
22598
|
+
continue;
|
|
22599
|
+
const regex = patternRegex(dir, pattern);
|
|
22600
|
+
if (regex)
|
|
22601
|
+
out.push({ regex, generated });
|
|
22602
|
+
}
|
|
22603
|
+
return out;
|
|
22604
|
+
}
|
|
22605
|
+
function generatedByAttributes(files, paths) {
|
|
22606
|
+
const rules = [...files].map(([file, text]) => {
|
|
22607
|
+
const dir = file.includes("/") ? file.slice(0, file.lastIndexOf("/")) : "";
|
|
22608
|
+
return {
|
|
22609
|
+
depth: dir ? dir.split("/").length : 0,
|
|
22610
|
+
rules: rulesOf(dir, text)
|
|
22611
|
+
};
|
|
22612
|
+
}).toSorted((left, right) => left.depth - right.depth).flatMap((entry) => entry.rules);
|
|
22613
|
+
const out = new Set;
|
|
22614
|
+
for (const file of paths) {
|
|
22615
|
+
const last = rules.findLast((rule) => rule.regex.test(file));
|
|
22616
|
+
if (last?.generated)
|
|
22617
|
+
out.add(file);
|
|
22618
|
+
}
|
|
22619
|
+
return out;
|
|
22620
|
+
}
|
|
22621
|
+
|
|
22622
|
+
// packages/workit-core/src/core/policy/substance.ts
|
|
22623
|
+
var SLASH_BLOCK = [["/*", "*/"]];
|
|
22624
|
+
var C_LIKE = { line: ["//"], block: SLASH_BLOCK, quotes: `"'` };
|
|
22625
|
+
var SYNTAXES = Object.fromEntries([
|
|
22626
|
+
...["ts", "mts", "cts", "js", "mjs", "cjs"].map((ext) => [ext, { ...C_LIKE, js: true }]),
|
|
22627
|
+
...["java", "kt", "kts", "scala", "swift", "dart", "groovy"].map((ext) => [
|
|
22628
|
+
ext,
|
|
22629
|
+
{ ...C_LIKE, triple: true }
|
|
22630
|
+
]),
|
|
22631
|
+
["go", { ...C_LIKE, rawBacktick: true }],
|
|
22632
|
+
...["css", "scss", "less"].map((ext) => [
|
|
22633
|
+
ext,
|
|
22634
|
+
{ line: [], block: SLASH_BLOCK, quotes: `"'`, cssUrl: true }
|
|
22635
|
+
]),
|
|
22636
|
+
...["py", "pyi"].map((ext) => [
|
|
22637
|
+
ext,
|
|
22638
|
+
{ line: ["#"], block: [], quotes: `"'`, triple: true, indented: true, fstring: true }
|
|
22639
|
+
]),
|
|
22640
|
+
["toml", { line: ["#"], block: [], quotes: `"`, literal: "'", triple: true }],
|
|
22641
|
+
...["html", "htm", "xml", "svg", "xhtml"].map((ext) => [
|
|
22642
|
+
ext,
|
|
22643
|
+
{ line: [], block: [["<!--", "-->"]], quotes: "", indented: true }
|
|
22644
|
+
])
|
|
22645
|
+
]);
|
|
22646
|
+
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;
|
|
22647
|
+
var extensionOf = (file) => {
|
|
22648
|
+
const name = file.slice(file.lastIndexOf("/") + 1);
|
|
22649
|
+
const dot = name.lastIndexOf(".");
|
|
22650
|
+
return dot > 0 ? name.slice(dot + 1).toLowerCase() : "";
|
|
22651
|
+
};
|
|
22652
|
+
var CI_PATH = /^\.github\/|(?:^|\/)(?:\.gitlab-ci\.ya?ml|Jenkinsfile|azure-pipelines\.ya?ml|\.pre-commit-config\.ya?ml|\.circleci\/.*)$/u;
|
|
22653
|
+
var syntaxOf = (file) => CI_PATH.test(file) ? null : SYNTAXES[extensionOf(file)] ?? null;
|
|
22654
|
+
var SPACE = /[ \t\r\f\v]/u;
|
|
22655
|
+
var WORD = /[\w$]/u;
|
|
22656
|
+
var NO_SPACE_AFTER = "([{,;";
|
|
22657
|
+
var NO_SPACE_BEFORE = ")]},;";
|
|
22658
|
+
var REGEX_AFTER = "(,=:[!&|?{};+-*%<>~^";
|
|
22659
|
+
var REGEX_KEYWORDS = new Set([
|
|
22660
|
+
"return",
|
|
22661
|
+
"typeof",
|
|
22662
|
+
"instanceof",
|
|
22663
|
+
"case",
|
|
22664
|
+
"do",
|
|
22665
|
+
"else",
|
|
22666
|
+
"in",
|
|
22667
|
+
"of",
|
|
22668
|
+
"new",
|
|
22669
|
+
"delete",
|
|
22670
|
+
"void",
|
|
22671
|
+
"throw",
|
|
22672
|
+
"yield",
|
|
22673
|
+
"await"
|
|
22674
|
+
]);
|
|
22675
|
+
function substanceOf(file, text) {
|
|
22676
|
+
const syntax = syntaxOf(file);
|
|
22677
|
+
if (!syntax)
|
|
22678
|
+
return plainSubstance(text);
|
|
22679
|
+
const markup = syntax.block.some(([open]) => open === "<!--");
|
|
22680
|
+
if (markup && (/<(?:script|style)\b|<!\[CDATA\[|<\?/iu.test(text) || /[^>\s][ \t]*<!--/u.test(text)))
|
|
22681
|
+
return plainSubstance(text);
|
|
22682
|
+
return lex(syntax, text);
|
|
22683
|
+
}
|
|
22684
|
+
function plainSubstance(text) {
|
|
22685
|
+
return text.split(`
|
|
22686
|
+
`).map((line) => line.replace(/[ \t\r\f\v]+$/u, "")).filter(Boolean).join(`
|
|
22687
|
+
`);
|
|
22688
|
+
}
|
|
22689
|
+
function lex(syntax, text) {
|
|
22690
|
+
const collapse = !syntax.indented;
|
|
22691
|
+
let out = "";
|
|
22692
|
+
let lineStart = 0;
|
|
22693
|
+
let kept = 0;
|
|
22694
|
+
let pendingSpace = false;
|
|
22695
|
+
const frames = [{ kind: "code", braces: 0 }];
|
|
22696
|
+
let index = 0;
|
|
22697
|
+
if (text.startsWith("#!")) {
|
|
22698
|
+
const end = text.indexOf(`
|
|
22699
|
+
`);
|
|
22700
|
+
out = end < 0 ? text : text.slice(0, end);
|
|
22701
|
+
kept = out.length;
|
|
22702
|
+
index = end < 0 ? text.length : end;
|
|
22703
|
+
}
|
|
22704
|
+
const emitCode = (chunk) => {
|
|
22705
|
+
if (collapse && pendingSpace && out.length > lineStart) {
|
|
22706
|
+
const before = out[out.length - 1];
|
|
22707
|
+
if (!NO_SPACE_AFTER.includes(before) && !NO_SPACE_BEFORE.includes(chunk[0]))
|
|
22708
|
+
out += " ";
|
|
22709
|
+
}
|
|
22710
|
+
pendingSpace = false;
|
|
22711
|
+
out += chunk;
|
|
22712
|
+
};
|
|
22713
|
+
const emitVerbatim = (chunk) => {
|
|
22714
|
+
emitCode(chunk);
|
|
22715
|
+
kept = out.length;
|
|
22716
|
+
};
|
|
22717
|
+
const newline = () => {
|
|
22718
|
+
if (!collapse) {
|
|
22719
|
+
let end = out.length;
|
|
22720
|
+
while (end > Math.max(lineStart, kept) && SPACE.test(out[end - 1]))
|
|
22721
|
+
end -= 1;
|
|
22722
|
+
out = out.slice(0, end);
|
|
22723
|
+
}
|
|
22724
|
+
pendingSpace = false;
|
|
22725
|
+
if (out.length > lineStart) {
|
|
22726
|
+
out += `
|
|
22727
|
+
`;
|
|
22728
|
+
lineStart = out.length;
|
|
22729
|
+
}
|
|
22730
|
+
};
|
|
22731
|
+
const regexAllowed = () => {
|
|
22732
|
+
let end = out.length;
|
|
22733
|
+
while (end > 0 && /\s/u.test(out[end - 1]))
|
|
22734
|
+
end -= 1;
|
|
22735
|
+
if (end === 0 || REGEX_AFTER.includes(out[end - 1]))
|
|
22736
|
+
return true;
|
|
22737
|
+
let start = end;
|
|
22738
|
+
while (start > 0 && WORD.test(out[start - 1]))
|
|
22739
|
+
start -= 1;
|
|
22740
|
+
return REGEX_KEYWORDS.has(out.slice(start, end));
|
|
22741
|
+
};
|
|
22742
|
+
const scanString = (quote, escapes, multiline) => {
|
|
22743
|
+
const prefix = text.slice(Math.max(0, index - 2), index).match(/[a-z]*$/iu)?.[0] ?? "";
|
|
22744
|
+
const fstring = syntax.fstring === true && /f/iu.test(prefix);
|
|
22745
|
+
let end = index + quote.length;
|
|
22746
|
+
while (end < text.length) {
|
|
22747
|
+
const char = text[end];
|
|
22748
|
+
if (escapes && char === "\\") {
|
|
22749
|
+
end += 2;
|
|
22750
|
+
continue;
|
|
22751
|
+
}
|
|
22752
|
+
if (text.startsWith(quote, end)) {
|
|
22753
|
+
if (fstring && unbalanced(text.slice(index + quote.length, end)))
|
|
22754
|
+
return false;
|
|
22755
|
+
emitVerbatim(text.slice(index, end + quote.length));
|
|
22756
|
+
index = end + quote.length;
|
|
22757
|
+
return true;
|
|
22758
|
+
}
|
|
22759
|
+
if (char === `
|
|
22760
|
+
` && !multiline)
|
|
22761
|
+
return false;
|
|
22762
|
+
end += 1;
|
|
22763
|
+
}
|
|
22764
|
+
return false;
|
|
22765
|
+
};
|
|
22766
|
+
while (index < text.length) {
|
|
22767
|
+
const frame = frames[frames.length - 1];
|
|
22768
|
+
const char = text[index];
|
|
22769
|
+
if (frame.kind === "template") {
|
|
22770
|
+
if (char === "\\") {
|
|
22771
|
+
emitVerbatim(text.slice(index, index + 2));
|
|
22772
|
+
index += 2;
|
|
22773
|
+
} else if (char === "`") {
|
|
22774
|
+
emitVerbatim(char);
|
|
22775
|
+
frames.pop();
|
|
22776
|
+
index += 1;
|
|
22777
|
+
} else if (text.startsWith("${", index)) {
|
|
22778
|
+
emitVerbatim("${");
|
|
22779
|
+
frames.push({ kind: "code", braces: 0 });
|
|
22780
|
+
index += 2;
|
|
22781
|
+
} else {
|
|
22782
|
+
out += char;
|
|
22783
|
+
kept = out.length;
|
|
22784
|
+
index += 1;
|
|
22785
|
+
}
|
|
22786
|
+
continue;
|
|
22787
|
+
}
|
|
22788
|
+
if (char === `
|
|
22789
|
+
`) {
|
|
22790
|
+
newline();
|
|
22791
|
+
index += 1;
|
|
22792
|
+
continue;
|
|
22793
|
+
}
|
|
22794
|
+
if (SPACE.test(char)) {
|
|
22795
|
+
if (collapse)
|
|
22796
|
+
pendingSpace = true;
|
|
22797
|
+
else
|
|
22798
|
+
out += char;
|
|
22799
|
+
index += 1;
|
|
22800
|
+
continue;
|
|
22801
|
+
}
|
|
22802
|
+
const lineOpener = syntax.line.find((opener) => text.startsWith(opener, index));
|
|
22803
|
+
if (lineOpener) {
|
|
22804
|
+
const end = text.indexOf(`
|
|
22805
|
+
`, index);
|
|
22806
|
+
const comment = text.slice(index, end < 0 ? text.length : end);
|
|
22807
|
+
if (DIRECTIVE.test(comment.slice(lineOpener.length)))
|
|
22808
|
+
emitVerbatim(comment);
|
|
22809
|
+
else
|
|
22810
|
+
pendingSpace = true;
|
|
22811
|
+
index = end < 0 ? text.length : end;
|
|
22812
|
+
continue;
|
|
22813
|
+
}
|
|
22814
|
+
const block = syntax.block.find(([open]) => text.startsWith(open, index));
|
|
22815
|
+
if (block) {
|
|
22816
|
+
const end = text.indexOf(block[1], index + block[0].length);
|
|
22817
|
+
if (end < 0)
|
|
22818
|
+
return null;
|
|
22819
|
+
const comment = text.slice(index, end + block[1].length);
|
|
22820
|
+
if (DIRECTIVE.test(comment.slice(block[0].length, -block[1].length)))
|
|
22821
|
+
emitVerbatim(comment);
|
|
22822
|
+
else
|
|
22823
|
+
pendingSpace = true;
|
|
22824
|
+
if (comment.includes(`
|
|
22825
|
+
`))
|
|
22826
|
+
newline();
|
|
22827
|
+
index = end + block[1].length;
|
|
22828
|
+
continue;
|
|
22829
|
+
}
|
|
22830
|
+
if (syntax.triple && (char === '"' || char === "'") && text.startsWith(char.repeat(3), index)) {
|
|
22831
|
+
if (!scanString(char.repeat(3), !syntax.literal?.includes(char), true))
|
|
22832
|
+
return null;
|
|
22833
|
+
continue;
|
|
22834
|
+
}
|
|
22835
|
+
if (syntax.quotes.includes(char)) {
|
|
22836
|
+
if (!scanString(char, true, Boolean(syntax.multiline)))
|
|
22837
|
+
return null;
|
|
22838
|
+
continue;
|
|
22839
|
+
}
|
|
22840
|
+
if (syntax.literal?.includes(char)) {
|
|
22841
|
+
if (!scanString(char, false, false))
|
|
22842
|
+
return null;
|
|
22843
|
+
continue;
|
|
22844
|
+
}
|
|
22845
|
+
if (syntax.rawBacktick && char === "`") {
|
|
22846
|
+
if (!scanString("`", false, true))
|
|
22847
|
+
return null;
|
|
22848
|
+
continue;
|
|
22849
|
+
}
|
|
22850
|
+
if (syntax.js && char === "`") {
|
|
22851
|
+
emitVerbatim(char);
|
|
22852
|
+
frames.push({ kind: "template" });
|
|
22853
|
+
index += 1;
|
|
22854
|
+
continue;
|
|
22855
|
+
}
|
|
22856
|
+
if (syntax.cssUrl && /^url\(\s*[^"')\s]/iu.test(text.slice(index, index + 64)))
|
|
22857
|
+
return null;
|
|
22858
|
+
if (syntax.js && char === "/" && !regexAllowed() && out.trimEnd().endsWith(")")) {
|
|
22859
|
+
const lineEnd = text.indexOf(`
|
|
22860
|
+
`, index);
|
|
22861
|
+
if (text.slice(index + 1, lineEnd < 0 ? text.length : lineEnd).includes("/"))
|
|
22862
|
+
return null;
|
|
22863
|
+
}
|
|
22864
|
+
if (syntax.js && char === "/" && regexAllowed()) {
|
|
22865
|
+
let end = index + 1;
|
|
22866
|
+
let inClass = false;
|
|
22867
|
+
while (end < text.length && (inClass || text[end] !== "/")) {
|
|
22868
|
+
if (text[end] === `
|
|
22869
|
+
`)
|
|
22870
|
+
return null;
|
|
22871
|
+
if (text[end] === "\\")
|
|
22872
|
+
end += 1;
|
|
22873
|
+
else if (text[end] === "[")
|
|
22874
|
+
inClass = true;
|
|
22875
|
+
else if (text[end] === "]")
|
|
22876
|
+
inClass = false;
|
|
22877
|
+
end += 1;
|
|
22878
|
+
}
|
|
22879
|
+
if (end >= text.length)
|
|
22880
|
+
return null;
|
|
22881
|
+
emitVerbatim(text.slice(index, end + 1));
|
|
22882
|
+
index = end + 1;
|
|
22883
|
+
continue;
|
|
22884
|
+
}
|
|
22885
|
+
if (frames.length > 1 && frame.kind === "code") {
|
|
22886
|
+
if (char === "{")
|
|
22887
|
+
frame.braces += 1;
|
|
22888
|
+
else if (char === "}") {
|
|
22889
|
+
if (frame.braces === 0) {
|
|
22890
|
+
emitVerbatim(char);
|
|
22891
|
+
frames.pop();
|
|
22892
|
+
index += 1;
|
|
22893
|
+
continue;
|
|
22894
|
+
}
|
|
22895
|
+
frame.braces -= 1;
|
|
22896
|
+
}
|
|
22897
|
+
}
|
|
22898
|
+
emitCode(char);
|
|
22899
|
+
index += 1;
|
|
22900
|
+
}
|
|
22901
|
+
if (frames.length !== 1)
|
|
22902
|
+
return null;
|
|
22903
|
+
newline();
|
|
22904
|
+
return out;
|
|
22905
|
+
}
|
|
22906
|
+
function unbalanced(body) {
|
|
22907
|
+
let depth = 0;
|
|
22908
|
+
for (const part of body.replaceAll("{{", "").replaceAll("}}", "")) {
|
|
22909
|
+
if (part === "{")
|
|
22910
|
+
depth += 1;
|
|
22911
|
+
else if (part === "}")
|
|
22912
|
+
depth = Math.max(0, depth - 1);
|
|
22913
|
+
}
|
|
22914
|
+
return depth > 0;
|
|
22915
|
+
}
|
|
22916
|
+
function hasOpaqueLineBreak(text) {
|
|
22917
|
+
return /\r(?!\n)|[\u2028\u2029]/u.test(text);
|
|
22918
|
+
}
|
|
22919
|
+
var decoder = new TextDecoder("utf-8", { fatal: true });
|
|
22920
|
+
function textOf(bytes) {
|
|
22921
|
+
if (bytes.includes(0))
|
|
22922
|
+
return null;
|
|
22923
|
+
try {
|
|
22924
|
+
return decoder.decode(bytes);
|
|
22925
|
+
} catch {
|
|
22926
|
+
return null;
|
|
22927
|
+
}
|
|
22928
|
+
}
|
|
22929
|
+
function cosmeticChange(file, before, after) {
|
|
22930
|
+
const left = textOf(before);
|
|
22931
|
+
const right = textOf(after);
|
|
22932
|
+
if (left === null || right === null)
|
|
22933
|
+
return false;
|
|
22934
|
+
if (hasOpaqueLineBreak(left) || hasOpaqueLineBreak(right))
|
|
22935
|
+
return false;
|
|
22936
|
+
const a = substanceOf(file, left);
|
|
22937
|
+
return a !== null && a === substanceOf(file, right);
|
|
22938
|
+
}
|
|
22939
|
+
|
|
22940
|
+
// packages/workit-core/src/core/policy/lane.ts
|
|
22941
|
+
var LANE_THRESHOLDS = {
|
|
22942
|
+
selfMaxLines: 100,
|
|
22943
|
+
selfMaxFiles: 5,
|
|
22944
|
+
fullMinLines: 500
|
|
22945
|
+
};
|
|
22946
|
+
var RISK_TOKENS = new Set([
|
|
22947
|
+
"auth",
|
|
22948
|
+
"authn",
|
|
22949
|
+
"authz",
|
|
22950
|
+
"oauth",
|
|
22951
|
+
"security",
|
|
22952
|
+
"permission",
|
|
22953
|
+
"permissions",
|
|
22954
|
+
"secret",
|
|
22955
|
+
"secrets",
|
|
22956
|
+
"crypto",
|
|
22957
|
+
"gate",
|
|
22958
|
+
"gates",
|
|
22959
|
+
"policy",
|
|
22960
|
+
"policies",
|
|
22961
|
+
"hook",
|
|
22962
|
+
"hooks",
|
|
22963
|
+
"husky",
|
|
22964
|
+
"lefthook",
|
|
22965
|
+
"release",
|
|
22966
|
+
"releases",
|
|
22967
|
+
"migration",
|
|
22968
|
+
"migrations",
|
|
22969
|
+
"migrate",
|
|
22970
|
+
"workflows"
|
|
22971
|
+
]);
|
|
22972
|
+
var RISK_FILES = new Set([
|
|
22973
|
+
".gitlab-ci.yml",
|
|
22974
|
+
"Jenkinsfile",
|
|
22975
|
+
"azure-pipelines.yml",
|
|
22976
|
+
".pre-commit-config.yaml",
|
|
22977
|
+
".workit/risk-paths"
|
|
22978
|
+
]);
|
|
22979
|
+
var RISK_NAMES = new Set([".gitattributes"]);
|
|
22980
|
+
var RISK_PATHS_FILE = ".workit/risk-paths";
|
|
22981
|
+
var LOCKFILES = new Set([
|
|
22982
|
+
"bun.lock",
|
|
22983
|
+
"bun.lockb",
|
|
22984
|
+
"package-lock.json",
|
|
22985
|
+
"npm-shrinkwrap.json",
|
|
22986
|
+
"yarn.lock",
|
|
22987
|
+
"pnpm-lock.yaml",
|
|
22988
|
+
"Cargo.lock",
|
|
22989
|
+
"go.sum",
|
|
22990
|
+
"poetry.lock",
|
|
22991
|
+
"uv.lock",
|
|
22992
|
+
"Pipfile.lock",
|
|
22993
|
+
"Gemfile.lock",
|
|
22994
|
+
"composer.lock"
|
|
22995
|
+
]);
|
|
22996
|
+
var DOC_EXT = /\.(?:md|mdx|markdown|rst|adoc|txt)$/iu;
|
|
22997
|
+
var DOC_NAMES = /^(?:license|licence|notice|authors|changelog|changes|contributors)$/iu;
|
|
22998
|
+
var INSTRUCTIONS = /(?:^|\/)(?:AGENTS|CLAUDE|GEMINI|SKILL)\.md$|(?:^|\/)(?:skills|agents|commands|rules|prompts)\/[^/]+/iu;
|
|
22999
|
+
var TEST_PATH = /(?:^|\/)(?:test|tests|__tests__|spec|specs|fixtures)\/|\.(?:test|spec)\.[^/]+$/iu;
|
|
23000
|
+
var basename = (file) => file.slice(file.lastIndexOf("/") + 1);
|
|
23001
|
+
var isDoc = (file) => !INSTRUCTIONS.test(file) && (DOC_EXT.test(file) || DOC_NAMES.test(basename(file)));
|
|
23002
|
+
function kindOf(file) {
|
|
23003
|
+
if (file.binary)
|
|
23004
|
+
return "behavior";
|
|
23005
|
+
if (file.generated)
|
|
23006
|
+
return "generated";
|
|
23007
|
+
if (LOCKFILES.has(basename(file.path)))
|
|
23008
|
+
return "lockfile";
|
|
23009
|
+
if (isDoc(file.path))
|
|
23010
|
+
return "doc";
|
|
23011
|
+
if (file.cosmetic)
|
|
23012
|
+
return "cosmetic";
|
|
23013
|
+
return TEST_PATH.test(file.path) ? "test" : "behavior";
|
|
23014
|
+
}
|
|
23015
|
+
var globCache = new Map;
|
|
23016
|
+
function globMatch(pattern, file) {
|
|
23017
|
+
let regex = globCache.get(pattern);
|
|
23018
|
+
if (!regex) {
|
|
23019
|
+
let source = "";
|
|
23020
|
+
for (let index = 0;index < pattern.length; index += 1) {
|
|
23021
|
+
const char = pattern[index];
|
|
23022
|
+
if (char === "*" && pattern[index + 1] === "*") {
|
|
23023
|
+
source += pattern[index + 2] === "/" ? "(?:[^/]*/)*" : ".*";
|
|
23024
|
+
index += pattern[index + 2] === "/" ? 2 : 1;
|
|
23025
|
+
} else if (char === "*")
|
|
23026
|
+
source += "[^/]*";
|
|
23027
|
+
else if (char === "?")
|
|
23028
|
+
source += "[^/]";
|
|
23029
|
+
else
|
|
23030
|
+
source += char.replace(/[.+^${}()|[\]\\]/gu, "\\$&");
|
|
23031
|
+
}
|
|
23032
|
+
regex = new RegExp(`^${source}$`, "u");
|
|
23033
|
+
globCache.set(pattern, regex);
|
|
23034
|
+
}
|
|
23035
|
+
return regex.test(file) || file.startsWith(`${pattern.replace(/\/$/u, "")}/`);
|
|
23036
|
+
}
|
|
23037
|
+
function isRiskPath(file, extra = []) {
|
|
23038
|
+
if (extra.some((pattern) => globMatch(pattern, file)))
|
|
23039
|
+
return true;
|
|
23040
|
+
if (RISK_FILES.has(file) || RISK_NAMES.has(basename(file)))
|
|
23041
|
+
return true;
|
|
23042
|
+
if (TEST_PATH.test(file) || isDoc(file))
|
|
23043
|
+
return false;
|
|
23044
|
+
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)));
|
|
23045
|
+
}
|
|
23046
|
+
var parseRiskPaths = (text) => text.split(`
|
|
23047
|
+
`).map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map((line) => line.replace(/^\//u, ""));
|
|
23048
|
+
function computeLane(input) {
|
|
23049
|
+
const riskFiles = input.files.filter((file) => isRiskPath(file.path, input.riskPaths)).map((file) => file.path);
|
|
23050
|
+
const risky = new Set(riskFiles);
|
|
23051
|
+
const kinds = input.files.map((file) => ({
|
|
23052
|
+
file,
|
|
23053
|
+
kind: risky.has(file.path) ? "behavior" : kindOf(file)
|
|
23054
|
+
}));
|
|
23055
|
+
const behavior = kinds.filter((entry) => entry.kind === "behavior" || entry.kind === "test" || entry.kind === "lockfile");
|
|
23056
|
+
const lines = behavior.filter((entry) => entry.kind !== "lockfile").reduce((sum, entry) => sum + entry.file.added + entry.file.deleted, 0);
|
|
23057
|
+
const opaque = behavior.filter((entry) => entry.kind === "lockfile" || entry.file.binary);
|
|
23058
|
+
const result = (lane, reasons) => ({
|
|
23059
|
+
lane,
|
|
23060
|
+
reasons,
|
|
23061
|
+
lines,
|
|
23062
|
+
files: behavior.length,
|
|
23063
|
+
riskFiles
|
|
23064
|
+
});
|
|
23065
|
+
const { selfMaxLines, selfMaxFiles, fullMinLines } = LANE_THRESHOLDS;
|
|
23066
|
+
if (input.riskTier === "high")
|
|
23067
|
+
return result("full", ["the task judgment records high risk"]);
|
|
23068
|
+
if (riskFiles.length)
|
|
23069
|
+
return result("full", [
|
|
23070
|
+
`touches a risk path: ${riskFiles.slice(0, 3).join(", ")}${riskFiles.length > 3 ? ", …" : ""}`
|
|
23071
|
+
]);
|
|
23072
|
+
if (!behavior.length)
|
|
23073
|
+
return result("none", [
|
|
23074
|
+
input.files.length ? "only docs, comments, formatting or generated copies changed" : "no changes"
|
|
23075
|
+
]);
|
|
23076
|
+
if (lines >= fullMinLines)
|
|
23077
|
+
return result("full", [`large diff: ${lines} lines (≥ ${fullMinLines})`]);
|
|
23078
|
+
if (lines > selfMaxLines)
|
|
23079
|
+
return result("focused", [`${lines} lines changed (> ${selfMaxLines})`]);
|
|
23080
|
+
if (behavior.length > selfMaxFiles)
|
|
23081
|
+
return result("focused", [`${behavior.length} behavior files changed (> ${selfMaxFiles})`]);
|
|
23082
|
+
if (opaque.length)
|
|
23083
|
+
return result("focused", [
|
|
23084
|
+
`a lockfile or binary changed: ${opaque.slice(0, 3).map((entry) => entry.file.path).join(", ")}${opaque.length > 3 ? ", …" : ""}`
|
|
23085
|
+
]);
|
|
23086
|
+
return result("self", [
|
|
23087
|
+
`small change: ${lines} line${lines === 1 ? "" : "s"} in ${behavior.length} file${behavior.length === 1 ? "" : "s"}, no risk path`
|
|
23088
|
+
]);
|
|
23089
|
+
}
|
|
23090
|
+
function untrackedStat(cwd, file) {
|
|
23091
|
+
try {
|
|
23092
|
+
const bytes = readFileSync4(path16.join(cwd, file));
|
|
23093
|
+
if (bytes.includes(0))
|
|
23094
|
+
return { path: file, added: 0, deleted: 0, binary: true };
|
|
23095
|
+
const text = bytes.toString("utf8");
|
|
23096
|
+
if (hasOpaqueLineBreak(text))
|
|
23097
|
+
return { path: file, added: 0, deleted: 0, binary: true };
|
|
23098
|
+
const lines = text.split(`
|
|
23099
|
+
`).length - (text.endsWith(`
|
|
23100
|
+
`) ? 1 : 0);
|
|
23101
|
+
return { path: file, added: lines, deleted: 0 };
|
|
23102
|
+
} catch {
|
|
23103
|
+
return { path: file, added: 0, deleted: 0, binary: true };
|
|
23104
|
+
}
|
|
23105
|
+
}
|
|
23106
|
+
var REGULAR = new Set(["100644", "100755"]);
|
|
23107
|
+
var ABSENT = /^0+$/u;
|
|
23108
|
+
function cosmeticFiles(cwd, fork, head) {
|
|
23109
|
+
const raw = diffRaw(cwd, fork, head);
|
|
23110
|
+
if (!raw)
|
|
23111
|
+
return null;
|
|
23112
|
+
const candidates = raw.filter((entry) => REGULAR.has(entry.oldMode) && entry.oldMode === entry.newMode && !ABSENT.test(entry.oldBlob) && (head === null || !ABSENT.test(entry.newBlob)));
|
|
23113
|
+
const blobs = readBlobs(cwd, candidates.flatMap((entry) => [entry.oldBlob, entry.newBlob]));
|
|
23114
|
+
if (!blobs)
|
|
23115
|
+
return null;
|
|
23116
|
+
const out = new Set;
|
|
23117
|
+
const opaque = new Set;
|
|
23118
|
+
for (const entry of candidates) {
|
|
23119
|
+
const before = blobs.get(entry.oldBlob);
|
|
23120
|
+
let after = blobs.get(entry.newBlob);
|
|
23121
|
+
if (!after && head === null && ABSENT.test(entry.newBlob))
|
|
23122
|
+
try {
|
|
23123
|
+
after = readFileSync4(path16.join(cwd, entry.path));
|
|
23124
|
+
} catch {
|
|
23125
|
+
after = undefined;
|
|
23126
|
+
}
|
|
23127
|
+
if (before && after && cosmeticChange(entry.path, before, after))
|
|
23128
|
+
out.add(entry.path);
|
|
23129
|
+
else if ([before, after].some((bytes) => bytes && hasOpaqueLineBreak(bytes.toString("utf8"))))
|
|
23130
|
+
opaque.add(entry.path);
|
|
23131
|
+
}
|
|
23132
|
+
return { cosmetic: out, opaque };
|
|
23133
|
+
}
|
|
23134
|
+
function generatedAt(cwd, fork, paths) {
|
|
23135
|
+
const files = treeFilesNamed(cwd, fork, ".gitattributes");
|
|
23136
|
+
const blobs = files?.size ? readBlobs(cwd, [...files.values()]) : null;
|
|
23137
|
+
if (!files || !blobs)
|
|
23138
|
+
return new Set;
|
|
23139
|
+
const texts = new Map;
|
|
23140
|
+
for (const [file, id] of files) {
|
|
23141
|
+
const bytes = blobs.get(id);
|
|
23142
|
+
if (bytes)
|
|
23143
|
+
texts.set(file, bytes.toString("utf8"));
|
|
23144
|
+
}
|
|
23145
|
+
return generatedByAttributes(texts, paths);
|
|
23146
|
+
}
|
|
23147
|
+
var forkOf = (cwd, base, head) => mergeBase(cwd, base, head ?? "HEAD");
|
|
23148
|
+
function laneFiles(cwd, fork, head) {
|
|
23149
|
+
const stats = diffNumstat(cwd, fork, head);
|
|
23150
|
+
const cosmetic = stats ? cosmeticFiles(cwd, fork, head) : null;
|
|
23151
|
+
if (!stats || !cosmetic)
|
|
23152
|
+
return null;
|
|
23153
|
+
const files = [
|
|
23154
|
+
...stats.map((entry) => ({
|
|
23155
|
+
...entry,
|
|
23156
|
+
...cosmetic.opaque.has(entry.path) ? { binary: true } : {},
|
|
23157
|
+
cosmetic: !entry.binary && cosmetic.cosmetic.has(entry.path)
|
|
23158
|
+
})),
|
|
23159
|
+
...head === null ? untrackedFiles(cwd).map((file) => untrackedStat(cwd, file)) : []
|
|
23160
|
+
];
|
|
23161
|
+
const generated = generatedAt(cwd, fork, files.map((entry) => entry.path));
|
|
23162
|
+
return files.map((entry) => ({
|
|
23163
|
+
...entry,
|
|
23164
|
+
generated: generated.has(entry.path)
|
|
23165
|
+
}));
|
|
23166
|
+
}
|
|
23167
|
+
function branchLane(cwd, options) {
|
|
23168
|
+
const candidates = options.base ? [`origin/${options.base}`, options.base] : [];
|
|
23169
|
+
const base = candidates.find((ref) => resolveRef(cwd, ref) !== null) ?? defaultBase(cwd) ?? null;
|
|
23170
|
+
const head = options.workingTree ? null : options.head;
|
|
23171
|
+
const fork = base && (options.workingTree || options.head) ? forkOf(cwd, base, head) : null;
|
|
23172
|
+
const files = fork ? laneFiles(cwd, fork, head) : null;
|
|
23173
|
+
const riskTier = options.judgment?.riskTier ?? null;
|
|
23174
|
+
if (!fork || !files) {
|
|
23175
|
+
const high = riskTier === "high";
|
|
23176
|
+
return {
|
|
23177
|
+
lane: high ? "full" : "focused",
|
|
23178
|
+
reasons: [
|
|
23179
|
+
`the diff of ${options.head?.slice(0, 12) ?? "(no head)"} against ${base ?? "(no base)"} cannot be read`,
|
|
23180
|
+
...high ? ["the task judgment records high risk"] : []
|
|
23181
|
+
],
|
|
23182
|
+
lines: 0,
|
|
23183
|
+
files: 0,
|
|
23184
|
+
riskFiles: [],
|
|
23185
|
+
base,
|
|
23186
|
+
head: options.head
|
|
23187
|
+
};
|
|
23188
|
+
}
|
|
23189
|
+
const repoRisk = parseRiskPaths(fileAt(cwd, fork, RISK_PATHS_FILE) ?? "");
|
|
23190
|
+
return {
|
|
23191
|
+
...computeLane({
|
|
23192
|
+
files,
|
|
23193
|
+
riskTier,
|
|
23194
|
+
riskPaths: [...repoRisk, ...options.riskPaths ?? []]
|
|
23195
|
+
}),
|
|
23196
|
+
base,
|
|
23197
|
+
head: options.head
|
|
23198
|
+
};
|
|
23199
|
+
}
|
|
23200
|
+
var laneNeed = (lane) => lane === "none" ? "none" : lane === "self" ? "self" : "non-author";
|
|
23201
|
+
|
|
22375
23202
|
// packages/workit-core/src/core/policy/derive.ts
|
|
22376
23203
|
var RULES = {
|
|
22377
23204
|
test: "check:test",
|
|
22378
23205
|
self: "verdict:self",
|
|
22379
23206
|
nonAuthor: "verdict:non-author",
|
|
22380
23207
|
verified: "verdict:verified",
|
|
23208
|
+
lane: "verdict:lane",
|
|
22381
23209
|
product: "decision:product",
|
|
22382
23210
|
plan: "plan"
|
|
22383
23211
|
};
|
|
@@ -22400,6 +23228,7 @@ var normalizedScope = (scope) => ({
|
|
|
22400
23228
|
function deriveRequirements(judgment, scope, constraints, verification = "self") {
|
|
22401
23229
|
const out = [];
|
|
22402
23230
|
const base = { scope, dependentAction: null };
|
|
23231
|
+
const proportional = verification === "proportional";
|
|
22403
23232
|
if (judgment.behaviorChange)
|
|
22404
23233
|
out.push(derived2({
|
|
22405
23234
|
...base,
|
|
@@ -22410,7 +23239,17 @@ function deriveRequirements(judgment, scope, constraints, verification = "self")
|
|
|
22410
23239
|
before: "close",
|
|
22411
23240
|
acceptanceAllowed: false
|
|
22412
23241
|
}));
|
|
22413
|
-
if (
|
|
23242
|
+
if (proportional && judgment.riskTier === "normal")
|
|
23243
|
+
out.push(derived2({
|
|
23244
|
+
...base,
|
|
23245
|
+
ruleId: RULES.lane,
|
|
23246
|
+
dimension: "review",
|
|
23247
|
+
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.",
|
|
23248
|
+
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.",
|
|
23249
|
+
before: "close",
|
|
23250
|
+
acceptanceAllowed: false
|
|
23251
|
+
}));
|
|
23252
|
+
if (!proportional && judgment.behaviorChange && judgment.riskTier === "normal")
|
|
22414
23253
|
out.push(verification === "independent" ? derived2({
|
|
22415
23254
|
...base,
|
|
22416
23255
|
ruleId: RULES.nonAuthor,
|
|
@@ -22513,7 +23352,7 @@ var productDecision = (task, ledger) => {
|
|
|
22513
23352
|
};
|
|
22514
23353
|
};
|
|
22515
23354
|
var planRecorded = (task, root) => {
|
|
22516
|
-
const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" &&
|
|
23355
|
+
const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync5(path17.resolve(root, ref.path)));
|
|
22517
23356
|
if (cited)
|
|
22518
23357
|
return {
|
|
22519
23358
|
met: true,
|
|
@@ -22527,14 +23366,30 @@ var planRecorded = (task, root) => {
|
|
|
22527
23366
|
decisionIds: []
|
|
22528
23367
|
};
|
|
22529
23368
|
};
|
|
22530
|
-
var
|
|
23369
|
+
var workingLane = (task, root) => branchLane(root, { head: null, workingTree: true, judgment: latestJudgment(task) });
|
|
23370
|
+
var laneVerdict = (task, root, ledger) => {
|
|
23371
|
+
if (!ledger.branch() && latestJudgment(task)?.behaviorChange === false)
|
|
23372
|
+
return {
|
|
23373
|
+
met: true,
|
|
23374
|
+
reason: "no branch to read a lane from, and the judgment records no behavior change",
|
|
23375
|
+
decisionIds: []
|
|
23376
|
+
};
|
|
23377
|
+
const lane = workingLane(task, root);
|
|
23378
|
+
const label = `lane ${lane.lane} (${lane.reasons.join("; ")})`;
|
|
23379
|
+
const need = laneNeed(lane.lane);
|
|
23380
|
+
if (need === "none")
|
|
23381
|
+
return { met: true, reason: `${label}: no verdict needed`, decisionIds: [] };
|
|
23382
|
+
const status = verdict(need === "self" ? RULES.self : RULES.nonAuthor, root, ledger);
|
|
23383
|
+
return { ...status, reason: `${label}: ${status.reason}` };
|
|
23384
|
+
};
|
|
23385
|
+
var verdict = (ruleId, root, ledger) => {
|
|
22531
23386
|
const branch = ledger.branch();
|
|
22532
23387
|
if (!branch)
|
|
22533
23388
|
return { met: false, reason: "no branch is checked out to hold a verdict", decisionIds: [] };
|
|
22534
23389
|
const check = checkVerdicts(root, branch, ledger.rows());
|
|
22535
23390
|
const failing = check.accepted.reasons.includes("failing_verdict");
|
|
22536
23391
|
const strong = (entry) => STRONG_RESULTS.has(String(entry.verdict.result));
|
|
22537
|
-
const met = !failing && (
|
|
23392
|
+
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)));
|
|
22538
23393
|
if (met)
|
|
22539
23394
|
return {
|
|
22540
23395
|
met: true,
|
|
@@ -22542,7 +23397,7 @@ var verdict = (requirement, root, ledger) => {
|
|
|
22542
23397
|
decisionIds: []
|
|
22543
23398
|
};
|
|
22544
23399
|
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, " ");
|
|
22545
|
-
const unblock =
|
|
23400
|
+
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>\``;
|
|
22546
23401
|
return { met: false, reason: `${why}: ${unblock}`, decisionIds: [] };
|
|
22547
23402
|
};
|
|
22548
23403
|
function derivedRuleStatus(task, requirement, root, ledger) {
|
|
@@ -22554,7 +23409,9 @@ function derivedRuleStatus(task, requirement, root, ledger) {
|
|
|
22554
23409
|
case RULES.self:
|
|
22555
23410
|
case RULES.nonAuthor:
|
|
22556
23411
|
case RULES.verified:
|
|
22557
|
-
return verdict(requirement, root, ledger);
|
|
23412
|
+
return verdict(requirement.ruleId, root, ledger);
|
|
23413
|
+
case RULES.lane:
|
|
23414
|
+
return laneVerdict(task, root, ledger);
|
|
22558
23415
|
default:
|
|
22559
23416
|
return null;
|
|
22560
23417
|
}
|
|
@@ -22562,14 +23419,14 @@ function derivedRuleStatus(task, requirement, root, ledger) {
|
|
|
22562
23419
|
|
|
22563
23420
|
// packages/workit-core/src/core/task-evaluation.ts
|
|
22564
23421
|
var digestBytes = (value) => createHash10("sha256").update(value).digest("hex");
|
|
22565
|
-
var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${
|
|
22566
|
-
var relative = (root, candidate) =>
|
|
23422
|
+
var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path18.sep}`);
|
|
23423
|
+
var relative = (root, candidate) => path18.relative(root, candidate).split(path18.sep).join("/") || ".";
|
|
22567
23424
|
var canonicalPath = (value) => {
|
|
22568
23425
|
if (typeof value !== "string" || !value)
|
|
22569
23426
|
return null;
|
|
22570
23427
|
if (value.includes("\\") || value.split("/").includes(".."))
|
|
22571
23428
|
return null;
|
|
22572
|
-
const normalized =
|
|
23429
|
+
const normalized = path18.posix.normalize(value);
|
|
22573
23430
|
if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
|
|
22574
23431
|
return null;
|
|
22575
23432
|
return normalized === "." ? "." : normalized.replace(/\/$/, "");
|
|
@@ -22605,7 +23462,7 @@ var compareCodeUnits2 = (left, right) => {
|
|
|
22605
23462
|
return left.length - right.length;
|
|
22606
23463
|
};
|
|
22607
23464
|
var gitPaths = (root) => {
|
|
22608
|
-
const result =
|
|
23465
|
+
const result = spawnSync11("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], {
|
|
22609
23466
|
cwd: root,
|
|
22610
23467
|
encoding: "buffer"
|
|
22611
23468
|
});
|
|
@@ -22617,21 +23474,21 @@ var gitPaths = (root) => {
|
|
|
22617
23474
|
git: !/not a git repository/i.test(stderr)
|
|
22618
23475
|
};
|
|
22619
23476
|
}
|
|
22620
|
-
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(
|
|
22621
|
-
const stagedDeleted =
|
|
23477
|
+
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path18.sep).join("/")) : [];
|
|
23478
|
+
const stagedDeleted = spawnSync11("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
|
|
22622
23479
|
if (stagedDeleted.status !== 0) {
|
|
22623
23480
|
const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
|
|
22624
23481
|
if (!/not a git repository/i.test(stderr))
|
|
22625
23482
|
return { paths, uncertain: true, git: true };
|
|
22626
23483
|
} else if (stagedDeleted.stdout) {
|
|
22627
|
-
paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(
|
|
23484
|
+
paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path18.sep).join("/")));
|
|
22628
23485
|
}
|
|
22629
23486
|
return { paths: [...new Set(paths)], uncertain: false, git: true };
|
|
22630
23487
|
};
|
|
22631
23488
|
var walk = (root, directory, output) => {
|
|
22632
23489
|
let names;
|
|
22633
23490
|
try {
|
|
22634
|
-
names =
|
|
23491
|
+
names = fs14.readdirSync(directory);
|
|
22635
23492
|
} catch {
|
|
22636
23493
|
return true;
|
|
22637
23494
|
}
|
|
@@ -22639,10 +23496,10 @@ var walk = (root, directory, output) => {
|
|
|
22639
23496
|
for (const name of names) {
|
|
22640
23497
|
if (name === ".git" || name === ".workit")
|
|
22641
23498
|
continue;
|
|
22642
|
-
const target =
|
|
23499
|
+
const target = path18.join(directory, name);
|
|
22643
23500
|
let stat;
|
|
22644
23501
|
try {
|
|
22645
|
-
stat =
|
|
23502
|
+
stat = fs14.lstatSync(target);
|
|
22646
23503
|
} catch {
|
|
22647
23504
|
uncertain = true;
|
|
22648
23505
|
continue;
|
|
@@ -22657,14 +23514,14 @@ var walk = (root, directory, output) => {
|
|
|
22657
23514
|
var scopeRoots = (root, scope) => {
|
|
22658
23515
|
const roots = [];
|
|
22659
23516
|
for (const item of scope.paths.length ? scope.paths : ["."]) {
|
|
22660
|
-
const target =
|
|
23517
|
+
const target = path18.resolve(root, item);
|
|
22661
23518
|
if (!inside(root, target))
|
|
22662
23519
|
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` }] });
|
|
22663
23520
|
let ancestor = target;
|
|
22664
|
-
while (!
|
|
22665
|
-
ancestor =
|
|
23521
|
+
while (!fs14.existsSync(ancestor) && ancestor !== root)
|
|
23522
|
+
ancestor = path18.dirname(ancestor);
|
|
22666
23523
|
try {
|
|
22667
|
-
if (!inside(root,
|
|
23524
|
+
if (!inside(root, fs14.realpathSync(ancestor)))
|
|
22668
23525
|
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` }] });
|
|
22669
23526
|
} catch {
|
|
22670
23527
|
return failure2("invalid_input", `candidate scope cannot be inspected: ${item}`);
|
|
@@ -22676,7 +23533,7 @@ var scopeRoots = (root, scope) => {
|
|
|
22676
23533
|
function captureCandidate(root, scope, environment = []) {
|
|
22677
23534
|
let checkout;
|
|
22678
23535
|
try {
|
|
22679
|
-
checkout =
|
|
23536
|
+
checkout = fs14.realpathSync(root);
|
|
22680
23537
|
} catch {
|
|
22681
23538
|
return failure2("invalid_input", "candidate root does not exist");
|
|
22682
23539
|
}
|
|
@@ -22694,11 +23551,11 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
22694
23551
|
if (item === ".git" || item === ".workit")
|
|
22695
23552
|
continue;
|
|
22696
23553
|
names.add(item);
|
|
22697
|
-
if (!
|
|
23554
|
+
if (!fs14.existsSync(target))
|
|
22698
23555
|
continue;
|
|
22699
23556
|
let stat;
|
|
22700
23557
|
try {
|
|
22701
|
-
stat =
|
|
23558
|
+
stat = fs14.lstatSync(target);
|
|
22702
23559
|
} catch {
|
|
22703
23560
|
uncertain = true;
|
|
22704
23561
|
continue;
|
|
@@ -22714,17 +23571,17 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
22714
23571
|
for (const item of [...names].toSorted()) {
|
|
22715
23572
|
if (!scopeMatches(item, normalizedScope))
|
|
22716
23573
|
continue;
|
|
22717
|
-
const target =
|
|
23574
|
+
const target = path18.join(checkout, item);
|
|
22718
23575
|
try {
|
|
22719
|
-
const stat =
|
|
23576
|
+
const stat = fs14.lstatSync(target);
|
|
22720
23577
|
if (stat.isSymbolicLink()) {
|
|
22721
|
-
const link =
|
|
23578
|
+
const link = fs14.readlinkSync(target);
|
|
22722
23579
|
files.push({ path: item, kind: "symlink", digest: digestBytes(link), executable: null });
|
|
22723
23580
|
} else if (stat.isFile()) {
|
|
22724
23581
|
files.push({
|
|
22725
23582
|
path: item,
|
|
22726
23583
|
kind: "file",
|
|
22727
|
-
digest: digestBytes(
|
|
23584
|
+
digest: digestBytes(fs14.readFileSync(target)),
|
|
22728
23585
|
executable: (stat.mode & 73) !== 0
|
|
22729
23586
|
});
|
|
22730
23587
|
} else if (!stat.isDirectory()) {
|
|
@@ -22749,7 +23606,7 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
22749
23606
|
const values = supplied.toSorted((left, right) => compareCodeUnits2(left.name, right.name)).map(({ name, value }) => ({ name, value, refs: [] }));
|
|
22750
23607
|
if (values.some(({ value }) => value === null))
|
|
22751
23608
|
completeness = "uncertain";
|
|
22752
|
-
const headResult =
|
|
23609
|
+
const headResult = spawnSync11("git", ["rev-parse", "HEAD"], { cwd: checkout, encoding: "utf8" });
|
|
22753
23610
|
if (headResult.status !== 0 && !/not a git repository/i.test(headResult.stderr ?? ""))
|
|
22754
23611
|
completeness = "uncertain";
|
|
22755
23612
|
const head = headResult.status === 0 ? headResult.stdout.trim() : null;
|
|
@@ -22889,7 +23746,7 @@ var findingVerificationPasses = (findingCandidateId, evidence) => evidence.statu
|
|
|
22889
23746
|
var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
22890
23747
|
let root;
|
|
22891
23748
|
try {
|
|
22892
|
-
root =
|
|
23749
|
+
root = fs14.realpathSync(checkoutRoot);
|
|
22893
23750
|
} catch {
|
|
22894
23751
|
return failure2("permission_denied", "checkout root is unavailable");
|
|
22895
23752
|
}
|
|
@@ -22898,23 +23755,23 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
|
22898
23755
|
continue;
|
|
22899
23756
|
if (!reference.digest)
|
|
22900
23757
|
return failure2("invalid_input", "document references require a byte digest");
|
|
22901
|
-
const target =
|
|
22902
|
-
if (target !== root && !target.startsWith(`${root}${
|
|
23758
|
+
const target = path18.resolve(root, reference.path);
|
|
23759
|
+
if (target !== root && !target.startsWith(`${root}${path18.sep}`))
|
|
22903
23760
|
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
22904
23761
|
fields: [
|
|
22905
23762
|
{ path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
|
|
22906
23763
|
]
|
|
22907
23764
|
});
|
|
22908
23765
|
try {
|
|
22909
|
-
const below =
|
|
23766
|
+
const below = path18.relative(root, target);
|
|
22910
23767
|
let current = root;
|
|
22911
|
-
for (const segment of below.split(
|
|
23768
|
+
for (const segment of below.split(path18.sep)) {
|
|
22912
23769
|
if (!segment)
|
|
22913
23770
|
continue;
|
|
22914
|
-
current =
|
|
22915
|
-
const stat =
|
|
22916
|
-
const real =
|
|
22917
|
-
if (real !== root && !real.startsWith(`${root}${
|
|
23771
|
+
current = path18.join(current, segment);
|
|
23772
|
+
const stat = fs14.lstatSync(current);
|
|
23773
|
+
const real = fs14.realpathSync(current);
|
|
23774
|
+
if (real !== root && !real.startsWith(`${root}${path18.sep}`))
|
|
22918
23775
|
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
22919
23776
|
fields: [
|
|
22920
23777
|
{
|
|
@@ -22930,7 +23787,7 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
|
22930
23787
|
if (current !== target && !stat.isDirectory())
|
|
22931
23788
|
return failure2("invalid_input", "document reference ancestor is not a directory");
|
|
22932
23789
|
}
|
|
22933
|
-
if (digestBytes(
|
|
23790
|
+
if (digestBytes(fs14.readFileSync(target)) !== reference.digest)
|
|
22934
23791
|
return failure2("permission_denied", "decision document bytes have changed");
|
|
22935
23792
|
} catch {
|
|
22936
23793
|
return failure2("invalid_input", "decision document is unavailable");
|
|
@@ -23773,7 +24630,7 @@ var judgeInputSummary = (raw) => {
|
|
|
23773
24630
|
|
|
23774
24631
|
// packages/workit-core/src/autonomy.ts
|
|
23775
24632
|
import os4 from "node:os";
|
|
23776
|
-
import
|
|
24633
|
+
import path19 from "node:path";
|
|
23777
24634
|
var accountHome = () => {
|
|
23778
24635
|
try {
|
|
23779
24636
|
return os4.userInfo().homedir;
|
|
@@ -23782,10 +24639,10 @@ var accountHome = () => {
|
|
|
23782
24639
|
}
|
|
23783
24640
|
};
|
|
23784
24641
|
var grantsHome = { resolve: accountHome };
|
|
23785
|
-
var grantsDir = () =>
|
|
24642
|
+
var grantsDir = () => path19.join(grantsHome.resolve(), ".config", "workit");
|
|
23786
24643
|
var grantsOverride = () => {
|
|
23787
|
-
const configured =
|
|
23788
|
-
return configured ===
|
|
24644
|
+
const configured = path19.resolve(resolveConfigDir());
|
|
24645
|
+
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`;
|
|
23789
24646
|
};
|
|
23790
24647
|
var GRANT_KINDS = ["push", "pr", "merge", "release", "rerun"];
|
|
23791
24648
|
var DEFAULT_GRANTS = Object.freeze({
|
|
@@ -23838,8 +24695,16 @@ function endpointView(entry, context) {
|
|
|
23838
24695
|
...issue ? { endpointIssue: issue } : {}
|
|
23839
24696
|
};
|
|
23840
24697
|
}
|
|
23841
|
-
var
|
|
23842
|
-
|
|
24698
|
+
var VERIFICATION_MODES = [
|
|
24699
|
+
"proportional",
|
|
24700
|
+
"self",
|
|
24701
|
+
"independent"
|
|
24702
|
+
];
|
|
24703
|
+
var DEFAULT_VERIFICATION = "proportional";
|
|
24704
|
+
var verificationOf = (entry) => {
|
|
24705
|
+
const value = entry?.verification;
|
|
24706
|
+
return VERIFICATION_MODES.includes(value) ? value : DEFAULT_VERIFICATION;
|
|
24707
|
+
};
|
|
23843
24708
|
var isGrantValue = (value) => value === true || value === false || value === "verified";
|
|
23844
24709
|
var normalized = (kind, value) => value === "verified" && kind !== "merge" ? true : value;
|
|
23845
24710
|
var fromAutoApprove = (value) => {
|
|
@@ -25586,9 +26451,9 @@ class WorkitCore {
|
|
|
25586
26451
|
}
|
|
25587
26452
|
}
|
|
25588
26453
|
// packages/workit-core/src/core/repo-context.ts
|
|
25589
|
-
import { spawnSync as
|
|
25590
|
-
import { existsSync as
|
|
25591
|
-
import
|
|
26454
|
+
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
26455
|
+
import { existsSync as existsSync7, readFileSync as readFileSync6, readdirSync as readdirSync4 } from "node:fs";
|
|
26456
|
+
import path20 from "node:path";
|
|
25592
26457
|
var isSafeContextRange = (value) => value.length <= 4096 && (() => {
|
|
25593
26458
|
try {
|
|
25594
26459
|
gitRevisionParts(value);
|
|
@@ -25615,7 +26480,7 @@ var invalidRange = (cwd) => ({
|
|
|
25615
26480
|
cwd
|
|
25616
26481
|
});
|
|
25617
26482
|
var runGit = (cwd, args) => {
|
|
25618
|
-
const result =
|
|
26483
|
+
const result = spawnSync12("git", args, { cwd, encoding: "utf8" });
|
|
25619
26484
|
return {
|
|
25620
26485
|
stdout: (result.stdout ?? "").trimEnd(),
|
|
25621
26486
|
stderr: (result.stderr ?? "").trimEnd(),
|
|
@@ -25722,7 +26587,7 @@ var findPrTemplate = (cwd) => {
|
|
|
25722
26587
|
]) {
|
|
25723
26588
|
const parts = rel.split("/");
|
|
25724
26589
|
const base = parts[parts.length - 1];
|
|
25725
|
-
const dir = parts.length > 1 ?
|
|
26590
|
+
const dir = parts.length > 1 ? path20.join(cwd, ...parts.slice(0, -1)) : cwd;
|
|
25726
26591
|
const actual = probeCaseInsensitive(dir, base);
|
|
25727
26592
|
if (actual)
|
|
25728
26593
|
return [...parts.slice(0, -1), actual].join("/");
|
|
@@ -25753,11 +26618,11 @@ var diffStatForRange = (cwd, range) => {
|
|
|
25753
26618
|
return runGit(cwd, ["diff", "--stat", "--"]).stdout;
|
|
25754
26619
|
};
|
|
25755
26620
|
var packageScripts = (cwd, keys) => {
|
|
25756
|
-
const pkgPath =
|
|
25757
|
-
if (!
|
|
26621
|
+
const pkgPath = path20.join(cwd, "package.json");
|
|
26622
|
+
if (!existsSync7(pkgPath))
|
|
25758
26623
|
return [];
|
|
25759
26624
|
try {
|
|
25760
|
-
const pkg = JSON.parse(
|
|
26625
|
+
const pkg = JSON.parse(readFileSync6(pkgPath, "utf8"));
|
|
25761
26626
|
return keys.filter((k) => pkg.scripts && typeof pkg.scripts[k] === "string").map((k) => `${k}: ${pkg.scripts?.[k]}`);
|
|
25762
26627
|
} catch {
|
|
25763
26628
|
return [];
|
|
@@ -25779,9 +26644,9 @@ var documentationFiles = (cwd) => {
|
|
|
25779
26644
|
if (entry.isDirectory()) {
|
|
25780
26645
|
if (excluded.has(entry.name))
|
|
25781
26646
|
continue;
|
|
25782
|
-
walk(
|
|
26647
|
+
walk(path20.join(dir, entry.name), depth + 1);
|
|
25783
26648
|
} else if (entry.isFile() && (entry.name === "README.md" || entry.name.endsWith(".md"))) {
|
|
25784
|
-
matches.push("./" +
|
|
26649
|
+
matches.push("./" + path20.relative(cwd, path20.join(dir, entry.name)).replaceAll("\\", "/"));
|
|
25785
26650
|
}
|
|
25786
26651
|
}
|
|
25787
26652
|
};
|
|
@@ -25789,15 +26654,15 @@ var documentationFiles = (cwd) => {
|
|
|
25789
26654
|
return matches.toSorted().slice(0, 200);
|
|
25790
26655
|
};
|
|
25791
26656
|
var readTrimmed2 = (file, maxLines) => {
|
|
25792
|
-
if (!
|
|
26657
|
+
if (!existsSync7(file))
|
|
25793
26658
|
return "";
|
|
25794
|
-
const lines =
|
|
26659
|
+
const lines = readFileSync6(file, "utf8").split(`
|
|
25795
26660
|
`);
|
|
25796
26661
|
return lines.slice(0, maxLines).join(`
|
|
25797
26662
|
`);
|
|
25798
26663
|
};
|
|
25799
26664
|
function prReadyContext(root, range) {
|
|
25800
|
-
const cwd =
|
|
26665
|
+
const cwd = path20.resolve(repoRoot(root));
|
|
25801
26666
|
if (range !== undefined && !isResolvableContextRange(cwd, range))
|
|
25802
26667
|
return invalidRange(cwd);
|
|
25803
26668
|
let stdout = "";
|
|
@@ -25855,7 +26720,7 @@ ${status.stderr}` : "");
|
|
|
25855
26720
|
stdout += `template_path: ${template}
|
|
25856
26721
|
|
|
25857
26722
|
`;
|
|
25858
|
-
stdout += readTrimmed2(
|
|
26723
|
+
stdout += readTrimmed2(path20.join(cwd, template), 220);
|
|
25859
26724
|
} else {
|
|
25860
26725
|
stdout += `template_path: none
|
|
25861
26726
|
|
|
@@ -25865,7 +26730,7 @@ ${status.stderr}` : "");
|
|
|
25865
26730
|
stdout += `
|
|
25866
26731
|
`;
|
|
25867
26732
|
stdout += printSection("Recent Validation Signals");
|
|
25868
|
-
if (
|
|
26733
|
+
if (existsSync7(path20.join(cwd, "package.json"))) {
|
|
25869
26734
|
stdout += `package.json detected. Common scripts:
|
|
25870
26735
|
`;
|
|
25871
26736
|
const found = packageScripts(cwd, ["lint", "format:check", "test", "build"]);
|
|
@@ -25874,7 +26739,7 @@ ${status.stderr}` : "");
|
|
|
25874
26739
|
`) + `
|
|
25875
26740
|
`;
|
|
25876
26741
|
}
|
|
25877
|
-
if (
|
|
26742
|
+
if (existsSync7(path20.join(cwd, "Cargo.toml")) || existsSync7(path20.join(cwd, "src-tauri/Cargo.toml"))) {
|
|
25878
26743
|
stdout += `Rust project detected.
|
|
25879
26744
|
`;
|
|
25880
26745
|
}
|
|
@@ -25907,7 +26772,7 @@ var CHANGELOG_RULES = `- Use an [Unreleased] section.
|
|
|
25907
26772
|
- Apply with the host-native editor, preserving the repository changelog conventions.
|
|
25908
26773
|
- If Unreleased already has duplicate category headings, normalize_only first.`;
|
|
25909
26774
|
function changelogContext(root, range) {
|
|
25910
|
-
const cwd =
|
|
26775
|
+
const cwd = path20.resolve(repoRoot(root));
|
|
25911
26776
|
if (range !== undefined && !isResolvableContextRange(cwd, range))
|
|
25912
26777
|
return invalidRange(cwd);
|
|
25913
26778
|
const resolvedRange = rangeArgOrDefault(range, cwd);
|
|
@@ -25925,8 +26790,8 @@ function changelogContext(root, range) {
|
|
|
25925
26790
|
stdout += CHANGELOG_RULES + `
|
|
25926
26791
|
`;
|
|
25927
26792
|
stdout += printSection("Existing CHANGELOG.md");
|
|
25928
|
-
const changelogPath =
|
|
25929
|
-
if (
|
|
26793
|
+
const changelogPath = path20.join(cwd, "CHANGELOG.md");
|
|
26794
|
+
if (existsSync7(changelogPath)) {
|
|
25930
26795
|
stdout += readTrimmed2(changelogPath, 260) + `
|
|
25931
26796
|
`;
|
|
25932
26797
|
} else {
|
|
@@ -25945,7 +26810,7 @@ function changelogContext(root, range) {
|
|
|
25945
26810
|
return { stdout, stderr: "", exitCode: 0, cwd };
|
|
25946
26811
|
}
|
|
25947
26812
|
function docsRefreshContext(root, range) {
|
|
25948
|
-
const cwd =
|
|
26813
|
+
const cwd = path20.resolve(repoRoot(root));
|
|
25949
26814
|
if (range !== undefined && !isResolvableContextRange(cwd, range))
|
|
25950
26815
|
return invalidRange(cwd);
|
|
25951
26816
|
const resolvedRange = rangeArgOrDefault(range, cwd);
|
|
@@ -25967,8 +26832,8 @@ function docsRefreshContext(root, range) {
|
|
|
25967
26832
|
`) + `
|
|
25968
26833
|
`;
|
|
25969
26834
|
stdout += printSection("README Preview");
|
|
25970
|
-
const readme =
|
|
25971
|
-
if (
|
|
26835
|
+
const readme = path20.join(cwd, "README.md");
|
|
26836
|
+
if (existsSync7(readme)) {
|
|
25972
26837
|
stdout += readTrimmed2(readme, 220) + `
|
|
25973
26838
|
`;
|
|
25974
26839
|
} else {
|
|
@@ -25976,10 +26841,10 @@ function docsRefreshContext(root, range) {
|
|
|
25976
26841
|
`;
|
|
25977
26842
|
}
|
|
25978
26843
|
stdout += printSection("Package Scripts");
|
|
25979
|
-
const pkgPath =
|
|
25980
|
-
if (
|
|
26844
|
+
const pkgPath = path20.join(cwd, "package.json");
|
|
26845
|
+
if (existsSync7(pkgPath)) {
|
|
25981
26846
|
try {
|
|
25982
|
-
const pkg = JSON.parse(
|
|
26847
|
+
const pkg = JSON.parse(readFileSync6(pkgPath, "utf8"));
|
|
25983
26848
|
stdout += JSON.stringify({ name: pkg.name, version: pkg.version, scripts: pkg.scripts }, null, 2) + `
|
|
25984
26849
|
`;
|
|
25985
26850
|
} catch {}
|
|
@@ -25990,7 +26855,7 @@ function docsRefreshContext(root, range) {
|
|
|
25990
26855
|
return { stdout, stderr: "", exitCode: 0, cwd };
|
|
25991
26856
|
}
|
|
25992
26857
|
function releaseNotesContext(root, rangeOrTag) {
|
|
25993
|
-
const cwd =
|
|
26858
|
+
const cwd = path20.resolve(repoRoot(root));
|
|
25994
26859
|
if (!rangeOrTag) {
|
|
25995
26860
|
return { stdout: "", stderr: `ERROR: release tag or range required
|
|
25996
26861
|
`, exitCode: 1, cwd };
|
|
@@ -26028,7 +26893,7 @@ function releaseNotesContext(root, rangeOrTag) {
|
|
|
26028
26893
|
`;
|
|
26029
26894
|
stdout += printSection("Existing Release Files");
|
|
26030
26895
|
for (const rel of ["CHANGELOG.md", "RELEASE_NOTES.md", ".github/releases.md"]) {
|
|
26031
|
-
if (
|
|
26896
|
+
if (existsSync7(path20.join(cwd, rel)))
|
|
26032
26897
|
stdout += rel + `
|
|
26033
26898
|
`;
|
|
26034
26899
|
}
|
|
@@ -26057,46 +26922,6 @@ function releaseNotesContext(root, rangeOrTag) {
|
|
|
26057
26922
|
|
|
26058
26923
|
// packages/workit-core/src/core/tracker-issues.ts
|
|
26059
26924
|
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
26060
|
-
|
|
26061
|
-
// packages/workit-core/src/core/pr-create.ts
|
|
26062
|
-
import fs14 from "node:fs";
|
|
26063
|
-
import path19 from "node:path";
|
|
26064
|
-
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
26065
|
-
// packages/workit-core/src/forge/pr-body.ts
|
|
26066
|
-
function parseGhIssue(value) {
|
|
26067
|
-
const m = /issues\/(\d+)/.exec(value);
|
|
26068
|
-
return m ? m[1] : String(value).trim().replace(/^#/, "");
|
|
26069
|
-
}
|
|
26070
|
-
|
|
26071
|
-
// packages/workit-core/src/core/pr-create.ts
|
|
26072
|
-
function whichOnPath(tool) {
|
|
26073
|
-
const names = process.platform === "win32" ? [tool, `${tool}.exe`, `${tool}.cmd`] : [tool];
|
|
26074
|
-
for (const dir of (process.env.PATH ?? "").split(path19.delimiter)) {
|
|
26075
|
-
if (!dir)
|
|
26076
|
-
continue;
|
|
26077
|
-
for (const name of names) {
|
|
26078
|
-
const candidate = path19.join(dir, name);
|
|
26079
|
-
try {
|
|
26080
|
-
fs14.accessSync(candidate, fs14.constants.X_OK);
|
|
26081
|
-
return candidate;
|
|
26082
|
-
} catch {}
|
|
26083
|
-
}
|
|
26084
|
-
}
|
|
26085
|
-
return null;
|
|
26086
|
-
}
|
|
26087
|
-
var hostingCliAvailable = (provider) => whichOnPath(provider === "gitlab" ? "glab" : "gh") !== null;
|
|
26088
|
-
var pushRemote = (cwd) => {
|
|
26089
|
-
const result = spawnSync12("git", ["remote", "get-url", "--push", "--all", "origin"], {
|
|
26090
|
-
cwd,
|
|
26091
|
-
encoding: "utf8"
|
|
26092
|
-
});
|
|
26093
|
-
if (result.status !== 0)
|
|
26094
|
-
return null;
|
|
26095
|
-
const urls = (result.stdout ?? "").split(/\r?\n/u).map((url) => url.trim()).filter(Boolean);
|
|
26096
|
-
return urls.length === 1 ? urls[0] : null;
|
|
26097
|
-
};
|
|
26098
|
-
|
|
26099
|
-
// packages/workit-core/src/core/tracker-issues.ts
|
|
26100
26925
|
var repoPathFromRemote = (remote) => {
|
|
26101
26926
|
let rest = (remote || "").trim().replace(/\/+$/, "");
|
|
26102
26927
|
if (!rest)
|
|
@@ -26196,7 +27021,7 @@ var fetchGitLabIssueBody = async (ref, root, deps = {}) => {
|
|
|
26196
27021
|
|
|
26197
27022
|
// packages/workit-core/src/core/youtrack.ts
|
|
26198
27023
|
import fs15 from "node:fs";
|
|
26199
|
-
import
|
|
27024
|
+
import path21 from "node:path";
|
|
26200
27025
|
|
|
26201
27026
|
// packages/workit-core/src/core/templates.ts
|
|
26202
27027
|
var repoRoot2 = assetRoot();
|
|
@@ -26209,8 +27034,8 @@ var resolveWorkspaceRoot = (explicit) => explicit || process.cwd();
|
|
|
26209
27034
|
// packages/workit-core/src/core/youtrack.ts
|
|
26210
27035
|
var ISSUE_RE = /^[A-Z]+-\d+$/;
|
|
26211
27036
|
var TOKEN_PLACEHOLDER = "YOUR_TOKEN_HERE";
|
|
26212
|
-
var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ??
|
|
26213
|
-
var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ??
|
|
27037
|
+
var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path21.join(configDir(), "youtrack.json");
|
|
27038
|
+
var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path21.join(resolveConfigDir(), "youtrack.json");
|
|
26214
27039
|
var youTrackTokenModeOk = (p) => {
|
|
26215
27040
|
if (process.platform === "win32")
|
|
26216
27041
|
return true;
|
|
@@ -26278,7 +27103,7 @@ var youTrackToken = () => {
|
|
|
26278
27103
|
if ("error" in loaded)
|
|
26279
27104
|
return loaded;
|
|
26280
27105
|
const tokenFile = String(loaded.config.tokenFile ?? "");
|
|
26281
|
-
const tokenPath = tokenFile ?
|
|
27106
|
+
const tokenPath = tokenFile ? path21.isAbsolute(tokenFile) ? path21.resolve(tokenFile) : path21.resolve(process.cwd(), tokenFile) : "";
|
|
26282
27107
|
if (!tokenPath || !fs15.existsSync(tokenPath))
|
|
26283
27108
|
return { error: "missing youtrack.token" };
|
|
26284
27109
|
if (!youTrackTokenModeOk(tokenPath))
|
|
@@ -26620,15 +27445,15 @@ function resolveGitRevision(root, value) {
|
|
|
26620
27445
|
}
|
|
26621
27446
|
function resolveInside(root, candidate) {
|
|
26622
27447
|
const base = realpathSync5(root);
|
|
26623
|
-
const target =
|
|
26624
|
-
if (target !== base && !target.startsWith(base +
|
|
27448
|
+
const target = path22.resolve(base, candidate);
|
|
27449
|
+
if (target !== base && !target.startsWith(base + path22.sep)) {
|
|
26625
27450
|
throw new Error("path must stay inside repository root");
|
|
26626
27451
|
}
|
|
26627
27452
|
let ancestor = target;
|
|
26628
|
-
while (!
|
|
26629
|
-
ancestor =
|
|
27453
|
+
while (!existsSync8(ancestor))
|
|
27454
|
+
ancestor = path22.dirname(ancestor);
|
|
26630
27455
|
const canonicalAncestor = realpathSync5(ancestor);
|
|
26631
|
-
if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base +
|
|
27456
|
+
if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path22.sep)) {
|
|
26632
27457
|
throw new Error("path must stay inside repository root");
|
|
26633
27458
|
}
|
|
26634
27459
|
return target;
|
|
@@ -26676,7 +27501,7 @@ var safeCapability = (value, allowed) => allowed.includes(value) ? value : "cont
|
|
|
26676
27501
|
var TOOL_CAPABILITIES = [...CONTEXT_KINDS, "workspace", "native_caller_identity"];
|
|
26677
27502
|
var VERSION = (() => {
|
|
26678
27503
|
try {
|
|
26679
|
-
const packageJson = JSON.parse(
|
|
27504
|
+
const packageJson = JSON.parse(readFileSync7(new URL("../package.json", import.meta.url), "utf8"));
|
|
26680
27505
|
return typeof packageJson.version === "string" ? packageJson.version : "0.0.0";
|
|
26681
27506
|
} catch {
|
|
26682
27507
|
return "0.0.0";
|
|
@@ -26686,13 +27511,13 @@ var rootVariants = (workspaceRoot) => {
|
|
|
26686
27511
|
if (!workspaceRoot)
|
|
26687
27512
|
return [];
|
|
26688
27513
|
const roots = new Set;
|
|
26689
|
-
for (const candidate of [workspaceRoot,
|
|
26690
|
-
if (
|
|
27514
|
+
for (const candidate of [workspaceRoot, path23.resolve(workspaceRoot)]) {
|
|
27515
|
+
if (path23.isAbsolute(candidate) && candidate !== path23.parse(candidate).root)
|
|
26691
27516
|
roots.add(candidate);
|
|
26692
27517
|
}
|
|
26693
27518
|
try {
|
|
26694
27519
|
const canonical = realpathSync6(workspaceRoot);
|
|
26695
|
-
if (canonical !==
|
|
27520
|
+
if (canonical !== path23.parse(canonical).root)
|
|
26696
27521
|
roots.add(canonical);
|
|
26697
27522
|
} catch {}
|
|
26698
27523
|
return [...roots].toSorted((left, right) => right.length - left.length);
|
|
@@ -26774,12 +27599,12 @@ var thrownResult = (tool, error, workspaceRoot) => {
|
|
|
26774
27599
|
};
|
|
26775
27600
|
function createMcpServer(host, contextProvider) {
|
|
26776
27601
|
assertMcpHost(host);
|
|
26777
|
-
const here =
|
|
27602
|
+
const here = path23.dirname(fileURLToPath2(import.meta.url));
|
|
26778
27603
|
const sourceMarker = markSourcesLoaded([
|
|
26779
|
-
|
|
26780
|
-
|
|
26781
|
-
|
|
26782
|
-
].filter((file) =>
|
|
27604
|
+
path23.join(here, "server.ts"),
|
|
27605
|
+
path23.join(here, "..", "..", "workit-core", "src", "core", "task-contract.ts"),
|
|
27606
|
+
path23.join(here, "..", "..", "workit-core", "src", "core", "task-engine.ts")
|
|
27607
|
+
].filter((file) => existsSync9(file)));
|
|
26783
27608
|
let staleWarned = false;
|
|
26784
27609
|
const server = new Server({ name: "workit", version: VERSION }, { capabilities: { tools: {}, resources: {} } });
|
|
26785
27610
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
@@ -26959,8 +27784,8 @@ var main = async () => {
|
|
|
26959
27784
|
process.exitCode = 2;
|
|
26960
27785
|
}
|
|
26961
27786
|
};
|
|
26962
|
-
var entryPath = process.argv[1] ?
|
|
26963
|
-
if (entryPath ===
|
|
27787
|
+
var entryPath = process.argv[1] ? path24.resolve(process.argv[1]) : "";
|
|
27788
|
+
if (entryPath === path24.resolve(fileURLToPath3(import.meta.url)))
|
|
26964
27789
|
await main();
|
|
26965
27790
|
export {
|
|
26966
27791
|
McpCapabilityUnavailableError,
|