@cleocode/cleo 2026.5.41 → 2026.5.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -3600,7 +3600,22 @@ function renderNexusProjectsClean(data, quiet) {
3600
3600
  if (matched === 0) return "";
3601
3601
  return `[nexus] Dry-run \u2014 ${matched} project(s) would be purged. Rerun without --dry-run to delete.`;
3602
3602
  }
3603
- return `[nexus] Purged ${purged} project(s). ${remaining} project(s) remaining in registry.`;
3603
+ const lines = [
3604
+ `[nexus] Purged ${purged} project(s). ${remaining} project(s) remaining in registry.`
3605
+ ];
3606
+ const fsRemoved = data["fsRemoved"];
3607
+ const fsFailed = data["fsFailed"];
3608
+ if (typeof fsRemoved === "number") {
3609
+ lines.push(
3610
+ `[nexus] Filesystem cleanup: removed ${fsRemoved} dir(s)` + (typeof fsFailed === "number" && fsFailed > 0 ? `, ${fsFailed} skipped/failed.` : ".")
3611
+ );
3612
+ }
3613
+ const vacuumBytesFreed = data["vacuumBytesFreed"];
3614
+ if (typeof vacuumBytesFreed === "number") {
3615
+ const mb = (vacuumBytesFreed / (1024 * 1024)).toFixed(1);
3616
+ lines.push(`[nexus] VACUUM reclaimed ${mb} MB.`);
3617
+ }
3618
+ return lines.join("\n");
3604
3619
  }
3605
3620
  function renderNexusProjectsCleanPreview(data, _quiet) {
3606
3621
  const matched = Number(data["matched"] ?? 0);
@@ -9876,6 +9891,24 @@ var init_registry = __esm({
9876
9891
  type: "boolean",
9877
9892
  required: false,
9878
9893
  description: "Match never-indexed rows"
9894
+ },
9895
+ {
9896
+ name: "matchOrphaned",
9897
+ type: "boolean",
9898
+ required: false,
9899
+ description: "Match rows whose project_path no longer exists on disk (T9117)"
9900
+ },
9901
+ {
9902
+ name: "removeFs",
9903
+ type: "boolean",
9904
+ required: false,
9905
+ description: "After DB delete, rm -rf each matched on-disk directory (T9117)"
9906
+ },
9907
+ {
9908
+ name: "vacuum",
9909
+ type: "boolean",
9910
+ required: false,
9911
+ description: "After delete, run sqlite VACUUM on nexus.db to reclaim space (T9117)"
9879
9912
  }
9880
9913
  ]
9881
9914
  },
