@cleocode/cleo 2026.5.94 → 2026.5.96

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
@@ -26843,7 +26843,8 @@ async function orchestrateSpawnOp(params) {
26843
26843
  params.protocolType,
26844
26844
  getProjectRoot10(),
26845
26845
  params.tier,
26846
- params.noWorktree
26846
+ params.noWorktree,
26847
+ params.spawnScope
26847
26848
  );
26848
26849
  }
26849
26850
  async function orchestrateHandoffOp(params) {
@@ -27684,7 +27685,8 @@ var init_orchestrate2 = __esm({
27684
27685
  taskId: params.taskId,
27685
27686
  protocolType: params.protocolType,
27686
27687
  tier,
27687
- noWorktree: params.noWorktree
27688
+ noWorktree: params.noWorktree,
27689
+ spawnScope: params.spawnScope
27688
27690
  };
27689
27691
  return wrapResult(await coreOps2.spawn(p), "mutate", "orchestrate", operation, startTime);
27690
27692
  }
@@ -31602,12 +31604,14 @@ var init_upgrade = __esm({
31602
31604
 
31603
31605
  // packages/cleo/src/dispatch/domains/worktree.ts
31604
31606
  import {
31607
+ adoptWorktree,
31605
31608
  forceUnlockWorktree,
31606
31609
  getLogger as getLogger18,
31607
31610
  getProjectRoot as getProjectRoot20,
31608
31611
  listWorktrees,
31609
31612
  pruneOrphanedWorktreesByStatus
31610
31613
  } from "@cleocode/core/internal";
31614
+ import { destroyWorktree } from "@cleocode/worktree";
31611
31615
  function coerceStatusFilter(value) {
31612
31616
  if (value === void 0 || value === null) return void 0;
31613
31617
  const raw = Array.isArray(value) ? value.filter((v) => typeof v === "string") : typeof value === "string" ? value.split(",").map((s) => s.trim()) : [];
@@ -31680,23 +31684,100 @@ var init_worktree2 = __esm({
31680
31684
  * Handle worktree mutations.
31681
31685
  *
31682
31686
  * Supported operations:
31687
+ * - `adopt` — register an externally-created worktree in the SSoT. Params:
31688
+ * `{ worktreePath, source?, taskId?, actor? }`. Returns an
31689
+ * {@link AdoptWorktreeResult} envelope. (T9804)
31690
+ * - `destroy` — explicitly destroy a single agent worktree. Params:
31691
+ * `{ taskId, force?, deleteBranch?, reason? }`. Returns a
31692
+ * {@link DestroyWorktreeResult} envelope (T9805).
31683
31693
  * - `prune` — remove orphan/merged worktrees. Params:
31684
- * `{ dryRun?, staleDays?, paths?, actor? }`. Returns a
31694
+ * `{ dryRun?, staleDays?, idleDays?, paths?, actor? }`. Returns a
31685
31695
  * {@link PruneOrphanedWorktreesResult} envelope.
31686
31696
  * - `forceUnlock` — clear wedge state for a single worktree. Params:
31687
31697
  * `{ taskId, actor? }`. Returns a {@link ForceUnlockWorktreeResult}.
31688
31698
  *
31689
31699
  * @task T9547
31700
+ * @task T9804
31701
+ * @task T9805
31690
31702
  */
31691
31703
  async mutate(operation, params) {
31692
31704
  const startTime = Date.now();
31693
31705
  try {
31694
31706
  switch (operation) {
31707
+ case "adopt": {
31708
+ const worktreePath = params?.["worktreePath"];
31709
+ if (typeof worktreePath !== "string" || worktreePath.length === 0) {
31710
+ return errorResult(
31711
+ "mutate",
31712
+ "worktree",
31713
+ operation,
31714
+ "E_VALIDATION",
31715
+ "Missing required param: worktreePath (pass the path to the worktree directory).",
31716
+ startTime
31717
+ );
31718
+ }
31719
+ const rawSource = params?.["source"];
31720
+ const validSources = ["claude-agent", "manual", "adopted"];
31721
+ const source = typeof rawSource === "string" && validSources.includes(rawSource) ? rawSource : void 0;
31722
+ const rawTaskId = params?.["taskId"];
31723
+ const taskId = rawTaskId === null ? null : typeof rawTaskId === "string" && rawTaskId.length > 0 ? rawTaskId : void 0;
31724
+ const opts = {
31725
+ projectRoot: getProjectRoot20(),
31726
+ worktreePath,
31727
+ ...source !== void 0 ? { source } : {},
31728
+ ...taskId !== void 0 ? { taskId } : {},
31729
+ ...typeof params?.["actor"] === "string" && params["actor"].length > 0 ? { actor: params["actor"] } : {}
31730
+ };
31731
+ const result = await adoptWorktree(opts);
31732
+ return wrapResult(
31733
+ result,
31734
+ "mutate",
31735
+ "worktree",
31736
+ operation,
31737
+ startTime
31738
+ );
31739
+ }
31740
+ case "destroy": {
31741
+ const taskId = params?.["taskId"];
31742
+ if (typeof taskId !== "string" || taskId.length === 0) {
31743
+ return errorResult(
31744
+ "mutate",
31745
+ "worktree",
31746
+ operation,
31747
+ "E_VALIDATION",
31748
+ "Missing required param: taskId (e.g. T9805).",
31749
+ startTime
31750
+ );
31751
+ }
31752
+ const opts = {
31753
+ taskId,
31754
+ force: params?.["force"] === true,
31755
+ deleteBranch: params?.["deleteBranch"] !== false,
31756
+ ...typeof params?.["reason"] === "string" && params["reason"].length > 0 ? { reason: params["reason"] } : {}
31757
+ };
31758
+ const result = await destroyWorktree(getProjectRoot20(), opts);
31759
+ const engineResult = result.error !== void 0 ? {
31760
+ success: false,
31761
+ error: {
31762
+ code: "E_DESTROY_FAILED",
31763
+ message: result.error,
31764
+ fix: "Check worktree state with `cleo worktree list`."
31765
+ }
31766
+ } : { success: true, data: result };
31767
+ return wrapResult(
31768
+ engineResult,
31769
+ "mutate",
31770
+ "worktree",
31771
+ operation,
31772
+ startTime
31773
+ );
31774
+ }
31695
31775
  case "prune": {
31696
31776
  const opts = {
31697
31777
  projectRoot: getProjectRoot20(),
31698
31778
  dryRun: params?.["dryRun"] === true,
31699
31779
  ...typeof params?.["staleDays"] === "number" ? { staleDays: params["staleDays"] } : {},
31780
+ ...typeof params?.["idleDays"] === "number" ? { staleDays: params["idleDays"] } : {},
31700
31781
  ...coerceStringList(params?.["paths"]) !== void 0 ? { paths: coerceStringList(params?.["paths"]) } : {},
31701
31782
  ...typeof params?.["actor"] === "string" && params["actor"].length > 0 ? { actor: params["actor"] } : {}
31702
31783
  };
@@ -31752,7 +31833,7 @@ var init_worktree2 = __esm({
31752
31833
  getSupportedOperations() {
31753
31834
  return {
31754
31835
  query: ["list"],
31755
- mutate: ["prune", "forceUnlock"]
31836
+ mutate: ["adopt", "destroy", "prune", "forceUnlock"]
31756
31837
  };
31757
31838
  }
31758
31839
  };
@@ -45771,16 +45852,27 @@ var init_doctor = __esm({
45771
45852
  process.exitCode = 2;
45772
45853
  }
45773
45854
  } else if (args["audit-worktree-orphans"]) {
45774
- progress.step(0, "Scanning for worktree-orphan .cleo/ directories");
45775
- const { scanWorktreeOrphans } = await import("@cleocode/core/doctor/worktree-orphans.js");
45855
+ progress.step(0, "Comprehensive worktree anomaly audit (T9808 / council D009)");
45856
+ const { auditWorktreeOrphansComprehensive, scanWorktreeOrphans } = await import("@cleocode/core/doctor/worktree-orphans.js");
45776
45857
  const projectRoot = getProjectRoot32();
45777
- const orphans = await scanWorktreeOrphans(projectRoot);
45778
- progress.complete(`Found ${orphans.length} orphan${orphans.length === 1 ? "" : "s"}`);
45858
+ const [comprehensive, legacyOrphans] = await Promise.all([
45859
+ auditWorktreeOrphansComprehensive(projectRoot),
45860
+ scanWorktreeOrphans(projectRoot)
45861
+ ]);
45862
+ const totalAnomalies = comprehensive.count;
45863
+ progress.complete(
45864
+ `Found ${totalAnomalies} anomal${totalAnomalies === 1 ? "y" : "ies"}` + (legacyOrphans.length > 0 ? ` (${legacyOrphans.length} legacy orphan(s))` : "")
45865
+ );
45779
45866
  cliOutput(
45780
- { projectRoot, orphans, count: orphans.length },
45867
+ {
45868
+ projectRoot,
45869
+ comprehensive,
45870
+ legacyOrphans,
45871
+ count: totalAnomalies
45872
+ },
45781
45873
  { command: "doctor", operation: "doctor.audit-worktree-orphans" }
45782
45874
  );
45783
- if (orphans.length > 0 && (process.exitCode === void 0 || process.exitCode === 0)) {
45875
+ if (totalAnomalies > 0 && (process.exitCode === void 0 || process.exitCode === 0)) {
45784
45876
  process.exitCode = 2;
45785
45877
  }
45786
45878
  } else if (args["prune-worktree-orphans"]) {
@@ -55587,6 +55679,10 @@ var init_orchestrate3 = __esm({
55587
55679
  "no-worktree": {
55588
55680
  type: "boolean",
55589
55681
  description: "Skip worktree provisioning for this spawn. The opt-out is logged to the audit log (T1140)."
55682
+ },
55683
+ scope: {
55684
+ type: "string",
55685
+ description: "T9807 sparse-checkout scope: directory prefix to check out in the worktree (cone mode). Example: --scope packages/cleo creates a worktree with only that subtree checked out. Reduces disk usage and checkout time for tasks scoped to a single package."
55590
55686
  }
55591
55687
  },
55592
55688
  async run({ args }) {
@@ -55605,7 +55701,8 @@ var init_orchestrate3 = __esm({
55605
55701
  taskId: args.taskId,
55606
55702
  protocolType: args.protocol,
55607
55703
  tier,
55608
- noWorktree: args["no-worktree"] === true
55704
+ noWorktree: args["no-worktree"] === true,
55705
+ ...args.scope ? { spawnScope: args.scope } : {}
55609
55706
  },
55610
55707
  { command: "orchestrate" }
55611
55708
  );
@@ -66247,7 +66344,7 @@ function renderOrphanPreamble(wt) {
66247
66344
  ""
66248
66345
  ].join("\n");
66249
66346
  }
66250
- var VALID_STATUS_VALUES, listCommand27, pruneCommand3, forceUnlockCommand, worktreeCommand;
66347
+ var VALID_STATUS_VALUES, listCommand27, pruneCommand3, destroyCommand, forceUnlockCommand, VALID_ADOPT_SOURCES, adoptCommand, worktreeCommand;
66251
66348
  var init_worktree3 = __esm({
66252
66349
  "packages/cleo/src/cli/commands/worktree.ts"() {
66253
66350
  "use strict";
@@ -66310,6 +66407,10 @@ var init_worktree3 = __esm({
66310
66407
  days: {
66311
66408
  type: "string",
66312
66409
  description: "Override staleness threshold passed through to the listing (default: 7)."
66410
+ },
66411
+ "idle-days": {
66412
+ type: "string",
66413
+ description: "Abandonment-timeout threshold in days (T9805 AC2). Worktrees whose last commit is older than this value AND have no open PR are also pruned."
66313
66414
  }
66314
66415
  },
66315
66416
  async run({ args }) {
@@ -66325,6 +66426,8 @@ var init_worktree3 = __esm({
66325
66426
  const yes = args["yes"] === true;
66326
66427
  const staleDaysRaw = typeof args["days"] === "string" ? args["days"] : void 0;
66327
66428
  const staleDays = staleDaysRaw !== void 0 ? Number.parseInt(staleDaysRaw, 10) : void 0;
66429
+ const idleDaysRaw = typeof args["idle-days"] === "string" ? args["idle-days"] : void 0;
66430
+ const idleDays = idleDaysRaw !== void 0 ? Number.parseInt(idleDaysRaw, 10) : void 0;
66328
66431
  const projectRoot = getProjectRoot42();
66329
66432
  const listResult = await listWorktrees2({
66330
66433
  projectRoot,
@@ -66398,12 +66501,61 @@ var init_worktree3 = __esm({
66398
66501
  {
66399
66502
  dryRun,
66400
66503
  paths: confirmedPaths,
66401
- ...staleDays !== void 0 && !Number.isNaN(staleDays) ? { staleDays } : {}
66504
+ ...staleDays !== void 0 && !Number.isNaN(staleDays) ? { staleDays } : {},
66505
+ ...idleDays !== void 0 && !Number.isNaN(idleDays) ? { idleDays } : {}
66402
66506
  },
66403
66507
  { command: "worktree-prune", operation: "worktree.prune" }
66404
66508
  );
66405
66509
  }
66406
66510
  });
66511
+ destroyCommand = defineCommand({
66512
+ meta: {
66513
+ name: "destroy",
66514
+ description: "Destroy the XDG worktree for a task, update audit log and sentinel index (T9805)."
66515
+ },
66516
+ args: {
66517
+ taskId: {
66518
+ type: "positional",
66519
+ description: "The task ID whose worktree to destroy (e.g. T9805).",
66520
+ required: true
66521
+ },
66522
+ force: {
66523
+ type: "boolean",
66524
+ description: "Force removal even when the worktree has uncommitted changes.",
66525
+ default: false
66526
+ },
66527
+ reason: {
66528
+ type: "string",
66529
+ description: "Reason string recorded in the audit log (e.g. pr-merged, manual, idle-timeout)."
66530
+ },
66531
+ "keep-branch": {
66532
+ type: "boolean",
66533
+ description: "Do not delete the task branch after removing the worktree.",
66534
+ default: false
66535
+ }
66536
+ },
66537
+ async run({ args }) {
66538
+ const rawTaskId = typeof args["taskId"] === "string" ? args["taskId"] : "";
66539
+ if (rawTaskId.length === 0) {
66540
+ cliError("Missing required positional: <taskId>.", 2);
66541
+ process.exit(2);
66542
+ return;
66543
+ }
66544
+ const reason = typeof args["reason"] === "string" && args["reason"].length > 0 ? args["reason"] : "manual";
66545
+ await dispatchFromCli(
66546
+ "mutate",
66547
+ "worktree",
66548
+ "destroy",
66549
+ {
66550
+ taskId: rawTaskId,
66551
+ force: args["force"] === true,
66552
+ deleteBranch: args["keep-branch"] !== true,
66553
+ reason
66554
+ },
66555
+ { command: "worktree-destroy", operation: "worktree.destroy" }
66556
+ );
66557
+ }
66558
+ });
66407
66559
  forceUnlockCommand = defineCommand({
66408
66560
  meta: {
66409
66561
  name: "force-unlock",
@@ -66432,6 +66584,56 @@ var init_worktree3 = __esm({
66432
66584
  );
66433
66585
  }
66434
66586
  });
66587
+ VALID_ADOPT_SOURCES = ["claude-agent", "manual", "adopted"];
66588
+ adoptCommand = defineCommand({
66589
+ meta: {
66590
+ name: "adopt",
66591
+ description: "Register an externally-created worktree (e.g. Claude Code Agent isolation:worktree) in the CLEO SSoT so it surfaces in `cleo worktree list`."
66592
+ },
66593
+ args: {
66594
+ path: {
66595
+ type: "positional",
66596
+ description: "Absolute or relative path to the worktree directory to adopt. For Claude Code Agent worktrees this is typically `.claude/worktrees/<sessionId>/`.",
66597
+ required: true
66598
+ },
66599
+ source: {
66600
+ type: "string",
66601
+ description: `Source classification for this worktree (${VALID_ADOPT_SOURCES.join("|")}). Defaults to \`claude-agent\` for paths under \`.claude/worktrees/\`, else \`manual\`.`
66602
+ },
66603
+ "task-id": {
66604
+ type: "string",
66605
+ description: "Optional task ID to associate with this worktree. When omitted the command attempts to extract it from the branch name."
66606
+ },
66607
+ actor: {
66608
+ type: "string",
66609
+ description: "Override actor name written to the audit log."
66610
+ }
66611
+ },
66612
+ async run({ args }) {
66613
+ const rawPath = typeof args["path"] === "string" ? args["path"] : "";
66614
+ if (rawPath.length === 0) {
66615
+ cliError("Missing required positional: <path>.", 2);
66616
+ process.exit(2);
66617
+ return;
66618
+ }
66619
+ const rawSource = typeof args["source"] === "string" ? args["source"] : void 0;
66620
+ const source = rawSource !== void 0 && VALID_ADOPT_SOURCES.includes(rawSource) ? rawSource : void 0;
66621
+ const rawTaskId = typeof args["task-id"] === "string" ? args["task-id"] : void 0;
66622
+ const rawActor = typeof args["actor"] === "string" ? args["actor"] : void 0;
66623
+ await dispatchFromCli(
66624
+ "mutate",
66625
+ "worktree",
66626
+ "adopt",
66627
+ {
66628
+ worktreePath: rawPath,
66629
+ ...source !== void 0 ? { source } : {},
66630
+ ...rawTaskId !== void 0 ? { taskId: rawTaskId } : {},
66631
+ ...rawActor !== void 0 ? { actor: rawActor } : {}
66632
+ },
66633
+ { command: "worktree-adopt", operation: "worktree.adopt" }
66634
+ );
66635
+ }
66636
+ });
66435
66637
  worktreeCommand = defineCommand({
66436
66638
  meta: {
66437
66639
  name: "worktree",
@@ -66439,7 +66641,9 @@ var init_worktree3 = __esm({
66439
66641
  },
66440
66642
  subCommands: {
66441
66643
  list: listCommand27,
66644
+ adopt: adoptCommand,
66442
66645
  prune: pruneCommand3,
66646
+ destroy: destroyCommand,
66443
66647
  "force-unlock": forceUnlockCommand
66444
66648
  },
66445
66649
  // Early-return when a subcommand was matched; citty still invokes the
@@ -67086,7 +67290,7 @@ var COMMAND_MANIFEST = [
67086
67290
  {
67087
67291
  exportName: "reqCommand",
67088
67292
  name: "req",
67089
- description: "Manage REQ-ID-addressable acceptance gates on tasks",
67293
+ description: "Manage REQ-ID-addressable acceptance gates on tasks (in-task gates only). For cross-task dependency edges, use ",
67090
67294
  load: async () => (await Promise.resolve().then(() => (init_req(), req_exports))).reqCommand
67091
67295
  },
67092
67296
  {
@@ -67254,7 +67458,7 @@ var COMMAND_MANIFEST = [
67254
67458
  {
67255
67459
  exportName: "updateCommand",
67256
67460
  name: "update",
67257
- description: "Update a task",
67461
+ description: "Update a task. Safe under concurrent invocation \u2014 retries on SQLITE_BUSY up to 4 attempts (gh#391).",
67258
67462
  load: async () => (await Promise.resolve().then(() => (init_update(), update_exports))).updateCommand
67259
67463
  },
67260
67464
  {