@brainervirus/workit-cli 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/dist/index.js +502 -469
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -65,7 +65,7 @@ var package_default;
|
|
|
65
65
|
var init_package = __esm(() => {
|
|
66
66
|
package_default = {
|
|
67
67
|
name: "@brainervirus/workit-cli",
|
|
68
|
-
version: "8.12.
|
|
68
|
+
version: "8.12.1",
|
|
69
69
|
private: false,
|
|
70
70
|
description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
71
71
|
keywords: [
|
|
@@ -103,9 +103,9 @@ var init_package = __esm(() => {
|
|
|
103
103
|
},
|
|
104
104
|
dependencies: {
|
|
105
105
|
"@babel/parser": "7.29.9",
|
|
106
|
-
"@brainervirus/workit-core": "^8.12.
|
|
107
|
-
"@brainervirus/workit-cursor": "^8.12.
|
|
108
|
-
"@brainervirus/workit-opencode": "^8.12.
|
|
106
|
+
"@brainervirus/workit-core": "^8.12.1",
|
|
107
|
+
"@brainervirus/workit-cursor": "^8.12.1",
|
|
108
|
+
"@brainervirus/workit-opencode": "^8.12.1",
|
|
109
109
|
"@inkjs/ui": "2.0.0",
|
|
110
110
|
ink: "7.1.1",
|
|
111
111
|
react: "19.2.8"
|
|
@@ -9939,11 +9939,224 @@ var init_file_lock = __esm(() => {
|
|
|
9939
9939
|
init_file_lock_sync();
|
|
9940
9940
|
});
|
|
9941
9941
|
|
|
9942
|
+
// packages/workit-core/src/core/logger.ts
|
|
9943
|
+
import { appendFileSync, mkdirSync, readdirSync, unlinkSync } from "node:fs";
|
|
9944
|
+
import os from "node:os";
|
|
9945
|
+
import path4 from "node:path";
|
|
9946
|
+
var REDACTED = "[REDACTED]", DEFAULT_MAX_RATE = 20, DEFAULT_RATE_WINDOW_MS = 1000, DEFAULT_MAX_FIELD_LENGTH = 200, DEFAULT_MAX_STACK_LINES = 30, DAY_FILE, RETAINED_DAYS = 7, SECRET_VALUE, KEY_EQ_VALUE, URL_QUERY, splitKey = (key) => key.split(/[_-]+|(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/).map((word) => word.toLowerCase()), SENSITIVE_WORDS, STACK_WORDS, escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), resolveStateDir = () => {
|
|
9947
|
+
const override = process.env.WORKFLOW_TOOLKIT_STATE;
|
|
9948
|
+
if (override)
|
|
9949
|
+
return override;
|
|
9950
|
+
const home = os.homedir();
|
|
9951
|
+
if (process.env.XDG_STATE_HOME)
|
|
9952
|
+
return path4.join(process.env.XDG_STATE_HOME, "workit");
|
|
9953
|
+
switch (os.platform()) {
|
|
9954
|
+
case "darwin":
|
|
9955
|
+
return path4.join(home, "Library", "Application Support", "workit");
|
|
9956
|
+
case "win32":
|
|
9957
|
+
return path4.join(process.env.LOCALAPPDATA ?? path4.join(home, "AppData", "Local"), "workit");
|
|
9958
|
+
default:
|
|
9959
|
+
return path4.join(process.env.HOME ?? home, ".local", "state", "workit");
|
|
9960
|
+
}
|
|
9961
|
+
}, homePattern, applyPatterns = (value) => {
|
|
9962
|
+
let out = value;
|
|
9963
|
+
out = out.replace(SECRET_VALUE, REDACTED);
|
|
9964
|
+
out = out.replace(KEY_EQ_VALUE, "$1$2[REDACTED]");
|
|
9965
|
+
out = out.replace(URL_QUERY, "$1?[REDACTED]");
|
|
9966
|
+
out = out.replace(homePattern, "~");
|
|
9967
|
+
if (process.platform === "win32")
|
|
9968
|
+
out = out.replace(/\\/g, "/");
|
|
9969
|
+
return out;
|
|
9970
|
+
}, redactString = (value, options) => {
|
|
9971
|
+
const out = applyPatterns(value);
|
|
9972
|
+
if (out.length > options.maxFieldLength) {
|
|
9973
|
+
return `${out.slice(0, options.maxFieldLength)}…`;
|
|
9974
|
+
}
|
|
9975
|
+
return out;
|
|
9976
|
+
}, boundStack = (value, options) => {
|
|
9977
|
+
if (typeof value !== "string")
|
|
9978
|
+
return redact(value, options);
|
|
9979
|
+
const lines = value.split(`
|
|
9980
|
+
`);
|
|
9981
|
+
const kept = lines.slice(0, options.maxStackLines).map(applyPatterns);
|
|
9982
|
+
const dropped = lines.length - kept.length;
|
|
9983
|
+
const body = dropped > 0 ? [...kept, ` ... ${dropped} more`] : kept;
|
|
9984
|
+
return body.join(`
|
|
9985
|
+
`);
|
|
9986
|
+
}, redact = (value, options = DEFAULT_OPTIONS) => {
|
|
9987
|
+
if (value === null || value === undefined)
|
|
9988
|
+
return null;
|
|
9989
|
+
if (typeof value === "boolean" || typeof value === "number")
|
|
9990
|
+
return value;
|
|
9991
|
+
if (typeof value === "string")
|
|
9992
|
+
return redactString(value, options);
|
|
9993
|
+
if (value instanceof Date)
|
|
9994
|
+
return value.toISOString();
|
|
9995
|
+
if (Array.isArray(value))
|
|
9996
|
+
return value.map((entry) => redact(entry, options));
|
|
9997
|
+
if (typeof value === "object") {
|
|
9998
|
+
const out = {};
|
|
9999
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
10000
|
+
const words = splitKey(key);
|
|
10001
|
+
if (words.some((word) => STACK_WORDS.has(word)))
|
|
10002
|
+
out[key] = boundStack(entry, options);
|
|
10003
|
+
else if (words.some((word) => SENSITIVE_WORDS.has(word)))
|
|
10004
|
+
out[key] = REDACTED;
|
|
10005
|
+
else
|
|
10006
|
+
out[key] = redact(entry, options);
|
|
10007
|
+
}
|
|
10008
|
+
return out;
|
|
10009
|
+
}
|
|
10010
|
+
return null;
|
|
10011
|
+
}, DEFAULT_OPTIONS, dailyFileName = (date) => {
|
|
10012
|
+
const y = date.getFullYear();
|
|
10013
|
+
const m = String(date.getMonth() + 1).padStart(2, "0");
|
|
10014
|
+
const d = String(date.getDate()).padStart(2, "0");
|
|
10015
|
+
return `workit-${y}-${m}-${d}.jsonl`;
|
|
10016
|
+
}, pruneOldFiles = (dir) => {
|
|
10017
|
+
try {
|
|
10018
|
+
const files = readdirSync(dir).filter((name) => DAY_FILE.test(name)).toSorted().toReversed();
|
|
10019
|
+
for (const file of files.slice(RETAINED_DAYS)) {
|
|
10020
|
+
try {
|
|
10021
|
+
unlinkSync(path4.join(dir, file));
|
|
10022
|
+
} catch {}
|
|
10023
|
+
}
|
|
10024
|
+
} catch {}
|
|
10025
|
+
}, createLogger = (options = {}) => {
|
|
10026
|
+
const stateDir = options.stateDir ?? resolveStateDir();
|
|
10027
|
+
const logDir = path4.join(stateDir, "logs");
|
|
10028
|
+
const now = options.now ?? (() => new Date);
|
|
10029
|
+
const maxRate = options.maxRate ?? DEFAULT_MAX_RATE;
|
|
10030
|
+
const rateWindowMs = options.rateWindowMs ?? DEFAULT_RATE_WINDOW_MS;
|
|
10031
|
+
const redactOptions = {
|
|
10032
|
+
maxFieldLength: options.maxFieldLength ?? DEFAULT_MAX_FIELD_LENGTH,
|
|
10033
|
+
maxStackLines: options.maxStackLines ?? DEFAULT_MAX_STACK_LINES
|
|
10034
|
+
};
|
|
10035
|
+
let windowStart = 0;
|
|
10036
|
+
const windowCounts = { debug: 0, info: 0, warn: 0, error: 0 };
|
|
10037
|
+
const emit = (level, message, context) => {
|
|
10038
|
+
const date = now();
|
|
10039
|
+
const elapsed = date.getTime() - windowStart;
|
|
10040
|
+
if (elapsed >= rateWindowMs || windowStart === 0) {
|
|
10041
|
+
windowStart = date.getTime();
|
|
10042
|
+
windowCounts.debug = 0;
|
|
10043
|
+
windowCounts.info = 0;
|
|
10044
|
+
windowCounts.warn = 0;
|
|
10045
|
+
windowCounts.error = 0;
|
|
10046
|
+
}
|
|
10047
|
+
windowCounts[level] += 1;
|
|
10048
|
+
if (windowCounts[level] > maxRate)
|
|
10049
|
+
return;
|
|
10050
|
+
let event = null;
|
|
10051
|
+
try {
|
|
10052
|
+
event = {
|
|
10053
|
+
level,
|
|
10054
|
+
time: date.toISOString(),
|
|
10055
|
+
message: redactString(message, redactOptions),
|
|
10056
|
+
context: redact(context ?? {}, redactOptions)
|
|
10057
|
+
};
|
|
10058
|
+
const line = `${JSON.stringify(event)}
|
|
10059
|
+
`;
|
|
10060
|
+
mkdirSync(logDir, { recursive: true, mode: 448 });
|
|
10061
|
+
appendFileSync(path4.join(logDir, dailyFileName(date)), line, { mode: 384 });
|
|
10062
|
+
pruneOldFiles(logDir);
|
|
10063
|
+
} catch {
|
|
10064
|
+
try {
|
|
10065
|
+
event = {
|
|
10066
|
+
level,
|
|
10067
|
+
time: date.toISOString(),
|
|
10068
|
+
message: redactString(message, redactOptions),
|
|
10069
|
+
context: { redaction_failed: true }
|
|
10070
|
+
};
|
|
10071
|
+
mkdirSync(logDir, { recursive: true, mode: 448 });
|
|
10072
|
+
appendFileSync(path4.join(logDir, dailyFileName(date)), `${JSON.stringify(event)}
|
|
10073
|
+
`, {
|
|
10074
|
+
mode: 384
|
|
10075
|
+
});
|
|
10076
|
+
} catch {}
|
|
10077
|
+
}
|
|
10078
|
+
for (const sink of [options.appLog, options.stderr]) {
|
|
10079
|
+
if (!sink)
|
|
10080
|
+
continue;
|
|
10081
|
+
if (!event)
|
|
10082
|
+
continue;
|
|
10083
|
+
try {
|
|
10084
|
+
sink(event);
|
|
10085
|
+
} catch {}
|
|
10086
|
+
}
|
|
10087
|
+
};
|
|
10088
|
+
return {
|
|
10089
|
+
debug: (message, context) => emit("debug", message, context),
|
|
10090
|
+
info: (message, context) => emit("info", message, context),
|
|
10091
|
+
warn: (message, context) => emit("warn", message, context),
|
|
10092
|
+
error: (message, context) => emit("error", message, context),
|
|
10093
|
+
guard: (name, fn) => {
|
|
10094
|
+
try {
|
|
10095
|
+
return fn();
|
|
10096
|
+
} catch (err) {
|
|
10097
|
+
emit("warn", "detector_failed", {
|
|
10098
|
+
detector: name,
|
|
10099
|
+
error: err instanceof Error ? err.message : String(err)
|
|
10100
|
+
});
|
|
10101
|
+
return;
|
|
10102
|
+
}
|
|
10103
|
+
}
|
|
10104
|
+
};
|
|
10105
|
+
};
|
|
10106
|
+
var init_logger = __esm(() => {
|
|
10107
|
+
DAY_FILE = /^workit-\d{4}-\d{2}-\d{2}\.jsonl$/;
|
|
10108
|
+
SECRET_VALUE = /\b(?:Bearer|Basic|Digest|Token)\s+\S+/gi;
|
|
10109
|
+
KEY_EQ_VALUE = /\b([A-Za-z0-9_-]*(?:token|secret|password|passwd|apikey|api[_-]?key|authorization|credential|bearer)[A-Za-z0-9_-]*)([:=]\s*).+/gi;
|
|
10110
|
+
URL_QUERY = /(https?:\/\/[^?#\s]+)\?[^#\s]*/g;
|
|
10111
|
+
SENSITIVE_WORDS = new Set([
|
|
10112
|
+
"token",
|
|
10113
|
+
"secret",
|
|
10114
|
+
"password",
|
|
10115
|
+
"passwd",
|
|
10116
|
+
"authorization",
|
|
10117
|
+
"credential",
|
|
10118
|
+
"credentials",
|
|
10119
|
+
"cookie",
|
|
10120
|
+
"api",
|
|
10121
|
+
"apikey",
|
|
10122
|
+
"apitoken",
|
|
10123
|
+
"accesstoken",
|
|
10124
|
+
"clientsecret",
|
|
10125
|
+
"refreshtoken",
|
|
10126
|
+
"key",
|
|
10127
|
+
"bearer",
|
|
10128
|
+
"prompt",
|
|
10129
|
+
"message",
|
|
10130
|
+
"messages",
|
|
10131
|
+
"content",
|
|
10132
|
+
"body",
|
|
10133
|
+
"args",
|
|
10134
|
+
"argument",
|
|
10135
|
+
"result",
|
|
10136
|
+
"results",
|
|
10137
|
+
"output",
|
|
10138
|
+
"issue",
|
|
10139
|
+
"description",
|
|
10140
|
+
"summary",
|
|
10141
|
+
"payload",
|
|
10142
|
+
"script",
|
|
10143
|
+
"command",
|
|
10144
|
+
"text",
|
|
10145
|
+
"query"
|
|
10146
|
+
]);
|
|
10147
|
+
STACK_WORDS = new Set(["stack", "stacktrace", "trace"]);
|
|
10148
|
+
homePattern = new RegExp(`${escapeRegExp(os.homedir())}(?=[/\\\\]|$)|\\$HOME(?=[/\\\\]|$)`, "g");
|
|
10149
|
+
DEFAULT_OPTIONS = {
|
|
10150
|
+
maxFieldLength: DEFAULT_MAX_FIELD_LENGTH,
|
|
10151
|
+
maxStackLines: DEFAULT_MAX_STACK_LINES
|
|
10152
|
+
};
|
|
10153
|
+
});
|
|
10154
|
+
|
|
9942
10155
|
// packages/workit-core/src/store/paths.ts
|
|
9943
10156
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
9944
10157
|
import { createHash as createHash2 } from "node:crypto";
|
|
9945
10158
|
import fs5 from "node:fs";
|
|
9946
|
-
import
|
|
10159
|
+
import path5 from "node:path";
|
|
9947
10160
|
function fastGit(root) {
|
|
9948
10161
|
if (DISCOVERY_ENV.some((name) => process.env[name]))
|
|
9949
10162
|
return null;
|
|
@@ -9959,7 +10172,7 @@ function fastGit(root) {
|
|
|
9959
10172
|
if (device !== null && stat.dev !== device)
|
|
9960
10173
|
return { kind: "none" };
|
|
9961
10174
|
device = stat.dev;
|
|
9962
|
-
const dotGit =
|
|
10175
|
+
const dotGit = path5.join(dir, ".git");
|
|
9963
10176
|
let entry = null;
|
|
9964
10177
|
try {
|
|
9965
10178
|
entry = fs5.statSync(dotGit);
|
|
@@ -9980,19 +10193,19 @@ function fastGit(root) {
|
|
|
9980
10193
|
const match = /^gitdir: (.+)$/mu.exec(text);
|
|
9981
10194
|
if (!match)
|
|
9982
10195
|
return null;
|
|
9983
|
-
gitDir =
|
|
10196
|
+
gitDir = path5.resolve(dir, match[1].trim());
|
|
9984
10197
|
} else
|
|
9985
10198
|
return null;
|
|
9986
|
-
if (!fs5.existsSync(
|
|
10199
|
+
if (!fs5.existsSync(path5.join(gitDir, "HEAD")))
|
|
9987
10200
|
return null;
|
|
9988
10201
|
} else if (isGitDir(dir))
|
|
9989
10202
|
gitDir = dir;
|
|
9990
10203
|
if (gitDir) {
|
|
9991
10204
|
let common = gitDir;
|
|
9992
10205
|
try {
|
|
9993
|
-
common =
|
|
10206
|
+
common = path5.resolve(gitDir, fs5.readFileSync(path5.join(gitDir, "commondir"), "utf8").trim());
|
|
9994
10207
|
} catch {}
|
|
9995
|
-
if (!fs5.existsSync(
|
|
10208
|
+
if (!fs5.existsSync(path5.join(common, "objects")))
|
|
9996
10209
|
return null;
|
|
9997
10210
|
return {
|
|
9998
10211
|
kind: "repo",
|
|
@@ -10002,26 +10215,26 @@ function fastGit(root) {
|
|
|
10002
10215
|
reftable: reftableRefs(common)
|
|
10003
10216
|
};
|
|
10004
10217
|
}
|
|
10005
|
-
const parent =
|
|
10218
|
+
const parent = path5.dirname(dir);
|
|
10006
10219
|
if (parent === dir)
|
|
10007
10220
|
return { kind: "none" };
|
|
10008
10221
|
dir = parent;
|
|
10009
10222
|
}
|
|
10010
10223
|
}
|
|
10011
10224
|
function resolveStore(root) {
|
|
10012
|
-
root =
|
|
10225
|
+
root = path5.resolve(root);
|
|
10013
10226
|
let directory = false;
|
|
10014
10227
|
try {
|
|
10015
10228
|
directory = fs5.statSync(root).isDirectory();
|
|
10016
10229
|
} catch {}
|
|
10017
10230
|
if (!directory)
|
|
10018
|
-
return { dir:
|
|
10231
|
+
return { dir: path5.join(root, ".workit"), shared: false, top: null };
|
|
10019
10232
|
const fast = fastGit(root);
|
|
10020
10233
|
if (fast?.kind === "none")
|
|
10021
|
-
return { dir:
|
|
10234
|
+
return { dir: path5.join(root, ".workit"), shared: false, top: null };
|
|
10022
10235
|
if (fast?.kind === "repo")
|
|
10023
10236
|
return {
|
|
10024
|
-
dir:
|
|
10237
|
+
dir: path5.join(fast.common, "workit"),
|
|
10025
10238
|
shared: true,
|
|
10026
10239
|
top: fast.top,
|
|
10027
10240
|
git: { gitDir: fast.gitDir, top: fast.top, reftable: fast.reftable }
|
|
@@ -10031,13 +10244,13 @@ function resolveStore(root) {
|
|
|
10031
10244
|
if (run.ok && common) {
|
|
10032
10245
|
const top = gitRun(root, ["rev-parse", "--path-format=absolute", "--show-toplevel"]);
|
|
10033
10246
|
return {
|
|
10034
|
-
dir:
|
|
10247
|
+
dir: path5.join(real(path5.resolve(root, common)), "workit"),
|
|
10035
10248
|
shared: true,
|
|
10036
10249
|
top: top.ok && top.stdout.trim() ? real(top.stdout.trim()) : null
|
|
10037
10250
|
};
|
|
10038
10251
|
}
|
|
10039
10252
|
if (run.missing || !run.ok && NOT_A_REPO.test(run.stderr))
|
|
10040
|
-
return { dir:
|
|
10253
|
+
return { dir: path5.join(root, ".workit"), shared: false, top: null };
|
|
10041
10254
|
return new Error(`cannot locate the workit store: git rev-parse failed (${run.stderr.trim().split(`
|
|
10042
10255
|
`)[0] || "no output"}); fix the repository (git status should work here)`);
|
|
10043
10256
|
}
|
|
@@ -10048,7 +10261,7 @@ function resolveTaskKey(root, location) {
|
|
|
10048
10261
|
if (location.git && !location.git.reftable) {
|
|
10049
10262
|
let head = "";
|
|
10050
10263
|
try {
|
|
10051
|
-
head = fs5.readFileSync(
|
|
10264
|
+
head = fs5.readFileSync(path5.join(location.git.gitDir, "HEAD"), "utf8").trim();
|
|
10052
10265
|
} catch {}
|
|
10053
10266
|
const ref = /^ref: refs\/heads\/(.+)$/u.exec(head);
|
|
10054
10267
|
if (ref && ref[1] !== ".invalid")
|
|
@@ -10079,7 +10292,7 @@ function resolveTaskKey(root, location) {
|
|
|
10079
10292
|
return { key: `detached-${shortHash(real(worktree))}`, kind: "detached", branch: null };
|
|
10080
10293
|
}
|
|
10081
10294
|
function checkoutRootOf(root, location) {
|
|
10082
|
-
const resolved =
|
|
10295
|
+
const resolved = path5.resolve(root);
|
|
10083
10296
|
let canonical = resolved;
|
|
10084
10297
|
try {
|
|
10085
10298
|
canonical = fs5.realpathSync(resolved);
|
|
@@ -10110,13 +10323,13 @@ function branchRenames(location) {
|
|
|
10110
10323
|
}
|
|
10111
10324
|
for (const entry of entries)
|
|
10112
10325
|
if (entry.isDirectory())
|
|
10113
|
-
walk(
|
|
10326
|
+
walk(path5.join(dir, entry.name));
|
|
10114
10327
|
else
|
|
10115
|
-
files.push(
|
|
10328
|
+
files.push(path5.join(dir, entry.name));
|
|
10116
10329
|
};
|
|
10117
|
-
walk(
|
|
10330
|
+
walk(path5.join(path5.dirname(location.dir), "logs", "refs", "heads"));
|
|
10118
10331
|
if (location.git)
|
|
10119
|
-
files.push(
|
|
10332
|
+
files.push(path5.join(location.git.gitDir, "logs", "HEAD"));
|
|
10120
10333
|
const seen = new Set;
|
|
10121
10334
|
const renames = [];
|
|
10122
10335
|
for (const file of files) {
|
|
@@ -10177,20 +10390,20 @@ var NOT_A_REPO, gitRun = (cwd, args) => {
|
|
|
10177
10390
|
}
|
|
10178
10391
|
}, DISCOVERY_ENV, isGitDir = (dir) => {
|
|
10179
10392
|
try {
|
|
10180
|
-
return fs5.statSync(
|
|
10393
|
+
return fs5.statSync(path5.join(dir, "HEAD")).isFile() && fs5.statSync(path5.join(dir, "objects")).isDirectory() && fs5.statSync(path5.join(dir, "refs")).isDirectory();
|
|
10181
10394
|
} catch {
|
|
10182
10395
|
return false;
|
|
10183
10396
|
}
|
|
10184
10397
|
}, reftableRefs = (common) => {
|
|
10185
10398
|
try {
|
|
10186
|
-
return /^\s*refstorage\s*=\s*reftable\s*$/imu.test(fs5.readFileSync(
|
|
10399
|
+
return /^\s*refstorage\s*=\s*reftable\s*$/imu.test(fs5.readFileSync(path5.join(common, "config"), "utf8"));
|
|
10187
10400
|
} catch {
|
|
10188
10401
|
return false;
|
|
10189
10402
|
}
|
|
10190
10403
|
}, rebasingBranch = (gitDir) => {
|
|
10191
10404
|
for (const state of ["rebase-merge", "rebase-apply"]) {
|
|
10192
10405
|
try {
|
|
10193
|
-
const ref = fs5.readFileSync(
|
|
10406
|
+
const ref = fs5.readFileSync(path5.join(gitDir, state, "head-name"), "utf8").trim();
|
|
10194
10407
|
const match = /^refs\/heads\/(.+)$/u.exec(ref);
|
|
10195
10408
|
if (match)
|
|
10196
10409
|
return match[1];
|
|
@@ -10201,7 +10414,7 @@ var NOT_A_REPO, gitRun = (cwd, args) => {
|
|
|
10201
10414
|
let canonical = real(root);
|
|
10202
10415
|
if (process.platform === "win32")
|
|
10203
10416
|
canonical = canonical.toLowerCase();
|
|
10204
|
-
const base =
|
|
10417
|
+
const base = path5.basename(canonical).replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 40) || "root";
|
|
10205
10418
|
return `${base}-${shortHash(canonical)}`;
|
|
10206
10419
|
};
|
|
10207
10420
|
var init_paths = __esm(() => {
|
|
@@ -10218,7 +10431,7 @@ var init_paths = __esm(() => {
|
|
|
10218
10431
|
// packages/workit-core/src/host-session.ts
|
|
10219
10432
|
import { createHash as createHash3 } from "node:crypto";
|
|
10220
10433
|
import fs6 from "node:fs";
|
|
10221
|
-
import
|
|
10434
|
+
import path6 from "node:path";
|
|
10222
10435
|
function hostSessionFromEnv(env) {
|
|
10223
10436
|
const value = (key) => env[key]?.trim() || null;
|
|
10224
10437
|
let inner = null;
|
|
@@ -10247,6 +10460,36 @@ function realHostSession(env) {
|
|
|
10247
10460
|
const hosted = declared.host !== null && declared.host !== "cli";
|
|
10248
10461
|
return { ...declared, kind: hosted ? "declared" : "none" };
|
|
10249
10462
|
}
|
|
10463
|
+
function migrateRepoIssued(cwd) {
|
|
10464
|
+
if (cwd === undefined)
|
|
10465
|
+
return;
|
|
10466
|
+
let old;
|
|
10467
|
+
try {
|
|
10468
|
+
const location = resolveStore(cwd);
|
|
10469
|
+
if (location instanceof Error)
|
|
10470
|
+
return;
|
|
10471
|
+
old = path6.join(location.dir, "hooks", "issued");
|
|
10472
|
+
if (!fs6.existsSync(old))
|
|
10473
|
+
return;
|
|
10474
|
+
} catch {
|
|
10475
|
+
return;
|
|
10476
|
+
}
|
|
10477
|
+
for (const lead of safeList(old)) {
|
|
10478
|
+
try {
|
|
10479
|
+
const from = path6.join(old, lead);
|
|
10480
|
+
if (!fs6.statSync(from).isDirectory())
|
|
10481
|
+
continue;
|
|
10482
|
+
const to = path6.join(userIssuedRoot(), lead);
|
|
10483
|
+
fs6.mkdirSync(to, { recursive: true, mode: 448 });
|
|
10484
|
+
for (const id of fs6.readdirSync(from)) {
|
|
10485
|
+
fs6.copyFileSync(path6.join(from, id), path6.join(to, id));
|
|
10486
|
+
fs6.rmSync(path6.join(from, id), { force: true });
|
|
10487
|
+
}
|
|
10488
|
+
removeIfEmpty(from);
|
|
10489
|
+
} catch {}
|
|
10490
|
+
}
|
|
10491
|
+
removeIfEmpty(old);
|
|
10492
|
+
}
|
|
10250
10493
|
function sessionClaimRefusal(env, claimed, cwd) {
|
|
10251
10494
|
const real = realHostSession(env);
|
|
10252
10495
|
const host = family(real.host);
|
|
@@ -10271,9 +10514,9 @@ function sessionClaimRefusal(env, claimed, cwd) {
|
|
|
10271
10514
|
issuedClaim = true;
|
|
10272
10515
|
}
|
|
10273
10516
|
const error = `forged_session: ${claimed} is neither this shell's session (${real.session}) nor an id its host issued to a child of it`;
|
|
10274
|
-
if (issuedClaim && noIssuedRecord(cwd) && host !== null && PLUGIN_UPDATE[host])
|
|
10517
|
+
if (issuedClaim && noIssuedRecord(cwd, leadOf(claimed)) && host !== null && PLUGIN_UPDATE[host])
|
|
10275
10518
|
return {
|
|
10276
|
-
error: `${error}; no SubagentStart hook
|
|
10519
|
+
error: `${error}; no SubagentStart hook has recorded an issued id for this lead`,
|
|
10277
10520
|
unblock: `the workit plugin hook is probably older than this CLI and does not record the ids it issues: update the plugin (${PLUGIN_UPDATE[host]}), then relaunch the verifier so its SubagentStart runs the new hook (workit doctor checks this as hook_issued_sessions)`
|
|
10278
10521
|
};
|
|
10279
10522
|
const ownChildShell = host !== null && OWN_CHILD_SHELL.has(host);
|
|
@@ -10282,32 +10525,35 @@ function sessionClaimRefusal(env, claimed, cwd) {
|
|
|
10282
10525
|
unblock: ownChildShell ? `record the verdict from the verifier's own ${host === "pi" ? "Pi worker" : "OpenCode child session"} shell, where WORKIT_SESSION_ID is already set; never set WORKIT_SESSION_ID or --session by hand` : "never name a session yourself: spawn a verifier or reviewer subagent and pass exactly the --session its SubagentStart context names, or pass --as verifier"
|
|
10283
10526
|
};
|
|
10284
10527
|
}
|
|
10285
|
-
var HOST_SESSION_VARS, family = (host) => host?.replace(/_(?:cli|desktop)$/, "") ?? null, hash = (value) => createHash3("sha256").update(value).digest("hex").slice(0, 32),
|
|
10286
|
-
|
|
10287
|
-
|
|
10288
|
-
}
|
|
10289
|
-
|
|
10290
|
-
|
|
10291
|
-
},
|
|
10528
|
+
var HOST_SESSION_VARS, family = (host) => host?.replace(/_(?:cli|desktop)$/, "") ?? null, hash = (value) => createHash3("sha256").update(value).digest("hex").slice(0, 32), userIssuedRoot = () => path6.join(resolveStateDir(), "issued"), safeList = (dir) => {
|
|
10529
|
+
try {
|
|
10530
|
+
return fs6.readdirSync(dir);
|
|
10531
|
+
} catch {
|
|
10532
|
+
return [];
|
|
10533
|
+
}
|
|
10534
|
+
}, removeIfEmpty = (dir) => {
|
|
10535
|
+
try {
|
|
10536
|
+
fs6.rmdirSync(dir);
|
|
10537
|
+
} catch {}
|
|
10538
|
+
}, noIssuedRecord = (cwd, lead) => {
|
|
10292
10539
|
if (cwd === undefined)
|
|
10293
10540
|
return false;
|
|
10294
10541
|
try {
|
|
10295
|
-
|
|
10296
|
-
return
|
|
10542
|
+
migrateRepoIssued(cwd);
|
|
10543
|
+
return !fs6.existsSync(path6.join(userIssuedRoot(), hash(lead)));
|
|
10297
10544
|
} catch {
|
|
10298
10545
|
return false;
|
|
10299
10546
|
}
|
|
10300
10547
|
}, PLUGIN_UPDATE, wasIssued = (cwd, lead, claimed) => {
|
|
10301
|
-
|
|
10302
|
-
return false;
|
|
10548
|
+
migrateRepoIssued(cwd);
|
|
10303
10549
|
try {
|
|
10304
|
-
|
|
10305
|
-
return dir !== null && fs6.existsSync(path5.join(dir, hash(claimed)));
|
|
10550
|
+
return fs6.existsSync(path6.join(userIssuedRoot(), hash(lead), hash(claimed)));
|
|
10306
10551
|
} catch {
|
|
10307
10552
|
return false;
|
|
10308
10553
|
}
|
|
10309
10554
|
}, leadOf = (session) => session.slice(0, session.lastIndexOf(":")), OWN_CHILD_SHELL, HOST_SET_VARIABLE;
|
|
10310
10555
|
var init_host_session = __esm(() => {
|
|
10556
|
+
init_logger();
|
|
10311
10557
|
init_paths();
|
|
10312
10558
|
HOST_SESSION_VARS = [
|
|
10313
10559
|
["OPENCODE_SESSION_ID", () => "opencode"],
|
|
@@ -10331,19 +10577,19 @@ var init_host_session = __esm(() => {
|
|
|
10331
10577
|
|
|
10332
10578
|
// packages/workit-core/src/core/package-root.ts
|
|
10333
10579
|
import { existsSync } from "node:fs";
|
|
10334
|
-
import
|
|
10580
|
+
import path7 from "node:path";
|
|
10335
10581
|
import { fileURLToPath } from "node:url";
|
|
10336
10582
|
var packageRoot = () => {
|
|
10337
|
-
let dir =
|
|
10583
|
+
let dir = path7.dirname(fileURLToPath(import.meta.url));
|
|
10338
10584
|
while (true) {
|
|
10339
|
-
const parent =
|
|
10340
|
-
if (existsSync(
|
|
10585
|
+
const parent = path7.dirname(dir);
|
|
10586
|
+
if (existsSync(path7.join(dir, "package.json")) || parent === dir)
|
|
10341
10587
|
return dir;
|
|
10342
10588
|
dir = parent;
|
|
10343
10589
|
}
|
|
10344
10590
|
}, assetRoot = () => {
|
|
10345
10591
|
const root = packageRoot();
|
|
10346
|
-
const assets =
|
|
10592
|
+
const assets = path7.join(root, "assets");
|
|
10347
10593
|
return existsSync(assets) ? assets : root;
|
|
10348
10594
|
};
|
|
10349
10595
|
var init_package_root = () => {};
|
|
@@ -10352,7 +10598,7 @@ var init_package_root = () => {};
|
|
|
10352
10598
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
10353
10599
|
import fs7 from "node:fs";
|
|
10354
10600
|
import { hostname } from "node:os";
|
|
10355
|
-
import
|
|
10601
|
+
import path8 from "node:path";
|
|
10356
10602
|
var metadataLockSchema, FOREIGN_LOCK_TTL_MS, UNREADABLE_LOCK_TTL_MS = 30000, RECLAIM_GUARD_TTL_MS = 30000, defaultLockTimeoutMs = 250, defaultLockTimeout = () => defaultLockTimeoutMs, setDefaultLockTimeout = (ms) => {
|
|
10357
10603
|
defaultLockTimeoutMs = ms;
|
|
10358
10604
|
}, parseMetadataLock = (raw) => {
|
|
@@ -10456,13 +10702,13 @@ var metadataLockSchema, FOREIGN_LOCK_TTL_MS, UNREADABLE_LOCK_TTL_MS = 30000, REC
|
|
|
10456
10702
|
return null;
|
|
10457
10703
|
}
|
|
10458
10704
|
}, lockPathFor = (root) => {
|
|
10459
|
-
let real =
|
|
10705
|
+
let real = path8.resolve(root);
|
|
10460
10706
|
try {
|
|
10461
10707
|
real = fs7.realpathSync(real);
|
|
10462
10708
|
} catch {}
|
|
10463
10709
|
const location = resolveStore(real);
|
|
10464
|
-
const dir = location instanceof Error ?
|
|
10465
|
-
return
|
|
10710
|
+
const dir = location instanceof Error ? path8.join(real, ".workit") : location.dir;
|
|
10711
|
+
return path8.join(dir, "checkouts", checkoutSlug(real), "metadata.lock");
|
|
10466
10712
|
}, clearAbandonedReclaimGuard = (lockPath, nowMs = Date.now()) => {
|
|
10467
10713
|
const guard = `${lockPath}.reclaim`;
|
|
10468
10714
|
const age = ageOf(guard, nowMs);
|
|
@@ -10549,7 +10795,7 @@ var init_store_lock = __esm(() => {
|
|
|
10549
10795
|
// packages/workit-core/src/store/event-log.ts
|
|
10550
10796
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
10551
10797
|
import fs8 from "node:fs";
|
|
10552
|
-
import
|
|
10798
|
+
import path9 from "node:path";
|
|
10553
10799
|
function readLog(file, from = 0, expectSeq = null) {
|
|
10554
10800
|
let fd;
|
|
10555
10801
|
try {
|
|
@@ -10622,7 +10868,7 @@ function appendEvent(file, event, validEnd) {
|
|
|
10622
10868
|
fs8.closeSync(fd);
|
|
10623
10869
|
}
|
|
10624
10870
|
if (created)
|
|
10625
|
-
fsyncDirectory(
|
|
10871
|
+
fsyncDirectory(path9.dirname(file));
|
|
10626
10872
|
return validEnd;
|
|
10627
10873
|
}
|
|
10628
10874
|
function replaceFile(file, bytes, durable) {
|
|
@@ -10638,7 +10884,7 @@ function replaceFile(file, bytes, durable) {
|
|
|
10638
10884
|
}
|
|
10639
10885
|
renameWithRetry(temporary, file);
|
|
10640
10886
|
if (durable)
|
|
10641
|
-
fsyncDirectory(
|
|
10887
|
+
fsyncDirectory(path9.dirname(file));
|
|
10642
10888
|
} catch (error) {
|
|
10643
10889
|
try {
|
|
10644
10890
|
fs8.unlinkSync(temporary);
|
|
@@ -10948,7 +11194,7 @@ var init_notes = __esm(() => {
|
|
|
10948
11194
|
// packages/workit-core/src/core/task-store.ts
|
|
10949
11195
|
import { createHash as createHash5, randomUUID as randomUUID3 } from "node:crypto";
|
|
10950
11196
|
import * as fs9 from "node:fs";
|
|
10951
|
-
import
|
|
11197
|
+
import path10 from "node:path";
|
|
10952
11198
|
|
|
10953
11199
|
class TaskStore {
|
|
10954
11200
|
root;
|
|
@@ -10960,7 +11206,7 @@ class TaskStore {
|
|
|
10960
11206
|
migrationChecked = false;
|
|
10961
11207
|
compactDue = new Set;
|
|
10962
11208
|
constructor(root, options = {}) {
|
|
10963
|
-
const resolved =
|
|
11209
|
+
const resolved = path10.resolve(root);
|
|
10964
11210
|
this.origin = fs9.existsSync(resolved) ? fs9.realpathSync(resolved) : resolved;
|
|
10965
11211
|
this.located = resolveStore(this.origin);
|
|
10966
11212
|
this.root = checkoutRootOf(this.origin, this.located);
|
|
@@ -10969,7 +11215,7 @@ class TaskStore {
|
|
|
10969
11215
|
this.migrateOnRead = options.migrateOnRead;
|
|
10970
11216
|
}
|
|
10971
11217
|
location() {
|
|
10972
|
-
if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs9.existsSync(
|
|
11218
|
+
if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs9.existsSync(path10.join(this.root, ".git"))) {
|
|
10973
11219
|
this.located = undefined;
|
|
10974
11220
|
this.migrationChecked = false;
|
|
10975
11221
|
}
|
|
@@ -11125,7 +11371,7 @@ class TaskStore {
|
|
|
11125
11371
|
const moved = this.bindLocked(again.data.id, key, input.now);
|
|
11126
11372
|
return moved.ok ? success(moved.data.revision, null, { task: moved.data, created: false, key }) : moved;
|
|
11127
11373
|
}
|
|
11128
|
-
const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" :
|
|
11374
|
+
const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path10.basename(this.root) || this.root;
|
|
11129
11375
|
const intent = {
|
|
11130
11376
|
objective: input.objective?.trim() || `Work on ${label}`,
|
|
11131
11377
|
scope: { description: `the checkout (${label})`, paths: ["."], exclusions: [] },
|
|
@@ -11185,14 +11431,14 @@ class TaskStore {
|
|
|
11185
11431
|
const branch = key.ok ? key.data.branch : null;
|
|
11186
11432
|
if (!branch || !location.ok)
|
|
11187
11433
|
return success(null, null, null);
|
|
11188
|
-
const common =
|
|
11189
|
-
const heads =
|
|
11190
|
-
const headLog = location.data.git ?
|
|
11434
|
+
const common = path10.dirname(location.data.dir);
|
|
11435
|
+
const heads = path10.join(common, "logs", "refs", "heads");
|
|
11436
|
+
const headLog = location.data.git ? path10.join(location.data.git.gitDir, "logs", "HEAD") : "";
|
|
11191
11437
|
const signatures = [
|
|
11192
|
-
|
|
11438
|
+
path10.join(heads, branch),
|
|
11193
11439
|
headLog,
|
|
11194
11440
|
heads,
|
|
11195
|
-
|
|
11441
|
+
path10.join(common, "packed-refs")
|
|
11196
11442
|
].map((file) => fileSignature(file) ?? "-");
|
|
11197
11443
|
const slot = `${location.data.dir}\x00${headLog}\x00${branch}`;
|
|
11198
11444
|
let resolved = origins.get(slot);
|
|
@@ -11204,7 +11450,7 @@ class TaskStore {
|
|
|
11204
11450
|
aliases.push(rename.from);
|
|
11205
11451
|
const start = branchStart(location.data, branch, aliases);
|
|
11206
11452
|
const slash = start?.indexOf("/") ?? -1;
|
|
11207
|
-
const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(
|
|
11453
|
+
const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(path10.join(common, "config")).includes(`[remote "${start.slice(0, slash)}"]`));
|
|
11208
11454
|
const name = start && (remote ? start.slice(slash + 1) : start);
|
|
11209
11455
|
resolved = {
|
|
11210
11456
|
signature: signatures.join("|"),
|
|
@@ -11442,13 +11688,13 @@ class TaskStore {
|
|
|
11442
11688
|
if (!ready.ok)
|
|
11443
11689
|
return ready;
|
|
11444
11690
|
const dirs = this.paths();
|
|
11445
|
-
const recovery =
|
|
11691
|
+
const recovery = path10.join(this.root, ".workit", "recovery");
|
|
11446
11692
|
if (fs9.existsSync(recovery)) {
|
|
11447
11693
|
let files = 0;
|
|
11448
11694
|
let bytes = 0;
|
|
11449
11695
|
try {
|
|
11450
11696
|
for (const name of fs9.readdirSync(recovery)) {
|
|
11451
|
-
const stat = fs9.lstatSync(
|
|
11697
|
+
const stat = fs9.lstatSync(path10.join(recovery, name));
|
|
11452
11698
|
if (!stat.isFile())
|
|
11453
11699
|
continue;
|
|
11454
11700
|
files += 1;
|
|
@@ -11501,7 +11747,7 @@ class TaskStore {
|
|
|
11501
11747
|
if (fs9.existsSync(dirs.blobs))
|
|
11502
11748
|
for (const name of fs9.readdirSync(dirs.blobs)) {
|
|
11503
11749
|
const digest = name.replace(/\.json$/, "");
|
|
11504
|
-
const file =
|
|
11750
|
+
const file = path10.join(dirs.blobs, name);
|
|
11505
11751
|
let stat;
|
|
11506
11752
|
try {
|
|
11507
11753
|
stat = fs9.lstatSync(file);
|
|
@@ -11519,7 +11765,7 @@ class TaskStore {
|
|
|
11519
11765
|
}
|
|
11520
11766
|
return success(null, null, null);
|
|
11521
11767
|
};
|
|
11522
|
-
const swept = dryRun ? sweep() : this.withLock(
|
|
11768
|
+
const swept = dryRun ? sweep() : this.withLock(path10.join(dirs.dir, "gc.lock"), sweep);
|
|
11523
11769
|
if (!swept.ok)
|
|
11524
11770
|
return swept;
|
|
11525
11771
|
const temporaryDirs = [
|
|
@@ -11527,7 +11773,7 @@ class TaskStore {
|
|
|
11527
11773
|
dirs.tasks,
|
|
11528
11774
|
dirs.blobs,
|
|
11529
11775
|
dirs.checkout,
|
|
11530
|
-
...names.map((name) =>
|
|
11776
|
+
...names.map((name) => path10.join(dirs.tasks, name))
|
|
11531
11777
|
];
|
|
11532
11778
|
for (const directory of temporaryDirs) {
|
|
11533
11779
|
if (!fs9.existsSync(directory))
|
|
@@ -11535,7 +11781,7 @@ class TaskStore {
|
|
|
11535
11781
|
for (const name of fs9.readdirSync(directory)) {
|
|
11536
11782
|
if (!name.endsWith(".tmp") && !name.endsWith(".probe"))
|
|
11537
11783
|
continue;
|
|
11538
|
-
const file =
|
|
11784
|
+
const file = path10.join(directory, name);
|
|
11539
11785
|
try {
|
|
11540
11786
|
const stat = fs9.lstatSync(file);
|
|
11541
11787
|
if (!stat.isFile() || nowMs - stat.mtimeMs <= STALE_TEMPORARY_MS)
|
|
@@ -11552,30 +11798,30 @@ class TaskStore {
|
|
|
11552
11798
|
}
|
|
11553
11799
|
paths() {
|
|
11554
11800
|
const location = this.location();
|
|
11555
|
-
const dir = location.ok ? location.data.dir :
|
|
11556
|
-
const checkout =
|
|
11801
|
+
const dir = location.ok ? location.data.dir : path10.join(this.root, ".workit");
|
|
11802
|
+
const checkout = path10.join(dir, "checkouts", checkoutSlug(this.root));
|
|
11557
11803
|
return {
|
|
11558
11804
|
dir,
|
|
11559
11805
|
shared: location.ok ? location.data.shared : false,
|
|
11560
|
-
marker:
|
|
11806
|
+
marker: path10.join(dir, "store.json"),
|
|
11561
11807
|
checkout,
|
|
11562
|
-
workspace:
|
|
11563
|
-
checkoutLock:
|
|
11564
|
-
tasks:
|
|
11565
|
-
index:
|
|
11566
|
-
blobs:
|
|
11567
|
-
legacy:
|
|
11568
|
-
v2:
|
|
11808
|
+
workspace: path10.join(checkout, "workspace.json"),
|
|
11809
|
+
checkoutLock: path10.join(checkout, "metadata.lock"),
|
|
11810
|
+
tasks: path10.join(dir, "tasks"),
|
|
11811
|
+
index: path10.join(dir, "task-index.json"),
|
|
11812
|
+
blobs: path10.join(dir, "blobs", "candidates"),
|
|
11813
|
+
legacy: path10.join(dir, "legacy", checkoutSlug(this.root), "v2"),
|
|
11814
|
+
v2: path10.join(this.root, ".workit")
|
|
11569
11815
|
};
|
|
11570
11816
|
}
|
|
11571
11817
|
eventsPath(taskId) {
|
|
11572
|
-
return
|
|
11818
|
+
return path10.join(this.paths().tasks, taskId, "events.jsonl");
|
|
11573
11819
|
}
|
|
11574
11820
|
snapshotPath(taskId) {
|
|
11575
|
-
return
|
|
11821
|
+
return path10.join(this.paths().tasks, taskId, "snapshot.json");
|
|
11576
11822
|
}
|
|
11577
11823
|
taskLockPath(taskId) {
|
|
11578
|
-
return
|
|
11824
|
+
return path10.join(this.paths().tasks, taskId, "lock");
|
|
11579
11825
|
}
|
|
11580
11826
|
ready(write = false) {
|
|
11581
11827
|
const location = this.location();
|
|
@@ -11614,13 +11860,13 @@ class TaskStore {
|
|
|
11614
11860
|
return {
|
|
11615
11861
|
read: (digest) => {
|
|
11616
11862
|
try {
|
|
11617
|
-
return JSON.parse(fs9.readFileSync(
|
|
11863
|
+
return JSON.parse(fs9.readFileSync(path10.join(dir, `${digest}.json`), "utf8"));
|
|
11618
11864
|
} catch (error) {
|
|
11619
11865
|
throw new LogDamage(`stored candidate ${digest} is missing or unreadable: ${String(error)}`);
|
|
11620
11866
|
}
|
|
11621
11867
|
},
|
|
11622
11868
|
write: (digest, value) => {
|
|
11623
|
-
const file =
|
|
11869
|
+
const file = path10.join(dir, `${digest}.json`);
|
|
11624
11870
|
if (fs9.existsSync(file)) {
|
|
11625
11871
|
const stamp = new Date;
|
|
11626
11872
|
try {
|
|
@@ -11812,7 +12058,7 @@ class TaskStore {
|
|
|
11812
12058
|
}
|
|
11813
12059
|
}
|
|
11814
12060
|
openTask(record, type, key, legacy = null) {
|
|
11815
|
-
const dir =
|
|
12061
|
+
const dir = path10.join(this.paths().tasks, record.id);
|
|
11816
12062
|
fs9.mkdirSync(dir, { recursive: true });
|
|
11817
12063
|
const blobs = this.blobStore();
|
|
11818
12064
|
const bound = key ? { ...key, boundAt: key.boundAt ?? new Date().toISOString() } : null;
|
|
@@ -11905,7 +12151,7 @@ class TaskStore {
|
|
|
11905
12151
|
}
|
|
11906
12152
|
withKeyLock(key, operation) {
|
|
11907
12153
|
const digest = createHash5("sha256").update(key).digest("hex").slice(0, 32);
|
|
11908
|
-
return this.withLock(
|
|
12154
|
+
return this.withLock(path10.join(this.paths().dir, "keys", `${digest}.lock`), operation);
|
|
11909
12155
|
}
|
|
11910
12156
|
bindLocked(taskId, key, timestamp) {
|
|
11911
12157
|
const current = this.readWorkspace();
|
|
@@ -12046,7 +12292,7 @@ class TaskStore {
|
|
|
12046
12292
|
writeWorkspace(record) {
|
|
12047
12293
|
const file = this.paths().workspace;
|
|
12048
12294
|
try {
|
|
12049
|
-
fs9.mkdirSync(
|
|
12295
|
+
fs9.mkdirSync(path10.dirname(file), { recursive: true });
|
|
12050
12296
|
replaceFile(file, `${canonicalJson(record)}
|
|
12051
12297
|
`, true);
|
|
12052
12298
|
return success(null, null, null);
|
|
@@ -12124,23 +12370,23 @@ class TaskStore {
|
|
|
12124
12370
|
return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", { expectedWorkspaceRevision: expected, actualWorkspaceRevision: actual });
|
|
12125
12371
|
}
|
|
12126
12372
|
v2Dirs() {
|
|
12127
|
-
return [...new Set([this.root, this.origin])].map((dir) =>
|
|
12373
|
+
return [...new Set([this.root, this.origin])].map((dir) => path10.join(dir, ".workit"));
|
|
12128
12374
|
}
|
|
12129
12375
|
pendingMigrations() {
|
|
12130
12376
|
return this.v2Dirs().filter((dir) => {
|
|
12131
|
-
const raw = this.readV2Workspace(
|
|
12377
|
+
const raw = this.readV2Workspace(path10.join(dir, "workspace.json"));
|
|
12132
12378
|
return raw !== null && raw !== TOMBSTONE;
|
|
12133
12379
|
});
|
|
12134
12380
|
}
|
|
12135
12381
|
migrateV2(v2) {
|
|
12136
12382
|
const dirs = this.paths();
|
|
12137
|
-
const v2Workspace =
|
|
12138
|
-
const v2Tasks =
|
|
12139
|
-
const legacy =
|
|
12383
|
+
const v2Workspace = path10.join(v2, "workspace.json");
|
|
12384
|
+
const v2Tasks = path10.join(v2, "tasks");
|
|
12385
|
+
const legacy = path10.join(dirs.dir, "legacy", checkoutSlug(path10.dirname(v2)), "v2");
|
|
12140
12386
|
const raw = this.readV2Workspace(v2Workspace);
|
|
12141
12387
|
if (raw === null || raw === TOMBSTONE)
|
|
12142
12388
|
return success(null, null, null);
|
|
12143
|
-
return this.withLock(dirs.checkoutLock, () => this.withLock(
|
|
12389
|
+
return this.withLock(dirs.checkoutLock, () => this.withLock(path10.join(v2, "metadata.lock"), () => {
|
|
12144
12390
|
const workspace = this.readV2Workspace(v2Workspace);
|
|
12145
12391
|
if (workspace === null || workspace === TOMBSTONE)
|
|
12146
12392
|
return success(null, null, null);
|
|
@@ -12149,7 +12395,7 @@ class TaskStore {
|
|
|
12149
12395
|
return failure2("recovery_required", `cannot migrate the 2.x store at ${v2}: ${parsedWorkspace.error}; move it aside to start fresh`, { path: v2Workspace });
|
|
12150
12396
|
let files = [];
|
|
12151
12397
|
try {
|
|
12152
|
-
files = fs9.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(
|
|
12398
|
+
files = fs9.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path10.join(v2Tasks, name)));
|
|
12153
12399
|
} catch {}
|
|
12154
12400
|
const current = this.readWorkspace();
|
|
12155
12401
|
if (!current.ok)
|
|
@@ -12167,21 +12413,21 @@ class TaskStore {
|
|
|
12167
12413
|
let skipped = 0;
|
|
12168
12414
|
const done = new Map;
|
|
12169
12415
|
try {
|
|
12170
|
-
fs9.mkdirSync(
|
|
12416
|
+
fs9.mkdirSync(path10.join(legacy, "tasks"), { recursive: true });
|
|
12171
12417
|
for (const name of ["workspace.json", "index.json"])
|
|
12172
|
-
if (fs9.existsSync(
|
|
12173
|
-
fs9.copyFileSync(
|
|
12418
|
+
if (fs9.existsSync(path10.join(v2, name)))
|
|
12419
|
+
fs9.copyFileSync(path10.join(v2, name), path10.join(legacy, name));
|
|
12174
12420
|
for (const name of files) {
|
|
12175
12421
|
const id = name.slice(0, -5);
|
|
12176
|
-
const file =
|
|
12422
|
+
const file = path10.join(v2Tasks, name);
|
|
12177
12423
|
const bytes = fs9.readFileSync(file, "utf8");
|
|
12178
12424
|
const digest = sha256(bytes);
|
|
12179
|
-
fs9.writeFileSync(
|
|
12425
|
+
fs9.writeFileSync(path10.join(legacy, "tasks", name), bytes);
|
|
12180
12426
|
const parsed = this.parseRecord(bytes, taskRecordSchema, "2.x task");
|
|
12181
12427
|
if (!parsed.ok || parsed.data.id !== id)
|
|
12182
12428
|
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 });
|
|
12183
12429
|
const record = { ...parsed.data, workspaceId: target.id };
|
|
12184
|
-
const origin = { path:
|
|
12430
|
+
const origin = { path: path10.join(legacy, "tasks", name), digest };
|
|
12185
12431
|
if (!fs9.existsSync(this.eventsPath(id))) {
|
|
12186
12432
|
this.openTask(record, "migrated.from_v2", null, origin);
|
|
12187
12433
|
migrated += 1;
|
|
@@ -12217,7 +12463,7 @@ class TaskStore {
|
|
|
12217
12463
|
try {
|
|
12218
12464
|
let complete = true;
|
|
12219
12465
|
for (const [name, digest] of done) {
|
|
12220
|
-
const file =
|
|
12466
|
+
const file = path10.join(v2Tasks, name);
|
|
12221
12467
|
if (sha256(fs9.readFileSync(file, "utf8")) !== digest) {
|
|
12222
12468
|
complete = false;
|
|
12223
12469
|
continue;
|
|
@@ -12228,7 +12474,7 @@ class TaskStore {
|
|
|
12228
12474
|
return failure2("busy", `the 2.x store at ${v2} changed during migration; retry`, {
|
|
12229
12475
|
path: v2
|
|
12230
12476
|
});
|
|
12231
|
-
fs9.rmSync(
|
|
12477
|
+
fs9.rmSync(path10.join(v2, "index.json"), { force: true });
|
|
12232
12478
|
this.writeTombstone(v2, target.id);
|
|
12233
12479
|
} catch (error) {
|
|
12234
12480
|
return failure2("storage_error", `cannot finish the 2.x migration: ${String(error)}`, {
|
|
@@ -12248,7 +12494,7 @@ class TaskStore {
|
|
|
12248
12494
|
}
|
|
12249
12495
|
adoptLocalStore() {
|
|
12250
12496
|
const dirs = this.paths();
|
|
12251
|
-
const marker =
|
|
12497
|
+
const marker = path10.join(dirs.v2, "store.json");
|
|
12252
12498
|
if (!dirs.shared || !fs9.existsSync(marker))
|
|
12253
12499
|
return success(null, null, null);
|
|
12254
12500
|
return this.withLock(dirs.checkoutLock, () => {
|
|
@@ -12258,7 +12504,7 @@ class TaskStore {
|
|
|
12258
12504
|
try {
|
|
12259
12505
|
const merge = (from, to) => {
|
|
12260
12506
|
if (!fs9.existsSync(to)) {
|
|
12261
|
-
fs9.mkdirSync(
|
|
12507
|
+
fs9.mkdirSync(path10.dirname(to), { recursive: true });
|
|
12262
12508
|
try {
|
|
12263
12509
|
fs9.renameSync(from, to);
|
|
12264
12510
|
} catch {
|
|
@@ -12269,24 +12515,24 @@ class TaskStore {
|
|
|
12269
12515
|
}
|
|
12270
12516
|
if (fs9.lstatSync(from).isDirectory() && fs9.lstatSync(to).isDirectory())
|
|
12271
12517
|
for (const name of fs9.readdirSync(from))
|
|
12272
|
-
merge(
|
|
12518
|
+
merge(path10.join(from, name), path10.join(to, name));
|
|
12273
12519
|
};
|
|
12274
12520
|
for (const sub of ["tasks", "checkouts", "blobs", "legacy"]) {
|
|
12275
|
-
const from =
|
|
12521
|
+
const from = path10.join(dirs.v2, sub);
|
|
12276
12522
|
if (!fs9.existsSync(from))
|
|
12277
12523
|
continue;
|
|
12278
12524
|
if (sub === "tasks") {
|
|
12279
12525
|
for (const name of fs9.readdirSync(from))
|
|
12280
|
-
if (validId(name) && !fs9.existsSync(
|
|
12526
|
+
if (validId(name) && !fs9.existsSync(path10.join(dirs.dir, sub, name)))
|
|
12281
12527
|
tasks += 1;
|
|
12282
12528
|
}
|
|
12283
|
-
merge(from,
|
|
12529
|
+
merge(from, path10.join(dirs.dir, sub));
|
|
12284
12530
|
}
|
|
12285
|
-
const ledger =
|
|
12286
|
-
if (fs9.existsSync(ledger) && !fs9.existsSync(
|
|
12287
|
-
merge(ledger,
|
|
12288
|
-
fs9.rmSync(
|
|
12289
|
-
fs9.renameSync(marker,
|
|
12531
|
+
const ledger = path10.join(dirs.v2, "ledger");
|
|
12532
|
+
if (fs9.existsSync(ledger) && !fs9.existsSync(path10.join(dirs.dir, "ledger")))
|
|
12533
|
+
merge(ledger, path10.join(dirs.dir, "ledger"));
|
|
12534
|
+
fs9.rmSync(path10.join(dirs.v2, "task-index.json"), { force: true });
|
|
12535
|
+
fs9.renameSync(marker, path10.join(dirs.v2, "store.moved.json"));
|
|
12290
12536
|
} catch (error) {
|
|
12291
12537
|
return failure2("storage_error", `cannot move ${dirs.v2} into ${dirs.dir}: ${String(error)}`, {
|
|
12292
12538
|
path: dirs.v2
|
|
@@ -12324,7 +12570,7 @@ class TaskStore {
|
|
|
12324
12570
|
schemaVersion: SCHEMA_VERSION,
|
|
12325
12571
|
id: workspaceId ?? newId(),
|
|
12326
12572
|
revision: newRevision(),
|
|
12327
|
-
root:
|
|
12573
|
+
root: path10.dirname(v2),
|
|
12328
12574
|
runtime: { createdWith: version, updatedWith: version },
|
|
12329
12575
|
writer: null,
|
|
12330
12576
|
store: {
|
|
@@ -12336,11 +12582,11 @@ class TaskStore {
|
|
|
12336
12582
|
critical: ["store"]
|
|
12337
12583
|
};
|
|
12338
12584
|
fs9.mkdirSync(v2, { recursive: true });
|
|
12339
|
-
const ignore =
|
|
12585
|
+
const ignore = path10.join(v2, ".gitignore");
|
|
12340
12586
|
if (!fs9.existsSync(ignore))
|
|
12341
12587
|
fs9.writeFileSync(ignore, `*
|
|
12342
12588
|
`);
|
|
12343
|
-
replaceFile(
|
|
12589
|
+
replaceFile(path10.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
|
|
12344
12590
|
`, true);
|
|
12345
12591
|
}
|
|
12346
12592
|
stubFor(taskId) {
|
|
@@ -12364,8 +12610,8 @@ class TaskStore {
|
|
|
12364
12610
|
}
|
|
12365
12611
|
writeTombstoneIfMissing() {
|
|
12366
12612
|
try {
|
|
12367
|
-
const v2 =
|
|
12368
|
-
if (fs9.existsSync(
|
|
12613
|
+
const v2 = path10.join(this.root, ".workit");
|
|
12614
|
+
if (fs9.existsSync(path10.join(v2, "workspace.json")))
|
|
12369
12615
|
return;
|
|
12370
12616
|
let id = null;
|
|
12371
12617
|
try {
|
|
@@ -12382,7 +12628,7 @@ class TaskStore {
|
|
|
12382
12628
|
replaceFile(dirs.marker, `${JSON.stringify({ format: "workit-store", version: STORE_FORMAT, createdWith: runtimeVersion() })}
|
|
12383
12629
|
`, false);
|
|
12384
12630
|
if (!dirs.shared) {
|
|
12385
|
-
const ignore =
|
|
12631
|
+
const ignore = path10.join(dirs.dir, ".gitignore");
|
|
12386
12632
|
let current = null;
|
|
12387
12633
|
try {
|
|
12388
12634
|
current = fs9.readFileSync(ignore, "utf8");
|
|
@@ -12442,7 +12688,7 @@ class TaskStore {
|
|
|
12442
12688
|
withLock(lockPath, operation) {
|
|
12443
12689
|
try {
|
|
12444
12690
|
this.initializeStorage();
|
|
12445
|
-
fs9.mkdirSync(
|
|
12691
|
+
fs9.mkdirSync(path10.dirname(lockPath), { recursive: true });
|
|
12446
12692
|
} catch (error) {
|
|
12447
12693
|
return failure2("storage_error", `unable to initialize store: ${String(error)}`, {
|
|
12448
12694
|
path: this.paths().dir
|
|
@@ -12505,7 +12751,7 @@ class TaskStore {
|
|
|
12505
12751
|
if (isTransientWindowsError(error) && !this.lockHolderPresent(lockPath) && !this.lockDirWritable(lockPath))
|
|
12506
12752
|
return failure2("storage_error", `cannot create the workit lock (${code}); no other Workit call holds it`, {
|
|
12507
12753
|
path: lockPath,
|
|
12508
|
-
guidance: `Check permissions and the read-only attribute on ${
|
|
12754
|
+
guidance: `Check permissions and the read-only attribute on ${path10.dirname(lockPath)}.`
|
|
12509
12755
|
});
|
|
12510
12756
|
if (code === "EEXIST" || code === "file_lock_timeout" || code === "file_lock_stale" || isTransientWindowsError(error)) {
|
|
12511
12757
|
let lock = null;
|
|
@@ -12563,7 +12809,7 @@ var MIGRATION_PENDING = "workit migration pending", STORE_FORMAT = 3, STORE_MIN_
|
|
|
12563
12809
|
}, 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 = () => {
|
|
12564
12810
|
if (cachedRuntimeVersion === null) {
|
|
12565
12811
|
try {
|
|
12566
|
-
const pkg = JSON.parse(fs9.readFileSync(
|
|
12812
|
+
const pkg = JSON.parse(fs9.readFileSync(path10.join(packageRoot(), "package.json"), "utf8"));
|
|
12567
12813
|
cachedRuntimeVersion = typeof pkg.version === "string" && pkg.version ? pkg.version : "0.0.0";
|
|
12568
12814
|
} catch {
|
|
12569
12815
|
cachedRuntimeVersion = "0.0.0";
|
|
@@ -12590,7 +12836,7 @@ var MIGRATION_PENDING = "workit migration pending", STORE_FORMAT = 3, STORE_MIN_
|
|
|
12590
12836
|
return "";
|
|
12591
12837
|
}
|
|
12592
12838
|
}, REFLOG_LINE, branchStart = (location, branch, aliases) => {
|
|
12593
|
-
const first = readText(
|
|
12839
|
+
const first = readText(path10.join(path10.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
|
|
12594
12840
|
`, 1)[0];
|
|
12595
12841
|
const created = REFLOG_LINE.exec(first);
|
|
12596
12842
|
const start = created && /^branch: Created from (\S+)$/u.exec(created[3])?.[1];
|
|
@@ -12600,7 +12846,7 @@ var MIGRATION_PENDING = "workit migration pending", STORE_FORMAT = 3, STORE_MIN_
|
|
|
12600
12846
|
return start;
|
|
12601
12847
|
if (!location.git)
|
|
12602
12848
|
return null;
|
|
12603
|
-
for (const line of readText(
|
|
12849
|
+
for (const line of readText(path10.join(location.git.gitDir, "logs", "HEAD")).split(`
|
|
12604
12850
|
`)) {
|
|
12605
12851
|
const entry = REFLOG_LINE.exec(line);
|
|
12606
12852
|
const moved = entry && /^checkout: moving from (\S+) to (\S+)$/u.exec(entry[3]);
|
|
@@ -12609,12 +12855,12 @@ var MIGRATION_PENDING = "workit migration pending", STORE_FORMAT = 3, STORE_MIN_
|
|
|
12609
12855
|
return moved[1];
|
|
12610
12856
|
}
|
|
12611
12857
|
return null;
|
|
12612
|
-
}, refExists = (common, ref) => fs9.existsSync(
|
|
12858
|
+
}, refExists = (common, ref) => fs9.existsSync(path10.join(common, ref)) || readText(path10.join(common, "packed-refs")).includes(` ${ref}
|
|
12613
12859
|
`), origins, sameDirectoryIdentity = (left, right) => {
|
|
12614
|
-
if (!
|
|
12860
|
+
if (!path10.isAbsolute(left) || !path10.isAbsolute(right))
|
|
12615
12861
|
return false;
|
|
12616
|
-
const normalizedLeft =
|
|
12617
|
-
const normalizedRight =
|
|
12862
|
+
const normalizedLeft = path10.resolve(left);
|
|
12863
|
+
const normalizedRight = path10.resolve(right);
|
|
12618
12864
|
try {
|
|
12619
12865
|
const a = fs9.statSync(normalizedLeft, { bigint: true });
|
|
12620
12866
|
const b = fs9.statSync(normalizedRight, { bigint: true });
|
|
@@ -12673,8 +12919,8 @@ var init_workers = __esm(() => {
|
|
|
12673
12919
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
12674
12920
|
import { createHash as createHash6 } from "node:crypto";
|
|
12675
12921
|
import fs10 from "node:fs";
|
|
12676
|
-
import
|
|
12677
|
-
import
|
|
12922
|
+
import os2 from "node:os";
|
|
12923
|
+
import path11 from "node:path";
|
|
12678
12924
|
function networkGitInvocation(cwd, args, timeoutMs) {
|
|
12679
12925
|
const seconds = Math.max(1, Math.ceil(timeoutMs / 1000));
|
|
12680
12926
|
const env = {
|
|
@@ -12732,9 +12978,9 @@ function worktreeTree(cwd, options = {}) {
|
|
|
12732
12978
|
return null;
|
|
12733
12979
|
const cap = options.maxUntrackedBytes ?? MAX_UNTRACKED_BYTES;
|
|
12734
12980
|
const timeoutMs = options.timeoutMs ?? GIT_TIMEOUTS.worktree;
|
|
12735
|
-
const scratch = fs10.mkdtempSync(
|
|
12981
|
+
const scratch = fs10.mkdtempSync(path11.join(os2.tmpdir(), "workit-tree-"));
|
|
12736
12982
|
try {
|
|
12737
|
-
const tempIndex =
|
|
12983
|
+
const tempIndex = path11.join(scratch, "index");
|
|
12738
12984
|
if (fs10.existsSync(indexPath))
|
|
12739
12985
|
seedIndex(indexPath, tempIndex);
|
|
12740
12986
|
const env = { ...process.env, GIT_INDEX_FILE: tempIndex };
|
|
@@ -12747,7 +12993,7 @@ function worktreeTree(cwd, options = {}) {
|
|
|
12747
12993
|
const skipped = [];
|
|
12748
12994
|
for (const file of untracked.stdout.split("\x00").filter(Boolean)) {
|
|
12749
12995
|
try {
|
|
12750
|
-
const stat = fs10.statSync(
|
|
12996
|
+
const stat = fs10.statSync(path11.join(top, file));
|
|
12751
12997
|
if (stat.isFile() && stat.size > cap)
|
|
12752
12998
|
skipped.push({ path: file, size: stat.size, mtimeMs: Math.trunc(stat.mtimeMs) });
|
|
12753
12999
|
} catch {}
|
|
@@ -12793,7 +13039,7 @@ function worktreeSignal(cwd, options = {}) {
|
|
|
12793
13039
|
if (entry.length < 4)
|
|
12794
13040
|
continue;
|
|
12795
13041
|
const file = entry.slice(3);
|
|
12796
|
-
const absolute =
|
|
13042
|
+
const absolute = path11.join(top, file);
|
|
12797
13043
|
let stat = "-";
|
|
12798
13044
|
try {
|
|
12799
13045
|
const info = fs10.lstatSync(absolute, { bigint: true });
|
|
@@ -12972,15 +13218,15 @@ function parseRemoteUrl(raw) {
|
|
|
12972
13218
|
path: cleanPath(decodeURIComponent(url.pathname))
|
|
12973
13219
|
};
|
|
12974
13220
|
}
|
|
12975
|
-
function readSshConfig(home =
|
|
13221
|
+
function readSshConfig(home = os2.homedir()) {
|
|
12976
13222
|
try {
|
|
12977
|
-
return { text: fs10.readFileSync(
|
|
13223
|
+
return { text: fs10.readFileSync(path11.join(home, ".ssh", "config"), "utf8"), home };
|
|
12978
13224
|
} catch {
|
|
12979
13225
|
return { text: "", home };
|
|
12980
13226
|
}
|
|
12981
13227
|
}
|
|
12982
13228
|
function resolveSshHost(alias, sshConfig) {
|
|
12983
|
-
const source = typeof sshConfig === "string" ? { text: sshConfig, home:
|
|
13229
|
+
const source = typeof sshConfig === "string" ? { text: sshConfig, home: os2.homedir() } : sshConfig;
|
|
12984
13230
|
let hostname = null;
|
|
12985
13231
|
let port = null;
|
|
12986
13232
|
const evaluate = (text, initiallyActive, neverMatch, depth) => {
|
|
@@ -13176,15 +13422,15 @@ child.on("exit", (code) => {
|
|
|
13176
13422
|
return [];
|
|
13177
13423
|
return [{ key: match[1].toLowerCase(), args: tokens(match[2]) }];
|
|
13178
13424
|
}), includeFiles = (spec, home) => {
|
|
13179
|
-
const expanded = spec.startsWith("~") ?
|
|
13180
|
-
const absolute =
|
|
13181
|
-
const dir =
|
|
13182
|
-
const base =
|
|
13425
|
+
const expanded = spec.startsWith("~") ? path11.join(home, spec.slice(1)) : spec;
|
|
13426
|
+
const absolute = path11.isAbsolute(expanded) ? expanded : path11.join(home, ".ssh", expanded);
|
|
13427
|
+
const dir = path11.dirname(absolute);
|
|
13428
|
+
const base = path11.basename(absolute);
|
|
13183
13429
|
if (!/[*?]/u.test(base))
|
|
13184
13430
|
return [absolute];
|
|
13185
13431
|
try {
|
|
13186
13432
|
const pattern = globToRegExp(base);
|
|
13187
|
-
return fs10.readdirSync(dir).filter((name) => pattern.test(name)).toSorted().map((name) =>
|
|
13433
|
+
return fs10.readdirSync(dir).filter((name) => pattern.test(name)).toSorted().map((name) => path11.join(dir, name));
|
|
13188
13434
|
} catch {
|
|
13189
13435
|
return [];
|
|
13190
13436
|
}
|
|
@@ -13229,13 +13475,13 @@ import {
|
|
|
13229
13475
|
copyFileSync as copyFileSync2,
|
|
13230
13476
|
cpSync as cpSync2,
|
|
13231
13477
|
existsSync as existsSync3,
|
|
13232
|
-
mkdirSync as
|
|
13478
|
+
mkdirSync as mkdirSync3,
|
|
13233
13479
|
readFileSync as readFileSync2,
|
|
13234
|
-
readdirSync as
|
|
13480
|
+
readdirSync as readdirSync3,
|
|
13235
13481
|
writeFileSync as writeFileSync2
|
|
13236
13482
|
} from "node:fs";
|
|
13237
|
-
import
|
|
13238
|
-
import
|
|
13483
|
+
import os3 from "node:os";
|
|
13484
|
+
import path12 from "node:path";
|
|
13239
13485
|
var diagnosticLogger, setDiagnosticLogger = (logger) => {
|
|
13240
13486
|
diagnosticLogger = logger;
|
|
13241
13487
|
}, getDiagnosticLogger = () => diagnosticLogger, PRESETS, mergePreset = (preset, input = {}, current = {
|
|
@@ -13247,14 +13493,14 @@ var diagnosticLogger, setDiagnosticLogger = (logger) => {
|
|
|
13247
13493
|
allowed: preset === "custom" ? input.allowed ?? current.branchPolicy.allowed : [...defs.allowed],
|
|
13248
13494
|
protected: preset === "custom" ? input.protectedNames ?? current.branchPolicy.protected : [...defs.protected]
|
|
13249
13495
|
};
|
|
13250
|
-
}, resolveConfigDir = () => process.env.WORKFLOW_TOOLKIT_CONFIG ?? process.env.WORKFLOW_TOOLKIT_CONFIG_DIR ??
|
|
13496
|
+
}, resolveConfigDir = () => process.env.WORKFLOW_TOOLKIT_CONFIG ?? process.env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path12.join(process.env.XDG_CONFIG_HOME || path12.join(os3.homedir(), ".config"), "workit"), migratedDir = null, migrationFailed = false, ensureConfigDir = (dir = resolveConfigDir()) => {
|
|
13251
13497
|
if (migratedDir === dir)
|
|
13252
13498
|
return dir;
|
|
13253
13499
|
if (process.env.WORKFLOW_TOOLKIT_CONFIG || process.env.WORKFLOW_TOOLKIT_CONFIG_DIR) {
|
|
13254
13500
|
migratedDir = dir;
|
|
13255
13501
|
return dir;
|
|
13256
13502
|
}
|
|
13257
|
-
const legacy =
|
|
13503
|
+
const legacy = path12.join(process.env.XDG_CONFIG_HOME || path12.join(os3.homedir(), ".config"), "workflow-toolkit");
|
|
13258
13504
|
if (!existsSync3(legacy)) {
|
|
13259
13505
|
migratedDir = dir;
|
|
13260
13506
|
return dir;
|
|
@@ -13264,11 +13510,11 @@ var diagnosticLogger, setDiagnosticLogger = (logger) => {
|
|
|
13264
13510
|
return dir;
|
|
13265
13511
|
}
|
|
13266
13512
|
migrationFailed = false;
|
|
13267
|
-
|
|
13513
|
+
mkdirSync3(dir, { recursive: true });
|
|
13268
13514
|
diagnosticLogger?.info(EVENT.migration, { from: legacy, to: dir });
|
|
13269
|
-
for (const entry of
|
|
13270
|
-
const src =
|
|
13271
|
-
const dest =
|
|
13515
|
+
for (const entry of readdirSync3(legacy, { withFileTypes: true })) {
|
|
13516
|
+
const src = path12.join(legacy, entry.name);
|
|
13517
|
+
const dest = path12.join(dir, entry.name);
|
|
13272
13518
|
if (existsSync3(dest))
|
|
13273
13519
|
continue;
|
|
13274
13520
|
try {
|
|
@@ -13323,7 +13569,7 @@ var diagnosticLogger, setDiagnosticLogger = (logger) => {
|
|
|
13323
13569
|
unchosenBranchPolicy.add(config);
|
|
13324
13570
|
return { status: "valid", path: file, config };
|
|
13325
13571
|
}, readConfigTyped = (dir) => {
|
|
13326
|
-
const file =
|
|
13572
|
+
const file = path12.join(dir ?? configDir(), "config.json");
|
|
13327
13573
|
return parseConfigResult(readSafe(file), file);
|
|
13328
13574
|
}, readConfig = () => {
|
|
13329
13575
|
const result = readConfigTyped();
|
|
@@ -13335,7 +13581,7 @@ var diagnosticLogger, setDiagnosticLogger = (logger) => {
|
|
|
13335
13581
|
if (result.status === "malformed")
|
|
13336
13582
|
throw new Error(result.error);
|
|
13337
13583
|
return result.config ?? DEFAULTS;
|
|
13338
|
-
}, vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ??
|
|
13584
|
+
}, vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path12.join(configDir(), "vcs.json"), branchGlobPattern = (glob) => new RegExp(`^${glob.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`, "i"), resolveBranchPolicy = (config, workspace, repoPreset) => {
|
|
13339
13585
|
const wp = workspace?.branchPolicy ?? {};
|
|
13340
13586
|
const workspacePreset = Object.hasOwn(PRESETS, wp.preset);
|
|
13341
13587
|
const detected = !workspacePreset && unchosenBranchPolicy.has(config) ? repoPreset?.() ?? null : null;
|
|
@@ -13466,7 +13712,7 @@ var init_branch_policy = __esm(() => {
|
|
|
13466
13712
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
13467
13713
|
import { createHash as createHash7 } from "node:crypto";
|
|
13468
13714
|
import { readFileSync as readFileSync3, realpathSync as realpathSync2 } from "node:fs";
|
|
13469
|
-
import
|
|
13715
|
+
import path13 from "node:path";
|
|
13470
13716
|
function workspaceDefaultTarget(cwd, globalDefault) {
|
|
13471
13717
|
const ws = resolveRuntimeWorkspaceVcs(cwd);
|
|
13472
13718
|
const wp = ws?.branchPolicy ?? {};
|
|
@@ -13511,7 +13757,7 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
13511
13757
|
document: parsed
|
|
13512
13758
|
};
|
|
13513
13759
|
}, readWorkspacesResult = (dir = configDir()) => {
|
|
13514
|
-
const file =
|
|
13760
|
+
const file = path13.join(dir, "workspaces.json");
|
|
13515
13761
|
let raw;
|
|
13516
13762
|
try {
|
|
13517
13763
|
raw = readFileSync3(file, "utf8");
|
|
@@ -13611,9 +13857,9 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
13611
13857
|
let main = null;
|
|
13612
13858
|
const dirs = git(["rev-parse", "--path-format=absolute", "--git-dir", "--git-common-dir"]);
|
|
13613
13859
|
const [gitDir, common] = (dirs ?? "").trim().split(/\r?\n/u);
|
|
13614
|
-
if (gitDir && common &&
|
|
13860
|
+
if (gitDir && common && path13.resolve(gitDir) !== path13.resolve(common)) {
|
|
13615
13861
|
const listed = /^worktree (.+)$/mu.exec(git(["worktree", "list", "--porcelain"]) ?? "")?.[1];
|
|
13616
|
-
main = listed?.trim() || (
|
|
13862
|
+
main = listed?.trim() || (path13.basename(common) === ".git" ? path13.dirname(common) : common);
|
|
13617
13863
|
}
|
|
13618
13864
|
mainCheckouts.set(cwd, main);
|
|
13619
13865
|
return main;
|
|
@@ -13691,7 +13937,7 @@ var nonBlank, branchPreset, commitPreset, workspaceBranchPolicySchema, workspace
|
|
|
13691
13937
|
}).passthrough();
|
|
13692
13938
|
return entrySchema;
|
|
13693
13939
|
}, resolveRuntimeWorkspaceVcs = (cwd) => resolveRuntimeWorkspaceCandidate(cwd, "vcs"), runtimeWorkspaceIndexSchema, matchRuntimeWorkspace = (cwd, dir = configDir()) => {
|
|
13694
|
-
const file =
|
|
13940
|
+
const file = path13.join(dir, "workspaces.json");
|
|
13695
13941
|
let raw;
|
|
13696
13942
|
try {
|
|
13697
13943
|
raw = readFileSync3(file, "utf8");
|
|
@@ -13871,7 +14117,7 @@ var init_workspaces = __esm(() => {
|
|
|
13871
14117
|
context.addIssue({ code: "custom", path: [field], message: "entries must be unique" });
|
|
13872
14118
|
}
|
|
13873
14119
|
}
|
|
13874
|
-
if (track.versionSource?.kind === "package-json" && (
|
|
14120
|
+
if (track.versionSource?.kind === "package-json" && (path13.posix.isAbsolute(track.versionSource.path.replaceAll("\\", "/")) || /^[A-Za-z]:\//u.test(track.versionSource.path.replaceAll("\\", "/")) || track.versionSource.path.replaceAll("\\", "/").split("/").includes(".."))) {
|
|
13875
14121
|
context.addIssue({
|
|
13876
14122
|
code: "custom",
|
|
13877
14123
|
path: ["versionSource", "path"],
|
|
@@ -14209,7 +14455,7 @@ function gitTrackProbe(cwd) {
|
|
|
14209
14455
|
const created = own.at(-1);
|
|
14210
14456
|
if (!created || created.subject !== "branch: Created from HEAD")
|
|
14211
14457
|
return null;
|
|
14212
|
-
const pattern = new RegExp(`^checkout: moving from (\\S+) to ${
|
|
14458
|
+
const pattern = new RegExp(`^checkout: moving from (\\S+) to ${escapeRegExp2(branch)}$`, "u");
|
|
14213
14459
|
const entry = reflog(cwd, "HEAD").findLast((item) => item.time >= created.time && item.sha === created.sha && pattern.test(item.subject));
|
|
14214
14460
|
return entry ? pattern.exec(entry.subject)?.[1] ?? null : null;
|
|
14215
14461
|
},
|
|
@@ -14357,7 +14603,7 @@ var ReleaseTrackError, KNOWN_FIELDS, BRANCH_FIELDS, PLACEHOLDER, HAS_PLACEHOLDER
|
|
|
14357
14603
|
return run.status === 0 ? (run.stdout ?? "").trim() : null;
|
|
14358
14604
|
}, recordedBaseKey = (branch) => `branch.${branch}.workitBase`, recordBranchBase = (cwd, branch, base) => {
|
|
14359
14605
|
git3(cwd, ["config", recordedBaseKey(branch), base]);
|
|
14360
|
-
},
|
|
14606
|
+
}, escapeRegExp2 = (text) => text.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&"), reflog = (cwd, ref) => (git3(cwd, ["log", "-g", "--date=unix", "--format=%H%x09%gd%x09%gs", ref, "--"]) ?? "").split(`
|
|
14361
14607
|
`).map((line) => {
|
|
14362
14608
|
const [sha = "", selector = "", ...subject] = line.split("\t");
|
|
14363
14609
|
return {
|
|
@@ -14407,7 +14653,7 @@ var init_release_tracks = __esm(() => {
|
|
|
14407
14653
|
|
|
14408
14654
|
// packages/workit-core/src/core/vcs-config.ts
|
|
14409
14655
|
import fs11 from "node:fs";
|
|
14410
|
-
import
|
|
14656
|
+
import path14 from "node:path";
|
|
14411
14657
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
14412
14658
|
function vcsConfig(mode, cwd, options = {}) {
|
|
14413
14659
|
const ws = resolveRuntimeWorkspaceVcs(vcsCwd(cwd));
|
|
@@ -14470,7 +14716,7 @@ function vcsConfig(mode, cwd, options = {}) {
|
|
|
14470
14716
|
const prov = cfg[provider] ?? {};
|
|
14471
14717
|
const out = {
|
|
14472
14718
|
ok: true,
|
|
14473
|
-
configPath:
|
|
14719
|
+
configPath: path14.resolve(cfgPath),
|
|
14474
14720
|
provider,
|
|
14475
14721
|
defaultTargetBranch: workspaceDefault,
|
|
14476
14722
|
pr: cfg.pr ?? {},
|
|
@@ -14490,7 +14736,7 @@ function vcsConfig(mode, cwd, options = {}) {
|
|
|
14490
14736
|
}
|
|
14491
14737
|
return out;
|
|
14492
14738
|
}
|
|
14493
|
-
var workspacesPath = () =>
|
|
14739
|
+
var workspacesPath = () => path14.join(configDir(), "workspaces.json"), vcsCwd = (cwd) => cwd ?? process.env.WORKFLOW_WORKSPACE_ROOT ?? process.cwd(), remoteProvider = (cwd) => {
|
|
14494
14740
|
const r = spawnSync8("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" });
|
|
14495
14741
|
if (r.status !== 0)
|
|
14496
14742
|
return null;
|
|
@@ -14537,7 +14783,7 @@ var init_vcs_config = __esm(() => {
|
|
|
14537
14783
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
14538
14784
|
import { createHash as createHash9, randomBytes as randomBytes2 } from "node:crypto";
|
|
14539
14785
|
import fs12 from "node:fs";
|
|
14540
|
-
import
|
|
14786
|
+
import path15 from "node:path";
|
|
14541
14787
|
function resolveCommit(cwd, ref) {
|
|
14542
14788
|
if (!safeRef(ref))
|
|
14543
14789
|
return null;
|
|
@@ -14603,14 +14849,14 @@ function diffHash(cwd, base, head) {
|
|
|
14603
14849
|
return `sha256:${hash.digest("hex")}`;
|
|
14604
14850
|
}
|
|
14605
14851
|
function storeRoot(cwd) {
|
|
14606
|
-
const location = resolveStore(
|
|
14852
|
+
const location = resolveStore(path15.resolve(cwd));
|
|
14607
14853
|
if (location instanceof Error)
|
|
14608
14854
|
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");
|
|
14609
14855
|
return { ok: true, value: { root: location.dir, shared: location.shared } };
|
|
14610
14856
|
}
|
|
14611
14857
|
function ledgerPath(cwd) {
|
|
14612
14858
|
const root = storeRoot(cwd);
|
|
14613
|
-
return root.ok ? { ok: true, value:
|
|
14859
|
+
return root.ok ? { ok: true, value: path15.join(root.value.root, "ledger", "ledger.jsonl") } : root;
|
|
14614
14860
|
}
|
|
14615
14861
|
function actorFromEnv(env) {
|
|
14616
14862
|
const value = (key) => {
|
|
@@ -14672,8 +14918,8 @@ function appendLine(file, build, options) {
|
|
|
14672
14918
|
}
|
|
14673
14919
|
};
|
|
14674
14920
|
try {
|
|
14675
|
-
fs12.mkdirSync(
|
|
14676
|
-
if (!options.forceLock && !onNetworkFs(
|
|
14921
|
+
fs12.mkdirSync(path15.dirname(file), { recursive: true });
|
|
14922
|
+
if (!options.forceLock && !onNetworkFs(path15.dirname(file)))
|
|
14677
14923
|
return write();
|
|
14678
14924
|
const locked = withLedgerLock(file, write);
|
|
14679
14925
|
return locked ?? err("busy", `ledger lock ${file}.lock is held`, "retry; remove the .lock directory if no workit process is running");
|
|
@@ -15352,7 +15598,7 @@ function summarizeRow(row) {
|
|
|
15352
15598
|
};
|
|
15353
15599
|
}
|
|
15354
15600
|
function stackPosition(root, branch) {
|
|
15355
|
-
const dir =
|
|
15601
|
+
const dir = path15.join(root, "stacks");
|
|
15356
15602
|
let names = [];
|
|
15357
15603
|
try {
|
|
15358
15604
|
names = fs12.readdirSync(dir).filter((name) => name.endsWith(".json"));
|
|
@@ -15362,7 +15608,7 @@ function stackPosition(root, branch) {
|
|
|
15362
15608
|
for (const name of names.toSorted()) {
|
|
15363
15609
|
let parsed;
|
|
15364
15610
|
try {
|
|
15365
|
-
parsed = JSON.parse(fs12.readFileSync(
|
|
15611
|
+
parsed = JSON.parse(fs12.readFileSync(path15.join(dir, name), "utf8"));
|
|
15366
15612
|
} catch {
|
|
15367
15613
|
continue;
|
|
15368
15614
|
}
|
|
@@ -15507,12 +15753,12 @@ var LEDGER_VERSION = 1, MAX_LINE_BYTES = 4096, VERDICT_RESULTS, PASSING, FAILING
|
|
|
15507
15753
|
}
|
|
15508
15754
|
}, LOCK_WAIT_MS = 5000, LOCK_STALE_MS = 30000, LOCK_OWNER = "owner", lockToken = (lock) => {
|
|
15509
15755
|
try {
|
|
15510
|
-
return fs12.readFileSync(
|
|
15756
|
+
return fs12.readFileSync(path15.join(lock, LOCK_OWNER), "utf8");
|
|
15511
15757
|
} catch {
|
|
15512
15758
|
return null;
|
|
15513
15759
|
}
|
|
15514
15760
|
}, lockAgeMs = (lock) => {
|
|
15515
|
-
for (const target of [
|
|
15761
|
+
for (const target of [path15.join(lock, LOCK_OWNER), lock]) {
|
|
15516
15762
|
try {
|
|
15517
15763
|
return Date.now() - fs12.statSync(target).mtimeMs;
|
|
15518
15764
|
} catch {}
|
|
@@ -15682,7 +15928,7 @@ var init_ledger = __esm(() => {
|
|
|
15682
15928
|
throw error;
|
|
15683
15929
|
}
|
|
15684
15930
|
const token = `${process.pid}-${randomBytes2(8).toString("hex")}`;
|
|
15685
|
-
fs12.writeFileSync(
|
|
15931
|
+
fs12.writeFileSync(path15.join(lock, LOCK_OWNER), token);
|
|
15686
15932
|
return token;
|
|
15687
15933
|
},
|
|
15688
15934
|
release(lock, token) {
|
|
@@ -15735,7 +15981,7 @@ var init_ledger = __esm(() => {
|
|
|
15735
15981
|
|
|
15736
15982
|
// packages/workit-core/src/core/policy/derive.ts
|
|
15737
15983
|
import { existsSync as existsSync4 } from "node:fs";
|
|
15738
|
-
import
|
|
15984
|
+
import path16 from "node:path";
|
|
15739
15985
|
function deriveRequirements(judgment, scope, constraints, verification = "self") {
|
|
15740
15986
|
const out = [];
|
|
15741
15987
|
const base = { scope, dependentAction: null };
|
|
@@ -15876,7 +16122,7 @@ var RULES, derived2 = (spec) => ({
|
|
|
15876
16122
|
decisionIds: []
|
|
15877
16123
|
};
|
|
15878
16124
|
}, planRecorded = (task, root) => {
|
|
15879
|
-
const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(
|
|
16125
|
+
const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(path16.resolve(root, ref.path)));
|
|
15880
16126
|
if (cited)
|
|
15881
16127
|
return {
|
|
15882
16128
|
met: true,
|
|
@@ -15925,7 +16171,7 @@ var init_derive = __esm(() => {
|
|
|
15925
16171
|
import { createHash as createHash10 } from "node:crypto";
|
|
15926
16172
|
import * as fs13 from "node:fs";
|
|
15927
16173
|
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
15928
|
-
import
|
|
16174
|
+
import path17 from "node:path";
|
|
15929
16175
|
function captureCandidate(root, scope, environment = []) {
|
|
15930
16176
|
let checkout;
|
|
15931
16177
|
try {
|
|
@@ -15967,7 +16213,7 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
15967
16213
|
for (const item of [...names].toSorted()) {
|
|
15968
16214
|
if (!scopeMatches(item, normalizedScope))
|
|
15969
16215
|
continue;
|
|
15970
|
-
const target =
|
|
16216
|
+
const target = path17.join(checkout, item);
|
|
15971
16217
|
try {
|
|
15972
16218
|
const stat = fs13.lstatSync(target);
|
|
15973
16219
|
if (stat.isSymbolicLink()) {
|
|
@@ -16340,12 +16586,12 @@ function evaluateClosure(requestedOutcome, view) {
|
|
|
16340
16586
|
requirementIds: evaluations.map((item) => item.requirementId)
|
|
16341
16587
|
});
|
|
16342
16588
|
}
|
|
16343
|
-
var digestBytes = (value) => createHash10("sha256").update(value).digest("hex"), inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${
|
|
16589
|
+
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) => {
|
|
16344
16590
|
if (typeof value !== "string" || !value)
|
|
16345
16591
|
return null;
|
|
16346
16592
|
if (value.includes("\\") || value.split("/").includes(".."))
|
|
16347
16593
|
return null;
|
|
16348
|
-
const normalized =
|
|
16594
|
+
const normalized = path17.posix.normalize(value);
|
|
16349
16595
|
if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
|
|
16350
16596
|
return null;
|
|
16351
16597
|
return normalized === "." ? "." : normalized.replace(/\/$/, "");
|
|
@@ -16387,14 +16633,14 @@ var digestBytes = (value) => createHash10("sha256").update(value).digest("hex"),
|
|
|
16387
16633
|
git: !/not a git repository/i.test(stderr)
|
|
16388
16634
|
};
|
|
16389
16635
|
}
|
|
16390
|
-
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(
|
|
16636
|
+
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path17.sep).join("/")) : [];
|
|
16391
16637
|
const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
|
|
16392
16638
|
if (stagedDeleted.status !== 0) {
|
|
16393
16639
|
const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
|
|
16394
16640
|
if (!/not a git repository/i.test(stderr))
|
|
16395
16641
|
return { paths, uncertain: true, git: true };
|
|
16396
16642
|
} else if (stagedDeleted.stdout) {
|
|
16397
|
-
paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(
|
|
16643
|
+
paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path17.sep).join("/")));
|
|
16398
16644
|
}
|
|
16399
16645
|
return { paths: [...new Set(paths)], uncertain: false, git: true };
|
|
16400
16646
|
}, walk = (root, directory, output) => {
|
|
@@ -16408,7 +16654,7 @@ var digestBytes = (value) => createHash10("sha256").update(value).digest("hex"),
|
|
|
16408
16654
|
for (const name of names) {
|
|
16409
16655
|
if (name === ".git" || name === ".workit")
|
|
16410
16656
|
continue;
|
|
16411
|
-
const target =
|
|
16657
|
+
const target = path17.join(directory, name);
|
|
16412
16658
|
let stat;
|
|
16413
16659
|
try {
|
|
16414
16660
|
stat = fs13.lstatSync(target);
|
|
@@ -16425,12 +16671,12 @@ var digestBytes = (value) => createHash10("sha256").update(value).digest("hex"),
|
|
|
16425
16671
|
}, scopeRoots = (root, scope) => {
|
|
16426
16672
|
const roots = [];
|
|
16427
16673
|
for (const item of scope.paths.length ? scope.paths : ["."]) {
|
|
16428
|
-
const target =
|
|
16674
|
+
const target = path17.resolve(root, item);
|
|
16429
16675
|
if (!inside(root, target))
|
|
16430
16676
|
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` }] });
|
|
16431
16677
|
let ancestor = target;
|
|
16432
16678
|
while (!fs13.existsSync(ancestor) && ancestor !== root)
|
|
16433
|
-
ancestor =
|
|
16679
|
+
ancestor = path17.dirname(ancestor);
|
|
16434
16680
|
try {
|
|
16435
16681
|
if (!inside(root, fs13.realpathSync(ancestor)))
|
|
16436
16682
|
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` }] });
|
|
@@ -16494,23 +16740,23 @@ var digestBytes = (value) => createHash10("sha256").update(value).digest("hex"),
|
|
|
16494
16740
|
continue;
|
|
16495
16741
|
if (!reference.digest)
|
|
16496
16742
|
return failure2("invalid_input", "document references require a byte digest");
|
|
16497
|
-
const target =
|
|
16498
|
-
if (target !== root && !target.startsWith(`${root}${
|
|
16743
|
+
const target = path17.resolve(root, reference.path);
|
|
16744
|
+
if (target !== root && !target.startsWith(`${root}${path17.sep}`))
|
|
16499
16745
|
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
16500
16746
|
fields: [
|
|
16501
16747
|
{ path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
|
|
16502
16748
|
]
|
|
16503
16749
|
});
|
|
16504
16750
|
try {
|
|
16505
|
-
const below =
|
|
16751
|
+
const below = path17.relative(root, target);
|
|
16506
16752
|
let current = root;
|
|
16507
|
-
for (const segment of below.split(
|
|
16753
|
+
for (const segment of below.split(path17.sep)) {
|
|
16508
16754
|
if (!segment)
|
|
16509
16755
|
continue;
|
|
16510
|
-
current =
|
|
16756
|
+
current = path17.join(current, segment);
|
|
16511
16757
|
const stat = fs13.lstatSync(current);
|
|
16512
16758
|
const real = fs13.realpathSync(current);
|
|
16513
|
-
if (real !== root && !real.startsWith(`${root}${
|
|
16759
|
+
if (real !== root && !real.startsWith(`${root}${path17.sep}`))
|
|
16514
16760
|
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
16515
16761
|
fields: [
|
|
16516
16762
|
{
|
|
@@ -16791,7 +17037,7 @@ var init_git = () => {};
|
|
|
16791
17037
|
// packages/workit-core/src/core/branch.ts
|
|
16792
17038
|
import { execFileSync } from "node:child_process";
|
|
16793
17039
|
import { createHash as createHash11 } from "node:crypto";
|
|
16794
|
-
import
|
|
17040
|
+
import path18 from "node:path";
|
|
16795
17041
|
function effectiveWorkspacePolicy(workspaceRoot, kind, profileName) {
|
|
16796
17042
|
const selected = resolveRuntimeWorkspacePolicy(workspaceRoot, kind, profileName?.trim() || process.env.WORKFLOW_PROFILE?.trim() || undefined);
|
|
16797
17043
|
const config = readConfig();
|
|
@@ -16990,7 +17236,7 @@ var withReleaseTracks = (workspaceRoot, policy) => {
|
|
|
16990
17236
|
let raw;
|
|
16991
17237
|
try {
|
|
16992
17238
|
raw = execFileSync("git", ["status", "--porcelain=v1"], {
|
|
16993
|
-
cwd:
|
|
17239
|
+
cwd: path18.resolve(workspaceRoot),
|
|
16994
17240
|
encoding: "utf8",
|
|
16995
17241
|
stdio: ["pipe", "pipe", "pipe"]
|
|
16996
17242
|
});
|
|
@@ -17228,13 +17474,13 @@ import {
|
|
|
17228
17474
|
fchmodSync,
|
|
17229
17475
|
fsyncSync,
|
|
17230
17476
|
lstatSync as lstatSync3,
|
|
17231
|
-
mkdirSync as
|
|
17477
|
+
mkdirSync as mkdirSync4,
|
|
17232
17478
|
openSync as openSync2,
|
|
17233
17479
|
renameSync as renameSync2,
|
|
17234
|
-
unlinkSync,
|
|
17480
|
+
unlinkSync as unlinkSync2,
|
|
17235
17481
|
writeFileSync as writeFileSync3
|
|
17236
17482
|
} from "node:fs";
|
|
17237
|
-
import
|
|
17483
|
+
import path19 from "node:path";
|
|
17238
17484
|
function writeFileExclusive(file, content, mode) {
|
|
17239
17485
|
try {
|
|
17240
17486
|
writeFileSync3(file, content, { encoding: "utf8", flag: "wx", mode });
|
|
@@ -17246,9 +17492,9 @@ function writeFileExclusive(file, content, mode) {
|
|
|
17246
17492
|
}
|
|
17247
17493
|
}
|
|
17248
17494
|
function writeFileAtomic(file, content, mode) {
|
|
17249
|
-
const absolute =
|
|
17250
|
-
let parent =
|
|
17251
|
-
const root =
|
|
17495
|
+
const absolute = path19.resolve(file);
|
|
17496
|
+
let parent = path19.dirname(absolute);
|
|
17497
|
+
const root = path19.parse(parent).root;
|
|
17252
17498
|
for (;; ) {
|
|
17253
17499
|
try {
|
|
17254
17500
|
if (lstatSync3(parent).isSymbolicLink())
|
|
@@ -17257,13 +17503,13 @@ function writeFileAtomic(file, content, mode) {
|
|
|
17257
17503
|
if (error.code !== "ENOENT")
|
|
17258
17504
|
throw error;
|
|
17259
17505
|
}
|
|
17260
|
-
const next =
|
|
17506
|
+
const next = path19.dirname(parent);
|
|
17261
17507
|
if (parent === root || next === parent)
|
|
17262
17508
|
break;
|
|
17263
17509
|
parent = next;
|
|
17264
17510
|
}
|
|
17265
|
-
const directory =
|
|
17266
|
-
|
|
17511
|
+
const directory = path19.dirname(absolute);
|
|
17512
|
+
mkdirSync4(directory, { recursive: true });
|
|
17267
17513
|
let existing = null;
|
|
17268
17514
|
try {
|
|
17269
17515
|
existing = lstatSync3(absolute);
|
|
@@ -17292,7 +17538,7 @@ function writeFileAtomic(file, content, mode) {
|
|
|
17292
17538
|
} catch {}
|
|
17293
17539
|
}
|
|
17294
17540
|
try {
|
|
17295
|
-
|
|
17541
|
+
unlinkSync2(temporary);
|
|
17296
17542
|
} catch {}
|
|
17297
17543
|
throw error;
|
|
17298
17544
|
}
|
|
@@ -17301,8 +17547,8 @@ var init_safe_write = () => {};
|
|
|
17301
17547
|
|
|
17302
17548
|
// packages/workit-core/src/autonomy.ts
|
|
17303
17549
|
import { copyFileSync as copyFileSync3, existsSync as existsSync6 } from "node:fs";
|
|
17304
|
-
import
|
|
17305
|
-
import
|
|
17550
|
+
import os4 from "node:os";
|
|
17551
|
+
import path20 from "node:path";
|
|
17306
17552
|
function endpointOf(entry) {
|
|
17307
17553
|
const raw = entry?.defaultEndpoint;
|
|
17308
17554
|
if (raw === undefined)
|
|
@@ -17541,13 +17787,13 @@ function listGrants(dir = grantsDir()) {
|
|
|
17541
17787
|
}
|
|
17542
17788
|
var accountHome = () => {
|
|
17543
17789
|
try {
|
|
17544
|
-
return
|
|
17790
|
+
return os4.userInfo().homedir;
|
|
17545
17791
|
} catch {
|
|
17546
|
-
return
|
|
17792
|
+
return os4.homedir();
|
|
17547
17793
|
}
|
|
17548
|
-
}, grantsHome, grantsDir = () =>
|
|
17549
|
-
const configured =
|
|
17550
|
-
return configured ===
|
|
17794
|
+
}, grantsHome, grantsDir = () => path20.join(grantsHome.resolve(), ".config", "workit"), grantsOverride = () => {
|
|
17795
|
+
const configured = path20.resolve(resolveConfigDir());
|
|
17796
|
+
return configured === path20.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 ${path20.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
|
|
17551
17797
|
}, GRANT_KINDS, DEFAULT_GRANTS, DEFAULT_ENDPOINTS, DEFAULT_ENDPOINT = "commit", isDefaultEndpoint = (value) => typeof value === "string" && DEFAULT_ENDPOINTS.includes(value), raisesEndpoint = (current, next) => DEFAULT_ENDPOINTS.indexOf(next) > DEFAULT_ENDPOINTS.indexOf(current), DEFAULT_VERIFICATION = "self", verificationOf = (entry) => entry?.verification === "independent" ? "independent" : "self", isGrantKind = (value) => typeof value === "string" && GRANT_KINDS.includes(value), isGrantValue = (value) => value === true || value === false || value === "verified", normalized = (kind, value) => value === "verified" && kind !== "merge" ? true : value, fromAutoApprove = (value) => {
|
|
17552
17798
|
if (value === true)
|
|
17553
17799
|
return { push: true, pr: true, merge: "verified" };
|
|
@@ -19291,12 +19537,12 @@ var init_pr_body = __esm(() => {
|
|
|
19291
19537
|
});
|
|
19292
19538
|
|
|
19293
19539
|
// packages/workit-core/src/core/pr-create.ts
|
|
19294
|
-
import
|
|
19540
|
+
import path21 from "node:path";
|
|
19295
19541
|
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
19296
19542
|
import { pathToFileURL } from "node:url";
|
|
19297
19543
|
var safePushUrl = (remote) => {
|
|
19298
19544
|
const raw = remote.trim();
|
|
19299
|
-
if (
|
|
19545
|
+
if (path21.isAbsolute(raw))
|
|
19300
19546
|
return pathToFileURL(raw).href;
|
|
19301
19547
|
if (!raw.includes("://")) {
|
|
19302
19548
|
const scp = /^(?:([^@\s]+)@)?([^:]+):(.+)$/u.exec(raw);
|
|
@@ -19357,7 +19603,7 @@ var init_scripts = __esm(() => {
|
|
|
19357
19603
|
|
|
19358
19604
|
// packages/workit-core/src/core/youtrack.ts
|
|
19359
19605
|
import fs14 from "node:fs";
|
|
19360
|
-
import
|
|
19606
|
+
import path22 from "node:path";
|
|
19361
19607
|
function readYouTrackConfig(required) {
|
|
19362
19608
|
const cfgPath = youTrackConfigPath();
|
|
19363
19609
|
if (!fs14.existsSync(cfgPath)) {
|
|
@@ -19381,7 +19627,7 @@ function youTrackConfigLoad() {
|
|
|
19381
19627
|
}
|
|
19382
19628
|
const cfgPath = loaded.path;
|
|
19383
19629
|
const tokenFile = String(loaded.config.tokenFile ?? "");
|
|
19384
|
-
const tokenPath = tokenFile ?
|
|
19630
|
+
const tokenPath = tokenFile ? path22.isAbsolute(tokenFile) ? path22.resolve(tokenFile) : path22.resolve(process.cwd(), tokenFile) : "";
|
|
19385
19631
|
if (!tokenPath || !fs14.existsSync(tokenPath)) {
|
|
19386
19632
|
return { error: "missing youtrack.token" };
|
|
19387
19633
|
}
|
|
@@ -19395,8 +19641,8 @@ function youTrackConfigLoad() {
|
|
|
19395
19641
|
const redacted = { ...loaded.config };
|
|
19396
19642
|
delete redacted.tokenFile;
|
|
19397
19643
|
redacted.tokenPresent = true;
|
|
19398
|
-
redacted.configPath =
|
|
19399
|
-
redacted.tokenPath =
|
|
19644
|
+
redacted.configPath = path22.resolve(cfgPath);
|
|
19645
|
+
redacted.tokenPath = path22.resolve(tokenPath);
|
|
19400
19646
|
return { data: redacted };
|
|
19401
19647
|
}
|
|
19402
19648
|
function tzParts(date, tz) {
|
|
@@ -19719,7 +19965,7 @@ async function postUpdate({
|
|
|
19719
19965
|
}
|
|
19720
19966
|
return { ok: true, issueId, postedComment: true };
|
|
19721
19967
|
}
|
|
19722
|
-
var ISSUE_RE, TOKEN_PLACEHOLDER = "YOUR_TOKEN_HERE", youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ??
|
|
19968
|
+
var ISSUE_RE, TOKEN_PLACEHOLDER = "YOUR_TOKEN_HERE", youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path22.join(configDir(), "youtrack.json"), youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path22.join(resolveConfigDir(), "youtrack.json"), youTrackTokenModeOk = (p) => {
|
|
19723
19969
|
if (process.platform === "win32")
|
|
19724
19970
|
return true;
|
|
19725
19971
|
const mode = fs14.statSync(p).mode & 511;
|
|
@@ -19755,7 +20001,7 @@ var ISSUE_RE, TOKEN_PLACEHOLDER = "YOUR_TOKEN_HERE", youTrackConfigPath = () =>
|
|
|
19755
20001
|
if ("error" in loaded)
|
|
19756
20002
|
return loaded;
|
|
19757
20003
|
const tokenFile = String(loaded.config.tokenFile ?? "");
|
|
19758
|
-
const tokenPath = tokenFile ?
|
|
20004
|
+
const tokenPath = tokenFile ? path22.isAbsolute(tokenFile) ? path22.resolve(tokenFile) : path22.resolve(process.cwd(), tokenFile) : "";
|
|
19759
20005
|
if (!tokenPath || !fs14.existsSync(tokenPath))
|
|
19760
20006
|
return { error: "missing youtrack.token" };
|
|
19761
20007
|
if (!youTrackTokenModeOk(tokenPath))
|
|
@@ -19860,18 +20106,18 @@ var init_context_read = __esm(() => {
|
|
|
19860
20106
|
|
|
19861
20107
|
// packages/workit-core/src/core.ts
|
|
19862
20108
|
import { existsSync as existsSync7, realpathSync as realpathSync5 } from "node:fs";
|
|
19863
|
-
import
|
|
20109
|
+
import path23 from "node:path";
|
|
19864
20110
|
function resolveInside(root, candidate) {
|
|
19865
20111
|
const base = realpathSync5(root);
|
|
19866
|
-
const target =
|
|
19867
|
-
if (target !== base && !target.startsWith(base +
|
|
20112
|
+
const target = path23.resolve(base, candidate);
|
|
20113
|
+
if (target !== base && !target.startsWith(base + path23.sep)) {
|
|
19868
20114
|
throw new Error("path must stay inside repository root");
|
|
19869
20115
|
}
|
|
19870
20116
|
let ancestor = target;
|
|
19871
20117
|
while (!existsSync7(ancestor))
|
|
19872
|
-
ancestor =
|
|
20118
|
+
ancestor = path23.dirname(ancestor);
|
|
19873
20119
|
const canonicalAncestor = realpathSync5(ancestor);
|
|
19874
|
-
if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base +
|
|
20120
|
+
if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path23.sep)) {
|
|
19875
20121
|
throw new Error("path must stay inside repository root");
|
|
19876
20122
|
}
|
|
19877
20123
|
return target;
|
|
@@ -19897,7 +20143,7 @@ var init_core3 = __esm(() => {
|
|
|
19897
20143
|
|
|
19898
20144
|
// packages/workit-cli/src/task.ts
|
|
19899
20145
|
import { readFileSync as readFileSync7 } from "node:fs";
|
|
19900
|
-
import
|
|
20146
|
+
import path24 from "node:path";
|
|
19901
20147
|
async function readInput(input) {
|
|
19902
20148
|
if (typeof input === "string")
|
|
19903
20149
|
return input;
|
|
@@ -20216,7 +20462,7 @@ var TASK_FAMILIES, workspaceRootFor = (deps = {}) => {
|
|
|
20216
20462
|
return explicit;
|
|
20217
20463
|
const cwd = deps.cwd ?? process.cwd();
|
|
20218
20464
|
const top = checkRoot(cwd);
|
|
20219
|
-
return sameDirectoryIdentity(top,
|
|
20465
|
+
return sameDirectoryIdentity(top, path24.resolve(cwd)) ? cwd : top;
|
|
20220
20466
|
}, TASK_ACTIONS, outOf = (deps) => deps.out ?? process.stdout, errOf = (deps) => deps.err ?? process.stderr, write = (stream, value) => stream.write(value.endsWith(`
|
|
20221
20467
|
`) ? value : `${value}
|
|
20222
20468
|
`), jsonResult = (stream, result) => write(stream, JSON.stringify(result)), usage = (message) => failure2("invalid_input", message), parseUsage = (message, json) => ({
|
|
@@ -21506,7 +21752,7 @@ var init_environment = __esm(() => {
|
|
|
21506
21752
|
|
|
21507
21753
|
// node_modules/ansi-escapes/base.js
|
|
21508
21754
|
import process2 from "node:process";
|
|
21509
|
-
import
|
|
21755
|
+
import os5 from "node:os";
|
|
21510
21756
|
var ESC = "\x1B[", SEP = ";", isTerminalApp, isWindows2, isTmux, cwdFunction, cursorTo = (x, y) => {
|
|
21511
21757
|
if (typeof x !== "number") {
|
|
21512
21758
|
throw new TypeError("The `x` argument is required");
|
|
@@ -21528,7 +21774,7 @@ var ESC = "\x1B[", SEP = ";", isTerminalApp, isWindows2, isTmux, cwdFunction, cu
|
|
|
21528
21774
|
if (isBrowser || !isWindows2) {
|
|
21529
21775
|
return false;
|
|
21530
21776
|
}
|
|
21531
|
-
const parts =
|
|
21777
|
+
const parts = os5.release().split(".");
|
|
21532
21778
|
const major = Number(parts[0]);
|
|
21533
21779
|
const build = Number(parts[2] ?? 0);
|
|
21534
21780
|
if (major < 10) {
|
|
@@ -57191,7 +57437,7 @@ var init_ansi_styles2 = __esm(() => {
|
|
|
57191
57437
|
|
|
57192
57438
|
// node_modules/chalk/source/vendor/supports-color/index.js
|
|
57193
57439
|
import process5 from "node:process";
|
|
57194
|
-
import
|
|
57440
|
+
import os6 from "node:os";
|
|
57195
57441
|
import tty2 from "node:tty";
|
|
57196
57442
|
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process5.argv) {
|
|
57197
57443
|
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
@@ -57249,7 +57495,7 @@ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
|
57249
57495
|
return min;
|
|
57250
57496
|
}
|
|
57251
57497
|
if (process5.platform === "win32") {
|
|
57252
|
-
const osRelease =
|
|
57498
|
+
const osRelease = os6.release().split(".");
|
|
57253
57499
|
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
57254
57500
|
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
57255
57501
|
}
|
|
@@ -63078,7 +63324,7 @@ var init_gitignore = __esm(() => {
|
|
|
63078
63324
|
|
|
63079
63325
|
// packages/workit-core/src/core/changelog.ts
|
|
63080
63326
|
import fs17 from "node:fs";
|
|
63081
|
-
import
|
|
63327
|
+
import path25 from "node:path";
|
|
63082
63328
|
import { createHash as createHash13 } from "node:crypto";
|
|
63083
63329
|
function normalizeBullet(text) {
|
|
63084
63330
|
text = text.trim();
|
|
@@ -63238,7 +63484,7 @@ function applyChangelog(target, entries, normalizeOnly) {
|
|
|
63238
63484
|
const rendered = renderChangelog(source.text, entries, normalizeOnly);
|
|
63239
63485
|
if ("error" in rendered)
|
|
63240
63486
|
return { error: rendered.error };
|
|
63241
|
-
fs17.mkdirSync(
|
|
63487
|
+
fs17.mkdirSync(path25.dirname(target), { recursive: true });
|
|
63242
63488
|
fs17.writeFileSync(target, rendered.text, "utf8");
|
|
63243
63489
|
return { ...rendered.result, path: target };
|
|
63244
63490
|
}
|
|
@@ -63381,14 +63627,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
63381
63627
|
}, changelogTarget = (workspaceRoot, changelogPath) => {
|
|
63382
63628
|
try {
|
|
63383
63629
|
const cwd = fs17.realpathSync(resolveWorkspaceRoot(workspaceRoot));
|
|
63384
|
-
const target =
|
|
63385
|
-
if (target !== cwd && !target.startsWith(cwd +
|
|
63630
|
+
const target = path25.resolve(cwd, changelogPath || "CHANGELOG.md");
|
|
63631
|
+
if (target !== cwd && !target.startsWith(cwd + path25.sep))
|
|
63386
63632
|
return { error: "changelog path must be inside workspace_root" };
|
|
63387
63633
|
let ancestor = target;
|
|
63388
63634
|
while (!fs17.existsSync(ancestor))
|
|
63389
|
-
ancestor =
|
|
63635
|
+
ancestor = path25.dirname(ancestor);
|
|
63390
63636
|
const canonicalAncestor = fs17.realpathSync(ancestor);
|
|
63391
|
-
if (canonicalAncestor !== cwd && !canonicalAncestor.startsWith(cwd +
|
|
63637
|
+
if (canonicalAncestor !== cwd && !canonicalAncestor.startsWith(cwd + path25.sep))
|
|
63392
63638
|
return { error: "changelog path must be inside workspace_root" };
|
|
63393
63639
|
return { cwd, target: fs17.existsSync(target) ? fs17.realpathSync(target) : target };
|
|
63394
63640
|
} catch {
|
|
@@ -63407,22 +63653,22 @@ var init_changelog = __esm(() => {
|
|
|
63407
63653
|
|
|
63408
63654
|
// packages/workit-core/src/core/hygiene.ts
|
|
63409
63655
|
import { existsSync as existsSync9, readFileSync as readFileSync9, writeFileSync as writeFileSync4 } from "node:fs";
|
|
63410
|
-
import
|
|
63411
|
-
var repoRoot2, templatesDir = () =>
|
|
63412
|
-
if (!existsSync9(
|
|
63656
|
+
import path26 from "node:path";
|
|
63657
|
+
var repoRoot2, templatesDir = () => path26.join(repoRoot2, "templates", "hygiene"), packageJson = (root) => {
|
|
63658
|
+
if (!existsSync9(path26.join(root, "package.json")))
|
|
63413
63659
|
return null;
|
|
63414
63660
|
try {
|
|
63415
|
-
return JSON.parse(readFileSync9(
|
|
63661
|
+
return JSON.parse(readFileSync9(path26.join(root, "package.json"), "utf8"));
|
|
63416
63662
|
} catch {
|
|
63417
63663
|
return null;
|
|
63418
63664
|
}
|
|
63419
63665
|
}, isOpenSource = (root) => {
|
|
63420
|
-
if (existsSync9(
|
|
63666
|
+
if (existsSync9(path26.join(root, "LICENSE")))
|
|
63421
63667
|
return true;
|
|
63422
63668
|
const pkg = packageJson(root);
|
|
63423
63669
|
if (pkg && !pkg.private)
|
|
63424
63670
|
return true;
|
|
63425
|
-
return
|
|
63671
|
+
return path26.basename(root) === "workflow-toolkit";
|
|
63426
63672
|
}, licenseHolder = (root) => {
|
|
63427
63673
|
const pkg = packageJson(root);
|
|
63428
63674
|
if (pkg) {
|
|
@@ -63443,13 +63689,13 @@ var repoRoot2, templatesDir = () => path25.join(repoRoot2, "templates", "hygiene
|
|
|
63443
63689
|
files.push("LICENSE", "CONTRIBUTING.md");
|
|
63444
63690
|
const planned = [];
|
|
63445
63691
|
for (const file of files) {
|
|
63446
|
-
if (existsSync9(
|
|
63692
|
+
if (existsSync9(path26.join(root, file)))
|
|
63447
63693
|
continue;
|
|
63448
|
-
const tpl =
|
|
63694
|
+
const tpl = path26.join(templatesDir(), file);
|
|
63449
63695
|
if (!existsSync9(tpl))
|
|
63450
63696
|
continue;
|
|
63451
|
-
const content = readFileSync9(tpl, "utf8").replace(/<PROJECT>/g,
|
|
63452
|
-
planned.push({ path:
|
|
63697
|
+
const content = readFileSync9(tpl, "utf8").replace(/<PROJECT>/g, path26.basename(root)).replace(/<YEAR>/g, String(new Date().getFullYear())).replace(/<HOLDER>\s*/g, licenseHolder(root));
|
|
63698
|
+
planned.push({ path: path26.join(root, file), content });
|
|
63453
63699
|
}
|
|
63454
63700
|
return planned;
|
|
63455
63701
|
};
|
|
@@ -63461,9 +63707,9 @@ var init_hygiene = __esm(() => {
|
|
|
63461
63707
|
|
|
63462
63708
|
// packages/workit-cli/src/admin/setup-state.ts
|
|
63463
63709
|
import { existsSync as existsSync10, readFileSync as readFileSync10 } from "node:fs";
|
|
63464
|
-
import
|
|
63710
|
+
import path27 from "node:path";
|
|
63465
63711
|
var classifySetupFile = (dir, name) => {
|
|
63466
|
-
const file =
|
|
63712
|
+
const file = path27.join(dir, name);
|
|
63467
63713
|
let raw;
|
|
63468
63714
|
try {
|
|
63469
63715
|
raw = readFileSync10(file, "utf8");
|
|
@@ -63501,7 +63747,7 @@ var init_setup_state = __esm(() => {
|
|
|
63501
63747
|
});
|
|
63502
63748
|
|
|
63503
63749
|
// packages/workit-cli/src/admin/registration.ts
|
|
63504
|
-
import
|
|
63750
|
+
import path28 from "node:path";
|
|
63505
63751
|
function isWorkitPlugin(value) {
|
|
63506
63752
|
const s = String(value).replaceAll("\\", "/");
|
|
63507
63753
|
const url = s.startsWith("file://") || s.startsWith("git+file://");
|
|
@@ -63534,11 +63780,11 @@ function mergeCursorEnabledPlugins(enabled) {
|
|
|
63534
63780
|
}
|
|
63535
63781
|
function mergeCursorPluginDirs(pluginDirs, pluginDir) {
|
|
63536
63782
|
const strip = (p) => {
|
|
63537
|
-
const j =
|
|
63538
|
-
return
|
|
63783
|
+
const j = path28.join(p);
|
|
63784
|
+
return path28.dirname(j) === j ? j : j.replace(/[\\/]+$/, "");
|
|
63539
63785
|
};
|
|
63540
63786
|
const normalized = strip(pluginDir);
|
|
63541
|
-
const legacy = strip(
|
|
63787
|
+
const legacy = strip(path28.join(path28.dirname(pluginDir), "workflow-toolkit"));
|
|
63542
63788
|
const prev = Array.isArray(pluginDirs) ? pluginDirs.map(String) : [];
|
|
63543
63789
|
const kept = prev.filter((d) => strip(d) !== legacy);
|
|
63544
63790
|
const exists = kept.some((d) => strip(d) === normalized);
|
|
@@ -63626,7 +63872,7 @@ function cursorMcpServerEntry(_packageDir) {
|
|
|
63626
63872
|
function cursorHooksEntry(pluginDir) {
|
|
63627
63873
|
return { command: `${cursorHookLauncher(pluginDir)} workit-cursor-session-start`, args: [] };
|
|
63628
63874
|
}
|
|
63629
|
-
var OPENCODE_NPM_PIN = "@brainervirus/workit-opencode", isRecord4 = (v) => v !== null && typeof v === "object" && !Array.isArray(v), named = (s, name) => s === name || s.startsWith(`${name}@`), CURSOR_RUNTIME_PACKAGE = "@brainervirus/workit-cursor@latest", cursorHookLauncher = (pluginDir) => pluginDir ? `node "${shellQuotedPath(
|
|
63875
|
+
var OPENCODE_NPM_PIN = "@brainervirus/workit-opencode", isRecord4 = (v) => v !== null && typeof v === "object" && !Array.isArray(v), named = (s, name) => s === name || s.startsWith(`${name}@`), CURSOR_RUNTIME_PACKAGE = "@brainervirus/workit-cursor@latest", cursorHookLauncher = (pluginDir) => pluginDir ? `node "${shellQuotedPath(path28.join(pluginDir, "hooks", "launch.mjs"))}"` : 'node "${CURSOR_PLUGIN_ROOT}/hooks/launch.mjs"', shellQuotedPath = (file) => path28.sep === "\\" ? file : file.replace(/([$`"\\])/g, "\\$1"), CURSOR_HOOK_RUN_COMMAND, CURSOR_PRETOOLUSE_MATCHER = "Write|Edit|Delete|Shell|Remove|ApplyPatch|Apply_Patch|Patch|Rename|Mkdir|Mv|Cp|Touch", CURSOR_HOOK_EVENTS, canonicalHookEntry = (event, pluginDir) => {
|
|
63630
63876
|
const command = `${cursorHookLauncher(pluginDir)} workit-cursor-hook`;
|
|
63631
63877
|
if (event === "preToolUse")
|
|
63632
63878
|
return { command, matcher: CURSOR_PRETOOLUSE_MATCHER, failClosed: false };
|
|
@@ -63659,219 +63905,6 @@ var init_support_matrix = __esm(() => {
|
|
|
63659
63905
|
};
|
|
63660
63906
|
});
|
|
63661
63907
|
|
|
63662
|
-
// packages/workit-core/src/core/logger.ts
|
|
63663
|
-
import { appendFileSync, mkdirSync as mkdirSync4, readdirSync as readdirSync4, unlinkSync as unlinkSync2 } from "node:fs";
|
|
63664
|
-
import os6 from "node:os";
|
|
63665
|
-
import path28 from "node:path";
|
|
63666
|
-
var REDACTED = "[REDACTED]", DEFAULT_MAX_RATE = 20, DEFAULT_RATE_WINDOW_MS = 1000, DEFAULT_MAX_FIELD_LENGTH = 200, DEFAULT_MAX_STACK_LINES = 30, DAY_FILE, RETAINED_DAYS = 7, SECRET_VALUE, KEY_EQ_VALUE, URL_QUERY, splitKey = (key) => key.split(/[_-]+|(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/).map((word) => word.toLowerCase()), SENSITIVE_WORDS, STACK_WORDS, escapeRegExp3 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), resolveStateDir = () => {
|
|
63667
|
-
const override = process.env.WORKFLOW_TOOLKIT_STATE;
|
|
63668
|
-
if (override)
|
|
63669
|
-
return override;
|
|
63670
|
-
const home = os6.homedir();
|
|
63671
|
-
if (process.env.XDG_STATE_HOME)
|
|
63672
|
-
return path28.join(process.env.XDG_STATE_HOME, "workit");
|
|
63673
|
-
switch (os6.platform()) {
|
|
63674
|
-
case "darwin":
|
|
63675
|
-
return path28.join(home, "Library", "Application Support", "workit");
|
|
63676
|
-
case "win32":
|
|
63677
|
-
return path28.join(process.env.LOCALAPPDATA ?? path28.join(home, "AppData", "Local"), "workit");
|
|
63678
|
-
default:
|
|
63679
|
-
return path28.join(process.env.HOME ?? home, ".local", "state", "workit");
|
|
63680
|
-
}
|
|
63681
|
-
}, homePattern, applyPatterns = (value) => {
|
|
63682
|
-
let out = value;
|
|
63683
|
-
out = out.replace(SECRET_VALUE, REDACTED);
|
|
63684
|
-
out = out.replace(KEY_EQ_VALUE, "$1$2[REDACTED]");
|
|
63685
|
-
out = out.replace(URL_QUERY, "$1?[REDACTED]");
|
|
63686
|
-
out = out.replace(homePattern, "~");
|
|
63687
|
-
if (process.platform === "win32")
|
|
63688
|
-
out = out.replace(/\\/g, "/");
|
|
63689
|
-
return out;
|
|
63690
|
-
}, redactString = (value, options) => {
|
|
63691
|
-
const out = applyPatterns(value);
|
|
63692
|
-
if (out.length > options.maxFieldLength) {
|
|
63693
|
-
return `${out.slice(0, options.maxFieldLength)}…`;
|
|
63694
|
-
}
|
|
63695
|
-
return out;
|
|
63696
|
-
}, boundStack = (value, options) => {
|
|
63697
|
-
if (typeof value !== "string")
|
|
63698
|
-
return redact(value, options);
|
|
63699
|
-
const lines = value.split(`
|
|
63700
|
-
`);
|
|
63701
|
-
const kept = lines.slice(0, options.maxStackLines).map(applyPatterns);
|
|
63702
|
-
const dropped = lines.length - kept.length;
|
|
63703
|
-
const body = dropped > 0 ? [...kept, ` ... ${dropped} more`] : kept;
|
|
63704
|
-
return body.join(`
|
|
63705
|
-
`);
|
|
63706
|
-
}, redact = (value, options = DEFAULT_OPTIONS) => {
|
|
63707
|
-
if (value === null || value === undefined)
|
|
63708
|
-
return null;
|
|
63709
|
-
if (typeof value === "boolean" || typeof value === "number")
|
|
63710
|
-
return value;
|
|
63711
|
-
if (typeof value === "string")
|
|
63712
|
-
return redactString(value, options);
|
|
63713
|
-
if (value instanceof Date)
|
|
63714
|
-
return value.toISOString();
|
|
63715
|
-
if (Array.isArray(value))
|
|
63716
|
-
return value.map((entry) => redact(entry, options));
|
|
63717
|
-
if (typeof value === "object") {
|
|
63718
|
-
const out = {};
|
|
63719
|
-
for (const [key, entry] of Object.entries(value)) {
|
|
63720
|
-
const words = splitKey(key);
|
|
63721
|
-
if (words.some((word) => STACK_WORDS.has(word)))
|
|
63722
|
-
out[key] = boundStack(entry, options);
|
|
63723
|
-
else if (words.some((word) => SENSITIVE_WORDS.has(word)))
|
|
63724
|
-
out[key] = REDACTED;
|
|
63725
|
-
else
|
|
63726
|
-
out[key] = redact(entry, options);
|
|
63727
|
-
}
|
|
63728
|
-
return out;
|
|
63729
|
-
}
|
|
63730
|
-
return null;
|
|
63731
|
-
}, DEFAULT_OPTIONS, dailyFileName = (date) => {
|
|
63732
|
-
const y = date.getFullYear();
|
|
63733
|
-
const m = String(date.getMonth() + 1).padStart(2, "0");
|
|
63734
|
-
const d = String(date.getDate()).padStart(2, "0");
|
|
63735
|
-
return `workit-${y}-${m}-${d}.jsonl`;
|
|
63736
|
-
}, pruneOldFiles = (dir) => {
|
|
63737
|
-
try {
|
|
63738
|
-
const files = readdirSync4(dir).filter((name) => DAY_FILE.test(name)).toSorted().toReversed();
|
|
63739
|
-
for (const file of files.slice(RETAINED_DAYS)) {
|
|
63740
|
-
try {
|
|
63741
|
-
unlinkSync2(path28.join(dir, file));
|
|
63742
|
-
} catch {}
|
|
63743
|
-
}
|
|
63744
|
-
} catch {}
|
|
63745
|
-
}, createLogger = (options = {}) => {
|
|
63746
|
-
const stateDir = options.stateDir ?? resolveStateDir();
|
|
63747
|
-
const logDir = path28.join(stateDir, "logs");
|
|
63748
|
-
const now = options.now ?? (() => new Date);
|
|
63749
|
-
const maxRate = options.maxRate ?? DEFAULT_MAX_RATE;
|
|
63750
|
-
const rateWindowMs = options.rateWindowMs ?? DEFAULT_RATE_WINDOW_MS;
|
|
63751
|
-
const redactOptions = {
|
|
63752
|
-
maxFieldLength: options.maxFieldLength ?? DEFAULT_MAX_FIELD_LENGTH,
|
|
63753
|
-
maxStackLines: options.maxStackLines ?? DEFAULT_MAX_STACK_LINES
|
|
63754
|
-
};
|
|
63755
|
-
let windowStart = 0;
|
|
63756
|
-
const windowCounts = { debug: 0, info: 0, warn: 0, error: 0 };
|
|
63757
|
-
const emit = (level, message, context) => {
|
|
63758
|
-
const date = now();
|
|
63759
|
-
const elapsed = date.getTime() - windowStart;
|
|
63760
|
-
if (elapsed >= rateWindowMs || windowStart === 0) {
|
|
63761
|
-
windowStart = date.getTime();
|
|
63762
|
-
windowCounts.debug = 0;
|
|
63763
|
-
windowCounts.info = 0;
|
|
63764
|
-
windowCounts.warn = 0;
|
|
63765
|
-
windowCounts.error = 0;
|
|
63766
|
-
}
|
|
63767
|
-
windowCounts[level] += 1;
|
|
63768
|
-
if (windowCounts[level] > maxRate)
|
|
63769
|
-
return;
|
|
63770
|
-
let event = null;
|
|
63771
|
-
try {
|
|
63772
|
-
event = {
|
|
63773
|
-
level,
|
|
63774
|
-
time: date.toISOString(),
|
|
63775
|
-
message: redactString(message, redactOptions),
|
|
63776
|
-
context: redact(context ?? {}, redactOptions)
|
|
63777
|
-
};
|
|
63778
|
-
const line = `${JSON.stringify(event)}
|
|
63779
|
-
`;
|
|
63780
|
-
mkdirSync4(logDir, { recursive: true, mode: 448 });
|
|
63781
|
-
appendFileSync(path28.join(logDir, dailyFileName(date)), line, { mode: 384 });
|
|
63782
|
-
pruneOldFiles(logDir);
|
|
63783
|
-
} catch {
|
|
63784
|
-
try {
|
|
63785
|
-
event = {
|
|
63786
|
-
level,
|
|
63787
|
-
time: date.toISOString(),
|
|
63788
|
-
message: redactString(message, redactOptions),
|
|
63789
|
-
context: { redaction_failed: true }
|
|
63790
|
-
};
|
|
63791
|
-
mkdirSync4(logDir, { recursive: true, mode: 448 });
|
|
63792
|
-
appendFileSync(path28.join(logDir, dailyFileName(date)), `${JSON.stringify(event)}
|
|
63793
|
-
`, {
|
|
63794
|
-
mode: 384
|
|
63795
|
-
});
|
|
63796
|
-
} catch {}
|
|
63797
|
-
}
|
|
63798
|
-
for (const sink of [options.appLog, options.stderr]) {
|
|
63799
|
-
if (!sink)
|
|
63800
|
-
continue;
|
|
63801
|
-
if (!event)
|
|
63802
|
-
continue;
|
|
63803
|
-
try {
|
|
63804
|
-
sink(event);
|
|
63805
|
-
} catch {}
|
|
63806
|
-
}
|
|
63807
|
-
};
|
|
63808
|
-
return {
|
|
63809
|
-
debug: (message, context) => emit("debug", message, context),
|
|
63810
|
-
info: (message, context) => emit("info", message, context),
|
|
63811
|
-
warn: (message, context) => emit("warn", message, context),
|
|
63812
|
-
error: (message, context) => emit("error", message, context),
|
|
63813
|
-
guard: (name, fn) => {
|
|
63814
|
-
try {
|
|
63815
|
-
return fn();
|
|
63816
|
-
} catch (err) {
|
|
63817
|
-
emit("warn", "detector_failed", {
|
|
63818
|
-
detector: name,
|
|
63819
|
-
error: err instanceof Error ? err.message : String(err)
|
|
63820
|
-
});
|
|
63821
|
-
return;
|
|
63822
|
-
}
|
|
63823
|
-
}
|
|
63824
|
-
};
|
|
63825
|
-
};
|
|
63826
|
-
var init_logger = __esm(() => {
|
|
63827
|
-
DAY_FILE = /^workit-\d{4}-\d{2}-\d{2}\.jsonl$/;
|
|
63828
|
-
SECRET_VALUE = /\b(?:Bearer|Basic|Digest|Token)\s+\S+/gi;
|
|
63829
|
-
KEY_EQ_VALUE = /\b([A-Za-z0-9_-]*(?:token|secret|password|passwd|apikey|api[_-]?key|authorization|credential|bearer)[A-Za-z0-9_-]*)([:=]\s*).+/gi;
|
|
63830
|
-
URL_QUERY = /(https?:\/\/[^?#\s]+)\?[^#\s]*/g;
|
|
63831
|
-
SENSITIVE_WORDS = new Set([
|
|
63832
|
-
"token",
|
|
63833
|
-
"secret",
|
|
63834
|
-
"password",
|
|
63835
|
-
"passwd",
|
|
63836
|
-
"authorization",
|
|
63837
|
-
"credential",
|
|
63838
|
-
"credentials",
|
|
63839
|
-
"cookie",
|
|
63840
|
-
"api",
|
|
63841
|
-
"apikey",
|
|
63842
|
-
"apitoken",
|
|
63843
|
-
"accesstoken",
|
|
63844
|
-
"clientsecret",
|
|
63845
|
-
"refreshtoken",
|
|
63846
|
-
"key",
|
|
63847
|
-
"bearer",
|
|
63848
|
-
"prompt",
|
|
63849
|
-
"message",
|
|
63850
|
-
"messages",
|
|
63851
|
-
"content",
|
|
63852
|
-
"body",
|
|
63853
|
-
"args",
|
|
63854
|
-
"argument",
|
|
63855
|
-
"result",
|
|
63856
|
-
"results",
|
|
63857
|
-
"output",
|
|
63858
|
-
"issue",
|
|
63859
|
-
"description",
|
|
63860
|
-
"summary",
|
|
63861
|
-
"payload",
|
|
63862
|
-
"script",
|
|
63863
|
-
"command",
|
|
63864
|
-
"text",
|
|
63865
|
-
"query"
|
|
63866
|
-
]);
|
|
63867
|
-
STACK_WORDS = new Set(["stack", "stacktrace", "trace"]);
|
|
63868
|
-
homePattern = new RegExp(`${escapeRegExp3(os6.homedir())}(?=[/\\\\]|$)|\\$HOME(?=[/\\\\]|$)`, "g");
|
|
63869
|
-
DEFAULT_OPTIONS = {
|
|
63870
|
-
maxFieldLength: DEFAULT_MAX_FIELD_LENGTH,
|
|
63871
|
-
maxStackLines: DEFAULT_MAX_STACK_LINES
|
|
63872
|
-
};
|
|
63873
|
-
});
|
|
63874
|
-
|
|
63875
63908
|
// packages/workit-cli/src/admin/host-install.ts
|
|
63876
63909
|
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
63877
63910
|
import {
|
|
@@ -66440,7 +66473,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66440
66473
|
fix: repair,
|
|
66441
66474
|
registryProbed
|
|
66442
66475
|
};
|
|
66443
|
-
}, HOOK_ISSUED_MARKER = "workit-issued-sessions/
|
|
66476
|
+
}, HOOK_ISSUED_MARKER = "workit-issued-sessions/2", hookRecordsIssued = (root) => {
|
|
66444
66477
|
let files;
|
|
66445
66478
|
try {
|
|
66446
66479
|
files = readdirSync7(path32.join(root, "dist")).filter((f) => f.endsWith(".js"));
|