@brainervirus/workit-cursor 8.11.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 +340 -225
- package/dist/mcp-server.js +277 -276
- package/dist/workit-hook.js +341 -227
- package/package.json +3 -3
- package/skills/workit-fanout/references/brief.md +23 -8
- package/skills/workit-fanout/references/orchestration.md +9 -4
|
@@ -9120,8 +9120,8 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
9120
9120
|
profiles: record(nonBlank, profileSchema).optional()
|
|
9121
9121
|
}).passthrough();
|
|
9122
9122
|
return entrySchema;
|
|
9123
|
-
}, resolveRuntimeWorkspaceVcs = (cwd) => resolveRuntimeWorkspaceCandidate(cwd, "vcs"), runtimeWorkspaceIndexSchema, matchRuntimeWorkspace = (cwd) => {
|
|
9124
|
-
const file = path3.join(
|
|
9123
|
+
}, resolveRuntimeWorkspaceVcs = (cwd) => resolveRuntimeWorkspaceCandidate(cwd, "vcs"), runtimeWorkspaceIndexSchema, matchRuntimeWorkspace = (cwd, dir = configDir()) => {
|
|
9124
|
+
const file = path3.join(dir, "workspaces.json");
|
|
9125
9125
|
let raw;
|
|
9126
9126
|
try {
|
|
9127
9127
|
raw = readFileSync2(file, "utf8");
|
|
@@ -9150,10 +9150,27 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
9150
9150
|
const matches = matchingEntries(cwd, entries ?? []);
|
|
9151
9151
|
const workspaceName = process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined;
|
|
9152
9152
|
const selected = selectWorkspaceMatch(matches, cwd, workspaceName);
|
|
9153
|
-
return selected ? { file, selected } : null;
|
|
9153
|
+
return selected ? { file, selected, matches } : null;
|
|
9154
9154
|
}, resolveRuntimeReleaseTracks = (cwd) => {
|
|
9155
9155
|
const matched = matchRuntimeWorkspace(cwd);
|
|
9156
9156
|
return matched ? { workspace: matched.selected.name, releaseTracks: matched.selected.releaseTracks } : null;
|
|
9157
|
+
}, workspaceTrailers = (cwd, dir) => {
|
|
9158
|
+
let matched;
|
|
9159
|
+
try {
|
|
9160
|
+
matched = matchRuntimeWorkspace(cwd, dir);
|
|
9161
|
+
} catch {
|
|
9162
|
+
return { enabled: true, workspace: null, from: null };
|
|
9163
|
+
}
|
|
9164
|
+
if (!matched)
|
|
9165
|
+
return { enabled: true, workspace: null, from: null };
|
|
9166
|
+
const { selected, matches } = matched;
|
|
9167
|
+
const enclosing = matches.filter((entry) => entry !== selected).toSorted((a, b) => globSpecificity(b.glob) - globSpecificity(a.glob));
|
|
9168
|
+
const source = [selected, ...enclosing].find((entry) => typeof entry.trailers === "boolean");
|
|
9169
|
+
return {
|
|
9170
|
+
enabled: source?.trailers !== false,
|
|
9171
|
+
workspace: selected.name,
|
|
9172
|
+
from: source?.name ?? null
|
|
9173
|
+
};
|
|
9157
9174
|
}, resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
|
|
9158
9175
|
const matched = matchRuntimeWorkspace(cwd);
|
|
9159
9176
|
if (!matched)
|
|
@@ -9264,6 +9281,7 @@ var init_workspaces = __esm(() => {
|
|
|
9264
9281
|
autoApprove: union([boolean2(), array(nonBlank)]).optional(),
|
|
9265
9282
|
defaultEndpoint: unknown().optional(),
|
|
9266
9283
|
verification: _enum(["self", "independent"]).optional(),
|
|
9284
|
+
trailers: boolean2().optional(),
|
|
9267
9285
|
autonomy: object(Object.fromEntries(["push", "pr", "merge", "release", "rerun"].map((kind) => [
|
|
9268
9286
|
kind,
|
|
9269
9287
|
union([boolean2(), literal("verified")]).optional()
|
|
@@ -9832,11 +9850,71 @@ var init_vcs_config = __esm(() => {
|
|
|
9832
9850
|
init_release_tracks();
|
|
9833
9851
|
});
|
|
9834
9852
|
|
|
9853
|
+
// packages/workit-core/src/core/logger.ts
|
|
9854
|
+
import os3 from "node:os";
|
|
9855
|
+
import path5 from "node:path";
|
|
9856
|
+
var SENSITIVE_WORDS, STACK_WORDS, escapeRegExp2 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), resolveStateDir = () => {
|
|
9857
|
+
const override = process.env.WORKFLOW_TOOLKIT_STATE;
|
|
9858
|
+
if (override)
|
|
9859
|
+
return override;
|
|
9860
|
+
const home = os3.homedir();
|
|
9861
|
+
if (process.env.XDG_STATE_HOME)
|
|
9862
|
+
return path5.join(process.env.XDG_STATE_HOME, "workit");
|
|
9863
|
+
switch (os3.platform()) {
|
|
9864
|
+
case "darwin":
|
|
9865
|
+
return path5.join(home, "Library", "Application Support", "workit");
|
|
9866
|
+
case "win32":
|
|
9867
|
+
return path5.join(process.env.LOCALAPPDATA ?? path5.join(home, "AppData", "Local"), "workit");
|
|
9868
|
+
default:
|
|
9869
|
+
return path5.join(process.env.HOME ?? home, ".local", "state", "workit");
|
|
9870
|
+
}
|
|
9871
|
+
}, homePattern;
|
|
9872
|
+
var init_logger = __esm(() => {
|
|
9873
|
+
SENSITIVE_WORDS = new Set([
|
|
9874
|
+
"token",
|
|
9875
|
+
"secret",
|
|
9876
|
+
"password",
|
|
9877
|
+
"passwd",
|
|
9878
|
+
"authorization",
|
|
9879
|
+
"credential",
|
|
9880
|
+
"credentials",
|
|
9881
|
+
"cookie",
|
|
9882
|
+
"api",
|
|
9883
|
+
"apikey",
|
|
9884
|
+
"apitoken",
|
|
9885
|
+
"accesstoken",
|
|
9886
|
+
"clientsecret",
|
|
9887
|
+
"refreshtoken",
|
|
9888
|
+
"key",
|
|
9889
|
+
"bearer",
|
|
9890
|
+
"prompt",
|
|
9891
|
+
"message",
|
|
9892
|
+
"messages",
|
|
9893
|
+
"content",
|
|
9894
|
+
"body",
|
|
9895
|
+
"args",
|
|
9896
|
+
"argument",
|
|
9897
|
+
"result",
|
|
9898
|
+
"results",
|
|
9899
|
+
"output",
|
|
9900
|
+
"issue",
|
|
9901
|
+
"description",
|
|
9902
|
+
"summary",
|
|
9903
|
+
"payload",
|
|
9904
|
+
"script",
|
|
9905
|
+
"command",
|
|
9906
|
+
"text",
|
|
9907
|
+
"query"
|
|
9908
|
+
]);
|
|
9909
|
+
STACK_WORDS = new Set(["stack", "stacktrace", "trace"]);
|
|
9910
|
+
homePattern = new RegExp(`${escapeRegExp2(os3.homedir())}(?=[/\\\\]|$)|\\$HOME(?=[/\\\\]|$)`, "g");
|
|
9911
|
+
});
|
|
9912
|
+
|
|
9835
9913
|
// packages/workit-core/src/store/paths.ts
|
|
9836
9914
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
9837
9915
|
import { createHash as createHash5 } from "node:crypto";
|
|
9838
9916
|
import fs3 from "node:fs";
|
|
9839
|
-
import
|
|
9917
|
+
import path6 from "node:path";
|
|
9840
9918
|
function fastGit(root) {
|
|
9841
9919
|
if (DISCOVERY_ENV.some((name) => process.env[name]))
|
|
9842
9920
|
return null;
|
|
@@ -9852,7 +9930,7 @@ function fastGit(root) {
|
|
|
9852
9930
|
if (device !== null && stat.dev !== device)
|
|
9853
9931
|
return { kind: "none" };
|
|
9854
9932
|
device = stat.dev;
|
|
9855
|
-
const dotGit =
|
|
9933
|
+
const dotGit = path6.join(dir, ".git");
|
|
9856
9934
|
let entry = null;
|
|
9857
9935
|
try {
|
|
9858
9936
|
entry = fs3.statSync(dotGit);
|
|
@@ -9873,19 +9951,19 @@ function fastGit(root) {
|
|
|
9873
9951
|
const match = /^gitdir: (.+)$/mu.exec(text);
|
|
9874
9952
|
if (!match)
|
|
9875
9953
|
return null;
|
|
9876
|
-
gitDir =
|
|
9954
|
+
gitDir = path6.resolve(dir, match[1].trim());
|
|
9877
9955
|
} else
|
|
9878
9956
|
return null;
|
|
9879
|
-
if (!fs3.existsSync(
|
|
9957
|
+
if (!fs3.existsSync(path6.join(gitDir, "HEAD")))
|
|
9880
9958
|
return null;
|
|
9881
9959
|
} else if (isGitDir(dir))
|
|
9882
9960
|
gitDir = dir;
|
|
9883
9961
|
if (gitDir) {
|
|
9884
9962
|
let common = gitDir;
|
|
9885
9963
|
try {
|
|
9886
|
-
common =
|
|
9964
|
+
common = path6.resolve(gitDir, fs3.readFileSync(path6.join(gitDir, "commondir"), "utf8").trim());
|
|
9887
9965
|
} catch {}
|
|
9888
|
-
if (!fs3.existsSync(
|
|
9966
|
+
if (!fs3.existsSync(path6.join(common, "objects")))
|
|
9889
9967
|
return null;
|
|
9890
9968
|
return {
|
|
9891
9969
|
kind: "repo",
|
|
@@ -9895,26 +9973,26 @@ function fastGit(root) {
|
|
|
9895
9973
|
reftable: reftableRefs(common)
|
|
9896
9974
|
};
|
|
9897
9975
|
}
|
|
9898
|
-
const parent =
|
|
9976
|
+
const parent = path6.dirname(dir);
|
|
9899
9977
|
if (parent === dir)
|
|
9900
9978
|
return { kind: "none" };
|
|
9901
9979
|
dir = parent;
|
|
9902
9980
|
}
|
|
9903
9981
|
}
|
|
9904
9982
|
function resolveStore(root) {
|
|
9905
|
-
root =
|
|
9983
|
+
root = path6.resolve(root);
|
|
9906
9984
|
let directory = false;
|
|
9907
9985
|
try {
|
|
9908
9986
|
directory = fs3.statSync(root).isDirectory();
|
|
9909
9987
|
} catch {}
|
|
9910
9988
|
if (!directory)
|
|
9911
|
-
return { dir:
|
|
9989
|
+
return { dir: path6.join(root, ".workit"), shared: false, top: null };
|
|
9912
9990
|
const fast = fastGit(root);
|
|
9913
9991
|
if (fast?.kind === "none")
|
|
9914
|
-
return { dir:
|
|
9992
|
+
return { dir: path6.join(root, ".workit"), shared: false, top: null };
|
|
9915
9993
|
if (fast?.kind === "repo")
|
|
9916
9994
|
return {
|
|
9917
|
-
dir:
|
|
9995
|
+
dir: path6.join(fast.common, "workit"),
|
|
9918
9996
|
shared: true,
|
|
9919
9997
|
top: fast.top,
|
|
9920
9998
|
git: { gitDir: fast.gitDir, top: fast.top, reftable: fast.reftable }
|
|
@@ -9924,13 +10002,13 @@ function resolveStore(root) {
|
|
|
9924
10002
|
if (run.ok && common) {
|
|
9925
10003
|
const top = gitRun(root, ["rev-parse", "--path-format=absolute", "--show-toplevel"]);
|
|
9926
10004
|
return {
|
|
9927
|
-
dir:
|
|
10005
|
+
dir: path6.join(real(path6.resolve(root, common)), "workit"),
|
|
9928
10006
|
shared: true,
|
|
9929
10007
|
top: top.ok && top.stdout.trim() ? real(top.stdout.trim()) : null
|
|
9930
10008
|
};
|
|
9931
10009
|
}
|
|
9932
10010
|
if (run.missing || !run.ok && NOT_A_REPO.test(run.stderr))
|
|
9933
|
-
return { dir:
|
|
10011
|
+
return { dir: path6.join(root, ".workit"), shared: false, top: null };
|
|
9934
10012
|
return new Error(`cannot locate the workit store: git rev-parse failed (${run.stderr.trim().split(`
|
|
9935
10013
|
`)[0] || "no output"}); fix the repository (git status should work here)`);
|
|
9936
10014
|
}
|
|
@@ -9941,7 +10019,7 @@ function resolveTaskKey(root, location) {
|
|
|
9941
10019
|
if (location.git && !location.git.reftable) {
|
|
9942
10020
|
let head = "";
|
|
9943
10021
|
try {
|
|
9944
|
-
head = fs3.readFileSync(
|
|
10022
|
+
head = fs3.readFileSync(path6.join(location.git.gitDir, "HEAD"), "utf8").trim();
|
|
9945
10023
|
} catch {}
|
|
9946
10024
|
const ref = /^ref: refs\/heads\/(.+)$/u.exec(head);
|
|
9947
10025
|
if (ref && ref[1] !== ".invalid")
|
|
@@ -9972,7 +10050,7 @@ function resolveTaskKey(root, location) {
|
|
|
9972
10050
|
return { key: `detached-${shortHash(real(worktree))}`, kind: "detached", branch: null };
|
|
9973
10051
|
}
|
|
9974
10052
|
function checkoutRootOf(root, location) {
|
|
9975
|
-
const resolved =
|
|
10053
|
+
const resolved = path6.resolve(root);
|
|
9976
10054
|
let canonical = resolved;
|
|
9977
10055
|
try {
|
|
9978
10056
|
canonical = fs3.realpathSync(resolved);
|
|
@@ -10003,13 +10081,13 @@ function branchRenames(location) {
|
|
|
10003
10081
|
}
|
|
10004
10082
|
for (const entry of entries)
|
|
10005
10083
|
if (entry.isDirectory())
|
|
10006
|
-
walk(
|
|
10084
|
+
walk(path6.join(dir, entry.name));
|
|
10007
10085
|
else
|
|
10008
|
-
files.push(
|
|
10086
|
+
files.push(path6.join(dir, entry.name));
|
|
10009
10087
|
};
|
|
10010
|
-
walk(
|
|
10088
|
+
walk(path6.join(path6.dirname(location.dir), "logs", "refs", "heads"));
|
|
10011
10089
|
if (location.git)
|
|
10012
|
-
files.push(
|
|
10090
|
+
files.push(path6.join(location.git.gitDir, "logs", "HEAD"));
|
|
10013
10091
|
const seen = new Set;
|
|
10014
10092
|
const renames = [];
|
|
10015
10093
|
for (const file of files) {
|
|
@@ -10070,20 +10148,20 @@ var NOT_A_REPO, gitRun = (cwd, args) => {
|
|
|
10070
10148
|
}
|
|
10071
10149
|
}, DISCOVERY_ENV, isGitDir = (dir) => {
|
|
10072
10150
|
try {
|
|
10073
|
-
return fs3.statSync(
|
|
10151
|
+
return fs3.statSync(path6.join(dir, "HEAD")).isFile() && fs3.statSync(path6.join(dir, "objects")).isDirectory() && fs3.statSync(path6.join(dir, "refs")).isDirectory();
|
|
10074
10152
|
} catch {
|
|
10075
10153
|
return false;
|
|
10076
10154
|
}
|
|
10077
10155
|
}, reftableRefs = (common) => {
|
|
10078
10156
|
try {
|
|
10079
|
-
return /^\s*refstorage\s*=\s*reftable\s*$/imu.test(fs3.readFileSync(
|
|
10157
|
+
return /^\s*refstorage\s*=\s*reftable\s*$/imu.test(fs3.readFileSync(path6.join(common, "config"), "utf8"));
|
|
10080
10158
|
} catch {
|
|
10081
10159
|
return false;
|
|
10082
10160
|
}
|
|
10083
10161
|
}, rebasingBranch = (gitDir) => {
|
|
10084
10162
|
for (const state of ["rebase-merge", "rebase-apply"]) {
|
|
10085
10163
|
try {
|
|
10086
|
-
const ref = fs3.readFileSync(
|
|
10164
|
+
const ref = fs3.readFileSync(path6.join(gitDir, state, "head-name"), "utf8").trim();
|
|
10087
10165
|
const match = /^refs\/heads\/(.+)$/u.exec(ref);
|
|
10088
10166
|
if (match)
|
|
10089
10167
|
return match[1];
|
|
@@ -10094,7 +10172,7 @@ var NOT_A_REPO, gitRun = (cwd, args) => {
|
|
|
10094
10172
|
let canonical = real(root);
|
|
10095
10173
|
if (process.platform === "win32")
|
|
10096
10174
|
canonical = canonical.toLowerCase();
|
|
10097
|
-
const base =
|
|
10175
|
+
const base = path6.basename(canonical).replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 40) || "root";
|
|
10098
10176
|
return `${base}-${shortHash(canonical)}`;
|
|
10099
10177
|
};
|
|
10100
10178
|
var init_paths = __esm(() => {
|
|
@@ -10111,7 +10189,7 @@ var init_paths = __esm(() => {
|
|
|
10111
10189
|
// packages/workit-core/src/host-session.ts
|
|
10112
10190
|
import { createHash as createHash6 } from "node:crypto";
|
|
10113
10191
|
import fs4 from "node:fs";
|
|
10114
|
-
import
|
|
10192
|
+
import path7 from "node:path";
|
|
10115
10193
|
function hostSessionFromEnv(env) {
|
|
10116
10194
|
const value = (key) => env[key]?.trim() || null;
|
|
10117
10195
|
let inner = null;
|
|
@@ -10130,30 +10208,64 @@ function hostSessionFromEnv(env) {
|
|
|
10130
10208
|
}
|
|
10131
10209
|
return inner ? { host: inner.host, session: inner.session } : { host: declared, session: null };
|
|
10132
10210
|
}
|
|
10133
|
-
function
|
|
10211
|
+
function migrateRepoIssued(cwd) {
|
|
10212
|
+
if (cwd === undefined)
|
|
10213
|
+
return;
|
|
10214
|
+
let old;
|
|
10134
10215
|
try {
|
|
10135
|
-
const
|
|
10136
|
-
if (
|
|
10216
|
+
const location = resolveStore(cwd);
|
|
10217
|
+
if (location instanceof Error)
|
|
10218
|
+
return;
|
|
10219
|
+
old = path7.join(location.dir, "hooks", "issued");
|
|
10220
|
+
if (!fs4.existsSync(old))
|
|
10137
10221
|
return;
|
|
10138
|
-
|
|
10222
|
+
} catch {
|
|
10223
|
+
return;
|
|
10224
|
+
}
|
|
10225
|
+
for (const lead of safeList(old)) {
|
|
10226
|
+
try {
|
|
10227
|
+
const from = path7.join(old, lead);
|
|
10228
|
+
if (!fs4.statSync(from).isDirectory())
|
|
10229
|
+
continue;
|
|
10230
|
+
const to = path7.join(userIssuedRoot(), lead);
|
|
10231
|
+
fs4.mkdirSync(to, { recursive: true, mode: 448 });
|
|
10232
|
+
for (const id of fs4.readdirSync(from)) {
|
|
10233
|
+
fs4.copyFileSync(path7.join(from, id), path7.join(to, id));
|
|
10234
|
+
fs4.rmSync(path7.join(from, id), { force: true });
|
|
10235
|
+
}
|
|
10236
|
+
removeIfEmpty(from);
|
|
10237
|
+
} catch {}
|
|
10238
|
+
}
|
|
10239
|
+
removeIfEmpty(old);
|
|
10240
|
+
}
|
|
10241
|
+
function recordIssuedSession(cwd, lead, issued) {
|
|
10242
|
+
try {
|
|
10243
|
+
migrateRepoIssued(cwd);
|
|
10244
|
+
const dir = path7.join(userIssuedRoot(), hash(lead));
|
|
10245
|
+
fs4.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
10139
10246
|
const own = hash(issued);
|
|
10140
|
-
fs4.writeFileSync(
|
|
10247
|
+
fs4.writeFileSync(path7.join(dir, own), ISSUED_SESSIONS_MARKER);
|
|
10141
10248
|
const entries = fs4.readdirSync(dir);
|
|
10142
10249
|
if (entries.length <= ISSUED_PER_LEAD)
|
|
10143
10250
|
return;
|
|
10144
|
-
const byAge = entries.filter((name) => name !== own).map((name) => ({ name, at: fs4.statSync(
|
|
10251
|
+
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);
|
|
10145
10252
|
for (const { name } of byAge.slice(0, entries.length - ISSUED_PER_LEAD))
|
|
10146
|
-
fs4.rmSync(
|
|
10253
|
+
fs4.rmSync(path7.join(dir, name), { force: true });
|
|
10147
10254
|
} catch {}
|
|
10148
10255
|
}
|
|
10149
|
-
var HOST_SESSION_VARS, family = (host) => host?.replace(/_(?:cli|desktop)$/, "") ?? null, ISSUED_PER_LEAD = 64, ISSUED_SESSIONS_MARKER = "workit-issued-sessions/
|
|
10150
|
-
|
|
10151
|
-
|
|
10152
|
-
}
|
|
10153
|
-
|
|
10154
|
-
|
|
10256
|
+
var HOST_SESSION_VARS, family = (host) => host?.replace(/_(?:cli|desktop)$/, "") ?? null, ISSUED_PER_LEAD = 64, ISSUED_SESSIONS_MARKER = "workit-issued-sessions/2", hash = (value) => createHash6("sha256").update(value).digest("hex").slice(0, 32), userIssuedRoot = () => path7.join(resolveStateDir(), "issued"), safeList = (dir) => {
|
|
10257
|
+
try {
|
|
10258
|
+
return fs4.readdirSync(dir);
|
|
10259
|
+
} catch {
|
|
10260
|
+
return [];
|
|
10261
|
+
}
|
|
10262
|
+
}, removeIfEmpty = (dir) => {
|
|
10263
|
+
try {
|
|
10264
|
+
fs4.rmdirSync(dir);
|
|
10265
|
+
} catch {}
|
|
10155
10266
|
}, OWN_CHILD_SHELL;
|
|
10156
10267
|
var init_host_session = __esm(() => {
|
|
10268
|
+
init_logger();
|
|
10157
10269
|
init_paths();
|
|
10158
10270
|
HOST_SESSION_VARS = [
|
|
10159
10271
|
["OPENCODE_SESSION_ID", () => "opencode"],
|
|
@@ -10170,7 +10282,7 @@ var init_host_session = __esm(() => {
|
|
|
10170
10282
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
10171
10283
|
import { createHash as createHash7, randomBytes } from "node:crypto";
|
|
10172
10284
|
import fs5 from "node:fs";
|
|
10173
|
-
import
|
|
10285
|
+
import path8 from "node:path";
|
|
10174
10286
|
function resolveCommit(cwd, ref) {
|
|
10175
10287
|
if (!safeRef(ref))
|
|
10176
10288
|
return null;
|
|
@@ -10236,14 +10348,14 @@ function diffHash(cwd, base, head) {
|
|
|
10236
10348
|
return `sha256:${hash.digest("hex")}`;
|
|
10237
10349
|
}
|
|
10238
10350
|
function storeRoot(cwd) {
|
|
10239
|
-
const location = resolveStore(
|
|
10351
|
+
const location = resolveStore(path8.resolve(cwd));
|
|
10240
10352
|
if (location instanceof Error)
|
|
10241
10353
|
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");
|
|
10242
10354
|
return { ok: true, value: { root: location.dir, shared: location.shared } };
|
|
10243
10355
|
}
|
|
10244
10356
|
function ledgerPath(cwd) {
|
|
10245
10357
|
const root = storeRoot(cwd);
|
|
10246
|
-
return root.ok ? { ok: true, value:
|
|
10358
|
+
return root.ok ? { ok: true, value: path8.join(root.value.root, "ledger", "ledger.jsonl") } : root;
|
|
10247
10359
|
}
|
|
10248
10360
|
function withLedgerLock(file, fn, waitMs = LOCK_WAIT_MS) {
|
|
10249
10361
|
const lock = `${file}.lock`;
|
|
@@ -10293,8 +10405,8 @@ function appendLine(file, build, options) {
|
|
|
10293
10405
|
}
|
|
10294
10406
|
};
|
|
10295
10407
|
try {
|
|
10296
|
-
fs5.mkdirSync(
|
|
10297
|
-
if (!options.forceLock && !onNetworkFs(
|
|
10408
|
+
fs5.mkdirSync(path8.dirname(file), { recursive: true });
|
|
10409
|
+
if (!options.forceLock && !onNetworkFs(path8.dirname(file)))
|
|
10298
10410
|
return write();
|
|
10299
10411
|
const locked = withLedgerLock(file, write);
|
|
10300
10412
|
return locked ?? err("busy", `ledger lock ${file}.lock is held`, "retry; remove the .lock directory if no workit process is running");
|
|
@@ -10709,12 +10821,12 @@ var LEDGER_VERSION = 1, MAX_LINE_BYTES = 4096, PASSING, FAILING, STRONG_RESULTS,
|
|
|
10709
10821
|
}
|
|
10710
10822
|
}, LOCK_WAIT_MS = 5000, LOCK_STALE_MS = 30000, LOCK_OWNER = "owner", lockToken = (lock) => {
|
|
10711
10823
|
try {
|
|
10712
|
-
return fs5.readFileSync(
|
|
10824
|
+
return fs5.readFileSync(path8.join(lock, LOCK_OWNER), "utf8");
|
|
10713
10825
|
} catch {
|
|
10714
10826
|
return null;
|
|
10715
10827
|
}
|
|
10716
10828
|
}, lockAgeMs = (lock) => {
|
|
10717
|
-
for (const target of [
|
|
10829
|
+
for (const target of [path8.join(lock, LOCK_OWNER), lock]) {
|
|
10718
10830
|
try {
|
|
10719
10831
|
return Date.now() - fs5.statSync(target).mtimeMs;
|
|
10720
10832
|
} catch {}
|
|
@@ -10824,7 +10936,7 @@ var init_ledger = __esm(() => {
|
|
|
10824
10936
|
throw error;
|
|
10825
10937
|
}
|
|
10826
10938
|
const token = `${process.pid}-${randomBytes(8).toString("hex")}`;
|
|
10827
|
-
fs5.writeFileSync(
|
|
10939
|
+
fs5.writeFileSync(path8.join(lock, LOCK_OWNER), token);
|
|
10828
10940
|
return token;
|
|
10829
10941
|
},
|
|
10830
10942
|
release(lock, token) {
|
|
@@ -10877,7 +10989,7 @@ var init_ledger = __esm(() => {
|
|
|
10877
10989
|
|
|
10878
10990
|
// packages/workit-core/src/core/policy/derive.ts
|
|
10879
10991
|
import { existsSync as existsSync2 } from "node:fs";
|
|
10880
|
-
import
|
|
10992
|
+
import path9 from "node:path";
|
|
10881
10993
|
function deriveRequirements(judgment, scope, constraints, verification = "self") {
|
|
10882
10994
|
const out = [];
|
|
10883
10995
|
const base = { scope, dependentAction: null };
|
|
@@ -11029,7 +11141,7 @@ var RULES, derived2 = (spec) => ({
|
|
|
11029
11141
|
decisionIds: []
|
|
11030
11142
|
};
|
|
11031
11143
|
}, planRecorded = (task, root) => {
|
|
11032
|
-
const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync2(
|
|
11144
|
+
const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync2(path9.resolve(root, ref.path)));
|
|
11033
11145
|
if (cited)
|
|
11034
11146
|
return {
|
|
11035
11147
|
met: true,
|
|
@@ -11625,8 +11737,8 @@ var init_judgment = __esm(() => {
|
|
|
11625
11737
|
var init_safe_write = () => {};
|
|
11626
11738
|
|
|
11627
11739
|
// packages/workit-core/src/autonomy.ts
|
|
11628
|
-
import
|
|
11629
|
-
import
|
|
11740
|
+
import os4 from "node:os";
|
|
11741
|
+
import path10 from "node:path";
|
|
11630
11742
|
function endpointOf(entry) {
|
|
11631
11743
|
const raw = entry?.defaultEndpoint;
|
|
11632
11744
|
if (raw === undefined)
|
|
@@ -11719,13 +11831,13 @@ function resolveAutonomy(cwd) {
|
|
|
11719
11831
|
}
|
|
11720
11832
|
var accountHome = () => {
|
|
11721
11833
|
try {
|
|
11722
|
-
return
|
|
11834
|
+
return os4.userInfo().homedir;
|
|
11723
11835
|
} catch {
|
|
11724
|
-
return
|
|
11836
|
+
return os4.homedir();
|
|
11725
11837
|
}
|
|
11726
|
-
}, grantsHome, grantsDir = () =>
|
|
11727
|
-
const configured =
|
|
11728
|
-
return configured ===
|
|
11838
|
+
}, grantsHome, grantsDir = () => path10.join(grantsHome.resolve(), ".config", "workit"), grantsOverride = () => {
|
|
11839
|
+
const configured = path10.resolve(resolveConfigDir());
|
|
11840
|
+
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`;
|
|
11729
11841
|
}, GRANT_KINDS, DEFAULT_GRANTS, DEFAULT_ENDPOINTS, DEFAULT_ENDPOINT = "commit", isDefaultEndpoint = (value) => typeof value === "string" && DEFAULT_ENDPOINTS.includes(value), DEFAULT_VERIFICATION = "self", verificationOf = (entry) => entry?.verification === "independent" ? "independent" : "self", isGrantValue = (value) => value === true || value === false || value === "verified", normalized = (kind, value) => value === "verified" && kind !== "merge" ? true : value, fromAutoApprove = (value) => {
|
|
11730
11842
|
if (value === true)
|
|
11731
11843
|
return { push: true, pr: true, merge: "verified" };
|
|
@@ -11865,7 +11977,7 @@ var init_read_open_flags = () => {};
|
|
|
11865
11977
|
// node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.js
|
|
11866
11978
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
11867
11979
|
import fsSync from "node:fs";
|
|
11868
|
-
import
|
|
11980
|
+
import path11 from "node:path";
|
|
11869
11981
|
function parseSidecarLockSnapshot(snapshot, parser) {
|
|
11870
11982
|
return snapshot && { ...snapshot, payload: parseSidecarLockPayload(snapshot.raw, parser) };
|
|
11871
11983
|
}
|
|
@@ -11893,13 +12005,13 @@ ${ownershipToken}
|
|
|
11893
12005
|
return { raw, ownershipToken };
|
|
11894
12006
|
}
|
|
11895
12007
|
function relativeSidecarLockPath(lockRoot, lockPath) {
|
|
11896
|
-
const resolved =
|
|
11897
|
-
const lexicalRelative =
|
|
11898
|
-
const relative = lexicalRelative !== ".." && !lexicalRelative.startsWith(`..${
|
|
11899
|
-
if (!relative || relative === ".." || relative.startsWith(`..${
|
|
12008
|
+
const resolved = path11.resolve(lockPath);
|
|
12009
|
+
const lexicalRelative = path11.relative(lockRoot.rootDir, resolved);
|
|
12010
|
+
const relative = lexicalRelative !== ".." && !lexicalRelative.startsWith(`..${path11.sep}`) && !path11.isAbsolute(lexicalRelative) ? lexicalRelative : path11.relative(lockRoot.rootReal, resolved);
|
|
12011
|
+
if (!relative || relative === ".." || relative.startsWith(`..${path11.sep}`) || path11.isAbsolute(relative)) {
|
|
11900
12012
|
throw new FsSafeError("outside-workspace", "sidecar lock path is outside lockRoot");
|
|
11901
12013
|
}
|
|
11902
|
-
return relative.split(
|
|
12014
|
+
return relative.split(path11.sep).join(path11.posix.sep);
|
|
11903
12015
|
}
|
|
11904
12016
|
function parseSidecarLockPayload(raw, parser) {
|
|
11905
12017
|
if (parser) {
|
|
@@ -12069,7 +12181,7 @@ function sleepSync(ms) {
|
|
|
12069
12181
|
|
|
12070
12182
|
// node_modules/@openclaw/fs-safe/dist/file-lock-sync.js
|
|
12071
12183
|
import fs8 from "node:fs";
|
|
12072
|
-
import
|
|
12184
|
+
import path12 from "node:path";
|
|
12073
12185
|
function getSyncHeldLocks() {
|
|
12074
12186
|
const globalWithState = globalThis;
|
|
12075
12187
|
if (!globalWithState[SYNC_HELD_LOCKS_KEY]) {
|
|
@@ -12147,26 +12259,26 @@ function canonicalLockParentSync(parent) {
|
|
|
12147
12259
|
return process.platform === "win32" ? fs8.realpathSync.native(parent) : fs8.realpathSync(parent);
|
|
12148
12260
|
}
|
|
12149
12261
|
function normalizeTargetPath(targetPath) {
|
|
12150
|
-
const resolved =
|
|
12151
|
-
fs8.mkdirSync(
|
|
12262
|
+
const resolved = path12.resolve(targetPath);
|
|
12263
|
+
fs8.mkdirSync(path12.dirname(resolved), { recursive: true });
|
|
12152
12264
|
try {
|
|
12153
|
-
return
|
|
12265
|
+
return path12.join(canonicalLockParentSync(path12.dirname(resolved)), path12.basename(resolved));
|
|
12154
12266
|
} catch {
|
|
12155
12267
|
return resolved;
|
|
12156
12268
|
}
|
|
12157
12269
|
}
|
|
12158
12270
|
function boundedLockPath(lockPath, lockRoot) {
|
|
12159
|
-
const resolved =
|
|
12271
|
+
const resolved = path12.resolve(lockPath);
|
|
12160
12272
|
if (!lockRoot)
|
|
12161
12273
|
return resolved;
|
|
12162
12274
|
relativeSidecarLockPath(lockRoot, resolved);
|
|
12163
|
-
const parent =
|
|
12275
|
+
const parent = path12.dirname(resolved);
|
|
12164
12276
|
const parentReal = canonicalLockParentSync(parent);
|
|
12165
|
-
const parentRelative =
|
|
12166
|
-
if (parentRelative === ".." || parentRelative.startsWith(`..${
|
|
12277
|
+
const parentRelative = path12.relative(lockRoot.rootReal, parentReal);
|
|
12278
|
+
if (parentRelative === ".." || parentRelative.startsWith(`..${path12.sep}`) || path12.isAbsolute(parentRelative)) {
|
|
12167
12279
|
throw new FsSafeError("outside-workspace", "sidecar lock parent is outside lockRoot");
|
|
12168
12280
|
}
|
|
12169
|
-
return
|
|
12281
|
+
return path12.join(parentReal, path12.basename(resolved));
|
|
12170
12282
|
}
|
|
12171
12283
|
function defaultShouldReclaim(snapshot, staleMs, nowMs) {
|
|
12172
12284
|
const createdAtMs = sidecarLockPayloadCreatedAtMs(snapshot.payload);
|
|
@@ -12383,13 +12495,13 @@ var init_file_lock = __esm(() => {
|
|
|
12383
12495
|
|
|
12384
12496
|
// packages/workit-core/src/core/package-root.ts
|
|
12385
12497
|
import { existsSync as existsSync3 } from "node:fs";
|
|
12386
|
-
import
|
|
12498
|
+
import path13 from "node:path";
|
|
12387
12499
|
import { fileURLToPath } from "node:url";
|
|
12388
12500
|
var packageRoot = () => {
|
|
12389
|
-
let dir =
|
|
12501
|
+
let dir = path13.dirname(fileURLToPath(import.meta.url));
|
|
12390
12502
|
while (true) {
|
|
12391
|
-
const parent =
|
|
12392
|
-
if (existsSync3(
|
|
12503
|
+
const parent = path13.dirname(dir);
|
|
12504
|
+
if (existsSync3(path13.join(dir, "package.json")) || parent === dir)
|
|
12393
12505
|
return dir;
|
|
12394
12506
|
dir = parent;
|
|
12395
12507
|
}
|
|
@@ -12530,7 +12642,7 @@ var init_store_lock = __esm(() => {
|
|
|
12530
12642
|
// packages/workit-core/src/store/event-log.ts
|
|
12531
12643
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
12532
12644
|
import fs10 from "node:fs";
|
|
12533
|
-
import
|
|
12645
|
+
import path14 from "node:path";
|
|
12534
12646
|
function readLog(file, from = 0, expectSeq = null) {
|
|
12535
12647
|
let fd;
|
|
12536
12648
|
try {
|
|
@@ -12603,7 +12715,7 @@ function appendEvent(file, event, validEnd) {
|
|
|
12603
12715
|
fs10.closeSync(fd);
|
|
12604
12716
|
}
|
|
12605
12717
|
if (created)
|
|
12606
|
-
fsyncDirectory(
|
|
12718
|
+
fsyncDirectory(path14.dirname(file));
|
|
12607
12719
|
return validEnd;
|
|
12608
12720
|
}
|
|
12609
12721
|
function replaceFile(file, bytes, durable) {
|
|
@@ -12619,7 +12731,7 @@ function replaceFile(file, bytes, durable) {
|
|
|
12619
12731
|
}
|
|
12620
12732
|
renameWithRetry(temporary, file);
|
|
12621
12733
|
if (durable)
|
|
12622
|
-
fsyncDirectory(
|
|
12734
|
+
fsyncDirectory(path14.dirname(file));
|
|
12623
12735
|
} catch (error) {
|
|
12624
12736
|
try {
|
|
12625
12737
|
fs10.unlinkSync(temporary);
|
|
@@ -12929,7 +13041,7 @@ var init_notes = __esm(() => {
|
|
|
12929
13041
|
// packages/workit-core/src/core/task-store.ts
|
|
12930
13042
|
import { createHash as createHash9, randomUUID as randomUUID3 } from "node:crypto";
|
|
12931
13043
|
import * as fs11 from "node:fs";
|
|
12932
|
-
import
|
|
13044
|
+
import path15 from "node:path";
|
|
12933
13045
|
|
|
12934
13046
|
class TaskStore {
|
|
12935
13047
|
root;
|
|
@@ -12941,7 +13053,7 @@ class TaskStore {
|
|
|
12941
13053
|
migrationChecked = false;
|
|
12942
13054
|
compactDue = new Set;
|
|
12943
13055
|
constructor(root, options = {}) {
|
|
12944
|
-
const resolved =
|
|
13056
|
+
const resolved = path15.resolve(root);
|
|
12945
13057
|
this.origin = fs11.existsSync(resolved) ? fs11.realpathSync(resolved) : resolved;
|
|
12946
13058
|
this.located = resolveStore(this.origin);
|
|
12947
13059
|
this.root = checkoutRootOf(this.origin, this.located);
|
|
@@ -12950,7 +13062,7 @@ class TaskStore {
|
|
|
12950
13062
|
this.migrateOnRead = options.migrateOnRead;
|
|
12951
13063
|
}
|
|
12952
13064
|
location() {
|
|
12953
|
-
if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs11.existsSync(
|
|
13065
|
+
if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs11.existsSync(path15.join(this.root, ".git"))) {
|
|
12954
13066
|
this.located = undefined;
|
|
12955
13067
|
this.migrationChecked = false;
|
|
12956
13068
|
}
|
|
@@ -13106,7 +13218,7 @@ class TaskStore {
|
|
|
13106
13218
|
const moved = this.bindLocked(again.data.id, key, input.now);
|
|
13107
13219
|
return moved.ok ? success(moved.data.revision, null, { task: moved.data, created: false, key }) : moved;
|
|
13108
13220
|
}
|
|
13109
|
-
const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" :
|
|
13221
|
+
const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path15.basename(this.root) || this.root;
|
|
13110
13222
|
const intent = {
|
|
13111
13223
|
objective: input.objective?.trim() || `Work on ${label}`,
|
|
13112
13224
|
scope: { description: `the checkout (${label})`, paths: ["."], exclusions: [] },
|
|
@@ -13166,14 +13278,14 @@ class TaskStore {
|
|
|
13166
13278
|
const branch = key.ok ? key.data.branch : null;
|
|
13167
13279
|
if (!branch || !location.ok)
|
|
13168
13280
|
return success(null, null, null);
|
|
13169
|
-
const common =
|
|
13170
|
-
const heads =
|
|
13171
|
-
const headLog = location.data.git ?
|
|
13281
|
+
const common = path15.dirname(location.data.dir);
|
|
13282
|
+
const heads = path15.join(common, "logs", "refs", "heads");
|
|
13283
|
+
const headLog = location.data.git ? path15.join(location.data.git.gitDir, "logs", "HEAD") : "";
|
|
13172
13284
|
const signatures = [
|
|
13173
|
-
|
|
13285
|
+
path15.join(heads, branch),
|
|
13174
13286
|
headLog,
|
|
13175
13287
|
heads,
|
|
13176
|
-
|
|
13288
|
+
path15.join(common, "packed-refs")
|
|
13177
13289
|
].map((file) => fileSignature(file) ?? "-");
|
|
13178
13290
|
const slot = `${location.data.dir}\x00${headLog}\x00${branch}`;
|
|
13179
13291
|
let resolved = origins.get(slot);
|
|
@@ -13185,7 +13297,7 @@ class TaskStore {
|
|
|
13185
13297
|
aliases.push(rename.from);
|
|
13186
13298
|
const start = branchStart(location.data, branch, aliases);
|
|
13187
13299
|
const slash = start?.indexOf("/") ?? -1;
|
|
13188
|
-
const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(
|
|
13300
|
+
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)}"]`));
|
|
13189
13301
|
const name = start && (remote ? start.slice(slash + 1) : start);
|
|
13190
13302
|
resolved = {
|
|
13191
13303
|
signature: signatures.join("|"),
|
|
@@ -13423,13 +13535,13 @@ class TaskStore {
|
|
|
13423
13535
|
if (!ready.ok)
|
|
13424
13536
|
return ready;
|
|
13425
13537
|
const dirs = this.paths();
|
|
13426
|
-
const recovery =
|
|
13538
|
+
const recovery = path15.join(this.root, ".workit", "recovery");
|
|
13427
13539
|
if (fs11.existsSync(recovery)) {
|
|
13428
13540
|
let files = 0;
|
|
13429
13541
|
let bytes = 0;
|
|
13430
13542
|
try {
|
|
13431
13543
|
for (const name of fs11.readdirSync(recovery)) {
|
|
13432
|
-
const stat = fs11.lstatSync(
|
|
13544
|
+
const stat = fs11.lstatSync(path15.join(recovery, name));
|
|
13433
13545
|
if (!stat.isFile())
|
|
13434
13546
|
continue;
|
|
13435
13547
|
files += 1;
|
|
@@ -13482,7 +13594,7 @@ class TaskStore {
|
|
|
13482
13594
|
if (fs11.existsSync(dirs.blobs))
|
|
13483
13595
|
for (const name of fs11.readdirSync(dirs.blobs)) {
|
|
13484
13596
|
const digest = name.replace(/\.json$/, "");
|
|
13485
|
-
const file =
|
|
13597
|
+
const file = path15.join(dirs.blobs, name);
|
|
13486
13598
|
let stat;
|
|
13487
13599
|
try {
|
|
13488
13600
|
stat = fs11.lstatSync(file);
|
|
@@ -13500,7 +13612,7 @@ class TaskStore {
|
|
|
13500
13612
|
}
|
|
13501
13613
|
return success(null, null, null);
|
|
13502
13614
|
};
|
|
13503
|
-
const swept = dryRun ? sweep() : this.withLock(
|
|
13615
|
+
const swept = dryRun ? sweep() : this.withLock(path15.join(dirs.dir, "gc.lock"), sweep);
|
|
13504
13616
|
if (!swept.ok)
|
|
13505
13617
|
return swept;
|
|
13506
13618
|
const temporaryDirs = [
|
|
@@ -13508,7 +13620,7 @@ class TaskStore {
|
|
|
13508
13620
|
dirs.tasks,
|
|
13509
13621
|
dirs.blobs,
|
|
13510
13622
|
dirs.checkout,
|
|
13511
|
-
...names.map((name) =>
|
|
13623
|
+
...names.map((name) => path15.join(dirs.tasks, name))
|
|
13512
13624
|
];
|
|
13513
13625
|
for (const directory of temporaryDirs) {
|
|
13514
13626
|
if (!fs11.existsSync(directory))
|
|
@@ -13516,7 +13628,7 @@ class TaskStore {
|
|
|
13516
13628
|
for (const name of fs11.readdirSync(directory)) {
|
|
13517
13629
|
if (!name.endsWith(".tmp") && !name.endsWith(".probe"))
|
|
13518
13630
|
continue;
|
|
13519
|
-
const file =
|
|
13631
|
+
const file = path15.join(directory, name);
|
|
13520
13632
|
try {
|
|
13521
13633
|
const stat = fs11.lstatSync(file);
|
|
13522
13634
|
if (!stat.isFile() || nowMs - stat.mtimeMs <= STALE_TEMPORARY_MS)
|
|
@@ -13533,30 +13645,30 @@ class TaskStore {
|
|
|
13533
13645
|
}
|
|
13534
13646
|
paths() {
|
|
13535
13647
|
const location = this.location();
|
|
13536
|
-
const dir = location.ok ? location.data.dir :
|
|
13537
|
-
const checkout =
|
|
13648
|
+
const dir = location.ok ? location.data.dir : path15.join(this.root, ".workit");
|
|
13649
|
+
const checkout = path15.join(dir, "checkouts", checkoutSlug(this.root));
|
|
13538
13650
|
return {
|
|
13539
13651
|
dir,
|
|
13540
13652
|
shared: location.ok ? location.data.shared : false,
|
|
13541
|
-
marker:
|
|
13653
|
+
marker: path15.join(dir, "store.json"),
|
|
13542
13654
|
checkout,
|
|
13543
|
-
workspace:
|
|
13544
|
-
checkoutLock:
|
|
13545
|
-
tasks:
|
|
13546
|
-
index:
|
|
13547
|
-
blobs:
|
|
13548
|
-
legacy:
|
|
13549
|
-
v2:
|
|
13655
|
+
workspace: path15.join(checkout, "workspace.json"),
|
|
13656
|
+
checkoutLock: path15.join(checkout, "metadata.lock"),
|
|
13657
|
+
tasks: path15.join(dir, "tasks"),
|
|
13658
|
+
index: path15.join(dir, "task-index.json"),
|
|
13659
|
+
blobs: path15.join(dir, "blobs", "candidates"),
|
|
13660
|
+
legacy: path15.join(dir, "legacy", checkoutSlug(this.root), "v2"),
|
|
13661
|
+
v2: path15.join(this.root, ".workit")
|
|
13550
13662
|
};
|
|
13551
13663
|
}
|
|
13552
13664
|
eventsPath(taskId) {
|
|
13553
|
-
return
|
|
13665
|
+
return path15.join(this.paths().tasks, taskId, "events.jsonl");
|
|
13554
13666
|
}
|
|
13555
13667
|
snapshotPath(taskId) {
|
|
13556
|
-
return
|
|
13668
|
+
return path15.join(this.paths().tasks, taskId, "snapshot.json");
|
|
13557
13669
|
}
|
|
13558
13670
|
taskLockPath(taskId) {
|
|
13559
|
-
return
|
|
13671
|
+
return path15.join(this.paths().tasks, taskId, "lock");
|
|
13560
13672
|
}
|
|
13561
13673
|
ready(write = false) {
|
|
13562
13674
|
const location = this.location();
|
|
@@ -13595,13 +13707,13 @@ class TaskStore {
|
|
|
13595
13707
|
return {
|
|
13596
13708
|
read: (digest) => {
|
|
13597
13709
|
try {
|
|
13598
|
-
return JSON.parse(fs11.readFileSync(
|
|
13710
|
+
return JSON.parse(fs11.readFileSync(path15.join(dir, `${digest}.json`), "utf8"));
|
|
13599
13711
|
} catch (error) {
|
|
13600
13712
|
throw new LogDamage(`stored candidate ${digest} is missing or unreadable: ${String(error)}`);
|
|
13601
13713
|
}
|
|
13602
13714
|
},
|
|
13603
13715
|
write: (digest, value) => {
|
|
13604
|
-
const file =
|
|
13716
|
+
const file = path15.join(dir, `${digest}.json`);
|
|
13605
13717
|
if (fs11.existsSync(file)) {
|
|
13606
13718
|
const stamp = new Date;
|
|
13607
13719
|
try {
|
|
@@ -13793,7 +13905,7 @@ class TaskStore {
|
|
|
13793
13905
|
}
|
|
13794
13906
|
}
|
|
13795
13907
|
openTask(record, type, key, legacy = null) {
|
|
13796
|
-
const dir =
|
|
13908
|
+
const dir = path15.join(this.paths().tasks, record.id);
|
|
13797
13909
|
fs11.mkdirSync(dir, { recursive: true });
|
|
13798
13910
|
const blobs = this.blobStore();
|
|
13799
13911
|
const bound = key ? { ...key, boundAt: key.boundAt ?? new Date().toISOString() } : null;
|
|
@@ -13886,7 +13998,7 @@ class TaskStore {
|
|
|
13886
13998
|
}
|
|
13887
13999
|
withKeyLock(key, operation) {
|
|
13888
14000
|
const digest = createHash9("sha256").update(key).digest("hex").slice(0, 32);
|
|
13889
|
-
return this.withLock(
|
|
14001
|
+
return this.withLock(path15.join(this.paths().dir, "keys", `${digest}.lock`), operation);
|
|
13890
14002
|
}
|
|
13891
14003
|
bindLocked(taskId, key, timestamp) {
|
|
13892
14004
|
const current = this.readWorkspace();
|
|
@@ -14027,7 +14139,7 @@ class TaskStore {
|
|
|
14027
14139
|
writeWorkspace(record) {
|
|
14028
14140
|
const file = this.paths().workspace;
|
|
14029
14141
|
try {
|
|
14030
|
-
fs11.mkdirSync(
|
|
14142
|
+
fs11.mkdirSync(path15.dirname(file), { recursive: true });
|
|
14031
14143
|
replaceFile(file, `${canonicalJson(record)}
|
|
14032
14144
|
`, true);
|
|
14033
14145
|
return success(null, null, null);
|
|
@@ -14105,23 +14217,23 @@ class TaskStore {
|
|
|
14105
14217
|
return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", { expectedWorkspaceRevision: expected, actualWorkspaceRevision: actual });
|
|
14106
14218
|
}
|
|
14107
14219
|
v2Dirs() {
|
|
14108
|
-
return [...new Set([this.root, this.origin])].map((dir) =>
|
|
14220
|
+
return [...new Set([this.root, this.origin])].map((dir) => path15.join(dir, ".workit"));
|
|
14109
14221
|
}
|
|
14110
14222
|
pendingMigrations() {
|
|
14111
14223
|
return this.v2Dirs().filter((dir) => {
|
|
14112
|
-
const raw = this.readV2Workspace(
|
|
14224
|
+
const raw = this.readV2Workspace(path15.join(dir, "workspace.json"));
|
|
14113
14225
|
return raw !== null && raw !== TOMBSTONE;
|
|
14114
14226
|
});
|
|
14115
14227
|
}
|
|
14116
14228
|
migrateV2(v2) {
|
|
14117
14229
|
const dirs = this.paths();
|
|
14118
|
-
const v2Workspace =
|
|
14119
|
-
const v2Tasks =
|
|
14120
|
-
const legacy =
|
|
14230
|
+
const v2Workspace = path15.join(v2, "workspace.json");
|
|
14231
|
+
const v2Tasks = path15.join(v2, "tasks");
|
|
14232
|
+
const legacy = path15.join(dirs.dir, "legacy", checkoutSlug(path15.dirname(v2)), "v2");
|
|
14121
14233
|
const raw = this.readV2Workspace(v2Workspace);
|
|
14122
14234
|
if (raw === null || raw === TOMBSTONE)
|
|
14123
14235
|
return success(null, null, null);
|
|
14124
|
-
return this.withLock(dirs.checkoutLock, () => this.withLock(
|
|
14236
|
+
return this.withLock(dirs.checkoutLock, () => this.withLock(path15.join(v2, "metadata.lock"), () => {
|
|
14125
14237
|
const workspace = this.readV2Workspace(v2Workspace);
|
|
14126
14238
|
if (workspace === null || workspace === TOMBSTONE)
|
|
14127
14239
|
return success(null, null, null);
|
|
@@ -14130,7 +14242,7 @@ class TaskStore {
|
|
|
14130
14242
|
return failure2("recovery_required", `cannot migrate the 2.x store at ${v2}: ${parsedWorkspace.error}; move it aside to start fresh`, { path: v2Workspace });
|
|
14131
14243
|
let files = [];
|
|
14132
14244
|
try {
|
|
14133
|
-
files = fs11.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(
|
|
14245
|
+
files = fs11.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path15.join(v2Tasks, name)));
|
|
14134
14246
|
} catch {}
|
|
14135
14247
|
const current = this.readWorkspace();
|
|
14136
14248
|
if (!current.ok)
|
|
@@ -14148,21 +14260,21 @@ class TaskStore {
|
|
|
14148
14260
|
let skipped = 0;
|
|
14149
14261
|
const done = new Map;
|
|
14150
14262
|
try {
|
|
14151
|
-
fs11.mkdirSync(
|
|
14263
|
+
fs11.mkdirSync(path15.join(legacy, "tasks"), { recursive: true });
|
|
14152
14264
|
for (const name of ["workspace.json", "index.json"])
|
|
14153
|
-
if (fs11.existsSync(
|
|
14154
|
-
fs11.copyFileSync(
|
|
14265
|
+
if (fs11.existsSync(path15.join(v2, name)))
|
|
14266
|
+
fs11.copyFileSync(path15.join(v2, name), path15.join(legacy, name));
|
|
14155
14267
|
for (const name of files) {
|
|
14156
14268
|
const id = name.slice(0, -5);
|
|
14157
|
-
const file =
|
|
14269
|
+
const file = path15.join(v2Tasks, name);
|
|
14158
14270
|
const bytes = fs11.readFileSync(file, "utf8");
|
|
14159
14271
|
const digest = sha256(bytes);
|
|
14160
|
-
fs11.writeFileSync(
|
|
14272
|
+
fs11.writeFileSync(path15.join(legacy, "tasks", name), bytes);
|
|
14161
14273
|
const parsed = this.parseRecord(bytes, taskRecordSchema, "2.x task");
|
|
14162
14274
|
if (!parsed.ok || parsed.data.id !== id)
|
|
14163
14275
|
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 });
|
|
14164
14276
|
const record = { ...parsed.data, workspaceId: target.id };
|
|
14165
|
-
const origin = { path:
|
|
14277
|
+
const origin = { path: path15.join(legacy, "tasks", name), digest };
|
|
14166
14278
|
if (!fs11.existsSync(this.eventsPath(id))) {
|
|
14167
14279
|
this.openTask(record, "migrated.from_v2", null, origin);
|
|
14168
14280
|
migrated += 1;
|
|
@@ -14198,7 +14310,7 @@ class TaskStore {
|
|
|
14198
14310
|
try {
|
|
14199
14311
|
let complete = true;
|
|
14200
14312
|
for (const [name, digest] of done) {
|
|
14201
|
-
const file =
|
|
14313
|
+
const file = path15.join(v2Tasks, name);
|
|
14202
14314
|
if (sha256(fs11.readFileSync(file, "utf8")) !== digest) {
|
|
14203
14315
|
complete = false;
|
|
14204
14316
|
continue;
|
|
@@ -14209,7 +14321,7 @@ class TaskStore {
|
|
|
14209
14321
|
return failure2("busy", `the 2.x store at ${v2} changed during migration; retry`, {
|
|
14210
14322
|
path: v2
|
|
14211
14323
|
});
|
|
14212
|
-
fs11.rmSync(
|
|
14324
|
+
fs11.rmSync(path15.join(v2, "index.json"), { force: true });
|
|
14213
14325
|
this.writeTombstone(v2, target.id);
|
|
14214
14326
|
} catch (error) {
|
|
14215
14327
|
return failure2("storage_error", `cannot finish the 2.x migration: ${String(error)}`, {
|
|
@@ -14229,7 +14341,7 @@ class TaskStore {
|
|
|
14229
14341
|
}
|
|
14230
14342
|
adoptLocalStore() {
|
|
14231
14343
|
const dirs = this.paths();
|
|
14232
|
-
const marker =
|
|
14344
|
+
const marker = path15.join(dirs.v2, "store.json");
|
|
14233
14345
|
if (!dirs.shared || !fs11.existsSync(marker))
|
|
14234
14346
|
return success(null, null, null);
|
|
14235
14347
|
return this.withLock(dirs.checkoutLock, () => {
|
|
@@ -14239,7 +14351,7 @@ class TaskStore {
|
|
|
14239
14351
|
try {
|
|
14240
14352
|
const merge = (from, to) => {
|
|
14241
14353
|
if (!fs11.existsSync(to)) {
|
|
14242
|
-
fs11.mkdirSync(
|
|
14354
|
+
fs11.mkdirSync(path15.dirname(to), { recursive: true });
|
|
14243
14355
|
try {
|
|
14244
14356
|
fs11.renameSync(from, to);
|
|
14245
14357
|
} catch {
|
|
@@ -14250,24 +14362,24 @@ class TaskStore {
|
|
|
14250
14362
|
}
|
|
14251
14363
|
if (fs11.lstatSync(from).isDirectory() && fs11.lstatSync(to).isDirectory())
|
|
14252
14364
|
for (const name of fs11.readdirSync(from))
|
|
14253
|
-
merge(
|
|
14365
|
+
merge(path15.join(from, name), path15.join(to, name));
|
|
14254
14366
|
};
|
|
14255
14367
|
for (const sub of ["tasks", "checkouts", "blobs", "legacy"]) {
|
|
14256
|
-
const from =
|
|
14368
|
+
const from = path15.join(dirs.v2, sub);
|
|
14257
14369
|
if (!fs11.existsSync(from))
|
|
14258
14370
|
continue;
|
|
14259
14371
|
if (sub === "tasks") {
|
|
14260
14372
|
for (const name of fs11.readdirSync(from))
|
|
14261
|
-
if (validId(name) && !fs11.existsSync(
|
|
14373
|
+
if (validId(name) && !fs11.existsSync(path15.join(dirs.dir, sub, name)))
|
|
14262
14374
|
tasks += 1;
|
|
14263
14375
|
}
|
|
14264
|
-
merge(from,
|
|
14376
|
+
merge(from, path15.join(dirs.dir, sub));
|
|
14265
14377
|
}
|
|
14266
|
-
const ledger =
|
|
14267
|
-
if (fs11.existsSync(ledger) && !fs11.existsSync(
|
|
14268
|
-
merge(ledger,
|
|
14269
|
-
fs11.rmSync(
|
|
14270
|
-
fs11.renameSync(marker,
|
|
14378
|
+
const ledger = path15.join(dirs.v2, "ledger");
|
|
14379
|
+
if (fs11.existsSync(ledger) && !fs11.existsSync(path15.join(dirs.dir, "ledger")))
|
|
14380
|
+
merge(ledger, path15.join(dirs.dir, "ledger"));
|
|
14381
|
+
fs11.rmSync(path15.join(dirs.v2, "task-index.json"), { force: true });
|
|
14382
|
+
fs11.renameSync(marker, path15.join(dirs.v2, "store.moved.json"));
|
|
14271
14383
|
} catch (error) {
|
|
14272
14384
|
return failure2("storage_error", `cannot move ${dirs.v2} into ${dirs.dir}: ${String(error)}`, {
|
|
14273
14385
|
path: dirs.v2
|
|
@@ -14305,7 +14417,7 @@ class TaskStore {
|
|
|
14305
14417
|
schemaVersion: SCHEMA_VERSION,
|
|
14306
14418
|
id: workspaceId ?? newId(),
|
|
14307
14419
|
revision: newRevision(),
|
|
14308
|
-
root:
|
|
14420
|
+
root: path15.dirname(v2),
|
|
14309
14421
|
runtime: { createdWith: version, updatedWith: version },
|
|
14310
14422
|
writer: null,
|
|
14311
14423
|
store: {
|
|
@@ -14317,11 +14429,11 @@ class TaskStore {
|
|
|
14317
14429
|
critical: ["store"]
|
|
14318
14430
|
};
|
|
14319
14431
|
fs11.mkdirSync(v2, { recursive: true });
|
|
14320
|
-
const ignore =
|
|
14432
|
+
const ignore = path15.join(v2, ".gitignore");
|
|
14321
14433
|
if (!fs11.existsSync(ignore))
|
|
14322
14434
|
fs11.writeFileSync(ignore, `*
|
|
14323
14435
|
`);
|
|
14324
|
-
replaceFile(
|
|
14436
|
+
replaceFile(path15.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
|
|
14325
14437
|
`, true);
|
|
14326
14438
|
}
|
|
14327
14439
|
stubFor(taskId) {
|
|
@@ -14345,8 +14457,8 @@ class TaskStore {
|
|
|
14345
14457
|
}
|
|
14346
14458
|
writeTombstoneIfMissing() {
|
|
14347
14459
|
try {
|
|
14348
|
-
const v2 =
|
|
14349
|
-
if (fs11.existsSync(
|
|
14460
|
+
const v2 = path15.join(this.root, ".workit");
|
|
14461
|
+
if (fs11.existsSync(path15.join(v2, "workspace.json")))
|
|
14350
14462
|
return;
|
|
14351
14463
|
let id = null;
|
|
14352
14464
|
try {
|
|
@@ -14363,7 +14475,7 @@ class TaskStore {
|
|
|
14363
14475
|
replaceFile(dirs.marker, `${JSON.stringify({ format: "workit-store", version: STORE_FORMAT, createdWith: runtimeVersion() })}
|
|
14364
14476
|
`, false);
|
|
14365
14477
|
if (!dirs.shared) {
|
|
14366
|
-
const ignore =
|
|
14478
|
+
const ignore = path15.join(dirs.dir, ".gitignore");
|
|
14367
14479
|
let current = null;
|
|
14368
14480
|
try {
|
|
14369
14481
|
current = fs11.readFileSync(ignore, "utf8");
|
|
@@ -14423,7 +14535,7 @@ class TaskStore {
|
|
|
14423
14535
|
withLock(lockPath, operation) {
|
|
14424
14536
|
try {
|
|
14425
14537
|
this.initializeStorage();
|
|
14426
|
-
fs11.mkdirSync(
|
|
14538
|
+
fs11.mkdirSync(path15.dirname(lockPath), { recursive: true });
|
|
14427
14539
|
} catch (error) {
|
|
14428
14540
|
return failure2("storage_error", `unable to initialize store: ${String(error)}`, {
|
|
14429
14541
|
path: this.paths().dir
|
|
@@ -14486,7 +14598,7 @@ class TaskStore {
|
|
|
14486
14598
|
if (isTransientWindowsError(error) && !this.lockHolderPresent(lockPath) && !this.lockDirWritable(lockPath))
|
|
14487
14599
|
return failure2("storage_error", `cannot create the workit lock (${code}); no other Workit call holds it`, {
|
|
14488
14600
|
path: lockPath,
|
|
14489
|
-
guidance: `Check permissions and the read-only attribute on ${
|
|
14601
|
+
guidance: `Check permissions and the read-only attribute on ${path15.dirname(lockPath)}.`
|
|
14490
14602
|
});
|
|
14491
14603
|
if (code === "EEXIST" || code === "file_lock_timeout" || code === "file_lock_stale" || isTransientWindowsError(error)) {
|
|
14492
14604
|
let lock = null;
|
|
@@ -14544,7 +14656,7 @@ var MIGRATION_PENDING = "workit migration pending", STORE_FORMAT = 3, STORE_MIN_
|
|
|
14544
14656
|
}, now = () => new Date().toISOString().replace(/\.\d{3}Z$/, "Z"), oldestFirst = (left, right) => left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id), cachedRuntimeVersion = null, runtimeVersion = () => {
|
|
14545
14657
|
if (cachedRuntimeVersion === null) {
|
|
14546
14658
|
try {
|
|
14547
|
-
const pkg = JSON.parse(fs11.readFileSync(
|
|
14659
|
+
const pkg = JSON.parse(fs11.readFileSync(path15.join(packageRoot(), "package.json"), "utf8"));
|
|
14548
14660
|
cachedRuntimeVersion = typeof pkg.version === "string" && pkg.version ? pkg.version : "0.0.0";
|
|
14549
14661
|
} catch {
|
|
14550
14662
|
cachedRuntimeVersion = "0.0.0";
|
|
@@ -14571,7 +14683,7 @@ var MIGRATION_PENDING = "workit migration pending", STORE_FORMAT = 3, STORE_MIN_
|
|
|
14571
14683
|
return "";
|
|
14572
14684
|
}
|
|
14573
14685
|
}, REFLOG_LINE, branchStart = (location, branch, aliases) => {
|
|
14574
|
-
const first = readText(
|
|
14686
|
+
const first = readText(path15.join(path15.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
|
|
14575
14687
|
`, 1)[0];
|
|
14576
14688
|
const created = REFLOG_LINE.exec(first);
|
|
14577
14689
|
const start = created && /^branch: Created from (\S+)$/u.exec(created[3])?.[1];
|
|
@@ -14581,7 +14693,7 @@ var MIGRATION_PENDING = "workit migration pending", STORE_FORMAT = 3, STORE_MIN_
|
|
|
14581
14693
|
return start;
|
|
14582
14694
|
if (!location.git)
|
|
14583
14695
|
return null;
|
|
14584
|
-
for (const line of readText(
|
|
14696
|
+
for (const line of readText(path15.join(location.git.gitDir, "logs", "HEAD")).split(`
|
|
14585
14697
|
`)) {
|
|
14586
14698
|
const entry = REFLOG_LINE.exec(line);
|
|
14587
14699
|
const moved = entry && /^checkout: moving from (\S+) to (\S+)$/u.exec(entry[3]);
|
|
@@ -14590,12 +14702,12 @@ var MIGRATION_PENDING = "workit migration pending", STORE_FORMAT = 3, STORE_MIN_
|
|
|
14590
14702
|
return moved[1];
|
|
14591
14703
|
}
|
|
14592
14704
|
return null;
|
|
14593
|
-
}, refExists = (common, ref) => fs11.existsSync(
|
|
14705
|
+
}, refExists = (common, ref) => fs11.existsSync(path15.join(common, ref)) || readText(path15.join(common, "packed-refs")).includes(` ${ref}
|
|
14594
14706
|
`), origins, sameDirectoryIdentity = (left, right) => {
|
|
14595
|
-
if (!
|
|
14707
|
+
if (!path15.isAbsolute(left) || !path15.isAbsolute(right))
|
|
14596
14708
|
return false;
|
|
14597
|
-
const normalizedLeft =
|
|
14598
|
-
const normalizedRight =
|
|
14709
|
+
const normalizedLeft = path15.resolve(left);
|
|
14710
|
+
const normalizedRight = path15.resolve(right);
|
|
14599
14711
|
try {
|
|
14600
14712
|
const a = fs11.statSync(normalizedLeft, { bigint: true });
|
|
14601
14713
|
const b = fs11.statSync(normalizedRight, { bigint: true });
|
|
@@ -14653,7 +14765,7 @@ var init_workers = __esm(() => {
|
|
|
14653
14765
|
// packages/workit-core/src/check-config.ts
|
|
14654
14766
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
14655
14767
|
import fs12 from "node:fs";
|
|
14656
|
-
import
|
|
14768
|
+
import path16 from "node:path";
|
|
14657
14769
|
function splitCommand(command) {
|
|
14658
14770
|
const argv = [];
|
|
14659
14771
|
let current = "";
|
|
@@ -14691,12 +14803,12 @@ function splitCommand(command) {
|
|
|
14691
14803
|
return argv.length ? argv : new Error("empty command");
|
|
14692
14804
|
}
|
|
14693
14805
|
function checkRoot(cwd) {
|
|
14694
|
-
return
|
|
14806
|
+
return path16.resolve(git4(cwd, ["rev-parse", "--show-toplevel"]) ?? cwd);
|
|
14695
14807
|
}
|
|
14696
14808
|
function detectedChecks(root) {
|
|
14697
14809
|
const read = (file) => {
|
|
14698
14810
|
try {
|
|
14699
|
-
return fs12.readFileSync(
|
|
14811
|
+
return fs12.readFileSync(path16.join(root, file), "utf8");
|
|
14700
14812
|
} catch {
|
|
14701
14813
|
return null;
|
|
14702
14814
|
}
|
|
@@ -14734,7 +14846,7 @@ function detectedChecks(root) {
|
|
|
14734
14846
|
}
|
|
14735
14847
|
function loadCheckConfig(cwd) {
|
|
14736
14848
|
const root = checkRoot(cwd);
|
|
14737
|
-
const file =
|
|
14849
|
+
const file = path16.join(root, CHECKS_FILE);
|
|
14738
14850
|
const none = (error = null) => ({
|
|
14739
14851
|
source: error ? CHECKS_FILE : "none",
|
|
14740
14852
|
root,
|
|
@@ -14783,7 +14895,7 @@ function loadCheckConfig(cwd) {
|
|
|
14783
14895
|
gates[gate] = names;
|
|
14784
14896
|
}
|
|
14785
14897
|
}
|
|
14786
|
-
return { source: CHECKS_FILE, root, checks, gates, error: null };
|
|
14898
|
+
return { source: CHECKS_FILE, root, checks, gates, error: null, resources: parsed.resources };
|
|
14787
14899
|
}
|
|
14788
14900
|
function matchesNamedCheck(config, name, argv, cwd) {
|
|
14789
14901
|
if (config.error || name === null || cwd !== ".")
|
|
@@ -14805,10 +14917,10 @@ function workitAvailable(env = process.env) {
|
|
|
14805
14917
|
return workitOnPath;
|
|
14806
14918
|
const windows = process.platform === "win32";
|
|
14807
14919
|
const exts = windows ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
|
|
14808
|
-
const dirs = (env.PATH ?? env.Path ?? "").split(
|
|
14920
|
+
const dirs = (env.PATH ?? env.Path ?? "").split(path16.delimiter).filter(Boolean);
|
|
14809
14921
|
workitOnPath = dirs.some((dir) => exts.some((ext) => {
|
|
14810
14922
|
try {
|
|
14811
|
-
return fs12.statSync(
|
|
14923
|
+
return fs12.statSync(path16.join(dir, `workit${ext}`)).isFile();
|
|
14812
14924
|
} catch {
|
|
14813
14925
|
return false;
|
|
14814
14926
|
}
|
|
@@ -14829,7 +14941,7 @@ var SCRIPT_CHECKS, CHECKS_FILE = "workit.checks.json", isRecord3 = (value) => ty
|
|
|
14829
14941
|
const value = run.status === 0 ? (run.stdout ?? "").trim() : "";
|
|
14830
14942
|
return value || null;
|
|
14831
14943
|
}, packageManager = (root) => {
|
|
14832
|
-
const has = (file) => fs12.existsSync(
|
|
14944
|
+
const has = (file) => fs12.existsSync(path16.join(root, file));
|
|
14833
14945
|
if (has("bun.lock") || has("bun.lockb"))
|
|
14834
14946
|
return "bun";
|
|
14835
14947
|
if (has("pnpm-lock.yaml"))
|
|
@@ -14855,7 +14967,7 @@ var init_check_config = __esm(() => {
|
|
|
14855
14967
|
import { createHash as createHash10 } from "node:crypto";
|
|
14856
14968
|
import * as fs13 from "node:fs";
|
|
14857
14969
|
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
14858
|
-
import
|
|
14970
|
+
import path17 from "node:path";
|
|
14859
14971
|
function captureCandidate(root, scope, environment = []) {
|
|
14860
14972
|
let checkout;
|
|
14861
14973
|
try {
|
|
@@ -14897,7 +15009,7 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
14897
15009
|
for (const item of [...names].toSorted()) {
|
|
14898
15010
|
if (!scopeMatches(item, normalizedScope))
|
|
14899
15011
|
continue;
|
|
14900
|
-
const target =
|
|
15012
|
+
const target = path17.join(checkout, item);
|
|
14901
15013
|
try {
|
|
14902
15014
|
const stat = fs13.lstatSync(target);
|
|
14903
15015
|
if (stat.isSymbolicLink()) {
|
|
@@ -15270,12 +15382,12 @@ function evaluateClosure(requestedOutcome, view) {
|
|
|
15270
15382
|
requirementIds: evaluations.map((item) => item.requirementId)
|
|
15271
15383
|
});
|
|
15272
15384
|
}
|
|
15273
|
-
var digestBytes = (value) => createHash10("sha256").update(value).digest("hex"), inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${
|
|
15385
|
+
var digestBytes = (value) => createHash10("sha256").update(value).digest("hex"), inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path17.sep}`), relative = (root, candidate) => path17.relative(root, candidate).split(path17.sep).join("/") || ".", canonicalPath = (value) => {
|
|
15274
15386
|
if (typeof value !== "string" || !value)
|
|
15275
15387
|
return null;
|
|
15276
15388
|
if (value.includes("\\") || value.split("/").includes(".."))
|
|
15277
15389
|
return null;
|
|
15278
|
-
const normalized =
|
|
15390
|
+
const normalized = path17.posix.normalize(value);
|
|
15279
15391
|
if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
|
|
15280
15392
|
return null;
|
|
15281
15393
|
return normalized === "." ? "." : normalized.replace(/\/$/, "");
|
|
@@ -15317,14 +15429,14 @@ var digestBytes = (value) => createHash10("sha256").update(value).digest("hex"),
|
|
|
15317
15429
|
git: !/not a git repository/i.test(stderr)
|
|
15318
15430
|
};
|
|
15319
15431
|
}
|
|
15320
|
-
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(
|
|
15432
|
+
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path17.sep).join("/")) : [];
|
|
15321
15433
|
const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
|
|
15322
15434
|
if (stagedDeleted.status !== 0) {
|
|
15323
15435
|
const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
|
|
15324
15436
|
if (!/not a git repository/i.test(stderr))
|
|
15325
15437
|
return { paths, uncertain: true, git: true };
|
|
15326
15438
|
} else if (stagedDeleted.stdout) {
|
|
15327
|
-
paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(
|
|
15439
|
+
paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path17.sep).join("/")));
|
|
15328
15440
|
}
|
|
15329
15441
|
return { paths: [...new Set(paths)], uncertain: false, git: true };
|
|
15330
15442
|
}, walk = (root, directory, output) => {
|
|
@@ -15338,7 +15450,7 @@ var digestBytes = (value) => createHash10("sha256").update(value).digest("hex"),
|
|
|
15338
15450
|
for (const name of names) {
|
|
15339
15451
|
if (name === ".git" || name === ".workit")
|
|
15340
15452
|
continue;
|
|
15341
|
-
const target =
|
|
15453
|
+
const target = path17.join(directory, name);
|
|
15342
15454
|
let stat;
|
|
15343
15455
|
try {
|
|
15344
15456
|
stat = fs13.lstatSync(target);
|
|
@@ -15355,12 +15467,12 @@ var digestBytes = (value) => createHash10("sha256").update(value).digest("hex"),
|
|
|
15355
15467
|
}, scopeRoots = (root, scope) => {
|
|
15356
15468
|
const roots = [];
|
|
15357
15469
|
for (const item of scope.paths.length ? scope.paths : ["."]) {
|
|
15358
|
-
const target =
|
|
15470
|
+
const target = path17.resolve(root, item);
|
|
15359
15471
|
if (!inside(root, target))
|
|
15360
15472
|
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` }] });
|
|
15361
15473
|
let ancestor = target;
|
|
15362
15474
|
while (!fs13.existsSync(ancestor) && ancestor !== root)
|
|
15363
|
-
ancestor =
|
|
15475
|
+
ancestor = path17.dirname(ancestor);
|
|
15364
15476
|
try {
|
|
15365
15477
|
if (!inside(root, fs13.realpathSync(ancestor)))
|
|
15366
15478
|
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` }] });
|
|
@@ -15424,23 +15536,23 @@ var digestBytes = (value) => createHash10("sha256").update(value).digest("hex"),
|
|
|
15424
15536
|
continue;
|
|
15425
15537
|
if (!reference.digest)
|
|
15426
15538
|
return failure2("invalid_input", "document references require a byte digest");
|
|
15427
|
-
const target =
|
|
15428
|
-
if (target !== root && !target.startsWith(`${root}${
|
|
15539
|
+
const target = path17.resolve(root, reference.path);
|
|
15540
|
+
if (target !== root && !target.startsWith(`${root}${path17.sep}`))
|
|
15429
15541
|
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
15430
15542
|
fields: [
|
|
15431
15543
|
{ path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
|
|
15432
15544
|
]
|
|
15433
15545
|
});
|
|
15434
15546
|
try {
|
|
15435
|
-
const below =
|
|
15547
|
+
const below = path17.relative(root, target);
|
|
15436
15548
|
let current = root;
|
|
15437
|
-
for (const segment of below.split(
|
|
15549
|
+
for (const segment of below.split(path17.sep)) {
|
|
15438
15550
|
if (!segment)
|
|
15439
15551
|
continue;
|
|
15440
|
-
current =
|
|
15552
|
+
current = path17.join(current, segment);
|
|
15441
15553
|
const stat = fs13.lstatSync(current);
|
|
15442
15554
|
const real = fs13.realpathSync(current);
|
|
15443
|
-
if (real !== root && !real.startsWith(`${root}${
|
|
15555
|
+
if (real !== root && !real.startsWith(`${root}${path17.sep}`))
|
|
15444
15556
|
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
15445
15557
|
fields: [
|
|
15446
15558
|
{
|
|
@@ -15550,9 +15662,9 @@ Autonomy contract:
|
|
|
15550
15662
|
ship), go to the effective endpoint in \`workit grant show\`: \`pr\` opens
|
|
15551
15663
|
the PR; \`green\` babysits it without asking (workit-ship) to merge-ready,
|
|
15552
15664
|
never merging; \`merged\` also lands it with \`workit pr merge\`.
|
|
15553
|
-
Merge and release need a workspace grant
|
|
15554
|
-
|
|
15555
|
-
|
|
15665
|
+
Merge and release need a workspace grant only the user raises from their
|
|
15666
|
+
own terminal (a blocked verb names how); never edit workspaces.json or route
|
|
15667
|
+
around a grant_required.
|
|
15556
15668
|
- Ask only for a product or preference choice, or for authority you lack, with
|
|
15557
15669
|
your recommended answer. Facts are yours: read, run or prototype.
|
|
15558
15670
|
- Label claims measured (run and seen this session), inferred, or guess.
|
|
@@ -15561,17 +15673,19 @@ Autonomy contract:
|
|
|
15561
15673
|
- Author is not verifier: your own verdict is \`--self\`, shown as
|
|
15562
15674
|
self-reviewed, never verified. High risk, \`verification: independent\` and
|
|
15563
15675
|
merge need a verifier with its own host-derived session (a subagent's
|
|
15564
|
-
\`<lead>:<child
|
|
15676
|
+
\`<lead>:<child>\`); never hand-mint one (\`<lead>-v1\`).
|
|
15565
15677
|
- A local-commit endpoint does not imply PR readiness, and a local commit alone
|
|
15566
15678
|
is not evidence of a requested remote push. Before reporting delivery,
|
|
15567
15679
|
reconcile every requested item and observe it (\`workit verify-delivery\`).
|
|
15568
15680
|
|
|
15569
15681
|
CLI first: if a step has one right answer, use the \`workit\` verb instead of
|
|
15570
15682
|
hand-running git, gh or glab (\`workit git|pr|ci|check\`; \`workit help\` lists
|
|
15571
|
-
the rest;
|
|
15683
|
+
the rest; lacking \`workit\`, \`npx -y @brainervirus/workit-cli\`).
|
|
15684
|
+
Add Co-Authored-By via \`workit git commit --trailer "K: v" -- <paths>\`, never
|
|
15685
|
+
an amend.
|
|
15572
15686
|
The task families (task, policy, evidence, finding, decision, worker, state)
|
|
15573
15687
|
are optional continuity for tracked work; each branch has one implicit task,
|
|
15574
|
-
|
|
15688
|
+
and a solo edit needs no task. A decision
|
|
15575
15689
|
records a user choice; it never authorizes an effect. Judge work once with
|
|
15576
15690
|
\`workit policy assess --judge risk= behavior= product-choice= plan=\`.
|
|
15577
15691
|
Across repositories, bind each item to its checkout, branch and endpoint,
|
|
@@ -17398,7 +17512,7 @@ var support = (descriptor, axis) => {
|
|
|
17398
17512
|
// packages/workit-core/src/hooks/context.ts
|
|
17399
17513
|
import { createHash as createHash11 } from "node:crypto";
|
|
17400
17514
|
import fs14 from "node:fs";
|
|
17401
|
-
import
|
|
17515
|
+
import path18 from "node:path";
|
|
17402
17516
|
function sessionCompactContext(store, session, context, selection = "session-bound") {
|
|
17403
17517
|
const listed = store.listTaskIndex();
|
|
17404
17518
|
if (!listed.ok)
|
|
@@ -17433,7 +17547,7 @@ function entryCompactContext(store, entry, session, context) {
|
|
|
17433
17547
|
return null;
|
|
17434
17548
|
const freshness = { mode: "signal", current: () => recentSignal(store.root) };
|
|
17435
17549
|
const observed = task?.data.evidence.some(isObservedCheck) ?? false;
|
|
17436
|
-
const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [
|
|
17550
|
+
const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [path18.resolve(store.root, ref.path)] : []));
|
|
17437
17551
|
const observedFiles = filesKey(files);
|
|
17438
17552
|
const compact = new WorkitCore(store, context).compactContext(entry?.id ?? null, freshness, origin && { origin: origin.origin, taskId: origin.entry.id });
|
|
17439
17553
|
if (!compact.ok || !compact.data)
|
|
@@ -17539,13 +17653,13 @@ ${options.addendum}` : ""}
|
|
|
17539
17653
|
if (location instanceof Error)
|
|
17540
17654
|
return null;
|
|
17541
17655
|
const session = [input.host, input.session.id, input.session.agentId ?? ""].join("\x00");
|
|
17542
|
-
return
|
|
17656
|
+
return path18.join(location.dir, "hooks", `turn-${digestOf(session).slice(0, 32)}.json`);
|
|
17543
17657
|
} catch {
|
|
17544
17658
|
return null;
|
|
17545
17659
|
}
|
|
17546
17660
|
}, writeTurnDigest = (file, digest) => {
|
|
17547
17661
|
try {
|
|
17548
|
-
fs14.mkdirSync(
|
|
17662
|
+
fs14.mkdirSync(path18.dirname(file), { recursive: true });
|
|
17549
17663
|
fs14.writeFileSync(file, `${JSON.stringify({ digest })}
|
|
17550
17664
|
`);
|
|
17551
17665
|
} catch {}
|
|
@@ -17558,7 +17672,7 @@ ${options.addendum}` : ""}
|
|
|
17558
17672
|
for (const name of fs14.readdirSync(dir)) {
|
|
17559
17673
|
if (!name.startsWith("turn-"))
|
|
17560
17674
|
continue;
|
|
17561
|
-
const file =
|
|
17675
|
+
const file = path18.join(dir, name);
|
|
17562
17676
|
try {
|
|
17563
17677
|
if (now - fs14.statSync(file).mtimeMs > TURN_TTL_MS)
|
|
17564
17678
|
fs14.rmSync(file, { force: true });
|
|
@@ -17586,7 +17700,7 @@ ${options.addendum}` : ""}
|
|
|
17586
17700
|
const file = turnMarker(input);
|
|
17587
17701
|
if (!file)
|
|
17588
17702
|
return;
|
|
17589
|
-
pruneTurnDigests(
|
|
17703
|
+
pruneTurnDigests(path18.dirname(file), Date.now());
|
|
17590
17704
|
if (text)
|
|
17591
17705
|
writeTurnDigest(file, digestOf(text));
|
|
17592
17706
|
else
|
|
@@ -17817,7 +17931,7 @@ var init_branch = __esm(() => {
|
|
|
17817
17931
|
// packages/workit-core/src/hooks/session-marker.ts
|
|
17818
17932
|
import { createHash as createHash13 } from "node:crypto";
|
|
17819
17933
|
import fs15 from "node:fs";
|
|
17820
|
-
import
|
|
17934
|
+
import path19 from "node:path";
|
|
17821
17935
|
var sessionMarkerFile = (input, session, store) => {
|
|
17822
17936
|
let dir = store;
|
|
17823
17937
|
if (dir === undefined) {
|
|
@@ -17827,7 +17941,7 @@ var sessionMarkerFile = (input, session, store) => {
|
|
|
17827
17941
|
dir = location.dir;
|
|
17828
17942
|
}
|
|
17829
17943
|
const name = createHash13("sha256").update(`${input.host}\x00${session}`).digest("hex").slice(0, 32);
|
|
17830
|
-
return
|
|
17944
|
+
return path19.join(dir, "hooks", `skills-${name}.json`);
|
|
17831
17945
|
}, list2 = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [], readSessionMarker = (file) => {
|
|
17832
17946
|
try {
|
|
17833
17947
|
const value = JSON.parse(fs15.readFileSync(file, "utf8"));
|
|
@@ -17837,7 +17951,7 @@ var sessionMarkerFile = (input, session, store) => {
|
|
|
17837
17951
|
}
|
|
17838
17952
|
}, writeSessionMarker = (file, marker) => {
|
|
17839
17953
|
try {
|
|
17840
|
-
fs15.mkdirSync(
|
|
17954
|
+
fs15.mkdirSync(path19.dirname(file), { recursive: true });
|
|
17841
17955
|
fs15.writeFileSync(file, JSON.stringify(marker));
|
|
17842
17956
|
} catch {}
|
|
17843
17957
|
};
|
|
@@ -17970,8 +18084,8 @@ var closingQuote = (command, start, dialect) => {
|
|
|
17970
18084
|
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
17971
18085
|
import { createHash as createHash14 } from "node:crypto";
|
|
17972
18086
|
import fs16 from "node:fs";
|
|
17973
|
-
import
|
|
17974
|
-
import
|
|
18087
|
+
import os5 from "node:os";
|
|
18088
|
+
import path20 from "node:path";
|
|
17975
18089
|
function rawInvocations(command, dialect = "posix", depth = 0) {
|
|
17976
18090
|
const found = [];
|
|
17977
18091
|
let dir = null;
|
|
@@ -17992,7 +18106,7 @@ function rawInvocations(command, dialect = "posix", depth = 0) {
|
|
|
17992
18106
|
const name = commandName(words[0]);
|
|
17993
18107
|
if (CD.has(name)) {
|
|
17994
18108
|
const target = cdTarget(words);
|
|
17995
|
-
dir = target === null ?
|
|
18109
|
+
dir = target === null ? os5.homedir() : joinDir(dir, target);
|
|
17996
18110
|
continue;
|
|
17997
18111
|
}
|
|
17998
18112
|
if (PUSHD.has(name)) {
|
|
@@ -18130,7 +18244,7 @@ function noteRawCommit(input, command, key) {
|
|
|
18130
18244
|
if (action.kind !== "commit")
|
|
18131
18245
|
continue;
|
|
18132
18246
|
const file = markerFile(repo, input.session.id, key);
|
|
18133
|
-
fs16.mkdirSync(
|
|
18247
|
+
fs16.mkdirSync(path20.dirname(file), { recursive: true });
|
|
18134
18248
|
fs16.writeFileSync(file, `${JSON.stringify({ head: headSha2(repo), at })}
|
|
18135
18249
|
`);
|
|
18136
18250
|
}
|
|
@@ -18157,11 +18271,11 @@ function settlePendingCommit(input) {
|
|
|
18157
18271
|
settle2(input, repo, file);
|
|
18158
18272
|
} catch {}
|
|
18159
18273
|
}
|
|
18160
|
-
var NONE2, SHELLS, PREFIXES2, SCRIPT_FLAG, CD, PUSHD, POPD, GIT_VALUE_OPTIONS, isAbsolute = (value) =>
|
|
18274
|
+
var NONE2, SHELLS, PREFIXES2, SCRIPT_FLAG, CD, PUSHD, POPD, GIT_VALUE_OPTIONS, isAbsolute = (value) => path20.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\"), joinDir = (base, next) => {
|
|
18161
18275
|
if (base === undefined || /[$`*?]/.test(next) || next === "-")
|
|
18162
18276
|
return;
|
|
18163
|
-
const expanded = next === "~" || next.startsWith("~/") ?
|
|
18164
|
-
return base === null || isAbsolute(expanded) ? expanded :
|
|
18277
|
+
const expanded = next === "~" || next.startsWith("~/") ? path20.join(os5.homedir(), next.slice(1)) : next;
|
|
18278
|
+
return base === null || isAbsolute(expanded) ? expanded : path20.join(base, expanded);
|
|
18165
18279
|
}, cdTarget = (words) => {
|
|
18166
18280
|
const args = words.slice(1);
|
|
18167
18281
|
const flag = args.findIndex((word) => /^-(?:literal)?path$/i.test(word));
|
|
@@ -18312,17 +18426,17 @@ var NONE2, SHELLS, PREFIXES2, SCRIPT_FLAG, CD, PUSHD, POPD, GIT_VALUE_OPTIONS, i
|
|
|
18312
18426
|
if (!git || git.reftable)
|
|
18313
18427
|
return null;
|
|
18314
18428
|
try {
|
|
18315
|
-
const head = fs16.readFileSync(
|
|
18429
|
+
const head = fs16.readFileSync(path20.join(git.gitDir, "HEAD"), "utf8").trim();
|
|
18316
18430
|
if (/^[0-9a-f]{40,64}$/.test(head))
|
|
18317
18431
|
return head;
|
|
18318
18432
|
const ref = /^ref: (refs\/.+)$/.exec(head)?.[1];
|
|
18319
18433
|
if (!ref)
|
|
18320
18434
|
return null;
|
|
18321
|
-
const common =
|
|
18435
|
+
const common = path20.dirname(repo.location.dir);
|
|
18322
18436
|
try {
|
|
18323
|
-
return fs16.readFileSync(
|
|
18437
|
+
return fs16.readFileSync(path20.join(common, ref), "utf8").trim() || null;
|
|
18324
18438
|
} catch {}
|
|
18325
|
-
const packed = fs16.readFileSync(
|
|
18439
|
+
const packed = fs16.readFileSync(path20.join(common, "packed-refs"), "utf8");
|
|
18326
18440
|
return new RegExp(`^([0-9a-f]{40,64}) ${ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`, "m").exec(packed)?.[1] ?? null;
|
|
18327
18441
|
} catch {
|
|
18328
18442
|
return null;
|
|
@@ -18402,7 +18516,7 @@ var NONE2, SHELLS, PREFIXES2, SCRIPT_FLAG, CD, PUSHD, POPD, GIT_VALUE_OPTIONS, i
|
|
|
18402
18516
|
const action = rawAction(invocation);
|
|
18403
18517
|
if (!action)
|
|
18404
18518
|
continue;
|
|
18405
|
-
const dir =
|
|
18519
|
+
const dir = path20.resolve(cwd, invocation.dir ?? ".");
|
|
18406
18520
|
if (!repos.has(dir)) {
|
|
18407
18521
|
const repo = repoAt(dir);
|
|
18408
18522
|
repos.set(dir, repo && isWorkitWorkspace(repo) ? repo : null);
|
|
@@ -18429,7 +18543,7 @@ var NONE2, SHELLS, PREFIXES2, SCRIPT_FLAG, CD, PUSHD, POPD, GIT_VALUE_OPTIONS, i
|
|
|
18429
18543
|
raw: [...marker.raw, ...fresh.map((kind) => agent + kind)]
|
|
18430
18544
|
});
|
|
18431
18545
|
return fresh.map((kind) => nudges.get(kind));
|
|
18432
|
-
}, deny = (reason) => ({ kind: "deny", reason, unblock: null }), NEXT_COMMAND = "next", MARKER_TTL_SECONDS = 3600, markerFile = (repo, session, key) =>
|
|
18546
|
+
}, deny = (reason) => ({ kind: "deny", reason, unblock: null }), NEXT_COMMAND = "next", MARKER_TTL_SECONDS = 3600, markerFile = (repo, session, key) => path20.join(repo.location.dir, "hooks", `commit-${createHash14("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`), callKey = (toolUseId, command) => toolUseId ?? `cmd:${createHash14("sha256").update(command).digest("hex")}`, headCommit = (dir) => {
|
|
18433
18547
|
const run = spawnSync11("git", [
|
|
18434
18548
|
"log",
|
|
18435
18549
|
"-1",
|
|
@@ -18552,7 +18666,7 @@ var init_raw_git = __esm(() => {
|
|
|
18552
18666
|
// packages/workit-core/src/core/route-intent.ts
|
|
18553
18667
|
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
18554
18668
|
import { existsSync as existsSync6 } from "node:fs";
|
|
18555
|
-
import
|
|
18669
|
+
import path21 from "node:path";
|
|
18556
18670
|
var UNKNOWABLE, SWITCH_CREATE, CHECKOUT_CREATE, WORKTREE_CREATE, BRANCH_NO_CREATE, BRANCH_RENAME, flagValue = (args, flags) => {
|
|
18557
18671
|
for (let index = 1;index < args.length; index++) {
|
|
18558
18672
|
const arg = args[index];
|
|
@@ -18630,7 +18744,7 @@ var UNKNOWABLE, SWITCH_CREATE, CHECKOUT_CREATE, WORKTREE_CREATE, BRANCH_NO_CREAT
|
|
|
18630
18744
|
for (const target of shellBranchTargets(command, dialect)) {
|
|
18631
18745
|
if (target.dir === undefined)
|
|
18632
18746
|
continue;
|
|
18633
|
-
const dir = target.dir === null ? root :
|
|
18747
|
+
const dir = target.dir === null ? root : path21.resolve(root, target.dir);
|
|
18634
18748
|
if (target.dir !== null && (!existsSync6(dir) || !inWorkitWorkspace(dir)))
|
|
18635
18749
|
continue;
|
|
18636
18750
|
if (localBranchExists(dir, target.branch))
|
|
@@ -18665,7 +18779,7 @@ var init_policy = __esm(() => {
|
|
|
18665
18779
|
|
|
18666
18780
|
// packages/workit-core/src/hooks/write-gate.ts
|
|
18667
18781
|
import { realpathSync as realpathSync5 } from "node:fs";
|
|
18668
|
-
import
|
|
18782
|
+
import path22 from "node:path";
|
|
18669
18783
|
function writeGate(cwd, paths) {
|
|
18670
18784
|
try {
|
|
18671
18785
|
const gate = gateFor(cwd);
|
|
@@ -18685,21 +18799,21 @@ function writeGate(cwd, paths) {
|
|
|
18685
18799
|
}
|
|
18686
18800
|
var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
|
|
18687
18801
|
let rest = "";
|
|
18688
|
-
for (let dir =
|
|
18802
|
+
for (let dir = path22.resolve(file);; dir = path22.dirname(dir)) {
|
|
18689
18803
|
try {
|
|
18690
|
-
return
|
|
18804
|
+
return path22.join(realpathSync5(dir), rest);
|
|
18691
18805
|
} catch {
|
|
18692
|
-
if (
|
|
18693
|
-
return
|
|
18694
|
-
rest = rest ?
|
|
18806
|
+
if (path22.dirname(dir) === dir)
|
|
18807
|
+
return path22.resolve(file);
|
|
18808
|
+
rest = rest ? path22.join(path22.basename(dir), rest) : path22.basename(dir);
|
|
18695
18809
|
}
|
|
18696
18810
|
}
|
|
18697
18811
|
}, exempt = (cwd, root, file, plans) => {
|
|
18698
18812
|
const fold = (value) => CASE_INSENSITIVE ? value.toLowerCase() : value;
|
|
18699
|
-
const relative =
|
|
18700
|
-
if (relative.startsWith("..") ||
|
|
18813
|
+
const relative = path22.relative(fold(canonical2(root)), fold(canonical2(path22.resolve(cwd, file))));
|
|
18814
|
+
if (relative.startsWith("..") || path22.isAbsolute(relative))
|
|
18701
18815
|
return true;
|
|
18702
|
-
const posix = relative.split(
|
|
18816
|
+
const posix = relative.split(path22.sep).join("/");
|
|
18703
18817
|
const segments = posix.split("/");
|
|
18704
18818
|
return /\.mdx?$/i.test(posix) || segments[0] === "docs" || segments.includes("plans") || [...plans].some((plan) => fold(plan) === posix);
|
|
18705
18819
|
}, PREFIXES3, operands = (words) => words.filter((item) => !item.startsWith("-")), editsOf = (input) => {
|
|
@@ -18791,7 +18905,7 @@ var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
|
|
|
18791
18905
|
if (!unknown && targets.length === 0)
|
|
18792
18906
|
return { writes: false, targets: null };
|
|
18793
18907
|
return { writes: true, targets: unknown ? null : targets };
|
|
18794
|
-
}, cache2, planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(
|
|
18908
|
+
}, cache2, planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(path22.resolve(root, file)) ?? "-").join("\x00"), gateFor = (cwd) => {
|
|
18795
18909
|
const store = new TaskStore(cwd);
|
|
18796
18910
|
const listed = store.listTaskIndex();
|
|
18797
18911
|
if (!listed.ok)
|
|
@@ -19215,9 +19329,9 @@ var init_skill_nudge = __esm(() => {
|
|
|
19215
19329
|
|
|
19216
19330
|
// packages/workit-core/src/hooks/hosts/fields.ts
|
|
19217
19331
|
import { existsSync as existsSync7, realpathSync as realpathSync6, statSync as statSync2 } from "node:fs";
|
|
19218
|
-
import
|
|
19332
|
+
import path23 from "node:path";
|
|
19219
19333
|
var isRecord4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value), nonEmpty2 = (value) => typeof value === "string" && value.trim() !== "", optionalText = (value) => typeof value === "string" ? value : null, existingDirectory = (value) => {
|
|
19220
|
-
if (!nonEmpty2(value) || !
|
|
19334
|
+
if (!nonEmpty2(value) || !path23.isAbsolute(value) || !existsSync7(value))
|
|
19221
19335
|
return null;
|
|
19222
19336
|
try {
|
|
19223
19337
|
return statSync2(value).isDirectory() ? realpathSync6(value) : null;
|
|
@@ -19362,16 +19476,16 @@ var usable2 = (value) => value === "native" || value === "partial", NONE5, resen
|
|
|
19362
19476
|
const prefix = descriptor.subagents.agentPrefix;
|
|
19363
19477
|
const name = agentType.startsWith(prefix) ? agentType.slice(prefix.length) : "";
|
|
19364
19478
|
return Object.hasOwn(ROLES, name) ? ROLES[name] : null;
|
|
19365
|
-
}, subagentSession = (session, agentId) => [session, agentId].filter((part) => Boolean(part)).join(":").replace(/[^A-Za-z0-9_.:@/+-]/g, "-").slice(0, 128), CLAUDE_WORKTREE,
|
|
19479
|
+
}, subagentSession = (session, agentId) => [session, agentId].filter((part) => Boolean(part)).join(":").replace(/[^A-Za-z0-9_.:@/+-]/g, "-").slice(0, 128), CLAUDE_WORKTREE, isolatedGit = (cwd) => `Run git as plain, separate commands inside your worktree (\`git switch -c <branch> <base>\`, ${workspaceTrailers(cwd).enabled ? '`git commit --trailer "Workit-Session=<your session>"`, `git push`; `workit doctor --fix` can install a prepare-commit-msg hook that adds the trailer' : "`git commit` (this workspace sets trailers: false: add no Workit-Session trailer), `git push`"}; add Co-Authored-By with \`git commit --trailer\` in the same commit, never by amending), never \`workit git …\`: Claude Code's worktree isolation refuses a command that wraps git and cannot be turned off (https://code.claude.com/docs/en/worktrees#how-claude-code-enforces-isolation). Never dodge that check by renaming or re-wrapping git. Use workit for the non-git verbs (\`workit check\`, \`workit ledger\`, \`workit pr\`).`, subagentStartText = (input, descriptor, event) => {
|
|
19366
19480
|
const session = input.session.id ?? null;
|
|
19367
19481
|
const role = workitRole(descriptor, event.agentType);
|
|
19368
19482
|
const who = `${descriptor.label} subagent ${event.agentId} (${event.agentType})`;
|
|
19369
19483
|
const isolated = descriptor.subagents.worktreeIsolation === "native" && (role === "implementer" || CLAUDE_WORKTREE.test(input.cwd));
|
|
19370
19484
|
const guide = role === "implementer" ? branchGuidance(input.cwd) : null;
|
|
19371
19485
|
if (role === "implementer" && isolated)
|
|
19372
|
-
return `Workit observed ${who} working in its own git worktree: it may edit and commit there, within its brief's scope. ${
|
|
19486
|
+
return `Workit observed ${who} working in its own git worktree: it may edit and commit there, within its brief's scope. ${isolatedGit(input.cwd)} Plain git is expected here, and the branch name is still policy-checked: a raw \`git switch -c\`, \`git checkout -b\`, \`git branch\` or \`git worktree add -b\` onto a protected or non-compliant name is denied, so use a policy-compliant branch.${guide ? ` ${guide}` : " (e.g. feature/<slug>)"} Never record a verdict on your own work. Never push, open a PR, or merge unless the brief asks for it.`;
|
|
19373
19487
|
if (isolated)
|
|
19374
|
-
return `${
|
|
19488
|
+
return `${isolatedGit(input.cwd)}
|
|
19375
19489
|
${subagentStartText({ ...input, cwd: "" }, descriptor, event)}`;
|
|
19376
19490
|
if (role === "implementer")
|
|
19377
19491
|
return `Workit observed ${who} as an implementer: it edits and commits only in its own git worktree (the lead makes one with \`workit fanout worktree create <slice>\`), never in the lead's checkout, within its brief's scope. Before the first commit, switch to a policy-compliant branch with \`workit git branch <branch> --base <base>\` (or \`--kind <kind> --slug <slug>\`, which picks the base); branch policy hooks still deny protected or non-compliant branches, raw git included.${guide ? ` ${guide}` : " (e.g. feature/<slug>)"} Never record a verdict on your own work. Never push, open a PR, or merge unless the brief asks for it.`;
|
|
@@ -19413,6 +19527,7 @@ ${subagentStartText({ ...input, cwd: "" }, descriptor, event)}`;
|
|
|
19413
19527
|
var init_handle = __esm(() => {
|
|
19414
19528
|
init_context();
|
|
19415
19529
|
init_branch();
|
|
19530
|
+
init_workspaces();
|
|
19416
19531
|
init_host_session();
|
|
19417
19532
|
init_policy();
|
|
19418
19533
|
init_raw_git();
|
|
@@ -19957,7 +20072,7 @@ var init_codex = __esm(() => {
|
|
|
19957
20072
|
|
|
19958
20073
|
// packages/workit-core/src/hooks/hosts/cursor.ts
|
|
19959
20074
|
import fs17 from "node:fs";
|
|
19960
|
-
import
|
|
20075
|
+
import path24 from "node:path";
|
|
19961
20076
|
var undocumented, none, CURSOR_DESCRIPTOR, EVENTS3, parseCursorHookInput = (value) => {
|
|
19962
20077
|
if (!isRecord4(value) || !Object.hasOwn(EVENTS3, String(value.hook_event_name)))
|
|
19963
20078
|
return { ok: false, error: "hook_event_name is required" };
|
|
@@ -20038,7 +20153,7 @@ var undocumented, none, CURSOR_DESCRIPTOR, EVENTS3, parseCursorHookInput = (valu
|
|
|
20038
20153
|
};
|
|
20039
20154
|
}
|
|
20040
20155
|
}, TRANSCRIPT_TAIL_BYTES, lastAssistantText = (file) => {
|
|
20041
|
-
if (!file || !
|
|
20156
|
+
if (!file || !path24.isAbsolute(file))
|
|
20042
20157
|
return null;
|
|
20043
20158
|
try {
|
|
20044
20159
|
const size = fs17.statSync(file).size;
|
|
@@ -20074,7 +20189,7 @@ var undocumented, none, CURSOR_DESCRIPTOR, EVENTS3, parseCursorHookInput = (valu
|
|
|
20074
20189
|
} catch {
|
|
20075
20190
|
return null;
|
|
20076
20191
|
}
|
|
20077
|
-
}, within = (root, dir) => dir === root || dir.startsWith(root.endsWith(
|
|
20192
|
+
}, within = (root, dir) => dir === root || dir.startsWith(root.endsWith(path24.sep) ? root : `${root}${path24.sep}`), hookCwd = (input) => {
|
|
20078
20193
|
const cwd = existingDirectory(input.cwd);
|
|
20079
20194
|
if (cwd && input.hook_event_name === "beforeShellExecution")
|
|
20080
20195
|
return cwd;
|