@@ -11748,6 +11781,7 @@ __export(engine_exports, {
11748
11781
  releaseGatesRun: () => releaseGatesRun,
11749
11782
  releaseIvtrAutoSuggest: () => releaseIvtrAutoSuggest,
11750
11783
  releaseList: () => releaseList,
11784
+ releasePrStatus: () => releasePrStatus,
11751
11785
  releasePrepare: () => releasePrepare,
11752
11786
  releasePublish: () => releasePublish,
11753
11787
  releasePush: () => releasePush,
@@ -11976,6 +12010,7 @@ import {
11976
12010
  releaseIvtrAutoSuggest,
11977
12011
  releaseList,
11978
12012
  releasePrepare,
12013
+ releasePrStatus,
11979
12014
  releasePublish,
11980
12015
  releasePush,
11981
12016
  releaseReconcile,
@@ -18251,7 +18286,10 @@ var init_nexus3 = __esm({
18251
18286
  includeTemp: params.includeTemp === true,
18252
18287
  includeTests: params.includeTests === true,
18253
18288
  matchUnhealthy: params.matchUnhealthy === true,
18254
- matchNeverIndexed: params.matchNeverIndexed === true
18289
+ matchNeverIndexed: params.matchNeverIndexed === true,
18290
+ matchOrphaned: params.matchOrphaned === true,
18291
+ removeFs: params.removeFs === true,
18292
+ vacuum: params.vacuum === true
18255
18293
  }),
18256
18294
  "projects.clean"
18257
18295
  ),
@@ -25204,6 +25242,9 @@ async function releaseShipOp(params) {
25204
25242
  getProjectRoot10()
25205
25243
  );
25206
25244
  }
25245
+ async function releasePrStatusOp(params) {
25246
+ return releasePrStatus(params.version, getProjectRoot10());
25247
+ }
25207
25248
  async function releaseCancelOp(params) {
25208
25249
  return releaseCancel(params.version, getProjectRoot10());
25209
25250
  }
@@ -25361,6 +25402,7 @@ var init_pipeline3 = __esm({
25361
25402
  "release.channel.show": releaseChannelShowOp,
25362
25403
  "release.changelog.since": releaseChangelogSinceOp,
25363
25404
  "release.ship": releaseShipOp,
25405
+ "release.pr-status": releasePrStatusOp,
25364
25406
  "release.cancel": releaseCancelOp,
25365
25407
  "release.rollback": releaseRollbackOp,
25366
25408
  "release.rollback.full": releaseRollbackFullOp,
@@ -25513,6 +25555,13 @@ var init_pipeline3 = __esm({
25513
25555
  }
25514
25556
  return wrapCoreResult(await coreOps2["release.ship"](params), "release.ship");
25515
25557
  },
25558
+ // release.pr-status — T9095 query: poll CI checks for an in-progress release PR
25559
+ "release.pr-status": async (params) => {
25560
+ if (!params.version) {
25561
+ return lafsError("E_INVALID_INPUT", "version is required", "release.pr-status");
25562
+ }
25563
+ return wrapCoreResult(await coreOps2["release.pr-status"](params), "release.pr-status");
25564
+ },
25516
25565
  "release.cancel": async (params) => {
25517
25566
  if (!params.version) {
25518
25567
  return lafsError("E_INVALID_INPUT", "version is required", "release.cancel");
@@ -39365,9 +39414,13 @@ var init_doctor = __esm({
39365
39414
  type: "boolean",
39366
39415
  description: "Move all rogue .cleo/ sub-package directories to .cleo/quarantine/ (never deletes)"
39367
39416
  },
39417
+ "scan-stray-nexus-dbs": {
39418
+ type: "boolean",
39419
+ description: "Scan ~/.local/share/cleo/ for orphaned nexus.db files and print report (T9052)"
39420
+ },
39368
39421
  "dry-run": {
39369
39422
  type: "boolean",
39370
- description: "With --quarantine-rogue-cleo-dirs: print what would be moved without moving"
39423
+ description: "With --quarantine-rogue-cleo-dirs or --scan-stray-nexus-dbs: print what would be done without acting"
39371
39424
  },
39372
39425
  // Global output format flags — read directly from args (no optsWithGlobals in citty)
39373
39426
  json: {
@@ -39555,6 +39608,53 @@ Errors (${errors.length}):`);
39555
39608
  }
39556
39609
  humanLine("");
39557
39610
  }
39611
+ } else if (args["scan-stray-nexus-dbs"]) {
39612
+ progress.step(0, "Scanning for stray nexus.db files");
39613
+ const { detectAndRemoveLegacyGlobalFiles, detectAndRemoveStrayProjectNexus } = await import("@cleocode/core/internal");
39614
+ const { getCleoHome: getCleoHome3 } = await import("@cleocode/core/internal");
39615
+ const cleoHome = getCleoHome3();
39616
+ const projectRoot = getProjectRoot24();
39617
+ const legacyResult = detectAndRemoveLegacyGlobalFiles(cleoHome);
39618
+ const strayResult = detectAndRemoveStrayProjectNexus(projectRoot);
39619
+ const isDryRun = args["dry-run"] === true;
39620
+ const report = {
39621
+ cleoHome,
39622
+ projectRoot,
39623
+ legacy: {
39624
+ removed: legacyResult.removed.length,
39625
+ files: legacyResult.removed
39626
+ },
39627
+ stray: {
39628
+ removed: strayResult.removed,
39629
+ path: strayResult.path
39630
+ },
39631
+ dryRun: isDryRun
39632
+ };
39633
+ progress.complete(
39634
+ `Found ${legacyResult.removed.length} legacy + ${strayResult.removed ? 1 : 0} stray nexus.db`
39635
+ );
39636
+ if (args.json) {
39637
+ process.stdout.write(JSON.stringify({ success: true, data: report }, null, 2) + "\n");
39638
+ } else {
39639
+ humanLine(`
39640
+ Stray nexus.db scan (${isDryRun ? "DRY RUN \u2014 no files touched" : "live"})`);
39641
+ humanLine(` CLEO home: ${cleoHome}`);
39642
+ humanLine(` Project: ${projectRoot}`);
39643
+ if (legacyResult.removed.length > 0) {
39644
+ humanLine(`
39645
+ Legacy files removed (${legacyResult.removed.length}):`);
39646
+ for (const f of legacyResult.removed) {
39647
+ humanLine(` \u2713 ${f}`);
39648
+ }
39649
+ } else {
39650
+ humanLine("\n No legacy files found.");
39651
+ }
39652
+ humanLine(
39653
+ `
39654
+ Stray project nexus.db: ${strayResult.removed ? "\u2713 removed" : "not found"} (${strayResult.path})`
39655
+ );
39656
+ humanLine("");
39657
+ }
39558
39658
  } else {
39559
39659
  progress.step(0, "Checking CLEO directory");
39560
39660
  await dispatchFromCli(
@@ -45283,6 +45383,18 @@ var init_nexus4 = __esm({
45283
45383
  type: "boolean",
45284
45384
  description: "Also match rows where last_indexed IS NULL"
45285
45385
  },
45386
+ orphans: {
45387
+ type: "boolean",
45388
+ description: "Also match rows whose project_path no longer exists on disk (T9117)"
45389
+ },
45390
+ "rm-fs": {
45391
+ type: "boolean",
45392
+ description: "After DB delete, rm -rf each matched on-disk directory (T9117). Implies --yes when combined with --orphans for fully unattended runs is still gated by confirmation."
45393
+ },
45394
+ vacuum: {
45395
+ type: "boolean",
45396
+ description: "After delete, run sqlite VACUUM on nexus.db to reclaim space (T9117)"
45397
+ },
45286
45398
  yes: {
45287
45399
  type: "boolean",
45288
45400
  description: "Skip confirmation prompt (still shows preview)"
@@ -45303,7 +45415,10 @@ var init_nexus4 = __esm({
45303
45415
  includeTemp: !!args["include-temp"],
45304
45416
  includeTests: !!args["include-tests"],
45305
45417
  matchUnhealthy: !!args.unhealthy,
45306
- matchNeverIndexed: !!args["never-indexed"]
45418
+ matchNeverIndexed: !!args["never-indexed"],
45419
+ matchOrphaned: !!args.orphans,
45420
+ removeFs: !!args["rm-fs"],
45421
+ vacuum: !!args.vacuum
45307
45422
  };
45308
45423
  try {
45309
45424
  const previewResp = await dispatchRaw("mutate", "nexus", "projects.clean", {
@@ -45395,7 +45510,10 @@ var init_nexus4 = __esm({
45395
45510
  matched: result.matched,
45396
45511
  purged: result.purged,
45397
45512
  remaining: result.remaining,
45398
- sample: result.sample
45513
+ sample: result.sample,
45514
+ fsRemoved: result.fsRemoved,
45515
+ fsFailed: result.fsFailed,
45516
+ vacuumBytesFreed: result.vacuumBytesFreed
45399
45517
  },
45400
45518
  {
45401
45519
  command: "nexus-projects-clean",
@@ -46688,14 +46806,82 @@ var init_ops = __esm({
46688
46806
  // packages/cleo/src/cli/commands/orchestrate.ts
46689
46807
  var orchestrate_exports = {};
46690
46808
  __export(orchestrate_exports, {
46809
+ formatRollupTable: () => formatRollupTable,
46691
46810
  orchestrateCommand: () => orchestrateCommand
46692
46811
  });
46693
- var startCommand5, statusCommand8, analyzeCommand4, readyCommand, nextCommand2, wavesCommand2, planCommand, spawnCommand2, validateCommand6, contextCommand4, ivtrCommand, parallelCommand, tesseraListCommand, tesseraInstantiateCommand, tesseraCommand, unblockCommand, bootstrapCommand, classifyCommand, fanoutStatusCommand, handoffCommand, spawnExecuteCommand, fanoutCommand, pruneCommand, worktreeCompleteCommand, conduitStatusCommand, conduitPeekCommand, conduitStartCommand, conduitStopCommand, approveCommand, rejectCommand, pendingCommand, conduitSendCommand, orchestrateCommand;
46812
+ import { orchestration } from "@cleocode/core";
46813
+ function formatRollupTable(rollup) {
46814
+ const waves = "waves" in rollup ? rollup.waves : [rollup];
46815
+ const lines = [];
46816
+ const header = ["WAVE", "TASK", "TITLE", "STATUS", "GATES", "LATEST"];
46817
+ const rows = [header];
46818
+ const blockers = [];
46819
+ for (const wave of waves) {
46820
+ for (const w of wave.workers) {
46821
+ const gateSummary = Object.entries(w.gates ?? {}).map(([k, v]) => `${k}=${v === true ? "ok" : v === false ? "fail" : "-"}`).join(",");
46822
+ const latest = w.latestManifestStatus ? `${w.latestManifestStatus}@${(w.latestManifestAt ?? "").slice(0, 19)}` : "-";
46823
+ rows.push([
46824
+ String(wave.waveId),
46825
+ w.taskId,
46826
+ (w.title ?? "").slice(0, 40),
46827
+ String(w.status ?? "-"),
46828
+ gateSummary || "-",
46829
+ latest
46830
+ ]);
46831
+ }
46832
+ for (const b of wave.blockers) blockers.push(b);
46833
+ }
46834
+ const widths = header.map((_, ci) => Math.max(...rows.map((r) => (r[ci] ?? "").length)));
46835
+ for (const row of rows) {
46836
+ lines.push(row.map((c, i) => (c ?? "").padEnd(widths[i] ?? 0)).join(" "));
46837
+ }
46838
+ if (blockers.length > 0) {
46839
+ lines.push("");
46840
+ lines.push("Blockers:");
46841
+ for (const b of blockers) {
46842
+ lines.push(` - ${b.taskId} [${b.reason}]${b.detail ? ` ${b.detail}` : ""}`);
46843
+ }
46844
+ }
46845
+ return lines.join("\n");
46846
+ }
46847
+ var rollupCommand, startCommand5, statusCommand8, analyzeCommand4, readyCommand, nextCommand2, wavesCommand2, planCommand, spawnCommand2, validateCommand6, contextCommand4, ivtrCommand, parallelCommand, tesseraListCommand, tesseraInstantiateCommand, tesseraCommand, unblockCommand, bootstrapCommand, classifyCommand, fanoutStatusCommand, handoffCommand, spawnExecuteCommand, fanoutCommand, pruneCommand, worktreeCompleteCommand, conduitStatusCommand, conduitPeekCommand, conduitStartCommand, conduitStopCommand, approveCommand, rejectCommand, pendingCommand, conduitSendCommand, orchestrateCommand;
46694
46848
  var init_orchestrate3 = __esm({
46695
46849
  "packages/cleo/src/cli/commands/orchestrate.ts"() {
46696
46850
  "use strict";
46697
46851
  init_dist();
46698
46852
  init_cli();
46853
+ rollupCommand = defineCommand({
46854
+ meta: {
46855
+ name: "roll-up",
46856
+ description: "Lead-tier rollup of an epic (all waves or filtered by --wave)"
46857
+ },
46858
+ args: {
46859
+ epicId: {
46860
+ type: "positional",
46861
+ description: "Epic ID to roll up",
46862
+ required: true
46863
+ },
46864
+ wave: {
46865
+ type: "string",
46866
+ description: "Filter to a single wave id (0-indexed)"
46867
+ },
46868
+ json: {
46869
+ type: "boolean",
46870
+ description: "Emit machine-readable JSON instead of a human table"
46871
+ }
46872
+ },
46873
+ async run({ args }) {
46874
+ const epicId = String(args.epicId);
46875
+ const result = args.wave !== void 0 && args.wave !== "" ? await orchestration.rollupWaveStatus(epicId, Number(args.wave)) : await orchestration.rollupEpicStatus(epicId);
46876
+ if (args.json) {
46877
+ process.stdout.write(`${JSON.stringify(result, null, 2)}
46878
+ `);
46879
+ return;
46880
+ }
46881
+ process.stdout.write(`${formatRollupTable(result)}
46882
+ `);
46883
+ }
46884
+ });
46699
46885
  startCommand5 = defineCommand({
46700
46886
  meta: { name: "start", description: "Start orchestrator session for an epic" },
46701
46887
  args: {
@@ -47454,6 +47640,7 @@ var init_orchestrate3 = __esm({
47454
47640
  subCommands: {
47455
47641
  start: startCommand5,
47456
47642
  status: statusCommand8,
47643
+ "roll-up": rollupCommand,
47457
47644
  analyze: analyzeCommand4,
47458
47645
  ready: readyCommand,
47459
47646
  next: nextCommand2,
@@ -48744,7 +48931,7 @@ __export(release_exports, {
48744
48931
  releaseCommand: () => releaseCommand
48745
48932
  });
48746
48933
  import { release as release2 } from "@cleocode/core";
48747
- var shipCommand, listCommand16, showCommand10, cancelCommand2, changelogCommand, rollbackCommand, rollbackFullCommand, channelCommand, startCommand7, verifyCommand2, publishCommand3, reconcileCommand3, releaseCommand;
48934
+ var shipCommand, listCommand16, showCommand10, cancelCommand2, changelogCommand, rollbackCommand, rollbackFullCommand, prStatusCommand, channelCommand, startCommand7, verifyCommand2, publishCommand3, reconcileCommand3, releaseCommand;
48748
48935
  var init_release3 = __esm({
48749
48936
  "packages/cleo/src/cli/commands/release.ts"() {
48750
48937
  "use strict";
@@ -48939,6 +49126,28 @@ var init_release3 = __esm({
48939
49126
  );
48940
49127
  }
48941
49128
  });
49129
+ prStatusCommand = defineCommand({
49130
+ meta: {
49131
+ name: "pr-status",
49132
+ description: "Poll CI check status for an in-progress release PR (T9095)"
49133
+ },
49134
+ args: {
49135
+ version: {
49136
+ type: "positional",
49137
+ description: "Release version (e.g. 2026.5.43)",
49138
+ required: true
49139
+ }
49140
+ },
49141
+ async run({ args }) {
49142
+ await dispatchFromCli(
49143
+ "query",
49144
+ "pipeline",
49145
+ "release.pr-status",
49146
+ { version: args.version },
49147
+ { command: "release" }
49148
+ );
49149
+ }
49150
+ });
48942
49151
  channelCommand = defineCommand({
48943
49152
  meta: {
48944
49153
  name: "channel",
@@ -49011,6 +49220,7 @@ var init_release3 = __esm({
49011
49220
  rollback: rollbackCommand,
49012
49221
  "rollback-full": rollbackFullCommand,
49013
49222
  channel: channelCommand,
49223
+ "pr-status": prStatusCommand,
49014
49224
  // Canonical 4-step pipeline (T1597 / ADR-063)
49015
49225
  start: startCommand7,
49016
49226
  verify: verifyCommand2,