@brainervirus/workit-cli 8.41.1 → 8.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +303 -107
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -9417,7 +9417,7 @@ var package_default;
9417
9417
  var init_package = __esm(() => {
9418
9418
  package_default = {
9419
9419
  name: "@brainervirus/workit-cli",
9420
- version: "8.41.1",
9420
+ version: "8.42.0",
9421
9421
  private: false,
9422
9422
  description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
9423
9423
  keywords: [
@@ -9455,13 +9455,13 @@ var init_package = __esm(() => {
9455
9455
  },
9456
9456
  dependencies: {
9457
9457
  "@babel/parser": "7.29.9",
9458
- "@brainervirus/workit-cursor": "^8.41.1",
9458
+ "@brainervirus/workit-cursor": "^8.42.0",
9459
9459
  "@inkjs/ui": "2.0.0",
9460
9460
  ink: "7.1.1",
9461
9461
  react: "19.2.8"
9462
9462
  },
9463
9463
  devDependencies: {
9464
- "@brainervirus/workit-core": "^8.41.1"
9464
+ "@brainervirus/workit-core": "^8.42.0"
9465
9465
  },
9466
9466
  engines: {
9467
9467
  node: ">=24"
@@ -21951,6 +21951,108 @@ var init_task = __esm(() => {
21951
21951
  };
21952
21952
  });
21953
21953
 
21954
+ // packages/workit-cli/src/style.ts
21955
+ import { stripVTControlCharacters } from "node:util";
21956
+ function createStyle(options = {}) {
21957
+ const enabled = colorEnabled(options);
21958
+ const pick = (open) => enabled ? sgr(open) : same2;
21959
+ return {
21960
+ enabled,
21961
+ width: enabled ? options.stream?.columns || undefined : undefined,
21962
+ ok: pick("32"),
21963
+ fail: pick("1;31"),
21964
+ warn: pick("33"),
21965
+ info: pick("2"),
21966
+ dim: pick("2"),
21967
+ bold: pick("1"),
21968
+ accent: pick("36"),
21969
+ diffAdd: pick("32"),
21970
+ diffDel: pick("31"),
21971
+ diffHunk: pick("36"),
21972
+ path: pick("2"),
21973
+ command: pick("1;36")
21974
+ };
21975
+ }
21976
+ function wrap(text, width, indent, firstUsed = indent) {
21977
+ if (!width || width <= indent + 10)
21978
+ return text;
21979
+ const lines = [];
21980
+ let line = "";
21981
+ let room = width - firstUsed;
21982
+ const place = (word) => {
21983
+ let rest = word;
21984
+ while (visibleLength(rest) > room) {
21985
+ const chars = Array.from(rest);
21986
+ lines.push(chars.slice(0, room).join(""));
21987
+ rest = chars.slice(room).join("");
21988
+ room = width - indent;
21989
+ }
21990
+ line = rest;
21991
+ };
21992
+ for (const word of text.split(/ +/)) {
21993
+ if (word === "")
21994
+ continue;
21995
+ if (line === "")
21996
+ place(word);
21997
+ else if (visibleLength(line) + 1 + visibleLength(word) <= room)
21998
+ line = `${line} ${word}`;
21999
+ else {
22000
+ lines.push(line);
22001
+ room = width - indent;
22002
+ place(word);
22003
+ }
22004
+ }
22005
+ lines.push(line);
22006
+ return lines.join(`
22007
+ ${" ".repeat(indent)}`);
22008
+ }
22009
+ function colorDiff(text, style) {
22010
+ if (!style.enabled)
22011
+ return text;
22012
+ return text.split(`
22013
+ `).map((line) => {
22014
+ if (line.startsWith("+++") || line.startsWith("---"))
22015
+ return style.bold(line);
22016
+ if (line.startsWith("+"))
22017
+ return style.diffAdd(line);
22018
+ if (line.startsWith("-"))
22019
+ return style.diffDel(line);
22020
+ if (line.startsWith("@@") || line.trim() === "…" || line.trim() === "...")
22021
+ return style.diffHunk(line);
22022
+ return style.dim(line);
22023
+ }).join(`
22024
+ `);
22025
+ }
22026
+ function spinnerPaint(elapsed, env, glyph) {
22027
+ const k = (Math.sin(elapsed / 2400 * Math.PI * 2) + 1) / 2;
22028
+ const [r, g, b] = [
22029
+ [170, 80],
22030
+ [120, 200],
22031
+ [255, 255]
22032
+ ].map(([from, to]) => Math.round(from + (to - from) * k));
22033
+ const depth = (env.COLORTERM || "").toLowerCase();
22034
+ const level = (v) => v < 48 ? 0 : v < 115 ? 1 : Math.min(5, Math.floor((v - 35) / 40));
22035
+ const code = depth === "truecolor" || depth === "24bit" ? `38;2;${r};${g};${b}` : /256/.test(env.TERM || "") ? `38;5;${16 + 36 * level(r) + 6 * level(g) + level(b)}` : "36";
22036
+ return `\x1B[${code}m${glyph}\x1B[0m`;
22037
+ }
22038
+ var truthy = (value) => value !== undefined && value !== "" && value !== "0" && value.toLowerCase() !== "false", terminalMode = (options) => {
22039
+ const env = options.env ?? process.env;
22040
+ if (options.json || !options.stream?.isTTY || truthy(env.CI))
22041
+ return "off";
22042
+ if (truthy(env.NO_COLOR) || env.TERM === "dumb")
22043
+ return "plain";
22044
+ return "spinner";
22045
+ }, colorEnabled = (options) => {
22046
+ if (options.json || !options.stream)
22047
+ return false;
22048
+ if (truthy((options.env ?? process.env).FORCE_COLOR))
22049
+ return true;
22050
+ return terminalMode(options) === "spinner";
22051
+ }, sgr = (open) => (text) => text === "" ? text : `\x1B[${open}m${text}\x1B[0m`, same2 = (text) => text, visibleLength = (text) => Array.from(stripVTControlCharacters(text)).length, SPINNER_FRAMES, SPINNER_FRAME_MS = 140;
22052
+ var init_style = __esm(() => {
22053
+ SPINNER_FRAMES = ["◐", "◓", "◑", "◒"];
22054
+ });
22055
+
21954
22056
  // packages/workit-cli/src/output.ts
21955
22057
  function emit(io, envelope, human) {
21956
22058
  if (io.json) {
@@ -21988,11 +22090,12 @@ async function withFailureLine(io, command, run, outcome) {
21988
22090
  });
21989
22091
  if (code === 0)
21990
22092
  return code;
22093
+ const red = createStyle({ stream: io.terminals?.stderr, env: io.env, json: io.json }).fail;
21991
22094
  if (outcome)
21992
- io.stderr(`workit: error: ${outcome} (${reason ?? EXIT_NAMES[code] ?? "failed"}, exit ${code})
22095
+ io.stderr(`${red(`workit: error: ${outcome} (${reason ?? EXIT_NAMES[code] ?? "failed"}, exit ${code})`)}
21993
22096
  `);
21994
22097
  else if (!wrote)
21995
- io.stderr(`workit: error: ${command} failed (exit ${code})
22098
+ io.stderr(`${red(`workit: error: ${command} failed (exit ${code})`)}
21996
22099
  `);
21997
22100
  return code;
21998
22101
  }
@@ -22017,6 +22120,7 @@ var EXIT, EXIT_BY_CODE, exitCodeFor = (code) => EXIT_BY_CODE[code], ok2 = (data)
22017
22120
  })));
22018
22121
  };
22019
22122
  var init_output = __esm(() => {
22123
+ init_style();
22020
22124
  EXIT = {
22021
22125
  ok: 0,
22022
22126
  failed: 1,
@@ -75191,14 +75295,18 @@ async function run4(argv, io) {
75191
75295
  ...io.env.HOME ? { home: io.env.HOME } : {}
75192
75296
  });
75193
75297
  const say = io.json ? io.stderr : io.stdout;
75298
+ const style = createStyle({
75299
+ stream: io.json ? io.terminals?.stderr : io.terminals?.stdout,
75300
+ env: io.env
75301
+ });
75194
75302
  for (const note of plan.notes)
75195
75303
  say(`${note}
75196
75304
  `);
75197
75305
  for (const blocked of plan.blocked)
75198
- say(`blocked: ${blocked}
75306
+ say(`${style.warn("blocked:")} ${blocked}
75199
75307
  `);
75200
75308
  for (const change of plan.changes)
75201
- say(`${permissionDiff(change)}
75309
+ say(`${colorDiff(permissionDiff(change), style)}
75202
75310
  `);
75203
75311
  const summary = {
75204
75312
  changes: plan.changes.map((c) => ({ host: c.host, file: c.file })),
@@ -75220,7 +75328,7 @@ async function run4(argv, io) {
75220
75328
  data: summary,
75221
75329
  unblock: `review the diff above, then run ${USAGE2.replace("[--dry-run | --yes]", "--yes")} or run it in a terminal`
75222
75330
  }));
75223
- const answer = await askOrCancel(io, () => askLine("Write Workit's permission block shown above? [y/N] ", io.json ? process.stderr : process.stdout));
75331
+ const answer = await askOrCancel(io, () => askLine(`${style.bold("Write Workit's permission block shown above?")} [y/N] `, io.json ? process.stderr : process.stdout));
75224
75332
  if (answer === null)
75225
75333
  return cancelled(io);
75226
75334
  if (!/^y(es)?$/i.test(answer.trim()))
@@ -75235,7 +75343,7 @@ async function run4(argv, io) {
75235
75343
  if (failed.length)
75236
75344
  return emit(io, fail2("failed", failed.map((e) => `${e.file}: ${e.detail ?? "failed"}`).join("; "), { data }));
75237
75345
  return emit(io, ok2(data), () => [
75238
- ...entries.map((e) => `written ${e.file}`),
75346
+ ...entries.map((e) => `${style.ok("written")} ${style.path(e.file)}`),
75239
75347
  "Restart the host sessions to load the new permissions. `workit uninstall` removes them."
75240
75348
  ]);
75241
75349
  }
@@ -75271,6 +75379,7 @@ var init_setup2 = __esm(() => {
75271
75379
  init_host_permissions();
75272
75380
  init_output();
75273
75381
  init_prompt();
75382
+ init_style();
75274
75383
  ALL_HOSTS = ["claude-code", "codex", "cursor", "opencode", "pi"];
75275
75384
  });
75276
75385
 
@@ -75279,7 +75388,7 @@ import { spawn } from "node:child_process";
75279
75388
  import path44 from "node:path";
75280
75389
  function createProgress(options = {}) {
75281
75390
  const env = options.env ?? process.env;
75282
- const mode = modeFor(options, env);
75391
+ const mode = terminalMode({ ...options, env });
75283
75392
  const stream = options.stream;
75284
75393
  const now = options.now ?? Date.now;
75285
75394
  const every = options.setInterval ?? ((tick, ms) => setInterval(tick, ms));
@@ -75287,7 +75396,7 @@ function createProgress(options = {}) {
75287
75396
  const proc = options.proc ?? process;
75288
75397
  const ascii = env.TERM === "dumb";
75289
75398
  const glyphs = mode === "spinner" ? { done: "\x1B[32m✓\x1B[0m", failed: "\x1B[31m✗\x1B[0m", skipped: "–" } : ascii ? { done: "ok", failed: "x", skipped: "-" } : { done: "✓", failed: "✗", skipped: "–" };
75290
- const start = (initial) => {
75399
+ const start = (initial, signals = true) => {
75291
75400
  if (mode === "off" || !stream)
75292
75401
  return NOOP_STEP;
75293
75402
  let text = initial;
@@ -75296,10 +75405,11 @@ function createProgress(options = {}) {
75296
75405
  let frame = 0;
75297
75406
  const draw = () => {
75298
75407
  const seconds = Math.floor((now() - began) / 1000);
75299
- let line = `${FRAMES[frame % FRAMES.length]} ${text} (${seconds}s)`;
75300
- if (stream.columns && line.length >= stream.columns)
75301
- line = `${line.slice(0, Math.max(1, stream.columns - 2))}…`;
75302
- stream.write(`${CLEAR}${line}`);
75408
+ let line = `${text} (${seconds}s)`;
75409
+ if (stream.columns && line.length + 2 >= stream.columns)
75410
+ line = `${line.slice(0, Math.max(1, stream.columns - 4))}…`;
75411
+ const glyph = spinnerPaint(now() - began, env, FRAMES[frame % FRAMES.length] ?? "");
75412
+ stream.write(`${CLEAR}${glyph} ${line}`);
75303
75413
  };
75304
75414
  let timer;
75305
75415
  if (mode === "spinner") {
@@ -75315,7 +75425,7 @@ function createProgress(options = {}) {
75315
75425
  proc.off(event, handler);
75316
75426
  handlers.length = 0;
75317
75427
  };
75318
- if (mode === "spinner") {
75428
+ if (mode === "spinner" && signals) {
75319
75429
  const onSignal = (signal) => () => {
75320
75430
  if (!finished) {
75321
75431
  finished = true;
@@ -75326,11 +75436,13 @@ function createProgress(options = {}) {
75326
75436
  release();
75327
75437
  proc.kill(proc.pid, signal);
75328
75438
  };
75439
+ handlers.push(["SIGINT", onSignal("SIGINT")], ["SIGTERM", onSignal("SIGTERM")]);
75440
+ }
75441
+ if (mode === "spinner") {
75329
75442
  const onExit = () => {
75330
75443
  if (!finished)
75331
75444
  stream.write(CLEAR);
75332
75445
  };
75333
- handlers.push(["SIGINT", onSignal("SIGINT")], ["SIGTERM", onSignal("SIGTERM")]);
75334
75446
  handlers.push(["exit", onExit]);
75335
75447
  for (const [event, handler] of handlers)
75336
75448
  proc.on(event, handler);
@@ -75357,7 +75469,7 @@ function createProgress(options = {}) {
75357
75469
  mode,
75358
75470
  start,
75359
75471
  async run(label, fn, classify) {
75360
- const step = start(label);
75472
+ const step = start(label, false);
75361
75473
  try {
75362
75474
  const value = await fn();
75363
75475
  step.end(classify ? classify(value) : "done");
@@ -75368,7 +75480,7 @@ function createProgress(options = {}) {
75368
75480
  }
75369
75481
  },
75370
75482
  runSync(label, fn, classify) {
75371
- const step = start(label);
75483
+ const step = start(label, false);
75372
75484
  const ticker = mode === "spinner" && stream ? (options.spawnTicker ?? ((text, began) => defaultTicker(text, began, stream)))(label, now()) : undefined;
75373
75485
  try {
75374
75486
  const value = fn();
@@ -75383,7 +75495,7 @@ function createProgress(options = {}) {
75383
75495
  }
75384
75496
  };
75385
75497
  }
75386
- var FRAMES, FRAME_MS = 120, CLEAR = "\r\x1B[2K", TICKER_SOURCE, defaultTicker = (label, began, stream) => {
75498
+ var FRAMES, FRAME_MS, CLEAR = "\r\x1B[2K", TICKER_SOURCE, defaultTicker = (label, began, stream) => {
75387
75499
  if (stream !== process.stderr)
75388
75500
  return;
75389
75501
  if (!/^(?:node|nodejs|bun)(?:\.exe)?$/i.test(path44.basename(process.execPath)))
@@ -75405,18 +75517,19 @@ var FRAMES, FRAME_MS = 120, CLEAR = "\r\x1B[2K", TICKER_SOURCE, defaultTicker =
75405
75517
  } catch {
75406
75518
  return;
75407
75519
  }
75408
- }, truthy = (value) => value !== undefined && value !== "" && value !== "0" && value.toLowerCase() !== "false", modeFor = (options, env) => {
75409
- if (options.json || !options.stream?.isTTY || truthy(env.CI))
75410
- return "off";
75411
- if (truthy(env.NO_COLOR) || env.TERM === "dumb")
75412
- return "plain";
75413
- return "spinner";
75414
- }, NOOP_STEP;
75520
+ }, NOOP_STEP, progressFor = (io) => {
75521
+ const stderr = io.terminals?.stderr;
75522
+ const stream = stderr?.write ? stderr : undefined;
75523
+ return createProgress({ json: io.json, env: io.env, ...stream ? { stream } : {} });
75524
+ };
75415
75525
  var init_progress = __esm(() => {
75416
- FRAMES = ["·", "✢", "✳", "∗", "✻", "✽"];
75526
+ init_style();
75527
+ FRAMES = SPINNER_FRAMES;
75528
+ FRAME_MS = SPINNER_FRAME_MS;
75417
75529
  TICKER_SOURCE = `
75418
75530
  const frames = ${JSON.stringify(FRAMES)};
75419
75531
  const { WORKIT_TICK_LABEL: label, WORKIT_TICK_BEGAN: began, WORKIT_TICK_COLS: cols } = process.env;
75532
+ const spinnerPaint = ${spinnerPaint.toString()};
75420
75533
  const parent = process.ppid;
75421
75534
  let frame = 0;
75422
75535
  const timer = setInterval(() => {
@@ -75425,9 +75538,9 @@ const timer = setInterval(() => {
75425
75538
  if (!alive || Date.now() - Number(began) > 600000) process.exit(0);
75426
75539
  frame += 1;
75427
75540
  const seconds = Math.floor((Date.now() - Number(began)) / 1000);
75428
- let line = frames[frame % frames.length] + " " + label + " (" + seconds + "s)";
75429
- if (Number(cols) && line.length >= Number(cols)) line = line.slice(0, Math.max(1, Number(cols) - 2)) + "…";
75430
- process.stderr.write(${JSON.stringify(CLEAR)} + line);
75541
+ let line = label + " (" + seconds + "s)";
75542
+ if (Number(cols) && line.length + 2 >= Number(cols)) line = line.slice(0, Math.max(1, Number(cols) - 4)) + "…";
75543
+ process.stderr.write(${JSON.stringify(CLEAR)} + spinnerPaint(Date.now() - Number(began), process.env, frames[frame % frames.length]) + " " + line);
75431
75544
  }, ${FRAME_MS});
75432
75545
  `;
75433
75546
  NOOP_STEP = { label: () => {}, end: () => {} };
@@ -76418,26 +76531,29 @@ var init_plan = __esm(() => {
76418
76531
  });
76419
76532
 
76420
76533
  // packages/workit-cli/src/upgrade/report.ts
76421
- var pad2 = (text) => text.padEnd(12), summary = (plan, permissions) => {
76422
- const lines = ["Workit upgrade plan:"];
76534
+ var pad2 = (text) => text.padEnd(12), PLAIN, summary = (plan, permissions, style = PLAIN) => {
76535
+ const host = (name) => ` ${style.bold(pad2(name))}`;
76536
+ const run = (fix) => fix ? ` (run: ${style.command(fix)})` : "";
76537
+ const version = (from, to) => `update ${style.dim(from)} -> ${style.ok(to)}`;
76538
+ const lines = [style.bold("Workit upgrade plan:")];
76423
76539
  if (plan.cli)
76424
- lines.push(` ${pad2("cli")}update ${plan.cli.installed} -> ${plan.cli.latest}`);
76540
+ lines.push(`${host("cli")}${version(plan.cli.installed, plan.cli.latest)}`);
76425
76541
  for (const entry of plan.entries) {
76426
- const what = entry.repair ? `reinstall missing plugin files (${entry.latest})` : entry.latest ? `update ${entry.installedVersion ?? "?"} -> ${entry.latest}` : `update (${entry.commands.map((c) => `${c.command} ${c.args.join(" ")}`).join(" && ")})`;
76427
- lines.push(` ${pad2(entry.host)}${what}`);
76542
+ const what = entry.repair ? `reinstall missing plugin files (${entry.latest})` : entry.latest ? version(entry.installedVersion ?? "?", entry.latest) : `update (${style.command(entry.commands.map((c) => `${c.command} ${c.args.join(" ")}`).join(" && "))})`;
76543
+ lines.push(`${host(entry.host)}${what}`);
76428
76544
  }
76429
76545
  for (const skipped of plan.skipped)
76430
- lines.push(` ${pad2(skipped.host)}${skipped.reason.startsWith("already current") ? "" : "skip: "}${skipped.reason}${skipped.fix ? ` (run: ${skipped.fix})` : ""}`);
76546
+ lines.push(`${host(skipped.host)}${skipped.reason.startsWith("already current") ? style.dim(skipped.reason) : `${style.warn("skip:")} ${skipped.reason}`}${run(skipped.fix)}`);
76431
76547
  for (const failed of plan.failed)
76432
- lines.push(` ${pad2(failed.host)}cannot upgrade: ${failed.reason}${failed.fix ? ` (run: ${failed.fix})` : ""}`);
76548
+ lines.push(`${host(failed.host)}${style.fail("cannot upgrade:")} ${failed.reason}${run(failed.fix)}`);
76433
76549
  for (const migration of plan.migrations)
76434
- lines.push(` ${pad2("config")}${migration.description}`);
76550
+ lines.push(`${host("config")}${migration.description}`);
76435
76551
  for (const change of permissions)
76436
- lines.push(` ${pad2("permissions")}refresh the ${change.host} block in ${change.file}`);
76552
+ lines.push(`${host("permissions")}refresh the ${change.host} block in ${style.path(change.file)}`);
76437
76553
  for (const blocked of plan.blocked)
76438
- lines.push(` blocked: ${blocked}`);
76554
+ lines.push(` ${style.fail("blocked:")} ${blocked}`);
76439
76555
  for (const warning of plan.warnings ?? [])
76440
- lines.push(` warning: ${warning}`);
76556
+ lines.push(` ${style.warn("warning:")} ${warning}`);
76441
76557
  return lines.join(`
76442
76558
  `) + `
76443
76559
  `;
@@ -76445,10 +76561,14 @@ var pad2 = (text) => text.padEnd(12), summary = (plan, permissions) => {
76445
76561
  const label = LABEL[entry.status];
76446
76562
  const head = entry.reason.slice(0, label.length);
76447
76563
  return entry.status !== "failed" && head.toLowerCase() === label.toLowerCase() && !/^[a-z]/i.test(entry.reason[label.length] ?? "") ? entry.reason.slice(label.length).replace(/^[\s:;,-]+/, "") : entry.reason;
76448
- }, table = (hosts) => [
76449
- "Result:",
76450
- ...hosts.map((entry) => ` ${pad2(entry.host)}${LABEL[entry.status].padEnd(16)}${reasonFor(entry)}${entry.fix && entry.status !== "updated" && entry.status !== "current" ? `
76451
- ${pad2("")}${"".padEnd(16)}fix: ${entry.fix}` : ""}`)
76564
+ }, PAINT, table = (hosts, style = PLAIN) => [
76565
+ style.bold("Result:"),
76566
+ ...hosts.map((entry) => {
76567
+ const paint = style[PAINT[entry.status]];
76568
+ const reason = reasonFor(entry);
76569
+ return ` ${style.bold(pad2(entry.host))}${paint(LABEL[entry.status])}${" ".repeat(16 - LABEL[entry.status].length)}${entry.status === "current" ? style.dim(reason) : reason}${entry.fix && entry.status !== "updated" && entry.status !== "current" ? `
76570
+ ${pad2("")}${"".padEnd(16)}fix: ${style.command(entry.fix)}` : ""}`;
76571
+ })
76452
76572
  ].join(`
76453
76573
  `) + `
76454
76574
  `, askConfirm = async (question, out) => {
@@ -76461,12 +76581,20 @@ var pad2 = (text) => text.padEnd(12), summary = (plan, permissions) => {
76461
76581
  return /^y(?:es)?$/i.test((await askLine(question)).trim());
76462
76582
  };
76463
76583
  var init_report = __esm(() => {
76584
+ init_style();
76585
+ PLAIN = createStyle({ json: true });
76464
76586
  LABEL = {
76465
76587
  updated: "updated",
76466
76588
  current: "already current",
76467
76589
  skipped: "skipped",
76468
76590
  failed: "FAILED"
76469
76591
  };
76592
+ PAINT = {
76593
+ updated: "ok",
76594
+ current: "dim",
76595
+ skipped: "warn",
76596
+ failed: "fail"
76597
+ };
76470
76598
  });
76471
76599
 
76472
76600
  // packages/workit-cli/src/upgrade.ts
@@ -76498,6 +76626,11 @@ async function runUpgradeCommand(argv, deps = {}) {
76498
76626
  });
76499
76627
  plan.ok = plan.blocked.length === 0 && plan.failed.length === 0;
76500
76628
  const { home, env } = upgradePaths(deps);
76629
+ const style = createStyle({
76630
+ stream: out === process.stdout ? process.stdout : undefined,
76631
+ env,
76632
+ json
76633
+ });
76501
76634
  const permissions = planHostPermissions({
76502
76635
  hosts: raw,
76503
76636
  refreshOnly: true,
@@ -76515,7 +76648,7 @@ async function runUpgradeCommand(argv, deps = {}) {
76515
76648
  };
76516
76649
  const withPermissions = (value) => permissions.changes.length ? { ...value, permissions: permissionPreview } : value;
76517
76650
  const applyCommand = `workit upgrade ${[...hostFlag === undefined ? [] : [`--hosts=${hostFlag}`], ...flags.has("--cli") ? ["--cli"] : [], "--yes"].join(" ")}`;
76518
- const nothingChanged = `preview only; nothing changed. Apply with: ${applyCommand}
76651
+ const nothingChanged = `${style.dim("preview only; nothing changed.")} Apply with: ${style.command(applyCommand)}
76519
76652
  `;
76520
76653
  if (json && !legacy && !flags.has("--yes")) {
76521
76654
  out.write(JSON.stringify(withPermissions(plan), null, 2) + `
@@ -76523,20 +76656,20 @@ async function runUpgradeCommand(argv, deps = {}) {
76523
76656
  return plan.blocked.length ? 1 : 0;
76524
76657
  }
76525
76658
  if (!json)
76526
- out.write(summary(plan, permissions.changes));
76659
+ out.write(summary(plan, permissions.changes, style));
76527
76660
  if (flags.has("--preview")) {
76528
76661
  out.write(nothingChanged);
76529
76662
  return plan.blocked.length ? 1 : 0;
76530
76663
  }
76531
76664
  if (plan.blocked.length) {
76532
- out.write(`Upgrade blocked: ${plan.blocked.join("; ")}
76665
+ out.write(`${style.fail("Upgrade blocked:")} ${plan.blocked.join("; ")}
76533
76666
  Nothing changed.
76534
76667
  `);
76535
76668
  return 1;
76536
76669
  }
76537
76670
  const work = plan.entries.length + plan.migrations.length + (plan.cli ? 1 : 0) + permissions.changes.length;
76538
76671
  if (work > 0 && !flags.has("--yes") && !legacy) {
76539
- const confirmed = await (deps.confirm ?? ((q) => askConfirm(q, out)))("Apply this upgrade? [y/N] ");
76672
+ const confirmed = await (deps.confirm ?? ((q) => askConfirm(q, out)))(`${style.bold("Apply this upgrade?")} [y/N] `);
76540
76673
  if (!confirmed) {
76541
76674
  out.write(nothingChanged);
76542
76675
  return 0;
@@ -76575,19 +76708,19 @@ Nothing changed.
76575
76708
  return failed ? 1 : 0;
76576
76709
  }
76577
76710
  if (result.error && result.hosts.every((h) => h.status !== "failed"))
76578
- out.write(`Upgrade stopped: ${result.error}
76711
+ out.write(`${style.fail("Upgrade stopped:")} ${result.error}
76579
76712
  `);
76580
- out.write(table(result.hosts));
76713
+ out.write(table(result.hosts, style));
76581
76714
  if (permissions.refused)
76582
- out.write(`permissions: not refreshed: ${permissions.refused}
76715
+ out.write(`permissions: ${style.warn("not refreshed:")} ${permissions.refused}
76583
76716
  `);
76584
76717
  if (result.backup)
76585
- out.write(`Backup: ${result.backup}
76718
+ out.write(`Backup: ${style.path(result.backup)}
76586
76719
  `);
76587
- out.write(left.length === 0 ? `Verified: workit doctor is clean for versions, assets, agents and permissions.
76588
- ` : `Left after upgrade (workit doctor):
76589
- ${left.map((check) => ` ${check.id}: ${check.detail}${check.fix ? `
76590
- fix: ${check.fix}` : ""}`).join(`
76720
+ out.write(left.length === 0 ? `${style.ok("Verified:")} workit doctor is clean for versions, assets, agents and permissions.
76721
+ ` : `${style.warn("Left after upgrade (workit doctor):")}
76722
+ ${left.map((check) => ` ${style.bold(check.id)}: ${check.detail}${check.fix ? `
76723
+ fix: ${style.command(check.fix)}` : ""}`).join(`
76591
76724
  `)}
76592
76725
  `);
76593
76726
  return failed ? 1 : 0;
@@ -76650,6 +76783,7 @@ var init_upgrade = __esm(() => {
76650
76783
  init_doctor();
76651
76784
  init_host_permissions();
76652
76785
  init_progress();
76786
+ init_style();
76653
76787
  init_apply();
76654
76788
  init_plan();
76655
76789
  init_report();
@@ -76946,6 +77080,7 @@ var init_knowledge = __esm(() => {
76946
77080
  // packages/workit-cli/src/verbs/doctor.ts
76947
77081
  var exports_doctor = {};
76948
77082
  __export(exports_doctor, {
77083
+ renderDoctor: () => renderDoctor,
76949
77084
  run: () => run7
76950
77085
  });
76951
77086
  async function confirmForcedLockClear(root, args, io) {
@@ -77010,7 +77145,7 @@ async function run7(argv, io) {
77010
77145
  };
77011
77146
  }
77012
77147
  }
77013
- const report = createProgress({ stream: process.stderr, json: io.json }).runSync("Checking Workit (workit doctor)", () => runDoctor({
77148
+ const report = progressFor(io).runSync("Checking Workit (workit doctor)", () => runDoctor({
77014
77149
  host: "cli",
77015
77150
  cwd: io.cwd,
77016
77151
  workspaceRoot: root,
@@ -77047,24 +77182,65 @@ async function run7(argv, io) {
77047
77182
  if (checksConfig && checksConfig.action !== "none")
77048
77183
  io.stdout(`fix: checks config ${checksConfig.action}: ${checksConfig.detail}
77049
77184
  `);
77050
- io.stdout(`workit doctor — ${report.ok ? "healthy" : "problems found"} (${report.offline ? "offline" : "online"})
77185
+ for (const line of renderDoctor(report, knowledgeLine, createStyle({ stream: io.terminals?.stdout, env: io.env, json: io.json })))
77186
+ io.stdout(`${line}
77051
77187
  `);
77188
+ return report.exitCode;
77189
+ }
77190
+ function renderDoctor(report, knowledgeLine, style) {
77191
+ const summary = `passed ${report.summary.passed} / warned ${report.summary.warned} / failed ${report.summary.failed}`;
77192
+ const header = `workit doctor — ${report.ok ? "healthy" : "problems found"} (${report.offline ? "offline" : "online"})`;
77193
+ if (!style.enabled) {
77194
+ const lines = [header];
77195
+ for (const check of report.checks) {
77196
+ const mark = check.status === "fail" ? "FAIL" : check.status === "warn" ? "WARN" : "ok ";
77197
+ lines.push(`${mark} ${check.id} — ${check.detail}`);
77198
+ if (check.fix)
77199
+ lines.push(` fix: ${check.fix.replaceAll(`
77200
+ `, `
77201
+ `)}`);
77202
+ }
77203
+ return [...lines, knowledgeLine, summary];
77204
+ }
77205
+ const marks = {
77206
+ pass: style.ok("ok "),
77207
+ info: style.info("info"),
77208
+ warn: style.warn("WARN"),
77209
+ fail: style.fail("FAIL")
77210
+ };
77211
+ const idWidth = Math.min(ID_COLUMN, Math.max(0, ...report.checks.map((check) => check.id.length)));
77212
+ const column = 5 + idWidth + 2;
77213
+ const fixLines = (fix) => ` fix: ${fix.split(`
77214
+ `).map((line) => style.command(line)).join(`
77215
+ `)}`;
77216
+ const row = (check) => {
77217
+ const id = check.id.padEnd(idWidth);
77218
+ const used = 5 + id.length + 2;
77219
+ return `${marks[check.status]} ${style.bold(id)} ${wrap(check.detail, style.width, column, used)}`;
77220
+ };
77221
+ const lines = [
77222
+ `workit doctor — ${report.ok ? style.ok("healthy") : style.fail("problems found")} ${style.dim(`(${report.offline ? "offline" : "online"})`)}`
77223
+ ];
77052
77224
  for (const check of report.checks) {
77053
- const mark = check.status === "fail" ? "FAIL" : check.status === "warn" ? "WARN" : "ok ";
77054
- io.stdout(`${mark} ${check.id} — ${check.detail}
77055
- `);
77225
+ lines.push(row(check));
77056
77226
  if (check.fix)
77057
- io.stdout(` fix: ${check.fix.replaceAll(`
77058
- `, `
77059
- `)}
77060
- `);
77227
+ lines.push(fixLines(check.fix));
77061
77228
  }
77062
- io.stdout(`${knowledgeLine}
77063
- `);
77064
- io.stdout(`passed ${report.summary.passed} / warned ${report.summary.warned} / failed ${report.summary.failed}
77065
- `);
77066
- return report.exitCode;
77229
+ lines.push(style.dim(wrap(knowledgeLine, style.width, 5)));
77230
+ const attention = report.checks.filter((c) => c.status === "fail" || c.status === "warn");
77231
+ if (attention.length > 0) {
77232
+ lines.push("", style.bold("Needs attention:"));
77233
+ for (const check of attention) {
77234
+ lines.push(row(check));
77235
+ if (check.fix)
77236
+ lines.push(fixLines(check.fix));
77237
+ }
77238
+ }
77239
+ const paint = report.summary.failed > 0 ? style.fail : report.summary.warned > 0 ? style.warn : style.ok;
77240
+ lines.push(paint(summary));
77241
+ return lines;
77067
77242
  }
77243
+ var ID_COLUMN = 28;
77068
77244
  var init_doctor2 = __esm(() => {
77069
77245
  init_package();
77070
77246
  init_doctor();
@@ -77072,6 +77248,7 @@ var init_doctor2 = __esm(() => {
77072
77248
  init_store_lock();
77073
77249
  init_output();
77074
77250
  init_progress();
77251
+ init_style();
77075
77252
  init_prompt();
77076
77253
  init_task();
77077
77254
  });
@@ -77555,7 +77732,7 @@ async function run8(argv, io) {
77555
77732
  const store = new TaskStore(workspaceRootFor({ cwd: io.cwd }));
77556
77733
  const location = store.location();
77557
77734
  const logs = location.ok ? pruneCheckLogs(location.data.dir, { dryRun }) : null;
77558
- const result = store.collectGarbage({ dryRun, pruneRecovery });
77735
+ const result = progressFor(io).runSync("Collecting garbage", () => store.collectGarbage({ dryRun, pruneRecovery }), (r) => r.ok ? "done" : "failed");
77559
77736
  if (!result.ok)
77560
77737
  return emit(io, fail2(result.code === "busy" ? "busy" : "failed", `${result.code}: ${result.error}`, {
77561
77738
  data: { code: result.code, details: result.details },
@@ -77580,6 +77757,7 @@ async function run8(argv, io) {
77580
77757
  }
77581
77758
  var megabytes = (bytes) => (bytes / 1048576).toFixed(1);
77582
77759
  var init_gc = __esm(() => {
77760
+ init_progress();
77583
77761
  init_checks3();
77584
77762
  init_task_store();
77585
77763
  init_output();
@@ -79428,7 +79606,7 @@ async function prepareHeavy(io, settings, label, runCwd, timeoutMs) {
79428
79606
  wrapper: null,
79429
79607
  env: io.env
79430
79608
  };
79431
- const progress = createProgress({ stream: process.stderr, json: io.json });
79609
+ const progress = progressFor(io);
79432
79610
  let waiting = null;
79433
79611
  const acquired = await acquireLease({
79434
79612
  dir,
@@ -85673,13 +85851,13 @@ function placeRef(ref, forge, tracker, relation, youtrackBase) {
85673
85851
  const configured = tracker?.provider === ref.tracker;
85674
85852
  const home = ref.tracker === forge.kind ? forge.host : DEFAULT_HOST[ref.tracker];
85675
85853
  const host = ref.host ?? (configured ? tracker?.host : null) ?? home;
85676
- const repo = ref.repo ?? (configured ? tracker?.repo : null) ?? (ref.tracker === forge.kind && same2(host, forge.host) ? forge.repo : null);
85854
+ const repo = ref.repo ?? (configured ? tracker?.repo : null) ?? (ref.tracker === forge.kind && same3(host, forge.host) ? forge.repo : null);
85677
85855
  if (!repo)
85678
85856
  return {
85679
85857
  error: `#${ref.id} is a ${ref.tracker} issue, but the PR is on ${forge.kind}: set issues.repo to the ${ref.tracker} project that holds it, or pass the issue URL`
85680
85858
  };
85681
- if (ref.tracker === forge.kind && same2(host, forge.host)) {
85682
- const own = same2(repo, forge.repo);
85859
+ if (ref.tracker === forge.kind && same3(host, forge.host)) {
85860
+ const own = same3(repo, forge.repo);
85683
85861
  return {
85684
85862
  tracker: ref.tracker,
85685
85863
  id: ref.id,
@@ -85816,7 +85994,7 @@ function issueForge(resolved, link, runner) {
85816
85994
  if (link.repo === null && link.host === null)
85817
85995
  return resolved.forge;
85818
85996
  const apiHost = resolved.forge.apiHost;
85819
- if (link.tracker !== resolved.forge.kind || !same2(link.host ?? apiHost, apiHost))
85997
+ if (link.tracker !== resolved.forge.kind || !same3(link.host ?? apiHost, apiHost))
85820
85998
  return null;
85821
85999
  const options = {
85822
86000
  apiHost,
@@ -85883,7 +86061,7 @@ async function postBacklinks(cwd, resolved, pr, links, deps = {}) {
85883
86061
  }
85884
86062
  return out;
85885
86063
  }
85886
- var DEFAULT_HOST, same2 = (left, right) => (left ?? "").toLowerCase() === (right ?? "").toLowerCase(), issueUrl = (kind, host, repo, id) => `https://${host}/${repo}/${kind === "gitlab" ? "-/" : ""}issues/${id}`, label = (link) => link.tracker === "youtrack" ? link.id : link.url ?? `${link.repo ?? ""}#${link.id}`, defaultYouTrackComment = (root, issueId, text, marker) => writeOnce(issueId, marker, "comments", async () => {
86064
+ var DEFAULT_HOST, same3 = (left, right) => (left ?? "").toLowerCase() === (right ?? "").toLowerCase(), issueUrl = (kind, host, repo, id) => `https://${host}/${repo}/${kind === "gitlab" ? "-/" : ""}issues/${id}`, label = (link) => link.tracker === "youtrack" ? link.id : link.url ?? `${link.repo ?? ""}#${link.id}`, defaultYouTrackComment = (root, issueId, text, marker) => writeOnce(issueId, marker, "comments", async () => {
85887
86065
  try {
85888
86066
  return {
85889
86067
  ok: true,
@@ -87843,7 +88021,7 @@ async function create4(argv, io) {
87843
88021
  return usage4(io, planned.error, CREATE_USAGE);
87844
88022
  const links = planned.data.links;
87845
88023
  const actor = actorFromEnv(io.env);
87846
- const result = await createPullRequest(io.cwd, connected.data, {
88024
+ const result = await progressFor(io).run("Opening the pull request", () => createPullRequest(io.cwd, connected.data, {
87847
88025
  base,
87848
88026
  title,
87849
88027
  body: withIssueLines(body ?? "", links),
@@ -87851,12 +88029,12 @@ async function create4(argv, io) {
87851
88029
  actor,
87852
88030
  labels: flags.lists.label ?? [],
87853
88031
  reviewers: flags.lists.reviewer ?? []
87854
- }, forgeDeps.sleep);
88032
+ }, forgeDeps.sleep), (r) => r.ok ? "done" : "failed");
87855
88033
  if (!result.ok)
87856
88034
  return forgeFail(io, result);
87857
88035
  const opened = result.data.created;
87858
88036
  const linked = opened ? recordIssueLinks(io.cwd, result.data, links, { actor, forge: forge.kind, repo: forge.repo }) : [];
87859
- const backlinks = opened && planned.data.backlink && links.length ? await postBacklinks(io.cwd, connected.data, result.data, links, { env: io.env }) : [];
88037
+ const backlinks = opened && planned.data.backlink && links.length ? await progressFor(io).run("Posting issue backlinks", () => postBacklinks(io.cwd, connected.data, result.data, links, { env: io.env })) : [];
87860
88038
  const created = {
87861
88039
  ...result.data,
87862
88040
  issues: links.map((link) => ({
@@ -87965,7 +88143,7 @@ async function merge3(argv, io) {
87965
88143
  const connected = connect(io);
87966
88144
  if (!connected.ok)
87967
88145
  return forgeFail(io, connected);
87968
- const result = await mergePullRequest(io.cwd, connected.data, {
88146
+ const result = await progressFor(io).run(`Merging PR #${pr}`, () => mergePullRequest(io.cwd, connected.data, {
87969
88147
  pr,
87970
88148
  method,
87971
88149
  deleteBranch: flags.booleans.has("delete-branch"),
@@ -87975,7 +88153,7 @@ async function merge3(argv, io) {
87975
88153
  ...baseRedOk && baseRedReason ? { baseRedOk: { reason: baseRedReason } } : {},
87976
88154
  ...subject !== undefined ? { subject } : {},
87977
88155
  ...body !== undefined ? { body } : {}
87978
- }, forgeDeps.sleep);
88156
+ }, forgeDeps.sleep), (r) => r.ok ? "done" : "failed");
87979
88157
  if (!result.ok)
87980
88158
  return emit(io, fail2(result.code, result.error, {
87981
88159
  unblock: result.unblock,
@@ -88179,6 +88357,7 @@ var CONVENTIONAL_TYPES, COMMITLINT_FILES, DEFAULT_IGNORES, UNCHECKED = (what) =>
88179
88357
  return `verdict ${verdict.verdictId} accepted for that head${verdict.cover ? ` (stack verdict on ${verdict.cover.branch} @ ${verdict.cover.head.slice(0, 12)})` : verdict.carry ? ` (${carryLabel(verdict.carry)})` : ""}`;
88180
88358
  }, acceptedHow = (verdict) => verdict.cover ? `stack verdict ${verdict.cover.verdictId} on ${verdict.cover.branch} @ ${verdict.cover.head.slice(0, 12)}` : verdict.carry ? carryLabel(verdict.carry) : verdict.basis, METHODS2;
88181
88359
  var init_pr = __esm(() => {
88360
+ init_progress();
88182
88361
  init_autonomy();
88183
88362
  init_issue_link();
88184
88363
  init_pr_edit();
@@ -88292,7 +88471,7 @@ async function wait2(argv, io) {
88292
88471
  let verdict = { state: "waiting", reason: "not_polled" };
88293
88472
  let baseContexts = null;
88294
88473
  let expectedMissing = [];
88295
- const waiting = createProgress({ stream: process.stderr, json: io.json }).start("Waiting for CI");
88474
+ const waiting = progressFor(io).start("Waiting for CI");
88296
88475
  const abort = (...args) => {
88297
88476
  waiting.end("failed");
88298
88477
  return forgeFail(io, ...args);
@@ -88415,15 +88594,15 @@ async function rerun(argv, io) {
88415
88594
  const number = selectPr(io.cwd, resolved, { pr, branch: flags.values.branch ?? null });
88416
88595
  if (!number.ok)
88417
88596
  return forgeFail(io, number);
88418
- const status = resolved.forge.prStatus(number.data);
88597
+ const status = progressFor(io).runSync(`Reading PR #${number.data} checks`, () => resolved.forge.prStatus(number.data), (r) => r.ok ? "done" : "failed");
88419
88598
  if (!status.ok)
88420
88599
  return forgeFail(io, status);
88421
- const done = executeRerun(io.cwd, resolved, status.data, {
88600
+ const done = progressFor(io).runSync("Rerunning the checks", () => executeRerun(io.cwd, resolved, status.data, {
88422
88601
  failed: names.length === 0,
88423
88602
  names,
88424
88603
  reason,
88425
88604
  force: flags.booleans.has("force")
88426
- });
88605
+ }), (r) => r.ok ? "done" : "failed");
88427
88606
  if (!done.ok)
88428
88607
  return forgeFail(io, done);
88429
88608
  const outcome = done.data;
@@ -89537,17 +89716,17 @@ async function releasePr(io, plan, dryRun) {
89537
89716
  const switched = switchToRelease(io.cwd, plan);
89538
89717
  if (!switched.ok)
89539
89718
  return forgeFail(io, switched);
89540
- const pushed = await subVerb(() => Promise.resolve().then(() => (init_git2(), exports_git)), ["push", "--set-upstream"], io);
89719
+ const pushed = await progressFor(io).run(`Pushing ${plan.branch}`, () => subVerb(() => Promise.resolve().then(() => (init_git2(), exports_git)), ["push", "--set-upstream"], io), (r) => r.ok ? "done" : "failed");
89541
89720
  if (!pushed.ok)
89542
89721
  return emit(io, pushed);
89543
- const pr = await subVerb(() => Promise.resolve().then(() => (init_pr(), exports_pr)), [
89722
+ const pr = await progressFor(io).run("Opening the release PR", () => subVerb(() => Promise.resolve().then(() => (init_pr(), exports_pr)), [
89544
89723
  "create",
89545
89724
  "--base",
89546
89725
  plan.production,
89547
89726
  "--title",
89548
89727
  title,
89549
89728
  `--body=${plan.changelog ?? `Release ${plan.version}`}`
89550
- ], io);
89729
+ ], io), (r) => r.ok ? "done" : "failed");
89551
89730
  if (!pr.ok)
89552
89731
  return emit(io, pr);
89553
89732
  recordReleaseStep(io.cwd, actorFromEnv(io.env), plan, {
@@ -89603,11 +89782,11 @@ async function finish2(argv, io) {
89603
89782
  if (!push.allowed)
89604
89783
  return blocked(io, push);
89605
89784
  const resume = `workit release finish ${plan.version}${plan.track ? ` --track ${plan.track}` : ""}`;
89606
- const merged = finishLocally(io.cwd, plan, actor);
89785
+ const merged = progressFor(io).runSync(`Merging release ${plan.version} locally`, () => finishLocally(io.cwd, plan, actor), (r) => r.ok ? "done" : "failed");
89607
89786
  if (!merged.ok)
89608
89787
  return forgeFail(io, merged, { step: "merge", resume });
89609
89788
  const notes = [...plan.notes];
89610
- const pushed = await subVerb(() => Promise.resolve().then(() => (init_git2(), exports_git)), ["push", ...[...plan.pushBranches, plan.tag].flatMap((ref) => ["--release", ref])], io);
89789
+ const pushed = await progressFor(io).run("Pushing the release branches and tag", () => subVerb(() => Promise.resolve().then(() => (init_git2(), exports_git)), ["push", ...[...plan.pushBranches, plan.tag].flatMap((ref) => ["--release", ref])], io), (r) => r.ok ? "done" : "failed");
89611
89790
  if (!pushed.ok)
89612
89791
  return emit(io, { ...pushed, data: { ...pushed.data, step: "push", resume } });
89613
89792
  if (plan.published && plan.remote) {
@@ -89739,6 +89918,7 @@ var START_USAGE = "workit release start <version> [--hotfix] [--track <t>] [--js
89739
89918
  { step: `verify ${plan.tag} on the remote`, done: false }
89740
89919
  ];
89741
89920
  var init_release2 = __esm(() => {
89921
+ init_progress();
89742
89922
  init_autonomy();
89743
89923
  init_verify();
89744
89924
  init_ops();
@@ -89789,14 +89969,14 @@ async function run19(argv, io) {
89789
89969
  if (expect === "pushed") {
89790
89970
  if (pr)
89791
89971
  return usage4(io, "push is checked by --branch, not --pr", USAGE12);
89792
- result = verifyPushed(io.cwd, { branch, sha, actor });
89972
+ result = progressFor(io).runSync("Checking the push", () => verifyPushed(io.cwd, { branch, sha, actor }), (r) => r.ok ? "done" : "failed");
89793
89973
  } else if (expect === "released") {
89794
- result = verifyReleased(io.cwd, { tag: flags.values.tag ?? null, pkg: flags.values.package ?? null, sha, actor }, forgeDeps.npm);
89974
+ result = progressFor(io).runSync("Checking the release", () => verifyReleased(io.cwd, { tag: flags.values.tag ?? null, pkg: flags.values.package ?? null, sha, actor }, forgeDeps.npm), (r) => r.ok ? "done" : "failed");
89795
89975
  } else {
89796
89976
  const connected = connect(io, branch);
89797
89977
  if (!connected.ok)
89798
89978
  return forgeFail(io, connected);
89799
- result = expect === "pr" ? verifyPr(io.cwd, connected.data, { pr, branch, sha, actor }) : verifyMerged(io.cwd, connected.data, { pr, branch, actor });
89979
+ result = expect === "pr" ? progressFor(io).runSync(`Checking the PR`, () => verifyPr(io.cwd, connected.data, { pr, branch, sha, actor }), (r) => r.ok ? "done" : "failed") : progressFor(io).runSync("Checking the merge", () => verifyMerged(io.cwd, connected.data, { pr, branch, actor }), (r) => r.ok ? "done" : "failed");
89800
89980
  }
89801
89981
  if (!result.ok)
89802
89982
  return forgeFail(io, result);
@@ -89823,6 +90003,7 @@ var USAGE12 = "workit verify-delivery [push|pr|merge|release] [--expect pushed|p
89823
90003
  ...report.observations.map((entry) => ` ${entry.ok ? "ok" : "x "} ${entry.kind}: expected ${entry.expected ?? "-"}, observed ${entry.observed ?? "(none)"}${entry.note ? ` — ${entry.note}` : ""}`)
89824
90004
  ];
89825
90005
  var init_verify_delivery = __esm(() => {
90006
+ init_progress();
89826
90007
  init_verify();
89827
90008
  init_task_store();
89828
90009
  init_task_delivery();
@@ -89958,7 +90139,7 @@ async function sync(argv, io, restack = false) {
89958
90139
  };
89959
90140
  }
89960
90141
  const name = selected.data.name;
89961
- const result = await withStackLock(io.cwd, name, async () => {
90142
+ const result = await progressFor(io).run(restack ? `Restacking ${name}` : `Syncing ${name}`, () => withStackLock(io.cwd, name, async () => {
89962
90143
  const fresh = readStack(io.cwd, name);
89963
90144
  if (!fresh.ok)
89964
90145
  return fresh;
@@ -89971,10 +90152,13 @@ async function sync(argv, io, restack = false) {
89971
90152
  ok: true,
89972
90153
  data: {
89973
90154
  ...synced.data,
89974
- pruned: pruneMergedBranches(io.cwd, ctx, stack, { dryRun, actor: actorFromEnv(io.env) })
90155
+ pruned: pruneMergedBranches(io.cwd, ctx, stack, {
90156
+ dryRun,
90157
+ actor: actorFromEnv(io.env)
90158
+ })
89975
90159
  }
89976
90160
  };
89977
- });
90161
+ }), (r) => r.ok ? "done" : "failed");
89978
90162
  if (!result.ok)
89979
90163
  return stackFailed(io, result);
89980
90164
  if (restack)
@@ -90023,7 +90207,7 @@ async function land(argv, io) {
90023
90207
  if (!connected.ok)
90024
90208
  return forgeFail(io, connected);
90025
90209
  const name = selected.data.name;
90026
- const result = await withStackLock(io.cwd, name, async () => {
90210
+ const result = await progressFor(io).run(`Landing ${name}`, () => withStackLock(io.cwd, name, async () => {
90027
90211
  const fresh = readStack(io.cwd, name);
90028
90212
  if (!fresh.ok)
90029
90213
  return fresh;
@@ -90041,7 +90225,7 @@ async function land(argv, io) {
90041
90225
  unverified,
90042
90226
  baseRedOk: baseRedOk && baseRedReason ? { reason: baseRedReason } : null
90043
90227
  });
90044
- });
90228
+ }), (r) => r.ok ? "done" : "failed");
90045
90229
  if (!result.ok)
90046
90230
  return stackFailed(io, result);
90047
90231
  const kind = connected.data.forge.kind;
@@ -90088,6 +90272,7 @@ var PLAN_USAGE = "workit stack plan [--name <n>] [--trunk <b> | --track <t>] [<b
90088
90272
  ...data.pruned.kept.map((item) => `kept merged branch ${item.branch}: ${item.reason}`)
90089
90273
  ], METHODS3;
90090
90274
  var init_stack2 = __esm(() => {
90275
+ init_progress();
90091
90276
  init_ledger();
90092
90277
  init_stack();
90093
90278
  init_output();
@@ -90850,11 +91035,11 @@ function check2(argv, io) {
90850
91035
  const selected = selectFanout(io.cwd, flags.values.name ?? null, currentBranch(io.cwd));
90851
91036
  if (!selected.ok)
90852
91037
  return failed(io, selected);
90853
- const result = checkFanout(io.cwd, selected.data, {
91038
+ const result = progressFor(io).runSync("Checking the fan-out slices", () => checkFanout(io.cwd, selected.data, {
90854
91039
  only: flags.positionals,
90855
91040
  trunkRef: flags.values.base ?? null,
90856
91041
  forge: forgeFor(io, flags.booleans.has("offline")).forge
90857
- });
91042
+ }), (r) => r.ok ? "done" : "failed");
90858
91043
  if (!result.ok)
90859
91044
  return failed(io, result);
90860
91045
  if (result.data.ready)
@@ -90883,11 +91068,11 @@ function status4(argv, io) {
90883
91068
  if (!selected.ok)
90884
91069
  return failed(io, selected);
90885
91070
  const forge = forgeFor(io, flags.booleans.has("offline"));
90886
- const result = fanoutStatus(io.cwd, selected.data, {
91071
+ const result = progressFor(io).runSync("Reading the fan-out status", () => fanoutStatus(io.cwd, selected.data, {
90887
91072
  forge: forge.forge,
90888
91073
  forgeError: forge.error,
90889
91074
  stuckAfterMs
90890
- });
91075
+ }), (r) => r.ok ? "done" : "failed");
90891
91076
  if (!result.ok)
90892
91077
  return failed(io, result);
90893
91078
  return emit(io, ok2(result.data), renderStatus2);
@@ -90993,6 +91178,7 @@ var PLAN_USAGE2 = "workit fanout plan <plan.json> [--name <n>] [--trunk <b> | --
90993
91178
  ];
90994
91179
  };
90995
91180
  var init_fanout2 = __esm(() => {
91181
+ init_progress();
90996
91182
  init_fanout_brief();
90997
91183
  init_fanout_check();
90998
91184
  init_fanout_status();
@@ -108171,7 +108357,7 @@ async function run25(argv, io) {
108171
108357
  }
108172
108358
  const results = [];
108173
108359
  for (const entry of steps) {
108174
- const outcome = await entry.run();
108360
+ const outcome = await progressFor(io).run(entry.label, () => entry.run());
108175
108361
  results.push({
108176
108362
  step: entry.label,
108177
108363
  status: outcome.status,
@@ -108206,6 +108392,7 @@ var USAGE18 = "workit youtrack note <ISSUE> (--markdown <t> | --file <p>) [--min
108206
108392
  }
108207
108393
  };
108208
108394
  var init_youtrack2 = __esm(() => {
108395
+ init_progress();
108209
108396
  init_youtrack();
108210
108397
  init_youtrack_tools();
108211
108398
  init_youtrack_writes();
@@ -109348,7 +109535,16 @@ var defaultIo = (json) => ({
109348
109535
  async function main(argv, overrides = {}, options = {}) {
109349
109536
  const parsed = parseGlobals(argv);
109350
109537
  const cwd = path78.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
109351
- const io = { ...defaultIo(parsed.json), ...overrides, json: parsed.json, cwd };
109538
+ const io = {
109539
+ ...defaultIo(parsed.json),
109540
+ terminals: {
109541
+ ...overrides.stdout ? {} : { stdout: process.stdout },
109542
+ ...overrides.stderr ? {} : { stderr: process.stderr }
109543
+ },
109544
+ ...overrides,
109545
+ json: parsed.json,
109546
+ cwd
109547
+ };
109352
109548
  if (parsed.error)
109353
109549
  return emit(io, fail2("invalid_input", parsed.error));
109354
109550
  if (parsed.session !== undefined) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-cli",
3
- "version": "8.41.1",
3
+ "version": "8.42.0",
4
4
  "private": false,
5
5
  "description": "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
6
6
  "keywords": [
@@ -38,13 +38,13 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "@babel/parser": "7.29.9",
41
- "@brainervirus/workit-cursor": "^8.41.1",
41
+ "@brainervirus/workit-cursor": "^8.42.0",
42
42
  "@inkjs/ui": "2.0.0",
43
43
  "ink": "7.1.1",
44
44
  "react": "19.2.8"
45
45
  },
46
46
  "devDependencies": {
47
- "@brainervirus/workit-core": "^8.41.1"
47
+ "@brainervirus/workit-core": "^8.42.0"
48
48
  },
49
49
  "engines": {
50
50
  "node": ">=24"