@brainervirus/workit-claude-code 8.38.2 → 8.38.3
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/.claude-plugin/plugin.json +1 -1
- package/dist/workit.js +928 -826
- package/package.json +3 -3
package/dist/workit.js
CHANGED
|
@@ -9317,7 +9317,7 @@ var package_default;
|
|
|
9317
9317
|
var init_package = __esm(() => {
|
|
9318
9318
|
package_default = {
|
|
9319
9319
|
name: "@brainervirus/workit-cli",
|
|
9320
|
-
version: "8.38.
|
|
9320
|
+
version: "8.38.3",
|
|
9321
9321
|
private: false,
|
|
9322
9322
|
description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
9323
9323
|
keywords: [
|
|
@@ -9355,13 +9355,13 @@ var init_package = __esm(() => {
|
|
|
9355
9355
|
},
|
|
9356
9356
|
dependencies: {
|
|
9357
9357
|
"@babel/parser": "7.29.9",
|
|
9358
|
-
"@brainervirus/workit-cursor": "^8.38.
|
|
9358
|
+
"@brainervirus/workit-cursor": "^8.38.3",
|
|
9359
9359
|
"@inkjs/ui": "2.0.0",
|
|
9360
9360
|
ink: "7.1.1",
|
|
9361
9361
|
react: "19.2.8"
|
|
9362
9362
|
},
|
|
9363
9363
|
devDependencies: {
|
|
9364
|
-
"@brainervirus/workit-core": "^8.38.
|
|
9364
|
+
"@brainervirus/workit-core": "^8.38.3"
|
|
9365
9365
|
},
|
|
9366
9366
|
engines: {
|
|
9367
9367
|
node: ">=24"
|
|
@@ -74838,171 +74838,156 @@ var init_setup2 = __esm(() => {
|
|
|
74838
74838
|
ALL_HOSTS = ["claude-code", "codex", "cursor", "opencode", "pi"];
|
|
74839
74839
|
});
|
|
74840
74840
|
|
|
74841
|
-
// packages/workit-cli/src/upgrade.ts
|
|
74842
|
-
import {
|
|
74843
|
-
import {
|
|
74844
|
-
existsSync as existsSync20,
|
|
74845
|
-
mkdtempSync as mkdtempSync3,
|
|
74846
|
-
rmSync as rmSync8,
|
|
74847
|
-
readFileSync as readFileSync21,
|
|
74848
|
-
readdirSync as readdirSync12,
|
|
74849
|
-
mkdirSync as mkdirSync11,
|
|
74850
|
-
copyFileSync as copyFileSync6,
|
|
74851
|
-
chmodSync as chmodSync2,
|
|
74852
|
-
cpSync as cpSync5,
|
|
74853
|
-
lstatSync as lstatSync7
|
|
74854
|
-
} from "node:fs";
|
|
74841
|
+
// packages/workit-cli/src/upgrade/shared.ts
|
|
74842
|
+
import { existsSync as existsSync20, readFileSync as readFileSync21 } from "node:fs";
|
|
74855
74843
|
import path44 from "node:path";
|
|
74856
74844
|
import os16 from "node:os";
|
|
74857
74845
|
import { createHash as createHash15 } from "node:crypto";
|
|
74858
|
-
|
|
74859
|
-
const
|
|
74860
|
-
const
|
|
74861
|
-
|
|
74862
|
-
|
|
74863
|
-
|
|
74864
|
-
|
|
74865
|
-
|
|
74866
|
-
|
|
74867
|
-
|
|
74868
|
-
|
|
74869
|
-
|
|
74870
|
-
|
|
74846
|
+
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", 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) => {
|
|
74847
|
+
const home = deps.home ?? deps.env?.HOME ?? os16.homedir();
|
|
74848
|
+
const env = {
|
|
74849
|
+
...process.env,
|
|
74850
|
+
...deps.home || deps.env?.HOME ? {
|
|
74851
|
+
HOME: home,
|
|
74852
|
+
CODEX_HOME: path44.join(home, ".codex"),
|
|
74853
|
+
CLAUDE_CONFIG_DIR: path44.join(home, ".claude"),
|
|
74854
|
+
PI_CODING_AGENT_DIR: path44.join(home, ".pi/agent"),
|
|
74855
|
+
XDG_CONFIG_HOME: path44.join(home, ".config"),
|
|
74856
|
+
WORKFLOW_TOOLKIT_CONFIG: undefined,
|
|
74857
|
+
WORKFLOW_TOOLKIT_CONFIG_DIR: undefined
|
|
74858
|
+
} : {},
|
|
74859
|
+
...deps.env,
|
|
74860
|
+
HOME: home
|
|
74871
74861
|
};
|
|
74872
|
-
|
|
74873
|
-
|
|
74874
|
-
|
|
74875
|
-
|
|
74862
|
+
const xdg = env.XDG_CONFIG_HOME || path44.join(home, ".config");
|
|
74863
|
+
const codexHome = env.CODEX_HOME ?? path44.join(home, ".codex");
|
|
74864
|
+
return {
|
|
74865
|
+
home,
|
|
74866
|
+
env,
|
|
74867
|
+
configDir: env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path44.join(xdg, "workit"),
|
|
74868
|
+
opencodeConfig: path44.join(xdg, "opencode/opencode.json"),
|
|
74869
|
+
piSettings: path44.join(env.PI_CODING_AGENT_DIR ?? path44.join(home, ".pi/agent"), "settings.json"),
|
|
74870
|
+
codexHome,
|
|
74871
|
+
codexConfig: path44.join(codexHome, "config.toml"),
|
|
74872
|
+
cursorRoot: path44.join(home, ".cursor/plugins/local/workit")
|
|
74873
|
+
};
|
|
74874
|
+
}, object2 = (file) => {
|
|
74875
|
+
if (!existsSync20(file))
|
|
74876
|
+
return null;
|
|
74877
|
+
let data;
|
|
74878
|
+
try {
|
|
74879
|
+
data = JSON.parse(readFileSync21(file, "utf8"));
|
|
74880
|
+
} catch {
|
|
74881
|
+
throw new Error(`${file} is not valid JSON; use the native host to inspect JSONC settings`);
|
|
74876
74882
|
}
|
|
74877
|
-
|
|
74878
|
-
|
|
74879
|
-
|
|
74880
|
-
|
|
74881
|
-
path44.join(home, ".cursor/mcp.json"),
|
|
74882
|
-
path44.join(paths.cursorRoot, "package.json"),
|
|
74883
|
-
paths.codexConfig,
|
|
74884
|
-
paths.piSettings
|
|
74885
|
-
])
|
|
74886
|
-
plan.configDigests[file] = digest2(file);
|
|
74883
|
+
if (!data || typeof data !== "object" || Array.isArray(data))
|
|
74884
|
+
throw new Error(`${file} is not a configuration object`);
|
|
74885
|
+
return data;
|
|
74886
|
+
}, objectOrNull = (file) => {
|
|
74887
74887
|
try {
|
|
74888
|
-
|
|
74889
|
-
|
|
74890
|
-
|
|
74891
|
-
id: "2.0-remove-ignored-trusted-paths",
|
|
74892
|
-
file: state.config.file,
|
|
74893
|
-
description: "Remove ignored Workit trustedPaths; native host permissions remain unchanged"
|
|
74894
|
-
});
|
|
74895
|
-
} catch (error) {
|
|
74896
|
-
plan.blocked.push(errorText(error));
|
|
74888
|
+
return object2(file);
|
|
74889
|
+
} catch {
|
|
74890
|
+
return null;
|
|
74897
74891
|
}
|
|
74898
|
-
|
|
74899
|
-
|
|
74900
|
-
|
|
74901
|
-
|
|
74902
|
-
|
|
74903
|
-
|
|
74904
|
-
|
|
74892
|
+
}, digest2 = (file) => existsSync20(file) ? createHash15("sha256").update(readFileSync21(file)).digest("hex") : "missing", runner = (deps) => deps.run ?? ((command, args) => {
|
|
74893
|
+
const { home, env } = upgradePaths(deps);
|
|
74894
|
+
let step;
|
|
74895
|
+
try {
|
|
74896
|
+
step = hostCommand(command, args, { home, env });
|
|
74897
|
+
} catch {
|
|
74898
|
+
return { status: 1, stdout: "" };
|
|
74905
74899
|
}
|
|
74906
|
-
|
|
74907
|
-
|
|
74908
|
-
|
|
74909
|
-
|
|
74910
|
-
|
|
74911
|
-
|
|
74912
|
-
|
|
74900
|
+
const result = runHostCommand(step, { home, env });
|
|
74901
|
+
return { status: result.exitCode, stdout: result.stdout };
|
|
74902
|
+
}), errorText = (error) => error instanceof Error ? error.message : "installed source could not be read", piInstalledVersion = (listing, selector) => {
|
|
74903
|
+
const lines = listing.split(/\r?\n/).map((line) => line.trim());
|
|
74904
|
+
const index = lines.indexOf(selector);
|
|
74905
|
+
if (index < 0 || !lines[index + 1] || !path44.isAbsolute(lines[index + 1]))
|
|
74906
|
+
return;
|
|
74907
|
+
const found = objectOrNull(path44.join(lines[index + 1], "package.json"));
|
|
74908
|
+
return found?.name === "@brainervirus/workit-pi" ? found.version : undefined;
|
|
74909
|
+
}, versionAtLeast = (installed, latest) => {
|
|
74910
|
+
if (!/^\d+\.\d+\.\d+$/.test(installed))
|
|
74911
|
+
return false;
|
|
74912
|
+
const current = installed.split(".").map(Number);
|
|
74913
|
+
const target = latest.split(".").map(Number);
|
|
74914
|
+
for (let index = 0;index < 3; index++) {
|
|
74915
|
+
if (current[index] !== target[index])
|
|
74916
|
+
return current[index] > target[index];
|
|
74913
74917
|
}
|
|
74914
|
-
|
|
74915
|
-
|
|
74916
|
-
|
|
74917
|
-
|
|
74918
|
-
|
|
74919
|
-
|
|
74920
|
-
|
|
74921
|
-
|
|
74922
|
-
|
|
74923
|
-
|
|
74924
|
-
|
|
74925
|
-
|
|
74926
|
-
|
|
74927
|
-
|
|
74928
|
-
|
|
74929
|
-
|
|
74930
|
-
|
|
74931
|
-
|
|
74932
|
-
|
|
74933
|
-
|
|
74934
|
-
|
|
74935
|
-
|
|
74936
|
-
|
|
74937
|
-
|
|
74938
|
-
|
|
74939
|
-
|
|
74940
|
-
|
|
74941
|
-
|
|
74942
|
-
|
|
74943
|
-
|
|
74944
|
-
|
|
74945
|
-
|
|
74946
|
-
|
|
74947
|
-
|
|
74948
|
-
|
|
74949
|
-
|
|
74950
|
-
|
|
74951
|
-
|
|
74952
|
-
|
|
74953
|
-
|
|
74954
|
-
|
|
74955
|
-
|
|
74956
|
-
|
|
74957
|
-
|
|
74958
|
-
|
|
74959
|
-
|
|
74960
|
-
|
|
74961
|
-
if (!latest) {
|
|
74962
|
-
plan.failed.push({
|
|
74963
|
-
host: source.host,
|
|
74964
|
-
status: "failed",
|
|
74965
|
-
reason: "registry version unavailable; existing installation preserved",
|
|
74966
|
-
fix: fixFor(source.host, source.selector)
|
|
74967
|
-
});
|
|
74968
|
-
continue;
|
|
74969
|
-
}
|
|
74970
|
-
if (source.installedVersion && versionAtLeast(source.installedVersion, latest)) {
|
|
74971
|
-
plan.skipped.push({
|
|
74972
|
-
host: source.host,
|
|
74973
|
-
reason: `already current (${source.installedVersion})`
|
|
74974
|
-
});
|
|
74975
|
-
continue;
|
|
74976
|
-
}
|
|
74977
|
-
const commands = source.host === "pi" ? [{ command: "pi", args: ["update", "--extension", source.selector] }] : source.host === "codex" ? [
|
|
74978
|
-
{
|
|
74979
|
-
command: "codex",
|
|
74980
|
-
args: ["plugin", "marketplace", "upgrade", CODEX_MARKETPLACE]
|
|
74981
|
-
},
|
|
74982
|
-
{
|
|
74983
|
-
command: "codex",
|
|
74984
|
-
args: ["plugin", "add", `workit@${CODEX_MARKETPLACE}`, "--json"]
|
|
74985
|
-
}
|
|
74986
|
-
] : planHostInstall("cursor", {
|
|
74987
|
-
home,
|
|
74988
|
-
env: deps.env,
|
|
74989
|
-
cwd: home,
|
|
74990
|
-
packageVersion: latest,
|
|
74991
|
-
targetDir: paths.cursorRoot
|
|
74992
|
-
});
|
|
74993
|
-
plan.entries.push({
|
|
74994
|
-
host: source.host,
|
|
74995
|
-
selector: source.selector,
|
|
74996
|
-
latest,
|
|
74997
|
-
commands,
|
|
74998
|
-
installedVersion: source.installedVersion,
|
|
74999
|
-
...source.kind === "repair" ? { repair: true } : {},
|
|
75000
|
-
fix: fixFor(source.host, source.selector)
|
|
74918
|
+
return true;
|
|
74919
|
+
}, registryVersion = (run, name) => {
|
|
74920
|
+
const latest = run("npm", ["view", name, "version"]);
|
|
74921
|
+
const version = latest.stdout.trim();
|
|
74922
|
+
return latest.status === 0 && /^\d+\.\d+\.\d+$/.test(version) ? version : undefined;
|
|
74923
|
+
};
|
|
74924
|
+
var init_shared = __esm(() => {
|
|
74925
|
+
init_host_install();
|
|
74926
|
+
LAUNCH_HOSTS = ["opencode", "cursor", "codex", "pi"];
|
|
74927
|
+
HOSTS2 = [...LAUNCH_HOSTS, "claude-code"];
|
|
74928
|
+
LIVE_HOSTS = new Set(["opencode", "claude-code"]);
|
|
74929
|
+
OPENCODE_UPDATE = `opencode plugin update ${OPENCODE_PACKAGE}`;
|
|
74930
|
+
});
|
|
74931
|
+
|
|
74932
|
+
// packages/workit-cli/src/upgrade/processes.ts
|
|
74933
|
+
import path45 from "node:path";
|
|
74934
|
+
var PROCESS_HOSTS, SCRIPT_RUNTIMES, classifyProcess = (proc) => {
|
|
74935
|
+
if (proc.state.startsWith("Z") || proc.args.includes("<defunct>"))
|
|
74936
|
+
return null;
|
|
74937
|
+
const argv0 = proc.args.trim().split(/\s+/)[0] ?? "";
|
|
74938
|
+
const baseName = (value) => path45.basename(value.replaceAll("\\", "/")).replace(/^\[|\]$/g, "").replace(/\.exe$/i, "").toLowerCase();
|
|
74939
|
+
let host = PROCESS_HOSTS[baseName(argv0)];
|
|
74940
|
+
if (!host && SCRIPT_RUNTIMES.has(baseName(argv0))) {
|
|
74941
|
+
const script = proc.args.trim().split(/\s+/).slice(1).find((arg) => !arg.startsWith("-"));
|
|
74942
|
+
if (script)
|
|
74943
|
+
host = PROCESS_HOSTS[baseName(script).replace(/\.(?:[cm]?js|ts)$/, "")];
|
|
74944
|
+
}
|
|
74945
|
+
if (!host)
|
|
74946
|
+
return null;
|
|
74947
|
+
if (host === "codex" && /\bapp-server\b/.test(proc.args))
|
|
74948
|
+
return /\bdaemon\s+pid-update-loop\b/.test(proc.args) ? null : { ...proc, host, kind: "daemon" };
|
|
74949
|
+
if (host === "opencode" && /\bserve\b/.test(proc.args))
|
|
74950
|
+
return { ...proc, host, kind: "daemon" };
|
|
74951
|
+
return { ...proc, host, kind: "session" };
|
|
74952
|
+
}, listProcesses = (deps) => {
|
|
74953
|
+
if (deps.processes)
|
|
74954
|
+
return deps.processes();
|
|
74955
|
+
if (deps.activeHosts)
|
|
74956
|
+
return deps.activeHosts().map((host) => ({ pid: 0, state: "S", args: host }));
|
|
74957
|
+
const run = runner(deps);
|
|
74958
|
+
if (process.platform === "win32") {
|
|
74959
|
+
const list = run("tasklist", ["/fo", "csv", "/nh"]);
|
|
74960
|
+
if (list.status !== 0)
|
|
74961
|
+
return null;
|
|
74962
|
+
return list.stdout.split(/\r?\n/).flatMap((line) => {
|
|
74963
|
+
const [image, pid] = line.split('","').map((cell) => cell.replaceAll('"', ""));
|
|
74964
|
+
return image && /^\d+$/.test(pid ?? "") ? [{ pid: Number(pid), state: "R", args: image }] : [];
|
|
75001
74965
|
});
|
|
75002
74966
|
}
|
|
75003
|
-
|
|
75004
|
-
|
|
75005
|
-
|
|
74967
|
+
const list = run("ps", ["-eo", "pid=,stat=,args="]);
|
|
74968
|
+
if (list.status !== 0)
|
|
74969
|
+
return null;
|
|
74970
|
+
return list.stdout.split(/\r?\n/).flatMap((line) => {
|
|
74971
|
+
const match = /^\s*(\d+)\s+(\S+)\s+(.+)$/.exec(line);
|
|
74972
|
+
return match ? [{ pid: Number(match[1]), state: match[2], args: match[3] }] : [];
|
|
74973
|
+
});
|
|
74974
|
+
}, describe2 = (proc) => `pid ${proc.pid}: ${proc.args.length > 120 ? `${proc.args.slice(0, 117)}...` : proc.args}`;
|
|
74975
|
+
var init_processes = __esm(() => {
|
|
74976
|
+
init_shared();
|
|
74977
|
+
PROCESS_HOSTS = {
|
|
74978
|
+
claude: "claude-code",
|
|
74979
|
+
codex: "codex",
|
|
74980
|
+
cursor: "cursor",
|
|
74981
|
+
opencode: "opencode",
|
|
74982
|
+
pi: "pi"
|
|
74983
|
+
};
|
|
74984
|
+
SCRIPT_RUNTIMES = new Set(["node", "nodejs", "bun"]);
|
|
74985
|
+
});
|
|
74986
|
+
|
|
74987
|
+
// packages/workit-cli/src/upgrade/apply.ts
|
|
74988
|
+
import { existsSync as existsSync21, readdirSync as readdirSync12, mkdirSync as mkdirSync11, copyFileSync as copyFileSync6, chmodSync as chmodSync2, cpSync as cpSync5 } from "node:fs";
|
|
74989
|
+
import path46 from "node:path";
|
|
74990
|
+
import { createHash as createHash16 } from "node:crypto";
|
|
75006
74991
|
function applyUpgrade(plan, deps = {}) {
|
|
75007
74992
|
const hosts = [...plan.failed];
|
|
75008
74993
|
const done = (backup) => {
|
|
@@ -75036,11 +75021,11 @@ function applyUpgrade(plan, deps = {}) {
|
|
|
75036
75021
|
};
|
|
75037
75022
|
const paths = upgradePaths(deps);
|
|
75038
75023
|
const { home, configDir } = paths;
|
|
75039
|
-
const backup =
|
|
75024
|
+
const backup = path46.join(home, ".local/state/workit/upgrades", new Date().toISOString().replaceAll(":", "-"));
|
|
75040
75025
|
mkdirSync11(backup, { recursive: true, mode: 448 });
|
|
75041
75026
|
for (const file of Object.keys(plan.configDigests))
|
|
75042
|
-
if (
|
|
75043
|
-
const target =
|
|
75027
|
+
if (existsSync21(file)) {
|
|
75028
|
+
const target = path46.join(backup, createHash16("sha256").update(file).digest("hex").slice(0, 12) + "-" + path46.basename(file));
|
|
75044
75029
|
copyFileSync6(file, target);
|
|
75045
75030
|
chmodSync2(target, 384);
|
|
75046
75031
|
}
|
|
@@ -75059,9 +75044,11 @@ function applyUpgrade(plan, deps = {}) {
|
|
|
75059
75044
|
}
|
|
75060
75045
|
const run = runner(deps);
|
|
75061
75046
|
let cursorBackupError = null;
|
|
75062
|
-
if (plan.entries.some((entry) => entry.host === "cursor") &&
|
|
75047
|
+
if (plan.entries.some((entry) => entry.host === "cursor") && existsSync21(paths.cursorRoot))
|
|
75063
75048
|
try {
|
|
75064
|
-
cpSync5(paths.cursorRoot,
|
|
75049
|
+
cpSync5(paths.cursorRoot, path46.join(backup, "cursor-package"), {
|
|
75050
|
+
recursive: true
|
|
75051
|
+
});
|
|
75065
75052
|
} catch (error) {
|
|
75066
75053
|
cursorBackupError = `could not back up the Cursor plugin: ${errorText(error)}`;
|
|
75067
75054
|
}
|
|
@@ -75069,7 +75056,12 @@ function applyUpgrade(plan, deps = {}) {
|
|
|
75069
75056
|
const running = (listed ?? []).flatMap((entry) => classifyProcess(entry) ?? []);
|
|
75070
75057
|
for (const entry of plan.entries) {
|
|
75071
75058
|
if (entry.host === "cursor" && cursorBackupError) {
|
|
75072
|
-
hosts.push({
|
|
75059
|
+
hosts.push({
|
|
75060
|
+
host: "cursor",
|
|
75061
|
+
status: "failed",
|
|
75062
|
+
reason: cursorBackupError,
|
|
75063
|
+
fix: entry.fix
|
|
75064
|
+
});
|
|
75073
75065
|
continue;
|
|
75074
75066
|
}
|
|
75075
75067
|
if (!LIVE_HOSTS.has(entry.host)) {
|
|
@@ -75178,238 +75170,356 @@ function applyUpgrade(plan, deps = {}) {
|
|
|
75178
75170
|
try {
|
|
75179
75171
|
hosts.push(applyCli(plan.cli, run, backup));
|
|
75180
75172
|
} catch (error) {
|
|
75181
|
-
hosts.push({
|
|
75173
|
+
hosts.push({
|
|
75174
|
+
host: "cli",
|
|
75175
|
+
status: "failed",
|
|
75176
|
+
reason: errorText(error),
|
|
75177
|
+
fix: CLI_FIX
|
|
75178
|
+
});
|
|
75182
75179
|
}
|
|
75183
75180
|
return done(backup);
|
|
75184
75181
|
}
|
|
75185
|
-
|
|
75186
|
-
const
|
|
75187
|
-
|
|
75188
|
-
|
|
75189
|
-
|
|
75190
|
-
|
|
75191
|
-
|
|
75192
|
-
out.write(USAGE3);
|
|
75193
|
-
return 2;
|
|
75182
|
+
var codexPluginRoot = (codexHome) => {
|
|
75183
|
+
const dir = path46.join(codexHome, "plugins", "cache", CODEX_MARKETPLACE, "workit");
|
|
75184
|
+
let versions = [];
|
|
75185
|
+
try {
|
|
75186
|
+
versions = readdirSync12(dir).filter((version) => /^\d+\.\d+\.\d+$/.test(version));
|
|
75187
|
+
} catch {
|
|
75188
|
+
return null;
|
|
75194
75189
|
}
|
|
75195
|
-
|
|
75196
|
-
|
|
75197
|
-
|
|
75198
|
-
|
|
75190
|
+
const newest = versions.reduce((best, version) => best && versionAtLeast(best, version) ? best : version, null);
|
|
75191
|
+
return newest ? path46.join(dir, newest) : null;
|
|
75192
|
+
}, opencodeVersion = (run) => {
|
|
75193
|
+
const listing = run("opencode", ["plugin", "list"]);
|
|
75194
|
+
if (listing.status !== 0)
|
|
75195
|
+
return;
|
|
75196
|
+
for (const line of listing.stdout.split(/\r?\n/)) {
|
|
75197
|
+
const fields = line.trim().split(/\s+/);
|
|
75198
|
+
if (fields.length < 3)
|
|
75199
|
+
continue;
|
|
75200
|
+
const source = fields[fields.length - 1].replace(/^file:\/\//, "");
|
|
75201
|
+
const version = fields[fields.length - 2];
|
|
75202
|
+
if (/^(?:npm:)?@brainervirus\/workit-opencode(?:@[^/\s]+)?$/.test(source) && /^\d+\.\d+\.\d+$/.test(version))
|
|
75203
|
+
return version;
|
|
75199
75204
|
}
|
|
75200
|
-
|
|
75201
|
-
|
|
75202
|
-
const run =
|
|
75203
|
-
const
|
|
75204
|
-
|
|
75205
|
-
|
|
75206
|
-
|
|
75207
|
-
|
|
75208
|
-
|
|
75209
|
-
hosts: raw,
|
|
75210
|
-
refreshOnly: true,
|
|
75211
|
-
shell: false,
|
|
75212
|
-
home,
|
|
75213
|
-
env
|
|
75205
|
+
return;
|
|
75206
|
+
}, applyEntry = (entry, context) => {
|
|
75207
|
+
const { run, paths, configDir } = context;
|
|
75208
|
+
const { home, env } = paths;
|
|
75209
|
+
const fail = (reason) => ({
|
|
75210
|
+
host: entry.host,
|
|
75211
|
+
status: "failed",
|
|
75212
|
+
reason,
|
|
75213
|
+
fix: entry.fix
|
|
75214
75214
|
});
|
|
75215
|
-
|
|
75216
|
-
|
|
75217
|
-
|
|
75218
|
-
|
|
75219
|
-
|
|
75220
|
-
|
|
75221
|
-
|
|
75222
|
-
|
|
75223
|
-
|
|
75224
|
-
|
|
75225
|
-
|
|
75226
|
-
|
|
75227
|
-
|
|
75228
|
-
|
|
75229
|
-
|
|
75230
|
-
|
|
75215
|
+
if (entry.host === "cursor") {
|
|
75216
|
+
const preview = {
|
|
75217
|
+
ok: true,
|
|
75218
|
+
blocked: [],
|
|
75219
|
+
preserved: [],
|
|
75220
|
+
overrides: [],
|
|
75221
|
+
platforms: ["cursor"],
|
|
75222
|
+
state: readSetupState(configDir),
|
|
75223
|
+
mutations: [
|
|
75224
|
+
{
|
|
75225
|
+
type: "install-host",
|
|
75226
|
+
platform: "cursor",
|
|
75227
|
+
path: path46.join(home, ".cursor/plugins/local/.workit-package-bootstrap"),
|
|
75228
|
+
commands: entry.commands.map((command) => ({
|
|
75229
|
+
...command,
|
|
75230
|
+
purpose: command.purpose ?? "Upgrade Cursor"
|
|
75231
|
+
}))
|
|
75232
|
+
},
|
|
75233
|
+
{ type: "install-adapter", platform: "cursor", path: paths.cursorRoot }
|
|
75234
|
+
]
|
|
75235
|
+
};
|
|
75236
|
+
const result = applySetupPreview(preview, {
|
|
75237
|
+
home,
|
|
75238
|
+
env,
|
|
75239
|
+
cwd: home,
|
|
75240
|
+
preferInstalledAdapter: true,
|
|
75241
|
+
runHostCommand: (command) => {
|
|
75242
|
+
const outcome = run(command.command, command.args);
|
|
75243
|
+
return {
|
|
75244
|
+
exitCode: outcome.status ?? 1,
|
|
75245
|
+
stdout: outcome.stdout,
|
|
75246
|
+
stderr: ""
|
|
75247
|
+
};
|
|
75248
|
+
}
|
|
75249
|
+
});
|
|
75250
|
+
const installed = objectOrNull(path46.join(paths.cursorRoot, "package.json"));
|
|
75251
|
+
if (!result.ok || installed?.version !== entry.latest)
|
|
75252
|
+
return fail("Cursor install did not verify the requested package version; inspect the installer before retrying");
|
|
75253
|
+
return {
|
|
75254
|
+
host: "cursor",
|
|
75255
|
+
status: "updated",
|
|
75256
|
+
reason: entry.repair ? `reinstalled missing plugin files (${entry.latest})` : `${entry.installedVersion ?? "?"} -> ${entry.latest}`
|
|
75257
|
+
};
|
|
75231
75258
|
}
|
|
75232
|
-
|
|
75233
|
-
|
|
75234
|
-
|
|
75235
|
-
|
|
75236
|
-
|
|
75259
|
+
const before = entry.host === "opencode" ? opencodeVersion(run) : undefined;
|
|
75260
|
+
for (const command of entry.commands)
|
|
75261
|
+
if (run(command.command, command.args).status !== 0)
|
|
75262
|
+
return fail(`\`${command.command} ${command.args.join(" ")}\` failed`);
|
|
75263
|
+
if (entry.host === "opencode") {
|
|
75264
|
+
const after = opencodeVersion(run);
|
|
75265
|
+
if (before && after)
|
|
75266
|
+
return after === before ? {
|
|
75267
|
+
host: "opencode",
|
|
75268
|
+
status: "current",
|
|
75269
|
+
reason: `already current (${after})`
|
|
75270
|
+
} : {
|
|
75271
|
+
host: "opencode",
|
|
75272
|
+
status: "updated",
|
|
75273
|
+
reason: `${before} -> ${after}; OpenCode V2 loads it live`
|
|
75274
|
+
};
|
|
75275
|
+
return {
|
|
75276
|
+
host: "opencode",
|
|
75277
|
+
status: "updated",
|
|
75278
|
+
reason: "scoped update ran; OpenCode V2 loads it live"
|
|
75279
|
+
};
|
|
75237
75280
|
}
|
|
75238
|
-
if (
|
|
75239
|
-
|
|
75240
|
-
|
|
75241
|
-
|
|
75242
|
-
|
|
75281
|
+
if (entry.host === "claude-code") {
|
|
75282
|
+
const after = claudeWorkitInstalls(home, env, null).find((install) => install.id === entry.selector)?.version;
|
|
75283
|
+
return after && after === entry.installedVersion ? {
|
|
75284
|
+
host: "claude-code",
|
|
75285
|
+
status: "current",
|
|
75286
|
+
reason: `already current (${after})`
|
|
75287
|
+
} : {
|
|
75288
|
+
host: "claude-code",
|
|
75289
|
+
status: "updated",
|
|
75290
|
+
reason: `${entry.installedVersion ?? "?"} -> ${after ?? "?"}; new sessions load it`
|
|
75291
|
+
};
|
|
75243
75292
|
}
|
|
75244
|
-
const
|
|
75245
|
-
if (
|
|
75246
|
-
|
|
75247
|
-
|
|
75248
|
-
|
|
75249
|
-
|
|
75250
|
-
|
|
75293
|
+
const verify = entry.host === "codex" ? run("codex", ["plugin", "list", "--json"]) : run("pi", ["list"]);
|
|
75294
|
+
if (verify.status !== 0)
|
|
75295
|
+
return fail("update verification failed");
|
|
75296
|
+
if (entry.host === "codex") {
|
|
75297
|
+
let installed = [];
|
|
75298
|
+
try {
|
|
75299
|
+
installed = JSON.parse(verify.stdout).installed ?? [];
|
|
75300
|
+
} catch {}
|
|
75301
|
+
if (!installed.some((plugin) => plugin.name === "workit" && plugin.marketplaceName === CODEX_MARKETPLACE && plugin.version === entry.latest))
|
|
75302
|
+
return fail("Codex did not report the requested Workit version");
|
|
75251
75303
|
}
|
|
75252
|
-
if (
|
|
75253
|
-
|
|
75254
|
-
|
|
75255
|
-
|
|
75256
|
-
|
|
75257
|
-
|
|
75258
|
-
|
|
75259
|
-
|
|
75260
|
-
|
|
75261
|
-
|
|
75262
|
-
|
|
75263
|
-
|
|
75264
|
-
|
|
75265
|
-
|
|
75266
|
-
|
|
75267
|
-
|
|
75304
|
+
if (entry.host === "pi" && piInstalledVersion(verify.stdout, entry.selector) !== entry.latest)
|
|
75305
|
+
return fail("Pi did not report the requested Workit package version");
|
|
75306
|
+
return {
|
|
75307
|
+
host: entry.host,
|
|
75308
|
+
status: "updated",
|
|
75309
|
+
reason: entry.repair ? `reinstalled missing plugin files (${entry.latest})` : `${entry.installedVersion ?? "?"} -> ${entry.latest}`
|
|
75310
|
+
};
|
|
75311
|
+
}, refreshCodexAgents = (run, codexHome) => {
|
|
75312
|
+
const root = codexPluginRoot(codexHome);
|
|
75313
|
+
const launcher = root && path46.join(root, "dist", "launch-mcp.js");
|
|
75314
|
+
if (!launcher || !existsSync21(launcher))
|
|
75315
|
+
return { ok: true, note: "" };
|
|
75316
|
+
const fix = `node ${JSON.stringify(launcher)} --install-agents`;
|
|
75317
|
+
return run("node", [launcher, "--install-agents"]).status === 0 ? { ok: true, note: "agents refreshed" } : { ok: false, note: "agent refresh failed", fix };
|
|
75318
|
+
}, applyCli = (cli, run, backup) => {
|
|
75319
|
+
const fail = (reason) => ({
|
|
75320
|
+
host: "cli",
|
|
75321
|
+
status: "failed",
|
|
75322
|
+
reason,
|
|
75323
|
+
fix: CLI_FIX
|
|
75324
|
+
});
|
|
75325
|
+
const currentRoot = run("npm", ["root", "--global"]);
|
|
75326
|
+
if (currentRoot.status !== 0 || currentRoot.stdout.trim() !== cli.root)
|
|
75327
|
+
return fail("Global npm location changed; preview again");
|
|
75328
|
+
const cliBackup = path46.join(backup, "cli-package");
|
|
75329
|
+
cpSync5(path46.join(cli.root, "@brainervirus/workit-cli"), cliBackup, {
|
|
75330
|
+
recursive: true
|
|
75331
|
+
});
|
|
75332
|
+
if (run("npm", ["install", "--global", `@brainervirus/workit-cli@${cli.latest}`]).status !== 0)
|
|
75333
|
+
return fail(`CLI update failed; preserved package at ${cliBackup}; use npm to repair or run node ${path46.join(cliBackup, "dist/index.js")}`);
|
|
75334
|
+
const installed = objectOrNull(path46.join(cli.root, "@brainervirus/workit-cli/package.json"));
|
|
75335
|
+
if (installed?.name !== "@brainervirus/workit-cli" || installed.version !== cli.latest)
|
|
75336
|
+
return fail(`CLI update did not verify the requested version; preserved package at ${cliBackup}`);
|
|
75337
|
+
return {
|
|
75338
|
+
host: "cli",
|
|
75339
|
+
status: "updated",
|
|
75340
|
+
reason: `${cli.installed} -> ${cli.latest}`
|
|
75341
|
+
};
|
|
75342
|
+
};
|
|
75343
|
+
var init_apply = __esm(() => {
|
|
75344
|
+
init_host_install();
|
|
75345
|
+
init_setup_state();
|
|
75346
|
+
init_setup();
|
|
75347
|
+
init_safe_write();
|
|
75348
|
+
init_processes();
|
|
75349
|
+
init_shared();
|
|
75350
|
+
});
|
|
75351
|
+
|
|
75352
|
+
// packages/workit-cli/src/upgrade/plan.ts
|
|
75353
|
+
import { existsSync as existsSync22, mkdtempSync as mkdtempSync3, rmSync as rmSync8, lstatSync as lstatSync7, readFileSync as readFileSync22 } from "node:fs";
|
|
75354
|
+
import path47 from "node:path";
|
|
75355
|
+
import os17 from "node:os";
|
|
75356
|
+
function previewUpgrade(hosts = HOSTS2, deps = {}) {
|
|
75357
|
+
const paths = upgradePaths(deps);
|
|
75358
|
+
const { home, configDir } = paths;
|
|
75359
|
+
const run = runner(deps);
|
|
75360
|
+
const state = readSetupState(configDir);
|
|
75361
|
+
const plan = {
|
|
75362
|
+
ok: true,
|
|
75363
|
+
blocked: [],
|
|
75364
|
+
failed: [],
|
|
75365
|
+
skipped: [],
|
|
75366
|
+
entries: [],
|
|
75367
|
+
configDigests: {},
|
|
75368
|
+
migrations: []
|
|
75369
|
+
};
|
|
75370
|
+
for (const file of [state.config, state.workspaces, state.youtrack, state.vcs]) {
|
|
75371
|
+
if (file.status === "malformed")
|
|
75372
|
+
plan.blocked.push(file.error ?? file.file);
|
|
75373
|
+
plan.configDigests[file.file] = digest2(file.file);
|
|
75374
|
+
}
|
|
75375
|
+
for (const file of [
|
|
75376
|
+
paths.opencodeConfig,
|
|
75377
|
+
paths.opencodeConfig + "c",
|
|
75378
|
+
path47.join(home, ".cursor/settings.json"),
|
|
75379
|
+
path47.join(home, ".cursor/mcp.json"),
|
|
75380
|
+
path47.join(paths.cursorRoot, "package.json"),
|
|
75381
|
+
paths.codexConfig,
|
|
75382
|
+
paths.piSettings
|
|
75383
|
+
])
|
|
75384
|
+
plan.configDigests[file] = digest2(file);
|
|
75385
|
+
try {
|
|
75386
|
+
const config = object2(state.config.file);
|
|
75387
|
+
if (config && Object.hasOwn(config, "trustedPaths"))
|
|
75388
|
+
plan.migrations.push({
|
|
75389
|
+
id: "2.0-remove-ignored-trusted-paths",
|
|
75390
|
+
file: state.config.file,
|
|
75391
|
+
description: "Remove ignored Workit trustedPaths; native host permissions remain unchanged"
|
|
75268
75392
|
});
|
|
75393
|
+
} catch (error) {
|
|
75394
|
+
plan.blocked.push(errorText(error));
|
|
75269
75395
|
}
|
|
75270
|
-
const
|
|
75271
|
-
|
|
75272
|
-
|
|
75273
|
-
|
|
75274
|
-
|
|
75275
|
-
|
|
75276
|
-
|
|
75277
|
-
ok: !failed,
|
|
75278
|
-
...written ? { permissions: { changes: permissionPreview.changes, written } } : permissions.refused ? { permissions: permissionPreview } : {},
|
|
75279
|
-
doctor: { clean: left.length === 0, left }
|
|
75280
|
-
}, null, 2) + `
|
|
75281
|
-
`);
|
|
75282
|
-
return failed ? 1 : 0;
|
|
75396
|
+
const installedSources = sources(paths, run, hosts, plan.failed);
|
|
75397
|
+
let opencodeHelp;
|
|
75398
|
+
if (installedSources.some((source) => source.host === "opencode")) {
|
|
75399
|
+
const probe = opencodeProbe(deps, ["--version"]);
|
|
75400
|
+
const installed = probe.status === 0 ? probe.stdout.match(/\d+\.\d+\.\d+/)?.[0] : undefined;
|
|
75401
|
+
if (installed && !versionAtLeast(installed, SUPPORT_MATRIX.opencode.minimum))
|
|
75402
|
+
(plan.warnings ??= []).push(`opencode ${installed}: ${OPENCODE_V1_FIX}`);
|
|
75283
75403
|
}
|
|
75284
|
-
|
|
75285
|
-
|
|
75286
|
-
|
|
75287
|
-
|
|
75288
|
-
|
|
75289
|
-
|
|
75290
|
-
|
|
75291
|
-
if (result.backup)
|
|
75292
|
-
out.write(`Backup: ${result.backup}
|
|
75293
|
-
`);
|
|
75294
|
-
out.write(left.length === 0 ? `Verified: workit doctor is clean for versions, assets, agents and permissions.
|
|
75295
|
-
` : `Left after upgrade (workit doctor):
|
|
75296
|
-
${left.map((check) => ` ${check.id}: ${check.detail}${check.fix ? `
|
|
75297
|
-
fix: ${check.fix}` : ""}`).join(`
|
|
75298
|
-
`)}
|
|
75299
|
-
`);
|
|
75300
|
-
return failed ? 1 : 0;
|
|
75301
|
-
}
|
|
75302
|
-
async function runLaunchCommand(argv, deps = {}) {
|
|
75303
|
-
const [host, ...args] = argv;
|
|
75304
|
-
if (!LAUNCH_HOSTS.includes(host)) {
|
|
75305
|
-
(deps.out ?? process.stdout).write(`Usage: workit launch <opencode|cursor|codex|pi> [--auto-upgrade] [-- host arguments]
|
|
75306
|
-
`);
|
|
75307
|
-
return 2;
|
|
75404
|
+
for (const host of ["opencode", "pi"]) {
|
|
75405
|
+
if (new Set(installedSources.filter((source) => source.host === host).map((source) => source.selector)).size > 1)
|
|
75406
|
+
plan.failed.push({
|
|
75407
|
+
host,
|
|
75408
|
+
status: "failed",
|
|
75409
|
+
reason: "conflicting Workit registrations; reconcile them in the native host before upgrading"
|
|
75410
|
+
});
|
|
75308
75411
|
}
|
|
75309
|
-
const
|
|
75310
|
-
const
|
|
75311
|
-
|
|
75312
|
-
|
|
75313
|
-
|
|
75314
|
-
|
|
75315
|
-
|
|
75316
|
-
|
|
75317
|
-
} catch (error) {
|
|
75318
|
-
(deps.out ?? process.stderr).write(`${error instanceof Error ? error.message : "Host executable unavailable"}
|
|
75319
|
-
`);
|
|
75320
|
-
return 1;
|
|
75412
|
+
const conflicted = new Set(plan.failed.map((entry) => entry.host));
|
|
75413
|
+
for (const source of installedSources.filter((candidate, index, list) => !conflicted.has(candidate.host) && list.findIndex((entry) => entry.host === candidate.host && entry.selector === candidate.selector) === index)) {
|
|
75414
|
+
if (source.kind === "pinned" || source.kind === "local") {
|
|
75415
|
+
plan.skipped.push({
|
|
75416
|
+
host: source.host,
|
|
75417
|
+
reason: `${source.kind} source preserved; change its source explicitly to upgrade`
|
|
75418
|
+
});
|
|
75419
|
+
continue;
|
|
75321
75420
|
}
|
|
75322
|
-
|
|
75323
|
-
|
|
75324
|
-
|
|
75325
|
-
|
|
75326
|
-
|
|
75327
|
-
|
|
75328
|
-
|
|
75329
|
-
|
|
75330
|
-
|
|
75331
|
-
|
|
75332
|
-
|
|
75333
|
-
|
|
75334
|
-
|
|
75421
|
+
if (source.host === "claude-code") {
|
|
75422
|
+
const [market] = source.selector.split("@").slice(1);
|
|
75423
|
+
plan.entries.push({
|
|
75424
|
+
host: "claude-code",
|
|
75425
|
+
selector: source.selector,
|
|
75426
|
+
latest: "",
|
|
75427
|
+
installedVersion: source.installedVersion,
|
|
75428
|
+
commands: [
|
|
75429
|
+
{
|
|
75430
|
+
command: "claude",
|
|
75431
|
+
args: ["plugin", "marketplace", "update", market ?? "workit"]
|
|
75432
|
+
},
|
|
75433
|
+
{ command: "claude", args: ["plugin", "update", source.selector] }
|
|
75434
|
+
],
|
|
75435
|
+
fix: `claude plugin marketplace update ${market ?? "workit"} && claude plugin update ${source.selector}`
|
|
75436
|
+
});
|
|
75437
|
+
continue;
|
|
75438
|
+
}
|
|
75439
|
+
if (source.host === "opencode") {
|
|
75440
|
+
opencodeHelp ??= opencodeProbe(deps, ["plugin", "--help"]).stdout;
|
|
75441
|
+
if (!/^\s*(?:opencode\s+plugin\s+)?update\b/m.test(opencodeHelp)) {
|
|
75442
|
+
plan.skipped.push({
|
|
75443
|
+
host: "opencode",
|
|
75444
|
+
reason: "this OpenCode has no `opencode plugin update`; upgrade OpenCode, then run the fix. Workit never updates unrelated plugins",
|
|
75445
|
+
fix: OPENCODE_UPDATE
|
|
75446
|
+
});
|
|
75447
|
+
continue;
|
|
75335
75448
|
}
|
|
75336
|
-
|
|
75337
|
-
|
|
75338
|
-
|
|
75339
|
-
|
|
75340
|
-
|
|
75341
|
-
|
|
75342
|
-
|
|
75449
|
+
plan.entries.push({
|
|
75450
|
+
host: "opencode",
|
|
75451
|
+
selector: source.selector,
|
|
75452
|
+
latest: "",
|
|
75453
|
+
commands: [{ command: "opencode", args: ["plugin", "update", OPENCODE_PACKAGE] }],
|
|
75454
|
+
fix: OPENCODE_UPDATE
|
|
75455
|
+
});
|
|
75456
|
+
continue;
|
|
75343
75457
|
}
|
|
75458
|
+
const latest = registryVersion(run, `@brainervirus/workit-${source.host}`);
|
|
75459
|
+
if (!latest) {
|
|
75460
|
+
plan.failed.push({
|
|
75461
|
+
host: source.host,
|
|
75462
|
+
status: "failed",
|
|
75463
|
+
reason: "registry version unavailable; existing installation preserved",
|
|
75464
|
+
fix: fixFor(source.host, source.selector)
|
|
75465
|
+
});
|
|
75466
|
+
continue;
|
|
75467
|
+
}
|
|
75468
|
+
if (source.installedVersion && versionAtLeast(source.installedVersion, latest)) {
|
|
75469
|
+
plan.skipped.push({
|
|
75470
|
+
host: source.host,
|
|
75471
|
+
reason: `already current (${source.installedVersion})`
|
|
75472
|
+
});
|
|
75473
|
+
continue;
|
|
75474
|
+
}
|
|
75475
|
+
const commands = source.host === "pi" ? [{ command: "pi", args: ["update", "--extension", source.selector] }] : source.host === "codex" ? [
|
|
75476
|
+
{
|
|
75477
|
+
command: "codex",
|
|
75478
|
+
args: ["plugin", "marketplace", "upgrade", CODEX_MARKETPLACE]
|
|
75479
|
+
},
|
|
75480
|
+
{
|
|
75481
|
+
command: "codex",
|
|
75482
|
+
args: ["plugin", "add", `workit@${CODEX_MARKETPLACE}`, "--json"]
|
|
75483
|
+
}
|
|
75484
|
+
] : planHostInstall("cursor", {
|
|
75485
|
+
home,
|
|
75486
|
+
env: deps.env,
|
|
75487
|
+
cwd: home,
|
|
75488
|
+
packageVersion: latest,
|
|
75489
|
+
targetDir: paths.cursorRoot
|
|
75490
|
+
});
|
|
75491
|
+
plan.entries.push({
|
|
75492
|
+
host: source.host,
|
|
75493
|
+
selector: source.selector,
|
|
75494
|
+
latest,
|
|
75495
|
+
commands,
|
|
75496
|
+
installedVersion: source.installedVersion,
|
|
75497
|
+
...source.kind === "repair" ? { repair: true } : {},
|
|
75498
|
+
fix: fixFor(source.host, source.selector)
|
|
75499
|
+
});
|
|
75344
75500
|
}
|
|
75345
|
-
|
|
75346
|
-
|
|
75347
|
-
return spawnSync17(launch.command, launch.args, {
|
|
75348
|
-
stdio: "inherit",
|
|
75349
|
-
env
|
|
75350
|
-
}).status ?? 1;
|
|
75501
|
+
plan.ok = plan.blocked.length === 0 && plan.failed.length === 0;
|
|
75502
|
+
return plan;
|
|
75351
75503
|
}
|
|
75352
|
-
var
|
|
75353
|
-
|
|
75354
|
-
const env = {
|
|
75355
|
-
...process.env,
|
|
75356
|
-
...deps.home || deps.env?.HOME ? {
|
|
75357
|
-
HOME: home,
|
|
75358
|
-
CODEX_HOME: path44.join(home, ".codex"),
|
|
75359
|
-
CLAUDE_CONFIG_DIR: path44.join(home, ".claude"),
|
|
75360
|
-
PI_CODING_AGENT_DIR: path44.join(home, ".pi/agent"),
|
|
75361
|
-
XDG_CONFIG_HOME: path44.join(home, ".config"),
|
|
75362
|
-
WORKFLOW_TOOLKIT_CONFIG: undefined,
|
|
75363
|
-
WORKFLOW_TOOLKIT_CONFIG_DIR: undefined
|
|
75364
|
-
} : {},
|
|
75365
|
-
...deps.env,
|
|
75366
|
-
HOME: home
|
|
75367
|
-
};
|
|
75368
|
-
const xdg = env.XDG_CONFIG_HOME || path44.join(home, ".config");
|
|
75369
|
-
const codexHome = env.CODEX_HOME ?? path44.join(home, ".codex");
|
|
75370
|
-
return {
|
|
75371
|
-
home,
|
|
75372
|
-
env,
|
|
75373
|
-
configDir: env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path44.join(xdg, "workit"),
|
|
75374
|
-
opencodeConfig: path44.join(xdg, "opencode/opencode.json"),
|
|
75375
|
-
piSettings: path44.join(env.PI_CODING_AGENT_DIR ?? path44.join(home, ".pi/agent"), "settings.json"),
|
|
75376
|
-
codexHome,
|
|
75377
|
-
codexConfig: path44.join(codexHome, "config.toml"),
|
|
75378
|
-
cursorRoot: path44.join(home, ".cursor/plugins/local/workit")
|
|
75379
|
-
};
|
|
75380
|
-
}, object2 = (file) => {
|
|
75381
|
-
if (!existsSync20(file))
|
|
75382
|
-
return null;
|
|
75383
|
-
let data;
|
|
75384
|
-
try {
|
|
75385
|
-
data = JSON.parse(readFileSync21(file, "utf8"));
|
|
75386
|
-
} catch {
|
|
75387
|
-
throw new Error(`${file} is not valid JSON; use the native host to inspect JSONC settings`);
|
|
75388
|
-
}
|
|
75389
|
-
if (!data || typeof data !== "object" || Array.isArray(data))
|
|
75390
|
-
throw new Error(`${file} is not a configuration object`);
|
|
75391
|
-
return data;
|
|
75392
|
-
}, objectOrNull = (file) => {
|
|
75393
|
-
try {
|
|
75394
|
-
return object2(file);
|
|
75395
|
-
} catch {
|
|
75396
|
-
return null;
|
|
75397
|
-
}
|
|
75398
|
-
}, digest2 = (file) => existsSync20(file) ? createHash15("sha256").update(readFileSync21(file)).digest("hex") : "missing", runner = (deps) => deps.run ?? ((command, args) => {
|
|
75399
|
-
const { home, env } = upgradePaths(deps);
|
|
75400
|
-
let step;
|
|
75504
|
+
var codexRegistered = (configFile) => {
|
|
75505
|
+
let text;
|
|
75401
75506
|
try {
|
|
75402
|
-
|
|
75507
|
+
text = readFileSync22(configFile, "utf8");
|
|
75403
75508
|
} catch {
|
|
75404
|
-
return
|
|
75509
|
+
return false;
|
|
75405
75510
|
}
|
|
75406
|
-
const
|
|
75407
|
-
|
|
75408
|
-
|
|
75511
|
+
const header = `[plugins."workit@${CODEX_MARKETPLACE}"]`;
|
|
75512
|
+
const start = text.split(/\r?\n/).findIndex((line) => line.trim() === header);
|
|
75513
|
+
if (start < 0)
|
|
75514
|
+
return false;
|
|
75515
|
+
const body = text.split(/\r?\n/).slice(start + 1).join(`
|
|
75516
|
+
`).split(/^\s*\[/m)[0];
|
|
75517
|
+
return !/^\s*enabled\s*=\s*false\b/m.test(body);
|
|
75518
|
+
}, classify = (host, selector) => ({
|
|
75409
75519
|
host,
|
|
75410
75520
|
selector,
|
|
75411
75521
|
kind: selector === `@brainervirus/workit-${host}` || selector === `@brainervirus/workit-${host}@latest` || selector === `npm:@brainervirus/workit-${host}` || selector === `npm:@brainervirus/workit-${host}@latest` ? "floating" : new RegExp(`^(?:npm:)?@brainervirus/workit-${host}@[^/]+$`).test(selector) ? "pinned" : "local"
|
|
75412
|
-
}),
|
|
75522
|
+
}), sources = (paths, run, hosts, failed) => {
|
|
75413
75523
|
const { home } = paths;
|
|
75414
75524
|
const result = [];
|
|
75415
75525
|
const guard = (host, read) => {
|
|
@@ -75427,7 +75537,7 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
|
|
|
75427
75537
|
}
|
|
75428
75538
|
};
|
|
75429
75539
|
guard("opencode", () => {
|
|
75430
|
-
if (
|
|
75540
|
+
if (existsSync22(paths.opencodeConfig + "c"))
|
|
75431
75541
|
throw new Error("OpenCode JSONC config is present; inspect effective native configuration before updating");
|
|
75432
75542
|
const oc = object2(paths.opencodeConfig);
|
|
75433
75543
|
if (oc && [oc.plugins, oc.plugin].some((value) => value !== undefined && !Array.isArray(value)))
|
|
@@ -75437,8 +75547,8 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
|
|
|
75437
75547
|
result.push(classify("opencode", pin));
|
|
75438
75548
|
});
|
|
75439
75549
|
guard("cursor", () => {
|
|
75440
|
-
const cursor = objectOrNull(
|
|
75441
|
-
const mcp = objectOrNull(
|
|
75550
|
+
const cursor = objectOrNull(path47.join(paths.cursorRoot, "package.json"));
|
|
75551
|
+
const mcp = objectOrNull(path47.join(home, ".cursor/mcp.json"));
|
|
75442
75552
|
const args = mcp?.mcpServers?.workit?.args ?? [];
|
|
75443
75553
|
const arg = args.find((value) => typeof value === "string" && value.startsWith("--package="));
|
|
75444
75554
|
const selector = typeof arg === "string" ? arg.slice(10) : "local";
|
|
@@ -75449,7 +75559,7 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
|
|
|
75449
75559
|
});
|
|
75450
75560
|
return;
|
|
75451
75561
|
}
|
|
75452
|
-
const settings = objectOrNull(
|
|
75562
|
+
const settings = objectOrNull(path47.join(home, ".cursor/settings.json"));
|
|
75453
75563
|
const dirs = Array.isArray(settings?.plugin_dirs) ? settings.plugin_dirs : [];
|
|
75454
75564
|
const registered = mcp?.mcpServers?.workit !== undefined || dirs.some((dir) => String(dir).replaceAll("\\", "/").replace(/\/+$/, "").endsWith("local/workit"));
|
|
75455
75565
|
if (registered)
|
|
@@ -75464,7 +75574,7 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
|
|
|
75464
75574
|
if (typeof source !== "string")
|
|
75465
75575
|
continue;
|
|
75466
75576
|
const npm = /^(?:npm:)?@brainervirus\/workit-pi(?:@[^/]+)?$/.test(source);
|
|
75467
|
-
const local =
|
|
75577
|
+
const local = path47.isAbsolute(source) && source.replaceAll("\\", "/").endsWith("/packages/workit-pi") && object2(path47.join(source, "package.json"))?.name === "@brainervirus/workit-pi";
|
|
75468
75578
|
if (!npm && !local)
|
|
75469
75579
|
continue;
|
|
75470
75580
|
const found = classify("pi", source);
|
|
@@ -75484,7 +75594,7 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
|
|
|
75484
75594
|
hostCommand("codex", [], { home, env: paths.env });
|
|
75485
75595
|
available = true;
|
|
75486
75596
|
} catch {}
|
|
75487
|
-
if (available ||
|
|
75597
|
+
if (available || existsSync22(paths.codexConfig))
|
|
75488
75598
|
throw new Error("Codex plugin inventory failed; inspect the native host before upgrading");
|
|
75489
75599
|
return;
|
|
75490
75600
|
}
|
|
@@ -75506,6 +75616,12 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
|
|
|
75506
75616
|
installedVersion: plugin.version
|
|
75507
75617
|
});
|
|
75508
75618
|
}
|
|
75619
|
+
if (!result.some((found) => found.host === "codex") && codexRegistered(paths.codexConfig))
|
|
75620
|
+
result.push({
|
|
75621
|
+
host: "codex",
|
|
75622
|
+
selector: "@brainervirus/workit-codex",
|
|
75623
|
+
kind: "repair"
|
|
75624
|
+
});
|
|
75509
75625
|
});
|
|
75510
75626
|
guard("claude-code", () => {
|
|
75511
75627
|
for (const install of claudeWorkitInstalls(home, paths.env, null))
|
|
@@ -75517,213 +75633,24 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
|
|
|
75517
75633
|
});
|
|
75518
75634
|
});
|
|
75519
75635
|
return result;
|
|
75520
|
-
}, piInstalledVersion = (listing, selector) => {
|
|
75521
|
-
const lines = listing.split(/\r?\n/).map((line) => line.trim());
|
|
75522
|
-
const index = lines.indexOf(selector);
|
|
75523
|
-
if (index < 0 || !lines[index + 1] || !path44.isAbsolute(lines[index + 1]))
|
|
75524
|
-
return;
|
|
75525
|
-
const found = objectOrNull(path44.join(lines[index + 1], "package.json"));
|
|
75526
|
-
return found?.name === "@brainervirus/workit-pi" ? found.version : undefined;
|
|
75527
|
-
}, versionAtLeast = (installed, latest) => {
|
|
75528
|
-
if (!/^\d+\.\d+\.\d+$/.test(installed))
|
|
75529
|
-
return false;
|
|
75530
|
-
const current = installed.split(".").map(Number);
|
|
75531
|
-
const target = latest.split(".").map(Number);
|
|
75532
|
-
for (let index = 0;index < 3; index++) {
|
|
75533
|
-
if (current[index] !== target[index])
|
|
75534
|
-
return current[index] > target[index];
|
|
75535
|
-
}
|
|
75536
|
-
return true;
|
|
75537
75636
|
}, opencodeProbe = (deps, args) => {
|
|
75538
|
-
const scratch = mkdtempSync3(
|
|
75637
|
+
const scratch = mkdtempSync3(path47.join(os17.tmpdir(), "workit-upgrade-opencode-"));
|
|
75539
75638
|
try {
|
|
75540
75639
|
return runner({
|
|
75541
75640
|
...deps,
|
|
75542
75641
|
env: {
|
|
75543
75642
|
...deps.env,
|
|
75544
|
-
XDG_DATA_HOME:
|
|
75545
|
-
XDG_STATE_HOME:
|
|
75546
|
-
XDG_CACHE_HOME:
|
|
75643
|
+
XDG_DATA_HOME: path47.join(scratch, "data"),
|
|
75644
|
+
XDG_STATE_HOME: path47.join(scratch, "state"),
|
|
75645
|
+
XDG_CACHE_HOME: path47.join(scratch, "cache")
|
|
75547
75646
|
}
|
|
75548
75647
|
})("opencode", args);
|
|
75549
75648
|
} finally {
|
|
75550
75649
|
rmSync8(scratch, { recursive: true, force: true });
|
|
75551
75650
|
}
|
|
75552
|
-
}, registryVersion = (run, name) => {
|
|
75553
|
-
const latest = run("npm", ["view", name, "version"]);
|
|
75554
|
-
const version = latest.stdout.trim();
|
|
75555
|
-
return latest.status === 0 && /^\d+\.\d+\.\d+$/.test(version) ? version : undefined;
|
|
75556
|
-
}, PROCESS_HOSTS, classifyProcess = (proc) => {
|
|
75557
|
-
if (proc.state.startsWith("Z") || proc.args.includes("<defunct>"))
|
|
75558
|
-
return null;
|
|
75559
|
-
const argv0 = proc.args.trim().split(/\s+/)[0] ?? "";
|
|
75560
|
-
const name = path44.basename(argv0.replaceAll("\\", "/")).replace(/^\[|\]$/g, "").replace(/\.exe$/i, "").toLowerCase();
|
|
75561
|
-
const host = PROCESS_HOSTS[name];
|
|
75562
|
-
if (!host)
|
|
75563
|
-
return null;
|
|
75564
|
-
if (host === "codex" && /\bapp-server\b/.test(proc.args))
|
|
75565
|
-
return /\bdaemon\s+pid-update-loop\b/.test(proc.args) ? null : { ...proc, host, kind: "daemon" };
|
|
75566
|
-
if (host === "opencode" && /\bserve\b/.test(proc.args))
|
|
75567
|
-
return { ...proc, host, kind: "daemon" };
|
|
75568
|
-
return { ...proc, host, kind: "session" };
|
|
75569
|
-
}, listProcesses = (deps) => {
|
|
75570
|
-
if (deps.processes)
|
|
75571
|
-
return deps.processes();
|
|
75572
|
-
if (deps.activeHosts)
|
|
75573
|
-
return deps.activeHosts().map((host) => ({ pid: 0, state: "S", args: host }));
|
|
75574
|
-
const run = runner(deps);
|
|
75575
|
-
if (process.platform === "win32") {
|
|
75576
|
-
const list = run("tasklist", ["/fo", "csv", "/nh"]);
|
|
75577
|
-
if (list.status !== 0)
|
|
75578
|
-
return null;
|
|
75579
|
-
return list.stdout.split(/\r?\n/).flatMap((line) => {
|
|
75580
|
-
const [image, pid] = line.split('","').map((cell) => cell.replaceAll('"', ""));
|
|
75581
|
-
return image && /^\d+$/.test(pid ?? "") ? [{ pid: Number(pid), state: "R", args: image }] : [];
|
|
75582
|
-
});
|
|
75583
|
-
}
|
|
75584
|
-
const list = run("ps", ["-eo", "pid=,stat=,args="]);
|
|
75585
|
-
if (list.status !== 0)
|
|
75586
|
-
return null;
|
|
75587
|
-
return list.stdout.split(/\r?\n/).flatMap((line) => {
|
|
75588
|
-
const match = /^\s*(\d+)\s+(\S+)\s+(.+)$/.exec(line);
|
|
75589
|
-
return match ? [{ pid: Number(match[1]), state: match[2], args: match[3] }] : [];
|
|
75590
|
-
});
|
|
75591
|
-
}, describe2 = (proc) => `pid ${proc.pid}: ${proc.args.length > 120 ? `${proc.args.slice(0, 117)}...` : proc.args}`, codexPluginRoot = (codexHome) => {
|
|
75592
|
-
const dir = path44.join(codexHome, "plugins", "cache", CODEX_MARKETPLACE, "workit");
|
|
75593
|
-
let versions = [];
|
|
75594
|
-
try {
|
|
75595
|
-
versions = readdirSync12(dir).filter((version) => /^\d+\.\d+\.\d+$/.test(version));
|
|
75596
|
-
} catch {
|
|
75597
|
-
return null;
|
|
75598
|
-
}
|
|
75599
|
-
const newest = versions.reduce((best, version) => best && versionAtLeast(best, version) ? best : version, null);
|
|
75600
|
-
return newest ? path44.join(dir, newest) : null;
|
|
75601
|
-
}, applyEntry = (entry, context) => {
|
|
75602
|
-
const { run, paths, configDir } = context;
|
|
75603
|
-
const { home, env } = paths;
|
|
75604
|
-
const fail = (reason) => ({
|
|
75605
|
-
host: entry.host,
|
|
75606
|
-
status: "failed",
|
|
75607
|
-
reason,
|
|
75608
|
-
fix: entry.fix
|
|
75609
|
-
});
|
|
75610
|
-
if (entry.host === "cursor") {
|
|
75611
|
-
const preview = {
|
|
75612
|
-
ok: true,
|
|
75613
|
-
blocked: [],
|
|
75614
|
-
preserved: [],
|
|
75615
|
-
overrides: [],
|
|
75616
|
-
platforms: ["cursor"],
|
|
75617
|
-
state: readSetupState(configDir),
|
|
75618
|
-
mutations: [
|
|
75619
|
-
{
|
|
75620
|
-
type: "install-host",
|
|
75621
|
-
platform: "cursor",
|
|
75622
|
-
path: path44.join(home, ".cursor/plugins/local/.workit-package-bootstrap"),
|
|
75623
|
-
commands: entry.commands.map((command) => ({
|
|
75624
|
-
...command,
|
|
75625
|
-
purpose: command.purpose ?? "Upgrade Cursor"
|
|
75626
|
-
}))
|
|
75627
|
-
},
|
|
75628
|
-
{ type: "install-adapter", platform: "cursor", path: paths.cursorRoot }
|
|
75629
|
-
]
|
|
75630
|
-
};
|
|
75631
|
-
const result = applySetupPreview(preview, {
|
|
75632
|
-
home,
|
|
75633
|
-
env,
|
|
75634
|
-
cwd: home,
|
|
75635
|
-
preferInstalledAdapter: true,
|
|
75636
|
-
runHostCommand: (command) => {
|
|
75637
|
-
const outcome = run(command.command, command.args);
|
|
75638
|
-
return {
|
|
75639
|
-
exitCode: outcome.status ?? 1,
|
|
75640
|
-
stdout: outcome.stdout,
|
|
75641
|
-
stderr: ""
|
|
75642
|
-
};
|
|
75643
|
-
}
|
|
75644
|
-
});
|
|
75645
|
-
const installed = objectOrNull(path44.join(paths.cursorRoot, "package.json"));
|
|
75646
|
-
if (!result.ok || installed?.version !== entry.latest)
|
|
75647
|
-
return fail("Cursor install did not verify the requested package version; inspect the installer before retrying");
|
|
75648
|
-
return {
|
|
75649
|
-
host: "cursor",
|
|
75650
|
-
status: "updated",
|
|
75651
|
-
reason: entry.repair ? `reinstalled missing plugin files (${entry.latest})` : `${entry.installedVersion ?? "?"} -> ${entry.latest}`
|
|
75652
|
-
};
|
|
75653
|
-
}
|
|
75654
|
-
for (const command of entry.commands)
|
|
75655
|
-
if (run(command.command, command.args).status !== 0)
|
|
75656
|
-
return fail(`\`${command.command} ${command.args.join(" ")}\` failed`);
|
|
75657
|
-
if (entry.host === "opencode")
|
|
75658
|
-
return {
|
|
75659
|
-
host: "opencode",
|
|
75660
|
-
status: "updated",
|
|
75661
|
-
reason: "scoped update ran; OpenCode V2 loads it live"
|
|
75662
|
-
};
|
|
75663
|
-
if (entry.host === "claude-code") {
|
|
75664
|
-
const after = claudeWorkitInstalls(home, env, null).find((install) => install.id === entry.selector)?.version;
|
|
75665
|
-
return after && after === entry.installedVersion ? {
|
|
75666
|
-
host: "claude-code",
|
|
75667
|
-
status: "current",
|
|
75668
|
-
reason: `already current (${after})`
|
|
75669
|
-
} : {
|
|
75670
|
-
host: "claude-code",
|
|
75671
|
-
status: "updated",
|
|
75672
|
-
reason: `${entry.installedVersion ?? "?"} -> ${after ?? "?"}; new sessions load it`
|
|
75673
|
-
};
|
|
75674
|
-
}
|
|
75675
|
-
const verify = entry.host === "codex" ? run("codex", ["plugin", "list", "--json"]) : run("pi", ["list"]);
|
|
75676
|
-
if (verify.status !== 0)
|
|
75677
|
-
return fail("update verification failed");
|
|
75678
|
-
if (entry.host === "codex") {
|
|
75679
|
-
let installed = [];
|
|
75680
|
-
try {
|
|
75681
|
-
installed = JSON.parse(verify.stdout).installed ?? [];
|
|
75682
|
-
} catch {}
|
|
75683
|
-
if (!installed.some((plugin) => plugin.name === "workit" && plugin.marketplaceName === CODEX_MARKETPLACE && plugin.version === entry.latest))
|
|
75684
|
-
return fail("Codex did not report the requested Workit version");
|
|
75685
|
-
}
|
|
75686
|
-
if (entry.host === "pi" && piInstalledVersion(verify.stdout, entry.selector) !== entry.latest)
|
|
75687
|
-
return fail("Pi did not report the requested Workit package version");
|
|
75688
|
-
return {
|
|
75689
|
-
host: entry.host,
|
|
75690
|
-
status: "updated",
|
|
75691
|
-
reason: `${entry.installedVersion ?? "?"} -> ${entry.latest}`
|
|
75692
|
-
};
|
|
75693
|
-
}, refreshCodexAgents = (run, codexHome) => {
|
|
75694
|
-
const root = codexPluginRoot(codexHome);
|
|
75695
|
-
const launcher = root && path44.join(root, "dist", "launch-mcp.js");
|
|
75696
|
-
if (!launcher || !existsSync20(launcher))
|
|
75697
|
-
return { ok: true, note: "" };
|
|
75698
|
-
const fix = `node ${JSON.stringify(launcher)} --install-agents`;
|
|
75699
|
-
return run("node", [launcher, "--install-agents"]).status === 0 ? { ok: true, note: "agents refreshed" } : { ok: false, note: "agent refresh failed", fix };
|
|
75700
|
-
}, applyCli = (cli, run, backup) => {
|
|
75701
|
-
const fail = (reason) => ({
|
|
75702
|
-
host: "cli",
|
|
75703
|
-
status: "failed",
|
|
75704
|
-
reason,
|
|
75705
|
-
fix: CLI_FIX
|
|
75706
|
-
});
|
|
75707
|
-
const currentRoot = run("npm", ["root", "--global"]);
|
|
75708
|
-
if (currentRoot.status !== 0 || currentRoot.stdout.trim() !== cli.root)
|
|
75709
|
-
return fail("Global npm location changed; preview again");
|
|
75710
|
-
const cliBackup = path44.join(backup, "cli-package");
|
|
75711
|
-
cpSync5(path44.join(cli.root, "@brainervirus/workit-cli"), cliBackup, {
|
|
75712
|
-
recursive: true
|
|
75713
|
-
});
|
|
75714
|
-
if (run("npm", ["install", "--global", `@brainervirus/workit-cli@${cli.latest}`]).status !== 0)
|
|
75715
|
-
return fail(`CLI update failed; preserved package at ${cliBackup}; use npm to repair or run node ${path44.join(cliBackup, "dist/index.js")}`);
|
|
75716
|
-
const installed = objectOrNull(path44.join(cli.root, "@brainervirus/workit-cli/package.json"));
|
|
75717
|
-
if (installed?.name !== "@brainervirus/workit-cli" || installed.version !== cli.latest)
|
|
75718
|
-
return fail(`CLI update did not verify the requested version; preserved package at ${cliBackup}`);
|
|
75719
|
-
return {
|
|
75720
|
-
host: "cli",
|
|
75721
|
-
status: "updated",
|
|
75722
|
-
reason: `${cli.installed} -> ${cli.latest}`
|
|
75723
|
-
};
|
|
75724
75651
|
}, planCli = (plan, run) => {
|
|
75725
75652
|
const root = run("npm", ["root", "--global"]);
|
|
75726
|
-
if (root.status !== 0 || !
|
|
75653
|
+
if (root.status !== 0 || !path47.isAbsolute(root.stdout.trim())) {
|
|
75727
75654
|
plan.skipped.push({
|
|
75728
75655
|
host: "cli",
|
|
75729
75656
|
reason: "global npm location could not be verified",
|
|
@@ -75731,9 +75658,9 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
|
|
|
75731
75658
|
});
|
|
75732
75659
|
return;
|
|
75733
75660
|
}
|
|
75734
|
-
const packageFile =
|
|
75661
|
+
const packageFile = path47.join(root.stdout.trim(), "@brainervirus/workit-cli/package.json");
|
|
75735
75662
|
const installed = objectOrNull(packageFile);
|
|
75736
|
-
if (installed?.name !== "@brainervirus/workit-cli" || lstatSync7(
|
|
75663
|
+
if (installed?.name !== "@brainervirus/workit-cli" || lstatSync7(path47.dirname(packageFile)).isSymbolicLink()) {
|
|
75737
75664
|
plan.skipped.push({
|
|
75738
75665
|
host: "cli",
|
|
75739
75666
|
reason: "no managed global CLI install (local links preserved); use npx @brainervirus/workit-cli@latest"
|
|
@@ -75760,7 +75687,18 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
|
|
|
75760
75687
|
host: "cli",
|
|
75761
75688
|
reason: `already current (${installed.version})`
|
|
75762
75689
|
});
|
|
75763
|
-
}
|
|
75690
|
+
};
|
|
75691
|
+
var init_plan = __esm(() => {
|
|
75692
|
+
init_registration();
|
|
75693
|
+
init_setup_state();
|
|
75694
|
+
init_host_install();
|
|
75695
|
+
init_doctor();
|
|
75696
|
+
init_support_matrix();
|
|
75697
|
+
init_shared();
|
|
75698
|
+
});
|
|
75699
|
+
|
|
75700
|
+
// packages/workit-cli/src/upgrade/report.ts
|
|
75701
|
+
var pad2 = (text) => text.padEnd(12), summary = (plan, permissions) => {
|
|
75764
75702
|
const lines = ["Workit upgrade plan:"];
|
|
75765
75703
|
if (plan.cli)
|
|
75766
75704
|
lines.push(` ${pad2("cli")}update ${plan.cli.installed} -> ${plan.cli.latest}`);
|
|
@@ -75797,29 +75735,8 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
|
|
|
75797
75735
|
}
|
|
75798
75736
|
await Promise.resolve().then(() => init_prompt());
|
|
75799
75737
|
return /^y(?:es)?$/i.test((await askLine(question)).trim());
|
|
75800
|
-
}
|
|
75801
|
-
|
|
75802
|
-
var init_upgrade = __esm(() => {
|
|
75803
|
-
init_package();
|
|
75804
|
-
init_registration();
|
|
75805
|
-
init_setup_state();
|
|
75806
|
-
init_host_install();
|
|
75807
|
-
init_setup();
|
|
75808
|
-
init_doctor();
|
|
75809
|
-
init_support_matrix();
|
|
75810
|
-
init_safe_write();
|
|
75811
|
-
init_host_permissions();
|
|
75812
|
-
LAUNCH_HOSTS = ["opencode", "cursor", "codex", "pi"];
|
|
75813
|
-
HOSTS2 = [...LAUNCH_HOSTS, "claude-code"];
|
|
75814
|
-
LIVE_HOSTS = new Set(["opencode", "claude-code"]);
|
|
75815
|
-
OPENCODE_UPDATE = `opencode plugin update ${OPENCODE_PACKAGE}`;
|
|
75816
|
-
PROCESS_HOSTS = {
|
|
75817
|
-
claude: "claude-code",
|
|
75818
|
-
codex: "codex",
|
|
75819
|
-
cursor: "cursor",
|
|
75820
|
-
opencode: "opencode",
|
|
75821
|
-
pi: "pi"
|
|
75822
|
-
};
|
|
75738
|
+
};
|
|
75739
|
+
var init_report = __esm(() => {
|
|
75823
75740
|
LABEL = {
|
|
75824
75741
|
updated: "updated",
|
|
75825
75742
|
current: "already current",
|
|
@@ -75828,6 +75745,191 @@ var init_upgrade = __esm(() => {
|
|
|
75828
75745
|
};
|
|
75829
75746
|
});
|
|
75830
75747
|
|
|
75748
|
+
// packages/workit-cli/src/upgrade.ts
|
|
75749
|
+
import { spawnSync as spawnSync17 } from "node:child_process";
|
|
75750
|
+
async function runUpgradeCommand(argv, deps = {}) {
|
|
75751
|
+
const out = deps.out ?? process.stdout;
|
|
75752
|
+
const flags = new Set(argv);
|
|
75753
|
+
const unknown = argv.filter((arg) => !["--apply", "--confirm", "--json", "--cli", "--preview", "--yes"].includes(arg) && !arg.startsWith("--hosts="));
|
|
75754
|
+
const hostFlag = argv.find((arg) => arg.startsWith("--hosts="))?.slice(8);
|
|
75755
|
+
const raw = hostFlag === "none" ? [] : hostFlag?.split(",") ?? HOSTS2;
|
|
75756
|
+
if (unknown.length || raw.some((host) => !HOSTS2.includes(host)) || flags.has("--preview") && (flags.has("--apply") || flags.has("--yes"))) {
|
|
75757
|
+
out.write(USAGE3);
|
|
75758
|
+
return 2;
|
|
75759
|
+
}
|
|
75760
|
+
if (flags.has("--apply") && !flags.has("--confirm")) {
|
|
75761
|
+
out.write(`Apply requires --confirm after reviewing the upgrade preview.
|
|
75762
|
+
`);
|
|
75763
|
+
return 2;
|
|
75764
|
+
}
|
|
75765
|
+
const legacy = flags.has("--apply");
|
|
75766
|
+
const json = flags.has("--json") || legacy;
|
|
75767
|
+
const run = runner(deps);
|
|
75768
|
+
const plan = previewUpgrade(raw, deps);
|
|
75769
|
+
if (hostFlag === undefined || flags.has("--cli"))
|
|
75770
|
+
planCli(plan, run);
|
|
75771
|
+
plan.ok = plan.blocked.length === 0 && plan.failed.length === 0;
|
|
75772
|
+
const { home, env } = upgradePaths(deps);
|
|
75773
|
+
const permissions = planHostPermissions({
|
|
75774
|
+
hosts: raw,
|
|
75775
|
+
refreshOnly: true,
|
|
75776
|
+
shell: false,
|
|
75777
|
+
home,
|
|
75778
|
+
env
|
|
75779
|
+
});
|
|
75780
|
+
const permissionPreview = {
|
|
75781
|
+
changes: permissions.changes.map((c) => ({
|
|
75782
|
+
host: c.host,
|
|
75783
|
+
file: c.file,
|
|
75784
|
+
diff: permissionDiff(c)
|
|
75785
|
+
})),
|
|
75786
|
+
...permissions.refused ? { refused: permissions.refused } : {}
|
|
75787
|
+
};
|
|
75788
|
+
const withPermissions = (value) => permissions.changes.length ? { ...value, permissions: permissionPreview } : value;
|
|
75789
|
+
const applyCommand = `workit upgrade ${[...hostFlag === undefined ? [] : [`--hosts=${hostFlag}`], ...flags.has("--cli") ? ["--cli"] : [], "--yes"].join(" ")}`;
|
|
75790
|
+
const nothingChanged = `preview only; nothing changed. Apply with: ${applyCommand}
|
|
75791
|
+
`;
|
|
75792
|
+
if (json && !legacy && !flags.has("--yes")) {
|
|
75793
|
+
out.write(JSON.stringify(withPermissions(plan), null, 2) + `
|
|
75794
|
+
`);
|
|
75795
|
+
return plan.blocked.length ? 1 : 0;
|
|
75796
|
+
}
|
|
75797
|
+
if (!json)
|
|
75798
|
+
out.write(summary(plan, permissions.changes));
|
|
75799
|
+
if (flags.has("--preview")) {
|
|
75800
|
+
out.write(nothingChanged);
|
|
75801
|
+
return plan.blocked.length ? 1 : 0;
|
|
75802
|
+
}
|
|
75803
|
+
if (plan.blocked.length) {
|
|
75804
|
+
out.write(`Upgrade blocked: ${plan.blocked.join("; ")}
|
|
75805
|
+
Nothing changed.
|
|
75806
|
+
`);
|
|
75807
|
+
return 1;
|
|
75808
|
+
}
|
|
75809
|
+
const work = plan.entries.length + plan.migrations.length + (plan.cli ? 1 : 0) + permissions.changes.length;
|
|
75810
|
+
if (work > 0 && !flags.has("--yes") && !legacy) {
|
|
75811
|
+
const confirmed = await (deps.confirm ?? ((q) => askConfirm(q, out)))("Apply this upgrade? [y/N] ");
|
|
75812
|
+
if (!confirmed) {
|
|
75813
|
+
out.write(nothingChanged);
|
|
75814
|
+
return 0;
|
|
75815
|
+
}
|
|
75816
|
+
}
|
|
75817
|
+
if (json)
|
|
75818
|
+
for (const warning of plan.warnings ?? [])
|
|
75819
|
+
out.write(`warning: ${warning}
|
|
75820
|
+
`);
|
|
75821
|
+
const result = applyUpgrade(plan, deps);
|
|
75822
|
+
let permissionsOk = true;
|
|
75823
|
+
let written;
|
|
75824
|
+
if (permissions.changes.length && !permissions.refused && !result.error?.startsWith("configuration changed")) {
|
|
75825
|
+
written = applyHostPermissions(permissions, { home, env });
|
|
75826
|
+
permissionsOk = written.every((entry) => entry.status === "written");
|
|
75827
|
+
for (const entry of written)
|
|
75828
|
+
result.hosts.push({
|
|
75829
|
+
host: entry.host,
|
|
75830
|
+
status: entry.status === "written" ? "updated" : "failed",
|
|
75831
|
+
reason: `permission block ${entry.status === "written" ? "refreshed" : entry.status} in ${entry.file}`,
|
|
75832
|
+
...entry.status === "written" ? {} : { fix: `workit setup --hosts=${entry.host}` }
|
|
75833
|
+
});
|
|
75834
|
+
}
|
|
75835
|
+
const failed = !result.ok || !permissionsOk;
|
|
75836
|
+
const cliVersion = result.hosts.some((h) => h.host === "cli" && h.status === "updated") ? plan.cli.latest : package_default.version;
|
|
75837
|
+
const report = (deps.doctor ?? ((version) => runDoctor({ home, env, cliVersion: version, only: "upgrade" })))(cliVersion);
|
|
75838
|
+
const left = report.checks.filter((check) => check.status === "warn" || check.status === "fail");
|
|
75839
|
+
if (json) {
|
|
75840
|
+
out.write(JSON.stringify({
|
|
75841
|
+
...result,
|
|
75842
|
+
ok: !failed,
|
|
75843
|
+
...written ? { permissions: { changes: permissionPreview.changes, written } } : permissions.refused ? { permissions: permissionPreview } : {},
|
|
75844
|
+
doctor: { clean: left.length === 0, left }
|
|
75845
|
+
}, null, 2) + `
|
|
75846
|
+
`);
|
|
75847
|
+
return failed ? 1 : 0;
|
|
75848
|
+
}
|
|
75849
|
+
if (result.error && result.hosts.every((h) => h.status !== "failed"))
|
|
75850
|
+
out.write(`Upgrade stopped: ${result.error}
|
|
75851
|
+
`);
|
|
75852
|
+
out.write(table(result.hosts));
|
|
75853
|
+
if (permissions.refused)
|
|
75854
|
+
out.write(`permissions: not refreshed: ${permissions.refused}
|
|
75855
|
+
`);
|
|
75856
|
+
if (result.backup)
|
|
75857
|
+
out.write(`Backup: ${result.backup}
|
|
75858
|
+
`);
|
|
75859
|
+
out.write(left.length === 0 ? `Verified: workit doctor is clean for versions, assets, agents and permissions.
|
|
75860
|
+
` : `Left after upgrade (workit doctor):
|
|
75861
|
+
${left.map((check) => ` ${check.id}: ${check.detail}${check.fix ? `
|
|
75862
|
+
fix: ${check.fix}` : ""}`).join(`
|
|
75863
|
+
`)}
|
|
75864
|
+
`);
|
|
75865
|
+
return failed ? 1 : 0;
|
|
75866
|
+
}
|
|
75867
|
+
async function runLaunchCommand(argv, deps = {}) {
|
|
75868
|
+
const [host, ...args] = argv;
|
|
75869
|
+
if (!LAUNCH_HOSTS.includes(host)) {
|
|
75870
|
+
(deps.out ?? process.stdout).write(`Usage: workit launch <opencode|cursor|codex|pi> [--auto-upgrade] [-- host arguments]
|
|
75871
|
+
`);
|
|
75872
|
+
return 2;
|
|
75873
|
+
}
|
|
75874
|
+
const auto = args[0] === "--auto-upgrade";
|
|
75875
|
+
const rest = auto ? args.slice(1) : args;
|
|
75876
|
+
const hostArgs = rest[0] === "--" ? rest.slice(1) : rest;
|
|
75877
|
+
const { home, env } = upgradePaths(deps);
|
|
75878
|
+
let launch;
|
|
75879
|
+
if (!deps.run) {
|
|
75880
|
+
try {
|
|
75881
|
+
launch = hostCommand(host, hostArgs, { home, env });
|
|
75882
|
+
} catch (error) {
|
|
75883
|
+
(deps.out ?? process.stderr).write(`${error instanceof Error ? error.message : "Host executable unavailable"}
|
|
75884
|
+
`);
|
|
75885
|
+
return 1;
|
|
75886
|
+
}
|
|
75887
|
+
}
|
|
75888
|
+
if (auto) {
|
|
75889
|
+
const plan = previewUpgrade([host], deps);
|
|
75890
|
+
const reasons = [...plan.blocked, ...plan.failed.map((entry) => entry.reason)];
|
|
75891
|
+
if (plan.ok) {
|
|
75892
|
+
for (const skipped of plan.skipped)
|
|
75893
|
+
(deps.out ?? process.stderr).write(`${skipped.host}: ${skipped.reason}${skipped.fix ? ` (run: ${skipped.fix})` : ""}
|
|
75894
|
+
`);
|
|
75895
|
+
const result = applyUpgrade(plan, deps);
|
|
75896
|
+
if (!result.ok) {
|
|
75897
|
+
(deps.out ?? process.stdout).write(`${result.error}
|
|
75898
|
+
`);
|
|
75899
|
+
return 1;
|
|
75900
|
+
}
|
|
75901
|
+
} else if (plan.blocked.length === 0 && reasons.every((reason) => reason.includes("registry version unavailable"))) {
|
|
75902
|
+
(deps.out ?? process.stderr).write(`Upgrade unavailable: ${reasons.join("; ")}. Starting the unchanged host.
|
|
75903
|
+
`);
|
|
75904
|
+
} else {
|
|
75905
|
+
(deps.out ?? process.stderr).write(`Upgrade blocked: ${reasons.join("; ")}
|
|
75906
|
+
`);
|
|
75907
|
+
return 1;
|
|
75908
|
+
}
|
|
75909
|
+
}
|
|
75910
|
+
if (deps.run)
|
|
75911
|
+
return deps.run(host, hostArgs).status ?? 1;
|
|
75912
|
+
return spawnSync17(launch.command, launch.args, {
|
|
75913
|
+
stdio: "inherit",
|
|
75914
|
+
env
|
|
75915
|
+
}).status ?? 1;
|
|
75916
|
+
}
|
|
75917
|
+
var USAGE3 = `Usage: workit upgrade [--hosts=opencode,cursor,codex,pi,claude-code|none] [--cli] [--preview | --yes | --apply --confirm] [--json]
|
|
75918
|
+
`;
|
|
75919
|
+
var init_upgrade = __esm(() => {
|
|
75920
|
+
init_package();
|
|
75921
|
+
init_host_install();
|
|
75922
|
+
init_doctor();
|
|
75923
|
+
init_host_permissions();
|
|
75924
|
+
init_apply();
|
|
75925
|
+
init_plan();
|
|
75926
|
+
init_report();
|
|
75927
|
+
init_shared();
|
|
75928
|
+
init_apply();
|
|
75929
|
+
init_plan();
|
|
75930
|
+
init_processes();
|
|
75931
|
+
});
|
|
75932
|
+
|
|
75831
75933
|
// packages/workit-cli/src/verbs/upgrade.ts
|
|
75832
75934
|
var exports_upgrade = {};
|
|
75833
75935
|
__export(exports_upgrade, {
|
|
@@ -75851,7 +75953,7 @@ var init_launch = __esm(() => {
|
|
|
75851
75953
|
// packages/workit-core/src/knowledge.ts
|
|
75852
75954
|
import { spawnSync as spawnSync18 } from "node:child_process";
|
|
75853
75955
|
import fs20 from "node:fs";
|
|
75854
|
-
import
|
|
75956
|
+
import path48 from "node:path";
|
|
75855
75957
|
function lintKnowledge(root) {
|
|
75856
75958
|
const seen = new Set;
|
|
75857
75959
|
const unreadable = [];
|
|
@@ -75955,7 +76057,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
|
|
|
75955
76057
|
const end = lines.indexOf("---", 1);
|
|
75956
76058
|
return end === -1 ? lines : [...lines.slice(0, end + 1).map(() => ""), ...lines.slice(end + 1)];
|
|
75957
76059
|
}, read = (root, file) => {
|
|
75958
|
-
const full =
|
|
76060
|
+
const full = path48.join(root, file);
|
|
75959
76061
|
try {
|
|
75960
76062
|
fs20.lstatSync(full);
|
|
75961
76063
|
} catch {
|
|
@@ -75996,7 +76098,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
|
|
|
75996
76098
|
}
|
|
75997
76099
|
}, brokenLinks = (root, doc, tracked) => {
|
|
75998
76100
|
const findings = [];
|
|
75999
|
-
const base =
|
|
76101
|
+
const base = path48.dirname(path48.join(root, doc.file));
|
|
76000
76102
|
const missing = (target, line, how) => findings.push({
|
|
76001
76103
|
rule: "broken-link",
|
|
76002
76104
|
file: doc.file,
|
|
@@ -76015,7 +76117,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
|
|
|
76015
76117
|
const local = localTarget(target);
|
|
76016
76118
|
if (!local)
|
|
76017
76119
|
continue;
|
|
76018
|
-
const resolved = local.startsWith("/") ?
|
|
76120
|
+
const resolved = local.startsWith("/") ? path48.join(root, local) : path48.resolve(base, local);
|
|
76019
76121
|
if (!exists2(resolved))
|
|
76020
76122
|
missing(target, index + 1, "link");
|
|
76021
76123
|
}
|
|
@@ -76025,9 +76127,9 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
|
|
|
76025
76127
|
continue;
|
|
76026
76128
|
const relative = /^\.\.?\//.test(candidate);
|
|
76027
76129
|
const first = candidate.split("/")[0];
|
|
76028
|
-
if (!relative && !(tracked ? tracked.has(first) : exists2(
|
|
76130
|
+
if (!relative && !(tracked ? tracked.has(first) : exists2(path48.join(root, first))))
|
|
76029
76131
|
continue;
|
|
76030
|
-
const resolved = relative ?
|
|
76132
|
+
const resolved = relative ? path48.resolve(base, candidate) : path48.join(root, candidate);
|
|
76031
76133
|
if (!exists2(resolved))
|
|
76032
76134
|
missing(span, index + 1, "pointer");
|
|
76033
76135
|
}
|
|
@@ -76350,10 +76452,10 @@ var init_redact = __esm(() => {
|
|
|
76350
76452
|
|
|
76351
76453
|
// packages/workit-core/src/checks.ts
|
|
76352
76454
|
import { spawn, spawnSync as spawnSync19 } from "node:child_process";
|
|
76353
|
-
import { createHash as
|
|
76455
|
+
import { createHash as createHash17 } from "node:crypto";
|
|
76354
76456
|
import fs21 from "node:fs";
|
|
76355
|
-
import
|
|
76356
|
-
import
|
|
76457
|
+
import os18 from "node:os";
|
|
76458
|
+
import path49 from "node:path";
|
|
76357
76459
|
import { StringDecoder } from "node:string_decoder";
|
|
76358
76460
|
function tailLines(text, lines = TAIL_LINES) {
|
|
76359
76461
|
const all = text.replace(/\r\n?/gu, `
|
|
@@ -76473,7 +76575,7 @@ function planSpawn(argv, options) {
|
|
|
76473
76575
|
return { file: argv[0], args: [], verbatim: false, shell: true };
|
|
76474
76576
|
if (options.platform !== "win32")
|
|
76475
76577
|
return { file: argv[0], args: argv.slice(1), verbatim: false, shell: false };
|
|
76476
|
-
const win =
|
|
76578
|
+
const win = path49.win32;
|
|
76477
76579
|
const isFile = options.isFile ?? ((file) => {
|
|
76478
76580
|
try {
|
|
76479
76581
|
return fs21.statSync(file).isFile();
|
|
@@ -76558,7 +76660,7 @@ function runCheckCommand(argv, options) {
|
|
|
76558
76660
|
`);
|
|
76559
76661
|
redactor.end();
|
|
76560
76662
|
resolve({
|
|
76561
|
-
exitCode: spawnError ? 127 : code !== null ? code : 128 + (signal ?
|
|
76663
|
+
exitCode: spawnError ? 127 : code !== null ? code : 128 + (signal ? os18.constants.signals[signal] ?? 1 : 1),
|
|
76562
76664
|
signal: signal ?? null,
|
|
76563
76665
|
timedOut,
|
|
76564
76666
|
durationMs: Date.now() - started,
|
|
@@ -76635,10 +76737,10 @@ function runCheckCommand(argv, options) {
|
|
|
76635
76737
|
function storeLog(storeRoot, log) {
|
|
76636
76738
|
const digest = logDigest(log);
|
|
76637
76739
|
const ref = `blobs/logs/${digest.slice("sha256:".length)}.log`;
|
|
76638
|
-
const file =
|
|
76740
|
+
const file = path49.join(storeRoot, ref);
|
|
76639
76741
|
try {
|
|
76640
76742
|
if (!fs21.existsSync(file)) {
|
|
76641
|
-
fs21.mkdirSync(
|
|
76743
|
+
fs21.mkdirSync(path49.dirname(file), { recursive: true });
|
|
76642
76744
|
const temp = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
76643
76745
|
fs21.writeFileSync(temp, log, { mode: 384 });
|
|
76644
76746
|
fs21.renameSync(temp, file);
|
|
@@ -76651,7 +76753,7 @@ function storeLog(storeRoot, log) {
|
|
|
76651
76753
|
function pruneCheckLogs(storeRoot, options = {}) {
|
|
76652
76754
|
const limits = { ...LOG_RETENTION, ...options.retention };
|
|
76653
76755
|
const now = options.now ?? Date.now();
|
|
76654
|
-
const dir =
|
|
76756
|
+
const dir = path49.join(storeRoot, "blobs", "logs");
|
|
76655
76757
|
const report = { removed: 0, removedBytes: 0, kept: 0 };
|
|
76656
76758
|
let names;
|
|
76657
76759
|
try {
|
|
@@ -76661,7 +76763,7 @@ function pruneCheckLogs(storeRoot, options = {}) {
|
|
|
76661
76763
|
}
|
|
76662
76764
|
const files = names.flatMap((name) => {
|
|
76663
76765
|
try {
|
|
76664
|
-
const stat = fs21.statSync(
|
|
76766
|
+
const stat = fs21.statSync(path49.join(dir, name));
|
|
76665
76767
|
return stat.isFile() ? [{ name, size: stat.size, mtimeMs: stat.mtimeMs }] : [];
|
|
76666
76768
|
} catch {
|
|
76667
76769
|
return [];
|
|
@@ -76680,7 +76782,7 @@ function pruneCheckLogs(storeRoot, options = {}) {
|
|
|
76680
76782
|
continue;
|
|
76681
76783
|
if (!options.dryRun)
|
|
76682
76784
|
try {
|
|
76683
|
-
fs21.rmSync(
|
|
76785
|
+
fs21.rmSync(path49.join(dir, file.name), { force: true });
|
|
76684
76786
|
} catch {
|
|
76685
76787
|
continue;
|
|
76686
76788
|
}
|
|
@@ -76689,7 +76791,7 @@ function pruneCheckLogs(storeRoot, options = {}) {
|
|
|
76689
76791
|
}
|
|
76690
76792
|
return report;
|
|
76691
76793
|
}
|
|
76692
|
-
var MAX_LOG_BYTES, TAIL_LINES = 80, MAX_LINE_CHARS = 400, redactLog = (text) => redactText(text), PEM_BEGIN, PEM_END, BATCH_BYTES, MAX_PENDING, PEM_BODY, MAX_KEY_LINES = 4096, MAX_KEY_BYTES, CMD_META, DRAIN_MS = 250, FORWARDED_SIGNALS, logDigest = (log) => `sha256:${
|
|
76794
|
+
var MAX_LOG_BYTES, TAIL_LINES = 80, MAX_LINE_CHARS = 400, redactLog = (text) => redactText(text), PEM_BEGIN, PEM_END, BATCH_BYTES, MAX_PENDING, PEM_BODY, MAX_KEY_LINES = 4096, MAX_KEY_BYTES, CMD_META, DRAIN_MS = 250, FORWARDED_SIGNALS, logDigest = (log) => `sha256:${createHash17("sha256").update(log).digest("hex")}`, LOG_RETENTION;
|
|
76693
76795
|
var init_checks3 = __esm(() => {
|
|
76694
76796
|
init_redact();
|
|
76695
76797
|
MAX_LOG_BYTES = 2 * 1024 * 1024;
|
|
@@ -76953,7 +77055,7 @@ __export(exports_workspace, {
|
|
|
76953
77055
|
run: () => run11,
|
|
76954
77056
|
runWorkspace: () => runWorkspace
|
|
76955
77057
|
});
|
|
76956
|
-
import { copyFileSync as copyFileSync7, existsSync as
|
|
77058
|
+
import { copyFileSync as copyFileSync7, existsSync as existsSync23 } from "node:fs";
|
|
76957
77059
|
function list2(argv, io) {
|
|
76958
77060
|
if (argv.length)
|
|
76959
77061
|
return usage3(io, `unexpected argument ${argv[0]}`);
|
|
@@ -77163,7 +77265,7 @@ usage: ${USAGE5}`)), load = (io) => {
|
|
|
77163
77265
|
return { ok: false, error: `${current.path} changed; retry` };
|
|
77164
77266
|
let backup = null;
|
|
77165
77267
|
try {
|
|
77166
|
-
if (
|
|
77268
|
+
if (existsSync23(current.path)) {
|
|
77167
77269
|
backup = `${current.path}.bak`;
|
|
77168
77270
|
copyFileSync7(current.path, backup);
|
|
77169
77271
|
}
|
|
@@ -77231,12 +77333,12 @@ var init_workspace = __esm(() => {
|
|
|
77231
77333
|
|
|
77232
77334
|
// packages/workit-core/src/core/heavy-rules.ts
|
|
77233
77335
|
import fs22 from "node:fs";
|
|
77234
|
-
import
|
|
77336
|
+
import path50 from "node:path";
|
|
77235
77337
|
function gitTop(cwd) {
|
|
77236
|
-
for (let dir =
|
|
77237
|
-
if (fs22.existsSync(
|
|
77338
|
+
for (let dir = path50.resolve(cwd);; dir = path50.dirname(dir)) {
|
|
77339
|
+
if (fs22.existsSync(path50.join(dir, ".git")))
|
|
77238
77340
|
return dir;
|
|
77239
|
-
if (
|
|
77341
|
+
if (path50.dirname(dir) === dir)
|
|
77240
77342
|
return null;
|
|
77241
77343
|
}
|
|
77242
77344
|
}
|
|
@@ -77277,19 +77379,19 @@ var init_heavy_rules = () => {};
|
|
|
77277
77379
|
|
|
77278
77380
|
// packages/workit-core/src/core/heavy.ts
|
|
77279
77381
|
import fs23 from "node:fs";
|
|
77280
|
-
import
|
|
77281
|
-
import
|
|
77382
|
+
import os19 from "node:os";
|
|
77383
|
+
import path51 from "node:path";
|
|
77282
77384
|
function stateDir2(env, platform = process.platform) {
|
|
77283
77385
|
if (env.WORKFLOW_TOOLKIT_STATE)
|
|
77284
77386
|
return env.WORKFLOW_TOOLKIT_STATE;
|
|
77285
77387
|
if (env.XDG_STATE_HOME)
|
|
77286
|
-
return
|
|
77287
|
-
const home = env.HOME ||
|
|
77388
|
+
return path51.join(env.XDG_STATE_HOME, "workit");
|
|
77389
|
+
const home = env.HOME || os19.homedir();
|
|
77288
77390
|
if (platform === "darwin")
|
|
77289
|
-
return
|
|
77391
|
+
return path51.join(home, "Library", "Application Support", "workit");
|
|
77290
77392
|
if (platform === "win32")
|
|
77291
|
-
return
|
|
77292
|
-
return
|
|
77393
|
+
return path51.join(env.LOCALAPPDATA ?? path51.join(home, "AppData", "Local"), "workit");
|
|
77394
|
+
return path51.join(home, ".local", "state", "workit");
|
|
77293
77395
|
}
|
|
77294
77396
|
function positional(words, from, values = PM_VALUES) {
|
|
77295
77397
|
let index = from;
|
|
@@ -77429,7 +77531,7 @@ function machinePatterns(env) {
|
|
|
77429
77531
|
return isRecord8(value) ? stringList2(value.patterns) : [];
|
|
77430
77532
|
}
|
|
77431
77533
|
function repoPatterns(cwd) {
|
|
77432
|
-
return repoHeavyCommands(gitTop(cwd) ??
|
|
77534
|
+
return repoHeavyCommands(gitTop(cwd) ?? path51.resolve(cwd));
|
|
77433
77535
|
}
|
|
77434
77536
|
function heavyLines(lines, options) {
|
|
77435
77537
|
const found = [];
|
|
@@ -77508,7 +77610,7 @@ function leaseRewrite(command) {
|
|
|
77508
77610
|
return null;
|
|
77509
77611
|
return `${prefix}workit check --heavy -- ${rest}`;
|
|
77510
77612
|
}
|
|
77511
|
-
var HEAVY_COMMANDS_FILE = "heavy-commands.json", heavyCommandsFile = (env) =>
|
|
77613
|
+
var HEAVY_COMMANDS_FILE = "heavy-commands.json", heavyCommandsFile = (env) => path51.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) => {
|
|
77512
77614
|
try {
|
|
77513
77615
|
return JSON.parse(fs23.readFileSync(file, "utf8"));
|
|
77514
77616
|
} catch {
|
|
@@ -77654,8 +77756,8 @@ var init_heavy = __esm(() => {
|
|
|
77654
77756
|
// packages/workit-core/src/core/resources.ts
|
|
77655
77757
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
77656
77758
|
import fs24 from "node:fs";
|
|
77657
|
-
import
|
|
77658
|
-
import
|
|
77759
|
+
import os20 from "node:os";
|
|
77760
|
+
import path52 from "node:path";
|
|
77659
77761
|
function memoryValue(value, host) {
|
|
77660
77762
|
const text = typeof value === "number" ? String(value) : typeof value === "string" ? value : "";
|
|
77661
77763
|
const percent = PERCENT.exec(text.trim());
|
|
@@ -77836,7 +77938,7 @@ function tryOnce(options, record, reclaimed) {
|
|
|
77836
77938
|
const text = `${JSON.stringify(record)}
|
|
77837
77939
|
`;
|
|
77838
77940
|
for (let slot = 0;slot < options.slots; slot += 1) {
|
|
77839
|
-
const file =
|
|
77941
|
+
const file = path52.join(options.dir, `slot-${slot}.json`);
|
|
77840
77942
|
for (let attempt = 0;attempt < 2; attempt += 1) {
|
|
77841
77943
|
try {
|
|
77842
77944
|
const fd = fs24.openSync(file, "wx", 384);
|
|
@@ -77961,7 +78063,7 @@ function heldLease(dir, id, options = {}) {
|
|
|
77961
78063
|
for (const name of names) {
|
|
77962
78064
|
if (!/^slot-\d+\.json$/u.test(name))
|
|
77963
78065
|
continue;
|
|
77964
|
-
const lease = parseLease(readText5(
|
|
78066
|
+
const lease = parseLease(readText5(path52.join(dir, name)));
|
|
77965
78067
|
if (lease?.id === id && !staleReason(lease, options.probe) && (options.ancestor ?? isAncestor)(lease.pid))
|
|
77966
78068
|
return lease;
|
|
77967
78069
|
}
|
|
@@ -78016,10 +78118,10 @@ async function runScoped(run, wrapper, sinks) {
|
|
|
78016
78118
|
}
|
|
78017
78119
|
function firstNotice(env, session, key, now = Date.now()) {
|
|
78018
78120
|
const id = (session ?? `ppid-${process.ppid}`).replace(/[^A-Za-z0-9_.-]/gu, "_").slice(0, 120);
|
|
78019
|
-
const dir =
|
|
78121
|
+
const dir = path52.join(stateDir2(env), "notices");
|
|
78020
78122
|
try {
|
|
78021
78123
|
fs24.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
78022
|
-
fs24.writeFileSync(
|
|
78124
|
+
fs24.writeFileSync(path52.join(dir, `${key}-${id}`), `${new Date(now).toISOString()}
|
|
78023
78125
|
`, {
|
|
78024
78126
|
flag: "wx",
|
|
78025
78127
|
mode: 384
|
|
@@ -78029,7 +78131,7 @@ function firstNotice(env, session, key, now = Date.now()) {
|
|
|
78029
78131
|
}
|
|
78030
78132
|
try {
|
|
78031
78133
|
for (const name of fs24.readdirSync(dir)) {
|
|
78032
|
-
const file =
|
|
78134
|
+
const file = path52.join(dir, name);
|
|
78033
78135
|
if (now - fs24.statSync(file).mtimeMs > NOTICE_TTL_MS)
|
|
78034
78136
|
fs24.rmSync(file, { force: true });
|
|
78035
78137
|
}
|
|
@@ -78039,7 +78141,7 @@ function firstNotice(env, session, key, now = Date.now()) {
|
|
|
78039
78141
|
function leaseSlots(dir, slots, probe = {}) {
|
|
78040
78142
|
const states = [];
|
|
78041
78143
|
for (let slot = 0;slot < slots; slot += 1) {
|
|
78042
|
-
const lease = parseLease(readText5(
|
|
78144
|
+
const lease = parseLease(readText5(path52.join(dir, `slot-${slot}.json`)));
|
|
78043
78145
|
states.push({
|
|
78044
78146
|
slot,
|
|
78045
78147
|
holder: lease ? holderOf(lease) : null,
|
|
@@ -78049,15 +78151,15 @@ function leaseSlots(dir, slots, probe = {}) {
|
|
|
78049
78151
|
return states;
|
|
78050
78152
|
}
|
|
78051
78153
|
var DEFAULT_HEAVY_CHECKS, DEFAULT_SLOTS = 1, DEFAULT_WAIT_S = 600, DEFAULT_MEMORY_SHARE = 0.4, DEFAULT_CPU_SHARE = 0.7, MAX_SLOTS = 64, UNREADABLE_TTL_MS = 30000, GUARD_TTL_MS = 30000, hostShape = () => ({
|
|
78052
|
-
totalMemBytes:
|
|
78053
|
-
cpus: Math.max(1,
|
|
78054
|
-
}), isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), SIZE, PERCENT, UNITS, leaseDir = (env) =>
|
|
78154
|
+
totalMemBytes: os20.totalmem(),
|
|
78155
|
+
cpus: Math.max(1, os20.availableParallelism?.() ?? os20.cpus().length)
|
|
78156
|
+
}), isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), SIZE, PERCENT, UNITS, leaseDir = (env) => path52.join(stateDir2(env), "leases"), readText5 = (file) => {
|
|
78055
78157
|
try {
|
|
78056
78158
|
return fs24.readFileSync(file, "utf8");
|
|
78057
78159
|
} catch {
|
|
78058
78160
|
return null;
|
|
78059
78161
|
}
|
|
78060
|
-
}, bootId = () => readText5("/proc/sys/kernel/random/boot_id")?.trim() || null, bootTime = () => Math.round((Date.now() -
|
|
78162
|
+
}, bootId = () => readText5("/proc/sys/kernel/random/boot_id")?.trim() || null, bootTime = () => Math.round((Date.now() - os20.uptime() * 1000) / 1000) * 1000, BOOT_SLACK_MS = 120000, statFields = (pid) => {
|
|
78061
78163
|
const stat = readText5(`/proc/${pid}/stat`);
|
|
78062
78164
|
return stat ? stat.slice(stat.lastIndexOf(")") + 2).split(" ") : null;
|
|
78063
78165
|
}, processStart = (pid) => statFields(pid)?.[19] ?? null, pidAlive2 = (pid) => {
|
|
@@ -78106,8 +78208,8 @@ __export(exports_check, {
|
|
|
78106
78208
|
run: () => run12,
|
|
78107
78209
|
workspaceResources: () => workspaceResources
|
|
78108
78210
|
});
|
|
78109
|
-
import
|
|
78110
|
-
import
|
|
78211
|
+
import os21 from "node:os";
|
|
78212
|
+
import path53 from "node:path";
|
|
78111
78213
|
function parse6(argv) {
|
|
78112
78214
|
const split = argv.indexOf("--");
|
|
78113
78215
|
const head = split >= 0 ? argv.slice(0, split) : [...argv];
|
|
@@ -78309,7 +78411,7 @@ function hostToolWaitCapMs(env) {
|
|
|
78309
78411
|
}
|
|
78310
78412
|
async function workspaceResources(io) {
|
|
78311
78413
|
const env = io.env;
|
|
78312
|
-
const dir = env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ??
|
|
78414
|
+
const dir = env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path53.join(env.XDG_CONFIG_HOME || path53.join(env.HOME || os21.homedir(), ".config"), "workit");
|
|
78313
78415
|
try {
|
|
78314
78416
|
await Promise.resolve().then(() => init_workspaces());
|
|
78315
78417
|
const workspace = resolveWorkspaceFrom(io.cwd, dir, env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined);
|
|
@@ -78428,7 +78530,7 @@ async function run12(argv, io) {
|
|
|
78428
78530
|
if (options.shell && command.length !== 1)
|
|
78429
78531
|
return emit(io, fail2("invalid_input", '--shell takes the command as one string: workit check --shell -- "<cmd>"'));
|
|
78430
78532
|
}
|
|
78431
|
-
const relCwd = posix(
|
|
78533
|
+
const relCwd = posix(path53.relative(top, runCwd));
|
|
78432
78534
|
const configured = !options.shell && matchesNamedCheck(config, name, command, relCwd);
|
|
78433
78535
|
const shadowed = !configured && name !== null ? config.checks.find((item) => item.name === name) : undefined;
|
|
78434
78536
|
if (shadowed)
|
|
@@ -78490,7 +78592,7 @@ async function run12(argv, io) {
|
|
|
78490
78592
|
const modifiedWorktree = key.tree !== null && treeAfter !== key.tree;
|
|
78491
78593
|
const store = storeRoot(io.cwd);
|
|
78492
78594
|
const blob = store.ok ? storeLog(store.value.root, result.log) : null;
|
|
78493
|
-
const logPath = store.ok && blob ?
|
|
78595
|
+
const logPath = store.ok && blob ? path53.join(store.value.root, blob.ref) : null;
|
|
78494
78596
|
const tail = tailLines(result.log, TAIL_LINES);
|
|
78495
78597
|
const passed = result.exitCode === 0 && !result.timedOut;
|
|
78496
78598
|
const bounded = boundedArgv(command);
|
|
@@ -78605,7 +78707,7 @@ async function run12(argv, io) {
|
|
|
78605
78707
|
return recordError.code === "busy" ? 4 : recordError.code === "invalid_input" ? 2 : 5;
|
|
78606
78708
|
return 0;
|
|
78607
78709
|
}
|
|
78608
|
-
var USAGE6 = 'workit check <name> [--full] [--no-lease --reason "<why>"] | workit check [--name <n>] [--shell] [--heavy] [--full] [--wait <s>] [--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(
|
|
78710
|
+
var USAGE6 = 'workit check <name> [--full] [--no-lease --reason "<why>"] | workit check [--name <n>] [--shell] [--heavy] [--full] [--wait <s>] [--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(path53.sep).join("/") || ".", ENGINE_CODES2, FINGERPRINT_VARS, ANSI_COLOR, WARNING_LINE, NO_WARNINGS, HOST_TOOL_WAIT_CAP_MS = 1e5;
|
|
78609
78711
|
var init_check = __esm(() => {
|
|
78610
78712
|
init_check_config();
|
|
78611
78713
|
init_checks3();
|
|
@@ -78634,7 +78736,7 @@ __export(exports_lock, {
|
|
|
78634
78736
|
run: () => run13
|
|
78635
78737
|
});
|
|
78636
78738
|
import fs25 from "node:fs";
|
|
78637
|
-
import
|
|
78739
|
+
import path54 from "node:path";
|
|
78638
78740
|
async function settingsFor(io) {
|
|
78639
78741
|
const workspace = await workspaceResources(io);
|
|
78640
78742
|
const config = loadCheckConfig(io.cwd);
|
|
@@ -78716,7 +78818,7 @@ function readPatterns(file) {
|
|
|
78716
78818
|
return { patterns: [] };
|
|
78717
78819
|
}
|
|
78718
78820
|
function writePatterns(file, value) {
|
|
78719
|
-
fs25.mkdirSync(
|
|
78821
|
+
fs25.mkdirSync(path54.dirname(file), { recursive: true, mode: 448 });
|
|
78720
78822
|
const temp = `${file}.${process.pid}.tmp`;
|
|
78721
78823
|
fs25.writeFileSync(temp, `${JSON.stringify(value, null, 2)}
|
|
78722
78824
|
`, { mode: 384 });
|
|
@@ -78802,9 +78904,9 @@ var exports_models = {};
|
|
|
78802
78904
|
__export(exports_models, {
|
|
78803
78905
|
run: () => run14
|
|
78804
78906
|
});
|
|
78805
|
-
import { existsSync as
|
|
78806
|
-
import
|
|
78807
|
-
import
|
|
78907
|
+
import { existsSync as existsSync24, readdirSync as readdirSync13, readFileSync as readFileSync23, statSync as statSync9 } from "node:fs";
|
|
78908
|
+
import os22 from "node:os";
|
|
78909
|
+
import path55 from "node:path";
|
|
78808
78910
|
async function run14(argv, io) {
|
|
78809
78911
|
const [sub, ...args] = argv.filter((arg) => arg !== "--json");
|
|
78810
78912
|
if (sub !== "show")
|
|
@@ -78865,7 +78967,7 @@ var USAGE8 = "workit models show [--role <role>] [--tier <tier>] [--host <host>]
|
|
|
78865
78967
|
const found = new Set;
|
|
78866
78968
|
let text = "";
|
|
78867
78969
|
try {
|
|
78868
|
-
text =
|
|
78970
|
+
text = readFileSync23(file, "utf8");
|
|
78869
78971
|
} catch {
|
|
78870
78972
|
return found;
|
|
78871
78973
|
}
|
|
@@ -78879,26 +78981,26 @@ var USAGE8 = "workit models show [--role <role>] [--tier <tier>] [--host <host>]
|
|
|
78879
78981
|
} catch {}
|
|
78880
78982
|
return found;
|
|
78881
78983
|
}, matches3 = (ran, configured) => ran.toLowerCase().includes(configured.toLowerCase()), usageReport = (cwd, env, days) => {
|
|
78882
|
-
const projects =
|
|
78984
|
+
const projects = path55.join(env.CLAUDE_CONFIG_DIR || path55.join(env.HOME || os22.homedir(), ".claude"), "projects");
|
|
78883
78985
|
const since = Date.now() - days * 86400000;
|
|
78884
78986
|
const types = {};
|
|
78885
78987
|
let agents = 0;
|
|
78886
78988
|
const dirs = (dir) => {
|
|
78887
78989
|
try {
|
|
78888
|
-
return readdirSync13(dir).map((name) =>
|
|
78990
|
+
return readdirSync13(dir).map((name) => path55.join(dir, name));
|
|
78889
78991
|
} catch {
|
|
78890
78992
|
return [];
|
|
78891
78993
|
}
|
|
78892
78994
|
};
|
|
78893
78995
|
for (const project of dirs(projects))
|
|
78894
78996
|
for (const session of dirs(project))
|
|
78895
|
-
for (const meta of dirs(
|
|
78997
|
+
for (const meta of dirs(path55.join(session, "subagents")).filter((f) => f.endsWith(".meta.json"))) {
|
|
78896
78998
|
try {
|
|
78897
78999
|
if (statSync9(meta).mtimeMs < since)
|
|
78898
79000
|
continue;
|
|
78899
|
-
const agentType = JSON.parse(
|
|
79001
|
+
const agentType = JSON.parse(readFileSync23(meta, "utf8")).agentType;
|
|
78900
79002
|
const transcript = meta.replace(/\.meta\.json$/, ".jsonl");
|
|
78901
|
-
if (typeof agentType !== "string" || !
|
|
79003
|
+
if (typeof agentType !== "string" || !existsSync24(transcript))
|
|
78902
79004
|
continue;
|
|
78903
79005
|
const ran = modelsOf(transcript);
|
|
78904
79006
|
if (!ran.size)
|
|
@@ -79037,8 +79139,8 @@ var success2 = (data) => ({ ok: true, data }), failure3 = (code, error, unblock)
|
|
|
79037
79139
|
|
|
79038
79140
|
// packages/workit-core/src/git/ops.ts
|
|
79039
79141
|
import { spawnSync as spawnSync20 } from "node:child_process";
|
|
79040
|
-
import { existsSync as
|
|
79041
|
-
import
|
|
79142
|
+
import { existsSync as existsSync25, readFileSync as readFileSync24 } from "node:fs";
|
|
79143
|
+
import path56 from "node:path";
|
|
79042
79144
|
function operationInProgress(cwd) {
|
|
79043
79145
|
const markers = [
|
|
79044
79146
|
["rebase-merge", "rebase"],
|
|
@@ -79051,18 +79153,18 @@ function operationInProgress(cwd) {
|
|
|
79051
79153
|
if (!run.ok)
|
|
79052
79154
|
return null;
|
|
79053
79155
|
const found = run.stdout.split(`
|
|
79054
|
-
`).map((line) =>
|
|
79156
|
+
`).map((line) => path56.resolve(cwd, line.trim()));
|
|
79055
79157
|
const conflicted = () => git5(cwd, ["ls-files", "-u"]).stdout.trim() !== "";
|
|
79056
79158
|
for (const [index, [, operation]] of markers.entries()) {
|
|
79057
79159
|
const marker = found[index];
|
|
79058
|
-
if (!marker || !
|
|
79160
|
+
if (!marker || !existsSync25(marker))
|
|
79059
79161
|
continue;
|
|
79060
|
-
if (index === 1 &&
|
|
79162
|
+
if (index === 1 && existsSync25(path56.join(marker, "applying")))
|
|
79061
79163
|
return { operation: "am", commitAllowed: false, branch: null };
|
|
79062
|
-
if (index === 0 &&
|
|
79164
|
+
if (index === 0 && existsSync25(path56.join(marker, "amend")) && !conflicted()) {
|
|
79063
79165
|
let headName = "";
|
|
79064
79166
|
try {
|
|
79065
|
-
headName =
|
|
79167
|
+
headName = readFileSync24(path56.join(marker, "head-name"), "utf8").trim();
|
|
79066
79168
|
} catch {}
|
|
79067
79169
|
const branch = headName.startsWith("refs/heads/") ? headName.slice("refs/heads/".length) : null;
|
|
79068
79170
|
return { operation, commitAllowed: branch !== null, branch };
|
|
@@ -79390,7 +79492,7 @@ function gitCommit(cwd, input) {
|
|
|
79390
79492
|
if (paths.some((value) => value.startsWith("-") || !value.trim()))
|
|
79391
79493
|
return failure3("invalid_input", "paths must not be empty or start with -");
|
|
79392
79494
|
const tracked = new Set(nulList(git5(cwd, ["ls-files", "-z", "--", ...paths]).stdout));
|
|
79393
|
-
const addable = paths.filter((value) =>
|
|
79495
|
+
const addable = paths.filter((value) => existsSync25(path56.resolve(cwd, value)) || [...tracked].some((file) => file === value || file.startsWith(`${value}/`)));
|
|
79394
79496
|
if (addable.length) {
|
|
79395
79497
|
const added = git5(cwd, ["add", "-A", "--", ...addable]);
|
|
79396
79498
|
if (!added.ok)
|
|
@@ -79929,12 +80031,12 @@ var init_ops = __esm(() => {
|
|
|
79929
80031
|
|
|
79930
80032
|
// packages/workit-core/src/verdict-cover.ts
|
|
79931
80033
|
import fs26 from "node:fs";
|
|
79932
|
-
import
|
|
80034
|
+
import path57 from "node:path";
|
|
79933
80035
|
function chainsAbove(cwd, branch) {
|
|
79934
80036
|
const root = storeRoot(cwd);
|
|
79935
80037
|
if (!root.ok)
|
|
79936
80038
|
return [];
|
|
79937
|
-
const dir =
|
|
80039
|
+
const dir = path57.join(root.value.root, "stacks");
|
|
79938
80040
|
let names = [];
|
|
79939
80041
|
try {
|
|
79940
80042
|
names = fs26.readdirSync(dir).filter((name) => name.endsWith(".json"));
|
|
@@ -79945,7 +80047,7 @@ function chainsAbove(cwd, branch) {
|
|
|
79945
80047
|
for (const name of names.toSorted()) {
|
|
79946
80048
|
let parsed;
|
|
79947
80049
|
try {
|
|
79948
|
-
parsed = JSON.parse(fs26.readFileSync(
|
|
80050
|
+
parsed = JSON.parse(fs26.readFileSync(path57.join(dir, name), "utf8"));
|
|
79949
80051
|
} catch {
|
|
79950
80052
|
continue;
|
|
79951
80053
|
}
|
|
@@ -80040,10 +80142,10 @@ var init_pr_lane = __esm(() => {
|
|
|
80040
80142
|
|
|
80041
80143
|
// packages/workit-core/src/forge/reruns.ts
|
|
80042
80144
|
import fs27 from "node:fs";
|
|
80043
|
-
import
|
|
80145
|
+
import path58 from "node:path";
|
|
80044
80146
|
function rerunLogPath(cwd) {
|
|
80045
80147
|
const common = gitCommonDir(cwd);
|
|
80046
|
-
return common ?
|
|
80148
|
+
return common ? path58.join(common, "workit", "ci-reruns.jsonl") : null;
|
|
80047
80149
|
}
|
|
80048
80150
|
function rerunCounts(cwd, key) {
|
|
80049
80151
|
const counts = new Map;
|
|
@@ -80078,7 +80180,7 @@ function recordReruns(cwd, rows) {
|
|
|
80078
80180
|
if (!file)
|
|
80079
80181
|
return false;
|
|
80080
80182
|
try {
|
|
80081
|
-
fs27.mkdirSync(
|
|
80183
|
+
fs27.mkdirSync(path58.dirname(file), { recursive: true });
|
|
80082
80184
|
fs27.appendFileSync(file, rows.map((row) => `${JSON.stringify(row)}
|
|
80083
80185
|
`).join(""));
|
|
80084
80186
|
return true;
|
|
@@ -80091,7 +80193,7 @@ function withRerunLock(cwd, fn) {
|
|
|
80091
80193
|
if (!file)
|
|
80092
80194
|
return fn();
|
|
80093
80195
|
const lock = `${file.slice(0, -".jsonl".length)}.lock`;
|
|
80094
|
-
fs27.mkdirSync(
|
|
80196
|
+
fs27.mkdirSync(path58.dirname(lock), { recursive: true });
|
|
80095
80197
|
const until = Date.now() + LOCK_WAIT_MS2;
|
|
80096
80198
|
for (;; ) {
|
|
80097
80199
|
try {
|
|
@@ -80508,7 +80610,7 @@ function recordAccepted(cwd, resolved, status, accepted, options) {
|
|
|
80508
80610
|
return recordReruns(cwd, rows);
|
|
80509
80611
|
}
|
|
80510
80612
|
var MAX_LOG_TAILS = 5, GITLAB_MERGEABLE, GITHUB_MERGEABLE, NO_CHECKS_GRACE_MS = 90000;
|
|
80511
|
-
var
|
|
80613
|
+
var init_report2 = __esm(() => {
|
|
80512
80614
|
init_rev();
|
|
80513
80615
|
init_ledger();
|
|
80514
80616
|
init_reruns();
|
|
@@ -81057,7 +81159,7 @@ var init_pr_ops = __esm(() => {
|
|
|
81057
81159
|
init_ledger();
|
|
81058
81160
|
init_verdict_cover();
|
|
81059
81161
|
init_pr_lane();
|
|
81060
|
-
|
|
81162
|
+
init_report2();
|
|
81061
81163
|
VERIFY_DELAYS_MS = [1000, 2000, 4000];
|
|
81062
81164
|
AFTER_REVIEW = {
|
|
81063
81165
|
commit: "stop here; review comes when the user asks",
|
|
@@ -81070,9 +81172,9 @@ var init_pr_ops = __esm(() => {
|
|
|
81070
81172
|
|
|
81071
81173
|
// packages/workit-core/src/stack.ts
|
|
81072
81174
|
import { spawnSync as spawnSync22 } from "node:child_process";
|
|
81073
|
-
import { createHash as
|
|
81175
|
+
import { createHash as createHash18, randomBytes as randomBytes4 } from "node:crypto";
|
|
81074
81176
|
import fs28 from "node:fs";
|
|
81075
|
-
import
|
|
81177
|
+
import path59 from "node:path";
|
|
81076
81178
|
function worktreeOf(cwd, branch) {
|
|
81077
81179
|
const list = gitRun3(cwd, ["worktree", "list", "--porcelain"]);
|
|
81078
81180
|
if (!list.ok)
|
|
@@ -81121,7 +81223,7 @@ function gitRestack(cwd, input) {
|
|
|
81121
81223
|
error: "no store root"
|
|
81122
81224
|
};
|
|
81123
81225
|
fs28.mkdirSync(scratch, { recursive: true });
|
|
81124
|
-
dir =
|
|
81226
|
+
dir = path59.join(scratch, `${input.branch.replace(/[^A-Za-z0-9._-]+/gu, "_").slice(0, 40)}-${randomBytes4(4).toString("hex")}`);
|
|
81125
81227
|
const added = gitRun3(cwd, ["worktree", "add", "-q", dir, input.branch], GIT_TIMEOUTS.worktree);
|
|
81126
81228
|
if (!added.ok)
|
|
81127
81229
|
return {
|
|
@@ -81177,7 +81279,7 @@ function pruneScratch(cwd) {
|
|
|
81177
81279
|
if (!scratch || !fs28.existsSync(scratch))
|
|
81178
81280
|
return;
|
|
81179
81281
|
for (const name of fs28.readdirSync(scratch)) {
|
|
81180
|
-
const dir =
|
|
81282
|
+
const dir = path59.join(scratch, name);
|
|
81181
81283
|
if (!rebaseInProgress(dir) && !trackedDirt(dir))
|
|
81182
81284
|
gitRun3(cwd, ["worktree", "remove", "--force", dir]);
|
|
81183
81285
|
}
|
|
@@ -81187,7 +81289,7 @@ function stacksDir(cwd) {
|
|
|
81187
81289
|
const root = storeRoot(cwd);
|
|
81188
81290
|
if (!root.ok)
|
|
81189
81291
|
return stackFail(root.code, root.error, root.unblock);
|
|
81190
|
-
return { ok: true, data:
|
|
81292
|
+
return { ok: true, data: path59.join(root.value.root, "stacks") };
|
|
81191
81293
|
}
|
|
81192
81294
|
function parseStack(raw) {
|
|
81193
81295
|
if (!isRecord12(raw) || !Array.isArray(raw.branches))
|
|
@@ -81239,7 +81341,7 @@ function readStack(cwd, name) {
|
|
|
81239
81341
|
const dir = stacksDir(cwd);
|
|
81240
81342
|
if (!dir.ok)
|
|
81241
81343
|
return dir;
|
|
81242
|
-
const file =
|
|
81344
|
+
const file = path59.join(dir.data, fileFor(name));
|
|
81243
81345
|
let text;
|
|
81244
81346
|
try {
|
|
81245
81347
|
text = fs28.readFileSync(file, "utf8");
|
|
@@ -81260,7 +81362,7 @@ function writeStack(cwd, stack, now = new Date) {
|
|
|
81260
81362
|
const dir = stacksDir(cwd);
|
|
81261
81363
|
if (!dir.ok)
|
|
81262
81364
|
return dir;
|
|
81263
|
-
const file =
|
|
81365
|
+
const file = path59.join(dir.data, fileFor(stack.name));
|
|
81264
81366
|
const temp = `${file}.${process.pid}.tmp`;
|
|
81265
81367
|
try {
|
|
81266
81368
|
fs28.mkdirSync(dir.data, { recursive: true });
|
|
@@ -81288,7 +81390,7 @@ function listStacks(cwd) {
|
|
|
81288
81390
|
for (const name of names) {
|
|
81289
81391
|
let parsed = null;
|
|
81290
81392
|
try {
|
|
81291
|
-
parsed = parseStack(JSON.parse(fs28.readFileSync(
|
|
81393
|
+
parsed = parseStack(JSON.parse(fs28.readFileSync(path59.join(dir.data, name), "utf8")));
|
|
81292
81394
|
} catch {
|
|
81293
81395
|
parsed = null;
|
|
81294
81396
|
}
|
|
@@ -81350,7 +81452,7 @@ function takeLock(lock) {
|
|
|
81350
81452
|
host: localLockHost(),
|
|
81351
81453
|
nonce: randomBytes4(8).toString("hex")
|
|
81352
81454
|
};
|
|
81353
|
-
fs28.writeFileSync(
|
|
81455
|
+
fs28.writeFileSync(path59.join(lock, OWNER), JSON.stringify(owner));
|
|
81354
81456
|
return owner;
|
|
81355
81457
|
}
|
|
81356
81458
|
function reapLock(lock, observed) {
|
|
@@ -81387,7 +81489,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
|
|
|
81387
81489
|
return dir;
|
|
81388
81490
|
if (!validName(name))
|
|
81389
81491
|
return stackFail("invalid_input", "a stack name must be 1-200 printable characters");
|
|
81390
|
-
const lock =
|
|
81492
|
+
const lock = path59.join(dir.data, `${fileFor(name)}.lock`);
|
|
81391
81493
|
try {
|
|
81392
81494
|
fs28.mkdirSync(dir.data, { recursive: true });
|
|
81393
81495
|
} catch (error) {
|
|
@@ -81417,7 +81519,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
|
|
|
81417
81519
|
const touch = () => {
|
|
81418
81520
|
try {
|
|
81419
81521
|
const now = new Date;
|
|
81420
|
-
fs28.utimesSync(
|
|
81522
|
+
fs28.utimesSync(path59.join(lock, OWNER), now, now);
|
|
81421
81523
|
} catch {}
|
|
81422
81524
|
};
|
|
81423
81525
|
const beat = setInterval(touch, HEARTBEAT_MS);
|
|
@@ -82318,10 +82420,10 @@ var STACK_VERSION = 1, stackFail = (code, error, unblock, data) => ({
|
|
|
82318
82420
|
return !status.ok || status.stdout.trim() !== "";
|
|
82319
82421
|
}, scratchDir = (cwd) => {
|
|
82320
82422
|
const dir = stacksDir(cwd);
|
|
82321
|
-
return dir.ok ?
|
|
82423
|
+
return dir.ok ? path59.join(dir.data, "worktrees") : null;
|
|
82322
82424
|
}, firstLine = (run) => (`${run.stderr}
|
|
82323
82425
|
${run.stdout}`.split(`
|
|
82324
|
-
`).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()}-${
|
|
82426
|
+
`).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) => {
|
|
82325
82427
|
if (name.length === 0 || name.length > 200)
|
|
82326
82428
|
return false;
|
|
82327
82429
|
for (let index = 0;index < name.length; index += 1) {
|
|
@@ -82333,12 +82435,12 @@ ${run.stdout}`.split(`
|
|
|
82333
82435
|
}, 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) => {
|
|
82334
82436
|
let raw = null;
|
|
82335
82437
|
try {
|
|
82336
|
-
raw = fs28.readFileSync(
|
|
82438
|
+
raw = fs28.readFileSync(path59.join(lock, OWNER), "utf8");
|
|
82337
82439
|
} catch {
|
|
82338
82440
|
raw = null;
|
|
82339
82441
|
}
|
|
82340
82442
|
let age = null;
|
|
82341
|
-
for (const target of [
|
|
82443
|
+
for (const target of [path59.join(lock, OWNER), lock])
|
|
82342
82444
|
try {
|
|
82343
82445
|
age = Date.now() - fs28.statSync(target).mtimeMs;
|
|
82344
82446
|
break;
|
|
@@ -82362,7 +82464,7 @@ var init_stack = __esm(() => {
|
|
|
82362
82464
|
init_autonomy();
|
|
82363
82465
|
init_store_lock();
|
|
82364
82466
|
init_pr_ops();
|
|
82365
|
-
|
|
82467
|
+
init_report2();
|
|
82366
82468
|
init_ops();
|
|
82367
82469
|
init_rev();
|
|
82368
82470
|
init_ledger();
|
|
@@ -82379,9 +82481,9 @@ var init_stack = __esm(() => {
|
|
|
82379
82481
|
|
|
82380
82482
|
// packages/workit-core/src/fanout.ts
|
|
82381
82483
|
import { spawnSync as spawnSync23 } from "node:child_process";
|
|
82382
|
-
import { createHash as
|
|
82484
|
+
import { createHash as createHash19 } from "node:crypto";
|
|
82383
82485
|
import fs29 from "node:fs";
|
|
82384
|
-
import
|
|
82486
|
+
import path60 from "node:path";
|
|
82385
82487
|
function expandBraces2(pattern, limit = 64) {
|
|
82386
82488
|
for (let index = 0;index < pattern.length; index += 1) {
|
|
82387
82489
|
if (pattern[index] === "\\") {
|
|
@@ -82627,7 +82729,7 @@ function parsePlan(raw, defaults, name) {
|
|
|
82627
82729
|
id,
|
|
82628
82730
|
branch,
|
|
82629
82731
|
base: optional("base") ?? "",
|
|
82630
|
-
worktree:
|
|
82732
|
+
worktree: path60.resolve(defaults.root, optional("worktree") ?? path60.join(defaults.worktreeRoot, id)),
|
|
82631
82733
|
tier,
|
|
82632
82734
|
reason,
|
|
82633
82735
|
dependsOn: [...new Set(dependsOn ?? [])],
|
|
@@ -82756,12 +82858,12 @@ function regeneratedFiles(root, tracked) {
|
|
|
82756
82858
|
const found = new Map;
|
|
82757
82859
|
let scripts;
|
|
82758
82860
|
try {
|
|
82759
|
-
const manifest = JSON.parse(fs29.readFileSync(
|
|
82861
|
+
const manifest = JSON.parse(fs29.readFileSync(path60.join(root, "package.json"), "utf8"));
|
|
82760
82862
|
scripts = manifest.scripts ?? {};
|
|
82761
82863
|
} catch {
|
|
82762
82864
|
return found;
|
|
82763
82865
|
}
|
|
82764
|
-
const runner = fs29.existsSync(
|
|
82866
|
+
const runner = fs29.existsSync(path60.join(root, "bun.lock")) ? "bun run" : fs29.existsSync(path60.join(root, "pnpm-lock.yaml")) ? "pnpm run" : fs29.existsSync(path60.join(root, "yarn.lock")) ? "yarn run" : "npm run";
|
|
82765
82867
|
const outputs = tracked.filter((file) => !CODE.test(file));
|
|
82766
82868
|
for (const [name, command] of Object.entries(scripts)) {
|
|
82767
82869
|
if (!name.startsWith("write:") || typeof command !== "string")
|
|
@@ -82769,7 +82871,7 @@ function regeneratedFiles(root, tracked) {
|
|
|
82769
82871
|
for (const file of command.match(/[\w./-]+\.[cm]?[jt]s\b/gu) ?? []) {
|
|
82770
82872
|
let source;
|
|
82771
82873
|
try {
|
|
82772
|
-
source = fs29.readFileSync(
|
|
82874
|
+
source = fs29.readFileSync(path60.join(root, file), "utf8");
|
|
82773
82875
|
} catch {
|
|
82774
82876
|
continue;
|
|
82775
82877
|
}
|
|
@@ -82891,11 +82993,11 @@ function defaultTrunk(cwd) {
|
|
|
82891
82993
|
}
|
|
82892
82994
|
function mainCheckout(cwd) {
|
|
82893
82995
|
const common = gitCommonDir(cwd);
|
|
82894
|
-
return common &&
|
|
82996
|
+
return common && path60.basename(common) === ".git" ? path60.dirname(common) : path60.resolve(cwd);
|
|
82895
82997
|
}
|
|
82896
82998
|
function worktreeRoot(cwd) {
|
|
82897
82999
|
const main = mainCheckout(cwd);
|
|
82898
|
-
return
|
|
83000
|
+
return path60.join(path60.dirname(main), `${path60.basename(main)}-wt`);
|
|
82899
83001
|
}
|
|
82900
83002
|
function sliceHash(slice) {
|
|
82901
83003
|
const {
|
|
@@ -82909,13 +83011,13 @@ function sliceHash(slice) {
|
|
|
82909
83011
|
issues: _issues,
|
|
82910
83012
|
...definition
|
|
82911
83013
|
} = slice;
|
|
82912
|
-
return
|
|
83014
|
+
return createHash19("sha256").update(JSON.stringify(definition)).digest("hex").slice(0, 16);
|
|
82913
83015
|
}
|
|
82914
83016
|
function fanoutsDir(cwd) {
|
|
82915
83017
|
const root = storeRoot(cwd);
|
|
82916
83018
|
if (!root.ok)
|
|
82917
83019
|
return fanoutFail(root.code, root.error, root.unblock);
|
|
82918
|
-
return { ok: true, data:
|
|
83020
|
+
return { ok: true, data: path60.join(root.value.root, "fanouts") };
|
|
82919
83021
|
}
|
|
82920
83022
|
function parseStored(raw) {
|
|
82921
83023
|
if (!isRecord13(raw) || typeof raw.name !== "string" || typeof raw.trunk !== "string")
|
|
@@ -82983,7 +83085,7 @@ function readFanout(cwd, name) {
|
|
|
82983
83085
|
const dir = fanoutsDir(cwd);
|
|
82984
83086
|
if (!dir.ok)
|
|
82985
83087
|
return dir;
|
|
82986
|
-
const file =
|
|
83088
|
+
const file = path60.join(dir.data, stackFileName(name));
|
|
82987
83089
|
let parsed = null;
|
|
82988
83090
|
try {
|
|
82989
83091
|
parsed = parseStored(JSON.parse(fs29.readFileSync(file, "utf8")));
|
|
@@ -83008,7 +83110,7 @@ function listFanouts(cwd) {
|
|
|
83008
83110
|
for (const entry of names) {
|
|
83009
83111
|
let parsed = null;
|
|
83010
83112
|
try {
|
|
83011
|
-
parsed = parseStored(JSON.parse(fs29.readFileSync(
|
|
83113
|
+
parsed = parseStored(JSON.parse(fs29.readFileSync(path60.join(dir.data, entry), "utf8")));
|
|
83012
83114
|
} catch {
|
|
83013
83115
|
parsed = null;
|
|
83014
83116
|
}
|
|
@@ -83047,7 +83149,7 @@ function writeFanout(cwd, plan) {
|
|
|
83047
83149
|
const dir = fanoutsDir(cwd);
|
|
83048
83150
|
if (!dir.ok)
|
|
83049
83151
|
return dir;
|
|
83050
|
-
const file =
|
|
83152
|
+
const file = path60.join(dir.data, stackFileName(plan.name));
|
|
83051
83153
|
const temp = `${file}.${process.pid}.tmp`;
|
|
83052
83154
|
try {
|
|
83053
83155
|
fs29.mkdirSync(dir.data, { recursive: true });
|
|
@@ -83258,13 +83360,13 @@ var init_fanout = __esm(() => {
|
|
|
83258
83360
|
// packages/workit-core/src/forge/exec.ts
|
|
83259
83361
|
import { spawnSync as spawnSync24 } from "node:child_process";
|
|
83260
83362
|
import fs30 from "node:fs";
|
|
83261
|
-
import
|
|
83363
|
+
import path61 from "node:path";
|
|
83262
83364
|
function findExecutable(bin, env) {
|
|
83263
|
-
const dirs = (env.PATH ?? env.Path ?? "").split(
|
|
83365
|
+
const dirs = (env.PATH ?? env.Path ?? "").split(path61.delimiter).filter(Boolean);
|
|
83264
83366
|
const exts = process.platform === "win32" ? [".exe"] : [""];
|
|
83265
83367
|
for (const dir of dirs)
|
|
83266
83368
|
for (const ext of exts) {
|
|
83267
|
-
const candidate =
|
|
83369
|
+
const candidate = path61.join(dir, `${bin}${ext}`);
|
|
83268
83370
|
try {
|
|
83269
83371
|
const stat = fs30.statSync(candidate);
|
|
83270
83372
|
if (stat.isFile())
|
|
@@ -84807,7 +84909,7 @@ var init_pr_edit = __esm(() => {
|
|
|
84807
84909
|
init_rev();
|
|
84808
84910
|
init_stack();
|
|
84809
84911
|
init_pr_ops();
|
|
84810
|
-
|
|
84912
|
+
init_report2();
|
|
84811
84913
|
});
|
|
84812
84914
|
|
|
84813
84915
|
// packages/workit-core/src/core/live-session.ts
|
|
@@ -84827,7 +84929,7 @@ var init_live_session = __esm(() => {
|
|
|
84827
84929
|
});
|
|
84828
84930
|
|
|
84829
84931
|
// packages/workit-core/src/hooks/write-gate.ts
|
|
84830
|
-
import
|
|
84932
|
+
import path62 from "node:path";
|
|
84831
84933
|
var CASE_INSENSITIVE, PREFIXES2, SCRIPT_SHELLS, cache3, MUTATING_GIT, DRY_N, MUTATING_WORKIT_GIT, CD2, PUSHD2, POPD2, UNKNOWN_DIR;
|
|
84832
84934
|
var init_write_gate = __esm(() => {
|
|
84833
84935
|
init_task_store();
|
|
@@ -84867,7 +84969,7 @@ var init_write_gate = __esm(() => {
|
|
|
84867
84969
|
CD2 = new Set(["cd", "chdir", "set-location", "sl"]);
|
|
84868
84970
|
PUSHD2 = new Set(["pushd", "push-location"]);
|
|
84869
84971
|
POPD2 = new Set(["popd", "pop-location"]);
|
|
84870
|
-
UNKNOWN_DIR =
|
|
84972
|
+
UNKNOWN_DIR = path62.resolve(path62.parse(process.cwd()).root, ".workit-unknown-dir");
|
|
84871
84973
|
});
|
|
84872
84974
|
|
|
84873
84975
|
// packages/workit-core/src/hooks/worktree-confine.ts
|
|
@@ -84892,20 +84994,20 @@ var init_worktree_confine = __esm(() => {
|
|
|
84892
84994
|
|
|
84893
84995
|
// packages/workit-core/src/worktree-deps.ts
|
|
84894
84996
|
import fs31 from "node:fs";
|
|
84895
|
-
import
|
|
84997
|
+
import path63 from "node:path";
|
|
84896
84998
|
function moduleDirs(main) {
|
|
84897
84999
|
const out = [];
|
|
84898
85000
|
const walk = (relative, depth) => {
|
|
84899
85001
|
let entries;
|
|
84900
85002
|
try {
|
|
84901
|
-
entries = fs31.readdirSync(
|
|
85003
|
+
entries = fs31.readdirSync(path63.join(main, relative), { withFileTypes: true });
|
|
84902
85004
|
} catch {
|
|
84903
85005
|
return;
|
|
84904
85006
|
}
|
|
84905
85007
|
for (const entry of entries) {
|
|
84906
85008
|
if (!entry.isDirectory())
|
|
84907
85009
|
continue;
|
|
84908
|
-
const child =
|
|
85010
|
+
const child = path63.join(relative, entry.name);
|
|
84909
85011
|
if (entry.name === MODULES)
|
|
84910
85012
|
out.push(child);
|
|
84911
85013
|
else if (depth < MAX_DEPTH2 && !entry.name.startsWith("."))
|
|
@@ -84919,8 +85021,8 @@ function linkEntry(main, worktree, source, target) {
|
|
|
84919
85021
|
const stat = fs31.lstatSync(source);
|
|
84920
85022
|
if (stat.isSymbolicLink()) {
|
|
84921
85023
|
const link = fs31.readlinkSync(source);
|
|
84922
|
-
const outside =
|
|
84923
|
-
const to = outside ?
|
|
85024
|
+
const outside = path63.isAbsolute(link) && within(link, main) && !path63.relative(main, link).split(path63.sep).includes(MODULES);
|
|
85025
|
+
const to = outside ? path63.join(worktree, path63.relative(main, link)) : link;
|
|
84924
85026
|
fs31.symlinkSync(to, target, process.platform === "win32" ? "junction" : undefined);
|
|
84925
85027
|
return;
|
|
84926
85028
|
}
|
|
@@ -84930,8 +85032,8 @@ function mirror(main, worktree, source, target, top) {
|
|
|
84930
85032
|
fs31.mkdirSync(target);
|
|
84931
85033
|
let count = 0;
|
|
84932
85034
|
for (const entry of fs31.readdirSync(source, { withFileTypes: true })) {
|
|
84933
|
-
const from =
|
|
84934
|
-
const to =
|
|
85035
|
+
const from = path63.join(source, entry.name);
|
|
85036
|
+
const to = path63.join(target, entry.name);
|
|
84935
85037
|
if (top && entry.isDirectory() && (entry.name.startsWith("@") || entry.name === ".bin"))
|
|
84936
85038
|
count += mirror(main, worktree, from, to, false);
|
|
84937
85039
|
else {
|
|
@@ -84947,16 +85049,16 @@ function linkWorktreeDependencies(main, worktree) {
|
|
|
84947
85049
|
const dirs = [];
|
|
84948
85050
|
let entries = 0;
|
|
84949
85051
|
for (const relative of moduleDirs(main)) {
|
|
84950
|
-
const target =
|
|
84951
|
-
if (!fs31.existsSync(
|
|
85052
|
+
const target = path63.join(worktree, relative);
|
|
85053
|
+
if (!fs31.existsSync(path63.dirname(target)) || fs31.existsSync(target))
|
|
84952
85054
|
continue;
|
|
84953
|
-
if (!gitRun4(worktree, ["check-ignore", "-q", `${relative.split(
|
|
84954
|
-
notes.push(`${relative.split(
|
|
85055
|
+
if (!gitRun4(worktree, ["check-ignore", "-q", `${relative.split(path63.sep).join("/")}/`]).ok) {
|
|
85056
|
+
notes.push(`${relative.split(path63.sep).join("/")} is not ignored by git, so it was not linked from ${main}; install dependencies in the worktree yourself`);
|
|
84955
85057
|
continue;
|
|
84956
85058
|
}
|
|
84957
85059
|
try {
|
|
84958
|
-
entries += mirror(main, worktree,
|
|
84959
|
-
dirs.push(relative.split(
|
|
85060
|
+
entries += mirror(main, worktree, path63.join(main, relative), target, true);
|
|
85061
|
+
dirs.push(relative.split(path63.sep).join("/"));
|
|
84960
85062
|
} catch (error) {
|
|
84961
85063
|
fs31.rmSync(target, { recursive: true, force: true });
|
|
84962
85064
|
notes.push(`could not link ${relative} from ${main} (${error.message}); install dependencies in the worktree yourself`);
|
|
@@ -84969,8 +85071,8 @@ function linkWorktreeDependencies(main, worktree) {
|
|
|
84969
85071
|
return { linked: { from: main, dirs, entries, ms }, notes };
|
|
84970
85072
|
}
|
|
84971
85073
|
var MODULES = "node_modules", MAX_DEPTH2 = 2, within = (child, parent) => {
|
|
84972
|
-
const relative =
|
|
84973
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
85074
|
+
const relative = path63.relative(parent, child);
|
|
85075
|
+
return relative === "" || !relative.startsWith("..") && !path63.isAbsolute(relative);
|
|
84974
85076
|
};
|
|
84975
85077
|
var init_worktree_deps = __esm(() => {
|
|
84976
85078
|
init_fanout();
|
|
@@ -84979,7 +85081,7 @@ var init_worktree_deps = __esm(() => {
|
|
|
84979
85081
|
// packages/workit-core/src/fanout-worktree.ts
|
|
84980
85082
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
84981
85083
|
import fs32 from "node:fs";
|
|
84982
|
-
import
|
|
85084
|
+
import path64 from "node:path";
|
|
84983
85085
|
function rowSample(lines) {
|
|
84984
85086
|
const out = [];
|
|
84985
85087
|
let bytes = 0;
|
|
@@ -85039,7 +85141,7 @@ function adminDir(worktree) {
|
|
|
85039
85141
|
const file = dir.stdout.trim();
|
|
85040
85142
|
let token = null;
|
|
85041
85143
|
try {
|
|
85042
|
-
token = fs32.readFileSync(
|
|
85144
|
+
token = fs32.readFileSync(path64.join(file, FANOUT_TOKEN_FILE), "utf8").trim() || null;
|
|
85043
85145
|
} catch {
|
|
85044
85146
|
token = null;
|
|
85045
85147
|
}
|
|
@@ -85047,7 +85149,7 @@ function adminDir(worktree) {
|
|
|
85047
85149
|
const stat = worktreeDeps.stat(file);
|
|
85048
85150
|
return {
|
|
85049
85151
|
path: file,
|
|
85050
|
-
id:
|
|
85152
|
+
id: path64.basename(file),
|
|
85051
85153
|
ino: stat.ino.toString(),
|
|
85052
85154
|
token,
|
|
85053
85155
|
birthMs: stat.birthtimeNs > 0n ? Number(stat.birthtimeMs) : null,
|
|
@@ -85063,7 +85165,7 @@ function markAdminDir(worktree) {
|
|
|
85063
85165
|
return null;
|
|
85064
85166
|
const token = randomBytes5(16).toString("hex");
|
|
85065
85167
|
try {
|
|
85066
|
-
fs32.writeFileSync(
|
|
85168
|
+
fs32.writeFileSync(path64.join(admin.path, FANOUT_TOKEN_FILE), `${token}
|
|
85067
85169
|
`);
|
|
85068
85170
|
} catch {
|
|
85069
85171
|
return null;
|
|
@@ -85078,7 +85180,7 @@ function excludeScratch(cwd) {
|
|
|
85078
85180
|
const common = gitCommonDir(cwd);
|
|
85079
85181
|
if (!common)
|
|
85080
85182
|
return;
|
|
85081
|
-
const file =
|
|
85183
|
+
const file = path64.join(common, "info", "exclude");
|
|
85082
85184
|
let text = "";
|
|
85083
85185
|
try {
|
|
85084
85186
|
text = fs32.readFileSync(file, "utf8");
|
|
@@ -85087,7 +85189,7 @@ function excludeScratch(cwd) {
|
|
|
85087
85189
|
}
|
|
85088
85190
|
if (text.split(/\r?\n/u).includes(EXCLUDE_LINE))
|
|
85089
85191
|
return;
|
|
85090
|
-
fs32.mkdirSync(
|
|
85192
|
+
fs32.mkdirSync(path64.dirname(file), { recursive: true });
|
|
85091
85193
|
fs32.appendFileSync(file, `${text && !text.endsWith(`
|
|
85092
85194
|
`) ? `
|
|
85093
85195
|
` : ""}# workit fanout: per-worker scratch dirs
|
|
@@ -85096,13 +85198,13 @@ ${EXCLUDE_LINE}
|
|
|
85096
85198
|
}
|
|
85097
85199
|
function worktreeDependencies(main, worktree) {
|
|
85098
85200
|
for (const [name, install] of LOCKFILES2) {
|
|
85099
|
-
const ours = readBytes(
|
|
85100
|
-
const theirs = readBytes(
|
|
85201
|
+
const ours = readBytes(path64.join(main, name));
|
|
85202
|
+
const theirs = readBytes(path64.join(worktree, name));
|
|
85101
85203
|
if (ours === null && theirs === null)
|
|
85102
85204
|
continue;
|
|
85103
85205
|
if (ours !== null && theirs !== null && ours.equals(theirs))
|
|
85104
85206
|
continue;
|
|
85105
|
-
if (fs32.existsSync(
|
|
85207
|
+
if (fs32.existsSync(path64.join(worktree, "node_modules")))
|
|
85106
85208
|
break;
|
|
85107
85209
|
const command = install(worktree);
|
|
85108
85210
|
return {
|
|
@@ -85116,7 +85218,7 @@ function worktreeDependencies(main, worktree) {
|
|
|
85116
85218
|
return { ...linkWorktreeDependencies(main, worktree), install: null };
|
|
85117
85219
|
}
|
|
85118
85220
|
function ensureScratch(worktree) {
|
|
85119
|
-
const scratch =
|
|
85221
|
+
const scratch = path64.join(worktree, SCRATCH_DIR);
|
|
85120
85222
|
fs32.mkdirSync(scratch, { recursive: true });
|
|
85121
85223
|
return scratch;
|
|
85122
85224
|
}
|
|
@@ -85355,7 +85457,7 @@ function unpushedCount(cwd, branch) {
|
|
|
85355
85457
|
return count.ok ? Number(count.stdout.trim()) : null;
|
|
85356
85458
|
}
|
|
85357
85459
|
function removeScratch(worktree) {
|
|
85358
|
-
const scratch =
|
|
85460
|
+
const scratch = path64.join(worktree, SCRATCH_DIR);
|
|
85359
85461
|
let stat;
|
|
85360
85462
|
try {
|
|
85361
85463
|
stat = fs32.lstatSync(scratch);
|
|
@@ -85371,16 +85473,16 @@ var SLOW, SCRATCH_DIR = ".workit-scratch", EXCLUDE_LINE, DIRTY_ROW_BYTES = 2000,
|
|
|
85371
85473
|
try {
|
|
85372
85474
|
return fs32.realpathSync.native(target);
|
|
85373
85475
|
} catch {
|
|
85374
|
-
return
|
|
85476
|
+
return path64.resolve(target);
|
|
85375
85477
|
}
|
|
85376
85478
|
}, samePath = (a, b) => {
|
|
85377
85479
|
const left = canonical2(a);
|
|
85378
85480
|
const right = canonical2(b);
|
|
85379
85481
|
return process.platform === "win32" || process.platform === "darwin" ? left.toLowerCase() === right.toLowerCase() : left === right;
|
|
85380
85482
|
}, inside3 = (child, parent) => {
|
|
85381
|
-
const relative =
|
|
85382
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
85383
|
-
}, slicePath = (cwd, slice) =>
|
|
85483
|
+
const relative = path64.relative(canonical2(parent), canonical2(child));
|
|
85484
|
+
return relative === "" || !relative.startsWith("..") && !path64.isAbsolute(relative);
|
|
85485
|
+
}, slicePath = (cwd, slice) => path64.isAbsolute(slice.worktree) ? slice.worktree : path64.resolve(mainCheckout(cwd), slice.worktree), CLOCK_SLACK_MS = 2000, worktreeDeps, LOCKFILES2, readBytes = (file) => {
|
|
85384
85486
|
try {
|
|
85385
85487
|
return fs32.readFileSync(file);
|
|
85386
85488
|
} catch {
|
|
@@ -85411,7 +85513,7 @@ var init_fanout_worktree = __esm(() => {
|
|
|
85411
85513
|
|
|
85412
85514
|
// packages/workit-core/src/forge/merge-cleanup.ts
|
|
85413
85515
|
import fs33 from "node:fs";
|
|
85414
|
-
import
|
|
85516
|
+
import path65 from "node:path";
|
|
85415
85517
|
function cleanupMergedBranch(cwd, branch, mergedHead) {
|
|
85416
85518
|
const out = { branchDeleted: false, worktreeRemoved: null, notes: [] };
|
|
85417
85519
|
if (!branch || branch.startsWith("-"))
|
|
@@ -85471,13 +85573,13 @@ var SLOW2, isFanoutWorktree = (worktree) => {
|
|
|
85471
85573
|
if (!dir.ok)
|
|
85472
85574
|
return false;
|
|
85473
85575
|
try {
|
|
85474
|
-
return fs33.readFileSync(
|
|
85576
|
+
return fs33.readFileSync(path65.join(dir.stdout.trim(), FANOUT_TOKEN_FILE), "utf8").trim() !== "";
|
|
85475
85577
|
} catch {
|
|
85476
85578
|
return false;
|
|
85477
85579
|
}
|
|
85478
85580
|
}, inside4 = (child, parent) => {
|
|
85479
|
-
const relative =
|
|
85480
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
85581
|
+
const relative = path65.relative(fs33.realpathSync.native(parent), fs33.realpathSync.native(child));
|
|
85582
|
+
return relative === "" || !relative.startsWith("..") && !path65.isAbsolute(relative);
|
|
85481
85583
|
};
|
|
85482
85584
|
var init_merge_cleanup = __esm(() => {
|
|
85483
85585
|
init_fanout();
|
|
@@ -85758,7 +85860,7 @@ var init_duration = __esm(() => {
|
|
|
85758
85860
|
});
|
|
85759
85861
|
|
|
85760
85862
|
// packages/workit-cli/src/verbs/forge-common.ts
|
|
85761
|
-
import { readFileSync as
|
|
85863
|
+
import { readFileSync as readFileSync25 } from "node:fs";
|
|
85762
85864
|
function parseFlags(argv, spec) {
|
|
85763
85865
|
const parsed = { values: {}, booleans: new Set, lists: {}, positionals: [] };
|
|
85764
85866
|
for (let index = 0;index < argv.length; index += 1) {
|
|
@@ -85913,7 +86015,7 @@ var init_forge_common = __esm(() => {
|
|
|
85913
86015
|
forgeDeps = {
|
|
85914
86016
|
runner: undefined,
|
|
85915
86017
|
npm: undefined,
|
|
85916
|
-
readStdin: () =>
|
|
86018
|
+
readStdin: () => readFileSync25(0, "utf8"),
|
|
85917
86019
|
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
85918
86020
|
now: () => Date.now()
|
|
85919
86021
|
};
|
|
@@ -85924,12 +86026,12 @@ var exports_pr = {};
|
|
|
85924
86026
|
__export(exports_pr, {
|
|
85925
86027
|
run: () => run15
|
|
85926
86028
|
});
|
|
85927
|
-
import { readFileSync as
|
|
85928
|
-
import
|
|
86029
|
+
import { readFileSync as readFileSync26 } from "node:fs";
|
|
86030
|
+
import path66 from "node:path";
|
|
85929
86031
|
function readBodyFile(io, file) {
|
|
85930
86032
|
try {
|
|
85931
86033
|
return {
|
|
85932
|
-
body: file === "-" ? forgeDeps.readStdin() :
|
|
86034
|
+
body: file === "-" ? forgeDeps.readStdin() : readFileSync26(path66.resolve(io.cwd, file), "utf8")
|
|
85933
86035
|
};
|
|
85934
86036
|
} catch {
|
|
85935
86037
|
return `cannot read --body-file ${file}`;
|
|
@@ -86440,7 +86542,7 @@ var init_pr = __esm(() => {
|
|
|
86440
86542
|
init_issue_link();
|
|
86441
86543
|
init_pr_edit();
|
|
86442
86544
|
init_pr_ops();
|
|
86443
|
-
|
|
86545
|
+
init_report2();
|
|
86444
86546
|
init_rev();
|
|
86445
86547
|
init_workspaces();
|
|
86446
86548
|
init_merge_cleanup();
|
|
@@ -86694,7 +86796,7 @@ async function run16(argv, io) {
|
|
|
86694
86796
|
}
|
|
86695
86797
|
var WAIT_USAGE = "workit ci wait [--pr <n> | --branch <b>] [--head <sha>] [--timeout 20m] [--interval 30s] [--json]", RERUN_USAGE = "workit ci rerun [--pr <n> | --branch <b>] [--check <name>… | --failed] --reason flake|infra [--force] [--json]", LOGS_USAGE = "workit ci logs --failed [--pr <n> | --branch <b>] [--json]", LOG_LINES = 60, ONE_POLL_MS = 20000, MAX_POLL_ERRORS = 3, seconds = (ms) => `${Math.round(ms / 1000)}s`;
|
|
86696
86798
|
var init_ci = __esm(() => {
|
|
86697
|
-
|
|
86799
|
+
init_report2();
|
|
86698
86800
|
init_ledger();
|
|
86699
86801
|
init_autonomy();
|
|
86700
86802
|
init_output();
|
|
@@ -86733,8 +86835,8 @@ var exports_git = {};
|
|
|
86733
86835
|
__export(exports_git, {
|
|
86734
86836
|
run: () => run17
|
|
86735
86837
|
});
|
|
86736
|
-
import { readFileSync as
|
|
86737
|
-
import
|
|
86838
|
+
import { readFileSync as readFileSync27 } from "node:fs";
|
|
86839
|
+
import path67 from "node:path";
|
|
86738
86840
|
function kindHint(cwd, kind) {
|
|
86739
86841
|
let kinds = [...BRANCH_KINDS];
|
|
86740
86842
|
try {
|
|
@@ -86838,7 +86940,7 @@ function commitMessage(parsed, io) {
|
|
|
86838
86940
|
|
|
86839
86941
|
`);
|
|
86840
86942
|
try {
|
|
86841
|
-
return file === "-" ?
|
|
86943
|
+
return file === "-" ? readFileSync27(0, "utf8") : readFileSync27(path67.resolve(io.cwd, file), "utf8");
|
|
86842
86944
|
} catch (error) {
|
|
86843
86945
|
return {
|
|
86844
86946
|
error: `cannot read -F ${file}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -87252,7 +87354,7 @@ var init_verify = __esm(() => {
|
|
|
87252
87354
|
init_exec();
|
|
87253
87355
|
init_rev();
|
|
87254
87356
|
init_ledger();
|
|
87255
|
-
|
|
87357
|
+
init_report2();
|
|
87256
87358
|
init_redact();
|
|
87257
87359
|
NPM_NAME = /^(?:@[A-Za-z0-9~][A-Za-z0-9-._~]*\/)?[A-Za-z0-9~][A-Za-z0-9-._~]*$/u;
|
|
87258
87360
|
SEMVER2 = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/u;
|
|
@@ -88271,15 +88373,15 @@ var init_stack2 = __esm(() => {
|
|
|
88271
88373
|
});
|
|
88272
88374
|
|
|
88273
88375
|
// packages/workit-core/src/fanout-brief.ts
|
|
88274
|
-
import { createHash as
|
|
88376
|
+
import { createHash as createHash20 } from "node:crypto";
|
|
88275
88377
|
import fs35 from "node:fs";
|
|
88276
|
-
import
|
|
88378
|
+
import path68 from "node:path";
|
|
88277
88379
|
function workerSession(lead, slice, attempt) {
|
|
88278
88380
|
const tail = attempt === null ? "" : `+try${attempt}`;
|
|
88279
88381
|
const full = `${lead}-w-${slice}${tail}`;
|
|
88280
88382
|
if (full.length <= SESSION_MAX)
|
|
88281
88383
|
return full;
|
|
88282
|
-
const digest =
|
|
88384
|
+
const digest = createHash20("sha256").update(slice).digest("hex").slice(0, 12);
|
|
88283
88385
|
return `${lead.slice(0, SESSION_MAX - 3 - digest.length - tail.length)}-w-${digest}${tail}`;
|
|
88284
88386
|
}
|
|
88285
88387
|
function renderBrief(cwd, plan, input) {
|
|
@@ -88355,7 +88457,7 @@ function renderBrief(cwd, plan, input) {
|
|
|
88355
88457
|
"STANDING:",
|
|
88356
88458
|
...standing.length ? standing.map((order) => ` - ${order.what}`) : [" - none recorded beyond this brief"],
|
|
88357
88459
|
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)`,
|
|
88358
|
-
...exists && typeof made?.install === "string" && !fs35.existsSync(
|
|
88460
|
+
...exists && typeof made?.install === "string" && !fs35.existsSync(path68.join(planned, "node_modules")) ? [`INSTALL: \`${made.install}\` first: the main checkout's node_modules was not linked here`] : [],
|
|
88359
88461
|
...identityLines(identity, minted),
|
|
88360
88462
|
...rules(mode, branch, slice.base, exists ? planned : null)
|
|
88361
88463
|
];
|
|
@@ -89085,7 +89187,7 @@ var DEFAULT_STUCK_MS, isoOf = (seconds) => {
|
|
|
89085
89187
|
}, newest = (...values) => values.filter((value) => Boolean(value) && !Number.isNaN(Date.parse(value ?? ""))).reduce((best, value) => best === null || Date.parse(value) > Date.parse(best) ? value : best, null);
|
|
89086
89188
|
var init_fanout_status = __esm(() => {
|
|
89087
89189
|
init_duration();
|
|
89088
|
-
|
|
89190
|
+
init_report2();
|
|
89089
89191
|
init_role_models();
|
|
89090
89192
|
init_ledger();
|
|
89091
89193
|
init_fanout_check();
|
|
@@ -89100,7 +89202,7 @@ __export(exports_fanout, {
|
|
|
89100
89202
|
run: () => run21
|
|
89101
89203
|
});
|
|
89102
89204
|
import fs36 from "node:fs";
|
|
89103
|
-
import
|
|
89205
|
+
import path69 from "node:path";
|
|
89104
89206
|
function forgeFor(io, offline) {
|
|
89105
89207
|
if (offline)
|
|
89106
89208
|
return { forge: null, error: "--offline" };
|
|
@@ -89161,7 +89263,7 @@ function plan2(argv, io) {
|
|
|
89161
89263
|
return usage4(io, "pass --trunk or --track, not both (--track picks the trunk)", PLAN_USAGE2);
|
|
89162
89264
|
if (flags.positionals.length !== 1)
|
|
89163
89265
|
return usage4(io, flags.positionals.length ? `unexpected argument ${flags.positionals[1]}` : "missing <plan.json>", PLAN_USAGE2);
|
|
89164
|
-
const file =
|
|
89266
|
+
const file = path69.resolve(io.cwd, flags.positionals[0]);
|
|
89165
89267
|
let raw;
|
|
89166
89268
|
try {
|
|
89167
89269
|
raw = JSON.parse(fs36.readFileSync(file, "utf8"));
|
|
@@ -104704,7 +104806,7 @@ var init_ast = __esm(() => {
|
|
|
104704
104806
|
|
|
104705
104807
|
// packages/workit-cli/src/test-audit/rules.ts
|
|
104706
104808
|
import { builtinModules } from "node:module";
|
|
104707
|
-
import
|
|
104809
|
+
import path70 from "node:path";
|
|
104708
104810
|
function testCallee(call) {
|
|
104709
104811
|
let callee = call.callee;
|
|
104710
104812
|
if (callee.type === "CallExpression")
|
|
@@ -105197,12 +105299,12 @@ function checkConstantsOnly(ctx, emit) {
|
|
|
105197
105299
|
}
|
|
105198
105300
|
function checkOverMocking(ctx, emit) {
|
|
105199
105301
|
const { program } = ctx.parsed;
|
|
105200
|
-
const unit =
|
|
105302
|
+
const unit = path70.basename(ctx.file).replace(/\.(?:[cm]?[jt]sx?)$/, "").replace(/\.(?:test|spec)$/, "");
|
|
105201
105303
|
const mocked = find2(program, (node) => node.type === "CallExpression" && MODULE_MOCK.test(calleeName(node.callee) ?? "") && node.arguments[0]?.type === "StringLiteral");
|
|
105202
105304
|
const internal = mocked.filter((call) => /^(?:\.|@\/|~\/)/.test(call.arguments[0].value));
|
|
105203
105305
|
for (const call of mocked) {
|
|
105204
105306
|
const spec = call.arguments[0].value;
|
|
105205
|
-
const base =
|
|
105307
|
+
const base = path70.basename(spec.replace(/\/index(?:\.[cm]?[jt]sx?)?$/, "")).replace(/\.(?:[cm]?[jt]sx?)$/, "");
|
|
105206
105308
|
if (base === unit)
|
|
105207
105309
|
emit({
|
|
105208
105310
|
rule: "over-mocking",
|
|
@@ -105591,8 +105693,8 @@ var init_rules = __esm(() => {
|
|
|
105591
105693
|
|
|
105592
105694
|
// packages/workit-cli/src/test-audit/audit.ts
|
|
105593
105695
|
import { spawnSync as spawnSync29 } from "node:child_process";
|
|
105594
|
-
import { existsSync as
|
|
105595
|
-
import
|
|
105696
|
+
import { existsSync as existsSync26, readdirSync as readdirSync14, readFileSync as readFileSync28, statSync as statSync10 } from "node:fs";
|
|
105697
|
+
import path71 from "node:path";
|
|
105596
105698
|
function git7(cwd, args) {
|
|
105597
105699
|
const run = spawnSync29("git", ["-c", "core.quotepath=off", ...args], {
|
|
105598
105700
|
cwd,
|
|
@@ -105605,7 +105707,7 @@ function walkTests(dir, out) {
|
|
|
105605
105707
|
for (const entry of readdirSync14(dir, { withFileTypes: true })) {
|
|
105606
105708
|
if (entry.name.startsWith(".") && entry.name !== "." && entry.isDirectory())
|
|
105607
105709
|
continue;
|
|
105608
|
-
const full =
|
|
105710
|
+
const full = path71.join(dir, entry.name);
|
|
105609
105711
|
if (entry.isDirectory()) {
|
|
105610
105712
|
if (!SKIP_DIRS.has(entry.name))
|
|
105611
105713
|
walkTests(full, out);
|
|
@@ -105617,8 +105719,8 @@ function expandPaths(cwd, inputs) {
|
|
|
105617
105719
|
const files = [];
|
|
105618
105720
|
const missing = [];
|
|
105619
105721
|
for (const input of inputs.length > 0 ? inputs : ["."]) {
|
|
105620
|
-
const full =
|
|
105621
|
-
if (!
|
|
105722
|
+
const full = path71.resolve(cwd, input);
|
|
105723
|
+
if (!existsSync26(full))
|
|
105622
105724
|
missing.push(input);
|
|
105623
105725
|
else if (statSync10(full).isDirectory())
|
|
105624
105726
|
walkTests(full, files);
|
|
@@ -105654,11 +105756,11 @@ function changedLines(cwd, base) {
|
|
|
105654
105756
|
for (let offset = 0;offset < count; offset += 1)
|
|
105655
105757
|
lines.add(start + offset);
|
|
105656
105758
|
}
|
|
105657
|
-
changed.set(
|
|
105759
|
+
changed.set(path71.join(root, file), lines);
|
|
105658
105760
|
}
|
|
105659
105761
|
const untracked = git7(root, ["ls-files", "--others", "--exclude-standard", "-z"]);
|
|
105660
105762
|
for (const file of untracked.stdout.split("\x00").filter(Boolean))
|
|
105661
|
-
changed.set(
|
|
105763
|
+
changed.set(path71.join(root, file), "all");
|
|
105662
105764
|
return changed;
|
|
105663
105765
|
}
|
|
105664
105766
|
function auditFiles(files, display) {
|
|
@@ -105671,7 +105773,7 @@ function auditFiles(files, display) {
|
|
|
105671
105773
|
const shown = display(file);
|
|
105672
105774
|
let parsed;
|
|
105673
105775
|
try {
|
|
105674
|
-
parsed = parseSource(
|
|
105776
|
+
parsed = parseSource(readFileSync28(file, "utf8"), file);
|
|
105675
105777
|
} catch (error) {
|
|
105676
105778
|
parseErrors.push({
|
|
105677
105779
|
file: shown,
|
|
@@ -105720,7 +105822,7 @@ function auditFiles(files, display) {
|
|
|
105720
105822
|
durationMs: Math.round(performance.now() - started)
|
|
105721
105823
|
};
|
|
105722
105824
|
}
|
|
105723
|
-
var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(
|
|
105825
|
+
var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(path71.sep).join("/"), SEVERITY_ORDER, ruleIds;
|
|
105724
105826
|
var init_audit = __esm(() => {
|
|
105725
105827
|
init_ast();
|
|
105726
105828
|
init_rules();
|
|
@@ -105734,12 +105836,12 @@ var init_audit = __esm(() => {
|
|
|
105734
105836
|
// packages/workit-cli/src/test-audit/mutate.ts
|
|
105735
105837
|
import { spawn as spawn2 } from "node:child_process";
|
|
105736
105838
|
import {
|
|
105737
|
-
existsSync as
|
|
105839
|
+
existsSync as existsSync27,
|
|
105738
105840
|
lstatSync as lstatSync8,
|
|
105739
105841
|
mkdirSync as mkdirSync12,
|
|
105740
105842
|
mkdtempSync as mkdtempSync4,
|
|
105741
105843
|
readdirSync as readdirSync15,
|
|
105742
|
-
readFileSync as
|
|
105844
|
+
readFileSync as readFileSync29,
|
|
105743
105845
|
readlinkSync as readlinkSync3,
|
|
105744
105846
|
realpathSync as realpathSync10,
|
|
105745
105847
|
renameSync as renameSync7,
|
|
@@ -105749,8 +105851,8 @@ import {
|
|
|
105749
105851
|
writeFileSync as writeFileSync12,
|
|
105750
105852
|
copyFileSync as copyFileSync8
|
|
105751
105853
|
} from "node:fs";
|
|
105752
|
-
import
|
|
105753
|
-
import
|
|
105854
|
+
import os23 from "node:os";
|
|
105855
|
+
import path72 from "node:path";
|
|
105754
105856
|
function mutantsFor(source, file, lines) {
|
|
105755
105857
|
const parsed = parseSource(source, file);
|
|
105756
105858
|
const out = [];
|
|
@@ -105823,7 +105925,7 @@ function relatedTests(source, testFiles) {
|
|
|
105823
105925
|
for (const match of text.matchAll(SPECIFIER)) {
|
|
105824
105926
|
const spec = match[1];
|
|
105825
105927
|
if (spec.startsWith(".")) {
|
|
105826
|
-
if (stripExt(
|
|
105928
|
+
if (stripExt(path72.posix.join(path72.posix.dirname(file), spec)) === target)
|
|
105827
105929
|
return true;
|
|
105828
105930
|
} else if (spec.includes("/") && stripExt(spec).split("/").slice(-2).join("/") === tail)
|
|
105829
105931
|
return true;
|
|
@@ -105831,7 +105933,7 @@ function relatedTests(source, testFiles) {
|
|
|
105831
105933
|
return false;
|
|
105832
105934
|
}).map((entry) => entry.file);
|
|
105833
105935
|
}
|
|
105834
|
-
function removeStaleCopies(tmp =
|
|
105936
|
+
function removeStaleCopies(tmp = os23.tmpdir()) {
|
|
105835
105937
|
let removed = 0;
|
|
105836
105938
|
let names = [];
|
|
105837
105939
|
try {
|
|
@@ -105843,12 +105945,12 @@ function removeStaleCopies(tmp = os22.tmpdir()) {
|
|
|
105843
105945
|
for (const name of names) {
|
|
105844
105946
|
if (!name.startsWith(TEMP_PREFIX))
|
|
105845
105947
|
continue;
|
|
105846
|
-
const dir =
|
|
105948
|
+
const dir = path72.join(tmp, name);
|
|
105847
105949
|
try {
|
|
105848
105950
|
const stat = lstatSync8(dir);
|
|
105849
105951
|
if (!stat.isDirectory() || uid !== undefined && stat.uid !== uid)
|
|
105850
105952
|
continue;
|
|
105851
|
-
const pid = Number(
|
|
105953
|
+
const pid = Number(readFileSync29(path72.join(dir, PID_FILE), "utf8"));
|
|
105852
105954
|
if (Number.isInteger(pid) && pid > 0 && alive(pid))
|
|
105853
105955
|
continue;
|
|
105854
105956
|
} catch (error) {
|
|
@@ -105865,8 +105967,8 @@ function removeStaleCopies(tmp = os22.tmpdir()) {
|
|
|
105865
105967
|
function linkNodeModules(origin, target, repo, copy) {
|
|
105866
105968
|
mkdirSync12(target, { recursive: true });
|
|
105867
105969
|
for (const entry of readdirSync15(origin, { withFileTypes: true })) {
|
|
105868
|
-
const from =
|
|
105869
|
-
const to =
|
|
105970
|
+
const from = path72.join(origin, entry.name);
|
|
105971
|
+
const to = path72.join(target, entry.name);
|
|
105870
105972
|
if (entry.name.startsWith("@") && entry.isDirectory()) {
|
|
105871
105973
|
linkNodeModules(from, to, repo, copy);
|
|
105872
105974
|
continue;
|
|
@@ -105882,9 +105984,9 @@ function linkNodeModules(origin, target, repo, copy) {
|
|
|
105882
105984
|
} catch {
|
|
105883
105985
|
continue;
|
|
105884
105986
|
}
|
|
105885
|
-
const relative =
|
|
105886
|
-
if (!relative.startsWith("..") && !
|
|
105887
|
-
symlinkSync(
|
|
105987
|
+
const relative = path72.relative(repo, real);
|
|
105988
|
+
if (!relative.startsWith("..") && !path72.isAbsolute(relative) && !relative.split(path72.sep).includes("node_modules")) {
|
|
105989
|
+
symlinkSync(path72.join(copy, relative), to, "junction");
|
|
105888
105990
|
continue;
|
|
105889
105991
|
}
|
|
105890
105992
|
}
|
|
@@ -105900,7 +106002,7 @@ function copySymlink(repo, tree, from, to) {
|
|
|
105900
106002
|
}
|
|
105901
106003
|
const realRepo = realpathSync10(repo);
|
|
105902
106004
|
if (real && inside5(realRepo, real)) {
|
|
105903
|
-
symlinkSync(
|
|
106005
|
+
symlinkSync(path72.relative(path72.dirname(to), path72.join(tree, path72.relative(realRepo, real))), to);
|
|
105904
106006
|
return;
|
|
105905
106007
|
}
|
|
105906
106008
|
if (real && statSync11(real).isFile())
|
|
@@ -105909,10 +106011,10 @@ function copySymlink(repo, tree, from, to) {
|
|
|
105909
106011
|
symlinkSync(readlinkSync3(from), to);
|
|
105910
106012
|
}
|
|
105911
106013
|
function writeInside(copy, file, content) {
|
|
105912
|
-
const target =
|
|
106014
|
+
const target = path72.join(copy, file);
|
|
105913
106015
|
try {
|
|
105914
106016
|
const stat = lstatSync8(target);
|
|
105915
|
-
if (!stat.isFile() || !inside5(realpathSync10(copy), realpathSync10(
|
|
106017
|
+
if (!stat.isFile() || !inside5(realpathSync10(copy), realpathSync10(path72.dirname(target))))
|
|
105916
106018
|
return false;
|
|
105917
106019
|
} catch {
|
|
105918
106020
|
return false;
|
|
@@ -105923,9 +106025,9 @@ function writeInside(copy, file, content) {
|
|
|
105923
106025
|
return true;
|
|
105924
106026
|
}
|
|
105925
106027
|
function copyWorkingTree(repo) {
|
|
105926
|
-
const dir = mkdtempSync4(
|
|
105927
|
-
writeFileSync12(
|
|
105928
|
-
const tree =
|
|
106028
|
+
const dir = mkdtempSync4(path72.join(os23.tmpdir(), TEMP_PREFIX));
|
|
106029
|
+
writeFileSync12(path72.join(dir, PID_FILE), String(process.pid));
|
|
106030
|
+
const tree = path72.join(dir, "tree");
|
|
105929
106031
|
const head = git7(repo, ["rev-parse", "--verify", "--quiet", "HEAD"]).stdout.trim();
|
|
105930
106032
|
if (head && git7(dir, ["clone", "-q", "--shared", "--no-checkout", repo, tree]).ok) {
|
|
105931
106033
|
const branch = git7(repo, ["symbolic-ref", "--quiet", "--short", "HEAD"]).stdout.trim();
|
|
@@ -105942,29 +106044,29 @@ function copyWorkingTree(repo) {
|
|
|
105942
106044
|
for (const relative of listed) {
|
|
105943
106045
|
if (!relative)
|
|
105944
106046
|
continue;
|
|
105945
|
-
const from =
|
|
106047
|
+
const from = path72.join(repo, relative);
|
|
105946
106048
|
let stat;
|
|
105947
106049
|
try {
|
|
105948
106050
|
stat = lstatSync8(from);
|
|
105949
106051
|
} catch {
|
|
105950
106052
|
continue;
|
|
105951
106053
|
}
|
|
105952
|
-
const to =
|
|
105953
|
-
mkdirSync12(
|
|
106054
|
+
const to = path72.join(tree, relative);
|
|
106055
|
+
mkdirSync12(path72.dirname(to), { recursive: true });
|
|
105954
106056
|
if (stat.isSymbolicLink())
|
|
105955
106057
|
copySymlink(repo, tree, from, to);
|
|
105956
106058
|
else if (stat.isFile())
|
|
105957
106059
|
copyFileSync8(from, to);
|
|
105958
|
-
let parent =
|
|
106060
|
+
let parent = path72.dirname(relative);
|
|
105959
106061
|
while (parent !== "." && !dirs.has(parent)) {
|
|
105960
106062
|
dirs.add(parent);
|
|
105961
|
-
parent =
|
|
106063
|
+
parent = path72.dirname(parent);
|
|
105962
106064
|
}
|
|
105963
106065
|
}
|
|
105964
106066
|
for (const parent of dirs) {
|
|
105965
|
-
const modules =
|
|
105966
|
-
if (
|
|
105967
|
-
linkNodeModules(modules,
|
|
106067
|
+
const modules = path72.join(repo, parent, "node_modules");
|
|
106068
|
+
if (existsSync27(modules) && !existsSync27(path72.join(tree, parent, "node_modules")))
|
|
106069
|
+
linkNodeModules(modules, path72.join(tree, parent, "node_modules"), repo, tree);
|
|
105968
106070
|
}
|
|
105969
106071
|
return { dir, tree };
|
|
105970
106072
|
}
|
|
@@ -106003,20 +106105,20 @@ async function runMutation(options) {
|
|
|
106003
106105
|
const tracked = git7(repo, ["ls-files", "-co", "--exclude-standard", "-z"]).stdout.split("\x00").filter(Boolean);
|
|
106004
106106
|
const testFiles = tracked.filter((file) => TEST_FILE.test(file)).map((file) => {
|
|
106005
106107
|
try {
|
|
106006
|
-
return { file, text:
|
|
106108
|
+
return { file, text: readFileSync29(path72.join(repo, file), "utf8") };
|
|
106007
106109
|
} catch {
|
|
106008
106110
|
return { file, text: "" };
|
|
106009
106111
|
}
|
|
106010
106112
|
});
|
|
106011
106113
|
const candidates = [];
|
|
106012
106114
|
for (const [absolute, lines] of [...options.changed].toSorted(([a], [b]) => a.localeCompare(b))) {
|
|
106013
|
-
const relative = toPosix(
|
|
106115
|
+
const relative = toPosix(path72.relative(repo, absolute));
|
|
106014
106116
|
if (!CODE_FILE.test(relative) || TEST_FILE.test(relative) || relative.endsWith(".d.ts"))
|
|
106015
106117
|
continue;
|
|
106016
|
-
if (NOT_SOURCE.test(relative) || !
|
|
106118
|
+
if (NOT_SOURCE.test(relative) || !existsSync27(absolute))
|
|
106017
106119
|
continue;
|
|
106018
106120
|
try {
|
|
106019
|
-
candidates.push(...mutantsFor(
|
|
106121
|
+
candidates.push(...mutantsFor(readFileSync29(absolute, "utf8"), relative, lines));
|
|
106020
106122
|
} catch {}
|
|
106021
106123
|
}
|
|
106022
106124
|
const mutants = candidates.map((mutant, index) => ({ ...mutant, id: index + 1 }));
|
|
@@ -106024,9 +106126,9 @@ async function runMutation(options) {
|
|
|
106024
106126
|
for (const mutant of mutants)
|
|
106025
106127
|
if (!related.has(mutant.file))
|
|
106026
106128
|
related.set(mutant.file, relatedTests(mutant.file, testFiles));
|
|
106027
|
-
const cwdRelative =
|
|
106129
|
+
const cwdRelative = path72.relative(repo, options.cwd);
|
|
106028
106130
|
const asArg = (file) => {
|
|
106029
|
-
const relative = toPosix(
|
|
106131
|
+
const relative = toPosix(path72.relative(cwdRelative, file));
|
|
106030
106132
|
return shellQuote(relative.startsWith(".") ? relative : `./${relative}`);
|
|
106031
106133
|
};
|
|
106032
106134
|
const commandFor = (tests) => options.command.replaceAll("{files}", () => tests.map(asArg).join(" "));
|
|
@@ -106062,7 +106164,7 @@ async function runMutation(options) {
|
|
|
106062
106164
|
return finish3(options, 0, results, counts, started);
|
|
106063
106165
|
removeStaleCopies();
|
|
106064
106166
|
const { dir: copyDir, tree: copy } = copyWorkingTree(repo);
|
|
106065
|
-
const copyCwd =
|
|
106167
|
+
const copyCwd = path72.join(copy, cwdRelative);
|
|
106066
106168
|
let current = null;
|
|
106067
106169
|
const restore = () => {
|
|
106068
106170
|
if (current)
|
|
@@ -106097,7 +106199,7 @@ async function runMutation(options) {
|
|
|
106097
106199
|
record({ ...mutant, status: "skipped", durationMs: 0, tests, reason: "budget" });
|
|
106098
106200
|
continue;
|
|
106099
106201
|
}
|
|
106100
|
-
const original =
|
|
106202
|
+
const original = readFileSync29(path72.join(copy, mutant.file), "utf8");
|
|
106101
106203
|
const mutated = original.slice(0, mutant.start) + mutant.replacement + original.slice(mutant.end);
|
|
106102
106204
|
current = { file: mutant.file, original };
|
|
106103
106205
|
if (!writeInside(copy, mutant.file, mutated)) {
|
|
@@ -106154,8 +106256,8 @@ var NOT_SOURCE, FLIPS, isStringy = (node) => node.type === "StringLiteral" || no
|
|
|
106154
106256
|
return error.code === "EPERM";
|
|
106155
106257
|
}
|
|
106156
106258
|
}, inside5 = (root, file) => {
|
|
106157
|
-
const relative =
|
|
106158
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
106259
|
+
const relative = path72.relative(root, file);
|
|
106260
|
+
return relative === "" || !relative.startsWith("..") && !path72.isAbsolute(relative);
|
|
106159
106261
|
}, active, killTree = (child) => {
|
|
106160
106262
|
try {
|
|
106161
106263
|
if (child.pid && process.platform !== "win32")
|
|
@@ -106203,8 +106305,8 @@ var exports_test_audit = {};
|
|
|
106203
106305
|
__export(exports_test_audit, {
|
|
106204
106306
|
run: () => run23
|
|
106205
106307
|
});
|
|
106206
|
-
import { existsSync as
|
|
106207
|
-
import
|
|
106308
|
+
import { existsSync as existsSync28 } from "node:fs";
|
|
106309
|
+
import path73 from "node:path";
|
|
106208
106310
|
function parse8(argv) {
|
|
106209
106311
|
const options = {
|
|
106210
106312
|
paths: [],
|
|
@@ -106309,8 +106411,8 @@ async function run23(argv, io) {
|
|
|
106309
106411
|
return emit(io, fail2("invalid_input", `${options}
|
|
106310
106412
|
usage: ${USAGE16}`));
|
|
106311
106413
|
const top = git7(io.cwd, ["rev-parse", "--show-toplevel"]);
|
|
106312
|
-
const repo = top.ok ?
|
|
106313
|
-
const display = (file) => toPosix(
|
|
106414
|
+
const repo = top.ok ? path73.resolve(top.stdout.trim()) : null;
|
|
106415
|
+
const display = (file) => toPosix(path73.relative(io.cwd, file) || file);
|
|
106314
106416
|
let base = null;
|
|
106315
106417
|
let changed = null;
|
|
106316
106418
|
if (options.diff || options.mutate) {
|
|
@@ -106327,7 +106429,7 @@ usage: ${USAGE16}`));
|
|
|
106327
106429
|
}
|
|
106328
106430
|
let files;
|
|
106329
106431
|
if (options.diff && changed)
|
|
106330
|
-
files = [...changed.keys()].filter((file) => TEST_FILE.test(toPosix(file)) &&
|
|
106432
|
+
files = [...changed.keys()].filter((file) => TEST_FILE.test(toPosix(file)) && existsSync28(file)).toSorted();
|
|
106331
106433
|
else {
|
|
106332
106434
|
const expanded = expandPaths(io.cwd, options.paths);
|
|
106333
106435
|
if (expanded.missing.length > 0)
|
|
@@ -106448,8 +106550,8 @@ var exports_youtrack = {};
|
|
|
106448
106550
|
__export(exports_youtrack, {
|
|
106449
106551
|
run: () => run25
|
|
106450
106552
|
});
|
|
106451
|
-
import { readFileSync as
|
|
106452
|
-
import
|
|
106553
|
+
import { readFileSync as readFileSync30 } from "node:fs";
|
|
106554
|
+
import path74 from "node:path";
|
|
106453
106555
|
async function run25(argv, io) {
|
|
106454
106556
|
const [sub, ...rest] = argv;
|
|
106455
106557
|
if (sub !== "note" && sub !== "time" && sub !== "meeting")
|
|
@@ -106495,7 +106597,7 @@ async function run25(argv, io) {
|
|
|
106495
106597
|
let markdown = flags.values.markdown ?? "";
|
|
106496
106598
|
if (flags.values.file)
|
|
106497
106599
|
try {
|
|
106498
|
-
markdown =
|
|
106600
|
+
markdown = readFileSync30(path74.resolve(io.cwd, flags.values.file), "utf8");
|
|
106499
106601
|
} catch (error) {
|
|
106500
106602
|
return usage4(io, `cannot read ${flags.values.file}: ${String(error)}`, USAGE18);
|
|
106501
106603
|
}
|
|
@@ -106563,8 +106665,8 @@ var exports_changelog = {};
|
|
|
106563
106665
|
__export(exports_changelog, {
|
|
106564
106666
|
run: () => run26
|
|
106565
106667
|
});
|
|
106566
|
-
import { readFileSync as
|
|
106567
|
-
import
|
|
106668
|
+
import { readFileSync as readFileSync31 } from "node:fs";
|
|
106669
|
+
import path75 from "node:path";
|
|
106568
106670
|
async function run26(argv, io) {
|
|
106569
106671
|
const [sub, ...rest] = argv;
|
|
106570
106672
|
if (sub !== "apply")
|
|
@@ -106610,7 +106712,7 @@ async function run26(argv, io) {
|
|
|
106610
106712
|
]);
|
|
106611
106713
|
}
|
|
106612
106714
|
var USAGE19 = "workit changelog apply (--entries <JSON|@file|-> | --normalize-only) [--path CHANGELOG.md] [--preview]", readEntries = (raw, cwd) => {
|
|
106613
|
-
const text = raw === "-" ?
|
|
106715
|
+
const text = raw === "-" ? readFileSync31(0, "utf8") : raw.startsWith("@") ? readFileSync31(path75.resolve(cwd, raw.slice(1)), "utf8") : raw;
|
|
106614
106716
|
return JSON.parse(text);
|
|
106615
106717
|
};
|
|
106616
106718
|
var init_changelog2 = __esm(() => {
|
|
@@ -106626,7 +106728,7 @@ __export(exports_handoff, {
|
|
|
106626
106728
|
run: () => run27
|
|
106627
106729
|
});
|
|
106628
106730
|
import fs37 from "node:fs";
|
|
106629
|
-
import
|
|
106731
|
+
import path76 from "node:path";
|
|
106630
106732
|
import { parseArgs as parseArgs2 } from "node:util";
|
|
106631
106733
|
function render3(brief) {
|
|
106632
106734
|
const lines = [
|
|
@@ -106666,9 +106768,9 @@ function bounded(brief, cwd) {
|
|
|
106666
106768
|
let file = null;
|
|
106667
106769
|
if (store.ok)
|
|
106668
106770
|
try {
|
|
106669
|
-
const dir =
|
|
106771
|
+
const dir = path76.join(store.value.root, "handoff");
|
|
106670
106772
|
fs37.mkdirSync(dir, { recursive: true });
|
|
106671
|
-
file =
|
|
106773
|
+
file = path76.join(dir, `${(brief.branch ?? "detached").replaceAll(/[^\w.-]+/gu, "-")}.txt`);
|
|
106672
106774
|
fs37.writeFileSync(file, `${[...body, ...tail].join(`
|
|
106673
106775
|
`)}
|
|
106674
106776
|
`, {
|
|
@@ -106745,7 +106847,7 @@ var init_handoff = __esm(() => {
|
|
|
106745
106847
|
// packages/workit-cli/src/main.ts
|
|
106746
106848
|
init_host_session();
|
|
106747
106849
|
init_package();
|
|
106748
|
-
import
|
|
106850
|
+
import path77 from "node:path";
|
|
106749
106851
|
|
|
106750
106852
|
// packages/workit-cli/src/verbs/registry.ts
|
|
106751
106853
|
var TASK_FAMILY_NAMES = [
|
|
@@ -107657,7 +107759,7 @@ var defaultIo = (json) => ({
|
|
|
107657
107759
|
});
|
|
107658
107760
|
async function main(argv, overrides = {}, options = {}) {
|
|
107659
107761
|
const parsed = parseGlobals(argv);
|
|
107660
|
-
const cwd =
|
|
107762
|
+
const cwd = path77.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
|
|
107661
107763
|
const io = { ...defaultIo(parsed.json), ...overrides, json: parsed.json, cwd };
|
|
107662
107764
|
if (parsed.error)
|
|
107663
107765
|
return emit(io, fail2("invalid_input", parsed.error));
|