@brainervirus/workit-claude-code 8.40.8 → 8.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/dist/workit.js +315 -106
- package/package.json +3 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "workit",
|
|
3
3
|
"displayName": "Workit",
|
|
4
|
-
"version": "8.
|
|
4
|
+
"version": "8.41.0",
|
|
5
5
|
"description": "Workflow rails for agentic coding: task context on every session, branch policy on shell commands, and the workit method skills",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "BrainerVirus"
|
package/dist/workit.js
CHANGED
|
@@ -9417,7 +9417,7 @@ var package_default;
|
|
|
9417
9417
|
var init_package = __esm(() => {
|
|
9418
9418
|
package_default = {
|
|
9419
9419
|
name: "@brainervirus/workit-cli",
|
|
9420
|
-
version: "8.
|
|
9420
|
+
version: "8.41.0",
|
|
9421
9421
|
private: false,
|
|
9422
9422
|
description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
9423
9423
|
keywords: [
|
|
@@ -9455,13 +9455,13 @@ var init_package = __esm(() => {
|
|
|
9455
9455
|
},
|
|
9456
9456
|
dependencies: {
|
|
9457
9457
|
"@babel/parser": "7.29.9",
|
|
9458
|
-
"@brainervirus/workit-cursor": "^8.
|
|
9458
|
+
"@brainervirus/workit-cursor": "^8.41.0",
|
|
9459
9459
|
"@inkjs/ui": "2.0.0",
|
|
9460
9460
|
ink: "7.1.1",
|
|
9461
9461
|
react: "19.2.8"
|
|
9462
9462
|
},
|
|
9463
9463
|
devDependencies: {
|
|
9464
|
-
"@brainervirus/workit-core": "^8.
|
|
9464
|
+
"@brainervirus/workit-core": "^8.41.0"
|
|
9465
9465
|
},
|
|
9466
9466
|
engines: {
|
|
9467
9467
|
node: ">=24"
|
|
@@ -75218,7 +75218,124 @@ var init_setup2 = __esm(() => {
|
|
|
75218
75218
|
ALL_HOSTS = ["claude-code", "codex", "cursor", "opencode", "pi"];
|
|
75219
75219
|
});
|
|
75220
75220
|
|
|
75221
|
+
// packages/workit-cli/src/progress.ts
|
|
75222
|
+
function createProgress(options = {}) {
|
|
75223
|
+
const env = options.env ?? process.env;
|
|
75224
|
+
const mode = modeFor(options, env);
|
|
75225
|
+
const stream = options.stream;
|
|
75226
|
+
const now = options.now ?? Date.now;
|
|
75227
|
+
const every = options.setInterval ?? ((tick, ms) => setInterval(tick, ms));
|
|
75228
|
+
const stop = options.clearInterval ?? ((timer) => clearInterval(timer));
|
|
75229
|
+
const proc = options.proc ?? process;
|
|
75230
|
+
const ascii = env.TERM === "dumb";
|
|
75231
|
+
const glyphs = mode === "spinner" ? { done: "\x1B[32m✓\x1B[0m", failed: "\x1B[31m✗\x1B[0m", skipped: "–" } : ascii ? { done: "ok", failed: "x", skipped: "-" } : { done: "✓", failed: "✗", skipped: "–" };
|
|
75232
|
+
const start = (initial) => {
|
|
75233
|
+
if (mode === "off" || !stream)
|
|
75234
|
+
return NOOP_STEP;
|
|
75235
|
+
let text = initial;
|
|
75236
|
+
let finished = false;
|
|
75237
|
+
const began = now();
|
|
75238
|
+
let frame = 0;
|
|
75239
|
+
const draw = () => {
|
|
75240
|
+
const seconds = Math.floor((now() - began) / 1000);
|
|
75241
|
+
let line = `${FRAMES[frame % FRAMES.length]} ${text} (${seconds}s)`;
|
|
75242
|
+
if (stream.columns && line.length >= stream.columns)
|
|
75243
|
+
line = `${line.slice(0, Math.max(1, stream.columns - 2))}…`;
|
|
75244
|
+
stream.write(`${CLEAR}${line}`);
|
|
75245
|
+
};
|
|
75246
|
+
let timer;
|
|
75247
|
+
if (mode === "spinner") {
|
|
75248
|
+
draw();
|
|
75249
|
+
timer = every(() => {
|
|
75250
|
+
frame += 1;
|
|
75251
|
+
draw();
|
|
75252
|
+
}, FRAME_MS);
|
|
75253
|
+
}
|
|
75254
|
+
const handlers = [];
|
|
75255
|
+
const release = () => {
|
|
75256
|
+
for (const [event, handler] of handlers)
|
|
75257
|
+
proc.off(event, handler);
|
|
75258
|
+
handlers.length = 0;
|
|
75259
|
+
};
|
|
75260
|
+
if (mode === "spinner") {
|
|
75261
|
+
const onSignal = (signal) => () => {
|
|
75262
|
+
if (!finished) {
|
|
75263
|
+
finished = true;
|
|
75264
|
+
if (timer !== undefined)
|
|
75265
|
+
stop(timer);
|
|
75266
|
+
stream.write(CLEAR);
|
|
75267
|
+
}
|
|
75268
|
+
release();
|
|
75269
|
+
proc.kill(proc.pid, signal);
|
|
75270
|
+
};
|
|
75271
|
+
const onExit = () => {
|
|
75272
|
+
if (!finished)
|
|
75273
|
+
stream.write(CLEAR);
|
|
75274
|
+
};
|
|
75275
|
+
handlers.push(["SIGINT", onSignal("SIGINT")], ["SIGTERM", onSignal("SIGTERM")]);
|
|
75276
|
+
handlers.push(["exit", onExit]);
|
|
75277
|
+
for (const [event, handler] of handlers)
|
|
75278
|
+
proc.on(event, handler);
|
|
75279
|
+
}
|
|
75280
|
+
return {
|
|
75281
|
+
label: (next) => {
|
|
75282
|
+
text = next;
|
|
75283
|
+
if (mode === "spinner" && !finished)
|
|
75284
|
+
draw();
|
|
75285
|
+
},
|
|
75286
|
+
end: (status, note) => {
|
|
75287
|
+
if (finished)
|
|
75288
|
+
return;
|
|
75289
|
+
finished = true;
|
|
75290
|
+
if (timer !== undefined)
|
|
75291
|
+
stop(timer);
|
|
75292
|
+
release();
|
|
75293
|
+
stream.write(`${mode === "spinner" ? CLEAR : ""}${glyphs[status]} ${text}${note ? `: ${note}` : ""}
|
|
75294
|
+
`);
|
|
75295
|
+
}
|
|
75296
|
+
};
|
|
75297
|
+
};
|
|
75298
|
+
return {
|
|
75299
|
+
mode,
|
|
75300
|
+
start,
|
|
75301
|
+
async run(label, fn, classify) {
|
|
75302
|
+
const step = start(label);
|
|
75303
|
+
try {
|
|
75304
|
+
const value = await fn();
|
|
75305
|
+
step.end(classify ? classify(value) : "done");
|
|
75306
|
+
return value;
|
|
75307
|
+
} catch (error) {
|
|
75308
|
+
step.end("failed");
|
|
75309
|
+
throw error;
|
|
75310
|
+
}
|
|
75311
|
+
},
|
|
75312
|
+
runSync(label, fn, classify) {
|
|
75313
|
+
const step = start(label);
|
|
75314
|
+
try {
|
|
75315
|
+
const value = fn();
|
|
75316
|
+
step.end(classify ? classify(value) : "done");
|
|
75317
|
+
return value;
|
|
75318
|
+
} catch (error) {
|
|
75319
|
+
step.end("failed");
|
|
75320
|
+
throw error;
|
|
75321
|
+
}
|
|
75322
|
+
}
|
|
75323
|
+
};
|
|
75324
|
+
}
|
|
75325
|
+
var FRAMES, FRAME_MS = 120, CLEAR = "\r\x1B[2K", truthy = (value) => value !== undefined && value !== "" && value !== "0" && value.toLowerCase() !== "false", modeFor = (options, env) => {
|
|
75326
|
+
if (options.json || !options.stream?.isTTY || truthy(env.CI))
|
|
75327
|
+
return "off";
|
|
75328
|
+
if (truthy(env.NO_COLOR) || env.TERM === "dumb")
|
|
75329
|
+
return "plain";
|
|
75330
|
+
return "spinner";
|
|
75331
|
+
}, NOOP_STEP;
|
|
75332
|
+
var init_progress = __esm(() => {
|
|
75333
|
+
FRAMES = ["·", "✢", "✳", "∗", "✻", "✽"];
|
|
75334
|
+
NOOP_STEP = { label: () => {}, end: () => {} };
|
|
75335
|
+
});
|
|
75336
|
+
|
|
75221
75337
|
// packages/workit-cli/src/upgrade/shared.ts
|
|
75338
|
+
import { spawn } from "node:child_process";
|
|
75222
75339
|
import { existsSync as existsSync21, readFileSync as readFileSync22 } from "node:fs";
|
|
75223
75340
|
import path44 from "node:path";
|
|
75224
75341
|
import os16 from "node:os";
|
|
@@ -75279,7 +75396,61 @@ var LAUNCH_HOSTS, HOSTS2, LIVE_HOSTS, OPENCODE_PACKAGE = "@brainervirus/workit-o
|
|
|
75279
75396
|
}
|
|
75280
75397
|
const result = runHostCommand(step, { home, env });
|
|
75281
75398
|
return { status: result.exitCode, stdout: result.stdout };
|
|
75282
|
-
}),
|
|
75399
|
+
}), COMMAND_TIMEOUT_MS = 60000, asyncRunner = (deps) => {
|
|
75400
|
+
if (deps.runAsync)
|
|
75401
|
+
return deps.runAsync;
|
|
75402
|
+
const injected = deps.run;
|
|
75403
|
+
if (injected)
|
|
75404
|
+
return async (command, args) => injected(command, args);
|
|
75405
|
+
return (command, args) => {
|
|
75406
|
+
const { home, env } = upgradePaths(deps);
|
|
75407
|
+
let step;
|
|
75408
|
+
try {
|
|
75409
|
+
step = hostCommand(command, args, { home, env });
|
|
75410
|
+
} catch {
|
|
75411
|
+
return Promise.resolve({ status: 1, stdout: "" });
|
|
75412
|
+
}
|
|
75413
|
+
if (process.platform === "win32" && /\.(?:cmd|bat)$/i.test(step.command))
|
|
75414
|
+
return Promise.resolve({ status: 1, stdout: "" });
|
|
75415
|
+
const childEnv = { ...process.env, ...env, HOME: home };
|
|
75416
|
+
childEnv.CODEX_HOME = env.CODEX_HOME ?? path44.join(home, ".codex");
|
|
75417
|
+
childEnv.PI_CODING_AGENT_DIR = env.PI_CODING_AGENT_DIR ?? path44.join(home, ".pi", "agent");
|
|
75418
|
+
childEnv.CLAUDE_CONFIG_DIR = env.CLAUDE_CONFIG_DIR ?? path44.join(home, ".claude");
|
|
75419
|
+
childEnv.XDG_CONFIG_HOME = env.XDG_CONFIG_HOME ?? path44.join(home, ".config");
|
|
75420
|
+
return new Promise((resolve) => {
|
|
75421
|
+
let stdout = "";
|
|
75422
|
+
let settled = false;
|
|
75423
|
+
const finish = (status) => {
|
|
75424
|
+
if (settled)
|
|
75425
|
+
return;
|
|
75426
|
+
settled = true;
|
|
75427
|
+
clearTimeout(timer);
|
|
75428
|
+
resolve({ status, stdout });
|
|
75429
|
+
};
|
|
75430
|
+
let child;
|
|
75431
|
+
try {
|
|
75432
|
+
child = spawn(step.command, step.args, {
|
|
75433
|
+
cwd: step.cwd,
|
|
75434
|
+
env: childEnv,
|
|
75435
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
75436
|
+
windowsHide: true,
|
|
75437
|
+
shell: false
|
|
75438
|
+
});
|
|
75439
|
+
} catch {
|
|
75440
|
+
resolve({ status: 1, stdout: "" });
|
|
75441
|
+
return;
|
|
75442
|
+
}
|
|
75443
|
+
const timer = setTimeout(() => {
|
|
75444
|
+
child.kill("SIGKILL");
|
|
75445
|
+
finish(1);
|
|
75446
|
+
}, COMMAND_TIMEOUT_MS);
|
|
75447
|
+
child.stdout?.setEncoding("utf8");
|
|
75448
|
+
child.stdout?.on("data", (chunk) => stdout += chunk);
|
|
75449
|
+
child.on("error", () => finish(1));
|
|
75450
|
+
child.on("close", (code) => finish(code ?? 1));
|
|
75451
|
+
});
|
|
75452
|
+
};
|
|
75453
|
+
}, errorText = (error) => error instanceof Error ? error.message : "installed source could not be read", piInstalledVersion = (listing, selector) => {
|
|
75283
75454
|
const lines = listing.split(/\r?\n/).map((line) => line.trim());
|
|
75284
75455
|
const index = lines.indexOf(selector);
|
|
75285
75456
|
if (index < 0 || !lines[index + 1] || !path44.isAbsolute(lines[index + 1]))
|
|
@@ -75368,7 +75539,7 @@ var init_processes = __esm(() => {
|
|
|
75368
75539
|
import { existsSync as existsSync22, readdirSync as readdirSync12, mkdirSync as mkdirSync11, copyFileSync as copyFileSync6, chmodSync as chmodSync2, cpSync as cpSync5 } from "node:fs";
|
|
75369
75540
|
import path46 from "node:path";
|
|
75370
75541
|
import { createHash as createHash16 } from "node:crypto";
|
|
75371
|
-
function applyUpgrade(plan, deps = {}) {
|
|
75542
|
+
async function applyUpgrade(plan, deps = {}) {
|
|
75372
75543
|
const hosts = [...plan.failed];
|
|
75373
75544
|
const done = (backup) => {
|
|
75374
75545
|
const failures = hosts.filter((entry) => entry.status === "failed");
|
|
@@ -75423,6 +75594,9 @@ function applyUpgrade(plan, deps = {}) {
|
|
|
75423
75594
|
`, 384);
|
|
75424
75595
|
}
|
|
75425
75596
|
const run = runner(deps);
|
|
75597
|
+
const runAsync = asyncRunner(deps);
|
|
75598
|
+
const progress = deps.progress ?? createProgress({ json: true });
|
|
75599
|
+
const statusOf = (outcome) => outcome?.status === "failed" ? "failed" : outcome?.status === "updated" ? "done" : "skipped";
|
|
75426
75600
|
let cursorBackupError = null;
|
|
75427
75601
|
if (plan.entries.some((entry) => entry.host === "cursor") && existsSync22(paths.cursorRoot))
|
|
75428
75602
|
try {
|
|
@@ -75435,96 +75609,104 @@ function applyUpgrade(plan, deps = {}) {
|
|
|
75435
75609
|
const listed = plan.entries.length ? listProcesses(deps) : [];
|
|
75436
75610
|
const running = (listed ?? []).flatMap((entry) => classifyProcess(entry) ?? []);
|
|
75437
75611
|
for (const entry of plan.entries) {
|
|
75438
|
-
|
|
75439
|
-
|
|
75440
|
-
|
|
75441
|
-
|
|
75442
|
-
reason: cursorBackupError,
|
|
75443
|
-
fix: entry.fix
|
|
75444
|
-
});
|
|
75445
|
-
continue;
|
|
75446
|
-
}
|
|
75447
|
-
if (!LIVE_HOSTS.has(entry.host)) {
|
|
75448
|
-
if (listed === null) {
|
|
75612
|
+
const before = hosts.length;
|
|
75613
|
+
const step = progress.start(`Updating ${entry.host}`);
|
|
75614
|
+
try {
|
|
75615
|
+
if (entry.host === "cursor" && cursorBackupError) {
|
|
75449
75616
|
hosts.push({
|
|
75450
|
-
host:
|
|
75451
|
-
status: "
|
|
75452
|
-
reason:
|
|
75453
|
-
fix:
|
|
75617
|
+
host: "cursor",
|
|
75618
|
+
status: "failed",
|
|
75619
|
+
reason: cursorBackupError,
|
|
75620
|
+
fix: entry.fix
|
|
75454
75621
|
});
|
|
75455
75622
|
continue;
|
|
75456
75623
|
}
|
|
75457
|
-
|
|
75458
|
-
|
|
75624
|
+
if (!LIVE_HOSTS.has(entry.host)) {
|
|
75625
|
+
if (listed === null) {
|
|
75626
|
+
hosts.push({
|
|
75627
|
+
host: entry.host,
|
|
75628
|
+
status: "skipped",
|
|
75629
|
+
reason: `running processes could not be listed; close ${entry.host} and rerun`,
|
|
75630
|
+
fix: `workit upgrade --hosts=${entry.host}`
|
|
75631
|
+
});
|
|
75632
|
+
continue;
|
|
75633
|
+
}
|
|
75634
|
+
const sessions = running.filter((proc) => proc.host === entry.host && proc.kind === "session");
|
|
75635
|
+
if (sessions.length) {
|
|
75636
|
+
hosts.push({
|
|
75637
|
+
host: entry.host,
|
|
75638
|
+
status: "skipped",
|
|
75639
|
+
reason: `close ${entry.host} (${sessions.map(describe2).join("; ")}), then rerun`,
|
|
75640
|
+
fix: `workit upgrade --hosts=${entry.host}`
|
|
75641
|
+
});
|
|
75642
|
+
continue;
|
|
75643
|
+
}
|
|
75644
|
+
}
|
|
75645
|
+
const daemons = running.filter((proc) => proc.host === "codex" && proc.kind === "daemon");
|
|
75646
|
+
const stopDaemon = entry.host === "codex" && daemons.length > 0;
|
|
75647
|
+
const stopped = stopDaemon ? await progress.run("Stopping the Codex app-server daemon", () => runAsync("codex", ["app-server", "daemon", "stop"]), (result) => result.status === 0 ? "done" : "failed") : null;
|
|
75648
|
+
if (stopped && stopped.status !== 0) {
|
|
75459
75649
|
hosts.push({
|
|
75460
|
-
host:
|
|
75461
|
-
status: "
|
|
75462
|
-
reason: `
|
|
75463
|
-
fix:
|
|
75650
|
+
host: "codex",
|
|
75651
|
+
status: "failed",
|
|
75652
|
+
reason: `could not stop the Codex app-server daemon (${daemons.map(describe2).join("; ")})`,
|
|
75653
|
+
fix: "codex app-server daemon stop && workit upgrade --hosts=codex"
|
|
75464
75654
|
});
|
|
75465
75655
|
continue;
|
|
75466
75656
|
}
|
|
75467
|
-
|
|
75468
|
-
|
|
75469
|
-
|
|
75470
|
-
|
|
75471
|
-
|
|
75472
|
-
|
|
75473
|
-
|
|
75474
|
-
|
|
75475
|
-
|
|
75476
|
-
|
|
75477
|
-
|
|
75478
|
-
|
|
75479
|
-
|
|
75480
|
-
|
|
75481
|
-
|
|
75482
|
-
|
|
75483
|
-
|
|
75484
|
-
|
|
75657
|
+
let outcome;
|
|
75658
|
+
try {
|
|
75659
|
+
outcome = await applyEntry(entry, { run, runAsync, paths, configDir });
|
|
75660
|
+
if (entry.host === "codex" && outcome.status === "updated") {
|
|
75661
|
+
const agents = await refreshCodexAgents(runAsync, paths.codexHome);
|
|
75662
|
+
if (!agents.ok)
|
|
75663
|
+
outcome = {
|
|
75664
|
+
...outcome,
|
|
75665
|
+
status: "failed",
|
|
75666
|
+
reason: `${outcome.reason}; ${agents.note}`,
|
|
75667
|
+
fix: agents.fix
|
|
75668
|
+
};
|
|
75669
|
+
else if (agents.note)
|
|
75670
|
+
outcome = { ...outcome, reason: `${outcome.reason}; ${agents.note}` };
|
|
75671
|
+
}
|
|
75672
|
+
} catch (error) {
|
|
75673
|
+
outcome = {
|
|
75674
|
+
host: entry.host,
|
|
75675
|
+
status: "failed",
|
|
75676
|
+
reason: errorText(error),
|
|
75677
|
+
fix: entry.fix
|
|
75678
|
+
};
|
|
75679
|
+
}
|
|
75680
|
+
if (stopDaemon) {
|
|
75681
|
+
const started = (await progress.run("Restarting the Codex app-server daemon", () => runAsync("codex", ["app-server", "daemon", "start"]), (result) => result.status === 0 ? "done" : "failed")).status === 0;
|
|
75682
|
+
outcome = started ? {
|
|
75683
|
+
...outcome,
|
|
75684
|
+
reason: `${outcome.reason}; app-server daemon stopped and started again`
|
|
75685
|
+
} : {
|
|
75686
|
+
...outcome,
|
|
75687
|
+
status: "failed",
|
|
75688
|
+
reason: `${outcome.reason}; the app-server daemon did not start again`,
|
|
75689
|
+
fix: "codex app-server daemon start"
|
|
75690
|
+
};
|
|
75691
|
+
}
|
|
75692
|
+
if (entry.host === "opencode") {
|
|
75693
|
+
const servers = running.filter((proc) => proc.host === "opencode" && proc.kind === "daemon");
|
|
75694
|
+
if (servers.length && outcome.status === "updated")
|
|
75485
75695
|
outcome = {
|
|
75486
75696
|
...outcome,
|
|
75487
|
-
|
|
75488
|
-
reason: `${outcome.reason}; ${agents.note}`,
|
|
75489
|
-
fix: agents.fix
|
|
75697
|
+
reason: `${outcome.reason}; restart opencode serve (${servers.map(describe2).join("; ")}) to load it`
|
|
75490
75698
|
};
|
|
75491
|
-
else if (agents.note)
|
|
75492
|
-
outcome = { ...outcome, reason: `${outcome.reason}; ${agents.note}` };
|
|
75493
75699
|
}
|
|
75494
|
-
|
|
75495
|
-
|
|
75496
|
-
|
|
75497
|
-
|
|
75498
|
-
reason: errorText(error),
|
|
75499
|
-
fix: entry.fix
|
|
75500
|
-
};
|
|
75501
|
-
}
|
|
75502
|
-
if (stopDaemon) {
|
|
75503
|
-
const started = run("codex", ["app-server", "daemon", "start"]).status === 0;
|
|
75504
|
-
outcome = started ? {
|
|
75505
|
-
...outcome,
|
|
75506
|
-
reason: `${outcome.reason}; app-server daemon stopped and started again`
|
|
75507
|
-
} : {
|
|
75508
|
-
...outcome,
|
|
75509
|
-
status: "failed",
|
|
75510
|
-
reason: `${outcome.reason}; the app-server daemon did not start again`,
|
|
75511
|
-
fix: "codex app-server daemon start"
|
|
75512
|
-
};
|
|
75513
|
-
}
|
|
75514
|
-
if (entry.host === "opencode") {
|
|
75515
|
-
const servers = running.filter((proc) => proc.host === "opencode" && proc.kind === "daemon");
|
|
75516
|
-
if (servers.length && outcome.status === "updated")
|
|
75517
|
-
outcome = {
|
|
75518
|
-
...outcome,
|
|
75519
|
-
reason: `${outcome.reason}; restart opencode serve (${servers.map(describe2).join("; ")}) to load it`
|
|
75520
|
-
};
|
|
75700
|
+
hosts.push(outcome);
|
|
75701
|
+
} finally {
|
|
75702
|
+
const added = hosts.length > before ? hosts[hosts.length - 1] : undefined;
|
|
75703
|
+
step.end(statusOf(added), added && added.status !== "updated" ? added.reason : undefined);
|
|
75521
75704
|
}
|
|
75522
|
-
hosts.push(outcome);
|
|
75523
75705
|
}
|
|
75524
75706
|
if (hosts.some((entry) => entry.host === "codex" && entry.status === "current")) {
|
|
75525
75707
|
let agents;
|
|
75526
75708
|
try {
|
|
75527
|
-
agents = refreshCodexAgents(
|
|
75709
|
+
agents = await refreshCodexAgents(runAsync, paths.codexHome);
|
|
75528
75710
|
} catch (error) {
|
|
75529
75711
|
agents = {
|
|
75530
75712
|
ok: false,
|
|
@@ -75548,7 +75730,7 @@ function applyUpgrade(plan, deps = {}) {
|
|
|
75548
75730
|
}
|
|
75549
75731
|
if (plan.cli)
|
|
75550
75732
|
try {
|
|
75551
|
-
hosts.push(applyCli(plan.cli,
|
|
75733
|
+
hosts.push(await progress.run("Updating the CLI", () => applyCli(plan.cli, runAsync, backup), statusOf));
|
|
75552
75734
|
} catch (error) {
|
|
75553
75735
|
hosts.push({
|
|
75554
75736
|
host: "cli",
|
|
@@ -75569,8 +75751,8 @@ var codexPluginRoot = (codexHome) => {
|
|
|
75569
75751
|
}
|
|
75570
75752
|
const newest = versions.reduce((best, version) => best && versionAtLeast(best, version) ? best : version, null);
|
|
75571
75753
|
return newest ? path46.join(dir, newest) : null;
|
|
75572
|
-
}, opencodeVersion = (run) => {
|
|
75573
|
-
const listing = run("opencode", ["plugin", "list"]);
|
|
75754
|
+
}, opencodeVersion = async (run) => {
|
|
75755
|
+
const listing = await run("opencode", ["plugin", "list"]);
|
|
75574
75756
|
if (listing.status !== 0)
|
|
75575
75757
|
return;
|
|
75576
75758
|
for (const line of listing.stdout.split(/\r?\n/)) {
|
|
@@ -75583,8 +75765,8 @@ var codexPluginRoot = (codexHome) => {
|
|
|
75583
75765
|
return version;
|
|
75584
75766
|
}
|
|
75585
75767
|
return;
|
|
75586
|
-
}, applyEntry = (entry, context) => {
|
|
75587
|
-
const { run, paths, configDir } = context;
|
|
75768
|
+
}, applyEntry = async (entry, context) => {
|
|
75769
|
+
const { run, runAsync, paths, configDir } = context;
|
|
75588
75770
|
const { home, env } = paths;
|
|
75589
75771
|
const fail = (reason) => ({
|
|
75590
75772
|
host: entry.host,
|
|
@@ -75636,12 +75818,12 @@ var codexPluginRoot = (codexHome) => {
|
|
|
75636
75818
|
reason: entry.repair ? `reinstalled missing plugin files (${entry.latest})` : `${entry.installedVersion ?? "?"} -> ${entry.latest}`
|
|
75637
75819
|
};
|
|
75638
75820
|
}
|
|
75639
|
-
const before = entry.host === "opencode" ? opencodeVersion(
|
|
75821
|
+
const before = entry.host === "opencode" ? await opencodeVersion(runAsync) : undefined;
|
|
75640
75822
|
for (const command of entry.commands)
|
|
75641
|
-
if (
|
|
75823
|
+
if ((await runAsync(command.command, command.args)).status !== 0)
|
|
75642
75824
|
return fail(`\`${command.command} ${command.args.join(" ")}\` failed`);
|
|
75643
75825
|
if (entry.host === "opencode") {
|
|
75644
|
-
const after = opencodeVersion(
|
|
75826
|
+
const after = await opencodeVersion(runAsync);
|
|
75645
75827
|
if (before && after)
|
|
75646
75828
|
return after === before ? {
|
|
75647
75829
|
host: "opencode",
|
|
@@ -75670,7 +75852,7 @@ var codexPluginRoot = (codexHome) => {
|
|
|
75670
75852
|
reason: `${entry.installedVersion ?? "?"} -> ${after ?? "?"}; new sessions load it`
|
|
75671
75853
|
};
|
|
75672
75854
|
}
|
|
75673
|
-
const verify = entry.host === "codex" ?
|
|
75855
|
+
const verify = entry.host === "codex" ? await runAsync("codex", ["plugin", "list", "--json"]) : await runAsync("pi", ["list"]);
|
|
75674
75856
|
if (verify.status !== 0)
|
|
75675
75857
|
return fail("update verification failed");
|
|
75676
75858
|
if (entry.host === "codex") {
|
|
@@ -75688,28 +75870,28 @@ var codexPluginRoot = (codexHome) => {
|
|
|
75688
75870
|
status: "updated",
|
|
75689
75871
|
reason: entry.repair ? `reinstalled missing plugin files (${entry.latest})` : `${entry.installedVersion ?? "?"} -> ${entry.latest}`
|
|
75690
75872
|
};
|
|
75691
|
-
}, refreshCodexAgents = (run, codexHome) => {
|
|
75873
|
+
}, refreshCodexAgents = async (run, codexHome) => {
|
|
75692
75874
|
const root = codexPluginRoot(codexHome);
|
|
75693
75875
|
const launcher = root && path46.join(root, "dist", "launch-mcp.js");
|
|
75694
75876
|
if (!launcher || !existsSync22(launcher))
|
|
75695
75877
|
return { ok: true, note: "" };
|
|
75696
75878
|
const fix = `node ${JSON.stringify(launcher)} --install-agents`;
|
|
75697
|
-
return run("node", [launcher, "--install-agents"]).status === 0 ? { ok: true, note: "agents refreshed" } : { ok: false, note: "agent refresh failed", fix };
|
|
75698
|
-
}, applyCli = (cli, run, backup) => {
|
|
75879
|
+
return (await run("node", [launcher, "--install-agents"])).status === 0 ? { ok: true, note: "agents refreshed" } : { ok: false, note: "agent refresh failed", fix };
|
|
75880
|
+
}, applyCli = async (cli, run, backup) => {
|
|
75699
75881
|
const fail = (reason) => ({
|
|
75700
75882
|
host: "cli",
|
|
75701
75883
|
status: "failed",
|
|
75702
75884
|
reason,
|
|
75703
75885
|
fix: CLI_FIX
|
|
75704
75886
|
});
|
|
75705
|
-
const currentRoot = run("npm", ["root", "--global"]);
|
|
75887
|
+
const currentRoot = await run("npm", ["root", "--global"]);
|
|
75706
75888
|
if (currentRoot.status !== 0 || currentRoot.stdout.trim() !== cli.root)
|
|
75707
75889
|
return fail("Global npm location changed; preview again");
|
|
75708
75890
|
const cliBackup = path46.join(backup, "cli-package");
|
|
75709
75891
|
cpSync5(path46.join(cli.root, "@brainervirus/workit-cli"), cliBackup, {
|
|
75710
75892
|
recursive: true
|
|
75711
75893
|
});
|
|
75712
|
-
if (run("npm", ["install", "--global", `@brainervirus/workit-cli@${cli.latest}`]).status !== 0)
|
|
75894
|
+
if ((await run("npm", ["install", "--global", `@brainervirus/workit-cli@${cli.latest}`])).status !== 0)
|
|
75713
75895
|
return fail(`CLI update failed; preserved package at ${cliBackup}; use npm to repair or run node ${path46.join(cliBackup, "dist/index.js")}`);
|
|
75714
75896
|
const installed = objectOrNull(path46.join(cli.root, "@brainervirus/workit-cli/package.json"));
|
|
75715
75897
|
if (installed?.name !== "@brainervirus/workit-cli" || installed.version !== cli.latest)
|
|
@@ -75725,6 +75907,7 @@ var init_apply = __esm(() => {
|
|
|
75725
75907
|
init_setup_state();
|
|
75726
75908
|
init_setup();
|
|
75727
75909
|
init_safe_write();
|
|
75910
|
+
init_progress();
|
|
75728
75911
|
init_processes();
|
|
75729
75912
|
init_shared();
|
|
75730
75913
|
});
|
|
@@ -76145,9 +76328,13 @@ async function runUpgradeCommand(argv, deps = {}) {
|
|
|
76145
76328
|
const legacy = flags.has("--apply");
|
|
76146
76329
|
const json = flags.has("--json") || legacy;
|
|
76147
76330
|
const run = runner(deps);
|
|
76148
|
-
const
|
|
76149
|
-
|
|
76150
|
-
|
|
76331
|
+
const progress = deps.progress ?? createProgress({ stream: process.stderr, json });
|
|
76332
|
+
const plan = progress.runSync("Planning the upgrade", () => {
|
|
76333
|
+
const planned = previewUpgrade(raw, deps);
|
|
76334
|
+
if (hostFlag === undefined || flags.has("--cli"))
|
|
76335
|
+
planCli(planned, run);
|
|
76336
|
+
return planned;
|
|
76337
|
+
});
|
|
76151
76338
|
plan.ok = plan.blocked.length === 0 && plan.failed.length === 0;
|
|
76152
76339
|
const { home, env } = upgradePaths(deps);
|
|
76153
76340
|
const permissions = planHostPermissions({
|
|
@@ -76198,11 +76385,11 @@ Nothing changed.
|
|
|
76198
76385
|
for (const warning of plan.warnings ?? [])
|
|
76199
76386
|
out.write(`warning: ${warning}
|
|
76200
76387
|
`);
|
|
76201
|
-
const result = applyUpgrade(plan, deps);
|
|
76388
|
+
const result = await applyUpgrade(plan, { ...deps, progress });
|
|
76202
76389
|
let permissionsOk = true;
|
|
76203
76390
|
let written;
|
|
76204
76391
|
if (permissions.changes.length && !permissions.refused && !result.error?.startsWith("configuration changed")) {
|
|
76205
|
-
written = applyHostPermissions(permissions, { home, env });
|
|
76392
|
+
written = progress.runSync("Refreshing the permission block", () => applyHostPermissions(permissions, { home, env }), (entries) => entries.every((entry) => entry.status === "written") ? "done" : "failed");
|
|
76206
76393
|
permissionsOk = written.every((entry) => entry.status === "written");
|
|
76207
76394
|
for (const entry of written)
|
|
76208
76395
|
result.hosts.push({
|
|
@@ -76214,7 +76401,7 @@ Nothing changed.
|
|
|
76214
76401
|
}
|
|
76215
76402
|
const failed = !result.ok || !permissionsOk;
|
|
76216
76403
|
const cliVersion = result.hosts.some((h) => h.host === "cli" && h.status === "updated") ? plan.cli.latest : package_default.version;
|
|
76217
|
-
const report = (deps.doctor ?? ((version) => runDoctor({ home, env, cliVersion: version, only: "upgrade" })))(cliVersion);
|
|
76404
|
+
const report = progress.runSync("Checking the result with workit doctor", () => (deps.doctor ?? ((version) => runDoctor({ home, env, cliVersion: version, only: "upgrade" })))(cliVersion));
|
|
76218
76405
|
const left = report.checks.filter((check) => check.status === "warn" || check.status === "fail");
|
|
76219
76406
|
if (json) {
|
|
76220
76407
|
out.write(JSON.stringify({
|
|
@@ -76272,7 +76459,7 @@ async function runLaunchCommand(argv, deps = {}) {
|
|
|
76272
76459
|
for (const skipped of plan.skipped)
|
|
76273
76460
|
(deps.out ?? process.stderr).write(`${skipped.host}: ${skipped.reason}${skipped.fix ? ` (run: ${skipped.fix})` : ""}
|
|
76274
76461
|
`);
|
|
76275
|
-
const result = applyUpgrade(plan, deps);
|
|
76462
|
+
const result = await applyUpgrade(plan, deps);
|
|
76276
76463
|
if (!result.ok) {
|
|
76277
76464
|
(deps.out ?? process.stdout).write(`${result.error}
|
|
76278
76465
|
`);
|
|
@@ -76301,6 +76488,7 @@ var init_upgrade = __esm(() => {
|
|
|
76301
76488
|
init_host_install();
|
|
76302
76489
|
init_doctor();
|
|
76303
76490
|
init_host_permissions();
|
|
76491
|
+
init_progress();
|
|
76304
76492
|
init_apply();
|
|
76305
76493
|
init_plan();
|
|
76306
76494
|
init_report();
|
|
@@ -76831,7 +77019,7 @@ var init_redact = __esm(() => {
|
|
|
76831
77019
|
});
|
|
76832
77020
|
|
|
76833
77021
|
// packages/workit-core/src/checks.ts
|
|
76834
|
-
import { spawn, spawnSync as spawnSync19 } from "node:child_process";
|
|
77022
|
+
import { spawn as spawn2, spawnSync as spawnSync19 } from "node:child_process";
|
|
76835
77023
|
import { createHash as createHash17 } from "node:crypto";
|
|
76836
77024
|
import fs21 from "node:fs";
|
|
76837
77025
|
import os18 from "node:os";
|
|
@@ -77060,7 +77248,7 @@ function runCheckCommand(argv, options) {
|
|
|
77060
77248
|
shell: plan.shell
|
|
77061
77249
|
};
|
|
77062
77250
|
try {
|
|
77063
|
-
child =
|
|
77251
|
+
child = spawn2(plan.file, plan.args, spawnOptions);
|
|
77064
77252
|
} catch (error) {
|
|
77065
77253
|
finish(null, null, error.code ?? error.message);
|
|
77066
77254
|
return;
|
|
@@ -79078,6 +79266,8 @@ async function prepareHeavy(io, settings, label, runCwd, timeoutMs) {
|
|
|
79078
79266
|
wrapper: null,
|
|
79079
79267
|
env: io.env
|
|
79080
79268
|
};
|
|
79269
|
+
const progress = createProgress({ stream: process.stderr, json: io.json });
|
|
79270
|
+
let waiting = null;
|
|
79081
79271
|
const acquired = await acquireLease({
|
|
79082
79272
|
dir,
|
|
79083
79273
|
slots: settings.slots,
|
|
@@ -79090,11 +79280,20 @@ async function prepareHeavy(io, settings, label, runCwd, timeoutMs) {
|
|
|
79090
79280
|
onStatus: (status) => {
|
|
79091
79281
|
const slots = `${settings.slots} slot${settings.slots === 1 ? "" : "s"}`;
|
|
79092
79282
|
const holders = status.holders.map((holder) => describeHolder(holder)).join("; ");
|
|
79283
|
+
if (progress.mode === "spinner") {
|
|
79284
|
+
const text = `Waiting for the heavy-check lease: held by ${holders || "nobody; waiters ahead"}, queue position ${status.position}`;
|
|
79285
|
+
if (waiting)
|
|
79286
|
+
waiting.label(text);
|
|
79287
|
+
else
|
|
79288
|
+
waiting = progress.start(text);
|
|
79289
|
+
return;
|
|
79290
|
+
}
|
|
79093
79291
|
io.stderr(status.first ? `workit: waiting for the heavy-check lease (${slots}): held by ${holders || "nobody; waiters ahead"}; queued at position ${status.position}, waiting up to ${formatWait(settings.waitMs)} (--wait <dur> sets it)
|
|
79094
79292
|
` : `workit: still queued for the heavy-check lease: position ${status.position}, ${formatWait(status.waitedMs)} of ${formatWait(settings.waitMs)} waited; held by ${holders || "nobody; waiters ahead"}
|
|
79095
79293
|
`);
|
|
79096
79294
|
}
|
|
79097
79295
|
});
|
|
79296
|
+
waiting?.end(acquired.ok ? "done" : "failed");
|
|
79098
79297
|
if (!acquired.ok && acquired.reason === "timeout") {
|
|
79099
79298
|
const holders = acquired.holders.map((holder) => describeHolder(holder)).join("; ");
|
|
79100
79299
|
const waited = formatWait(acquired.waitedMs);
|
|
@@ -79376,6 +79575,7 @@ var init_check = __esm(() => {
|
|
|
79376
79575
|
init_package();
|
|
79377
79576
|
init_ledger();
|
|
79378
79577
|
init_output();
|
|
79578
|
+
init_progress();
|
|
79379
79579
|
init_host_session();
|
|
79380
79580
|
init_resources();
|
|
79381
79581
|
MAX_UNVERIFIED_RUN_MS = 6 * 3600000;
|
|
@@ -87930,6 +88130,11 @@ async function wait2(argv, io) {
|
|
|
87930
88130
|
let verdict = { state: "waiting", reason: "not_polled" };
|
|
87931
88131
|
let baseContexts = null;
|
|
87932
88132
|
let expectedMissing = [];
|
|
88133
|
+
const waiting = createProgress({ stream: process.stderr, json: io.json }).start("Waiting for CI");
|
|
88134
|
+
const abort = (...args) => {
|
|
88135
|
+
waiting.end("failed");
|
|
88136
|
+
return forgeFail(io, ...args);
|
|
88137
|
+
};
|
|
87933
88138
|
for (;; ) {
|
|
87934
88139
|
const read = resolved.forge.prStatus(number.data);
|
|
87935
88140
|
polls += 1;
|
|
@@ -87939,7 +88144,7 @@ async function wait2(argv, io) {
|
|
|
87939
88144
|
status = read.data;
|
|
87940
88145
|
const doc = buildStatusDoc(io.cwd, resolved, status, { logLines: 0, behind: false });
|
|
87941
88146
|
if (!doc.ok)
|
|
87942
|
-
return
|
|
88147
|
+
return abort(doc);
|
|
87943
88148
|
recordPrStatus(io.cwd, doc.data, actor);
|
|
87944
88149
|
if (status.requiredContexts === null && baseContexts === null) {
|
|
87945
88150
|
const base = resolved.forge.branchChecks(status.base);
|
|
@@ -87950,12 +88155,14 @@ async function wait2(argv, io) {
|
|
|
87950
88155
|
verdict = waitVerdict(doc.data, { head, elapsedMs, expectedMissing });
|
|
87951
88156
|
if (verdict.state !== "waiting")
|
|
87952
88157
|
break;
|
|
88158
|
+
const pending = doc.data.checks.pending;
|
|
88159
|
+
waiting.label(`Waiting for CI: ${pending.length} check${pending.length === 1 ? "" : "s"} pending${pending.length ? ` (${pending.slice(0, 3).join(", ")}${pending.length > 3 ? ", …" : ""})` : ""}`);
|
|
87953
88160
|
} else {
|
|
87954
88161
|
errors += 1;
|
|
87955
88162
|
if (read.code !== "unavailable" && read.code !== "failed")
|
|
87956
|
-
return
|
|
88163
|
+
return abort(read);
|
|
87957
88164
|
if (errors >= MAX_POLL_ERRORS)
|
|
87958
|
-
return
|
|
88165
|
+
return abort(read, { polls });
|
|
87959
88166
|
}
|
|
87960
88167
|
const remaining = deadline - forgeDeps.now();
|
|
87961
88168
|
if (remaining <= 0)
|
|
@@ -87963,6 +88170,7 @@ async function wait2(argv, io) {
|
|
|
87963
88170
|
await forgeDeps.sleep(Math.min(pollDelay(intervalMs, polls - 1), remaining));
|
|
87964
88171
|
}
|
|
87965
88172
|
const elapsedMs = forgeDeps.now() - started;
|
|
88173
|
+
waiting.end(verdict.state === "ready" ? "done" : verdict.state === "waiting" ? "skipped" : "failed");
|
|
87966
88174
|
if (!status)
|
|
87967
88175
|
return emit(io, fail2("unavailable", "no successful poll before the timeout", { data: { polls } }));
|
|
87968
88176
|
const left = deadline - forgeDeps.now();
|
|
@@ -88129,6 +88337,7 @@ var init_ci = __esm(() => {
|
|
|
88129
88337
|
init_ledger();
|
|
88130
88338
|
init_autonomy();
|
|
88131
88339
|
init_output();
|
|
88340
|
+
init_progress();
|
|
88132
88341
|
init_forge_common();
|
|
88133
88342
|
});
|
|
88134
88343
|
|
|
@@ -107016,7 +107225,7 @@ var init_audit = __esm(() => {
|
|
|
107016
107225
|
});
|
|
107017
107226
|
|
|
107018
107227
|
// packages/workit-cli/src/test-audit/mutate.ts
|
|
107019
|
-
import { spawn as
|
|
107228
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
107020
107229
|
import {
|
|
107021
107230
|
existsSync as existsSync29,
|
|
107022
107231
|
lstatSync as lstatSync9,
|
|
@@ -107255,7 +107464,7 @@ function copyWorkingTree(repo) {
|
|
|
107255
107464
|
function runCommand(command, cwd, timeoutMs, env) {
|
|
107256
107465
|
const started = performance.now();
|
|
107257
107466
|
return new Promise((resolve) => {
|
|
107258
|
-
const child =
|
|
107467
|
+
const child = spawn3(command, {
|
|
107259
107468
|
cwd,
|
|
107260
107469
|
env,
|
|
107261
107470
|
shell: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-claude-code",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.41.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit Claude Code plugin — session and per-turn task context, branch policy on git shell commands, workit method skills, and verifier/reviewer/implementer agents",
|
|
6
6
|
"keywords": [
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"build": "bun scripts/build.ts"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@brainervirus/workit-cli": "^8.
|
|
43
|
-
"@brainervirus/workit-core": "^8.
|
|
42
|
+
"@brainervirus/workit-cli": "^8.41.0",
|
|
43
|
+
"@brainervirus/workit-core": "^8.41.0"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
|
46
46
|
"node": ">=24"
|