@brainervirus/workit-cli 8.41.0 → 8.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +752 -394
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -9417,7 +9417,7 @@ var package_default;
|
|
|
9417
9417
|
var init_package = __esm(() => {
|
|
9418
9418
|
package_default = {
|
|
9419
9419
|
name: "@brainervirus/workit-cli",
|
|
9420
|
-
version: "8.
|
|
9420
|
+
version: "8.42.0",
|
|
9421
9421
|
private: false,
|
|
9422
9422
|
description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
9423
9423
|
keywords: [
|
|
@@ -9455,13 +9455,13 @@ var init_package = __esm(() => {
|
|
|
9455
9455
|
},
|
|
9456
9456
|
dependencies: {
|
|
9457
9457
|
"@babel/parser": "7.29.9",
|
|
9458
|
-
"@brainervirus/workit-cursor": "^8.
|
|
9458
|
+
"@brainervirus/workit-cursor": "^8.42.0",
|
|
9459
9459
|
"@inkjs/ui": "2.0.0",
|
|
9460
9460
|
ink: "7.1.1",
|
|
9461
9461
|
react: "19.2.8"
|
|
9462
9462
|
},
|
|
9463
9463
|
devDependencies: {
|
|
9464
|
-
"@brainervirus/workit-core": "^8.
|
|
9464
|
+
"@brainervirus/workit-core": "^8.42.0"
|
|
9465
9465
|
},
|
|
9466
9466
|
engines: {
|
|
9467
9467
|
node: ">=24"
|
|
@@ -21951,6 +21951,108 @@ var init_task = __esm(() => {
|
|
|
21951
21951
|
};
|
|
21952
21952
|
});
|
|
21953
21953
|
|
|
21954
|
+
// packages/workit-cli/src/style.ts
|
|
21955
|
+
import { stripVTControlCharacters } from "node:util";
|
|
21956
|
+
function createStyle(options = {}) {
|
|
21957
|
+
const enabled = colorEnabled(options);
|
|
21958
|
+
const pick = (open) => enabled ? sgr(open) : same2;
|
|
21959
|
+
return {
|
|
21960
|
+
enabled,
|
|
21961
|
+
width: enabled ? options.stream?.columns || undefined : undefined,
|
|
21962
|
+
ok: pick("32"),
|
|
21963
|
+
fail: pick("1;31"),
|
|
21964
|
+
warn: pick("33"),
|
|
21965
|
+
info: pick("2"),
|
|
21966
|
+
dim: pick("2"),
|
|
21967
|
+
bold: pick("1"),
|
|
21968
|
+
accent: pick("36"),
|
|
21969
|
+
diffAdd: pick("32"),
|
|
21970
|
+
diffDel: pick("31"),
|
|
21971
|
+
diffHunk: pick("36"),
|
|
21972
|
+
path: pick("2"),
|
|
21973
|
+
command: pick("1;36")
|
|
21974
|
+
};
|
|
21975
|
+
}
|
|
21976
|
+
function wrap(text, width, indent, firstUsed = indent) {
|
|
21977
|
+
if (!width || width <= indent + 10)
|
|
21978
|
+
return text;
|
|
21979
|
+
const lines = [];
|
|
21980
|
+
let line = "";
|
|
21981
|
+
let room = width - firstUsed;
|
|
21982
|
+
const place = (word) => {
|
|
21983
|
+
let rest = word;
|
|
21984
|
+
while (visibleLength(rest) > room) {
|
|
21985
|
+
const chars = Array.from(rest);
|
|
21986
|
+
lines.push(chars.slice(0, room).join(""));
|
|
21987
|
+
rest = chars.slice(room).join("");
|
|
21988
|
+
room = width - indent;
|
|
21989
|
+
}
|
|
21990
|
+
line = rest;
|
|
21991
|
+
};
|
|
21992
|
+
for (const word of text.split(/ +/)) {
|
|
21993
|
+
if (word === "")
|
|
21994
|
+
continue;
|
|
21995
|
+
if (line === "")
|
|
21996
|
+
place(word);
|
|
21997
|
+
else if (visibleLength(line) + 1 + visibleLength(word) <= room)
|
|
21998
|
+
line = `${line} ${word}`;
|
|
21999
|
+
else {
|
|
22000
|
+
lines.push(line);
|
|
22001
|
+
room = width - indent;
|
|
22002
|
+
place(word);
|
|
22003
|
+
}
|
|
22004
|
+
}
|
|
22005
|
+
lines.push(line);
|
|
22006
|
+
return lines.join(`
|
|
22007
|
+
${" ".repeat(indent)}`);
|
|
22008
|
+
}
|
|
22009
|
+
function colorDiff(text, style) {
|
|
22010
|
+
if (!style.enabled)
|
|
22011
|
+
return text;
|
|
22012
|
+
return text.split(`
|
|
22013
|
+
`).map((line) => {
|
|
22014
|
+
if (line.startsWith("+++") || line.startsWith("---"))
|
|
22015
|
+
return style.bold(line);
|
|
22016
|
+
if (line.startsWith("+"))
|
|
22017
|
+
return style.diffAdd(line);
|
|
22018
|
+
if (line.startsWith("-"))
|
|
22019
|
+
return style.diffDel(line);
|
|
22020
|
+
if (line.startsWith("@@") || line.trim() === "…" || line.trim() === "...")
|
|
22021
|
+
return style.diffHunk(line);
|
|
22022
|
+
return style.dim(line);
|
|
22023
|
+
}).join(`
|
|
22024
|
+
`);
|
|
22025
|
+
}
|
|
22026
|
+
function spinnerPaint(elapsed, env, glyph) {
|
|
22027
|
+
const k = (Math.sin(elapsed / 2400 * Math.PI * 2) + 1) / 2;
|
|
22028
|
+
const [r, g, b] = [
|
|
22029
|
+
[170, 80],
|
|
22030
|
+
[120, 200],
|
|
22031
|
+
[255, 255]
|
|
22032
|
+
].map(([from, to]) => Math.round(from + (to - from) * k));
|
|
22033
|
+
const depth = (env.COLORTERM || "").toLowerCase();
|
|
22034
|
+
const level = (v) => v < 48 ? 0 : v < 115 ? 1 : Math.min(5, Math.floor((v - 35) / 40));
|
|
22035
|
+
const code = depth === "truecolor" || depth === "24bit" ? `38;2;${r};${g};${b}` : /256/.test(env.TERM || "") ? `38;5;${16 + 36 * level(r) + 6 * level(g) + level(b)}` : "36";
|
|
22036
|
+
return `\x1B[${code}m${glyph}\x1B[0m`;
|
|
22037
|
+
}
|
|
22038
|
+
var truthy = (value) => value !== undefined && value !== "" && value !== "0" && value.toLowerCase() !== "false", terminalMode = (options) => {
|
|
22039
|
+
const env = options.env ?? process.env;
|
|
22040
|
+
if (options.json || !options.stream?.isTTY || truthy(env.CI))
|
|
22041
|
+
return "off";
|
|
22042
|
+
if (truthy(env.NO_COLOR) || env.TERM === "dumb")
|
|
22043
|
+
return "plain";
|
|
22044
|
+
return "spinner";
|
|
22045
|
+
}, colorEnabled = (options) => {
|
|
22046
|
+
if (options.json || !options.stream)
|
|
22047
|
+
return false;
|
|
22048
|
+
if (truthy((options.env ?? process.env).FORCE_COLOR))
|
|
22049
|
+
return true;
|
|
22050
|
+
return terminalMode(options) === "spinner";
|
|
22051
|
+
}, sgr = (open) => (text) => text === "" ? text : `\x1B[${open}m${text}\x1B[0m`, same2 = (text) => text, visibleLength = (text) => Array.from(stripVTControlCharacters(text)).length, SPINNER_FRAMES, SPINNER_FRAME_MS = 140;
|
|
22052
|
+
var init_style = __esm(() => {
|
|
22053
|
+
SPINNER_FRAMES = ["◐", "◓", "◑", "◒"];
|
|
22054
|
+
});
|
|
22055
|
+
|
|
21954
22056
|
// packages/workit-cli/src/output.ts
|
|
21955
22057
|
function emit(io, envelope, human) {
|
|
21956
22058
|
if (io.json) {
|
|
@@ -21988,11 +22090,12 @@ async function withFailureLine(io, command, run, outcome) {
|
|
|
21988
22090
|
});
|
|
21989
22091
|
if (code === 0)
|
|
21990
22092
|
return code;
|
|
22093
|
+
const red = createStyle({ stream: io.terminals?.stderr, env: io.env, json: io.json }).fail;
|
|
21991
22094
|
if (outcome)
|
|
21992
|
-
io.stderr(`workit: error: ${outcome} (${reason ?? EXIT_NAMES[code] ?? "failed"}, exit ${code})
|
|
22095
|
+
io.stderr(`${red(`workit: error: ${outcome} (${reason ?? EXIT_NAMES[code] ?? "failed"}, exit ${code})`)}
|
|
21993
22096
|
`);
|
|
21994
22097
|
else if (!wrote)
|
|
21995
|
-
io.stderr(`workit: error: ${command} failed (exit ${code})
|
|
22098
|
+
io.stderr(`${red(`workit: error: ${command} failed (exit ${code})`)}
|
|
21996
22099
|
`);
|
|
21997
22100
|
return code;
|
|
21998
22101
|
}
|
|
@@ -22017,6 +22120,7 @@ var EXIT, EXIT_BY_CODE, exitCodeFor = (code) => EXIT_BY_CODE[code], ok2 = (data)
|
|
|
22017
22120
|
})));
|
|
22018
22121
|
};
|
|
22019
22122
|
var init_output = __esm(() => {
|
|
22123
|
+
init_style();
|
|
22020
22124
|
EXIT = {
|
|
22021
22125
|
ok: 0,
|
|
22022
22126
|
failed: 1,
|
|
@@ -66193,7 +66297,7 @@ import path33 from "node:path";
|
|
|
66193
66297
|
function hostCommand(name, args, options = {}) {
|
|
66194
66298
|
const executable = findHostExecutable(name, options);
|
|
66195
66299
|
if (!executable)
|
|
66196
|
-
throw new Error(`${name} executable was not found on PATH or supported user bin directories`);
|
|
66300
|
+
throw new Error(path33.isAbsolute(name) || name.includes("/") || name.includes("\\") ? `${name} does not exist or is not executable` : `${name} executable was not found on PATH or supported user bin directories`);
|
|
66197
66301
|
if (process.platform === "win32" && /\.(?:cmd|bat)$/i.test(executable)) {
|
|
66198
66302
|
const node = findHostExecutable("node", options);
|
|
66199
66303
|
if (!node)
|
|
@@ -66217,6 +66321,17 @@ function resolveWindowsShimEntry(contents, shim, exists = existsSync13) {
|
|
|
66217
66321
|
return null;
|
|
66218
66322
|
}
|
|
66219
66323
|
function findHostExecutable(name, options = {}) {
|
|
66324
|
+
if (path33.isAbsolute(name) || name.includes("/") || name.includes("\\")) {
|
|
66325
|
+
try {
|
|
66326
|
+
if (!statSync2(name).isFile())
|
|
66327
|
+
return null;
|
|
66328
|
+
if (process.platform !== "win32")
|
|
66329
|
+
accessSync(name, constants2.X_OK);
|
|
66330
|
+
return name;
|
|
66331
|
+
} catch {
|
|
66332
|
+
return null;
|
|
66333
|
+
}
|
|
66334
|
+
}
|
|
66220
66335
|
const env = options.env ?? process.env;
|
|
66221
66336
|
const home = options.home ?? env.HOME ?? os9.homedir();
|
|
66222
66337
|
const suffixes = process.platform === "win32" ? ["", ".exe", ".cmd", ".bat"] : [""];
|
|
@@ -67761,7 +67876,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67761
67876
|
return null;
|
|
67762
67877
|
dir = parent;
|
|
67763
67878
|
}
|
|
67764
|
-
},
|
|
67879
|
+
}, listProcessesMatching = (match) => {
|
|
67765
67880
|
const r = spawnSync16("ps", ["-eo", "pid=,lstart=,args="], {
|
|
67766
67881
|
encoding: "utf8",
|
|
67767
67882
|
timeout: 5000
|
|
@@ -67772,14 +67887,14 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67772
67887
|
for (const row of r.stdout.split(`
|
|
67773
67888
|
`)) {
|
|
67774
67889
|
const m = /^\s*(\d+)\s+(\w{3}\s+\w{3}\s+\d+\s+[\d:]+\s+\d{4})\s+(.*)$/.exec(row);
|
|
67775
|
-
if (!m ||
|
|
67890
|
+
if (!m || !match(m[3]))
|
|
67776
67891
|
continue;
|
|
67777
67892
|
const startedMs = Date.parse(m[2]);
|
|
67778
67893
|
if (Number.isFinite(startedMs))
|
|
67779
67894
|
found.push({ pid: Number(m[1]), startedMs, args: m[3] });
|
|
67780
67895
|
}
|
|
67781
67896
|
return found;
|
|
67782
|
-
}, resolve = (options) => {
|
|
67897
|
+
}, listClaudeProcesses = () => listProcessesMatching((args) => /^(\S*\/)?claude(\s|$)/.test(args)), listCodexProcesses = () => listProcessesMatching((args) => /^(\S*\/)?codex(\.js)?(\s|$)|^(\S*\/)?node(js)?\s+(\S+\s+)*?\S*\/codex(\.js)?(\s|$)/.test(args) && !/\bdaemon\s+pid-update-loop\b/.test(args)), resolve = (options) => {
|
|
67783
67898
|
const env = options.env ?? process.env;
|
|
67784
67899
|
const home = options.home ?? env.HOME ?? os12.homedir();
|
|
67785
67900
|
const configDir = options.configDir ?? env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path39.join(home, ".config", "workit");
|
|
@@ -67807,7 +67922,8 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67807
67922
|
installer: options.installer ?? false,
|
|
67808
67923
|
cliVersion: options.cliVersion ?? null,
|
|
67809
67924
|
scopeProbe: options.scopeProbe ?? probeScope,
|
|
67810
|
-
claudeProcesses: options.claudeProcesses ?? listClaudeProcesses
|
|
67925
|
+
claudeProcesses: options.claudeProcesses ?? listClaudeProcesses,
|
|
67926
|
+
codexProcesses: options.codexProcesses ?? listCodexProcesses
|
|
67811
67927
|
};
|
|
67812
67928
|
}, readJson = (p) => {
|
|
67813
67929
|
try {
|
|
@@ -68563,7 +68679,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
68563
68679
|
id: "launcher",
|
|
68564
68680
|
status: "fail",
|
|
68565
68681
|
detail: `missing or invalid launcher entry: ${missing.join("; ")}`,
|
|
68566
|
-
fix: `Rebuild and reinstall the workit package (bun run build) — dist entries must be non-empty Node launchers`
|
|
68682
|
+
fix: dev ? `Rebuild and reinstall the workit package (bun run build) — dist entries must be non-empty Node launchers` : "workit upgrade --hosts=cursor — it reinstalls the plugin files and re-registers the MCP launcher"
|
|
68567
68683
|
};
|
|
68568
68684
|
}
|
|
68569
68685
|
if (!dev && res.host !== "cursor") {
|
|
@@ -69804,6 +69920,49 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
69804
69920
|
status: "warn",
|
|
69805
69921
|
detail: `started before Workit ${latest.install.version} was installed: ${rows.join("; ")}; quit and start \`claude --resume ${first ?? "<session id>"}\` to load it (\`/resume\` keeps the old plugin)`
|
|
69806
69922
|
};
|
|
69923
|
+
}, checkCodexSessionPlugin = (res) => {
|
|
69924
|
+
const id = "codex_session_plugin";
|
|
69925
|
+
if (process.platform === "win32")
|
|
69926
|
+
return {
|
|
69927
|
+
id,
|
|
69928
|
+
status: "info",
|
|
69929
|
+
detail: "running Codex processes are not checked on Windows"
|
|
69930
|
+
};
|
|
69931
|
+
const installs = codexWorkitInstalls(res).filter((install) => install.root && install.version);
|
|
69932
|
+
const stamped = installs.flatMap((install) => {
|
|
69933
|
+
try {
|
|
69934
|
+
return [{ install, at: statSync6(install.root).mtimeMs }];
|
|
69935
|
+
} catch {
|
|
69936
|
+
return [];
|
|
69937
|
+
}
|
|
69938
|
+
});
|
|
69939
|
+
const latest = stamped.toSorted((a, b) => b.at - a.at)[0];
|
|
69940
|
+
if (!latest)
|
|
69941
|
+
return {
|
|
69942
|
+
id,
|
|
69943
|
+
status: "info",
|
|
69944
|
+
detail: "no Workit Codex plugin install recorded — skipping"
|
|
69945
|
+
};
|
|
69946
|
+
const running = res.codexProcesses();
|
|
69947
|
+
if (running === null)
|
|
69948
|
+
return {
|
|
69949
|
+
id,
|
|
69950
|
+
status: "info",
|
|
69951
|
+
detail: "could not list running codex processes (ps) — skipping"
|
|
69952
|
+
};
|
|
69953
|
+
const stale = running.filter((proc) => proc.startedMs < latest.at);
|
|
69954
|
+
if (stale.length === 0)
|
|
69955
|
+
return {
|
|
69956
|
+
id,
|
|
69957
|
+
status: "info",
|
|
69958
|
+
detail: `${running.length} running codex process(es), none started before Workit ${latest.install.version} was installed`
|
|
69959
|
+
};
|
|
69960
|
+
const rows = stale.map((proc) => `pid ${proc.pid} started ${new Date(proc.startedMs).toISOString()} (${proc.args.slice(0, 60)})`);
|
|
69961
|
+
return {
|
|
69962
|
+
id,
|
|
69963
|
+
status: "warn",
|
|
69964
|
+
detail: `started before Workit ${latest.install.version} was installed: ${rows.join("; ")}; they keep the old plugin until restarted, new Codex sessions load it`
|
|
69965
|
+
};
|
|
69807
69966
|
}, HOOK_ISSUED_MARKER = "workit-issued-sessions/3", hookRecordsIssued = (root) => {
|
|
69808
69967
|
let files;
|
|
69809
69968
|
try {
|
|
@@ -70095,6 +70254,7 @@ var init_doctor = __esm(() => {
|
|
|
70095
70254
|
checkOpencodeVersion,
|
|
70096
70255
|
checkClaudePlugin,
|
|
70097
70256
|
checkClaudeSessionPlugin,
|
|
70257
|
+
checkCodexSessionPlugin,
|
|
70098
70258
|
checkHookIssuedSessions,
|
|
70099
70259
|
checkWorkitOnPath,
|
|
70100
70260
|
checkAssets,
|
|
@@ -75135,14 +75295,18 @@ async function run4(argv, io) {
|
|
|
75135
75295
|
...io.env.HOME ? { home: io.env.HOME } : {}
|
|
75136
75296
|
});
|
|
75137
75297
|
const say = io.json ? io.stderr : io.stdout;
|
|
75298
|
+
const style = createStyle({
|
|
75299
|
+
stream: io.json ? io.terminals?.stderr : io.terminals?.stdout,
|
|
75300
|
+
env: io.env
|
|
75301
|
+
});
|
|
75138
75302
|
for (const note of plan.notes)
|
|
75139
75303
|
say(`${note}
|
|
75140
75304
|
`);
|
|
75141
75305
|
for (const blocked of plan.blocked)
|
|
75142
|
-
say(
|
|
75306
|
+
say(`${style.warn("blocked:")} ${blocked}
|
|
75143
75307
|
`);
|
|
75144
75308
|
for (const change of plan.changes)
|
|
75145
|
-
say(`${permissionDiff(change)}
|
|
75309
|
+
say(`${colorDiff(permissionDiff(change), style)}
|
|
75146
75310
|
`);
|
|
75147
75311
|
const summary = {
|
|
75148
75312
|
changes: plan.changes.map((c) => ({ host: c.host, file: c.file })),
|
|
@@ -75164,7 +75328,7 @@ async function run4(argv, io) {
|
|
|
75164
75328
|
data: summary,
|
|
75165
75329
|
unblock: `review the diff above, then run ${USAGE2.replace("[--dry-run | --yes]", "--yes")} or run it in a terminal`
|
|
75166
75330
|
}));
|
|
75167
|
-
const answer = await askOrCancel(io, () => askLine("Write Workit's permission block shown above? [y/N]
|
|
75331
|
+
const answer = await askOrCancel(io, () => askLine(`${style.bold("Write Workit's permission block shown above?")} [y/N] `, io.json ? process.stderr : process.stdout));
|
|
75168
75332
|
if (answer === null)
|
|
75169
75333
|
return cancelled(io);
|
|
75170
75334
|
if (!/^y(es)?$/i.test(answer.trim()))
|
|
@@ -75179,7 +75343,7 @@ async function run4(argv, io) {
|
|
|
75179
75343
|
if (failed.length)
|
|
75180
75344
|
return emit(io, fail2("failed", failed.map((e) => `${e.file}: ${e.detail ?? "failed"}`).join("; "), { data }));
|
|
75181
75345
|
return emit(io, ok2(data), () => [
|
|
75182
|
-
...entries.map((e) =>
|
|
75346
|
+
...entries.map((e) => `${style.ok("written")} ${style.path(e.file)}`),
|
|
75183
75347
|
"Restart the host sessions to load the new permissions. `workit uninstall` removes them."
|
|
75184
75348
|
]);
|
|
75185
75349
|
}
|
|
@@ -75215,13 +75379,16 @@ var init_setup2 = __esm(() => {
|
|
|
75215
75379
|
init_host_permissions();
|
|
75216
75380
|
init_output();
|
|
75217
75381
|
init_prompt();
|
|
75382
|
+
init_style();
|
|
75218
75383
|
ALL_HOSTS = ["claude-code", "codex", "cursor", "opencode", "pi"];
|
|
75219
75384
|
});
|
|
75220
75385
|
|
|
75221
75386
|
// packages/workit-cli/src/progress.ts
|
|
75387
|
+
import { spawn } from "node:child_process";
|
|
75388
|
+
import path44 from "node:path";
|
|
75222
75389
|
function createProgress(options = {}) {
|
|
75223
75390
|
const env = options.env ?? process.env;
|
|
75224
|
-
const mode =
|
|
75391
|
+
const mode = terminalMode({ ...options, env });
|
|
75225
75392
|
const stream = options.stream;
|
|
75226
75393
|
const now = options.now ?? Date.now;
|
|
75227
75394
|
const every = options.setInterval ?? ((tick, ms) => setInterval(tick, ms));
|
|
@@ -75229,7 +75396,7 @@ function createProgress(options = {}) {
|
|
|
75229
75396
|
const proc = options.proc ?? process;
|
|
75230
75397
|
const ascii = env.TERM === "dumb";
|
|
75231
75398
|
const glyphs = mode === "spinner" ? { done: "\x1B[32m✓\x1B[0m", failed: "\x1B[31m✗\x1B[0m", skipped: "–" } : ascii ? { done: "ok", failed: "x", skipped: "-" } : { done: "✓", failed: "✗", skipped: "–" };
|
|
75232
|
-
const start = (initial) => {
|
|
75399
|
+
const start = (initial, signals = true) => {
|
|
75233
75400
|
if (mode === "off" || !stream)
|
|
75234
75401
|
return NOOP_STEP;
|
|
75235
75402
|
let text = initial;
|
|
@@ -75238,10 +75405,11 @@ function createProgress(options = {}) {
|
|
|
75238
75405
|
let frame = 0;
|
|
75239
75406
|
const draw = () => {
|
|
75240
75407
|
const seconds = Math.floor((now() - began) / 1000);
|
|
75241
|
-
let line = `${
|
|
75242
|
-
if (stream.columns && line.length >= stream.columns)
|
|
75243
|
-
line = `${line.slice(0, Math.max(1, stream.columns -
|
|
75244
|
-
|
|
75408
|
+
let line = `${text} (${seconds}s)`;
|
|
75409
|
+
if (stream.columns && line.length + 2 >= stream.columns)
|
|
75410
|
+
line = `${line.slice(0, Math.max(1, stream.columns - 4))}…`;
|
|
75411
|
+
const glyph = spinnerPaint(now() - began, env, FRAMES[frame % FRAMES.length] ?? "");
|
|
75412
|
+
stream.write(`${CLEAR}${glyph} ${line}`);
|
|
75245
75413
|
};
|
|
75246
75414
|
let timer;
|
|
75247
75415
|
if (mode === "spinner") {
|
|
@@ -75257,7 +75425,7 @@ function createProgress(options = {}) {
|
|
|
75257
75425
|
proc.off(event, handler);
|
|
75258
75426
|
handlers.length = 0;
|
|
75259
75427
|
};
|
|
75260
|
-
if (mode === "spinner") {
|
|
75428
|
+
if (mode === "spinner" && signals) {
|
|
75261
75429
|
const onSignal = (signal) => () => {
|
|
75262
75430
|
if (!finished) {
|
|
75263
75431
|
finished = true;
|
|
@@ -75268,11 +75436,13 @@ function createProgress(options = {}) {
|
|
|
75268
75436
|
release();
|
|
75269
75437
|
proc.kill(proc.pid, signal);
|
|
75270
75438
|
};
|
|
75439
|
+
handlers.push(["SIGINT", onSignal("SIGINT")], ["SIGTERM", onSignal("SIGTERM")]);
|
|
75440
|
+
}
|
|
75441
|
+
if (mode === "spinner") {
|
|
75271
75442
|
const onExit = () => {
|
|
75272
75443
|
if (!finished)
|
|
75273
75444
|
stream.write(CLEAR);
|
|
75274
75445
|
};
|
|
75275
|
-
handlers.push(["SIGINT", onSignal("SIGINT")], ["SIGTERM", onSignal("SIGTERM")]);
|
|
75276
75446
|
handlers.push(["exit", onExit]);
|
|
75277
75447
|
for (const [event, handler] of handlers)
|
|
75278
75448
|
proc.on(event, handler);
|
|
@@ -75299,7 +75469,7 @@ function createProgress(options = {}) {
|
|
|
75299
75469
|
mode,
|
|
75300
75470
|
start,
|
|
75301
75471
|
async run(label, fn, classify) {
|
|
75302
|
-
const step = start(label);
|
|
75472
|
+
const step = start(label, false);
|
|
75303
75473
|
try {
|
|
75304
75474
|
const value = await fn();
|
|
75305
75475
|
step.end(classify ? classify(value) : "done");
|
|
@@ -75310,63 +75480,111 @@ function createProgress(options = {}) {
|
|
|
75310
75480
|
}
|
|
75311
75481
|
},
|
|
75312
75482
|
runSync(label, fn, classify) {
|
|
75313
|
-
const step = start(label);
|
|
75483
|
+
const step = start(label, false);
|
|
75484
|
+
const ticker = mode === "spinner" && stream ? (options.spawnTicker ?? ((text, began) => defaultTicker(text, began, stream)))(label, now()) : undefined;
|
|
75314
75485
|
try {
|
|
75315
75486
|
const value = fn();
|
|
75487
|
+
ticker?.stop();
|
|
75316
75488
|
step.end(classify ? classify(value) : "done");
|
|
75317
75489
|
return value;
|
|
75318
75490
|
} catch (error) {
|
|
75491
|
+
ticker?.stop();
|
|
75319
75492
|
step.end("failed");
|
|
75320
75493
|
throw error;
|
|
75321
75494
|
}
|
|
75322
75495
|
}
|
|
75323
75496
|
};
|
|
75324
75497
|
}
|
|
75325
|
-
var FRAMES, FRAME_MS
|
|
75326
|
-
if (
|
|
75327
|
-
return
|
|
75328
|
-
if (
|
|
75329
|
-
return
|
|
75330
|
-
|
|
75331
|
-
|
|
75498
|
+
var FRAMES, FRAME_MS, CLEAR = "\r\x1B[2K", TICKER_SOURCE, defaultTicker = (label, began, stream) => {
|
|
75499
|
+
if (stream !== process.stderr)
|
|
75500
|
+
return;
|
|
75501
|
+
if (!/^(?:node|nodejs|bun)(?:\.exe)?$/i.test(path44.basename(process.execPath)))
|
|
75502
|
+
return;
|
|
75503
|
+
try {
|
|
75504
|
+
const child = spawn(process.execPath, ["-e", TICKER_SOURCE], {
|
|
75505
|
+
env: {
|
|
75506
|
+
...process.env,
|
|
75507
|
+
WORKIT_TICK_LABEL: label,
|
|
75508
|
+
WORKIT_TICK_BEGAN: String(began),
|
|
75509
|
+
WORKIT_TICK_COLS: String(stream.columns ?? 0)
|
|
75510
|
+
},
|
|
75511
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
75512
|
+
windowsHide: true
|
|
75513
|
+
});
|
|
75514
|
+
child.on("error", () => {});
|
|
75515
|
+
child.unref();
|
|
75516
|
+
return { stop: () => void child.kill("SIGKILL") };
|
|
75517
|
+
} catch {
|
|
75518
|
+
return;
|
|
75519
|
+
}
|
|
75520
|
+
}, NOOP_STEP, progressFor = (io) => {
|
|
75521
|
+
const stderr = io.terminals?.stderr;
|
|
75522
|
+
const stream = stderr?.write ? stderr : undefined;
|
|
75523
|
+
return createProgress({ json: io.json, env: io.env, ...stream ? { stream } : {} });
|
|
75524
|
+
};
|
|
75332
75525
|
var init_progress = __esm(() => {
|
|
75333
|
-
|
|
75526
|
+
init_style();
|
|
75527
|
+
FRAMES = SPINNER_FRAMES;
|
|
75528
|
+
FRAME_MS = SPINNER_FRAME_MS;
|
|
75529
|
+
TICKER_SOURCE = `
|
|
75530
|
+
const frames = ${JSON.stringify(FRAMES)};
|
|
75531
|
+
const { WORKIT_TICK_LABEL: label, WORKIT_TICK_BEGAN: began, WORKIT_TICK_COLS: cols } = process.env;
|
|
75532
|
+
const spinnerPaint = ${spinnerPaint.toString()};
|
|
75533
|
+
const parent = process.ppid;
|
|
75534
|
+
let frame = 0;
|
|
75535
|
+
const timer = setInterval(() => {
|
|
75536
|
+
let alive = process.ppid === parent;
|
|
75537
|
+
if (alive) try { process.kill(parent, 0); } catch { alive = false; }
|
|
75538
|
+
if (!alive || Date.now() - Number(began) > 600000) process.exit(0);
|
|
75539
|
+
frame += 1;
|
|
75540
|
+
const seconds = Math.floor((Date.now() - Number(began)) / 1000);
|
|
75541
|
+
let line = label + " (" + seconds + "s)";
|
|
75542
|
+
if (Number(cols) && line.length + 2 >= Number(cols)) line = line.slice(0, Math.max(1, Number(cols) - 4)) + "…";
|
|
75543
|
+
process.stderr.write(${JSON.stringify(CLEAR)} + spinnerPaint(Date.now() - Number(began), process.env, frames[frame % frames.length]) + " " + line);
|
|
75544
|
+
}, ${FRAME_MS});
|
|
75545
|
+
`;
|
|
75334
75546
|
NOOP_STEP = { label: () => {}, end: () => {} };
|
|
75335
75547
|
});
|
|
75336
75548
|
|
|
75337
75549
|
// packages/workit-cli/src/upgrade/shared.ts
|
|
75338
|
-
import { spawn } from "node:child_process";
|
|
75550
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
75339
75551
|
import { existsSync as existsSync21, readFileSync as readFileSync22 } from "node:fs";
|
|
75340
|
-
import
|
|
75552
|
+
import path45 from "node:path";
|
|
75341
75553
|
import os16 from "node:os";
|
|
75342
75554
|
import { createHash as createHash15 } from "node:crypto";
|
|
75343
|
-
|
|
75555
|
+
function errorText(error) {
|
|
75556
|
+
return error instanceof Error ? error.message : "installed source could not be read";
|
|
75557
|
+
}
|
|
75558
|
+
var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-opencode", OPENCODE_UPDATE, CODEX_MARKETPLACE = "workflow-toolkit", CLI_FIX = "npm install --global @brainervirus/workit-cli@latest", stderrTail = (text, lines = 5) => (text ?? "").split(/\r?\n/).map((line) => line.trim()).filter(Boolean).slice(-lines).join(" | "), failureReason = (command, result) => {
|
|
75559
|
+
const tail = stderrTail(result.stderr);
|
|
75560
|
+
return `\`${command.command} ${command.args.join(" ")}\` failed${tail ? `: ${tail}` : ""}`;
|
|
75561
|
+
}, fixFor = (host, selector = "") => host === "pi" ? `pi update --extension ${selector || "npm:@brainervirus/workit-pi"}` : host === "codex" ? `codex plugin marketplace upgrade ${CODEX_MARKETPLACE} && codex plugin add workit@${CODEX_MARKETPLACE}` : host === "claude-code" ? "claude plugin marketplace update workit && claude plugin update workit@workit" : host === "opencode" ? OPENCODE_UPDATE : host === "cursor" ? "workit upgrade --hosts=cursor" : CLI_FIX, upgradePaths = (deps) => {
|
|
75344
75562
|
const home = deps.home ?? deps.env?.HOME ?? os16.homedir();
|
|
75345
75563
|
const env = {
|
|
75346
75564
|
...process.env,
|
|
75347
75565
|
...deps.home || deps.env?.HOME ? {
|
|
75348
75566
|
HOME: home,
|
|
75349
|
-
CODEX_HOME:
|
|
75350
|
-
CLAUDE_CONFIG_DIR:
|
|
75351
|
-
PI_CODING_AGENT_DIR:
|
|
75352
|
-
XDG_CONFIG_HOME:
|
|
75567
|
+
CODEX_HOME: path45.join(home, ".codex"),
|
|
75568
|
+
CLAUDE_CONFIG_DIR: path45.join(home, ".claude"),
|
|
75569
|
+
PI_CODING_AGENT_DIR: path45.join(home, ".pi/agent"),
|
|
75570
|
+
XDG_CONFIG_HOME: path45.join(home, ".config"),
|
|
75353
75571
|
WORKFLOW_TOOLKIT_CONFIG: undefined,
|
|
75354
75572
|
WORKFLOW_TOOLKIT_CONFIG_DIR: undefined
|
|
75355
75573
|
} : {},
|
|
75356
75574
|
...deps.env,
|
|
75357
75575
|
HOME: home
|
|
75358
75576
|
};
|
|
75359
|
-
const xdg = env.XDG_CONFIG_HOME ||
|
|
75360
|
-
const codexHome = env.CODEX_HOME ??
|
|
75577
|
+
const xdg = env.XDG_CONFIG_HOME || path45.join(home, ".config");
|
|
75578
|
+
const codexHome = env.CODEX_HOME ?? path45.join(home, ".codex");
|
|
75361
75579
|
return {
|
|
75362
75580
|
home,
|
|
75363
75581
|
env,
|
|
75364
|
-
configDir: env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ??
|
|
75365
|
-
opencodeConfig:
|
|
75366
|
-
piSettings:
|
|
75582
|
+
configDir: env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path45.join(xdg, "workit"),
|
|
75583
|
+
opencodeConfig: path45.join(xdg, "opencode/opencode.json"),
|
|
75584
|
+
piSettings: path45.join(env.PI_CODING_AGENT_DIR ?? path45.join(home, ".pi/agent"), "settings.json"),
|
|
75367
75585
|
codexHome,
|
|
75368
|
-
codexConfig:
|
|
75369
|
-
cursorRoot:
|
|
75586
|
+
codexConfig: path45.join(codexHome, "config.toml"),
|
|
75587
|
+
cursorRoot: path45.join(home, ".cursor/plugins/local/workit")
|
|
75370
75588
|
};
|
|
75371
75589
|
}, object2 = (file) => {
|
|
75372
75590
|
if (!existsSync21(file))
|
|
@@ -75391,11 +75609,11 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
|
|
|
75391
75609
|
let step;
|
|
75392
75610
|
try {
|
|
75393
75611
|
step = hostCommand(command, args, { home, env });
|
|
75394
|
-
} catch {
|
|
75395
|
-
return { status: 1, stdout: "" };
|
|
75612
|
+
} catch (error) {
|
|
75613
|
+
return { status: 1, stdout: "", stderr: errorText(error) };
|
|
75396
75614
|
}
|
|
75397
75615
|
const result = runHostCommand(step, { home, env });
|
|
75398
|
-
return { status: result.exitCode, stdout: result.stdout };
|
|
75616
|
+
return { status: result.exitCode, stdout: result.stdout, stderr: result.stderr };
|
|
75399
75617
|
}), COMMAND_TIMEOUT_MS = 60000, asyncRunner = (deps) => {
|
|
75400
75618
|
if (deps.runAsync)
|
|
75401
75619
|
return deps.runAsync;
|
|
@@ -75407,37 +75625,42 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
|
|
|
75407
75625
|
let step;
|
|
75408
75626
|
try {
|
|
75409
75627
|
step = hostCommand(command, args, { home, env });
|
|
75410
|
-
} catch {
|
|
75411
|
-
return Promise.resolve({ status: 1, stdout: "" });
|
|
75628
|
+
} catch (error) {
|
|
75629
|
+
return Promise.resolve({ status: 1, stdout: "", stderr: errorText(error) });
|
|
75412
75630
|
}
|
|
75413
75631
|
if (process.platform === "win32" && /\.(?:cmd|bat)$/i.test(step.command))
|
|
75414
|
-
return Promise.resolve({
|
|
75632
|
+
return Promise.resolve({
|
|
75633
|
+
status: 1,
|
|
75634
|
+
stdout: "",
|
|
75635
|
+
stderr: `Cannot safely execute batch shim ${step.command}`
|
|
75636
|
+
});
|
|
75415
75637
|
const childEnv = { ...process.env, ...env, HOME: home };
|
|
75416
|
-
childEnv.CODEX_HOME = env.CODEX_HOME ??
|
|
75417
|
-
childEnv.PI_CODING_AGENT_DIR = env.PI_CODING_AGENT_DIR ??
|
|
75418
|
-
childEnv.CLAUDE_CONFIG_DIR = env.CLAUDE_CONFIG_DIR ??
|
|
75419
|
-
childEnv.XDG_CONFIG_HOME = env.XDG_CONFIG_HOME ??
|
|
75638
|
+
childEnv.CODEX_HOME = env.CODEX_HOME ?? path45.join(home, ".codex");
|
|
75639
|
+
childEnv.PI_CODING_AGENT_DIR = env.PI_CODING_AGENT_DIR ?? path45.join(home, ".pi", "agent");
|
|
75640
|
+
childEnv.CLAUDE_CONFIG_DIR = env.CLAUDE_CONFIG_DIR ?? path45.join(home, ".claude");
|
|
75641
|
+
childEnv.XDG_CONFIG_HOME = env.XDG_CONFIG_HOME ?? path45.join(home, ".config");
|
|
75420
75642
|
return new Promise((resolve) => {
|
|
75421
75643
|
let stdout = "";
|
|
75644
|
+
let stderr = "";
|
|
75422
75645
|
let settled = false;
|
|
75423
75646
|
const finish = (status) => {
|
|
75424
75647
|
if (settled)
|
|
75425
75648
|
return;
|
|
75426
75649
|
settled = true;
|
|
75427
75650
|
clearTimeout(timer);
|
|
75428
|
-
resolve({ status, stdout });
|
|
75651
|
+
resolve({ status, stdout, stderr });
|
|
75429
75652
|
};
|
|
75430
75653
|
let child;
|
|
75431
75654
|
try {
|
|
75432
|
-
child =
|
|
75655
|
+
child = spawn2(step.command, step.args, {
|
|
75433
75656
|
cwd: step.cwd,
|
|
75434
75657
|
env: childEnv,
|
|
75435
|
-
stdio: ["ignore", "pipe", "
|
|
75658
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
75436
75659
|
windowsHide: true,
|
|
75437
75660
|
shell: false
|
|
75438
75661
|
});
|
|
75439
|
-
} catch {
|
|
75440
|
-
resolve({ status: 1, stdout: "" });
|
|
75662
|
+
} catch (error) {
|
|
75663
|
+
resolve({ status: 1, stdout: "", stderr: errorText(error) });
|
|
75441
75664
|
return;
|
|
75442
75665
|
}
|
|
75443
75666
|
const timer = setTimeout(() => {
|
|
@@ -75446,16 +75669,21 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
|
|
|
75446
75669
|
}, COMMAND_TIMEOUT_MS);
|
|
75447
75670
|
child.stdout?.setEncoding("utf8");
|
|
75448
75671
|
child.stdout?.on("data", (chunk) => stdout += chunk);
|
|
75449
|
-
child.
|
|
75672
|
+
child.stderr?.setEncoding("utf8");
|
|
75673
|
+
child.stderr?.on("data", (chunk) => stderr = (stderr + chunk).slice(-4000));
|
|
75674
|
+
child.on("error", (error) => {
|
|
75675
|
+
stderr += error.message;
|
|
75676
|
+
finish(1);
|
|
75677
|
+
});
|
|
75450
75678
|
child.on("close", (code) => finish(code ?? 1));
|
|
75451
75679
|
});
|
|
75452
75680
|
};
|
|
75453
|
-
},
|
|
75681
|
+
}, piInstalledVersion = (listing, selector) => {
|
|
75454
75682
|
const lines = listing.split(/\r?\n/).map((line) => line.trim());
|
|
75455
75683
|
const index = lines.indexOf(selector);
|
|
75456
|
-
if (index < 0 || !lines[index + 1] || !
|
|
75684
|
+
if (index < 0 || !lines[index + 1] || !path45.isAbsolute(lines[index + 1]))
|
|
75457
75685
|
return;
|
|
75458
|
-
const found = objectOrNull(
|
|
75686
|
+
const found = objectOrNull(path45.join(lines[index + 1], "package.json"));
|
|
75459
75687
|
return found?.name === "@brainervirus/workit-pi" ? found.version : undefined;
|
|
75460
75688
|
}, versionAtLeast = (installed, latest) => {
|
|
75461
75689
|
if (!/^\d+\.\d+\.\d+$/.test(installed))
|
|
@@ -75481,12 +75709,12 @@ var init_shared = __esm(() => {
|
|
|
75481
75709
|
});
|
|
75482
75710
|
|
|
75483
75711
|
// packages/workit-cli/src/upgrade/processes.ts
|
|
75484
|
-
import
|
|
75712
|
+
import path46 from "node:path";
|
|
75485
75713
|
var PROCESS_HOSTS, SCRIPT_RUNTIMES, classifyProcess = (proc) => {
|
|
75486
75714
|
if (proc.state.startsWith("Z") || proc.args.includes("<defunct>"))
|
|
75487
75715
|
return null;
|
|
75488
75716
|
const argv0 = proc.args.trim().split(/\s+/)[0] ?? "";
|
|
75489
|
-
const baseName = (value) =>
|
|
75717
|
+
const baseName = (value) => path46.basename(value.replaceAll("\\", "/")).replace(/^\[|\]$/g, "").replace(/\.exe$/i, "").toLowerCase();
|
|
75490
75718
|
let host = PROCESS_HOSTS[baseName(argv0)];
|
|
75491
75719
|
if (!host && SCRIPT_RUNTIMES.has(baseName(argv0))) {
|
|
75492
75720
|
const script = proc.args.trim().split(/\s+/).slice(1).find((arg) => !arg.startsWith("-"));
|
|
@@ -75537,7 +75765,7 @@ var init_processes = __esm(() => {
|
|
|
75537
75765
|
|
|
75538
75766
|
// packages/workit-cli/src/upgrade/apply.ts
|
|
75539
75767
|
import { existsSync as existsSync22, readdirSync as readdirSync12, mkdirSync as mkdirSync11, copyFileSync as copyFileSync6, chmodSync as chmodSync2, cpSync as cpSync5 } from "node:fs";
|
|
75540
|
-
import
|
|
75768
|
+
import path47 from "node:path";
|
|
75541
75769
|
import { createHash as createHash16 } from "node:crypto";
|
|
75542
75770
|
async function applyUpgrade(plan, deps = {}) {
|
|
75543
75771
|
const hosts = [...plan.failed];
|
|
@@ -75572,11 +75800,11 @@ async function applyUpgrade(plan, deps = {}) {
|
|
|
75572
75800
|
};
|
|
75573
75801
|
const paths = upgradePaths(deps);
|
|
75574
75802
|
const { home, configDir } = paths;
|
|
75575
|
-
const backup =
|
|
75803
|
+
const backup = path47.join(home, ".local/state/workit/upgrades", new Date().toISOString().replaceAll(":", "-"));
|
|
75576
75804
|
mkdirSync11(backup, { recursive: true, mode: 448 });
|
|
75577
75805
|
for (const file of Object.keys(plan.configDigests))
|
|
75578
75806
|
if (existsSync22(file)) {
|
|
75579
|
-
const target =
|
|
75807
|
+
const target = path47.join(backup, createHash16("sha256").update(file).digest("hex").slice(0, 12) + "-" + path47.basename(file));
|
|
75580
75808
|
copyFileSync6(file, target);
|
|
75581
75809
|
chmodSync2(target, 384);
|
|
75582
75810
|
}
|
|
@@ -75593,14 +75821,13 @@ async function applyUpgrade(plan, deps = {}) {
|
|
|
75593
75821
|
writeFileAtomic(migration.file, JSON.stringify(value, null, 2) + `
|
|
75594
75822
|
`, 384);
|
|
75595
75823
|
}
|
|
75596
|
-
const run = runner(deps);
|
|
75597
75824
|
const runAsync = asyncRunner(deps);
|
|
75598
75825
|
const progress = deps.progress ?? createProgress({ json: true });
|
|
75599
75826
|
const statusOf = (outcome) => outcome?.status === "failed" ? "failed" : outcome?.status === "updated" ? "done" : "skipped";
|
|
75600
75827
|
let cursorBackupError = null;
|
|
75601
75828
|
if (plan.entries.some((entry) => entry.host === "cursor") && existsSync22(paths.cursorRoot))
|
|
75602
75829
|
try {
|
|
75603
|
-
cpSync5(paths.cursorRoot,
|
|
75830
|
+
cpSync5(paths.cursorRoot, path47.join(backup, "cursor-package"), {
|
|
75604
75831
|
recursive: true
|
|
75605
75832
|
});
|
|
75606
75833
|
} catch (error) {
|
|
@@ -75649,14 +75876,14 @@ async function applyUpgrade(plan, deps = {}) {
|
|
|
75649
75876
|
hosts.push({
|
|
75650
75877
|
host: "codex",
|
|
75651
75878
|
status: "failed",
|
|
75652
|
-
reason: `could not stop the Codex app-server daemon (${daemons.map(describe2).join("; ")})`,
|
|
75879
|
+
reason: `could not stop the Codex app-server daemon (${daemons.map(describe2).join("; ")})${stderrTail(stopped.stderr) ? `: ${stderrTail(stopped.stderr)}` : ""}`,
|
|
75653
75880
|
fix: "codex app-server daemon stop && workit upgrade --hosts=codex"
|
|
75654
75881
|
});
|
|
75655
75882
|
continue;
|
|
75656
75883
|
}
|
|
75657
75884
|
let outcome;
|
|
75658
75885
|
try {
|
|
75659
|
-
outcome = await applyEntry(entry, {
|
|
75886
|
+
outcome = await applyEntry(entry, { runAsync, paths, configDir });
|
|
75660
75887
|
if (entry.host === "codex" && outcome.status === "updated") {
|
|
75661
75888
|
const agents = await refreshCodexAgents(runAsync, paths.codexHome);
|
|
75662
75889
|
if (!agents.ok)
|
|
@@ -75667,7 +75894,10 @@ async function applyUpgrade(plan, deps = {}) {
|
|
|
75667
75894
|
fix: agents.fix
|
|
75668
75895
|
};
|
|
75669
75896
|
else if (agents.note)
|
|
75670
|
-
outcome = {
|
|
75897
|
+
outcome = {
|
|
75898
|
+
...outcome,
|
|
75899
|
+
reason: `${outcome.reason}; ${agents.note}`
|
|
75900
|
+
};
|
|
75671
75901
|
}
|
|
75672
75902
|
} catch (error) {
|
|
75673
75903
|
outcome = {
|
|
@@ -75741,8 +75971,11 @@ async function applyUpgrade(plan, deps = {}) {
|
|
|
75741
75971
|
}
|
|
75742
75972
|
return done(backup);
|
|
75743
75973
|
}
|
|
75744
|
-
var
|
|
75745
|
-
const
|
|
75974
|
+
var briefDetail = (detail) => {
|
|
75975
|
+
const lines = detail.split(/\r?\n/).filter((line) => line.trim());
|
|
75976
|
+
return (lines.length > 6 ? [lines[0], ...lines.slice(-5)] : lines).join(" | ");
|
|
75977
|
+
}, codexPluginRoot = (codexHome) => {
|
|
75978
|
+
const dir = path47.join(codexHome, "plugins", "cache", CODEX_MARKETPLACE, "workit");
|
|
75746
75979
|
let versions = [];
|
|
75747
75980
|
try {
|
|
75748
75981
|
versions = readdirSync12(dir).filter((version) => /^\d+\.\d+\.\d+$/.test(version));
|
|
@@ -75750,7 +75983,7 @@ var codexPluginRoot = (codexHome) => {
|
|
|
75750
75983
|
return null;
|
|
75751
75984
|
}
|
|
75752
75985
|
const newest = versions.reduce((best, version) => best && versionAtLeast(best, version) ? best : version, null);
|
|
75753
|
-
return newest ?
|
|
75986
|
+
return newest ? path47.join(dir, newest) : null;
|
|
75754
75987
|
}, opencodeVersion = async (run) => {
|
|
75755
75988
|
const listing = await run("opencode", ["plugin", "list"]);
|
|
75756
75989
|
if (listing.status !== 0)
|
|
@@ -75766,7 +75999,7 @@ var codexPluginRoot = (codexHome) => {
|
|
|
75766
75999
|
}
|
|
75767
76000
|
return;
|
|
75768
76001
|
}, applyEntry = async (entry, context) => {
|
|
75769
|
-
const {
|
|
76002
|
+
const { runAsync, paths, configDir } = context;
|
|
75770
76003
|
const { home, env } = paths;
|
|
75771
76004
|
const fail = (reason) => ({
|
|
75772
76005
|
host: entry.host,
|
|
@@ -75775,6 +76008,30 @@ var codexPluginRoot = (codexHome) => {
|
|
|
75775
76008
|
fix: entry.fix
|
|
75776
76009
|
});
|
|
75777
76010
|
if (entry.host === "cursor") {
|
|
76011
|
+
const commands = entry.commands.map((command) => ({
|
|
76012
|
+
...command,
|
|
76013
|
+
purpose: command.purpose ?? "Upgrade Cursor"
|
|
76014
|
+
}));
|
|
76015
|
+
const recorded = new Map;
|
|
76016
|
+
let history = "";
|
|
76017
|
+
for (const command of commands) {
|
|
76018
|
+
if (command.skipWhenOutputIncludes && history.includes(command.skipWhenOutputIncludes))
|
|
76019
|
+
continue;
|
|
76020
|
+
const outcome = await runAsync(command.command, command.args);
|
|
76021
|
+
const result = {
|
|
76022
|
+
exitCode: outcome.status ?? 1,
|
|
76023
|
+
stdout: outcome.stdout,
|
|
76024
|
+
stderr: outcome.stderr ?? ""
|
|
76025
|
+
};
|
|
76026
|
+
recorded.set(command, result);
|
|
76027
|
+
history += `
|
|
76028
|
+
${result.stdout}
|
|
76029
|
+
${result.stderr}`;
|
|
76030
|
+
if (result.exitCode !== 0)
|
|
76031
|
+
break;
|
|
76032
|
+
}
|
|
76033
|
+
const cursorSettings = path47.join(home, ".cursor", "settings.json");
|
|
76034
|
+
const cursorMcp = path47.join(home, ".cursor", "mcp.json");
|
|
75778
76035
|
const preview = {
|
|
75779
76036
|
ok: true,
|
|
75780
76037
|
blocked: [],
|
|
@@ -75786,13 +76043,12 @@ var codexPluginRoot = (codexHome) => {
|
|
|
75786
76043
|
{
|
|
75787
76044
|
type: "install-host",
|
|
75788
76045
|
platform: "cursor",
|
|
75789
|
-
path:
|
|
75790
|
-
commands
|
|
75791
|
-
...command,
|
|
75792
|
-
purpose: command.purpose ?? "Upgrade Cursor"
|
|
75793
|
-
}))
|
|
76046
|
+
path: path47.join(home, ".cursor/plugins/local/.workit-package-bootstrap"),
|
|
76047
|
+
commands
|
|
75794
76048
|
},
|
|
75795
|
-
{ type: "install-adapter", platform: "cursor", path: paths.cursorRoot }
|
|
76049
|
+
{ type: "install-adapter", platform: "cursor", path: paths.cursorRoot },
|
|
76050
|
+
{ type: "register-platform", platform: "cursor", path: cursorSettings },
|
|
76051
|
+
{ type: "register-platform", platform: "cursor", path: cursorMcp }
|
|
75796
76052
|
]
|
|
75797
76053
|
};
|
|
75798
76054
|
const result = applySetupPreview(preview, {
|
|
@@ -75800,16 +76056,16 @@ var codexPluginRoot = (codexHome) => {
|
|
|
75800
76056
|
env,
|
|
75801
76057
|
cwd: home,
|
|
75802
76058
|
preferInstalledAdapter: true,
|
|
75803
|
-
runHostCommand: (command) => {
|
|
75804
|
-
|
|
75805
|
-
|
|
75806
|
-
|
|
75807
|
-
stdout: outcome.stdout,
|
|
75808
|
-
stderr: ""
|
|
75809
|
-
};
|
|
76059
|
+
runHostCommand: (command) => recorded.get(command) ?? {
|
|
76060
|
+
exitCode: 1,
|
|
76061
|
+
stdout: "",
|
|
76062
|
+
stderr: "command did not run"
|
|
75810
76063
|
}
|
|
75811
76064
|
});
|
|
75812
|
-
const installed = objectOrNull(
|
|
76065
|
+
const installed = objectOrNull(path47.join(paths.cursorRoot, "package.json"));
|
|
76066
|
+
const problems = result.entries.filter((one) => one.status === "Failed").map((one) => one.detail ?? `${one.file} failed`);
|
|
76067
|
+
if (problems.length)
|
|
76068
|
+
return fail(`Cursor install failed: ${problems.map(briefDetail).join("; ")}`);
|
|
75813
76069
|
if (!result.ok || installed?.version !== entry.latest)
|
|
75814
76070
|
return fail("Cursor install did not verify the requested package version; inspect the installer before retrying");
|
|
75815
76071
|
return {
|
|
@@ -75819,9 +76075,13 @@ var codexPluginRoot = (codexHome) => {
|
|
|
75819
76075
|
};
|
|
75820
76076
|
}
|
|
75821
76077
|
const before = entry.host === "opencode" ? await opencodeVersion(runAsync) : undefined;
|
|
75822
|
-
for (const command of entry.commands)
|
|
75823
|
-
|
|
75824
|
-
|
|
76078
|
+
for (const command of entry.commands) {
|
|
76079
|
+
let result = await runAsync(command.command, command.args);
|
|
76080
|
+
if (result.status !== 0 && entry.host === "opencode")
|
|
76081
|
+
result = await runAsync(command.command, command.args);
|
|
76082
|
+
if (result.status !== 0)
|
|
76083
|
+
return fail(failureReason(command, result));
|
|
76084
|
+
}
|
|
75825
76085
|
if (entry.host === "opencode") {
|
|
75826
76086
|
const after = await opencodeVersion(runAsync);
|
|
75827
76087
|
if (before && after)
|
|
@@ -75854,7 +76114,7 @@ var codexPluginRoot = (codexHome) => {
|
|
|
75854
76114
|
}
|
|
75855
76115
|
const verify = entry.host === "codex" ? await runAsync("codex", ["plugin", "list", "--json"]) : await runAsync("pi", ["list"]);
|
|
75856
76116
|
if (verify.status !== 0)
|
|
75857
|
-
return fail(
|
|
76117
|
+
return fail(`update verification failed${stderrTail(verify.stderr) ? `: ${stderrTail(verify.stderr)}` : ""}`);
|
|
75858
76118
|
if (entry.host === "codex") {
|
|
75859
76119
|
let installed = [];
|
|
75860
76120
|
try {
|
|
@@ -75872,11 +76132,16 @@ var codexPluginRoot = (codexHome) => {
|
|
|
75872
76132
|
};
|
|
75873
76133
|
}, refreshCodexAgents = async (run, codexHome) => {
|
|
75874
76134
|
const root = codexPluginRoot(codexHome);
|
|
75875
|
-
const launcher = root &&
|
|
76135
|
+
const launcher = root && path47.join(root, "dist", "launch-mcp.js");
|
|
75876
76136
|
if (!launcher || !existsSync22(launcher))
|
|
75877
76137
|
return { ok: true, note: "" };
|
|
75878
76138
|
const fix = `node ${JSON.stringify(launcher)} --install-agents`;
|
|
75879
|
-
|
|
76139
|
+
const refreshed = await run("node", [launcher, "--install-agents"]);
|
|
76140
|
+
return refreshed.status === 0 ? { ok: true, note: "agents refreshed" } : {
|
|
76141
|
+
ok: false,
|
|
76142
|
+
note: `agent refresh failed${stderrTail(refreshed.stderr) ? `: ${stderrTail(refreshed.stderr)}` : ""}`,
|
|
76143
|
+
fix
|
|
76144
|
+
};
|
|
75880
76145
|
}, applyCli = async (cli, run, backup) => {
|
|
75881
76146
|
const fail = (reason) => ({
|
|
75882
76147
|
host: "cli",
|
|
@@ -75887,13 +76152,18 @@ var codexPluginRoot = (codexHome) => {
|
|
|
75887
76152
|
const currentRoot = await run("npm", ["root", "--global"]);
|
|
75888
76153
|
if (currentRoot.status !== 0 || currentRoot.stdout.trim() !== cli.root)
|
|
75889
76154
|
return fail("Global npm location changed; preview again");
|
|
75890
|
-
const cliBackup =
|
|
75891
|
-
cpSync5(
|
|
76155
|
+
const cliBackup = path47.join(backup, "cli-package");
|
|
76156
|
+
cpSync5(path47.join(cli.root, "@brainervirus/workit-cli"), cliBackup, {
|
|
75892
76157
|
recursive: true
|
|
75893
76158
|
});
|
|
75894
|
-
|
|
75895
|
-
|
|
75896
|
-
|
|
76159
|
+
const install = await run("npm", [
|
|
76160
|
+
"install",
|
|
76161
|
+
"--global",
|
|
76162
|
+
`@brainervirus/workit-cli@${cli.latest}`
|
|
76163
|
+
]);
|
|
76164
|
+
if (install.status !== 0)
|
|
76165
|
+
return fail(`CLI update failed${stderrTail(install.stderr) ? ` (${stderrTail(install.stderr)})` : ""}; preserved package at ${cliBackup}; use npm to repair or run node ${path47.join(cliBackup, "dist/index.js")}`);
|
|
76166
|
+
const installed = objectOrNull(path47.join(cli.root, "@brainervirus/workit-cli/package.json"));
|
|
75897
76167
|
if (installed?.name !== "@brainervirus/workit-cli" || installed.version !== cli.latest)
|
|
75898
76168
|
return fail(`CLI update did not verify the requested version; preserved package at ${cliBackup}`);
|
|
75899
76169
|
return {
|
|
@@ -75914,7 +76184,7 @@ var init_apply = __esm(() => {
|
|
|
75914
76184
|
|
|
75915
76185
|
// packages/workit-cli/src/upgrade/plan.ts
|
|
75916
76186
|
import { existsSync as existsSync23, mkdtempSync as mkdtempSync3, rmSync as rmSync8, lstatSync as lstatSync8, readFileSync as readFileSync23 } from "node:fs";
|
|
75917
|
-
import
|
|
76187
|
+
import path48 from "node:path";
|
|
75918
76188
|
import os17 from "node:os";
|
|
75919
76189
|
function previewUpgrade(hosts = HOSTS2, deps = {}) {
|
|
75920
76190
|
const paths = upgradePaths(deps);
|
|
@@ -75938,9 +76208,9 @@ function previewUpgrade(hosts = HOSTS2, deps = {}) {
|
|
|
75938
76208
|
for (const file of [
|
|
75939
76209
|
paths.opencodeConfig,
|
|
75940
76210
|
paths.opencodeConfig + "c",
|
|
75941
|
-
|
|
75942
|
-
|
|
75943
|
-
|
|
76211
|
+
path48.join(home, ".cursor/settings.json"),
|
|
76212
|
+
path48.join(home, ".cursor/mcp.json"),
|
|
76213
|
+
path48.join(paths.cursorRoot, "package.json"),
|
|
75944
76214
|
paths.codexConfig,
|
|
75945
76215
|
paths.piSettings
|
|
75946
76216
|
])
|
|
@@ -76110,8 +76380,8 @@ var codexRegistered = (configFile) => {
|
|
|
76110
76380
|
result.push(classify("opencode", pin));
|
|
76111
76381
|
});
|
|
76112
76382
|
guard("cursor", () => {
|
|
76113
|
-
const cursor = objectOrNull(
|
|
76114
|
-
const mcp = objectOrNull(
|
|
76383
|
+
const cursor = objectOrNull(path48.join(paths.cursorRoot, "package.json"));
|
|
76384
|
+
const mcp = objectOrNull(path48.join(home, ".cursor/mcp.json"));
|
|
76115
76385
|
const args = mcp?.mcpServers?.workit?.args ?? [];
|
|
76116
76386
|
const arg = args.find((value) => typeof value === "string" && value.startsWith("--package="));
|
|
76117
76387
|
const selector = typeof arg === "string" ? arg.slice(10) : "local";
|
|
@@ -76122,7 +76392,7 @@ var codexRegistered = (configFile) => {
|
|
|
76122
76392
|
});
|
|
76123
76393
|
return;
|
|
76124
76394
|
}
|
|
76125
|
-
const settings = objectOrNull(
|
|
76395
|
+
const settings = objectOrNull(path48.join(home, ".cursor/settings.json"));
|
|
76126
76396
|
const dirs = Array.isArray(settings?.plugin_dirs) ? settings.plugin_dirs : [];
|
|
76127
76397
|
const registered = mcp?.mcpServers?.workit !== undefined || dirs.some((dir) => String(dir).replaceAll("\\", "/").replace(/\/+$/, "").endsWith("local/workit"));
|
|
76128
76398
|
if (registered)
|
|
@@ -76137,7 +76407,7 @@ var codexRegistered = (configFile) => {
|
|
|
76137
76407
|
if (typeof source !== "string")
|
|
76138
76408
|
continue;
|
|
76139
76409
|
const npm = /^(?:npm:)?@brainervirus\/workit-pi(?:@[^/]+)?$/.test(source);
|
|
76140
|
-
const local =
|
|
76410
|
+
const local = path48.isAbsolute(source) && source.replaceAll("\\", "/").endsWith("/packages/workit-pi") && object2(path48.join(source, "package.json"))?.name === "@brainervirus/workit-pi";
|
|
76141
76411
|
if (!npm && !local)
|
|
76142
76412
|
continue;
|
|
76143
76413
|
const found = classify("pi", source);
|
|
@@ -76197,15 +76467,15 @@ var codexRegistered = (configFile) => {
|
|
|
76197
76467
|
});
|
|
76198
76468
|
return result;
|
|
76199
76469
|
}, opencodeProbe = (deps, args) => {
|
|
76200
|
-
const scratch = mkdtempSync3(
|
|
76470
|
+
const scratch = mkdtempSync3(path48.join(os17.tmpdir(), "workit-upgrade-opencode-"));
|
|
76201
76471
|
try {
|
|
76202
76472
|
return runner({
|
|
76203
76473
|
...deps,
|
|
76204
76474
|
env: {
|
|
76205
76475
|
...deps.env,
|
|
76206
|
-
XDG_DATA_HOME:
|
|
76207
|
-
XDG_STATE_HOME:
|
|
76208
|
-
XDG_CACHE_HOME:
|
|
76476
|
+
XDG_DATA_HOME: path48.join(scratch, "data"),
|
|
76477
|
+
XDG_STATE_HOME: path48.join(scratch, "state"),
|
|
76478
|
+
XDG_CACHE_HOME: path48.join(scratch, "cache")
|
|
76209
76479
|
}
|
|
76210
76480
|
})("opencode", args);
|
|
76211
76481
|
} finally {
|
|
@@ -76213,7 +76483,7 @@ var codexRegistered = (configFile) => {
|
|
|
76213
76483
|
}
|
|
76214
76484
|
}, planCli = (plan, run) => {
|
|
76215
76485
|
const root = run("npm", ["root", "--global"]);
|
|
76216
|
-
if (root.status !== 0 || !
|
|
76486
|
+
if (root.status !== 0 || !path48.isAbsolute(root.stdout.trim())) {
|
|
76217
76487
|
plan.skipped.push({
|
|
76218
76488
|
host: "cli",
|
|
76219
76489
|
reason: "global npm location could not be verified",
|
|
@@ -76221,9 +76491,9 @@ var codexRegistered = (configFile) => {
|
|
|
76221
76491
|
});
|
|
76222
76492
|
return;
|
|
76223
76493
|
}
|
|
76224
|
-
const packageFile =
|
|
76494
|
+
const packageFile = path48.join(root.stdout.trim(), "@brainervirus/workit-cli/package.json");
|
|
76225
76495
|
const installed = objectOrNull(packageFile);
|
|
76226
|
-
if (installed?.name !== "@brainervirus/workit-cli" || lstatSync8(
|
|
76496
|
+
if (installed?.name !== "@brainervirus/workit-cli" || lstatSync8(path48.dirname(packageFile)).isSymbolicLink()) {
|
|
76227
76497
|
plan.skipped.push({
|
|
76228
76498
|
host: "cli",
|
|
76229
76499
|
reason: "no managed global CLI install (local links preserved); use npx @brainervirus/workit-cli@latest"
|
|
@@ -76261,33 +76531,44 @@ var init_plan = __esm(() => {
|
|
|
76261
76531
|
});
|
|
76262
76532
|
|
|
76263
76533
|
// packages/workit-cli/src/upgrade/report.ts
|
|
76264
|
-
var pad2 = (text) => text.padEnd(12), summary = (plan, permissions) => {
|
|
76265
|
-
const
|
|
76534
|
+
var pad2 = (text) => text.padEnd(12), PLAIN, summary = (plan, permissions, style = PLAIN) => {
|
|
76535
|
+
const host = (name) => ` ${style.bold(pad2(name))}`;
|
|
76536
|
+
const run = (fix) => fix ? ` (run: ${style.command(fix)})` : "";
|
|
76537
|
+
const version = (from, to) => `update ${style.dim(from)} -> ${style.ok(to)}`;
|
|
76538
|
+
const lines = [style.bold("Workit upgrade plan:")];
|
|
76266
76539
|
if (plan.cli)
|
|
76267
|
-
lines.push(
|
|
76540
|
+
lines.push(`${host("cli")}${version(plan.cli.installed, plan.cli.latest)}`);
|
|
76268
76541
|
for (const entry of plan.entries) {
|
|
76269
|
-
const what = entry.repair ? `reinstall missing plugin files (${entry.latest})` : entry.latest ?
|
|
76270
|
-
lines.push(
|
|
76542
|
+
const what = entry.repair ? `reinstall missing plugin files (${entry.latest})` : entry.latest ? version(entry.installedVersion ?? "?", entry.latest) : `update (${style.command(entry.commands.map((c) => `${c.command} ${c.args.join(" ")}`).join(" && "))})`;
|
|
76543
|
+
lines.push(`${host(entry.host)}${what}`);
|
|
76271
76544
|
}
|
|
76272
76545
|
for (const skipped of plan.skipped)
|
|
76273
|
-
lines.push(
|
|
76546
|
+
lines.push(`${host(skipped.host)}${skipped.reason.startsWith("already current") ? style.dim(skipped.reason) : `${style.warn("skip:")} ${skipped.reason}`}${run(skipped.fix)}`);
|
|
76274
76547
|
for (const failed of plan.failed)
|
|
76275
|
-
lines.push(
|
|
76548
|
+
lines.push(`${host(failed.host)}${style.fail("cannot upgrade:")} ${failed.reason}${run(failed.fix)}`);
|
|
76276
76549
|
for (const migration of plan.migrations)
|
|
76277
|
-
lines.push(
|
|
76550
|
+
lines.push(`${host("config")}${migration.description}`);
|
|
76278
76551
|
for (const change of permissions)
|
|
76279
|
-
lines.push(
|
|
76552
|
+
lines.push(`${host("permissions")}refresh the ${change.host} block in ${style.path(change.file)}`);
|
|
76280
76553
|
for (const blocked of plan.blocked)
|
|
76281
|
-
lines.push(` blocked: ${blocked}`);
|
|
76554
|
+
lines.push(` ${style.fail("blocked:")} ${blocked}`);
|
|
76282
76555
|
for (const warning of plan.warnings ?? [])
|
|
76283
|
-
lines.push(` warning: ${warning}`);
|
|
76556
|
+
lines.push(` ${style.warn("warning:")} ${warning}`);
|
|
76284
76557
|
return lines.join(`
|
|
76285
76558
|
`) + `
|
|
76286
76559
|
`;
|
|
76287
|
-
}, LABEL,
|
|
76288
|
-
|
|
76289
|
-
|
|
76290
|
-
|
|
76560
|
+
}, LABEL, reasonFor = (entry) => {
|
|
76561
|
+
const label = LABEL[entry.status];
|
|
76562
|
+
const head = entry.reason.slice(0, label.length);
|
|
76563
|
+
return entry.status !== "failed" && head.toLowerCase() === label.toLowerCase() && !/^[a-z]/i.test(entry.reason[label.length] ?? "") ? entry.reason.slice(label.length).replace(/^[\s:;,-]+/, "") : entry.reason;
|
|
76564
|
+
}, PAINT, table = (hosts, style = PLAIN) => [
|
|
76565
|
+
style.bold("Result:"),
|
|
76566
|
+
...hosts.map((entry) => {
|
|
76567
|
+
const paint = style[PAINT[entry.status]];
|
|
76568
|
+
const reason = reasonFor(entry);
|
|
76569
|
+
return ` ${style.bold(pad2(entry.host))}${paint(LABEL[entry.status])}${" ".repeat(16 - LABEL[entry.status].length)}${entry.status === "current" ? style.dim(reason) : reason}${entry.fix && entry.status !== "updated" && entry.status !== "current" ? `
|
|
76570
|
+
${pad2("")}${"".padEnd(16)}fix: ${style.command(entry.fix)}` : ""}`;
|
|
76571
|
+
})
|
|
76291
76572
|
].join(`
|
|
76292
76573
|
`) + `
|
|
76293
76574
|
`, askConfirm = async (question, out) => {
|
|
@@ -76300,12 +76581,20 @@ var pad2 = (text) => text.padEnd(12), summary = (plan, permissions) => {
|
|
|
76300
76581
|
return /^y(?:es)?$/i.test((await askLine(question)).trim());
|
|
76301
76582
|
};
|
|
76302
76583
|
var init_report = __esm(() => {
|
|
76584
|
+
init_style();
|
|
76585
|
+
PLAIN = createStyle({ json: true });
|
|
76303
76586
|
LABEL = {
|
|
76304
76587
|
updated: "updated",
|
|
76305
76588
|
current: "already current",
|
|
76306
76589
|
skipped: "skipped",
|
|
76307
76590
|
failed: "FAILED"
|
|
76308
76591
|
};
|
|
76592
|
+
PAINT = {
|
|
76593
|
+
updated: "ok",
|
|
76594
|
+
current: "dim",
|
|
76595
|
+
skipped: "warn",
|
|
76596
|
+
failed: "fail"
|
|
76597
|
+
};
|
|
76309
76598
|
});
|
|
76310
76599
|
|
|
76311
76600
|
// packages/workit-cli/src/upgrade.ts
|
|
@@ -76337,6 +76626,11 @@ async function runUpgradeCommand(argv, deps = {}) {
|
|
|
76337
76626
|
});
|
|
76338
76627
|
plan.ok = plan.blocked.length === 0 && plan.failed.length === 0;
|
|
76339
76628
|
const { home, env } = upgradePaths(deps);
|
|
76629
|
+
const style = createStyle({
|
|
76630
|
+
stream: out === process.stdout ? process.stdout : undefined,
|
|
76631
|
+
env,
|
|
76632
|
+
json
|
|
76633
|
+
});
|
|
76340
76634
|
const permissions = planHostPermissions({
|
|
76341
76635
|
hosts: raw,
|
|
76342
76636
|
refreshOnly: true,
|
|
@@ -76354,7 +76648,7 @@ async function runUpgradeCommand(argv, deps = {}) {
|
|
|
76354
76648
|
};
|
|
76355
76649
|
const withPermissions = (value) => permissions.changes.length ? { ...value, permissions: permissionPreview } : value;
|
|
76356
76650
|
const applyCommand = `workit upgrade ${[...hostFlag === undefined ? [] : [`--hosts=${hostFlag}`], ...flags.has("--cli") ? ["--cli"] : [], "--yes"].join(" ")}`;
|
|
76357
|
-
const nothingChanged =
|
|
76651
|
+
const nothingChanged = `${style.dim("preview only; nothing changed.")} Apply with: ${style.command(applyCommand)}
|
|
76358
76652
|
`;
|
|
76359
76653
|
if (json && !legacy && !flags.has("--yes")) {
|
|
76360
76654
|
out.write(JSON.stringify(withPermissions(plan), null, 2) + `
|
|
@@ -76362,20 +76656,20 @@ async function runUpgradeCommand(argv, deps = {}) {
|
|
|
76362
76656
|
return plan.blocked.length ? 1 : 0;
|
|
76363
76657
|
}
|
|
76364
76658
|
if (!json)
|
|
76365
|
-
out.write(summary(plan, permissions.changes));
|
|
76659
|
+
out.write(summary(plan, permissions.changes, style));
|
|
76366
76660
|
if (flags.has("--preview")) {
|
|
76367
76661
|
out.write(nothingChanged);
|
|
76368
76662
|
return plan.blocked.length ? 1 : 0;
|
|
76369
76663
|
}
|
|
76370
76664
|
if (plan.blocked.length) {
|
|
76371
|
-
out.write(
|
|
76665
|
+
out.write(`${style.fail("Upgrade blocked:")} ${plan.blocked.join("; ")}
|
|
76372
76666
|
Nothing changed.
|
|
76373
76667
|
`);
|
|
76374
76668
|
return 1;
|
|
76375
76669
|
}
|
|
76376
76670
|
const work = plan.entries.length + plan.migrations.length + (plan.cli ? 1 : 0) + permissions.changes.length;
|
|
76377
76671
|
if (work > 0 && !flags.has("--yes") && !legacy) {
|
|
76378
|
-
const confirmed = await (deps.confirm ?? ((q) => askConfirm(q, out)))("Apply this upgrade? [y/N]
|
|
76672
|
+
const confirmed = await (deps.confirm ?? ((q) => askConfirm(q, out)))(`${style.bold("Apply this upgrade?")} [y/N] `);
|
|
76379
76673
|
if (!confirmed) {
|
|
76380
76674
|
out.write(nothingChanged);
|
|
76381
76675
|
return 0;
|
|
@@ -76393,9 +76687,9 @@ Nothing changed.
|
|
|
76393
76687
|
permissionsOk = written.every((entry) => entry.status === "written");
|
|
76394
76688
|
for (const entry of written)
|
|
76395
76689
|
result.hosts.push({
|
|
76396
|
-
host:
|
|
76690
|
+
host: "permissions",
|
|
76397
76691
|
status: entry.status === "written" ? "updated" : "failed",
|
|
76398
|
-
reason:
|
|
76692
|
+
reason: `${entry.host} block ${entry.status === "written" ? "refreshed" : entry.status} in ${entry.file}`,
|
|
76399
76693
|
...entry.status === "written" ? {} : { fix: `workit setup --hosts=${entry.host}` }
|
|
76400
76694
|
});
|
|
76401
76695
|
}
|
|
@@ -76414,19 +76708,19 @@ Nothing changed.
|
|
|
76414
76708
|
return failed ? 1 : 0;
|
|
76415
76709
|
}
|
|
76416
76710
|
if (result.error && result.hosts.every((h) => h.status !== "failed"))
|
|
76417
|
-
out.write(
|
|
76711
|
+
out.write(`${style.fail("Upgrade stopped:")} ${result.error}
|
|
76418
76712
|
`);
|
|
76419
|
-
out.write(table(result.hosts));
|
|
76713
|
+
out.write(table(result.hosts, style));
|
|
76420
76714
|
if (permissions.refused)
|
|
76421
|
-
out.write(`permissions: not refreshed: ${permissions.refused}
|
|
76715
|
+
out.write(`permissions: ${style.warn("not refreshed:")} ${permissions.refused}
|
|
76422
76716
|
`);
|
|
76423
76717
|
if (result.backup)
|
|
76424
|
-
out.write(`Backup: ${result.backup}
|
|
76718
|
+
out.write(`Backup: ${style.path(result.backup)}
|
|
76425
76719
|
`);
|
|
76426
|
-
out.write(left.length === 0 ?
|
|
76427
|
-
` :
|
|
76428
|
-
${left.map((check) => ` ${check.id}: ${check.detail}${check.fix ? `
|
|
76429
|
-
fix: ${check.fix}` : ""}`).join(`
|
|
76720
|
+
out.write(left.length === 0 ? `${style.ok("Verified:")} workit doctor is clean for versions, assets, agents and permissions.
|
|
76721
|
+
` : `${style.warn("Left after upgrade (workit doctor):")}
|
|
76722
|
+
${left.map((check) => ` ${style.bold(check.id)}: ${check.detail}${check.fix ? `
|
|
76723
|
+
fix: ${style.command(check.fix)}` : ""}`).join(`
|
|
76430
76724
|
`)}
|
|
76431
76725
|
`);
|
|
76432
76726
|
return failed ? 1 : 0;
|
|
@@ -76489,6 +76783,7 @@ var init_upgrade = __esm(() => {
|
|
|
76489
76783
|
init_doctor();
|
|
76490
76784
|
init_host_permissions();
|
|
76491
76785
|
init_progress();
|
|
76786
|
+
init_style();
|
|
76492
76787
|
init_apply();
|
|
76493
76788
|
init_plan();
|
|
76494
76789
|
init_report();
|
|
@@ -76521,7 +76816,7 @@ var init_launch = __esm(() => {
|
|
|
76521
76816
|
// packages/workit-core/src/knowledge.ts
|
|
76522
76817
|
import { spawnSync as spawnSync18 } from "node:child_process";
|
|
76523
76818
|
import fs20 from "node:fs";
|
|
76524
|
-
import
|
|
76819
|
+
import path49 from "node:path";
|
|
76525
76820
|
function lintKnowledge(root) {
|
|
76526
76821
|
const seen = new Set;
|
|
76527
76822
|
const unreadable = [];
|
|
@@ -76625,7 +76920,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
|
|
|
76625
76920
|
const end = lines.indexOf("---", 1);
|
|
76626
76921
|
return end === -1 ? lines : [...lines.slice(0, end + 1).map(() => ""), ...lines.slice(end + 1)];
|
|
76627
76922
|
}, read = (root, file) => {
|
|
76628
|
-
const full =
|
|
76923
|
+
const full = path49.join(root, file);
|
|
76629
76924
|
try {
|
|
76630
76925
|
fs20.lstatSync(full);
|
|
76631
76926
|
} catch {
|
|
@@ -76666,7 +76961,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
|
|
|
76666
76961
|
}
|
|
76667
76962
|
}, brokenLinks = (root, doc, tracked) => {
|
|
76668
76963
|
const findings = [];
|
|
76669
|
-
const base =
|
|
76964
|
+
const base = path49.dirname(path49.join(root, doc.file));
|
|
76670
76965
|
const missing = (target, line, how) => findings.push({
|
|
76671
76966
|
rule: "broken-link",
|
|
76672
76967
|
file: doc.file,
|
|
@@ -76685,7 +76980,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
|
|
|
76685
76980
|
const local = localTarget(target);
|
|
76686
76981
|
if (!local)
|
|
76687
76982
|
continue;
|
|
76688
|
-
const resolved = local.startsWith("/") ?
|
|
76983
|
+
const resolved = local.startsWith("/") ? path49.join(root, local) : path49.resolve(base, local);
|
|
76689
76984
|
if (!exists2(resolved))
|
|
76690
76985
|
missing(target, index + 1, "link");
|
|
76691
76986
|
}
|
|
@@ -76695,9 +76990,9 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
|
|
|
76695
76990
|
continue;
|
|
76696
76991
|
const relative = /^\.\.?\//.test(candidate);
|
|
76697
76992
|
const first = candidate.split("/")[0];
|
|
76698
|
-
if (!relative && !(tracked ? tracked.has(first) : exists2(
|
|
76993
|
+
if (!relative && !(tracked ? tracked.has(first) : exists2(path49.join(root, first))))
|
|
76699
76994
|
continue;
|
|
76700
|
-
const resolved = relative ?
|
|
76995
|
+
const resolved = relative ? path49.resolve(base, candidate) : path49.join(root, candidate);
|
|
76701
76996
|
if (!exists2(resolved))
|
|
76702
76997
|
missing(span, index + 1, "pointer");
|
|
76703
76998
|
}
|
|
@@ -76785,6 +77080,7 @@ var init_knowledge = __esm(() => {
|
|
|
76785
77080
|
// packages/workit-cli/src/verbs/doctor.ts
|
|
76786
77081
|
var exports_doctor = {};
|
|
76787
77082
|
__export(exports_doctor, {
|
|
77083
|
+
renderDoctor: () => renderDoctor,
|
|
76788
77084
|
run: () => run7
|
|
76789
77085
|
});
|
|
76790
77086
|
async function confirmForcedLockClear(root, args, io) {
|
|
@@ -76849,12 +77145,12 @@ async function run7(argv, io) {
|
|
|
76849
77145
|
};
|
|
76850
77146
|
}
|
|
76851
77147
|
}
|
|
76852
|
-
const report = runDoctor({
|
|
77148
|
+
const report = progressFor(io).runSync("Checking Workit (workit doctor)", () => runDoctor({
|
|
76853
77149
|
host: "cli",
|
|
76854
77150
|
cwd: io.cwd,
|
|
76855
77151
|
workspaceRoot: root,
|
|
76856
77152
|
cliVersion: package_default.version
|
|
76857
|
-
});
|
|
77153
|
+
}), (done) => done.ok ? "done" : "failed");
|
|
76858
77154
|
let knowledge = null;
|
|
76859
77155
|
try {
|
|
76860
77156
|
knowledge = lintKnowledge(root);
|
|
@@ -76886,30 +77182,73 @@ async function run7(argv, io) {
|
|
|
76886
77182
|
if (checksConfig && checksConfig.action !== "none")
|
|
76887
77183
|
io.stdout(`fix: checks config ${checksConfig.action}: ${checksConfig.detail}
|
|
76888
77184
|
`);
|
|
76889
|
-
|
|
77185
|
+
for (const line of renderDoctor(report, knowledgeLine, createStyle({ stream: io.terminals?.stdout, env: io.env, json: io.json })))
|
|
77186
|
+
io.stdout(`${line}
|
|
76890
77187
|
`);
|
|
77188
|
+
return report.exitCode;
|
|
77189
|
+
}
|
|
77190
|
+
function renderDoctor(report, knowledgeLine, style) {
|
|
77191
|
+
const summary = `passed ${report.summary.passed} / warned ${report.summary.warned} / failed ${report.summary.failed}`;
|
|
77192
|
+
const header = `workit doctor — ${report.ok ? "healthy" : "problems found"} (${report.offline ? "offline" : "online"})`;
|
|
77193
|
+
if (!style.enabled) {
|
|
77194
|
+
const lines = [header];
|
|
77195
|
+
for (const check of report.checks) {
|
|
77196
|
+
const mark = check.status === "fail" ? "FAIL" : check.status === "warn" ? "WARN" : "ok ";
|
|
77197
|
+
lines.push(`${mark} ${check.id} — ${check.detail}`);
|
|
77198
|
+
if (check.fix)
|
|
77199
|
+
lines.push(` fix: ${check.fix.replaceAll(`
|
|
77200
|
+
`, `
|
|
77201
|
+
`)}`);
|
|
77202
|
+
}
|
|
77203
|
+
return [...lines, knowledgeLine, summary];
|
|
77204
|
+
}
|
|
77205
|
+
const marks = {
|
|
77206
|
+
pass: style.ok("ok "),
|
|
77207
|
+
info: style.info("info"),
|
|
77208
|
+
warn: style.warn("WARN"),
|
|
77209
|
+
fail: style.fail("FAIL")
|
|
77210
|
+
};
|
|
77211
|
+
const idWidth = Math.min(ID_COLUMN, Math.max(0, ...report.checks.map((check) => check.id.length)));
|
|
77212
|
+
const column = 5 + idWidth + 2;
|
|
77213
|
+
const fixLines = (fix) => ` fix: ${fix.split(`
|
|
77214
|
+
`).map((line) => style.command(line)).join(`
|
|
77215
|
+
`)}`;
|
|
77216
|
+
const row = (check) => {
|
|
77217
|
+
const id = check.id.padEnd(idWidth);
|
|
77218
|
+
const used = 5 + id.length + 2;
|
|
77219
|
+
return `${marks[check.status]} ${style.bold(id)} ${wrap(check.detail, style.width, column, used)}`;
|
|
77220
|
+
};
|
|
77221
|
+
const lines = [
|
|
77222
|
+
`workit doctor — ${report.ok ? style.ok("healthy") : style.fail("problems found")} ${style.dim(`(${report.offline ? "offline" : "online"})`)}`
|
|
77223
|
+
];
|
|
76891
77224
|
for (const check of report.checks) {
|
|
76892
|
-
|
|
76893
|
-
io.stdout(`${mark} ${check.id} — ${check.detail}
|
|
76894
|
-
`);
|
|
77225
|
+
lines.push(row(check));
|
|
76895
77226
|
if (check.fix)
|
|
76896
|
-
|
|
76897
|
-
`, `
|
|
76898
|
-
`)}
|
|
76899
|
-
`);
|
|
77227
|
+
lines.push(fixLines(check.fix));
|
|
76900
77228
|
}
|
|
76901
|
-
|
|
76902
|
-
|
|
76903
|
-
|
|
76904
|
-
|
|
76905
|
-
|
|
77229
|
+
lines.push(style.dim(wrap(knowledgeLine, style.width, 5)));
|
|
77230
|
+
const attention = report.checks.filter((c) => c.status === "fail" || c.status === "warn");
|
|
77231
|
+
if (attention.length > 0) {
|
|
77232
|
+
lines.push("", style.bold("Needs attention:"));
|
|
77233
|
+
for (const check of attention) {
|
|
77234
|
+
lines.push(row(check));
|
|
77235
|
+
if (check.fix)
|
|
77236
|
+
lines.push(fixLines(check.fix));
|
|
77237
|
+
}
|
|
77238
|
+
}
|
|
77239
|
+
const paint = report.summary.failed > 0 ? style.fail : report.summary.warned > 0 ? style.warn : style.ok;
|
|
77240
|
+
lines.push(paint(summary));
|
|
77241
|
+
return lines;
|
|
76906
77242
|
}
|
|
77243
|
+
var ID_COLUMN = 28;
|
|
76907
77244
|
var init_doctor2 = __esm(() => {
|
|
76908
77245
|
init_package();
|
|
76909
77246
|
init_doctor();
|
|
76910
77247
|
init_knowledge();
|
|
76911
77248
|
init_store_lock();
|
|
76912
77249
|
init_output();
|
|
77250
|
+
init_progress();
|
|
77251
|
+
init_style();
|
|
76913
77252
|
init_prompt();
|
|
76914
77253
|
init_task();
|
|
76915
77254
|
});
|
|
@@ -77019,11 +77358,11 @@ var init_redact = __esm(() => {
|
|
|
77019
77358
|
});
|
|
77020
77359
|
|
|
77021
77360
|
// packages/workit-core/src/checks.ts
|
|
77022
|
-
import { spawn as
|
|
77361
|
+
import { spawn as spawn3, spawnSync as spawnSync19 } from "node:child_process";
|
|
77023
77362
|
import { createHash as createHash17 } from "node:crypto";
|
|
77024
77363
|
import fs21 from "node:fs";
|
|
77025
77364
|
import os18 from "node:os";
|
|
77026
|
-
import
|
|
77365
|
+
import path50 from "node:path";
|
|
77027
77366
|
import { StringDecoder } from "node:string_decoder";
|
|
77028
77367
|
function tailLines(text, lines = TAIL_LINES) {
|
|
77029
77368
|
const all = text.replace(/\r\n?/gu, `
|
|
@@ -77143,7 +77482,7 @@ function planSpawn(argv, options) {
|
|
|
77143
77482
|
return { file: argv[0], args: [], verbatim: false, shell: true };
|
|
77144
77483
|
if (options.platform !== "win32")
|
|
77145
77484
|
return { file: argv[0], args: argv.slice(1), verbatim: false, shell: false };
|
|
77146
|
-
const win =
|
|
77485
|
+
const win = path50.win32;
|
|
77147
77486
|
const isFile = options.isFile ?? ((file) => {
|
|
77148
77487
|
try {
|
|
77149
77488
|
return fs21.statSync(file).isFile();
|
|
@@ -77248,7 +77587,7 @@ function runCheckCommand(argv, options) {
|
|
|
77248
77587
|
shell: plan.shell
|
|
77249
77588
|
};
|
|
77250
77589
|
try {
|
|
77251
|
-
child =
|
|
77590
|
+
child = spawn3(plan.file, plan.args, spawnOptions);
|
|
77252
77591
|
} catch (error) {
|
|
77253
77592
|
finish(null, null, error.code ?? error.message);
|
|
77254
77593
|
return;
|
|
@@ -77305,10 +77644,10 @@ function runCheckCommand(argv, options) {
|
|
|
77305
77644
|
function storeLog(storeRoot, log) {
|
|
77306
77645
|
const digest = logDigest(log);
|
|
77307
77646
|
const ref = `blobs/logs/${digest.slice("sha256:".length)}.log`;
|
|
77308
|
-
const file =
|
|
77647
|
+
const file = path50.join(storeRoot, ref);
|
|
77309
77648
|
try {
|
|
77310
77649
|
if (!fs21.existsSync(file)) {
|
|
77311
|
-
fs21.mkdirSync(
|
|
77650
|
+
fs21.mkdirSync(path50.dirname(file), { recursive: true });
|
|
77312
77651
|
const temp = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
77313
77652
|
fs21.writeFileSync(temp, log, { mode: 384 });
|
|
77314
77653
|
fs21.renameSync(temp, file);
|
|
@@ -77321,7 +77660,7 @@ function storeLog(storeRoot, log) {
|
|
|
77321
77660
|
function pruneCheckLogs(storeRoot, options = {}) {
|
|
77322
77661
|
const limits = { ...LOG_RETENTION, ...options.retention };
|
|
77323
77662
|
const now = options.now ?? Date.now();
|
|
77324
|
-
const dir =
|
|
77663
|
+
const dir = path50.join(storeRoot, "blobs", "logs");
|
|
77325
77664
|
const report = { removed: 0, removedBytes: 0, kept: 0 };
|
|
77326
77665
|
let names;
|
|
77327
77666
|
try {
|
|
@@ -77331,7 +77670,7 @@ function pruneCheckLogs(storeRoot, options = {}) {
|
|
|
77331
77670
|
}
|
|
77332
77671
|
const files = names.flatMap((name) => {
|
|
77333
77672
|
try {
|
|
77334
|
-
const stat = fs21.statSync(
|
|
77673
|
+
const stat = fs21.statSync(path50.join(dir, name));
|
|
77335
77674
|
return stat.isFile() ? [{ name, size: stat.size, mtimeMs: stat.mtimeMs }] : [];
|
|
77336
77675
|
} catch {
|
|
77337
77676
|
return [];
|
|
@@ -77350,7 +77689,7 @@ function pruneCheckLogs(storeRoot, options = {}) {
|
|
|
77350
77689
|
continue;
|
|
77351
77690
|
if (!options.dryRun)
|
|
77352
77691
|
try {
|
|
77353
|
-
fs21.rmSync(
|
|
77692
|
+
fs21.rmSync(path50.join(dir, file.name), { force: true });
|
|
77354
77693
|
} catch {
|
|
77355
77694
|
continue;
|
|
77356
77695
|
}
|
|
@@ -77393,7 +77732,7 @@ async function run8(argv, io) {
|
|
|
77393
77732
|
const store = new TaskStore(workspaceRootFor({ cwd: io.cwd }));
|
|
77394
77733
|
const location = store.location();
|
|
77395
77734
|
const logs = location.ok ? pruneCheckLogs(location.data.dir, { dryRun }) : null;
|
|
77396
|
-
const result = store.collectGarbage({ dryRun, pruneRecovery });
|
|
77735
|
+
const result = progressFor(io).runSync("Collecting garbage", () => store.collectGarbage({ dryRun, pruneRecovery }), (r) => r.ok ? "done" : "failed");
|
|
77397
77736
|
if (!result.ok)
|
|
77398
77737
|
return emit(io, fail2(result.code === "busy" ? "busy" : "failed", `${result.code}: ${result.error}`, {
|
|
77399
77738
|
data: { code: result.code, details: result.details },
|
|
@@ -77418,6 +77757,7 @@ async function run8(argv, io) {
|
|
|
77418
77757
|
}
|
|
77419
77758
|
var megabytes = (bytes) => (bytes / 1048576).toFixed(1);
|
|
77420
77759
|
var init_gc = __esm(() => {
|
|
77760
|
+
init_progress();
|
|
77421
77761
|
init_checks3();
|
|
77422
77762
|
init_task_store();
|
|
77423
77763
|
init_output();
|
|
@@ -78002,12 +78342,12 @@ var init_workspace = __esm(() => {
|
|
|
78002
78342
|
|
|
78003
78343
|
// packages/workit-core/src/core/heavy-rules.ts
|
|
78004
78344
|
import fs22 from "node:fs";
|
|
78005
|
-
import
|
|
78345
|
+
import path51 from "node:path";
|
|
78006
78346
|
function gitTop(cwd) {
|
|
78007
|
-
for (let dir =
|
|
78008
|
-
if (fs22.existsSync(
|
|
78347
|
+
for (let dir = path51.resolve(cwd);; dir = path51.dirname(dir)) {
|
|
78348
|
+
if (fs22.existsSync(path51.join(dir, ".git")))
|
|
78009
78349
|
return dir;
|
|
78010
|
-
if (
|
|
78350
|
+
if (path51.dirname(dir) === dir)
|
|
78011
78351
|
return null;
|
|
78012
78352
|
}
|
|
78013
78353
|
}
|
|
@@ -78049,18 +78389,18 @@ var init_heavy_rules = () => {};
|
|
|
78049
78389
|
// packages/workit-core/src/core/heavy.ts
|
|
78050
78390
|
import fs23 from "node:fs";
|
|
78051
78391
|
import os19 from "node:os";
|
|
78052
|
-
import
|
|
78392
|
+
import path52 from "node:path";
|
|
78053
78393
|
function stateDir2(env, platform = process.platform) {
|
|
78054
78394
|
if (env.WORKFLOW_TOOLKIT_STATE)
|
|
78055
78395
|
return env.WORKFLOW_TOOLKIT_STATE;
|
|
78056
78396
|
if (env.XDG_STATE_HOME)
|
|
78057
|
-
return
|
|
78397
|
+
return path52.join(env.XDG_STATE_HOME, "workit");
|
|
78058
78398
|
const home = env.HOME || os19.homedir();
|
|
78059
78399
|
if (platform === "darwin")
|
|
78060
|
-
return
|
|
78400
|
+
return path52.join(home, "Library", "Application Support", "workit");
|
|
78061
78401
|
if (platform === "win32")
|
|
78062
|
-
return
|
|
78063
|
-
return
|
|
78402
|
+
return path52.join(env.LOCALAPPDATA ?? path52.join(home, "AppData", "Local"), "workit");
|
|
78403
|
+
return path52.join(home, ".local", "state", "workit");
|
|
78064
78404
|
}
|
|
78065
78405
|
function positional(words, from, values = PM_VALUES) {
|
|
78066
78406
|
let index = from;
|
|
@@ -78200,7 +78540,7 @@ function machinePatterns(env) {
|
|
|
78200
78540
|
return isRecord8(value) ? stringList2(value.patterns) : [];
|
|
78201
78541
|
}
|
|
78202
78542
|
function repoPatterns(cwd) {
|
|
78203
|
-
return repoHeavyCommands(gitTop(cwd) ??
|
|
78543
|
+
return repoHeavyCommands(gitTop(cwd) ?? path52.resolve(cwd));
|
|
78204
78544
|
}
|
|
78205
78545
|
function heavyLines(lines, options) {
|
|
78206
78546
|
const found = [];
|
|
@@ -78279,7 +78619,7 @@ function leaseRewrite(command) {
|
|
|
78279
78619
|
return null;
|
|
78280
78620
|
return `${prefix}workit check --heavy -- ${rest}`;
|
|
78281
78621
|
}
|
|
78282
|
-
var HEAVY_COMMANDS_FILE = "heavy-commands.json", heavyCommandsFile = (env) =>
|
|
78622
|
+
var HEAVY_COMMANDS_FILE = "heavy-commands.json", heavyCommandsFile = (env) => path52.join(stateDir2(env), HEAVY_COMMANDS_FILE), HEAVY_SCRIPT, INFO_FLAGS, WATCH_FLAG, WATCH_SCRIPT, sub = (...names) => new Set(names), TOOLS, PM_VALUES, baseName2 = (word) => (word?.split(/[\\/]/u).at(-1) ?? "").toLowerCase().replace(/\.(?:exe|cmd|bat|ps1)$/u, ""), WORKIT, PYTHONS, NPM_INSTALL, NPM_RUN, NPM_TEST, EXEC, globWord = (word) => new RegExp(`^${word.replace(/[.+?^${}()|[\]\\]/gu, "\\$&").replaceAll("*", ".*")}$`, "u"), matches2 = (matchers, words) => matchers.length <= words.length && matchers.every((matcher, index) => index === 0 ? matcher.test(words[0]) || matcher.test(baseName2(words[0])) : matcher.test(words[index])), readJson2 = (file) => {
|
|
78283
78623
|
try {
|
|
78284
78624
|
return JSON.parse(fs23.readFileSync(file, "utf8"));
|
|
78285
78625
|
} catch {
|
|
@@ -78426,7 +78766,7 @@ var init_heavy = __esm(() => {
|
|
|
78426
78766
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
78427
78767
|
import fs24 from "node:fs";
|
|
78428
78768
|
import os20 from "node:os";
|
|
78429
|
-
import
|
|
78769
|
+
import path53 from "node:path";
|
|
78430
78770
|
function memoryValue(value, host) {
|
|
78431
78771
|
const text = typeof value === "number" ? String(value) : typeof value === "string" ? value : "";
|
|
78432
78772
|
const percent = PERCENT.exec(text.trim());
|
|
@@ -78622,7 +78962,7 @@ function tryOnce(options, record, reclaimed) {
|
|
|
78622
78962
|
const text = `${JSON.stringify(record)}
|
|
78623
78963
|
`;
|
|
78624
78964
|
for (let slot = 0;slot < options.slots; slot += 1) {
|
|
78625
|
-
const file =
|
|
78965
|
+
const file = path53.join(options.dir, `slot-${slot}.json`);
|
|
78626
78966
|
for (let attempt = 0;attempt < 2; attempt += 1) {
|
|
78627
78967
|
try {
|
|
78628
78968
|
const fd = fs24.openSync(file, "wx", 384);
|
|
@@ -78667,7 +79007,7 @@ function leaseQueue(dir, probe = {}) {
|
|
|
78667
79007
|
}
|
|
78668
79008
|
const entries = [];
|
|
78669
79009
|
for (const name of names.filter((item) => item.endsWith(".json")).toSorted()) {
|
|
78670
|
-
const file =
|
|
79010
|
+
const file = path53.join(queueDir(dir), name);
|
|
78671
79011
|
const record = parseLease(readText5(file));
|
|
78672
79012
|
if (!record)
|
|
78673
79013
|
continue;
|
|
@@ -78683,9 +79023,9 @@ function leaseQueue(dir, probe = {}) {
|
|
|
78683
79023
|
function waitersAhead(options, own) {
|
|
78684
79024
|
let ahead = 0;
|
|
78685
79025
|
for (const entry of leaseQueue(options.dir, options.probe)) {
|
|
78686
|
-
if (
|
|
79026
|
+
if (path53.basename(entry.file) >= own)
|
|
78687
79027
|
break;
|
|
78688
|
-
if (!TICKET.test(
|
|
79028
|
+
if (!TICKET.test(path53.basename(entry.file)))
|
|
78689
79029
|
continue;
|
|
78690
79030
|
if (entry.stale && reclaim(entry.file, (current) => !current || staleReason(current, options.probe) !== null))
|
|
78691
79031
|
continue;
|
|
@@ -78697,7 +79037,7 @@ function liveHolders(options) {
|
|
|
78697
79037
|
return leaseSlots(options.dir, options.slots, options.probe).filter((slot) => slot.holder && !slot.stale).map((slot) => slot.holder);
|
|
78698
79038
|
}
|
|
78699
79039
|
function writeTicket(file, record) {
|
|
78700
|
-
fs24.mkdirSync(
|
|
79040
|
+
fs24.mkdirSync(path53.dirname(file), { recursive: true, mode: 448 });
|
|
78701
79041
|
fs24.writeFileSync(file, `${JSON.stringify(record)}
|
|
78702
79042
|
`, { mode: 384 });
|
|
78703
79043
|
}
|
|
@@ -78742,7 +79082,7 @@ async function acquireLease(options) {
|
|
|
78742
79082
|
const reclaimed = [];
|
|
78743
79083
|
let waitedOn = [];
|
|
78744
79084
|
const name = ticketName(started, record.id);
|
|
78745
|
-
const ticket =
|
|
79085
|
+
const ticket = path53.join(queueDir(options.dir), name);
|
|
78746
79086
|
const ticketRecord = {
|
|
78747
79087
|
...record,
|
|
78748
79088
|
maxAgeMs: options.waitMs + 60000
|
|
@@ -78863,7 +79203,7 @@ function heldLease(dir, id, options = {}) {
|
|
|
78863
79203
|
for (const name of names) {
|
|
78864
79204
|
if (!/^slot-\d+\.json$/u.test(name))
|
|
78865
79205
|
continue;
|
|
78866
|
-
const lease = parseLease(readText5(
|
|
79206
|
+
const lease = parseLease(readText5(path53.join(dir, name)));
|
|
78867
79207
|
if (lease?.id === id && !staleReason(lease, options.probe) && (options.ancestor ?? isAncestor)(lease.pid))
|
|
78868
79208
|
return lease;
|
|
78869
79209
|
}
|
|
@@ -78918,10 +79258,10 @@ async function runScoped(run, wrapper, sinks) {
|
|
|
78918
79258
|
}
|
|
78919
79259
|
function firstNotice(env, session, key, now = Date.now()) {
|
|
78920
79260
|
const id = (session ?? `ppid-${process.ppid}`).replace(/[^A-Za-z0-9_.-]/gu, "_").slice(0, 120);
|
|
78921
|
-
const dir =
|
|
79261
|
+
const dir = path53.join(stateDir2(env), "notices");
|
|
78922
79262
|
try {
|
|
78923
79263
|
fs24.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
78924
|
-
fs24.writeFileSync(
|
|
79264
|
+
fs24.writeFileSync(path53.join(dir, `${key}-${id}`), `${new Date(now).toISOString()}
|
|
78925
79265
|
`, {
|
|
78926
79266
|
flag: "wx",
|
|
78927
79267
|
mode: 384
|
|
@@ -78931,7 +79271,7 @@ function firstNotice(env, session, key, now = Date.now()) {
|
|
|
78931
79271
|
}
|
|
78932
79272
|
try {
|
|
78933
79273
|
for (const name of fs24.readdirSync(dir)) {
|
|
78934
|
-
const file =
|
|
79274
|
+
const file = path53.join(dir, name);
|
|
78935
79275
|
if (now - fs24.statSync(file).mtimeMs > NOTICE_TTL_MS)
|
|
78936
79276
|
fs24.rmSync(file, { force: true });
|
|
78937
79277
|
}
|
|
@@ -78941,7 +79281,7 @@ function firstNotice(env, session, key, now = Date.now()) {
|
|
|
78941
79281
|
function leaseSlots(dir, slots, probe = {}) {
|
|
78942
79282
|
const states = [];
|
|
78943
79283
|
for (let slot = 0;slot < slots; slot += 1) {
|
|
78944
|
-
const lease = parseLease(readText5(
|
|
79284
|
+
const lease = parseLease(readText5(path53.join(dir, `slot-${slot}.json`)));
|
|
78945
79285
|
states.push({
|
|
78946
79286
|
slot,
|
|
78947
79287
|
holder: lease ? holderOf(lease) : null,
|
|
@@ -78953,7 +79293,7 @@ function leaseSlots(dir, slots, probe = {}) {
|
|
|
78953
79293
|
var DEFAULT_HEAVY_CHECKS, DEFAULT_LIGHT_CHECKS, DEFAULT_SLOTS = 1, DEFAULT_WAIT_S = 1800, DEFAULT_MEMORY_SHARE = 0.4, DEFAULT_CPU_SHARE = 0.7, MAX_SLOTS = 64, UNREADABLE_TTL_MS = 30000, GUARD_TTL_MS = 30000, hostShape = () => ({
|
|
78954
79294
|
totalMemBytes: os20.totalmem(),
|
|
78955
79295
|
cpus: Math.max(1, os20.availableParallelism?.() ?? os20.cpus().length)
|
|
78956
|
-
}), isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), SIZE, PERCENT, UNITS, leaseDir = (env) =>
|
|
79296
|
+
}), isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), SIZE, PERCENT, UNITS, leaseDir = (env) => path53.join(stateDir2(env), "leases"), readText5 = (file) => {
|
|
78957
79297
|
try {
|
|
78958
79298
|
return fs24.readFileSync(file, "utf8");
|
|
78959
79299
|
} catch {
|
|
@@ -78984,7 +79324,7 @@ var DEFAULT_HEAVY_CHECKS, DEFAULT_LIGHT_CHECKS, DEFAULT_SLOTS = 1, DEFAULT_WAIT_
|
|
|
78984
79324
|
cwd: lease.cwd,
|
|
78985
79325
|
session: lease.session,
|
|
78986
79326
|
startedAt: lease.startedAt
|
|
78987
|
-
}), realClock, queueDir = (dir) =>
|
|
79327
|
+
}), realClock, queueDir = (dir) => path53.join(dir, "queue"), TICKET, ticketName = (now, id) => `${String(now).padStart(15, "0")}-${String(process.hrtime.bigint() % 10n ** 16n).padStart(16, "0")}-${id}.json`, SCOPE_START_FAILURE, NOTICE_TTL_MS;
|
|
78988
79328
|
var init_resources = __esm(() => {
|
|
78989
79329
|
init_checks3();
|
|
78990
79330
|
init_heavy();
|
|
@@ -79014,7 +79354,7 @@ __export(exports_check, {
|
|
|
79014
79354
|
workspaceResources: () => workspaceResources
|
|
79015
79355
|
});
|
|
79016
79356
|
import os21 from "node:os";
|
|
79017
|
-
import
|
|
79357
|
+
import path54 from "node:path";
|
|
79018
79358
|
function parse6(argv) {
|
|
79019
79359
|
const split = argv.indexOf("--");
|
|
79020
79360
|
const head = split >= 0 ? argv.slice(0, split) : [...argv];
|
|
@@ -79245,7 +79585,7 @@ ${footer}`;
|
|
|
79245
79585
|
}
|
|
79246
79586
|
async function workspaceResources(io) {
|
|
79247
79587
|
const env = io.env;
|
|
79248
|
-
const dir = env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ??
|
|
79588
|
+
const dir = env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path54.join(env.XDG_CONFIG_HOME || path54.join(env.HOME || os21.homedir(), ".config"), "workit");
|
|
79249
79589
|
try {
|
|
79250
79590
|
await Promise.resolve().then(() => init_workspaces());
|
|
79251
79591
|
const workspace = resolveWorkspaceFrom(io.cwd, dir, env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined);
|
|
@@ -79266,7 +79606,7 @@ async function prepareHeavy(io, settings, label, runCwd, timeoutMs) {
|
|
|
79266
79606
|
wrapper: null,
|
|
79267
79607
|
env: io.env
|
|
79268
79608
|
};
|
|
79269
|
-
const progress =
|
|
79609
|
+
const progress = progressFor(io);
|
|
79270
79610
|
let waiting = null;
|
|
79271
79611
|
const acquired = await acquireLease({
|
|
79272
79612
|
dir,
|
|
@@ -79387,7 +79727,7 @@ async function run12(argv, io) {
|
|
|
79387
79727
|
if (options.shell && command.length !== 1)
|
|
79388
79728
|
return emit(io, fail2("invalid_input", '--shell takes the command as one string: workit check --shell -- "<cmd>"'));
|
|
79389
79729
|
}
|
|
79390
|
-
const relCwd = posix(
|
|
79730
|
+
const relCwd = posix(path54.relative(top, runCwd));
|
|
79391
79731
|
const configured = !options.shell && matchesNamedCheck(config, name, command, relCwd);
|
|
79392
79732
|
const shadowed = !configured && name !== null ? config.checks.find((item) => item.name === name) : undefined;
|
|
79393
79733
|
if (shadowed)
|
|
@@ -79452,7 +79792,7 @@ async function run12(argv, io) {
|
|
|
79452
79792
|
const modifiedWorktree = key.tree !== null && treeAfter !== key.tree;
|
|
79453
79793
|
const store = storeRoot(io.cwd);
|
|
79454
79794
|
const blob = store.ok ? storeLog(store.value.root, result.log) : null;
|
|
79455
|
-
const logPath = store.ok && blob ?
|
|
79795
|
+
const logPath = store.ok && blob ? path54.join(store.value.root, blob.ref) : null;
|
|
79456
79796
|
const tail = tailLines(result.log, TAIL_LINES);
|
|
79457
79797
|
const passed = result.exitCode === 0 && !result.timedOut;
|
|
79458
79798
|
const bounded = boundedArgv(command);
|
|
@@ -79567,7 +79907,7 @@ async function run12(argv, io) {
|
|
|
79567
79907
|
return recordError.code === "busy" ? 4 : recordError.code === "invalid_input" ? 2 : 5;
|
|
79568
79908
|
return 0;
|
|
79569
79909
|
}
|
|
79570
|
-
var USAGE6 = 'workit check <name> [--full] [--wait <dur> | --no-wait] [--no-lease --reason "<why>"] | workit check [--name <n>] [--shell] [--heavy] [--full] [--wait <dur> | --no-wait] [--timeout <s>] [--task <id>] [--json] -- <cmd…>', OUTPUT_LINES = 60, MAX_UNVERIFIED_RUN_MS, RECORD_TAIL_LINES = 20, RECORD_TAIL_CHARS = 200, posix = (value) => value.split(
|
|
79910
|
+
var USAGE6 = 'workit check <name> [--full] [--wait <dur> | --no-wait] [--no-lease --reason "<why>"] | workit check [--name <n>] [--shell] [--heavy] [--full] [--wait <dur> | --no-wait] [--timeout <s>] [--task <id>] [--json] -- <cmd…>', OUTPUT_LINES = 60, MAX_UNVERIFIED_RUN_MS, RECORD_TAIL_LINES = 20, RECORD_TAIL_CHARS = 200, posix = (value) => value.split(path54.sep).join("/") || ".", ENGINE_CODES2, FINGERPRINT_VARS, ANSI_COLOR, WARNING_LINE, NO_WARNINGS, STDERR_TAIL_LINES = 10, STDERR_KEEP_CHARS = 65536, FAILURE_LINE, MAX_FAILURE_LINES = 15;
|
|
79571
79911
|
var init_check = __esm(() => {
|
|
79572
79912
|
init_check_config();
|
|
79573
79913
|
init_checks3();
|
|
@@ -79598,7 +79938,7 @@ __export(exports_lock, {
|
|
|
79598
79938
|
run: () => run13
|
|
79599
79939
|
});
|
|
79600
79940
|
import fs25 from "node:fs";
|
|
79601
|
-
import
|
|
79941
|
+
import path55 from "node:path";
|
|
79602
79942
|
async function settingsFor(io) {
|
|
79603
79943
|
const workspace = await workspaceResources(io);
|
|
79604
79944
|
const config = loadCheckConfig(io.cwd);
|
|
@@ -79690,7 +80030,7 @@ function readPatterns(file) {
|
|
|
79690
80030
|
return { patterns: [] };
|
|
79691
80031
|
}
|
|
79692
80032
|
function writePatterns(file, value) {
|
|
79693
|
-
fs25.mkdirSync(
|
|
80033
|
+
fs25.mkdirSync(path55.dirname(file), { recursive: true, mode: 448 });
|
|
79694
80034
|
const temp = `${file}.${process.pid}.tmp`;
|
|
79695
80035
|
fs25.writeFileSync(temp, `${JSON.stringify(value, null, 2)}
|
|
79696
80036
|
`, { mode: 384 });
|
|
@@ -79778,7 +80118,7 @@ __export(exports_models, {
|
|
|
79778
80118
|
});
|
|
79779
80119
|
import { existsSync as existsSync25, readdirSync as readdirSync13, readFileSync as readFileSync24, statSync as statSync9 } from "node:fs";
|
|
79780
80120
|
import os22 from "node:os";
|
|
79781
|
-
import
|
|
80121
|
+
import path56 from "node:path";
|
|
79782
80122
|
async function run14(argv, io) {
|
|
79783
80123
|
const [sub, ...args] = argv.filter((arg) => arg !== "--json");
|
|
79784
80124
|
if (sub !== "show")
|
|
@@ -79853,20 +80193,20 @@ var USAGE8 = "workit models show [--role <role>] [--tier <tier>] [--host <host>]
|
|
|
79853
80193
|
} catch {}
|
|
79854
80194
|
return found;
|
|
79855
80195
|
}, matches3 = (ran, configured) => ran.toLowerCase().includes(configured.toLowerCase()), usageReport = (cwd, env, days) => {
|
|
79856
|
-
const projects =
|
|
80196
|
+
const projects = path56.join(env.CLAUDE_CONFIG_DIR || path56.join(env.HOME || os22.homedir(), ".claude"), "projects");
|
|
79857
80197
|
const since = Date.now() - days * 86400000;
|
|
79858
80198
|
const types = {};
|
|
79859
80199
|
let agents = 0;
|
|
79860
80200
|
const dirs = (dir) => {
|
|
79861
80201
|
try {
|
|
79862
|
-
return readdirSync13(dir).map((name) =>
|
|
80202
|
+
return readdirSync13(dir).map((name) => path56.join(dir, name));
|
|
79863
80203
|
} catch {
|
|
79864
80204
|
return [];
|
|
79865
80205
|
}
|
|
79866
80206
|
};
|
|
79867
80207
|
for (const project of dirs(projects))
|
|
79868
80208
|
for (const session of dirs(project))
|
|
79869
|
-
for (const meta of dirs(
|
|
80209
|
+
for (const meta of dirs(path56.join(session, "subagents")).filter((f) => f.endsWith(".meta.json"))) {
|
|
79870
80210
|
try {
|
|
79871
80211
|
if (statSync9(meta).mtimeMs < since)
|
|
79872
80212
|
continue;
|
|
@@ -80012,7 +80352,7 @@ var success2 = (data) => ({ ok: true, data }), failure3 = (code, error, unblock)
|
|
|
80012
80352
|
// packages/workit-core/src/git/ops.ts
|
|
80013
80353
|
import { spawnSync as spawnSync20 } from "node:child_process";
|
|
80014
80354
|
import { existsSync as existsSync26, readFileSync as readFileSync25 } from "node:fs";
|
|
80015
|
-
import
|
|
80355
|
+
import path57 from "node:path";
|
|
80016
80356
|
function operationInProgress(cwd) {
|
|
80017
80357
|
const markers = [
|
|
80018
80358
|
["rebase-merge", "rebase"],
|
|
@@ -80025,18 +80365,18 @@ function operationInProgress(cwd) {
|
|
|
80025
80365
|
if (!run.ok)
|
|
80026
80366
|
return null;
|
|
80027
80367
|
const found = run.stdout.split(`
|
|
80028
|
-
`).map((line) =>
|
|
80368
|
+
`).map((line) => path57.resolve(cwd, line.trim()));
|
|
80029
80369
|
const conflicted = () => git5(cwd, ["ls-files", "-u"]).stdout.trim() !== "";
|
|
80030
80370
|
for (const [index, [, operation]] of markers.entries()) {
|
|
80031
80371
|
const marker = found[index];
|
|
80032
80372
|
if (!marker || !existsSync26(marker))
|
|
80033
80373
|
continue;
|
|
80034
|
-
if (index === 1 && existsSync26(
|
|
80374
|
+
if (index === 1 && existsSync26(path57.join(marker, "applying")))
|
|
80035
80375
|
return { operation: "am", commitAllowed: false, branch: null };
|
|
80036
|
-
if (index === 0 && existsSync26(
|
|
80376
|
+
if (index === 0 && existsSync26(path57.join(marker, "amend")) && !conflicted()) {
|
|
80037
80377
|
let headName = "";
|
|
80038
80378
|
try {
|
|
80039
|
-
headName = readFileSync25(
|
|
80379
|
+
headName = readFileSync25(path57.join(marker, "head-name"), "utf8").trim();
|
|
80040
80380
|
} catch {}
|
|
80041
80381
|
const branch = headName.startsWith("refs/heads/") ? headName.slice("refs/heads/".length) : null;
|
|
80042
80382
|
return { operation, commitAllowed: branch !== null, branch };
|
|
@@ -80364,7 +80704,7 @@ function gitCommit(cwd, input) {
|
|
|
80364
80704
|
if (paths.some((value) => value.startsWith("-") || !value.trim()))
|
|
80365
80705
|
return failure3("invalid_input", "paths must not be empty or start with -");
|
|
80366
80706
|
const tracked = new Set(nulList(git5(cwd, ["ls-files", "-z", "--", ...paths]).stdout));
|
|
80367
|
-
const addable = paths.filter((value) => existsSync26(
|
|
80707
|
+
const addable = paths.filter((value) => existsSync26(path57.resolve(cwd, value)) || [...tracked].some((file) => file === value || file.startsWith(`${value}/`)));
|
|
80368
80708
|
if (addable.length) {
|
|
80369
80709
|
const added = git5(cwd, ["add", "-A", "--", ...addable]);
|
|
80370
80710
|
if (!added.ok)
|
|
@@ -80903,12 +81243,12 @@ var init_ops = __esm(() => {
|
|
|
80903
81243
|
|
|
80904
81244
|
// packages/workit-core/src/verdict-cover.ts
|
|
80905
81245
|
import fs26 from "node:fs";
|
|
80906
|
-
import
|
|
81246
|
+
import path58 from "node:path";
|
|
80907
81247
|
function chainsAbove(cwd, branch) {
|
|
80908
81248
|
const root = storeRoot(cwd);
|
|
80909
81249
|
if (!root.ok)
|
|
80910
81250
|
return [];
|
|
80911
|
-
const dir =
|
|
81251
|
+
const dir = path58.join(root.value.root, "stacks");
|
|
80912
81252
|
let names = [];
|
|
80913
81253
|
try {
|
|
80914
81254
|
names = fs26.readdirSync(dir).filter((name) => name.endsWith(".json"));
|
|
@@ -80919,7 +81259,7 @@ function chainsAbove(cwd, branch) {
|
|
|
80919
81259
|
for (const name of names.toSorted()) {
|
|
80920
81260
|
let parsed;
|
|
80921
81261
|
try {
|
|
80922
|
-
parsed = JSON.parse(fs26.readFileSync(
|
|
81262
|
+
parsed = JSON.parse(fs26.readFileSync(path58.join(dir, name), "utf8"));
|
|
80923
81263
|
} catch {
|
|
80924
81264
|
continue;
|
|
80925
81265
|
}
|
|
@@ -81075,10 +81415,10 @@ var init_check_evidence = __esm(() => {
|
|
|
81075
81415
|
|
|
81076
81416
|
// packages/workit-core/src/forge/reruns.ts
|
|
81077
81417
|
import fs27 from "node:fs";
|
|
81078
|
-
import
|
|
81418
|
+
import path59 from "node:path";
|
|
81079
81419
|
function rerunLogPath(cwd) {
|
|
81080
81420
|
const common = gitCommonDir(cwd);
|
|
81081
|
-
return common ?
|
|
81421
|
+
return common ? path59.join(common, "workit", "ci-reruns.jsonl") : null;
|
|
81082
81422
|
}
|
|
81083
81423
|
function rerunCounts(cwd, key) {
|
|
81084
81424
|
const counts = new Map;
|
|
@@ -81113,7 +81453,7 @@ function recordReruns(cwd, rows) {
|
|
|
81113
81453
|
if (!file)
|
|
81114
81454
|
return false;
|
|
81115
81455
|
try {
|
|
81116
|
-
fs27.mkdirSync(
|
|
81456
|
+
fs27.mkdirSync(path59.dirname(file), { recursive: true });
|
|
81117
81457
|
fs27.appendFileSync(file, rows.map((row) => `${JSON.stringify(row)}
|
|
81118
81458
|
`).join(""));
|
|
81119
81459
|
return true;
|
|
@@ -81126,7 +81466,7 @@ function withRerunLock(cwd, fn) {
|
|
|
81126
81466
|
if (!file)
|
|
81127
81467
|
return fn();
|
|
81128
81468
|
const lock = `${file.slice(0, -".jsonl".length)}.lock`;
|
|
81129
|
-
fs27.mkdirSync(
|
|
81469
|
+
fs27.mkdirSync(path59.dirname(lock), { recursive: true });
|
|
81130
81470
|
const until = Date.now() + LOCK_WAIT_MS2;
|
|
81131
81471
|
for (;; ) {
|
|
81132
81472
|
try {
|
|
@@ -82122,7 +82462,7 @@ var init_pr_ops = __esm(() => {
|
|
|
82122
82462
|
import { spawnSync as spawnSync22 } from "node:child_process";
|
|
82123
82463
|
import { createHash as createHash18, randomBytes as randomBytes4 } from "node:crypto";
|
|
82124
82464
|
import fs28 from "node:fs";
|
|
82125
|
-
import
|
|
82465
|
+
import path60 from "node:path";
|
|
82126
82466
|
function worktreeOf(cwd, branch) {
|
|
82127
82467
|
const list = gitRun3(cwd, ["worktree", "list", "--porcelain"]);
|
|
82128
82468
|
if (!list.ok)
|
|
@@ -82171,7 +82511,7 @@ function gitRestack(cwd, input) {
|
|
|
82171
82511
|
error: "no store root"
|
|
82172
82512
|
};
|
|
82173
82513
|
fs28.mkdirSync(scratch, { recursive: true });
|
|
82174
|
-
dir =
|
|
82514
|
+
dir = path60.join(scratch, `${input.branch.replace(/[^A-Za-z0-9._-]+/gu, "_").slice(0, 40)}-${randomBytes4(4).toString("hex")}`);
|
|
82175
82515
|
const added = gitRun3(cwd, ["worktree", "add", "-q", dir, input.branch], GIT_TIMEOUTS.worktree);
|
|
82176
82516
|
if (!added.ok)
|
|
82177
82517
|
return {
|
|
@@ -82227,7 +82567,7 @@ function pruneScratch(cwd) {
|
|
|
82227
82567
|
if (!scratch || !fs28.existsSync(scratch))
|
|
82228
82568
|
return;
|
|
82229
82569
|
for (const name of fs28.readdirSync(scratch)) {
|
|
82230
|
-
const dir =
|
|
82570
|
+
const dir = path60.join(scratch, name);
|
|
82231
82571
|
if (!rebaseInProgress(dir) && !trackedDirt(dir))
|
|
82232
82572
|
gitRun3(cwd, ["worktree", "remove", "--force", dir]);
|
|
82233
82573
|
}
|
|
@@ -82237,7 +82577,7 @@ function stacksDir(cwd) {
|
|
|
82237
82577
|
const root = storeRoot(cwd);
|
|
82238
82578
|
if (!root.ok)
|
|
82239
82579
|
return stackFail(root.code, root.error, root.unblock);
|
|
82240
|
-
return { ok: true, data:
|
|
82580
|
+
return { ok: true, data: path60.join(root.value.root, "stacks") };
|
|
82241
82581
|
}
|
|
82242
82582
|
function parseStack(raw) {
|
|
82243
82583
|
if (!isRecord12(raw) || !Array.isArray(raw.branches))
|
|
@@ -82289,7 +82629,7 @@ function readStack(cwd, name) {
|
|
|
82289
82629
|
const dir = stacksDir(cwd);
|
|
82290
82630
|
if (!dir.ok)
|
|
82291
82631
|
return dir;
|
|
82292
|
-
const file =
|
|
82632
|
+
const file = path60.join(dir.data, fileFor(name));
|
|
82293
82633
|
let text;
|
|
82294
82634
|
try {
|
|
82295
82635
|
text = fs28.readFileSync(file, "utf8");
|
|
@@ -82310,7 +82650,7 @@ function writeStack(cwd, stack, now = new Date) {
|
|
|
82310
82650
|
const dir = stacksDir(cwd);
|
|
82311
82651
|
if (!dir.ok)
|
|
82312
82652
|
return dir;
|
|
82313
|
-
const file =
|
|
82653
|
+
const file = path60.join(dir.data, fileFor(stack.name));
|
|
82314
82654
|
const temp = `${file}.${process.pid}.tmp`;
|
|
82315
82655
|
try {
|
|
82316
82656
|
fs28.mkdirSync(dir.data, { recursive: true });
|
|
@@ -82338,7 +82678,7 @@ function listStacks(cwd) {
|
|
|
82338
82678
|
for (const name of names) {
|
|
82339
82679
|
let parsed = null;
|
|
82340
82680
|
try {
|
|
82341
|
-
parsed = parseStack(JSON.parse(fs28.readFileSync(
|
|
82681
|
+
parsed = parseStack(JSON.parse(fs28.readFileSync(path60.join(dir.data, name), "utf8")));
|
|
82342
82682
|
} catch {
|
|
82343
82683
|
parsed = null;
|
|
82344
82684
|
}
|
|
@@ -82400,7 +82740,7 @@ function takeLock(lock) {
|
|
|
82400
82740
|
host: localLockHost(),
|
|
82401
82741
|
nonce: randomBytes4(8).toString("hex")
|
|
82402
82742
|
};
|
|
82403
|
-
fs28.writeFileSync(
|
|
82743
|
+
fs28.writeFileSync(path60.join(lock, OWNER), JSON.stringify(owner));
|
|
82404
82744
|
return owner;
|
|
82405
82745
|
}
|
|
82406
82746
|
function reapLock(lock, observed) {
|
|
@@ -82437,7 +82777,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
|
|
|
82437
82777
|
return dir;
|
|
82438
82778
|
if (!validName(name))
|
|
82439
82779
|
return stackFail("invalid_input", "a stack name must be 1-200 printable characters");
|
|
82440
|
-
const lock =
|
|
82780
|
+
const lock = path60.join(dir.data, `${fileFor(name)}.lock`);
|
|
82441
82781
|
try {
|
|
82442
82782
|
fs28.mkdirSync(dir.data, { recursive: true });
|
|
82443
82783
|
} catch (error) {
|
|
@@ -82467,7 +82807,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
|
|
|
82467
82807
|
const touch = () => {
|
|
82468
82808
|
try {
|
|
82469
82809
|
const now = new Date;
|
|
82470
|
-
fs28.utimesSync(
|
|
82810
|
+
fs28.utimesSync(path60.join(lock, OWNER), now, now);
|
|
82471
82811
|
} catch {}
|
|
82472
82812
|
};
|
|
82473
82813
|
const beat = setInterval(touch, HEARTBEAT_MS);
|
|
@@ -83436,7 +83776,7 @@ var STACK_VERSION = 1, stackFail = (code, error, unblock, data) => ({
|
|
|
83436
83776
|
return !status.ok || status.stdout.trim() !== "";
|
|
83437
83777
|
}, scratchDir = (cwd) => {
|
|
83438
83778
|
const dir = stacksDir(cwd);
|
|
83439
|
-
return dir.ok ?
|
|
83779
|
+
return dir.ok ? path60.join(dir.data, "worktrees") : null;
|
|
83440
83780
|
}, firstLine = (run) => (`${run.stderr}
|
|
83441
83781
|
${run.stdout}`.split(`
|
|
83442
83782
|
`).find((line) => line.trim()) ?? "git failed").trim().slice(0, 300), stackFileName = (name) => `${name.replace(/[^A-Za-z0-9._-]+/gu, "_").replace(/^[._]+/u, "").slice(0, 48).toLowerCase()}-${createHash18("sha256").update(name).digest("hex").slice(0, 12)}.json`, fileFor, validName = (name) => {
|
|
@@ -83451,12 +83791,12 @@ ${run.stdout}`.split(`
|
|
|
83451
83791
|
}, isRecord12 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), str3 = (value) => typeof value === "string" && value ? value : null, LOCK_WAIT_MS3 = 2000, HEARTBEAT_MS = 20000, HEARTBEAT_STALE_MS, OWNERLESS_STALE_MS = 30000, OWNER = "owner", readOwner = (lock) => {
|
|
83452
83792
|
let raw = null;
|
|
83453
83793
|
try {
|
|
83454
|
-
raw = fs28.readFileSync(
|
|
83794
|
+
raw = fs28.readFileSync(path60.join(lock, OWNER), "utf8");
|
|
83455
83795
|
} catch {
|
|
83456
83796
|
raw = null;
|
|
83457
83797
|
}
|
|
83458
83798
|
let age = null;
|
|
83459
|
-
for (const target of [
|
|
83799
|
+
for (const target of [path60.join(lock, OWNER), lock])
|
|
83460
83800
|
try {
|
|
83461
83801
|
age = Date.now() - fs28.statSync(target).mtimeMs;
|
|
83462
83802
|
break;
|
|
@@ -83500,7 +83840,7 @@ var init_stack = __esm(() => {
|
|
|
83500
83840
|
import { spawnSync as spawnSync23 } from "node:child_process";
|
|
83501
83841
|
import { createHash as createHash19 } from "node:crypto";
|
|
83502
83842
|
import fs29 from "node:fs";
|
|
83503
|
-
import
|
|
83843
|
+
import path61 from "node:path";
|
|
83504
83844
|
function expandBraces2(pattern, limit = 64) {
|
|
83505
83845
|
for (let index = 0;index < pattern.length; index += 1) {
|
|
83506
83846
|
if (pattern[index] === "\\") {
|
|
@@ -83746,7 +84086,7 @@ function parsePlan(raw, defaults, name) {
|
|
|
83746
84086
|
id,
|
|
83747
84087
|
branch,
|
|
83748
84088
|
base: optional("base") ?? "",
|
|
83749
|
-
worktree:
|
|
84089
|
+
worktree: path61.resolve(defaults.root, optional("worktree") ?? path61.join(defaults.worktreeRoot, id)),
|
|
83750
84090
|
tier,
|
|
83751
84091
|
reason,
|
|
83752
84092
|
dependsOn: [...new Set(dependsOn ?? [])],
|
|
@@ -83875,12 +84215,12 @@ function regeneratedFiles(root, tracked) {
|
|
|
83875
84215
|
const found = new Map;
|
|
83876
84216
|
let scripts;
|
|
83877
84217
|
try {
|
|
83878
|
-
const manifest = JSON.parse(fs29.readFileSync(
|
|
84218
|
+
const manifest = JSON.parse(fs29.readFileSync(path61.join(root, "package.json"), "utf8"));
|
|
83879
84219
|
scripts = manifest.scripts ?? {};
|
|
83880
84220
|
} catch {
|
|
83881
84221
|
return found;
|
|
83882
84222
|
}
|
|
83883
|
-
const runner = fs29.existsSync(
|
|
84223
|
+
const runner = fs29.existsSync(path61.join(root, "bun.lock")) ? "bun run" : fs29.existsSync(path61.join(root, "pnpm-lock.yaml")) ? "pnpm run" : fs29.existsSync(path61.join(root, "yarn.lock")) ? "yarn run" : "npm run";
|
|
83884
84224
|
const outputs = tracked.filter((file) => !CODE.test(file));
|
|
83885
84225
|
for (const [name, command] of Object.entries(scripts)) {
|
|
83886
84226
|
if (!name.startsWith("write:") || typeof command !== "string")
|
|
@@ -83888,7 +84228,7 @@ function regeneratedFiles(root, tracked) {
|
|
|
83888
84228
|
for (const file of command.match(/[\w./-]+\.[cm]?[jt]s\b/gu) ?? []) {
|
|
83889
84229
|
let source;
|
|
83890
84230
|
try {
|
|
83891
|
-
source = fs29.readFileSync(
|
|
84231
|
+
source = fs29.readFileSync(path61.join(root, file), "utf8");
|
|
83892
84232
|
} catch {
|
|
83893
84233
|
continue;
|
|
83894
84234
|
}
|
|
@@ -84010,11 +84350,11 @@ function defaultTrunk(cwd) {
|
|
|
84010
84350
|
}
|
|
84011
84351
|
function mainCheckout(cwd) {
|
|
84012
84352
|
const common = gitCommonDir(cwd);
|
|
84013
|
-
return common &&
|
|
84353
|
+
return common && path61.basename(common) === ".git" ? path61.dirname(common) : path61.resolve(cwd);
|
|
84014
84354
|
}
|
|
84015
84355
|
function worktreeRoot(cwd) {
|
|
84016
84356
|
const main = mainCheckout(cwd);
|
|
84017
|
-
return
|
|
84357
|
+
return path61.join(path61.dirname(main), `${path61.basename(main)}-wt`);
|
|
84018
84358
|
}
|
|
84019
84359
|
function sliceHash(slice) {
|
|
84020
84360
|
const {
|
|
@@ -84034,7 +84374,7 @@ function fanoutsDir(cwd) {
|
|
|
84034
84374
|
const root = storeRoot(cwd);
|
|
84035
84375
|
if (!root.ok)
|
|
84036
84376
|
return fanoutFail(root.code, root.error, root.unblock);
|
|
84037
|
-
return { ok: true, data:
|
|
84377
|
+
return { ok: true, data: path61.join(root.value.root, "fanouts") };
|
|
84038
84378
|
}
|
|
84039
84379
|
function parseStored(raw) {
|
|
84040
84380
|
if (!isRecord13(raw) || typeof raw.name !== "string" || typeof raw.trunk !== "string")
|
|
@@ -84102,7 +84442,7 @@ function readFanout(cwd, name) {
|
|
|
84102
84442
|
const dir = fanoutsDir(cwd);
|
|
84103
84443
|
if (!dir.ok)
|
|
84104
84444
|
return dir;
|
|
84105
|
-
const file =
|
|
84445
|
+
const file = path61.join(dir.data, stackFileName(name));
|
|
84106
84446
|
let parsed = null;
|
|
84107
84447
|
try {
|
|
84108
84448
|
parsed = parseStored(JSON.parse(fs29.readFileSync(file, "utf8")));
|
|
@@ -84127,7 +84467,7 @@ function listFanouts(cwd) {
|
|
|
84127
84467
|
for (const entry of names) {
|
|
84128
84468
|
let parsed = null;
|
|
84129
84469
|
try {
|
|
84130
|
-
parsed = parseStored(JSON.parse(fs29.readFileSync(
|
|
84470
|
+
parsed = parseStored(JSON.parse(fs29.readFileSync(path61.join(dir.data, entry), "utf8")));
|
|
84131
84471
|
} catch {
|
|
84132
84472
|
parsed = null;
|
|
84133
84473
|
}
|
|
@@ -84166,7 +84506,7 @@ function writeFanout(cwd, plan) {
|
|
|
84166
84506
|
const dir = fanoutsDir(cwd);
|
|
84167
84507
|
if (!dir.ok)
|
|
84168
84508
|
return dir;
|
|
84169
|
-
const file =
|
|
84509
|
+
const file = path61.join(dir.data, stackFileName(plan.name));
|
|
84170
84510
|
const temp = `${file}.${process.pid}.tmp`;
|
|
84171
84511
|
try {
|
|
84172
84512
|
fs29.mkdirSync(dir.data, { recursive: true });
|
|
@@ -84377,13 +84717,13 @@ var init_fanout = __esm(() => {
|
|
|
84377
84717
|
// packages/workit-core/src/forge/exec.ts
|
|
84378
84718
|
import { spawnSync as spawnSync24 } from "node:child_process";
|
|
84379
84719
|
import fs30 from "node:fs";
|
|
84380
|
-
import
|
|
84720
|
+
import path62 from "node:path";
|
|
84381
84721
|
function findExecutable(bin, env) {
|
|
84382
|
-
const dirs = (env.PATH ?? env.Path ?? "").split(
|
|
84722
|
+
const dirs = (env.PATH ?? env.Path ?? "").split(path62.delimiter).filter(Boolean);
|
|
84383
84723
|
const exts = process.platform === "win32" ? [".exe"] : [""];
|
|
84384
84724
|
for (const dir of dirs)
|
|
84385
84725
|
for (const ext of exts) {
|
|
84386
|
-
const candidate =
|
|
84726
|
+
const candidate = path62.join(dir, `${bin}${ext}`);
|
|
84387
84727
|
try {
|
|
84388
84728
|
const stat = fs30.statSync(candidate);
|
|
84389
84729
|
if (stat.isFile())
|
|
@@ -85511,13 +85851,13 @@ function placeRef(ref, forge, tracker, relation, youtrackBase) {
|
|
|
85511
85851
|
const configured = tracker?.provider === ref.tracker;
|
|
85512
85852
|
const home = ref.tracker === forge.kind ? forge.host : DEFAULT_HOST[ref.tracker];
|
|
85513
85853
|
const host = ref.host ?? (configured ? tracker?.host : null) ?? home;
|
|
85514
|
-
const repo = ref.repo ?? (configured ? tracker?.repo : null) ?? (ref.tracker === forge.kind &&
|
|
85854
|
+
const repo = ref.repo ?? (configured ? tracker?.repo : null) ?? (ref.tracker === forge.kind && same3(host, forge.host) ? forge.repo : null);
|
|
85515
85855
|
if (!repo)
|
|
85516
85856
|
return {
|
|
85517
85857
|
error: `#${ref.id} is a ${ref.tracker} issue, but the PR is on ${forge.kind}: set issues.repo to the ${ref.tracker} project that holds it, or pass the issue URL`
|
|
85518
85858
|
};
|
|
85519
|
-
if (ref.tracker === forge.kind &&
|
|
85520
|
-
const own =
|
|
85859
|
+
if (ref.tracker === forge.kind && same3(host, forge.host)) {
|
|
85860
|
+
const own = same3(repo, forge.repo);
|
|
85521
85861
|
return {
|
|
85522
85862
|
tracker: ref.tracker,
|
|
85523
85863
|
id: ref.id,
|
|
@@ -85654,7 +85994,7 @@ function issueForge(resolved, link, runner) {
|
|
|
85654
85994
|
if (link.repo === null && link.host === null)
|
|
85655
85995
|
return resolved.forge;
|
|
85656
85996
|
const apiHost = resolved.forge.apiHost;
|
|
85657
|
-
if (link.tracker !== resolved.forge.kind || !
|
|
85997
|
+
if (link.tracker !== resolved.forge.kind || !same3(link.host ?? apiHost, apiHost))
|
|
85658
85998
|
return null;
|
|
85659
85999
|
const options = {
|
|
85660
86000
|
apiHost,
|
|
@@ -85721,7 +86061,7 @@ async function postBacklinks(cwd, resolved, pr, links, deps = {}) {
|
|
|
85721
86061
|
}
|
|
85722
86062
|
return out;
|
|
85723
86063
|
}
|
|
85724
|
-
var DEFAULT_HOST,
|
|
86064
|
+
var DEFAULT_HOST, same3 = (left, right) => (left ?? "").toLowerCase() === (right ?? "").toLowerCase(), issueUrl = (kind, host, repo, id) => `https://${host}/${repo}/${kind === "gitlab" ? "-/" : ""}issues/${id}`, label = (link) => link.tracker === "youtrack" ? link.id : link.url ?? `${link.repo ?? ""}#${link.id}`, defaultYouTrackComment = (root, issueId, text, marker) => writeOnce(issueId, marker, "comments", async () => {
|
|
85725
86065
|
try {
|
|
85726
86066
|
return {
|
|
85727
86067
|
ok: true,
|
|
@@ -86173,7 +86513,7 @@ var init_live_session = __esm(() => {
|
|
|
86173
86513
|
});
|
|
86174
86514
|
|
|
86175
86515
|
// packages/workit-core/src/hooks/write-gate.ts
|
|
86176
|
-
import
|
|
86516
|
+
import path63 from "node:path";
|
|
86177
86517
|
var CASE_INSENSITIVE, PREFIXES2, SCRIPT_SHELLS, cache3, MUTATING_GIT, DRY_N, MUTATING_WORKIT_GIT, CD2, PUSHD2, POPD2, UNKNOWN_DIR;
|
|
86178
86518
|
var init_write_gate = __esm(() => {
|
|
86179
86519
|
init_task_store();
|
|
@@ -86213,7 +86553,7 @@ var init_write_gate = __esm(() => {
|
|
|
86213
86553
|
CD2 = new Set(["cd", "chdir", "set-location", "sl"]);
|
|
86214
86554
|
PUSHD2 = new Set(["pushd", "push-location"]);
|
|
86215
86555
|
POPD2 = new Set(["popd", "pop-location"]);
|
|
86216
|
-
UNKNOWN_DIR =
|
|
86556
|
+
UNKNOWN_DIR = path63.resolve(path63.parse(process.cwd()).root, ".workit-unknown-dir");
|
|
86217
86557
|
});
|
|
86218
86558
|
|
|
86219
86559
|
// packages/workit-core/src/hooks/worktree-confine.ts
|
|
@@ -86238,20 +86578,20 @@ var init_worktree_confine = __esm(() => {
|
|
|
86238
86578
|
|
|
86239
86579
|
// packages/workit-core/src/worktree-deps.ts
|
|
86240
86580
|
import fs31 from "node:fs";
|
|
86241
|
-
import
|
|
86581
|
+
import path64 from "node:path";
|
|
86242
86582
|
function moduleDirs(main) {
|
|
86243
86583
|
const out = [];
|
|
86244
86584
|
const walk = (relative, depth) => {
|
|
86245
86585
|
let entries;
|
|
86246
86586
|
try {
|
|
86247
|
-
entries = fs31.readdirSync(
|
|
86587
|
+
entries = fs31.readdirSync(path64.join(main, relative), { withFileTypes: true });
|
|
86248
86588
|
} catch {
|
|
86249
86589
|
return;
|
|
86250
86590
|
}
|
|
86251
86591
|
for (const entry of entries) {
|
|
86252
86592
|
if (!entry.isDirectory())
|
|
86253
86593
|
continue;
|
|
86254
|
-
const child =
|
|
86594
|
+
const child = path64.join(relative, entry.name);
|
|
86255
86595
|
if (entry.name === MODULES)
|
|
86256
86596
|
out.push(child);
|
|
86257
86597
|
else if (depth < MAX_DEPTH2 && !entry.name.startsWith("."))
|
|
@@ -86265,8 +86605,8 @@ function linkEntry(main, worktree, source, target) {
|
|
|
86265
86605
|
const stat = fs31.lstatSync(source);
|
|
86266
86606
|
if (stat.isSymbolicLink()) {
|
|
86267
86607
|
const link = fs31.readlinkSync(source);
|
|
86268
|
-
const outside =
|
|
86269
|
-
const to = outside ?
|
|
86608
|
+
const outside = path64.isAbsolute(link) && within(link, main) && !path64.relative(main, link).split(path64.sep).includes(MODULES);
|
|
86609
|
+
const to = outside ? path64.join(worktree, path64.relative(main, link)) : link;
|
|
86270
86610
|
fs31.symlinkSync(to, target, process.platform === "win32" ? "junction" : undefined);
|
|
86271
86611
|
return;
|
|
86272
86612
|
}
|
|
@@ -86276,8 +86616,8 @@ function mirror(main, worktree, source, target, top) {
|
|
|
86276
86616
|
fs31.mkdirSync(target);
|
|
86277
86617
|
let count = 0;
|
|
86278
86618
|
for (const entry of fs31.readdirSync(source, { withFileTypes: true })) {
|
|
86279
|
-
const from =
|
|
86280
|
-
const to =
|
|
86619
|
+
const from = path64.join(source, entry.name);
|
|
86620
|
+
const to = path64.join(target, entry.name);
|
|
86281
86621
|
if (top && entry.isDirectory() && (entry.name.startsWith("@") || entry.name === ".bin"))
|
|
86282
86622
|
count += mirror(main, worktree, from, to, false);
|
|
86283
86623
|
else {
|
|
@@ -86293,16 +86633,16 @@ function linkWorktreeDependencies(main, worktree) {
|
|
|
86293
86633
|
const dirs = [];
|
|
86294
86634
|
let entries = 0;
|
|
86295
86635
|
for (const relative of moduleDirs(main)) {
|
|
86296
|
-
const target =
|
|
86297
|
-
if (!fs31.existsSync(
|
|
86636
|
+
const target = path64.join(worktree, relative);
|
|
86637
|
+
if (!fs31.existsSync(path64.dirname(target)) || fs31.existsSync(target))
|
|
86298
86638
|
continue;
|
|
86299
|
-
if (!gitRun4(worktree, ["check-ignore", "-q", `${relative.split(
|
|
86300
|
-
notes.push(`${relative.split(
|
|
86639
|
+
if (!gitRun4(worktree, ["check-ignore", "-q", `${relative.split(path64.sep).join("/")}/`]).ok) {
|
|
86640
|
+
notes.push(`${relative.split(path64.sep).join("/")} is not ignored by git, so it was not linked from ${main}; install dependencies in the worktree yourself`);
|
|
86301
86641
|
continue;
|
|
86302
86642
|
}
|
|
86303
86643
|
try {
|
|
86304
|
-
entries += mirror(main, worktree,
|
|
86305
|
-
dirs.push(relative.split(
|
|
86644
|
+
entries += mirror(main, worktree, path64.join(main, relative), target, true);
|
|
86645
|
+
dirs.push(relative.split(path64.sep).join("/"));
|
|
86306
86646
|
} catch (error) {
|
|
86307
86647
|
fs31.rmSync(target, { recursive: true, force: true });
|
|
86308
86648
|
notes.push(`could not link ${relative} from ${main} (${error.message}); install dependencies in the worktree yourself`);
|
|
@@ -86315,8 +86655,8 @@ function linkWorktreeDependencies(main, worktree) {
|
|
|
86315
86655
|
return { linked: { from: main, dirs, entries, ms }, notes };
|
|
86316
86656
|
}
|
|
86317
86657
|
var MODULES = "node_modules", MAX_DEPTH2 = 2, within = (child, parent) => {
|
|
86318
|
-
const relative =
|
|
86319
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
86658
|
+
const relative = path64.relative(parent, child);
|
|
86659
|
+
return relative === "" || !relative.startsWith("..") && !path64.isAbsolute(relative);
|
|
86320
86660
|
};
|
|
86321
86661
|
var init_worktree_deps = __esm(() => {
|
|
86322
86662
|
init_fanout();
|
|
@@ -86325,7 +86665,7 @@ var init_worktree_deps = __esm(() => {
|
|
|
86325
86665
|
// packages/workit-core/src/fanout-worktree.ts
|
|
86326
86666
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
86327
86667
|
import fs32 from "node:fs";
|
|
86328
|
-
import
|
|
86668
|
+
import path65 from "node:path";
|
|
86329
86669
|
function rowSample(lines) {
|
|
86330
86670
|
const out = [];
|
|
86331
86671
|
let bytes = 0;
|
|
@@ -86385,7 +86725,7 @@ function adminDir(worktree) {
|
|
|
86385
86725
|
const file = dir.stdout.trim();
|
|
86386
86726
|
let token = null;
|
|
86387
86727
|
try {
|
|
86388
|
-
token = fs32.readFileSync(
|
|
86728
|
+
token = fs32.readFileSync(path65.join(file, FANOUT_TOKEN_FILE), "utf8").trim() || null;
|
|
86389
86729
|
} catch {
|
|
86390
86730
|
token = null;
|
|
86391
86731
|
}
|
|
@@ -86393,7 +86733,7 @@ function adminDir(worktree) {
|
|
|
86393
86733
|
const stat = worktreeDeps.stat(file);
|
|
86394
86734
|
return {
|
|
86395
86735
|
path: file,
|
|
86396
|
-
id:
|
|
86736
|
+
id: path65.basename(file),
|
|
86397
86737
|
ino: stat.ino.toString(),
|
|
86398
86738
|
token,
|
|
86399
86739
|
birthMs: stat.birthtimeNs > 0n ? Number(stat.birthtimeMs) : null,
|
|
@@ -86409,7 +86749,7 @@ function markAdminDir(worktree) {
|
|
|
86409
86749
|
return null;
|
|
86410
86750
|
const token = randomBytes5(16).toString("hex");
|
|
86411
86751
|
try {
|
|
86412
|
-
fs32.writeFileSync(
|
|
86752
|
+
fs32.writeFileSync(path65.join(admin.path, FANOUT_TOKEN_FILE), `${token}
|
|
86413
86753
|
`);
|
|
86414
86754
|
} catch {
|
|
86415
86755
|
return null;
|
|
@@ -86424,7 +86764,7 @@ function excludeScratch(cwd) {
|
|
|
86424
86764
|
const common = gitCommonDir(cwd);
|
|
86425
86765
|
if (!common)
|
|
86426
86766
|
return;
|
|
86427
|
-
const file =
|
|
86767
|
+
const file = path65.join(common, "info", "exclude");
|
|
86428
86768
|
let text = "";
|
|
86429
86769
|
try {
|
|
86430
86770
|
text = fs32.readFileSync(file, "utf8");
|
|
@@ -86433,7 +86773,7 @@ function excludeScratch(cwd) {
|
|
|
86433
86773
|
}
|
|
86434
86774
|
if (text.split(/\r?\n/u).includes(EXCLUDE_LINE))
|
|
86435
86775
|
return;
|
|
86436
|
-
fs32.mkdirSync(
|
|
86776
|
+
fs32.mkdirSync(path65.dirname(file), { recursive: true });
|
|
86437
86777
|
fs32.appendFileSync(file, `${text && !text.endsWith(`
|
|
86438
86778
|
`) ? `
|
|
86439
86779
|
` : ""}# workit fanout: per-worker scratch dirs
|
|
@@ -86442,13 +86782,13 @@ ${EXCLUDE_LINE}
|
|
|
86442
86782
|
}
|
|
86443
86783
|
function worktreeDependencies(main, worktree) {
|
|
86444
86784
|
for (const [name, install] of LOCKFILES2) {
|
|
86445
|
-
const ours = readBytes(
|
|
86446
|
-
const theirs = readBytes(
|
|
86785
|
+
const ours = readBytes(path65.join(main, name));
|
|
86786
|
+
const theirs = readBytes(path65.join(worktree, name));
|
|
86447
86787
|
if (ours === null && theirs === null)
|
|
86448
86788
|
continue;
|
|
86449
86789
|
if (ours !== null && theirs !== null && ours.equals(theirs))
|
|
86450
86790
|
continue;
|
|
86451
|
-
if (fs32.existsSync(
|
|
86791
|
+
if (fs32.existsSync(path65.join(worktree, "node_modules")))
|
|
86452
86792
|
break;
|
|
86453
86793
|
const command = install(worktree);
|
|
86454
86794
|
return {
|
|
@@ -86460,7 +86800,7 @@ function worktreeDependencies(main, worktree) {
|
|
|
86460
86800
|
};
|
|
86461
86801
|
}
|
|
86462
86802
|
const stale = staleBunInstall(main);
|
|
86463
|
-
if (stale && !fs32.existsSync(
|
|
86803
|
+
if (stale && !fs32.existsSync(path65.join(worktree, "node_modules"))) {
|
|
86464
86804
|
const command = `bun install --frozen-lockfile --cwd ${worktree}`;
|
|
86465
86805
|
return {
|
|
86466
86806
|
linked: null,
|
|
@@ -86473,9 +86813,9 @@ function worktreeDependencies(main, worktree) {
|
|
|
86473
86813
|
return { ...linkWorktreeDependencies(main, worktree), install: null };
|
|
86474
86814
|
}
|
|
86475
86815
|
function staleBunInstall(main) {
|
|
86476
|
-
if (!fs32.existsSync(
|
|
86816
|
+
if (!fs32.existsSync(path65.join(main, "node_modules")))
|
|
86477
86817
|
return null;
|
|
86478
|
-
const text = readBytes(
|
|
86818
|
+
const text = readBytes(path65.join(main, "bun.lock"))?.toString("utf8");
|
|
86479
86819
|
if (!text)
|
|
86480
86820
|
return null;
|
|
86481
86821
|
let packages;
|
|
@@ -86502,7 +86842,7 @@ function staleBunInstall(main) {
|
|
|
86502
86842
|
const version = spec.slice(at + 1);
|
|
86503
86843
|
if (name !== key || version.includes(":"))
|
|
86504
86844
|
continue;
|
|
86505
|
-
const manifest = readBytes(
|
|
86845
|
+
const manifest = readBytes(path65.join(main, "node_modules", key, "package.json"));
|
|
86506
86846
|
if (!manifest) {
|
|
86507
86847
|
problems.push(`${key} missing`);
|
|
86508
86848
|
continue;
|
|
@@ -86519,7 +86859,7 @@ function staleBunInstall(main) {
|
|
|
86519
86859
|
return problems.length ? problems.join("; ") : null;
|
|
86520
86860
|
}
|
|
86521
86861
|
function ensureScratch(worktree) {
|
|
86522
|
-
const scratch =
|
|
86862
|
+
const scratch = path65.join(worktree, SCRATCH_DIR);
|
|
86523
86863
|
fs32.mkdirSync(scratch, { recursive: true });
|
|
86524
86864
|
return scratch;
|
|
86525
86865
|
}
|
|
@@ -86793,7 +87133,7 @@ function unpushedCount(cwd, branch) {
|
|
|
86793
87133
|
return count.ok ? Number(count.stdout.trim()) : null;
|
|
86794
87134
|
}
|
|
86795
87135
|
function removeScratch(worktree) {
|
|
86796
|
-
const scratch =
|
|
87136
|
+
const scratch = path65.join(worktree, SCRATCH_DIR);
|
|
86797
87137
|
let stat;
|
|
86798
87138
|
try {
|
|
86799
87139
|
stat = fs32.lstatSync(scratch);
|
|
@@ -86809,16 +87149,16 @@ var SLOW, SCRATCH_DIR = ".workit-scratch", EXCLUDE_LINE, DIRTY_ROW_BYTES = 2000,
|
|
|
86809
87149
|
try {
|
|
86810
87150
|
return fs32.realpathSync.native(target);
|
|
86811
87151
|
} catch {
|
|
86812
|
-
return
|
|
87152
|
+
return path65.resolve(target);
|
|
86813
87153
|
}
|
|
86814
87154
|
}, samePath = (a, b) => {
|
|
86815
87155
|
const left = canonical2(a);
|
|
86816
87156
|
const right = canonical2(b);
|
|
86817
87157
|
return process.platform === "win32" || process.platform === "darwin" ? left.toLowerCase() === right.toLowerCase() : left === right;
|
|
86818
87158
|
}, inside3 = (child, parent) => {
|
|
86819
|
-
const relative =
|
|
86820
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
86821
|
-
}, slicePath = (cwd, slice) =>
|
|
87159
|
+
const relative = path65.relative(canonical2(parent), canonical2(child));
|
|
87160
|
+
return relative === "" || !relative.startsWith("..") && !path65.isAbsolute(relative);
|
|
87161
|
+
}, slicePath = (cwd, slice) => path65.isAbsolute(slice.worktree) ? slice.worktree : path65.resolve(mainCheckout(cwd), slice.worktree), CLOCK_SLACK_MS = 2000, worktreeDeps, LOCKFILES2, readBytes = (file) => {
|
|
86822
87162
|
try {
|
|
86823
87163
|
return fs32.readFileSync(file);
|
|
86824
87164
|
} catch {
|
|
@@ -86850,7 +87190,7 @@ var init_fanout_worktree = __esm(() => {
|
|
|
86850
87190
|
|
|
86851
87191
|
// packages/workit-core/src/forge/merge-cleanup.ts
|
|
86852
87192
|
import fs33 from "node:fs";
|
|
86853
|
-
import
|
|
87193
|
+
import path66 from "node:path";
|
|
86854
87194
|
function cleanupMergedBranch(cwd, branch, mergedHead) {
|
|
86855
87195
|
const out = { branchDeleted: false, worktreeRemoved: null, notes: [] };
|
|
86856
87196
|
if (!branch || branch.startsWith("-"))
|
|
@@ -86910,13 +87250,13 @@ var SLOW2, isFanoutWorktree = (worktree) => {
|
|
|
86910
87250
|
if (!dir.ok)
|
|
86911
87251
|
return false;
|
|
86912
87252
|
try {
|
|
86913
|
-
return fs33.readFileSync(
|
|
87253
|
+
return fs33.readFileSync(path66.join(dir.stdout.trim(), FANOUT_TOKEN_FILE), "utf8").trim() !== "";
|
|
86914
87254
|
} catch {
|
|
86915
87255
|
return false;
|
|
86916
87256
|
}
|
|
86917
87257
|
}, inside4 = (child, parent) => {
|
|
86918
|
-
const relative =
|
|
86919
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
87258
|
+
const relative = path66.relative(fs33.realpathSync.native(parent), fs33.realpathSync.native(child));
|
|
87259
|
+
return relative === "" || !relative.startsWith("..") && !path66.isAbsolute(relative);
|
|
86920
87260
|
};
|
|
86921
87261
|
var init_merge_cleanup = __esm(() => {
|
|
86922
87262
|
init_fanout();
|
|
@@ -87368,7 +87708,7 @@ __export(exports_pr, {
|
|
|
87368
87708
|
run: () => run15
|
|
87369
87709
|
});
|
|
87370
87710
|
import { existsSync as existsSync27, readFileSync as readFileSync27 } from "node:fs";
|
|
87371
|
-
import
|
|
87711
|
+
import path67 from "node:path";
|
|
87372
87712
|
function titleRules(cwd) {
|
|
87373
87713
|
let root;
|
|
87374
87714
|
try {
|
|
@@ -87379,7 +87719,7 @@ function titleRules(cwd) {
|
|
|
87379
87719
|
let text = null;
|
|
87380
87720
|
let name = "";
|
|
87381
87721
|
for (const candidate of COMMITLINT_FILES) {
|
|
87382
|
-
const full =
|
|
87722
|
+
const full = path67.join(root, candidate);
|
|
87383
87723
|
if (!existsSync27(full))
|
|
87384
87724
|
continue;
|
|
87385
87725
|
text = readFileSync27(full, "utf8");
|
|
@@ -87388,7 +87728,7 @@ function titleRules(cwd) {
|
|
|
87388
87728
|
}
|
|
87389
87729
|
if (text === null) {
|
|
87390
87730
|
try {
|
|
87391
|
-
const pkg = JSON.parse(readFileSync27(
|
|
87731
|
+
const pkg = JSON.parse(readFileSync27(path67.join(root, "package.json"), "utf8"));
|
|
87392
87732
|
if (pkg.commitlint === undefined)
|
|
87393
87733
|
return { rules: null, note: null };
|
|
87394
87734
|
text = JSON.stringify(pkg.commitlint);
|
|
@@ -87485,7 +87825,7 @@ function refuseTitle(io, title, line) {
|
|
|
87485
87825
|
function readBodyFile(io, file) {
|
|
87486
87826
|
try {
|
|
87487
87827
|
return {
|
|
87488
|
-
body: file === "-" ? forgeDeps.readStdin() : readFileSync27(
|
|
87828
|
+
body: file === "-" ? forgeDeps.readStdin() : readFileSync27(path67.resolve(io.cwd, file), "utf8")
|
|
87489
87829
|
};
|
|
87490
87830
|
} catch {
|
|
87491
87831
|
return `cannot read --body-file ${file}`;
|
|
@@ -87681,7 +88021,7 @@ async function create4(argv, io) {
|
|
|
87681
88021
|
return usage4(io, planned.error, CREATE_USAGE);
|
|
87682
88022
|
const links = planned.data.links;
|
|
87683
88023
|
const actor = actorFromEnv(io.env);
|
|
87684
|
-
const result = await createPullRequest(io.cwd, connected.data, {
|
|
88024
|
+
const result = await progressFor(io).run("Opening the pull request", () => createPullRequest(io.cwd, connected.data, {
|
|
87685
88025
|
base,
|
|
87686
88026
|
title,
|
|
87687
88027
|
body: withIssueLines(body ?? "", links),
|
|
@@ -87689,12 +88029,12 @@ async function create4(argv, io) {
|
|
|
87689
88029
|
actor,
|
|
87690
88030
|
labels: flags.lists.label ?? [],
|
|
87691
88031
|
reviewers: flags.lists.reviewer ?? []
|
|
87692
|
-
}, forgeDeps.sleep);
|
|
88032
|
+
}, forgeDeps.sleep), (r) => r.ok ? "done" : "failed");
|
|
87693
88033
|
if (!result.ok)
|
|
87694
88034
|
return forgeFail(io, result);
|
|
87695
88035
|
const opened = result.data.created;
|
|
87696
88036
|
const linked = opened ? recordIssueLinks(io.cwd, result.data, links, { actor, forge: forge.kind, repo: forge.repo }) : [];
|
|
87697
|
-
const backlinks = opened && planned.data.backlink && links.length ? await postBacklinks(io.cwd, connected.data, result.data, links, { env: io.env }) : [];
|
|
88037
|
+
const backlinks = opened && planned.data.backlink && links.length ? await progressFor(io).run("Posting issue backlinks", () => postBacklinks(io.cwd, connected.data, result.data, links, { env: io.env })) : [];
|
|
87698
88038
|
const created = {
|
|
87699
88039
|
...result.data,
|
|
87700
88040
|
issues: links.map((link) => ({
|
|
@@ -87803,7 +88143,7 @@ async function merge3(argv, io) {
|
|
|
87803
88143
|
const connected = connect(io);
|
|
87804
88144
|
if (!connected.ok)
|
|
87805
88145
|
return forgeFail(io, connected);
|
|
87806
|
-
const result = await mergePullRequest(io.cwd, connected.data, {
|
|
88146
|
+
const result = await progressFor(io).run(`Merging PR #${pr}`, () => mergePullRequest(io.cwd, connected.data, {
|
|
87807
88147
|
pr,
|
|
87808
88148
|
method,
|
|
87809
88149
|
deleteBranch: flags.booleans.has("delete-branch"),
|
|
@@ -87813,7 +88153,7 @@ async function merge3(argv, io) {
|
|
|
87813
88153
|
...baseRedOk && baseRedReason ? { baseRedOk: { reason: baseRedReason } } : {},
|
|
87814
88154
|
...subject !== undefined ? { subject } : {},
|
|
87815
88155
|
...body !== undefined ? { body } : {}
|
|
87816
|
-
}, forgeDeps.sleep);
|
|
88156
|
+
}, forgeDeps.sleep), (r) => r.ok ? "done" : "failed");
|
|
87817
88157
|
if (!result.ok)
|
|
87818
88158
|
return emit(io, fail2(result.code, result.error, {
|
|
87819
88159
|
unblock: result.unblock,
|
|
@@ -88017,6 +88357,7 @@ var CONVENTIONAL_TYPES, COMMITLINT_FILES, DEFAULT_IGNORES, UNCHECKED = (what) =>
|
|
|
88017
88357
|
return `verdict ${verdict.verdictId} accepted for that head${verdict.cover ? ` (stack verdict on ${verdict.cover.branch} @ ${verdict.cover.head.slice(0, 12)})` : verdict.carry ? ` (${carryLabel(verdict.carry)})` : ""}`;
|
|
88018
88358
|
}, acceptedHow = (verdict) => verdict.cover ? `stack verdict ${verdict.cover.verdictId} on ${verdict.cover.branch} @ ${verdict.cover.head.slice(0, 12)}` : verdict.carry ? carryLabel(verdict.carry) : verdict.basis, METHODS2;
|
|
88019
88359
|
var init_pr = __esm(() => {
|
|
88360
|
+
init_progress();
|
|
88020
88361
|
init_autonomy();
|
|
88021
88362
|
init_issue_link();
|
|
88022
88363
|
init_pr_edit();
|
|
@@ -88130,7 +88471,7 @@ async function wait2(argv, io) {
|
|
|
88130
88471
|
let verdict = { state: "waiting", reason: "not_polled" };
|
|
88131
88472
|
let baseContexts = null;
|
|
88132
88473
|
let expectedMissing = [];
|
|
88133
|
-
const waiting =
|
|
88474
|
+
const waiting = progressFor(io).start("Waiting for CI");
|
|
88134
88475
|
const abort = (...args) => {
|
|
88135
88476
|
waiting.end("failed");
|
|
88136
88477
|
return forgeFail(io, ...args);
|
|
@@ -88253,15 +88594,15 @@ async function rerun(argv, io) {
|
|
|
88253
88594
|
const number = selectPr(io.cwd, resolved, { pr, branch: flags.values.branch ?? null });
|
|
88254
88595
|
if (!number.ok)
|
|
88255
88596
|
return forgeFail(io, number);
|
|
88256
|
-
const status = resolved.forge.prStatus(number.data);
|
|
88597
|
+
const status = progressFor(io).runSync(`Reading PR #${number.data} checks`, () => resolved.forge.prStatus(number.data), (r) => r.ok ? "done" : "failed");
|
|
88257
88598
|
if (!status.ok)
|
|
88258
88599
|
return forgeFail(io, status);
|
|
88259
|
-
const done = executeRerun(io.cwd, resolved, status.data, {
|
|
88600
|
+
const done = progressFor(io).runSync("Rerunning the checks", () => executeRerun(io.cwd, resolved, status.data, {
|
|
88260
88601
|
failed: names.length === 0,
|
|
88261
88602
|
names,
|
|
88262
88603
|
reason,
|
|
88263
88604
|
force: flags.booleans.has("force")
|
|
88264
|
-
});
|
|
88605
|
+
}), (r) => r.ok ? "done" : "failed");
|
|
88265
88606
|
if (!done.ok)
|
|
88266
88607
|
return forgeFail(io, done);
|
|
88267
88608
|
const outcome = done.data;
|
|
@@ -88374,7 +88715,7 @@ __export(exports_git, {
|
|
|
88374
88715
|
run: () => run17
|
|
88375
88716
|
});
|
|
88376
88717
|
import { readFileSync as readFileSync28 } from "node:fs";
|
|
88377
|
-
import
|
|
88718
|
+
import path68 from "node:path";
|
|
88378
88719
|
function kindHint(cwd, kind) {
|
|
88379
88720
|
let kinds = [...BRANCH_KINDS];
|
|
88380
88721
|
try {
|
|
@@ -88478,7 +88819,7 @@ function commitMessage(parsed, io) {
|
|
|
88478
88819
|
|
|
88479
88820
|
`);
|
|
88480
88821
|
try {
|
|
88481
|
-
return file === "-" ? readFileSync28(0, "utf8") : readFileSync28(
|
|
88822
|
+
return file === "-" ? readFileSync28(0, "utf8") : readFileSync28(path68.resolve(io.cwd, file), "utf8");
|
|
88482
88823
|
} catch (error) {
|
|
88483
88824
|
return {
|
|
88484
88825
|
error: `cannot read -F ${file}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -89375,17 +89716,17 @@ async function releasePr(io, plan, dryRun) {
|
|
|
89375
89716
|
const switched = switchToRelease(io.cwd, plan);
|
|
89376
89717
|
if (!switched.ok)
|
|
89377
89718
|
return forgeFail(io, switched);
|
|
89378
|
-
const pushed = await subVerb(() => Promise.resolve().then(() => (init_git2(), exports_git)), ["push", "--set-upstream"], io);
|
|
89719
|
+
const pushed = await progressFor(io).run(`Pushing ${plan.branch}`, () => subVerb(() => Promise.resolve().then(() => (init_git2(), exports_git)), ["push", "--set-upstream"], io), (r) => r.ok ? "done" : "failed");
|
|
89379
89720
|
if (!pushed.ok)
|
|
89380
89721
|
return emit(io, pushed);
|
|
89381
|
-
const pr = await subVerb(() => Promise.resolve().then(() => (init_pr(), exports_pr)), [
|
|
89722
|
+
const pr = await progressFor(io).run("Opening the release PR", () => subVerb(() => Promise.resolve().then(() => (init_pr(), exports_pr)), [
|
|
89382
89723
|
"create",
|
|
89383
89724
|
"--base",
|
|
89384
89725
|
plan.production,
|
|
89385
89726
|
"--title",
|
|
89386
89727
|
title,
|
|
89387
89728
|
`--body=${plan.changelog ?? `Release ${plan.version}`}`
|
|
89388
|
-
], io);
|
|
89729
|
+
], io), (r) => r.ok ? "done" : "failed");
|
|
89389
89730
|
if (!pr.ok)
|
|
89390
89731
|
return emit(io, pr);
|
|
89391
89732
|
recordReleaseStep(io.cwd, actorFromEnv(io.env), plan, {
|
|
@@ -89441,11 +89782,11 @@ async function finish2(argv, io) {
|
|
|
89441
89782
|
if (!push.allowed)
|
|
89442
89783
|
return blocked(io, push);
|
|
89443
89784
|
const resume = `workit release finish ${plan.version}${plan.track ? ` --track ${plan.track}` : ""}`;
|
|
89444
|
-
const merged = finishLocally(io.cwd, plan, actor);
|
|
89785
|
+
const merged = progressFor(io).runSync(`Merging release ${plan.version} locally`, () => finishLocally(io.cwd, plan, actor), (r) => r.ok ? "done" : "failed");
|
|
89445
89786
|
if (!merged.ok)
|
|
89446
89787
|
return forgeFail(io, merged, { step: "merge", resume });
|
|
89447
89788
|
const notes = [...plan.notes];
|
|
89448
|
-
const pushed = await subVerb(() => Promise.resolve().then(() => (init_git2(), exports_git)), ["push", ...[...plan.pushBranches, plan.tag].flatMap((ref) => ["--release", ref])], io);
|
|
89789
|
+
const pushed = await progressFor(io).run("Pushing the release branches and tag", () => subVerb(() => Promise.resolve().then(() => (init_git2(), exports_git)), ["push", ...[...plan.pushBranches, plan.tag].flatMap((ref) => ["--release", ref])], io), (r) => r.ok ? "done" : "failed");
|
|
89449
89790
|
if (!pushed.ok)
|
|
89450
89791
|
return emit(io, { ...pushed, data: { ...pushed.data, step: "push", resume } });
|
|
89451
89792
|
if (plan.published && plan.remote) {
|
|
@@ -89577,6 +89918,7 @@ var START_USAGE = "workit release start <version> [--hotfix] [--track <t>] [--js
|
|
|
89577
89918
|
{ step: `verify ${plan.tag} on the remote`, done: false }
|
|
89578
89919
|
];
|
|
89579
89920
|
var init_release2 = __esm(() => {
|
|
89921
|
+
init_progress();
|
|
89580
89922
|
init_autonomy();
|
|
89581
89923
|
init_verify();
|
|
89582
89924
|
init_ops();
|
|
@@ -89627,14 +89969,14 @@ async function run19(argv, io) {
|
|
|
89627
89969
|
if (expect === "pushed") {
|
|
89628
89970
|
if (pr)
|
|
89629
89971
|
return usage4(io, "push is checked by --branch, not --pr", USAGE12);
|
|
89630
|
-
result = verifyPushed(io.cwd, { branch, sha, actor });
|
|
89972
|
+
result = progressFor(io).runSync("Checking the push", () => verifyPushed(io.cwd, { branch, sha, actor }), (r) => r.ok ? "done" : "failed");
|
|
89631
89973
|
} else if (expect === "released") {
|
|
89632
|
-
result = verifyReleased(io.cwd, { tag: flags.values.tag ?? null, pkg: flags.values.package ?? null, sha, actor }, forgeDeps.npm);
|
|
89974
|
+
result = progressFor(io).runSync("Checking the release", () => verifyReleased(io.cwd, { tag: flags.values.tag ?? null, pkg: flags.values.package ?? null, sha, actor }, forgeDeps.npm), (r) => r.ok ? "done" : "failed");
|
|
89633
89975
|
} else {
|
|
89634
89976
|
const connected = connect(io, branch);
|
|
89635
89977
|
if (!connected.ok)
|
|
89636
89978
|
return forgeFail(io, connected);
|
|
89637
|
-
result = expect === "pr" ? verifyPr(io.cwd, connected.data, { pr, branch, sha, actor }) : verifyMerged(io.cwd, connected.data, { pr, branch, actor });
|
|
89979
|
+
result = expect === "pr" ? progressFor(io).runSync(`Checking the PR`, () => verifyPr(io.cwd, connected.data, { pr, branch, sha, actor }), (r) => r.ok ? "done" : "failed") : progressFor(io).runSync("Checking the merge", () => verifyMerged(io.cwd, connected.data, { pr, branch, actor }), (r) => r.ok ? "done" : "failed");
|
|
89638
89980
|
}
|
|
89639
89981
|
if (!result.ok)
|
|
89640
89982
|
return forgeFail(io, result);
|
|
@@ -89661,6 +90003,7 @@ var USAGE12 = "workit verify-delivery [push|pr|merge|release] [--expect pushed|p
|
|
|
89661
90003
|
...report.observations.map((entry) => ` ${entry.ok ? "ok" : "x "} ${entry.kind}: expected ${entry.expected ?? "-"}, observed ${entry.observed ?? "(none)"}${entry.note ? ` — ${entry.note}` : ""}`)
|
|
89662
90004
|
];
|
|
89663
90005
|
var init_verify_delivery = __esm(() => {
|
|
90006
|
+
init_progress();
|
|
89664
90007
|
init_verify();
|
|
89665
90008
|
init_task_store();
|
|
89666
90009
|
init_task_delivery();
|
|
@@ -89796,7 +90139,7 @@ async function sync(argv, io, restack = false) {
|
|
|
89796
90139
|
};
|
|
89797
90140
|
}
|
|
89798
90141
|
const name = selected.data.name;
|
|
89799
|
-
const result = await withStackLock(io.cwd, name, async () => {
|
|
90142
|
+
const result = await progressFor(io).run(restack ? `Restacking ${name}` : `Syncing ${name}`, () => withStackLock(io.cwd, name, async () => {
|
|
89800
90143
|
const fresh = readStack(io.cwd, name);
|
|
89801
90144
|
if (!fresh.ok)
|
|
89802
90145
|
return fresh;
|
|
@@ -89809,10 +90152,13 @@ async function sync(argv, io, restack = false) {
|
|
|
89809
90152
|
ok: true,
|
|
89810
90153
|
data: {
|
|
89811
90154
|
...synced.data,
|
|
89812
|
-
pruned: pruneMergedBranches(io.cwd, ctx, stack, {
|
|
90155
|
+
pruned: pruneMergedBranches(io.cwd, ctx, stack, {
|
|
90156
|
+
dryRun,
|
|
90157
|
+
actor: actorFromEnv(io.env)
|
|
90158
|
+
})
|
|
89813
90159
|
}
|
|
89814
90160
|
};
|
|
89815
|
-
});
|
|
90161
|
+
}), (r) => r.ok ? "done" : "failed");
|
|
89816
90162
|
if (!result.ok)
|
|
89817
90163
|
return stackFailed(io, result);
|
|
89818
90164
|
if (restack)
|
|
@@ -89861,7 +90207,7 @@ async function land(argv, io) {
|
|
|
89861
90207
|
if (!connected.ok)
|
|
89862
90208
|
return forgeFail(io, connected);
|
|
89863
90209
|
const name = selected.data.name;
|
|
89864
|
-
const result = await withStackLock(io.cwd, name, async () => {
|
|
90210
|
+
const result = await progressFor(io).run(`Landing ${name}`, () => withStackLock(io.cwd, name, async () => {
|
|
89865
90211
|
const fresh = readStack(io.cwd, name);
|
|
89866
90212
|
if (!fresh.ok)
|
|
89867
90213
|
return fresh;
|
|
@@ -89879,7 +90225,7 @@ async function land(argv, io) {
|
|
|
89879
90225
|
unverified,
|
|
89880
90226
|
baseRedOk: baseRedOk && baseRedReason ? { reason: baseRedReason } : null
|
|
89881
90227
|
});
|
|
89882
|
-
});
|
|
90228
|
+
}), (r) => r.ok ? "done" : "failed");
|
|
89883
90229
|
if (!result.ok)
|
|
89884
90230
|
return stackFailed(io, result);
|
|
89885
90231
|
const kind = connected.data.forge.kind;
|
|
@@ -89926,6 +90272,7 @@ var PLAN_USAGE = "workit stack plan [--name <n>] [--trunk <b> | --track <t>] [<b
|
|
|
89926
90272
|
...data.pruned.kept.map((item) => `kept merged branch ${item.branch}: ${item.reason}`)
|
|
89927
90273
|
], METHODS3;
|
|
89928
90274
|
var init_stack2 = __esm(() => {
|
|
90275
|
+
init_progress();
|
|
89929
90276
|
init_ledger();
|
|
89930
90277
|
init_stack();
|
|
89931
90278
|
init_output();
|
|
@@ -89936,7 +90283,7 @@ var init_stack2 = __esm(() => {
|
|
|
89936
90283
|
// packages/workit-core/src/fanout-brief.ts
|
|
89937
90284
|
import { createHash as createHash20 } from "node:crypto";
|
|
89938
90285
|
import fs35 from "node:fs";
|
|
89939
|
-
import
|
|
90286
|
+
import path69 from "node:path";
|
|
89940
90287
|
function workerSession(lead, slice, attempt) {
|
|
89941
90288
|
const tail = attempt === null ? "" : `+try${attempt}`;
|
|
89942
90289
|
const full = `${lead}-w-${slice}${tail}`;
|
|
@@ -90019,7 +90366,7 @@ function renderBrief(cwd, plan, input) {
|
|
|
90019
90366
|
"STANDING:",
|
|
90020
90367
|
...standing.length ? standing.map((order) => ` - ${order.what}`) : [" - none recorded beyond this brief"],
|
|
90021
90368
|
exists ? `WORKTREE: ${planned} (made by \`workit fanout worktree create ${slice.id}\`; yours alone)` : `WORKTREE: ${planned} (not made yet: the lead runs \`workit fanout worktree create ${slice.id}\` before spawning, then renders this brief again)`,
|
|
90022
|
-
...exists && typeof made?.install === "string" && !fs35.existsSync(
|
|
90369
|
+
...exists && typeof made?.install === "string" && !fs35.existsSync(path69.join(planned, "node_modules")) ? [`INSTALL: \`${made.install}\` first: the main checkout's node_modules was not linked here`] : [],
|
|
90023
90370
|
...identityLines(identity, minted),
|
|
90024
90371
|
...rules(mode, branch, sliceBase, exists ? planned : null)
|
|
90025
90372
|
];
|
|
@@ -90561,7 +90908,7 @@ __export(exports_fanout, {
|
|
|
90561
90908
|
run: () => run21
|
|
90562
90909
|
});
|
|
90563
90910
|
import fs36 from "node:fs";
|
|
90564
|
-
import
|
|
90911
|
+
import path70 from "node:path";
|
|
90565
90912
|
function forgeFor(io, offline) {
|
|
90566
90913
|
if (offline)
|
|
90567
90914
|
return { forge: null, error: "--offline" };
|
|
@@ -90622,7 +90969,7 @@ function plan2(argv, io) {
|
|
|
90622
90969
|
return usage4(io, "pass --trunk or --track, not both (--track picks the trunk)", PLAN_USAGE2);
|
|
90623
90970
|
if (flags.positionals.length !== 1)
|
|
90624
90971
|
return usage4(io, flags.positionals.length ? `unexpected argument ${flags.positionals[1]}` : "missing <plan.json>", PLAN_USAGE2);
|
|
90625
|
-
const file =
|
|
90972
|
+
const file = path70.resolve(io.cwd, flags.positionals[0]);
|
|
90626
90973
|
let raw;
|
|
90627
90974
|
try {
|
|
90628
90975
|
raw = JSON.parse(fs36.readFileSync(file, "utf8"));
|
|
@@ -90688,11 +91035,11 @@ function check2(argv, io) {
|
|
|
90688
91035
|
const selected = selectFanout(io.cwd, flags.values.name ?? null, currentBranch(io.cwd));
|
|
90689
91036
|
if (!selected.ok)
|
|
90690
91037
|
return failed(io, selected);
|
|
90691
|
-
const result = checkFanout(io.cwd, selected.data, {
|
|
91038
|
+
const result = progressFor(io).runSync("Checking the fan-out slices", () => checkFanout(io.cwd, selected.data, {
|
|
90692
91039
|
only: flags.positionals,
|
|
90693
91040
|
trunkRef: flags.values.base ?? null,
|
|
90694
91041
|
forge: forgeFor(io, flags.booleans.has("offline")).forge
|
|
90695
|
-
});
|
|
91042
|
+
}), (r) => r.ok ? "done" : "failed");
|
|
90696
91043
|
if (!result.ok)
|
|
90697
91044
|
return failed(io, result);
|
|
90698
91045
|
if (result.data.ready)
|
|
@@ -90721,11 +91068,11 @@ function status4(argv, io) {
|
|
|
90721
91068
|
if (!selected.ok)
|
|
90722
91069
|
return failed(io, selected);
|
|
90723
91070
|
const forge = forgeFor(io, flags.booleans.has("offline"));
|
|
90724
|
-
const result = fanoutStatus(io.cwd, selected.data, {
|
|
91071
|
+
const result = progressFor(io).runSync("Reading the fan-out status", () => fanoutStatus(io.cwd, selected.data, {
|
|
90725
91072
|
forge: forge.forge,
|
|
90726
91073
|
forgeError: forge.error,
|
|
90727
91074
|
stuckAfterMs
|
|
90728
|
-
});
|
|
91075
|
+
}), (r) => r.ok ? "done" : "failed");
|
|
90729
91076
|
if (!result.ok)
|
|
90730
91077
|
return failed(io, result);
|
|
90731
91078
|
return emit(io, ok2(result.data), renderStatus2);
|
|
@@ -90831,6 +91178,7 @@ var PLAN_USAGE2 = "workit fanout plan <plan.json> [--name <n>] [--trunk <b> | --
|
|
|
90831
91178
|
];
|
|
90832
91179
|
};
|
|
90833
91180
|
var init_fanout2 = __esm(() => {
|
|
91181
|
+
init_progress();
|
|
90834
91182
|
init_fanout_brief();
|
|
90835
91183
|
init_fanout_check();
|
|
90836
91184
|
init_fanout_status();
|
|
@@ -106197,7 +106545,7 @@ var init_ast = __esm(() => {
|
|
|
106197
106545
|
|
|
106198
106546
|
// packages/workit-cli/src/test-audit/rules.ts
|
|
106199
106547
|
import { builtinModules } from "node:module";
|
|
106200
|
-
import
|
|
106548
|
+
import path71 from "node:path";
|
|
106201
106549
|
function testCallee(call) {
|
|
106202
106550
|
let callee = call.callee;
|
|
106203
106551
|
if (callee.type === "CallExpression")
|
|
@@ -106690,12 +107038,12 @@ function checkConstantsOnly(ctx, emit) {
|
|
|
106690
107038
|
}
|
|
106691
107039
|
function checkOverMocking(ctx, emit) {
|
|
106692
107040
|
const { program } = ctx.parsed;
|
|
106693
|
-
const unit =
|
|
107041
|
+
const unit = path71.basename(ctx.file).replace(/\.(?:[cm]?[jt]sx?)$/, "").replace(/\.(?:test|spec)$/, "");
|
|
106694
107042
|
const mocked = find2(program, (node) => node.type === "CallExpression" && MODULE_MOCK.test(calleeName(node.callee) ?? "") && node.arguments[0]?.type === "StringLiteral");
|
|
106695
107043
|
const internal = mocked.filter((call) => /^(?:\.|@\/|~\/)/.test(call.arguments[0].value));
|
|
106696
107044
|
for (const call of mocked) {
|
|
106697
107045
|
const spec = call.arguments[0].value;
|
|
106698
|
-
const base =
|
|
107046
|
+
const base = path71.basename(spec.replace(/\/index(?:\.[cm]?[jt]sx?)?$/, "")).replace(/\.(?:[cm]?[jt]sx?)$/, "");
|
|
106699
107047
|
if (base === unit)
|
|
106700
107048
|
emit({
|
|
106701
107049
|
rule: "over-mocking",
|
|
@@ -107085,7 +107433,7 @@ var init_rules = __esm(() => {
|
|
|
107085
107433
|
// packages/workit-cli/src/test-audit/audit.ts
|
|
107086
107434
|
import { spawnSync as spawnSync29 } from "node:child_process";
|
|
107087
107435
|
import { existsSync as existsSync28, readdirSync as readdirSync14, readFileSync as readFileSync29, statSync as statSync10 } from "node:fs";
|
|
107088
|
-
import
|
|
107436
|
+
import path72 from "node:path";
|
|
107089
107437
|
function git7(cwd, args) {
|
|
107090
107438
|
const run = spawnSync29("git", ["-c", "core.quotepath=off", ...args], {
|
|
107091
107439
|
cwd,
|
|
@@ -107098,7 +107446,7 @@ function walkTests(dir, out) {
|
|
|
107098
107446
|
for (const entry of readdirSync14(dir, { withFileTypes: true })) {
|
|
107099
107447
|
if (entry.name.startsWith(".") && entry.name !== "." && entry.isDirectory())
|
|
107100
107448
|
continue;
|
|
107101
|
-
const full =
|
|
107449
|
+
const full = path72.join(dir, entry.name);
|
|
107102
107450
|
if (entry.isDirectory()) {
|
|
107103
107451
|
if (!SKIP_DIRS.has(entry.name))
|
|
107104
107452
|
walkTests(full, out);
|
|
@@ -107110,7 +107458,7 @@ function expandPaths(cwd, inputs) {
|
|
|
107110
107458
|
const files = [];
|
|
107111
107459
|
const missing = [];
|
|
107112
107460
|
for (const input of inputs.length > 0 ? inputs : ["."]) {
|
|
107113
|
-
const full =
|
|
107461
|
+
const full = path72.resolve(cwd, input);
|
|
107114
107462
|
if (!existsSync28(full))
|
|
107115
107463
|
missing.push(input);
|
|
107116
107464
|
else if (statSync10(full).isDirectory())
|
|
@@ -107147,11 +107495,11 @@ function changedLines(cwd, base) {
|
|
|
107147
107495
|
for (let offset = 0;offset < count; offset += 1)
|
|
107148
107496
|
lines.add(start + offset);
|
|
107149
107497
|
}
|
|
107150
|
-
changed.set(
|
|
107498
|
+
changed.set(path72.join(root, file), lines);
|
|
107151
107499
|
}
|
|
107152
107500
|
const untracked = git7(root, ["ls-files", "--others", "--exclude-standard", "-z"]);
|
|
107153
107501
|
for (const file of untracked.stdout.split("\x00").filter(Boolean))
|
|
107154
|
-
changed.set(
|
|
107502
|
+
changed.set(path72.join(root, file), "all");
|
|
107155
107503
|
return changed;
|
|
107156
107504
|
}
|
|
107157
107505
|
function auditFiles(files, display) {
|
|
@@ -107213,7 +107561,7 @@ function auditFiles(files, display) {
|
|
|
107213
107561
|
durationMs: Math.round(performance.now() - started)
|
|
107214
107562
|
};
|
|
107215
107563
|
}
|
|
107216
|
-
var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(
|
|
107564
|
+
var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(path72.sep).join("/"), SEVERITY_ORDER, ruleIds;
|
|
107217
107565
|
var init_audit = __esm(() => {
|
|
107218
107566
|
init_ast();
|
|
107219
107567
|
init_rules();
|
|
@@ -107225,7 +107573,7 @@ var init_audit = __esm(() => {
|
|
|
107225
107573
|
});
|
|
107226
107574
|
|
|
107227
107575
|
// packages/workit-cli/src/test-audit/mutate.ts
|
|
107228
|
-
import { spawn as
|
|
107576
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
107229
107577
|
import {
|
|
107230
107578
|
existsSync as existsSync29,
|
|
107231
107579
|
lstatSync as lstatSync9,
|
|
@@ -107243,7 +107591,7 @@ import {
|
|
|
107243
107591
|
copyFileSync as copyFileSync8
|
|
107244
107592
|
} from "node:fs";
|
|
107245
107593
|
import os23 from "node:os";
|
|
107246
|
-
import
|
|
107594
|
+
import path73 from "node:path";
|
|
107247
107595
|
function mutantsFor(source, file, lines) {
|
|
107248
107596
|
const parsed = parseSource(source, file);
|
|
107249
107597
|
const out = [];
|
|
@@ -107316,7 +107664,7 @@ function relatedTests(source, testFiles) {
|
|
|
107316
107664
|
for (const match of text.matchAll(SPECIFIER)) {
|
|
107317
107665
|
const spec = match[1];
|
|
107318
107666
|
if (spec.startsWith(".")) {
|
|
107319
|
-
if (stripExt(
|
|
107667
|
+
if (stripExt(path73.posix.join(path73.posix.dirname(file), spec)) === target)
|
|
107320
107668
|
return true;
|
|
107321
107669
|
} else if (spec.includes("/") && stripExt(spec).split("/").slice(-2).join("/") === tail)
|
|
107322
107670
|
return true;
|
|
@@ -107336,12 +107684,12 @@ function removeStaleCopies(tmp = os23.tmpdir()) {
|
|
|
107336
107684
|
for (const name of names) {
|
|
107337
107685
|
if (!name.startsWith(TEMP_PREFIX))
|
|
107338
107686
|
continue;
|
|
107339
|
-
const dir =
|
|
107687
|
+
const dir = path73.join(tmp, name);
|
|
107340
107688
|
try {
|
|
107341
107689
|
const stat = lstatSync9(dir);
|
|
107342
107690
|
if (!stat.isDirectory() || uid !== undefined && stat.uid !== uid)
|
|
107343
107691
|
continue;
|
|
107344
|
-
const pid = Number(readFileSync30(
|
|
107692
|
+
const pid = Number(readFileSync30(path73.join(dir, PID_FILE), "utf8"));
|
|
107345
107693
|
if (Number.isInteger(pid) && pid > 0 && alive(pid))
|
|
107346
107694
|
continue;
|
|
107347
107695
|
} catch (error) {
|
|
@@ -107358,8 +107706,8 @@ function removeStaleCopies(tmp = os23.tmpdir()) {
|
|
|
107358
107706
|
function linkNodeModules(origin, target, repo, copy) {
|
|
107359
107707
|
mkdirSync12(target, { recursive: true });
|
|
107360
107708
|
for (const entry of readdirSync15(origin, { withFileTypes: true })) {
|
|
107361
|
-
const from =
|
|
107362
|
-
const to =
|
|
107709
|
+
const from = path73.join(origin, entry.name);
|
|
107710
|
+
const to = path73.join(target, entry.name);
|
|
107363
107711
|
if (entry.name.startsWith("@") && entry.isDirectory()) {
|
|
107364
107712
|
linkNodeModules(from, to, repo, copy);
|
|
107365
107713
|
continue;
|
|
@@ -107375,9 +107723,9 @@ function linkNodeModules(origin, target, repo, copy) {
|
|
|
107375
107723
|
} catch {
|
|
107376
107724
|
continue;
|
|
107377
107725
|
}
|
|
107378
|
-
const relative =
|
|
107379
|
-
if (!relative.startsWith("..") && !
|
|
107380
|
-
symlinkSync(
|
|
107726
|
+
const relative = path73.relative(repo, real);
|
|
107727
|
+
if (!relative.startsWith("..") && !path73.isAbsolute(relative) && !relative.split(path73.sep).includes("node_modules")) {
|
|
107728
|
+
symlinkSync(path73.join(copy, relative), to, "junction");
|
|
107381
107729
|
continue;
|
|
107382
107730
|
}
|
|
107383
107731
|
}
|
|
@@ -107393,7 +107741,7 @@ function copySymlink(repo, tree, from, to) {
|
|
|
107393
107741
|
}
|
|
107394
107742
|
const realRepo = realpathSync11(repo);
|
|
107395
107743
|
if (real && inside5(realRepo, real)) {
|
|
107396
|
-
symlinkSync(
|
|
107744
|
+
symlinkSync(path73.relative(path73.dirname(to), path73.join(tree, path73.relative(realRepo, real))), to);
|
|
107397
107745
|
return;
|
|
107398
107746
|
}
|
|
107399
107747
|
if (real && statSync11(real).isFile())
|
|
@@ -107402,10 +107750,10 @@ function copySymlink(repo, tree, from, to) {
|
|
|
107402
107750
|
symlinkSync(readlinkSync3(from), to);
|
|
107403
107751
|
}
|
|
107404
107752
|
function writeInside(copy, file, content) {
|
|
107405
|
-
const target =
|
|
107753
|
+
const target = path73.join(copy, file);
|
|
107406
107754
|
try {
|
|
107407
107755
|
const stat = lstatSync9(target);
|
|
107408
|
-
if (!stat.isFile() || !inside5(realpathSync11(copy), realpathSync11(
|
|
107756
|
+
if (!stat.isFile() || !inside5(realpathSync11(copy), realpathSync11(path73.dirname(target))))
|
|
107409
107757
|
return false;
|
|
107410
107758
|
} catch {
|
|
107411
107759
|
return false;
|
|
@@ -107416,9 +107764,9 @@ function writeInside(copy, file, content) {
|
|
|
107416
107764
|
return true;
|
|
107417
107765
|
}
|
|
107418
107766
|
function copyWorkingTree(repo) {
|
|
107419
|
-
const dir = mkdtempSync4(
|
|
107420
|
-
writeFileSync13(
|
|
107421
|
-
const tree =
|
|
107767
|
+
const dir = mkdtempSync4(path73.join(os23.tmpdir(), TEMP_PREFIX));
|
|
107768
|
+
writeFileSync13(path73.join(dir, PID_FILE), String(process.pid));
|
|
107769
|
+
const tree = path73.join(dir, "tree");
|
|
107422
107770
|
const head = git7(repo, ["rev-parse", "--verify", "--quiet", "HEAD"]).stdout.trim();
|
|
107423
107771
|
if (head && git7(dir, ["clone", "-q", "--shared", "--no-checkout", repo, tree]).ok) {
|
|
107424
107772
|
const branch = git7(repo, ["symbolic-ref", "--quiet", "--short", "HEAD"]).stdout.trim();
|
|
@@ -107435,36 +107783,36 @@ function copyWorkingTree(repo) {
|
|
|
107435
107783
|
for (const relative of listed) {
|
|
107436
107784
|
if (!relative)
|
|
107437
107785
|
continue;
|
|
107438
|
-
const from =
|
|
107786
|
+
const from = path73.join(repo, relative);
|
|
107439
107787
|
let stat;
|
|
107440
107788
|
try {
|
|
107441
107789
|
stat = lstatSync9(from);
|
|
107442
107790
|
} catch {
|
|
107443
107791
|
continue;
|
|
107444
107792
|
}
|
|
107445
|
-
const to =
|
|
107446
|
-
mkdirSync12(
|
|
107793
|
+
const to = path73.join(tree, relative);
|
|
107794
|
+
mkdirSync12(path73.dirname(to), { recursive: true });
|
|
107447
107795
|
if (stat.isSymbolicLink())
|
|
107448
107796
|
copySymlink(repo, tree, from, to);
|
|
107449
107797
|
else if (stat.isFile())
|
|
107450
107798
|
copyFileSync8(from, to);
|
|
107451
|
-
let parent =
|
|
107799
|
+
let parent = path73.dirname(relative);
|
|
107452
107800
|
while (parent !== "." && !dirs.has(parent)) {
|
|
107453
107801
|
dirs.add(parent);
|
|
107454
|
-
parent =
|
|
107802
|
+
parent = path73.dirname(parent);
|
|
107455
107803
|
}
|
|
107456
107804
|
}
|
|
107457
107805
|
for (const parent of dirs) {
|
|
107458
|
-
const modules =
|
|
107459
|
-
if (existsSync29(modules) && !existsSync29(
|
|
107460
|
-
linkNodeModules(modules,
|
|
107806
|
+
const modules = path73.join(repo, parent, "node_modules");
|
|
107807
|
+
if (existsSync29(modules) && !existsSync29(path73.join(tree, parent, "node_modules")))
|
|
107808
|
+
linkNodeModules(modules, path73.join(tree, parent, "node_modules"), repo, tree);
|
|
107461
107809
|
}
|
|
107462
107810
|
return { dir, tree };
|
|
107463
107811
|
}
|
|
107464
107812
|
function runCommand(command, cwd, timeoutMs, env) {
|
|
107465
107813
|
const started = performance.now();
|
|
107466
107814
|
return new Promise((resolve) => {
|
|
107467
|
-
const child =
|
|
107815
|
+
const child = spawn4(command, {
|
|
107468
107816
|
cwd,
|
|
107469
107817
|
env,
|
|
107470
107818
|
shell: true,
|
|
@@ -107496,14 +107844,14 @@ async function runMutation(options) {
|
|
|
107496
107844
|
const tracked = git7(repo, ["ls-files", "-co", "--exclude-standard", "-z"]).stdout.split("\x00").filter(Boolean);
|
|
107497
107845
|
const testFiles = tracked.filter((file) => TEST_FILE.test(file)).map((file) => {
|
|
107498
107846
|
try {
|
|
107499
|
-
return { file, text: readFileSync30(
|
|
107847
|
+
return { file, text: readFileSync30(path73.join(repo, file), "utf8") };
|
|
107500
107848
|
} catch {
|
|
107501
107849
|
return { file, text: "" };
|
|
107502
107850
|
}
|
|
107503
107851
|
});
|
|
107504
107852
|
const candidates = [];
|
|
107505
107853
|
for (const [absolute, lines] of [...options.changed].toSorted(([a], [b]) => a.localeCompare(b))) {
|
|
107506
|
-
const relative = toPosix(
|
|
107854
|
+
const relative = toPosix(path73.relative(repo, absolute));
|
|
107507
107855
|
if (!CODE_FILE.test(relative) || TEST_FILE.test(relative) || relative.endsWith(".d.ts"))
|
|
107508
107856
|
continue;
|
|
107509
107857
|
if (NOT_SOURCE.test(relative) || !existsSync29(absolute))
|
|
@@ -107517,9 +107865,9 @@ async function runMutation(options) {
|
|
|
107517
107865
|
for (const mutant of mutants)
|
|
107518
107866
|
if (!related.has(mutant.file))
|
|
107519
107867
|
related.set(mutant.file, relatedTests(mutant.file, testFiles));
|
|
107520
|
-
const cwdRelative =
|
|
107868
|
+
const cwdRelative = path73.relative(repo, options.cwd);
|
|
107521
107869
|
const asArg = (file) => {
|
|
107522
|
-
const relative = toPosix(
|
|
107870
|
+
const relative = toPosix(path73.relative(cwdRelative, file));
|
|
107523
107871
|
return shellQuote(relative.startsWith(".") ? relative : `./${relative}`);
|
|
107524
107872
|
};
|
|
107525
107873
|
const commandFor = (tests) => options.command.replaceAll("{files}", () => tests.map(asArg).join(" "));
|
|
@@ -107555,7 +107903,7 @@ async function runMutation(options) {
|
|
|
107555
107903
|
return finish3(options, 0, results, counts, started);
|
|
107556
107904
|
removeStaleCopies();
|
|
107557
107905
|
const { dir: copyDir, tree: copy } = copyWorkingTree(repo);
|
|
107558
|
-
const copyCwd =
|
|
107906
|
+
const copyCwd = path73.join(copy, cwdRelative);
|
|
107559
107907
|
let current = null;
|
|
107560
107908
|
const restore = () => {
|
|
107561
107909
|
if (current)
|
|
@@ -107590,7 +107938,7 @@ async function runMutation(options) {
|
|
|
107590
107938
|
record({ ...mutant, status: "skipped", durationMs: 0, tests, reason: "budget" });
|
|
107591
107939
|
continue;
|
|
107592
107940
|
}
|
|
107593
|
-
const original = readFileSync30(
|
|
107941
|
+
const original = readFileSync30(path73.join(copy, mutant.file), "utf8");
|
|
107594
107942
|
const mutated = original.slice(0, mutant.start) + mutant.replacement + original.slice(mutant.end);
|
|
107595
107943
|
current = { file: mutant.file, original };
|
|
107596
107944
|
if (!writeInside(copy, mutant.file, mutated)) {
|
|
@@ -107647,8 +107995,8 @@ var NOT_SOURCE, FLIPS, isStringy = (node) => node.type === "StringLiteral" || no
|
|
|
107647
107995
|
return error.code === "EPERM";
|
|
107648
107996
|
}
|
|
107649
107997
|
}, inside5 = (root, file) => {
|
|
107650
|
-
const relative =
|
|
107651
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
107998
|
+
const relative = path73.relative(root, file);
|
|
107999
|
+
return relative === "" || !relative.startsWith("..") && !path73.isAbsolute(relative);
|
|
107652
108000
|
}, active, killTree = (child) => {
|
|
107653
108001
|
try {
|
|
107654
108002
|
if (child.pid && process.platform !== "win32")
|
|
@@ -107697,7 +108045,7 @@ __export(exports_test_audit, {
|
|
|
107697
108045
|
run: () => run23
|
|
107698
108046
|
});
|
|
107699
108047
|
import { existsSync as existsSync30 } from "node:fs";
|
|
107700
|
-
import
|
|
108048
|
+
import path74 from "node:path";
|
|
107701
108049
|
function parse8(argv) {
|
|
107702
108050
|
const options = {
|
|
107703
108051
|
paths: [],
|
|
@@ -107802,8 +108150,8 @@ async function run23(argv, io) {
|
|
|
107802
108150
|
return emit(io, fail2("invalid_input", `${options}
|
|
107803
108151
|
usage: ${USAGE16}`));
|
|
107804
108152
|
const top = git7(io.cwd, ["rev-parse", "--show-toplevel"]);
|
|
107805
|
-
const repo = top.ok ?
|
|
107806
|
-
const display = (file) => toPosix(
|
|
108153
|
+
const repo = top.ok ? path74.resolve(top.stdout.trim()) : null;
|
|
108154
|
+
const display = (file) => toPosix(path74.relative(io.cwd, file) || file);
|
|
107807
108155
|
let base = null;
|
|
107808
108156
|
let changed = null;
|
|
107809
108157
|
if (options.diff || options.mutate) {
|
|
@@ -107942,7 +108290,7 @@ __export(exports_youtrack, {
|
|
|
107942
108290
|
run: () => run25
|
|
107943
108291
|
});
|
|
107944
108292
|
import { readFileSync as readFileSync31 } from "node:fs";
|
|
107945
|
-
import
|
|
108293
|
+
import path75 from "node:path";
|
|
107946
108294
|
async function run25(argv, io) {
|
|
107947
108295
|
const [sub, ...rest] = argv;
|
|
107948
108296
|
if (sub !== "note" && sub !== "time" && sub !== "meeting")
|
|
@@ -107988,7 +108336,7 @@ async function run25(argv, io) {
|
|
|
107988
108336
|
let markdown = flags.values.markdown ?? "";
|
|
107989
108337
|
if (flags.values.file)
|
|
107990
108338
|
try {
|
|
107991
|
-
markdown = readFileSync31(
|
|
108339
|
+
markdown = readFileSync31(path75.resolve(io.cwd, flags.values.file), "utf8");
|
|
107992
108340
|
} catch (error) {
|
|
107993
108341
|
return usage4(io, `cannot read ${flags.values.file}: ${String(error)}`, USAGE18);
|
|
107994
108342
|
}
|
|
@@ -108009,7 +108357,7 @@ async function run25(argv, io) {
|
|
|
108009
108357
|
}
|
|
108010
108358
|
const results = [];
|
|
108011
108359
|
for (const entry of steps) {
|
|
108012
|
-
const outcome = await entry.run();
|
|
108360
|
+
const outcome = await progressFor(io).run(entry.label, () => entry.run());
|
|
108013
108361
|
results.push({
|
|
108014
108362
|
step: entry.label,
|
|
108015
108363
|
status: outcome.status,
|
|
@@ -108044,6 +108392,7 @@ var USAGE18 = "workit youtrack note <ISSUE> (--markdown <t> | --file <p>) [--min
|
|
|
108044
108392
|
}
|
|
108045
108393
|
};
|
|
108046
108394
|
var init_youtrack2 = __esm(() => {
|
|
108395
|
+
init_progress();
|
|
108047
108396
|
init_youtrack();
|
|
108048
108397
|
init_youtrack_tools();
|
|
108049
108398
|
init_youtrack_writes();
|
|
@@ -108057,7 +108406,7 @@ __export(exports_changelog, {
|
|
|
108057
108406
|
run: () => run26
|
|
108058
108407
|
});
|
|
108059
108408
|
import { readFileSync as readFileSync32 } from "node:fs";
|
|
108060
|
-
import
|
|
108409
|
+
import path76 from "node:path";
|
|
108061
108410
|
async function run26(argv, io) {
|
|
108062
108411
|
const [sub, ...rest] = argv;
|
|
108063
108412
|
if (sub !== "apply")
|
|
@@ -108103,7 +108452,7 @@ async function run26(argv, io) {
|
|
|
108103
108452
|
]);
|
|
108104
108453
|
}
|
|
108105
108454
|
var USAGE19 = "workit changelog apply (--entries <JSON|@file|-> | --normalize-only) [--path CHANGELOG.md] [--preview]", readEntries = (raw, cwd) => {
|
|
108106
|
-
const text = raw === "-" ? readFileSync32(0, "utf8") : raw.startsWith("@") ? readFileSync32(
|
|
108455
|
+
const text = raw === "-" ? readFileSync32(0, "utf8") : raw.startsWith("@") ? readFileSync32(path76.resolve(cwd, raw.slice(1)), "utf8") : raw;
|
|
108107
108456
|
return JSON.parse(text);
|
|
108108
108457
|
};
|
|
108109
108458
|
var init_changelog2 = __esm(() => {
|
|
@@ -108119,7 +108468,7 @@ __export(exports_handoff, {
|
|
|
108119
108468
|
run: () => run27
|
|
108120
108469
|
});
|
|
108121
108470
|
import fs37 from "node:fs";
|
|
108122
|
-
import
|
|
108471
|
+
import path77 from "node:path";
|
|
108123
108472
|
import { parseArgs as parseArgs2 } from "node:util";
|
|
108124
108473
|
function render3(brief) {
|
|
108125
108474
|
const lines = [
|
|
@@ -108159,9 +108508,9 @@ function bounded(brief, cwd) {
|
|
|
108159
108508
|
let file = null;
|
|
108160
108509
|
if (store.ok)
|
|
108161
108510
|
try {
|
|
108162
|
-
const dir =
|
|
108511
|
+
const dir = path77.join(store.value.root, "handoff");
|
|
108163
108512
|
fs37.mkdirSync(dir, { recursive: true });
|
|
108164
|
-
file =
|
|
108513
|
+
file = path77.join(dir, `${(brief.branch ?? "detached").replaceAll(/[^\w.-]+/gu, "-")}.txt`);
|
|
108165
108514
|
fs37.writeFileSync(file, `${[...body, ...tail].join(`
|
|
108166
108515
|
`)}
|
|
108167
108516
|
`, {
|
|
@@ -108236,7 +108585,7 @@ var init_handoff = __esm(() => {
|
|
|
108236
108585
|
});
|
|
108237
108586
|
|
|
108238
108587
|
// packages/workit-cli/src/main.ts
|
|
108239
|
-
import
|
|
108588
|
+
import path78 from "node:path";
|
|
108240
108589
|
|
|
108241
108590
|
// packages/workit-core/src/git/env-redirect.ts
|
|
108242
108591
|
var GIT_REDIRECT_ENV = [
|
|
@@ -109185,8 +109534,17 @@ var defaultIo = (json) => ({
|
|
|
109185
109534
|
});
|
|
109186
109535
|
async function main(argv, overrides = {}, options = {}) {
|
|
109187
109536
|
const parsed = parseGlobals(argv);
|
|
109188
|
-
const cwd =
|
|
109189
|
-
const io = {
|
|
109537
|
+
const cwd = path78.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
|
|
109538
|
+
const io = {
|
|
109539
|
+
...defaultIo(parsed.json),
|
|
109540
|
+
terminals: {
|
|
109541
|
+
...overrides.stdout ? {} : { stdout: process.stdout },
|
|
109542
|
+
...overrides.stderr ? {} : { stderr: process.stderr }
|
|
109543
|
+
},
|
|
109544
|
+
...overrides,
|
|
109545
|
+
json: parsed.json,
|
|
109546
|
+
cwd
|
|
109547
|
+
};
|
|
109190
109548
|
if (parsed.error)
|
|
109191
109549
|
return emit(io, fail2("invalid_input", parsed.error));
|
|
109192
109550
|
if (parsed.session !== undefined) {
|