@brainervirus/workit-cursor 8.12.0 → 8.12.1
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 +306 -212
- package/dist/mcp-server.js +273 -273
- package/dist/workit-hook.js +307 -214
- package/package.json +3 -3
package/dist/workit-hook.js
CHANGED
|
@@ -8377,7 +8377,7 @@ import { realpathSync as realpathSync4 } from "node:fs";
|
|
|
8377
8377
|
|
|
8378
8378
|
// packages/workit-core/src/core/policy/derive.ts
|
|
8379
8379
|
import { existsSync as existsSync2 } from "node:fs";
|
|
8380
|
-
import
|
|
8380
|
+
import path9 from "node:path";
|
|
8381
8381
|
|
|
8382
8382
|
// packages/workit-core/src/git/rev.ts
|
|
8383
8383
|
import { spawnSync } from "node:child_process";
|
|
@@ -8564,7 +8564,7 @@ function pushRemoteName(cwd, branch) {
|
|
|
8564
8564
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
8565
8565
|
import { createHash as createHash7, randomBytes } from "node:crypto";
|
|
8566
8566
|
import fs5 from "node:fs";
|
|
8567
|
-
import
|
|
8567
|
+
import path8 from "node:path";
|
|
8568
8568
|
|
|
8569
8569
|
// packages/workit-core/src/core/vcs-config.ts
|
|
8570
8570
|
import fs2 from "node:fs";
|
|
@@ -9821,13 +9821,72 @@ function vcsConfig(mode, cwd, options = {}) {
|
|
|
9821
9821
|
// packages/workit-core/src/host-session.ts
|
|
9822
9822
|
import { createHash as createHash6 } from "node:crypto";
|
|
9823
9823
|
import fs4 from "node:fs";
|
|
9824
|
-
import
|
|
9824
|
+
import path7 from "node:path";
|
|
9825
|
+
|
|
9826
|
+
// packages/workit-core/src/core/logger.ts
|
|
9827
|
+
import os3 from "node:os";
|
|
9828
|
+
import path5 from "node:path";
|
|
9829
|
+
var SENSITIVE_WORDS = new Set([
|
|
9830
|
+
"token",
|
|
9831
|
+
"secret",
|
|
9832
|
+
"password",
|
|
9833
|
+
"passwd",
|
|
9834
|
+
"authorization",
|
|
9835
|
+
"credential",
|
|
9836
|
+
"credentials",
|
|
9837
|
+
"cookie",
|
|
9838
|
+
"api",
|
|
9839
|
+
"apikey",
|
|
9840
|
+
"apitoken",
|
|
9841
|
+
"accesstoken",
|
|
9842
|
+
"clientsecret",
|
|
9843
|
+
"refreshtoken",
|
|
9844
|
+
"key",
|
|
9845
|
+
"bearer",
|
|
9846
|
+
"prompt",
|
|
9847
|
+
"message",
|
|
9848
|
+
"messages",
|
|
9849
|
+
"content",
|
|
9850
|
+
"body",
|
|
9851
|
+
"args",
|
|
9852
|
+
"argument",
|
|
9853
|
+
"result",
|
|
9854
|
+
"results",
|
|
9855
|
+
"output",
|
|
9856
|
+
"issue",
|
|
9857
|
+
"description",
|
|
9858
|
+
"summary",
|
|
9859
|
+
"payload",
|
|
9860
|
+
"script",
|
|
9861
|
+
"command",
|
|
9862
|
+
"text",
|
|
9863
|
+
"query"
|
|
9864
|
+
]);
|
|
9865
|
+
var STACK_WORDS = new Set(["stack", "stacktrace", "trace"]);
|
|
9866
|
+
var escapeRegExp2 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9867
|
+
var resolveStateDir = () => {
|
|
9868
|
+
const override = process.env.WORKFLOW_TOOLKIT_STATE;
|
|
9869
|
+
if (override)
|
|
9870
|
+
return override;
|
|
9871
|
+
const home = os3.homedir();
|
|
9872
|
+
if (process.env.XDG_STATE_HOME)
|
|
9873
|
+
return path5.join(process.env.XDG_STATE_HOME, "workit");
|
|
9874
|
+
switch (os3.platform()) {
|
|
9875
|
+
case "darwin":
|
|
9876
|
+
return path5.join(home, "Library", "Application Support", "workit");
|
|
9877
|
+
case "win32":
|
|
9878
|
+
return path5.join(process.env.LOCALAPPDATA ?? path5.join(home, "AppData", "Local"), "workit");
|
|
9879
|
+
default:
|
|
9880
|
+
return path5.join(process.env.HOME ?? home, ".local", "state", "workit");
|
|
9881
|
+
}
|
|
9882
|
+
};
|
|
9883
|
+
var homePattern = new RegExp(`${escapeRegExp2(os3.homedir())}(?=[/\\\\]|$)|\\$HOME(?=[/\\\\]|$)`, "g");
|
|
9825
9884
|
|
|
9826
9885
|
// packages/workit-core/src/store/paths.ts
|
|
9827
9886
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
9828
9887
|
import { createHash as createHash5 } from "node:crypto";
|
|
9829
9888
|
import fs3 from "node:fs";
|
|
9830
|
-
import
|
|
9889
|
+
import path6 from "node:path";
|
|
9831
9890
|
var NOT_A_REPO = /not a git repository \(or any (of the parent directories|parent up to)/u;
|
|
9832
9891
|
var gitRun = (cwd, args) => {
|
|
9833
9892
|
const run = spawnSync6("git", args, {
|
|
@@ -9869,14 +9928,14 @@ var DISCOVERY_ENV = [
|
|
|
9869
9928
|
];
|
|
9870
9929
|
var isGitDir = (dir) => {
|
|
9871
9930
|
try {
|
|
9872
|
-
return fs3.statSync(
|
|
9931
|
+
return fs3.statSync(path6.join(dir, "HEAD")).isFile() && fs3.statSync(path6.join(dir, "objects")).isDirectory() && fs3.statSync(path6.join(dir, "refs")).isDirectory();
|
|
9873
9932
|
} catch {
|
|
9874
9933
|
return false;
|
|
9875
9934
|
}
|
|
9876
9935
|
};
|
|
9877
9936
|
var reftableRefs = (common) => {
|
|
9878
9937
|
try {
|
|
9879
|
-
return /^\s*refstorage\s*=\s*reftable\s*$/imu.test(fs3.readFileSync(
|
|
9938
|
+
return /^\s*refstorage\s*=\s*reftable\s*$/imu.test(fs3.readFileSync(path6.join(common, "config"), "utf8"));
|
|
9880
9939
|
} catch {
|
|
9881
9940
|
return false;
|
|
9882
9941
|
}
|
|
@@ -9896,7 +9955,7 @@ function fastGit(root) {
|
|
|
9896
9955
|
if (device !== null && stat.dev !== device)
|
|
9897
9956
|
return { kind: "none" };
|
|
9898
9957
|
device = stat.dev;
|
|
9899
|
-
const dotGit =
|
|
9958
|
+
const dotGit = path6.join(dir, ".git");
|
|
9900
9959
|
let entry = null;
|
|
9901
9960
|
try {
|
|
9902
9961
|
entry = fs3.statSync(dotGit);
|
|
@@ -9917,19 +9976,19 @@ function fastGit(root) {
|
|
|
9917
9976
|
const match = /^gitdir: (.+)$/mu.exec(text);
|
|
9918
9977
|
if (!match)
|
|
9919
9978
|
return null;
|
|
9920
|
-
gitDir =
|
|
9979
|
+
gitDir = path6.resolve(dir, match[1].trim());
|
|
9921
9980
|
} else
|
|
9922
9981
|
return null;
|
|
9923
|
-
if (!fs3.existsSync(
|
|
9982
|
+
if (!fs3.existsSync(path6.join(gitDir, "HEAD")))
|
|
9924
9983
|
return null;
|
|
9925
9984
|
} else if (isGitDir(dir))
|
|
9926
9985
|
gitDir = dir;
|
|
9927
9986
|
if (gitDir) {
|
|
9928
9987
|
let common = gitDir;
|
|
9929
9988
|
try {
|
|
9930
|
-
common =
|
|
9989
|
+
common = path6.resolve(gitDir, fs3.readFileSync(path6.join(gitDir, "commondir"), "utf8").trim());
|
|
9931
9990
|
} catch {}
|
|
9932
|
-
if (!fs3.existsSync(
|
|
9991
|
+
if (!fs3.existsSync(path6.join(common, "objects")))
|
|
9933
9992
|
return null;
|
|
9934
9993
|
return {
|
|
9935
9994
|
kind: "repo",
|
|
@@ -9939,26 +9998,26 @@ function fastGit(root) {
|
|
|
9939
9998
|
reftable: reftableRefs(common)
|
|
9940
9999
|
};
|
|
9941
10000
|
}
|
|
9942
|
-
const parent =
|
|
10001
|
+
const parent = path6.dirname(dir);
|
|
9943
10002
|
if (parent === dir)
|
|
9944
10003
|
return { kind: "none" };
|
|
9945
10004
|
dir = parent;
|
|
9946
10005
|
}
|
|
9947
10006
|
}
|
|
9948
10007
|
function resolveStore(root) {
|
|
9949
|
-
root =
|
|
10008
|
+
root = path6.resolve(root);
|
|
9950
10009
|
let directory = false;
|
|
9951
10010
|
try {
|
|
9952
10011
|
directory = fs3.statSync(root).isDirectory();
|
|
9953
10012
|
} catch {}
|
|
9954
10013
|
if (!directory)
|
|
9955
|
-
return { dir:
|
|
10014
|
+
return { dir: path6.join(root, ".workit"), shared: false, top: null };
|
|
9956
10015
|
const fast = fastGit(root);
|
|
9957
10016
|
if (fast?.kind === "none")
|
|
9958
|
-
return { dir:
|
|
10017
|
+
return { dir: path6.join(root, ".workit"), shared: false, top: null };
|
|
9959
10018
|
if (fast?.kind === "repo")
|
|
9960
10019
|
return {
|
|
9961
|
-
dir:
|
|
10020
|
+
dir: path6.join(fast.common, "workit"),
|
|
9962
10021
|
shared: true,
|
|
9963
10022
|
top: fast.top,
|
|
9964
10023
|
git: { gitDir: fast.gitDir, top: fast.top, reftable: fast.reftable }
|
|
@@ -9968,20 +10027,20 @@ function resolveStore(root) {
|
|
|
9968
10027
|
if (run.ok && common) {
|
|
9969
10028
|
const top = gitRun(root, ["rev-parse", "--path-format=absolute", "--show-toplevel"]);
|
|
9970
10029
|
return {
|
|
9971
|
-
dir:
|
|
10030
|
+
dir: path6.join(real(path6.resolve(root, common)), "workit"),
|
|
9972
10031
|
shared: true,
|
|
9973
10032
|
top: top.ok && top.stdout.trim() ? real(top.stdout.trim()) : null
|
|
9974
10033
|
};
|
|
9975
10034
|
}
|
|
9976
10035
|
if (run.missing || !run.ok && NOT_A_REPO.test(run.stderr))
|
|
9977
|
-
return { dir:
|
|
10036
|
+
return { dir: path6.join(root, ".workit"), shared: false, top: null };
|
|
9978
10037
|
return new Error(`cannot locate the workit store: git rev-parse failed (${run.stderr.trim().split(`
|
|
9979
10038
|
`)[0] || "no output"}); fix the repository (git status should work here)`);
|
|
9980
10039
|
}
|
|
9981
10040
|
var rebasingBranch = (gitDir) => {
|
|
9982
10041
|
for (const state of ["rebase-merge", "rebase-apply"]) {
|
|
9983
10042
|
try {
|
|
9984
|
-
const ref = fs3.readFileSync(
|
|
10043
|
+
const ref = fs3.readFileSync(path6.join(gitDir, state, "head-name"), "utf8").trim();
|
|
9985
10044
|
const match = /^refs\/heads\/(.+)$/u.exec(ref);
|
|
9986
10045
|
if (match)
|
|
9987
10046
|
return match[1];
|
|
@@ -9996,7 +10055,7 @@ function resolveTaskKey(root, location) {
|
|
|
9996
10055
|
if (location.git && !location.git.reftable) {
|
|
9997
10056
|
let head = "";
|
|
9998
10057
|
try {
|
|
9999
|
-
head = fs3.readFileSync(
|
|
10058
|
+
head = fs3.readFileSync(path6.join(location.git.gitDir, "HEAD"), "utf8").trim();
|
|
10000
10059
|
} catch {}
|
|
10001
10060
|
const ref = /^ref: refs\/heads\/(.+)$/u.exec(head);
|
|
10002
10061
|
if (ref && ref[1] !== ".invalid")
|
|
@@ -10027,7 +10086,7 @@ function resolveTaskKey(root, location) {
|
|
|
10027
10086
|
return { key: `detached-${shortHash(real(worktree))}`, kind: "detached", branch: null };
|
|
10028
10087
|
}
|
|
10029
10088
|
function checkoutRootOf(root, location) {
|
|
10030
|
-
const resolved =
|
|
10089
|
+
const resolved = path6.resolve(root);
|
|
10031
10090
|
let canonical = resolved;
|
|
10032
10091
|
try {
|
|
10033
10092
|
canonical = fs3.realpathSync(resolved);
|
|
@@ -10058,13 +10117,13 @@ function branchRenames(location) {
|
|
|
10058
10117
|
}
|
|
10059
10118
|
for (const entry of entries)
|
|
10060
10119
|
if (entry.isDirectory())
|
|
10061
|
-
walk(
|
|
10120
|
+
walk(path6.join(dir, entry.name));
|
|
10062
10121
|
else
|
|
10063
|
-
files.push(
|
|
10122
|
+
files.push(path6.join(dir, entry.name));
|
|
10064
10123
|
};
|
|
10065
|
-
walk(
|
|
10124
|
+
walk(path6.join(path6.dirname(location.dir), "logs", "refs", "heads"));
|
|
10066
10125
|
if (location.git)
|
|
10067
|
-
files.push(
|
|
10126
|
+
files.push(path6.join(location.git.gitDir, "logs", "HEAD"));
|
|
10068
10127
|
const seen = new Set;
|
|
10069
10128
|
const renames = [];
|
|
10070
10129
|
for (const file of files) {
|
|
@@ -10099,7 +10158,7 @@ var checkoutSlug = (root) => {
|
|
|
10099
10158
|
let canonical = real(root);
|
|
10100
10159
|
if (process.platform === "win32")
|
|
10101
10160
|
canonical = canonical.toLowerCase();
|
|
10102
|
-
const base =
|
|
10161
|
+
const base = path6.basename(canonical).replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 40) || "root";
|
|
10103
10162
|
return `${base}-${shortHash(canonical)}`;
|
|
10104
10163
|
};
|
|
10105
10164
|
|
|
@@ -10132,30 +10191,64 @@ function hostSessionFromEnv(env) {
|
|
|
10132
10191
|
return inner ? { host: inner.host, session: inner.session } : { host: declared, session: null };
|
|
10133
10192
|
}
|
|
10134
10193
|
var ISSUED_PER_LEAD = 64;
|
|
10135
|
-
var ISSUED_SESSIONS_MARKER = "workit-issued-sessions/
|
|
10194
|
+
var ISSUED_SESSIONS_MARKER = "workit-issued-sessions/2";
|
|
10136
10195
|
var hash = (value) => createHash6("sha256").update(value).digest("hex").slice(0, 32);
|
|
10137
|
-
var
|
|
10138
|
-
|
|
10139
|
-
|
|
10196
|
+
var userIssuedRoot = () => path7.join(resolveStateDir(), "issued");
|
|
10197
|
+
function migrateRepoIssued(cwd) {
|
|
10198
|
+
if (cwd === undefined)
|
|
10199
|
+
return;
|
|
10200
|
+
let old;
|
|
10201
|
+
try {
|
|
10202
|
+
const location = resolveStore(cwd);
|
|
10203
|
+
if (location instanceof Error)
|
|
10204
|
+
return;
|
|
10205
|
+
old = path7.join(location.dir, "hooks", "issued");
|
|
10206
|
+
if (!fs4.existsSync(old))
|
|
10207
|
+
return;
|
|
10208
|
+
} catch {
|
|
10209
|
+
return;
|
|
10210
|
+
}
|
|
10211
|
+
for (const lead of safeList(old)) {
|
|
10212
|
+
try {
|
|
10213
|
+
const from = path7.join(old, lead);
|
|
10214
|
+
if (!fs4.statSync(from).isDirectory())
|
|
10215
|
+
continue;
|
|
10216
|
+
const to = path7.join(userIssuedRoot(), lead);
|
|
10217
|
+
fs4.mkdirSync(to, { recursive: true, mode: 448 });
|
|
10218
|
+
for (const id of fs4.readdirSync(from)) {
|
|
10219
|
+
fs4.copyFileSync(path7.join(from, id), path7.join(to, id));
|
|
10220
|
+
fs4.rmSync(path7.join(from, id), { force: true });
|
|
10221
|
+
}
|
|
10222
|
+
removeIfEmpty(from);
|
|
10223
|
+
} catch {}
|
|
10224
|
+
}
|
|
10225
|
+
removeIfEmpty(old);
|
|
10226
|
+
}
|
|
10227
|
+
var safeList = (dir) => {
|
|
10228
|
+
try {
|
|
10229
|
+
return fs4.readdirSync(dir);
|
|
10230
|
+
} catch {
|
|
10231
|
+
return [];
|
|
10232
|
+
}
|
|
10140
10233
|
};
|
|
10141
|
-
var
|
|
10142
|
-
|
|
10143
|
-
|
|
10234
|
+
var removeIfEmpty = (dir) => {
|
|
10235
|
+
try {
|
|
10236
|
+
fs4.rmdirSync(dir);
|
|
10237
|
+
} catch {}
|
|
10144
10238
|
};
|
|
10145
10239
|
function recordIssuedSession(cwd, lead, issued) {
|
|
10146
10240
|
try {
|
|
10147
|
-
|
|
10148
|
-
|
|
10149
|
-
|
|
10150
|
-
fs4.mkdirSync(dir, { recursive: true });
|
|
10241
|
+
migrateRepoIssued(cwd);
|
|
10242
|
+
const dir = path7.join(userIssuedRoot(), hash(lead));
|
|
10243
|
+
fs4.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
10151
10244
|
const own = hash(issued);
|
|
10152
|
-
fs4.writeFileSync(
|
|
10245
|
+
fs4.writeFileSync(path7.join(dir, own), ISSUED_SESSIONS_MARKER);
|
|
10153
10246
|
const entries = fs4.readdirSync(dir);
|
|
10154
10247
|
if (entries.length <= ISSUED_PER_LEAD)
|
|
10155
10248
|
return;
|
|
10156
|
-
const byAge = entries.filter((name) => name !== own).map((name) => ({ name, at: fs4.statSync(
|
|
10249
|
+
const byAge = entries.filter((name) => name !== own).map((name) => ({ name, at: fs4.statSync(path7.join(dir, name)).mtimeMs })).toSorted((a, b) => a.at - b.at);
|
|
10157
10250
|
for (const { name } of byAge.slice(0, entries.length - ISSUED_PER_LEAD))
|
|
10158
|
-
fs4.rmSync(
|
|
10251
|
+
fs4.rmSync(path7.join(dir, name), { force: true });
|
|
10159
10252
|
} catch {}
|
|
10160
10253
|
}
|
|
10161
10254
|
var OWN_CHILD_SHELL = new Set(["opencode", "pi"]);
|
|
@@ -10277,14 +10370,14 @@ function diffHash(cwd, base, head) {
|
|
|
10277
10370
|
return `sha256:${hash.digest("hex")}`;
|
|
10278
10371
|
}
|
|
10279
10372
|
function storeRoot(cwd) {
|
|
10280
|
-
const location = resolveStore(
|
|
10373
|
+
const location = resolveStore(path8.resolve(cwd));
|
|
10281
10374
|
if (location instanceof Error)
|
|
10282
10375
|
return err("unavailable", location.message.replace(/; fix the repository.*$/u, ""), "fix the repository (git status should work here) or run from a non-git directory");
|
|
10283
10376
|
return { ok: true, value: { root: location.dir, shared: location.shared } };
|
|
10284
10377
|
}
|
|
10285
10378
|
function ledgerPath(cwd) {
|
|
10286
10379
|
const root = storeRoot(cwd);
|
|
10287
|
-
return root.ok ? { ok: true, value:
|
|
10380
|
+
return root.ok ? { ok: true, value: path8.join(root.value.root, "ledger", "ledger.jsonl") } : root;
|
|
10288
10381
|
}
|
|
10289
10382
|
var newId2 = () => `${Date.now().toString(36)}-${randomBytes(6).toString("hex")}`;
|
|
10290
10383
|
var NETWORK_FS_TYPES = new Set([
|
|
@@ -10314,13 +10407,13 @@ var LOCK_STALE_MS = 30000;
|
|
|
10314
10407
|
var LOCK_OWNER = "owner";
|
|
10315
10408
|
var lockToken = (lock) => {
|
|
10316
10409
|
try {
|
|
10317
|
-
return fs5.readFileSync(
|
|
10410
|
+
return fs5.readFileSync(path8.join(lock, LOCK_OWNER), "utf8");
|
|
10318
10411
|
} catch {
|
|
10319
10412
|
return null;
|
|
10320
10413
|
}
|
|
10321
10414
|
};
|
|
10322
10415
|
var lockAgeMs = (lock) => {
|
|
10323
|
-
for (const target of [
|
|
10416
|
+
for (const target of [path8.join(lock, LOCK_OWNER), lock]) {
|
|
10324
10417
|
try {
|
|
10325
10418
|
return Date.now() - fs5.statSync(target).mtimeMs;
|
|
10326
10419
|
} catch {}
|
|
@@ -10337,7 +10430,7 @@ var ledgerLock = {
|
|
|
10337
10430
|
throw error;
|
|
10338
10431
|
}
|
|
10339
10432
|
const token = `${process.pid}-${randomBytes(8).toString("hex")}`;
|
|
10340
|
-
fs5.writeFileSync(
|
|
10433
|
+
fs5.writeFileSync(path8.join(lock, LOCK_OWNER), token);
|
|
10341
10434
|
return token;
|
|
10342
10435
|
},
|
|
10343
10436
|
release(lock, token) {
|
|
@@ -10462,8 +10555,8 @@ function appendLine(file, build, options) {
|
|
|
10462
10555
|
}
|
|
10463
10556
|
};
|
|
10464
10557
|
try {
|
|
10465
|
-
fs5.mkdirSync(
|
|
10466
|
-
if (!options.forceLock && !onNetworkFs(
|
|
10558
|
+
fs5.mkdirSync(path8.dirname(file), { recursive: true });
|
|
10559
|
+
if (!options.forceLock && !onNetworkFs(path8.dirname(file)))
|
|
10467
10560
|
return write();
|
|
10468
10561
|
const locked = withLedgerLock(file, write);
|
|
10469
10562
|
return locked ?? err("busy", `ledger lock ${file}.lock is held`, "retry; remove the .lock directory if no workit process is running");
|
|
@@ -11026,7 +11119,7 @@ var productDecision = (task, ledger) => {
|
|
|
11026
11119
|
};
|
|
11027
11120
|
};
|
|
11028
11121
|
var planRecorded = (task, root) => {
|
|
11029
|
-
const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync2(
|
|
11122
|
+
const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync2(path9.resolve(root, ref.path)));
|
|
11030
11123
|
if (cited)
|
|
11031
11124
|
return {
|
|
11032
11125
|
met: true,
|
|
@@ -11641,20 +11734,20 @@ var judgeInputSummary = (raw) => {
|
|
|
11641
11734
|
};
|
|
11642
11735
|
|
|
11643
11736
|
// packages/workit-core/src/autonomy.ts
|
|
11644
|
-
import
|
|
11645
|
-
import
|
|
11737
|
+
import os4 from "node:os";
|
|
11738
|
+
import path10 from "node:path";
|
|
11646
11739
|
var accountHome = () => {
|
|
11647
11740
|
try {
|
|
11648
|
-
return
|
|
11741
|
+
return os4.userInfo().homedir;
|
|
11649
11742
|
} catch {
|
|
11650
|
-
return
|
|
11743
|
+
return os4.homedir();
|
|
11651
11744
|
}
|
|
11652
11745
|
};
|
|
11653
11746
|
var grantsHome = { resolve: accountHome };
|
|
11654
|
-
var grantsDir = () =>
|
|
11747
|
+
var grantsDir = () => path10.join(grantsHome.resolve(), ".config", "workit");
|
|
11655
11748
|
var grantsOverride = () => {
|
|
11656
|
-
const configured =
|
|
11657
|
-
return configured ===
|
|
11749
|
+
const configured = path10.resolve(resolveConfigDir());
|
|
11750
|
+
return configured === path10.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 ${path10.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
|
|
11658
11751
|
};
|
|
11659
11752
|
var GRANT_KINDS = ["push", "pr", "merge", "release", "rerun"];
|
|
11660
11753
|
var DEFAULT_GRANTS = Object.freeze({
|
|
@@ -11780,7 +11873,7 @@ var grantHint = (workspace, kind) => `ask the user to run, in their own terminal
|
|
|
11780
11873
|
// packages/workit-core/src/core/task-store.ts
|
|
11781
11874
|
import { createHash as createHash9, randomUUID as randomUUID3 } from "node:crypto";
|
|
11782
11875
|
import * as fs11 from "node:fs";
|
|
11783
|
-
import
|
|
11876
|
+
import path15 from "node:path";
|
|
11784
11877
|
|
|
11785
11878
|
// node_modules/@openclaw/fs-safe/dist/errors.js
|
|
11786
11879
|
var OPERATIONAL_CODES = new Set([
|
|
@@ -11831,7 +11924,7 @@ function sameFileIdentity(left, right, platform = process.platform) {
|
|
|
11831
11924
|
// node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.js
|
|
11832
11925
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
11833
11926
|
import fsSync from "node:fs";
|
|
11834
|
-
import
|
|
11927
|
+
import path11 from "node:path";
|
|
11835
11928
|
|
|
11836
11929
|
// node_modules/@openclaw/fs-safe/dist/bounded-read.js
|
|
11837
11930
|
import fs6 from "node:fs";
|
|
@@ -11921,13 +12014,13 @@ ${ownershipToken}
|
|
|
11921
12014
|
return { raw, ownershipToken };
|
|
11922
12015
|
}
|
|
11923
12016
|
function relativeSidecarLockPath(lockRoot, lockPath) {
|
|
11924
|
-
const resolved =
|
|
11925
|
-
const lexicalRelative =
|
|
11926
|
-
const relative = lexicalRelative !== ".." && !lexicalRelative.startsWith(`..${
|
|
11927
|
-
if (!relative || relative === ".." || relative.startsWith(`..${
|
|
12017
|
+
const resolved = path11.resolve(lockPath);
|
|
12018
|
+
const lexicalRelative = path11.relative(lockRoot.rootDir, resolved);
|
|
12019
|
+
const relative = lexicalRelative !== ".." && !lexicalRelative.startsWith(`..${path11.sep}`) && !path11.isAbsolute(lexicalRelative) ? lexicalRelative : path11.relative(lockRoot.rootReal, resolved);
|
|
12020
|
+
if (!relative || relative === ".." || relative.startsWith(`..${path11.sep}`) || path11.isAbsolute(relative)) {
|
|
11928
12021
|
throw new FsSafeError("outside-workspace", "sidecar lock path is outside lockRoot");
|
|
11929
12022
|
}
|
|
11930
|
-
return relative.split(
|
|
12023
|
+
return relative.split(path11.sep).join(path11.posix.sep);
|
|
11931
12024
|
}
|
|
11932
12025
|
function parseSidecarLockPayload(raw, parser) {
|
|
11933
12026
|
if (parser) {
|
|
@@ -12074,7 +12167,7 @@ function getFsSafeLockConfig() {
|
|
|
12074
12167
|
|
|
12075
12168
|
// node_modules/@openclaw/fs-safe/dist/file-lock-sync.js
|
|
12076
12169
|
import fs8 from "node:fs";
|
|
12077
|
-
import
|
|
12170
|
+
import path12 from "node:path";
|
|
12078
12171
|
|
|
12079
12172
|
// node_modules/@openclaw/fs-safe/dist/timing.js
|
|
12080
12173
|
function sleepSync(ms) {
|
|
@@ -12165,26 +12258,26 @@ function canonicalLockParentSync(parent) {
|
|
|
12165
12258
|
return process.platform === "win32" ? fs8.realpathSync.native(parent) : fs8.realpathSync(parent);
|
|
12166
12259
|
}
|
|
12167
12260
|
function normalizeTargetPath(targetPath) {
|
|
12168
|
-
const resolved =
|
|
12169
|
-
fs8.mkdirSync(
|
|
12261
|
+
const resolved = path12.resolve(targetPath);
|
|
12262
|
+
fs8.mkdirSync(path12.dirname(resolved), { recursive: true });
|
|
12170
12263
|
try {
|
|
12171
|
-
return
|
|
12264
|
+
return path12.join(canonicalLockParentSync(path12.dirname(resolved)), path12.basename(resolved));
|
|
12172
12265
|
} catch {
|
|
12173
12266
|
return resolved;
|
|
12174
12267
|
}
|
|
12175
12268
|
}
|
|
12176
12269
|
function boundedLockPath(lockPath, lockRoot) {
|
|
12177
|
-
const resolved =
|
|
12270
|
+
const resolved = path12.resolve(lockPath);
|
|
12178
12271
|
if (!lockRoot)
|
|
12179
12272
|
return resolved;
|
|
12180
12273
|
relativeSidecarLockPath(lockRoot, resolved);
|
|
12181
|
-
const parent =
|
|
12274
|
+
const parent = path12.dirname(resolved);
|
|
12182
12275
|
const parentReal = canonicalLockParentSync(parent);
|
|
12183
|
-
const parentRelative =
|
|
12184
|
-
if (parentRelative === ".." || parentRelative.startsWith(`..${
|
|
12276
|
+
const parentRelative = path12.relative(lockRoot.rootReal, parentReal);
|
|
12277
|
+
if (parentRelative === ".." || parentRelative.startsWith(`..${path12.sep}`) || path12.isAbsolute(parentRelative)) {
|
|
12185
12278
|
throw new FsSafeError("outside-workspace", "sidecar lock parent is outside lockRoot");
|
|
12186
12279
|
}
|
|
12187
|
-
return
|
|
12280
|
+
return path12.join(parentReal, path12.basename(resolved));
|
|
12188
12281
|
}
|
|
12189
12282
|
function defaultShouldReclaim(snapshot, staleMs, nowMs) {
|
|
12190
12283
|
const createdAtMs = sidecarLockPayloadCreatedAtMs(snapshot.payload);
|
|
@@ -12385,13 +12478,13 @@ function acquireFileLockSync(targetPath, options) {
|
|
|
12385
12478
|
}
|
|
12386
12479
|
// packages/workit-core/src/core/package-root.ts
|
|
12387
12480
|
import { existsSync as existsSync3 } from "node:fs";
|
|
12388
|
-
import
|
|
12481
|
+
import path13 from "node:path";
|
|
12389
12482
|
import { fileURLToPath } from "node:url";
|
|
12390
12483
|
var packageRoot = () => {
|
|
12391
|
-
let dir =
|
|
12484
|
+
let dir = path13.dirname(fileURLToPath(import.meta.url));
|
|
12392
12485
|
while (true) {
|
|
12393
|
-
const parent =
|
|
12394
|
-
if (existsSync3(
|
|
12486
|
+
const parent = path13.dirname(dir);
|
|
12487
|
+
if (existsSync3(path13.join(dir, "package.json")) || parent === dir)
|
|
12395
12488
|
return dir;
|
|
12396
12489
|
dir = parent;
|
|
12397
12490
|
}
|
|
@@ -12540,7 +12633,7 @@ var clearAbandonedReclaimGuard = (lockPath, nowMs = Date.now()) => {
|
|
|
12540
12633
|
// packages/workit-core/src/store/event-log.ts
|
|
12541
12634
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
12542
12635
|
import fs10 from "node:fs";
|
|
12543
|
-
import
|
|
12636
|
+
import path14 from "node:path";
|
|
12544
12637
|
var EVENT_VERSION = 1;
|
|
12545
12638
|
|
|
12546
12639
|
class LogDamage extends Error {
|
|
@@ -12651,7 +12744,7 @@ function appendEvent(file, event, validEnd) {
|
|
|
12651
12744
|
fs10.closeSync(fd);
|
|
12652
12745
|
}
|
|
12653
12746
|
if (created)
|
|
12654
|
-
fsyncDirectory(
|
|
12747
|
+
fsyncDirectory(path14.dirname(file));
|
|
12655
12748
|
return validEnd;
|
|
12656
12749
|
}
|
|
12657
12750
|
function replaceFile(file, bytes, durable) {
|
|
@@ -12667,7 +12760,7 @@ function replaceFile(file, bytes, durable) {
|
|
|
12667
12760
|
}
|
|
12668
12761
|
renameWithRetry(temporary, file);
|
|
12669
12762
|
if (durable)
|
|
12670
|
-
fsyncDirectory(
|
|
12763
|
+
fsyncDirectory(path14.dirname(file));
|
|
12671
12764
|
} catch (error) {
|
|
12672
12765
|
try {
|
|
12673
12766
|
fs10.unlinkSync(temporary);
|
|
@@ -13010,7 +13103,7 @@ var cachedRuntimeVersion = null;
|
|
|
13010
13103
|
var runtimeVersion = () => {
|
|
13011
13104
|
if (cachedRuntimeVersion === null) {
|
|
13012
13105
|
try {
|
|
13013
|
-
const pkg = JSON.parse(fs11.readFileSync(
|
|
13106
|
+
const pkg = JSON.parse(fs11.readFileSync(path15.join(packageRoot(), "package.json"), "utf8"));
|
|
13014
13107
|
cachedRuntimeVersion = typeof pkg.version === "string" && pkg.version ? pkg.version : "0.0.0";
|
|
13015
13108
|
} catch {
|
|
13016
13109
|
cachedRuntimeVersion = "0.0.0";
|
|
@@ -13043,7 +13136,7 @@ var readText = (file) => {
|
|
|
13043
13136
|
};
|
|
13044
13137
|
var REFLOG_LINE = /^[0-9a-f]+ ([0-9a-f]+) .* (\d+) [+-]\d{4}\t(.*)$/u;
|
|
13045
13138
|
var branchStart = (location, branch, aliases) => {
|
|
13046
|
-
const first = readText(
|
|
13139
|
+
const first = readText(path15.join(path15.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
|
|
13047
13140
|
`, 1)[0];
|
|
13048
13141
|
const created = REFLOG_LINE.exec(first);
|
|
13049
13142
|
const start = created && /^branch: Created from (\S+)$/u.exec(created[3])?.[1];
|
|
@@ -13053,7 +13146,7 @@ var branchStart = (location, branch, aliases) => {
|
|
|
13053
13146
|
return start;
|
|
13054
13147
|
if (!location.git)
|
|
13055
13148
|
return null;
|
|
13056
|
-
for (const line of readText(
|
|
13149
|
+
for (const line of readText(path15.join(location.git.gitDir, "logs", "HEAD")).split(`
|
|
13057
13150
|
`)) {
|
|
13058
13151
|
const entry = REFLOG_LINE.exec(line);
|
|
13059
13152
|
const moved = entry && /^checkout: moving from (\S+) to (\S+)$/u.exec(entry[3]);
|
|
@@ -13063,14 +13156,14 @@ var branchStart = (location, branch, aliases) => {
|
|
|
13063
13156
|
}
|
|
13064
13157
|
return null;
|
|
13065
13158
|
};
|
|
13066
|
-
var refExists = (common, ref) => fs11.existsSync(
|
|
13159
|
+
var refExists = (common, ref) => fs11.existsSync(path15.join(common, ref)) || readText(path15.join(common, "packed-refs")).includes(` ${ref}
|
|
13067
13160
|
`);
|
|
13068
13161
|
var origins = new Map;
|
|
13069
13162
|
var sameDirectoryIdentity = (left, right) => {
|
|
13070
|
-
if (!
|
|
13163
|
+
if (!path15.isAbsolute(left) || !path15.isAbsolute(right))
|
|
13071
13164
|
return false;
|
|
13072
|
-
const normalizedLeft =
|
|
13073
|
-
const normalizedRight =
|
|
13165
|
+
const normalizedLeft = path15.resolve(left);
|
|
13166
|
+
const normalizedRight = path15.resolve(right);
|
|
13074
13167
|
try {
|
|
13075
13168
|
const a = fs11.statSync(normalizedLeft, { bigint: true });
|
|
13076
13169
|
const b = fs11.statSync(normalizedRight, { bigint: true });
|
|
@@ -13116,7 +13209,7 @@ class TaskStore {
|
|
|
13116
13209
|
migrationChecked = false;
|
|
13117
13210
|
compactDue = new Set;
|
|
13118
13211
|
constructor(root, options = {}) {
|
|
13119
|
-
const resolved =
|
|
13212
|
+
const resolved = path15.resolve(root);
|
|
13120
13213
|
this.origin = fs11.existsSync(resolved) ? fs11.realpathSync(resolved) : resolved;
|
|
13121
13214
|
this.located = resolveStore(this.origin);
|
|
13122
13215
|
this.root = checkoutRootOf(this.origin, this.located);
|
|
@@ -13125,7 +13218,7 @@ class TaskStore {
|
|
|
13125
13218
|
this.migrateOnRead = options.migrateOnRead;
|
|
13126
13219
|
}
|
|
13127
13220
|
location() {
|
|
13128
|
-
if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs11.existsSync(
|
|
13221
|
+
if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs11.existsSync(path15.join(this.root, ".git"))) {
|
|
13129
13222
|
this.located = undefined;
|
|
13130
13223
|
this.migrationChecked = false;
|
|
13131
13224
|
}
|
|
@@ -13281,7 +13374,7 @@ class TaskStore {
|
|
|
13281
13374
|
const moved = this.bindLocked(again.data.id, key, input.now);
|
|
13282
13375
|
return moved.ok ? success(moved.data.revision, null, { task: moved.data, created: false, key }) : moved;
|
|
13283
13376
|
}
|
|
13284
|
-
const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" :
|
|
13377
|
+
const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path15.basename(this.root) || this.root;
|
|
13285
13378
|
const intent = {
|
|
13286
13379
|
objective: input.objective?.trim() || `Work on ${label}`,
|
|
13287
13380
|
scope: { description: `the checkout (${label})`, paths: ["."], exclusions: [] },
|
|
@@ -13341,14 +13434,14 @@ class TaskStore {
|
|
|
13341
13434
|
const branch = key.ok ? key.data.branch : null;
|
|
13342
13435
|
if (!branch || !location.ok)
|
|
13343
13436
|
return success(null, null, null);
|
|
13344
|
-
const common =
|
|
13345
|
-
const heads =
|
|
13346
|
-
const headLog = location.data.git ?
|
|
13437
|
+
const common = path15.dirname(location.data.dir);
|
|
13438
|
+
const heads = path15.join(common, "logs", "refs", "heads");
|
|
13439
|
+
const headLog = location.data.git ? path15.join(location.data.git.gitDir, "logs", "HEAD") : "";
|
|
13347
13440
|
const signatures = [
|
|
13348
|
-
|
|
13441
|
+
path15.join(heads, branch),
|
|
13349
13442
|
headLog,
|
|
13350
13443
|
heads,
|
|
13351
|
-
|
|
13444
|
+
path15.join(common, "packed-refs")
|
|
13352
13445
|
].map((file) => fileSignature(file) ?? "-");
|
|
13353
13446
|
const slot = `${location.data.dir}\x00${headLog}\x00${branch}`;
|
|
13354
13447
|
let resolved = origins.get(slot);
|
|
@@ -13360,7 +13453,7 @@ class TaskStore {
|
|
|
13360
13453
|
aliases.push(rename.from);
|
|
13361
13454
|
const start = branchStart(location.data, branch, aliases);
|
|
13362
13455
|
const slash = start?.indexOf("/") ?? -1;
|
|
13363
|
-
const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(
|
|
13456
|
+
const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(path15.join(common, "config")).includes(`[remote "${start.slice(0, slash)}"]`));
|
|
13364
13457
|
const name = start && (remote ? start.slice(slash + 1) : start);
|
|
13365
13458
|
resolved = {
|
|
13366
13459
|
signature: signatures.join("|"),
|
|
@@ -13598,13 +13691,13 @@ class TaskStore {
|
|
|
13598
13691
|
if (!ready.ok)
|
|
13599
13692
|
return ready;
|
|
13600
13693
|
const dirs = this.paths();
|
|
13601
|
-
const recovery =
|
|
13694
|
+
const recovery = path15.join(this.root, ".workit", "recovery");
|
|
13602
13695
|
if (fs11.existsSync(recovery)) {
|
|
13603
13696
|
let files = 0;
|
|
13604
13697
|
let bytes = 0;
|
|
13605
13698
|
try {
|
|
13606
13699
|
for (const name of fs11.readdirSync(recovery)) {
|
|
13607
|
-
const stat = fs11.lstatSync(
|
|
13700
|
+
const stat = fs11.lstatSync(path15.join(recovery, name));
|
|
13608
13701
|
if (!stat.isFile())
|
|
13609
13702
|
continue;
|
|
13610
13703
|
files += 1;
|
|
@@ -13657,7 +13750,7 @@ class TaskStore {
|
|
|
13657
13750
|
if (fs11.existsSync(dirs.blobs))
|
|
13658
13751
|
for (const name of fs11.readdirSync(dirs.blobs)) {
|
|
13659
13752
|
const digest = name.replace(/\.json$/, "");
|
|
13660
|
-
const file =
|
|
13753
|
+
const file = path15.join(dirs.blobs, name);
|
|
13661
13754
|
let stat;
|
|
13662
13755
|
try {
|
|
13663
13756
|
stat = fs11.lstatSync(file);
|
|
@@ -13675,7 +13768,7 @@ class TaskStore {
|
|
|
13675
13768
|
}
|
|
13676
13769
|
return success(null, null, null);
|
|
13677
13770
|
};
|
|
13678
|
-
const swept = dryRun ? sweep() : this.withLock(
|
|
13771
|
+
const swept = dryRun ? sweep() : this.withLock(path15.join(dirs.dir, "gc.lock"), sweep);
|
|
13679
13772
|
if (!swept.ok)
|
|
13680
13773
|
return swept;
|
|
13681
13774
|
const temporaryDirs = [
|
|
@@ -13683,7 +13776,7 @@ class TaskStore {
|
|
|
13683
13776
|
dirs.tasks,
|
|
13684
13777
|
dirs.blobs,
|
|
13685
13778
|
dirs.checkout,
|
|
13686
|
-
...names.map((name) =>
|
|
13779
|
+
...names.map((name) => path15.join(dirs.tasks, name))
|
|
13687
13780
|
];
|
|
13688
13781
|
for (const directory of temporaryDirs) {
|
|
13689
13782
|
if (!fs11.existsSync(directory))
|
|
@@ -13691,7 +13784,7 @@ class TaskStore {
|
|
|
13691
13784
|
for (const name of fs11.readdirSync(directory)) {
|
|
13692
13785
|
if (!name.endsWith(".tmp") && !name.endsWith(".probe"))
|
|
13693
13786
|
continue;
|
|
13694
|
-
const file =
|
|
13787
|
+
const file = path15.join(directory, name);
|
|
13695
13788
|
try {
|
|
13696
13789
|
const stat = fs11.lstatSync(file);
|
|
13697
13790
|
if (!stat.isFile() || nowMs - stat.mtimeMs <= STALE_TEMPORARY_MS)
|
|
@@ -13708,30 +13801,30 @@ class TaskStore {
|
|
|
13708
13801
|
}
|
|
13709
13802
|
paths() {
|
|
13710
13803
|
const location = this.location();
|
|
13711
|
-
const dir = location.ok ? location.data.dir :
|
|
13712
|
-
const checkout =
|
|
13804
|
+
const dir = location.ok ? location.data.dir : path15.join(this.root, ".workit");
|
|
13805
|
+
const checkout = path15.join(dir, "checkouts", checkoutSlug(this.root));
|
|
13713
13806
|
return {
|
|
13714
13807
|
dir,
|
|
13715
13808
|
shared: location.ok ? location.data.shared : false,
|
|
13716
|
-
marker:
|
|
13809
|
+
marker: path15.join(dir, "store.json"),
|
|
13717
13810
|
checkout,
|
|
13718
|
-
workspace:
|
|
13719
|
-
checkoutLock:
|
|
13720
|
-
tasks:
|
|
13721
|
-
index:
|
|
13722
|
-
blobs:
|
|
13723
|
-
legacy:
|
|
13724
|
-
v2:
|
|
13811
|
+
workspace: path15.join(checkout, "workspace.json"),
|
|
13812
|
+
checkoutLock: path15.join(checkout, "metadata.lock"),
|
|
13813
|
+
tasks: path15.join(dir, "tasks"),
|
|
13814
|
+
index: path15.join(dir, "task-index.json"),
|
|
13815
|
+
blobs: path15.join(dir, "blobs", "candidates"),
|
|
13816
|
+
legacy: path15.join(dir, "legacy", checkoutSlug(this.root), "v2"),
|
|
13817
|
+
v2: path15.join(this.root, ".workit")
|
|
13725
13818
|
};
|
|
13726
13819
|
}
|
|
13727
13820
|
eventsPath(taskId) {
|
|
13728
|
-
return
|
|
13821
|
+
return path15.join(this.paths().tasks, taskId, "events.jsonl");
|
|
13729
13822
|
}
|
|
13730
13823
|
snapshotPath(taskId) {
|
|
13731
|
-
return
|
|
13824
|
+
return path15.join(this.paths().tasks, taskId, "snapshot.json");
|
|
13732
13825
|
}
|
|
13733
13826
|
taskLockPath(taskId) {
|
|
13734
|
-
return
|
|
13827
|
+
return path15.join(this.paths().tasks, taskId, "lock");
|
|
13735
13828
|
}
|
|
13736
13829
|
ready(write = false) {
|
|
13737
13830
|
const location = this.location();
|
|
@@ -13770,13 +13863,13 @@ class TaskStore {
|
|
|
13770
13863
|
return {
|
|
13771
13864
|
read: (digest) => {
|
|
13772
13865
|
try {
|
|
13773
|
-
return JSON.parse(fs11.readFileSync(
|
|
13866
|
+
return JSON.parse(fs11.readFileSync(path15.join(dir, `${digest}.json`), "utf8"));
|
|
13774
13867
|
} catch (error) {
|
|
13775
13868
|
throw new LogDamage(`stored candidate ${digest} is missing or unreadable: ${String(error)}`);
|
|
13776
13869
|
}
|
|
13777
13870
|
},
|
|
13778
13871
|
write: (digest, value) => {
|
|
13779
|
-
const file =
|
|
13872
|
+
const file = path15.join(dir, `${digest}.json`);
|
|
13780
13873
|
if (fs11.existsSync(file)) {
|
|
13781
13874
|
const stamp = new Date;
|
|
13782
13875
|
try {
|
|
@@ -13968,7 +14061,7 @@ class TaskStore {
|
|
|
13968
14061
|
}
|
|
13969
14062
|
}
|
|
13970
14063
|
openTask(record, type, key, legacy = null) {
|
|
13971
|
-
const dir =
|
|
14064
|
+
const dir = path15.join(this.paths().tasks, record.id);
|
|
13972
14065
|
fs11.mkdirSync(dir, { recursive: true });
|
|
13973
14066
|
const blobs = this.blobStore();
|
|
13974
14067
|
const bound = key ? { ...key, boundAt: key.boundAt ?? new Date().toISOString() } : null;
|
|
@@ -14061,7 +14154,7 @@ class TaskStore {
|
|
|
14061
14154
|
}
|
|
14062
14155
|
withKeyLock(key, operation) {
|
|
14063
14156
|
const digest = createHash9("sha256").update(key).digest("hex").slice(0, 32);
|
|
14064
|
-
return this.withLock(
|
|
14157
|
+
return this.withLock(path15.join(this.paths().dir, "keys", `${digest}.lock`), operation);
|
|
14065
14158
|
}
|
|
14066
14159
|
bindLocked(taskId, key, timestamp) {
|
|
14067
14160
|
const current = this.readWorkspace();
|
|
@@ -14202,7 +14295,7 @@ class TaskStore {
|
|
|
14202
14295
|
writeWorkspace(record) {
|
|
14203
14296
|
const file = this.paths().workspace;
|
|
14204
14297
|
try {
|
|
14205
|
-
fs11.mkdirSync(
|
|
14298
|
+
fs11.mkdirSync(path15.dirname(file), { recursive: true });
|
|
14206
14299
|
replaceFile(file, `${canonicalJson(record)}
|
|
14207
14300
|
`, true);
|
|
14208
14301
|
return success(null, null, null);
|
|
@@ -14280,23 +14373,23 @@ class TaskStore {
|
|
|
14280
14373
|
return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", { expectedWorkspaceRevision: expected, actualWorkspaceRevision: actual });
|
|
14281
14374
|
}
|
|
14282
14375
|
v2Dirs() {
|
|
14283
|
-
return [...new Set([this.root, this.origin])].map((dir) =>
|
|
14376
|
+
return [...new Set([this.root, this.origin])].map((dir) => path15.join(dir, ".workit"));
|
|
14284
14377
|
}
|
|
14285
14378
|
pendingMigrations() {
|
|
14286
14379
|
return this.v2Dirs().filter((dir) => {
|
|
14287
|
-
const raw = this.readV2Workspace(
|
|
14380
|
+
const raw = this.readV2Workspace(path15.join(dir, "workspace.json"));
|
|
14288
14381
|
return raw !== null && raw !== TOMBSTONE;
|
|
14289
14382
|
});
|
|
14290
14383
|
}
|
|
14291
14384
|
migrateV2(v2) {
|
|
14292
14385
|
const dirs = this.paths();
|
|
14293
|
-
const v2Workspace =
|
|
14294
|
-
const v2Tasks =
|
|
14295
|
-
const legacy =
|
|
14386
|
+
const v2Workspace = path15.join(v2, "workspace.json");
|
|
14387
|
+
const v2Tasks = path15.join(v2, "tasks");
|
|
14388
|
+
const legacy = path15.join(dirs.dir, "legacy", checkoutSlug(path15.dirname(v2)), "v2");
|
|
14296
14389
|
const raw = this.readV2Workspace(v2Workspace);
|
|
14297
14390
|
if (raw === null || raw === TOMBSTONE)
|
|
14298
14391
|
return success(null, null, null);
|
|
14299
|
-
return this.withLock(dirs.checkoutLock, () => this.withLock(
|
|
14392
|
+
return this.withLock(dirs.checkoutLock, () => this.withLock(path15.join(v2, "metadata.lock"), () => {
|
|
14300
14393
|
const workspace = this.readV2Workspace(v2Workspace);
|
|
14301
14394
|
if (workspace === null || workspace === TOMBSTONE)
|
|
14302
14395
|
return success(null, null, null);
|
|
@@ -14305,7 +14398,7 @@ class TaskStore {
|
|
|
14305
14398
|
return failure2("recovery_required", `cannot migrate the 2.x store at ${v2}: ${parsedWorkspace.error}; move it aside to start fresh`, { path: v2Workspace });
|
|
14306
14399
|
let files = [];
|
|
14307
14400
|
try {
|
|
14308
|
-
files = fs11.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(
|
|
14401
|
+
files = fs11.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path15.join(v2Tasks, name)));
|
|
14309
14402
|
} catch {}
|
|
14310
14403
|
const current = this.readWorkspace();
|
|
14311
14404
|
if (!current.ok)
|
|
@@ -14323,21 +14416,21 @@ class TaskStore {
|
|
|
14323
14416
|
let skipped = 0;
|
|
14324
14417
|
const done = new Map;
|
|
14325
14418
|
try {
|
|
14326
|
-
fs11.mkdirSync(
|
|
14419
|
+
fs11.mkdirSync(path15.join(legacy, "tasks"), { recursive: true });
|
|
14327
14420
|
for (const name of ["workspace.json", "index.json"])
|
|
14328
|
-
if (fs11.existsSync(
|
|
14329
|
-
fs11.copyFileSync(
|
|
14421
|
+
if (fs11.existsSync(path15.join(v2, name)))
|
|
14422
|
+
fs11.copyFileSync(path15.join(v2, name), path15.join(legacy, name));
|
|
14330
14423
|
for (const name of files) {
|
|
14331
14424
|
const id = name.slice(0, -5);
|
|
14332
|
-
const file =
|
|
14425
|
+
const file = path15.join(v2Tasks, name);
|
|
14333
14426
|
const bytes = fs11.readFileSync(file, "utf8");
|
|
14334
14427
|
const digest = sha256(bytes);
|
|
14335
|
-
fs11.writeFileSync(
|
|
14428
|
+
fs11.writeFileSync(path15.join(legacy, "tasks", name), bytes);
|
|
14336
14429
|
const parsed = this.parseRecord(bytes, taskRecordSchema, "2.x task");
|
|
14337
14430
|
if (!parsed.ok || parsed.data.id !== id)
|
|
14338
14431
|
return failure2("recovery_required", `cannot migrate 2.x task ${id}: ${parsed.ok ? "file name and record ID differ" : parsed.error}; move ${file} aside to continue`, { path: file });
|
|
14339
14432
|
const record = { ...parsed.data, workspaceId: target.id };
|
|
14340
|
-
const origin = { path:
|
|
14433
|
+
const origin = { path: path15.join(legacy, "tasks", name), digest };
|
|
14341
14434
|
if (!fs11.existsSync(this.eventsPath(id))) {
|
|
14342
14435
|
this.openTask(record, "migrated.from_v2", null, origin);
|
|
14343
14436
|
migrated += 1;
|
|
@@ -14373,7 +14466,7 @@ class TaskStore {
|
|
|
14373
14466
|
try {
|
|
14374
14467
|
let complete = true;
|
|
14375
14468
|
for (const [name, digest] of done) {
|
|
14376
|
-
const file =
|
|
14469
|
+
const file = path15.join(v2Tasks, name);
|
|
14377
14470
|
if (sha256(fs11.readFileSync(file, "utf8")) !== digest) {
|
|
14378
14471
|
complete = false;
|
|
14379
14472
|
continue;
|
|
@@ -14384,7 +14477,7 @@ class TaskStore {
|
|
|
14384
14477
|
return failure2("busy", `the 2.x store at ${v2} changed during migration; retry`, {
|
|
14385
14478
|
path: v2
|
|
14386
14479
|
});
|
|
14387
|
-
fs11.rmSync(
|
|
14480
|
+
fs11.rmSync(path15.join(v2, "index.json"), { force: true });
|
|
14388
14481
|
this.writeTombstone(v2, target.id);
|
|
14389
14482
|
} catch (error) {
|
|
14390
14483
|
return failure2("storage_error", `cannot finish the 2.x migration: ${String(error)}`, {
|
|
@@ -14404,7 +14497,7 @@ class TaskStore {
|
|
|
14404
14497
|
}
|
|
14405
14498
|
adoptLocalStore() {
|
|
14406
14499
|
const dirs = this.paths();
|
|
14407
|
-
const marker =
|
|
14500
|
+
const marker = path15.join(dirs.v2, "store.json");
|
|
14408
14501
|
if (!dirs.shared || !fs11.existsSync(marker))
|
|
14409
14502
|
return success(null, null, null);
|
|
14410
14503
|
return this.withLock(dirs.checkoutLock, () => {
|
|
@@ -14414,7 +14507,7 @@ class TaskStore {
|
|
|
14414
14507
|
try {
|
|
14415
14508
|
const merge = (from, to) => {
|
|
14416
14509
|
if (!fs11.existsSync(to)) {
|
|
14417
|
-
fs11.mkdirSync(
|
|
14510
|
+
fs11.mkdirSync(path15.dirname(to), { recursive: true });
|
|
14418
14511
|
try {
|
|
14419
14512
|
fs11.renameSync(from, to);
|
|
14420
14513
|
} catch {
|
|
@@ -14425,24 +14518,24 @@ class TaskStore {
|
|
|
14425
14518
|
}
|
|
14426
14519
|
if (fs11.lstatSync(from).isDirectory() && fs11.lstatSync(to).isDirectory())
|
|
14427
14520
|
for (const name of fs11.readdirSync(from))
|
|
14428
|
-
merge(
|
|
14521
|
+
merge(path15.join(from, name), path15.join(to, name));
|
|
14429
14522
|
};
|
|
14430
14523
|
for (const sub of ["tasks", "checkouts", "blobs", "legacy"]) {
|
|
14431
|
-
const from =
|
|
14524
|
+
const from = path15.join(dirs.v2, sub);
|
|
14432
14525
|
if (!fs11.existsSync(from))
|
|
14433
14526
|
continue;
|
|
14434
14527
|
if (sub === "tasks") {
|
|
14435
14528
|
for (const name of fs11.readdirSync(from))
|
|
14436
|
-
if (validId(name) && !fs11.existsSync(
|
|
14529
|
+
if (validId(name) && !fs11.existsSync(path15.join(dirs.dir, sub, name)))
|
|
14437
14530
|
tasks += 1;
|
|
14438
14531
|
}
|
|
14439
|
-
merge(from,
|
|
14532
|
+
merge(from, path15.join(dirs.dir, sub));
|
|
14440
14533
|
}
|
|
14441
|
-
const ledger =
|
|
14442
|
-
if (fs11.existsSync(ledger) && !fs11.existsSync(
|
|
14443
|
-
merge(ledger,
|
|
14444
|
-
fs11.rmSync(
|
|
14445
|
-
fs11.renameSync(marker,
|
|
14534
|
+
const ledger = path15.join(dirs.v2, "ledger");
|
|
14535
|
+
if (fs11.existsSync(ledger) && !fs11.existsSync(path15.join(dirs.dir, "ledger")))
|
|
14536
|
+
merge(ledger, path15.join(dirs.dir, "ledger"));
|
|
14537
|
+
fs11.rmSync(path15.join(dirs.v2, "task-index.json"), { force: true });
|
|
14538
|
+
fs11.renameSync(marker, path15.join(dirs.v2, "store.moved.json"));
|
|
14446
14539
|
} catch (error) {
|
|
14447
14540
|
return failure2("storage_error", `cannot move ${dirs.v2} into ${dirs.dir}: ${String(error)}`, {
|
|
14448
14541
|
path: dirs.v2
|
|
@@ -14480,7 +14573,7 @@ class TaskStore {
|
|
|
14480
14573
|
schemaVersion: SCHEMA_VERSION,
|
|
14481
14574
|
id: workspaceId ?? newId(),
|
|
14482
14575
|
revision: newRevision(),
|
|
14483
|
-
root:
|
|
14576
|
+
root: path15.dirname(v2),
|
|
14484
14577
|
runtime: { createdWith: version, updatedWith: version },
|
|
14485
14578
|
writer: null,
|
|
14486
14579
|
store: {
|
|
@@ -14492,11 +14585,11 @@ class TaskStore {
|
|
|
14492
14585
|
critical: ["store"]
|
|
14493
14586
|
};
|
|
14494
14587
|
fs11.mkdirSync(v2, { recursive: true });
|
|
14495
|
-
const ignore =
|
|
14588
|
+
const ignore = path15.join(v2, ".gitignore");
|
|
14496
14589
|
if (!fs11.existsSync(ignore))
|
|
14497
14590
|
fs11.writeFileSync(ignore, `*
|
|
14498
14591
|
`);
|
|
14499
|
-
replaceFile(
|
|
14592
|
+
replaceFile(path15.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
|
|
14500
14593
|
`, true);
|
|
14501
14594
|
}
|
|
14502
14595
|
stubFor(taskId) {
|
|
@@ -14520,8 +14613,8 @@ class TaskStore {
|
|
|
14520
14613
|
}
|
|
14521
14614
|
writeTombstoneIfMissing() {
|
|
14522
14615
|
try {
|
|
14523
|
-
const v2 =
|
|
14524
|
-
if (fs11.existsSync(
|
|
14616
|
+
const v2 = path15.join(this.root, ".workit");
|
|
14617
|
+
if (fs11.existsSync(path15.join(v2, "workspace.json")))
|
|
14525
14618
|
return;
|
|
14526
14619
|
let id = null;
|
|
14527
14620
|
try {
|
|
@@ -14538,7 +14631,7 @@ class TaskStore {
|
|
|
14538
14631
|
replaceFile(dirs.marker, `${JSON.stringify({ format: "workit-store", version: STORE_FORMAT, createdWith: runtimeVersion() })}
|
|
14539
14632
|
`, false);
|
|
14540
14633
|
if (!dirs.shared) {
|
|
14541
|
-
const ignore =
|
|
14634
|
+
const ignore = path15.join(dirs.dir, ".gitignore");
|
|
14542
14635
|
let current = null;
|
|
14543
14636
|
try {
|
|
14544
14637
|
current = fs11.readFileSync(ignore, "utf8");
|
|
@@ -14598,7 +14691,7 @@ class TaskStore {
|
|
|
14598
14691
|
withLock(lockPath, operation) {
|
|
14599
14692
|
try {
|
|
14600
14693
|
this.initializeStorage();
|
|
14601
|
-
fs11.mkdirSync(
|
|
14694
|
+
fs11.mkdirSync(path15.dirname(lockPath), { recursive: true });
|
|
14602
14695
|
} catch (error) {
|
|
14603
14696
|
return failure2("storage_error", `unable to initialize store: ${String(error)}`, {
|
|
14604
14697
|
path: this.paths().dir
|
|
@@ -14661,7 +14754,7 @@ class TaskStore {
|
|
|
14661
14754
|
if (isTransientWindowsError(error) && !this.lockHolderPresent(lockPath) && !this.lockDirWritable(lockPath))
|
|
14662
14755
|
return failure2("storage_error", `cannot create the workit lock (${code}); no other Workit call holds it`, {
|
|
14663
14756
|
path: lockPath,
|
|
14664
|
-
guidance: `Check permissions and the read-only attribute on ${
|
|
14757
|
+
guidance: `Check permissions and the read-only attribute on ${path15.dirname(lockPath)}.`
|
|
14665
14758
|
});
|
|
14666
14759
|
if (code === "EEXIST" || code === "file_lock_timeout" || code === "file_lock_stale" || isTransientWindowsError(error)) {
|
|
14667
14760
|
let lock = null;
|
|
@@ -14688,12 +14781,12 @@ var workerBlocksTransition = (transition, state) => transition === "pause" ? fal
|
|
|
14688
14781
|
import { createHash as createHash10 } from "node:crypto";
|
|
14689
14782
|
import * as fs13 from "node:fs";
|
|
14690
14783
|
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
14691
|
-
import
|
|
14784
|
+
import path17 from "node:path";
|
|
14692
14785
|
|
|
14693
14786
|
// packages/workit-core/src/check-config.ts
|
|
14694
14787
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
14695
14788
|
import fs12 from "node:fs";
|
|
14696
|
-
import
|
|
14789
|
+
import path16 from "node:path";
|
|
14697
14790
|
var SCRIPT_CHECKS = ["test", "lint", "typecheck", "check"];
|
|
14698
14791
|
var CHECKS_FILE = "workit.checks.json";
|
|
14699
14792
|
var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -14746,10 +14839,10 @@ var git4 = (cwd, args) => {
|
|
|
14746
14839
|
return value || null;
|
|
14747
14840
|
};
|
|
14748
14841
|
function checkRoot(cwd) {
|
|
14749
|
-
return
|
|
14842
|
+
return path16.resolve(git4(cwd, ["rev-parse", "--show-toplevel"]) ?? cwd);
|
|
14750
14843
|
}
|
|
14751
14844
|
var packageManager = (root) => {
|
|
14752
|
-
const has = (file) => fs12.existsSync(
|
|
14845
|
+
const has = (file) => fs12.existsSync(path16.join(root, file));
|
|
14753
14846
|
if (has("bun.lock") || has("bun.lockb"))
|
|
14754
14847
|
return "bun";
|
|
14755
14848
|
if (has("pnpm-lock.yaml"))
|
|
@@ -14769,7 +14862,7 @@ var CHECK_NAME = /^[a-z0-9][a-z0-9:._-]{0,63}$/u;
|
|
|
14769
14862
|
function detectedChecks(root) {
|
|
14770
14863
|
const read = (file) => {
|
|
14771
14864
|
try {
|
|
14772
|
-
return fs12.readFileSync(
|
|
14865
|
+
return fs12.readFileSync(path16.join(root, file), "utf8");
|
|
14773
14866
|
} catch {
|
|
14774
14867
|
return null;
|
|
14775
14868
|
}
|
|
@@ -14808,7 +14901,7 @@ function detectedChecks(root) {
|
|
|
14808
14901
|
var GATES = ["testing", "verification"];
|
|
14809
14902
|
function loadCheckConfig(cwd) {
|
|
14810
14903
|
const root = checkRoot(cwd);
|
|
14811
|
-
const file =
|
|
14904
|
+
const file = path16.join(root, CHECKS_FILE);
|
|
14812
14905
|
const none = (error = null) => ({
|
|
14813
14906
|
source: error ? CHECKS_FILE : "none",
|
|
14814
14907
|
root,
|
|
@@ -14881,10 +14974,10 @@ function workitAvailable(env = process.env) {
|
|
|
14881
14974
|
return workitOnPath;
|
|
14882
14975
|
const windows = process.platform === "win32";
|
|
14883
14976
|
const exts = windows ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
|
|
14884
|
-
const dirs = (env.PATH ?? env.Path ?? "").split(
|
|
14977
|
+
const dirs = (env.PATH ?? env.Path ?? "").split(path16.delimiter).filter(Boolean);
|
|
14885
14978
|
workitOnPath = dirs.some((dir) => exts.some((ext) => {
|
|
14886
14979
|
try {
|
|
14887
|
-
return fs12.statSync(
|
|
14980
|
+
return fs12.statSync(path16.join(dir, `workit${ext}`)).isFile();
|
|
14888
14981
|
} catch {
|
|
14889
14982
|
return false;
|
|
14890
14983
|
}
|
|
@@ -14897,14 +14990,14 @@ function checkCommand(args, version, onPath = workitAvailable()) {
|
|
|
14897
14990
|
|
|
14898
14991
|
// packages/workit-core/src/core/task-evaluation.ts
|
|
14899
14992
|
var digestBytes = (value) => createHash10("sha256").update(value).digest("hex");
|
|
14900
|
-
var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${
|
|
14901
|
-
var relative = (root, candidate) =>
|
|
14993
|
+
var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path17.sep}`);
|
|
14994
|
+
var relative = (root, candidate) => path17.relative(root, candidate).split(path17.sep).join("/") || ".";
|
|
14902
14995
|
var canonicalPath = (value) => {
|
|
14903
14996
|
if (typeof value !== "string" || !value)
|
|
14904
14997
|
return null;
|
|
14905
14998
|
if (value.includes("\\") || value.split("/").includes(".."))
|
|
14906
14999
|
return null;
|
|
14907
|
-
const normalized =
|
|
15000
|
+
const normalized = path17.posix.normalize(value);
|
|
14908
15001
|
if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
|
|
14909
15002
|
return null;
|
|
14910
15003
|
return normalized === "." ? "." : normalized.replace(/\/$/, "");
|
|
@@ -14952,14 +15045,14 @@ var gitPaths = (root) => {
|
|
|
14952
15045
|
git: !/not a git repository/i.test(stderr)
|
|
14953
15046
|
};
|
|
14954
15047
|
}
|
|
14955
|
-
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(
|
|
15048
|
+
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path17.sep).join("/")) : [];
|
|
14956
15049
|
const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
|
|
14957
15050
|
if (stagedDeleted.status !== 0) {
|
|
14958
15051
|
const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
|
|
14959
15052
|
if (!/not a git repository/i.test(stderr))
|
|
14960
15053
|
return { paths, uncertain: true, git: true };
|
|
14961
15054
|
} else if (stagedDeleted.stdout) {
|
|
14962
|
-
paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(
|
|
15055
|
+
paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path17.sep).join("/")));
|
|
14963
15056
|
}
|
|
14964
15057
|
return { paths: [...new Set(paths)], uncertain: false, git: true };
|
|
14965
15058
|
};
|
|
@@ -14974,7 +15067,7 @@ var walk = (root, directory, output) => {
|
|
|
14974
15067
|
for (const name of names) {
|
|
14975
15068
|
if (name === ".git" || name === ".workit")
|
|
14976
15069
|
continue;
|
|
14977
|
-
const target =
|
|
15070
|
+
const target = path17.join(directory, name);
|
|
14978
15071
|
let stat;
|
|
14979
15072
|
try {
|
|
14980
15073
|
stat = fs13.lstatSync(target);
|
|
@@ -14992,12 +15085,12 @@ var walk = (root, directory, output) => {
|
|
|
14992
15085
|
var scopeRoots = (root, scope) => {
|
|
14993
15086
|
const roots = [];
|
|
14994
15087
|
for (const item of scope.paths.length ? scope.paths : ["."]) {
|
|
14995
|
-
const target =
|
|
15088
|
+
const target = path17.resolve(root, item);
|
|
14996
15089
|
if (!inside(root, target))
|
|
14997
15090
|
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` }] });
|
|
14998
15091
|
let ancestor = target;
|
|
14999
15092
|
while (!fs13.existsSync(ancestor) && ancestor !== root)
|
|
15000
|
-
ancestor =
|
|
15093
|
+
ancestor = path17.dirname(ancestor);
|
|
15001
15094
|
try {
|
|
15002
15095
|
if (!inside(root, fs13.realpathSync(ancestor)))
|
|
15003
15096
|
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` }] });
|
|
@@ -15049,7 +15142,7 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
15049
15142
|
for (const item of [...names].toSorted()) {
|
|
15050
15143
|
if (!scopeMatches(item, normalizedScope))
|
|
15051
15144
|
continue;
|
|
15052
|
-
const target =
|
|
15145
|
+
const target = path17.join(checkout, item);
|
|
15053
15146
|
try {
|
|
15054
15147
|
const stat = fs13.lstatSync(target);
|
|
15055
15148
|
if (stat.isSymbolicLink()) {
|
|
@@ -15233,23 +15326,23 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
|
15233
15326
|
continue;
|
|
15234
15327
|
if (!reference.digest)
|
|
15235
15328
|
return failure2("invalid_input", "document references require a byte digest");
|
|
15236
|
-
const target =
|
|
15237
|
-
if (target !== root && !target.startsWith(`${root}${
|
|
15329
|
+
const target = path17.resolve(root, reference.path);
|
|
15330
|
+
if (target !== root && !target.startsWith(`${root}${path17.sep}`))
|
|
15238
15331
|
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
15239
15332
|
fields: [
|
|
15240
15333
|
{ path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
|
|
15241
15334
|
]
|
|
15242
15335
|
});
|
|
15243
15336
|
try {
|
|
15244
|
-
const below =
|
|
15337
|
+
const below = path17.relative(root, target);
|
|
15245
15338
|
let current = root;
|
|
15246
|
-
for (const segment of below.split(
|
|
15339
|
+
for (const segment of below.split(path17.sep)) {
|
|
15247
15340
|
if (!segment)
|
|
15248
15341
|
continue;
|
|
15249
|
-
current =
|
|
15342
|
+
current = path17.join(current, segment);
|
|
15250
15343
|
const stat = fs13.lstatSync(current);
|
|
15251
15344
|
const real = fs13.realpathSync(current);
|
|
15252
|
-
if (real !== root && !real.startsWith(`${root}${
|
|
15345
|
+
if (real !== root && !real.startsWith(`${root}${path17.sep}`))
|
|
15253
15346
|
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
15254
15347
|
fields: [
|
|
15255
15348
|
{
|
|
@@ -17467,7 +17560,7 @@ var capabilitiesFor = (descriptor, observed = {}) => descriptor.capabilities.map
|
|
|
17467
17560
|
// packages/workit-core/src/hooks/context.ts
|
|
17468
17561
|
import { createHash as createHash11 } from "node:crypto";
|
|
17469
17562
|
import fs14 from "node:fs";
|
|
17470
|
-
import
|
|
17563
|
+
import path18 from "node:path";
|
|
17471
17564
|
var MIGRATION_PENDING_NOTE = "workit migration pending — run `workit task status`";
|
|
17472
17565
|
var migrationPending = (result) => !result.ok && result.code === "needs_input" && (result.error ?? "").startsWith(MIGRATION_PENDING);
|
|
17473
17566
|
var boundTo = (entry, session) => entry.sessions.some((item) => item.host === session.host && item.handle === session.handle);
|
|
@@ -17552,7 +17645,7 @@ function entryCompactContext(store, entry, session, context) {
|
|
|
17552
17645
|
return null;
|
|
17553
17646
|
const freshness = { mode: "signal", current: () => recentSignal(store.root) };
|
|
17554
17647
|
const observed = task?.data.evidence.some(isObservedCheck) ?? false;
|
|
17555
|
-
const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [
|
|
17648
|
+
const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [path18.resolve(store.root, ref.path)] : []));
|
|
17556
17649
|
const observedFiles = filesKey(files);
|
|
17557
17650
|
const compact = new WorkitCore(store, context).compactContext(entry?.id ?? null, freshness, origin && { origin: origin.origin, taskId: origin.entry.id });
|
|
17558
17651
|
if (!compact.ok || !compact.data)
|
|
@@ -17630,14 +17723,14 @@ var turnMarker = (input) => {
|
|
|
17630
17723
|
if (location instanceof Error)
|
|
17631
17724
|
return null;
|
|
17632
17725
|
const session = [input.host, input.session.id, input.session.agentId ?? ""].join("\x00");
|
|
17633
|
-
return
|
|
17726
|
+
return path18.join(location.dir, "hooks", `turn-${digestOf(session).slice(0, 32)}.json`);
|
|
17634
17727
|
} catch {
|
|
17635
17728
|
return null;
|
|
17636
17729
|
}
|
|
17637
17730
|
};
|
|
17638
17731
|
var writeTurnDigest = (file, digest) => {
|
|
17639
17732
|
try {
|
|
17640
|
-
fs14.mkdirSync(
|
|
17733
|
+
fs14.mkdirSync(path18.dirname(file), { recursive: true });
|
|
17641
17734
|
fs14.writeFileSync(file, `${JSON.stringify({ digest })}
|
|
17642
17735
|
`);
|
|
17643
17736
|
} catch {}
|
|
@@ -17652,7 +17745,7 @@ var pruneTurnDigests = (dir, now) => {
|
|
|
17652
17745
|
for (const name of fs14.readdirSync(dir)) {
|
|
17653
17746
|
if (!name.startsWith("turn-"))
|
|
17654
17747
|
continue;
|
|
17655
|
-
const file =
|
|
17748
|
+
const file = path18.join(dir, name);
|
|
17656
17749
|
try {
|
|
17657
17750
|
if (now - fs14.statSync(file).mtimeMs > TURN_TTL_MS)
|
|
17658
17751
|
fs14.rmSync(file, { force: true });
|
|
@@ -17682,7 +17775,7 @@ var seedTurnContext = (input, descriptor, text = turnContextText(input, descript
|
|
|
17682
17775
|
const file = turnMarker(input);
|
|
17683
17776
|
if (!file)
|
|
17684
17777
|
return;
|
|
17685
|
-
pruneTurnDigests(
|
|
17778
|
+
pruneTurnDigests(path18.dirname(file), Date.now());
|
|
17686
17779
|
if (text)
|
|
17687
17780
|
writeTurnDigest(file, digestOf(text));
|
|
17688
17781
|
else
|
|
@@ -17691,14 +17784,14 @@ var seedTurnContext = (input, descriptor, text = turnContextText(input, descript
|
|
|
17691
17784
|
// packages/workit-core/src/core/route-intent.ts
|
|
17692
17785
|
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
17693
17786
|
import { existsSync as existsSync6 } from "node:fs";
|
|
17694
|
-
import
|
|
17787
|
+
import path21 from "node:path";
|
|
17695
17788
|
|
|
17696
17789
|
// packages/workit-core/src/hooks/raw-git.ts
|
|
17697
17790
|
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
17698
17791
|
import { createHash as createHash14 } from "node:crypto";
|
|
17699
17792
|
import fs16 from "node:fs";
|
|
17700
|
-
import
|
|
17701
|
-
import
|
|
17793
|
+
import os5 from "node:os";
|
|
17794
|
+
import path20 from "node:path";
|
|
17702
17795
|
|
|
17703
17796
|
// packages/workit-core/src/core/branch.ts
|
|
17704
17797
|
import { createHash as createHash12 } from "node:crypto";
|
|
@@ -17911,7 +18004,7 @@ var globOf = (pattern) => pattern.source.replace(/^\^|\$$/gu, "").replaceAll(".*
|
|
|
17911
18004
|
// packages/workit-core/src/hooks/session-marker.ts
|
|
17912
18005
|
import { createHash as createHash13 } from "node:crypto";
|
|
17913
18006
|
import fs15 from "node:fs";
|
|
17914
|
-
import
|
|
18007
|
+
import path19 from "node:path";
|
|
17915
18008
|
var sessionMarkerFile = (input, session, store) => {
|
|
17916
18009
|
let dir = store;
|
|
17917
18010
|
if (dir === undefined) {
|
|
@@ -17921,7 +18014,7 @@ var sessionMarkerFile = (input, session, store) => {
|
|
|
17921
18014
|
dir = location.dir;
|
|
17922
18015
|
}
|
|
17923
18016
|
const name = createHash13("sha256").update(`${input.host}\x00${session}`).digest("hex").slice(0, 32);
|
|
17924
|
-
return
|
|
18017
|
+
return path19.join(dir, "hooks", `skills-${name}.json`);
|
|
17925
18018
|
};
|
|
17926
18019
|
var list2 = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
17927
18020
|
var readSessionMarker = (file) => {
|
|
@@ -17934,7 +18027,7 @@ var readSessionMarker = (file) => {
|
|
|
17934
18027
|
};
|
|
17935
18028
|
var writeSessionMarker = (file, marker) => {
|
|
17936
18029
|
try {
|
|
17937
|
-
fs15.mkdirSync(
|
|
18030
|
+
fs15.mkdirSync(path19.dirname(file), { recursive: true });
|
|
17938
18031
|
fs15.writeFileSync(file, JSON.stringify(marker));
|
|
17939
18032
|
} catch {}
|
|
17940
18033
|
};
|
|
@@ -18079,12 +18172,12 @@ var GIT_VALUE_OPTIONS = new Set([
|
|
|
18079
18172
|
"--config-env",
|
|
18080
18173
|
"--super-prefix"
|
|
18081
18174
|
]);
|
|
18082
|
-
var isAbsolute = (value) =>
|
|
18175
|
+
var isAbsolute = (value) => path20.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\");
|
|
18083
18176
|
var joinDir = (base, next) => {
|
|
18084
18177
|
if (base === undefined || /[$`*?]/.test(next) || next === "-")
|
|
18085
18178
|
return;
|
|
18086
|
-
const expanded = next === "~" || next.startsWith("~/") ?
|
|
18087
|
-
return base === null || isAbsolute(expanded) ? expanded :
|
|
18179
|
+
const expanded = next === "~" || next.startsWith("~/") ? path20.join(os5.homedir(), next.slice(1)) : next;
|
|
18180
|
+
return base === null || isAbsolute(expanded) ? expanded : path20.join(base, expanded);
|
|
18088
18181
|
};
|
|
18089
18182
|
var cdTarget = (words) => {
|
|
18090
18183
|
const args = words.slice(1);
|
|
@@ -18135,7 +18228,7 @@ function rawInvocations(command, dialect = "posix", depth = 0) {
|
|
|
18135
18228
|
const name = commandName(words[0]);
|
|
18136
18229
|
if (CD.has(name)) {
|
|
18137
18230
|
const target = cdTarget(words);
|
|
18138
|
-
dir = target === null ?
|
|
18231
|
+
dir = target === null ? os5.homedir() : joinDir(dir, target);
|
|
18139
18232
|
continue;
|
|
18140
18233
|
}
|
|
18141
18234
|
if (PUSHD.has(name)) {
|
|
@@ -18393,17 +18486,17 @@ var headSha2 = (repo) => {
|
|
|
18393
18486
|
if (!git || git.reftable)
|
|
18394
18487
|
return null;
|
|
18395
18488
|
try {
|
|
18396
|
-
const head = fs16.readFileSync(
|
|
18489
|
+
const head = fs16.readFileSync(path20.join(git.gitDir, "HEAD"), "utf8").trim();
|
|
18397
18490
|
if (/^[0-9a-f]{40,64}$/.test(head))
|
|
18398
18491
|
return head;
|
|
18399
18492
|
const ref = /^ref: (refs\/.+)$/.exec(head)?.[1];
|
|
18400
18493
|
if (!ref)
|
|
18401
18494
|
return null;
|
|
18402
|
-
const common =
|
|
18495
|
+
const common = path20.dirname(repo.location.dir);
|
|
18403
18496
|
try {
|
|
18404
|
-
return fs16.readFileSync(
|
|
18497
|
+
return fs16.readFileSync(path20.join(common, ref), "utf8").trim() || null;
|
|
18405
18498
|
} catch {}
|
|
18406
|
-
const packed = fs16.readFileSync(
|
|
18499
|
+
const packed = fs16.readFileSync(path20.join(common, "packed-refs"), "utf8");
|
|
18407
18500
|
return new RegExp(`^([0-9a-f]{40,64}) ${ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`, "m").exec(packed)?.[1] ?? null;
|
|
18408
18501
|
} catch {
|
|
18409
18502
|
return null;
|
|
@@ -18492,7 +18585,7 @@ var actionsIn = (cwd, command, dialect) => {
|
|
|
18492
18585
|
const action = rawAction(invocation);
|
|
18493
18586
|
if (!action)
|
|
18494
18587
|
continue;
|
|
18495
|
-
const dir =
|
|
18588
|
+
const dir = path20.resolve(cwd, invocation.dir ?? ".");
|
|
18496
18589
|
if (!repos.has(dir)) {
|
|
18497
18590
|
const repo = repoAt(dir);
|
|
18498
18591
|
repos.set(dir, repo && isWorkitWorkspace(repo) ? repo : null);
|
|
@@ -18572,7 +18665,7 @@ function rawGitPre(input, command, options = {}) {
|
|
|
18572
18665
|
var deny = (reason) => ({ kind: "deny", reason, unblock: null });
|
|
18573
18666
|
var NEXT_COMMAND = "next";
|
|
18574
18667
|
var MARKER_TTL_SECONDS = 3600;
|
|
18575
|
-
var markerFile = (repo, session, key) =>
|
|
18668
|
+
var markerFile = (repo, session, key) => path20.join(repo.location.dir, "hooks", `commit-${createHash14("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`);
|
|
18576
18669
|
var callKey = (toolUseId, command) => toolUseId ?? `cmd:${createHash14("sha256").update(command).digest("hex")}`;
|
|
18577
18670
|
function noteRawCommit(input, command, key) {
|
|
18578
18671
|
try {
|
|
@@ -18583,7 +18676,7 @@ function noteRawCommit(input, command, key) {
|
|
|
18583
18676
|
if (action.kind !== "commit")
|
|
18584
18677
|
continue;
|
|
18585
18678
|
const file = markerFile(repo, input.session.id, key);
|
|
18586
|
-
fs16.mkdirSync(
|
|
18679
|
+
fs16.mkdirSync(path20.dirname(file), { recursive: true });
|
|
18587
18680
|
fs16.writeFileSync(file, `${JSON.stringify({ head: headSha2(repo), at })}
|
|
18588
18681
|
`);
|
|
18589
18682
|
}
|
|
@@ -18756,7 +18849,7 @@ var shellBranchPolicyViolation = (root, command, dialect = "posix") => {
|
|
|
18756
18849
|
for (const target of shellBranchTargets(command, dialect)) {
|
|
18757
18850
|
if (target.dir === undefined)
|
|
18758
18851
|
continue;
|
|
18759
|
-
const dir = target.dir === null ? root :
|
|
18852
|
+
const dir = target.dir === null ? root : path21.resolve(root, target.dir);
|
|
18760
18853
|
if (target.dir !== null && (!existsSync6(dir) || !inWorkitWorkspace(dir)))
|
|
18761
18854
|
continue;
|
|
18762
18855
|
if (localBranchExists(dir, target.branch))
|
|
@@ -18776,27 +18869,27 @@ var shellPolicy = (cwd, command, dialect = "posix") => {
|
|
|
18776
18869
|
};
|
|
18777
18870
|
// packages/workit-core/src/hooks/write-gate.ts
|
|
18778
18871
|
import { realpathSync as realpathSync5 } from "node:fs";
|
|
18779
|
-
import
|
|
18872
|
+
import path22 from "node:path";
|
|
18780
18873
|
var NONE3 = { kind: "none" };
|
|
18781
18874
|
var CASE_INSENSITIVE = process.platform === "darwin" || process.platform === "win32";
|
|
18782
18875
|
var canonical2 = (file) => {
|
|
18783
18876
|
let rest = "";
|
|
18784
|
-
for (let dir =
|
|
18877
|
+
for (let dir = path22.resolve(file);; dir = path22.dirname(dir)) {
|
|
18785
18878
|
try {
|
|
18786
|
-
return
|
|
18879
|
+
return path22.join(realpathSync5(dir), rest);
|
|
18787
18880
|
} catch {
|
|
18788
|
-
if (
|
|
18789
|
-
return
|
|
18790
|
-
rest = rest ?
|
|
18881
|
+
if (path22.dirname(dir) === dir)
|
|
18882
|
+
return path22.resolve(file);
|
|
18883
|
+
rest = rest ? path22.join(path22.basename(dir), rest) : path22.basename(dir);
|
|
18791
18884
|
}
|
|
18792
18885
|
}
|
|
18793
18886
|
};
|
|
18794
18887
|
var exempt = (cwd, root, file, plans) => {
|
|
18795
18888
|
const fold = (value) => CASE_INSENSITIVE ? value.toLowerCase() : value;
|
|
18796
|
-
const relative =
|
|
18797
|
-
if (relative.startsWith("..") ||
|
|
18889
|
+
const relative = path22.relative(fold(canonical2(root)), fold(canonical2(path22.resolve(cwd, file))));
|
|
18890
|
+
if (relative.startsWith("..") || path22.isAbsolute(relative))
|
|
18798
18891
|
return true;
|
|
18799
|
-
const posix = relative.split(
|
|
18892
|
+
const posix = relative.split(path22.sep).join("/");
|
|
18800
18893
|
const segments = posix.split("/");
|
|
18801
18894
|
return /\.mdx?$/i.test(posix) || segments[0] === "docs" || segments.includes("plans") || [...plans].some((plan) => fold(plan) === posix);
|
|
18802
18895
|
};
|
|
@@ -18894,7 +18987,7 @@ var shellWrites = (command) => {
|
|
|
18894
18987
|
return { writes: true, targets: unknown ? null : targets };
|
|
18895
18988
|
};
|
|
18896
18989
|
var cache2 = new Map;
|
|
18897
|
-
var planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(
|
|
18990
|
+
var planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(path22.resolve(root, file)) ?? "-").join("\x00");
|
|
18898
18991
|
var gateFor = (cwd) => {
|
|
18899
18992
|
const store = new TaskStore(cwd);
|
|
18900
18993
|
const listed = store.listTaskIndex();
|
|
@@ -19335,12 +19428,12 @@ ${line}` };
|
|
|
19335
19428
|
};
|
|
19336
19429
|
// packages/workit-core/src/hooks/hosts/fields.ts
|
|
19337
19430
|
import { existsSync as existsSync7, realpathSync as realpathSync6, statSync as statSync2 } from "node:fs";
|
|
19338
|
-
import
|
|
19431
|
+
import path23 from "node:path";
|
|
19339
19432
|
var isRecord4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
19340
19433
|
var nonEmpty2 = (value) => typeof value === "string" && value.trim() !== "";
|
|
19341
19434
|
var optionalText = (value) => typeof value === "string" ? value : null;
|
|
19342
19435
|
var existingDirectory = (value) => {
|
|
19343
|
-
if (!nonEmpty2(value) || !
|
|
19436
|
+
if (!nonEmpty2(value) || !path23.isAbsolute(value) || !existsSync7(value))
|
|
19344
19437
|
return null;
|
|
19345
19438
|
try {
|
|
19346
19439
|
return statSync2(value).isDirectory() ? realpathSync6(value) : null;
|
|
@@ -20079,7 +20172,7 @@ var codexAdapter = {
|
|
|
20079
20172
|
|
|
20080
20173
|
// packages/workit-core/src/hooks/hosts/cursor.ts
|
|
20081
20174
|
import fs17 from "node:fs";
|
|
20082
|
-
import
|
|
20175
|
+
import path24 from "node:path";
|
|
20083
20176
|
var undocumented = { support: "undocumented", native: null };
|
|
20084
20177
|
var none = { support: "none", native: null };
|
|
20085
20178
|
var CURSOR_DESCRIPTOR = {
|
|
@@ -20276,7 +20369,7 @@ var protocolEvent2 = (input) => {
|
|
|
20276
20369
|
};
|
|
20277
20370
|
var TRANSCRIPT_TAIL_BYTES = 256 * 1024;
|
|
20278
20371
|
var lastAssistantText = (file) => {
|
|
20279
|
-
if (!file || !
|
|
20372
|
+
if (!file || !path24.isAbsolute(file))
|
|
20280
20373
|
return null;
|
|
20281
20374
|
try {
|
|
20282
20375
|
const size = fs17.statSync(file).size;
|
|
@@ -20313,7 +20406,7 @@ var lastAssistantText = (file) => {
|
|
|
20313
20406
|
return null;
|
|
20314
20407
|
}
|
|
20315
20408
|
};
|
|
20316
|
-
var within = (root, dir) => dir === root || dir.startsWith(root.endsWith(
|
|
20409
|
+
var within = (root, dir) => dir === root || dir.startsWith(root.endsWith(path24.sep) ? root : `${root}${path24.sep}`);
|
|
20317
20410
|
var hookCwd = (input) => {
|
|
20318
20411
|
const cwd = existingDirectory(input.cwd);
|
|
20319
20412
|
if (cwd && input.hook_event_name === "beforeShellExecution")
|